summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorscox <scox@138bc75d-0d04-0410-961f-82ee72b054a4>1998-12-01 16:52:56 +0000
committerscox <scox@138bc75d-0d04-0410-961f-82ee72b054a4>1998-12-01 16:52:56 +0000
commit16c730c97a80bdb81e955e8b14d4466d520ec59b (patch)
tree39eb2e0c7c345f15e1b7b803b6069bed1e5a46d5
parent64c0b0d5744cffaa12921d5202683f3d2718f08c (diff)
downloadgcc-16c730c97a80bdb81e955e8b14d4466d520ec59b.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@24047 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog17
-rw-r--r--gcc/config/mips/mips.h31
-rw-r--r--gcc/config/mips/mips.md478
3 files changed, 388 insertions, 138 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 67856df3c88..c239f45e906 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,20 @@
+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>
* jump.c (jump_optimize): Call regs_set_between_p with PREV_INSN(x),
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index f36398a8862..13f1b7bd227 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -336,16 +336,18 @@ extern void mips_select_section ();
#define MASK_4300_MUL_FIX 0x00080000 /* Work-around early Vr4300 CPU bug */
#define MASK_MIPS3900 0x00100000 /* like -mips1 only 3900 */
#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*/
#define MASK_MIPS_TFILE 0x00000000 /* flag for mips-tfile usage */
/* Debug switches, not documented */
-#define MASK_DEBUG 0x40000000 /* Eliminate version # in .s file */
-#define MASK_DEBUG_A 0x20000000 /* don't allow <label>($reg) addrs */
-#define MASK_DEBUG_B 0x10000000 /* GO_IF_LEGITIMATE_ADDRESS debug */
-#define MASK_DEBUG_C 0x08000000 /* don't expand seq, etc. */
-#define MASK_DEBUG_D 0x04000000 /* don't do define_split's */
+#define MASK_DEBUG 0 /* Eliminate version # in .s file */
+#define MASK_DEBUG_A 0x40000000 /* don't allow <label>($reg) addrs */
+#define MASK_DEBUG_B 0x20000000 /* GO_IF_LEGITIMATE_ADDRESS debug */
+#define MASK_DEBUG_C 0x10000000 /* don't expand seq, etc. */
+#define MASK_DEBUG_D 0 /* don't do define_split's */
#define MASK_DEBUG_E 0 /* function_arg debug */
#define MASK_DEBUG_F 0
#define MASK_DEBUG_G 0 /* don't support 64 bit arithmetic */
@@ -425,6 +427,9 @@ extern void mips_select_section ();
#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
code. */
@@ -490,6 +495,10 @@ extern void mips_select_section ();
{"no-fix4300", -MASK_4300_MUL_FIX}, \
{"4650", MASK_MAD | MASK_SINGLE_FLOAT}, \
{"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}, \
{"debuga", MASK_DEBUG_A}, \
{"debugb", MASK_DEBUG_B}, \
@@ -2144,6 +2153,7 @@ extern struct mips_frame_info current_frame_info;
{ RETURN_ADDRESS_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
{ RETURN_ADDRESS_POINTER_REGNUM, GP_REG_FIRST + 30}, \
{ 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, GP_REG_FIRST + 30}, \
{ FRAME_POINTER_REGNUM, GP_REG_FIRST + 17}}
@@ -2169,11 +2179,14 @@ extern struct mips_frame_info current_frame_info;
*/
#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 \
&& ! (TARGET_MIPS16 && TARGET_64BIT) \
&& (! 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
specifies the initial difference between the specified pair of
@@ -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, \
so we must add 4 bytes to the offset to get the right value. */ \
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)) \
* (BYTES_BIG_ENDIAN != 0)); \
}
diff --git a/gcc/config/mips/mips.md b/gcc/config/mips/mips.md
index 5282fe0939d..14c4457a76e 100644
--- a/gcc/config/mips/mips.md
+++ b/gcc/config/mips/mips.md
@@ -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,46 @@
(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\";
+ rtx label;
- 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],
+ 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 "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 +2289,46 @@
(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\";
+ rtx label;
- 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],
+ 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 "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 +2339,37 @@
(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\";
+ rtx label;
- 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],
+ 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 "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 +2380,372 @@
(clobber (match_scratch:DI 5 "=h"))
(clobber (match_scratch:DI 6 "=a"))]
"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]))
- 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 (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 "mode" "DI")
- (set_attr "length" "8")]) ;; various tests for dividing by 0 and such
+ [(set_attr "type" "unknown")
+ (set_attr "length" "2")])
(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]);
+ rtx label;
+
+ 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"
- [(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]);
+ rtx label;
+
+ 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"
- [(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]);
+ rtx label;
+
+ 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"
- [(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]);
+ rtx label;
+
+ 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"
- [(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]);
+ rtx label;
+
+ 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"
- [(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]);
+ rtx label;
+
+ 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"
- [(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]);
+ rtx label;
+
+ 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"
- [(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]);
+ rtx label;
+
+ 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"
- [(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")])
;;
;; ....................