diff options
author | msaitoh <msaitoh@pkgsrc.org> | 2001-01-22 21:04:12 +0000 |
---|---|---|
committer | msaitoh <msaitoh@pkgsrc.org> | 2001-01-22 21:04:12 +0000 |
commit | 2a887ba07639277f1b354ff31dfe2cbac3241d08 (patch) | |
tree | f7ff8cbf498bd92702ea65feecb6631d3127f2c0 /cross | |
parent | 707845f16f6d756aa4c7495dfc59a5c99acd4193 (diff) | |
download | pkgsrc-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')
-rw-r--r-- | cross/COMMON/patches-egcs/patch-st | 746 |
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))); |