Hello Richard, Your change to gcc 3.5: 2004-05-17 Richard Sandiford <rsandifo@xxxxxxxxxx> * config/mips/mips.h (MASK_DEBUG_G, TARGET_DEBUG_G_MODE): Delete. (TARGET_SWITCHES): Remove debugg. * config/mips/mips.md (adddi3, ashldi3, ashrdi3, lshrdi3): Only handle TARGET_64BIT. (subdi3): Replace the define_expand with a define_insn, the latter renamed from subdi3_internal_3. (negdi2): Likewise negdi2_internal_2. (adddi3_internal_[12], subdi3_internal, ashldi3_internal{,2,3}) (ashrdi3_internal{,2,3}, lshrdi3_internal{,2,3}): Remove patterns and associated define_splits. (adddi3_internal): Renamed from adddi3_internal_3. (ashldi3_internal): Likewise ashldi3_internal4. (ashrdi3_internal): Likewise ashrdi3_internal4. (lshrdi3_internal): Likewise lshrdi3_internal4. breaks 32-bit Linux builds. Linux relies on simple operations (addition/subtraction and shifts) on "long long" variables being implemented inline without a call to libgcc, which isn't linked in. After your change Linux has unresolved references to external __ashldi3(), __ashrdi3() and __lshrdi3() functions at the final link. Here is a complete revert of the relevant changes that works for me, but please feel free to provide a replacement. Either way, please make ashldi3, ashrdi3 and lshrdi3 available for 32-bit targets again. 2004-07-19 Maciej W. Rozycki <macro@xxxxxxxxxxxxxx> * config/mips/mips.md (ashldi3, ashrdi3, lshrdi3): Handle !TARGET_64BIT again, partially reverting the change from 2004-05-17. (ashldi3_internal{,2,3}, ashrdi3_internal{,2,3}, lshrdi3_internal{,2,3}): Restore patterns and associated define_splits. (ashldi3_internal4): Rename from ashldi3_internal. (ashrdi3_internal4): Likewise ashrdi3_internal. (lshrdi3_internal4): Likewise lshrdi3_internal. Maciej gcc-3.5.0-20040714-mips-xshxdi32.patch diff -up --recursive --new-file gcc-3.5.0-20040714.macro/gcc/config/mips/mips.md gcc-3.5.0-20040714/gcc/config/mips/mips.md --- gcc-3.5.0-20040714.macro/gcc/config/mips/mips.md 2004-07-13 04:59:54.000000000 +0000 +++ gcc-3.5.0-20040714/gcc/config/mips/mips.md 2004-07-17 19:00:14.000000000 +0000 @@ -4997,37 +4997,213 @@ dsrl\t%3,%3,1\n\ { operands[2] = GEN_INT (INTVAL (operands[2]) - 8); }) (define_expand "ashldi3" - [(set (match_operand:DI 0 "register_operand") - (ashift:DI (match_operand:DI 1 "register_operand") - (match_operand:SI 2 "arith_operand")))] - "TARGET_64BIT" + [(parallel [(set (match_operand:DI 0 "register_operand") + (ashift:DI (match_operand:DI 1 "register_operand") + (match_operand:SI 2 "arith_operand"))) + (clobber (match_dup 3))])] + "TARGET_64BIT || !TARGET_MIPS16" { - /* On the mips16, a shift of more than 8 is a four byte - instruction, so, for a shift between 8 and 16, it is just as - fast to do two shifts of 8 or less. If there is a lot of - shifting going on, we may win in CSE. Otherwise combine will - put the shifts back together again. This can be called by - function_arg, so we must be careful not to allocate a new - register if we've reached the reload pass. */ - if (TARGET_MIPS16 - && optimize - && GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) > 8 - && INTVAL (operands[2]) <= 16 - && ! reload_in_progress - && ! reload_completed) + if (TARGET_64BIT) { - rtx temp = gen_reg_rtx (DImode); + /* On the mips16, a shift of more than 8 is a four byte + instruction, so, for a shift between 8 and 16, it is just as + fast to do two shifts of 8 or less. If there is a lot of + shifting going on, we may win in CSE. Otherwise combine will + put the shifts back together again. This can be called by + function_arg, so we must be careful not to allocate a new + register if we've reached the reload pass. */ + if (TARGET_MIPS16 + && optimize + && GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) > 8 + && INTVAL (operands[2]) <= 16 + && ! reload_in_progress + && ! reload_completed) + { + rtx temp = gen_reg_rtx (DImode); - emit_insn (gen_ashldi3_internal (temp, operands[1], GEN_INT (8))); - emit_insn (gen_ashldi3_internal (operands[0], temp, - GEN_INT (INTVAL (operands[2]) - 8))); + emit_insn (gen_ashldi3_internal4 (temp, operands[1], GEN_INT (8))); + emit_insn (gen_ashldi3_internal4 (operands[0], temp, + GEN_INT (INTVAL (operands[2]) - 8))); + DONE; + } + + emit_insn (gen_ashldi3_internal4 (operands[0], operands[1], + operands[2])); DONE; } + + operands[3] = gen_reg_rtx (SImode); }) (define_insn "ashldi3_internal" + [(set (match_operand:DI 0 "register_operand" "=&d") + (ashift:DI (match_operand:DI 1 "register_operand" "d") + (match_operand:SI 2 "register_operand" "d"))) + (clobber (match_operand:SI 3 "register_operand" "=d"))] + "!TARGET_64BIT && !TARGET_MIPS16" + "sll\t%3,%2,26\;\ +bgez\t%3,1f%#\;\ +sll\t%M0,%L1,%2\;\ +%(b\t3f\;\ +move\t%L0,%.%)\ +\n\n\ +%~1:\;\ +%(beq\t%3,%.,2f\;\ +sll\t%M0,%M1,%2%)\ +\n\;\ +subu\t%3,%.,%2\;\ +srl\t%3,%L1,%3\;\ +or\t%M0,%M0,%3\n\ +%~2:\;\ +sll\t%L0,%L1,%2\n\ +%~3:" + [(set_attr "type" "multi") + (set_attr "mode" "SI") + (set_attr "length" "48")]) + + +(define_insn "ashldi3_internal2" + [(set (match_operand:DI 0 "register_operand" "=d") + (ashift:DI (match_operand:DI 1 "register_operand" "d") + (match_operand:SI 2 "small_int" "IJK"))) + (clobber (match_operand:SI 3 "register_operand" "=d"))] + "!TARGET_64BIT && !TARGET_MIPS16 + && (INTVAL (operands[2]) & 32) != 0" +{ + operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); + return "sll\t%M0,%L1,%2\;move\t%L0,%."; +} + [(set_attr "type" "multi") + (set_attr "mode" "DI") + (set_attr "length" "8")]) + + +(define_split + [(set (match_operand:DI 0 "register_operand") + (ashift:DI (match_operand:DI 1 "register_operand") + (match_operand:SI 2 "small_int"))) + (clobber (match_operand:SI 3 "register_operand"))] + "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_64BIT + && !TARGET_DEBUG_D_MODE && !TARGET_MIPS16 + && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER + && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER + && (INTVAL (operands[2]) & 32) != 0" + + [(set (subreg:SI (match_dup 0) 4) (ashift:SI (subreg:SI (match_dup 1) 0) (match_dup 2))) + (set (subreg:SI (match_dup 0) 0) (const_int 0))] + + "operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);") + + +(define_split + [(set (match_operand:DI 0 "register_operand") + (ashift:DI (match_operand:DI 1 "register_operand") + (match_operand:SI 2 "small_int"))) + (clobber (match_operand:SI 3 "register_operand"))] + "reload_completed && WORDS_BIG_ENDIAN && !TARGET_64BIT + && !TARGET_DEBUG_D_MODE && !TARGET_MIPS16 + && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER + && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER + && (INTVAL (operands[2]) & 32) != 0" + + [(set (subreg:SI (match_dup 0) 0) (ashift:SI (subreg:SI (match_dup 1) 4) (match_dup 2))) + (set (subreg:SI (match_dup 0) 4) (const_int 0))] + + "operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);") + + +(define_insn "ashldi3_internal3" + [(set (match_operand:DI 0 "register_operand" "=d") + (ashift:DI (match_operand:DI 1 "register_operand" "d") + (match_operand:SI 2 "small_int" "IJK"))) + (clobber (match_operand:SI 3 "register_operand" "=d"))] + "!TARGET_64BIT && !TARGET_MIPS16 + && (INTVAL (operands[2]) & 63) < 32 + && (INTVAL (operands[2]) & 63) != 0" +{ + int amount = INTVAL (operands[2]); + + operands[2] = GEN_INT (amount & 31); + operands[4] = GEN_INT ((-amount) & 31); + + return "sll\t%M0,%M1,%2\;srl\t%3,%L1,%4\;or\t%M0,%M0,%3\;sll\t%L0,%L1,%2"; +} + [(set_attr "type" "multi") + (set_attr "mode" "DI") + (set_attr "length" "16")]) + + +(define_split + [(set (match_operand:DI 0 "register_operand") + (ashift:DI (match_operand:DI 1 "register_operand") + (match_operand:SI 2 "small_int"))) + (clobber (match_operand:SI 3 "register_operand"))] + "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_64BIT + && !TARGET_DEBUG_D_MODE && !TARGET_MIPS16 + && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER + && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER + && (INTVAL (operands[2]) & 63) < 32 + && (INTVAL (operands[2]) & 63) != 0" + + [(set (subreg:SI (match_dup 0) 4) + (ashift:SI (subreg:SI (match_dup 1) 4) + (match_dup 2))) + + (set (match_dup 3) + (lshiftrt:SI (subreg:SI (match_dup 1) 0) + (match_dup 4))) + + (set (subreg:SI (match_dup 0) 4) + (ior:SI (subreg:SI (match_dup 0) 4) + (match_dup 3))) + + (set (subreg:SI (match_dup 0) 0) + (ashift:SI (subreg:SI (match_dup 1) 0) + (match_dup 2)))] +{ + int amount = INTVAL (operands[2]); + operands[2] = GEN_INT (amount & 31); + operands[4] = GEN_INT ((-amount) & 31); +}) + + +(define_split + [(set (match_operand:DI 0 "register_operand") + (ashift:DI (match_operand:DI 1 "register_operand") + (match_operand:SI 2 "small_int"))) + (clobber (match_operand:SI 3 "register_operand"))] + "reload_completed && WORDS_BIG_ENDIAN && !TARGET_64BIT + && !TARGET_DEBUG_D_MODE && !TARGET_MIPS16 + && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER + && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER + && (INTVAL (operands[2]) & 63) < 32 + && (INTVAL (operands[2]) & 63) != 0" + + [(set (subreg:SI (match_dup 0) 0) + (ashift:SI (subreg:SI (match_dup 1) 0) + (match_dup 2))) + + (set (match_dup 3) + (lshiftrt:SI (subreg:SI (match_dup 1) 4) + (match_dup 4))) + + (set (subreg:SI (match_dup 0) 0) + (ior:SI (subreg:SI (match_dup 0) 0) + (match_dup 3))) + + (set (subreg:SI (match_dup 0) 4) + (ashift:SI (subreg:SI (match_dup 1) 4) + (match_dup 2)))] +{ + int amount = INTVAL (operands[2]); + operands[2] = GEN_INT (amount & 31); + operands[4] = GEN_INT ((-amount) & 31); +}) + + +(define_insn "ashldi3_internal4" [(set (match_operand:DI 0 "register_operand" "=d") (ashift:DI (match_operand:DI 1 "register_operand" "d") (match_operand:SI 2 "arith_operand" "dI")))] @@ -5157,33 +5333,208 @@ dsrl\t%3,%3,1\n\ { operands[2] = GEN_INT (INTVAL (operands[2]) - 8); }) (define_expand "ashrdi3" - [(set (match_operand:DI 0 "register_operand") - (ashiftrt:DI (match_operand:DI 1 "register_operand") - (match_operand:SI 2 "arith_operand")))] - "TARGET_64BIT" + [(parallel [(set (match_operand:DI 0 "register_operand") + (ashiftrt:DI (match_operand:DI 1 "register_operand") + (match_operand:SI 2 "arith_operand"))) + (clobber (match_dup 3))])] + "TARGET_64BIT || !TARGET_MIPS16" { - /* On the mips16, a shift of more than 8 is a four byte - instruction, so, for a shift between 8 and 16, it is just as - fast to do two shifts of 8 or less. If there is a lot of - shifting going on, we may win in CSE. Otherwise combine will - put the shifts back together again. */ - if (TARGET_MIPS16 - && optimize - && GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) > 8 - && INTVAL (operands[2]) <= 16) + if (TARGET_64BIT) { - rtx temp = gen_reg_rtx (DImode); + /* On the mips16, a shift of more than 8 is a four byte + instruction, so, for a shift between 8 and 16, it is just as + fast to do two shifts of 8 or less. If there is a lot of + shifting going on, we may win in CSE. Otherwise combine will + put the shifts back together again. */ + if (TARGET_MIPS16 + && optimize + && GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) > 8 + && INTVAL (operands[2]) <= 16) + { + rtx temp = gen_reg_rtx (DImode); + + emit_insn (gen_ashrdi3_internal4 (temp, operands[1], GEN_INT (8))); + emit_insn (gen_ashrdi3_internal4 (operands[0], temp, + GEN_INT (INTVAL (operands[2]) - 8))); + DONE; + } - emit_insn (gen_ashrdi3_internal (temp, operands[1], GEN_INT (8))); - emit_insn (gen_ashrdi3_internal (operands[0], temp, - GEN_INT (INTVAL (operands[2]) - 8))); + emit_insn (gen_ashrdi3_internal4 (operands[0], operands[1], + operands[2])); DONE; } + + operands[3] = gen_reg_rtx (SImode); }) (define_insn "ashrdi3_internal" + [(set (match_operand:DI 0 "register_operand" "=&d") + (ashiftrt:DI (match_operand:DI 1 "register_operand" "d") + (match_operand:SI 2 "register_operand" "d"))) + (clobber (match_operand:SI 3 "register_operand" "=d"))] + "!TARGET_64BIT && !TARGET_MIPS16" + "sll\t%3,%2,26\;\ +bgez\t%3,1f%#\;\ +sra\t%L0,%M1,%2\;\ +%(b\t3f\;\ +sra\t%M0,%M1,31%)\ +\n\n\ +%~1:\;\ +%(beq\t%3,%.,2f\;\ +srl\t%L0,%L1,%2%)\ +\n\;\ +subu\t%3,%.,%2\;\ +sll\t%3,%M1,%3\;\ +or\t%L0,%L0,%3\n\ +%~2:\;\ +sra\t%M0,%M1,%2\n\ +%~3:" + [(set_attr "type" "multi") + (set_attr "mode" "DI") + (set_attr "length" "48")]) + + +(define_insn "ashrdi3_internal2" + [(set (match_operand:DI 0 "register_operand" "=d") + (ashiftrt:DI (match_operand:DI 1 "register_operand" "d") + (match_operand:SI 2 "small_int" "IJK"))) + (clobber (match_operand:SI 3 "register_operand" "=d"))] + "!TARGET_64BIT && (INTVAL (operands[2]) & 32) != 0" +{ + operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); + return "sra\t%L0,%M1,%2\;sra\t%M0,%M1,31"; +} + [(set_attr "type" "multi") + (set_attr "mode" "DI") + (set_attr "length" "8")]) + + +(define_split + [(set (match_operand:DI 0 "register_operand") + (ashiftrt:DI (match_operand:DI 1 "register_operand") + (match_operand:SI 2 "small_int"))) + (clobber (match_operand:SI 3 "register_operand"))] + "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_64BIT + && !TARGET_DEBUG_D_MODE + && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER + && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER + && (INTVAL (operands[2]) & 32) != 0" + + [(set (subreg:SI (match_dup 0) 0) (ashiftrt:SI (subreg:SI (match_dup 1) 4) (match_dup 2))) + (set (subreg:SI (match_dup 0) 4) (ashiftrt:SI (subreg:SI (match_dup 1) 4) (const_int 31)))] + + "operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);") + + +(define_split + [(set (match_operand:DI 0 "register_operand") + (ashiftrt:DI (match_operand:DI 1 "register_operand") + (match_operand:SI 2 "small_int"))) + (clobber (match_operand:SI 3 "register_operand"))] + "reload_completed && WORDS_BIG_ENDIAN && !TARGET_64BIT + && !TARGET_DEBUG_D_MODE + && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER + && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER + && (INTVAL (operands[2]) & 32) != 0" + + [(set (subreg:SI (match_dup 0) 4) (ashiftrt:SI (subreg:SI (match_dup 1) 0) (match_dup 2))) + (set (subreg:SI (match_dup 0) 0) (ashiftrt:SI (subreg:SI (match_dup 1) 0) (const_int 31)))] + + "operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);") + + +(define_insn "ashrdi3_internal3" + [(set (match_operand:DI 0 "register_operand" "=d") + (ashiftrt:DI (match_operand:DI 1 "register_operand" "d") + (match_operand:SI 2 "small_int" "IJK"))) + (clobber (match_operand:SI 3 "register_operand" "=d"))] + "!TARGET_64BIT && !TARGET_MIPS16 + && (INTVAL (operands[2]) & 63) < 32 + && (INTVAL (operands[2]) & 63) != 0" +{ + int amount = INTVAL (operands[2]); + + operands[2] = GEN_INT (amount & 31); + operands[4] = GEN_INT ((-amount) & 31); + + return "srl\t%L0,%L1,%2\;sll\t%3,%M1,%4\;or\t%L0,%L0,%3\;sra\t%M0,%M1,%2"; +} + [(set_attr "type" "multi") + (set_attr "mode" "DI") + (set_attr "length" "16")]) + + +(define_split + [(set (match_operand:DI 0 "register_operand") + (ashiftrt:DI (match_operand:DI 1 "register_operand") + (match_operand:SI 2 "small_int"))) + (clobber (match_operand:SI 3 "register_operand"))] + "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_64BIT + && !TARGET_DEBUG_D_MODE && !TARGET_MIPS16 + && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER + && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER + && (INTVAL (operands[2]) & 63) < 32 + && (INTVAL (operands[2]) & 63) != 0" + + [(set (subreg:SI (match_dup 0) 0) + (lshiftrt:SI (subreg:SI (match_dup 1) 0) + (match_dup 2))) + + (set (match_dup 3) + (ashift:SI (subreg:SI (match_dup 1) 4) + (match_dup 4))) + + (set (subreg:SI (match_dup 0) 0) + (ior:SI (subreg:SI (match_dup 0) 0) + (match_dup 3))) + + (set (subreg:SI (match_dup 0) 4) + (ashiftrt:SI (subreg:SI (match_dup 1) 4) + (match_dup 2)))] +{ + int amount = INTVAL (operands[2]); + operands[2] = GEN_INT (amount & 31); + operands[4] = GEN_INT ((-amount) & 31); +}) + + +(define_split + [(set (match_operand:DI 0 "register_operand") + (ashiftrt:DI (match_operand:DI 1 "register_operand") + (match_operand:SI 2 "small_int"))) + (clobber (match_operand:SI 3 "register_operand"))] + "reload_completed && WORDS_BIG_ENDIAN && !TARGET_64BIT + && !TARGET_DEBUG_D_MODE && !TARGET_MIPS16 + && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER + && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER + && (INTVAL (operands[2]) & 63) < 32 + && (INTVAL (operands[2]) & 63) != 0" + + [(set (subreg:SI (match_dup 0) 4) + (lshiftrt:SI (subreg:SI (match_dup 1) 4) + (match_dup 2))) + + (set (match_dup 3) + (ashift:SI (subreg:SI (match_dup 1) 0) + (match_dup 4))) + + (set (subreg:SI (match_dup 0) 4) + (ior:SI (subreg:SI (match_dup 0) 4) + (match_dup 3))) + + (set (subreg:SI (match_dup 0) 0) + (ashiftrt:SI (subreg:SI (match_dup 1) 0) + (match_dup 2)))] +{ + int amount = INTVAL (operands[2]); + operands[2] = GEN_INT (amount & 31); + operands[4] = GEN_INT ((-amount) & 31); +}) + + +(define_insn "ashrdi3_internal4" [(set (match_operand:DI 0 "register_operand" "=d") (ashiftrt:DI (match_operand:DI 1 "register_operand" "d") (match_operand:SI 2 "arith_operand" "dI")))] @@ -5332,33 +5683,209 @@ dsrl\t%3,%3,1\n\ (set_attr "length" "16")]) (define_expand "lshrdi3" - [(set (match_operand:DI 0 "register_operand") - (lshiftrt:DI (match_operand:DI 1 "register_operand") - (match_operand:SI 2 "arith_operand")))] - "TARGET_64BIT" + [(parallel [(set (match_operand:DI 0 "register_operand") + (lshiftrt:DI (match_operand:DI 1 "register_operand") + (match_operand:SI 2 "arith_operand"))) + (clobber (match_dup 3))])] + "TARGET_64BIT || !TARGET_MIPS16" { - /* On the mips16, a shift of more than 8 is a four byte - instruction, so, for a shift between 8 and 16, it is just as - fast to do two shifts of 8 or less. If there is a lot of - shifting going on, we may win in CSE. Otherwise combine will - put the shifts back together again. */ - if (TARGET_MIPS16 - && optimize - && GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) > 8 - && INTVAL (operands[2]) <= 16) + if (TARGET_64BIT) { - rtx temp = gen_reg_rtx (DImode); + /* On the mips16, a shift of more than 8 is a four byte + instruction, so, for a shift between 8 and 16, it is just as + fast to do two shifts of 8 or less. If there is a lot of + shifting going on, we may win in CSE. Otherwise combine will + put the shifts back together again. */ + if (TARGET_MIPS16 + && optimize + && GET_CODE (operands[2]) == CONST_INT + && INTVAL (operands[2]) > 8 + && INTVAL (operands[2]) <= 16) + { + rtx temp = gen_reg_rtx (DImode); - emit_insn (gen_lshrdi3_internal (temp, operands[1], GEN_INT (8))); - emit_insn (gen_lshrdi3_internal (operands[0], temp, - GEN_INT (INTVAL (operands[2]) - 8))); + emit_insn (gen_lshrdi3_internal4 (temp, operands[1], GEN_INT (8))); + emit_insn (gen_lshrdi3_internal4 (operands[0], temp, + GEN_INT (INTVAL (operands[2]) - 8))); + DONE; + } + + emit_insn (gen_lshrdi3_internal4 (operands[0], operands[1], + operands[2])); DONE; } + + operands[3] = gen_reg_rtx (SImode); }) (define_insn "lshrdi3_internal" + [(set (match_operand:DI 0 "register_operand" "=&d") + (lshiftrt:DI (match_operand:DI 1 "register_operand" "d") + (match_operand:SI 2 "register_operand" "d"))) + (clobber (match_operand:SI 3 "register_operand" "=d"))] + "!TARGET_64BIT && !TARGET_MIPS16" + "sll\t%3,%2,26\;\ +bgez\t%3,1f%#\;\ +srl\t%L0,%M1,%2\;\ +%(b\t3f\;\ +move\t%M0,%.%)\ +\n\n\ +%~1:\;\ +%(beq\t%3,%.,2f\;\ +srl\t%L0,%L1,%2%)\ +\n\;\ +subu\t%3,%.,%2\;\ +sll\t%3,%M1,%3\;\ +or\t%L0,%L0,%3\n\ +%~2:\;\ +srl\t%M0,%M1,%2\n\ +%~3:" + [(set_attr "type" "multi") + (set_attr "mode" "DI") + (set_attr "length" "48")]) + + +(define_insn "lshrdi3_internal2" + [(set (match_operand:DI 0 "register_operand" "=d") + (lshiftrt:DI (match_operand:DI 1 "register_operand" "d") + (match_operand:SI 2 "small_int" "IJK"))) + (clobber (match_operand:SI 3 "register_operand" "=d"))] + "!TARGET_64BIT && !TARGET_MIPS16 + && (INTVAL (operands[2]) & 32) != 0" +{ + operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f); + return "srl\t%L0,%M1,%2\;move\t%M0,%."; +} + [(set_attr "type" "multi") + (set_attr "mode" "DI") + (set_attr "length" "8")]) + + +(define_split + [(set (match_operand:DI 0 "register_operand") + (lshiftrt:DI (match_operand:DI 1 "register_operand") + (match_operand:SI 2 "small_int"))) + (clobber (match_operand:SI 3 "register_operand"))] + "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_64BIT + && !TARGET_DEBUG_D_MODE && !TARGET_MIPS16 + && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER + && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER + && (INTVAL (operands[2]) & 32) != 0" + + [(set (subreg:SI (match_dup 0) 0) (lshiftrt:SI (subreg:SI (match_dup 1) 4) (match_dup 2))) + (set (subreg:SI (match_dup 0) 4) (const_int 0))] + + "operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);") + + +(define_split + [(set (match_operand:DI 0 "register_operand") + (lshiftrt:DI (match_operand:DI 1 "register_operand") + (match_operand:SI 2 "small_int"))) + (clobber (match_operand:SI 3 "register_operand"))] + "reload_completed && WORDS_BIG_ENDIAN && !TARGET_64BIT + && !TARGET_DEBUG_D_MODE && !TARGET_MIPS16 + && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER + && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER + && (INTVAL (operands[2]) & 32) != 0" + + [(set (subreg:SI (match_dup 0) 4) (lshiftrt:SI (subreg:SI (match_dup 1) 0) (match_dup 2))) + (set (subreg:SI (match_dup 0) 0) (const_int 0))] + + "operands[2] = GEN_INT (INTVAL (operands[2]) & 0x1f);") + + +(define_insn "lshrdi3_internal3" + [(set (match_operand:DI 0 "register_operand" "=d") + (lshiftrt:DI (match_operand:DI 1 "register_operand" "d") + (match_operand:SI 2 "small_int" "IJK"))) + (clobber (match_operand:SI 3 "register_operand" "=d"))] + "!TARGET_64BIT && !TARGET_MIPS16 + && (INTVAL (operands[2]) & 63) < 32 + && (INTVAL (operands[2]) & 63) != 0" +{ + int amount = INTVAL (operands[2]); + + operands[2] = GEN_INT (amount & 31); + operands[4] = GEN_INT ((-amount) & 31); + + return "srl\t%L0,%L1,%2\;sll\t%3,%M1,%4\;or\t%L0,%L0,%3\;srl\t%M0,%M1,%2"; +} + [(set_attr "type" "multi") + (set_attr "mode" "DI") + (set_attr "length" "16")]) + + +(define_split + [(set (match_operand:DI 0 "register_operand") + (lshiftrt:DI (match_operand:DI 1 "register_operand") + (match_operand:SI 2 "small_int"))) + (clobber (match_operand:SI 3 "register_operand"))] + "reload_completed && !WORDS_BIG_ENDIAN && !TARGET_64BIT + && !TARGET_DEBUG_D_MODE && !TARGET_MIPS16 + && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER + && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER + && (INTVAL (operands[2]) & 63) < 32 + && (INTVAL (operands[2]) & 63) != 0" + + [(set (subreg:SI (match_dup 0) 0) + (lshiftrt:SI (subreg:SI (match_dup 1) 0) + (match_dup 2))) + + (set (match_dup 3) + (ashift:SI (subreg:SI (match_dup 1) 4) + (match_dup 4))) + + (set (subreg:SI (match_dup 0) 0) + (ior:SI (subreg:SI (match_dup 0) 0) + (match_dup 3))) + + (set (subreg:SI (match_dup 0) 4) + (lshiftrt:SI (subreg:SI (match_dup 1) 4) + (match_dup 2)))] +{ + int amount = INTVAL (operands[2]); + operands[2] = GEN_INT (amount & 31); + operands[4] = GEN_INT ((-amount) & 31); +}) + + +(define_split + [(set (match_operand:DI 0 "register_operand") + (lshiftrt:DI (match_operand:DI 1 "register_operand") + (match_operand:SI 2 "small_int"))) + (clobber (match_operand:SI 3 "register_operand"))] + "reload_completed && WORDS_BIG_ENDIAN && !TARGET_64BIT + && !TARGET_DEBUG_D_MODE && !TARGET_MIPS16 + && GET_CODE (operands[0]) == REG && REGNO (operands[0]) < FIRST_PSEUDO_REGISTER + && GET_CODE (operands[1]) == REG && REGNO (operands[1]) < FIRST_PSEUDO_REGISTER + && (INTVAL (operands[2]) & 63) < 32 + && (INTVAL (operands[2]) & 63) != 0" + + [(set (subreg:SI (match_dup 0) 4) + (lshiftrt:SI (subreg:SI (match_dup 1) 4) + (match_dup 2))) + + (set (match_dup 3) + (ashift:SI (subreg:SI (match_dup 1) 0) + (match_dup 4))) + + (set (subreg:SI (match_dup 0) 4) + (ior:SI (subreg:SI (match_dup 0) 4) + (match_dup 3))) + + (set (subreg:SI (match_dup 0) 0) + (lshiftrt:SI (subreg:SI (match_dup 1) 0) + (match_dup 2)))] +{ + int amount = INTVAL (operands[2]); + operands[2] = GEN_INT (amount & 31); + operands[4] = GEN_INT ((-amount) & 31); +}) + + +(define_insn "lshrdi3_internal4" [(set (match_operand:DI 0 "register_operand" "=d") (lshiftrt:DI (match_operand:DI 1 "register_operand" "d") (match_operand:SI 2 "arith_operand" "dI")))]