From 771b60860b0d3f91c0d93eb61efc95bc8e8f2227 Mon Sep 17 00:00:00 2001 From: bwilson Date: Sat, 3 Feb 2007 01:23:05 +0000 Subject: [PATCH] * 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@121533 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 16 +++++ gcc/config/xtensa/xtensa-protos.h | 5 +- gcc/config/xtensa/xtensa.c | 117 +++++++++++++++++++++++++++++++++- gcc/config/xtensa/xtensa.h | 131 ++++++-------------------------------- 4 files changed, 154 insertions(+), 115 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index dc35247..73626e6 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,19 @@ +2007-02-02 Bob Wilson + + * 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 * config/ia64/ia64.c (ia64_print_operand): Fix compare strings. diff --git a/gcc/config/xtensa/xtensa-protos.h b/gcc/config/xtensa/xtensa-protos.h index 762aa0a..f6cca7a 100644 --- a/gcc/config/xtensa/xtensa-protos.h +++ b/gcc/config/xtensa/xtensa-protos.h @@ -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); diff --git a/gcc/config/xtensa/xtensa.c b/gcc/config/xtensa/xtensa.c index 49a8992..6269f1f 100644 --- a/gcc/config/xtensa/xtensa.c +++ b/gcc/config/xtensa/xtensa.c @@ -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) { diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h index d1fe022..11c4184 100644 --- a/gcc/config/xtensa/xtensa.h +++ b/gcc/config/xtensa/xtensa.h @@ -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 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 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 (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)) \ - 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)) \ + if (xtensa_legitimate_address_p (MODE, ADDR, REG_OK_STRICT_FLAG)) \ 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) -- 2.7.4