targhooks.c revision 169690
159243Sobrien/* Default target hook functions. 259243Sobrien Copyright (C) 2003, 2004, 2005, 2007 Free Software Foundation, Inc. 359243Sobrien 459243SobrienThis file is part of GCC. 559243Sobrien 659243SobrienGCC is free software; you can redistribute it and/or modify it under 759243Sobrienthe terms of the GNU General Public License as published by the Free 859243SobrienSoftware Foundation; either version 2, or (at your option) any later 959243Sobrienversion. 1059243Sobrien 1159243SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 12100616SmpWARRANTY; without even the implied warranty of MERCHANTABILITY or 1359243SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1459243Sobrienfor more details. 1559243Sobrien 1659243SobrienYou should have received a copy of the GNU General Public License 1759243Sobrienalong with GCC; see the file COPYING. If not, write to the Free 1859243SobrienSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 1959243Sobrien02110-1301, USA. */ 2059243Sobrien 2159243Sobrien/* The migration of target macros to target hooks works as follows: 2259243Sobrien 2359243Sobrien 1. Create a target hook that uses the existing target macros to 2459243Sobrien implement the same functionality. 2559243Sobrien 2659243Sobrien 2. Convert all the MI files to use the hook instead of the macro. 2759243Sobrien 2859415Sobrien 3. Repeat for a majority of the remaining target macros. This will 2959243Sobrien take some time. 3059243Sobrien 3159243Sobrien 4. Tell target maintainers to start migrating. 3259243Sobrien 3359243Sobrien 5. Eventually convert the backends to override the hook instead of 3459243Sobrien defining the macros. This will take some time too. 3559243Sobrien 3659243Sobrien 6. TBD when, poison the macros. Unmigrated targets will break at 3759415Sobrien this point. 3859243Sobrien 3959415Sobrien Note that we expect steps 1-3 to be done by the people that 4059243Sobrien understand what the MI does with each macro, and step 5 to be done 4159243Sobrien by the target maintainers for their respective targets. 4259243Sobrien 4359243Sobrien Note that steps 1 and 2 don't have to be done together, but no 4459243Sobrien target can override the new hook until step 2 is complete for it. 4559243Sobrien 4659243Sobrien Once the macros are poisoned, we will revert to the old migration 4759243Sobrien rules - migrate the macro, callers, and targets all at once. This 4859415Sobrien comment can thus be removed at that point. */ 4959243Sobrien 5059415Sobrien#include "config.h" 5159415Sobrien#include "system.h" 5259243Sobrien#include "coretypes.h" 5359243Sobrien#include "tm.h" 5459243Sobrien#include "machmode.h" 5559243Sobrien#include "rtl.h" 5659243Sobrien#include "tree.h" 5759243Sobrien#include "expr.h" 5859243Sobrien#include "output.h" 5959243Sobrien#include "toplev.h" 6059243Sobrien#include "function.h" 6159243Sobrien#include "target.h" 6259243Sobrien#include "tm_p.h" 6359243Sobrien#include "target-def.h" 6459243Sobrien#include "ggc.h" 6559243Sobrien#include "hard-reg-set.h" 6659243Sobrien#include "reload.h" 6759243Sobrien#include "optabs.h" 6859243Sobrien#include "recog.h" 6959243Sobrien 7059243Sobrien 7159415Sobrienvoid 7259243Sobriendefault_external_libcall (rtx fun ATTRIBUTE_UNUSED) 7359243Sobrien{ 7459243Sobrien#ifdef ASM_OUTPUT_EXTERNAL_LIBCALL 75231990Smp ASM_OUTPUT_EXTERNAL_LIBCALL(asm_out_file, fun); 7659243Sobrien#endif 7759243Sobrien} 7859243Sobrien 7959243Sobrienenum machine_mode 8059243Sobriendefault_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2) 8159243Sobrien{ 8259243Sobrien if (m1 == m2) 8359243Sobrien return m1; 8459243Sobrien return VOIDmode; 8559243Sobrien} 8659243Sobrien 8759243Sobrienbool 8859243Sobriendefault_return_in_memory (tree type, 8959243Sobrien tree fntype ATTRIBUTE_UNUSED) 9059243Sobrien{ 9159243Sobrien#ifndef RETURN_IN_MEMORY 9259243Sobrien return (TYPE_MODE (type) == BLKmode); 9359243Sobrien#else 9459415Sobrien return RETURN_IN_MEMORY (type); 9559243Sobrien#endif 9659243Sobrien} 9759243Sobrien 9859243Sobrienrtx 9959243Sobriendefault_expand_builtin_saveregs (void) 10059243Sobrien{ 10159243Sobrien error ("__builtin_saveregs not supported by this target"); 10259243Sobrien return const0_rtx; 10359243Sobrien} 10459243Sobrien 10559243Sobrienvoid 10659243Sobriendefault_setup_incoming_varargs (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED, 10759243Sobrien enum machine_mode mode ATTRIBUTE_UNUSED, 10859243Sobrien tree type ATTRIBUTE_UNUSED, 10959243Sobrien int *pretend_arg_size ATTRIBUTE_UNUSED, 11059243Sobrien int second_time ATTRIBUTE_UNUSED) 11159243Sobrien{ 11259243Sobrien} 11359243Sobrien 11459243Sobrien/* The default implementation of TARGET_BUILTIN_SETJMP_FRAME_VALUE. */ 11559243Sobrien 11659243Sobrienrtx 11759243Sobriendefault_builtin_setjmp_frame_value (void) 11859243Sobrien{ 11959243Sobrien return virtual_stack_vars_rtx; 12059243Sobrien} 12159243Sobrien 12259243Sobrien/* Generic hook that takes a CUMULATIVE_ARGS pointer and returns false. */ 12359243Sobrien 12459243Sobrienbool 12559243Sobrienhook_bool_CUMULATIVE_ARGS_false (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED) 12659243Sobrien{ 12759243Sobrien return false; 12859243Sobrien} 12959243Sobrien 13059243Sobrienbool 13159243Sobriendefault_pretend_outgoing_varargs_named (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED) 132167465Smp{ 133167465Smp return (targetm.calls.setup_incoming_varargs 13459243Sobrien != default_setup_incoming_varargs); 13559243Sobrien} 136167465Smp 13759243Sobrienenum machine_mode 13859243Sobriendefault_eh_return_filter_mode (void) 13959243Sobrien{ 14059243Sobrien return word_mode; 14159243Sobrien} 14259243Sobrien 14359243Sobrien/* The default implementation of TARGET_SHIFT_TRUNCATION_MASK. */ 14459415Sobrien 14559243Sobrienunsigned HOST_WIDE_INT 14659243Sobriendefault_shift_truncation_mask (enum machine_mode mode) 14759243Sobrien{ 14859243Sobrien return SHIFT_COUNT_TRUNCATED ? GET_MODE_BITSIZE (mode) - 1 : 0; 14959415Sobrien} 15059243Sobrien 15159243Sobrien/* The default implementation of TARGET_MIN_DIVISIONS_FOR_RECIP_MUL. */ 15259243Sobrien 15359243Sobrienunsigned int 15459243Sobriendefault_min_divisions_for_recip_mul (enum machine_mode mode ATTRIBUTE_UNUSED) 15559415Sobrien{ 15659243Sobrien return have_insn_for (DIV, mode) ? 3 : 2; 15759415Sobrien} 15859243Sobrien 15959243Sobrien/* The default implementation of TARGET_MODE_REP_EXTENDED. */ 16059243Sobrien 16159243Sobrienint 16259243Sobriendefault_mode_rep_extended (enum machine_mode mode ATTRIBUTE_UNUSED, 16359243Sobrien enum machine_mode mode_rep ATTRIBUTE_UNUSED) 16459243Sobrien{ 16559243Sobrien return UNKNOWN; 16659243Sobrien} 16759243Sobrien 16859243Sobrien/* Generic hook that takes a CUMULATIVE_ARGS pointer and returns true. */ 16959243Sobrien 17059243Sobrienbool 17159243Sobrienhook_bool_CUMULATIVE_ARGS_true (CUMULATIVE_ARGS * a ATTRIBUTE_UNUSED) 17259243Sobrien{ 17359243Sobrien return true; 17459243Sobrien} 17559243Sobrien 17659243Sobrien 17759243Sobrien/* The generic C++ ABI specifies this is a 64-bit value. */ 17859243Sobrientree 179145479Smpdefault_cxx_guard_type (void) 180145479Smp{ 181145479Smp return long_long_integer_type_node; 182145479Smp} 183145479Smp 184145479Smp 185145479Smp/* Returns the size of the cookie to use when allocating an array 18659243Sobrien whose elements have the indicated TYPE. Assumes that it is already 18759243Sobrien known that a cookie is needed. */ 18859243Sobrien 18959243Sobrientree 19059243Sobriendefault_cxx_get_cookie_size (tree type) 19159415Sobrien{ 19259243Sobrien tree cookie_size; 19359243Sobrien 19459415Sobrien /* We need to allocate an additional max (sizeof (size_t), alignof 19559243Sobrien (true_type)) bytes. */ 19659243Sobrien tree sizetype_size; 19759243Sobrien tree type_align; 19859243Sobrien 19959243Sobrien sizetype_size = size_in_bytes (sizetype); 20059243Sobrien type_align = size_int (TYPE_ALIGN_UNIT (type)); 20159243Sobrien if (INT_CST_LT_UNSIGNED (type_align, sizetype_size)) 20259243Sobrien cookie_size = sizetype_size; 20359243Sobrien else 20459243Sobrien cookie_size = type_align; 20559243Sobrien 20659243Sobrien return cookie_size; 20759243Sobrien} 20859243Sobrien 20959243Sobrien/* Return true if a parameter must be passed by reference. This version 21059243Sobrien of the TARGET_PASS_BY_REFERENCE hook uses just MUST_PASS_IN_STACK. */ 21159243Sobrien 21259243Sobrienbool 21359243Sobrienhook_pass_by_reference_must_pass_in_stack (CUMULATIVE_ARGS *c ATTRIBUTE_UNUSED, 21459243Sobrien enum machine_mode mode ATTRIBUTE_UNUSED, tree type ATTRIBUTE_UNUSED, 21583098Smp bool named_arg ATTRIBUTE_UNUSED) 21683098Smp{ 21783098Smp return targetm.calls.must_pass_in_stack (mode, type); 21859243Sobrien} 21959243Sobrien 22059243Sobrien/* Return true if a parameter follows callee copies conventions. This 22159243Sobrien version of the hook is true for all named arguments. */ 22259243Sobrien 22359243Sobrienbool 22459243Sobrienhook_callee_copies_named (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED, 22559243Sobrien enum machine_mode mode ATTRIBUTE_UNUSED, 22659243Sobrien tree type ATTRIBUTE_UNUSED, bool named) 22759243Sobrien{ 22859243Sobrien return named; 22959243Sobrien} 23059243Sobrien 23159243Sobrien/* Emit any directives required to unwind this instruction. */ 23259243Sobrien 23359243Sobrienvoid 23459243Sobriendefault_unwind_emit (FILE * stream ATTRIBUTE_UNUSED, 23559243Sobrien rtx insn ATTRIBUTE_UNUSED) 23659243Sobrien{ 23759243Sobrien /* Should never happen. */ 23859243Sobrien gcc_unreachable (); 23959243Sobrien} 24059415Sobrien 24159243Sobrien/* True if MODE is valid for the target. By "valid", we mean able to 24259243Sobrien be manipulated in non-trivial ways. In particular, this means all 24359243Sobrien the arithmetic is supported. 24459243Sobrien 24559243Sobrien By default we guess this means that any C type is supported. If 24659243Sobrien we can't map the mode back to a type that would be available in C, 24759243Sobrien then reject it. Special case, here, is the double-word arithmetic 24859415Sobrien supported by optabs.c. */ 24959243Sobrien 25059243Sobrienbool 25159243Sobriendefault_scalar_mode_supported_p (enum machine_mode mode) 25259243Sobrien{ 25359243Sobrien int precision = GET_MODE_PRECISION (mode); 25459243Sobrien 25559243Sobrien switch (GET_MODE_CLASS (mode)) 25659243Sobrien { 25759243Sobrien case MODE_PARTIAL_INT: 25859243Sobrien case MODE_INT: 25959243Sobrien if (precision == CHAR_TYPE_SIZE) 26059243Sobrien return true; 26159243Sobrien if (precision == SHORT_TYPE_SIZE) 26259243Sobrien return true; 26359243Sobrien if (precision == INT_TYPE_SIZE) 26459243Sobrien return true; 26559243Sobrien if (precision == LONG_TYPE_SIZE) 26659243Sobrien return true; 26759243Sobrien if (precision == LONG_LONG_TYPE_SIZE) 26859243Sobrien return true; 26959243Sobrien if (precision == 2 * BITS_PER_WORD) 27059243Sobrien return true; 27159243Sobrien return false; 27259243Sobrien 27359243Sobrien case MODE_FLOAT: 27459243Sobrien if (precision == FLOAT_TYPE_SIZE) 27559243Sobrien return true; 27659243Sobrien if (precision == DOUBLE_TYPE_SIZE) 27759243Sobrien return true; 27859243Sobrien if (precision == LONG_DOUBLE_TYPE_SIZE) 27959243Sobrien return true; 28059243Sobrien return false; 28159243Sobrien 28259243Sobrien case MODE_DECIMAL_FLOAT: 28359243Sobrien return false; 28459243Sobrien 28559243Sobrien default: 28659243Sobrien gcc_unreachable (); 28759243Sobrien } 28859243Sobrien} 28959415Sobrien 29059243Sobrien/* True if the target supports decimal floating point. */ 29159243Sobrien 29259243Sobrienbool 29359415Sobriendefault_decimal_float_supported_p (void) 29459243Sobrien{ 29559243Sobrien return ENABLE_DECIMAL_FLOAT; 29659243Sobrien} 29759243Sobrien 29859243Sobrien/* NULL if INSN insn is valid within a low-overhead loop, otherwise returns 29959243Sobrien an error message. 30059243Sobrien 30159243Sobrien This function checks whether a given INSN is valid within a low-overhead 30259243Sobrien loop. If INSN is invalid it returns the reason for that, otherwise it 30359243Sobrien returns NULL. A called function may clobber any special registers required 30459243Sobrien for low-overhead looping. Additionally, some targets (eg, PPC) use the count 30559243Sobrien register for branch on table instructions. We reject the doloop pattern in 30659243Sobrien these cases. */ 30759243Sobrien 30859243Sobrienconst char * 30959243Sobriendefault_invalid_within_doloop (rtx insn) 31059243Sobrien{ 31159243Sobrien if (CALL_P (insn)) 31259243Sobrien return "Function call in loop."; 31359415Sobrien 31459415Sobrien if (JUMP_P (insn) 31559415Sobrien && (GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC 31659243Sobrien || GET_CODE (PATTERN (insn)) == ADDR_VEC)) 31759243Sobrien return "Computed branch in the loop."; 31859243Sobrien 31959243Sobrien return NULL; 32059243Sobrien} 32159243Sobrien 32259243Sobrienbool 32359243Sobrienhook_bool_CUMULATIVE_ARGS_mode_tree_bool_false ( 32459243Sobrien CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED, 32559243Sobrien enum machine_mode mode ATTRIBUTE_UNUSED, 32659243Sobrien tree type ATTRIBUTE_UNUSED, bool named ATTRIBUTE_UNUSED) 32759243Sobrien{ 32859243Sobrien return false; 32959243Sobrien} 33059243Sobrien 33159415Sobrienbool 33259243Sobrienhook_bool_CUMULATIVE_ARGS_mode_tree_bool_true ( 33359243Sobrien CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED, 33459243Sobrien enum machine_mode mode ATTRIBUTE_UNUSED, 33559243Sobrien tree type ATTRIBUTE_UNUSED, bool named ATTRIBUTE_UNUSED) 33659243Sobrien{ 33759243Sobrien return true; 33859243Sobrien} 33959243Sobrien 34059243Sobrienint 34159243Sobrienhook_int_CUMULATIVE_ARGS_mode_tree_bool_0 ( 34259243Sobrien CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED, 34359243Sobrien enum machine_mode mode ATTRIBUTE_UNUSED, 34459243Sobrien tree type ATTRIBUTE_UNUSED, bool named ATTRIBUTE_UNUSED) 34559243Sobrien{ 34659243Sobrien return 0; 34759243Sobrien} 34859243Sobrien 34959243Sobrienvoid 35059243Sobrienhook_void_bitmap (bitmap regs ATTRIBUTE_UNUSED) 35159243Sobrien{ 35259243Sobrien} 35359243Sobrien 35459243Sobrienconst char * 35559243Sobrienhook_invalid_arg_for_unprototyped_fn ( 35659243Sobrien tree typelist ATTRIBUTE_UNUSED, 35759243Sobrien tree funcdecl ATTRIBUTE_UNUSED, 35859243Sobrien tree val ATTRIBUTE_UNUSED) 35959243Sobrien{ 36059243Sobrien return NULL; 36159415Sobrien} 36259243Sobrien 36359243Sobrien/* Initialize the stack protection decls. */ 36459243Sobrien 36559243Sobrien/* Stack protection related decls living in libgcc. */ 36659243Sobrienstatic GTY(()) tree stack_chk_guard_decl; 36759243Sobrien 36859243Sobrientree 36959243Sobriendefault_stack_protect_guard (void) 37059243Sobrien{ 37159243Sobrien tree t = stack_chk_guard_decl; 37259243Sobrien 37359243Sobrien if (t == NULL) 37459243Sobrien { 37559243Sobrien t = build_decl (VAR_DECL, get_identifier ("__stack_chk_guard"), 37659243Sobrien ptr_type_node); 37759243Sobrien TREE_STATIC (t) = 1; 37859243Sobrien TREE_PUBLIC (t) = 1; 37959415Sobrien DECL_EXTERNAL (t) = 1; 38059243Sobrien TREE_USED (t) = 1; 38159243Sobrien TREE_THIS_VOLATILE (t) = 1; 38259243Sobrien DECL_ARTIFICIAL (t) = 1; 38359243Sobrien DECL_IGNORED_P (t) = 1; 38459243Sobrien 38559243Sobrien stack_chk_guard_decl = t; 38659415Sobrien } 38759243Sobrien 38859243Sobrien return t; 38959243Sobrien} 39059243Sobrien 39159415Sobrienstatic GTY(()) tree stack_chk_fail_decl; 39259243Sobrien 39359243Sobrientree 39459243Sobriendefault_external_stack_protect_fail (void) 39559243Sobrien{ 39659243Sobrien tree t = stack_chk_fail_decl; 39759243Sobrien 39859243Sobrien if (t == NULL_TREE) 39959243Sobrien { 40059243Sobrien t = build_function_type_list (void_type_node, NULL_TREE); 40159415Sobrien t = build_decl (FUNCTION_DECL, get_identifier ("__stack_chk_fail"), t); 40259243Sobrien TREE_STATIC (t) = 1; 40359243Sobrien TREE_PUBLIC (t) = 1; 40459243Sobrien DECL_EXTERNAL (t) = 1; 40559243Sobrien TREE_USED (t) = 1; 40659243Sobrien TREE_THIS_VOLATILE (t) = 1; 40759243Sobrien TREE_NOTHROW (t) = 1; 40859243Sobrien DECL_ARTIFICIAL (t) = 1; 40959243Sobrien DECL_IGNORED_P (t) = 1; 41059243Sobrien DECL_VISIBILITY (t) = VISIBILITY_DEFAULT; 41159243Sobrien DECL_VISIBILITY_SPECIFIED (t) = 1; 41259243Sobrien 41359243Sobrien stack_chk_fail_decl = t; 41459243Sobrien } 41559243Sobrien 41659243Sobrien return build_function_call_expr (t, NULL_TREE); 41759243Sobrien} 41859243Sobrien 41959243Sobrientree 42059243Sobriendefault_hidden_stack_protect_fail (void) 42159243Sobrien{ 42259243Sobrien#ifndef HAVE_GAS_HIDDEN 42359243Sobrien return default_external_stack_protect_fail (); 42459243Sobrien#else 42559243Sobrien tree t = stack_chk_fail_decl; 42659243Sobrien 42759243Sobrien if (!flag_pic) 42859243Sobrien return default_external_stack_protect_fail (); 42959243Sobrien 43059415Sobrien if (t == NULL_TREE) 43159243Sobrien { 43259243Sobrien t = build_function_type_list (void_type_node, NULL_TREE); 43359243Sobrien t = build_decl (FUNCTION_DECL, 43459243Sobrien get_identifier ("__stack_chk_fail_local"), t); 43559243Sobrien TREE_STATIC (t) = 1; 43659243Sobrien TREE_PUBLIC (t) = 1; 43759243Sobrien DECL_EXTERNAL (t) = 1; 43859415Sobrien TREE_USED (t) = 1; 43959243Sobrien TREE_THIS_VOLATILE (t) = 1; 44059243Sobrien TREE_NOTHROW (t) = 1; 44159243Sobrien DECL_ARTIFICIAL (t) = 1; 44259243Sobrien DECL_IGNORED_P (t) = 1; 44359243Sobrien DECL_VISIBILITY_SPECIFIED (t) = 1; 44459415Sobrien DECL_VISIBILITY (t) = VISIBILITY_HIDDEN; 44559243Sobrien 44659243Sobrien stack_chk_fail_decl = t; 447231990Smp } 448231990Smp 449231990Smp return build_function_call_expr (t, NULL_TREE); 450231990Smp#endif 451231990Smp} 452231990Smp 453231990Smpbool 454231990Smphook_bool_rtx_commutative_p (rtx x, int outer_code ATTRIBUTE_UNUSED) 455231990Smp{ 456231990Smp return COMMUTATIVE_P (x); 457231990Smp} 45859243Sobrien 45959243Sobrienrtx 46059243Sobriendefault_function_value (tree ret_type ATTRIBUTE_UNUSED, 46159243Sobrien tree fn_decl_or_type, 46259243Sobrien bool outgoing ATTRIBUTE_UNUSED) 46359243Sobrien{ 46459243Sobrien /* The old interface doesn't handle receiving the function type. */ 46559243Sobrien if (fn_decl_or_type 46659243Sobrien && !DECL_P (fn_decl_or_type)) 46759243Sobrien fn_decl_or_type = NULL; 46859243Sobrien 46959243Sobrien#ifdef FUNCTION_OUTGOING_VALUE 47059243Sobrien if (outgoing) 47159243Sobrien return FUNCTION_OUTGOING_VALUE (ret_type, fn_decl_or_type); 47259243Sobrien#endif 47359243Sobrien 47459243Sobrien#ifdef FUNCTION_VALUE 47559243Sobrien return FUNCTION_VALUE (ret_type, fn_decl_or_type); 47659243Sobrien#else 47759243Sobrien return NULL_RTX; 47859243Sobrien#endif 47959243Sobrien} 48059243Sobrien 48159243Sobrienrtx 48259243Sobriendefault_internal_arg_pointer (void) 48359243Sobrien{ 48459243Sobrien /* If the reg that the virtual arg pointer will be translated into is 48559243Sobrien not a fixed reg or is the stack pointer, make a copy of the virtual 48659415Sobrien arg pointer, and address parms via the copy. The frame pointer is 48759243Sobrien considered fixed even though it is not marked as such. */ 48859243Sobrien if ((ARG_POINTER_REGNUM == STACK_POINTER_REGNUM 48959243Sobrien || ! (fixed_regs[ARG_POINTER_REGNUM] 49059243Sobrien || ARG_POINTER_REGNUM == FRAME_POINTER_REGNUM))) 49159243Sobrien return copy_to_reg (virtual_incoming_args_rtx); 49259243Sobrien else 49359243Sobrien return virtual_incoming_args_rtx; 49459243Sobrien} 49559243Sobrien 49659243Sobrienenum reg_class 49759243Sobriendefault_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x ATTRIBUTE_UNUSED, 49859243Sobrien enum reg_class reload_class ATTRIBUTE_UNUSED, 49959243Sobrien enum machine_mode reload_mode ATTRIBUTE_UNUSED, 50059243Sobrien secondary_reload_info *sri) 50159243Sobrien{ 50259243Sobrien enum reg_class class = NO_REGS; 50359243Sobrien 50459243Sobrien if (sri->prev_sri && sri->prev_sri->t_icode != CODE_FOR_nothing) 50559243Sobrien { 50659243Sobrien sri->icode = sri->prev_sri->t_icode; 50759243Sobrien return NO_REGS; 50859243Sobrien } 50959243Sobrien#ifdef SECONDARY_INPUT_RELOAD_CLASS 51059243Sobrien if (in_p) 51159243Sobrien class = SECONDARY_INPUT_RELOAD_CLASS (reload_class, reload_mode, x); 51259243Sobrien#endif 51359243Sobrien#ifdef SECONDARY_OUTPUT_RELOAD_CLASS 51459243Sobrien if (! in_p) 51559243Sobrien class = SECONDARY_OUTPUT_RELOAD_CLASS (reload_class, reload_mode, x); 51659243Sobrien#endif 51759243Sobrien if (class != NO_REGS) 51859243Sobrien { 51959243Sobrien enum insn_code icode = (in_p ? reload_in_optab[(int) reload_mode] 52059243Sobrien : reload_out_optab[(int) reload_mode]); 52159243Sobrien 52259243Sobrien if (icode != CODE_FOR_nothing 52359243Sobrien && insn_data[(int) icode].operand[in_p].predicate 52459243Sobrien && ! insn_data[(int) icode].operand[in_p].predicate (x, reload_mode)) 52559243Sobrien icode = CODE_FOR_nothing; 52659243Sobrien else if (icode != CODE_FOR_nothing) 52759415Sobrien { 52859243Sobrien const char *insn_constraint, *scratch_constraint; 52959243Sobrien char insn_letter, scratch_letter; 53059415Sobrien enum reg_class insn_class, scratch_class; 53159243Sobrien 53259243Sobrien gcc_assert (insn_data[(int) icode].n_operands == 3); 53359243Sobrien insn_constraint = insn_data[(int) icode].operand[!in_p].constraint; 53459243Sobrien if (!*insn_constraint) 53559243Sobrien insn_class = ALL_REGS; 53659243Sobrien else 53759243Sobrien { 53859243Sobrien if (in_p) 53959415Sobrien { 54059243Sobrien gcc_assert (*insn_constraint == '='); 54159243Sobrien insn_constraint++; 54259243Sobrien } 54359243Sobrien insn_letter = *insn_constraint; 54459243Sobrien insn_class 54559243Sobrien = (insn_letter == 'r' ? GENERAL_REGS 54659243Sobrien : REG_CLASS_FROM_CONSTRAINT ((unsigned char) insn_letter, 54759243Sobrien insn_constraint)); 54859243Sobrien gcc_assert (insn_class != NO_REGS); 54959415Sobrien } 55059243Sobrien 55159415Sobrien scratch_constraint = insn_data[(int) icode].operand[2].constraint; 55259243Sobrien /* The scratch register's constraint must start with "=&", 55359243Sobrien except for an input reload, where only "=" is necessary, 55459243Sobrien and where it might be beneficial to re-use registers from 55559243Sobrien the input. */ 55659243Sobrien gcc_assert (scratch_constraint[0] == '=' 55759243Sobrien && (in_p || scratch_constraint[1] == '&')); 55859243Sobrien scratch_constraint++; 55959243Sobrien if (*scratch_constraint == '&') 56059243Sobrien scratch_constraint++; 56159243Sobrien scratch_letter = *scratch_constraint; 56259243Sobrien scratch_class 56359415Sobrien = (scratch_letter == 'r' ? GENERAL_REGS 56459243Sobrien : REG_CLASS_FROM_CONSTRAINT ((unsigned char) scratch_letter, 56559243Sobrien scratch_constraint)); 56659243Sobrien 56759243Sobrien if (reg_class_subset_p (reload_class, insn_class)) 56859243Sobrien { 56959243Sobrien gcc_assert (scratch_class == class); 57059243Sobrien class = NO_REGS; 57159243Sobrien } 57259243Sobrien else 57359243Sobrien class = insn_class; 57459243Sobrien 57559243Sobrien } 57659243Sobrien if (class == NO_REGS) 57759243Sobrien sri->icode = icode; 57859243Sobrien else 57959243Sobrien sri->t_icode = icode; 58059243Sobrien } 58159243Sobrien return class; 58259243Sobrien} 58359243Sobrien 58459243Sobrien 58559243Sobrien/* If STRICT_ALIGNMENT is true we use the container type for accessing 58659243Sobrien volatile bitfields. This is generally the preferred behavior for memory 58759243Sobrien mapped peripherals on RISC architectures. 58859243Sobrien If STRICT_ALIGNMENT is false we use the narrowest type possible. This 58959243Sobrien is typically used to avoid spurious page faults and extra memory accesses 59059243Sobrien due to unaligned accesses on CISC architectures. */ 59159243Sobrien 59259243Sobrienbool 59359243Sobriendefault_narrow_bitfield (void) 59459243Sobrien{ 59559243Sobrien return !STRICT_ALIGNMENT; 59659243Sobrien} 59759243Sobrien 59859243Sobrien/* By default, if flag_pic is true, then neither local nor global relocs 59959415Sobrien should be placed in readonly memory. */ 60059243Sobrien 60159243Sobrienint 60259243Sobriendefault_reloc_rw_mask (void) 60359243Sobrien{ 60459243Sobrien return flag_pic ? 3 : 0; 60559243Sobrien} 60659243Sobrien 60759243Sobrien#include "gt-targhooks.h" 60859243Sobrien