diff options
Diffstat (limited to 'gcc/config/sh/sh.c')
-rw-r--r-- | gcc/config/sh/sh.c | 136 |
1 files changed, 133 insertions, 3 deletions
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 4207719dc44..0015f7029a4 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -48,6 +48,7 @@ Boston, MA 02111-1307, USA. */ #include "basic-block.h" #include "ra.h" #include "cfglayout.h" +#include "intl.h" int code_for_indirect_jump_scratch = CODE_FOR_indirect_jump_scratch; @@ -246,6 +247,7 @@ static rtx sh_builtin_saveregs (void); static void sh_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode, tree, int *, int); static bool sh_strict_argument_naming (CUMULATIVE_ARGS *); static bool sh_pretend_outgoing_varargs_named (CUMULATIVE_ARGS *); +static tree sh_build_builtin_va_list (void); /* Initialize the GCC target structure. */ @@ -345,6 +347,12 @@ static bool sh_pretend_outgoing_varargs_named (CUMULATIVE_ARGS *); #undef TARGET_PRETEND_OUTGOING_VARARGS_NAMED #define TARGET_PRETEND_OUTGOING_VARARGS_NAMED sh_pretend_outgoing_varargs_named +#undef TARGET_BUILD_BUILTIN_VA_LIST +#define TARGET_BUILD_BUILTIN_VA_LIST sh_build_builtin_va_list + +#undef TARGET_PCH_VALID_P +#define TARGET_PCH_VALID_P sh_pch_valid_p + struct gcc_target targetm = TARGET_INITIALIZER; /* Print the operand address in x to the stream. */ @@ -5911,8 +5919,8 @@ sh_builtin_saveregs (void) /* Define the `__builtin_va_list' type for the ABI. */ -tree -sh_build_va_list (void) +static tree +sh_build_builtin_va_list (void) { tree f_next_o, f_next_o_limit, f_next_fp, f_next_fp_limit, f_next_stack; tree record; @@ -5921,7 +5929,7 @@ sh_build_va_list (void) || TARGET_HITACHI || sh_cfun_attr_renesas_p ()) return ptr_type_node; - record = make_node (RECORD_TYPE); + record = (*lang_hooks.types.make_type) (RECORD_TYPE); f_next_o = build_decl (FIELD_DECL, get_identifier ("__va_next_o"), ptr_type_node); @@ -6833,6 +6841,90 @@ sh_cfun_interrupt_handler_p (void) DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE); } + +/* ??? target_switches in toplev.c is static, hence we have to duplicate it. */ +static const struct +{ + const char *const name; + const int value; + const char *const description; +} +sh_target_switches[] = TARGET_SWITCHES; +#define target_switches sh_target_switches + +/* Like default_pch_valid_p, but take flag_mask into account. */ +const char * +sh_pch_valid_p (const void *data_p, size_t len) +{ + const char *data = (const char *)data_p; + const char *flag_that_differs = NULL; + size_t i; + int old_flags; + int flag_mask + = (SH1_BIT | SH2_BIT | SH3_BIT | SH_E_BIT | HARD_SH4_BIT | FPU_SINGLE_BIT + | SH4_BIT | HITACHI_BIT | LITTLE_ENDIAN_BIT); + + /* -fpic and -fpie also usually make a PCH invalid. */ + if (data[0] != flag_pic) + return _("created and used with different settings of -fpic"); + if (data[1] != flag_pie) + return _("created and used with different settings of -fpie"); + data += 2; + + /* Check target_flags. */ + memcpy (&old_flags, data, sizeof (target_flags)); + if (((old_flags ^ target_flags) & flag_mask) != 0) + { + for (i = 0; i < ARRAY_SIZE (target_switches); i++) + { + int bits; + + bits = target_switches[i].value; + if (bits < 0) + bits = -bits; + bits &= flag_mask; + if ((target_flags & bits) != (old_flags & bits)) + { + flag_that_differs = target_switches[i].name; + goto make_message; + } + } + abort (); + } + data += sizeof (target_flags); + len -= sizeof (target_flags); + + /* Check string options. */ +#ifdef TARGET_OPTIONS + for (i = 0; i < ARRAY_SIZE (target_options); i++) + { + const char *str = *target_options[i].variable; + size_t l; + if (! str) + str = ""; + l = strlen (str) + 1; + if (len < l || memcmp (data, str, l) != 0) + { + flag_that_differs = target_options[i].prefix; + goto make_message; + } + data += l; + len -= l; + } +#endif + + return NULL; + + make_message: + { + char *r; + asprintf (&r, _("created and used with differing settings of `-m%s'"), + flag_that_differs); + if (r == NULL) + return _("out of memory"); + return r; + } +} /* Predicates used by the templates. */ @@ -8806,6 +8898,15 @@ sh_register_operand (rtx op, enum machine_mode mode) return register_operand (op, mode); } +int +cmpsi_operand (rtx op, enum machine_mode mode) +{ + if (GET_CODE (op) == REG && REGNO (op) == T_REG + && GET_MODE (op) == SImode) + return 1; + return arith_operand (op, mode); +} + static rtx emit_load_ptr (rtx, rtx); static rtx @@ -9037,4 +9138,33 @@ sh_get_pr_initial_val (void) return val; } +int +sh_expand_t_scc (enum rtx_code code, rtx target) +{ + rtx result = target; + HOST_WIDE_INT val; + + if (GET_CODE (sh_compare_op0) != REG || REGNO (sh_compare_op0) != T_REG + || GET_CODE (sh_compare_op1) != CONST_INT) + return 0; + if (GET_CODE (result) != REG) + result = gen_reg_rtx (SImode); + val = INTVAL (sh_compare_op1); + if ((code == EQ && val == 1) || (code == NE && val == 0)) + emit_insn (gen_movt (result)); + else if ((code == EQ && val == 0) || (code == NE && val == 1)) + { + emit_insn (gen_rtx_CLOBBER (VOIDmode, result)); + emit_insn (gen_subc (result, result, result)); + emit_insn (gen_addsi3 (result, result, GEN_INT (1))); + } + else if (code == EQ || code == NE) + emit_insn (gen_move_insn (result, GEN_INT (code == NE))); + else + return 0; + if (result != target) + emit_move_insn (target, result); + return 1; +} + #include "gt-sh.h" |