Commit cdeed45a by Kaz Kojima

sh-protos.h (sh_legitimate_index_p): Declare.

	* config/sh/sh-protos.h (sh_legitimate_index_p): Declare.
	(sh_legitimate_address_p): Likewise.
	* config/sh/sh.c (sh_legitimate_index_p): New.
	(sh_legitimate_address_p): Likewise.
	* config/sh/sh.h (REG_OK_FOR_BASE_P): Add STRICT parameter.
	(REG_OK_FOR_INDEX_P, SUBREG_OK_FOR_INDEX_P): Likewise.
	(MODE_DISP_OK_4, MODE_DISP_OK_8): Remove.
	(MAYBE_BASE_REGISTER_RTX_P): New macro.
	(MAYBE_INDEX_REGISTER_RTX_P): Likewise.
	(BASE_REGISTER_RTX_P): Use MAYBE_BASE_REGISTER_RTX_P.
	(INDEX_REGISTER_RTX_P): Use MAYBE_INDEX_REGISTER_RTX_P.
	(GO_IF_LEGITIMATE_INDEX): Use sh_legitimate_index_p.
	(GO_IF_LEGITIMATE_ADDRESS): Use sh_legitimate_address_p.

From-SVN: r147450
parent 11953426
2009-05-12 Kaz Kojima <kkojima@gcc.gnu.org>
* config/sh/sh-protos.h (sh_legitimate_index_p): Declare.
(sh_legitimate_address_p): Likewise.
* config/sh/sh.c (sh_legitimate_index_p): New.
(sh_legitimate_address_p): Likewise.
* config/sh/sh.h (REG_OK_FOR_BASE_P): Add STRICT parameter.
(REG_OK_FOR_INDEX_P, SUBREG_OK_FOR_INDEX_P): Likewise.
(MODE_DISP_OK_4, MODE_DISP_OK_8): Remove.
(MAYBE_BASE_REGISTER_RTX_P): New macro.
(MAYBE_INDEX_REGISTER_RTX_P): Likewise.
(BASE_REGISTER_RTX_P): Use MAYBE_BASE_REGISTER_RTX_P.
(INDEX_REGISTER_RTX_P): Use MAYBE_INDEX_REGISTER_RTX_P.
(GO_IF_LEGITIMATE_INDEX): Use sh_legitimate_index_p.
(GO_IF_LEGITIMATE_ADDRESS): Use sh_legitimate_address_p.
2009-05-12 Jan Hubicka <jh@suse.cz> 2009-05-12 Jan Hubicka <jh@suse.cz>
* tree-inline.c (estimate_operator_cost): Add operands; * tree-inline.c (estimate_operator_cost): Add operands;
......
...@@ -58,6 +58,8 @@ extern int fp_zero_operand (rtx); ...@@ -58,6 +58,8 @@ extern int fp_zero_operand (rtx);
extern int fp_one_operand (rtx); extern int fp_one_operand (rtx);
extern int fp_int_operand (rtx); extern int fp_int_operand (rtx);
extern rtx get_fpscr_rtx (void); extern rtx get_fpscr_rtx (void);
extern bool sh_legitimate_index_p (enum machine_mode, rtx);
extern bool sh_legitimate_address_p (enum machine_mode, rtx, bool);
extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx); extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx);
extern int nonpic_symbol_mentioned_p (rtx); extern int nonpic_symbol_mentioned_p (rtx);
extern void emit_sf_insn (rtx); extern void emit_sf_insn (rtx);
......
...@@ -8950,6 +8950,124 @@ sh_insn_length_adjustment (rtx insn) ...@@ -8950,6 +8950,124 @@ sh_insn_length_adjustment (rtx insn)
return 0; return 0;
} }
/* Return TRUE for a valid displacement for the REG+disp addressing
with MODE. */
/* ??? The SH2e does not have the REG+disp addressing mode when loading values
into the FRx registers. We implement this by setting the maximum offset
to zero when the value is SFmode. This also restricts loading of SFmode
values into the integer registers, but that can't be helped. */
/* The SH allows a displacement in a QI or HI amode, but only when the
other operand is R0. GCC doesn't handle this very well, so we forgot
all of that.
A legitimate index for a QI or HI is 0, SI can be any number 0..63,
DI can be any number 0..60. */
bool
sh_legitimate_index_p (enum machine_mode mode, rtx op)
{
if (GET_CODE (op) == CONST_INT)
{
if (TARGET_SHMEDIA)
{
int size;
/* Check if this the address of an unaligned load / store. */
if (mode == VOIDmode)
return CONST_OK_FOR_I06 (INTVAL (op));
size = GET_MODE_SIZE (mode);
return (!(INTVAL (op) & (size - 1))
&& INTVAL (op) >= -512 * size
&& INTVAL (op) < 512 * size);
}
if (TARGET_SH2A)
{
if (GET_MODE_SIZE (mode) == 1
&& (unsigned) INTVAL (op) < 4096)
return true;
}
if ((GET_MODE_SIZE (mode) == 4
&& (unsigned) INTVAL (op) < 64
&& !(INTVAL (op) & 3)
&& !(TARGET_SH2E && mode == SFmode))
|| (GET_MODE_SIZE (mode) == 4
&& (unsigned) INTVAL (op) < 16383
&& !(INTVAL (op) & 3) && TARGET_SH2A))
return true;
if ((GET_MODE_SIZE (mode) == 8
&& (unsigned) INTVAL (op) < 60
&& !(INTVAL (op) & 3)
&& !((TARGET_SH4 || TARGET_SH2A) && mode == DFmode))
|| ((GET_MODE_SIZE (mode)==8)
&& (unsigned) INTVAL (op) < 8192
&& !(INTVAL (op) & (TARGET_SH2A_DOUBLE ? 7 : 3))
&& (TARGET_SH2A && mode == DFmode)))
return true;
}
return false;
}
/* Recognize an RTL expression that is a valid memory address for
an instruction.
The MODE argument is the machine mode for the MEM expression
that wants to use this address.
Allow REG
REG+disp
REG+r0
REG++
--REG */
bool
sh_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
{
if (MAYBE_BASE_REGISTER_RTX_P (x, strict))
return true;
else if ((GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_DEC)
&& ! TARGET_SHMEDIA
&& MAYBE_BASE_REGISTER_RTX_P (XEXP (x, 0), strict))
return true;
else if (GET_CODE (x) == PLUS
&& (mode != PSImode || reload_completed))
{
rtx xop0 = XEXP (x, 0);
rtx xop1 = XEXP (x, 1);
if (GET_MODE_SIZE (mode) <= 8
&& MAYBE_BASE_REGISTER_RTX_P (xop0, strict)
&& sh_legitimate_index_p (mode, xop1))
return true;
if ((ALLOW_INDEXED_ADDRESS || GET_MODE (x) == DImode
|| ((xop0 == stack_pointer_rtx
|| xop0 == hard_frame_pointer_rtx)
&& REG_P (xop1) && REGNO (xop1) == R0_REG)
|| ((xop1 == stack_pointer_rtx
|| xop1 == hard_frame_pointer_rtx)
&& REG_P (xop0) && REGNO (xop0) == R0_REG))
&& ((!TARGET_SHMEDIA && GET_MODE_SIZE (mode) <= 4)
|| (TARGET_SHMEDIA && GET_MODE_SIZE (mode) <= 8)
|| ((TARGET_SH4 || TARGET_SH2A_DOUBLE)
&& TARGET_FMOVD && mode == DFmode)))
{
if (MAYBE_BASE_REGISTER_RTX_P (xop1, strict)
&& MAYBE_INDEX_REGISTER_RTX_P (xop0, strict))
return true;
if (MAYBE_INDEX_REGISTER_RTX_P (xop1, strict)
&& MAYBE_BASE_REGISTER_RTX_P (xop0, strict))
return true;
}
}
return false;
}
/* Return TRUE if X references a SYMBOL_REF or LABEL_REF whose symbol /* Return TRUE if X references a SYMBOL_REF or LABEL_REF whose symbol
isn't protected by a PIC unspec. */ isn't protected by a PIC unspec. */
int int
......
...@@ -2191,45 +2191,25 @@ struct sh_args { ...@@ -2191,45 +2191,25 @@ struct sh_args {
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx /* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
and check its validity for a certain class. and check its validity for a certain class.
We have two alternate definitions for each of them. The suitable hard regs are always accepted and all pseudo regs
The usual definition accepts all pseudo regs; the other rejects are also accepted if STRICT is not set. */
them unless they have been allocated suitable hard regs.
The symbol REG_OK_STRICT causes the latter definition to be used. */ /* Nonzero if X is a reg that can be used as a base reg. */
#define REG_OK_FOR_BASE_P(X, STRICT) \
#ifndef REG_OK_STRICT (GENERAL_OR_AP_REGISTER_P (REGNO (X)) \
|| (!STRICT && REGNO (X) >= FIRST_PSEUDO_REGISTER))
/* Nonzero if X is a hard reg that can be used as a base reg
or if it is a pseudo reg. */ /* Nonzero if X is a reg that can be used as an index. */
#define REG_OK_FOR_BASE_P(X) \ #define REG_OK_FOR_INDEX_P(X, STRICT) \
(GENERAL_OR_AP_REGISTER_P (REGNO (X)) || REGNO (X) >= FIRST_PSEUDO_REGISTER) ((TARGET_SHMEDIA ? GENERAL_REGISTER_P (REGNO (X)) \
: REGNO (X) == R0_REG) \
/* Nonzero if X is a hard reg that can be used as an index || (!STRICT && REGNO (X) >= FIRST_PSEUDO_REGISTER))
or if it is a pseudo reg. */
#define REG_OK_FOR_INDEX_P(X) \ /* Nonzero if X/OFFSET is a reg that can be used as an index. */
((TARGET_SHMEDIA ? GENERAL_REGISTER_P (REGNO (X)) \ #define SUBREG_OK_FOR_INDEX_P(X, OFFSET, STRICT) \
: REGNO (X) == R0_REG) || REGNO (X) >= FIRST_PSEUDO_REGISTER) ((TARGET_SHMEDIA ? GENERAL_REGISTER_P (REGNO (X)) \
: REGNO (X) == R0_REG && OFFSET == 0) \
/* Nonzero if X/OFFSET is a hard reg that can be used as an index || (!STRICT && REGNO (X) >= FIRST_PSEUDO_REGISTER))
or if X is a pseudo reg. */
#define SUBREG_OK_FOR_INDEX_P(X, OFFSET) \
((TARGET_SHMEDIA ? GENERAL_REGISTER_P (REGNO (X)) \
: REGNO (X) == R0_REG && OFFSET == 0) || REGNO (X) >= FIRST_PSEUDO_REGISTER)
#else
/* Nonzero if X is a hard reg that can be used as a base reg. */
#define REG_OK_FOR_BASE_P(X) \
REGNO_OK_FOR_BASE_P (REGNO (X))
/* Nonzero if X is a hard reg that can be used as an index. */
#define REG_OK_FOR_INDEX_P(X) \
REGNO_OK_FOR_INDEX_P (REGNO (X))
/* Nonzero if X/OFFSET is a hard reg that can be used as an index. */
#define SUBREG_OK_FOR_INDEX_P(X, OFFSET) \
(REGNO_OK_FOR_INDEX_P (REGNO (X)) && (OFFSET) == 0)
#endif
/* Macros for extra constraints. */ /* Macros for extra constraints. */
...@@ -2305,144 +2285,55 @@ struct sh_args { ...@@ -2305,144 +2285,55 @@ struct sh_args {
|| PCREL_SYMOFF_P (OP)) \ || PCREL_SYMOFF_P (OP)) \
: NON_PIC_REFERENCE_P (OP)) : NON_PIC_REFERENCE_P (OP))
/* GO_IF_LEGITIMATE_ADDRESS recognizes an RTL expression #define MAYBE_BASE_REGISTER_RTX_P(X, STRICT) \
that is a valid memory address for an instruction. ((GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X, STRICT)) \
The MODE argument is the machine mode for the MEM expression || (GET_CODE (X) == SUBREG \
that wants to use this address. */ && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (GET_MODE ((X))), \
#define MODE_DISP_OK_4(X,MODE) \
(GET_MODE_SIZE (MODE) == 4 && (unsigned) INTVAL (X) < 64 \
&& ! (INTVAL (X) & 3) && ! (TARGET_SH2E && (MODE) == SFmode))
#define MODE_DISP_OK_8(X,MODE) \
((GET_MODE_SIZE(MODE)==8) && ((unsigned)INTVAL(X)<60) \
&& ! (INTVAL(X) & 3) && ! (TARGET_SH4 && (MODE) == DFmode))
#undef MODE_DISP_OK_4
#define MODE_DISP_OK_4(X,MODE) \
((GET_MODE_SIZE (MODE) == 4 && (unsigned) INTVAL (X) < 64 \
&& ! (INTVAL (X) & 3) && ! (TARGET_SH2E && (MODE) == SFmode)) \
|| ((GET_MODE_SIZE(MODE)==4) && ((unsigned)INTVAL(X)<16383) \
&& ! (INTVAL(X) & 3) && TARGET_SH2A))
#undef MODE_DISP_OK_8
#define MODE_DISP_OK_8(X,MODE) \
(((GET_MODE_SIZE(MODE)==8) && ((unsigned)INTVAL(X)<60) \
&& ! (INTVAL(X) & 3) && ! ((TARGET_SH4 || TARGET_SH2A) && (MODE) == DFmode)) \
|| ((GET_MODE_SIZE(MODE)==8) && ((unsigned)INTVAL(X)<8192) \
&& ! (INTVAL(X) & (TARGET_SH2A_DOUBLE ? 7 : 3)) && (TARGET_SH2A && (MODE) == DFmode)))
#define BASE_REGISTER_RTX_P(X) \
((GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \
|| (GET_CODE (X) == SUBREG \
&& TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (GET_MODE ((X))), \
GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (X)))) \ GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (X)))) \
&& GET_CODE (SUBREG_REG (X)) == REG \ && GET_CODE (SUBREG_REG (X)) == REG \
&& REG_OK_FOR_BASE_P (SUBREG_REG (X)))) && REG_OK_FOR_BASE_P (SUBREG_REG (X), STRICT)))
/* Since this must be r0, which is a single register class, we must check /* Since this must be r0, which is a single register class, we must check
SUBREGs more carefully, to be sure that we don't accept one that extends SUBREGs more carefully, to be sure that we don't accept one that extends
outside the class. */ outside the class. */
#define INDEX_REGISTER_RTX_P(X) \ #define MAYBE_INDEX_REGISTER_RTX_P(X, STRICT) \
((GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X)) \ ((GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X, STRICT)) \
|| (GET_CODE (X) == SUBREG \ || (GET_CODE (X) == SUBREG \
&& TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (GET_MODE ((X))), \ && TRULY_NOOP_TRUNCATION (GET_MODE_BITSIZE (GET_MODE ((X))), \
GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (X)))) \ GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (X)))) \
&& GET_CODE (SUBREG_REG (X)) == REG \ && GET_CODE (SUBREG_REG (X)) == REG \
&& SUBREG_OK_FOR_INDEX_P (SUBREG_REG (X), SUBREG_BYTE (X)))) && SUBREG_OK_FOR_INDEX_P (SUBREG_REG (X), SUBREG_BYTE (X), STRICT)))
/* Jump to LABEL if X is a valid address RTX. This must also take
REG_OK_STRICT into account when deciding about valid registers, but it uses
the above macros so we are in luck.
Allow REG #ifdef REG_OK_STRICT
REG+disp #define BASE_REGISTER_RTX_P(X) MAYBE_BASE_REGISTER_RTX_P(X, true)
REG+r0 #define INDEX_REGISTER_RTX_P(X) MAYBE_INDEX_REGISTER_RTX_P(X, true)
REG++ #else
--REG */ #define BASE_REGISTER_RTX_P(X) MAYBE_BASE_REGISTER_RTX_P(X, false)
#define INDEX_REGISTER_RTX_P(X) MAYBE_INDEX_REGISTER_RTX_P(X, false)
/* ??? The SH2e does not have the REG+disp addressing mode when loading values #endif
into the FRx registers. We implement this by setting the maximum offset
to zero when the value is SFmode. This also restricts loading of SFmode
values into the integer registers, but that can't be helped. */
/* The SH allows a displacement in a QI or HI amode, but only when the
other operand is R0. GCC doesn't handle this very well, so we forgo
all of that.
A legitimate index for a QI or HI is 0, SI can be any number 0..63,
DI can be any number 0..60. */
#define GO_IF_LEGITIMATE_INDEX(MODE, OP, LABEL) \
do { \
if (GET_CODE (OP) == CONST_INT) \
{ \
if (TARGET_SHMEDIA) \
{ \
int MODE_SIZE; \
/* Check if this the address of an unaligned load / store. */\
if ((MODE) == VOIDmode) \
{ \
if (CONST_OK_FOR_I06 (INTVAL (OP))) \
goto LABEL; \
break; \
} \
MODE_SIZE = GET_MODE_SIZE (MODE); \
if (! (INTVAL (OP) & (MODE_SIZE - 1)) \
&& INTVAL (OP) >= -512 * MODE_SIZE \
&& INTVAL (OP) < 512 * MODE_SIZE) \
goto LABEL; \
else \
break; \
} \
if (TARGET_SH2A) \
{ \
if (GET_MODE_SIZE (MODE) == 1 \
&& (unsigned) INTVAL (OP) < 4096) \
goto LABEL; \
} \
if (MODE_DISP_OK_4 ((OP), (MODE))) goto LABEL; \
if (MODE_DISP_OK_8 ((OP), (MODE))) goto LABEL; \
} \
} while(0)
#define ALLOW_INDEXED_ADDRESS \ #define ALLOW_INDEXED_ADDRESS \
((!TARGET_SHMEDIA32 && !TARGET_SHCOMPACT) || TARGET_ALLOW_INDEXED_ADDRESS) ((!TARGET_SHMEDIA32 && !TARGET_SHCOMPACT) || TARGET_ALLOW_INDEXED_ADDRESS)
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \ #define GO_IF_LEGITIMATE_INDEX(MODE, OP, WIN) \
{ \ do { \
if (BASE_REGISTER_RTX_P (X)) \ if (sh_legitimate_index_p ((MODE), (OP))) \
goto LABEL; \ goto WIN; \
else if ((GET_CODE (X) == POST_INC || GET_CODE (X) == PRE_DEC) \ } while (0)
&& ! TARGET_SHMEDIA \
&& BASE_REGISTER_RTX_P (XEXP ((X), 0))) \ #ifdef REG_OK_STRICT
goto LABEL; \ #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \
else if (GET_CODE (X) == PLUS \ do { \
&& ((MODE) != PSImode || reload_completed)) \ if (sh_legitimate_address_p ((MODE), (X), true)) \
{ \ goto LABEL; \
rtx xop0 = XEXP ((X), 0); \ } while (0)
rtx xop1 = XEXP ((X), 1); \ #else
if (GET_MODE_SIZE (MODE) <= 8 && BASE_REGISTER_RTX_P (xop0)) \ #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, LABEL) \
GO_IF_LEGITIMATE_INDEX ((MODE), xop1, LABEL); \ do { \
if ((ALLOW_INDEXED_ADDRESS || GET_MODE (X) == DImode \ if (sh_legitimate_address_p ((MODE), (X), false)) \
|| ((xop0 == stack_pointer_rtx \ goto LABEL; \
|| xop0 == hard_frame_pointer_rtx) \ } while (0)
&& REG_P (xop1) && REGNO (xop1) == R0_REG) \ #endif
|| ((xop1 == stack_pointer_rtx \
|| xop1 == hard_frame_pointer_rtx) \
&& REG_P (xop0) && REGNO (xop0) == R0_REG)) \
&& ((!TARGET_SHMEDIA && GET_MODE_SIZE (MODE) <= 4) \
|| (TARGET_SHMEDIA && GET_MODE_SIZE (MODE) <= 8) \
|| ((TARGET_SH4 || TARGET_SH2A_DOUBLE) \
&& TARGET_FMOVD && MODE == DFmode))) \
{ \
if (BASE_REGISTER_RTX_P (xop1) && INDEX_REGISTER_RTX_P (xop0))\
goto LABEL; \
if (INDEX_REGISTER_RTX_P (xop1) && BASE_REGISTER_RTX_P (xop0))\
goto LABEL; \
} \
} \
}
/* A C compound statement that attempts to replace X, which is an address /* A C compound statement that attempts to replace X, which is an address
that needs reloading, with a valid memory address for an operand of that needs reloading, with a valid memory address for an operand of
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment