aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authorNick Clifton <nickc@redhat.com>2009-07-06 13:55:09 +0000
committerNick Clifton <nickc@gcc.gnu.org>2009-07-06 13:55:09 +0000
commit7a61cf6f09d0a08de70d1f15f089a79cbec1ab1e (patch)
treef2b4569c011e34c11f7d7c4e6539913dbbd5f507 /gcc/config
parent83f63251d92b61d083e7801e762089b372cbcf8e (diff)
downloadgcc-7a61cf6f09d0a08de70d1f15f089a79cbec1ab1e.zip
gcc-7a61cf6f09d0a08de70d1f15f089a79cbec1ab1e.tar.gz
gcc-7a61cf6f09d0a08de70d1f15f089a79cbec1ab1e.tar.bz2
lib1funcs.h (FMOVD_WORKS): Only define if __FMOVD_ENABLED__ is defined.
* config.sh/lib1funcs.h (FMOVD_WORKS): Only define if __FMOVD_ENABLED__ is defined. * config/sh/sh.h (TARGET_FMOVD): Provide a default definition. (MASK_FMOVD): Likewise. (TARGET_CPU_CPP_BUILTINS): Define __FMOVD_ENABLED__ if TARGET_FMOVD is true. * config/sh/sh.md (movdf_i4): For alternative 0 use either one or two fmov instructions depending upon whether TARGET_FMOVD is enabled. (split for DF load from memory into register): Also handle MEMs which consist of REG+DISP addressing. (split for DF store from register to memory): Likewise. (movsf_ie): Always use single fp_mode. * config/sh/sh.c (sh_override_options): Do not automatically enable TARGET_MOVD for the SH2A when supporting doubles - leave that to the -mfmovd command line switch. (broken_move): Do not restrict fldi test to only the SH4 and SH4A. (fldi_ok): Always allow. * config/sh/sh.opt (mfmovd): Remove this switch. * doc/invoke.texi (-mfmovd): Remove documentation of this switch. Co-Authored-By: DJ Delorie <dj@redhat.com> From-SVN: r149283
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/sh/lib1funcs.h4
-rw-r--r--gcc/config/sh/sh.c15
-rw-r--r--gcc/config/sh/sh.h7
-rw-r--r--gcc/config/sh/sh.md185
-rw-r--r--gcc/config/sh/sh.opt3
5 files changed, 140 insertions, 74 deletions
diff --git a/gcc/config/sh/lib1funcs.h b/gcc/config/sh/lib1funcs.h
index d16a18b..af4b41c 100644
--- a/gcc/config/sh/lib1funcs.h
+++ b/gcc/config/sh/lib1funcs.h
@@ -42,8 +42,8 @@ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
#define ALIAS(X,Y) .global GLOBAL(X); .set GLOBAL(X),GLOBAL(Y)
-#ifdef __SH2A__
-#undef FMOVD_WORKS
+#if defined __SH2A__ && defined __FMOVD_ENABLED__
+#undef FMOVD_WORKS
#define FMOVD_WORKS
#endif
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 08cae31..18123c3 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -694,11 +694,7 @@ sh_override_options (void)
if (TARGET_SH2E)
sh_cpu = PROCESSOR_SH2E;
if (TARGET_SH2A)
- {
- sh_cpu = PROCESSOR_SH2A;
- if (TARGET_SH2A_DOUBLE)
- target_flags |= MASK_FMOVD;
- }
+ sh_cpu = PROCESSOR_SH2A;
if (TARGET_SH3)
sh_cpu = PROCESSOR_SH3;
if (TARGET_SH3E)
@@ -4208,14 +4204,13 @@ broken_move (rtx insn)
&& GET_CODE (SET_SRC (pat)) == CONST_DOUBLE
&& (fp_zero_operand (SET_SRC (pat))
|| fp_one_operand (SET_SRC (pat)))
- /* ??? If this is a -m4 or -m4-single compilation, in general
- we don't know the current setting of fpscr, so disable fldi.
+ /* In general we don't know the current setting of fpscr, so disable fldi.
There is an exception if this was a register-register move
before reload - and hence it was ascertained that we have
single precision setting - and in a post-reload optimization
we changed this to do a constant load. In that case
we don't have an r0 clobber, hence we must use fldi. */
- && (! TARGET_SH4 || TARGET_FMOVD
+ && (TARGET_FMOVD
|| (GET_CODE (XEXP (XVECEXP (PATTERN (insn), 0, 2), 0))
== SCRATCH))
&& REG_P (SET_DEST (pat))
@@ -8876,7 +8871,7 @@ fp_one_operand (rtx op)
return REAL_VALUES_EQUAL (r, dconst1);
}
-/* For -m4 and -m4-single-only, mode switching is used. If we are
+/* In general mode switching is used. If we are
compiling without -mfmovd, movsf_ie isn't taken into account for
mode switching. We could check in machine_dependent_reorg for
cases where we know we are in single precision mode, but there is
@@ -8886,7 +8881,7 @@ fp_one_operand (rtx op)
int
fldi_ok (void)
{
- return ! TARGET_SH4 || TARGET_FMOVD || reload_completed;
+ return 1;
}
int
diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h
index d8b9a29..d9a4c5f 100644
--- a/gcc/config/sh/sh.h
+++ b/gcc/config/sh/sh.h
@@ -28,6 +28,11 @@ along with GCC; see the file COPYING3. If not see
#define TARGET_VERSION \
fputs (" (Hitachi SH)", stderr);
+#ifndef TARGET_FMOVD
+#define TARGET_FMOVD 0
+#define MASK_FMOVD 0
+#endif
+
/* Unfortunately, insn-attrtab.c doesn't include insn-codes.h. We can't
include it here, because bconfig.h is also included by gencodes.c . */
/* ??? No longer true. */
@@ -91,6 +96,8 @@ do { \
builtin_define ("__SH_FPU_DOUBLE__"); \
if (TARGET_HITACHI) \
builtin_define ("__HITACHI__"); \
+ if (TARGET_FMOVD) \
+ builtin_define ("__FMOVD_ENABLED__"); \
builtin_define (TARGET_LITTLE_ENDIAN \
? "__LITTLE_ENDIAN__" : "__BIG_ENDIAN__"); \
} while (0)
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index e446164..30084c2 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -5780,25 +5780,31 @@ label:
;; up pcloads, so we need usable length information for that.
(define_insn "movdf_i4"
[(set (match_operand:DF 0 "general_movdst_operand" "=d,r,d,d,m,r,r,m,!??r,!???d")
- (match_operand:DF 1 "general_movsrc_operand" "d,r,F,m,d,FQ,m,r,d,r"))
- (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c"))
- (clobber (match_scratch:SI 3 "=X,X,&z,X,X,X,X,X,X,X"))]
+ (match_operand:DF 1 "general_movsrc_operand" "d,r,F,m,d,FQ,m,r,d,r"))
+ (use (match_operand:PSI 2 "fpscr_operand" "c,c,c,c,c,c,c,c,c,c"))
+ (clobber (match_scratch:SI 3 "=X,X,&z,X,X,X,X,X,X,X"))]
"(TARGET_SH4 || TARGET_SH2A_DOUBLE)
&& (arith_reg_operand (operands[0], DFmode)
|| arith_reg_operand (operands[1], DFmode))"
- "@
- fmov %1,%0
- #
- #
- fmov.d %1,%0
- fmov.d %1,%0
- #
- #
- #
- #
- #"
+ {
+ switch (which_alternative)
+ {
+ case 0:
+ if (TARGET_FMOVD)
+ return "fmov %1,%0";
+ else if (REGNO (operands[0]) != REGNO (operands[1]) + 1)
+ return "fmov %R1,%R0\n\tfmov %S1,%S0";
+ else
+ return "fmov %S1,%S0\n\tfmov %R1,%R0";
+ case 3:
+ case 4:
+ return "fmov.d %1,%0";
+ default:
+ return "#";
+ }
+ }
[(set_attr_alternative "length"
- [(if_then_else (eq_attr "fmovd" "yes") (const_int 2) (const_int 4))
+ [(if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 8))
(const_int 4)
(if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
(if_then_else (eq_attr "fmovd" "yes") (const_int 4) (const_int 6))
@@ -6032,37 +6038,63 @@ label:
"(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
&& FP_OR_XD_REGISTER_P (true_regnum (operands[0]))"
[(const_int 0)]
- "
{
int regno = true_regnum (operands[0]);
- rtx addr, insn, adjust = NULL_RTX;
+ rtx addr, insn;
rtx mem2 = change_address (operands[1], SFmode, NULL_RTX);
- rtx reg0 = gen_rtx_REG (SFmode, regno + !! TARGET_LITTLE_ENDIAN);
- rtx reg1 = gen_rtx_REG (SFmode, regno + ! TARGET_LITTLE_ENDIAN);
+ rtx reg0 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 1 : 0));
+ rtx reg1 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 0 : 1));
operands[1] = copy_rtx (mem2);
addr = XEXP (mem2, 0);
- if (GET_CODE (addr) != POST_INC)
+
+ switch (GET_CODE (addr))
{
- /* If we have to modify the stack pointer, the value that we have
- read with post-increment might be modified by an interrupt,
- so write it back. */
- if (REGNO (addr) == STACK_POINTER_REGNUM)
- adjust = gen_push_e (reg0);
- else
- adjust = gen_addsi3 (addr, addr, GEN_INT (-4));
- XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
- }
- addr = XEXP (addr, 0);
- insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2]));
- add_reg_note (insn, REG_INC, addr);
- insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
- if (adjust)
- emit_insn (adjust);
- else
- add_reg_note (insn, REG_INC, addr);
+ case REG:
+ /* This is complicated. If the register is an arithmetic register
+ we can just fall through to the REG+DISP case below. Otherwise
+ we have to use a combination of POST_INC and REG addressing... */
+ if (! arith_reg_operand (operands[1], SFmode))
+ {
+ XEXP (mem2, 0) = addr = gen_rtx_POST_INC (SImode, addr);
+ insn = emit_insn (gen_movsf_ie (reg0, mem2, operands[2]));
+ add_reg_note (insn, REG_INC, XEXP (addr, 0));
+
+ emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
+
+ /* If we have modified the stack pointer, the value that we have
+ read with post-increment might be modified by an interrupt,
+ so write it back. */
+ if (REGNO (addr) == STACK_POINTER_REGNUM)
+ emit_insn (gen_push_e (reg0));
+ else
+ emit_insn (gen_addsi3 (XEXP (operands[1], 0), XEXP (operands[1], 0), GEN_INT (-4)));
+ break;
+ }
+ /* Fall through. */
+
+ case PLUS:
+ emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
+ operands[1] = copy_rtx (operands[1]);
+ XEXP (operands[1], 0) = plus_constant (addr, 4);
+ emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
+ break;
+
+ case POST_INC:
+ insn = emit_insn (gen_movsf_ie (reg0, operands[1], operands[2]));
+ add_reg_note (insn, REG_INC, XEXP (addr, 0));
+
+ insn = emit_insn (gen_movsf_ie (reg1, operands[1], operands[2]));
+ add_reg_note (insn, REG_INC, XEXP (addr, 0));
+ break;
+
+ default:
+ debug_rtx (addr);
+ gcc_unreachable ();
+ }
+
DONE;
-}")
+})
(define_split
[(set (match_operand:DF 0 "memory_operand" "")
@@ -6072,35 +6104,70 @@ label:
"(TARGET_SH4 || TARGET_SH2A_DOUBLE) && ! TARGET_FMOVD && reload_completed
&& FP_OR_XD_REGISTER_P (true_regnum (operands[1]))"
[(const_int 0)]
- "
{
int regno = true_regnum (operands[1]);
- rtx insn, addr, adjust = NULL_RTX;
+ rtx insn, addr;
+ rtx reg0 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 1 : 0));
+ rtx reg1 = gen_rtx_REG (SFmode, regno + (TARGET_LITTLE_ENDIAN ? 0 : 1));
operands[0] = copy_rtx (operands[0]);
PUT_MODE (operands[0], SFmode);
- insn = emit_insn (gen_movsf_ie (operands[0],
- gen_rtx_REG (SFmode,
- regno + ! TARGET_LITTLE_ENDIAN),
- operands[2]));
- operands[0] = copy_rtx (operands[0]);
addr = XEXP (operands[0], 0);
- if (GET_CODE (addr) != PRE_DEC)
+
+ switch (GET_CODE (addr))
{
- adjust = gen_addsi3 (addr, addr, GEN_INT (4));
- emit_insn_before (adjust, insn);
- XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr);
+ case REG:
+ /* This is complicated. If the register is an arithmetic register
+ we can just fall through to the REG+DISP case below. Otherwise
+ we have to use a combination of REG and PRE_DEC addressing... */
+ if (! arith_reg_operand (operands[0], SFmode))
+ {
+ emit_insn (gen_addsi3 (addr, addr, GEN_INT (4)));
+ emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
+
+ operands[0] = copy_rtx (operands[0]);
+ XEXP (operands[0], 0) = addr = gen_rtx_PRE_DEC (SImode, addr);
+
+ insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
+ add_reg_note (insn, REG_INC, XEXP (addr, 0));
+ break;
+ }
+ /* Fall through. */
+
+ case PLUS:
+ /* Since REG+DISP addressing has already been decided upon by gcc
+ we can rely upon it having chosen an arithmetic register as the
+ register component of the address. Just emit the lower numbered
+ register first, to the lower address, then the higher numbered
+ register to the higher address. */
+ emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
+
+ operands[0] = copy_rtx (operands[0]);
+ XEXP (operands[0], 0) = plus_constant (addr, 4);
+
+ emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
+ break;
+
+ case PRE_DEC:
+ /* This is easy. Output the word to go to the higher address
+ first (ie the word in the higher numbered register) then the
+ word to go to the lower address. */
+
+ insn = emit_insn (gen_movsf_ie (operands[0], reg1, operands[2]));
+ add_reg_note (insn, REG_INC, XEXP (addr, 0));
+
+ insn = emit_insn (gen_movsf_ie (operands[0], reg0, operands[2]));
+ add_reg_note (insn, REG_INC, XEXP (addr, 0));
+ break;
+
+ default:
+ /* FAIL; */
+ debug_rtx (addr);
+ gcc_unreachable ();
}
- addr = XEXP (addr, 0);
- if (! adjust)
- add_reg_note (insn, REG_INC, addr);
- insn = emit_insn (gen_movsf_ie (operands[0],
- gen_rtx_REG (SFmode,
- regno + !! TARGET_LITTLE_ENDIAN),
- operands[2]));
- add_reg_note (insn, REG_INC, addr);
+
DONE;
-}")
+})
;; If the output is a register and the input is memory or a register, we have
;; to be careful and see which word needs to be loaded first.
@@ -6562,7 +6629,7 @@ label:
(const_int 0)])
(set (attr "fp_mode") (if_then_else (eq_attr "fmovd" "yes")
(const_string "single")
- (const_string "none")))])
+ (const_string "single")))])
(define_split
[(set (match_operand:SF 0 "register_operand" "")
diff --git a/gcc/config/sh/sh.opt b/gcc/config/sh/sh.opt
index f365b2b..b2e7c6d 100644
--- a/gcc/config/sh/sh.opt
+++ b/gcc/config/sh/sh.opt
@@ -248,9 +248,6 @@ mfixed-range=
Target RejectNegative Joined Var(sh_fixed_range_str)
Specify range of registers to make fixed
-mfmovd
-Target RejectNegative Mask(FMOVD) Undocumented
-
mfused-madd
Target Var(TARGET_FMAC)
Enable the use of the fused floating point multiply-accumulate operation