mips-protos.h (mips_legitimate_address_p): New function.
* config/mips/mips-protos.h (mips_legitimate_address_p): New function. (mips_reg_mode_ok_for_base_p): Likewise. * config/mips/mips.h (REG_OK_STRICT_P): Don't define. (REG_OK_FOR_INDEX_P): Define unconditionally. (REG_MODE_OK_FOR_BASE_P): Use mips_reg_mode_ok_for_base_p. (GO_IF_LEGITIMATE_ADDRESS): Use mips_legitimate_address_p. * config/mips/mips.c (mips16_simple_memory_operand): Adjust now that GET_MODE_SIZE is unsigned. (mips_reg_mode_ok_for_base_p): Define. (mips_legitimate_address_p): Likewise. Adjust now that GET_MODE_SIZE is unsigned. (block_move_loop): Make the number of bytes unsigned. (expand_block_move): Likewise. (function_arg): Make the loop counter unsigned to match the boundary condition. From-SVN: r33188
This commit is contained in:
parent
d636c18c54
commit
c94c981720
4 changed files with 178 additions and 123 deletions
|
@ -1,3 +1,22 @@
|
|||
2000-04-16 Mark Mitchell <mark@codesourcery.com>
|
||||
|
||||
* config/mips/mips-protos.h (mips_legitimate_address_p): New
|
||||
function.
|
||||
(mips_reg_mode_ok_for_base_p): Likewise.
|
||||
* config/mips/mips.h (REG_OK_STRICT_P): Don't define.
|
||||
(REG_OK_FOR_INDEX_P): Define unconditionally.
|
||||
(REG_MODE_OK_FOR_BASE_P): Use mips_reg_mode_ok_for_base_p.
|
||||
(GO_IF_LEGITIMATE_ADDRESS): Use mips_legitimate_address_p.
|
||||
* config/mips/mips.c (mips16_simple_memory_operand): Adjust now
|
||||
that GET_MODE_SIZE is unsigned.
|
||||
(mips_reg_mode_ok_for_base_p): Define.
|
||||
(mips_legitimate_address_p): Likewise. Adjust now
|
||||
that GET_MODE_SIZE is unsigned.
|
||||
(block_move_loop): Make the number of bytes unsigned.
|
||||
(expand_block_move): Likewise.
|
||||
(function_arg): Make the loop counter unsigned to match the
|
||||
boundary condition.
|
||||
|
||||
2000-04-16 Richard Henderson <rth@cygnus.com>
|
||||
|
||||
* rtl.h (enum insn_note): New enumeration. Subsume
|
||||
|
|
|
@ -130,6 +130,8 @@ extern int se_uns_arith_operand PARAMS ((rtx, enum machine_mode));
|
|||
extern int se_arith_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int se_nonmemory_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int se_nonimmediate_operand PARAMS ((rtx, enum machine_mode));
|
||||
extern int mips_legitimate_address_p PARAMS ((enum machine_mode, rtx, int));
|
||||
extern int mips_reg_mode_ok_for_base_p PARAMS ((rtx, enum machine_mode, int));
|
||||
extern int extend_operator PARAMS ((rtx, enum machine_mode));
|
||||
extern int highpart_shift_operator PARAMS ((rtx, enum machine_mode));
|
||||
extern int m16_uimm3_b PARAMS ((rtx, enum machine_mode));
|
||||
|
|
|
@ -91,8 +91,10 @@ static enum internal_test map_test_to_internal_test PARAMS ((enum rtx_code));
|
|||
static int mips16_simple_memory_operand PARAMS ((rtx, rtx,
|
||||
enum machine_mode));
|
||||
static int m16_check_op PARAMS ((rtx, int, int, int));
|
||||
static void block_move_loop PARAMS ((rtx, rtx, int, int,
|
||||
rtx, rtx));
|
||||
static void block_move_loop PARAMS ((rtx, rtx,
|
||||
unsigned int,
|
||||
int,
|
||||
rtx, rtx));
|
||||
static void block_move_call PARAMS ((rtx, rtx, rtx));
|
||||
static FILE *mips_make_temp_file PARAMS ((void));
|
||||
static void save_restore_insns PARAMS ((int, rtx,
|
||||
|
@ -671,7 +673,8 @@ mips16_simple_memory_operand (reg, offset, mode)
|
|||
rtx offset;
|
||||
enum machine_mode mode;
|
||||
{
|
||||
int size, off;
|
||||
unsigned int size;
|
||||
int off;
|
||||
|
||||
if (mode == BLKmode)
|
||||
{
|
||||
|
@ -1208,6 +1211,136 @@ mips_check_split (address, mode)
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* This function is used to implement REG_MODE_OK_FOR_BASE_P. */
|
||||
|
||||
int
|
||||
mips_reg_mode_ok_for_base_p (reg, mode, strict)
|
||||
rtx reg;
|
||||
enum machine_mode mode;
|
||||
int strict;
|
||||
{
|
||||
return (strict
|
||||
? REGNO_MODE_OK_FOR_BASE_P (REGNO (reg), mode)
|
||||
: GP_REG_OR_PSEUDO_NONSTRICT_P (REGNO (reg), mode));
|
||||
}
|
||||
|
||||
/* This function is used to implement GO_IF_LEGITIMATE_ADDRESS. It
|
||||
returns a nonzero value if XINSN is a legitimate address for a
|
||||
memory operand of the indicated MODE. STRICT is non-zero if this
|
||||
function is called during reload. */
|
||||
|
||||
int
|
||||
mips_legitimate_address_p (mode, xinsn, strict)
|
||||
enum machine_mode mode;
|
||||
rtx xinsn;
|
||||
int strict;
|
||||
{
|
||||
if (TARGET_DEBUG_B_MODE)
|
||||
{
|
||||
GO_PRINTF2 ("\n========== GO_IF_LEGITIMATE_ADDRESS, %sstrict\n",
|
||||
strict ? "" : "not ");
|
||||
GO_DEBUG_RTX (xinsn);
|
||||
}
|
||||
|
||||
/* Check for constant before stripping off SUBREG, so that we don't
|
||||
accept (subreg (const_int)) which will fail to reload. */
|
||||
if (CONSTANT_ADDRESS_P (xinsn)
|
||||
&& ! (mips_split_addresses && mips_check_split (xinsn, mode))
|
||||
&& (! TARGET_MIPS16 || mips16_constant (xinsn, mode, 1, 0)))
|
||||
return 1;
|
||||
|
||||
while (GET_CODE (xinsn) == SUBREG)
|
||||
xinsn = SUBREG_REG (xinsn);
|
||||
|
||||
/* The mips16 can only use the stack pointer as a base register when
|
||||
loading SImode or DImode values. */
|
||||
if (GET_CODE (xinsn) == REG
|
||||
&& mips_reg_mode_ok_for_base_p (xinsn, mode, strict))
|
||||
return 1;
|
||||
|
||||
if (GET_CODE (xinsn) == LO_SUM && mips_split_addresses)
|
||||
{
|
||||
register rtx xlow0 = XEXP (xinsn, 0);
|
||||
register rtx xlow1 = XEXP (xinsn, 1);
|
||||
|
||||
while (GET_CODE (xlow0) == SUBREG)
|
||||
xlow0 = SUBREG_REG (xlow0);
|
||||
if (GET_CODE (xlow0) == REG
|
||||
&& mips_reg_mode_ok_for_base_p (xlow0, mode, strict)
|
||||
&& mips_check_split (xlow1, mode))
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (GET_CODE (xinsn) == PLUS)
|
||||
{
|
||||
register rtx xplus0 = XEXP (xinsn, 0);
|
||||
register rtx xplus1 = XEXP (xinsn, 1);
|
||||
register enum rtx_code code0;
|
||||
register enum rtx_code code1;
|
||||
|
||||
while (GET_CODE (xplus0) == SUBREG)
|
||||
xplus0 = SUBREG_REG (xplus0);
|
||||
code0 = GET_CODE (xplus0);
|
||||
|
||||
while (GET_CODE (xplus1) == SUBREG)
|
||||
xplus1 = SUBREG_REG (xplus1);
|
||||
code1 = GET_CODE (xplus1);
|
||||
|
||||
/* The mips16 can only use the stack pointer as a base register
|
||||
when loading SImode or DImode values. */
|
||||
if (code0 == REG
|
||||
&& mips_reg_mode_ok_for_base_p (xplus0, mode, strict))
|
||||
{
|
||||
if (code1 == CONST_INT && SMALL_INT (xplus1))
|
||||
return 1;
|
||||
|
||||
/* On the mips16, we represent GP relative offsets in RTL.
|
||||
These are 16 bit signed values, and can serve as register
|
||||
offsets. */
|
||||
if (TARGET_MIPS16
|
||||
&& mips16_gp_offset_p (xplus1))
|
||||
return 1;
|
||||
|
||||
/* For some code sequences, you actually get better code by
|
||||
pretending that the MIPS supports an address mode of a
|
||||
constant address + a register, even though the real
|
||||
machine doesn't support it. This is because the
|
||||
assembler can use $r1 to load just the high 16 bits, add
|
||||
in the register, and fold the low 16 bits into the memory
|
||||
reference, whereas the compiler generates a 4 instruction
|
||||
sequence. On the other hand, CSE is not as effective.
|
||||
It would be a win to generate the lui directly, but the
|
||||
MIPS assembler does not have syntax to generate the
|
||||
appropriate relocation. */
|
||||
|
||||
/* Also accept CONST_INT addresses here, so no else. */
|
||||
/* Reject combining an embedded PIC text segment reference
|
||||
with a register. That requires an additional
|
||||
instruction. */
|
||||
/* ??? Reject combining an address with a register for the MIPS
|
||||
64 bit ABI, because the SGI assembler can not handle this. */
|
||||
if (!TARGET_DEBUG_A_MODE
|
||||
&& (mips_abi == ABI_32
|
||||
|| mips_abi == ABI_O64
|
||||
|| mips_abi == ABI_EABI)
|
||||
&& CONSTANT_ADDRESS_P (xplus1)
|
||||
&& ! mips_split_addresses
|
||||
&& (!TARGET_EMBEDDED_PIC
|
||||
|| code1 != CONST
|
||||
|| GET_CODE (XEXP (xplus1, 0)) != MINUS)
|
||||
&& !TARGET_MIPS16)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (TARGET_DEBUG_B_MODE)
|
||||
GO_PRINTF ("Not a legitimate address\n");
|
||||
|
||||
/* The address was not legitimate. */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* We need a lot of little routines to check constant values on the
|
||||
mips16. These are used to figure out how long the instruction will
|
||||
|
@ -3033,7 +3166,7 @@ static void
|
|||
block_move_loop (dest_reg, src_reg, bytes, align, orig_dest, orig_src)
|
||||
rtx dest_reg; /* register holding destination address */
|
||||
rtx src_reg; /* register holding source address */
|
||||
int bytes; /* # bytes to move */
|
||||
unsigned int bytes; /* # bytes to move */
|
||||
int align; /* alignment */
|
||||
rtx orig_dest; /* original dest for change_address */
|
||||
rtx orig_src; /* original source for making a reg note */
|
||||
|
@ -3145,14 +3278,14 @@ expand_block_move (operands)
|
|||
rtx bytes_rtx = operands[2];
|
||||
rtx align_rtx = operands[3];
|
||||
int constp = GET_CODE (bytes_rtx) == CONST_INT;
|
||||
HOST_WIDE_INT bytes = constp ? INTVAL (bytes_rtx) : 0;
|
||||
int align = INTVAL (align_rtx);
|
||||
unsigned HOST_WIDE_INT bytes = constp ? INTVAL (bytes_rtx) : 0;
|
||||
unsigned int align = INTVAL (align_rtx);
|
||||
rtx orig_src = operands[1];
|
||||
rtx orig_dest = operands[0];
|
||||
rtx src_reg;
|
||||
rtx dest_reg;
|
||||
|
||||
if (constp && bytes <= 0)
|
||||
if (constp && bytes == 0)
|
||||
return;
|
||||
|
||||
if (align > UNITS_PER_WORD)
|
||||
|
@ -3863,7 +3996,7 @@ function_arg (cum, mode, type, named)
|
|||
unsigned int chunks;
|
||||
HOST_WIDE_INT bitpos;
|
||||
unsigned int regno;
|
||||
int i;
|
||||
unsigned int i;
|
||||
|
||||
/* ??? If this is a packed structure, then the last hunk won't
|
||||
be 64 bits. */
|
||||
|
|
|
@ -2725,21 +2725,15 @@ typedef struct mips_args {
|
|||
need to be strict. */
|
||||
|
||||
#ifndef REG_OK_STRICT
|
||||
|
||||
#define REG_OK_STRICT_P 0
|
||||
#define REG_OK_FOR_INDEX_P(X) 0
|
||||
#define REG_MODE_OK_FOR_BASE_P(X, MODE) \
|
||||
GP_REG_OR_PSEUDO_NONSTRICT_P (REGNO (X), (MODE))
|
||||
|
||||
mips_reg_mode_ok_for_base_p (X, MODE, 0)
|
||||
#else
|
||||
|
||||
#define REG_OK_STRICT_P 1
|
||||
#define REG_OK_FOR_INDEX_P(X) 0
|
||||
#define REG_MODE_OK_FOR_BASE_P(X, MODE) \
|
||||
REGNO_MODE_OK_FOR_BASE_P (REGNO (X), (MODE))
|
||||
|
||||
mips_reg_mode_ok_for_base_p (X, MODE, 1)
|
||||
#endif
|
||||
|
||||
#define REG_OK_FOR_INDEX_P(X) 0
|
||||
|
||||
|
||||
/* Maximum number of registers that can appear in a valid memory address. */
|
||||
|
||||
|
@ -2806,112 +2800,19 @@ typedef struct mips_args {
|
|||
#define GO_DEBUG_RTX(x)
|
||||
#endif
|
||||
|
||||
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
|
||||
{ \
|
||||
register rtx xinsn = (X); \
|
||||
\
|
||||
if (TARGET_DEBUG_B_MODE) \
|
||||
{ \
|
||||
GO_PRINTF2 ("\n========== GO_IF_LEGITIMATE_ADDRESS, %sstrict\n", \
|
||||
(REG_OK_STRICT_P) ? "" : "not "); \
|
||||
GO_DEBUG_RTX (xinsn); \
|
||||
} \
|
||||
\
|
||||
/* Check for constant before stripping off SUBREG, so that we don't \
|
||||
accept (subreg (const_int)) which will fail to reload. */ \
|
||||
if (CONSTANT_ADDRESS_P (xinsn) \
|
||||
&& ! (mips_split_addresses && mips_check_split (xinsn, MODE)) \
|
||||
&& (! TARGET_MIPS16 || mips16_constant (xinsn, MODE, 1, 0))) \
|
||||
goto ADDR; \
|
||||
\
|
||||
while (GET_CODE (xinsn) == SUBREG) \
|
||||
xinsn = SUBREG_REG (xinsn); \
|
||||
\
|
||||
/* The mips16 can only use the stack pointer as a base register when \
|
||||
loading SImode or DImode values. */ \
|
||||
if (GET_CODE (xinsn) == REG && REG_MODE_OK_FOR_BASE_P (xinsn, MODE)) \
|
||||
goto ADDR; \
|
||||
\
|
||||
if (GET_CODE (xinsn) == LO_SUM && mips_split_addresses) \
|
||||
{ \
|
||||
register rtx xlow0 = XEXP (xinsn, 0); \
|
||||
register rtx xlow1 = XEXP (xinsn, 1); \
|
||||
\
|
||||
while (GET_CODE (xlow0) == SUBREG) \
|
||||
xlow0 = SUBREG_REG (xlow0); \
|
||||
if (GET_CODE (xlow0) == REG \
|
||||
&& REG_MODE_OK_FOR_BASE_P (xlow0, MODE) \
|
||||
&& mips_check_split (xlow1, MODE)) \
|
||||
goto ADDR; \
|
||||
} \
|
||||
\
|
||||
if (GET_CODE (xinsn) == PLUS) \
|
||||
{ \
|
||||
register rtx xplus0 = XEXP (xinsn, 0); \
|
||||
register rtx xplus1 = XEXP (xinsn, 1); \
|
||||
register enum rtx_code code0; \
|
||||
register enum rtx_code code1; \
|
||||
\
|
||||
while (GET_CODE (xplus0) == SUBREG) \
|
||||
xplus0 = SUBREG_REG (xplus0); \
|
||||
code0 = GET_CODE (xplus0); \
|
||||
\
|
||||
while (GET_CODE (xplus1) == SUBREG) \
|
||||
xplus1 = SUBREG_REG (xplus1); \
|
||||
code1 = GET_CODE (xplus1); \
|
||||
\
|
||||
/* The mips16 can only use the stack pointer as a base register \
|
||||
when loading SImode or DImode values. */ \
|
||||
if (code0 == REG && REG_MODE_OK_FOR_BASE_P (xplus0, MODE)) \
|
||||
{ \
|
||||
if (code1 == CONST_INT \
|
||||
&& INTVAL (xplus1) >= -32768 \
|
||||
&& INTVAL (xplus1) + GET_MODE_SIZE (MODE) - 1 <= 32767) \
|
||||
goto ADDR; \
|
||||
\
|
||||
/* On the mips16, we represent GP relative offsets in RTL. \
|
||||
These are 16 bit signed values, and can serve as register \
|
||||
offsets. */ \
|
||||
if (TARGET_MIPS16 \
|
||||
&& mips16_gp_offset_p (xplus1)) \
|
||||
goto ADDR; \
|
||||
\
|
||||
/* For some code sequences, you actually get better code by \
|
||||
pretending that the MIPS supports an address mode of a \
|
||||
constant address + a register, even though the real \
|
||||
machine doesn't support it. This is because the \
|
||||
assembler can use $r1 to load just the high 16 bits, add \
|
||||
in the register, and fold the low 16 bits into the memory \
|
||||
reference, whereas the compiler generates a 4 instruction \
|
||||
sequence. On the other hand, CSE is not as effective. \
|
||||
It would be a win to generate the lui directly, but the \
|
||||
MIPS assembler does not have syntax to generate the \
|
||||
appropriate relocation. */ \
|
||||
\
|
||||
/* Also accept CONST_INT addresses here, so no else. */ \
|
||||
/* Reject combining an embedded PIC text segment reference \
|
||||
with a register. That requires an additional \
|
||||
instruction. */ \
|
||||
/* ??? Reject combining an address with a register for the MIPS \
|
||||
64 bit ABI, because the SGI assembler can not handle this. */ \
|
||||
if (!TARGET_DEBUG_A_MODE \
|
||||
&& (mips_abi == ABI_32 \
|
||||
|| mips_abi == ABI_O64 \
|
||||
|| mips_abi == ABI_EABI) \
|
||||
&& CONSTANT_ADDRESS_P (xplus1) \
|
||||
&& ! mips_split_addresses \
|
||||
&& (!TARGET_EMBEDDED_PIC \
|
||||
|| code1 != CONST \
|
||||
|| GET_CODE (XEXP (xplus1, 0)) != MINUS) \
|
||||
&& !TARGET_MIPS16) \
|
||||
goto ADDR; \
|
||||
} \
|
||||
} \
|
||||
\
|
||||
if (TARGET_DEBUG_B_MODE) \
|
||||
GO_PRINTF ("Not a legitimate address\n"); \
|
||||
#ifdef REG_OK_STRICT
|
||||
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
|
||||
{ \
|
||||
if (mips_legitimate_address_p (MODE, X, 1)) \
|
||||
goto ADDR; \
|
||||
}
|
||||
|
||||
#else
|
||||
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
|
||||
{ \
|
||||
if (mips_legitimate_address_p (MODE, X, 0)) \
|
||||
goto ADDR; \
|
||||
}
|
||||
#endif
|
||||
|
||||
/* A C expression that is 1 if the RTX X is a constant which is a
|
||||
valid address. This is defined to be the same as `CONSTANT_P (X)',
|
||||
|
|
Loading…
Add table
Reference in a new issue