Files
pkgsrc-ng/cross/COMMON/patches-egcs/patch-st
T
2013-09-26 17:14:40 +02:00

747 lines
25 KiB
Plaintext

--- 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)));