summaryrefslogtreecommitdiff
path: root/cross/COMMON
diff options
context:
space:
mode:
authormsaitoh <msaitoh@pkgsrc.org>2001-01-22 21:04:12 +0000
committermsaitoh <msaitoh@pkgsrc.org>2001-01-22 21:04:12 +0000
commit2a887ba07639277f1b354ff31dfe2cbac3241d08 (patch)
treef7ff8cbf498bd92702ea65feecb6631d3127f2c0 /cross/COMMON
parent707845f16f6d756aa4c7495dfc59a5c99acd4193 (diff)
downloadpkgsrc-2a887ba07639277f1b354ff31dfe2cbac3241d08.tar.gz
patches for sh3. Sync with:
gnu/dist/gcc/config/sh/sh.c rev. 1.7 sh.h rev. 1.5 sh.md rev. 1.7
Diffstat (limited to 'cross/COMMON')
-rw-r--r--cross/COMMON/patches-egcs/patch-st746
1 files changed, 746 insertions, 0 deletions
diff --git a/cross/COMMON/patches-egcs/patch-st b/cross/COMMON/patches-egcs/patch-st
new file mode 100644
index 00000000000..29c7c4265ab
--- /dev/null
+++ b/cross/COMMON/patches-egcs/patch-st
@@ -0,0 +1,746 @@
+--- gcc/config/sh/sh.c.orig Wed Feb 24 10:44:34 1999
++++ gcc/config/sh/sh.c Mon Jan 22 21:09:51 2001
+@@ -22,6 +22,8 @@
+ Improved by Jim Wilson (wilson@cygnus.com). */
+
+ #include "config.h"
++#include "system.h"
++#include "insn-config.h"
+
+ #include <stdio.h>
+
+@@ -29,11 +31,15 @@
+ #include "tree.h"
+ #include "flags.h"
+ #include "insn-flags.h"
++#include "except.h"
+ #include "expr.h"
++#include "function.h"
+ #include "regs.h"
+ #include "hard-reg-set.h"
+ #include "output.h"
+ #include "insn-attr.h"
++#include "toplev.h"
++#include "recog.h"
+
+ int code_for_indirect_jump_scratch = CODE_FOR_indirect_jump_scratch;
+
+@@ -131,7 +137,8 @@
+ switch (GET_CODE (x))
+ {
+ case REG:
+- fprintf (stream, "@%s", reg_names[REGNO (x)]);
++ case SUBREG:
++ fprintf (stream, "@%s", reg_names[true_regnum (x)]);
+ break;
+
+ case PLUS:
+@@ -143,13 +150,19 @@
+ {
+ case CONST_INT:
+ fprintf (stream, "@(%d,%s)", INTVAL (index),
+- reg_names[REGNO (base)]);
++ reg_names[true_regnum (base)]);
+ break;
+
+ case REG:
+- fprintf (stream, "@(r0,%s)",
+- reg_names[MAX (REGNO (base), REGNO (index))]);
++ case SUBREG:
++ {
++ int base_num = true_regnum (base);
++ int index_num = true_regnum (index);
++
++ fprintf (stream, "@(r0,%s)",
++ reg_names[MAX (base_num,index_num)]);
+ break;
++ }
+
+ default:
+ debug_rtx (x);
+@@ -159,11 +172,11 @@
+ break;
+
+ case PRE_DEC:
+- fprintf (stream, "@-%s", reg_names[REGNO (XEXP (x, 0))]);
++ fprintf (stream, "@-%s", reg_names[true_regnum (XEXP (x, 0))]);
+ break;
+
+ case POST_INC:
+- fprintf (stream, "@%s+", reg_names[REGNO (XEXP (x, 0))]);
++ fprintf (stream, "@%s+", reg_names[true_regnum (XEXP (x, 0))]);
+ break;
+
+ default:
+@@ -230,16 +243,31 @@
+ fputs (reg_names[REGNO (x) + 1], (stream));
+ break;
+ case MEM:
+- print_operand_address (stream,
+- XEXP (adj_offsettable_operand (x, 4), 0));
++ if (GET_CODE (XEXP (x, 0)) != PRE_DEC
++ && GET_CODE (XEXP (x, 0)) != POST_INC)
++ x = adj_offsettable_operand (x, 4);
++ print_operand_address (stream, XEXP (x, 0));
+ break;
+ }
+ break;
++ case 'o':
++ switch (GET_CODE (x))
++ {
++ case PLUS: fputs ("add", stream); break;
++ case MINUS: fputs ("sub", stream); break;
++ case MULT: fputs ("mul", stream); break;
++ case DIV: fputs ("div", stream); break;
++ }
++ break;
+ default:
+ switch (GET_CODE (x))
+ {
+ case REG:
+- fputs (reg_names[REGNO (x)], (stream));
++ if (REGNO (x) >= FIRST_FP_REG && REGNO (x) <= LAST_FP_REG
++ && GET_MODE_SIZE (GET_MODE (x)) > 4)
++ fprintf ((stream), "d%s", reg_names[REGNO (x)]+1);
++ else
++ fputs (reg_names[REGNO (x)], (stream));
+ break;
+ case MEM:
+ output_address (XEXP (x, 0));
+@@ -402,6 +430,7 @@
+ if ((code != EQ && code != NE
+ && (sh_compare_op1 != const0_rtx
+ || code == GTU || code == GEU || code == LTU || code == LEU))
++ || (mode == DImode && sh_compare_op1 != const0_rtx)
+ || TARGET_SH3E && GET_MODE_CLASS (mode) == MODE_FLOAT)
+ sh_compare_op1 = force_reg (mode, sh_compare_op1);
+
+@@ -694,9 +723,9 @@
+
+ char *
+ output_ieee_ccmpeq (insn, operands)
+- rtx insn, operands;
++ rtx insn, *operands;
+ {
+- output_branchy_insn (NE, "bt\t%l9\\;fcmp/eq\t%1,%0", insn, operands);
++ return output_branchy_insn (NE, "bt\t%l9\\;fcmp/eq\t%1,%0", insn, operands);
+ }
+
+ /* Output to FILE the start of the assembler file. */
+@@ -1602,8 +1631,16 @@
+ case 5:
+ {
+ int i = 16 - size;
+- emit_insn (gen_shl_sext_ext (dest, source, GEN_INT (16 - insize),
+- GEN_INT (16)));
++ if (! rtx_equal_function_value_matters
++ && ! reload_in_progress && ! reload_completed)
++ emit_insn (gen_shl_sext_ext (dest, source, left_rtx, size_rtx));
++ else
++ {
++ operands[0] = dest;
++ operands[2] = GEN_INT (16 - insize);
++ gen_shifty_hi_op (ASHIFT, operands);
++ emit_insn (gen_extendhisi2 (dest, gen_lowpart (HImode, dest)));
++ }
+ /* Don't use gen_ashrsi3 because it generates new pseudos. */
+ while (--i >= 0)
+ gen_ashift (ASHIFTRT, 1, dest);
+@@ -2124,7 +2161,7 @@
+ for (i = XVECLEN (pattern, 0) - 1; i >= 0; i--)
+ {
+ part = XVECEXP (pattern, 0, i);
+- if (part == reg_part)
++ if (part == reg_part || GET_CODE (part) == CLOBBER)
+ continue;
+ if (reg_mentioned_p (reg, ((GET_CODE (part) == SET
+ && GET_CODE (SET_DEST (part)) == REG)
+@@ -2464,6 +2501,13 @@
+ }
+ else
+ jump = emit_jump_insn_after (gen_return (), insn);
++ /* Emit a barrier so that reorg knows that any following instructions
++ are not reachable via a fall-through path.
++ But don't do this when not optimizing, since we wouldn't supress the
++ alignment for the barrier then, and could end up with out-of-range
++ pc-relative loads. */
++ if (optimize)
++ emit_barrier_after (jump);
+ emit_label_after (bp->near_label, insn);
+ JUMP_LABEL (jump) = bp->far_label;
+ if (! invert_jump (insn, label))
+@@ -2481,7 +2525,7 @@
+
+ for (insn = first; insn; insn = NEXT_INSN (insn))
+ {
+- rtx vec_lab, pat, prev, prevpat, x;
++ rtx vec_lab, pat, prev, prevpat, x, braf_label;
+
+ if (GET_CODE (insn) != JUMP_INSN
+ || GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC)
+@@ -2504,10 +2548,15 @@
+ if (GET_CODE (x) == LABEL_REF && XEXP (x, 0) == vec_lab)
+ break;
+ }
++
++ /* Emit the reference label of the braf where it belongs, right after
++ the casesi_jump_2 (i.e. braf). */
++ braf_label = XEXP (XEXP (SET_SRC (XVECEXP (prevpat, 0, 0)), 1), 0);
++ emit_label_after (braf_label, prev);
++
+ /* Fix up the ADDR_DIF_VEC to be relative
+ to the reference address of the braf. */
+- XEXP (XEXP (pat, 0), 0)
+- = XEXP (XEXP (SET_SRC (XVECEXP (prevpat, 0, 0)), 1), 0);
++ XEXP (XEXP (pat, 0), 0) = braf_label;
+ }
+ }
+
+--- gcc/config/sh/sh.h.orig Mon Jun 1 23:25:44 1998
++++ gcc/config/sh/sh.h Mon Jan 22 21:09:51 2001
+@@ -1143,7 +1143,8 @@
+ else if ((GET_CODE (X) == POST_INC || GET_CODE (X) == PRE_DEC) \
+ && BASE_REGISTER_RTX_P (XEXP ((X), 0))) \
+ goto LABEL; \
+- else if (GET_CODE (X) == PLUS && MODE != PSImode) \
++ else if (GET_CODE (X) == PLUS \
++ && ((MODE) != PSImode || reload_completed)) \
+ { \
+ rtx xop0 = XEXP ((X), 0); \
+ rtx xop1 = XEXP ((X), 1); \
+@@ -1465,7 +1466,7 @@
+ and another. */
+
+ #define REGISTER_MOVE_COST(SRCCLASS, DSTCLASS) \
+- ((DSTCLASS) == PR_REG ? 10 \
++ ((DSTCLASS) == PR_REGS ? 10 \
+ : (((DSTCLASS) == FP_REGS && (SRCCLASS) == GENERAL_REGS) \
+ || ((DSTCLASS) == GENERAL_REGS && (SRCCLASS) == FP_REGS)) ? 4 \
+ : 1)
+@@ -1566,10 +1567,10 @@
+ }
+
+ #define ASM_OUTPUT_REG_PUSH(file, v) \
+- fprintf ((file), "\tmov.l\tr%s,-@r15\n", (v));
++ fprintf ((file), "\tmov.l\tr%d,@-r15\n", (v));
+
+ #define ASM_OUTPUT_REG_POP(file, v) \
+- fprintf ((file), "\tmov.l\t@r15+,r%s\n", (v));
++ fprintf ((file), "\tmov.l\t@r15+,r%d\n", (v));
+
+ /* The assembler's names for the registers. RFP need not always be used as
+ the Real framepointer; it can also be used as a normal general register.
+@@ -1957,3 +1958,5 @@
+ #define HAVE_ATEXIT
+
+ #define SH_DYNAMIC_SHIFT_COST (TARGET_SH3 ? (TARGET_SMALLCODE ? 1 : 2) : 20)
++
++#define DWARF_LINE_MIN_INSTR_LENGTH 2
+--- gcc/config/sh/sh.md.orig Thu Apr 23 22:37:16 1998
++++ gcc/config/sh/sh.md Mon Jan 22 21:09:51 2001
+@@ -661,7 +661,7 @@
+ ;; This reload would clobber the value in r0 we are trying to store.
+ ;; If we let reload allocate r0, then this problem can never happen.
+
+-(define_insn ""
++(define_insn "udivsi3_i1"
+ [(set (match_operand:SI 0 "register_operand" "=z")
+ (udiv:SI (reg:SI 4) (reg:SI 5)))
+ (clobber (reg:SI 18))
+@@ -674,9 +674,9 @@
+ (set_attr "needs_delay_slot" "yes")])
+
+ (define_expand "udivsi3"
+- [(set (reg:SI 4) (match_operand:SI 1 "general_operand" ""))
++ [(set (match_dup 3) (symbol_ref:SI "__udivsi3"))
++ (set (reg:SI 4) (match_operand:SI 1 "general_operand" ""))
+ (set (reg:SI 5) (match_operand:SI 2 "general_operand" ""))
+- (set (match_dup 3) (symbol_ref:SI "__udivsi3"))
+ (parallel [(set (match_operand:SI 0 "register_operand" "")
+ (udiv:SI (reg:SI 4)
+ (reg:SI 5)))
+@@ -685,9 +685,26 @@
+ (clobber (reg:SI 4))
+ (use (match_dup 3))])]
+ ""
+- "operands[3] = gen_reg_rtx(SImode);")
++ "
++{
++ rtx first, last;
+
+-(define_insn ""
++ operands[3] = gen_reg_rtx(SImode);
++ /* Emit the move of the address to a pseudo outside of the libcall. */
++ emit_move_insn (operands[3],
++ gen_rtx_SYMBOL_REF (SImode, \"__udivsi3\"));
++ last = gen_udivsi3_i1 (operands[0], operands[3]);
++ first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
++ emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
++ last = emit_insn (last);
++ /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
++ invariant code motion can move it. */
++ REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
++ REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
++ DONE;
++}")
++
++(define_insn "divsi3_i1"
+ [(set (match_operand:SI 0 "register_operand" "=z")
+ (div:SI (reg:SI 4) (reg:SI 5)))
+ (clobber (reg:SI 18))
+@@ -702,9 +719,9 @@
+ (set_attr "needs_delay_slot" "yes")])
+
+ (define_expand "divsi3"
+- [(set (reg:SI 4) (match_operand:SI 1 "general_operand" ""))
++ [(set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
++ (set (reg:SI 4) (match_operand:SI 1 "general_operand" ""))
+ (set (reg:SI 5) (match_operand:SI 2 "general_operand" ""))
+- (set (match_dup 3) (symbol_ref:SI "__sdivsi3"))
+ (parallel [(set (match_operand:SI 0 "register_operand" "")
+ (div:SI (reg:SI 4)
+ (reg:SI 5)))
+@@ -715,13 +732,29 @@
+ (clobber (reg:SI 3))
+ (use (match_dup 3))])]
+ ""
+- "operands[3] = gen_reg_rtx(SImode);")
++ "
++{
++ rtx first, last;
++
++ operands[3] = gen_reg_rtx(SImode);
++ /* Emit the move of the address to a pseudo outside of the libcall. */
++ emit_move_insn (operands[3], gen_rtx_SYMBOL_REF (SImode, \"__sdivsi3\"));
++ last = gen_divsi3_i1 (operands[0], operands[3]);
++ first = emit_move_insn (gen_rtx_REG (SImode, 4), operands[1]);
++ emit_move_insn (gen_rtx_REG (SImode, 5), operands[2]);
++ last = emit_insn (last);
++ /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
++ invariant code motion can move it. */
++ REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
++ REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
++ DONE;
++}")
+
+ ;; -------------------------------------------------------------------------
+ ;; Multiplication instructions
+ ;; -------------------------------------------------------------------------
+
+-(define_insn ""
++(define_insn "umulhisi3_i"
+ [(set (reg:SI 21)
+ (mult:SI (zero_extend:SI (match_operand:HI 0 "arith_reg_operand" "r"))
+ (zero_extend:SI (match_operand:HI 1 "arith_reg_operand" "r"))))]
+@@ -729,7 +762,7 @@
+ "mulu %1,%0"
+ [(set_attr "type" "smpy")])
+
+-(define_insn ""
++(define_insn "mulhisi3_i"
+ [(set (reg:SI 21)
+ (mult:SI (sign_extend:SI
+ (match_operand:HI 0 "arith_reg_operand" "r"))
+@@ -748,7 +781,18 @@
+ (set (match_operand:SI 0 "arith_reg_operand" "")
+ (reg:SI 21))]
+ ""
+- "")
++ "
++{
++ rtx first, last;
++
++ first = emit_insn (gen_mulhisi3_i (operands[1], operands[2]));
++ last = emit_move_insn (operands[0], gen_rtx_REG (SImode, 21));
++ /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
++ invariant code motion can move it. */
++ REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
++ REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
++ DONE;
++}")
+
+ (define_expand "umulhisi3"
+ [(set (reg:SI 21)
+@@ -759,7 +803,18 @@
+ (set (match_operand:SI 0 "arith_reg_operand" "")
+ (reg:SI 21))]
+ ""
+- "")
++ "
++{
++ rtx first, last;
++
++ first = emit_insn (gen_umulhisi3_i (operands[1], operands[2]));
++ last = emit_move_insn (operands[0], gen_rtx_REG (SImode, 21));
++ /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
++ invariant code motion can move it. */
++ REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
++ REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
++ DONE;
++}")
+
+ ;; mulsi3 on the SH2 can be done in one instruction, on the SH1 we generate
+ ;; a call to a routine which clobbers known registers.
+@@ -782,7 +837,6 @@
+ (define_expand "mulsi3_call"
+ [(set (reg:SI 4) (match_operand:SI 1 "general_operand" ""))
+ (set (reg:SI 5) (match_operand:SI 2 "general_operand" ""))
+- (set (match_dup 3) (symbol_ref:SI "__mulsi3"))
+ (parallel[(set (match_operand:SI 0 "register_operand" "")
+ (mult:SI (reg:SI 4)
+ (reg:SI 5)))
+@@ -792,9 +846,9 @@
+ (clobber (reg:SI 3))
+ (clobber (reg:SI 2))
+ (clobber (reg:SI 1))
+- (use (match_dup 3))])]
++ (use (match_operand:SI 3 "register_operand" ""))])]
+ ""
+- "operands[3] = gen_reg_rtx(SImode);")
++ "")
+
+ (define_insn "mul_l"
+ [(set (reg:SI 21)
+@@ -813,82 +867,120 @@
+ ""
+ "
+ {
++ rtx first, last;
++
+ if (!TARGET_SH2)
+ {
+- FAIL;
+- /* ??? Does this give worse or better code? */
+- emit_insn (gen_mulsi3_call (operands[0], operands[1], operands[2]));
+- DONE;
++ /* The address must be set outside the libcall,
++ since it goes into a pseudo. */
++ rtx addr = force_reg (SImode, gen_rtx_SYMBOL_REF (SImode, \"__mulsi3\"));
++ rtx insns = gen_mulsi3_call (operands[0], operands[1], operands[2], addr);
++ first = XVECEXP (insns, 0, 0);
++ last = XVECEXP (insns, 0, XVECLEN (insns, 0) - 1);
++ emit_insn (insns);
+ }
++ else
++ {
++ rtx macl = gen_rtx_REG (SImode, MACL_REG);
++
++ first = emit_insn (gen_mul_l (operands[1], operands[2]));
++ /* consec_sets_giv can only recognize the first insn that sets a
++ giv as the giv insn. So we must tag this also with a REG_EQUAL
++ note. */
++ last = emit_insn (gen_movsi_i ((operands[0]), macl));
++ }
++ /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
++ invariant code motion can move it. */
++ REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
++ REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
++ DONE;
+ }")
+
+ (define_insn "mulsidi3_i"
+- [(set (reg:DI 20)
+- (mult:DI (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
+- (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))))]
++ [(set (reg:SI 20)
++ (truncate:SI
++ (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
++ (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
++ (const_int 32))))
++ (set (reg:SI 21)
++ (mult:SI (match_dup 0)
++ (match_dup 1)))]
+ "TARGET_SH2"
+ "dmuls.l %1,%0"
+ [(set_attr "type" "dmpy")])
+
+-(define_expand "mulsidi3"
+- [(set (reg:DI 20)
++(define_insn "mulsidi3"
++ [(set (match_operand:DI 0 "arith_reg_operand" "=r")
++ (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
++ (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
++ (clobber (reg:DI 20))]
++ "TARGET_SH2"
++ "#")
++
++(define_split
++ [(set (match_operand:DI 0 "arith_reg_operand" "")
+ (mult:DI (sign_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
+ (sign_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
+- (set (match_operand:DI 0 "arith_reg_operand" "")
+- (reg:DI 20))]
++ (clobber (reg:DI 20))]
+ "TARGET_SH2"
++ [(const_int 0)]
+ "
+ {
+- /* We must swap the two words when copying them from MACH/MACL to the
+- output register. */
+- if (TARGET_LITTLE_ENDIAN)
+- {
+- rtx low_dst = operand_subword (operands[0], 0, 1, DImode);
+- rtx high_dst = operand_subword (operands[0], 1, 1, DImode);
+-
+- emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
+-
+- emit_insn (gen_rtx (CLOBBER, VOIDmode, operands[0]));
+- emit_move_insn (low_dst, gen_rtx (REG, SImode, 21));
+- emit_move_insn (high_dst, gen_rtx (REG, SImode, 20));
+- DONE;
+- }
++ rtx low_dst = gen_lowpart (SImode, operands[0]);
++ rtx high_dst = gen_highpart (SImode, operands[0]);
++
++ emit_insn (gen_mulsidi3_i (operands[1], operands[2]));
++
++ emit_move_insn (low_dst, gen_rtx_REG (SImode, 21));
++ emit_move_insn (high_dst, gen_rtx_REG (SImode, 20));
++ /* We need something to tag the possible REG_EQUAL notes on to. */
++ emit_move_insn (operands[0], operands[0]);
++ DONE;
+ }")
+
+ (define_insn "umulsidi3_i"
+- [(set (reg:DI 20)
+- (mult:DI (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
+- (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))))]
++ [(set (reg:SI 20)
++ (truncate:SI
++ (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
++ (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r")))
++ (const_int 32))))
++ (set (reg:SI 21)
++ (mult:SI (match_dup 0)
++ (match_dup 1)))]
+ "TARGET_SH2"
+ "dmulu.l %1,%0"
+ [(set_attr "type" "dmpy")])
+
+-(define_expand "umulsidi3"
+- [(set (reg:DI 20)
++(define_insn "umulsidi3"
++ [(set (match_operand:DI 0 "arith_reg_operand" "=r")
++ (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" "r"))
++ (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" "r"))))
++ (clobber (reg:DI 20))]
++ "TARGET_SH2"
++ "#")
++
++(define_split
++ [(set (match_operand:DI 0 "arith_reg_operand" "")
+ (mult:DI (zero_extend:DI (match_operand:SI 1 "arith_reg_operand" ""))
+ (zero_extend:DI (match_operand:SI 2 "arith_reg_operand" ""))))
+- (set (match_operand:DI 0 "arith_reg_operand" "")
+- (reg:DI 20))]
++ (clobber (reg:DI 20))]
+ "TARGET_SH2"
++ [(const_int 0)]
+ "
+ {
+- /* We must swap the two words when copying them from MACH/MACL to the
+- output register. */
+- if (TARGET_LITTLE_ENDIAN)
+- {
+- rtx low_dst = operand_subword (operands[0], 0, 1, DImode);
+- rtx high_dst = operand_subword (operands[0], 1, 1, DImode);
+-
+- emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
+-
+- emit_insn (gen_rtx (CLOBBER, VOIDmode, operands[0]));
+- emit_move_insn (low_dst, gen_rtx (REG, SImode, 21));
+- emit_move_insn (high_dst, gen_rtx (REG, SImode, 20));
+- DONE;
+- }
++ rtx low_dst = gen_lowpart (SImode, operands[0]);
++ rtx high_dst = gen_highpart (SImode, operands[0]);
++
++ emit_insn (gen_umulsidi3_i (operands[1], operands[2]));
++
++ emit_move_insn (low_dst, gen_rtx_REG (SImode, 21));
++ emit_move_insn (high_dst, gen_rtx_REG (SImode, 20));
++ /* We need something to tag the possible REG_EQUAL notes on to. */
++ emit_move_insn (operands[0], operands[0]);
++ DONE;
+ }")
+
+-(define_insn ""
++(define_insn "smulsi3_highpart_i"
+ [(set (reg:SI 20)
+ (truncate:SI
+ (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
+@@ -909,9 +1001,27 @@
+ (set (match_operand:SI 0 "arith_reg_operand" "")
+ (reg:SI 20))]
+ "TARGET_SH2"
+- "")
++ "
++{
++ rtx first, last;
+
+-(define_insn ""
++ first = emit_insn (gen_smulsi3_highpart_i (operands[1], operands[2]));
++ last = emit_move_insn (operands[0], gen_rtx_REG (SImode, 20));
++ /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
++ invariant code motion can move it. */
++ REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
++ REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
++ /* expand_binop can't find a suitable code in mul_highpart_optab to
++ make a REG_EQUAL note from, so make one here.
++ ??? Alternatively, we could put this at the calling site of expand_binop,
++ i.e. expand_mult_highpart. */
++ REG_NOTES (last)
++ = gen_rtx_EXPR_LIST (REG_EQUAL, copy_rtx (SET_SRC (single_set (first))),
++ REG_NOTES (last));
++ DONE;
++}")
++
++(define_insn "umulsi3_highpart_i"
+ [(set (reg:SI 20)
+ (truncate:SI
+ (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 0 "arith_reg_operand" "r"))
+@@ -932,7 +1042,18 @@
+ (set (match_operand:SI 0 "arith_reg_operand" "")
+ (reg:SI 20))]
+ "TARGET_SH2"
+- "")
++ "
++{
++ rtx first, last;
++
++ first = emit_insn (gen_umulsi3_highpart_i (operands[1], operands[2]));
++ last = emit_move_insn (operands[0], gen_rtx_REG (SImode, 20));
++ /* Wrap the sequence in REG_LIBCALL / REG_RETVAL notes so that loop
++ invariant code motion can move it. */
++ REG_NOTES (first) = gen_rtx_INSN_LIST (REG_LIBCALL, last, REG_NOTES (first));
++ REG_NOTES (last) = gen_rtx_INSN_LIST (REG_RETVAL, first, REG_NOTES (last));
++ DONE;
++}")
+
+ ;; -------------------------------------------------------------------------
+ ;; Logical operations
+@@ -1825,19 +1946,20 @@
+ ""
+ "sett")
+
+-;; t/r is first, so that it will be preferred over r/r when reloading a move
+-;; of a pseudo-reg into the T reg
++;; t/r must come after r/r, lest reload will try to reload stuff like
++;; (set (subreg:SI (mem:QI (plus:SI (reg:SI 15 r15) (const_int 12)) 0) 0)
++;; (made from (set (subreg:SI (reg:QI 73) 0) ) into T.
+ (define_insn "movsi_i"
+- [(set (match_operand:SI 0 "general_movdst_operand" "=t,r,r,r,r,r,m,<,<,xl,x,l,r")
+- (match_operand:SI 1 "general_movsrc_operand" "r,Q,rI,m,xl,t,r,x,l,r,>,>,i"))]
++ [(set (match_operand:SI 0 "general_movdst_operand" "=r,r,t,r,r,r,m,<,<,xl,x,l,r")
++ (match_operand:SI 1 "general_movsrc_operand" "Q,rI,r,mr,xl,t,r,x,l,r,>,>,i"))]
+ "
+ ! TARGET_SH3E
+ && (register_operand (operands[0], SImode)
+ || register_operand (operands[1], SImode))"
+ "@
+- cmp/pl %1
+ mov.l %1,%0
+ mov %1,%0
++ cmp/pl %1
+ mov.l %1,%0
+ sts %1,%0
+ movt %0
+@@ -1848,7 +1970,7 @@
+ lds.l %1,%0
+ lds.l %1,%0
+ fake %1,%0"
+- [(set_attr "type" "*,pcload_si,move,load_si,move,move,store,store,pstore,move,load,pload,pcload_si")
++ [(set_attr "type" "pcload_si,move,*,load_si,move,move,store,store,pstore,move,load,pload,pcload_si")
+ (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*")])
+
+ ;; t/r must come after r/r, lest reload will try to reload stuff like
+@@ -1856,8 +1978,8 @@
+ ;; ??? This allows moves from macl to fpul to be recognized, but these moves
+ ;; will require a reload.
+ (define_insn "movsi_ie"
+- [(set (match_operand:SI 0 "general_movdst_operand" "=r,r,t,r,r,r,m,<,<,xl,x,l,r,y,r,y")
+- (match_operand:SI 1 "general_movsrc_operand" "Q,rI,r,m,xl,t,r,x,l,r,>,>,i,r,y,y"))]
++ [(set (match_operand:SI 0 "general_movdst_operand" "=r,r,t,r,r,r,m,<,<,xl,x,l,y,r,y,r,y")
++ (match_operand:SI 1 "general_movsrc_operand" "Q,rI,r,mr,xl,t,r,x,l,r,>,>,>,i,r,y,y"))]
+ "TARGET_SH3E
+ && (register_operand (operands[0], SImode)
+ || register_operand (operands[1], SImode))"
+@@ -1874,16 +1996,17 @@
+ lds %1,%0
+ lds.l %1,%0
+ lds.l %1,%0
++ lds.l %1,%0
+ fake %1,%0
+ lds %1,%0
+ sts %1,%0
+ ! move optimized away"
+- [(set_attr "type" "pcload_si,move,*,load_si,move,move,store,store,pstore,move,load,pload,pcload_si,gp_fpul,gp_fpul,nil")
+- (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,0")])
++ [(set_attr "type" "pcload_si,move,*,load_si,move,move,store,store,pstore,move,load,pload,load,pcload_si,gp_fpul,gp_fpul,nil")
++ (set_attr "length" "*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,*,0")])
+
+ (define_insn "movsi_i_lowpart"
+ [(set (strict_low_part (match_operand:SI 0 "general_movdst_operand" "=r,r,r,r,r,m,r"))
+- (match_operand:SI 1 "general_movsrc_operand" "Q,rI,m,xl,t,r,i"))]
++ (match_operand:SI 1 "general_movsrc_operand" "Q,rI,mr,xl,t,r,i"))]
+ "register_operand (operands[0], SImode)
+ || register_operand (operands[1], SImode)"
+ "@
+@@ -2087,7 +2210,8 @@
+ FAIL;
+ reg = XEXP (addr, 0);
+ const_int = XEXP (addr, 1);
+- if (GET_CODE (reg) != REG || GET_CODE (const_int) != CONST_INT)
++ if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
++ && GET_CODE (const_int) == CONST_INT))
+ FAIL;
+ emit_move_insn (operands[2], const_int);
+ emit_move_insn (operands[0],
+@@ -2113,7 +2237,8 @@
+ FAIL;
+ reg = XEXP (addr, 0);
+ const_int = XEXP (addr, 1);
+- if (GET_CODE (reg) != REG || GET_CODE (const_int) != CONST_INT)
++ if (! (BASE_REGISTER_RTX_P (reg) && INDEX_REGISTER_RTX_P (operands[2])
++ && GET_CODE (const_int) == CONST_INT))
+ FAIL;
+ emit_move_insn (operands[2], const_int);
+ emit_move_insn (change_address (operands[1], VOIDmode,
+@@ -2249,7 +2374,7 @@
+ ;; This one has the additional purpose to record a possible scratch register
+ ;; for the following branch.
+ (define_insn "indirect_jump_scratch"
+- [(set (match_operand 0 "register_operand" "r")
++ [(set (match_operand 0 "register_operand" "=r")
+ (unspec [(match_operand 1 "const_int_operand" "")] 4))]
+ ""
+ ""
+@@ -2478,7 +2603,7 @@
+ {
+ int i;
+
+- emit_call_insn (gen_call (operands[0], const0_rtx, const0_rtx, const0_rtx));
++ emit_call_insn (gen_call (operands[0], const0_rtx));
+
+ for (i = 0; i < XVECLEN (operands[2], 0); i++)
+ {
+@@ -2974,6 +3099,7 @@
+ (use (match_operand:SI 0 "arith_reg_operand" "r"))
+ (use (reg:SI 6))
+ (clobber (reg:SI 17))
++ (clobber (reg:SI 18))
+ (clobber (reg:SI 4))
+ (clobber (reg:SI 5))
+ (clobber (reg:SI 6))
+@@ -3144,10 +3270,9 @@
+
+ size /= 8;
+ orig_address = XEXP (operands[0], 0);
+- addr_target = gen_reg_rtx (SImode);
+ shift_reg = gen_reg_rtx (SImode);
+ emit_insn (gen_movsi (shift_reg, operands[3]));
+- emit_insn (gen_addsi3 (addr_target, orig_address, GEN_INT (size - 1)));
++ addr_target = copy_addr_to_reg (plus_constant (orig_address, size - 1));
+
+ operands[0] = change_address (operands[0], QImode, addr_target);
+ emit_insn (gen_movqi (operands[0], gen_rtx (SUBREG, QImode, shift_reg, 0)));