More merging. Move GO_IF_LEGITIMATE_ADDRESS stuff into vax.c from vax.h.

Extend it to properly deal with indirect and indexed addressing modes.
Add preliminary PIC support.
This commit is contained in:
matt 2000-12-22 06:16:45 +00:00
parent 3723b80490
commit 4241925fa2
2 changed files with 208 additions and 153 deletions

View File

@ -43,8 +43,9 @@ split_quadword_operands (operands, low, n)
int i;
/* Split operands. */
low[0] = low[1] = low[2] = 0;
for (i = 0; i < 3; i++)
for (i = 0; i < n; i++)
low[i] = 0;
for (i = 0; i < n; i++)
{
if (low[i])
/* it's already been figured out */;
@ -52,7 +53,7 @@ split_quadword_operands (operands, low, n)
&& (GET_CODE (XEXP (operands[i], 0)) == POST_INC))
{
rtx addr = XEXP (operands[i], 0);
operands[i] = low[i] = gen_rtx (MEM, SImode, addr);
operands[i] = low[i] = gen_rtx_MEM (SImode, addr);
if (which_alternative == 0 && i == 0)
{
addr = XEXP (operands[i], 0);
@ -249,7 +250,7 @@ print_operand_address (file, addr)
}
}
char *
const char *
rev_cond_name (op)
rtx op;
{
@ -286,8 +287,10 @@ vax_float_literal(c)
register rtx c;
{
register enum machine_mode mode;
#if HOST_FLOAT_FORMAT == VAX_FLOAT_FORMAT
int i;
union {double d; int i[2];} val;
#endif
if (GET_CODE (c) != CONST_DOUBLE)
return 0;
@ -323,7 +326,8 @@ vax_float_literal(c)
2 - indirect */
int vax_address_cost(addr)
int
vax_address_cost (addr)
register rtx addr;
{
int reg = 0, indexed = 0, indir = 0, offset = 0, predec = 0;
@ -365,6 +369,8 @@ int vax_address_cost(addr)
indir = 2; /* 3 on VAX 2 */
addr = XEXP (addr, 0);
goto restart;
default:
break;
}
/* Up to 3 things can be added in an address. They are stored in
@ -402,7 +408,7 @@ vax_rtx_cost (x)
enum machine_mode mode = GET_MODE (x);
register int c;
int i = 0; /* may be modified in switch */
char *fmt = GET_RTX_FORMAT (code); /* may be modified in switch */
const char *fmt = GET_RTX_FORMAT (code); /* may be modified in switch */
switch (code)
{
@ -427,6 +433,8 @@ vax_rtx_cost (x)
case QImode:
c = 10; /* 3-4 on VAX 9000, 20-28 on VAX 2 */
break;
default:
break;
}
break;
case UDIV:
@ -582,7 +590,7 @@ vax_rtx_cost (x)
/* Check a `double' value for validity for a particular machine mode. */
static char *float_strings[] =
static const char *const float_strings[] =
{
"1.70141173319264430e+38", /* 2^127 (2^24 - 1) / 2^24 */
"-1.70141173319264430e+38",
@ -621,7 +629,7 @@ check_float_value (mode, d, overflow)
if ((mode) == SFmode)
{
REAL_VALUE_TYPE r;
bcopy ((char *) d, (char *) &r, sizeof (REAL_VALUE_TYPE));
memcpy (&r, d, sizeof (REAL_VALUE_TYPE));
if (REAL_VALUES_LESS (float_values[0], r))
{
bcopy ((char *) &float_values[0], (char *) d,
@ -651,6 +659,178 @@ check_float_value (mode, d, overflow)
return 0;
}
/* Nonzero if X is a hard reg that can be used as an index. */
#define XREG_OK_FOR_INDEX_P(X, STRICT) (!(STRICT) || REGNO_OK_FOR_INDEX_P (REGNO (X)))
/* Nonzero if X is a hard reg that can be used as a base reg. */
#define XREG_OK_FOR_BASE_P(X, STRICT) (!(STRICT) || REGNO_OK_FOR_BASE_P (REGNO (X)))
#ifdef NO_EXTERNAL_INDIRECT_ADDRESS
/* Re-definition of CONSTANT_ADDRESS_P, which is true only when there
are no SYMBOL_REFs for external symbols present and allow valid
addressing modes. */
#define INDIRECTABLE_CONSTANT_ADDRESS_P(X, INDEXED, INDIRECT) \
(GET_CODE (X) == LABEL_REF \
|| (!INDEXED && GET_CODE (X) == SYMBOL_REF \
&& (!INDIRECT || SYMBOL_REF_FLAG (X))) \
|| (!INDEXED && GET_CODE (X) == CONST \
&& GET_CODE (XEXP ((X), 0)) == PLUS \
&& GET_CODE (XEXP (XEXP ((X), 0), 0)) == SYMBOL_REF \
&& ((!INDIRECT && !(flag_pic)) \
|| SYMBOL_REF_FLAG (XEXP (XEXP ((X), 0), 0)))) \
|| GET_CODE (X) == CONST_INT)
/* Non-zero if X is an address which can be indirected. External symbols
could be in a sharable image library, so we disallow those. */
#define INDIRECTABLE_ADDRESS_P(X, STRICT, INDEXED, INDIRECT) \
(INDIRECTABLE_CONSTANT_ADDRESS_P (X, INDEXED, INDIRECT) \
|| (GET_CODE (X) == REG && XREG_OK_FOR_BASE_P (X, STRICT)) \
|| (GET_CODE (X) == PLUS \
&& GET_CODE (XEXP (X, 0)) == REG \
&& XREG_OK_FOR_BASE_P (XEXP (X, 0), STRICT) \
&& GET_CODE (XEXP (X, 1)) != SYMBOL_REF \
&& !(GET_CODE (XEXP (X, 1)) == CONST \
&& GET_CODE (XEXP (XEXP (X, 1), 0)) == PLUS \
&& GET_CODE (XEXP (XEXP (XEXP (X, 1), 0), 0)) == SYMBOL_REF) \
&& INDIRECTABLE_CONSTANT_ADDRESS_P (XEXP (X, 1), INDEXED, INDIRECT)))
#else /* not NO_EXTERNAL_INDIRECT_ADDRESS */
#define INDIRECTABLE_CONSTANT_ADDRESS_P(X, INDEXED, INDIRECT) \
CONSTANT_ADDRESS_P (X)
/* Non-zero if X is an address which can be indirected. */
#define INDIRECTABLE_ADDRESS_P(X, STRICT, INDEXED, INDIRECT) \
(INDIRECTABLE_CONSTANT_ADDRESS_P (X, INDEXED, INDIRECT) \
|| (GET_CODE (X) == REG && XREG_OK_FOR_BASE_P (X, STRICT)) \
|| (GET_CODE (X) == PLUS \
&& GET_CODE (XEXP (X, 0)) == REG \
&& XREG_OK_FOR_BASE_P (XEXP (X, 0), STRICT) \
&& CONSTANT_ADDRESS_P (XEXP (X, 1))))
#endif /* not NO_EXTERNAL_INDIRECT_ADDRESS */
/* Go to ADDR if X is a valid address not using indexing.
(This much is the easy part.) */
#define GO_IF_NONINDEXED_ADDRESS(X, ADDR, STRICT, INDEXED) \
{ register rtx xfoob = (X); \
if (GET_CODE (X) == REG) \
{ \
extern rtx *reg_equiv_mem; \
if (! reload_in_progress \
|| (xfoob = reg_equiv_mem[REGNO (X)]) == 0 \
|| INDIRECTABLE_ADDRESS_P (xfoob, STRICT, INDEXED, 0)) \
goto ADDR; \
} \
if (INDIRECTABLE_CONSTANT_ADDRESS_P (X, INDEXED, 0)) goto ADDR; \
if (INDIRECTABLE_ADDRESS_P (X, STRICT, INDEXED, 0)) goto ADDR; \
xfoob = XEXP (X, 0); \
if (GET_CODE (X) == MEM \
&& INDIRECTABLE_ADDRESS_P (xfoob, STRICT, INDEXED, \
(flag_pic))) \
goto ADDR; \
if ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_INC) \
&& GET_CODE (xfoob) == REG \
&& XREG_OK_FOR_BASE_P (xfoob, STRICT)) \
goto ADDR; }
/* 1 if PROD is either a reg times size of mode MODE
or just a reg, if MODE is just one byte.
This macro's expansion uses the temporary variables xfoo0 and xfoo1
that must be declared in the surrounding context. */
#define INDEX_TERM_P(PROD, MODE, STRICT) \
(GET_MODE_SIZE (MODE) == 1 \
? (GET_CODE (PROD) == REG && XREG_OK_FOR_BASE_P (PROD, STRICT)) \
: (GET_CODE (PROD) == MULT \
&& \
(xfoo0 = XEXP (PROD, 0), xfoo1 = XEXP (PROD, 1), \
((GET_CODE (xfoo0) == CONST_INT \
&& GET_CODE (xfoo1) == REG \
&& INTVAL (xfoo0) == (int)GET_MODE_SIZE (MODE) \
&& XREG_OK_FOR_INDEX_P (xfoo1, STRICT)) \
|| \
(GET_CODE (xfoo1) == CONST_INT \
&& GET_CODE (xfoo0) == REG \
&& INTVAL (xfoo1) == (int)GET_MODE_SIZE (MODE) \
&& XREG_OK_FOR_INDEX_P (xfoo0, STRICT))))))
/* Go to ADDR if X is the sum of a register
and a valid index term for mode MODE. */
#define GO_IF_REG_PLUS_INDEX(X, MODE, ADDR, STRICT) \
{ register rtx xfooa; \
if (GET_CODE (X) == PLUS) \
{ if (GET_CODE (XEXP (X, 0)) == REG \
&& XREG_OK_FOR_BASE_P (XEXP (X, 0), STRICT) \
&& (xfooa = XEXP (X, 1), \
INDEX_TERM_P (xfooa, MODE, STRICT))) \
goto ADDR; \
if (GET_CODE (XEXP (X, 1)) == REG \
&& XREG_OK_FOR_BASE_P (XEXP (X, 1), STRICT) \
&& (xfooa = XEXP (X, 0), \
INDEX_TERM_P (xfooa, MODE, STRICT))) \
goto ADDR; } }
int
legitimate_pic_operand_p(x, strict)
register rtx x;
int strict ATTRIBUTE_UNUSED;
{
if (GET_CODE (x) != SYMBOL_REF
&& !(GET_CODE (x) == CONST
&& GET_CODE (XEXP (x, 0)) == PLUS
&& GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF))
{
return 1;
}
return 0;
}
int
legitimate_address_p(mode, xbar, strict)
enum machine_mode mode;
register rtx xbar;
int strict;
{
register rtx xfoo, xfoo0, xfoo1;
GO_IF_NONINDEXED_ADDRESS (xbar, win, strict, 0);
if (GET_CODE (xbar) == PLUS)
{
/* Handle <address>[index] represented with index-sum outermost */
xfoo = XEXP (xbar, 0);
if (INDEX_TERM_P (xfoo, mode, strict))
{
GO_IF_NONINDEXED_ADDRESS (XEXP (xbar, 1), win, strict, 1);
}
xfoo = XEXP (xbar, 1);
if (INDEX_TERM_P (xfoo, mode, strict))
{
GO_IF_NONINDEXED_ADDRESS (XEXP (xbar, 0), win, strict, 1);
}
/* Handle offset(reg)[index] with offset added outermost */
if (INDIRECTABLE_CONSTANT_ADDRESS_P (XEXP (xbar, 0), 1, 0))
{
if (GET_CODE (XEXP (xbar, 1)) == REG
&& XREG_OK_FOR_BASE_P (XEXP (xbar, 1), strict))
goto win;
GO_IF_REG_PLUS_INDEX (XEXP (xbar, 1), mode, win, strict);
}
if (INDIRECTABLE_CONSTANT_ADDRESS_P (XEXP (xbar, 1), 1, 0))
{
if (GET_CODE (XEXP (xbar, 0)) == REG
&& XREG_OK_FOR_BASE_P (XEXP (xbar, 0), strict))
goto win;
GO_IF_REG_PLUS_INDEX (XEXP (xbar, 0), mode, win, strict);
}
}
}
return 0;
win:
return 1;
}
#ifdef VMS_TARGET
/* Additional support code for VMS target. */
@ -661,7 +841,7 @@ check_float_value (mode, d, overflow)
static
struct extern_list {
struct extern_list *next; /* next external */
char *name; /* name of the external */
const char *name; /* name of the external */
int size; /* external's actual size */
int in_const; /* section type flag */
} *extern_head = 0, *pending_head = 0;

View File

@ -69,14 +69,14 @@ extern int target_flags;
An empty string NAME is used to identify the default VALUE. */
#define TARGET_SWITCHES \
{ {"unix", MASK_UNIX_ASM}, \
{"gnu", -MASK_UNIX_ASM}, \
{"vaxc-alignment", MASK_VAXC_ALIGNMENT}, \
{"g", MASK_G_FLOAT}, \
{"g-float", MASK_G_FLOAT}, \
{"d", -MASK_G_FLOAT}, \
{"d-float", -MASK_G_FLOAT}, \
{ "", TARGET_DEFAULT}}
{ {"unix", MASK_UNIX_ASM, "Generate code for UNIX assembler"}, \
{"gnu", -MASK_UNIX_ASM, "Generate code for GNU assembler (gas)"}, \
{"vaxc-alignment", MASK_VAXC_ALIGNMENT, "Use VAXC structure conventions"}, \
{"g", MASK_G_FLOAT, "Generate GFLOAT double precision code"}, \
{"g-float", MASK_G_FLOAT, "Generate GFLOAT double precision code"}, \
{"d", -MASK_G_FLOAT, "Generate DFLOAT double precision code"}, \
{"d-float", -MASK_G_FLOAT, "Generate DFLOAT double precision code"}, \
{ "", TARGET_DEFAULT, 0}}
/* Default target_flags if no switches specified. */
@ -649,6 +649,9 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
/* Nonzero if X is a hard reg that can be used as a base reg
or if it is a pseudo reg. */
#define REG_OK_FOR_BASE_P(X) 1
#define LEGITIMATE_PIC_OPERAND_P(X) legitimate_pic_operand_p (X, 0)
#define GO_IF_LEGITIMATE_ADDRESS(ZMODE, XOP, LABEL) \
do { if (legitimate_address_p(ZMODE, XOP, 0)) goto LABEL; } while (0)
#else
@ -656,144 +659,12 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P (REGNO (X))
/* 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))
#define LEGITIMATE_PIC_OPERAND_P(X) legitimate_pic_operand_p (X, 1)
#define GO_IF_LEGITIMATE_ADDRESS(ZMODE, XOP, LABEL) \
do { if (legitimate_address_p(ZMODE, XOP, 1)) goto LABEL; } while (0)
#endif
/* GO_IF_LEGITIMATE_ADDRESS recognizes 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.
The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS,
except for CONSTANT_ADDRESS_P which is actually machine-independent. */
#ifdef NO_EXTERNAL_INDIRECT_ADDRESS
/* Zero if this contains a (CONST (PLUS (SYMBOL_REF) (...))) and the
symbol in the SYMBOL_REF is an external symbol. */
#define INDIRECTABLE_CONSTANT_P(X) \
(! (GET_CODE ((X)) == CONST \
&& GET_CODE (XEXP ((X), 0)) == PLUS \
&& GET_CODE (XEXP (XEXP ((X), 0), 0)) == SYMBOL_REF \
&& SYMBOL_REF_FLAG (XEXP (XEXP ((X), 0), 0))))
/* Re-definition of CONSTANT_ADDRESS_P, which is true only when there
are no SYMBOL_REFs for external symbols present. */
#define INDIRECTABLE_CONSTANT_ADDRESS_P(X) \
(GET_CODE (X) == LABEL_REF \
|| (GET_CODE (X) == SYMBOL_REF && !SYMBOL_REF_FLAG (X)) \
|| (GET_CODE (X) == CONST && INDIRECTABLE_CONSTANT_P(X)) \
|| GET_CODE (X) == CONST_INT)
/* Non-zero if X is an address which can be indirected. External symbols
could be in a sharable image library, so we disallow those. */
#define INDIRECTABLE_ADDRESS_P(X) \
(INDIRECTABLE_CONSTANT_ADDRESS_P (X) \
|| (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \
|| (GET_CODE (X) == PLUS \
&& GET_CODE (XEXP (X, 0)) == REG \
&& REG_OK_FOR_BASE_P (XEXP (X, 0)) \
&& INDIRECTABLE_CONSTANT_ADDRESS_P (XEXP (X, 1))))
#else /* not NO_EXTERNAL_INDIRECT_ADDRESS */
#define INDIRECTABLE_CONSTANT_ADDRESS_P(X) CONSTANT_ADDRESS_P(X)
/* Non-zero if X is an address which can be indirected. */
#define INDIRECTABLE_ADDRESS_P(X) \
(CONSTANT_ADDRESS_P (X) \
|| (GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \
|| (GET_CODE (X) == PLUS \
&& GET_CODE (XEXP (X, 0)) == REG \
&& REG_OK_FOR_BASE_P (XEXP (X, 0)) \
&& CONSTANT_ADDRESS_P (XEXP (X, 1))))
#endif /* not NO_EXTERNAL_INDIRECT_ADDRESS */
/* Go to ADDR if X is a valid address not using indexing.
(This much is the easy part.) */
#define GO_IF_NONINDEXED_ADDRESS(X, ADDR) \
{ register rtx xfoob = (X); \
if (GET_CODE (xfoob) == REG) \
{ \
extern rtx *reg_equiv_mem; \
if (! reload_in_progress \
|| reg_equiv_mem[REGNO (xfoob)] == 0 \
|| INDIRECTABLE_ADDRESS_P (reg_equiv_mem[REGNO (xfoob)])) \
goto ADDR; \
} \
if (CONSTANT_ADDRESS_P (xfoob)) goto ADDR; \
if (INDIRECTABLE_ADDRESS_P (xfoob)) goto ADDR; \
xfoob = XEXP (X, 0); \
if (GET_CODE (X) == MEM && INDIRECTABLE_ADDRESS_P (xfoob)) \
goto ADDR; \
if ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_INC) \
&& GET_CODE (xfoob) == REG && REG_OK_FOR_BASE_P (xfoob)) \
goto ADDR; }
/* 1 if PROD is either a reg times size of mode MODE
or just a reg, if MODE is just one byte.
This macro's expansion uses the temporary variables xfoo0 and xfoo1
that must be declared in the surrounding context. */
#define INDEX_TERM_P(PROD, MODE) \
(GET_MODE_SIZE (MODE) == 1 \
? (GET_CODE (PROD) == REG && REG_OK_FOR_BASE_P (PROD)) \
: (GET_CODE (PROD) == MULT \
&& \
(xfoo0 = XEXP (PROD, 0), xfoo1 = XEXP (PROD, 1), \
((GET_CODE (xfoo0) == CONST_INT \
&& INTVAL (xfoo0) == GET_MODE_SIZE (MODE) \
&& GET_CODE (xfoo1) == REG \
&& REG_OK_FOR_INDEX_P (xfoo1)) \
|| \
(GET_CODE (xfoo1) == CONST_INT \
&& INTVAL (xfoo1) == GET_MODE_SIZE (MODE) \
&& GET_CODE (xfoo0) == REG \
&& REG_OK_FOR_INDEX_P (xfoo0))))))
/* Go to ADDR if X is the sum of a register
and a valid index term for mode MODE. */
#define GO_IF_REG_PLUS_INDEX(X, MODE, ADDR) \
{ register rtx xfooa; \
if (GET_CODE (X) == PLUS) \
{ if (GET_CODE (XEXP (X, 0)) == REG \
&& REG_OK_FOR_BASE_P (XEXP (X, 0)) \
&& (xfooa = XEXP (X, 1), \
INDEX_TERM_P (xfooa, MODE))) \
goto ADDR; \
if (GET_CODE (XEXP (X, 1)) == REG \
&& REG_OK_FOR_BASE_P (XEXP (X, 1)) \
&& (xfooa = XEXP (X, 0), \
INDEX_TERM_P (xfooa, MODE))) \
goto ADDR; } }
#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
{ register rtx xfoo, xfoo0, xfoo1; \
GO_IF_NONINDEXED_ADDRESS (X, ADDR); \
if (GET_CODE (X) == PLUS) \
{ /* Handle <address>[index] represented with index-sum outermost */\
xfoo = XEXP (X, 0); \
if (INDEX_TERM_P (xfoo, MODE)) \
{ GO_IF_NONINDEXED_ADDRESS (XEXP (X, 1), ADDR); } \
xfoo = XEXP (X, 1); \
if (INDEX_TERM_P (xfoo, MODE)) \
{ GO_IF_NONINDEXED_ADDRESS (XEXP (X, 0), ADDR); } \
/* Handle offset(reg)[index] with offset added outermost */ \
if (INDIRECTABLE_CONSTANT_ADDRESS_P (XEXP (X, 0))) \
{ if (GET_CODE (XEXP (X, 1)) == REG \
&& REG_OK_FOR_BASE_P (XEXP (X, 1))) \
goto ADDR; \
GO_IF_REG_PLUS_INDEX (XEXP (X, 1), MODE, ADDR); } \
if (INDIRECTABLE_CONSTANT_ADDRESS_P (XEXP (X, 1))) \
{ if (GET_CODE (XEXP (X, 0)) == REG \
&& REG_OK_FOR_BASE_P (XEXP (X, 0))) \
goto ADDR; \
GO_IF_REG_PLUS_INDEX (XEXP (X, 0), MODE, ADDR); } } }
/* Try machine-dependent ways of modifying an illegitimate address
to be legitimate. If we find one, return the new, valid address.
This macro is used in only one place: `memory_address' in explow.c.
@ -822,8 +693,12 @@ enum reg_class { NO_REGS, ALL_REGS, LIM_REG_CLASSES };
goto LABEL; \
if (GET_CODE (ADDR) == PLUS) \
{ if (CONSTANT_ADDRESS_P (XEXP (ADDR, 0)) \
&& (!(flag_pic) \
|| GET_CODE (XEXP (ADDR, 0)) != SYMBOL_REF) \
&& GET_CODE (XEXP (ADDR, 1)) == REG); \
else if (CONSTANT_ADDRESS_P (XEXP (ADDR, 1)) \
&& (!(flag_pic) \
|| GET_CODE (XEXP (ADDR, 1)) != SYMBOL_REF) \
&& GET_CODE (XEXP (ADDR, 0)) == REG); \
else goto LABEL; }}
@ -1308,7 +1183,7 @@ VAX operand formatting codes:
((CODE) == '#')
#define PRINT_OPERAND(FILE, X, CODE) \
{ extern char *rev_cond_name (); \
{ extern const char *rev_cond_name (); \
if (CODE == '#') fputc (ASM_DOUBLE_CHAR, FILE); \
else if (CODE == 'C') \
fputs (rev_cond_name (X), FILE); \