From b97b06879d752144e246bdc1da52f98003de3437 Mon Sep 17 00:00:00 2001 From: rsandifo Date: Tue, 6 Mar 2007 08:54:31 +0000 Subject: [PATCH] gcc/ PR target/23482 PR target/17114 * config/m68k/m68k-protos.h (m68k_legitimate_base_reg_p): Declare. (m68k_legitimate_index_reg_p, m68k_legitimate_address_p): Likewise. (m68k_matches_q_p, m68k_matches_u_p): Likewise. * config/m68k/m68k.h (EXTRA_CONSTRAINT): Use m68k_matches_q_p and m68k_matches_u_p. (PCREL_GENERAL_OPERAND_OK, LEGITIMATE_BASE_REG_P): Delete. (INDIRECTABLE_1_ADDRESS_P, GO_IF_NONINDEXED_ADDRESS): Delete. (GO_IF_INDEXABLE_BASE, GO_IF_INDEXING, GO_IF_INDEXED_ADDRESS): Delete. (LEGITIMATE_INDEX_REG_P, LEGITIMATE_INDEX_P): Delete. (GO_IF_COLDFIRE_FPU_LEGITIMATE_ADDRESS): Delete. (REG_STRICT_P): New macro. (LEGITIMATE_PIC_OPERAND_P): Use REG_STRICT_P rather than PCREL_GENERAL_OPERAND_OK. (REG_OK_FOR_BASE_P): Merge definitions. Use REG_STRICT_P and m68k_legitimate_base_reg_p. (REG_MODE_OK_FOR_INDEX_P): Likewise m68k_legitimate_index_reg_p. (GO_IF_LEGITIMATE_ADDRESS): Likewise m68k_legitimate_address_p. (PIC_CASE_VECTOR_ADDRESS): Update comment. * config/m68k/m68k.c (m68k_address): New structure. (m68k_legitimate_base_reg_p, m68k_legitimate_index_reg_p) (m68k_decompose_index, m68k_legitimate_constant_address_p) (m68k_jump_table_ref_p, m68k_decompose_address) (m68k_legitimate_address_p, m68k_legitimate_mem_p, m68k_matches_q_p) (m68k_matches_u_p): New functions. (print_operand_address): Rewrite to use m68k_decompose_index. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@122604 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 30 ++ gcc/config/m68k/m68k-protos.h | 5 + gcc/config/m68k/m68k.c | 667 ++++++++++++++++++++++++++++-------------- gcc/config/m68k/m68k.h | 156 +--------- 4 files changed, 490 insertions(+), 368 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 6b19d77..c22df68 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,33 @@ +2007-03-06 Richard Sandiford + + PR target/23482 + PR target/17114 + * config/m68k/m68k-protos.h (m68k_legitimate_base_reg_p): Declare. + (m68k_legitimate_index_reg_p, m68k_legitimate_address_p): Likewise. + (m68k_matches_q_p, m68k_matches_u_p): Likewise. + * config/m68k/m68k.h (EXTRA_CONSTRAINT): Use m68k_matches_q_p + and m68k_matches_u_p. + (PCREL_GENERAL_OPERAND_OK, LEGITIMATE_BASE_REG_P): Delete. + (INDIRECTABLE_1_ADDRESS_P, GO_IF_NONINDEXED_ADDRESS): Delete. + (GO_IF_INDEXABLE_BASE, GO_IF_INDEXING, GO_IF_INDEXED_ADDRESS): Delete. + (LEGITIMATE_INDEX_REG_P, LEGITIMATE_INDEX_P): Delete. + (GO_IF_COLDFIRE_FPU_LEGITIMATE_ADDRESS): Delete. + (REG_STRICT_P): New macro. + (LEGITIMATE_PIC_OPERAND_P): Use REG_STRICT_P rather than + PCREL_GENERAL_OPERAND_OK. + (REG_OK_FOR_BASE_P): Merge definitions. Use REG_STRICT_P and + m68k_legitimate_base_reg_p. + (REG_MODE_OK_FOR_INDEX_P): Likewise m68k_legitimate_index_reg_p. + (GO_IF_LEGITIMATE_ADDRESS): Likewise m68k_legitimate_address_p. + (PIC_CASE_VECTOR_ADDRESS): Update comment. + * config/m68k/m68k.c (m68k_address): New structure. + (m68k_legitimate_base_reg_p, m68k_legitimate_index_reg_p) + (m68k_decompose_index, m68k_legitimate_constant_address_p) + (m68k_jump_table_ref_p, m68k_decompose_address) + (m68k_legitimate_address_p, m68k_legitimate_mem_p, m68k_matches_q_p) + (m68k_matches_u_p): New functions. + (print_operand_address): Rewrite to use m68k_decompose_index. + 2007/03/05 David Taylor * gcc.c: Correct copyright date in --version output. diff --git a/gcc/config/m68k/m68k-protos.h b/gcc/config/m68k/m68k-protos.h index d0ff670..ba137d6 100644 --- a/gcc/config/m68k/m68k-protos.h +++ b/gcc/config/m68k/m68k-protos.h @@ -50,7 +50,12 @@ extern int standard_68881_constant_p (rtx); extern void print_operand_address (FILE *, rtx); extern void print_operand (FILE *, rtx, int); extern void notice_update_cc (rtx, rtx); +extern bool m68k_legitimate_base_reg_p (rtx, bool); +extern bool m68k_legitimate_index_reg_p (rtx, bool); extern bool m68k_illegitimate_symbolic_constant_p (rtx); +extern bool m68k_legitimate_address_p (enum machine_mode, rtx, bool); +extern bool m68k_matches_q_p (rtx); +extern bool m68k_matches_u_p (rtx); extern rtx legitimize_pic_address (rtx, enum machine_mode, rtx); extern int valid_dbcc_comparison_p_2 (rtx, enum machine_mode); extern rtx m68k_libcall_value (enum machine_mode); diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index 90e2491..57e15c8 100644 --- a/gcc/config/m68k/m68k.c +++ b/gcc/config/m68k/m68k.c @@ -103,6 +103,27 @@ struct m68k_frame /* Current frame information calculated by m68k_compute_frame_layout(). */ static struct m68k_frame current_frame; +/* Structure describing an m68k address. + + If CODE is UNKNOWN, the address is BASE + INDEX * SCALE + OFFSET, + with null fields evaluating to 0. Here: + + - BASE satisfies m68k_legitimate_base_reg_p + - INDEX satisfies m68k_legitimate_index_reg_p + - OFFSET satisfies m68k_legitimate_constant_address_p + + INDEX is either HImode or SImode. The other fields are SImode. + + If CODE is PRE_DEC, the address is -(BASE). If CODE is POST_INC, + the address is (BASE)+. */ +struct m68k_address { + enum rtx_code code; + rtx base; + rtx index; + rtx offset; + int scale; +}; + static bool m68k_handle_option (size_t, const char *, int); static rtx find_addr_reg (rtx); static const char *singlemove_string (rtx *); @@ -1666,6 +1687,76 @@ output_btst (rtx *operands, rtx countop, rtx dataop, rtx insn, int signpos) return "btst %0,%1"; } +/* Return true if X is a legitimate base register. STRICT_P says + whether we need strict checking. */ + +bool +m68k_legitimate_base_reg_p (rtx x, bool strict_p) +{ + /* Allow SUBREG everywhere we allow REG. This results in better code. */ + if (!strict_p && GET_CODE (x) == SUBREG) + x = SUBREG_REG (x); + + return (REG_P (x) + && (strict_p + ? REGNO_OK_FOR_BASE_P (REGNO (x)) + : !DATA_REGNO_P (REGNO (x)) && !FP_REGNO_P (REGNO (x)))); +} + +/* Return true if X is a legitimate index register. STRICT_P says + whether we need strict checking. */ + +bool +m68k_legitimate_index_reg_p (rtx x, bool strict_p) +{ + if (!strict_p && GET_CODE (x) == SUBREG) + x = SUBREG_REG (x); + + return (REG_P (x) + && (strict_p + ? REGNO_OK_FOR_INDEX_P (REGNO (x)) + : !FP_REGNO_P (REGNO (x)))); +} + +/* Return true if X is a legitimate index expression for a (d8,An,Xn) or + (bd,An,Xn) addressing mode. Fill in the INDEX and SCALE fields of + ADDRESS if so. STRICT_P says whether we need strict checking. */ + +static bool +m68k_decompose_index (rtx x, bool strict_p, struct m68k_address *address) +{ + int scale; + + /* Check for a scale factor. */ + scale = 1; + if ((TARGET_68020 || TARGET_COLDFIRE) + && GET_CODE (x) == MULT + && GET_CODE (XEXP (x, 1)) == CONST_INT + && (INTVAL (XEXP (x, 1)) == 2 + || INTVAL (XEXP (x, 1)) == 4 + || (INTVAL (XEXP (x, 1)) == 8 + && (TARGET_COLDFIRE_FPU || !TARGET_COLDFIRE)))) + { + scale = INTVAL (XEXP (x, 1)); + x = XEXP (x, 0); + } + + /* Check for a word extension. */ + if (!TARGET_COLDFIRE + && GET_CODE (x) == SIGN_EXTEND + && GET_MODE (XEXP (x, 0)) == HImode) + x = XEXP (x, 0); + + if (m68k_legitimate_index_reg_p (x, strict_p)) + { + address->scale = scale; + address->index = x; + return true; + } + + return false; +} + /* Return true if X is an illegitimate symbolic constant. */ bool @@ -1683,6 +1774,251 @@ m68k_illegitimate_symbolic_constant_p (rtx x) return false; } +/* Return true if X is a legitimate constant address that can reach + bytes in the range [X, X + REACH). STRICT_P says whether we need + strict checking. */ + +static bool +m68k_legitimate_constant_address_p (rtx x, unsigned int reach, bool strict_p) +{ + rtx base, offset; + + if (!CONSTANT_ADDRESS_P (x)) + return false; + + if (flag_pic + && !(strict_p && TARGET_PCREL) + && symbolic_operand (x, VOIDmode)) + return false; + + if (M68K_OFFSETS_MUST_BE_WITHIN_SECTIONS_P && reach > 1) + { + split_const (x, &base, &offset); + if (GET_CODE (base) == SYMBOL_REF + && !offset_within_block_p (base, INTVAL (offset) + reach - 1)) + return false; + } + + return true; +} + +/* Return true if X is a LABEL_REF for a jump table. Assume that unplaced + labels will become jump tables. */ + +static bool +m68k_jump_table_ref_p (rtx x) +{ + if (GET_CODE (x) != LABEL_REF) + return false; + + x = XEXP (x, 0); + if (!NEXT_INSN (x) && !PREV_INSN (x)) + return true; + + x = next_nonnote_insn (x); + return x && JUMP_TABLE_DATA_P (x); +} + +/* Return true if X is a legitimate address for values of mode MODE. + STRICT_P says whether strict checking is needed. If the address + is valid, describe its components in *ADDRESS. */ + +static bool +m68k_decompose_address (enum machine_mode mode, rtx x, + bool strict_p, struct m68k_address *address) +{ + unsigned int reach; + + memset (address, 0, sizeof (*address)); + + if (mode == BLKmode) + reach = 1; + else + reach = GET_MODE_SIZE (mode); + + /* Check for (An) (mode 2). */ + if (m68k_legitimate_base_reg_p (x, strict_p)) + { + address->base = x; + return true; + } + + /* Check for -(An) and (An)+ (modes 3 and 4). */ + if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == POST_INC) + && m68k_legitimate_base_reg_p (XEXP (x, 0), strict_p)) + { + address->code = GET_CODE (x); + address->base = XEXP (x, 0); + return true; + } + + /* Check for (d16,An) (mode 5). */ + if (GET_CODE (x) == PLUS + && GET_CODE (XEXP (x, 1)) == CONST_INT + && IN_RANGE (INTVAL (XEXP (x, 1)), -0x8000, 0x8000 - reach) + && m68k_legitimate_base_reg_p (XEXP (x, 0), strict_p)) + { + address->base = XEXP (x, 0); + address->offset = XEXP (x, 1); + return true; + } + + /* Check for GOT loads. These are (bd,An,Xn) addresses if + TARGET_68020 && flag_pic == 2, otherwise they are (d16,An) + addresses. */ + if (flag_pic + && GET_CODE (x) == PLUS + && XEXP (x, 0) == pic_offset_table_rtx + && (GET_CODE (XEXP (x, 1)) == SYMBOL_REF + || GET_CODE (XEXP (x, 1)) == LABEL_REF)) + { + address->base = XEXP (x, 0); + address->offset = XEXP (x, 1); + return true; + } + + /* The ColdFire FPU only accepts addressing modes 2-5. */ + if (TARGET_COLDFIRE_FPU && GET_MODE_CLASS (mode) == MODE_FLOAT) + return false; + + /* Check for (xxx).w and (xxx).l. Also, in the TARGET_PCREL case, + check for (d16,PC) or (bd,PC,Xn) with a suppressed index register. + All these modes are variations of mode 7. */ + if (m68k_legitimate_constant_address_p (x, reach, strict_p)) + { + address->offset = x; + return true; + } + + /* Check for (d8,PC,Xn), a mode 7 form. This case is needed for + tablejumps. + + ??? do_tablejump creates these addresses before placing the target + label, so we have to assume that unplaced labels are jump table + references. It seems unlikely that we would ever generate indexed + accesses to unplaced labels in other cases. */ + if (GET_CODE (x) == PLUS + && m68k_jump_table_ref_p (XEXP (x, 1)) + && m68k_decompose_index (XEXP (x, 0), strict_p, address)) + { + address->offset = XEXP (x, 1); + return true; + } + + /* Everything hereafter deals with (d8,An,Xn.SIZE*SCALE) or + (bd,An,Xn.SIZE*SCALE) addresses. */ + + if (TARGET_68020) + { + /* Check for a nonzero base displacement. */ + if (GET_CODE (x) == PLUS + && m68k_legitimate_constant_address_p (XEXP (x, 1), reach, strict_p)) + { + address->offset = XEXP (x, 1); + x = XEXP (x, 0); + } + + /* Check for a suppressed index register. */ + if (m68k_legitimate_base_reg_p (x, strict_p)) + { + address->base = x; + return true; + } + + /* Check for a suppressed base register. Do not allow this case + for non-symbolic offsets as it effectively gives gcc freedom + to treat data registers as base registers, which can generate + worse code. */ + if (address->offset + && symbolic_operand (address->offset, VOIDmode) + && m68k_decompose_index (x, strict_p, address)) + return true; + } + else + { + /* Check for a nonzero base displacement. */ + if (GET_CODE (x) == PLUS + && GET_CODE (XEXP (x, 1)) == CONST_INT + && IN_RANGE (INTVAL (XEXP (x, 1)), -0x80, 0x80 - reach)) + { + address->offset = XEXP (x, 1); + x = XEXP (x, 0); + } + } + + /* We now expect the sum of a base and an index. */ + if (GET_CODE (x) == PLUS) + { + if (m68k_legitimate_base_reg_p (XEXP (x, 0), strict_p) + && m68k_decompose_index (XEXP (x, 1), strict_p, address)) + { + address->base = XEXP (x, 0); + return true; + } + + if (m68k_legitimate_base_reg_p (XEXP (x, 1), strict_p) + && m68k_decompose_index (XEXP (x, 0), strict_p, address)) + { + address->base = XEXP (x, 1); + return true; + } + } + return false; +} + +/* Return true if X is a legitimate address for values of mode MODE. + STRICT_P says whether strict checking is needed. */ + +bool +m68k_legitimate_address_p (enum machine_mode mode, rtx x, bool strict_p) +{ + struct m68k_address address; + + return m68k_decompose_address (mode, x, strict_p, &address); +} + +/* Return true if X is a memory, describing its address in ADDRESS if so. + Apply strict checking if called during or after reload. */ + +static bool +m68k_legitimate_mem_p (rtx x, struct m68k_address *address) +{ + return (MEM_P (x) + && m68k_decompose_address (GET_MODE (x), XEXP (x, 0), + reload_in_progress || reload_completed, + address)); +} + +/* Return true if X matches the 'Q' constraint. It must be a memory + with a base address and no constant offset or index. */ + +bool +m68k_matches_q_p (rtx x) +{ + struct m68k_address address; + + return (m68k_legitimate_mem_p (x, &address) + && address.code == UNKNOWN + && address.base + && !address.offset + && !address.index); +} + +/* Return true if X matches the 'U' constraint. It must be a base address + with a constant offset and no index. */ + +bool +m68k_matches_u_p (rtx x) +{ + struct m68k_address address; + + return (m68k_legitimate_mem_p (x, &address) + && address.code == UNKNOWN + && address.base + && address.offset + && !address.index); +} + /* Legitimize PIC addresses. If the address is already position-independent, we return ORIG. Newly generated position-independent addresses go to REG. If we need more @@ -3271,265 +3607,142 @@ print_operand (FILE *file, rtx op, int letter) offset is output in word mode (e.g. movel a5@(_foo:w), a0). When generating -fPIC code the offset is output in long mode (e.g. movel a5@(_foo:l), a0) */ -#if MOTOROLA -# define ASM_OUTPUT_CASE_FETCH(file, labelno, regname) \ - asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,%s.", labelno, labelno, regname) -#else /* !MOTOROLA */ -# define ASM_OUTPUT_CASE_FETCH(file, labelno, regname) \ - asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b,%s:", labelno, labelno, regname) -#endif /* !MOTOROLA */ - void print_operand_address (FILE *file, rtx addr) { - register rtx reg1, reg2, breg, ireg; - rtx offset; - - switch (GET_CODE (addr)) - { - case REG: - fprintf (file, MOTOROLA ? "(%s)" : "%s@", M68K_REGNAME (REGNO (addr))); - break; - case PRE_DEC: - fprintf (file, MOTOROLA ? "-(%s)" : "%s@-", - M68K_REGNAME (REGNO (XEXP (addr, 0)))); - break; - case POST_INC: - fprintf (file, MOTOROLA ? "(%s)+" : "%s@+", - M68K_REGNAME (REGNO (XEXP (addr, 0)))); - break; - case PLUS: - reg1 = reg2 = ireg = breg = offset = 0; - if (CONSTANT_ADDRESS_P (XEXP (addr, 0))) - { - offset = XEXP (addr, 0); - addr = XEXP (addr, 1); - } - else if (CONSTANT_ADDRESS_P (XEXP (addr, 1))) - { - offset = XEXP (addr, 1); - addr = XEXP (addr, 0); - } - if (GET_CODE (addr) != PLUS) - { - ; - } - else if (GET_CODE (XEXP (addr, 0)) == SIGN_EXTEND) - { - reg1 = XEXP (addr, 0); - addr = XEXP (addr, 1); - } - else if (GET_CODE (XEXP (addr, 1)) == SIGN_EXTEND) - { - reg1 = XEXP (addr, 1); - addr = XEXP (addr, 0); - } - else if (GET_CODE (XEXP (addr, 0)) == MULT) - { - reg1 = XEXP (addr, 0); - addr = XEXP (addr, 1); - } - else if (GET_CODE (XEXP (addr, 1)) == MULT) - { - reg1 = XEXP (addr, 1); - addr = XEXP (addr, 0); - } - else if (GET_CODE (XEXP (addr, 0)) == REG) - { - reg1 = XEXP (addr, 0); - addr = XEXP (addr, 1); - } - else if (GET_CODE (XEXP (addr, 1)) == REG) - { - reg1 = XEXP (addr, 1); - addr = XEXP (addr, 0); - } - if (GET_CODE (addr) == REG || GET_CODE (addr) == MULT - || GET_CODE (addr) == SIGN_EXTEND) + struct m68k_address address; + + if (!m68k_decompose_address (QImode, addr, true, &address)) + gcc_unreachable (); + + if (address.code == PRE_DEC) + fprintf (file, MOTOROLA ? "-(%s)" : "%s@-", + M68K_REGNAME (REGNO (address.base))); + else if (address.code == POST_INC) + fprintf (file, MOTOROLA ? "(%s)+" : "%s@+", + M68K_REGNAME (REGNO (address.base))); + else if (!address.base && !address.index) + { + /* A constant address. */ + gcc_assert (address.offset == addr); + if (GET_CODE (addr) == CONST_INT) { - if (reg1 == 0) - reg1 = addr; + /* (xxx).w or (xxx).l. */ + if (IN_RANGE (INTVAL (addr), -0x8000, 0x7fff)) + fprintf (file, MOTOROLA ? "%d.w" : "%d:w", (int) INTVAL (addr)); else - reg2 = addr; - addr = 0; - } -#if 0 /* for OLD_INDEXING */ - else if (GET_CODE (addr) == PLUS) - { - if (GET_CODE (XEXP (addr, 0)) == REG) - { - reg2 = XEXP (addr, 0); - addr = XEXP (addr, 1); - } - else if (GET_CODE (XEXP (addr, 1)) == REG) - { - reg2 = XEXP (addr, 1); - addr = XEXP (addr, 0); - } - } -#endif - if (offset != 0) - { - gcc_assert (!addr); - addr = offset; + fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (addr)); } - if ((reg1 && (GET_CODE (reg1) == SIGN_EXTEND - || GET_CODE (reg1) == MULT)) - || (reg2 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg2)))) - { - breg = reg2; - ireg = reg1; - } - else if (reg1 != 0 && REGNO_OK_FOR_BASE_P (REGNO (reg1))) + else if (TARGET_PCREL) { - breg = reg1; - ireg = reg2; + /* (d16,PC) or (bd,PC,Xn) (with suppressed index register). */ + fputc ('(', file); + output_addr_const (file, addr); + asm_fprintf (file, flag_pic == 1 ? ":w,%Rpc)" : ":l,%Rpc)"); } - if (ireg != 0 && breg == 0 && GET_CODE (addr) == LABEL_REF - && ! (flag_pic && ireg == pic_offset_table_rtx)) + else { - int scale = 1; - if (GET_CODE (ireg) == MULT) - { - scale = INTVAL (XEXP (ireg, 1)); - ireg = XEXP (ireg, 0); - } - if (GET_CODE (ireg) == SIGN_EXTEND) + /* (xxx).l. We need a special case for SYMBOL_REF if the symbol + name ends in `.', as the last 2 characters can be + mistaken as a size suffix. Put the name in parentheses. */ + if (GET_CODE (addr) == SYMBOL_REF + && strlen (XSTR (addr, 0)) > 2 + && XSTR (addr, 0)[strlen (XSTR (addr, 0)) - 2] == '.') { - ASM_OUTPUT_CASE_FETCH (file, - CODE_LABEL_NUMBER (XEXP (addr, 0)), - M68K_REGNAME (REGNO (XEXP (ireg, 0)))); - fprintf (file, "w"); + putc ('(', file); + output_addr_const (file, addr); + putc (')', file); } else - { - ASM_OUTPUT_CASE_FETCH (file, - CODE_LABEL_NUMBER (XEXP (addr, 0)), - M68K_REGNAME (REGNO (ireg))); - fprintf (file, "l"); - } - if (scale != 1) - fprintf (file, MOTOROLA ? "*%d" : ":%d", scale); - putc (')', file); - break; - } - if (breg != 0 && ireg == 0 && GET_CODE (addr) == LABEL_REF - && ! (flag_pic && breg == pic_offset_table_rtx)) - { - ASM_OUTPUT_CASE_FETCH (file, - CODE_LABEL_NUMBER (XEXP (addr, 0)), - M68K_REGNAME (REGNO (breg))); - fprintf (file, "l)"); - break; + output_addr_const (file, addr); } - if (ireg != 0 || breg != 0) + } + else + { + int labelno; + + /* If ADDR is a (d8,pc,Xn) address, this is the number of the + label being acceesed, otherwise it is -1. */ + labelno = (address.offset + && !address.base + && GET_CODE (address.offset) == LABEL_REF + ? CODE_LABEL_NUMBER (XEXP (address.offset, 0)) + : -1); + if (MOTOROLA) { - int scale = 1; - - gcc_assert (breg); - gcc_assert (flag_pic || !addr || GET_CODE (addr) != LABEL_REF); - - if (MOTOROLA) + /* Print the "offset(base" component. */ + if (labelno >= 0) + asm_fprintf (file, "%LL%d-%LLI%d.b(%Rpc,", labelno, labelno); + else { - if (addr != 0) + if (address.offset) { - output_addr_const (file, addr); - if (flag_pic && (breg == pic_offset_table_rtx)) + output_addr_const (file, address.offset); + if (flag_pic && address.base == pic_offset_table_rtx) { fprintf (file, "@GOT"); - if (flag_pic == 1) + if (flag_pic == 1 && TARGET_68020) fprintf (file, ".w"); } } - fprintf (file, "(%s", M68K_REGNAME (REGNO (breg))); - if (ireg != 0) - putc (',', file); + putc ('(', file); + if (address.base) + fputs (M68K_REGNAME (REGNO (address.base)), file); } - else /* !MOTOROLA */ + /* Print the ",index" component, if any. */ + if (address.index) { - fprintf (file, "%s@(", M68K_REGNAME (REGNO (breg))); - if (addr != 0) - { - output_addr_const (file, addr); - if (breg == pic_offset_table_rtx) - switch (flag_pic) - { - case 1: - fprintf (file, ":w"); - break; - case 2: - fprintf (file, ":l"); - break; - default: - break; - } - if (ireg != 0) - putc (',', file); - } - } /* !MOTOROLA */ - if (ireg != 0 && GET_CODE (ireg) == MULT) - { - scale = INTVAL (XEXP (ireg, 1)); - ireg = XEXP (ireg, 0); + if (address.base) + putc (',', file); + fprintf (file, "%s.%c", + M68K_REGNAME (REGNO (address.index)), + GET_MODE (address.index) == HImode ? 'w' : 'l'); + if (address.scale != 1) + fprintf (file, "*%d", address.scale); } - if (ireg != 0 && GET_CODE (ireg) == SIGN_EXTEND) - fprintf (file, MOTOROLA ? "%s.w" : "%s:w", - M68K_REGNAME (REGNO (XEXP (ireg, 0)))); - else if (ireg != 0) - fprintf (file, MOTOROLA ? "%s.l" : "%s:l", - M68K_REGNAME (REGNO (ireg))); - if (scale != 1) - fprintf (file, MOTOROLA ? "*%d" : ":%d", scale); putc (')', file); - break; - } - else if (reg1 != 0 && GET_CODE (addr) == LABEL_REF - && ! (flag_pic && reg1 == pic_offset_table_rtx)) - { - ASM_OUTPUT_CASE_FETCH (file, - CODE_LABEL_NUMBER (XEXP (addr, 0)), - M68K_REGNAME (REGNO (reg1))); - fprintf (file, "l)"); - break; } - /* FALL-THROUGH (is this really what we want?) */ - default: - if (GET_CODE (addr) == CONST_INT - && INTVAL (addr) < 0x8000 - && INTVAL (addr) >= -0x8000) - { - fprintf (file, MOTOROLA ? "%d.w" : "%d:w", (int) INTVAL (addr)); - } - else if (GET_CODE (addr) == CONST_INT) + else /* !MOTOROLA */ { - fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (addr)); - } - else if (TARGET_PCREL) - { - fputc ('(', file); - output_addr_const (file, addr); - if (flag_pic == 1) - asm_fprintf (file, ":w,%Rpc)"); + if (!address.offset && !address.index) + fprintf (file, "%s@", M68K_REGNAME (REGNO (address.base))); else - asm_fprintf (file, ":l,%Rpc)"); - } - else - { - /* Special case for SYMBOL_REF if the symbol name ends in - `.', this can be mistaken as a size suffix. Put - the name in parentheses. */ - if (GET_CODE (addr) == SYMBOL_REF - && strlen (XSTR (addr, 0)) > 2 - && XSTR (addr, 0)[strlen (XSTR (addr, 0)) - 2] == '.') { - putc ('(', file); - output_addr_const (file, addr); + /* Print the "base@(offset" component. */ + if (labelno >= 0) + asm_fprintf (file, "%Rpc@(%LL%d-%LLI%d-2:b", labelno, labelno); + else + { + if (address.base) + fputs (M68K_REGNAME (REGNO (address.base)), file); + fprintf (file, "@("); + if (address.offset) + { + output_addr_const (file, address.offset); + if (address.base == pic_offset_table_rtx && TARGET_68020) + switch (flag_pic) + { + case 1: + fprintf (file, ":w"); break; + case 2: + fprintf (file, ":l"); break; + default: + break; + } + } + } + /* Print the ",index" component, if any. */ + if (address.index) + { + fprintf (file, ",%s:%c", + M68K_REGNAME (REGNO (address.index)), + GET_MODE (address.index) == HImode ? 'w' : 'l'); + if (address.scale != 1) + fprintf (file, ":%d", address.scale); + } putc (')', file); } - else - output_addr_const (file, addr); } - break; } } diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h index f960f3b..0465688 100644 --- a/gcc/config/m68k/m68k.h +++ b/gcc/config/m68k/m68k.h @@ -535,14 +535,10 @@ extern enum reg_class regno_reg_class[]; || GET_CODE (OP) == CONST)) \ : \ (CODE) == 'Q' \ - ? (GET_CODE (OP) == MEM \ - && GET_CODE (XEXP (OP, 0)) == REG) \ + ? m68k_matches_q_p (OP) \ : \ (CODE) == 'U' \ - ? (GET_CODE (OP) == MEM \ - && GET_CODE (XEXP (OP, 0)) == PLUS \ - && GET_CODE (XEXP (XEXP (OP, 0), 0)) == REG \ - && GET_CODE (XEXP (XEXP (OP, 0), 1)) == CONST_INT) \ + ? m68k_matches_u_p (OP) \ : \ (CODE) == 'W' \ ? const_call_operand (OP, VOIDmode) \ @@ -807,153 +803,31 @@ __transfer_from_trampoline () \ && !m68k_illegitimate_symbolic_constant_p (X)) #ifndef REG_OK_STRICT -#define PCREL_GENERAL_OPERAND_OK 0 +#define REG_STRICT_P 0 #else -#define PCREL_GENERAL_OPERAND_OK (TARGET_PCREL) +#define REG_STRICT_P 1 #endif -#define LEGITIMATE_PIC_OPERAND_P(X) \ - (! symbolic_operand (X, VOIDmode) \ - || PCREL_GENERAL_OPERAND_OK) +#define LEGITIMATE_PIC_OPERAND_P(X) \ + (!symbolic_operand (X, VOIDmode) \ + || (TARGET_PCREL && REG_STRICT_P)) -#ifndef REG_OK_STRICT - -/* Nonzero if X is a hard reg that can be used as an index - or if it is a pseudo reg. */ -#define REG_OK_FOR_INDEX_P(X) !FP_REGNO_P (REGNO (X)) -/* 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) \ - (!DATA_REGNO_P (REGNO (X)) && !FP_REGNO_P (REGNO (X))) + m68k_legitimate_base_reg_p (X, REG_STRICT_P) -#else +#define REG_OK_FOR_INDEX_P(X) \ + m68k_legitimate_index_reg_p (X, REG_STRICT_P) -/* 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 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)) - -#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. - - When generating PIC, an address involving a SYMBOL_REF is legitimate - if and only if it is the sum of pic_offset_table_rtx and the SYMBOL_REF. - We use LEGITIMATE_PIC_OPERAND_P to throw out the illegitimate addresses, - and we explicitly check for the sum of pic_offset_table_rtx and a SYMBOL_REF. - - Likewise for a LABEL_REF when generating PIC. - - The other macros defined here are used only in GO_IF_LEGITIMATE_ADDRESS. */ - -/* Allow SUBREG everywhere we allow REG. This results in better code. It - also makes function inlining work when inline functions are called with - arguments that are SUBREGs. */ - -#define LEGITIMATE_BASE_REG_P(X) \ - ((GET_CODE (X) == REG && REG_OK_FOR_BASE_P (X)) \ - || (GET_CODE (X) == SUBREG \ - && GET_CODE (SUBREG_REG (X)) == REG \ - && REG_OK_FOR_BASE_P (SUBREG_REG (X)))) - -#define INDIRECTABLE_1_ADDRESS_P(X) \ - ((CONSTANT_ADDRESS_P (X) && (!flag_pic || LEGITIMATE_PIC_OPERAND_P (X))) \ - || LEGITIMATE_BASE_REG_P (X) \ - || ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_INC) \ - && LEGITIMATE_BASE_REG_P (XEXP (X, 0))) \ - || (GET_CODE (X) == PLUS \ - && LEGITIMATE_BASE_REG_P (XEXP (X, 0)) \ - && GET_CODE (XEXP (X, 1)) == CONST_INT \ - && (TARGET_68020 \ - || ((unsigned) INTVAL (XEXP (X, 1)) + 0x8000) < 0x10000)) \ - || (GET_CODE (X) == PLUS && XEXP (X, 0) == pic_offset_table_rtx \ - && flag_pic && GET_CODE (XEXP (X, 1)) == SYMBOL_REF) \ - || (GET_CODE (X) == PLUS && XEXP (X, 0) == pic_offset_table_rtx \ - && flag_pic && GET_CODE (XEXP (X, 1)) == LABEL_REF)) - -#define GO_IF_NONINDEXED_ADDRESS(X, ADDR) \ -{ if (INDIRECTABLE_1_ADDRESS_P (X)) goto ADDR; } - -/* Only labels on dispatch tables are valid for indexing from. */ -#define GO_IF_INDEXABLE_BASE(X, ADDR) \ -{ rtx temp; \ - if (GET_CODE (X) == LABEL_REF \ - && (temp = next_nonnote_insn (XEXP (X, 0))) != 0 \ - && GET_CODE (temp) == JUMP_INSN \ - && (GET_CODE (PATTERN (temp)) == ADDR_VEC \ - || GET_CODE (PATTERN (temp)) == ADDR_DIFF_VEC)) \ - goto ADDR; \ - if (LEGITIMATE_BASE_REG_P (X)) goto ADDR; } - -#define GO_IF_INDEXING(X, ADDR) \ -{ if (GET_CODE (X) == PLUS && LEGITIMATE_INDEX_P (XEXP (X, 0))) \ - { GO_IF_INDEXABLE_BASE (XEXP (X, 1), ADDR); } \ - if (GET_CODE (X) == PLUS && LEGITIMATE_INDEX_P (XEXP (X, 1))) \ - { GO_IF_INDEXABLE_BASE (XEXP (X, 0), ADDR); } } - -#define GO_IF_INDEXED_ADDRESS(X, ADDR) \ -{ GO_IF_INDEXING (X, ADDR); \ - if (GET_CODE (X) == PLUS) \ - { if (GET_CODE (XEXP (X, 1)) == CONST_INT \ - && (TARGET_68020 || (unsigned) INTVAL (XEXP (X, 1)) + 0x80 < 0x100)) \ - { rtx go_temp = XEXP (X, 0); GO_IF_INDEXING (go_temp, ADDR); } \ - if (GET_CODE (XEXP (X, 0)) == CONST_INT \ - && (TARGET_68020 || (unsigned) INTVAL (XEXP (X, 0)) + 0x80 < 0x100)) \ - { rtx go_temp = XEXP (X, 1); GO_IF_INDEXING (go_temp, ADDR); } } } - -/* ColdFire/5200 does not allow HImode index registers. */ -#define LEGITIMATE_INDEX_REG_P(X) \ - ((GET_CODE (X) == REG && REG_OK_FOR_INDEX_P (X)) \ - || (! TARGET_COLDFIRE \ - && GET_CODE (X) == SIGN_EXTEND \ - && GET_CODE (XEXP (X, 0)) == REG \ - && GET_MODE (XEXP (X, 0)) == HImode \ - && REG_OK_FOR_INDEX_P (XEXP (X, 0))) \ - || (GET_CODE (X) == SUBREG \ - && GET_CODE (SUBREG_REG (X)) == REG \ - && REG_OK_FOR_INDEX_P (SUBREG_REG (X)))) - -#define LEGITIMATE_INDEX_P(X) \ - (LEGITIMATE_INDEX_REG_P (X) \ - || ((TARGET_68020 || TARGET_COLDFIRE) && GET_CODE (X) == MULT \ - && LEGITIMATE_INDEX_REG_P (XEXP (X, 0)) \ - && GET_CODE (XEXP (X, 1)) == CONST_INT \ - && (INTVAL (XEXP (X, 1)) == 2 \ - || INTVAL (XEXP (X, 1)) == 4 \ - || (INTVAL (XEXP (X, 1)) == 8 \ - && (TARGET_COLDFIRE_FPU || !TARGET_COLDFIRE))))) - -/* ColdFire FPU only accepts addressing modes 2-5. */ -#define GO_IF_COLDFIRE_FPU_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -{ if (LEGITIMATE_BASE_REG_P (X) \ - || ((GET_CODE (X) == PRE_DEC || GET_CODE (X) == POST_INC) \ - && LEGITIMATE_BASE_REG_P (XEXP (X, 0))) \ - || ((GET_CODE (X) == PLUS) && LEGITIMATE_BASE_REG_P (XEXP (X, 0)) \ - && (GET_CODE (XEXP (X, 1)) == CONST_INT) \ - && ((((unsigned) INTVAL (XEXP (X, 1)) + 0x8000) < 0x10000)))) \ - goto ADDR;} - -/* If pic, we accept INDEX+LABEL, which is what do_tablejump makes. */ #define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \ -{ if (TARGET_COLDFIRE_FPU && (GET_MODE_CLASS (MODE) == MODE_FLOAT)) \ + do \ { \ - GO_IF_COLDFIRE_FPU_LEGITIMATE_ADDRESS (MODE, X, ADDR); \ + if (m68k_legitimate_address_p (MODE, X, REG_STRICT_P)) \ + goto ADDR; \ } \ - else \ - { \ - GO_IF_NONINDEXED_ADDRESS (X, ADDR); \ - GO_IF_INDEXED_ADDRESS (X, ADDR); \ - if (flag_pic && MODE == CASE_VECTOR_MODE && GET_CODE (X) == PLUS \ - && LEGITIMATE_INDEX_P (XEXP (X, 0)) \ - && GET_CODE (XEXP (X, 1)) == LABEL_REF) \ - goto ADDR; \ - }} + while (0) /* Don't call memory_address_noforce for the address to fetch - the switch offset. This address is ok as it stands (see above), + the switch offset. This address is ok as it stands, but memory_address_noforce would alter it. */ #define PIC_CASE_VECTOR_ADDRESS(index) index -- 2.7.4