Mercurial > hg > CbC > CbC_gcc
diff gcc/config/mcore/mcore.c @ 111:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | f6334be47118 |
children | 84e7813d76e9 |
line wrap: on
line diff
--- a/gcc/config/mcore/mcore.c Sun Aug 21 07:07:55 2011 +0900 +++ b/gcc/config/mcore/mcore.c Fri Oct 27 22:46:09 2017 +0900 @@ -1,6 +1,5 @@ /* Output routines for Motorola MCore processor - Copyright (C) 1993, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2007, 2008, - 2009, 2010 Free Software Foundation, Inc. + Copyright (C) 1993-2017 Free Software Foundation, Inc. This file is part of GCC. @@ -21,28 +20,30 @@ #include "config.h" #include "system.h" #include "coretypes.h" -#include "tm.h" +#include "backend.h" +#include "target.h" #include "rtl.h" #include "tree.h" +#include "df.h" +#include "memmodel.h" #include "tm_p.h" +#include "stringpool.h" +#include "attribs.h" +#include "emit-rtl.h" +#include "diagnostic-core.h" +#include "stor-layout.h" +#include "varasm.h" +#include "calls.h" #include "mcore.h" -#include "regs.h" -#include "hard-reg-set.h" -#include "insn-config.h" -#include "conditions.h" #include "output.h" -#include "insn-attr.h" -#include "flags.h" -#include "obstack.h" +#include "explow.h" #include "expr.h" -#include "reload.h" -#include "recog.h" -#include "function.h" -#include "ggc.h" -#include "diagnostic-core.h" -#include "target.h" +#include "cfgrtl.h" +#include "builtins.h" +#include "regs.h" + +/* This file should be included last. */ #include "target-def.h" -#include "df.h" /* For dumping information about frame sizes. */ char * mcore_current_function_name = 0; @@ -93,16 +94,16 @@ static void output_stack_adjust (int, int); static int calc_live_regs (int *); -static int try_constant_tricks (long, HOST_WIDE_INT *, HOST_WIDE_INT *); -static const char * output_inline_const (enum machine_mode, rtx *); +static int try_constant_tricks (HOST_WIDE_INT, HOST_WIDE_INT *, HOST_WIDE_INT *); +static const char * output_inline_const (machine_mode, rtx *); static void layout_mcore_frame (struct mcore_frame *); -static void mcore_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode, tree, int *, int); +static void mcore_setup_incoming_varargs (cumulative_args_t, machine_mode, tree, int *, int); static cond_type is_cond_candidate (rtx); -static rtx emit_new_cond_insn (rtx, int); -static rtx conditionalize_block (rtx); +static rtx_insn *emit_new_cond_insn (rtx_insn *, int); +static rtx_insn *conditionalize_block (rtx_insn *); static void conditionalize_optimization (void); static void mcore_reorg (void); -static rtx handle_structs_in_regs (enum machine_mode, const_tree, int); +static rtx handle_structs_in_regs (machine_mode, const_tree, int); static void mcore_mark_dllexport (tree); static void mcore_mark_dllimport (tree); static int mcore_dllexport_p (tree); @@ -113,59 +114,51 @@ unsigned int, tree); #endif static void mcore_print_operand (FILE *, rtx, int); -static void mcore_print_operand_address (FILE *, rtx); +static void mcore_print_operand_address (FILE *, machine_mode, rtx); static bool mcore_print_operand_punct_valid_p (unsigned char code); static void mcore_unique_section (tree, int); static void mcore_encode_section_info (tree, rtx, int); static const char *mcore_strip_name_encoding (const char *); -static int mcore_const_costs (rtx, RTX_CODE); -static int mcore_and_cost (rtx); -static int mcore_ior_cost (rtx); -static bool mcore_rtx_costs (rtx, int, int, int *, bool); +static int mcore_const_costs (rtx, RTX_CODE); +static int mcore_and_cost (rtx); +static int mcore_ior_cost (rtx); +static bool mcore_rtx_costs (rtx, machine_mode, int, int, + int *, bool); static void mcore_external_libcall (rtx); static bool mcore_return_in_memory (const_tree, const_tree); -static int mcore_arg_partial_bytes (CUMULATIVE_ARGS *, - enum machine_mode, +static int mcore_arg_partial_bytes (cumulative_args_t, + machine_mode, tree, bool); -static rtx mcore_function_arg (CUMULATIVE_ARGS *, - enum machine_mode, +static rtx mcore_function_arg (cumulative_args_t, + machine_mode, const_tree, bool); -static void mcore_function_arg_advance (CUMULATIVE_ARGS *, - enum machine_mode, +static void mcore_function_arg_advance (cumulative_args_t, + machine_mode, const_tree, bool); -static unsigned int mcore_function_arg_boundary (enum machine_mode, +static unsigned int mcore_function_arg_boundary (machine_mode, const_tree); static void mcore_asm_trampoline_template (FILE *); static void mcore_trampoline_init (rtx, tree, rtx); +static bool mcore_warn_func_return (tree); static void mcore_option_override (void); +static bool mcore_legitimate_constant_p (machine_mode, rtx); +static bool mcore_legitimate_address_p (machine_mode, rtx, bool, + addr_space_t); +static bool mcore_hard_regno_mode_ok (unsigned int, machine_mode); +static bool mcore_modes_tieable_p (machine_mode, machine_mode); /* MCore specific attributes. */ static const struct attribute_spec mcore_attribute_table[] = { - /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ - { "dllexport", 0, 0, true, false, false, NULL }, - { "dllimport", 0, 0, true, false, false, NULL }, - { "naked", 0, 0, true, false, false, mcore_handle_naked_attribute }, - { NULL, 0, 0, false, false, false, NULL } + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler, + affects_type_identity } */ + { "dllexport", 0, 0, true, false, false, NULL, false }, + { "dllimport", 0, 0, true, false, false, NULL, false }, + { "naked", 0, 0, true, false, false, mcore_handle_naked_attribute, + false }, + { NULL, 0, 0, false, false, false, NULL, false } }; - -/* What options are we going to default to specific settings when - -O* happens; the user can subsequently override these settings. - - Omitting the frame pointer is a very good idea on the MCore. - Scheduling isn't worth anything on the current MCore implementation. */ - -static const struct default_options mcore_option_optimization_table[] = - { - { OPT_LEVELS_1_PLUS, OPT_ffunction_cse, NULL, 0 }, - { OPT_LEVELS_1_PLUS, OPT_fomit_frame_pointer, NULL, 1 }, - { OPT_LEVELS_ALL, OPT_fcaller_saves, NULL, 0 }, - { OPT_LEVELS_ALL, OPT_fschedule_insns, NULL, 0 }, - { OPT_LEVELS_ALL, OPT_fschedule_insns2, NULL, 0 }, - { OPT_LEVELS_SIZE, OPT_mhardlit, NULL, 0 }, - { OPT_LEVELS_NONE, 0, NULL, 0 } - }; /* Initialize the GCC target structure. */ #undef TARGET_ASM_EXTERNAL_LIBCALL @@ -196,8 +189,6 @@ #define TARGET_ASM_UNIQUE_SECTION mcore_unique_section #undef TARGET_ASM_FUNCTION_RODATA_SECTION #define TARGET_ASM_FUNCTION_RODATA_SECTION default_no_function_rodata_section -#undef TARGET_DEFAULT_TARGET_FLAGS -#define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT #undef TARGET_ENCODE_SECTION_INFO #define TARGET_ENCODE_SECTION_INFO mcore_encode_section_info #undef TARGET_STRIP_NAME_ENCODING @@ -205,7 +196,7 @@ #undef TARGET_RTX_COSTS #define TARGET_RTX_COSTS mcore_rtx_costs #undef TARGET_ADDRESS_COST -#define TARGET_ADDRESS_COST hook_int_rtx_bool_0 +#define TARGET_ADDRESS_COST hook_int_rtx_mode_as_bool_0 #undef TARGET_MACHINE_DEPENDENT_REORG #define TARGET_MACHINE_DEPENDENT_REORG mcore_reorg @@ -239,11 +230,26 @@ #undef TARGET_OPTION_OVERRIDE #define TARGET_OPTION_OVERRIDE mcore_option_override -#undef TARGET_OPTION_OPTIMIZATION_TABLE -#define TARGET_OPTION_OPTIMIZATION_TABLE mcore_option_optimization_table - -#undef TARGET_EXCEPT_UNWIND_INFO -#define TARGET_EXCEPT_UNWIND_INFO sjlj_except_unwind_info + +#undef TARGET_LEGITIMATE_CONSTANT_P +#define TARGET_LEGITIMATE_CONSTANT_P mcore_legitimate_constant_p +#undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P +#define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P mcore_legitimate_address_p + +#undef TARGET_LRA_P +#define TARGET_LRA_P hook_bool_void_false + +#undef TARGET_WARN_FUNC_RETURN +#define TARGET_WARN_FUNC_RETURN mcore_warn_func_return + +#undef TARGET_HARD_REGNO_MODE_OK +#define TARGET_HARD_REGNO_MODE_OK mcore_hard_regno_mode_ok + +#undef TARGET_MODES_TIEABLE_P +#define TARGET_MODES_TIEABLE_P mcore_modes_tieable_p + +#undef TARGET_CONSTANT_ALIGNMENT +#define TARGET_CONSTANT_ALIGNMENT constant_alignment_word_strings struct gcc_target targetm = TARGET_INITIALIZER; @@ -319,7 +325,7 @@ /* Print the operand address in x to the stream. */ static void -mcore_print_operand_address (FILE * stream, rtx x) +mcore_print_operand_address (FILE * stream, machine_mode /*mode*/, rtx x) { switch (GET_CODE (x)) { @@ -411,7 +417,7 @@ break; case MEM: mcore_print_operand_address - (stream, XEXP (adjust_address (x, SImode, 4), 0)); + (stream, GET_MODE (x), XEXP (adjust_address (x, SImode, 4), 0)); break; default: gcc_unreachable (); @@ -435,7 +441,7 @@ fputs (reg_names[REGNO (x)], (stream)); break; case MEM: - output_address (XEXP (x, 0)); + output_address (GET_MODE (x), XEXP (x, 0)); break; default: output_addr_const (stream, x); @@ -526,9 +532,12 @@ } static bool -mcore_rtx_costs (rtx x, int code, int outer_code, int * total, - bool speed ATTRIBUTE_UNUSED) +mcore_rtx_costs (rtx x, machine_mode mode ATTRIBUTE_UNUSED, int outer_code, + int opno ATTRIBUTE_UNUSED, + int * total, bool speed ATTRIBUTE_UNUSED) { + int code = GET_CODE (x); + switch (code) { case CONST_INT: @@ -614,7 +623,7 @@ case EQ: /* Use inverted condition, cmpne. */ code = NE; invert = true; - /* Drop through. */ + /* FALLTHRU */ case NE: /* Use normal condition, cmpne. */ if (GET_CODE (op1) == CONST_INT && ! CONST_OK_FOR_K (INTVAL (op1))) @@ -624,7 +633,7 @@ case LE: /* Use inverted condition, reversed cmplt. */ code = GT; invert = true; - /* Drop through. */ + /* FALLTHRU */ case GT: /* Use normal condition, reversed cmplt. */ if (GET_CODE (op1) == CONST_INT) @@ -634,7 +643,7 @@ case GE: /* Use inverted condition, cmplt. */ code = LT; invert = true; - /* Drop through. */ + /* FALLTHRU */ case LT: /* Use normal condition, cmplt. */ if (GET_CODE (op1) == CONST_INT && @@ -649,7 +658,7 @@ gcc_assert (GET_CODE (op1) != CONST_INT || INTVAL (op1) != 0); code = LEU; invert = true; - /* Drop through. */ + /* FALLTHRU */ case LEU: /* Use normal condition, reversed cmphs. */ if (GET_CODE (op1) == CONST_INT && INTVAL (op1) != 0) @@ -659,7 +668,7 @@ case LTU: /* Use inverted condition, cmphs. */ code = GEU; invert = true; - /* Drop through. */ + /* FALLTHRU */ case GEU: /* Use normal condition, cmphs. */ if (GET_CODE (op1) == CONST_INT && INTVAL (op1) != 0) @@ -670,9 +679,7 @@ break; } - emit_insn (gen_rtx_SET (VOIDmode, - cc_reg, - gen_rtx_fmt_ee (code, CCmode, op0, op1))); + emit_insn (gen_rtx_SET (cc_reg, gen_rtx_fmt_ee (code, CCmode, op0, op1))); return invert; } @@ -912,9 +919,9 @@ can ignore subregs by extracting the actual register. BRC */ int -mcore_is_dead (rtx first, rtx reg) +mcore_is_dead (rtx_insn *first, rtx reg) { - rtx insn; + rtx_insn *insn; /* For mcore, subregs can't live independently of their parent regs. */ if (GET_CODE (reg) == SUBREG) @@ -928,10 +935,10 @@ to assume that it is live. */ for (insn = NEXT_INSN (first); insn; insn = NEXT_INSN (insn)) { - if (GET_CODE (insn) == JUMP_INSN) + if (JUMP_P (insn)) return 0; /* We lose track, assume it is alive. */ - else if (GET_CODE(insn) == CALL_INSN) + else if (CALL_P (insn)) { /* Call's might use it for target or register parms. */ if (reg_referenced_p (reg, PATTERN (insn)) @@ -940,7 +947,7 @@ else if (dead_or_set_p (insn, reg)) return 1; } - else if (GET_CODE (insn) == INSN) + else if (NONJUMP_INSN_P (insn)) { if (reg_referenced_p (reg, PATTERN (insn))) return 0; @@ -1165,7 +1172,7 @@ /* Output an inline constant. */ static const char * -output_inline_const (enum machine_mode mode, rtx operands[]) +output_inline_const (machine_mode mode, rtx operands[]) { HOST_WIDE_INT x = 0, y = 0; int trick_no; @@ -1265,7 +1272,7 @@ const char * mcore_output_move (rtx insn ATTRIBUTE_UNUSED, rtx operands[], - enum machine_mode mode ATTRIBUTE_UNUSED) + machine_mode mode ATTRIBUTE_UNUSED) { rtx dst = operands[0]; rtx src = operands[1]; @@ -1286,11 +1293,11 @@ else switch (GET_MODE (src)) /* r-m */ { - case SImode: + case E_SImode: return "ldw\t%0,%1"; - case HImode: + case E_HImode: return "ld.h\t%0,%1"; - case QImode: + case E_QImode: return "ld.b\t%0,%1"; default: gcc_unreachable (); @@ -1317,11 +1324,11 @@ else if (GET_CODE (dst) == MEM) /* m-r */ switch (GET_MODE (dst)) { - case SImode: + case E_SImode: return "stw\t%1,%0"; - case HImode: + case E_HImode: return "st.h\t%1,%0"; - case QImode: + case E_QImode: return "st.b\t%1,%0"; default: gcc_unreachable (); @@ -1335,7 +1342,7 @@ to take care when we see overlapping source and dest registers. */ const char * -mcore_output_movedouble (rtx operands[], enum machine_mode mode ATTRIBUTE_UNUSED) +mcore_output_movedouble (rtx operands[], machine_mode mode ATTRIBUTE_UNUSED) { rtx dst = operands[0]; rtx src = operands[1]; @@ -1355,7 +1362,7 @@ } else if (GET_CODE (src) == MEM) { - rtx memexp = memexp = XEXP (src, 0); + rtx memexp = XEXP (src, 0); int dstreg = REGNO (dst); int basereg = -1; @@ -1462,14 +1469,16 @@ if ((INTVAL (operands[3]) & 1) == 0) { mask = ~(1 << posn); - emit_insn (gen_rtx_SET (SImode, operands[0], - gen_rtx_AND (SImode, operands[0], GEN_INT (mask)))); + emit_insn (gen_rtx_SET (operands[0], + gen_rtx_AND (SImode, operands[0], + GEN_INT (mask)))); } else { mask = 1 << posn; - emit_insn (gen_rtx_SET (SImode, operands[0], - gen_rtx_IOR (SImode, operands[0], GEN_INT (mask)))); + emit_insn (gen_rtx_SET (operands[0], + gen_rtx_IOR (SImode, operands[0], + GEN_INT (mask)))); } return 1; @@ -1498,8 +1507,8 @@ && INTVAL (operands[3]) == ((1 << width) - 1)) { mreg = force_reg (SImode, GEN_INT (INTVAL (operands[3]) << posn)); - emit_insn (gen_rtx_SET (SImode, operands[0], - gen_rtx_IOR (SImode, operands[0], mreg))); + emit_insn (gen_rtx_SET (operands[0], + gen_rtx_IOR (SImode, operands[0], mreg))); return 1; } @@ -1507,8 +1516,8 @@ mreg = force_reg (SImode, GEN_INT (~(((1 << width) - 1) << posn))); /* Clear the field, to overlay it later with the source. */ - emit_insn (gen_rtx_SET (SImode, operands[0], - gen_rtx_AND (SImode, operands[0], mreg))); + emit_insn (gen_rtx_SET (operands[0], + gen_rtx_AND (SImode, operands[0], mreg))); /* If the source is constant 0, we've nothing to add back. */ if (GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[3]) == 0) @@ -1527,17 +1536,16 @@ if (width + posn != (int) GET_MODE_SIZE (SImode)) { ereg = force_reg (SImode, GEN_INT ((1 << width) - 1)); - emit_insn (gen_rtx_SET (SImode, sreg, - gen_rtx_AND (SImode, sreg, ereg))); + emit_insn (gen_rtx_SET (sreg, gen_rtx_AND (SImode, sreg, ereg))); } /* Insert source value in dest. */ if (posn != 0) - emit_insn (gen_rtx_SET (SImode, sreg, - gen_rtx_ASHIFT (SImode, sreg, GEN_INT (posn)))); + emit_insn (gen_rtx_SET (sreg, gen_rtx_ASHIFT (SImode, sreg, + GEN_INT (posn)))); - emit_insn (gen_rtx_SET (SImode, operands[0], - gen_rtx_IOR (SImode, operands[0], sreg))); + emit_insn (gen_rtx_SET (operands[0], + gen_rtx_IOR (SImode, operands[0], sreg))); return 1; } @@ -1557,7 +1565,7 @@ known constants. DEST and SRC are registers. OFFSET is the known starting point for the output pattern. */ -static const enum machine_mode mode_from_align[] = +static const machine_mode mode_from_align[] = { VOIDmode, QImode, HImode, VOIDmode, SImode, }; @@ -1566,7 +1574,7 @@ block_move_sequence (rtx dst_mem, rtx src_mem, int size, int align) { rtx temp[2]; - enum machine_mode mode[2]; + machine_mode mode[2]; int amount[2]; bool active[2]; int phase = 0; @@ -1608,7 +1616,7 @@ temp[next] = gen_reg_rtx (mode[next]); x = adjust_address (src_mem, mode[next], offset_ld); - emit_insn (gen_rtx_SET (VOIDmode, temp[next], x)); + emit_insn (gen_rtx_SET (temp[next], x)); offset_ld += next_amount; size -= next_amount; @@ -1620,7 +1628,7 @@ active[phase] = false; x = adjust_address (dst_mem, mode[phase], offset_st); - emit_insn (gen_rtx_SET (VOIDmode, x, temp[phase])); + emit_insn (gen_rtx_SET (x, temp[phase])); offset_st += amount[phase]; } @@ -1929,11 +1937,13 @@ /* Keep track of some information about varargs for the prolog. */ static void -mcore_setup_incoming_varargs (CUMULATIVE_ARGS *args_so_far, - enum machine_mode mode, tree type, +mcore_setup_incoming_varargs (cumulative_args_t args_so_far_v, + machine_mode mode, tree type, int * ptr_pretend_size ATTRIBUTE_UNUSED, int second_time ATTRIBUTE_UNUSED) { + CUMULATIVE_ARGS *args_so_far = get_cumulative_args (args_so_far_v); + current_function_anonymous_args = 1; /* We need to know how many argument registers are used before @@ -1978,8 +1988,7 @@ gcc_assert (GET_CODE (x) == SYMBOL_REF); - if (mcore_current_function_name) - free (mcore_current_function_name); + free (mcore_current_function_name); mcore_current_function_name = xstrdup (XSTR (x, 0)); @@ -2019,7 +2028,8 @@ { emit_insn (gen_movsi (gen_rtx_MEM (SImode, - plus_constant (stack_pointer_rtx, offset)), + plus_constant (Pmode, stack_pointer_rtx, + offset)), gen_rtx_REG (SImode, rn))); } } @@ -2054,7 +2064,8 @@ { emit_insn (gen_movsi (gen_rtx_MEM (SImode, - plus_constant (stack_pointer_rtx, offs)), + plus_constant (Pmode, stack_pointer_rtx, + offs)), gen_rtx_REG (SImode, i))); offs += 4; } @@ -2149,7 +2160,8 @@ emit_insn (gen_movsi (gen_rtx_REG (SImode, i), gen_rtx_MEM (SImode, - plus_constant (stack_pointer_rtx, offs)))); + plus_constant (Pmode, stack_pointer_rtx, + offs)))); offs += 4; } } @@ -2264,7 +2276,7 @@ changed into a conditional. Only bother with SImode items. If we wanted to be a little more aggressive, we could also do other modes such as DImode with reg-reg move or load 0. */ - if (GET_CODE (insn) == INSN) + if (NONJUMP_INSN_P (insn)) { rtx pat = PATTERN (insn); rtx src, dst; @@ -2315,9 +2327,9 @@ */ } - else if (GET_CODE (insn) == JUMP_INSN && - GET_CODE (PATTERN (insn)) == SET && - GET_CODE (XEXP (PATTERN (insn), 1)) == LABEL_REF) + else if (JUMP_P (insn) + && GET_CODE (PATTERN (insn)) == SET + && GET_CODE (XEXP (PATTERN (insn), 1)) == LABEL_REF) return COND_BRANCH_INSN; return COND_NO; @@ -2326,8 +2338,8 @@ /* Emit a conditional version of insn and replace the old insn with the new one. Return the new insn if emitted. */ -static rtx -emit_new_cond_insn (rtx insn, int cond) +static rtx_insn * +emit_new_cond_insn (rtx_insn *insn, int cond) { rtx c_insn = 0; rtx pat, dst, src; @@ -2338,7 +2350,7 @@ pat = PATTERN (insn); - if (GET_CODE (insn) == INSN) + if (NONJUMP_INSN_P (insn)) { dst = SET_DEST (pat); src = SET_SRC (pat); @@ -2411,7 +2423,7 @@ delete_insn (insn); - return c_insn; + return as_a <rtx_insn *> (c_insn); } /* Attempt to change a basic block into a series of conditional insns. This @@ -2443,14 +2455,14 @@ we can delete the L2 label if NUSES==1 and re-apply the optimization starting at the last instruction of block 2. This may allow an entire if-then-else statement to be conditionalized. BRC */ -static rtx -conditionalize_block (rtx first) +static rtx_insn * +conditionalize_block (rtx_insn *first) { - rtx insn; + rtx_insn *insn; rtx br_pat; - rtx end_blk_1_br = 0; - rtx end_blk_2_insn = 0; - rtx start_blk_3_lab = 0; + rtx_insn *end_blk_1_br = 0; + rtx_insn *end_blk_2_insn = 0; + rtx_insn *start_blk_3_lab = 0; int cond; int br_lab_num; int blk_size = 0; @@ -2459,9 +2471,9 @@ /* Check that the first insn is a candidate conditional jump. This is the one that we'll eliminate. If not, advance to the next insn to try. */ - if (GET_CODE (first) != JUMP_INSN || - GET_CODE (PATTERN (first)) != SET || - GET_CODE (XEXP (PATTERN (first), 1)) != IF_THEN_ELSE) + if (! JUMP_P (first) + || GET_CODE (PATTERN (first)) != SET + || GET_CODE (XEXP (PATTERN (first), 1)) != IF_THEN_ELSE) return NEXT_INSN (first); /* Extract some information we need. */ @@ -2539,9 +2551,9 @@ for (insn = NEXT_INSN (end_blk_1_br); insn != start_blk_3_lab; insn = NEXT_INSN (insn)) { - rtx newinsn; - - if (INSN_DELETED_P (insn)) + rtx_insn *newinsn; + + if (insn->deleted ()) continue; /* Try to form a conditional variant of the instruction and emit it. */ @@ -2587,15 +2599,12 @@ static void conditionalize_optimization (void) { - rtx insn; + rtx_insn *insn; for (insn = get_insns (); insn; insn = conditionalize_block (insn)) continue; } -static int saved_warn_return_type = -1; -static int saved_warn_return_type_count = 0; - /* This is to handle loads from the constant pool. */ static void @@ -2604,21 +2613,6 @@ /* Reset this variable. */ current_function_anonymous_args = 0; - /* Restore the warn_return_type if it has been altered. */ - if (saved_warn_return_type != -1) - { - /* Only restore the value if we have reached another function. - The test of warn_return_type occurs in final_function () in - c-decl.c a long time after the code for the function is generated, - so we need a counter to tell us when we have finished parsing that - function and can restore the flag. */ - if (--saved_warn_return_type_count == 0) - { - warn_return_type = saved_warn_return_type; - saved_warn_return_type = -1; - } - } - if (optimize == 0) return; @@ -2654,7 +2648,7 @@ enum reg_class mcore_secondary_reload_class (enum reg_class rclass, - enum machine_mode mode ATTRIBUTE_UNUSED, rtx x) + machine_mode mode ATTRIBUTE_UNUSED, rtx x) { if (TEST_HARD_REG_BIT (reg_class_contents[rclass], 15) && !mcore_r15_operand_p (x)) @@ -2710,7 +2704,7 @@ hold a function argument of mode MODE and type TYPE. */ int -mcore_num_arg_regs (enum machine_mode mode, const_tree type) +mcore_num_arg_regs (machine_mode mode, const_tree type) { int size; @@ -2726,7 +2720,7 @@ } static rtx -handle_structs_in_regs (enum machine_mode mode, const_tree type, int reg) +handle_structs_in_regs (machine_mode mode, const_tree type, int reg) { int size; @@ -2772,7 +2766,7 @@ rtx mcore_function_value (const_tree valtype, const_tree func) { - enum machine_mode mode; + machine_mode mode; int unsigned_p; mode = TYPE_MODE (valtype); @@ -2802,7 +2796,7 @@ its data type forbids. */ static rtx -mcore_function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, +mcore_function_arg (cumulative_args_t cum, machine_mode mode, const_tree type, bool named) { int arg_reg; @@ -2813,7 +2807,7 @@ if (targetm.calls.must_pass_in_stack (mode, type)) return 0; - arg_reg = ROUND_REG (*cum, mode); + arg_reg = ROUND_REG (*get_cumulative_args (cum), mode); if (arg_reg < NPARM_REGS) return handle_structs_in_regs (mode, type, FIRST_PARM_REG + arg_reg); @@ -2822,15 +2816,17 @@ } static void -mcore_function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, +mcore_function_arg_advance (cumulative_args_t cum_v, machine_mode mode, const_tree type, bool named ATTRIBUTE_UNUSED) { + CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); + *cum = (ROUND_REG (*cum, mode) + (int)named * mcore_num_arg_regs (mode, type)); } static unsigned int -mcore_function_arg_boundary (enum machine_mode mode, +mcore_function_arg_boundary (machine_mode mode, const_tree type ATTRIBUTE_UNUSED) { /* Doubles must be aligned to an 8 byte boundary. */ @@ -2847,10 +2843,10 @@ the function. */ static int -mcore_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode, +mcore_arg_partial_bytes (cumulative_args_t cum, machine_mode mode, tree type, bool named) { - int reg = ROUND_REG (*cum, mode); + int reg = ROUND_REG (*get_cumulative_args (cum), mode); if (named == 0) return 0; @@ -3067,25 +3063,7 @@ mcore_handle_naked_attribute (tree * node, tree name, tree args ATTRIBUTE_UNUSED, int flags ATTRIBUTE_UNUSED, bool * no_add_attrs) { - if (TREE_CODE (*node) == FUNCTION_DECL) - { - /* PR14310 - don't complain about lack of return statement - in naked functions. The solution here is a gross hack - but this is the only way to solve the problem without - adding a new feature to GCC. I did try submitting a patch - that would add such a new feature, but it was (rightfully) - rejected on the grounds that it was creeping featurism, - so hence this code. */ - if (warn_return_type) - { - saved_warn_return_type = warn_return_type; - warn_return_type = 0; - saved_warn_return_type_count = 2; - } - else if (saved_warn_return_type_count) - saved_warn_return_type_count = 2; - } - else + if (TREE_CODE (*node) != FUNCTION_DECL) { warning (OPT_Wattributes, "%qE attribute only applies to functions", name); @@ -3128,7 +3106,7 @@ sprintf (string, "%s%s", prefix, name); - DECL_SECTION_NAME (decl) = build_string (len, string); + set_decl_section_name (decl, string); } int @@ -3137,6 +3115,14 @@ return lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE; } +static bool +mcore_warn_func_return (tree decl) +{ + /* Naked functions are implemented entirely in assembly, including the + return sequence, so suppress warnings about this. */ + return lookup_attribute ("naked", DECL_ATTRIBUTES (decl)) == NULL_TREE; +} + #ifdef OBJECT_FORMAT_ELF static void mcore_asm_named_section (const char *name, @@ -3204,3 +3190,103 @@ mem = adjust_address (m_tramp, SImode, 12); emit_move_insn (mem, fnaddr); } + +/* Implement TARGET_LEGITIMATE_CONSTANT_P + + On the MCore, allow anything but a double. */ + +static bool +mcore_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x) +{ + return GET_CODE (x) != CONST_DOUBLE; +} + +/* Helper function for `mcore_legitimate_address_p'. */ + +static bool +mcore_reg_ok_for_base_p (const_rtx reg, bool strict_p) +{ + if (strict_p) + return REGNO_OK_FOR_BASE_P (REGNO (reg)); + else + return (REGNO (reg) <= 16 || !HARD_REGISTER_P (reg)); +} + +static bool +mcore_base_register_rtx_p (const_rtx x, bool strict_p) +{ + return REG_P(x) && mcore_reg_ok_for_base_p (x, strict_p); +} + +/* A legitimate index for a QI is 0..15, for HI is 0..30, for SI is 0..60, + and for DI is 0..56 because we use two SI loads, etc. */ + +static bool +mcore_legitimate_index_p (machine_mode mode, const_rtx op) +{ + if (CONST_INT_P (op)) + { + if (GET_MODE_SIZE (mode) >= 4 + && (((unsigned HOST_WIDE_INT) INTVAL (op)) % 4) == 0 + && ((unsigned HOST_WIDE_INT) INTVAL (op)) + <= (unsigned HOST_WIDE_INT) 64 - GET_MODE_SIZE (mode)) + return true; + if (GET_MODE_SIZE (mode) == 2 + && (((unsigned HOST_WIDE_INT) INTVAL (op)) % 2) == 0 + && ((unsigned HOST_WIDE_INT) INTVAL (op)) <= 30) + return true; + if (GET_MODE_SIZE (mode) == 1 + && ((unsigned HOST_WIDE_INT) INTVAL (op)) <= 15) + return true; + } + return false; +} + + +/* Worker function for TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P. + + Allow REG + REG + disp */ + +static bool +mcore_legitimate_address_p (machine_mode mode, rtx x, bool strict_p, + addr_space_t as) +{ + gcc_assert (ADDR_SPACE_GENERIC_P (as)); + + if (mcore_base_register_rtx_p (x, strict_p)) + return true; + else if (GET_CODE (x) == PLUS || GET_CODE (x) == LO_SUM) + { + rtx xop0 = XEXP (x, 0); + rtx xop1 = XEXP (x, 1); + if (mcore_base_register_rtx_p (xop0, strict_p) + && mcore_legitimate_index_p (mode, xop1)) + return true; + if (mcore_base_register_rtx_p (xop1, strict_p) + && mcore_legitimate_index_p (mode, xop0)) + return true; + } + + return false; +} + +/* Implement TARGET_HARD_REGNO_MODE_OK. We may keep double values in + even registers. */ + +static bool +mcore_hard_regno_mode_ok (unsigned int regno, machine_mode mode) +{ + if (TARGET_8ALIGN && GET_MODE_SIZE (mode) > UNITS_PER_WORD) + return (regno & 1) == 0; + + return regno < 18; +} + +/* Implement TARGET_MODES_TIEABLE_P. */ + +static bool +mcore_modes_tieable_p (machine_mode mode1, machine_mode mode2) +{ + return mode1 == mode2 || GET_MODE_CLASS (mode1) == GET_MODE_CLASS (mode2); +}