xtensa.c (smalloffset_mem_p): Use BASE_REG_P.
* config/xtensa/xtensa.c (smalloffset_mem_p): Use BASE_REG_P. (xtensa_legitimate_address_p): New. (xtensa_legitimize_address): New. (xtensa_output_addr_const_extra): New. * config/xtensa/xtensa.h (REG_OK_STRICT_FLAG): Define. (BASE_REG_P): New. (REG_OK_FOR_BASE_P): Use BASE_REG_P. (GO_IF_LEGITIMATE_ADDRESS): Move code to xtensa_legitimate_address_p. (LEGITIMIZE_ADDRESS): Move code to xtensa_legitimize_address. (OUTPUT_ADDR_CONST_EXTRA): Move code to xtensa_output_addr_const_extra. * config/xtensa/xtensa-protos.h (xtensa_legitimate_address_p): New. (xtensa_legitimize_address): New. (xtensa_output_addr_const_extra): New. From-SVN: r121533
This commit is contained in:
parent
2e6524ba30
commit
da1f39e475
@ -1,3 +1,19 @@
|
||||
2007-02-02 Bob Wilson <bob.wilson@acm.org>
|
||||
|
||||
* config/xtensa/xtensa.c (smalloffset_mem_p): Use BASE_REG_P.
|
||||
(xtensa_legitimate_address_p): New.
|
||||
(xtensa_legitimize_address): New.
|
||||
(xtensa_output_addr_const_extra): New.
|
||||
* config/xtensa/xtensa.h (REG_OK_STRICT_FLAG): Define.
|
||||
(BASE_REG_P): New.
|
||||
(REG_OK_FOR_BASE_P): Use BASE_REG_P.
|
||||
(GO_IF_LEGITIMATE_ADDRESS): Move code to xtensa_legitimate_address_p.
|
||||
(LEGITIMIZE_ADDRESS): Move code to xtensa_legitimize_address.
|
||||
(OUTPUT_ADDR_CONST_EXTRA): Move code to xtensa_output_addr_const_extra.
|
||||
* config/xtensa/xtensa-protos.h (xtensa_legitimate_address_p): New.
|
||||
(xtensa_legitimize_address): New.
|
||||
(xtensa_output_addr_const_extra): New.
|
||||
|
||||
2007-02-02 Steve Ellcey <sje@cup.hp.com>
|
||||
|
||||
* config/ia64/ia64.c (ia64_print_operand): Fix compare strings.
|
||||
|
@ -1,5 +1,5 @@
|
||||
/* Prototypes of target machine for GNU compiler for Xtensa.
|
||||
Copyright 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
|
||||
Copyright 2001, 2002, 2003, 2004, 2005, 2007 Free Software Foundation, Inc.
|
||||
Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica.
|
||||
|
||||
This file is part of GCC.
|
||||
@ -52,6 +52,8 @@ extern char *xtensa_emit_branch (bool, bool, rtx *);
|
||||
extern char *xtensa_emit_bit_branch (bool, bool, rtx *);
|
||||
extern char *xtensa_emit_movcc (bool, bool, bool, rtx *);
|
||||
extern char *xtensa_emit_call (int, rtx *);
|
||||
extern bool xtensa_legitimate_address_p (enum machine_mode, rtx, bool);
|
||||
extern rtx xtensa_legitimize_address (rtx, rtx, enum machine_mode);
|
||||
|
||||
#ifdef TREE_CODE
|
||||
extern void init_cumulative_args (CUMULATIVE_ARGS *, int);
|
||||
@ -60,6 +62,7 @@ extern void xtensa_va_start (tree, rtx);
|
||||
|
||||
extern void print_operand (FILE *, rtx, int);
|
||||
extern void print_operand_address (FILE *, rtx);
|
||||
extern bool xtensa_output_addr_const_extra (FILE *, rtx);
|
||||
extern void xtensa_output_literal (FILE *, rtx, enum machine_mode, int);
|
||||
extern rtx xtensa_return_addr (int, rtx);
|
||||
extern enum reg_class xtensa_preferred_reload_class (rtx, enum reg_class, int);
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Subroutines for insn-output.c for Tensilica's Xtensa architecture.
|
||||
Copyright 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
Free Software Foundation, Inc.
|
||||
Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica.
|
||||
|
||||
This file is part of GCC.
|
||||
@ -397,7 +398,7 @@ smalloffset_mem_p (rtx op)
|
||||
{
|
||||
rtx addr = XEXP (op, 0);
|
||||
if (GET_CODE (addr) == REG)
|
||||
return REG_OK_FOR_BASE_P (addr);
|
||||
return BASE_REG_P (addr, 0);
|
||||
if (GET_CODE (addr) == PLUS)
|
||||
{
|
||||
rtx offset = XEXP (addr, 0);
|
||||
@ -686,7 +687,8 @@ xtensa_expand_conditional_branch (rtx *operands, enum rtx_code test_code)
|
||||
|
||||
case CMP_SF:
|
||||
if (!TARGET_HARD_FLOAT)
|
||||
fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode, cmp0, cmp1));
|
||||
fatal_insn ("bad test", gen_rtx_fmt_ee (test_code, VOIDmode,
|
||||
cmp0, cmp1));
|
||||
invert = FALSE;
|
||||
cmp = gen_float_relational (test_code, cmp0, cmp1);
|
||||
break;
|
||||
@ -1370,6 +1372,92 @@ xtensa_emit_call (int callop, rtx *operands)
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
xtensa_legitimate_address_p (enum machine_mode mode, rtx addr, bool strict)
|
||||
{
|
||||
/* Allow constant pool addresses. */
|
||||
if (mode != BLKmode && GET_MODE_SIZE (mode) >= UNITS_PER_WORD
|
||||
&& ! TARGET_CONST16 && constantpool_address_p (addr))
|
||||
return true;
|
||||
|
||||
while (GET_CODE (addr) == SUBREG)
|
||||
addr = SUBREG_REG (addr);
|
||||
|
||||
/* Allow base registers. */
|
||||
if (GET_CODE (addr) == REG && BASE_REG_P (addr, strict))
|
||||
return true;
|
||||
|
||||
/* Check for "register + offset" addressing. */
|
||||
if (GET_CODE (addr) == PLUS)
|
||||
{
|
||||
rtx xplus0 = XEXP (addr, 0);
|
||||
rtx xplus1 = XEXP (addr, 1);
|
||||
enum rtx_code code0;
|
||||
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);
|
||||
|
||||
/* Swap operands if necessary so the register is first. */
|
||||
if (code0 != REG && code1 == REG)
|
||||
{
|
||||
xplus0 = XEXP (addr, 1);
|
||||
xplus1 = XEXP (addr, 0);
|
||||
code0 = GET_CODE (xplus0);
|
||||
code1 = GET_CODE (xplus1);
|
||||
}
|
||||
|
||||
if (code0 == REG && BASE_REG_P (xplus0, strict)
|
||||
&& code1 == CONST_INT
|
||||
&& xtensa_mem_offset (INTVAL (xplus1), mode))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
rtx
|
||||
xtensa_legitimize_address (rtx x,
|
||||
rtx oldx ATTRIBUTE_UNUSED,
|
||||
enum machine_mode mode)
|
||||
{
|
||||
if (GET_CODE (x) == PLUS)
|
||||
{
|
||||
rtx plus0 = XEXP (x, 0);
|
||||
rtx plus1 = XEXP (x, 1);
|
||||
|
||||
if (GET_CODE (plus0) != REG && GET_CODE (plus1) == REG)
|
||||
{
|
||||
plus0 = XEXP (x, 1);
|
||||
plus1 = XEXP (x, 0);
|
||||
}
|
||||
|
||||
/* Try to split up the offset to use an ADDMI instruction. */
|
||||
if (GET_CODE (plus0) == REG
|
||||
&& GET_CODE (plus1) == CONST_INT
|
||||
&& !xtensa_mem_offset (INTVAL (plus1), mode)
|
||||
&& !xtensa_simm8 (INTVAL (plus1))
|
||||
&& xtensa_mem_offset (INTVAL (plus1) & 0xff, mode)
|
||||
&& xtensa_simm8x256 (INTVAL (plus1) & ~0xff))
|
||||
{
|
||||
rtx temp = gen_reg_rtx (Pmode);
|
||||
rtx addmi_offset = GEN_INT (INTVAL (plus1) & ~0xff);
|
||||
emit_insn (gen_rtx_SET (Pmode, temp,
|
||||
gen_rtx_PLUS (Pmode, plus0, addmi_offset)));
|
||||
return gen_rtx_PLUS (Pmode, temp, GEN_INT (INTVAL (plus1) & 0xff));
|
||||
}
|
||||
}
|
||||
|
||||
return NULL_RTX;
|
||||
}
|
||||
|
||||
|
||||
/* Return the debugger register number to use for 'regno'. */
|
||||
|
||||
int
|
||||
@ -1820,6 +1908,29 @@ print_operand_address (FILE *file, rtx addr)
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
xtensa_output_addr_const_extra (FILE *fp, rtx x)
|
||||
{
|
||||
if (GET_CODE (x) == UNSPEC && XVECLEN (x, 0) == 1)
|
||||
{
|
||||
switch (XINT (x, 1))
|
||||
{
|
||||
case UNSPEC_PLT:
|
||||
if (flag_pic)
|
||||
{
|
||||
output_addr_const (fp, XVECEXP (x, 0, 0));
|
||||
fputs ("@PLT", fp);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
xtensa_output_literal (FILE *file, rtx x, enum machine_mode mode, int labelno)
|
||||
{
|
||||
|
@ -1,5 +1,6 @@
|
||||
/* Definitions of Tensilica's Xtensa target machine for GNU compiler.
|
||||
Copyright 2001, 2002, 2003, 2004, 2005, 2006 Free Software Foundation, Inc.
|
||||
Copyright 2001, 2002, 2003, 2004, 2005, 2006, 2007
|
||||
Free Software Foundation, Inc.
|
||||
Contributed by Bob Wilson (bwilson@tensilica.com) at Tensilica.
|
||||
|
||||
This file is part of GCC.
|
||||
@ -825,39 +826,27 @@ typedef struct xtensa_args
|
||||
/* Addressing modes, and classification of registers for them. */
|
||||
|
||||
/* C expressions which are nonzero if register number NUM is suitable
|
||||
for use as a base or index register in operand addresses. It may
|
||||
be either a suitable hard register or a pseudo register that has
|
||||
been allocated such a hard register. The difference between an
|
||||
index register and a base register is that the index register may
|
||||
be scaled. */
|
||||
for use as a base or index register in operand addresses. */
|
||||
|
||||
#define REGNO_OK_FOR_INDEX_P(NUM) 0
|
||||
#define REGNO_OK_FOR_BASE_P(NUM) \
|
||||
(GP_REG_P (NUM) || GP_REG_P ((unsigned) reg_renumber[NUM]))
|
||||
|
||||
#define REGNO_OK_FOR_INDEX_P(NUM) 0
|
||||
|
||||
/* C expressions that are nonzero if X (assumed to be a `reg' RTX) is
|
||||
valid for use as a base or index register. For hard registers, it
|
||||
should always accept those which the hardware permits and reject
|
||||
the others. Whether the macro accepts or rejects pseudo registers
|
||||
must be controlled by `REG_OK_STRICT'. This usually requires two
|
||||
variant definitions, of which `REG_OK_STRICT' controls the one
|
||||
actually used. The difference between an index register and a base
|
||||
register is that the index register may be scaled. */
|
||||
valid for use as a base or index register. */
|
||||
|
||||
#ifdef REG_OK_STRICT
|
||||
#define REG_OK_STRICT_FLAG 1
|
||||
#else
|
||||
#define REG_OK_STRICT_FLAG 0
|
||||
#endif
|
||||
|
||||
#define BASE_REG_P(X, STRICT) \
|
||||
((!(STRICT) && REGNO (X) >= FIRST_PSEUDO_REGISTER) \
|
||||
|| REGNO_OK_FOR_BASE_P (REGNO (X)))
|
||||
|
||||
#define REG_OK_FOR_INDEX_P(X) 0
|
||||
#define REG_OK_FOR_BASE_P(X) \
|
||||
REGNO_OK_FOR_BASE_P (REGNO (X))
|
||||
|
||||
#else /* !REG_OK_STRICT */
|
||||
|
||||
#define REG_OK_FOR_INDEX_P(X) 0
|
||||
#define REG_OK_FOR_BASE_P(X) \
|
||||
((REGNO (X) >= FIRST_PSEUDO_REGISTER) || (GP_REG_P (REGNO (X))))
|
||||
|
||||
#endif /* !REG_OK_STRICT */
|
||||
#define REG_OK_FOR_BASE_P(X) BASE_REG_P (X, REG_OK_STRICT_FLAG)
|
||||
|
||||
/* Maximum number of registers that can appear in a valid memory address. */
|
||||
#define MAX_REGS_PER_ADDRESS 1
|
||||
@ -865,52 +854,8 @@ typedef struct xtensa_args
|
||||
/* Identify valid Xtensa addresses. */
|
||||
#define GO_IF_LEGITIMATE_ADDRESS(MODE, ADDR, LABEL) \
|
||||
do { \
|
||||
rtx xinsn = (ADDR); \
|
||||
\
|
||||
/* allow constant pool addresses */ \
|
||||
if ((MODE) != BLKmode && GET_MODE_SIZE (MODE) >= UNITS_PER_WORD \
|
||||
&& !TARGET_CONST16 && constantpool_address_p (xinsn)) \
|
||||
if (xtensa_legitimate_address_p (MODE, ADDR, REG_OK_STRICT_FLAG)) \
|
||||
goto LABEL; \
|
||||
\
|
||||
while (GET_CODE (xinsn) == SUBREG) \
|
||||
xinsn = SUBREG_REG (xinsn); \
|
||||
\
|
||||
/* allow base registers */ \
|
||||
if (GET_CODE (xinsn) == REG && REG_OK_FOR_BASE_P (xinsn)) \
|
||||
goto LABEL; \
|
||||
\
|
||||
/* check for "register + offset" addressing */ \
|
||||
if (GET_CODE (xinsn) == PLUS) \
|
||||
{ \
|
||||
rtx xplus0 = XEXP (xinsn, 0); \
|
||||
rtx xplus1 = XEXP (xinsn, 1); \
|
||||
enum rtx_code code0; \
|
||||
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); \
|
||||
\
|
||||
/* swap operands if necessary so the register is first */ \
|
||||
if (code0 != REG && code1 == REG) \
|
||||
{ \
|
||||
xplus0 = XEXP (xinsn, 1); \
|
||||
xplus1 = XEXP (xinsn, 0); \
|
||||
code0 = GET_CODE (xplus0); \
|
||||
code1 = GET_CODE (xplus1); \
|
||||
} \
|
||||
\
|
||||
if (code0 == REG && REG_OK_FOR_BASE_P (xplus0) \
|
||||
&& code1 == CONST_INT \
|
||||
&& xtensa_mem_offset (INTVAL (xplus1), (MODE))) \
|
||||
{ \
|
||||
goto LABEL; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
/* A C expression that is 1 if the RTX X is a constant which is a
|
||||
@ -934,36 +879,13 @@ typedef struct xtensa_args
|
||||
&& GET_CODE (X) != LABEL_REF \
|
||||
&& GET_CODE (X) != CONST)
|
||||
|
||||
/* Tell GCC how to use ADDMI to generate addresses. */
|
||||
#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
|
||||
do { \
|
||||
rtx xinsn = (X); \
|
||||
if (GET_CODE (xinsn) == PLUS) \
|
||||
{ \
|
||||
rtx plus0 = XEXP (xinsn, 0); \
|
||||
rtx plus1 = XEXP (xinsn, 1); \
|
||||
\
|
||||
if (GET_CODE (plus0) != REG && GET_CODE (plus1) == REG) \
|
||||
{ \
|
||||
plus0 = XEXP (xinsn, 1); \
|
||||
plus1 = XEXP (xinsn, 0); \
|
||||
} \
|
||||
\
|
||||
if (GET_CODE (plus0) == REG \
|
||||
&& GET_CODE (plus1) == CONST_INT \
|
||||
&& !xtensa_mem_offset (INTVAL (plus1), MODE) \
|
||||
&& !xtensa_simm8 (INTVAL (plus1)) \
|
||||
&& xtensa_mem_offset (INTVAL (plus1) & 0xff, MODE) \
|
||||
&& xtensa_simm8x256 (INTVAL (plus1) & ~0xff)) \
|
||||
{ \
|
||||
rtx temp = gen_reg_rtx (Pmode); \
|
||||
emit_insn (gen_rtx_SET (Pmode, temp, \
|
||||
gen_rtx_PLUS (Pmode, plus0, \
|
||||
GEN_INT (INTVAL (plus1) & ~0xff)))); \
|
||||
(X) = gen_rtx_PLUS (Pmode, temp, \
|
||||
GEN_INT (INTVAL (plus1) & 0xff)); \
|
||||
goto WIN; \
|
||||
} \
|
||||
rtx new_x = xtensa_legitimize_address (X, OLDX, MODE); \
|
||||
if (new_x) \
|
||||
{ \
|
||||
X = new_x; \
|
||||
goto WIN; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
@ -1066,20 +988,7 @@ typedef struct xtensa_args
|
||||
constants. Used for PIC-specific UNSPECs. */
|
||||
#define OUTPUT_ADDR_CONST_EXTRA(STREAM, X, FAIL) \
|
||||
do { \
|
||||
if (flag_pic && GET_CODE (X) == UNSPEC && XVECLEN ((X), 0) == 1) \
|
||||
{ \
|
||||
switch (XINT ((X), 1)) \
|
||||
{ \
|
||||
case UNSPEC_PLT: \
|
||||
output_addr_const ((STREAM), XVECEXP ((X), 0, 0)); \
|
||||
fputs ("@PLT", (STREAM)); \
|
||||
break; \
|
||||
default: \
|
||||
goto FAIL; \
|
||||
} \
|
||||
break; \
|
||||
} \
|
||||
else \
|
||||
if (xtensa_output_addr_const_extra (STREAM, X) == FALSE) \
|
||||
goto FAIL; \
|
||||
} while (0)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user