diff options
author | scox <scox@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-12-01 16:52:56 +0000 |
---|---|---|
committer | scox <scox@138bc75d-0d04-0410-961f-82ee72b054a4> | 1998-12-01 16:52:56 +0000 |
commit | 16c730c97a80bdb81e955e8b14d4466d520ec59b (patch) | |
tree | 39eb2e0c7c345f15e1b7b803b6069bed1e5a46d5 | |
parent | 64c0b0d5744cffaa12921d5202683f3d2718f08c (diff) | |
download | gcc-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/ChangeLog | 17 | ||||
-rw-r--r-- | gcc/config/mips/mips.h | 31 | ||||
-rw-r--r-- | gcc/config/mips/mips.md | 478 |
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")]) ;; ;; .................... |