X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fconfig%2Fv850%2Fv850.c;h=b7dd0921d4a876cc422eb5ed027b3e8d37d8c214;hb=9a3865f966dc1e3daa62bf36a998bc646775da02;hp=f3a165d28f484be4681cdac494b18a72af70e354;hpb=f054eb3c16ec5aec863986d2e14a6174a77e3cd4;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/config/v850/v850.c b/gcc/config/v850/v850.c index f3a165d28f4..b7dd0921d4a 100644 --- a/gcc/config/v850/v850.c +++ b/gcc/config/v850/v850.c @@ -1,13 +1,13 @@ /* Subroutines for insn-output.c for NEC V850 series - Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 - Free Software Foundation, Inc. + Copyright (C) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, + 2006, 2007, 2008, 2009 Free Software Foundation, Inc. Contributed by Jeff Law (law@cygnus.com). This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) + the Free Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT @@ -16,9 +16,8 @@ for more details. You should have received a copy of the GNU General Public License - along with GCC; see the file COPYING. If not, write to the Free - Software Foundation, 59 Temple Place - Suite 330, Boston, MA - 02111-1307, USA. */ + along with GCC; see the file COPYING3. If not see + . */ #include "config.h" #include "system.h" @@ -43,42 +42,48 @@ #include "tm_p.h" #include "target.h" #include "target-def.h" +#include "df.h" #ifndef streq #define streq(a,b) (strcmp (a, b) == 0) #endif /* Function prototypes for stupid compilers: */ +static bool v850_handle_option (size_t, const char *, int); static void const_double_split (rtx, HOST_WIDE_INT *, HOST_WIDE_INT *); static int const_costs_int (HOST_WIDE_INT, int); static int const_costs (rtx, enum rtx_code); -static bool v850_rtx_costs (rtx, int, int, int *); +static bool v850_rtx_costs (rtx, int, int, int *, bool); static void substitute_ep_register (rtx, rtx, int, int, rtx *, rtx *); static void v850_reorg (void); static int ep_memory_offset (enum machine_mode, int); static void v850_set_data_area (tree, v850_data_area); -const struct attribute_spec v850_attribute_table[]; static tree v850_handle_interrupt_attribute (tree *, tree, tree, int, bool *); static tree v850_handle_data_area_attribute (tree *, tree, tree, int, bool *); static void v850_insert_attributes (tree, tree *); -static void v850_select_section (tree, int, unsigned HOST_WIDE_INT); +static void v850_asm_init_sections (void); +static section *v850_select_section (tree, int, unsigned HOST_WIDE_INT); static void v850_encode_data_area (tree, rtx); static void v850_encode_section_info (tree, rtx, int); -static bool v850_return_in_memory (tree, tree); +static bool v850_return_in_memory (const_tree, const_tree); +static rtx v850_function_value (const_tree, const_tree, bool); static void v850_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode, tree, int *, int); static bool v850_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode, - tree, bool); + const_tree, bool); static int v850_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode, tree, bool); +static bool v850_can_eliminate (const int, const int); +static void v850_asm_trampoline_template (FILE *); +static void v850_trampoline_init (rtx, tree, rtx); /* Information about the various small memory areas. */ struct small_memory_info small_memory[ (int)SMALL_MEMORY_max ] = { - /* name value max physical max */ - { "tda", (char *)0, 0, 256 }, - { "sda", (char *)0, 0, 65536 }, - { "zda", (char *)0, 0, 32768 }, + /* name max physical max */ + { "tda", 0, 256 }, + { "sda", 0, 65536 }, + { "zda", 0, 32768 }, }; /* Names of the various data areas used on the v850. */ @@ -95,6 +100,26 @@ static int v850_interrupt_cache_p = FALSE; /* Whether current function is an interrupt handler. */ static int v850_interrupt_p = FALSE; + +static GTY(()) section *rosdata_section; +static GTY(()) section *rozdata_section; +static GTY(()) section *tdata_section; +static GTY(()) section *zdata_section; +static GTY(()) section *zbss_section; + +/* V850 specific attributes. */ + +static const struct attribute_spec v850_attribute_table[] = +{ + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ + { "interrupt_handler", 0, 0, true, false, false, v850_handle_interrupt_attribute }, + { "interrupt", 0, 0, true, false, false, v850_handle_interrupt_attribute }, + { "sda", 0, 0, true, false, false, v850_handle_data_area_attribute }, + { "tda", 0, 0, true, false, false, v850_handle_data_area_attribute }, + { "zda", 0, 0, true, false, false, v850_handle_data_area_attribute }, + { NULL, 0, 0, false, false, false, NULL } +}; + /* Initialize the GCC target structure. */ #undef TARGET_ASM_ALIGNED_HI_OP @@ -109,27 +134,40 @@ static int v850_interrupt_p = FALSE; #undef TARGET_ASM_SELECT_SECTION #define TARGET_ASM_SELECT_SECTION v850_select_section +/* The assembler supports switchable .bss sections, but + v850_select_section doesn't yet make use of them. */ +#undef TARGET_HAVE_SWITCHABLE_BSS_SECTIONS +#define TARGET_HAVE_SWITCHABLE_BSS_SECTIONS false + #undef TARGET_ENCODE_SECTION_INFO #define TARGET_ENCODE_SECTION_INFO v850_encode_section_info #undef TARGET_ASM_FILE_START_FILE_DIRECTIVE #define TARGET_ASM_FILE_START_FILE_DIRECTIVE true +#undef TARGET_DEFAULT_TARGET_FLAGS +#define TARGET_DEFAULT_TARGET_FLAGS (MASK_DEFAULT | MASK_APP_REGS) +#undef TARGET_HANDLE_OPTION +#define TARGET_HANDLE_OPTION v850_handle_option + #undef TARGET_RTX_COSTS #define TARGET_RTX_COSTS v850_rtx_costs #undef TARGET_ADDRESS_COST -#define TARGET_ADDRESS_COST hook_int_rtx_0 +#define TARGET_ADDRESS_COST hook_int_rtx_bool_0 #undef TARGET_MACHINE_DEPENDENT_REORG #define TARGET_MACHINE_DEPENDENT_REORG v850_reorg #undef TARGET_PROMOTE_PROTOTYPES -#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true +#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true #undef TARGET_RETURN_IN_MEMORY #define TARGET_RETURN_IN_MEMORY v850_return_in_memory +#undef TARGET_FUNCTION_VALUE +#define TARGET_FUNCTION_VALUE v850_function_value + #undef TARGET_PASS_BY_REFERENCE #define TARGET_PASS_BY_REFERENCE v850_pass_by_reference @@ -142,55 +180,78 @@ static int v850_interrupt_p = FALSE; #undef TARGET_ARG_PARTIAL_BYTES #define TARGET_ARG_PARTIAL_BYTES v850_arg_partial_bytes +#undef TARGET_CAN_ELIMINATE +#define TARGET_CAN_ELIMINATE v850_can_eliminate + +#undef TARGET_ASM_TRAMPOLINE_TEMPLATE +#define TARGET_ASM_TRAMPOLINE_TEMPLATE v850_asm_trampoline_template +#undef TARGET_TRAMPOLINE_INIT +#define TARGET_TRAMPOLINE_INIT v850_trampoline_init + struct gcc_target targetm = TARGET_INITIALIZER; -/* Sometimes certain combinations of command options do not make - sense on a particular target machine. You can define a macro - `OVERRIDE_OPTIONS' to take account of this. This macro, if - defined, is executed once just after all the command options have - been parsed. +/* Set the maximum size of small memory area TYPE to the value given + by VALUE. Return true if VALUE was syntactically correct. VALUE + starts with the argument separator: either "-" or "=". */ - Don't use this macro to turn on various extra optimizations for - `-O'. That is what `OPTIMIZATION_OPTIONS' is for. */ - -void -override_options (void) +static bool +v850_handle_memory_option (enum small_memory_type type, const char *value) { - int i; - extern int atoi (const char *); + int i, size; - /* Parse -m{s,t,z}da=nnn switches */ - for (i = 0; i < (int)SMALL_MEMORY_max; i++) - { - if (small_memory[i].value) - { - if (!ISDIGIT (*small_memory[i].value)) - error ("%s=%s is not numeric", - small_memory[i].name, - small_memory[i].value); - else - { - small_memory[i].max = atoi (small_memory[i].value); - if (small_memory[i].max > small_memory[i].physical_max) - error ("%s=%s is too large", - small_memory[i].name, - small_memory[i].value); - } - } - } + if (*value != '-' && *value != '=') + return false; + + value++; + for (i = 0; value[i]; i++) + if (!ISDIGIT (value[i])) + return false; + + size = atoi (value); + if (size > small_memory[type].physical_max) + error ("value passed to %<-m%s%> is too large", small_memory[type].name); + else + small_memory[type].max = size; + return true; +} - /* Make sure that the US_BIT_SET mask has been correctly initialized. */ - if ((target_flags & MASK_US_MASK_SET) == 0) +/* Implement TARGET_HANDLE_OPTION. */ + +static bool +v850_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED) +{ + switch (code) { - target_flags |= MASK_US_MASK_SET; - target_flags &= ~MASK_US_BIT_SET; + case OPT_mspace: + target_flags |= MASK_EP | MASK_PROLOG_FUNCTION; + return true; + + case OPT_mv850: + target_flags &= ~(MASK_CPU ^ MASK_V850); + return true; + + case OPT_mv850e: + case OPT_mv850e1: + target_flags &= ~(MASK_CPU ^ MASK_V850E); + return true; + + case OPT_mtda: + return v850_handle_memory_option (SMALL_MEMORY_TDA, arg); + + case OPT_msda: + return v850_handle_memory_option (SMALL_MEMORY_SDA, arg); + + case OPT_mzda: + return v850_handle_memory_option (SMALL_MEMORY_ZDA, arg); + + default: + return true; } } - static bool v850_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED, - enum machine_mode mode, tree type, + enum machine_mode mode, const_tree type, bool named ATTRIBUTE_UNUSED) { unsigned HOST_WIDE_INT size; @@ -203,8 +264,9 @@ v850_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED, return size > 8; } -/* Return an RTX to represent where a value with mode MODE will be returned - from a function. If the result is 0, the argument is pushed. */ +/* Return an RTX to represent where an argument with mode MODE + and type TYPE will be passed to a function. If the result + is NULL_RTX, the argument will be pushed. */ rtx function_arg (CUMULATIVE_ARGS * cum, @@ -212,7 +274,7 @@ function_arg (CUMULATIVE_ARGS * cum, tree type, int named) { - rtx result = 0; + rtx result = NULL_RTX; int size, align; if (TARGET_GHS && !named) @@ -224,7 +286,11 @@ function_arg (CUMULATIVE_ARGS * cum, size = GET_MODE_SIZE (mode); if (size < 1) - return 0; + { + /* Once we have stopped using argument registers, do not start up again. */ + cum->nbytes = 4 * UNITS_PER_WORD; + return NULL_RTX; + } if (type) align = TYPE_ALIGN (type) / BITS_PER_UNIT; @@ -234,11 +300,11 @@ function_arg (CUMULATIVE_ARGS * cum, cum->nbytes = (cum->nbytes + align - 1) &~(align - 1); if (cum->nbytes > 4 * UNITS_PER_WORD) - return 0; + return NULL_RTX; if (type == NULL_TREE && cum->nbytes + size > 4 * UNITS_PER_WORD) - return 0; + return NULL_RTX; switch (cum->nbytes / UNITS_PER_WORD) { @@ -255,7 +321,7 @@ function_arg (CUMULATIVE_ARGS * cum, result = gen_rtx_REG (mode, 9); break; default: - result = 0; + result = NULL_RTX; } return result; @@ -279,12 +345,15 @@ v850_arg_partial_bytes (CUMULATIVE_ARGS * cum, enum machine_mode mode, else size = GET_MODE_SIZE (mode); + if (size < 1) + size = 1; + if (type) align = TYPE_ALIGN (type) / BITS_PER_UNIT; else align = size; - cum->nbytes = (cum->nbytes + align - 1) &~(align - 1); + cum->nbytes = (cum->nbytes + align - 1) & ~ (align - 1); if (cum->nbytes > 4 * UNITS_PER_WORD) return 0; @@ -387,10 +456,12 @@ const_costs (rtx r, enum rtx_code c) static bool v850_rtx_costs (rtx x, - int code, + int codearg, int outer_code ATTRIBUTE_UNUSED, - int * total) + int * total, bool speed) { + enum rtx_code code = (enum rtx_code) codearg; + switch (code) { case CONST_INT: @@ -405,7 +476,7 @@ v850_rtx_costs (rtx x, case DIV: case UMOD: case UDIV: - if (TARGET_V850E && optimize_size) + if (TARGET_V850E && !speed) *total = 6; else *total = 60; @@ -431,6 +502,11 @@ v850_rtx_costs (rtx x, *total = 20; return true; + case ZERO_EXTRACT: + if (outer_code == COMPARE) + *total = 0; + return false; + default: return false; } @@ -497,30 +573,40 @@ print_operand (FILE * file, rtx x, int code) fprintf (file, "l"); break; default: - abort (); + gcc_unreachable (); } break; case 'F': /* high word of CONST_DOUBLE */ - if (GET_CODE (x) == CONST_INT) - fprintf (file, "%d", (INTVAL (x) >= 0) ? 0 : -1); - else if (GET_CODE (x) == CONST_DOUBLE) + switch (GET_CODE (x)) { + case CONST_INT: + fprintf (file, "%d", (INTVAL (x) >= 0) ? 0 : -1); + break; + + case CONST_DOUBLE: const_double_split (x, &high, &low); fprintf (file, "%ld", (long) high); + break; + + default: + gcc_unreachable (); } - else - abort (); break; case 'G': /* low word of CONST_DOUBLE */ - if (GET_CODE (x) == CONST_INT) - fprintf (file, "%ld", (long) INTVAL (x)); - else if (GET_CODE (x) == CONST_DOUBLE) + switch (GET_CODE (x)) { + case CONST_INT: + fprintf (file, "%ld", (long) INTVAL (x)); + break; + + case CONST_DOUBLE: const_double_split (x, &high, &low); fprintf (file, "%ld", (long) low); + break; + + default: + gcc_unreachable (); } - else - abort (); break; case 'L': fprintf (file, "%d\n", (int)(INTVAL (x) & 0xffff)); @@ -529,54 +615,42 @@ print_operand (FILE * file, rtx x, int code) fprintf (file, "%d", exact_log2 (INTVAL (x))); break; case 'O': - if (special_symbolref_operand (x, VOIDmode)) - { - if (GET_CODE (x) == SYMBOL_REF) - ; - else if (GET_CODE (x) == CONST) - x = XEXP (XEXP (x, 0), 0); - else - abort (); - - if (SYMBOL_REF_ZDA_P (x)) - fprintf (file, "zdaoff"); - else if (SYMBOL_REF_SDA_P (x)) - fprintf (file, "sdaoff"); - else if (SYMBOL_REF_TDA_P (x)) - fprintf (file, "tdaoff"); - else - abort (); - } + gcc_assert (special_symbolref_operand (x, VOIDmode)); + + if (GET_CODE (x) == CONST) + x = XEXP (XEXP (x, 0), 0); else - abort (); + gcc_assert (GET_CODE (x) == SYMBOL_REF); + + if (SYMBOL_REF_ZDA_P (x)) + fprintf (file, "zdaoff"); + else if (SYMBOL_REF_SDA_P (x)) + fprintf (file, "sdaoff"); + else if (SYMBOL_REF_TDA_P (x)) + fprintf (file, "tdaoff"); + else + gcc_unreachable (); break; case 'P': - if (special_symbolref_operand (x, VOIDmode)) - output_addr_const (file, x); - else - abort (); + gcc_assert (special_symbolref_operand (x, VOIDmode)); + output_addr_const (file, x); break; case 'Q': - if (special_symbolref_operand (x, VOIDmode)) - { - if (GET_CODE (x) == SYMBOL_REF) - ; - else if (GET_CODE (x) == CONST) - x = XEXP (XEXP (x, 0), 0); - else - abort (); - - if (SYMBOL_REF_ZDA_P (x)) - fprintf (file, "r0"); - else if (SYMBOL_REF_SDA_P (x)) - fprintf (file, "gp"); - else if (SYMBOL_REF_TDA_P (x)) - fprintf (file, "ep"); - else - abort (); - } + gcc_assert (special_symbolref_operand (x, VOIDmode)); + + if (GET_CODE (x) == CONST) + x = XEXP (XEXP (x, 0), 0); + else + gcc_assert (GET_CODE (x) == SYMBOL_REF); + + if (SYMBOL_REF_ZDA_P (x)) + fprintf (file, "r0"); + else if (SYMBOL_REF_SDA_P (x)) + fprintf (file, "gp"); + else if (SYMBOL_REF_TDA_P (x)) + fprintf (file, "ep"); else - abort (); + gcc_unreachable (); break; case 'R': /* 2nd word of a double. */ switch (GET_CODE (x)) @@ -597,7 +671,7 @@ print_operand (FILE * file, rtx x, int code) break; case 'S': { - /* if it's a reference to a TDA variable, use sst/sld vs. st/ld */ + /* If it's a reference to a TDA variable, use sst/sld vs. st/ld. */ if (GET_CODE (x) == MEM && ep_memory_operand (x, GET_MODE (x), FALSE)) fputs ("s", file); @@ -615,7 +689,7 @@ print_operand (FILE * file, rtx x, int code) switch (GET_MODE (x)) { default: - abort (); + gcc_unreachable (); case QImode: fputs (".b", file); break; case HImode: fputs (".h", file); break; @@ -627,12 +701,13 @@ print_operand (FILE * file, rtx x, int code) fputs (reg_names[0], file); break; case 'z': /* reg or zero */ - if (x == const0_rtx) - fputs (reg_names[0], file); - else if (GET_CODE (x) == REG) + if (GET_CODE (x) == REG) fputs (reg_names[REGNO (x)], file); else - abort (); + { + gcc_assert (x == const0_rtx); + fputs (reg_names[0], file); + } break; default: switch (GET_CODE (x)) @@ -659,7 +734,7 @@ print_operand (FILE * file, rtx x, int code) print_operand_address (file, x); break; default: - abort (); + gcc_unreachable (); } break; @@ -758,7 +833,7 @@ print_operand_address (FILE * file, rtx addr) reg_name = "ep"; } else - abort (); + gcc_unreachable (); fprintf (file, "%s(", off_name); output_addr_const (file, addr); @@ -822,10 +897,10 @@ output_move_single (rtx * operands) { HOST_WIDE_INT value = INTVAL (src); - if (CONST_OK_FOR_J (value)) /* Signed 5 bit immediate. */ + if (CONST_OK_FOR_J (value)) /* Signed 5-bit immediate. */ return "mov %1,%0"; - else if (CONST_OK_FOR_K (value)) /* Signed 16 bit immediate. */ + else if (CONST_OK_FOR_K (value)) /* Signed 16-bit immediate. */ return "movea lo(%1),%.,%0"; else if (CONST_OK_FOR_L (value)) /* Upper 16 bits were set. */ @@ -844,10 +919,10 @@ output_move_single (rtx * operands) const_double_split (src, &high, &low); - if (CONST_OK_FOR_J (high)) /* Signed 5 bit immediate. */ + if (CONST_OK_FOR_J (high)) /* Signed 5-bit immediate. */ return "mov %F1,%0"; - else if (CONST_OK_FOR_K (high)) /* Signed 16 bit immediate. */ + else if (CONST_OK_FOR_K (high)) /* Signed 16-bit immediate. */ return "movea lo(%F1),%.,%0"; else if (CONST_OK_FOR_L (high)) /* Upper 16 bits were set. */ @@ -906,84 +981,6 @@ output_move_single (rtx * operands) } -/* Return appropriate code to load up an 8 byte integer or - floating point value */ - -const char * -output_move_double (rtx * operands) -{ - enum machine_mode mode = GET_MODE (operands[0]); - rtx dst = operands[0]; - rtx src = operands[1]; - - if (register_operand (dst, mode) - && register_operand (src, mode)) - { - if (REGNO (src) + 1 == REGNO (dst)) - return "mov %R1,%R0\n\tmov %1,%0"; - else - return "mov %1,%0\n\tmov %R1,%R0"; - } - - /* Storing 0 */ - if (GET_CODE (dst) == MEM - && ((GET_CODE (src) == CONST_INT && INTVAL (src) == 0) - || (GET_CODE (src) == CONST_DOUBLE && CONST_DOUBLE_OK_FOR_G (src)))) - return "st.w %.,%0\n\tst.w %.,%R0"; - - if (GET_CODE (src) == CONST_INT || GET_CODE (src) == CONST_DOUBLE) - { - HOST_WIDE_INT high_low[2]; - int i; - rtx xop[10]; - - if (GET_CODE (src) == CONST_DOUBLE) - const_double_split (src, &high_low[1], &high_low[0]); - else - { - high_low[0] = INTVAL (src); - high_low[1] = (INTVAL (src) >= 0) ? 0 : -1; - } - - for (i = 0; i < 2; i++) - { - xop[0] = gen_rtx_REG (SImode, REGNO (dst)+i); - xop[1] = GEN_INT (high_low[i]); - output_asm_insn (output_move_single (xop), xop); - } - - return ""; - } - - if (GET_CODE (src) == MEM) - { - int ptrreg = -1; - int dreg = REGNO (dst); - rtx inside = XEXP (src, 0); - - if (GET_CODE (inside) == REG) - ptrreg = REGNO (inside); - else if (GET_CODE (inside) == SUBREG) - ptrreg = subreg_regno (inside); - else if (GET_CODE (inside) == PLUS) - ptrreg = REGNO (XEXP (inside, 0)); - else if (GET_CODE (inside) == LO_SUM) - ptrreg = REGNO (XEXP (inside, 0)); - - if (dreg == ptrreg) - return "ld.w %R1,%R0\n\tld.w %1,%0"; - } - - if (GET_CODE (src) == MEM) - return "ld.w %1,%0\n\tld.w %R1,%R0"; - - if (GET_CODE (dst) == MEM) - return "st.w %1,%0\n\tst.w %R1,%R0"; - - return "mov %1,%0\n\tmov %R1,%R0"; -} - - /* Return maximum offset supported for a short EP memory reference of mode MODE and signedness UNSIGNEDP. */ @@ -1037,6 +1034,13 @@ ep_memory_operand (rtx op, enum machine_mode mode, int unsigned_load) int max_offset; int mask; + /* If we are not using the EP register on a per-function basis + then do not allow this optimization at all. This is to + prevent the use of the SLD/SST instructions which cannot be + guaranteed to work properly due to a hardware bug. */ + if (!TARGET_EP) + return FALSE; + if (GET_CODE (op) != MEM) return FALSE; @@ -1078,132 +1082,6 @@ ep_memory_operand (rtx op, enum machine_mode mode, int unsigned_load) return FALSE; } - -/* Return true if OP is either a register or 0 */ - -int -reg_or_0_operand (rtx op, enum machine_mode mode) -{ - if (GET_CODE (op) == CONST_INT) - return INTVAL (op) == 0; - - else if (GET_CODE (op) == CONST_DOUBLE) - return CONST_DOUBLE_OK_FOR_G (op); - - else - return register_operand (op, mode); -} - -/* Return true if OP is either a register or a signed five bit integer */ - -int -reg_or_int5_operand (rtx op, enum machine_mode mode) -{ - if (GET_CODE (op) == CONST_INT) - return CONST_OK_FOR_J (INTVAL (op)); - - else - return register_operand (op, mode); -} - -/* Return true if OP is either a register or a signed nine bit integer. */ - -int -reg_or_int9_operand (rtx op, enum machine_mode mode) -{ - if (GET_CODE (op) == CONST_INT) - return CONST_OK_FOR_O (INTVAL (op)); - - return register_operand (op, mode); -} - -/* Return true if OP is either a register or a const integer. */ - -int -reg_or_const_operand (rtx op, enum machine_mode mode) -{ - if (GET_CODE (op) == CONST_INT) - return TRUE; - - return register_operand (op, mode); -} - -/* Return true if OP is a valid call operand. */ - -int -call_address_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - /* Only registers are valid call operands if TARGET_LONG_CALLS. */ - if (TARGET_LONG_CALLS) - return GET_CODE (op) == REG; - return (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == REG); -} - -int -special_symbolref_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - if (GET_CODE (op) == CONST - && GET_CODE (XEXP (op, 0)) == PLUS - && GET_CODE (XEXP (XEXP (op, 0), 1)) == CONST_INT - && CONST_OK_FOR_K (INTVAL (XEXP (XEXP (op, 0), 1)))) - op = XEXP (XEXP (op, 0), 0); - - if (GET_CODE (op) == SYMBOL_REF) - return (SYMBOL_REF_FLAGS (op) - & (SYMBOL_FLAG_ZDA | SYMBOL_FLAG_TDA | SYMBOL_FLAG_SDA)) != 0; - - return FALSE; -} - -int -movsi_source_operand (rtx op, enum machine_mode mode) -{ - /* Some constants, as well as symbolic operands - must be done with HIGH & LO_SUM patterns. */ - if (CONSTANT_P (op) - && GET_CODE (op) != HIGH - && !(GET_CODE (op) == CONST_INT - && (CONST_OK_FOR_J (INTVAL (op)) - || CONST_OK_FOR_K (INTVAL (op)) - || CONST_OK_FOR_L (INTVAL (op))))) - return special_symbolref_operand (op, mode); - else - return general_operand (op, mode); -} - -int -power_of_two_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - if (GET_CODE (op) != CONST_INT) - return 0; - - if (exact_log2 (INTVAL (op)) == -1) - return 0; - return 1; -} - -int -not_power_of_two_operand (rtx op, enum machine_mode mode) -{ - unsigned int mask; - - if (mode == QImode) - mask = 0xff; - else if (mode == HImode) - mask = 0xffff; - else if (mode == SImode) - mask = 0xffffffff; - else - return 0; - - if (GET_CODE (op) != CONST_INT) - return 0; - - if (exact_log2 (~INTVAL (op) & mask) == -1) - return 0; - return 1; -} - /* Substitute memory references involving a pointer, to use the ep pointer, taking care to save and preserve the ep. */ @@ -1221,7 +1099,7 @@ substitute_ep_register (rtx first_insn, if (!*p_r1) { - regs_ever_live[1] = 1; + df_set_regs_ever_live (1, true); *p_r1 = gen_rtx_REG (Pmode, 1); *p_ep = gen_rtx_REG (Pmode, 30); } @@ -1547,12 +1425,15 @@ compute_register_save_size (long * p_reg_saved) int size = 0; int i; int interrupt_handler = v850_interrupt_function_p (current_function_decl); - int call_p = regs_ever_live [LINK_POINTER_REGNUM]; + int call_p = df_regs_ever_live_p (LINK_POINTER_REGNUM); long reg_saved = 0; /* Count the return pointer if we need to save it. */ - if (current_function_profile && !call_p) - regs_ever_live [LINK_POINTER_REGNUM] = call_p = 1; + if (crtl->profile && !call_p) + { + df_set_regs_ever_live (LINK_POINTER_REGNUM, true); + call_p = 1; + } /* Count space for the register saves. */ if (interrupt_handler) @@ -1561,7 +1442,7 @@ compute_register_save_size (long * p_reg_saved) switch (i) { default: - if (regs_ever_live[i] || call_p) + if (df_regs_ever_live_p (i) || call_p) { size += 4; reg_saved |= 1L << i; @@ -1589,7 +1470,7 @@ compute_register_save_size (long * p_reg_saved) { /* Find the first register that needs to be saved. */ for (i = 0; i <= 31; i++) - if (regs_ever_live[i] && ((! call_used_regs[i]) + if (df_regs_ever_live_p (i) && ((! call_used_regs[i]) || i == LINK_POINTER_REGNUM)) break; @@ -1621,7 +1502,7 @@ compute_register_save_size (long * p_reg_saved) reg_saved |= 1L << i; } - if (regs_ever_live [LINK_POINTER_REGNUM]) + if (df_regs_ever_live_p (LINK_POINTER_REGNUM)) { size += 4; reg_saved |= 1L << LINK_POINTER_REGNUM; @@ -1630,7 +1511,7 @@ compute_register_save_size (long * p_reg_saved) else { for (; i <= 31; i++) - if (regs_ever_live[i] && ((! call_used_regs[i]) + if (df_regs_ever_live_p (i) && ((! call_used_regs[i]) || i == LINK_POINTER_REGNUM)) { size += 4; @@ -1650,7 +1531,7 @@ compute_frame_size (int size, long * p_reg_saved) { return (size + compute_register_save_size (p_reg_saved) - + current_function_outgoing_args_size); + + crtl->outgoing_args_size); } @@ -1687,7 +1568,7 @@ expand_prologue (void) } /* Save arg registers to the stack if necessary. */ - else if (current_function_args_info.anonymous_args) + else if (crtl->args.info.anonymous_args) { if (TARGET_PROLOG_FUNCTION && TARGET_V850E && !TARGET_DISABLE_CALLT) emit_insn (gen_save_r6_r9_v850e ()); @@ -1829,7 +1710,7 @@ Saved %d bytes via prologue function (%d vs. %d) for function %s\n", if (init_stack_alloc) emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, - GEN_INT (-init_stack_alloc))); + GEN_INT (- (signed) init_stack_alloc))); /* Save the return pointer first. */ if (num_save > 0 && REGNO (save_regs[num_save-1]) == LINK_POINTER_REGNUM) @@ -1883,7 +1764,7 @@ expand_epilogue (void) int offset; unsigned int size = get_frame_size (); long reg_saved = 0; - unsigned int actual_fsize = compute_frame_size (size, ®_saved); + int actual_fsize = compute_frame_size (size, ®_saved); unsigned int init_stack_free = 0; rtx restore_regs[32]; rtx restore_all; @@ -1927,7 +1808,7 @@ expand_epilogue (void) if (TARGET_PROLOG_FUNCTION && num_restore > 0 - && actual_fsize >= default_stack + && actual_fsize >= (signed) default_stack && !interrupt_handler) { int alloc_stack = (4 * num_restore) + default_stack; @@ -2008,7 +1889,7 @@ Saved %d bytes via epilogue function (%d vs. %d) in function %s\n", } } - /* If no epilog save function is available, restore the registers the + /* If no epilogue save function is available, restore the registers the old fashioned way (one by one). */ if (!restore_all) { @@ -2016,10 +1897,10 @@ Saved %d bytes via epilogue function (%d vs. %d) in function %s\n", if (actual_fsize && !CONST_OK_FOR_K (-actual_fsize)) init_stack_free = 4 * num_restore; else - init_stack_free = actual_fsize; + init_stack_free = (signed) actual_fsize; /* Deallocate the rest of the stack if it is > 32K. */ - if (actual_fsize > init_stack_free) + if ((unsigned int) actual_fsize > init_stack_free) { int diff; @@ -2071,7 +1952,7 @@ Saved %d bytes via epilogue function (%d vs. %d) in function %s\n", plus_constant (stack_pointer_rtx, offset))); - emit_insn (gen_rtx_USE (VOIDmode, restore_regs[i])); + emit_use (restore_regs[i]); offset -= 4; } @@ -2093,7 +1974,7 @@ Saved %d bytes via epilogue function (%d vs. %d) in function %s\n", else if (actual_fsize) emit_jump_insn (gen_return_internal ()); else - emit_jump_insn (gen_return ()); + emit_jump_insn (gen_return_simple ()); } v850_interrupt_cache_p = FALSE; @@ -2185,17 +2066,6 @@ v850_set_data_area (tree decl, v850_data_area data_area) (name, NULL, DECL_ATTRIBUTES (decl)); } -const struct attribute_spec v850_attribute_table[] = -{ - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ - { "interrupt_handler", 0, 0, true, false, false, v850_handle_interrupt_attribute }, - { "interrupt", 0, 0, true, false, false, v850_handle_interrupt_attribute }, - { "sda", 0, 0, true, false, false, v850_handle_data_area_attribute }, - { "tda", 0, 0, true, false, false, v850_handle_data_area_attribute }, - { "zda", 0, 0, true, false, false, v850_handle_data_area_attribute }, - { NULL, 0, 0, false, false, false, NULL } -}; - /* Handle an "interrupt" attribute; arguments as in struct attribute_spec.handler. */ static tree @@ -2207,8 +2077,8 @@ v850_handle_interrupt_attribute (tree * node, { if (TREE_CODE (*node) != FUNCTION_DECL) { - warning ("%qs attribute only applies to functions", - IDENTIFIER_POINTER (name)); + warning (OPT_Wattributes, "%qE attribute only applies to functions", + name); *no_add_attrs = true; } @@ -2236,15 +2106,16 @@ v850_handle_data_area_attribute (tree* node, else if (is_attribute_p ("zda", name)) data_area = DATA_AREA_ZDA; else - abort (); + gcc_unreachable (); switch (TREE_CODE (decl)) { case VAR_DECL: if (current_function_decl != NULL_TREE) { - error ("%Jdata area attributes cannot be specified for " - "local variables", decl, decl); + error_at (DECL_SOURCE_LOCATION (decl), + "data area attributes cannot be specified for " + "local variables"); *no_add_attrs = true; } @@ -2254,8 +2125,8 @@ v850_handle_data_area_attribute (tree* node, area = v850_get_data_area (decl); if (area != DATA_AREA_NORMAL && data_area != area) { - error ("%Jdata area of '%D' conflicts with previous declaration", - decl, decl); + error ("data area of %q+D conflicts with previous declaration", + decl); *no_add_attrs = true; } break; @@ -2351,7 +2222,7 @@ v850_encode_data_area (tree decl, rtx symbol) case DATA_AREA_ZDA: flags |= SYMBOL_FLAG_ZDA; break; case DATA_AREA_TDA: flags |= SYMBOL_FLAG_TDA; break; case DATA_AREA_SDA: flags |= SYMBOL_FLAG_SDA; break; - default: abort (); + default: gcc_unreachable (); } SYMBOL_REF_FLAGS (symbol) = flags; } @@ -2366,75 +2237,6 @@ v850_encode_section_info (tree decl, rtx rtl, int first) v850_encode_data_area (decl, XEXP (rtl, 0)); } -/* Return true if the given RTX is a register which can be restored - by a function epilogue. */ -int -register_is_ok_for_epilogue (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - /* The save/restore routines can only cope with registers 20 - 31. */ - return ((GET_CODE (op) == REG) - && (((REGNO (op) >= 20) && REGNO (op) <= 31))); -} - -/* Return nonzero if the given RTX is suitable for collapsing into - jump to a function epilogue. */ -int -pattern_is_ok_for_epilogue (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - int count = XVECLEN (op, 0); - int i; - - /* If there are no registers to restore then the function epilogue - is not suitable. */ - if (count <= 2) - return 0; - - /* The pattern matching has already established that we are performing a - function epilogue and that we are popping at least one register. We must - now check the remaining entries in the vector to make sure that they are - also register pops. There is no good reason why there should ever be - anything else in this vector, but being paranoid always helps... - - The test below performs the C equivalent of this machine description - pattern match: - - (set (match_operand:SI n "register_is_ok_for_epilogue" "r") - (mem:SI (plus:SI (reg:SI 3) (match_operand:SI n "immediate_operand" "i")))) - */ - - for (i = 3; i < count; i++) - { - rtx vector_element = XVECEXP (op, 0, i); - rtx dest; - rtx src; - rtx plus; - - if (GET_CODE (vector_element) != SET) - return 0; - - dest = SET_DEST (vector_element); - src = SET_SRC (vector_element); - - if (GET_CODE (dest) != REG - || GET_MODE (dest) != SImode - || ! register_is_ok_for_epilogue (dest, SImode) - || GET_CODE (src) != MEM - || GET_MODE (src) != SImode) - return 0; - - plus = XEXP (src, 0); - - if (GET_CODE (plus) != PLUS - || GET_CODE (XEXP (plus, 0)) != REG - || GET_MODE (XEXP (plus, 0)) != SImode - || REGNO (XEXP (plus, 0)) != STACK_POINTER_REGNUM - || GET_CODE (XEXP (plus, 1)) != CONST_INT) - return 0; - } - - return 1; -} - /* Construct a JR instruction to a routine that will perform the equivalent of the RTL passed in as an argument. This RTL is a function epilogue that pops registers off the stack and possibly releases some extra stack space @@ -2453,18 +2255,15 @@ construct_restore_jr (rtx op) if (count <= 2) { - error ("bogus JR construction: %d\n", count); + error ("bogus JR construction: %d", count); return NULL; } /* Work out how many bytes to pop off the stack before retrieving registers. */ - if (GET_CODE (XVECEXP (op, 0, 1)) != SET) - abort (); - if (GET_CODE (SET_SRC (XVECEXP (op, 0, 1))) != PLUS) - abort (); - if (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 1)), 1)) != CONST_INT) - abort (); + gcc_assert (GET_CODE (XVECEXP (op, 0, 1)) == SET); + gcc_assert (GET_CODE (SET_SRC (XVECEXP (op, 0, 1))) == PLUS); + gcc_assert (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 1)), 1)) == CONST_INT); stack_bytes = INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 1)), 1)); @@ -2484,12 +2283,10 @@ construct_restore_jr (rtx op) { rtx vector_element = XVECEXP (op, 0, i); - if (GET_CODE (vector_element) != SET) - abort (); - if (GET_CODE (SET_DEST (vector_element)) != REG) - abort (); - if (! register_is_ok_for_epilogue (SET_DEST (vector_element), SImode)) - abort (); + gcc_assert (GET_CODE (vector_element) == SET); + gcc_assert (GET_CODE (SET_DEST (vector_element)) == REG); + gcc_assert (register_is_ok_for_epilogue (SET_DEST (vector_element), + SImode)); mask |= 1 << REGNO (SET_DEST (vector_element)); } @@ -2501,24 +2298,19 @@ construct_restore_jr (rtx op) break; } - if (first >= 32) - abort (); + gcc_assert (first < 32); /* Discover the last register to pop. */ if (mask & (1 << LINK_POINTER_REGNUM)) { - if (stack_bytes != 16) - abort (); + gcc_assert (stack_bytes == 16); last = LINK_POINTER_REGNUM; } else { - if (stack_bytes != 0) - abort (); - - if ((mask & (1 << 29)) == 0) - abort (); + gcc_assert (!stack_bytes); + gcc_assert (mask & (1 << 29)); last = 29; } @@ -2552,89 +2344,6 @@ construct_restore_jr (rtx op) } -/* Return nonzero if the given RTX is suitable for collapsing into - a jump to a function prologue. */ -int -pattern_is_ok_for_prologue (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - int count = XVECLEN (op, 0); - int i; - rtx vector_element; - - /* If there are no registers to save then the function prologue - is not suitable. */ - if (count <= 2) - return 0; - - /* The pattern matching has already established that we are adjusting the - stack and pushing at least one register. We must now check that the - remaining entries in the vector to make sure that they are also register - pushes, except for the last entry which should be a CLOBBER of r10. - - The test below performs the C equivalent of this machine description - pattern match: - - (set (mem:SI (plus:SI (reg:SI 3) - (match_operand:SI 2 "immediate_operand" "i"))) - (match_operand:SI 3 "register_is_ok_for_epilogue" "r")) - - */ - - for (i = 2; i < count - (TARGET_LONG_CALLS ? 2: 1); i++) - { - rtx dest; - rtx src; - rtx plus; - - vector_element = XVECEXP (op, 0, i); - - if (GET_CODE (vector_element) != SET) - return 0; - - dest = SET_DEST (vector_element); - src = SET_SRC (vector_element); - - if (GET_CODE (dest) != MEM - || GET_MODE (dest) != SImode - || GET_CODE (src) != REG - || GET_MODE (src) != SImode - || ! register_is_ok_for_epilogue (src, SImode)) - return 0; - - plus = XEXP (dest, 0); - - if ( GET_CODE (plus) != PLUS - || GET_CODE (XEXP (plus, 0)) != REG - || GET_MODE (XEXP (plus, 0)) != SImode - || REGNO (XEXP (plus, 0)) != STACK_POINTER_REGNUM - || GET_CODE (XEXP (plus, 1)) != CONST_INT) - return 0; - - /* If the register is being pushed somewhere other than the stack - space just acquired by the first operand then abandon this quest. - Note: the test is <= because both values are negative. */ - if (INTVAL (XEXP (plus, 1)) - <= INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1))) - { - return 0; - } - } - - /* Make sure that the last entries in the vector are clobbers. */ - for (; i < count; i++) - { - vector_element = XVECEXP (op, 0, i); - - if (GET_CODE (vector_element) != CLOBBER - || GET_CODE (XEXP (vector_element, 0)) != REG - || !(REGNO (XEXP (vector_element, 0)) == 10 - || (TARGET_LONG_CALLS ? (REGNO (XEXP (vector_element, 0)) == 11) : 0 ))) - return 0; - } - - return 1; -} - /* Construct a JARL instruction to a routine that will perform the equivalent of the RTL passed as a parameter. This RTL is a function prologue that saves some of the registers r20 - r31 onto the stack, and possibly acquires @@ -2658,14 +2367,10 @@ construct_save_jarl (rtx op) } /* Paranoia. */ - if (GET_CODE (XVECEXP (op, 0, 0)) != SET) - abort (); - if (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != PLUS) - abort (); - if (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0)) != REG) - abort (); - if (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)) != CONST_INT) - abort (); + gcc_assert (GET_CODE (XVECEXP (op, 0, 0)) == SET); + gcc_assert (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) == PLUS); + gcc_assert (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 0)) == REG); + gcc_assert (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)) == CONST_INT); /* Work out how many bytes to push onto the stack after storing the registers. */ @@ -2687,12 +2392,10 @@ construct_save_jarl (rtx op) { rtx vector_element = XVECEXP (op, 0, i); - if (GET_CODE (vector_element) != SET) - abort (); - if (GET_CODE (SET_SRC (vector_element)) != REG) - abort (); - if (! register_is_ok_for_epilogue (SET_SRC (vector_element), SImode)) - abort (); + gcc_assert (GET_CODE (vector_element) == SET); + gcc_assert (GET_CODE (SET_SRC (vector_element)) == REG); + gcc_assert (register_is_ok_for_epilogue (SET_SRC (vector_element), + SImode)); mask |= 1 << REGNO (SET_SRC (vector_element)); } @@ -2704,23 +2407,19 @@ construct_save_jarl (rtx op) break; } - if (first >= 32) - abort (); + gcc_assert (first < 32); /* Discover the last register to push. */ if (mask & (1 << LINK_POINTER_REGNUM)) { - if (stack_bytes != -16) - abort (); + gcc_assert (stack_bytes == -16); last = LINK_POINTER_REGNUM; } else { - if (stack_bytes != 0) - abort (); - if ((mask & (1 << 29)) == 0) - abort (); + gcc_assert (!stack_bytes); + gcc_assert (mask & (1 << 29)); last = 29; } @@ -2763,24 +2462,24 @@ void v850_output_aligned_bss (FILE * file, tree decl, const char * name, - int size, + unsigned HOST_WIDE_INT size, int align) { switch (v850_get_data_area (decl)) { case DATA_AREA_ZDA: - zbss_section (); + switch_to_section (zbss_section); break; case DATA_AREA_SDA: - sbss_section (); + switch_to_section (sbss_section); break; case DATA_AREA_TDA: - tdata_section (); + switch_to_section (tdata_section); default: - bss_section (); + switch_to_section (bss_section); break; } @@ -2899,7 +2598,7 @@ v850_insert_attributes (tree decl, tree * attr_ptr ATTRIBUTE_UNUSED ) switch (v850_get_data_area (decl)) { default: - abort (); + gcc_unreachable (); case DATA_AREA_SDA: kind = ((TREE_READONLY (decl)) @@ -2946,67 +2645,6 @@ v850_insert_attributes (tree decl, tree * attr_ptr ATTRIBUTE_UNUSED ) } } -/* Return nonzero if the given RTX is suitable - for collapsing into a DISPOSE instruction. */ - -int -pattern_is_ok_for_dispose (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - int count = XVECLEN (op, 0); - int i; - - /* If there are no registers to restore then - the dispose instruction is not suitable. */ - if (count <= 2) - return 0; - - /* The pattern matching has already established that we are performing a - function epilogue and that we are popping at least one register. We must - now check the remaining entries in the vector to make sure that they are - also register pops. There is no good reason why there should ever be - anything else in this vector, but being paranoid always helps... - - The test below performs the C equivalent of this machine description - pattern match: - - (set (match_operand:SI n "register_is_ok_for_epilogue" "r") - (mem:SI (plus:SI (reg:SI 3) - (match_operand:SI n "immediate_operand" "i")))) - */ - - for (i = 3; i < count; i++) - { - rtx vector_element = XVECEXP (op, 0, i); - rtx dest; - rtx src; - rtx plus; - - if (GET_CODE (vector_element) != SET) - return 0; - - dest = SET_DEST (vector_element); - src = SET_SRC (vector_element); - - if ( GET_CODE (dest) != REG - || GET_MODE (dest) != SImode - || ! register_is_ok_for_epilogue (dest, SImode) - || GET_CODE (src) != MEM - || GET_MODE (src) != SImode) - return 0; - - plus = XEXP (src, 0); - - if ( GET_CODE (plus) != PLUS - || GET_CODE (XEXP (plus, 0)) != REG - || GET_MODE (XEXP (plus, 0)) != SImode - || REGNO (XEXP (plus, 0)) != STACK_POINTER_REGNUM - || GET_CODE (XEXP (plus, 1)) != CONST_INT) - return 0; - } - - return 1; -} - /* Construct a DISPOSE instruction that is the equivalent of the given RTX. We have already verified that this should be possible. */ @@ -3023,18 +2661,15 @@ construct_dispose_instruction (rtx op) if (count <= 2) { - error ("Bogus DISPOSE construction: %d\n", count); + error ("bogus DISPOSE construction: %d", count); return NULL; } /* Work out how many bytes to pop off the stack before retrieving registers. */ - if (GET_CODE (XVECEXP (op, 0, 1)) != SET) - abort (); - if (GET_CODE (SET_SRC (XVECEXP (op, 0, 1))) != PLUS) - abort (); - if (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 1)), 1)) != CONST_INT) - abort (); + gcc_assert (GET_CODE (XVECEXP (op, 0, 1)) == SET); + gcc_assert (GET_CODE (SET_SRC (XVECEXP (op, 0, 1))) == PLUS); + gcc_assert (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 1)), 1)) == CONST_INT); stack_bytes = INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 1)), 1)); @@ -3045,7 +2680,7 @@ construct_dispose_instruction (rtx op) will fit into the DISPOSE instruction. */ if (stack_bytes > 128) { - error ("Too much stack space to dispose of: %d", stack_bytes); + error ("too much stack space to dispose of: %d", stack_bytes); return NULL; } @@ -3056,12 +2691,10 @@ construct_dispose_instruction (rtx op) { rtx vector_element = XVECEXP (op, 0, i); - if (GET_CODE (vector_element) != SET) - abort (); - if (GET_CODE (SET_DEST (vector_element)) != REG) - abort (); - if (! register_is_ok_for_epilogue (SET_DEST (vector_element), SImode)) - abort (); + gcc_assert (GET_CODE (vector_element) == SET); + gcc_assert (GET_CODE (SET_DEST (vector_element)) == REG); + gcc_assert (register_is_ok_for_epilogue (SET_DEST (vector_element), + SImode)); if (REGNO (SET_DEST (vector_element)) == 2) use_callt = 1; @@ -3133,75 +2766,6 @@ construct_dispose_instruction (rtx op) return buff; } -/* Return nonzero if the given RTX is suitable - for collapsing into a PREPARE instruction. */ - -int -pattern_is_ok_for_prepare (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) -{ - int count = XVECLEN (op, 0); - int i; - - /* If there are no registers to restore then the prepare instruction - is not suitable. */ - if (count <= 1) - return 0; - - /* The pattern matching has already established that we are adjusting the - stack and pushing at least one register. We must now check that the - remaining entries in the vector to make sure that they are also register - pushes. - - The test below performs the C equivalent of this machine description - pattern match: - - (set (mem:SI (plus:SI (reg:SI 3) - (match_operand:SI 2 "immediate_operand" "i"))) - (match_operand:SI 3 "register_is_ok_for_epilogue" "r")) - - */ - - for (i = 2; i < count; i++) - { - rtx vector_element = XVECEXP (op, 0, i); - rtx dest; - rtx src; - rtx plus; - - if (GET_CODE (vector_element) != SET) - return 0; - - dest = SET_DEST (vector_element); - src = SET_SRC (vector_element); - - if ( GET_CODE (dest) != MEM - || GET_MODE (dest) != SImode - || GET_CODE (src) != REG - || GET_MODE (src) != SImode - || ! register_is_ok_for_epilogue (src, SImode) - ) - return 0; - - plus = XEXP (dest, 0); - - if ( GET_CODE (plus) != PLUS - || GET_CODE (XEXP (plus, 0)) != REG - || GET_MODE (XEXP (plus, 0)) != SImode - || REGNO (XEXP (plus, 0)) != STACK_POINTER_REGNUM - || GET_CODE (XEXP (plus, 1)) != CONST_INT) - return 0; - - /* If the register is being pushed somewhere other than the stack - space just acquired by the first operand then abandon this quest. - Note: the test is <= because both values are negative. */ - if (INTVAL (XEXP (plus, 1)) - <= INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1))) - return 0; - } - - return 1; -} - /* Construct a PREPARE instruction that is the equivalent of the given RTL. We have already verified that this should be possible. */ @@ -3218,18 +2782,15 @@ construct_prepare_instruction (rtx op) if (count <= 1) { - error ("Bogus PREPEARE construction: %d\n", count); + error ("bogus PREPEARE construction: %d", count); return NULL; } /* Work out how many bytes to push onto the stack after storing the registers. */ - if (GET_CODE (XVECEXP (op, 0, 0)) != SET) - abort (); - if (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) != PLUS) - abort (); - if (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)) != CONST_INT) - abort (); + gcc_assert (GET_CODE (XVECEXP (op, 0, 0)) == SET); + gcc_assert (GET_CODE (SET_SRC (XVECEXP (op, 0, 0))) == PLUS); + gcc_assert (GET_CODE (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)) == CONST_INT); stack_bytes = INTVAL (XEXP (SET_SRC (XVECEXP (op, 0, 0)), 1)); @@ -3240,7 +2801,7 @@ construct_prepare_instruction (rtx op) will fit into the DISPOSE instruction. */ if (stack_bytes < -128) { - error ("Too much stack space to prepare: %d", stack_bytes); + error ("too much stack space to prepare: %d", stack_bytes); return NULL; } @@ -3250,12 +2811,10 @@ construct_prepare_instruction (rtx op) { rtx vector_element = XVECEXP (op, 0, i); - if (GET_CODE (vector_element) != SET) - abort (); - if (GET_CODE (SET_SRC (vector_element)) != REG) - abort (); - if (! register_is_ok_for_epilogue (SET_SRC (vector_element), SImode)) - abort (); + gcc_assert (GET_CODE (vector_element) == SET); + gcc_assert (GET_CODE (SET_SRC (vector_element)) == REG); + gcc_assert (register_is_ok_for_epilogue (SET_SRC (vector_element), + SImode)); if (REGNO (SET_SRC (vector_element)) == 2) use_callt = 1; @@ -3338,7 +2897,34 @@ v850_return_addr (int count) return get_hard_reg_initial_val (Pmode, LINK_POINTER_REGNUM); } +/* Implement TARGET_ASM_INIT_SECTIONS. */ + static void +v850_asm_init_sections (void) +{ + rosdata_section + = get_unnamed_section (0, output_section_asm_op, + "\t.section .rosdata,\"a\""); + + rozdata_section + = get_unnamed_section (0, output_section_asm_op, + "\t.section .rozdata,\"a\""); + + tdata_section + = get_unnamed_section (SECTION_WRITE, output_section_asm_op, + "\t.section .tdata,\"aw\""); + + zdata_section + = get_unnamed_section (SECTION_WRITE, output_section_asm_op, + "\t.section .zdata,\"aw\""); + + zbss_section + = get_unnamed_section (SECTION_WRITE | SECTION_BSS, + output_section_asm_op, + "\t.section .zbss,\"aw\""); +} + +static section * v850_select_section (tree exp, int reloc ATTRIBUTE_UNUSED, unsigned HOST_WIDE_INT align ATTRIBUTE_UNUSED) @@ -3358,43 +2944,40 @@ v850_select_section (tree exp, switch (v850_get_data_area (exp)) { case DATA_AREA_ZDA: - if (is_const) - rozdata_section (); - else - zdata_section (); - break; + return is_const ? rozdata_section : zdata_section; case DATA_AREA_TDA: - tdata_section (); - break; + return tdata_section; case DATA_AREA_SDA: - if (is_const) - rosdata_section (); - else - sdata_section (); - break; + return is_const ? rosdata_section : sdata_section; default: - if (is_const) - readonly_data_section (); - else - data_section (); - break; + return is_const ? readonly_data_section : data_section; } } - else - readonly_data_section (); + return readonly_data_section; } /* Worker function for TARGET_RETURN_IN_MEMORY. */ static bool -v850_return_in_memory (tree type, tree fntype ATTRIBUTE_UNUSED) +v850_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) { /* Return values > 8 bytes in length in memory. */ return int_size_in_bytes (type) > 8 || TYPE_MODE (type) == BLKmode; } + +/* Worker function for TARGET_FUNCTION_VALUE. */ + +rtx +v850_function_value (const_tree valtype, + const_tree fn_decl_or_type ATTRIBUTE_UNUSED, + bool outgoing ATTRIBUTE_UNUSED) +{ + return gen_rtx_REG (TYPE_MODE (valtype), 10); +} + /* Worker function for TARGET_SETUP_INCOMING_VARARGS. */ @@ -3407,3 +2990,44 @@ v850_setup_incoming_varargs (CUMULATIVE_ARGS *ca, { ca->anonymous_args = (!TARGET_GHS ? 1 : 0); } + +/* Worker function for TARGET_CAN_ELIMINATE. */ + +static bool +v850_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to) +{ + return (to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true); +} + + +/* Worker function for TARGET_ASM_TRAMPOLINE_TEMPLATE. */ + +static void +v850_asm_trampoline_template (FILE *f) +{ + fprintf (f, "\tjarl .+4,r12\n"); + fprintf (f, "\tld.w 12[r12],r20\n"); + fprintf (f, "\tld.w 16[r12],r12\n"); + fprintf (f, "\tjmp [r12]\n"); + fprintf (f, "\tnop\n"); + fprintf (f, "\t.long 0\n"); + fprintf (f, "\t.long 0\n"); +} + +/* Worker function for TARGET_TRAMPOLINE_INIT. */ + +static void +v850_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value) +{ + rtx mem, fnaddr = XEXP (DECL_RTL (fndecl), 0); + + emit_block_move (m_tramp, assemble_trampoline_template (), + GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL); + + mem = adjust_address (m_tramp, SImode, 16); + emit_move_insn (mem, chain_value); + mem = adjust_address (m_tramp, SImode, 20); + emit_move_insn (mem, fnaddr); +} + +#include "gt-v850.h"