1169689Skan/* Subroutines used for MIPS code generation. 2169689Skan Copyright (C) 1989, 1990, 1991, 1993, 1994, 1995, 1996, 1997, 1998, 3169689Skan 1999, 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc. 4169689Skan Contributed by A. Lichnewsky, lich@inria.inria.fr. 5169689Skan Changes by Michael Meissner, meissner@osf.org. 6169689Skan 64 bit r4000 support by Ian Lance Taylor, ian@cygnus.com, and 7169689Skan Brendan Eich, brendan@microunity.com. 8169689Skan 9169689SkanThis file is part of GCC. 10169689Skan 11169689SkanGCC is free software; you can redistribute it and/or modify 12169689Skanit under the terms of the GNU General Public License as published by 13169689Skanthe Free Software Foundation; either version 2, or (at your option) 14169689Skanany later version. 15169689Skan 16169689SkanGCC is distributed in the hope that it will be useful, 17169689Skanbut WITHOUT ANY WARRANTY; without even the implied warranty of 18169689SkanMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19169689SkanGNU General Public License for more details. 20169689Skan 21169689SkanYou should have received a copy of the GNU General Public License 22169689Skanalong with GCC; see the file COPYING. If not, write to 23169689Skanthe Free Software Foundation, 51 Franklin Street, Fifth Floor, 24169689SkanBoston, MA 02110-1301, USA. */ 25169689Skan 26169689Skan#include "config.h" 27169689Skan#include "system.h" 28169689Skan#include "coretypes.h" 29169689Skan#include "tm.h" 30169689Skan#include <signal.h> 31169689Skan#include "rtl.h" 32169689Skan#include "regs.h" 33169689Skan#include "hard-reg-set.h" 34169689Skan#include "real.h" 35169689Skan#include "insn-config.h" 36169689Skan#include "conditions.h" 37169689Skan#include "insn-attr.h" 38169689Skan#include "recog.h" 39169689Skan#include "toplev.h" 40169689Skan#include "output.h" 41169689Skan#include "tree.h" 42169689Skan#include "function.h" 43169689Skan#include "expr.h" 44169689Skan#include "optabs.h" 45169689Skan#include "flags.h" 46169689Skan#include "reload.h" 47169689Skan#include "tm_p.h" 48169689Skan#include "ggc.h" 49169689Skan#include "gstab.h" 50169689Skan#include "hashtab.h" 51169689Skan#include "debug.h" 52169689Skan#include "target.h" 53169689Skan#include "target-def.h" 54169689Skan#include "integrate.h" 55169689Skan#include "langhooks.h" 56169689Skan#include "cfglayout.h" 57169689Skan#include "sched-int.h" 58169689Skan#include "tree-gimple.h" 59169689Skan#include "bitmap.h" 60169689Skan 61169689Skan/* True if X is an unspec wrapper around a SYMBOL_REF or LABEL_REF. */ 62169689Skan#define UNSPEC_ADDRESS_P(X) \ 63169689Skan (GET_CODE (X) == UNSPEC \ 64169689Skan && XINT (X, 1) >= UNSPEC_ADDRESS_FIRST \ 65169689Skan && XINT (X, 1) < UNSPEC_ADDRESS_FIRST + NUM_SYMBOL_TYPES) 66169689Skan 67169689Skan/* Extract the symbol or label from UNSPEC wrapper X. */ 68169689Skan#define UNSPEC_ADDRESS(X) \ 69169689Skan XVECEXP (X, 0, 0) 70169689Skan 71169689Skan/* Extract the symbol type from UNSPEC wrapper X. */ 72169689Skan#define UNSPEC_ADDRESS_TYPE(X) \ 73169689Skan ((enum mips_symbol_type) (XINT (X, 1) - UNSPEC_ADDRESS_FIRST)) 74169689Skan 75169689Skan/* The maximum distance between the top of the stack frame and the 76169689Skan value $sp has when we save & restore registers. 77169689Skan 78169689Skan Use a maximum gap of 0x100 in the mips16 case. We can then use 79169689Skan unextended instructions to save and restore registers, and to 80169689Skan allocate and deallocate the top part of the frame. 81169689Skan 82169689Skan The value in the !mips16 case must be a SMALL_OPERAND and must 83169689Skan preserve the maximum stack alignment. */ 84169689Skan#define MIPS_MAX_FIRST_STACK_STEP (TARGET_MIPS16 ? 0x100 : 0x7ff0) 85169689Skan 86169689Skan/* True if INSN is a mips.md pattern or asm statement. */ 87169689Skan#define USEFUL_INSN_P(INSN) \ 88169689Skan (INSN_P (INSN) \ 89169689Skan && GET_CODE (PATTERN (INSN)) != USE \ 90169689Skan && GET_CODE (PATTERN (INSN)) != CLOBBER \ 91169689Skan && GET_CODE (PATTERN (INSN)) != ADDR_VEC \ 92169689Skan && GET_CODE (PATTERN (INSN)) != ADDR_DIFF_VEC) 93169689Skan 94169689Skan/* If INSN is a delayed branch sequence, return the first instruction 95169689Skan in the sequence, otherwise return INSN itself. */ 96169689Skan#define SEQ_BEGIN(INSN) \ 97169689Skan (INSN_P (INSN) && GET_CODE (PATTERN (INSN)) == SEQUENCE \ 98169689Skan ? XVECEXP (PATTERN (INSN), 0, 0) \ 99169689Skan : (INSN)) 100169689Skan 101169689Skan/* Likewise for the last instruction in a delayed branch sequence. */ 102169689Skan#define SEQ_END(INSN) \ 103169689Skan (INSN_P (INSN) && GET_CODE (PATTERN (INSN)) == SEQUENCE \ 104169689Skan ? XVECEXP (PATTERN (INSN), 0, XVECLEN (PATTERN (INSN), 0) - 1) \ 105169689Skan : (INSN)) 106169689Skan 107169689Skan/* Execute the following loop body with SUBINSN set to each instruction 108169689Skan between SEQ_BEGIN (INSN) and SEQ_END (INSN) inclusive. */ 109169689Skan#define FOR_EACH_SUBINSN(SUBINSN, INSN) \ 110169689Skan for ((SUBINSN) = SEQ_BEGIN (INSN); \ 111169689Skan (SUBINSN) != NEXT_INSN (SEQ_END (INSN)); \ 112169689Skan (SUBINSN) = NEXT_INSN (SUBINSN)) 113169689Skan 114169689Skan/* Classifies an address. 115169689Skan 116169689Skan ADDRESS_REG 117169689Skan A natural register + offset address. The register satisfies 118169689Skan mips_valid_base_register_p and the offset is a const_arith_operand. 119169689Skan 120169689Skan ADDRESS_LO_SUM 121169689Skan A LO_SUM rtx. The first operand is a valid base register and 122169689Skan the second operand is a symbolic address. 123169689Skan 124169689Skan ADDRESS_CONST_INT 125169689Skan A signed 16-bit constant address. 126169689Skan 127169689Skan ADDRESS_SYMBOLIC: 128169689Skan A constant symbolic address (equivalent to CONSTANT_SYMBOLIC). */ 129169689Skanenum mips_address_type { 130169689Skan ADDRESS_REG, 131169689Skan ADDRESS_LO_SUM, 132169689Skan ADDRESS_CONST_INT, 133169689Skan ADDRESS_SYMBOLIC 134169689Skan}; 135169689Skan 136169689Skan/* Classifies the prototype of a builtin function. */ 137169689Skanenum mips_function_type 138169689Skan{ 139169689Skan MIPS_V2SF_FTYPE_V2SF, 140169689Skan MIPS_V2SF_FTYPE_V2SF_V2SF, 141169689Skan MIPS_V2SF_FTYPE_V2SF_V2SF_INT, 142169689Skan MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF, 143169689Skan MIPS_V2SF_FTYPE_SF_SF, 144169689Skan MIPS_INT_FTYPE_V2SF_V2SF, 145169689Skan MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF, 146169689Skan MIPS_INT_FTYPE_SF_SF, 147169689Skan MIPS_INT_FTYPE_DF_DF, 148169689Skan MIPS_SF_FTYPE_V2SF, 149169689Skan MIPS_SF_FTYPE_SF, 150169689Skan MIPS_SF_FTYPE_SF_SF, 151169689Skan MIPS_DF_FTYPE_DF, 152169689Skan MIPS_DF_FTYPE_DF_DF, 153169689Skan 154169689Skan /* For MIPS DSP ASE */ 155169689Skan MIPS_DI_FTYPE_DI_SI, 156169689Skan MIPS_DI_FTYPE_DI_SI_SI, 157169689Skan MIPS_DI_FTYPE_DI_V2HI_V2HI, 158169689Skan MIPS_DI_FTYPE_DI_V4QI_V4QI, 159169689Skan MIPS_SI_FTYPE_DI_SI, 160169689Skan MIPS_SI_FTYPE_PTR_SI, 161169689Skan MIPS_SI_FTYPE_SI, 162169689Skan MIPS_SI_FTYPE_SI_SI, 163169689Skan MIPS_SI_FTYPE_V2HI, 164169689Skan MIPS_SI_FTYPE_V2HI_V2HI, 165169689Skan MIPS_SI_FTYPE_V4QI, 166169689Skan MIPS_SI_FTYPE_V4QI_V4QI, 167169689Skan MIPS_SI_FTYPE_VOID, 168169689Skan MIPS_V2HI_FTYPE_SI, 169169689Skan MIPS_V2HI_FTYPE_SI_SI, 170169689Skan MIPS_V2HI_FTYPE_V2HI, 171169689Skan MIPS_V2HI_FTYPE_V2HI_SI, 172169689Skan MIPS_V2HI_FTYPE_V2HI_V2HI, 173169689Skan MIPS_V2HI_FTYPE_V4QI, 174169689Skan MIPS_V2HI_FTYPE_V4QI_V2HI, 175169689Skan MIPS_V4QI_FTYPE_SI, 176169689Skan MIPS_V4QI_FTYPE_V2HI_V2HI, 177169689Skan MIPS_V4QI_FTYPE_V4QI_SI, 178169689Skan MIPS_V4QI_FTYPE_V4QI_V4QI, 179169689Skan MIPS_VOID_FTYPE_SI_SI, 180169689Skan MIPS_VOID_FTYPE_V2HI_V2HI, 181169689Skan MIPS_VOID_FTYPE_V4QI_V4QI, 182169689Skan 183169689Skan /* The last type. */ 184169689Skan MIPS_MAX_FTYPE_MAX 185169689Skan}; 186169689Skan 187169689Skan/* Specifies how a builtin function should be converted into rtl. */ 188169689Skanenum mips_builtin_type 189169689Skan{ 190169689Skan /* The builtin corresponds directly to an .md pattern. The return 191169689Skan value is mapped to operand 0 and the arguments are mapped to 192169689Skan operands 1 and above. */ 193169689Skan MIPS_BUILTIN_DIRECT, 194169689Skan 195169689Skan /* The builtin corresponds directly to an .md pattern. There is no return 196169689Skan value and the arguments are mapped to operands 0 and above. */ 197169689Skan MIPS_BUILTIN_DIRECT_NO_TARGET, 198169689Skan 199169689Skan /* The builtin corresponds to a comparison instruction followed by 200169689Skan a mips_cond_move_tf_ps pattern. The first two arguments are the 201169689Skan values to compare and the second two arguments are the vector 202169689Skan operands for the movt.ps or movf.ps instruction (in assembly order). */ 203169689Skan MIPS_BUILTIN_MOVF, 204169689Skan MIPS_BUILTIN_MOVT, 205169689Skan 206169689Skan /* The builtin corresponds to a V2SF comparison instruction. Operand 0 207169689Skan of this instruction is the result of the comparison, which has mode 208169689Skan CCV2 or CCV4. The function arguments are mapped to operands 1 and 209169689Skan above. The function's return value is an SImode boolean that is 210169689Skan true under the following conditions: 211169689Skan 212169689Skan MIPS_BUILTIN_CMP_ANY: one of the registers is true 213169689Skan MIPS_BUILTIN_CMP_ALL: all of the registers are true 214169689Skan MIPS_BUILTIN_CMP_LOWER: the first register is true 215169689Skan MIPS_BUILTIN_CMP_UPPER: the second register is true. */ 216169689Skan MIPS_BUILTIN_CMP_ANY, 217169689Skan MIPS_BUILTIN_CMP_ALL, 218169689Skan MIPS_BUILTIN_CMP_UPPER, 219169689Skan MIPS_BUILTIN_CMP_LOWER, 220169689Skan 221169689Skan /* As above, but the instruction only sets a single $fcc register. */ 222169689Skan MIPS_BUILTIN_CMP_SINGLE, 223169689Skan 224169689Skan /* For generating bposge32 branch instructions in MIPS32 DSP ASE. */ 225169689Skan MIPS_BUILTIN_BPOSGE32 226169689Skan}; 227169689Skan 228169689Skan/* Invokes MACRO (COND) for each c.cond.fmt condition. */ 229169689Skan#define MIPS_FP_CONDITIONS(MACRO) \ 230169689Skan MACRO (f), \ 231169689Skan MACRO (un), \ 232169689Skan MACRO (eq), \ 233169689Skan MACRO (ueq), \ 234169689Skan MACRO (olt), \ 235169689Skan MACRO (ult), \ 236169689Skan MACRO (ole), \ 237169689Skan MACRO (ule), \ 238169689Skan MACRO (sf), \ 239169689Skan MACRO (ngle), \ 240169689Skan MACRO (seq), \ 241169689Skan MACRO (ngl), \ 242169689Skan MACRO (lt), \ 243169689Skan MACRO (nge), \ 244169689Skan MACRO (le), \ 245169689Skan MACRO (ngt) 246169689Skan 247169689Skan/* Enumerates the codes above as MIPS_FP_COND_<X>. */ 248169689Skan#define DECLARE_MIPS_COND(X) MIPS_FP_COND_ ## X 249169689Skanenum mips_fp_condition { 250169689Skan MIPS_FP_CONDITIONS (DECLARE_MIPS_COND) 251169689Skan}; 252169689Skan 253169689Skan/* Index X provides the string representation of MIPS_FP_COND_<X>. */ 254169689Skan#define STRINGIFY(X) #X 255169689Skanstatic const char *const mips_fp_conditions[] = { 256169689Skan MIPS_FP_CONDITIONS (STRINGIFY) 257169689Skan}; 258169689Skan 259169689Skan/* A function to save or store a register. The first argument is the 260169689Skan register and the second is the stack slot. */ 261169689Skantypedef void (*mips_save_restore_fn) (rtx, rtx); 262169689Skan 263169689Skanstruct mips16_constant; 264169689Skanstruct mips_arg_info; 265169689Skanstruct mips_address_info; 266169689Skanstruct mips_integer_op; 267169689Skanstruct mips_sim; 268169689Skan 269169689Skanstatic enum mips_symbol_type mips_classify_symbol (rtx); 270169689Skanstatic void mips_split_const (rtx, rtx *, HOST_WIDE_INT *); 271169689Skanstatic bool mips_offset_within_object_p (rtx, HOST_WIDE_INT); 272169689Skanstatic bool mips_valid_base_register_p (rtx, enum machine_mode, int); 273169689Skanstatic bool mips_symbolic_address_p (enum mips_symbol_type, enum machine_mode); 274169689Skanstatic bool mips_classify_address (struct mips_address_info *, rtx, 275169689Skan enum machine_mode, int); 276169689Skanstatic bool mips_cannot_force_const_mem (rtx); 277169689Skanstatic bool mips_use_blocks_for_constant_p (enum machine_mode, rtx); 278169689Skanstatic int mips_symbol_insns (enum mips_symbol_type); 279169689Skanstatic bool mips16_unextended_reference_p (enum machine_mode mode, rtx, rtx); 280169689Skanstatic rtx mips_force_temporary (rtx, rtx); 281169689Skanstatic rtx mips_unspec_offset_high (rtx, rtx, rtx, enum mips_symbol_type); 282169689Skanstatic rtx mips_add_offset (rtx, rtx, HOST_WIDE_INT); 283169689Skanstatic unsigned int mips_build_shift (struct mips_integer_op *, HOST_WIDE_INT); 284169689Skanstatic unsigned int mips_build_lower (struct mips_integer_op *, 285169689Skan unsigned HOST_WIDE_INT); 286169689Skanstatic unsigned int mips_build_integer (struct mips_integer_op *, 287169689Skan unsigned HOST_WIDE_INT); 288169689Skanstatic void mips_legitimize_const_move (enum machine_mode, rtx, rtx); 289169689Skanstatic int m16_check_op (rtx, int, int, int); 290169689Skanstatic bool mips_rtx_costs (rtx, int, int, int *); 291169689Skanstatic int mips_address_cost (rtx); 292169689Skanstatic void mips_emit_compare (enum rtx_code *, rtx *, rtx *, bool); 293169689Skanstatic void mips_load_call_address (rtx, rtx, int); 294169689Skanstatic bool mips_function_ok_for_sibcall (tree, tree); 295169689Skanstatic void mips_block_move_straight (rtx, rtx, HOST_WIDE_INT); 296169689Skanstatic void mips_adjust_block_mem (rtx, HOST_WIDE_INT, rtx *, rtx *); 297169689Skanstatic void mips_block_move_loop (rtx, rtx, HOST_WIDE_INT); 298169689Skanstatic void mips_arg_info (const CUMULATIVE_ARGS *, enum machine_mode, 299169689Skan tree, int, struct mips_arg_info *); 300169689Skanstatic bool mips_get_unaligned_mem (rtx *, unsigned int, int, rtx *, rtx *); 301169689Skanstatic void mips_set_architecture (const struct mips_cpu_info *); 302169689Skanstatic void mips_set_tune (const struct mips_cpu_info *); 303169689Skanstatic bool mips_handle_option (size_t, const char *, int); 304169689Skanstatic struct machine_function *mips_init_machine_status (void); 305169689Skanstatic void print_operand_reloc (FILE *, rtx, const char **); 306169689Skan#if TARGET_IRIX 307169689Skanstatic void irix_output_external_libcall (rtx); 308169689Skan#endif 309169689Skanstatic void mips_file_start (void); 310169689Skanstatic void mips_file_end (void); 311169689Skanstatic bool mips_rewrite_small_data_p (rtx); 312169689Skanstatic int mips_small_data_pattern_1 (rtx *, void *); 313169689Skanstatic int mips_rewrite_small_data_1 (rtx *, void *); 314169689Skanstatic bool mips_function_has_gp_insn (void); 315169689Skanstatic unsigned int mips_global_pointer (void); 316169689Skanstatic bool mips_save_reg_p (unsigned int); 317169689Skanstatic void mips_save_restore_reg (enum machine_mode, int, HOST_WIDE_INT, 318169689Skan mips_save_restore_fn); 319169689Skanstatic void mips_for_each_saved_reg (HOST_WIDE_INT, mips_save_restore_fn); 320169689Skanstatic void mips_output_cplocal (void); 321169689Skanstatic void mips_emit_loadgp (void); 322169689Skanstatic void mips_output_function_prologue (FILE *, HOST_WIDE_INT); 323169689Skanstatic void mips_set_frame_expr (rtx); 324169689Skanstatic rtx mips_frame_set (rtx, rtx); 325169689Skanstatic void mips_save_reg (rtx, rtx); 326169689Skanstatic void mips_output_function_epilogue (FILE *, HOST_WIDE_INT); 327169689Skanstatic void mips_restore_reg (rtx, rtx); 328169689Skanstatic void mips_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, 329169689Skan HOST_WIDE_INT, tree); 330169689Skanstatic int symbolic_expression_p (rtx); 331169689Skanstatic section *mips_select_rtx_section (enum machine_mode, rtx, 332169689Skan unsigned HOST_WIDE_INT); 333169689Skanstatic section *mips_function_rodata_section (tree); 334169689Skanstatic bool mips_in_small_data_p (tree); 335169689Skanstatic bool mips_use_anchors_for_symbol_p (rtx); 336169689Skanstatic int mips_fpr_return_fields (tree, tree *); 337169689Skanstatic bool mips_return_in_msb (tree); 338169689Skanstatic rtx mips_return_fpr_pair (enum machine_mode mode, 339169689Skan enum machine_mode mode1, HOST_WIDE_INT, 340169689Skan enum machine_mode mode2, HOST_WIDE_INT); 341169689Skanstatic rtx mips16_gp_pseudo_reg (void); 342169689Skanstatic void mips16_fp_args (FILE *, int, int); 343169689Skanstatic void build_mips16_function_stub (FILE *); 344169689Skanstatic rtx dump_constants_1 (enum machine_mode, rtx, rtx); 345169689Skanstatic void dump_constants (struct mips16_constant *, rtx); 346169689Skanstatic int mips16_insn_length (rtx); 347169689Skanstatic int mips16_rewrite_pool_refs (rtx *, void *); 348169689Skanstatic void mips16_lay_out_constants (void); 349169689Skanstatic void mips_sim_reset (struct mips_sim *); 350169689Skanstatic void mips_sim_init (struct mips_sim *, state_t); 351169689Skanstatic void mips_sim_next_cycle (struct mips_sim *); 352169689Skanstatic void mips_sim_wait_reg (struct mips_sim *, rtx, rtx); 353169689Skanstatic int mips_sim_wait_regs_2 (rtx *, void *); 354169689Skanstatic void mips_sim_wait_regs_1 (rtx *, void *); 355169689Skanstatic void mips_sim_wait_regs (struct mips_sim *, rtx); 356169689Skanstatic void mips_sim_wait_units (struct mips_sim *, rtx); 357169689Skanstatic void mips_sim_wait_insn (struct mips_sim *, rtx); 358169689Skanstatic void mips_sim_record_set (rtx, rtx, void *); 359169689Skanstatic void mips_sim_issue_insn (struct mips_sim *, rtx); 360169689Skanstatic void mips_sim_issue_nop (struct mips_sim *); 361169689Skanstatic void mips_sim_finish_insn (struct mips_sim *, rtx); 362169689Skanstatic void vr4130_avoid_branch_rt_conflict (rtx); 363169689Skanstatic void vr4130_align_insns (void); 364169689Skanstatic void mips_avoid_hazard (rtx, rtx, int *, rtx *, rtx); 365169689Skanstatic void mips_avoid_hazards (void); 366169689Skanstatic void mips_reorg (void); 367169689Skanstatic bool mips_strict_matching_cpu_name_p (const char *, const char *); 368169689Skanstatic bool mips_matching_cpu_name_p (const char *, const char *); 369169689Skanstatic const struct mips_cpu_info *mips_parse_cpu (const char *); 370169689Skanstatic const struct mips_cpu_info *mips_cpu_info_from_isa (int); 371169689Skanstatic bool mips_return_in_memory (tree, tree); 372169689Skanstatic bool mips_strict_argument_naming (CUMULATIVE_ARGS *); 373169689Skanstatic void mips_macc_chains_record (rtx); 374169689Skanstatic void mips_macc_chains_reorder (rtx *, int); 375169689Skanstatic void vr4130_true_reg_dependence_p_1 (rtx, rtx, void *); 376169689Skanstatic bool vr4130_true_reg_dependence_p (rtx); 377169689Skanstatic bool vr4130_swap_insns_p (rtx, rtx); 378169689Skanstatic void vr4130_reorder (rtx *, int); 379169689Skanstatic void mips_promote_ready (rtx *, int, int); 380169689Skanstatic int mips_sched_reorder (FILE *, int, rtx *, int *, int); 381169689Skanstatic int mips_variable_issue (FILE *, int, rtx, int); 382169689Skanstatic int mips_adjust_cost (rtx, rtx, rtx, int); 383169689Skanstatic int mips_issue_rate (void); 384169689Skanstatic int mips_multipass_dfa_lookahead (void); 385169689Skanstatic void mips_init_libfuncs (void); 386169689Skanstatic void mips_setup_incoming_varargs (CUMULATIVE_ARGS *, enum machine_mode, 387169689Skan tree, int *, int); 388169689Skanstatic tree mips_build_builtin_va_list (void); 389169689Skanstatic tree mips_gimplify_va_arg_expr (tree, tree, tree *, tree *); 390169689Skanstatic bool mips_pass_by_reference (CUMULATIVE_ARGS *, enum machine_mode mode, 391169689Skan tree, bool); 392169689Skanstatic bool mips_callee_copies (CUMULATIVE_ARGS *, enum machine_mode mode, 393169689Skan tree, bool); 394169689Skanstatic int mips_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode mode, 395169689Skan tree, bool); 396169689Skanstatic bool mips_valid_pointer_mode (enum machine_mode); 397169689Skanstatic bool mips_vector_mode_supported_p (enum machine_mode); 398169689Skanstatic rtx mips_prepare_builtin_arg (enum insn_code, unsigned int, tree *); 399169689Skanstatic rtx mips_prepare_builtin_target (enum insn_code, unsigned int, rtx); 400169689Skanstatic rtx mips_expand_builtin (tree, rtx, rtx, enum machine_mode, int); 401169689Skanstatic void mips_init_builtins (void); 402169689Skanstatic rtx mips_expand_builtin_direct (enum insn_code, rtx, tree, bool); 403169689Skanstatic rtx mips_expand_builtin_movtf (enum mips_builtin_type, 404169689Skan enum insn_code, enum mips_fp_condition, 405169689Skan rtx, tree); 406169689Skanstatic rtx mips_expand_builtin_compare (enum mips_builtin_type, 407169689Skan enum insn_code, enum mips_fp_condition, 408169689Skan rtx, tree); 409169689Skanstatic rtx mips_expand_builtin_bposge (enum mips_builtin_type, rtx); 410169689Skanstatic void mips_encode_section_info (tree, rtx, int); 411169689Skanstatic void mips_extra_live_on_entry (bitmap); 412169689Skanstatic int mips_mode_rep_extended (enum machine_mode, enum machine_mode); 413169689Skan 414169689Skan/* Structure to be filled in by compute_frame_size with register 415169689Skan save masks, and offsets for the current function. */ 416169689Skan 417169689Skanstruct mips_frame_info GTY(()) 418169689Skan{ 419169689Skan HOST_WIDE_INT total_size; /* # bytes that the entire frame takes up */ 420169689Skan HOST_WIDE_INT var_size; /* # bytes that variables take up */ 421169689Skan HOST_WIDE_INT args_size; /* # bytes that outgoing arguments take up */ 422169689Skan HOST_WIDE_INT cprestore_size; /* # bytes that the .cprestore slot takes up */ 423169689Skan HOST_WIDE_INT gp_reg_size; /* # bytes needed to store gp regs */ 424169689Skan HOST_WIDE_INT fp_reg_size; /* # bytes needed to store fp regs */ 425169689Skan unsigned int mask; /* mask of saved gp registers */ 426169689Skan unsigned int fmask; /* mask of saved fp registers */ 427169689Skan HOST_WIDE_INT gp_save_offset; /* offset from vfp to store gp registers */ 428169689Skan HOST_WIDE_INT fp_save_offset; /* offset from vfp to store fp registers */ 429169689Skan HOST_WIDE_INT gp_sp_offset; /* offset from new sp to store gp registers */ 430169689Skan HOST_WIDE_INT fp_sp_offset; /* offset from new sp to store fp registers */ 431169689Skan bool initialized; /* true if frame size already calculated */ 432169689Skan int num_gp; /* number of gp registers saved */ 433169689Skan int num_fp; /* number of fp registers saved */ 434169689Skan}; 435169689Skan 436169689Skanstruct machine_function GTY(()) { 437169689Skan /* Pseudo-reg holding the value of $28 in a mips16 function which 438169689Skan refers to GP relative global variables. */ 439169689Skan rtx mips16_gp_pseudo_rtx; 440169689Skan 441169689Skan /* The number of extra stack bytes taken up by register varargs. 442169689Skan This area is allocated by the callee at the very top of the frame. */ 443169689Skan int varargs_size; 444169689Skan 445169689Skan /* Current frame information, calculated by compute_frame_size. */ 446169689Skan struct mips_frame_info frame; 447169689Skan 448169689Skan /* The register to use as the global pointer within this function. */ 449169689Skan unsigned int global_pointer; 450169689Skan 451169689Skan /* True if mips_adjust_insn_length should ignore an instruction's 452169689Skan hazard attribute. */ 453169689Skan bool ignore_hazard_length_p; 454169689Skan 455169689Skan /* True if the whole function is suitable for .set noreorder and 456169689Skan .set nomacro. */ 457169689Skan bool all_noreorder_p; 458169689Skan 459169689Skan /* True if the function is known to have an instruction that needs $gp. */ 460169689Skan bool has_gp_insn_p; 461169689Skan}; 462169689Skan 463169689Skan/* Information about a single argument. */ 464169689Skanstruct mips_arg_info 465169689Skan{ 466169689Skan /* True if the argument is passed in a floating-point register, or 467169689Skan would have been if we hadn't run out of registers. */ 468169689Skan bool fpr_p; 469169689Skan 470169689Skan /* The number of words passed in registers, rounded up. */ 471169689Skan unsigned int reg_words; 472169689Skan 473169689Skan /* For EABI, the offset of the first register from GP_ARG_FIRST or 474169689Skan FP_ARG_FIRST. For other ABIs, the offset of the first register from 475169689Skan the start of the ABI's argument structure (see the CUMULATIVE_ARGS 476169689Skan comment for details). 477169689Skan 478169689Skan The value is MAX_ARGS_IN_REGISTERS if the argument is passed entirely 479169689Skan on the stack. */ 480169689Skan unsigned int reg_offset; 481169689Skan 482169689Skan /* The number of words that must be passed on the stack, rounded up. */ 483169689Skan unsigned int stack_words; 484169689Skan 485169689Skan /* The offset from the start of the stack overflow area of the argument's 486169689Skan first stack word. Only meaningful when STACK_WORDS is nonzero. */ 487169689Skan unsigned int stack_offset; 488169689Skan}; 489169689Skan 490169689Skan 491169689Skan/* Information about an address described by mips_address_type. 492169689Skan 493169689Skan ADDRESS_CONST_INT 494169689Skan No fields are used. 495169689Skan 496169689Skan ADDRESS_REG 497169689Skan REG is the base register and OFFSET is the constant offset. 498169689Skan 499169689Skan ADDRESS_LO_SUM 500169689Skan REG is the register that contains the high part of the address, 501169689Skan OFFSET is the symbolic address being referenced and SYMBOL_TYPE 502169689Skan is the type of OFFSET's symbol. 503169689Skan 504169689Skan ADDRESS_SYMBOLIC 505169689Skan SYMBOL_TYPE is the type of symbol being referenced. */ 506169689Skan 507169689Skanstruct mips_address_info 508169689Skan{ 509169689Skan enum mips_address_type type; 510169689Skan rtx reg; 511169689Skan rtx offset; 512169689Skan enum mips_symbol_type symbol_type; 513169689Skan}; 514169689Skan 515169689Skan 516169689Skan/* One stage in a constant building sequence. These sequences have 517169689Skan the form: 518169689Skan 519169689Skan A = VALUE[0] 520169689Skan A = A CODE[1] VALUE[1] 521169689Skan A = A CODE[2] VALUE[2] 522169689Skan ... 523169689Skan 524169689Skan where A is an accumulator, each CODE[i] is a binary rtl operation 525169689Skan and each VALUE[i] is a constant integer. */ 526169689Skanstruct mips_integer_op { 527169689Skan enum rtx_code code; 528169689Skan unsigned HOST_WIDE_INT value; 529169689Skan}; 530169689Skan 531169689Skan 532169689Skan/* The largest number of operations needed to load an integer constant. 533169689Skan The worst accepted case for 64-bit constants is LUI,ORI,SLL,ORI,SLL,ORI. 534169689Skan When the lowest bit is clear, we can try, but reject a sequence with 535169689Skan an extra SLL at the end. */ 536169689Skan#define MIPS_MAX_INTEGER_OPS 7 537169689Skan 538169689Skan 539169689Skan/* Global variables for machine-dependent things. */ 540169689Skan 541169689Skan/* Threshold for data being put into the small data/bss area, instead 542169689Skan of the normal data area. */ 543169689Skanint mips_section_threshold = -1; 544169689Skan 545169689Skan/* Count the number of .file directives, so that .loc is up to date. */ 546169689Skanint num_source_filenames = 0; 547169689Skan 548169689Skan/* Count the number of sdb related labels are generated (to find block 549169689Skan start and end boundaries). */ 550169689Skanint sdb_label_count = 0; 551169689Skan 552169689Skan/* Next label # for each statement for Silicon Graphics IRIS systems. */ 553169689Skanint sym_lineno = 0; 554169689Skan 555169689Skan/* Linked list of all externals that are to be emitted when optimizing 556169689Skan for the global pointer if they haven't been declared by the end of 557169689Skan the program with an appropriate .comm or initialization. */ 558169689Skan 559169689Skanstruct extern_list GTY (()) 560169689Skan{ 561169689Skan struct extern_list *next; /* next external */ 562169689Skan const char *name; /* name of the external */ 563169689Skan int size; /* size in bytes */ 564169689Skan}; 565169689Skan 566169689Skanstatic GTY (()) struct extern_list *extern_head = 0; 567169689Skan 568169689Skan/* Name of the file containing the current function. */ 569169689Skanconst char *current_function_file = ""; 570169689Skan 571169689Skan/* Number of nested .set noreorder, noat, nomacro, and volatile requests. */ 572169689Skanint set_noreorder; 573169689Skanint set_noat; 574169689Skanint set_nomacro; 575169689Skanint set_volatile; 576169689Skan 577169689Skan/* The next branch instruction is a branch likely, not branch normal. */ 578169689Skanint mips_branch_likely; 579169689Skan 580169689Skan/* The operands passed to the last cmpMM expander. */ 581169689Skanrtx cmp_operands[2]; 582169689Skan 583169689Skan/* The target cpu for code generation. */ 584169689Skanenum processor_type mips_arch; 585169689Skanconst struct mips_cpu_info *mips_arch_info; 586169689Skan 587169689Skan/* The target cpu for optimization and scheduling. */ 588169689Skanenum processor_type mips_tune; 589169689Skanconst struct mips_cpu_info *mips_tune_info; 590169689Skan 591169689Skan/* Which instruction set architecture to use. */ 592169689Skanint mips_isa; 593169689Skan 594169689Skan/* Which ABI to use. */ 595169689Skanint mips_abi = MIPS_ABI_DEFAULT; 596169689Skan 597169689Skan/* Cost information to use. */ 598169689Skanconst struct mips_rtx_cost_data *mips_cost; 599169689Skan 600169689Skan/* Whether we are generating mips16 hard float code. In mips16 mode 601169689Skan we always set TARGET_SOFT_FLOAT; this variable is nonzero if 602169689Skan -msoft-float was not specified by the user, which means that we 603169689Skan should arrange to call mips32 hard floating point code. */ 604169689Skanint mips16_hard_float; 605169689Skan 606169689Skan/* The architecture selected by -mipsN. */ 607169689Skanstatic const struct mips_cpu_info *mips_isa_info; 608169689Skan 609169689Skan/* If TRUE, we split addresses into their high and low parts in the RTL. */ 610169689Skanint mips_split_addresses; 611169689Skan 612169689Skan/* Mode used for saving/restoring general purpose registers. */ 613169689Skanstatic enum machine_mode gpr_mode; 614169689Skan 615169689Skan/* Array giving truth value on whether or not a given hard register 616169689Skan can support a given mode. */ 617169689Skanchar mips_hard_regno_mode_ok[(int)MAX_MACHINE_MODE][FIRST_PSEUDO_REGISTER]; 618169689Skan 619169689Skan/* List of all MIPS punctuation characters used by print_operand. */ 620169689Skanchar mips_print_operand_punct[256]; 621169689Skan 622169689Skan/* Map GCC register number to debugger register number. */ 623169689Skanint mips_dbx_regno[FIRST_PSEUDO_REGISTER]; 624169689Skan 625169689Skan/* A copy of the original flag_delayed_branch: see override_options. */ 626169689Skanstatic int mips_flag_delayed_branch; 627169689Skan 628169689Skanstatic GTY (()) int mips_output_filename_first_time = 1; 629169689Skan 630169689Skan/* mips_split_p[X] is true if symbols of type X can be split by 631169689Skan mips_split_symbol(). */ 632169689Skanbool mips_split_p[NUM_SYMBOL_TYPES]; 633169689Skan 634169689Skan/* mips_lo_relocs[X] is the relocation to use when a symbol of type X 635169689Skan appears in a LO_SUM. It can be null if such LO_SUMs aren't valid or 636169689Skan if they are matched by a special .md file pattern. */ 637169689Skanstatic const char *mips_lo_relocs[NUM_SYMBOL_TYPES]; 638169689Skan 639169689Skan/* Likewise for HIGHs. */ 640169689Skanstatic const char *mips_hi_relocs[NUM_SYMBOL_TYPES]; 641169689Skan 642169689Skan/* Map hard register number to register class */ 643169689Skanconst enum reg_class mips_regno_to_class[] = 644169689Skan{ 645169689Skan LEA_REGS, LEA_REGS, M16_NA_REGS, V1_REG, 646169689Skan M16_REGS, M16_REGS, M16_REGS, M16_REGS, 647169689Skan LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS, 648169689Skan LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS, 649169689Skan M16_NA_REGS, M16_NA_REGS, LEA_REGS, LEA_REGS, 650169689Skan LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS, 651169689Skan T_REG, PIC_FN_ADDR_REG, LEA_REGS, LEA_REGS, 652169689Skan LEA_REGS, LEA_REGS, LEA_REGS, LEA_REGS, 653169689Skan FP_REGS, FP_REGS, FP_REGS, FP_REGS, 654169689Skan FP_REGS, FP_REGS, FP_REGS, FP_REGS, 655169689Skan FP_REGS, FP_REGS, FP_REGS, FP_REGS, 656169689Skan FP_REGS, FP_REGS, FP_REGS, FP_REGS, 657169689Skan FP_REGS, FP_REGS, FP_REGS, FP_REGS, 658169689Skan FP_REGS, FP_REGS, FP_REGS, FP_REGS, 659169689Skan FP_REGS, FP_REGS, FP_REGS, FP_REGS, 660169689Skan FP_REGS, FP_REGS, FP_REGS, FP_REGS, 661169689Skan HI_REG, LO_REG, NO_REGS, ST_REGS, 662169689Skan ST_REGS, ST_REGS, ST_REGS, ST_REGS, 663169689Skan ST_REGS, ST_REGS, ST_REGS, NO_REGS, 664169689Skan NO_REGS, ALL_REGS, ALL_REGS, NO_REGS, 665169689Skan COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS, 666169689Skan COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS, 667169689Skan COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS, 668169689Skan COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS, 669169689Skan COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS, 670169689Skan COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS, 671169689Skan COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS, 672169689Skan COP0_REGS, COP0_REGS, COP0_REGS, COP0_REGS, 673169689Skan COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS, 674169689Skan COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS, 675169689Skan COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS, 676169689Skan COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS, 677169689Skan COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS, 678169689Skan COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS, 679169689Skan COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS, 680169689Skan COP2_REGS, COP2_REGS, COP2_REGS, COP2_REGS, 681169689Skan COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS, 682169689Skan COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS, 683169689Skan COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS, 684169689Skan COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS, 685169689Skan COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS, 686169689Skan COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS, 687169689Skan COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS, 688169689Skan COP3_REGS, COP3_REGS, COP3_REGS, COP3_REGS, 689169689Skan DSP_ACC_REGS, DSP_ACC_REGS, DSP_ACC_REGS, DSP_ACC_REGS, 690169689Skan DSP_ACC_REGS, DSP_ACC_REGS, ALL_REGS, ALL_REGS, 691169689Skan ALL_REGS, ALL_REGS, ALL_REGS, ALL_REGS 692169689Skan}; 693169689Skan 694169689Skan/* Table of machine dependent attributes. */ 695169689Skanconst struct attribute_spec mips_attribute_table[] = 696169689Skan{ 697169689Skan { "long_call", 0, 0, false, true, true, NULL }, 698169689Skan { NULL, 0, 0, false, false, false, NULL } 699169689Skan}; 700169689Skan 701169689Skan/* A table describing all the processors gcc knows about. Names are 702169689Skan matched in the order listed. The first mention of an ISA level is 703169689Skan taken as the canonical name for that ISA. 704169689Skan 705169689Skan To ease comparison, please keep this table in the same order as 706169689Skan gas's mips_cpu_info_table[]. */ 707169689Skanconst struct mips_cpu_info mips_cpu_info_table[] = { 708169689Skan /* Entries for generic ISAs */ 709169689Skan { "mips1", PROCESSOR_R3000, 1 }, 710169689Skan { "mips2", PROCESSOR_R6000, 2 }, 711169689Skan { "mips3", PROCESSOR_R4000, 3 }, 712169689Skan { "mips4", PROCESSOR_R8000, 4 }, 713169689Skan { "mips32", PROCESSOR_4KC, 32 }, 714169689Skan { "mips32r2", PROCESSOR_M4K, 33 }, 715169689Skan { "mips64", PROCESSOR_5KC, 64 }, 716208737Sjmallett { "mips64r2", PROCESSOR_5KC, 65 }, 717169689Skan 718169689Skan /* MIPS I */ 719169689Skan { "r3000", PROCESSOR_R3000, 1 }, 720169689Skan { "r2000", PROCESSOR_R3000, 1 }, /* = r3000 */ 721169689Skan { "r3900", PROCESSOR_R3900, 1 }, 722169689Skan 723169689Skan /* MIPS II */ 724169689Skan { "r6000", PROCESSOR_R6000, 2 }, 725169689Skan 726169689Skan /* MIPS III */ 727169689Skan { "r4000", PROCESSOR_R4000, 3 }, 728169689Skan { "vr4100", PROCESSOR_R4100, 3 }, 729169689Skan { "vr4111", PROCESSOR_R4111, 3 }, 730169689Skan { "vr4120", PROCESSOR_R4120, 3 }, 731169689Skan { "vr4130", PROCESSOR_R4130, 3 }, 732169689Skan { "vr4300", PROCESSOR_R4300, 3 }, 733169689Skan { "r4400", PROCESSOR_R4000, 3 }, /* = r4000 */ 734169689Skan { "r4600", PROCESSOR_R4600, 3 }, 735169689Skan { "orion", PROCESSOR_R4600, 3 }, /* = r4600 */ 736169689Skan { "r4650", PROCESSOR_R4650, 3 }, 737169689Skan 738169689Skan /* MIPS IV */ 739169689Skan { "r8000", PROCESSOR_R8000, 4 }, 740169689Skan { "vr5000", PROCESSOR_R5000, 4 }, 741169689Skan { "vr5400", PROCESSOR_R5400, 4 }, 742169689Skan { "vr5500", PROCESSOR_R5500, 4 }, 743169689Skan { "rm7000", PROCESSOR_R7000, 4 }, 744169689Skan { "rm9000", PROCESSOR_R9000, 4 }, 745169689Skan 746169689Skan /* MIPS32 */ 747169689Skan { "4kc", PROCESSOR_4KC, 32 }, 748169689Skan { "4km", PROCESSOR_4KC, 32 }, /* = 4kc */ 749169689Skan { "4kp", PROCESSOR_4KP, 32 }, 750169689Skan 751169689Skan /* MIPS32 Release 2 */ 752169689Skan { "m4k", PROCESSOR_M4K, 33 }, 753169689Skan { "24k", PROCESSOR_24K, 33 }, 754169689Skan { "24kc", PROCESSOR_24K, 33 }, /* 24K no FPU */ 755169689Skan { "24kf", PROCESSOR_24K, 33 }, /* 24K 1:2 FPU */ 756169689Skan { "24kx", PROCESSOR_24KX, 33 }, /* 24K 1:1 FPU */ 757169689Skan 758169689Skan /* MIPS64 */ 759169689Skan { "5kc", PROCESSOR_5KC, 64 }, 760169689Skan { "5kf", PROCESSOR_5KF, 64 }, 761169689Skan { "20kc", PROCESSOR_20KC, 64 }, 762169689Skan { "sb1", PROCESSOR_SB1, 64 }, 763169689Skan { "sb1a", PROCESSOR_SB1A, 64 }, 764169689Skan { "sr71000", PROCESSOR_SR71000, 64 }, 765169689Skan 766208737Sjmallett /* MIPS64R2 */ 767208737Sjmallett { "octeon", PROCESSOR_OCTEON, 65 }, 768208737Sjmallett 769169689Skan /* End marker */ 770169689Skan { 0, 0, 0 } 771169689Skan}; 772169689Skan 773169689Skan/* Default costs. If these are used for a processor we should look 774169689Skan up the actual costs. */ 775169689Skan#define DEFAULT_COSTS COSTS_N_INSNS (6), /* fp_add */ \ 776169689Skan COSTS_N_INSNS (7), /* fp_mult_sf */ \ 777169689Skan COSTS_N_INSNS (8), /* fp_mult_df */ \ 778169689Skan COSTS_N_INSNS (23), /* fp_div_sf */ \ 779169689Skan COSTS_N_INSNS (36), /* fp_div_df */ \ 780169689Skan COSTS_N_INSNS (10), /* int_mult_si */ \ 781169689Skan COSTS_N_INSNS (10), /* int_mult_di */ \ 782169689Skan COSTS_N_INSNS (69), /* int_div_si */ \ 783169689Skan COSTS_N_INSNS (69), /* int_div_di */ \ 784169689Skan 2, /* branch_cost */ \ 785169689Skan 4 /* memory_latency */ 786169689Skan 787169689Skan/* Need to replace these with the costs of calling the appropriate 788169689Skan libgcc routine. */ 789169689Skan#define SOFT_FP_COSTS COSTS_N_INSNS (256), /* fp_add */ \ 790169689Skan COSTS_N_INSNS (256), /* fp_mult_sf */ \ 791169689Skan COSTS_N_INSNS (256), /* fp_mult_df */ \ 792169689Skan COSTS_N_INSNS (256), /* fp_div_sf */ \ 793169689Skan COSTS_N_INSNS (256) /* fp_div_df */ 794169689Skan 795169689Skanstatic struct mips_rtx_cost_data const mips_rtx_cost_data[PROCESSOR_MAX] = 796169689Skan { 797169689Skan { /* R3000 */ 798169689Skan COSTS_N_INSNS (2), /* fp_add */ 799169689Skan COSTS_N_INSNS (4), /* fp_mult_sf */ 800169689Skan COSTS_N_INSNS (5), /* fp_mult_df */ 801169689Skan COSTS_N_INSNS (12), /* fp_div_sf */ 802169689Skan COSTS_N_INSNS (19), /* fp_div_df */ 803169689Skan COSTS_N_INSNS (12), /* int_mult_si */ 804169689Skan COSTS_N_INSNS (12), /* int_mult_di */ 805169689Skan COSTS_N_INSNS (35), /* int_div_si */ 806169689Skan COSTS_N_INSNS (35), /* int_div_di */ 807169689Skan 1, /* branch_cost */ 808169689Skan 4 /* memory_latency */ 809169689Skan 810169689Skan }, 811169689Skan { /* 4KC */ 812169689Skan SOFT_FP_COSTS, 813169689Skan COSTS_N_INSNS (6), /* int_mult_si */ 814169689Skan COSTS_N_INSNS (6), /* int_mult_di */ 815169689Skan COSTS_N_INSNS (36), /* int_div_si */ 816169689Skan COSTS_N_INSNS (36), /* int_div_di */ 817169689Skan 1, /* branch_cost */ 818169689Skan 4 /* memory_latency */ 819169689Skan }, 820169689Skan { /* 4KP */ 821169689Skan SOFT_FP_COSTS, 822169689Skan COSTS_N_INSNS (36), /* int_mult_si */ 823169689Skan COSTS_N_INSNS (36), /* int_mult_di */ 824169689Skan COSTS_N_INSNS (37), /* int_div_si */ 825169689Skan COSTS_N_INSNS (37), /* int_div_di */ 826169689Skan 1, /* branch_cost */ 827169689Skan 4 /* memory_latency */ 828169689Skan }, 829169689Skan { /* 5KC */ 830169689Skan SOFT_FP_COSTS, 831169689Skan COSTS_N_INSNS (4), /* int_mult_si */ 832169689Skan COSTS_N_INSNS (11), /* int_mult_di */ 833169689Skan COSTS_N_INSNS (36), /* int_div_si */ 834169689Skan COSTS_N_INSNS (68), /* int_div_di */ 835169689Skan 1, /* branch_cost */ 836169689Skan 4 /* memory_latency */ 837169689Skan }, 838169689Skan { /* 5KF */ 839169689Skan COSTS_N_INSNS (4), /* fp_add */ 840169689Skan COSTS_N_INSNS (4), /* fp_mult_sf */ 841169689Skan COSTS_N_INSNS (5), /* fp_mult_df */ 842169689Skan COSTS_N_INSNS (17), /* fp_div_sf */ 843169689Skan COSTS_N_INSNS (32), /* fp_div_df */ 844169689Skan COSTS_N_INSNS (4), /* int_mult_si */ 845169689Skan COSTS_N_INSNS (11), /* int_mult_di */ 846169689Skan COSTS_N_INSNS (36), /* int_div_si */ 847169689Skan COSTS_N_INSNS (68), /* int_div_di */ 848169689Skan 1, /* branch_cost */ 849169689Skan 4 /* memory_latency */ 850169689Skan }, 851169689Skan { /* 20KC */ 852169689Skan DEFAULT_COSTS 853169689Skan }, 854169689Skan { /* 24k */ 855169689Skan COSTS_N_INSNS (8), /* fp_add */ 856169689Skan COSTS_N_INSNS (8), /* fp_mult_sf */ 857169689Skan COSTS_N_INSNS (10), /* fp_mult_df */ 858169689Skan COSTS_N_INSNS (34), /* fp_div_sf */ 859169689Skan COSTS_N_INSNS (64), /* fp_div_df */ 860169689Skan COSTS_N_INSNS (5), /* int_mult_si */ 861169689Skan COSTS_N_INSNS (5), /* int_mult_di */ 862169689Skan COSTS_N_INSNS (41), /* int_div_si */ 863169689Skan COSTS_N_INSNS (41), /* int_div_di */ 864169689Skan 1, /* branch_cost */ 865169689Skan 4 /* memory_latency */ 866169689Skan }, 867169689Skan { /* 24kx */ 868169689Skan COSTS_N_INSNS (4), /* fp_add */ 869169689Skan COSTS_N_INSNS (4), /* fp_mult_sf */ 870169689Skan COSTS_N_INSNS (5), /* fp_mult_df */ 871169689Skan COSTS_N_INSNS (17), /* fp_div_sf */ 872169689Skan COSTS_N_INSNS (32), /* fp_div_df */ 873169689Skan COSTS_N_INSNS (5), /* int_mult_si */ 874169689Skan COSTS_N_INSNS (5), /* int_mult_di */ 875169689Skan COSTS_N_INSNS (41), /* int_div_si */ 876169689Skan COSTS_N_INSNS (41), /* int_div_di */ 877169689Skan 1, /* branch_cost */ 878169689Skan 4 /* memory_latency */ 879169689Skan }, 880169689Skan { /* M4k */ 881169689Skan DEFAULT_COSTS 882169689Skan }, 883169689Skan { /* R3900 */ 884169689Skan COSTS_N_INSNS (2), /* fp_add */ 885169689Skan COSTS_N_INSNS (4), /* fp_mult_sf */ 886169689Skan COSTS_N_INSNS (5), /* fp_mult_df */ 887169689Skan COSTS_N_INSNS (12), /* fp_div_sf */ 888169689Skan COSTS_N_INSNS (19), /* fp_div_df */ 889169689Skan COSTS_N_INSNS (2), /* int_mult_si */ 890169689Skan COSTS_N_INSNS (2), /* int_mult_di */ 891169689Skan COSTS_N_INSNS (35), /* int_div_si */ 892169689Skan COSTS_N_INSNS (35), /* int_div_di */ 893169689Skan 1, /* branch_cost */ 894169689Skan 4 /* memory_latency */ 895169689Skan }, 896169689Skan { /* R6000 */ 897169689Skan COSTS_N_INSNS (3), /* fp_add */ 898169689Skan COSTS_N_INSNS (5), /* fp_mult_sf */ 899169689Skan COSTS_N_INSNS (6), /* fp_mult_df */ 900169689Skan COSTS_N_INSNS (15), /* fp_div_sf */ 901169689Skan COSTS_N_INSNS (16), /* fp_div_df */ 902169689Skan COSTS_N_INSNS (17), /* int_mult_si */ 903169689Skan COSTS_N_INSNS (17), /* int_mult_di */ 904169689Skan COSTS_N_INSNS (38), /* int_div_si */ 905169689Skan COSTS_N_INSNS (38), /* int_div_di */ 906169689Skan 2, /* branch_cost */ 907169689Skan 6 /* memory_latency */ 908169689Skan }, 909169689Skan { /* R4000 */ 910169689Skan COSTS_N_INSNS (6), /* fp_add */ 911169689Skan COSTS_N_INSNS (7), /* fp_mult_sf */ 912169689Skan COSTS_N_INSNS (8), /* fp_mult_df */ 913169689Skan COSTS_N_INSNS (23), /* fp_div_sf */ 914169689Skan COSTS_N_INSNS (36), /* fp_div_df */ 915169689Skan COSTS_N_INSNS (10), /* int_mult_si */ 916169689Skan COSTS_N_INSNS (10), /* int_mult_di */ 917169689Skan COSTS_N_INSNS (69), /* int_div_si */ 918169689Skan COSTS_N_INSNS (69), /* int_div_di */ 919169689Skan 2, /* branch_cost */ 920169689Skan 6 /* memory_latency */ 921169689Skan }, 922169689Skan { /* R4100 */ 923169689Skan DEFAULT_COSTS 924169689Skan }, 925169689Skan { /* R4111 */ 926169689Skan DEFAULT_COSTS 927169689Skan }, 928169689Skan { /* R4120 */ 929169689Skan DEFAULT_COSTS 930169689Skan }, 931169689Skan { /* R4130 */ 932169689Skan /* The only costs that appear to be updated here are 933169689Skan integer multiplication. */ 934169689Skan SOFT_FP_COSTS, 935169689Skan COSTS_N_INSNS (4), /* int_mult_si */ 936169689Skan COSTS_N_INSNS (6), /* int_mult_di */ 937169689Skan COSTS_N_INSNS (69), /* int_div_si */ 938169689Skan COSTS_N_INSNS (69), /* int_div_di */ 939169689Skan 1, /* branch_cost */ 940169689Skan 4 /* memory_latency */ 941169689Skan }, 942169689Skan { /* R4300 */ 943169689Skan DEFAULT_COSTS 944169689Skan }, 945169689Skan { /* R4600 */ 946169689Skan DEFAULT_COSTS 947169689Skan }, 948169689Skan { /* R4650 */ 949169689Skan DEFAULT_COSTS 950169689Skan }, 951169689Skan { /* R5000 */ 952169689Skan COSTS_N_INSNS (6), /* fp_add */ 953169689Skan COSTS_N_INSNS (4), /* fp_mult_sf */ 954169689Skan COSTS_N_INSNS (5), /* fp_mult_df */ 955169689Skan COSTS_N_INSNS (23), /* fp_div_sf */ 956169689Skan COSTS_N_INSNS (36), /* fp_div_df */ 957169689Skan COSTS_N_INSNS (5), /* int_mult_si */ 958169689Skan COSTS_N_INSNS (5), /* int_mult_di */ 959169689Skan COSTS_N_INSNS (36), /* int_div_si */ 960169689Skan COSTS_N_INSNS (36), /* int_div_di */ 961169689Skan 1, /* branch_cost */ 962169689Skan 4 /* memory_latency */ 963169689Skan }, 964169689Skan { /* R5400 */ 965169689Skan COSTS_N_INSNS (6), /* fp_add */ 966169689Skan COSTS_N_INSNS (5), /* fp_mult_sf */ 967169689Skan COSTS_N_INSNS (6), /* fp_mult_df */ 968169689Skan COSTS_N_INSNS (30), /* fp_div_sf */ 969169689Skan COSTS_N_INSNS (59), /* fp_div_df */ 970169689Skan COSTS_N_INSNS (3), /* int_mult_si */ 971169689Skan COSTS_N_INSNS (4), /* int_mult_di */ 972169689Skan COSTS_N_INSNS (42), /* int_div_si */ 973169689Skan COSTS_N_INSNS (74), /* int_div_di */ 974169689Skan 1, /* branch_cost */ 975169689Skan 4 /* memory_latency */ 976169689Skan }, 977169689Skan { /* R5500 */ 978169689Skan COSTS_N_INSNS (6), /* fp_add */ 979169689Skan COSTS_N_INSNS (5), /* fp_mult_sf */ 980169689Skan COSTS_N_INSNS (6), /* fp_mult_df */ 981169689Skan COSTS_N_INSNS (30), /* fp_div_sf */ 982169689Skan COSTS_N_INSNS (59), /* fp_div_df */ 983169689Skan COSTS_N_INSNS (5), /* int_mult_si */ 984169689Skan COSTS_N_INSNS (9), /* int_mult_di */ 985169689Skan COSTS_N_INSNS (42), /* int_div_si */ 986169689Skan COSTS_N_INSNS (74), /* int_div_di */ 987169689Skan 1, /* branch_cost */ 988169689Skan 4 /* memory_latency */ 989169689Skan }, 990169689Skan { /* R7000 */ 991169689Skan /* The only costs that are changed here are 992169689Skan integer multiplication. */ 993169689Skan COSTS_N_INSNS (6), /* fp_add */ 994169689Skan COSTS_N_INSNS (7), /* fp_mult_sf */ 995169689Skan COSTS_N_INSNS (8), /* fp_mult_df */ 996169689Skan COSTS_N_INSNS (23), /* fp_div_sf */ 997169689Skan COSTS_N_INSNS (36), /* fp_div_df */ 998169689Skan COSTS_N_INSNS (5), /* int_mult_si */ 999169689Skan COSTS_N_INSNS (9), /* int_mult_di */ 1000169689Skan COSTS_N_INSNS (69), /* int_div_si */ 1001169689Skan COSTS_N_INSNS (69), /* int_div_di */ 1002169689Skan 1, /* branch_cost */ 1003169689Skan 4 /* memory_latency */ 1004169689Skan }, 1005169689Skan { /* R8000 */ 1006169689Skan DEFAULT_COSTS 1007169689Skan }, 1008169689Skan { /* R9000 */ 1009169689Skan /* The only costs that are changed here are 1010169689Skan integer multiplication. */ 1011169689Skan COSTS_N_INSNS (6), /* fp_add */ 1012169689Skan COSTS_N_INSNS (7), /* fp_mult_sf */ 1013169689Skan COSTS_N_INSNS (8), /* fp_mult_df */ 1014169689Skan COSTS_N_INSNS (23), /* fp_div_sf */ 1015169689Skan COSTS_N_INSNS (36), /* fp_div_df */ 1016169689Skan COSTS_N_INSNS (3), /* int_mult_si */ 1017169689Skan COSTS_N_INSNS (8), /* int_mult_di */ 1018169689Skan COSTS_N_INSNS (69), /* int_div_si */ 1019169689Skan COSTS_N_INSNS (69), /* int_div_di */ 1020169689Skan 1, /* branch_cost */ 1021169689Skan 4 /* memory_latency */ 1022169689Skan }, 1023169689Skan { /* SB1 */ 1024169689Skan /* These costs are the same as the SB-1A below. */ 1025169689Skan COSTS_N_INSNS (4), /* fp_add */ 1026169689Skan COSTS_N_INSNS (4), /* fp_mult_sf */ 1027169689Skan COSTS_N_INSNS (4), /* fp_mult_df */ 1028169689Skan COSTS_N_INSNS (24), /* fp_div_sf */ 1029169689Skan COSTS_N_INSNS (32), /* fp_div_df */ 1030169689Skan COSTS_N_INSNS (3), /* int_mult_si */ 1031169689Skan COSTS_N_INSNS (4), /* int_mult_di */ 1032169689Skan COSTS_N_INSNS (36), /* int_div_si */ 1033169689Skan COSTS_N_INSNS (68), /* int_div_di */ 1034169689Skan 1, /* branch_cost */ 1035169689Skan 4 /* memory_latency */ 1036169689Skan }, 1037169689Skan { /* SB1-A */ 1038169689Skan /* These costs are the same as the SB-1 above. */ 1039169689Skan COSTS_N_INSNS (4), /* fp_add */ 1040169689Skan COSTS_N_INSNS (4), /* fp_mult_sf */ 1041169689Skan COSTS_N_INSNS (4), /* fp_mult_df */ 1042169689Skan COSTS_N_INSNS (24), /* fp_div_sf */ 1043169689Skan COSTS_N_INSNS (32), /* fp_div_df */ 1044169689Skan COSTS_N_INSNS (3), /* int_mult_si */ 1045169689Skan COSTS_N_INSNS (4), /* int_mult_di */ 1046169689Skan COSTS_N_INSNS (36), /* int_div_si */ 1047169689Skan COSTS_N_INSNS (68), /* int_div_di */ 1048169689Skan 1, /* branch_cost */ 1049169689Skan 4 /* memory_latency */ 1050169689Skan }, 1051169689Skan { /* SR71000 */ 1052169689Skan DEFAULT_COSTS 1053169689Skan }, 1054169689Skan }; 1055169689Skan 1056169689Skan 1057169689Skan/* Nonzero if -march should decide the default value of MASK_SOFT_FLOAT. */ 1058169689Skan#ifndef MIPS_MARCH_CONTROLS_SOFT_FLOAT 1059169689Skan#define MIPS_MARCH_CONTROLS_SOFT_FLOAT 0 1060169689Skan#endif 1061169689Skan 1062169689Skan/* Initialize the GCC target structure. */ 1063169689Skan#undef TARGET_ASM_ALIGNED_HI_OP 1064169689Skan#define TARGET_ASM_ALIGNED_HI_OP "\t.half\t" 1065169689Skan#undef TARGET_ASM_ALIGNED_SI_OP 1066169689Skan#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t" 1067169689Skan#undef TARGET_ASM_ALIGNED_DI_OP 1068169689Skan#define TARGET_ASM_ALIGNED_DI_OP "\t.dword\t" 1069169689Skan 1070169689Skan#undef TARGET_ASM_FUNCTION_PROLOGUE 1071169689Skan#define TARGET_ASM_FUNCTION_PROLOGUE mips_output_function_prologue 1072169689Skan#undef TARGET_ASM_FUNCTION_EPILOGUE 1073169689Skan#define TARGET_ASM_FUNCTION_EPILOGUE mips_output_function_epilogue 1074169689Skan#undef TARGET_ASM_SELECT_RTX_SECTION 1075169689Skan#define TARGET_ASM_SELECT_RTX_SECTION mips_select_rtx_section 1076169689Skan#undef TARGET_ASM_FUNCTION_RODATA_SECTION 1077169689Skan#define TARGET_ASM_FUNCTION_RODATA_SECTION mips_function_rodata_section 1078169689Skan 1079169689Skan#undef TARGET_SCHED_REORDER 1080169689Skan#define TARGET_SCHED_REORDER mips_sched_reorder 1081169689Skan#undef TARGET_SCHED_VARIABLE_ISSUE 1082169689Skan#define TARGET_SCHED_VARIABLE_ISSUE mips_variable_issue 1083169689Skan#undef TARGET_SCHED_ADJUST_COST 1084169689Skan#define TARGET_SCHED_ADJUST_COST mips_adjust_cost 1085169689Skan#undef TARGET_SCHED_ISSUE_RATE 1086169689Skan#define TARGET_SCHED_ISSUE_RATE mips_issue_rate 1087169689Skan#undef TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD 1088169689Skan#define TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD \ 1089169689Skan mips_multipass_dfa_lookahead 1090169689Skan 1091169689Skan#undef TARGET_DEFAULT_TARGET_FLAGS 1092169689Skan#define TARGET_DEFAULT_TARGET_FLAGS \ 1093169689Skan (TARGET_DEFAULT \ 1094169689Skan | TARGET_CPU_DEFAULT \ 1095169689Skan | TARGET_ENDIAN_DEFAULT \ 1096169689Skan | TARGET_FP_EXCEPTIONS_DEFAULT \ 1097169689Skan | MASK_CHECK_ZERO_DIV \ 1098169689Skan | MASK_FUSED_MADD) 1099169689Skan#undef TARGET_HANDLE_OPTION 1100169689Skan#define TARGET_HANDLE_OPTION mips_handle_option 1101169689Skan 1102169689Skan#undef TARGET_FUNCTION_OK_FOR_SIBCALL 1103169689Skan#define TARGET_FUNCTION_OK_FOR_SIBCALL mips_function_ok_for_sibcall 1104169689Skan 1105169689Skan#undef TARGET_VALID_POINTER_MODE 1106169689Skan#define TARGET_VALID_POINTER_MODE mips_valid_pointer_mode 1107169689Skan#undef TARGET_RTX_COSTS 1108169689Skan#define TARGET_RTX_COSTS mips_rtx_costs 1109169689Skan#undef TARGET_ADDRESS_COST 1110169689Skan#define TARGET_ADDRESS_COST mips_address_cost 1111169689Skan 1112169689Skan#undef TARGET_IN_SMALL_DATA_P 1113169689Skan#define TARGET_IN_SMALL_DATA_P mips_in_small_data_p 1114169689Skan 1115169689Skan#undef TARGET_MACHINE_DEPENDENT_REORG 1116169689Skan#define TARGET_MACHINE_DEPENDENT_REORG mips_reorg 1117169689Skan 1118169689Skan#undef TARGET_ASM_FILE_START 1119169689Skan#undef TARGET_ASM_FILE_END 1120169689Skan#define TARGET_ASM_FILE_START mips_file_start 1121169689Skan#define TARGET_ASM_FILE_END mips_file_end 1122169689Skan#undef TARGET_ASM_FILE_START_FILE_DIRECTIVE 1123169689Skan#define TARGET_ASM_FILE_START_FILE_DIRECTIVE true 1124169689Skan 1125169689Skan#undef TARGET_INIT_LIBFUNCS 1126169689Skan#define TARGET_INIT_LIBFUNCS mips_init_libfuncs 1127169689Skan 1128169689Skan#undef TARGET_BUILD_BUILTIN_VA_LIST 1129169689Skan#define TARGET_BUILD_BUILTIN_VA_LIST mips_build_builtin_va_list 1130169689Skan#undef TARGET_GIMPLIFY_VA_ARG_EXPR 1131169689Skan#define TARGET_GIMPLIFY_VA_ARG_EXPR mips_gimplify_va_arg_expr 1132169689Skan 1133169689Skan#undef TARGET_PROMOTE_FUNCTION_ARGS 1134169689Skan#define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true 1135169689Skan#undef TARGET_PROMOTE_FUNCTION_RETURN 1136169689Skan#define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true 1137169689Skan#undef TARGET_PROMOTE_PROTOTYPES 1138169689Skan#define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true 1139169689Skan 1140169689Skan#undef TARGET_RETURN_IN_MEMORY 1141169689Skan#define TARGET_RETURN_IN_MEMORY mips_return_in_memory 1142169689Skan#undef TARGET_RETURN_IN_MSB 1143169689Skan#define TARGET_RETURN_IN_MSB mips_return_in_msb 1144169689Skan 1145169689Skan#undef TARGET_ASM_OUTPUT_MI_THUNK 1146169689Skan#define TARGET_ASM_OUTPUT_MI_THUNK mips_output_mi_thunk 1147169689Skan#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK 1148169689Skan#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true 1149169689Skan 1150169689Skan#undef TARGET_SETUP_INCOMING_VARARGS 1151169689Skan#define TARGET_SETUP_INCOMING_VARARGS mips_setup_incoming_varargs 1152169689Skan#undef TARGET_STRICT_ARGUMENT_NAMING 1153169689Skan#define TARGET_STRICT_ARGUMENT_NAMING mips_strict_argument_naming 1154169689Skan#undef TARGET_MUST_PASS_IN_STACK 1155169689Skan#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size 1156169689Skan#undef TARGET_PASS_BY_REFERENCE 1157169689Skan#define TARGET_PASS_BY_REFERENCE mips_pass_by_reference 1158169689Skan#undef TARGET_CALLEE_COPIES 1159169689Skan#define TARGET_CALLEE_COPIES mips_callee_copies 1160169689Skan#undef TARGET_ARG_PARTIAL_BYTES 1161169689Skan#define TARGET_ARG_PARTIAL_BYTES mips_arg_partial_bytes 1162169689Skan 1163169689Skan#undef TARGET_MODE_REP_EXTENDED 1164169689Skan#define TARGET_MODE_REP_EXTENDED mips_mode_rep_extended 1165169689Skan 1166169689Skan#undef TARGET_VECTOR_MODE_SUPPORTED_P 1167169689Skan#define TARGET_VECTOR_MODE_SUPPORTED_P mips_vector_mode_supported_p 1168169689Skan 1169169689Skan#undef TARGET_INIT_BUILTINS 1170169689Skan#define TARGET_INIT_BUILTINS mips_init_builtins 1171169689Skan#undef TARGET_EXPAND_BUILTIN 1172169689Skan#define TARGET_EXPAND_BUILTIN mips_expand_builtin 1173169689Skan 1174169689Skan#undef TARGET_HAVE_TLS 1175169689Skan#define TARGET_HAVE_TLS HAVE_AS_TLS 1176169689Skan 1177169689Skan#undef TARGET_CANNOT_FORCE_CONST_MEM 1178169689Skan#define TARGET_CANNOT_FORCE_CONST_MEM mips_cannot_force_const_mem 1179169689Skan 1180169689Skan#undef TARGET_ENCODE_SECTION_INFO 1181169689Skan#define TARGET_ENCODE_SECTION_INFO mips_encode_section_info 1182169689Skan 1183169689Skan#undef TARGET_ATTRIBUTE_TABLE 1184169689Skan#define TARGET_ATTRIBUTE_TABLE mips_attribute_table 1185169689Skan 1186169689Skan#undef TARGET_EXTRA_LIVE_ON_ENTRY 1187169689Skan#define TARGET_EXTRA_LIVE_ON_ENTRY mips_extra_live_on_entry 1188169689Skan 1189169689Skan#undef TARGET_MIN_ANCHOR_OFFSET 1190169689Skan#define TARGET_MIN_ANCHOR_OFFSET -32768 1191169689Skan#undef TARGET_MAX_ANCHOR_OFFSET 1192169689Skan#define TARGET_MAX_ANCHOR_OFFSET 32767 1193169689Skan#undef TARGET_USE_BLOCKS_FOR_CONSTANT_P 1194169689Skan#define TARGET_USE_BLOCKS_FOR_CONSTANT_P mips_use_blocks_for_constant_p 1195169689Skan#undef TARGET_USE_ANCHORS_FOR_SYMBOL_P 1196169689Skan#define TARGET_USE_ANCHORS_FOR_SYMBOL_P mips_use_anchors_for_symbol_p 1197169689Skan 1198169689Skanstruct gcc_target targetm = TARGET_INITIALIZER; 1199169689Skan 1200169689Skan/* Classify symbol X, which must be a SYMBOL_REF or a LABEL_REF. */ 1201169689Skan 1202169689Skanstatic enum mips_symbol_type 1203169689Skanmips_classify_symbol (rtx x) 1204169689Skan{ 1205169689Skan if (GET_CODE (x) == LABEL_REF) 1206169689Skan { 1207169689Skan if (TARGET_MIPS16) 1208169689Skan return SYMBOL_CONSTANT_POOL; 1209169689Skan if (TARGET_ABICALLS && !TARGET_ABSOLUTE_ABICALLS) 1210169689Skan return SYMBOL_GOT_LOCAL; 1211169689Skan return SYMBOL_GENERAL; 1212169689Skan } 1213169689Skan 1214169689Skan gcc_assert (GET_CODE (x) == SYMBOL_REF); 1215169689Skan 1216169689Skan if (SYMBOL_REF_TLS_MODEL (x)) 1217169689Skan return SYMBOL_TLS; 1218169689Skan 1219169689Skan if (CONSTANT_POOL_ADDRESS_P (x)) 1220169689Skan { 1221169689Skan if (TARGET_MIPS16) 1222169689Skan return SYMBOL_CONSTANT_POOL; 1223169689Skan 1224169689Skan if (GET_MODE_SIZE (get_pool_mode (x)) <= mips_section_threshold) 1225169689Skan return SYMBOL_SMALL_DATA; 1226169689Skan } 1227169689Skan 1228169689Skan /* Do not use small-data accesses for weak symbols; they may end up 1229169689Skan being zero. */ 1230169689Skan if (SYMBOL_REF_SMALL_P (x) 1231169689Skan && !SYMBOL_REF_WEAK (x)) 1232169689Skan return SYMBOL_SMALL_DATA; 1233169689Skan 1234169689Skan if (TARGET_ABICALLS) 1235169689Skan { 1236169689Skan if (SYMBOL_REF_DECL (x) == 0) 1237169689Skan { 1238169689Skan if (!SYMBOL_REF_LOCAL_P (x)) 1239169689Skan return SYMBOL_GOT_GLOBAL; 1240169689Skan } 1241169689Skan else 1242169689Skan { 1243169689Skan /* Don't use GOT accesses for locally-binding symbols if 1244169689Skan TARGET_ABSOLUTE_ABICALLS. Otherwise, there are three 1245169689Skan cases to consider: 1246169689Skan 1247169689Skan - o32 PIC (either with or without explicit relocs) 1248169689Skan - n32/n64 PIC without explicit relocs 1249169689Skan - n32/n64 PIC with explicit relocs 1250169689Skan 1251169689Skan In the first case, both local and global accesses will use an 1252169689Skan R_MIPS_GOT16 relocation. We must correctly predict which of 1253169689Skan the two semantics (local or global) the assembler and linker 1254169689Skan will apply. The choice doesn't depend on the symbol's 1255169689Skan visibility, so we deliberately ignore decl_visibility and 1256169689Skan binds_local_p here. 1257169689Skan 1258169689Skan In the second case, the assembler will not use R_MIPS_GOT16 1259169689Skan relocations, but it chooses between local and global accesses 1260169689Skan in the same way as for o32 PIC. 1261169689Skan 1262169689Skan In the third case we have more freedom since both forms of 1263169689Skan access will work for any kind of symbol. However, there seems 1264169689Skan little point in doing things differently. */ 1265169689Skan if (DECL_P (SYMBOL_REF_DECL (x)) 1266169689Skan && TREE_PUBLIC (SYMBOL_REF_DECL (x)) 1267169689Skan && !(TARGET_ABSOLUTE_ABICALLS 1268169689Skan && targetm.binds_local_p (SYMBOL_REF_DECL (x)))) 1269169689Skan return SYMBOL_GOT_GLOBAL; 1270169689Skan } 1271169689Skan 1272169689Skan if (!TARGET_ABSOLUTE_ABICALLS) 1273169689Skan return SYMBOL_GOT_LOCAL; 1274169689Skan } 1275169689Skan 1276169689Skan return SYMBOL_GENERAL; 1277169689Skan} 1278169689Skan 1279169689Skan 1280169689Skan/* Split X into a base and a constant offset, storing them in *BASE 1281169689Skan and *OFFSET respectively. */ 1282169689Skan 1283169689Skanstatic void 1284169689Skanmips_split_const (rtx x, rtx *base, HOST_WIDE_INT *offset) 1285169689Skan{ 1286169689Skan *offset = 0; 1287169689Skan 1288169689Skan if (GET_CODE (x) == CONST) 1289169689Skan { 1290169689Skan x = XEXP (x, 0); 1291169689Skan if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 1)) == CONST_INT) 1292169689Skan { 1293169689Skan *offset += INTVAL (XEXP (x, 1)); 1294169689Skan x = XEXP (x, 0); 1295169689Skan } 1296169689Skan } 1297169689Skan *base = x; 1298169689Skan} 1299169689Skan 1300234855Sgonzo/* Classify symbolic expression X, given that it appears in context 1301234855Sgonzo CONTEXT. */ 1302169689Skan 1303234855Sgonzostatic enum mips_symbol_type 1304234855Sgonzomips_classify_symbolic_expression (rtx x) 1305234855Sgonzo{ 1306234855Sgonzo HOST_WIDE_INT offset; 1307234855Sgonzo 1308234855Sgonzo mips_split_const (x, &x, &offset); 1309234855Sgonzo if (UNSPEC_ADDRESS_P (x)) 1310234855Sgonzo return UNSPEC_ADDRESS_TYPE (x); 1311234855Sgonzo 1312234855Sgonzo return mips_classify_symbol (x); 1313234855Sgonzo} 1314234855Sgonzo 1315169689Skan/* Return true if SYMBOL is a SYMBOL_REF and OFFSET + SYMBOL points 1316169689Skan to the same object as SYMBOL, or to the same object_block. */ 1317169689Skan 1318169689Skanstatic bool 1319169689Skanmips_offset_within_object_p (rtx symbol, HOST_WIDE_INT offset) 1320169689Skan{ 1321169689Skan if (GET_CODE (symbol) != SYMBOL_REF) 1322169689Skan return false; 1323169689Skan 1324169689Skan if (CONSTANT_POOL_ADDRESS_P (symbol) 1325169689Skan && offset >= 0 1326169689Skan && offset < (int) GET_MODE_SIZE (get_pool_mode (symbol))) 1327169689Skan return true; 1328169689Skan 1329169689Skan if (SYMBOL_REF_DECL (symbol) != 0 1330169689Skan && offset >= 0 1331169689Skan && offset < int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (symbol)))) 1332169689Skan return true; 1333169689Skan 1334169689Skan if (SYMBOL_REF_HAS_BLOCK_INFO_P (symbol) 1335169689Skan && SYMBOL_REF_BLOCK (symbol) 1336169689Skan && SYMBOL_REF_BLOCK_OFFSET (symbol) >= 0 1337169689Skan && ((unsigned HOST_WIDE_INT) offset + SYMBOL_REF_BLOCK_OFFSET (symbol) 1338169689Skan < (unsigned HOST_WIDE_INT) SYMBOL_REF_BLOCK (symbol)->size)) 1339169689Skan return true; 1340169689Skan 1341169689Skan return false; 1342169689Skan} 1343169689Skan 1344169689Skan 1345169689Skan/* Return true if X is a symbolic constant that can be calculated in 1346169689Skan the same way as a bare symbol. If it is, store the type of the 1347169689Skan symbol in *SYMBOL_TYPE. */ 1348169689Skan 1349169689Skanbool 1350169689Skanmips_symbolic_constant_p (rtx x, enum mips_symbol_type *symbol_type) 1351169689Skan{ 1352169689Skan HOST_WIDE_INT offset; 1353169689Skan 1354169689Skan mips_split_const (x, &x, &offset); 1355169689Skan if (UNSPEC_ADDRESS_P (x)) 1356169689Skan *symbol_type = UNSPEC_ADDRESS_TYPE (x); 1357169689Skan else if (GET_CODE (x) == SYMBOL_REF || GET_CODE (x) == LABEL_REF) 1358169689Skan { 1359169689Skan *symbol_type = mips_classify_symbol (x); 1360169689Skan if (*symbol_type == SYMBOL_TLS) 1361169689Skan return false; 1362169689Skan } 1363169689Skan else 1364169689Skan return false; 1365169689Skan 1366169689Skan if (offset == 0) 1367169689Skan return true; 1368169689Skan 1369169689Skan /* Check whether a nonzero offset is valid for the underlying 1370169689Skan relocations. */ 1371169689Skan switch (*symbol_type) 1372169689Skan { 1373169689Skan case SYMBOL_GENERAL: 1374169689Skan case SYMBOL_64_HIGH: 1375169689Skan case SYMBOL_64_MID: 1376169689Skan case SYMBOL_64_LOW: 1377169689Skan /* If the target has 64-bit pointers and the object file only 1378169689Skan supports 32-bit symbols, the values of those symbols will be 1379169689Skan sign-extended. In this case we can't allow an arbitrary offset 1380169689Skan in case the 32-bit value X + OFFSET has a different sign from X. */ 1381169689Skan if (Pmode == DImode && !ABI_HAS_64BIT_SYMBOLS) 1382169689Skan return mips_offset_within_object_p (x, offset); 1383169689Skan 1384169689Skan /* In other cases the relocations can handle any offset. */ 1385169689Skan return true; 1386169689Skan 1387169689Skan case SYMBOL_CONSTANT_POOL: 1388169689Skan /* Allow constant pool references to be converted to LABEL+CONSTANT. 1389169689Skan In this case, we no longer have access to the underlying constant, 1390169689Skan but the original symbol-based access was known to be valid. */ 1391169689Skan if (GET_CODE (x) == LABEL_REF) 1392169689Skan return true; 1393169689Skan 1394169689Skan /* Fall through. */ 1395169689Skan 1396169689Skan case SYMBOL_SMALL_DATA: 1397169689Skan /* Make sure that the offset refers to something within the 1398169689Skan underlying object. This should guarantee that the final 1399169689Skan PC- or GP-relative offset is within the 16-bit limit. */ 1400169689Skan return mips_offset_within_object_p (x, offset); 1401169689Skan 1402169689Skan case SYMBOL_GOT_LOCAL: 1403169689Skan case SYMBOL_GOTOFF_PAGE: 1404169689Skan /* The linker should provide enough local GOT entries for a 1405169689Skan 16-bit offset. Larger offsets may lead to GOT overflow. */ 1406169689Skan return SMALL_OPERAND (offset); 1407169689Skan 1408169689Skan case SYMBOL_GOT_GLOBAL: 1409169689Skan case SYMBOL_GOTOFF_GLOBAL: 1410169689Skan case SYMBOL_GOTOFF_CALL: 1411169689Skan case SYMBOL_GOTOFF_LOADGP: 1412169689Skan case SYMBOL_TLSGD: 1413169689Skan case SYMBOL_TLSLDM: 1414169689Skan case SYMBOL_DTPREL: 1415169689Skan case SYMBOL_TPREL: 1416169689Skan case SYMBOL_GOTTPREL: 1417169689Skan case SYMBOL_TLS: 1418169689Skan return false; 1419169689Skan } 1420169689Skan gcc_unreachable (); 1421169689Skan} 1422169689Skan 1423169689Skan 1424169689Skan/* This function is used to implement REG_MODE_OK_FOR_BASE_P. */ 1425169689Skan 1426169689Skanint 1427169689Skanmips_regno_mode_ok_for_base_p (int regno, enum machine_mode mode, int strict) 1428169689Skan{ 1429169689Skan if (regno >= FIRST_PSEUDO_REGISTER) 1430169689Skan { 1431169689Skan if (!strict) 1432169689Skan return true; 1433169689Skan regno = reg_renumber[regno]; 1434169689Skan } 1435169689Skan 1436169689Skan /* These fake registers will be eliminated to either the stack or 1437169689Skan hard frame pointer, both of which are usually valid base registers. 1438169689Skan Reload deals with the cases where the eliminated form isn't valid. */ 1439169689Skan if (regno == ARG_POINTER_REGNUM || regno == FRAME_POINTER_REGNUM) 1440169689Skan return true; 1441169689Skan 1442169689Skan /* In mips16 mode, the stack pointer can only address word and doubleword 1443169689Skan values, nothing smaller. There are two problems here: 1444169689Skan 1445169689Skan (a) Instantiating virtual registers can introduce new uses of the 1446169689Skan stack pointer. If these virtual registers are valid addresses, 1447169689Skan the stack pointer should be too. 1448169689Skan 1449169689Skan (b) Most uses of the stack pointer are not made explicit until 1450169689Skan FRAME_POINTER_REGNUM and ARG_POINTER_REGNUM have been eliminated. 1451169689Skan We don't know until that stage whether we'll be eliminating to the 1452169689Skan stack pointer (which needs the restriction) or the hard frame 1453169689Skan pointer (which doesn't). 1454169689Skan 1455169689Skan All in all, it seems more consistent to only enforce this restriction 1456169689Skan during and after reload. */ 1457169689Skan if (TARGET_MIPS16 && regno == STACK_POINTER_REGNUM) 1458169689Skan return !strict || GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8; 1459169689Skan 1460169689Skan return TARGET_MIPS16 ? M16_REG_P (regno) : GP_REG_P (regno); 1461169689Skan} 1462169689Skan 1463169689Skan 1464169689Skan/* Return true if X is a valid base register for the given mode. 1465169689Skan Allow only hard registers if STRICT. */ 1466169689Skan 1467169689Skanstatic bool 1468169689Skanmips_valid_base_register_p (rtx x, enum machine_mode mode, int strict) 1469169689Skan{ 1470169689Skan if (!strict && GET_CODE (x) == SUBREG) 1471169689Skan x = SUBREG_REG (x); 1472169689Skan 1473169689Skan return (REG_P (x) 1474169689Skan && mips_regno_mode_ok_for_base_p (REGNO (x), mode, strict)); 1475169689Skan} 1476169689Skan 1477169689Skan 1478169689Skan/* Return true if symbols of type SYMBOL_TYPE can directly address a value 1479169689Skan with mode MODE. This is used for both symbolic and LO_SUM addresses. */ 1480169689Skan 1481169689Skanstatic bool 1482169689Skanmips_symbolic_address_p (enum mips_symbol_type symbol_type, 1483169689Skan enum machine_mode mode) 1484169689Skan{ 1485169689Skan switch (symbol_type) 1486169689Skan { 1487169689Skan case SYMBOL_GENERAL: 1488169689Skan return !TARGET_MIPS16; 1489169689Skan 1490169689Skan case SYMBOL_SMALL_DATA: 1491169689Skan return true; 1492169689Skan 1493169689Skan case SYMBOL_CONSTANT_POOL: 1494169689Skan /* PC-relative addressing is only available for lw and ld. */ 1495169689Skan return GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8; 1496169689Skan 1497169689Skan case SYMBOL_GOT_LOCAL: 1498169689Skan return true; 1499169689Skan 1500169689Skan case SYMBOL_GOT_GLOBAL: 1501169689Skan /* The address will have to be loaded from the GOT first. */ 1502169689Skan return false; 1503169689Skan 1504169689Skan case SYMBOL_GOTOFF_PAGE: 1505169689Skan case SYMBOL_GOTOFF_GLOBAL: 1506169689Skan case SYMBOL_GOTOFF_CALL: 1507169689Skan case SYMBOL_GOTOFF_LOADGP: 1508169689Skan case SYMBOL_TLS: 1509169689Skan case SYMBOL_TLSGD: 1510169689Skan case SYMBOL_TLSLDM: 1511169689Skan case SYMBOL_DTPREL: 1512169689Skan case SYMBOL_GOTTPREL: 1513169689Skan case SYMBOL_TPREL: 1514169689Skan case SYMBOL_64_HIGH: 1515169689Skan case SYMBOL_64_MID: 1516169689Skan case SYMBOL_64_LOW: 1517169689Skan return true; 1518169689Skan } 1519169689Skan gcc_unreachable (); 1520169689Skan} 1521169689Skan 1522169689Skan 1523169689Skan/* Return true if X is a valid address for machine mode MODE. If it is, 1524169689Skan fill in INFO appropriately. STRICT is true if we should only accept 1525169689Skan hard base registers. */ 1526169689Skan 1527169689Skanstatic bool 1528169689Skanmips_classify_address (struct mips_address_info *info, rtx x, 1529169689Skan enum machine_mode mode, int strict) 1530169689Skan{ 1531169689Skan switch (GET_CODE (x)) 1532169689Skan { 1533169689Skan case REG: 1534169689Skan case SUBREG: 1535169689Skan info->type = ADDRESS_REG; 1536169689Skan info->reg = x; 1537169689Skan info->offset = const0_rtx; 1538169689Skan return mips_valid_base_register_p (info->reg, mode, strict); 1539169689Skan 1540169689Skan case PLUS: 1541169689Skan info->type = ADDRESS_REG; 1542169689Skan info->reg = XEXP (x, 0); 1543169689Skan info->offset = XEXP (x, 1); 1544169689Skan return (mips_valid_base_register_p (info->reg, mode, strict) 1545169689Skan && const_arith_operand (info->offset, VOIDmode)); 1546169689Skan 1547169689Skan case LO_SUM: 1548169689Skan info->type = ADDRESS_LO_SUM; 1549169689Skan info->reg = XEXP (x, 0); 1550169689Skan info->offset = XEXP (x, 1); 1551234855Sgonzo /* We have to trust the creator of the LO_SUM to do something vaguely 1552234855Sgonzo sane. Target-independent code that creates a LO_SUM should also 1553234855Sgonzo create and verify the matching HIGH. Target-independent code that 1554234855Sgonzo adds an offset to a LO_SUM must prove that the offset will not 1555234855Sgonzo induce a carry. Failure to do either of these things would be 1556234855Sgonzo a bug, and we are not required to check for it here. The MIPS 1557234855Sgonzo backend itself should only create LO_SUMs for valid symbolic 1558234855Sgonzo constants, with the high part being either a HIGH or a copy 1559234855Sgonzo of _gp. */ 1560234855Sgonzo info->symbol_type = mips_classify_symbolic_expression (info->offset); 1561169689Skan return (mips_valid_base_register_p (info->reg, mode, strict) 1562169689Skan && mips_symbolic_address_p (info->symbol_type, mode) 1563169689Skan && mips_lo_relocs[info->symbol_type] != 0); 1564169689Skan 1565169689Skan case CONST_INT: 1566169689Skan /* Small-integer addresses don't occur very often, but they 1567169689Skan are legitimate if $0 is a valid base register. */ 1568169689Skan info->type = ADDRESS_CONST_INT; 1569169689Skan return !TARGET_MIPS16 && SMALL_INT (x); 1570169689Skan 1571169689Skan case CONST: 1572169689Skan case LABEL_REF: 1573169689Skan case SYMBOL_REF: 1574169689Skan info->type = ADDRESS_SYMBOLIC; 1575169689Skan return (mips_symbolic_constant_p (x, &info->symbol_type) 1576169689Skan && mips_symbolic_address_p (info->symbol_type, mode) 1577169689Skan && !mips_split_p[info->symbol_type]); 1578169689Skan 1579169689Skan default: 1580169689Skan return false; 1581169689Skan } 1582169689Skan} 1583169689Skan 1584169689Skan/* Return true if X is a thread-local symbol. */ 1585169689Skan 1586169689Skanstatic bool 1587169689Skanmips_tls_operand_p (rtx x) 1588169689Skan{ 1589169689Skan return GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_TLS_MODEL (x) != 0; 1590169689Skan} 1591169689Skan 1592169689Skan/* Return true if X can not be forced into a constant pool. */ 1593169689Skan 1594169689Skanstatic int 1595169689Skanmips_tls_symbol_ref_1 (rtx *x, void *data ATTRIBUTE_UNUSED) 1596169689Skan{ 1597169689Skan return mips_tls_operand_p (*x); 1598169689Skan} 1599169689Skan 1600169689Skan/* Return true if X can not be forced into a constant pool. */ 1601169689Skan 1602169689Skanstatic bool 1603169689Skanmips_cannot_force_const_mem (rtx x) 1604169689Skan{ 1605169689Skan rtx base; 1606169689Skan HOST_WIDE_INT offset; 1607169689Skan 1608169689Skan if (!TARGET_MIPS16) 1609169689Skan { 1610169689Skan /* As an optimization, reject constants that mips_legitimize_move 1611169689Skan can expand inline. 1612169689Skan 1613169689Skan Suppose we have a multi-instruction sequence that loads constant C 1614169689Skan into register R. If R does not get allocated a hard register, and 1615169689Skan R is used in an operand that allows both registers and memory 1616169689Skan references, reload will consider forcing C into memory and using 1617169689Skan one of the instruction's memory alternatives. Returning false 1618169689Skan here will force it to use an input reload instead. */ 1619169689Skan if (GET_CODE (x) == CONST_INT) 1620169689Skan return true; 1621169689Skan 1622169689Skan mips_split_const (x, &base, &offset); 1623169689Skan if (symbolic_operand (base, VOIDmode) && SMALL_OPERAND (offset)) 1624169689Skan return true; 1625169689Skan } 1626169689Skan 1627169689Skan if (TARGET_HAVE_TLS && for_each_rtx (&x, &mips_tls_symbol_ref_1, 0)) 1628169689Skan return true; 1629169689Skan 1630169689Skan return false; 1631169689Skan} 1632169689Skan 1633169689Skan/* Implement TARGET_USE_BLOCKS_FOR_CONSTANT_P. MIPS16 uses per-function 1634169689Skan constant pools, but normal-mode code doesn't need to. */ 1635169689Skan 1636169689Skanstatic bool 1637169689Skanmips_use_blocks_for_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, 1638169689Skan rtx x ATTRIBUTE_UNUSED) 1639169689Skan{ 1640169689Skan return !TARGET_MIPS16; 1641169689Skan} 1642169689Skan 1643169689Skan/* Return the number of instructions needed to load a symbol of the 1644169689Skan given type into a register. If valid in an address, the same number 1645169689Skan of instructions are needed for loads and stores. Treat extended 1646169689Skan mips16 instructions as two instructions. */ 1647169689Skan 1648169689Skanstatic int 1649169689Skanmips_symbol_insns (enum mips_symbol_type type) 1650169689Skan{ 1651169689Skan switch (type) 1652169689Skan { 1653169689Skan case SYMBOL_GENERAL: 1654169689Skan /* In mips16 code, general symbols must be fetched from the 1655169689Skan constant pool. */ 1656169689Skan if (TARGET_MIPS16) 1657169689Skan return 0; 1658169689Skan 1659169689Skan /* When using 64-bit symbols, we need 5 preparatory instructions, 1660169689Skan such as: 1661169689Skan 1662169689Skan lui $at,%highest(symbol) 1663169689Skan daddiu $at,$at,%higher(symbol) 1664169689Skan dsll $at,$at,16 1665169689Skan daddiu $at,$at,%hi(symbol) 1666169689Skan dsll $at,$at,16 1667169689Skan 1668169689Skan The final address is then $at + %lo(symbol). With 32-bit 1669169689Skan symbols we just need a preparatory lui. */ 1670169689Skan return (ABI_HAS_64BIT_SYMBOLS ? 6 : 2); 1671169689Skan 1672169689Skan case SYMBOL_SMALL_DATA: 1673169689Skan return 1; 1674169689Skan 1675169689Skan case SYMBOL_CONSTANT_POOL: 1676169689Skan /* This case is for mips16 only. Assume we'll need an 1677169689Skan extended instruction. */ 1678169689Skan return 2; 1679169689Skan 1680169689Skan case SYMBOL_GOT_LOCAL: 1681169689Skan case SYMBOL_GOT_GLOBAL: 1682169689Skan /* Unless -funit-at-a-time is in effect, we can't be sure whether 1683169689Skan the local/global classification is accurate. See override_options 1684169689Skan for details. 1685169689Skan 1686169689Skan The worst cases are: 1687169689Skan 1688169689Skan (1) For local symbols when generating o32 or o64 code. The assembler 1689169689Skan will use: 1690169689Skan 1691169689Skan lw $at,%got(symbol) 1692169689Skan nop 1693169689Skan 1694169689Skan ...and the final address will be $at + %lo(symbol). 1695169689Skan 1696169689Skan (2) For global symbols when -mxgot. The assembler will use: 1697169689Skan 1698169689Skan lui $at,%got_hi(symbol) 1699169689Skan (d)addu $at,$at,$gp 1700169689Skan 1701169689Skan ...and the final address will be $at + %got_lo(symbol). */ 1702169689Skan return 3; 1703169689Skan 1704169689Skan case SYMBOL_GOTOFF_PAGE: 1705169689Skan case SYMBOL_GOTOFF_GLOBAL: 1706169689Skan case SYMBOL_GOTOFF_CALL: 1707169689Skan case SYMBOL_GOTOFF_LOADGP: 1708169689Skan case SYMBOL_64_HIGH: 1709169689Skan case SYMBOL_64_MID: 1710169689Skan case SYMBOL_64_LOW: 1711169689Skan case SYMBOL_TLSGD: 1712169689Skan case SYMBOL_TLSLDM: 1713169689Skan case SYMBOL_DTPREL: 1714169689Skan case SYMBOL_GOTTPREL: 1715169689Skan case SYMBOL_TPREL: 1716169689Skan /* Check whether the offset is a 16- or 32-bit value. */ 1717169689Skan return mips_split_p[type] ? 2 : 1; 1718169689Skan 1719169689Skan case SYMBOL_TLS: 1720169689Skan /* We don't treat a bare TLS symbol as a constant. */ 1721169689Skan return 0; 1722169689Skan } 1723169689Skan gcc_unreachable (); 1724169689Skan} 1725169689Skan 1726169689Skan/* Return true if X is a legitimate $sp-based address for mode MDOE. */ 1727169689Skan 1728169689Skanbool 1729169689Skanmips_stack_address_p (rtx x, enum machine_mode mode) 1730169689Skan{ 1731169689Skan struct mips_address_info addr; 1732169689Skan 1733169689Skan return (mips_classify_address (&addr, x, mode, false) 1734169689Skan && addr.type == ADDRESS_REG 1735169689Skan && addr.reg == stack_pointer_rtx); 1736169689Skan} 1737169689Skan 1738169689Skan/* Return true if a value at OFFSET bytes from BASE can be accessed 1739169689Skan using an unextended mips16 instruction. MODE is the mode of the 1740169689Skan value. 1741169689Skan 1742169689Skan Usually the offset in an unextended instruction is a 5-bit field. 1743169689Skan The offset is unsigned and shifted left once for HIs, twice 1744169689Skan for SIs, and so on. An exception is SImode accesses off the 1745169689Skan stack pointer, which have an 8-bit immediate field. */ 1746169689Skan 1747169689Skanstatic bool 1748169689Skanmips16_unextended_reference_p (enum machine_mode mode, rtx base, rtx offset) 1749169689Skan{ 1750169689Skan if (TARGET_MIPS16 1751169689Skan && GET_CODE (offset) == CONST_INT 1752169689Skan && INTVAL (offset) >= 0 1753169689Skan && (INTVAL (offset) & (GET_MODE_SIZE (mode) - 1)) == 0) 1754169689Skan { 1755169689Skan if (GET_MODE_SIZE (mode) == 4 && base == stack_pointer_rtx) 1756169689Skan return INTVAL (offset) < 256 * GET_MODE_SIZE (mode); 1757169689Skan return INTVAL (offset) < 32 * GET_MODE_SIZE (mode); 1758169689Skan } 1759169689Skan return false; 1760169689Skan} 1761169689Skan 1762169689Skan 1763169689Skan/* Return the number of instructions needed to load or store a value 1764169689Skan of mode MODE at X. Return 0 if X isn't valid for MODE. 1765169689Skan 1766169689Skan For mips16 code, count extended instructions as two instructions. */ 1767169689Skan 1768169689Skanint 1769169689Skanmips_address_insns (rtx x, enum machine_mode mode) 1770169689Skan{ 1771169689Skan struct mips_address_info addr; 1772169689Skan int factor; 1773169689Skan 1774169689Skan if (mode == BLKmode) 1775169689Skan /* BLKmode is used for single unaligned loads and stores. */ 1776169689Skan factor = 1; 1777169689Skan else 1778169689Skan /* Each word of a multi-word value will be accessed individually. */ 1779169689Skan factor = (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; 1780169689Skan 1781169689Skan if (mips_classify_address (&addr, x, mode, false)) 1782169689Skan switch (addr.type) 1783169689Skan { 1784169689Skan case ADDRESS_REG: 1785169689Skan if (TARGET_MIPS16 1786169689Skan && !mips16_unextended_reference_p (mode, addr.reg, addr.offset)) 1787169689Skan return factor * 2; 1788169689Skan return factor; 1789169689Skan 1790169689Skan case ADDRESS_LO_SUM: 1791169689Skan return (TARGET_MIPS16 ? factor * 2 : factor); 1792169689Skan 1793169689Skan case ADDRESS_CONST_INT: 1794169689Skan return factor; 1795169689Skan 1796169689Skan case ADDRESS_SYMBOLIC: 1797169689Skan return factor * mips_symbol_insns (addr.symbol_type); 1798169689Skan } 1799169689Skan return 0; 1800169689Skan} 1801169689Skan 1802169689Skan 1803169689Skan/* Likewise for constant X. */ 1804169689Skan 1805169689Skanint 1806169689Skanmips_const_insns (rtx x) 1807169689Skan{ 1808169689Skan struct mips_integer_op codes[MIPS_MAX_INTEGER_OPS]; 1809169689Skan enum mips_symbol_type symbol_type; 1810169689Skan HOST_WIDE_INT offset; 1811169689Skan 1812169689Skan switch (GET_CODE (x)) 1813169689Skan { 1814169689Skan case HIGH: 1815169689Skan if (TARGET_MIPS16 1816169689Skan || !mips_symbolic_constant_p (XEXP (x, 0), &symbol_type) 1817169689Skan || !mips_split_p[symbol_type]) 1818169689Skan return 0; 1819169689Skan 1820169689Skan return 1; 1821169689Skan 1822169689Skan case CONST_INT: 1823169689Skan if (TARGET_MIPS16) 1824169689Skan /* Unsigned 8-bit constants can be loaded using an unextended 1825169689Skan LI instruction. Unsigned 16-bit constants can be loaded 1826169689Skan using an extended LI. Negative constants must be loaded 1827169689Skan using LI and then negated. */ 1828169689Skan return (INTVAL (x) >= 0 && INTVAL (x) < 256 ? 1 1829169689Skan : SMALL_OPERAND_UNSIGNED (INTVAL (x)) ? 2 1830169689Skan : INTVAL (x) > -256 && INTVAL (x) < 0 ? 2 1831169689Skan : SMALL_OPERAND_UNSIGNED (-INTVAL (x)) ? 3 1832169689Skan : 0); 1833169689Skan 1834169689Skan return mips_build_integer (codes, INTVAL (x)); 1835169689Skan 1836169689Skan case CONST_DOUBLE: 1837169689Skan case CONST_VECTOR: 1838169689Skan return (!TARGET_MIPS16 && x == CONST0_RTX (GET_MODE (x)) ? 1 : 0); 1839169689Skan 1840169689Skan case CONST: 1841169689Skan if (CONST_GP_P (x)) 1842169689Skan return 1; 1843169689Skan 1844169689Skan /* See if we can refer to X directly. */ 1845169689Skan if (mips_symbolic_constant_p (x, &symbol_type)) 1846169689Skan return mips_symbol_insns (symbol_type); 1847169689Skan 1848169689Skan /* Otherwise try splitting the constant into a base and offset. 1849169689Skan 16-bit offsets can be added using an extra addiu. Larger offsets 1850169689Skan must be calculated separately and then added to the base. */ 1851169689Skan mips_split_const (x, &x, &offset); 1852169689Skan if (offset != 0) 1853169689Skan { 1854169689Skan int n = mips_const_insns (x); 1855169689Skan if (n != 0) 1856169689Skan { 1857169689Skan if (SMALL_OPERAND (offset)) 1858169689Skan return n + 1; 1859169689Skan else 1860169689Skan return n + 1 + mips_build_integer (codes, offset); 1861169689Skan } 1862169689Skan } 1863169689Skan return 0; 1864169689Skan 1865169689Skan case SYMBOL_REF: 1866169689Skan case LABEL_REF: 1867169689Skan return mips_symbol_insns (mips_classify_symbol (x)); 1868169689Skan 1869169689Skan default: 1870169689Skan return 0; 1871169689Skan } 1872169689Skan} 1873169689Skan 1874169689Skan 1875169689Skan/* Return the number of instructions needed for memory reference X. 1876169689Skan Count extended mips16 instructions as two instructions. */ 1877169689Skan 1878169689Skanint 1879169689Skanmips_fetch_insns (rtx x) 1880169689Skan{ 1881169689Skan gcc_assert (MEM_P (x)); 1882169689Skan return mips_address_insns (XEXP (x, 0), GET_MODE (x)); 1883169689Skan} 1884169689Skan 1885169689Skan 1886169689Skan/* Return the number of instructions needed for an integer division. */ 1887169689Skan 1888169689Skanint 1889169689Skanmips_idiv_insns (void) 1890169689Skan{ 1891169689Skan int count; 1892169689Skan 1893169689Skan count = 1; 1894169689Skan if (TARGET_CHECK_ZERO_DIV) 1895169689Skan { 1896169689Skan if (GENERATE_DIVIDE_TRAPS) 1897169689Skan count++; 1898169689Skan else 1899169689Skan count += 2; 1900169689Skan } 1901169689Skan 1902169689Skan if (TARGET_FIX_R4000 || TARGET_FIX_R4400) 1903169689Skan count++; 1904169689Skan return count; 1905169689Skan} 1906169689Skan 1907169689Skan/* This function is used to implement GO_IF_LEGITIMATE_ADDRESS. It 1908169689Skan returns a nonzero value if X is a legitimate address for a memory 1909169689Skan operand of the indicated MODE. STRICT is nonzero if this function 1910169689Skan is called during reload. */ 1911169689Skan 1912169689Skanbool 1913169689Skanmips_legitimate_address_p (enum machine_mode mode, rtx x, int strict) 1914169689Skan{ 1915169689Skan struct mips_address_info addr; 1916169689Skan 1917169689Skan return mips_classify_address (&addr, x, mode, strict); 1918169689Skan} 1919169689Skan 1920169689Skan 1921169689Skan/* Copy VALUE to a register and return that register. If new psuedos 1922169689Skan are allowed, copy it into a new register, otherwise use DEST. */ 1923169689Skan 1924169689Skanstatic rtx 1925169689Skanmips_force_temporary (rtx dest, rtx value) 1926169689Skan{ 1927169689Skan if (!no_new_pseudos) 1928169689Skan return force_reg (Pmode, value); 1929169689Skan else 1930169689Skan { 1931169689Skan emit_move_insn (copy_rtx (dest), value); 1932169689Skan return dest; 1933169689Skan } 1934169689Skan} 1935169689Skan 1936169689Skan 1937169689Skan/* Return a LO_SUM expression for ADDR. TEMP is as for mips_force_temporary 1938169689Skan and is used to load the high part into a register. */ 1939169689Skan 1940169689Skanrtx 1941169689Skanmips_split_symbol (rtx temp, rtx addr) 1942169689Skan{ 1943169689Skan rtx high; 1944169689Skan 1945169689Skan if (TARGET_MIPS16) 1946169689Skan high = mips16_gp_pseudo_reg (); 1947169689Skan else 1948169689Skan high = mips_force_temporary (temp, gen_rtx_HIGH (Pmode, copy_rtx (addr))); 1949169689Skan return gen_rtx_LO_SUM (Pmode, high, addr); 1950169689Skan} 1951169689Skan 1952169689Skan 1953169689Skan/* Return an UNSPEC address with underlying address ADDRESS and symbol 1954169689Skan type SYMBOL_TYPE. */ 1955169689Skan 1956169689Skanrtx 1957169689Skanmips_unspec_address (rtx address, enum mips_symbol_type symbol_type) 1958169689Skan{ 1959169689Skan rtx base; 1960169689Skan HOST_WIDE_INT offset; 1961169689Skan 1962169689Skan mips_split_const (address, &base, &offset); 1963169689Skan base = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, base), 1964169689Skan UNSPEC_ADDRESS_FIRST + symbol_type); 1965169689Skan return plus_constant (gen_rtx_CONST (Pmode, base), offset); 1966169689Skan} 1967169689Skan 1968169689Skan 1969169689Skan/* If mips_unspec_address (ADDR, SYMBOL_TYPE) is a 32-bit value, add the 1970169689Skan high part to BASE and return the result. Just return BASE otherwise. 1971169689Skan TEMP is available as a temporary register if needed. 1972169689Skan 1973169689Skan The returned expression can be used as the first operand to a LO_SUM. */ 1974169689Skan 1975169689Skanstatic rtx 1976169689Skanmips_unspec_offset_high (rtx temp, rtx base, rtx addr, 1977169689Skan enum mips_symbol_type symbol_type) 1978169689Skan{ 1979169689Skan if (mips_split_p[symbol_type]) 1980169689Skan { 1981169689Skan addr = gen_rtx_HIGH (Pmode, mips_unspec_address (addr, symbol_type)); 1982169689Skan addr = mips_force_temporary (temp, addr); 1983169689Skan return mips_force_temporary (temp, gen_rtx_PLUS (Pmode, addr, base)); 1984169689Skan } 1985169689Skan return base; 1986169689Skan} 1987169689Skan 1988169689Skan 1989169689Skan/* Return a legitimate address for REG + OFFSET. TEMP is as for 1990169689Skan mips_force_temporary; it is only needed when OFFSET is not a 1991169689Skan SMALL_OPERAND. */ 1992169689Skan 1993169689Skanstatic rtx 1994169689Skanmips_add_offset (rtx temp, rtx reg, HOST_WIDE_INT offset) 1995169689Skan{ 1996169689Skan if (!SMALL_OPERAND (offset)) 1997169689Skan { 1998169689Skan rtx high; 1999169689Skan if (TARGET_MIPS16) 2000169689Skan { 2001169689Skan /* Load the full offset into a register so that we can use 2002169689Skan an unextended instruction for the address itself. */ 2003169689Skan high = GEN_INT (offset); 2004169689Skan offset = 0; 2005169689Skan } 2006169689Skan else 2007169689Skan { 2008169689Skan /* Leave OFFSET as a 16-bit offset and put the excess in HIGH. */ 2009169689Skan high = GEN_INT (CONST_HIGH_PART (offset)); 2010169689Skan offset = CONST_LOW_PART (offset); 2011169689Skan } 2012169689Skan high = mips_force_temporary (temp, high); 2013169689Skan reg = mips_force_temporary (temp, gen_rtx_PLUS (Pmode, high, reg)); 2014169689Skan } 2015169689Skan return plus_constant (reg, offset); 2016169689Skan} 2017169689Skan 2018169689Skan/* Emit a call to __tls_get_addr. SYM is the TLS symbol we are 2019169689Skan referencing, and TYPE is the symbol type to use (either global 2020169689Skan dynamic or local dynamic). V0 is an RTX for the return value 2021169689Skan location. The entire insn sequence is returned. */ 2022169689Skan 2023169689Skanstatic GTY(()) rtx mips_tls_symbol; 2024169689Skan 2025169689Skanstatic rtx 2026169689Skanmips_call_tls_get_addr (rtx sym, enum mips_symbol_type type, rtx v0) 2027169689Skan{ 2028169689Skan rtx insn, loc, tga, a0; 2029169689Skan 2030169689Skan a0 = gen_rtx_REG (Pmode, GP_ARG_FIRST); 2031169689Skan 2032169689Skan if (!mips_tls_symbol) 2033169689Skan mips_tls_symbol = init_one_libfunc ("__tls_get_addr"); 2034169689Skan 2035169689Skan loc = mips_unspec_address (sym, type); 2036169689Skan 2037169689Skan start_sequence (); 2038169689Skan 2039169689Skan emit_insn (gen_rtx_SET (Pmode, a0, 2040169689Skan gen_rtx_LO_SUM (Pmode, pic_offset_table_rtx, loc))); 2041169689Skan tga = gen_rtx_MEM (Pmode, mips_tls_symbol); 2042169689Skan insn = emit_call_insn (gen_call_value (v0, tga, const0_rtx, const0_rtx)); 2043169689Skan CONST_OR_PURE_CALL_P (insn) = 1; 2044169689Skan use_reg (&CALL_INSN_FUNCTION_USAGE (insn), v0); 2045169689Skan use_reg (&CALL_INSN_FUNCTION_USAGE (insn), a0); 2046169689Skan insn = get_insns (); 2047169689Skan 2048169689Skan end_sequence (); 2049169689Skan 2050169689Skan return insn; 2051169689Skan} 2052169689Skan 2053169689Skan/* Generate the code to access LOC, a thread local SYMBOL_REF. The 2054169689Skan return value will be a valid address and move_operand (either a REG 2055169689Skan or a LO_SUM). */ 2056169689Skan 2057169689Skanstatic rtx 2058169689Skanmips_legitimize_tls_address (rtx loc) 2059169689Skan{ 2060169689Skan rtx dest, insn, v0, v1, tmp1, tmp2, eqv; 2061169689Skan enum tls_model model; 2062169689Skan 2063169689Skan v0 = gen_rtx_REG (Pmode, GP_RETURN); 2064169689Skan v1 = gen_rtx_REG (Pmode, GP_RETURN + 1); 2065169689Skan 2066169689Skan model = SYMBOL_REF_TLS_MODEL (loc); 2067169689Skan /* Only TARGET_ABICALLS code can have more than one module; other 2068169689Skan code must be be static and should not use a GOT. All TLS models 2069169689Skan reduce to local exec in this situation. */ 2070169689Skan if (!TARGET_ABICALLS) 2071169689Skan model = TLS_MODEL_LOCAL_EXEC; 2072169689Skan 2073169689Skan switch (model) 2074169689Skan { 2075169689Skan case TLS_MODEL_GLOBAL_DYNAMIC: 2076169689Skan insn = mips_call_tls_get_addr (loc, SYMBOL_TLSGD, v0); 2077169689Skan dest = gen_reg_rtx (Pmode); 2078169689Skan emit_libcall_block (insn, dest, v0, loc); 2079169689Skan break; 2080169689Skan 2081169689Skan case TLS_MODEL_LOCAL_DYNAMIC: 2082169689Skan insn = mips_call_tls_get_addr (loc, SYMBOL_TLSLDM, v0); 2083169689Skan tmp1 = gen_reg_rtx (Pmode); 2084169689Skan 2085169689Skan /* Attach a unique REG_EQUIV, to allow the RTL optimizers to 2086169689Skan share the LDM result with other LD model accesses. */ 2087169689Skan eqv = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx), 2088169689Skan UNSPEC_TLS_LDM); 2089169689Skan emit_libcall_block (insn, tmp1, v0, eqv); 2090169689Skan 2091169689Skan tmp2 = mips_unspec_offset_high (NULL, tmp1, loc, SYMBOL_DTPREL); 2092169689Skan dest = gen_rtx_LO_SUM (Pmode, tmp2, 2093169689Skan mips_unspec_address (loc, SYMBOL_DTPREL)); 2094169689Skan break; 2095169689Skan 2096169689Skan case TLS_MODEL_INITIAL_EXEC: 2097169689Skan tmp1 = gen_reg_rtx (Pmode); 2098169689Skan tmp2 = mips_unspec_address (loc, SYMBOL_GOTTPREL); 2099169689Skan if (Pmode == DImode) 2100169689Skan { 2101169689Skan emit_insn (gen_tls_get_tp_di (v1)); 2102169689Skan emit_insn (gen_load_gotdi (tmp1, pic_offset_table_rtx, tmp2)); 2103169689Skan } 2104169689Skan else 2105169689Skan { 2106169689Skan emit_insn (gen_tls_get_tp_si (v1)); 2107169689Skan emit_insn (gen_load_gotsi (tmp1, pic_offset_table_rtx, tmp2)); 2108169689Skan } 2109169689Skan dest = gen_reg_rtx (Pmode); 2110169689Skan emit_insn (gen_add3_insn (dest, tmp1, v1)); 2111169689Skan break; 2112169689Skan 2113169689Skan case TLS_MODEL_LOCAL_EXEC: 2114169689Skan if (Pmode == DImode) 2115169689Skan emit_insn (gen_tls_get_tp_di (v1)); 2116169689Skan else 2117169689Skan emit_insn (gen_tls_get_tp_si (v1)); 2118169689Skan 2119169689Skan tmp1 = mips_unspec_offset_high (NULL, v1, loc, SYMBOL_TPREL); 2120169689Skan dest = gen_rtx_LO_SUM (Pmode, tmp1, 2121169689Skan mips_unspec_address (loc, SYMBOL_TPREL)); 2122169689Skan break; 2123169689Skan 2124169689Skan default: 2125169689Skan gcc_unreachable (); 2126169689Skan } 2127169689Skan 2128169689Skan return dest; 2129169689Skan} 2130169689Skan 2131169689Skan/* This function is used to implement LEGITIMIZE_ADDRESS. If *XLOC can 2132169689Skan be legitimized in a way that the generic machinery might not expect, 2133169689Skan put the new address in *XLOC and return true. MODE is the mode of 2134169689Skan the memory being accessed. */ 2135169689Skan 2136169689Skanbool 2137169689Skanmips_legitimize_address (rtx *xloc, enum machine_mode mode) 2138169689Skan{ 2139169689Skan enum mips_symbol_type symbol_type; 2140169689Skan 2141169689Skan if (mips_tls_operand_p (*xloc)) 2142169689Skan { 2143169689Skan *xloc = mips_legitimize_tls_address (*xloc); 2144169689Skan return true; 2145169689Skan } 2146169689Skan 2147169689Skan /* See if the address can split into a high part and a LO_SUM. */ 2148169689Skan if (mips_symbolic_constant_p (*xloc, &symbol_type) 2149169689Skan && mips_symbolic_address_p (symbol_type, mode) 2150169689Skan && mips_split_p[symbol_type]) 2151169689Skan { 2152169689Skan *xloc = mips_split_symbol (0, *xloc); 2153169689Skan return true; 2154169689Skan } 2155169689Skan 2156169689Skan if (GET_CODE (*xloc) == PLUS && GET_CODE (XEXP (*xloc, 1)) == CONST_INT) 2157169689Skan { 2158169689Skan /* Handle REG + CONSTANT using mips_add_offset. */ 2159169689Skan rtx reg; 2160169689Skan 2161169689Skan reg = XEXP (*xloc, 0); 2162169689Skan if (!mips_valid_base_register_p (reg, mode, 0)) 2163169689Skan reg = copy_to_mode_reg (Pmode, reg); 2164169689Skan *xloc = mips_add_offset (0, reg, INTVAL (XEXP (*xloc, 1))); 2165169689Skan return true; 2166169689Skan } 2167169689Skan 2168169689Skan return false; 2169169689Skan} 2170169689Skan 2171169689Skan 2172169689Skan/* Subroutine of mips_build_integer (with the same interface). 2173169689Skan Assume that the final action in the sequence should be a left shift. */ 2174169689Skan 2175169689Skanstatic unsigned int 2176169689Skanmips_build_shift (struct mips_integer_op *codes, HOST_WIDE_INT value) 2177169689Skan{ 2178169689Skan unsigned int i, shift; 2179169689Skan 2180169689Skan /* Shift VALUE right until its lowest bit is set. Shift arithmetically 2181169689Skan since signed numbers are easier to load than unsigned ones. */ 2182169689Skan shift = 0; 2183169689Skan while ((value & 1) == 0) 2184169689Skan value /= 2, shift++; 2185169689Skan 2186169689Skan i = mips_build_integer (codes, value); 2187169689Skan codes[i].code = ASHIFT; 2188169689Skan codes[i].value = shift; 2189169689Skan return i + 1; 2190169689Skan} 2191169689Skan 2192169689Skan 2193169689Skan/* As for mips_build_shift, but assume that the final action will be 2194169689Skan an IOR or PLUS operation. */ 2195169689Skan 2196169689Skanstatic unsigned int 2197169689Skanmips_build_lower (struct mips_integer_op *codes, unsigned HOST_WIDE_INT value) 2198169689Skan{ 2199169689Skan unsigned HOST_WIDE_INT high; 2200169689Skan unsigned int i; 2201169689Skan 2202169689Skan high = value & ~(unsigned HOST_WIDE_INT) 0xffff; 2203169689Skan if (!LUI_OPERAND (high) && (value & 0x18000) == 0x18000) 2204169689Skan { 2205169689Skan /* The constant is too complex to load with a simple lui/ori pair 2206169689Skan so our goal is to clear as many trailing zeros as possible. 2207169689Skan In this case, we know bit 16 is set and that the low 16 bits 2208169689Skan form a negative number. If we subtract that number from VALUE, 2209169689Skan we will clear at least the lowest 17 bits, maybe more. */ 2210169689Skan i = mips_build_integer (codes, CONST_HIGH_PART (value)); 2211169689Skan codes[i].code = PLUS; 2212169689Skan codes[i].value = CONST_LOW_PART (value); 2213169689Skan } 2214169689Skan else 2215169689Skan { 2216169689Skan i = mips_build_integer (codes, high); 2217169689Skan codes[i].code = IOR; 2218169689Skan codes[i].value = value & 0xffff; 2219169689Skan } 2220169689Skan return i + 1; 2221169689Skan} 2222169689Skan 2223169689Skan 2224169689Skan/* Fill CODES with a sequence of rtl operations to load VALUE. 2225169689Skan Return the number of operations needed. */ 2226169689Skan 2227169689Skanstatic unsigned int 2228169689Skanmips_build_integer (struct mips_integer_op *codes, 2229169689Skan unsigned HOST_WIDE_INT value) 2230169689Skan{ 2231169689Skan if (SMALL_OPERAND (value) 2232169689Skan || SMALL_OPERAND_UNSIGNED (value) 2233169689Skan || LUI_OPERAND (value)) 2234169689Skan { 2235169689Skan /* The value can be loaded with a single instruction. */ 2236169689Skan codes[0].code = UNKNOWN; 2237169689Skan codes[0].value = value; 2238169689Skan return 1; 2239169689Skan } 2240169689Skan else if ((value & 1) != 0 || LUI_OPERAND (CONST_HIGH_PART (value))) 2241169689Skan { 2242169689Skan /* Either the constant is a simple LUI/ORI combination or its 2243169689Skan lowest bit is set. We don't want to shift in this case. */ 2244169689Skan return mips_build_lower (codes, value); 2245169689Skan } 2246169689Skan else if ((value & 0xffff) == 0) 2247169689Skan { 2248169689Skan /* The constant will need at least three actions. The lowest 2249169689Skan 16 bits are clear, so the final action will be a shift. */ 2250169689Skan return mips_build_shift (codes, value); 2251169689Skan } 2252169689Skan else 2253169689Skan { 2254169689Skan /* The final action could be a shift, add or inclusive OR. 2255169689Skan Rather than use a complex condition to select the best 2256169689Skan approach, try both mips_build_shift and mips_build_lower 2257169689Skan and pick the one that gives the shortest sequence. 2258169689Skan Note that this case is only used once per constant. */ 2259169689Skan struct mips_integer_op alt_codes[MIPS_MAX_INTEGER_OPS]; 2260169689Skan unsigned int cost, alt_cost; 2261169689Skan 2262169689Skan cost = mips_build_shift (codes, value); 2263169689Skan alt_cost = mips_build_lower (alt_codes, value); 2264169689Skan if (alt_cost < cost) 2265169689Skan { 2266169689Skan memcpy (codes, alt_codes, alt_cost * sizeof (codes[0])); 2267169689Skan cost = alt_cost; 2268169689Skan } 2269169689Skan return cost; 2270169689Skan } 2271169689Skan} 2272169689Skan 2273169689Skan 2274169689Skan/* Load VALUE into DEST, using TEMP as a temporary register if need be. */ 2275169689Skan 2276169689Skanvoid 2277169689Skanmips_move_integer (rtx dest, rtx temp, unsigned HOST_WIDE_INT value) 2278169689Skan{ 2279169689Skan struct mips_integer_op codes[MIPS_MAX_INTEGER_OPS]; 2280169689Skan enum machine_mode mode; 2281169689Skan unsigned int i, cost; 2282169689Skan rtx x; 2283169689Skan 2284169689Skan mode = GET_MODE (dest); 2285169689Skan cost = mips_build_integer (codes, value); 2286169689Skan 2287169689Skan /* Apply each binary operation to X. Invariant: X is a legitimate 2288169689Skan source operand for a SET pattern. */ 2289169689Skan x = GEN_INT (codes[0].value); 2290169689Skan for (i = 1; i < cost; i++) 2291169689Skan { 2292169689Skan if (no_new_pseudos) 2293169689Skan { 2294169689Skan emit_insn (gen_rtx_SET (VOIDmode, temp, x)); 2295169689Skan x = temp; 2296169689Skan } 2297169689Skan else 2298169689Skan x = force_reg (mode, x); 2299169689Skan x = gen_rtx_fmt_ee (codes[i].code, mode, x, GEN_INT (codes[i].value)); 2300169689Skan } 2301169689Skan 2302169689Skan emit_insn (gen_rtx_SET (VOIDmode, dest, x)); 2303169689Skan} 2304169689Skan 2305169689Skan 2306169689Skan/* Subroutine of mips_legitimize_move. Move constant SRC into register 2307169689Skan DEST given that SRC satisfies immediate_operand but doesn't satisfy 2308169689Skan move_operand. */ 2309169689Skan 2310169689Skanstatic void 2311169689Skanmips_legitimize_const_move (enum machine_mode mode, rtx dest, rtx src) 2312169689Skan{ 2313169689Skan rtx base; 2314169689Skan HOST_WIDE_INT offset; 2315169689Skan 2316169689Skan /* Split moves of big integers into smaller pieces. */ 2317169689Skan if (splittable_const_int_operand (src, mode)) 2318169689Skan { 2319169689Skan mips_move_integer (dest, dest, INTVAL (src)); 2320169689Skan return; 2321169689Skan } 2322169689Skan 2323169689Skan /* Split moves of symbolic constants into high/low pairs. */ 2324169689Skan if (splittable_symbolic_operand (src, mode)) 2325169689Skan { 2326169689Skan emit_insn (gen_rtx_SET (VOIDmode, dest, mips_split_symbol (dest, src))); 2327169689Skan return; 2328169689Skan } 2329169689Skan 2330169689Skan if (mips_tls_operand_p (src)) 2331169689Skan { 2332169689Skan emit_move_insn (dest, mips_legitimize_tls_address (src)); 2333169689Skan return; 2334169689Skan } 2335169689Skan 2336169689Skan /* If we have (const (plus symbol offset)), load the symbol first 2337169689Skan and then add in the offset. This is usually better than forcing 2338169689Skan the constant into memory, at least in non-mips16 code. */ 2339169689Skan mips_split_const (src, &base, &offset); 2340169689Skan if (!TARGET_MIPS16 2341169689Skan && offset != 0 2342169689Skan && (!no_new_pseudos || SMALL_OPERAND (offset))) 2343169689Skan { 2344169689Skan base = mips_force_temporary (dest, base); 2345169689Skan emit_move_insn (dest, mips_add_offset (0, base, offset)); 2346169689Skan return; 2347169689Skan } 2348169689Skan 2349169689Skan src = force_const_mem (mode, src); 2350169689Skan 2351169689Skan /* When using explicit relocs, constant pool references are sometimes 2352169689Skan not legitimate addresses. */ 2353169689Skan if (!memory_operand (src, VOIDmode)) 2354169689Skan src = replace_equiv_address (src, mips_split_symbol (dest, XEXP (src, 0))); 2355169689Skan emit_move_insn (dest, src); 2356169689Skan} 2357169689Skan 2358169689Skan 2359169689Skan/* If (set DEST SRC) is not a valid instruction, emit an equivalent 2360169689Skan sequence that is valid. */ 2361169689Skan 2362169689Skanbool 2363169689Skanmips_legitimize_move (enum machine_mode mode, rtx dest, rtx src) 2364169689Skan{ 2365169689Skan if (!register_operand (dest, mode) && !reg_or_0_operand (src, mode)) 2366169689Skan { 2367169689Skan emit_move_insn (dest, force_reg (mode, src)); 2368169689Skan return true; 2369169689Skan } 2370169689Skan 2371169689Skan /* Check for individual, fully-reloaded mflo and mfhi instructions. */ 2372169689Skan if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD 2373169689Skan && REG_P (src) && MD_REG_P (REGNO (src)) 2374169689Skan && REG_P (dest) && GP_REG_P (REGNO (dest))) 2375169689Skan { 2376169689Skan int other_regno = REGNO (src) == HI_REGNUM ? LO_REGNUM : HI_REGNUM; 2377169689Skan if (GET_MODE_SIZE (mode) <= 4) 2378169689Skan emit_insn (gen_mfhilo_si (gen_rtx_REG (SImode, REGNO (dest)), 2379169689Skan gen_rtx_REG (SImode, REGNO (src)), 2380169689Skan gen_rtx_REG (SImode, other_regno))); 2381169689Skan else 2382169689Skan emit_insn (gen_mfhilo_di (gen_rtx_REG (DImode, REGNO (dest)), 2383169689Skan gen_rtx_REG (DImode, REGNO (src)), 2384169689Skan gen_rtx_REG (DImode, other_regno))); 2385169689Skan return true; 2386169689Skan } 2387169689Skan 2388169689Skan /* We need to deal with constants that would be legitimate 2389169689Skan immediate_operands but not legitimate move_operands. */ 2390169689Skan if (CONSTANT_P (src) && !move_operand (src, mode)) 2391169689Skan { 2392169689Skan mips_legitimize_const_move (mode, dest, src); 2393169689Skan set_unique_reg_note (get_last_insn (), REG_EQUAL, copy_rtx (src)); 2394169689Skan return true; 2395169689Skan } 2396169689Skan return false; 2397169689Skan} 2398169689Skan 2399169689Skan/* We need a lot of little routines to check constant values on the 2400169689Skan mips16. These are used to figure out how long the instruction will 2401169689Skan be. It would be much better to do this using constraints, but 2402169689Skan there aren't nearly enough letters available. */ 2403169689Skan 2404169689Skanstatic int 2405169689Skanm16_check_op (rtx op, int low, int high, int mask) 2406169689Skan{ 2407169689Skan return (GET_CODE (op) == CONST_INT 2408169689Skan && INTVAL (op) >= low 2409169689Skan && INTVAL (op) <= high 2410169689Skan && (INTVAL (op) & mask) == 0); 2411169689Skan} 2412169689Skan 2413169689Skanint 2414169689Skanm16_uimm3_b (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) 2415169689Skan{ 2416169689Skan return m16_check_op (op, 0x1, 0x8, 0); 2417169689Skan} 2418169689Skan 2419169689Skanint 2420169689Skanm16_simm4_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) 2421169689Skan{ 2422169689Skan return m16_check_op (op, - 0x8, 0x7, 0); 2423169689Skan} 2424169689Skan 2425169689Skanint 2426169689Skanm16_nsimm4_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) 2427169689Skan{ 2428169689Skan return m16_check_op (op, - 0x7, 0x8, 0); 2429169689Skan} 2430169689Skan 2431169689Skanint 2432169689Skanm16_simm5_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) 2433169689Skan{ 2434169689Skan return m16_check_op (op, - 0x10, 0xf, 0); 2435169689Skan} 2436169689Skan 2437169689Skanint 2438169689Skanm16_nsimm5_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) 2439169689Skan{ 2440169689Skan return m16_check_op (op, - 0xf, 0x10, 0); 2441169689Skan} 2442169689Skan 2443169689Skanint 2444169689Skanm16_uimm5_4 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) 2445169689Skan{ 2446169689Skan return m16_check_op (op, (- 0x10) << 2, 0xf << 2, 3); 2447169689Skan} 2448169689Skan 2449169689Skanint 2450169689Skanm16_nuimm5_4 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) 2451169689Skan{ 2452169689Skan return m16_check_op (op, (- 0xf) << 2, 0x10 << 2, 3); 2453169689Skan} 2454169689Skan 2455169689Skanint 2456169689Skanm16_simm8_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) 2457169689Skan{ 2458169689Skan return m16_check_op (op, - 0x80, 0x7f, 0); 2459169689Skan} 2460169689Skan 2461169689Skanint 2462169689Skanm16_nsimm8_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) 2463169689Skan{ 2464169689Skan return m16_check_op (op, - 0x7f, 0x80, 0); 2465169689Skan} 2466169689Skan 2467169689Skanint 2468169689Skanm16_uimm8_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) 2469169689Skan{ 2470169689Skan return m16_check_op (op, 0x0, 0xff, 0); 2471169689Skan} 2472169689Skan 2473169689Skanint 2474169689Skanm16_nuimm8_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) 2475169689Skan{ 2476169689Skan return m16_check_op (op, - 0xff, 0x0, 0); 2477169689Skan} 2478169689Skan 2479169689Skanint 2480169689Skanm16_uimm8_m1_1 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) 2481169689Skan{ 2482169689Skan return m16_check_op (op, - 0x1, 0xfe, 0); 2483169689Skan} 2484169689Skan 2485169689Skanint 2486169689Skanm16_uimm8_4 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) 2487169689Skan{ 2488169689Skan return m16_check_op (op, 0x0, 0xff << 2, 3); 2489169689Skan} 2490169689Skan 2491169689Skanint 2492169689Skanm16_nuimm8_4 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) 2493169689Skan{ 2494169689Skan return m16_check_op (op, (- 0xff) << 2, 0x0, 3); 2495169689Skan} 2496169689Skan 2497169689Skanint 2498169689Skanm16_simm8_8 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) 2499169689Skan{ 2500169689Skan return m16_check_op (op, (- 0x80) << 3, 0x7f << 3, 7); 2501169689Skan} 2502169689Skan 2503169689Skanint 2504169689Skanm16_nsimm8_8 (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED) 2505169689Skan{ 2506169689Skan return m16_check_op (op, (- 0x7f) << 3, 0x80 << 3, 7); 2507169689Skan} 2508169689Skan 2509169689Skanstatic bool 2510169689Skanmips_rtx_costs (rtx x, int code, int outer_code, int *total) 2511169689Skan{ 2512169689Skan enum machine_mode mode = GET_MODE (x); 2513169689Skan bool float_mode_p = FLOAT_MODE_P (mode); 2514169689Skan 2515169689Skan switch (code) 2516169689Skan { 2517169689Skan case CONST_INT: 2518169689Skan if (TARGET_MIPS16) 2519169689Skan { 2520169689Skan /* A number between 1 and 8 inclusive is efficient for a shift. 2521169689Skan Otherwise, we will need an extended instruction. */ 2522169689Skan if ((outer_code) == ASHIFT || (outer_code) == ASHIFTRT 2523169689Skan || (outer_code) == LSHIFTRT) 2524169689Skan { 2525169689Skan if (INTVAL (x) >= 1 && INTVAL (x) <= 8) 2526169689Skan *total = 0; 2527169689Skan else 2528169689Skan *total = COSTS_N_INSNS (1); 2529169689Skan return true; 2530169689Skan } 2531169689Skan 2532169689Skan /* We can use cmpi for an xor with an unsigned 16 bit value. */ 2533169689Skan if ((outer_code) == XOR 2534169689Skan && INTVAL (x) >= 0 && INTVAL (x) < 0x10000) 2535169689Skan { 2536169689Skan *total = 0; 2537169689Skan return true; 2538169689Skan } 2539169689Skan 2540169689Skan /* We may be able to use slt or sltu for a comparison with a 2541169689Skan signed 16 bit value. (The boundary conditions aren't quite 2542169689Skan right, but this is just a heuristic anyhow.) */ 2543169689Skan if (((outer_code) == LT || (outer_code) == LE 2544169689Skan || (outer_code) == GE || (outer_code) == GT 2545169689Skan || (outer_code) == LTU || (outer_code) == LEU 2546169689Skan || (outer_code) == GEU || (outer_code) == GTU) 2547169689Skan && INTVAL (x) >= -0x8000 && INTVAL (x) < 0x8000) 2548169689Skan { 2549169689Skan *total = 0; 2550169689Skan return true; 2551169689Skan } 2552169689Skan 2553169689Skan /* Equality comparisons with 0 are cheap. */ 2554169689Skan if (((outer_code) == EQ || (outer_code) == NE) 2555169689Skan && INTVAL (x) == 0) 2556169689Skan { 2557169689Skan *total = 0; 2558169689Skan return true; 2559169689Skan } 2560169689Skan 2561169689Skan /* Constants in the range 0...255 can be loaded with an unextended 2562169689Skan instruction. They are therefore as cheap as a register move. 2563169689Skan 2564169689Skan Given the choice between "li R1,0...255" and "move R1,R2" 2565169689Skan (where R2 is a known constant), it is usually better to use "li", 2566169689Skan since we do not want to unnecessarily extend the lifetime 2567169689Skan of R2. */ 2568169689Skan if (outer_code == SET 2569169689Skan && INTVAL (x) >= 0 2570169689Skan && INTVAL (x) < 256) 2571169689Skan { 2572169689Skan *total = 0; 2573169689Skan return true; 2574169689Skan } 2575169689Skan } 2576169689Skan else 2577169689Skan { 2578169689Skan /* These can be used anywhere. */ 2579169689Skan *total = 0; 2580169689Skan return true; 2581169689Skan } 2582169689Skan 2583169689Skan /* Otherwise fall through to the handling below because 2584169689Skan we'll need to construct the constant. */ 2585169689Skan 2586169689Skan case CONST: 2587169689Skan case SYMBOL_REF: 2588169689Skan case LABEL_REF: 2589169689Skan case CONST_DOUBLE: 2590169689Skan if (LEGITIMATE_CONSTANT_P (x)) 2591169689Skan { 2592169689Skan *total = COSTS_N_INSNS (1); 2593169689Skan return true; 2594169689Skan } 2595169689Skan else 2596169689Skan { 2597169689Skan /* The value will need to be fetched from the constant pool. */ 2598169689Skan *total = CONSTANT_POOL_COST; 2599169689Skan return true; 2600169689Skan } 2601169689Skan 2602169689Skan case MEM: 2603169689Skan { 2604169689Skan /* If the address is legitimate, return the number of 2605169689Skan instructions it needs, otherwise use the default handling. */ 2606169689Skan int n = mips_address_insns (XEXP (x, 0), GET_MODE (x)); 2607169689Skan if (n > 0) 2608169689Skan { 2609169689Skan *total = COSTS_N_INSNS (n + 1); 2610169689Skan return true; 2611169689Skan } 2612169689Skan return false; 2613169689Skan } 2614169689Skan 2615169689Skan case FFS: 2616169689Skan *total = COSTS_N_INSNS (6); 2617169689Skan return true; 2618169689Skan 2619169689Skan case NOT: 2620169689Skan *total = COSTS_N_INSNS ((mode == DImode && !TARGET_64BIT) ? 2 : 1); 2621169689Skan return true; 2622169689Skan 2623169689Skan case AND: 2624169689Skan case IOR: 2625169689Skan case XOR: 2626169689Skan if (mode == DImode && !TARGET_64BIT) 2627169689Skan { 2628169689Skan *total = COSTS_N_INSNS (2); 2629169689Skan return true; 2630169689Skan } 2631169689Skan return false; 2632169689Skan 2633169689Skan case ASHIFT: 2634169689Skan case ASHIFTRT: 2635169689Skan case LSHIFTRT: 2636169689Skan if (mode == DImode && !TARGET_64BIT) 2637169689Skan { 2638169689Skan *total = COSTS_N_INSNS ((GET_CODE (XEXP (x, 1)) == CONST_INT) 2639169689Skan ? 4 : 12); 2640169689Skan return true; 2641169689Skan } 2642169689Skan return false; 2643169689Skan 2644169689Skan case ABS: 2645169689Skan if (float_mode_p) 2646169689Skan *total = COSTS_N_INSNS (1); 2647169689Skan else 2648169689Skan *total = COSTS_N_INSNS (4); 2649169689Skan return true; 2650169689Skan 2651169689Skan case LO_SUM: 2652169689Skan *total = COSTS_N_INSNS (1); 2653169689Skan return true; 2654169689Skan 2655169689Skan case PLUS: 2656169689Skan case MINUS: 2657169689Skan if (float_mode_p) 2658169689Skan { 2659169689Skan *total = mips_cost->fp_add; 2660169689Skan return true; 2661169689Skan } 2662169689Skan 2663169689Skan else if (mode == DImode && !TARGET_64BIT) 2664169689Skan { 2665169689Skan *total = COSTS_N_INSNS (4); 2666169689Skan return true; 2667169689Skan } 2668169689Skan return false; 2669169689Skan 2670169689Skan case NEG: 2671169689Skan if (mode == DImode && !TARGET_64BIT) 2672169689Skan { 2673169689Skan *total = COSTS_N_INSNS (4); 2674169689Skan return true; 2675169689Skan } 2676169689Skan return false; 2677169689Skan 2678169689Skan case MULT: 2679169689Skan if (mode == SFmode) 2680169689Skan *total = mips_cost->fp_mult_sf; 2681169689Skan 2682169689Skan else if (mode == DFmode) 2683169689Skan *total = mips_cost->fp_mult_df; 2684169689Skan 2685169689Skan else if (mode == SImode) 2686169689Skan *total = mips_cost->int_mult_si; 2687169689Skan 2688169689Skan else 2689169689Skan *total = mips_cost->int_mult_di; 2690169689Skan 2691169689Skan return true; 2692169689Skan 2693169689Skan case DIV: 2694169689Skan case MOD: 2695169689Skan if (float_mode_p) 2696169689Skan { 2697169689Skan if (mode == SFmode) 2698169689Skan *total = mips_cost->fp_div_sf; 2699169689Skan else 2700169689Skan *total = mips_cost->fp_div_df; 2701169689Skan 2702169689Skan return true; 2703169689Skan } 2704169689Skan /* Fall through. */ 2705169689Skan 2706169689Skan case UDIV: 2707169689Skan case UMOD: 2708169689Skan if (mode == DImode) 2709169689Skan *total = mips_cost->int_div_di; 2710169689Skan else 2711169689Skan *total = mips_cost->int_div_si; 2712169689Skan 2713169689Skan return true; 2714169689Skan 2715169689Skan case SIGN_EXTEND: 2716169689Skan /* A sign extend from SImode to DImode in 64 bit mode is often 2717169689Skan zero instructions, because the result can often be used 2718169689Skan directly by another instruction; we'll call it one. */ 2719169689Skan if (TARGET_64BIT && mode == DImode 2720169689Skan && GET_MODE (XEXP (x, 0)) == SImode) 2721169689Skan *total = COSTS_N_INSNS (1); 2722169689Skan else 2723169689Skan *total = COSTS_N_INSNS (2); 2724169689Skan return true; 2725169689Skan 2726169689Skan case ZERO_EXTEND: 2727169689Skan if (TARGET_64BIT && mode == DImode 2728169689Skan && GET_MODE (XEXP (x, 0)) == SImode) 2729169689Skan *total = COSTS_N_INSNS (2); 2730169689Skan else 2731169689Skan *total = COSTS_N_INSNS (1); 2732169689Skan return true; 2733169689Skan 2734169689Skan case FLOAT: 2735169689Skan case UNSIGNED_FLOAT: 2736169689Skan case FIX: 2737169689Skan case FLOAT_EXTEND: 2738169689Skan case FLOAT_TRUNCATE: 2739169689Skan case SQRT: 2740169689Skan *total = mips_cost->fp_add; 2741169689Skan return true; 2742169689Skan 2743169689Skan default: 2744169689Skan return false; 2745169689Skan } 2746169689Skan} 2747169689Skan 2748169689Skan/* Provide the costs of an addressing mode that contains ADDR. 2749169689Skan If ADDR is not a valid address, its cost is irrelevant. */ 2750169689Skan 2751169689Skanstatic int 2752169689Skanmips_address_cost (rtx addr) 2753169689Skan{ 2754169689Skan return mips_address_insns (addr, SImode); 2755169689Skan} 2756169689Skan 2757169689Skan/* Return one word of double-word value OP, taking into account the fixed 2758169689Skan endianness of certain registers. HIGH_P is true to select the high part, 2759169689Skan false to select the low part. */ 2760169689Skan 2761169689Skanrtx 2762169689Skanmips_subword (rtx op, int high_p) 2763169689Skan{ 2764169689Skan unsigned int byte; 2765169689Skan enum machine_mode mode; 2766169689Skan 2767169689Skan mode = GET_MODE (op); 2768169689Skan if (mode == VOIDmode) 2769169689Skan mode = DImode; 2770169689Skan 2771169689Skan if (TARGET_BIG_ENDIAN ? !high_p : high_p) 2772169689Skan byte = UNITS_PER_WORD; 2773169689Skan else 2774169689Skan byte = 0; 2775169689Skan 2776169689Skan if (REG_P (op)) 2777169689Skan { 2778169689Skan if (FP_REG_P (REGNO (op))) 2779169689Skan return gen_rtx_REG (word_mode, high_p ? REGNO (op) + 1 : REGNO (op)); 2780169689Skan if (ACC_HI_REG_P (REGNO (op))) 2781169689Skan return gen_rtx_REG (word_mode, high_p ? REGNO (op) : REGNO (op) + 1); 2782169689Skan } 2783169689Skan 2784169689Skan if (MEM_P (op)) 2785169689Skan return mips_rewrite_small_data (adjust_address (op, word_mode, byte)); 2786169689Skan 2787169689Skan return simplify_gen_subreg (word_mode, op, mode, byte); 2788169689Skan} 2789169689Skan 2790169689Skan 2791169689Skan/* Return true if a 64-bit move from SRC to DEST should be split into two. */ 2792169689Skan 2793169689Skanbool 2794169689Skanmips_split_64bit_move_p (rtx dest, rtx src) 2795169689Skan{ 2796169689Skan if (TARGET_64BIT) 2797169689Skan return false; 2798169689Skan 2799169689Skan /* FP->FP moves can be done in a single instruction. */ 2800169689Skan if (FP_REG_RTX_P (src) && FP_REG_RTX_P (dest)) 2801169689Skan return false; 2802169689Skan 2803169689Skan /* Check for floating-point loads and stores. They can be done using 2804169689Skan ldc1 and sdc1 on MIPS II and above. */ 2805169689Skan if (mips_isa > 1) 2806169689Skan { 2807169689Skan if (FP_REG_RTX_P (dest) && MEM_P (src)) 2808169689Skan return false; 2809169689Skan if (FP_REG_RTX_P (src) && MEM_P (dest)) 2810169689Skan return false; 2811169689Skan } 2812169689Skan return true; 2813169689Skan} 2814169689Skan 2815169689Skan 2816169689Skan/* Split a 64-bit move from SRC to DEST assuming that 2817169689Skan mips_split_64bit_move_p holds. 2818169689Skan 2819169689Skan Moves into and out of FPRs cause some difficulty here. Such moves 2820169689Skan will always be DFmode, since paired FPRs are not allowed to store 2821169689Skan DImode values. The most natural representation would be two separate 2822169689Skan 32-bit moves, such as: 2823169689Skan 2824169689Skan (set (reg:SI $f0) (mem:SI ...)) 2825169689Skan (set (reg:SI $f1) (mem:SI ...)) 2826169689Skan 2827169689Skan However, the second insn is invalid because odd-numbered FPRs are 2828169689Skan not allowed to store independent values. Use the patterns load_df_low, 2829169689Skan load_df_high and store_df_high instead. */ 2830169689Skan 2831169689Skanvoid 2832169689Skanmips_split_64bit_move (rtx dest, rtx src) 2833169689Skan{ 2834169689Skan if (FP_REG_RTX_P (dest)) 2835169689Skan { 2836169689Skan /* Loading an FPR from memory or from GPRs. */ 2837169689Skan emit_insn (gen_load_df_low (copy_rtx (dest), mips_subword (src, 0))); 2838169689Skan emit_insn (gen_load_df_high (dest, mips_subword (src, 1), 2839169689Skan copy_rtx (dest))); 2840169689Skan } 2841169689Skan else if (FP_REG_RTX_P (src)) 2842169689Skan { 2843169689Skan /* Storing an FPR into memory or GPRs. */ 2844169689Skan emit_move_insn (mips_subword (dest, 0), mips_subword (src, 0)); 2845169689Skan emit_insn (gen_store_df_high (mips_subword (dest, 1), src)); 2846169689Skan } 2847169689Skan else 2848169689Skan { 2849169689Skan /* The operation can be split into two normal moves. Decide in 2850169689Skan which order to do them. */ 2851169689Skan rtx low_dest; 2852169689Skan 2853169689Skan low_dest = mips_subword (dest, 0); 2854169689Skan if (REG_P (low_dest) 2855169689Skan && reg_overlap_mentioned_p (low_dest, src)) 2856169689Skan { 2857169689Skan emit_move_insn (mips_subword (dest, 1), mips_subword (src, 1)); 2858169689Skan emit_move_insn (low_dest, mips_subword (src, 0)); 2859169689Skan } 2860169689Skan else 2861169689Skan { 2862169689Skan emit_move_insn (low_dest, mips_subword (src, 0)); 2863169689Skan emit_move_insn (mips_subword (dest, 1), mips_subword (src, 1)); 2864169689Skan } 2865169689Skan } 2866169689Skan} 2867169689Skan 2868169689Skan/* Return the appropriate instructions to move SRC into DEST. Assume 2869169689Skan that SRC is operand 1 and DEST is operand 0. */ 2870169689Skan 2871169689Skanconst char * 2872169689Skanmips_output_move (rtx dest, rtx src) 2873169689Skan{ 2874169689Skan enum rtx_code dest_code, src_code; 2875169689Skan bool dbl_p; 2876169689Skan 2877169689Skan dest_code = GET_CODE (dest); 2878169689Skan src_code = GET_CODE (src); 2879169689Skan dbl_p = (GET_MODE_SIZE (GET_MODE (dest)) == 8); 2880169689Skan 2881169689Skan if (dbl_p && mips_split_64bit_move_p (dest, src)) 2882169689Skan return "#"; 2883169689Skan 2884169689Skan if ((src_code == REG && GP_REG_P (REGNO (src))) 2885169689Skan || (!TARGET_MIPS16 && src == CONST0_RTX (GET_MODE (dest)))) 2886169689Skan { 2887169689Skan if (dest_code == REG) 2888169689Skan { 2889169689Skan if (GP_REG_P (REGNO (dest))) 2890169689Skan return "move\t%0,%z1"; 2891169689Skan 2892169689Skan if (MD_REG_P (REGNO (dest))) 2893169689Skan return "mt%0\t%z1"; 2894169689Skan 2895169689Skan if (DSP_ACC_REG_P (REGNO (dest))) 2896169689Skan { 2897169689Skan static char retval[] = "mt__\t%z1,%q0"; 2898169689Skan retval[2] = reg_names[REGNO (dest)][4]; 2899169689Skan retval[3] = reg_names[REGNO (dest)][5]; 2900169689Skan return retval; 2901169689Skan } 2902169689Skan 2903169689Skan if (FP_REG_P (REGNO (dest))) 2904169689Skan return (dbl_p ? "dmtc1\t%z1,%0" : "mtc1\t%z1,%0"); 2905169689Skan 2906169689Skan if (ALL_COP_REG_P (REGNO (dest))) 2907169689Skan { 2908169689Skan static char retval[] = "dmtc_\t%z1,%0"; 2909169689Skan 2910169689Skan retval[4] = COPNUM_AS_CHAR_FROM_REGNUM (REGNO (dest)); 2911169689Skan return (dbl_p ? retval : retval + 1); 2912169689Skan } 2913169689Skan } 2914169689Skan if (dest_code == MEM) 2915169689Skan return (dbl_p ? "sd\t%z1,%0" : "sw\t%z1,%0"); 2916169689Skan } 2917169689Skan if (dest_code == REG && GP_REG_P (REGNO (dest))) 2918169689Skan { 2919169689Skan if (src_code == REG) 2920169689Skan { 2921169689Skan if (DSP_ACC_REG_P (REGNO (src))) 2922169689Skan { 2923169689Skan static char retval[] = "mf__\t%0,%q1"; 2924169689Skan retval[2] = reg_names[REGNO (src)][4]; 2925169689Skan retval[3] = reg_names[REGNO (src)][5]; 2926169689Skan return retval; 2927169689Skan } 2928169689Skan 2929169689Skan if (ST_REG_P (REGNO (src)) && ISA_HAS_8CC) 2930169689Skan return "lui\t%0,0x3f80\n\tmovf\t%0,%.,%1"; 2931169689Skan 2932169689Skan if (FP_REG_P (REGNO (src))) 2933169689Skan return (dbl_p ? "dmfc1\t%0,%1" : "mfc1\t%0,%1"); 2934169689Skan 2935169689Skan if (ALL_COP_REG_P (REGNO (src))) 2936169689Skan { 2937169689Skan static char retval[] = "dmfc_\t%0,%1"; 2938169689Skan 2939169689Skan retval[4] = COPNUM_AS_CHAR_FROM_REGNUM (REGNO (src)); 2940169689Skan return (dbl_p ? retval : retval + 1); 2941169689Skan } 2942169689Skan } 2943169689Skan 2944169689Skan if (src_code == MEM) 2945169689Skan return (dbl_p ? "ld\t%0,%1" : "lw\t%0,%1"); 2946169689Skan 2947169689Skan if (src_code == CONST_INT) 2948169689Skan { 2949169689Skan /* Don't use the X format, because that will give out of 2950169689Skan range numbers for 64 bit hosts and 32 bit targets. */ 2951169689Skan if (!TARGET_MIPS16) 2952169689Skan return "li\t%0,%1\t\t\t# %X1"; 2953169689Skan 2954169689Skan if (INTVAL (src) >= 0 && INTVAL (src) <= 0xffff) 2955169689Skan return "li\t%0,%1"; 2956169689Skan 2957169689Skan if (INTVAL (src) < 0 && INTVAL (src) >= -0xffff) 2958169689Skan return "#"; 2959169689Skan } 2960169689Skan 2961169689Skan if (src_code == HIGH) 2962169689Skan return "lui\t%0,%h1"; 2963169689Skan 2964169689Skan if (CONST_GP_P (src)) 2965169689Skan return "move\t%0,%1"; 2966169689Skan 2967169689Skan if (symbolic_operand (src, VOIDmode)) 2968169689Skan return (dbl_p ? "dla\t%0,%1" : "la\t%0,%1"); 2969169689Skan } 2970169689Skan if (src_code == REG && FP_REG_P (REGNO (src))) 2971169689Skan { 2972169689Skan if (dest_code == REG && FP_REG_P (REGNO (dest))) 2973169689Skan { 2974169689Skan if (GET_MODE (dest) == V2SFmode) 2975169689Skan return "mov.ps\t%0,%1"; 2976169689Skan else 2977169689Skan return (dbl_p ? "mov.d\t%0,%1" : "mov.s\t%0,%1"); 2978169689Skan } 2979169689Skan 2980169689Skan if (dest_code == MEM) 2981169689Skan return (dbl_p ? "sdc1\t%1,%0" : "swc1\t%1,%0"); 2982169689Skan } 2983169689Skan if (dest_code == REG && FP_REG_P (REGNO (dest))) 2984169689Skan { 2985169689Skan if (src_code == MEM) 2986169689Skan return (dbl_p ? "ldc1\t%0,%1" : "lwc1\t%0,%1"); 2987169689Skan } 2988169689Skan if (dest_code == REG && ALL_COP_REG_P (REGNO (dest)) && src_code == MEM) 2989169689Skan { 2990169689Skan static char retval[] = "l_c_\t%0,%1"; 2991169689Skan 2992169689Skan retval[1] = (dbl_p ? 'd' : 'w'); 2993169689Skan retval[3] = COPNUM_AS_CHAR_FROM_REGNUM (REGNO (dest)); 2994169689Skan return retval; 2995169689Skan } 2996169689Skan if (dest_code == MEM && src_code == REG && ALL_COP_REG_P (REGNO (src))) 2997169689Skan { 2998169689Skan static char retval[] = "s_c_\t%1,%0"; 2999169689Skan 3000169689Skan retval[1] = (dbl_p ? 'd' : 'w'); 3001169689Skan retval[3] = COPNUM_AS_CHAR_FROM_REGNUM (REGNO (src)); 3002169689Skan return retval; 3003169689Skan } 3004169689Skan gcc_unreachable (); 3005169689Skan} 3006169689Skan 3007169689Skan/* Restore $gp from its save slot. Valid only when using o32 or 3008169689Skan o64 abicalls. */ 3009169689Skan 3010169689Skanvoid 3011169689Skanmips_restore_gp (void) 3012169689Skan{ 3013169689Skan rtx address, slot; 3014169689Skan 3015169689Skan gcc_assert (TARGET_ABICALLS && TARGET_OLDABI); 3016169689Skan 3017169689Skan address = mips_add_offset (pic_offset_table_rtx, 3018169689Skan frame_pointer_needed 3019169689Skan ? hard_frame_pointer_rtx 3020169689Skan : stack_pointer_rtx, 3021169689Skan current_function_outgoing_args_size); 3022169689Skan slot = gen_rtx_MEM (Pmode, address); 3023169689Skan 3024169689Skan emit_move_insn (pic_offset_table_rtx, slot); 3025169689Skan if (!TARGET_EXPLICIT_RELOCS) 3026169689Skan emit_insn (gen_blockage ()); 3027169689Skan} 3028169689Skan 3029169689Skan/* Emit an instruction of the form (set TARGET (CODE OP0 OP1)). */ 3030169689Skan 3031169689Skanstatic void 3032169689Skanmips_emit_binary (enum rtx_code code, rtx target, rtx op0, rtx op1) 3033169689Skan{ 3034169689Skan emit_insn (gen_rtx_SET (VOIDmode, target, 3035169689Skan gen_rtx_fmt_ee (code, GET_MODE (target), op0, op1))); 3036169689Skan} 3037169689Skan 3038169689Skan/* Return true if CMP1 is a suitable second operand for relational 3039169689Skan operator CODE. See also the *sCC patterns in mips.md. */ 3040169689Skan 3041169689Skanstatic bool 3042169689Skanmips_relational_operand_ok_p (enum rtx_code code, rtx cmp1) 3043169689Skan{ 3044169689Skan switch (code) 3045169689Skan { 3046169689Skan case GT: 3047169689Skan case GTU: 3048169689Skan return reg_or_0_operand (cmp1, VOIDmode); 3049169689Skan 3050169689Skan case GE: 3051169689Skan case GEU: 3052169689Skan return !TARGET_MIPS16 && cmp1 == const1_rtx; 3053169689Skan 3054169689Skan case LT: 3055169689Skan case LTU: 3056169689Skan return arith_operand (cmp1, VOIDmode); 3057169689Skan 3058169689Skan case LE: 3059169689Skan return sle_operand (cmp1, VOIDmode); 3060169689Skan 3061169689Skan case LEU: 3062169689Skan return sleu_operand (cmp1, VOIDmode); 3063169689Skan 3064169689Skan default: 3065169689Skan gcc_unreachable (); 3066169689Skan } 3067169689Skan} 3068169689Skan 3069169689Skan/* Canonicalize LE or LEU comparisons into LT comparisons when 3070169689Skan possible to avoid extra instructions or inverting the 3071169689Skan comparison. */ 3072169689Skan 3073169689Skanstatic bool 3074169689Skanmips_canonicalize_comparison (enum rtx_code *code, rtx *cmp1, 3075169689Skan enum machine_mode mode) 3076169689Skan{ 3077169689Skan HOST_WIDE_INT original, plus_one; 3078169689Skan 3079169689Skan if (GET_CODE (*cmp1) != CONST_INT) 3080169689Skan return false; 3081169689Skan 3082169689Skan original = INTVAL (*cmp1); 3083169689Skan plus_one = trunc_int_for_mode ((unsigned HOST_WIDE_INT) original + 1, mode); 3084169689Skan 3085169689Skan switch (*code) 3086169689Skan { 3087169689Skan case LE: 3088169689Skan if (original < plus_one) 3089169689Skan { 3090169689Skan *code = LT; 3091169689Skan *cmp1 = force_reg (mode, GEN_INT (plus_one)); 3092169689Skan return true; 3093169689Skan } 3094169689Skan break; 3095169689Skan 3096169689Skan case LEU: 3097169689Skan if (plus_one != 0) 3098169689Skan { 3099169689Skan *code = LTU; 3100169689Skan *cmp1 = force_reg (mode, GEN_INT (plus_one)); 3101169689Skan return true; 3102169689Skan } 3103169689Skan break; 3104169689Skan 3105169689Skan default: 3106169689Skan return false; 3107169689Skan } 3108169689Skan 3109169689Skan return false; 3110169689Skan 3111169689Skan} 3112169689Skan 3113169689Skan/* Compare CMP0 and CMP1 using relational operator CODE and store the 3114169689Skan result in TARGET. CMP0 and TARGET are register_operands that have 3115169689Skan the same integer mode. If INVERT_PTR is nonnull, it's OK to set 3116169689Skan TARGET to the inverse of the result and flip *INVERT_PTR instead. */ 3117169689Skan 3118169689Skanstatic void 3119169689Skanmips_emit_int_relational (enum rtx_code code, bool *invert_ptr, 3120169689Skan rtx target, rtx cmp0, rtx cmp1) 3121169689Skan{ 3122169689Skan /* First see if there is a MIPS instruction that can do this operation 3123169689Skan with CMP1 in its current form. If not, try to canonicalize the 3124169689Skan comparison to LT. If that fails, try doing the same for the 3125169689Skan inverse operation. If that also fails, force CMP1 into a register 3126169689Skan and try again. */ 3127169689Skan if (mips_relational_operand_ok_p (code, cmp1)) 3128169689Skan mips_emit_binary (code, target, cmp0, cmp1); 3129169689Skan else if (mips_canonicalize_comparison (&code, &cmp1, GET_MODE (target))) 3130169689Skan mips_emit_binary (code, target, cmp0, cmp1); 3131169689Skan else 3132169689Skan { 3133169689Skan enum rtx_code inv_code = reverse_condition (code); 3134169689Skan if (!mips_relational_operand_ok_p (inv_code, cmp1)) 3135169689Skan { 3136169689Skan cmp1 = force_reg (GET_MODE (cmp0), cmp1); 3137169689Skan mips_emit_int_relational (code, invert_ptr, target, cmp0, cmp1); 3138169689Skan } 3139169689Skan else if (invert_ptr == 0) 3140169689Skan { 3141169689Skan rtx inv_target = gen_reg_rtx (GET_MODE (target)); 3142169689Skan mips_emit_binary (inv_code, inv_target, cmp0, cmp1); 3143169689Skan mips_emit_binary (XOR, target, inv_target, const1_rtx); 3144169689Skan } 3145169689Skan else 3146169689Skan { 3147169689Skan *invert_ptr = !*invert_ptr; 3148169689Skan mips_emit_binary (inv_code, target, cmp0, cmp1); 3149169689Skan } 3150169689Skan } 3151169689Skan} 3152169689Skan 3153169689Skan/* Return a register that is zero iff CMP0 and CMP1 are equal. 3154169689Skan The register will have the same mode as CMP0. */ 3155169689Skan 3156169689Skanstatic rtx 3157169689Skanmips_zero_if_equal (rtx cmp0, rtx cmp1) 3158169689Skan{ 3159169689Skan if (cmp1 == const0_rtx) 3160169689Skan return cmp0; 3161169689Skan 3162169689Skan if (uns_arith_operand (cmp1, VOIDmode)) 3163169689Skan return expand_binop (GET_MODE (cmp0), xor_optab, 3164169689Skan cmp0, cmp1, 0, 0, OPTAB_DIRECT); 3165169689Skan 3166169689Skan return expand_binop (GET_MODE (cmp0), sub_optab, 3167169689Skan cmp0, cmp1, 0, 0, OPTAB_DIRECT); 3168169689Skan} 3169169689Skan 3170169689Skan/* Convert *CODE into a code that can be used in a floating-point 3171169689Skan scc instruction (c.<cond>.<fmt>). Return true if the values of 3172169689Skan the condition code registers will be inverted, with 0 indicating 3173169689Skan that the condition holds. */ 3174169689Skan 3175169689Skanstatic bool 3176169689Skanmips_reverse_fp_cond_p (enum rtx_code *code) 3177169689Skan{ 3178169689Skan switch (*code) 3179169689Skan { 3180169689Skan case NE: 3181169689Skan case LTGT: 3182169689Skan case ORDERED: 3183169689Skan *code = reverse_condition_maybe_unordered (*code); 3184169689Skan return true; 3185169689Skan 3186169689Skan default: 3187169689Skan return false; 3188169689Skan } 3189169689Skan} 3190169689Skan 3191169689Skan/* Convert a comparison into something that can be used in a branch or 3192169689Skan conditional move. cmp_operands[0] and cmp_operands[1] are the values 3193169689Skan being compared and *CODE is the code used to compare them. 3194169689Skan 3195169689Skan Update *CODE, *OP0 and *OP1 so that they describe the final comparison. 3196169689Skan If NEED_EQ_NE_P, then only EQ/NE comparisons against zero are possible, 3197169689Skan otherwise any standard branch condition can be used. The standard branch 3198169689Skan conditions are: 3199169689Skan 3200169689Skan - EQ/NE between two registers. 3201169689Skan - any comparison between a register and zero. */ 3202169689Skan 3203169689Skanstatic void 3204169689Skanmips_emit_compare (enum rtx_code *code, rtx *op0, rtx *op1, bool need_eq_ne_p) 3205169689Skan{ 3206169689Skan if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) == MODE_INT) 3207169689Skan { 3208169689Skan if (!need_eq_ne_p && cmp_operands[1] == const0_rtx) 3209169689Skan { 3210169689Skan *op0 = cmp_operands[0]; 3211169689Skan *op1 = cmp_operands[1]; 3212169689Skan } 3213169689Skan else if (*code == EQ || *code == NE) 3214169689Skan { 3215169689Skan if (need_eq_ne_p) 3216169689Skan { 3217169689Skan *op0 = mips_zero_if_equal (cmp_operands[0], cmp_operands[1]); 3218169689Skan *op1 = const0_rtx; 3219169689Skan } 3220169689Skan else 3221169689Skan { 3222169689Skan *op0 = cmp_operands[0]; 3223169689Skan *op1 = force_reg (GET_MODE (*op0), cmp_operands[1]); 3224169689Skan } 3225169689Skan } 3226169689Skan else 3227169689Skan { 3228169689Skan /* The comparison needs a separate scc instruction. Store the 3229169689Skan result of the scc in *OP0 and compare it against zero. */ 3230169689Skan bool invert = false; 3231169689Skan *op0 = gen_reg_rtx (GET_MODE (cmp_operands[0])); 3232169689Skan *op1 = const0_rtx; 3233169689Skan mips_emit_int_relational (*code, &invert, *op0, 3234169689Skan cmp_operands[0], cmp_operands[1]); 3235169689Skan *code = (invert ? EQ : NE); 3236169689Skan } 3237169689Skan } 3238169689Skan else 3239169689Skan { 3240169689Skan enum rtx_code cmp_code; 3241169689Skan 3242169689Skan /* Floating-point tests use a separate c.cond.fmt comparison to 3243169689Skan set a condition code register. The branch or conditional move 3244169689Skan will then compare that register against zero. 3245169689Skan 3246169689Skan Set CMP_CODE to the code of the comparison instruction and 3247169689Skan *CODE to the code that the branch or move should use. */ 3248169689Skan cmp_code = *code; 3249169689Skan *code = mips_reverse_fp_cond_p (&cmp_code) ? EQ : NE; 3250169689Skan *op0 = (ISA_HAS_8CC 3251169689Skan ? gen_reg_rtx (CCmode) 3252169689Skan : gen_rtx_REG (CCmode, FPSW_REGNUM)); 3253169689Skan *op1 = const0_rtx; 3254169689Skan mips_emit_binary (cmp_code, *op0, cmp_operands[0], cmp_operands[1]); 3255169689Skan } 3256169689Skan} 3257169689Skan 3258169689Skan/* Try comparing cmp_operands[0] and cmp_operands[1] using rtl code CODE. 3259169689Skan Store the result in TARGET and return true if successful. 3260169689Skan 3261169689Skan On 64-bit targets, TARGET may be wider than cmp_operands[0]. */ 3262169689Skan 3263169689Skanbool 3264169689Skanmips_emit_scc (enum rtx_code code, rtx target) 3265169689Skan{ 3266169689Skan if (GET_MODE_CLASS (GET_MODE (cmp_operands[0])) != MODE_INT) 3267169689Skan return false; 3268169689Skan 3269169689Skan target = gen_lowpart (GET_MODE (cmp_operands[0]), target); 3270169689Skan if (code == EQ || code == NE) 3271169689Skan { 3272169689Skan rtx zie = mips_zero_if_equal (cmp_operands[0], cmp_operands[1]); 3273169689Skan mips_emit_binary (code, target, zie, const0_rtx); 3274169689Skan } 3275169689Skan else 3276169689Skan mips_emit_int_relational (code, 0, target, 3277169689Skan cmp_operands[0], cmp_operands[1]); 3278169689Skan return true; 3279169689Skan} 3280169689Skan 3281169689Skan/* Emit the common code for doing conditional branches. 3282169689Skan operand[0] is the label to jump to. 3283169689Skan The comparison operands are saved away by cmp{si,di,sf,df}. */ 3284169689Skan 3285169689Skanvoid 3286169689Skangen_conditional_branch (rtx *operands, enum rtx_code code) 3287169689Skan{ 3288169689Skan rtx op0, op1, condition; 3289169689Skan 3290169689Skan mips_emit_compare (&code, &op0, &op1, TARGET_MIPS16); 3291169689Skan condition = gen_rtx_fmt_ee (code, VOIDmode, op0, op1); 3292169689Skan emit_jump_insn (gen_condjump (condition, operands[0])); 3293169689Skan} 3294169689Skan 3295169689Skan/* Implement: 3296169689Skan 3297169689Skan (set temp (COND:CCV2 CMP_OP0 CMP_OP1)) 3298169689Skan (set DEST (unspec [TRUE_SRC FALSE_SRC temp] UNSPEC_MOVE_TF_PS)) */ 3299169689Skan 3300169689Skanvoid 3301169689Skanmips_expand_vcondv2sf (rtx dest, rtx true_src, rtx false_src, 3302169689Skan enum rtx_code cond, rtx cmp_op0, rtx cmp_op1) 3303169689Skan{ 3304169689Skan rtx cmp_result; 3305169689Skan bool reversed_p; 3306169689Skan 3307169689Skan reversed_p = mips_reverse_fp_cond_p (&cond); 3308169689Skan cmp_result = gen_reg_rtx (CCV2mode); 3309169689Skan emit_insn (gen_scc_ps (cmp_result, 3310169689Skan gen_rtx_fmt_ee (cond, VOIDmode, cmp_op0, cmp_op1))); 3311169689Skan if (reversed_p) 3312169689Skan emit_insn (gen_mips_cond_move_tf_ps (dest, false_src, true_src, 3313169689Skan cmp_result)); 3314169689Skan else 3315169689Skan emit_insn (gen_mips_cond_move_tf_ps (dest, true_src, false_src, 3316169689Skan cmp_result)); 3317169689Skan} 3318169689Skan 3319169689Skan/* Emit the common code for conditional moves. OPERANDS is the array 3320169689Skan of operands passed to the conditional move define_expand. */ 3321169689Skan 3322169689Skanvoid 3323169689Skangen_conditional_move (rtx *operands) 3324169689Skan{ 3325169689Skan enum rtx_code code; 3326169689Skan rtx op0, op1; 3327169689Skan 3328169689Skan code = GET_CODE (operands[1]); 3329169689Skan mips_emit_compare (&code, &op0, &op1, true); 3330169689Skan emit_insn (gen_rtx_SET (VOIDmode, operands[0], 3331169689Skan gen_rtx_IF_THEN_ELSE (GET_MODE (operands[0]), 3332169689Skan gen_rtx_fmt_ee (code, 3333169689Skan GET_MODE (op0), 3334169689Skan op0, op1), 3335169689Skan operands[2], operands[3]))); 3336169689Skan} 3337169689Skan 3338169689Skan/* Emit a conditional trap. OPERANDS is the array of operands passed to 3339169689Skan the conditional_trap expander. */ 3340169689Skan 3341169689Skanvoid 3342169689Skanmips_gen_conditional_trap (rtx *operands) 3343169689Skan{ 3344169689Skan rtx op0, op1; 3345169689Skan enum rtx_code cmp_code = GET_CODE (operands[0]); 3346169689Skan enum machine_mode mode = GET_MODE (cmp_operands[0]); 3347169689Skan 3348169689Skan /* MIPS conditional trap machine instructions don't have GT or LE 3349169689Skan flavors, so we must invert the comparison and convert to LT and 3350169689Skan GE, respectively. */ 3351169689Skan switch (cmp_code) 3352169689Skan { 3353169689Skan case GT: cmp_code = LT; break; 3354169689Skan case LE: cmp_code = GE; break; 3355169689Skan case GTU: cmp_code = LTU; break; 3356169689Skan case LEU: cmp_code = GEU; break; 3357169689Skan default: break; 3358169689Skan } 3359169689Skan if (cmp_code == GET_CODE (operands[0])) 3360169689Skan { 3361169689Skan op0 = cmp_operands[0]; 3362169689Skan op1 = cmp_operands[1]; 3363169689Skan } 3364169689Skan else 3365169689Skan { 3366169689Skan op0 = cmp_operands[1]; 3367169689Skan op1 = cmp_operands[0]; 3368169689Skan } 3369169689Skan op0 = force_reg (mode, op0); 3370169689Skan if (!arith_operand (op1, mode)) 3371169689Skan op1 = force_reg (mode, op1); 3372169689Skan 3373169689Skan emit_insn (gen_rtx_TRAP_IF (VOIDmode, 3374169689Skan gen_rtx_fmt_ee (cmp_code, mode, op0, op1), 3375169689Skan operands[1])); 3376169689Skan} 3377169689Skan 3378169689Skan/* Load function address ADDR into register DEST. SIBCALL_P is true 3379169689Skan if the address is needed for a sibling call. */ 3380169689Skan 3381169689Skanstatic void 3382169689Skanmips_load_call_address (rtx dest, rtx addr, int sibcall_p) 3383169689Skan{ 3384169689Skan /* If we're generating PIC, and this call is to a global function, 3385169689Skan try to allow its address to be resolved lazily. This isn't 3386169689Skan possible for NewABI sibcalls since the value of $gp on entry 3387169689Skan to the stub would be our caller's gp, not ours. */ 3388169689Skan if (TARGET_EXPLICIT_RELOCS 3389169689Skan && !(sibcall_p && TARGET_NEWABI) 3390169689Skan && global_got_operand (addr, VOIDmode)) 3391169689Skan { 3392169689Skan rtx high, lo_sum_symbol; 3393169689Skan 3394169689Skan high = mips_unspec_offset_high (dest, pic_offset_table_rtx, 3395169689Skan addr, SYMBOL_GOTOFF_CALL); 3396169689Skan lo_sum_symbol = mips_unspec_address (addr, SYMBOL_GOTOFF_CALL); 3397169689Skan if (Pmode == SImode) 3398169689Skan emit_insn (gen_load_callsi (dest, high, lo_sum_symbol)); 3399169689Skan else 3400169689Skan emit_insn (gen_load_calldi (dest, high, lo_sum_symbol)); 3401169689Skan } 3402169689Skan else 3403169689Skan emit_move_insn (dest, addr); 3404169689Skan} 3405169689Skan 3406169689Skan 3407169689Skan/* Expand a call or call_value instruction. RESULT is where the 3408169689Skan result will go (null for calls), ADDR is the address of the 3409169689Skan function, ARGS_SIZE is the size of the arguments and AUX is 3410169689Skan the value passed to us by mips_function_arg. SIBCALL_P is true 3411169689Skan if we are expanding a sibling call, false if we're expanding 3412169689Skan a normal call. */ 3413169689Skan 3414169689Skanvoid 3415169689Skanmips_expand_call (rtx result, rtx addr, rtx args_size, rtx aux, int sibcall_p) 3416169689Skan{ 3417169689Skan rtx orig_addr, pattern, insn; 3418169689Skan 3419169689Skan orig_addr = addr; 3420169689Skan if (!call_insn_operand (addr, VOIDmode)) 3421169689Skan { 3422169689Skan addr = gen_reg_rtx (Pmode); 3423169689Skan mips_load_call_address (addr, orig_addr, sibcall_p); 3424169689Skan } 3425169689Skan 3426169689Skan if (TARGET_MIPS16 3427169689Skan && mips16_hard_float 3428169689Skan && build_mips16_call_stub (result, addr, args_size, 3429169689Skan aux == 0 ? 0 : (int) GET_MODE (aux))) 3430169689Skan return; 3431169689Skan 3432169689Skan if (result == 0) 3433169689Skan pattern = (sibcall_p 3434169689Skan ? gen_sibcall_internal (addr, args_size) 3435169689Skan : gen_call_internal (addr, args_size)); 3436169689Skan else if (GET_CODE (result) == PARALLEL && XVECLEN (result, 0) == 2) 3437169689Skan { 3438169689Skan rtx reg1, reg2; 3439169689Skan 3440169689Skan reg1 = XEXP (XVECEXP (result, 0, 0), 0); 3441169689Skan reg2 = XEXP (XVECEXP (result, 0, 1), 0); 3442169689Skan pattern = 3443169689Skan (sibcall_p 3444169689Skan ? gen_sibcall_value_multiple_internal (reg1, addr, args_size, reg2) 3445169689Skan : gen_call_value_multiple_internal (reg1, addr, args_size, reg2)); 3446169689Skan } 3447169689Skan else 3448169689Skan pattern = (sibcall_p 3449169689Skan ? gen_sibcall_value_internal (result, addr, args_size) 3450169689Skan : gen_call_value_internal (result, addr, args_size)); 3451169689Skan 3452169689Skan insn = emit_call_insn (pattern); 3453169689Skan 3454169689Skan /* Lazy-binding stubs require $gp to be valid on entry. */ 3455169689Skan if (global_got_operand (orig_addr, VOIDmode)) 3456169689Skan use_reg (&CALL_INSN_FUNCTION_USAGE (insn), pic_offset_table_rtx); 3457169689Skan} 3458169689Skan 3459169689Skan 3460169689Skan/* We can handle any sibcall when TARGET_SIBCALLS is true. */ 3461169689Skan 3462169689Skanstatic bool 3463169689Skanmips_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED, 3464169689Skan tree exp ATTRIBUTE_UNUSED) 3465169689Skan{ 3466169689Skan return TARGET_SIBCALLS; 3467169689Skan} 3468169689Skan 3469169689Skan/* Emit code to move general operand SRC into condition-code 3470169689Skan register DEST. SCRATCH is a scratch TFmode float register. 3471169689Skan The sequence is: 3472169689Skan 3473169689Skan FP1 = SRC 3474169689Skan FP2 = 0.0f 3475169689Skan DEST = FP2 < FP1 3476169689Skan 3477169689Skan where FP1 and FP2 are single-precision float registers 3478169689Skan taken from SCRATCH. */ 3479169689Skan 3480169689Skanvoid 3481169689Skanmips_emit_fcc_reload (rtx dest, rtx src, rtx scratch) 3482169689Skan{ 3483169689Skan rtx fp1, fp2; 3484169689Skan 3485169689Skan /* Change the source to SFmode. */ 3486169689Skan if (MEM_P (src)) 3487169689Skan src = adjust_address (src, SFmode, 0); 3488169689Skan else if (REG_P (src) || GET_CODE (src) == SUBREG) 3489169689Skan src = gen_rtx_REG (SFmode, true_regnum (src)); 3490169689Skan 3491169689Skan fp1 = gen_rtx_REG (SFmode, REGNO (scratch)); 3492169689Skan fp2 = gen_rtx_REG (SFmode, REGNO (scratch) + FP_INC); 3493169689Skan 3494169689Skan emit_move_insn (copy_rtx (fp1), src); 3495169689Skan emit_move_insn (copy_rtx (fp2), CONST0_RTX (SFmode)); 3496169689Skan emit_insn (gen_slt_sf (dest, fp2, fp1)); 3497169689Skan} 3498169689Skan 3499169689Skan/* Emit code to change the current function's return address to 3500169689Skan ADDRESS. SCRATCH is available as a scratch register, if needed. 3501169689Skan ADDRESS and SCRATCH are both word-mode GPRs. */ 3502169689Skan 3503169689Skanvoid 3504169689Skanmips_set_return_address (rtx address, rtx scratch) 3505169689Skan{ 3506169689Skan rtx slot_address; 3507169689Skan 3508169689Skan compute_frame_size (get_frame_size ()); 3509169689Skan gcc_assert ((cfun->machine->frame.mask >> 31) & 1); 3510169689Skan slot_address = mips_add_offset (scratch, stack_pointer_rtx, 3511169689Skan cfun->machine->frame.gp_sp_offset); 3512169689Skan 3513169689Skan emit_move_insn (gen_rtx_MEM (GET_MODE (address), slot_address), address); 3514169689Skan} 3515169689Skan 3516169689Skan/* Emit straight-line code to move LENGTH bytes from SRC to DEST. 3517169689Skan Assume that the areas do not overlap. */ 3518169689Skan 3519169689Skanstatic void 3520169689Skanmips_block_move_straight (rtx dest, rtx src, HOST_WIDE_INT length) 3521169689Skan{ 3522169689Skan HOST_WIDE_INT offset, delta; 3523169689Skan unsigned HOST_WIDE_INT bits; 3524169689Skan int i; 3525169689Skan enum machine_mode mode; 3526169689Skan rtx *regs; 3527169689Skan 3528169689Skan /* Work out how many bits to move at a time. If both operands have 3529169689Skan half-word alignment, it is usually better to move in half words. 3530169689Skan For instance, lh/lh/sh/sh is usually better than lwl/lwr/swl/swr 3531169689Skan and lw/lw/sw/sw is usually better than ldl/ldr/sdl/sdr. 3532169689Skan Otherwise move word-sized chunks. */ 3533169689Skan if (MEM_ALIGN (src) == BITS_PER_WORD / 2 3534169689Skan && MEM_ALIGN (dest) == BITS_PER_WORD / 2) 3535169689Skan bits = BITS_PER_WORD / 2; 3536169689Skan else 3537169689Skan bits = BITS_PER_WORD; 3538169689Skan 3539169689Skan mode = mode_for_size (bits, MODE_INT, 0); 3540169689Skan delta = bits / BITS_PER_UNIT; 3541169689Skan 3542169689Skan /* Allocate a buffer for the temporary registers. */ 3543169689Skan regs = alloca (sizeof (rtx) * length / delta); 3544169689Skan 3545169689Skan /* Load as many BITS-sized chunks as possible. Use a normal load if 3546169689Skan the source has enough alignment, otherwise use left/right pairs. */ 3547169689Skan for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++) 3548169689Skan { 3549169689Skan regs[i] = gen_reg_rtx (mode); 3550169689Skan if (MEM_ALIGN (src) >= bits) 3551169689Skan emit_move_insn (regs[i], adjust_address (src, mode, offset)); 3552169689Skan else 3553169689Skan { 3554169689Skan rtx part = adjust_address (src, BLKmode, offset); 3555169689Skan if (!mips_expand_unaligned_load (regs[i], part, bits, 0)) 3556169689Skan gcc_unreachable (); 3557169689Skan } 3558169689Skan } 3559169689Skan 3560169689Skan /* Copy the chunks to the destination. */ 3561169689Skan for (offset = 0, i = 0; offset + delta <= length; offset += delta, i++) 3562169689Skan if (MEM_ALIGN (dest) >= bits) 3563169689Skan emit_move_insn (adjust_address (dest, mode, offset), regs[i]); 3564169689Skan else 3565169689Skan { 3566169689Skan rtx part = adjust_address (dest, BLKmode, offset); 3567169689Skan if (!mips_expand_unaligned_store (part, regs[i], bits, 0)) 3568169689Skan gcc_unreachable (); 3569169689Skan } 3570169689Skan 3571169689Skan /* Mop up any left-over bytes. */ 3572169689Skan if (offset < length) 3573169689Skan { 3574169689Skan src = adjust_address (src, BLKmode, offset); 3575169689Skan dest = adjust_address (dest, BLKmode, offset); 3576169689Skan move_by_pieces (dest, src, length - offset, 3577169689Skan MIN (MEM_ALIGN (src), MEM_ALIGN (dest)), 0); 3578169689Skan } 3579169689Skan} 3580169689Skan 3581169689Skan#define MAX_MOVE_REGS 4 3582169689Skan#define MAX_MOVE_BYTES (MAX_MOVE_REGS * UNITS_PER_WORD) 3583169689Skan 3584169689Skan 3585169689Skan/* Helper function for doing a loop-based block operation on memory 3586169689Skan reference MEM. Each iteration of the loop will operate on LENGTH 3587169689Skan bytes of MEM. 3588169689Skan 3589169689Skan Create a new base register for use within the loop and point it to 3590169689Skan the start of MEM. Create a new memory reference that uses this 3591169689Skan register. Store them in *LOOP_REG and *LOOP_MEM respectively. */ 3592169689Skan 3593169689Skanstatic void 3594169689Skanmips_adjust_block_mem (rtx mem, HOST_WIDE_INT length, 3595169689Skan rtx *loop_reg, rtx *loop_mem) 3596169689Skan{ 3597169689Skan *loop_reg = copy_addr_to_reg (XEXP (mem, 0)); 3598169689Skan 3599169689Skan /* Although the new mem does not refer to a known location, 3600169689Skan it does keep up to LENGTH bytes of alignment. */ 3601169689Skan *loop_mem = change_address (mem, BLKmode, *loop_reg); 3602169689Skan set_mem_align (*loop_mem, MIN (MEM_ALIGN (mem), length * BITS_PER_UNIT)); 3603169689Skan} 3604169689Skan 3605169689Skan 3606169689Skan/* Move LENGTH bytes from SRC to DEST using a loop that moves MAX_MOVE_BYTES 3607169689Skan per iteration. LENGTH must be at least MAX_MOVE_BYTES. Assume that the 3608169689Skan memory regions do not overlap. */ 3609169689Skan 3610169689Skanstatic void 3611169689Skanmips_block_move_loop (rtx dest, rtx src, HOST_WIDE_INT length) 3612169689Skan{ 3613169689Skan rtx label, src_reg, dest_reg, final_src; 3614169689Skan HOST_WIDE_INT leftover; 3615169689Skan 3616169689Skan leftover = length % MAX_MOVE_BYTES; 3617169689Skan length -= leftover; 3618169689Skan 3619169689Skan /* Create registers and memory references for use within the loop. */ 3620169689Skan mips_adjust_block_mem (src, MAX_MOVE_BYTES, &src_reg, &src); 3621169689Skan mips_adjust_block_mem (dest, MAX_MOVE_BYTES, &dest_reg, &dest); 3622169689Skan 3623169689Skan /* Calculate the value that SRC_REG should have after the last iteration 3624169689Skan of the loop. */ 3625169689Skan final_src = expand_simple_binop (Pmode, PLUS, src_reg, GEN_INT (length), 3626169689Skan 0, 0, OPTAB_WIDEN); 3627169689Skan 3628169689Skan /* Emit the start of the loop. */ 3629169689Skan label = gen_label_rtx (); 3630169689Skan emit_label (label); 3631169689Skan 3632169689Skan /* Emit the loop body. */ 3633169689Skan mips_block_move_straight (dest, src, MAX_MOVE_BYTES); 3634169689Skan 3635169689Skan /* Move on to the next block. */ 3636169689Skan emit_move_insn (src_reg, plus_constant (src_reg, MAX_MOVE_BYTES)); 3637169689Skan emit_move_insn (dest_reg, plus_constant (dest_reg, MAX_MOVE_BYTES)); 3638169689Skan 3639169689Skan /* Emit the loop condition. */ 3640169689Skan if (Pmode == DImode) 3641169689Skan emit_insn (gen_cmpdi (src_reg, final_src)); 3642169689Skan else 3643169689Skan emit_insn (gen_cmpsi (src_reg, final_src)); 3644169689Skan emit_jump_insn (gen_bne (label)); 3645169689Skan 3646169689Skan /* Mop up any left-over bytes. */ 3647169689Skan if (leftover) 3648169689Skan mips_block_move_straight (dest, src, leftover); 3649169689Skan} 3650169689Skan 3651169689Skan/* Expand a movmemsi instruction. */ 3652169689Skan 3653169689Skanbool 3654169689Skanmips_expand_block_move (rtx dest, rtx src, rtx length) 3655169689Skan{ 3656169689Skan if (GET_CODE (length) == CONST_INT) 3657169689Skan { 3658169689Skan if (INTVAL (length) <= 2 * MAX_MOVE_BYTES) 3659169689Skan { 3660169689Skan mips_block_move_straight (dest, src, INTVAL (length)); 3661169689Skan return true; 3662169689Skan } 3663169689Skan else if (optimize) 3664169689Skan { 3665169689Skan mips_block_move_loop (dest, src, INTVAL (length)); 3666169689Skan return true; 3667169689Skan } 3668169689Skan } 3669169689Skan return false; 3670169689Skan} 3671169689Skan 3672169689Skan/* Argument support functions. */ 3673169689Skan 3674169689Skan/* Initialize CUMULATIVE_ARGS for a function. */ 3675169689Skan 3676169689Skanvoid 3677169689Skaninit_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, 3678169689Skan rtx libname ATTRIBUTE_UNUSED) 3679169689Skan{ 3680169689Skan static CUMULATIVE_ARGS zero_cum; 3681169689Skan tree param, next_param; 3682169689Skan 3683169689Skan *cum = zero_cum; 3684169689Skan cum->prototype = (fntype && TYPE_ARG_TYPES (fntype)); 3685169689Skan 3686169689Skan /* Determine if this function has variable arguments. This is 3687169689Skan indicated by the last argument being 'void_type_mode' if there 3688169689Skan are no variable arguments. The standard MIPS calling sequence 3689169689Skan passes all arguments in the general purpose registers in this case. */ 3690169689Skan 3691169689Skan for (param = fntype ? TYPE_ARG_TYPES (fntype) : 0; 3692169689Skan param != 0; param = next_param) 3693169689Skan { 3694169689Skan next_param = TREE_CHAIN (param); 3695169689Skan if (next_param == 0 && TREE_VALUE (param) != void_type_node) 3696169689Skan cum->gp_reg_found = 1; 3697169689Skan } 3698169689Skan} 3699169689Skan 3700169689Skan 3701169689Skan/* Fill INFO with information about a single argument. CUM is the 3702169689Skan cumulative state for earlier arguments. MODE is the mode of this 3703169689Skan argument and TYPE is its type (if known). NAMED is true if this 3704169689Skan is a named (fixed) argument rather than a variable one. */ 3705169689Skan 3706169689Skanstatic void 3707169689Skanmips_arg_info (const CUMULATIVE_ARGS *cum, enum machine_mode mode, 3708169689Skan tree type, int named, struct mips_arg_info *info) 3709169689Skan{ 3710169689Skan bool doubleword_aligned_p; 3711169689Skan unsigned int num_bytes, num_words, max_regs; 3712169689Skan 3713169689Skan /* Work out the size of the argument. */ 3714169689Skan num_bytes = type ? int_size_in_bytes (type) : GET_MODE_SIZE (mode); 3715169689Skan num_words = (num_bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD; 3716169689Skan 3717169689Skan /* Decide whether it should go in a floating-point register, assuming 3718169689Skan one is free. Later code checks for availability. 3719169689Skan 3720169689Skan The checks against UNITS_PER_FPVALUE handle the soft-float and 3721169689Skan single-float cases. */ 3722169689Skan switch (mips_abi) 3723169689Skan { 3724169689Skan case ABI_EABI: 3725169689Skan /* The EABI conventions have traditionally been defined in terms 3726169689Skan of TYPE_MODE, regardless of the actual type. */ 3727169689Skan info->fpr_p = ((GET_MODE_CLASS (mode) == MODE_FLOAT 3728169689Skan || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT) 3729169689Skan && GET_MODE_SIZE (mode) <= UNITS_PER_FPVALUE); 3730169689Skan break; 3731169689Skan 3732169689Skan case ABI_32: 3733169689Skan case ABI_O64: 3734169689Skan /* Only leading floating-point scalars are passed in 3735169689Skan floating-point registers. We also handle vector floats the same 3736169689Skan say, which is OK because they are not covered by the standard ABI. */ 3737169689Skan info->fpr_p = (!cum->gp_reg_found 3738169689Skan && cum->arg_number < 2 3739169689Skan && (type == 0 || SCALAR_FLOAT_TYPE_P (type) 3740169689Skan || VECTOR_FLOAT_TYPE_P (type)) 3741169689Skan && (GET_MODE_CLASS (mode) == MODE_FLOAT 3742169689Skan || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT) 3743169689Skan && GET_MODE_SIZE (mode) <= UNITS_PER_FPVALUE); 3744169689Skan break; 3745169689Skan 3746169689Skan case ABI_N32: 3747169689Skan case ABI_64: 3748169689Skan /* Scalar and complex floating-point types are passed in 3749169689Skan floating-point registers. */ 3750169689Skan info->fpr_p = (named 3751169689Skan && (type == 0 || FLOAT_TYPE_P (type)) 3752169689Skan && (GET_MODE_CLASS (mode) == MODE_FLOAT 3753169689Skan || GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT 3754169689Skan || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT) 3755169689Skan && GET_MODE_UNIT_SIZE (mode) <= UNITS_PER_FPVALUE); 3756169689Skan 3757169689Skan /* ??? According to the ABI documentation, the real and imaginary 3758169689Skan parts of complex floats should be passed in individual registers. 3759169689Skan The real and imaginary parts of stack arguments are supposed 3760169689Skan to be contiguous and there should be an extra word of padding 3761169689Skan at the end. 3762169689Skan 3763169689Skan This has two problems. First, it makes it impossible to use a 3764169689Skan single "void *" va_list type, since register and stack arguments 3765169689Skan are passed differently. (At the time of writing, MIPSpro cannot 3766169689Skan handle complex float varargs correctly.) Second, it's unclear 3767169689Skan what should happen when there is only one register free. 3768169689Skan 3769169689Skan For now, we assume that named complex floats should go into FPRs 3770169689Skan if there are two FPRs free, otherwise they should be passed in the 3771169689Skan same way as a struct containing two floats. */ 3772169689Skan if (info->fpr_p 3773169689Skan && GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT 3774169689Skan && GET_MODE_UNIT_SIZE (mode) < UNITS_PER_FPVALUE) 3775169689Skan { 3776169689Skan if (cum->num_gprs >= MAX_ARGS_IN_REGISTERS - 1) 3777169689Skan info->fpr_p = false; 3778169689Skan else 3779169689Skan num_words = 2; 3780169689Skan } 3781169689Skan break; 3782169689Skan 3783169689Skan default: 3784169689Skan gcc_unreachable (); 3785169689Skan } 3786169689Skan 3787169689Skan /* See whether the argument has doubleword alignment. */ 3788169689Skan doubleword_aligned_p = FUNCTION_ARG_BOUNDARY (mode, type) > BITS_PER_WORD; 3789169689Skan 3790169689Skan /* Set REG_OFFSET to the register count we're interested in. 3791169689Skan The EABI allocates the floating-point registers separately, 3792169689Skan but the other ABIs allocate them like integer registers. */ 3793169689Skan info->reg_offset = (mips_abi == ABI_EABI && info->fpr_p 3794169689Skan ? cum->num_fprs 3795169689Skan : cum->num_gprs); 3796169689Skan 3797169689Skan /* Advance to an even register if the argument is doubleword-aligned. */ 3798169689Skan if (doubleword_aligned_p) 3799169689Skan info->reg_offset += info->reg_offset & 1; 3800169689Skan 3801169689Skan /* Work out the offset of a stack argument. */ 3802169689Skan info->stack_offset = cum->stack_words; 3803169689Skan if (doubleword_aligned_p) 3804169689Skan info->stack_offset += info->stack_offset & 1; 3805169689Skan 3806169689Skan max_regs = MAX_ARGS_IN_REGISTERS - info->reg_offset; 3807169689Skan 3808169689Skan /* Partition the argument between registers and stack. */ 3809169689Skan info->reg_words = MIN (num_words, max_regs); 3810169689Skan info->stack_words = num_words - info->reg_words; 3811169689Skan} 3812169689Skan 3813169689Skan 3814169689Skan/* Implement FUNCTION_ARG_ADVANCE. */ 3815169689Skan 3816169689Skanvoid 3817169689Skanfunction_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, 3818169689Skan tree type, int named) 3819169689Skan{ 3820169689Skan struct mips_arg_info info; 3821169689Skan 3822169689Skan mips_arg_info (cum, mode, type, named, &info); 3823169689Skan 3824169689Skan if (!info.fpr_p) 3825169689Skan cum->gp_reg_found = true; 3826169689Skan 3827169689Skan /* See the comment above the cumulative args structure in mips.h 3828169689Skan for an explanation of what this code does. It assumes the O32 3829169689Skan ABI, which passes at most 2 arguments in float registers. */ 3830169689Skan if (cum->arg_number < 2 && info.fpr_p) 3831169689Skan cum->fp_code += (mode == SFmode ? 1 : 2) << ((cum->arg_number - 1) * 2); 3832169689Skan 3833169689Skan if (mips_abi != ABI_EABI || !info.fpr_p) 3834169689Skan cum->num_gprs = info.reg_offset + info.reg_words; 3835169689Skan else if (info.reg_words > 0) 3836169689Skan cum->num_fprs += FP_INC; 3837169689Skan 3838169689Skan if (info.stack_words > 0) 3839169689Skan cum->stack_words = info.stack_offset + info.stack_words; 3840169689Skan 3841169689Skan cum->arg_number++; 3842169689Skan} 3843169689Skan 3844169689Skan/* Implement FUNCTION_ARG. */ 3845169689Skan 3846169689Skanstruct rtx_def * 3847169689Skanfunction_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode, 3848169689Skan tree type, int named) 3849169689Skan{ 3850169689Skan struct mips_arg_info info; 3851169689Skan 3852169689Skan /* We will be called with a mode of VOIDmode after the last argument 3853169689Skan has been seen. Whatever we return will be passed to the call 3854169689Skan insn. If we need a mips16 fp_code, return a REG with the code 3855169689Skan stored as the mode. */ 3856169689Skan if (mode == VOIDmode) 3857169689Skan { 3858169689Skan if (TARGET_MIPS16 && cum->fp_code != 0) 3859169689Skan return gen_rtx_REG ((enum machine_mode) cum->fp_code, 0); 3860169689Skan 3861169689Skan else 3862169689Skan return 0; 3863169689Skan } 3864169689Skan 3865169689Skan mips_arg_info (cum, mode, type, named, &info); 3866169689Skan 3867169689Skan /* Return straight away if the whole argument is passed on the stack. */ 3868169689Skan if (info.reg_offset == MAX_ARGS_IN_REGISTERS) 3869169689Skan return 0; 3870169689Skan 3871169689Skan if (type != 0 3872169689Skan && TREE_CODE (type) == RECORD_TYPE 3873169689Skan && TARGET_NEWABI 3874169689Skan && TYPE_SIZE_UNIT (type) 3875169689Skan && host_integerp (TYPE_SIZE_UNIT (type), 1) 3876169689Skan && named) 3877169689Skan { 3878169689Skan /* The Irix 6 n32/n64 ABIs say that if any 64 bit chunk of the 3879169689Skan structure contains a double in its entirety, then that 64 bit 3880169689Skan chunk is passed in a floating point register. */ 3881169689Skan tree field; 3882169689Skan 3883169689Skan /* First check to see if there is any such field. */ 3884169689Skan for (field = TYPE_FIELDS (type); field; field = TREE_CHAIN (field)) 3885169689Skan if (TREE_CODE (field) == FIELD_DECL 3886169689Skan && TREE_CODE (TREE_TYPE (field)) == REAL_TYPE 3887169689Skan && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD 3888169689Skan && host_integerp (bit_position (field), 0) 3889169689Skan && int_bit_position (field) % BITS_PER_WORD == 0) 3890169689Skan break; 3891169689Skan 3892169689Skan if (field != 0) 3893169689Skan { 3894169689Skan /* Now handle the special case by returning a PARALLEL 3895169689Skan indicating where each 64 bit chunk goes. INFO.REG_WORDS 3896169689Skan chunks are passed in registers. */ 3897169689Skan unsigned int i; 3898169689Skan HOST_WIDE_INT bitpos; 3899169689Skan rtx ret; 3900169689Skan 3901169689Skan /* assign_parms checks the mode of ENTRY_PARM, so we must 3902169689Skan use the actual mode here. */ 3903169689Skan ret = gen_rtx_PARALLEL (mode, rtvec_alloc (info.reg_words)); 3904169689Skan 3905169689Skan bitpos = 0; 3906169689Skan field = TYPE_FIELDS (type); 3907169689Skan for (i = 0; i < info.reg_words; i++) 3908169689Skan { 3909169689Skan rtx reg; 3910169689Skan 3911169689Skan for (; field; field = TREE_CHAIN (field)) 3912169689Skan if (TREE_CODE (field) == FIELD_DECL 3913169689Skan && int_bit_position (field) >= bitpos) 3914169689Skan break; 3915169689Skan 3916169689Skan if (field 3917169689Skan && int_bit_position (field) == bitpos 3918169689Skan && TREE_CODE (TREE_TYPE (field)) == REAL_TYPE 3919169689Skan && !TARGET_SOFT_FLOAT 3920169689Skan && TYPE_PRECISION (TREE_TYPE (field)) == BITS_PER_WORD) 3921169689Skan reg = gen_rtx_REG (DFmode, FP_ARG_FIRST + info.reg_offset + i); 3922169689Skan else 3923169689Skan reg = gen_rtx_REG (DImode, GP_ARG_FIRST + info.reg_offset + i); 3924169689Skan 3925169689Skan XVECEXP (ret, 0, i) 3926169689Skan = gen_rtx_EXPR_LIST (VOIDmode, reg, 3927169689Skan GEN_INT (bitpos / BITS_PER_UNIT)); 3928169689Skan 3929169689Skan bitpos += BITS_PER_WORD; 3930169689Skan } 3931169689Skan return ret; 3932169689Skan } 3933169689Skan } 3934169689Skan 3935169689Skan /* Handle the n32/n64 conventions for passing complex floating-point 3936169689Skan arguments in FPR pairs. The real part goes in the lower register 3937169689Skan and the imaginary part goes in the upper register. */ 3938169689Skan if (TARGET_NEWABI 3939169689Skan && info.fpr_p 3940169689Skan && GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT) 3941169689Skan { 3942169689Skan rtx real, imag; 3943169689Skan enum machine_mode inner; 3944169689Skan int reg; 3945169689Skan 3946169689Skan inner = GET_MODE_INNER (mode); 3947169689Skan reg = FP_ARG_FIRST + info.reg_offset; 3948169689Skan if (info.reg_words * UNITS_PER_WORD == GET_MODE_SIZE (inner)) 3949169689Skan { 3950169689Skan /* Real part in registers, imaginary part on stack. */ 3951169689Skan gcc_assert (info.stack_words == info.reg_words); 3952169689Skan return gen_rtx_REG (inner, reg); 3953169689Skan } 3954169689Skan else 3955169689Skan { 3956169689Skan gcc_assert (info.stack_words == 0); 3957169689Skan real = gen_rtx_EXPR_LIST (VOIDmode, 3958169689Skan gen_rtx_REG (inner, reg), 3959169689Skan const0_rtx); 3960169689Skan imag = gen_rtx_EXPR_LIST (VOIDmode, 3961169689Skan gen_rtx_REG (inner, 3962169689Skan reg + info.reg_words / 2), 3963169689Skan GEN_INT (GET_MODE_SIZE (inner))); 3964169689Skan return gen_rtx_PARALLEL (mode, gen_rtvec (2, real, imag)); 3965169689Skan } 3966169689Skan } 3967169689Skan 3968169689Skan if (!info.fpr_p) 3969169689Skan return gen_rtx_REG (mode, GP_ARG_FIRST + info.reg_offset); 3970169689Skan else if (info.reg_offset == 1) 3971169689Skan /* This code handles the special o32 case in which the second word 3972169689Skan of the argument structure is passed in floating-point registers. */ 3973169689Skan return gen_rtx_REG (mode, FP_ARG_FIRST + FP_INC); 3974169689Skan else 3975169689Skan return gen_rtx_REG (mode, FP_ARG_FIRST + info.reg_offset); 3976169689Skan} 3977169689Skan 3978169689Skan 3979169689Skan/* Implement TARGET_ARG_PARTIAL_BYTES. */ 3980169689Skan 3981169689Skanstatic int 3982169689Skanmips_arg_partial_bytes (CUMULATIVE_ARGS *cum, 3983169689Skan enum machine_mode mode, tree type, bool named) 3984169689Skan{ 3985169689Skan struct mips_arg_info info; 3986169689Skan 3987169689Skan mips_arg_info (cum, mode, type, named, &info); 3988169689Skan return info.stack_words > 0 ? info.reg_words * UNITS_PER_WORD : 0; 3989169689Skan} 3990169689Skan 3991169689Skan 3992169689Skan/* Implement FUNCTION_ARG_BOUNDARY. Every parameter gets at least 3993169689Skan PARM_BOUNDARY bits of alignment, but will be given anything up 3994169689Skan to STACK_BOUNDARY bits if the type requires it. */ 3995169689Skan 3996169689Skanint 3997169689Skanfunction_arg_boundary (enum machine_mode mode, tree type) 3998169689Skan{ 3999169689Skan unsigned int alignment; 4000169689Skan 4001169689Skan alignment = type ? TYPE_ALIGN (type) : GET_MODE_ALIGNMENT (mode); 4002169689Skan if (alignment < PARM_BOUNDARY) 4003169689Skan alignment = PARM_BOUNDARY; 4004169689Skan if (alignment > STACK_BOUNDARY) 4005169689Skan alignment = STACK_BOUNDARY; 4006169689Skan return alignment; 4007169689Skan} 4008169689Skan 4009169689Skan/* Return true if FUNCTION_ARG_PADDING (MODE, TYPE) should return 4010169689Skan upward rather than downward. In other words, return true if the 4011169689Skan first byte of the stack slot has useful data, false if the last 4012169689Skan byte does. */ 4013169689Skan 4014169689Skanbool 4015169689Skanmips_pad_arg_upward (enum machine_mode mode, tree type) 4016169689Skan{ 4017169689Skan /* On little-endian targets, the first byte of every stack argument 4018169689Skan is passed in the first byte of the stack slot. */ 4019169689Skan if (!BYTES_BIG_ENDIAN) 4020169689Skan return true; 4021169689Skan 4022169689Skan /* Otherwise, integral types are padded downward: the last byte of a 4023169689Skan stack argument is passed in the last byte of the stack slot. */ 4024169689Skan if (type != 0 4025169689Skan ? INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type) 4026169689Skan : GET_MODE_CLASS (mode) == MODE_INT) 4027169689Skan return false; 4028169689Skan 4029169689Skan /* Big-endian o64 pads floating-point arguments downward. */ 4030169689Skan if (mips_abi == ABI_O64) 4031169689Skan if (type != 0 ? FLOAT_TYPE_P (type) : GET_MODE_CLASS (mode) == MODE_FLOAT) 4032169689Skan return false; 4033169689Skan 4034169689Skan /* Other types are padded upward for o32, o64, n32 and n64. */ 4035169689Skan if (mips_abi != ABI_EABI) 4036169689Skan return true; 4037169689Skan 4038169689Skan /* Arguments smaller than a stack slot are padded downward. */ 4039169689Skan if (mode != BLKmode) 4040169689Skan return (GET_MODE_BITSIZE (mode) >= PARM_BOUNDARY); 4041169689Skan else 4042169689Skan return (int_size_in_bytes (type) >= (PARM_BOUNDARY / BITS_PER_UNIT)); 4043169689Skan} 4044169689Skan 4045169689Skan 4046169689Skan/* Likewise BLOCK_REG_PADDING (MODE, TYPE, ...). Return !BYTES_BIG_ENDIAN 4047169689Skan if the least significant byte of the register has useful data. Return 4048169689Skan the opposite if the most significant byte does. */ 4049169689Skan 4050169689Skanbool 4051169689Skanmips_pad_reg_upward (enum machine_mode mode, tree type) 4052169689Skan{ 4053169689Skan /* No shifting is required for floating-point arguments. */ 4054169689Skan if (type != 0 ? FLOAT_TYPE_P (type) : GET_MODE_CLASS (mode) == MODE_FLOAT) 4055169689Skan return !BYTES_BIG_ENDIAN; 4056169689Skan 4057169689Skan /* Otherwise, apply the same padding to register arguments as we do 4058169689Skan to stack arguments. */ 4059169689Skan return mips_pad_arg_upward (mode, type); 4060169689Skan} 4061169689Skan 4062169689Skanstatic void 4063169689Skanmips_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode, 4064169689Skan tree type, int *pretend_size ATTRIBUTE_UNUSED, 4065169689Skan int no_rtl) 4066169689Skan{ 4067169689Skan CUMULATIVE_ARGS local_cum; 4068169689Skan int gp_saved, fp_saved; 4069169689Skan 4070169689Skan /* The caller has advanced CUM up to, but not beyond, the last named 4071169689Skan argument. Advance a local copy of CUM past the last "real" named 4072169689Skan argument, to find out how many registers are left over. */ 4073169689Skan 4074169689Skan local_cum = *cum; 4075169689Skan FUNCTION_ARG_ADVANCE (local_cum, mode, type, 1); 4076169689Skan 4077169689Skan /* Found out how many registers we need to save. */ 4078169689Skan gp_saved = MAX_ARGS_IN_REGISTERS - local_cum.num_gprs; 4079169689Skan fp_saved = (EABI_FLOAT_VARARGS_P 4080169689Skan ? MAX_ARGS_IN_REGISTERS - local_cum.num_fprs 4081169689Skan : 0); 4082169689Skan 4083169689Skan if (!no_rtl) 4084169689Skan { 4085169689Skan if (gp_saved > 0) 4086169689Skan { 4087169689Skan rtx ptr, mem; 4088169689Skan 4089169689Skan ptr = plus_constant (virtual_incoming_args_rtx, 4090169689Skan REG_PARM_STACK_SPACE (cfun->decl) 4091169689Skan - gp_saved * UNITS_PER_WORD); 4092169689Skan mem = gen_rtx_MEM (BLKmode, ptr); 4093169689Skan set_mem_alias_set (mem, get_varargs_alias_set ()); 4094169689Skan 4095169689Skan move_block_from_reg (local_cum.num_gprs + GP_ARG_FIRST, 4096169689Skan mem, gp_saved); 4097169689Skan } 4098169689Skan if (fp_saved > 0) 4099169689Skan { 4100169689Skan /* We can't use move_block_from_reg, because it will use 4101169689Skan the wrong mode. */ 4102169689Skan enum machine_mode mode; 4103169689Skan int off, i; 4104169689Skan 4105169689Skan /* Set OFF to the offset from virtual_incoming_args_rtx of 4106169689Skan the first float register. The FP save area lies below 4107169689Skan the integer one, and is aligned to UNITS_PER_FPVALUE bytes. */ 4108169689Skan off = -gp_saved * UNITS_PER_WORD; 4109169689Skan off &= ~(UNITS_PER_FPVALUE - 1); 4110169689Skan off -= fp_saved * UNITS_PER_FPREG; 4111169689Skan 4112169689Skan mode = TARGET_SINGLE_FLOAT ? SFmode : DFmode; 4113169689Skan 4114169689Skan for (i = local_cum.num_fprs; i < MAX_ARGS_IN_REGISTERS; i += FP_INC) 4115169689Skan { 4116169689Skan rtx ptr, mem; 4117169689Skan 4118169689Skan ptr = plus_constant (virtual_incoming_args_rtx, off); 4119169689Skan mem = gen_rtx_MEM (mode, ptr); 4120169689Skan set_mem_alias_set (mem, get_varargs_alias_set ()); 4121169689Skan emit_move_insn (mem, gen_rtx_REG (mode, FP_ARG_FIRST + i)); 4122169689Skan off += UNITS_PER_HWFPVALUE; 4123169689Skan } 4124169689Skan } 4125169689Skan } 4126169689Skan if (REG_PARM_STACK_SPACE (cfun->decl) == 0) 4127169689Skan cfun->machine->varargs_size = (gp_saved * UNITS_PER_WORD 4128169689Skan + fp_saved * UNITS_PER_FPREG); 4129169689Skan} 4130169689Skan 4131169689Skan/* Create the va_list data type. 4132169689Skan We keep 3 pointers, and two offsets. 4133169689Skan Two pointers are to the overflow area, which starts at the CFA. 4134169689Skan One of these is constant, for addressing into the GPR save area below it. 4135169689Skan The other is advanced up the stack through the overflow region. 4136169689Skan The third pointer is to the GPR save area. Since the FPR save area 4137169689Skan is just below it, we can address FPR slots off this pointer. 4138169689Skan We also keep two one-byte offsets, which are to be subtracted from the 4139169689Skan constant pointers to yield addresses in the GPR and FPR save areas. 4140169689Skan These are downcounted as float or non-float arguments are used, 4141169689Skan and when they get to zero, the argument must be obtained from the 4142169689Skan overflow region. 4143169689Skan If !EABI_FLOAT_VARARGS_P, then no FPR save area exists, and a single 4144169689Skan pointer is enough. It's started at the GPR save area, and is 4145169689Skan advanced, period. 4146169689Skan Note that the GPR save area is not constant size, due to optimization 4147169689Skan in the prologue. Hence, we can't use a design with two pointers 4148169689Skan and two offsets, although we could have designed this with two pointers 4149169689Skan and three offsets. */ 4150169689Skan 4151169689Skanstatic tree 4152169689Skanmips_build_builtin_va_list (void) 4153169689Skan{ 4154169689Skan if (EABI_FLOAT_VARARGS_P) 4155169689Skan { 4156169689Skan tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff, f_res, record; 4157169689Skan tree array, index; 4158169689Skan 4159169689Skan record = (*lang_hooks.types.make_type) (RECORD_TYPE); 4160169689Skan 4161169689Skan f_ovfl = build_decl (FIELD_DECL, get_identifier ("__overflow_argptr"), 4162169689Skan ptr_type_node); 4163169689Skan f_gtop = build_decl (FIELD_DECL, get_identifier ("__gpr_top"), 4164169689Skan ptr_type_node); 4165169689Skan f_ftop = build_decl (FIELD_DECL, get_identifier ("__fpr_top"), 4166169689Skan ptr_type_node); 4167169689Skan f_goff = build_decl (FIELD_DECL, get_identifier ("__gpr_offset"), 4168169689Skan unsigned_char_type_node); 4169169689Skan f_foff = build_decl (FIELD_DECL, get_identifier ("__fpr_offset"), 4170169689Skan unsigned_char_type_node); 4171169689Skan /* Explicitly pad to the size of a pointer, so that -Wpadded won't 4172169689Skan warn on every user file. */ 4173169689Skan index = build_int_cst (NULL_TREE, GET_MODE_SIZE (ptr_mode) - 2 - 1); 4174169689Skan array = build_array_type (unsigned_char_type_node, 4175169689Skan build_index_type (index)); 4176169689Skan f_res = build_decl (FIELD_DECL, get_identifier ("__reserved"), array); 4177169689Skan 4178169689Skan DECL_FIELD_CONTEXT (f_ovfl) = record; 4179169689Skan DECL_FIELD_CONTEXT (f_gtop) = record; 4180169689Skan DECL_FIELD_CONTEXT (f_ftop) = record; 4181169689Skan DECL_FIELD_CONTEXT (f_goff) = record; 4182169689Skan DECL_FIELD_CONTEXT (f_foff) = record; 4183169689Skan DECL_FIELD_CONTEXT (f_res) = record; 4184169689Skan 4185169689Skan TYPE_FIELDS (record) = f_ovfl; 4186169689Skan TREE_CHAIN (f_ovfl) = f_gtop; 4187169689Skan TREE_CHAIN (f_gtop) = f_ftop; 4188169689Skan TREE_CHAIN (f_ftop) = f_goff; 4189169689Skan TREE_CHAIN (f_goff) = f_foff; 4190169689Skan TREE_CHAIN (f_foff) = f_res; 4191169689Skan 4192169689Skan layout_type (record); 4193169689Skan return record; 4194169689Skan } 4195169689Skan else if (TARGET_IRIX && TARGET_IRIX6) 4196169689Skan /* On IRIX 6, this type is 'char *'. */ 4197169689Skan return build_pointer_type (char_type_node); 4198169689Skan else 4199169689Skan /* Otherwise, we use 'void *'. */ 4200169689Skan return ptr_type_node; 4201169689Skan} 4202169689Skan 4203169689Skan/* Implement va_start. */ 4204169689Skan 4205169689Skanvoid 4206169689Skanmips_va_start (tree valist, rtx nextarg) 4207169689Skan{ 4208169689Skan if (EABI_FLOAT_VARARGS_P) 4209169689Skan { 4210169689Skan const CUMULATIVE_ARGS *cum; 4211169689Skan tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff; 4212169689Skan tree ovfl, gtop, ftop, goff, foff; 4213169689Skan tree t; 4214169689Skan int gpr_save_area_size; 4215169689Skan int fpr_save_area_size; 4216169689Skan int fpr_offset; 4217169689Skan 4218169689Skan cum = ¤t_function_args_info; 4219169689Skan gpr_save_area_size 4220169689Skan = (MAX_ARGS_IN_REGISTERS - cum->num_gprs) * UNITS_PER_WORD; 4221169689Skan fpr_save_area_size 4222169689Skan = (MAX_ARGS_IN_REGISTERS - cum->num_fprs) * UNITS_PER_FPREG; 4223169689Skan 4224169689Skan f_ovfl = TYPE_FIELDS (va_list_type_node); 4225169689Skan f_gtop = TREE_CHAIN (f_ovfl); 4226169689Skan f_ftop = TREE_CHAIN (f_gtop); 4227169689Skan f_goff = TREE_CHAIN (f_ftop); 4228169689Skan f_foff = TREE_CHAIN (f_goff); 4229169689Skan 4230169689Skan ovfl = build3 (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl, 4231169689Skan NULL_TREE); 4232169689Skan gtop = build3 (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop, 4233169689Skan NULL_TREE); 4234169689Skan ftop = build3 (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop, 4235169689Skan NULL_TREE); 4236169689Skan goff = build3 (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff, 4237169689Skan NULL_TREE); 4238169689Skan foff = build3 (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff, 4239169689Skan NULL_TREE); 4240169689Skan 4241169689Skan /* Emit code to initialize OVFL, which points to the next varargs 4242169689Skan stack argument. CUM->STACK_WORDS gives the number of stack 4243169689Skan words used by named arguments. */ 4244169689Skan t = make_tree (TREE_TYPE (ovfl), virtual_incoming_args_rtx); 4245169689Skan if (cum->stack_words > 0) 4246169689Skan t = build2 (PLUS_EXPR, TREE_TYPE (ovfl), t, 4247169689Skan build_int_cst (NULL_TREE, 4248169689Skan cum->stack_words * UNITS_PER_WORD)); 4249169689Skan t = build2 (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t); 4250169689Skan expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 4251169689Skan 4252169689Skan /* Emit code to initialize GTOP, the top of the GPR save area. */ 4253169689Skan t = make_tree (TREE_TYPE (gtop), virtual_incoming_args_rtx); 4254169689Skan t = build2 (MODIFY_EXPR, TREE_TYPE (gtop), gtop, t); 4255169689Skan expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 4256169689Skan 4257169689Skan /* Emit code to initialize FTOP, the top of the FPR save area. 4258169689Skan This address is gpr_save_area_bytes below GTOP, rounded 4259169689Skan down to the next fp-aligned boundary. */ 4260169689Skan t = make_tree (TREE_TYPE (ftop), virtual_incoming_args_rtx); 4261169689Skan fpr_offset = gpr_save_area_size + UNITS_PER_FPVALUE - 1; 4262169689Skan fpr_offset &= ~(UNITS_PER_FPVALUE - 1); 4263169689Skan if (fpr_offset) 4264169689Skan t = build2 (PLUS_EXPR, TREE_TYPE (ftop), t, 4265169689Skan build_int_cst (NULL_TREE, -fpr_offset)); 4266169689Skan t = build2 (MODIFY_EXPR, TREE_TYPE (ftop), ftop, t); 4267169689Skan expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 4268169689Skan 4269169689Skan /* Emit code to initialize GOFF, the offset from GTOP of the 4270169689Skan next GPR argument. */ 4271169689Skan t = build2 (MODIFY_EXPR, TREE_TYPE (goff), goff, 4272169689Skan build_int_cst (NULL_TREE, gpr_save_area_size)); 4273169689Skan expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 4274169689Skan 4275169689Skan /* Likewise emit code to initialize FOFF, the offset from FTOP 4276169689Skan of the next FPR argument. */ 4277169689Skan t = build2 (MODIFY_EXPR, TREE_TYPE (foff), foff, 4278169689Skan build_int_cst (NULL_TREE, fpr_save_area_size)); 4279169689Skan expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL); 4280169689Skan } 4281169689Skan else 4282169689Skan { 4283169689Skan nextarg = plus_constant (nextarg, -cfun->machine->varargs_size); 4284169689Skan std_expand_builtin_va_start (valist, nextarg); 4285169689Skan } 4286169689Skan} 4287169689Skan 4288169689Skan/* Implement va_arg. */ 4289169689Skan 4290169689Skanstatic tree 4291169689Skanmips_gimplify_va_arg_expr (tree valist, tree type, tree *pre_p, tree *post_p) 4292169689Skan{ 4293169689Skan HOST_WIDE_INT size, rsize; 4294169689Skan tree addr; 4295169689Skan bool indirect; 4296169689Skan 4297169689Skan indirect = pass_by_reference (NULL, TYPE_MODE (type), type, 0); 4298169689Skan 4299169689Skan if (indirect) 4300169689Skan type = build_pointer_type (type); 4301169689Skan 4302169689Skan size = int_size_in_bytes (type); 4303169689Skan rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD; 4304169689Skan 4305169689Skan if (mips_abi != ABI_EABI || !EABI_FLOAT_VARARGS_P) 4306169689Skan addr = std_gimplify_va_arg_expr (valist, type, pre_p, post_p); 4307169689Skan else 4308169689Skan { 4309169689Skan /* Not a simple merged stack. */ 4310169689Skan 4311169689Skan tree f_ovfl, f_gtop, f_ftop, f_goff, f_foff; 4312169689Skan tree ovfl, top, off, align; 4313169689Skan HOST_WIDE_INT osize; 4314169689Skan tree t, u; 4315169689Skan 4316169689Skan f_ovfl = TYPE_FIELDS (va_list_type_node); 4317169689Skan f_gtop = TREE_CHAIN (f_ovfl); 4318169689Skan f_ftop = TREE_CHAIN (f_gtop); 4319169689Skan f_goff = TREE_CHAIN (f_ftop); 4320169689Skan f_foff = TREE_CHAIN (f_goff); 4321169689Skan 4322169689Skan /* We maintain separate pointers and offsets for floating-point 4323169689Skan and integer arguments, but we need similar code in both cases. 4324169689Skan Let: 4325169689Skan 4326169689Skan TOP be the top of the register save area; 4327169689Skan OFF be the offset from TOP of the next register; 4328169689Skan ADDR_RTX be the address of the argument; 4329169689Skan RSIZE be the number of bytes used to store the argument 4330169689Skan when it's in the register save area; 4331169689Skan OSIZE be the number of bytes used to store it when it's 4332169689Skan in the stack overflow area; and 4333169689Skan PADDING be (BYTES_BIG_ENDIAN ? OSIZE - RSIZE : 0) 4334169689Skan 4335169689Skan The code we want is: 4336169689Skan 4337169689Skan 1: off &= -rsize; // round down 4338169689Skan 2: if (off != 0) 4339169689Skan 3: { 4340169689Skan 4: addr_rtx = top - off; 4341169689Skan 5: off -= rsize; 4342169689Skan 6: } 4343169689Skan 7: else 4344169689Skan 8: { 4345169689Skan 9: ovfl += ((intptr_t) ovfl + osize - 1) & -osize; 4346169689Skan 10: addr_rtx = ovfl + PADDING; 4347169689Skan 11: ovfl += osize; 4348169689Skan 14: } 4349169689Skan 4350169689Skan [1] and [9] can sometimes be optimized away. */ 4351169689Skan 4352169689Skan ovfl = build3 (COMPONENT_REF, TREE_TYPE (f_ovfl), valist, f_ovfl, 4353169689Skan NULL_TREE); 4354169689Skan 4355169689Skan if (GET_MODE_CLASS (TYPE_MODE (type)) == MODE_FLOAT 4356169689Skan && GET_MODE_SIZE (TYPE_MODE (type)) <= UNITS_PER_FPVALUE) 4357169689Skan { 4358169689Skan top = build3 (COMPONENT_REF, TREE_TYPE (f_ftop), valist, f_ftop, 4359169689Skan NULL_TREE); 4360169689Skan off = build3 (COMPONENT_REF, TREE_TYPE (f_foff), valist, f_foff, 4361169689Skan NULL_TREE); 4362169689Skan 4363169689Skan /* When floating-point registers are saved to the stack, 4364169689Skan each one will take up UNITS_PER_HWFPVALUE bytes, regardless 4365169689Skan of the float's precision. */ 4366169689Skan rsize = UNITS_PER_HWFPVALUE; 4367169689Skan 4368169689Skan /* Overflow arguments are padded to UNITS_PER_WORD bytes 4369169689Skan (= PARM_BOUNDARY bits). This can be different from RSIZE 4370169689Skan in two cases: 4371169689Skan 4372169689Skan (1) On 32-bit targets when TYPE is a structure such as: 4373169689Skan 4374169689Skan struct s { float f; }; 4375169689Skan 4376169689Skan Such structures are passed in paired FPRs, so RSIZE 4377169689Skan will be 8 bytes. However, the structure only takes 4378169689Skan up 4 bytes of memory, so OSIZE will only be 4. 4379169689Skan 4380169689Skan (2) In combinations such as -mgp64 -msingle-float 4381169689Skan -fshort-double. Doubles passed in registers 4382169689Skan will then take up 4 (UNITS_PER_HWFPVALUE) bytes, 4383169689Skan but those passed on the stack take up 4384169689Skan UNITS_PER_WORD bytes. */ 4385169689Skan osize = MAX (GET_MODE_SIZE (TYPE_MODE (type)), UNITS_PER_WORD); 4386169689Skan } 4387169689Skan else 4388169689Skan { 4389169689Skan top = build3 (COMPONENT_REF, TREE_TYPE (f_gtop), valist, f_gtop, 4390169689Skan NULL_TREE); 4391169689Skan off = build3 (COMPONENT_REF, TREE_TYPE (f_goff), valist, f_goff, 4392169689Skan NULL_TREE); 4393169689Skan if (rsize > UNITS_PER_WORD) 4394169689Skan { 4395169689Skan /* [1] Emit code for: off &= -rsize. */ 4396169689Skan t = build2 (BIT_AND_EXPR, TREE_TYPE (off), off, 4397169689Skan build_int_cst (NULL_TREE, -rsize)); 4398169689Skan t = build2 (MODIFY_EXPR, TREE_TYPE (off), off, t); 4399169689Skan gimplify_and_add (t, pre_p); 4400169689Skan } 4401169689Skan osize = rsize; 4402169689Skan } 4403169689Skan 4404169689Skan /* [2] Emit code to branch if off == 0. */ 4405169689Skan t = build2 (NE_EXPR, boolean_type_node, off, 4406169689Skan build_int_cst (TREE_TYPE (off), 0)); 4407169689Skan addr = build3 (COND_EXPR, ptr_type_node, t, NULL_TREE, NULL_TREE); 4408169689Skan 4409169689Skan /* [5] Emit code for: off -= rsize. We do this as a form of 4410169689Skan post-increment not available to C. Also widen for the 4411169689Skan coming pointer arithmetic. */ 4412169689Skan t = fold_convert (TREE_TYPE (off), build_int_cst (NULL_TREE, rsize)); 4413169689Skan t = build2 (POSTDECREMENT_EXPR, TREE_TYPE (off), off, t); 4414169689Skan t = fold_convert (sizetype, t); 4415169689Skan t = fold_convert (TREE_TYPE (top), t); 4416169689Skan 4417169689Skan /* [4] Emit code for: addr_rtx = top - off. On big endian machines, 4418169689Skan the argument has RSIZE - SIZE bytes of leading padding. */ 4419169689Skan t = build2 (MINUS_EXPR, TREE_TYPE (top), top, t); 4420169689Skan if (BYTES_BIG_ENDIAN && rsize > size) 4421169689Skan { 4422169689Skan u = fold_convert (TREE_TYPE (t), build_int_cst (NULL_TREE, 4423169689Skan rsize - size)); 4424169689Skan t = build2 (PLUS_EXPR, TREE_TYPE (t), t, u); 4425169689Skan } 4426169689Skan COND_EXPR_THEN (addr) = t; 4427169689Skan 4428169689Skan if (osize > UNITS_PER_WORD) 4429169689Skan { 4430169689Skan /* [9] Emit: ovfl += ((intptr_t) ovfl + osize - 1) & -osize. */ 4431169689Skan u = fold_convert (TREE_TYPE (ovfl), 4432169689Skan build_int_cst (NULL_TREE, osize - 1)); 4433169689Skan t = build2 (PLUS_EXPR, TREE_TYPE (ovfl), ovfl, u); 4434169689Skan u = fold_convert (TREE_TYPE (ovfl), 4435169689Skan build_int_cst (NULL_TREE, -osize)); 4436169689Skan t = build2 (BIT_AND_EXPR, TREE_TYPE (ovfl), t, u); 4437169689Skan align = build2 (MODIFY_EXPR, TREE_TYPE (ovfl), ovfl, t); 4438169689Skan } 4439169689Skan else 4440169689Skan align = NULL; 4441169689Skan 4442169689Skan /* [10, 11]. Emit code to store ovfl in addr_rtx, then 4443169689Skan post-increment ovfl by osize. On big-endian machines, 4444169689Skan the argument has OSIZE - SIZE bytes of leading padding. */ 4445169689Skan u = fold_convert (TREE_TYPE (ovfl), 4446169689Skan build_int_cst (NULL_TREE, osize)); 4447169689Skan t = build2 (POSTINCREMENT_EXPR, TREE_TYPE (ovfl), ovfl, u); 4448169689Skan if (BYTES_BIG_ENDIAN && osize > size) 4449169689Skan { 4450169689Skan u = fold_convert (TREE_TYPE (t), 4451169689Skan build_int_cst (NULL_TREE, osize - size)); 4452169689Skan t = build2 (PLUS_EXPR, TREE_TYPE (t), t, u); 4453169689Skan } 4454169689Skan 4455169689Skan /* String [9] and [10,11] together. */ 4456169689Skan if (align) 4457169689Skan t = build2 (COMPOUND_EXPR, TREE_TYPE (t), align, t); 4458169689Skan COND_EXPR_ELSE (addr) = t; 4459169689Skan 4460169689Skan addr = fold_convert (build_pointer_type (type), addr); 4461169689Skan addr = build_va_arg_indirect_ref (addr); 4462169689Skan } 4463169689Skan 4464169689Skan if (indirect) 4465169689Skan addr = build_va_arg_indirect_ref (addr); 4466169689Skan 4467169689Skan return addr; 4468169689Skan} 4469169689Skan 4470169689Skan/* Return true if it is possible to use left/right accesses for a 4471169689Skan bitfield of WIDTH bits starting BITPOS bits into *OP. When 4472169689Skan returning true, update *OP, *LEFT and *RIGHT as follows: 4473169689Skan 4474169689Skan *OP is a BLKmode reference to the whole field. 4475169689Skan 4476169689Skan *LEFT is a QImode reference to the first byte if big endian or 4477169689Skan the last byte if little endian. This address can be used in the 4478169689Skan left-side instructions (lwl, swl, ldl, sdl). 4479169689Skan 4480169689Skan *RIGHT is a QImode reference to the opposite end of the field and 4481169689Skan can be used in the patterning right-side instruction. */ 4482169689Skan 4483169689Skanstatic bool 4484169689Skanmips_get_unaligned_mem (rtx *op, unsigned int width, int bitpos, 4485169689Skan rtx *left, rtx *right) 4486169689Skan{ 4487169689Skan rtx first, last; 4488169689Skan 4489169689Skan /* Check that the operand really is a MEM. Not all the extv and 4490169689Skan extzv predicates are checked. */ 4491169689Skan if (!MEM_P (*op)) 4492169689Skan return false; 4493169689Skan 4494169689Skan /* Check that the size is valid. */ 4495169689Skan if (width != 32 && (!TARGET_64BIT || width != 64)) 4496169689Skan return false; 4497169689Skan 4498169689Skan /* We can only access byte-aligned values. Since we are always passed 4499169689Skan a reference to the first byte of the field, it is not necessary to 4500169689Skan do anything with BITPOS after this check. */ 4501169689Skan if (bitpos % BITS_PER_UNIT != 0) 4502169689Skan return false; 4503169689Skan 4504169689Skan /* Reject aligned bitfields: we want to use a normal load or store 4505169689Skan instead of a left/right pair. */ 4506169689Skan if (MEM_ALIGN (*op) >= width) 4507169689Skan return false; 4508169689Skan 4509169689Skan /* Adjust *OP to refer to the whole field. This also has the effect 4510169689Skan of legitimizing *OP's address for BLKmode, possibly simplifying it. */ 4511169689Skan *op = adjust_address (*op, BLKmode, 0); 4512169689Skan set_mem_size (*op, GEN_INT (width / BITS_PER_UNIT)); 4513169689Skan 4514169689Skan /* Get references to both ends of the field. We deliberately don't 4515169689Skan use the original QImode *OP for FIRST since the new BLKmode one 4516169689Skan might have a simpler address. */ 4517169689Skan first = adjust_address (*op, QImode, 0); 4518169689Skan last = adjust_address (*op, QImode, width / BITS_PER_UNIT - 1); 4519169689Skan 4520169689Skan /* Allocate to LEFT and RIGHT according to endianness. LEFT should 4521169689Skan be the upper word and RIGHT the lower word. */ 4522169689Skan if (TARGET_BIG_ENDIAN) 4523169689Skan *left = first, *right = last; 4524169689Skan else 4525169689Skan *left = last, *right = first; 4526169689Skan 4527169689Skan return true; 4528169689Skan} 4529169689Skan 4530169689Skan 4531169689Skan/* Try to emit the equivalent of (set DEST (zero_extract SRC WIDTH BITPOS)). 4532169689Skan Return true on success. We only handle cases where zero_extract is 4533169689Skan equivalent to sign_extract. */ 4534169689Skan 4535169689Skanbool 4536169689Skanmips_expand_unaligned_load (rtx dest, rtx src, unsigned int width, int bitpos) 4537169689Skan{ 4538169689Skan rtx left, right, temp; 4539169689Skan 4540169689Skan /* If TARGET_64BIT, the destination of a 32-bit load will be a 4541169689Skan paradoxical word_mode subreg. This is the only case in which 4542169689Skan we allow the destination to be larger than the source. */ 4543169689Skan if (GET_CODE (dest) == SUBREG 4544169689Skan && GET_MODE (dest) == DImode 4545169689Skan && SUBREG_BYTE (dest) == 0 4546169689Skan && GET_MODE (SUBREG_REG (dest)) == SImode) 4547169689Skan dest = SUBREG_REG (dest); 4548169689Skan 4549169689Skan /* After the above adjustment, the destination must be the same 4550169689Skan width as the source. */ 4551169689Skan if (GET_MODE_BITSIZE (GET_MODE (dest)) != width) 4552169689Skan return false; 4553169689Skan 4554169689Skan if (!mips_get_unaligned_mem (&src, width, bitpos, &left, &right)) 4555169689Skan return false; 4556169689Skan 4557169689Skan temp = gen_reg_rtx (GET_MODE (dest)); 4558169689Skan if (GET_MODE (dest) == DImode) 4559169689Skan { 4560169689Skan emit_insn (gen_mov_ldl (temp, src, left)); 4561169689Skan emit_insn (gen_mov_ldr (dest, copy_rtx (src), right, temp)); 4562169689Skan } 4563169689Skan else 4564169689Skan { 4565169689Skan emit_insn (gen_mov_lwl (temp, src, left)); 4566169689Skan emit_insn (gen_mov_lwr (dest, copy_rtx (src), right, temp)); 4567169689Skan } 4568169689Skan return true; 4569169689Skan} 4570169689Skan 4571169689Skan 4572169689Skan/* Try to expand (set (zero_extract DEST WIDTH BITPOS) SRC). Return 4573169689Skan true on success. */ 4574169689Skan 4575169689Skanbool 4576169689Skanmips_expand_unaligned_store (rtx dest, rtx src, unsigned int width, int bitpos) 4577169689Skan{ 4578169689Skan rtx left, right; 4579169689Skan enum machine_mode mode; 4580169689Skan 4581169689Skan if (!mips_get_unaligned_mem (&dest, width, bitpos, &left, &right)) 4582169689Skan return false; 4583169689Skan 4584169689Skan mode = mode_for_size (width, MODE_INT, 0); 4585169689Skan src = gen_lowpart (mode, src); 4586169689Skan 4587169689Skan if (mode == DImode) 4588169689Skan { 4589169689Skan emit_insn (gen_mov_sdl (dest, src, left)); 4590169689Skan emit_insn (gen_mov_sdr (copy_rtx (dest), copy_rtx (src), right)); 4591169689Skan } 4592169689Skan else 4593169689Skan { 4594169689Skan emit_insn (gen_mov_swl (dest, src, left)); 4595169689Skan emit_insn (gen_mov_swr (copy_rtx (dest), copy_rtx (src), right)); 4596169689Skan } 4597169689Skan return true; 4598169689Skan} 4599169689Skan 4600169689Skan/* Return true if X is a MEM with the same size as MODE. */ 4601169689Skan 4602169689Skanbool 4603169689Skanmips_mem_fits_mode_p (enum machine_mode mode, rtx x) 4604169689Skan{ 4605169689Skan rtx size; 4606169689Skan 4607169689Skan if (!MEM_P (x)) 4608169689Skan return false; 4609169689Skan 4610169689Skan size = MEM_SIZE (x); 4611169689Skan return size && INTVAL (size) == GET_MODE_SIZE (mode); 4612169689Skan} 4613169689Skan 4614169689Skan/* Return true if (zero_extract OP SIZE POSITION) can be used as the 4615169689Skan source of an "ext" instruction or the destination of an "ins" 4616169689Skan instruction. OP must be a register operand and the following 4617169689Skan conditions must hold: 4618169689Skan 4619169689Skan 0 <= POSITION < GET_MODE_BITSIZE (GET_MODE (op)) 4620169689Skan 0 < SIZE <= GET_MODE_BITSIZE (GET_MODE (op)) 4621169689Skan 0 < POSITION + SIZE <= GET_MODE_BITSIZE (GET_MODE (op)) 4622169689Skan 4623169689Skan Also reject lengths equal to a word as they are better handled 4624169689Skan by the move patterns. */ 4625169689Skan 4626169689Skanbool 4627169689Skanmips_use_ins_ext_p (rtx op, rtx size, rtx position) 4628169689Skan{ 4629169689Skan HOST_WIDE_INT len, pos; 4630169689Skan 4631169689Skan if (!ISA_HAS_EXT_INS 4632169689Skan || !register_operand (op, VOIDmode) 4633169689Skan || GET_MODE_BITSIZE (GET_MODE (op)) > BITS_PER_WORD) 4634169689Skan return false; 4635169689Skan 4636169689Skan len = INTVAL (size); 4637169689Skan pos = INTVAL (position); 4638169689Skan 4639169689Skan if (len <= 0 || len >= GET_MODE_BITSIZE (GET_MODE (op)) 4640169689Skan || pos < 0 || pos + len > GET_MODE_BITSIZE (GET_MODE (op))) 4641169689Skan return false; 4642169689Skan 4643169689Skan return true; 4644169689Skan} 4645169689Skan 4646169689Skan/* Set up globals to generate code for the ISA or processor 4647169689Skan described by INFO. */ 4648169689Skan 4649169689Skanstatic void 4650169689Skanmips_set_architecture (const struct mips_cpu_info *info) 4651169689Skan{ 4652169689Skan if (info != 0) 4653169689Skan { 4654169689Skan mips_arch_info = info; 4655169689Skan mips_arch = info->cpu; 4656169689Skan mips_isa = info->isa; 4657169689Skan } 4658169689Skan} 4659169689Skan 4660169689Skan 4661169689Skan/* Likewise for tuning. */ 4662169689Skan 4663169689Skanstatic void 4664169689Skanmips_set_tune (const struct mips_cpu_info *info) 4665169689Skan{ 4666169689Skan if (info != 0) 4667169689Skan { 4668169689Skan mips_tune_info = info; 4669169689Skan mips_tune = info->cpu; 4670169689Skan } 4671169689Skan} 4672169689Skan 4673169689Skan/* Implement TARGET_HANDLE_OPTION. */ 4674169689Skan 4675169689Skanstatic bool 4676169689Skanmips_handle_option (size_t code, const char *arg, int value ATTRIBUTE_UNUSED) 4677169689Skan{ 4678169689Skan switch (code) 4679169689Skan { 4680169689Skan case OPT_mabi_: 4681169689Skan if (strcmp (arg, "32") == 0) 4682169689Skan mips_abi = ABI_32; 4683169689Skan else if (strcmp (arg, "o64") == 0) 4684169689Skan mips_abi = ABI_O64; 4685169689Skan else if (strcmp (arg, "n32") == 0) 4686169689Skan mips_abi = ABI_N32; 4687169689Skan else if (strcmp (arg, "64") == 0) 4688169689Skan mips_abi = ABI_64; 4689169689Skan else if (strcmp (arg, "eabi") == 0) 4690169689Skan mips_abi = ABI_EABI; 4691169689Skan else 4692169689Skan return false; 4693169689Skan return true; 4694169689Skan 4695169689Skan case OPT_march_: 4696169689Skan case OPT_mtune_: 4697169689Skan return mips_parse_cpu (arg) != 0; 4698169689Skan 4699169689Skan case OPT_mips: 4700169689Skan mips_isa_info = mips_parse_cpu (ACONCAT (("mips", arg, NULL))); 4701169689Skan return mips_isa_info != 0; 4702169689Skan 4703169689Skan case OPT_mno_flush_func: 4704169689Skan mips_cache_flush_func = NULL; 4705169689Skan return true; 4706169689Skan 4707169689Skan default: 4708169689Skan return true; 4709169689Skan } 4710169689Skan} 4711169689Skan 4712169689Skan/* Set up the threshold for data to go into the small data area, instead 4713169689Skan of the normal data area, and detect any conflicts in the switches. */ 4714169689Skan 4715169689Skanvoid 4716169689Skanoverride_options (void) 4717169689Skan{ 4718169689Skan int i, start, regno; 4719169689Skan enum machine_mode mode; 4720169689Skan 4721169689Skan mips_section_threshold = g_switch_set ? g_switch_value : MIPS_DEFAULT_GVALUE; 4722169689Skan 4723169689Skan /* The following code determines the architecture and register size. 4724169689Skan Similar code was added to GAS 2.14 (see tc-mips.c:md_after_parse_args()). 4725169689Skan The GAS and GCC code should be kept in sync as much as possible. */ 4726169689Skan 4727169689Skan if (mips_arch_string != 0) 4728169689Skan mips_set_architecture (mips_parse_cpu (mips_arch_string)); 4729169689Skan 4730169689Skan if (mips_isa_info != 0) 4731169689Skan { 4732169689Skan if (mips_arch_info == 0) 4733169689Skan mips_set_architecture (mips_isa_info); 4734169689Skan else if (mips_arch_info->isa != mips_isa_info->isa) 4735169689Skan error ("-%s conflicts with the other architecture options, " 4736169689Skan "which specify a %s processor", 4737169689Skan mips_isa_info->name, 4738169689Skan mips_cpu_info_from_isa (mips_arch_info->isa)->name); 4739169689Skan } 4740169689Skan 4741169689Skan if (mips_arch_info == 0) 4742169689Skan { 4743169689Skan#ifdef MIPS_CPU_STRING_DEFAULT 4744169689Skan mips_set_architecture (mips_parse_cpu (MIPS_CPU_STRING_DEFAULT)); 4745169689Skan#else 4746169689Skan mips_set_architecture (mips_cpu_info_from_isa (MIPS_ISA_DEFAULT)); 4747169689Skan#endif 4748169689Skan } 4749169689Skan 4750169689Skan if (ABI_NEEDS_64BIT_REGS && !ISA_HAS_64BIT_REGS) 4751169689Skan error ("-march=%s is not compatible with the selected ABI", 4752169689Skan mips_arch_info->name); 4753169689Skan 4754169689Skan /* Optimize for mips_arch, unless -mtune selects a different processor. */ 4755169689Skan if (mips_tune_string != 0) 4756169689Skan mips_set_tune (mips_parse_cpu (mips_tune_string)); 4757169689Skan 4758169689Skan if (mips_tune_info == 0) 4759169689Skan mips_set_tune (mips_arch_info); 4760169689Skan 4761169689Skan /* Set cost structure for the processor. */ 4762169689Skan mips_cost = &mips_rtx_cost_data[mips_tune]; 4763169689Skan 4764169689Skan if ((target_flags_explicit & MASK_64BIT) != 0) 4765169689Skan { 4766169689Skan /* The user specified the size of the integer registers. Make sure 4767169689Skan it agrees with the ABI and ISA. */ 4768169689Skan if (TARGET_64BIT && !ISA_HAS_64BIT_REGS) 4769169689Skan error ("-mgp64 used with a 32-bit processor"); 4770169689Skan else if (!TARGET_64BIT && ABI_NEEDS_64BIT_REGS) 4771169689Skan error ("-mgp32 used with a 64-bit ABI"); 4772169689Skan else if (TARGET_64BIT && ABI_NEEDS_32BIT_REGS) 4773169689Skan error ("-mgp64 used with a 32-bit ABI"); 4774169689Skan } 4775169689Skan else 4776169689Skan { 4777169689Skan /* Infer the integer register size from the ABI and processor. 4778169689Skan Restrict ourselves to 32-bit registers if that's all the 4779169689Skan processor has, or if the ABI cannot handle 64-bit registers. */ 4780169689Skan if (ABI_NEEDS_32BIT_REGS || !ISA_HAS_64BIT_REGS) 4781169689Skan target_flags &= ~MASK_64BIT; 4782169689Skan else 4783169689Skan target_flags |= MASK_64BIT; 4784169689Skan } 4785169689Skan 4786169689Skan if ((target_flags_explicit & MASK_FLOAT64) != 0) 4787169689Skan { 4788169689Skan /* Really, -mfp32 and -mfp64 are ornamental options. There's 4789169689Skan only one right answer here. */ 4790169689Skan if (TARGET_64BIT && TARGET_DOUBLE_FLOAT && !TARGET_FLOAT64) 4791169689Skan error ("unsupported combination: %s", "-mgp64 -mfp32 -mdouble-float"); 4792169689Skan else if (!TARGET_64BIT && TARGET_FLOAT64) 4793169689Skan error ("unsupported combination: %s", "-mgp32 -mfp64"); 4794169689Skan else if (TARGET_SINGLE_FLOAT && TARGET_FLOAT64) 4795169689Skan error ("unsupported combination: %s", "-mfp64 -msingle-float"); 4796169689Skan } 4797169689Skan else 4798169689Skan { 4799169689Skan /* -msingle-float selects 32-bit float registers. Otherwise the 4800169689Skan float registers should be the same size as the integer ones. */ 4801169689Skan if (TARGET_64BIT && TARGET_DOUBLE_FLOAT) 4802169689Skan target_flags |= MASK_FLOAT64; 4803169689Skan else 4804169689Skan target_flags &= ~MASK_FLOAT64; 4805169689Skan } 4806169689Skan 4807169689Skan /* End of code shared with GAS. */ 4808169689Skan 4809169689Skan if ((target_flags_explicit & MASK_LONG64) == 0) 4810169689Skan { 4811169689Skan if ((mips_abi == ABI_EABI && TARGET_64BIT) || mips_abi == ABI_64) 4812169689Skan target_flags |= MASK_LONG64; 4813169689Skan else 4814169689Skan target_flags &= ~MASK_LONG64; 4815169689Skan } 4816169689Skan 4817169689Skan if (MIPS_MARCH_CONTROLS_SOFT_FLOAT 4818169689Skan && (target_flags_explicit & MASK_SOFT_FLOAT) == 0) 4819169689Skan { 4820169689Skan /* For some configurations, it is useful to have -march control 4821169689Skan the default setting of MASK_SOFT_FLOAT. */ 4822169689Skan switch ((int) mips_arch) 4823169689Skan { 4824169689Skan case PROCESSOR_R4100: 4825169689Skan case PROCESSOR_R4111: 4826169689Skan case PROCESSOR_R4120: 4827169689Skan case PROCESSOR_R4130: 4828169689Skan target_flags |= MASK_SOFT_FLOAT; 4829169689Skan break; 4830169689Skan 4831169689Skan default: 4832169689Skan target_flags &= ~MASK_SOFT_FLOAT; 4833169689Skan break; 4834169689Skan } 4835169689Skan } 4836169689Skan 4837169689Skan if (!TARGET_OLDABI) 4838169689Skan flag_pcc_struct_return = 0; 4839169689Skan 4840169689Skan if ((target_flags_explicit & MASK_BRANCHLIKELY) == 0) 4841169689Skan { 4842169689Skan /* If neither -mbranch-likely nor -mno-branch-likely was given 4843169689Skan on the command line, set MASK_BRANCHLIKELY based on the target 4844169689Skan architecture. 4845169689Skan 4846169689Skan By default, we enable use of Branch Likely instructions on 4847169689Skan all architectures which support them with the following 4848169689Skan exceptions: when creating MIPS32 or MIPS64 code, and when 4849169689Skan tuning for architectures where their use tends to hurt 4850169689Skan performance. 4851169689Skan 4852169689Skan The MIPS32 and MIPS64 architecture specifications say "Software 4853169689Skan is strongly encouraged to avoid use of Branch Likely 4854169689Skan instructions, as they will be removed from a future revision 4855169689Skan of the [MIPS32 and MIPS64] architecture." Therefore, we do not 4856169689Skan issue those instructions unless instructed to do so by 4857169689Skan -mbranch-likely. */ 4858169689Skan if (ISA_HAS_BRANCHLIKELY 4859208737Sjmallett && !(ISA_MIPS32 || ISA_MIPS32R2 || ISA_MIPS64 || ISA_MIPS64R2) 4860169689Skan && !(TUNE_MIPS5500 || TUNE_SB1)) 4861169689Skan target_flags |= MASK_BRANCHLIKELY; 4862169689Skan else 4863169689Skan target_flags &= ~MASK_BRANCHLIKELY; 4864169689Skan } 4865169689Skan if (TARGET_BRANCHLIKELY && !ISA_HAS_BRANCHLIKELY) 4866169689Skan warning (0, "generation of Branch Likely instructions enabled, but not supported by architecture"); 4867169689Skan 4868169689Skan /* The effect of -mabicalls isn't defined for the EABI. */ 4869169689Skan if (mips_abi == ABI_EABI && TARGET_ABICALLS) 4870169689Skan { 4871169689Skan error ("unsupported combination: %s", "-mabicalls -mabi=eabi"); 4872169689Skan target_flags &= ~MASK_ABICALLS; 4873169689Skan } 4874169689Skan 4875169689Skan if (TARGET_ABICALLS) 4876169689Skan { 4877169689Skan /* We need to set flag_pic for executables as well as DSOs 4878169689Skan because we may reference symbols that are not defined in 4879169689Skan the final executable. (MIPS does not use things like 4880169689Skan copy relocs, for example.) 4881169689Skan 4882169689Skan Also, there is a body of code that uses __PIC__ to distinguish 4883169689Skan between -mabicalls and -mno-abicalls code. */ 4884169689Skan flag_pic = 1; 4885169689Skan if (mips_section_threshold > 0) 4886169689Skan warning (0, "%<-G%> is incompatible with %<-mabicalls%>"); 4887169689Skan } 4888169689Skan 4889169689Skan /* mips_split_addresses is a half-way house between explicit 4890169689Skan relocations and the traditional assembler macros. It can 4891169689Skan split absolute 32-bit symbolic constants into a high/lo_sum 4892169689Skan pair but uses macros for other sorts of access. 4893169689Skan 4894169689Skan Like explicit relocation support for REL targets, it relies 4895169689Skan on GNU extensions in the assembler and the linker. 4896169689Skan 4897169689Skan Although this code should work for -O0, it has traditionally 4898169689Skan been treated as an optimization. */ 4899169689Skan if (!TARGET_MIPS16 && TARGET_SPLIT_ADDRESSES 4900169689Skan && optimize && !flag_pic 4901169689Skan && !ABI_HAS_64BIT_SYMBOLS) 4902169689Skan mips_split_addresses = 1; 4903169689Skan else 4904169689Skan mips_split_addresses = 0; 4905169689Skan 4906169689Skan /* -mvr4130-align is a "speed over size" optimization: it usually produces 4907169689Skan faster code, but at the expense of more nops. Enable it at -O3 and 4908169689Skan above. */ 4909169689Skan if (optimize > 2 && (target_flags_explicit & MASK_VR4130_ALIGN) == 0) 4910169689Skan target_flags |= MASK_VR4130_ALIGN; 4911169689Skan 4912169689Skan /* When compiling for the mips16, we cannot use floating point. We 4913169689Skan record the original hard float value in mips16_hard_float. */ 4914169689Skan if (TARGET_MIPS16) 4915169689Skan { 4916169689Skan if (TARGET_SOFT_FLOAT) 4917169689Skan mips16_hard_float = 0; 4918169689Skan else 4919169689Skan mips16_hard_float = 1; 4920169689Skan target_flags |= MASK_SOFT_FLOAT; 4921169689Skan 4922169689Skan /* Don't run the scheduler before reload, since it tends to 4923169689Skan increase register pressure. */ 4924169689Skan flag_schedule_insns = 0; 4925169689Skan 4926169689Skan /* Don't do hot/cold partitioning. The constant layout code expects 4927169689Skan the whole function to be in a single section. */ 4928169689Skan flag_reorder_blocks_and_partition = 0; 4929169689Skan 4930169689Skan /* Silently disable -mexplicit-relocs since it doesn't apply 4931169689Skan to mips16 code. Even so, it would overly pedantic to warn 4932169689Skan about "-mips16 -mexplicit-relocs", especially given that 4933169689Skan we use a %gprel() operator. */ 4934169689Skan target_flags &= ~MASK_EXPLICIT_RELOCS; 4935169689Skan } 4936169689Skan 4937169689Skan /* When using explicit relocs, we call dbr_schedule from within 4938169689Skan mips_reorg. */ 4939169689Skan if (TARGET_EXPLICIT_RELOCS) 4940169689Skan { 4941169689Skan mips_flag_delayed_branch = flag_delayed_branch; 4942169689Skan flag_delayed_branch = 0; 4943169689Skan } 4944169689Skan 4945169689Skan#ifdef MIPS_TFMODE_FORMAT 4946169689Skan REAL_MODE_FORMAT (TFmode) = &MIPS_TFMODE_FORMAT; 4947169689Skan#endif 4948169689Skan 4949169689Skan /* Make sure that the user didn't turn off paired single support when 4950169689Skan MIPS-3D support is requested. */ 4951169689Skan if (TARGET_MIPS3D && (target_flags_explicit & MASK_PAIRED_SINGLE_FLOAT) 4952169689Skan && !TARGET_PAIRED_SINGLE_FLOAT) 4953169689Skan error ("-mips3d requires -mpaired-single"); 4954169689Skan 4955169689Skan /* If TARGET_MIPS3D, enable MASK_PAIRED_SINGLE_FLOAT. */ 4956169689Skan if (TARGET_MIPS3D) 4957169689Skan target_flags |= MASK_PAIRED_SINGLE_FLOAT; 4958169689Skan 4959169689Skan /* Make sure that when TARGET_PAIRED_SINGLE_FLOAT is true, TARGET_FLOAT64 4960169689Skan and TARGET_HARD_FLOAT are both true. */ 4961169689Skan if (TARGET_PAIRED_SINGLE_FLOAT && !(TARGET_FLOAT64 && TARGET_HARD_FLOAT)) 4962169689Skan error ("-mips3d/-mpaired-single must be used with -mfp64 -mhard-float"); 4963169689Skan 4964169689Skan /* Make sure that the ISA supports TARGET_PAIRED_SINGLE_FLOAT when it is 4965169689Skan enabled. */ 4966169689Skan if (TARGET_PAIRED_SINGLE_FLOAT && !ISA_MIPS64) 4967169689Skan error ("-mips3d/-mpaired-single must be used with -mips64"); 4968169689Skan 4969169689Skan if (TARGET_MIPS16 && TARGET_DSP) 4970169689Skan error ("-mips16 and -mdsp cannot be used together"); 4971169689Skan 4972169689Skan mips_print_operand_punct['?'] = 1; 4973169689Skan mips_print_operand_punct['#'] = 1; 4974169689Skan mips_print_operand_punct['/'] = 1; 4975169689Skan mips_print_operand_punct['&'] = 1; 4976169689Skan mips_print_operand_punct['!'] = 1; 4977169689Skan mips_print_operand_punct['*'] = 1; 4978169689Skan mips_print_operand_punct['@'] = 1; 4979169689Skan mips_print_operand_punct['.'] = 1; 4980169689Skan mips_print_operand_punct['('] = 1; 4981169689Skan mips_print_operand_punct[')'] = 1; 4982169689Skan mips_print_operand_punct['['] = 1; 4983169689Skan mips_print_operand_punct[']'] = 1; 4984169689Skan mips_print_operand_punct['<'] = 1; 4985169689Skan mips_print_operand_punct['>'] = 1; 4986169689Skan mips_print_operand_punct['{'] = 1; 4987169689Skan mips_print_operand_punct['}'] = 1; 4988169689Skan mips_print_operand_punct['^'] = 1; 4989169689Skan mips_print_operand_punct['$'] = 1; 4990169689Skan mips_print_operand_punct['+'] = 1; 4991169689Skan mips_print_operand_punct['~'] = 1; 4992169689Skan 4993169689Skan /* Set up array to map GCC register number to debug register number. 4994169689Skan Ignore the special purpose register numbers. */ 4995169689Skan 4996169689Skan for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 4997169689Skan mips_dbx_regno[i] = -1; 4998169689Skan 4999169689Skan start = GP_DBX_FIRST - GP_REG_FIRST; 5000169689Skan for (i = GP_REG_FIRST; i <= GP_REG_LAST; i++) 5001169689Skan mips_dbx_regno[i] = i + start; 5002169689Skan 5003169689Skan start = FP_DBX_FIRST - FP_REG_FIRST; 5004169689Skan for (i = FP_REG_FIRST; i <= FP_REG_LAST; i++) 5005169689Skan mips_dbx_regno[i] = i + start; 5006169689Skan 5007169689Skan mips_dbx_regno[HI_REGNUM] = MD_DBX_FIRST + 0; 5008169689Skan mips_dbx_regno[LO_REGNUM] = MD_DBX_FIRST + 1; 5009169689Skan 5010169689Skan /* Set up array giving whether a given register can hold a given mode. */ 5011169689Skan 5012169689Skan for (mode = VOIDmode; 5013169689Skan mode != MAX_MACHINE_MODE; 5014169689Skan mode = (enum machine_mode) ((int)mode + 1)) 5015169689Skan { 5016169689Skan register int size = GET_MODE_SIZE (mode); 5017169689Skan register enum mode_class class = GET_MODE_CLASS (mode); 5018169689Skan 5019169689Skan for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) 5020169689Skan { 5021169689Skan register int temp; 5022169689Skan 5023169689Skan if (mode == CCV2mode) 5024169689Skan temp = (ISA_HAS_8CC 5025169689Skan && ST_REG_P (regno) 5026169689Skan && (regno - ST_REG_FIRST) % 2 == 0); 5027169689Skan 5028169689Skan else if (mode == CCV4mode) 5029169689Skan temp = (ISA_HAS_8CC 5030169689Skan && ST_REG_P (regno) 5031169689Skan && (regno - ST_REG_FIRST) % 4 == 0); 5032169689Skan 5033169689Skan else if (mode == CCmode) 5034169689Skan { 5035169689Skan if (! ISA_HAS_8CC) 5036169689Skan temp = (regno == FPSW_REGNUM); 5037169689Skan else 5038169689Skan temp = (ST_REG_P (regno) || GP_REG_P (regno) 5039169689Skan || FP_REG_P (regno)); 5040169689Skan } 5041169689Skan 5042169689Skan else if (GP_REG_P (regno)) 5043169689Skan temp = ((regno & 1) == 0 || size <= UNITS_PER_WORD); 5044169689Skan 5045169689Skan else if (FP_REG_P (regno)) 5046169689Skan temp = ((regno % FP_INC) == 0) 5047169689Skan && (((class == MODE_FLOAT || class == MODE_COMPLEX_FLOAT 5048169689Skan || class == MODE_VECTOR_FLOAT) 5049169689Skan && size <= UNITS_PER_FPVALUE) 5050169689Skan /* Allow integer modes that fit into a single 5051169689Skan register. We need to put integers into FPRs 5052169689Skan when using instructions like cvt and trunc. 5053169689Skan We can't allow sizes smaller than a word, 5054169689Skan the FPU has no appropriate load/store 5055169689Skan instructions for those. */ 5056169689Skan || (class == MODE_INT 5057169689Skan && size >= MIN_UNITS_PER_WORD 5058169689Skan && size <= UNITS_PER_FPREG) 5059169689Skan /* Allow TFmode for CCmode reloads. */ 5060169689Skan || (ISA_HAS_8CC && mode == TFmode)); 5061169689Skan 5062169689Skan else if (ACC_REG_P (regno)) 5063169689Skan temp = (INTEGRAL_MODE_P (mode) 5064169689Skan && (size <= UNITS_PER_WORD 5065169689Skan || (ACC_HI_REG_P (regno) 5066169689Skan && size == 2 * UNITS_PER_WORD))); 5067169689Skan 5068169689Skan else if (ALL_COP_REG_P (regno)) 5069169689Skan temp = (class == MODE_INT && size <= UNITS_PER_WORD); 5070169689Skan else 5071169689Skan temp = 0; 5072169689Skan 5073169689Skan mips_hard_regno_mode_ok[(int)mode][regno] = temp; 5074169689Skan } 5075169689Skan } 5076169689Skan 5077169689Skan /* Save GPR registers in word_mode sized hunks. word_mode hasn't been 5078169689Skan initialized yet, so we can't use that here. */ 5079169689Skan gpr_mode = TARGET_64BIT ? DImode : SImode; 5080169689Skan 5081169689Skan /* Provide default values for align_* for 64-bit targets. */ 5082169689Skan if (TARGET_64BIT && !TARGET_MIPS16) 5083169689Skan { 5084169689Skan if (align_loops == 0) 5085169689Skan align_loops = 8; 5086169689Skan if (align_jumps == 0) 5087169689Skan align_jumps = 8; 5088169689Skan if (align_functions == 0) 5089169689Skan align_functions = 8; 5090169689Skan } 5091169689Skan 5092169689Skan /* Function to allocate machine-dependent function status. */ 5093169689Skan init_machine_status = &mips_init_machine_status; 5094169689Skan 5095169689Skan if (ABI_HAS_64BIT_SYMBOLS) 5096169689Skan { 5097169689Skan if (TARGET_EXPLICIT_RELOCS) 5098169689Skan { 5099169689Skan mips_split_p[SYMBOL_64_HIGH] = true; 5100169689Skan mips_hi_relocs[SYMBOL_64_HIGH] = "%highest("; 5101169689Skan mips_lo_relocs[SYMBOL_64_HIGH] = "%higher("; 5102169689Skan 5103169689Skan mips_split_p[SYMBOL_64_MID] = true; 5104169689Skan mips_hi_relocs[SYMBOL_64_MID] = "%higher("; 5105169689Skan mips_lo_relocs[SYMBOL_64_MID] = "%hi("; 5106169689Skan 5107169689Skan mips_split_p[SYMBOL_64_LOW] = true; 5108169689Skan mips_hi_relocs[SYMBOL_64_LOW] = "%hi("; 5109169689Skan mips_lo_relocs[SYMBOL_64_LOW] = "%lo("; 5110169689Skan 5111169689Skan mips_split_p[SYMBOL_GENERAL] = true; 5112169689Skan mips_lo_relocs[SYMBOL_GENERAL] = "%lo("; 5113169689Skan } 5114169689Skan } 5115169689Skan else 5116169689Skan { 5117169689Skan if (TARGET_EXPLICIT_RELOCS || mips_split_addresses) 5118169689Skan { 5119169689Skan mips_split_p[SYMBOL_GENERAL] = true; 5120169689Skan mips_hi_relocs[SYMBOL_GENERAL] = "%hi("; 5121169689Skan mips_lo_relocs[SYMBOL_GENERAL] = "%lo("; 5122169689Skan } 5123169689Skan } 5124169689Skan 5125169689Skan if (TARGET_MIPS16) 5126169689Skan { 5127169689Skan /* The high part is provided by a pseudo copy of $gp. */ 5128169689Skan mips_split_p[SYMBOL_SMALL_DATA] = true; 5129169689Skan mips_lo_relocs[SYMBOL_SMALL_DATA] = "%gprel("; 5130169689Skan } 5131169689Skan 5132169689Skan if (TARGET_EXPLICIT_RELOCS) 5133169689Skan { 5134169689Skan /* Small data constants are kept whole until after reload, 5135169689Skan then lowered by mips_rewrite_small_data. */ 5136169689Skan mips_lo_relocs[SYMBOL_SMALL_DATA] = "%gp_rel("; 5137169689Skan 5138169689Skan mips_split_p[SYMBOL_GOT_LOCAL] = true; 5139169689Skan if (TARGET_NEWABI) 5140169689Skan { 5141169689Skan mips_lo_relocs[SYMBOL_GOTOFF_PAGE] = "%got_page("; 5142169689Skan mips_lo_relocs[SYMBOL_GOT_LOCAL] = "%got_ofst("; 5143169689Skan } 5144169689Skan else 5145169689Skan { 5146169689Skan mips_lo_relocs[SYMBOL_GOTOFF_PAGE] = "%got("; 5147169689Skan mips_lo_relocs[SYMBOL_GOT_LOCAL] = "%lo("; 5148169689Skan } 5149169689Skan 5150169689Skan if (TARGET_XGOT) 5151169689Skan { 5152169689Skan /* The HIGH and LO_SUM are matched by special .md patterns. */ 5153169689Skan mips_split_p[SYMBOL_GOT_GLOBAL] = true; 5154169689Skan 5155169689Skan mips_split_p[SYMBOL_GOTOFF_GLOBAL] = true; 5156169689Skan mips_hi_relocs[SYMBOL_GOTOFF_GLOBAL] = "%got_hi("; 5157169689Skan mips_lo_relocs[SYMBOL_GOTOFF_GLOBAL] = "%got_lo("; 5158169689Skan 5159169689Skan mips_split_p[SYMBOL_GOTOFF_CALL] = true; 5160169689Skan mips_hi_relocs[SYMBOL_GOTOFF_CALL] = "%call_hi("; 5161169689Skan mips_lo_relocs[SYMBOL_GOTOFF_CALL] = "%call_lo("; 5162169689Skan } 5163169689Skan else 5164169689Skan { 5165169689Skan if (TARGET_NEWABI) 5166169689Skan mips_lo_relocs[SYMBOL_GOTOFF_GLOBAL] = "%got_disp("; 5167169689Skan else 5168169689Skan mips_lo_relocs[SYMBOL_GOTOFF_GLOBAL] = "%got("; 5169169689Skan mips_lo_relocs[SYMBOL_GOTOFF_CALL] = "%call16("; 5170169689Skan } 5171169689Skan } 5172169689Skan 5173169689Skan if (TARGET_NEWABI) 5174169689Skan { 5175169689Skan mips_split_p[SYMBOL_GOTOFF_LOADGP] = true; 5176169689Skan mips_hi_relocs[SYMBOL_GOTOFF_LOADGP] = "%hi(%neg(%gp_rel("; 5177169689Skan mips_lo_relocs[SYMBOL_GOTOFF_LOADGP] = "%lo(%neg(%gp_rel("; 5178169689Skan } 5179169689Skan 5180169689Skan /* Thread-local relocation operators. */ 5181169689Skan mips_lo_relocs[SYMBOL_TLSGD] = "%tlsgd("; 5182169689Skan mips_lo_relocs[SYMBOL_TLSLDM] = "%tlsldm("; 5183169689Skan mips_split_p[SYMBOL_DTPREL] = 1; 5184169689Skan mips_hi_relocs[SYMBOL_DTPREL] = "%dtprel_hi("; 5185169689Skan mips_lo_relocs[SYMBOL_DTPREL] = "%dtprel_lo("; 5186169689Skan mips_lo_relocs[SYMBOL_GOTTPREL] = "%gottprel("; 5187169689Skan mips_split_p[SYMBOL_TPREL] = 1; 5188169689Skan mips_hi_relocs[SYMBOL_TPREL] = "%tprel_hi("; 5189169689Skan mips_lo_relocs[SYMBOL_TPREL] = "%tprel_lo("; 5190169689Skan 5191169689Skan /* We don't have a thread pointer access instruction on MIPS16, or 5192169689Skan appropriate TLS relocations. */ 5193169689Skan if (TARGET_MIPS16) 5194169689Skan targetm.have_tls = false; 5195169689Skan 5196169689Skan /* Default to working around R4000 errata only if the processor 5197169689Skan was selected explicitly. */ 5198169689Skan if ((target_flags_explicit & MASK_FIX_R4000) == 0 5199169689Skan && mips_matching_cpu_name_p (mips_arch_info->name, "r4000")) 5200169689Skan target_flags |= MASK_FIX_R4000; 5201169689Skan 5202169689Skan /* Default to working around R4400 errata only if the processor 5203169689Skan was selected explicitly. */ 5204169689Skan if ((target_flags_explicit & MASK_FIX_R4400) == 0 5205169689Skan && mips_matching_cpu_name_p (mips_arch_info->name, "r4400")) 5206169689Skan target_flags |= MASK_FIX_R4400; 5207169689Skan} 5208169689Skan 5209169689Skan/* Implement CONDITIONAL_REGISTER_USAGE. */ 5210169689Skan 5211169689Skanvoid 5212169689Skanmips_conditional_register_usage (void) 5213169689Skan{ 5214169689Skan if (!TARGET_DSP) 5215169689Skan { 5216169689Skan int regno; 5217169689Skan 5218169689Skan for (regno = DSP_ACC_REG_FIRST; regno <= DSP_ACC_REG_LAST; regno++) 5219169689Skan fixed_regs[regno] = call_used_regs[regno] = 1; 5220169689Skan } 5221169689Skan if (!TARGET_HARD_FLOAT) 5222169689Skan { 5223169689Skan int regno; 5224169689Skan 5225169689Skan for (regno = FP_REG_FIRST; regno <= FP_REG_LAST; regno++) 5226169689Skan fixed_regs[regno] = call_used_regs[regno] = 1; 5227169689Skan for (regno = ST_REG_FIRST; regno <= ST_REG_LAST; regno++) 5228169689Skan fixed_regs[regno] = call_used_regs[regno] = 1; 5229169689Skan } 5230169689Skan else if (! ISA_HAS_8CC) 5231169689Skan { 5232169689Skan int regno; 5233169689Skan 5234169689Skan /* We only have a single condition code register. We 5235169689Skan implement this by hiding all the condition code registers, 5236169689Skan and generating RTL that refers directly to ST_REG_FIRST. */ 5237169689Skan for (regno = ST_REG_FIRST; regno <= ST_REG_LAST; regno++) 5238169689Skan fixed_regs[regno] = call_used_regs[regno] = 1; 5239169689Skan } 5240169689Skan /* In mips16 mode, we permit the $t temporary registers to be used 5241169689Skan for reload. We prohibit the unused $s registers, since they 5242169689Skan are caller saved, and saving them via a mips16 register would 5243169689Skan probably waste more time than just reloading the value. */ 5244169689Skan if (TARGET_MIPS16) 5245169689Skan { 5246169689Skan fixed_regs[18] = call_used_regs[18] = 1; 5247169689Skan fixed_regs[19] = call_used_regs[19] = 1; 5248169689Skan fixed_regs[20] = call_used_regs[20] = 1; 5249169689Skan fixed_regs[21] = call_used_regs[21] = 1; 5250169689Skan fixed_regs[22] = call_used_regs[22] = 1; 5251169689Skan fixed_regs[23] = call_used_regs[23] = 1; 5252169689Skan fixed_regs[26] = call_used_regs[26] = 1; 5253169689Skan fixed_regs[27] = call_used_regs[27] = 1; 5254169689Skan fixed_regs[30] = call_used_regs[30] = 1; 5255169689Skan } 5256169689Skan /* fp20-23 are now caller saved. */ 5257169689Skan if (mips_abi == ABI_64) 5258169689Skan { 5259169689Skan int regno; 5260169689Skan for (regno = FP_REG_FIRST + 20; regno < FP_REG_FIRST + 24; regno++) 5261169689Skan call_really_used_regs[regno] = call_used_regs[regno] = 1; 5262169689Skan } 5263169689Skan /* Odd registers from fp21 to fp31 are now caller saved. */ 5264169689Skan if (mips_abi == ABI_N32) 5265169689Skan { 5266169689Skan int regno; 5267169689Skan for (regno = FP_REG_FIRST + 21; regno <= FP_REG_FIRST + 31; regno+=2) 5268169689Skan call_really_used_regs[regno] = call_used_regs[regno] = 1; 5269169689Skan } 5270169689Skan} 5271169689Skan 5272169689Skan/* Allocate a chunk of memory for per-function machine-dependent data. */ 5273169689Skanstatic struct machine_function * 5274169689Skanmips_init_machine_status (void) 5275169689Skan{ 5276169689Skan return ((struct machine_function *) 5277169689Skan ggc_alloc_cleared (sizeof (struct machine_function))); 5278169689Skan} 5279169689Skan 5280169689Skan/* On the mips16, we want to allocate $24 (T_REG) before other 5281169689Skan registers for instructions for which it is possible. This helps 5282169689Skan avoid shuffling registers around in order to set up for an xor, 5283169689Skan encouraging the compiler to use a cmp instead. */ 5284169689Skan 5285169689Skanvoid 5286169689Skanmips_order_regs_for_local_alloc (void) 5287169689Skan{ 5288169689Skan register int i; 5289169689Skan 5290169689Skan for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 5291169689Skan reg_alloc_order[i] = i; 5292169689Skan 5293169689Skan if (TARGET_MIPS16) 5294169689Skan { 5295169689Skan /* It really doesn't matter where we put register 0, since it is 5296169689Skan a fixed register anyhow. */ 5297169689Skan reg_alloc_order[0] = 24; 5298169689Skan reg_alloc_order[24] = 0; 5299169689Skan } 5300169689Skan} 5301169689Skan 5302169689Skan 5303169689Skan/* The MIPS debug format wants all automatic variables and arguments 5304169689Skan to be in terms of the virtual frame pointer (stack pointer before 5305169689Skan any adjustment in the function), while the MIPS 3.0 linker wants 5306169689Skan the frame pointer to be the stack pointer after the initial 5307169689Skan adjustment. So, we do the adjustment here. The arg pointer (which 5308169689Skan is eliminated) points to the virtual frame pointer, while the frame 5309169689Skan pointer (which may be eliminated) points to the stack pointer after 5310169689Skan the initial adjustments. */ 5311169689Skan 5312169689SkanHOST_WIDE_INT 5313169689Skanmips_debugger_offset (rtx addr, HOST_WIDE_INT offset) 5314169689Skan{ 5315169689Skan rtx offset2 = const0_rtx; 5316169689Skan rtx reg = eliminate_constant_term (addr, &offset2); 5317169689Skan 5318169689Skan if (offset == 0) 5319169689Skan offset = INTVAL (offset2); 5320169689Skan 5321169689Skan if (reg == stack_pointer_rtx || reg == frame_pointer_rtx 5322169689Skan || reg == hard_frame_pointer_rtx) 5323169689Skan { 5324169689Skan HOST_WIDE_INT frame_size = (!cfun->machine->frame.initialized) 5325169689Skan ? compute_frame_size (get_frame_size ()) 5326169689Skan : cfun->machine->frame.total_size; 5327169689Skan 5328169689Skan /* MIPS16 frame is smaller */ 5329169689Skan if (frame_pointer_needed && TARGET_MIPS16) 5330169689Skan frame_size -= cfun->machine->frame.args_size; 5331169689Skan 5332169689Skan offset = offset - frame_size; 5333169689Skan } 5334169689Skan 5335169689Skan /* sdbout_parms does not want this to crash for unrecognized cases. */ 5336169689Skan#if 0 5337169689Skan else if (reg != arg_pointer_rtx) 5338169689Skan fatal_insn ("mips_debugger_offset called with non stack/frame/arg pointer", 5339169689Skan addr); 5340169689Skan#endif 5341169689Skan 5342169689Skan return offset; 5343169689Skan} 5344169689Skan 5345169689Skan/* Implement the PRINT_OPERAND macro. The MIPS-specific operand codes are: 5346169689Skan 5347169689Skan 'X' OP is CONST_INT, prints 32 bits in hexadecimal format = "0x%08x", 5348169689Skan 'x' OP is CONST_INT, prints 16 bits in hexadecimal format = "0x%04x", 5349169689Skan 'h' OP is HIGH, prints %hi(X), 5350169689Skan 'd' output integer constant in decimal, 5351169689Skan 'z' if the operand is 0, use $0 instead of normal operand. 5352169689Skan 'D' print second part of double-word register or memory operand. 5353169689Skan 'L' print low-order register of double-word register operand. 5354169689Skan 'M' print high-order register of double-word register operand. 5355169689Skan 'C' print part of opcode for a branch condition. 5356169689Skan 'F' print part of opcode for a floating-point branch condition. 5357169689Skan 'N' print part of opcode for a branch condition, inverted. 5358169689Skan 'W' print part of opcode for a floating-point branch condition, inverted. 5359169689Skan 'T' print 'f' for (eq:CC ...), 't' for (ne:CC ...), 5360169689Skan 'z' for (eq:?I ...), 'n' for (ne:?I ...). 5361169689Skan 't' like 'T', but with the EQ/NE cases reversed 5362169689Skan 'Y' for a CONST_INT X, print mips_fp_conditions[X] 5363169689Skan 'Z' print the operand and a comma for ISA_HAS_8CC, otherwise print nothing 5364169689Skan 'R' print the reloc associated with LO_SUM 5365169689Skan 'q' print DSP accumulator registers 5366169689Skan 5367169689Skan The punctuation characters are: 5368169689Skan 5369169689Skan '(' Turn on .set noreorder 5370169689Skan ')' Turn on .set reorder 5371169689Skan '[' Turn on .set noat 5372169689Skan ']' Turn on .set at 5373169689Skan '<' Turn on .set nomacro 5374169689Skan '>' Turn on .set macro 5375169689Skan '{' Turn on .set volatile (not GAS) 5376169689Skan '}' Turn on .set novolatile (not GAS) 5377169689Skan '&' Turn on .set noreorder if filling delay slots 5378169689Skan '*' Turn on both .set noreorder and .set nomacro if filling delay slots 5379169689Skan '!' Turn on .set nomacro if filling delay slots 5380169689Skan '#' Print nop if in a .set noreorder section. 5381169689Skan '/' Like '#', but does nothing within a delayed branch sequence 5382169689Skan '?' Print 'l' if we are to use a branch likely instead of normal branch. 5383169689Skan '@' Print the name of the assembler temporary register (at or $1). 5384169689Skan '.' Print the name of the register with a hard-wired zero (zero or $0). 5385169689Skan '^' Print the name of the pic call-through register (t9 or $25). 5386169689Skan '$' Print the name of the stack pointer register (sp or $29). 5387169689Skan '+' Print the name of the gp register (usually gp or $28). 5388169689Skan '~' Output a branch alignment to LABEL_ALIGN(NULL). */ 5389169689Skan 5390169689Skanvoid 5391169689Skanprint_operand (FILE *file, rtx op, int letter) 5392169689Skan{ 5393169689Skan register enum rtx_code code; 5394169689Skan 5395169689Skan if (PRINT_OPERAND_PUNCT_VALID_P (letter)) 5396169689Skan { 5397169689Skan switch (letter) 5398169689Skan { 5399169689Skan case '?': 5400169689Skan if (mips_branch_likely) 5401169689Skan putc ('l', file); 5402169689Skan break; 5403169689Skan 5404169689Skan case '@': 5405169689Skan fputs (reg_names [GP_REG_FIRST + 1], file); 5406169689Skan break; 5407169689Skan 5408169689Skan case '^': 5409169689Skan fputs (reg_names [PIC_FUNCTION_ADDR_REGNUM], file); 5410169689Skan break; 5411169689Skan 5412169689Skan case '.': 5413169689Skan fputs (reg_names [GP_REG_FIRST + 0], file); 5414169689Skan break; 5415169689Skan 5416169689Skan case '$': 5417169689Skan fputs (reg_names[STACK_POINTER_REGNUM], file); 5418169689Skan break; 5419169689Skan 5420169689Skan case '+': 5421169689Skan fputs (reg_names[PIC_OFFSET_TABLE_REGNUM], file); 5422169689Skan break; 5423169689Skan 5424169689Skan case '&': 5425169689Skan if (final_sequence != 0 && set_noreorder++ == 0) 5426169689Skan fputs (".set\tnoreorder\n\t", file); 5427169689Skan break; 5428169689Skan 5429169689Skan case '*': 5430169689Skan if (final_sequence != 0) 5431169689Skan { 5432169689Skan if (set_noreorder++ == 0) 5433169689Skan fputs (".set\tnoreorder\n\t", file); 5434169689Skan 5435169689Skan if (set_nomacro++ == 0) 5436169689Skan fputs (".set\tnomacro\n\t", file); 5437169689Skan } 5438169689Skan break; 5439169689Skan 5440169689Skan case '!': 5441169689Skan if (final_sequence != 0 && set_nomacro++ == 0) 5442169689Skan fputs ("\n\t.set\tnomacro", file); 5443169689Skan break; 5444169689Skan 5445169689Skan case '#': 5446169689Skan if (set_noreorder != 0) 5447169689Skan fputs ("\n\tnop", file); 5448169689Skan break; 5449169689Skan 5450169689Skan case '/': 5451169689Skan /* Print an extra newline so that the delayed insn is separated 5452169689Skan from the following ones. This looks neater and is consistent 5453169689Skan with non-nop delayed sequences. */ 5454169689Skan if (set_noreorder != 0 && final_sequence == 0) 5455169689Skan fputs ("\n\tnop\n", file); 5456169689Skan break; 5457169689Skan 5458169689Skan case '(': 5459169689Skan if (set_noreorder++ == 0) 5460169689Skan fputs (".set\tnoreorder\n\t", file); 5461169689Skan break; 5462169689Skan 5463169689Skan case ')': 5464169689Skan if (set_noreorder == 0) 5465169689Skan error ("internal error: %%) found without a %%( in assembler pattern"); 5466169689Skan 5467169689Skan else if (--set_noreorder == 0) 5468169689Skan fputs ("\n\t.set\treorder", file); 5469169689Skan 5470169689Skan break; 5471169689Skan 5472169689Skan case '[': 5473169689Skan if (set_noat++ == 0) 5474169689Skan fputs (".set\tnoat\n\t", file); 5475169689Skan break; 5476169689Skan 5477169689Skan case ']': 5478169689Skan if (set_noat == 0) 5479169689Skan error ("internal error: %%] found without a %%[ in assembler pattern"); 5480169689Skan else if (--set_noat == 0) 5481169689Skan fputs ("\n\t.set\tat", file); 5482169689Skan 5483169689Skan break; 5484169689Skan 5485169689Skan case '<': 5486169689Skan if (set_nomacro++ == 0) 5487169689Skan fputs (".set\tnomacro\n\t", file); 5488169689Skan break; 5489169689Skan 5490169689Skan case '>': 5491169689Skan if (set_nomacro == 0) 5492169689Skan error ("internal error: %%> found without a %%< in assembler pattern"); 5493169689Skan else if (--set_nomacro == 0) 5494169689Skan fputs ("\n\t.set\tmacro", file); 5495169689Skan 5496169689Skan break; 5497169689Skan 5498169689Skan case '{': 5499169689Skan if (set_volatile++ == 0) 5500169689Skan fputs ("#.set\tvolatile\n\t", file); 5501169689Skan break; 5502169689Skan 5503169689Skan case '}': 5504169689Skan if (set_volatile == 0) 5505169689Skan error ("internal error: %%} found without a %%{ in assembler pattern"); 5506169689Skan else if (--set_volatile == 0) 5507169689Skan fputs ("\n\t#.set\tnovolatile", file); 5508169689Skan 5509169689Skan break; 5510169689Skan 5511169689Skan case '~': 5512169689Skan { 5513169689Skan if (align_labels_log > 0) 5514169689Skan ASM_OUTPUT_ALIGN (file, align_labels_log); 5515169689Skan } 5516169689Skan break; 5517169689Skan 5518169689Skan default: 5519169689Skan error ("PRINT_OPERAND: unknown punctuation '%c'", letter); 5520169689Skan break; 5521169689Skan } 5522169689Skan 5523169689Skan return; 5524169689Skan } 5525169689Skan 5526169689Skan if (! op) 5527169689Skan { 5528169689Skan error ("PRINT_OPERAND null pointer"); 5529169689Skan return; 5530169689Skan } 5531169689Skan 5532169689Skan code = GET_CODE (op); 5533169689Skan 5534169689Skan if (letter == 'C') 5535169689Skan switch (code) 5536169689Skan { 5537169689Skan case EQ: fputs ("eq", file); break; 5538169689Skan case NE: fputs ("ne", file); break; 5539169689Skan case GT: fputs ("gt", file); break; 5540169689Skan case GE: fputs ("ge", file); break; 5541169689Skan case LT: fputs ("lt", file); break; 5542169689Skan case LE: fputs ("le", file); break; 5543169689Skan case GTU: fputs ("gtu", file); break; 5544169689Skan case GEU: fputs ("geu", file); break; 5545169689Skan case LTU: fputs ("ltu", file); break; 5546169689Skan case LEU: fputs ("leu", file); break; 5547169689Skan default: 5548169689Skan fatal_insn ("PRINT_OPERAND, invalid insn for %%C", op); 5549169689Skan } 5550169689Skan 5551169689Skan else if (letter == 'N') 5552169689Skan switch (code) 5553169689Skan { 5554169689Skan case EQ: fputs ("ne", file); break; 5555169689Skan case NE: fputs ("eq", file); break; 5556169689Skan case GT: fputs ("le", file); break; 5557169689Skan case GE: fputs ("lt", file); break; 5558169689Skan case LT: fputs ("ge", file); break; 5559169689Skan case LE: fputs ("gt", file); break; 5560169689Skan case GTU: fputs ("leu", file); break; 5561169689Skan case GEU: fputs ("ltu", file); break; 5562169689Skan case LTU: fputs ("geu", file); break; 5563169689Skan case LEU: fputs ("gtu", file); break; 5564169689Skan default: 5565169689Skan fatal_insn ("PRINT_OPERAND, invalid insn for %%N", op); 5566169689Skan } 5567169689Skan 5568169689Skan else if (letter == 'F') 5569169689Skan switch (code) 5570169689Skan { 5571169689Skan case EQ: fputs ("c1f", file); break; 5572169689Skan case NE: fputs ("c1t", file); break; 5573169689Skan default: 5574169689Skan fatal_insn ("PRINT_OPERAND, invalid insn for %%F", op); 5575169689Skan } 5576169689Skan 5577169689Skan else if (letter == 'W') 5578169689Skan switch (code) 5579169689Skan { 5580169689Skan case EQ: fputs ("c1t", file); break; 5581169689Skan case NE: fputs ("c1f", file); break; 5582169689Skan default: 5583169689Skan fatal_insn ("PRINT_OPERAND, invalid insn for %%W", op); 5584169689Skan } 5585169689Skan 5586169689Skan else if (letter == 'h') 5587169689Skan { 5588169689Skan if (GET_CODE (op) == HIGH) 5589169689Skan op = XEXP (op, 0); 5590169689Skan 5591169689Skan print_operand_reloc (file, op, mips_hi_relocs); 5592169689Skan } 5593169689Skan 5594169689Skan else if (letter == 'R') 5595169689Skan print_operand_reloc (file, op, mips_lo_relocs); 5596169689Skan 5597169689Skan else if (letter == 'Y') 5598169689Skan { 5599169689Skan if (GET_CODE (op) == CONST_INT 5600169689Skan && ((unsigned HOST_WIDE_INT) INTVAL (op) 5601169689Skan < ARRAY_SIZE (mips_fp_conditions))) 5602169689Skan fputs (mips_fp_conditions[INTVAL (op)], file); 5603169689Skan else 5604169689Skan output_operand_lossage ("invalid %%Y value"); 5605169689Skan } 5606169689Skan 5607169689Skan else if (letter == 'Z') 5608169689Skan { 5609169689Skan if (ISA_HAS_8CC) 5610169689Skan { 5611169689Skan print_operand (file, op, 0); 5612169689Skan fputc (',', file); 5613169689Skan } 5614169689Skan } 5615169689Skan 5616169689Skan else if (letter == 'q') 5617169689Skan { 5618169689Skan int regnum; 5619169689Skan 5620169689Skan if (code != REG) 5621169689Skan fatal_insn ("PRINT_OPERAND, invalid insn for %%q", op); 5622169689Skan 5623169689Skan regnum = REGNO (op); 5624169689Skan if (MD_REG_P (regnum)) 5625169689Skan fprintf (file, "$ac0"); 5626169689Skan else if (DSP_ACC_REG_P (regnum)) 5627169689Skan fprintf (file, "$ac%c", reg_names[regnum][3]); 5628169689Skan else 5629169689Skan fatal_insn ("PRINT_OPERAND, invalid insn for %%q", op); 5630169689Skan } 5631169689Skan 5632169689Skan else if (code == REG || code == SUBREG) 5633169689Skan { 5634169689Skan register int regnum; 5635169689Skan 5636169689Skan if (code == REG) 5637169689Skan regnum = REGNO (op); 5638169689Skan else 5639169689Skan regnum = true_regnum (op); 5640169689Skan 5641169689Skan if ((letter == 'M' && ! WORDS_BIG_ENDIAN) 5642169689Skan || (letter == 'L' && WORDS_BIG_ENDIAN) 5643169689Skan || letter == 'D') 5644169689Skan regnum++; 5645169689Skan 5646169689Skan fprintf (file, "%s", reg_names[regnum]); 5647169689Skan } 5648169689Skan 5649169689Skan else if (code == MEM) 5650169689Skan { 5651169689Skan if (letter == 'D') 5652169689Skan output_address (plus_constant (XEXP (op, 0), 4)); 5653169689Skan else 5654169689Skan output_address (XEXP (op, 0)); 5655169689Skan } 5656169689Skan 5657169689Skan else if (letter == 'x' && GET_CODE (op) == CONST_INT) 5658169689Skan fprintf (file, HOST_WIDE_INT_PRINT_HEX, 0xffff & INTVAL(op)); 5659169689Skan 5660169689Skan else if (letter == 'X' && GET_CODE(op) == CONST_INT) 5661169689Skan fprintf (file, HOST_WIDE_INT_PRINT_HEX, INTVAL (op)); 5662169689Skan 5663169689Skan else if (letter == 'd' && GET_CODE(op) == CONST_INT) 5664169689Skan fprintf (file, HOST_WIDE_INT_PRINT_DEC, (INTVAL(op))); 5665169689Skan 5666169689Skan else if (letter == 'z' && op == CONST0_RTX (GET_MODE (op))) 5667169689Skan fputs (reg_names[GP_REG_FIRST], file); 5668169689Skan 5669169689Skan else if (letter == 'd' || letter == 'x' || letter == 'X') 5670169689Skan output_operand_lossage ("invalid use of %%d, %%x, or %%X"); 5671169689Skan 5672169689Skan else if (letter == 'T' || letter == 't') 5673169689Skan { 5674169689Skan int truth = (code == NE) == (letter == 'T'); 5675169689Skan fputc ("zfnt"[truth * 2 + (GET_MODE (op) == CCmode)], file); 5676169689Skan } 5677169689Skan 5678169689Skan else if (CONST_GP_P (op)) 5679169689Skan fputs (reg_names[GLOBAL_POINTER_REGNUM], file); 5680169689Skan 5681169689Skan else 5682169689Skan output_addr_const (file, op); 5683169689Skan} 5684169689Skan 5685169689Skan 5686169689Skan/* Print symbolic operand OP, which is part of a HIGH or LO_SUM. 5687169689Skan RELOCS is the array of relocations to use. */ 5688169689Skan 5689169689Skanstatic void 5690169689Skanprint_operand_reloc (FILE *file, rtx op, const char **relocs) 5691169689Skan{ 5692169689Skan enum mips_symbol_type symbol_type; 5693169689Skan const char *p; 5694169689Skan rtx base; 5695169689Skan HOST_WIDE_INT offset; 5696169689Skan 5697234855Sgonzo symbol_type = mips_classify_symbolic_expression (op); 5698234855Sgonzo if (relocs[symbol_type] == 0) 5699169689Skan fatal_insn ("PRINT_OPERAND, invalid operand for relocation", op); 5700169689Skan 5701169689Skan /* If OP uses an UNSPEC address, we want to print the inner symbol. */ 5702169689Skan mips_split_const (op, &base, &offset); 5703169689Skan if (UNSPEC_ADDRESS_P (base)) 5704169689Skan op = plus_constant (UNSPEC_ADDRESS (base), offset); 5705169689Skan 5706169689Skan fputs (relocs[symbol_type], file); 5707169689Skan output_addr_const (file, op); 5708169689Skan for (p = relocs[symbol_type]; *p != 0; p++) 5709169689Skan if (*p == '(') 5710169689Skan fputc (')', file); 5711169689Skan} 5712169689Skan 5713169689Skan/* Output address operand X to FILE. */ 5714169689Skan 5715169689Skanvoid 5716169689Skanprint_operand_address (FILE *file, rtx x) 5717169689Skan{ 5718169689Skan struct mips_address_info addr; 5719169689Skan 5720169689Skan if (mips_classify_address (&addr, x, word_mode, true)) 5721169689Skan switch (addr.type) 5722169689Skan { 5723169689Skan case ADDRESS_REG: 5724169689Skan print_operand (file, addr.offset, 0); 5725169689Skan fprintf (file, "(%s)", reg_names[REGNO (addr.reg)]); 5726169689Skan return; 5727169689Skan 5728169689Skan case ADDRESS_LO_SUM: 5729169689Skan print_operand (file, addr.offset, 'R'); 5730169689Skan fprintf (file, "(%s)", reg_names[REGNO (addr.reg)]); 5731169689Skan return; 5732169689Skan 5733169689Skan case ADDRESS_CONST_INT: 5734169689Skan output_addr_const (file, x); 5735169689Skan fprintf (file, "(%s)", reg_names[0]); 5736169689Skan return; 5737169689Skan 5738169689Skan case ADDRESS_SYMBOLIC: 5739169689Skan output_addr_const (file, x); 5740169689Skan return; 5741169689Skan } 5742169689Skan gcc_unreachable (); 5743169689Skan} 5744169689Skan 5745169689Skan/* When using assembler macros, keep track of all of small-data externs 5746169689Skan so that mips_file_end can emit the appropriate declarations for them. 5747169689Skan 5748169689Skan In most cases it would be safe (though pointless) to emit .externs 5749169689Skan for other symbols too. One exception is when an object is within 5750169689Skan the -G limit but declared by the user to be in a section other 5751169689Skan than .sbss or .sdata. */ 5752169689Skan 5753169689Skanint 5754169689Skanmips_output_external (FILE *file ATTRIBUTE_UNUSED, tree decl, const char *name) 5755169689Skan{ 5756169689Skan register struct extern_list *p; 5757169689Skan 5758169689Skan if (!TARGET_EXPLICIT_RELOCS && mips_in_small_data_p (decl)) 5759169689Skan { 5760169689Skan p = (struct extern_list *) ggc_alloc (sizeof (struct extern_list)); 5761169689Skan p->next = extern_head; 5762169689Skan p->name = name; 5763169689Skan p->size = int_size_in_bytes (TREE_TYPE (decl)); 5764169689Skan extern_head = p; 5765169689Skan } 5766169689Skan 5767169689Skan if (TARGET_IRIX && mips_abi == ABI_32 && TREE_CODE (decl) == FUNCTION_DECL) 5768169689Skan { 5769169689Skan p = (struct extern_list *) ggc_alloc (sizeof (struct extern_list)); 5770169689Skan p->next = extern_head; 5771169689Skan p->name = name; 5772169689Skan p->size = -1; 5773169689Skan extern_head = p; 5774169689Skan } 5775169689Skan 5776169689Skan return 0; 5777169689Skan} 5778169689Skan 5779169689Skan#if TARGET_IRIX 5780169689Skanstatic void 5781169689Skanirix_output_external_libcall (rtx fun) 5782169689Skan{ 5783169689Skan register struct extern_list *p; 5784169689Skan 5785169689Skan if (mips_abi == ABI_32) 5786169689Skan { 5787169689Skan p = (struct extern_list *) ggc_alloc (sizeof (struct extern_list)); 5788169689Skan p->next = extern_head; 5789169689Skan p->name = XSTR (fun, 0); 5790169689Skan p->size = -1; 5791169689Skan extern_head = p; 5792169689Skan } 5793169689Skan} 5794169689Skan#endif 5795169689Skan 5796169689Skan/* Emit a new filename to a stream. If we are smuggling stabs, try to 5797169689Skan put out a MIPS ECOFF file and a stab. */ 5798169689Skan 5799169689Skanvoid 5800169689Skanmips_output_filename (FILE *stream, const char *name) 5801169689Skan{ 5802169689Skan 5803169689Skan /* If we are emitting DWARF-2, let dwarf2out handle the ".file" 5804169689Skan directives. */ 5805169689Skan if (write_symbols == DWARF2_DEBUG) 5806169689Skan return; 5807169689Skan else if (mips_output_filename_first_time) 5808169689Skan { 5809169689Skan mips_output_filename_first_time = 0; 5810169689Skan num_source_filenames += 1; 5811169689Skan current_function_file = name; 5812169689Skan fprintf (stream, "\t.file\t%d ", num_source_filenames); 5813169689Skan output_quoted_string (stream, name); 5814169689Skan putc ('\n', stream); 5815169689Skan } 5816169689Skan 5817169689Skan /* If we are emitting stabs, let dbxout.c handle this (except for 5818169689Skan the mips_output_filename_first_time case). */ 5819169689Skan else if (write_symbols == DBX_DEBUG) 5820169689Skan return; 5821169689Skan 5822169689Skan else if (name != current_function_file 5823169689Skan && strcmp (name, current_function_file) != 0) 5824169689Skan { 5825169689Skan num_source_filenames += 1; 5826169689Skan current_function_file = name; 5827169689Skan fprintf (stream, "\t.file\t%d ", num_source_filenames); 5828169689Skan output_quoted_string (stream, name); 5829169689Skan putc ('\n', stream); 5830169689Skan } 5831169689Skan} 5832169689Skan 5833169689Skan/* Output an ASCII string, in a space-saving way. PREFIX is the string 5834169689Skan that should be written before the opening quote, such as "\t.ascii\t" 5835169689Skan for real string data or "\t# " for a comment. */ 5836169689Skan 5837169689Skanvoid 5838169689Skanmips_output_ascii (FILE *stream, const char *string_param, size_t len, 5839169689Skan const char *prefix) 5840169689Skan{ 5841169689Skan size_t i; 5842169689Skan int cur_pos = 17; 5843169689Skan register const unsigned char *string = 5844169689Skan (const unsigned char *)string_param; 5845169689Skan 5846169689Skan fprintf (stream, "%s\"", prefix); 5847169689Skan for (i = 0; i < len; i++) 5848169689Skan { 5849169689Skan register int c = string[i]; 5850169689Skan 5851169689Skan if (ISPRINT (c)) 5852169689Skan { 5853169689Skan if (c == '\\' || c == '\"') 5854169689Skan { 5855169689Skan putc ('\\', stream); 5856169689Skan cur_pos++; 5857169689Skan } 5858169689Skan putc (c, stream); 5859169689Skan cur_pos++; 5860169689Skan } 5861169689Skan else 5862169689Skan { 5863169689Skan fprintf (stream, "\\%03o", c); 5864169689Skan cur_pos += 4; 5865169689Skan } 5866169689Skan 5867169689Skan if (cur_pos > 72 && i+1 < len) 5868169689Skan { 5869169689Skan cur_pos = 17; 5870169689Skan fprintf (stream, "\"\n%s\"", prefix); 5871169689Skan } 5872169689Skan } 5873169689Skan fprintf (stream, "\"\n"); 5874169689Skan} 5875169689Skan 5876169689Skan/* Implement TARGET_ASM_FILE_START. */ 5877169689Skan 5878169689Skanstatic void 5879169689Skanmips_file_start (void) 5880169689Skan{ 5881169689Skan default_file_start (); 5882169689Skan 5883169689Skan if (!TARGET_IRIX) 5884169689Skan { 5885169689Skan /* Generate a special section to describe the ABI switches used to 5886169689Skan produce the resultant binary. This used to be done by the assembler 5887169689Skan setting bits in the ELF header's flags field, but we have run out of 5888169689Skan bits. GDB needs this information in order to be able to correctly 5889169689Skan debug these binaries. See the function mips_gdbarch_init() in 5890169689Skan gdb/mips-tdep.c. This is unnecessary for the IRIX 5/6 ABIs and 5891169689Skan causes unnecessary IRIX 6 ld warnings. */ 5892169689Skan const char * abi_string = NULL; 5893169689Skan 5894169689Skan switch (mips_abi) 5895169689Skan { 5896169689Skan case ABI_32: abi_string = "abi32"; break; 5897169689Skan case ABI_N32: abi_string = "abiN32"; break; 5898169689Skan case ABI_64: abi_string = "abi64"; break; 5899169689Skan case ABI_O64: abi_string = "abiO64"; break; 5900169689Skan case ABI_EABI: abi_string = TARGET_64BIT ? "eabi64" : "eabi32"; break; 5901169689Skan default: 5902169689Skan gcc_unreachable (); 5903169689Skan } 5904169689Skan /* Note - we use fprintf directly rather than calling switch_to_section 5905169689Skan because in this way we can avoid creating an allocated section. We 5906169689Skan do not want this section to take up any space in the running 5907169689Skan executable. */ 5908169689Skan fprintf (asm_out_file, "\t.section .mdebug.%s\n", abi_string); 5909169689Skan 5910169689Skan /* There is no ELF header flag to distinguish long32 forms of the 5911169689Skan EABI from long64 forms. Emit a special section to help tools 5912169689Skan such as GDB. Do the same for o64, which is sometimes used with 5913169689Skan -mlong64. */ 5914169689Skan if (mips_abi == ABI_EABI || mips_abi == ABI_O64) 5915169689Skan fprintf (asm_out_file, "\t.section .gcc_compiled_long%d\n", 5916169689Skan TARGET_LONG64 ? 64 : 32); 5917169689Skan 5918169689Skan /* Restore the default section. */ 5919169689Skan fprintf (asm_out_file, "\t.previous\n"); 5920169689Skan } 5921169689Skan 5922169689Skan /* Generate the pseudo ops that System V.4 wants. */ 5923169689Skan if (TARGET_ABICALLS) 5924169689Skan fprintf (asm_out_file, "\t.abicalls\n"); 5925169689Skan 5926169689Skan if (TARGET_MIPS16) 5927169689Skan fprintf (asm_out_file, "\t.set\tmips16\n"); 5928169689Skan 5929169689Skan if (flag_verbose_asm) 5930169689Skan fprintf (asm_out_file, "\n%s -G value = %d, Arch = %s, ISA = %d\n", 5931169689Skan ASM_COMMENT_START, 5932169689Skan mips_section_threshold, mips_arch_info->name, mips_isa); 5933169689Skan} 5934169689Skan 5935169689Skan#ifdef BSS_SECTION_ASM_OP 5936169689Skan/* Implement ASM_OUTPUT_ALIGNED_BSS. This differs from the default only 5937169689Skan in the use of sbss. */ 5938169689Skan 5939169689Skanvoid 5940169689Skanmips_output_aligned_bss (FILE *stream, tree decl, const char *name, 5941169689Skan unsigned HOST_WIDE_INT size, int align) 5942169689Skan{ 5943169689Skan extern tree last_assemble_variable_decl; 5944169689Skan 5945169689Skan if (mips_in_small_data_p (decl)) 5946169689Skan switch_to_section (get_named_section (NULL, ".sbss", 0)); 5947169689Skan else 5948169689Skan switch_to_section (bss_section); 5949169689Skan ASM_OUTPUT_ALIGN (stream, floor_log2 (align / BITS_PER_UNIT)); 5950169689Skan last_assemble_variable_decl = decl; 5951169689Skan ASM_DECLARE_OBJECT_NAME (stream, name, decl); 5952169689Skan ASM_OUTPUT_SKIP (stream, size != 0 ? size : 1); 5953169689Skan} 5954169689Skan#endif 5955169689Skan 5956169689Skan/* Implement TARGET_ASM_FILE_END. When using assembler macros, emit 5957169689Skan .externs for any small-data variables that turned out to be external. */ 5958169689Skan 5959169689Skanstatic void 5960169689Skanmips_file_end (void) 5961169689Skan{ 5962169689Skan tree name_tree; 5963169689Skan struct extern_list *p; 5964169689Skan 5965169689Skan if (extern_head) 5966169689Skan { 5967169689Skan fputs ("\n", asm_out_file); 5968169689Skan 5969169689Skan for (p = extern_head; p != 0; p = p->next) 5970169689Skan { 5971169689Skan name_tree = get_identifier (p->name); 5972169689Skan 5973169689Skan /* Positively ensure only one .extern for any given symbol. */ 5974169689Skan if (!TREE_ASM_WRITTEN (name_tree) 5975169689Skan && TREE_SYMBOL_REFERENCED (name_tree)) 5976169689Skan { 5977169689Skan TREE_ASM_WRITTEN (name_tree) = 1; 5978169689Skan /* In IRIX 5 or IRIX 6 for the O32 ABI, we must output a 5979169689Skan `.global name .text' directive for every used but 5980169689Skan undefined function. If we don't, the linker may perform 5981169689Skan an optimization (skipping over the insns that set $gp) 5982169689Skan when it is unsafe. */ 5983169689Skan if (TARGET_IRIX && mips_abi == ABI_32 && p->size == -1) 5984169689Skan { 5985169689Skan fputs ("\t.globl ", asm_out_file); 5986169689Skan assemble_name (asm_out_file, p->name); 5987169689Skan fputs (" .text\n", asm_out_file); 5988169689Skan } 5989169689Skan else 5990169689Skan { 5991169689Skan fputs ("\t.extern\t", asm_out_file); 5992169689Skan assemble_name (asm_out_file, p->name); 5993169689Skan fprintf (asm_out_file, ", %d\n", p->size); 5994169689Skan } 5995169689Skan } 5996169689Skan } 5997169689Skan } 5998169689Skan} 5999169689Skan 6000169689Skan/* Implement ASM_OUTPUT_ALIGNED_DECL_COMMON. This is usually the same as the 6001169689Skan elfos.h version, but we also need to handle -muninit-const-in-rodata. */ 6002169689Skan 6003169689Skanvoid 6004169689Skanmips_output_aligned_decl_common (FILE *stream, tree decl, const char *name, 6005169689Skan unsigned HOST_WIDE_INT size, 6006169689Skan unsigned int align) 6007169689Skan{ 6008169689Skan /* If the target wants uninitialized const declarations in 6009169689Skan .rdata then don't put them in .comm. */ 6010169689Skan if (TARGET_EMBEDDED_DATA && TARGET_UNINIT_CONST_IN_RODATA 6011169689Skan && TREE_CODE (decl) == VAR_DECL && TREE_READONLY (decl) 6012169689Skan && (DECL_INITIAL (decl) == 0 || DECL_INITIAL (decl) == error_mark_node)) 6013169689Skan { 6014169689Skan if (TREE_PUBLIC (decl) && DECL_NAME (decl)) 6015169689Skan targetm.asm_out.globalize_label (stream, name); 6016169689Skan 6017169689Skan switch_to_section (readonly_data_section); 6018169689Skan ASM_OUTPUT_ALIGN (stream, floor_log2 (align / BITS_PER_UNIT)); 6019169689Skan mips_declare_object (stream, name, "", 6020169689Skan ":\n\t.space\t" HOST_WIDE_INT_PRINT_UNSIGNED "\n", 6021169689Skan size); 6022169689Skan } 6023169689Skan else 6024169689Skan mips_declare_common_object (stream, name, "\n\t.comm\t", 6025169689Skan size, align, true); 6026169689Skan} 6027169689Skan 6028169689Skan/* Declare a common object of SIZE bytes using asm directive INIT_STRING. 6029169689Skan NAME is the name of the object and ALIGN is the required alignment 6030169689Skan in bytes. TAKES_ALIGNMENT_P is true if the directive takes a third 6031169689Skan alignment argument. */ 6032169689Skan 6033169689Skanvoid 6034169689Skanmips_declare_common_object (FILE *stream, const char *name, 6035169689Skan const char *init_string, 6036169689Skan unsigned HOST_WIDE_INT size, 6037169689Skan unsigned int align, bool takes_alignment_p) 6038169689Skan{ 6039169689Skan if (!takes_alignment_p) 6040169689Skan { 6041169689Skan size += (align / BITS_PER_UNIT) - 1; 6042169689Skan size -= size % (align / BITS_PER_UNIT); 6043169689Skan mips_declare_object (stream, name, init_string, 6044169689Skan "," HOST_WIDE_INT_PRINT_UNSIGNED "\n", size); 6045169689Skan } 6046169689Skan else 6047169689Skan mips_declare_object (stream, name, init_string, 6048169689Skan "," HOST_WIDE_INT_PRINT_UNSIGNED ",%u\n", 6049169689Skan size, align / BITS_PER_UNIT); 6050169689Skan} 6051169689Skan 6052169689Skan/* Emit either a label, .comm, or .lcomm directive. When using assembler 6053169689Skan macros, mark the symbol as written so that mips_file_end won't emit an 6054169689Skan .extern for it. STREAM is the output file, NAME is the name of the 6055169689Skan symbol, INIT_STRING is the string that should be written before the 6056169689Skan symbol and FINAL_STRING is the string that should be written after it. 6057169689Skan FINAL_STRING is a printf() format that consumes the remaining arguments. */ 6058169689Skan 6059169689Skanvoid 6060169689Skanmips_declare_object (FILE *stream, const char *name, const char *init_string, 6061169689Skan const char *final_string, ...) 6062169689Skan{ 6063169689Skan va_list ap; 6064169689Skan 6065169689Skan fputs (init_string, stream); 6066169689Skan assemble_name (stream, name); 6067169689Skan va_start (ap, final_string); 6068169689Skan vfprintf (stream, final_string, ap); 6069169689Skan va_end (ap); 6070169689Skan 6071169689Skan if (!TARGET_EXPLICIT_RELOCS) 6072169689Skan { 6073169689Skan tree name_tree = get_identifier (name); 6074169689Skan TREE_ASM_WRITTEN (name_tree) = 1; 6075169689Skan } 6076169689Skan} 6077169689Skan 6078169689Skan#ifdef ASM_OUTPUT_SIZE_DIRECTIVE 6079169689Skanextern int size_directive_output; 6080169689Skan 6081169689Skan/* Implement ASM_DECLARE_OBJECT_NAME. This is like most of the standard ELF 6082169689Skan definitions except that it uses mips_declare_object() to emit the label. */ 6083169689Skan 6084169689Skanvoid 6085169689Skanmips_declare_object_name (FILE *stream, const char *name, 6086169689Skan tree decl ATTRIBUTE_UNUSED) 6087169689Skan{ 6088169689Skan#ifdef ASM_OUTPUT_TYPE_DIRECTIVE 6089169689Skan ASM_OUTPUT_TYPE_DIRECTIVE (stream, name, "object"); 6090169689Skan#endif 6091169689Skan 6092169689Skan size_directive_output = 0; 6093169689Skan if (!flag_inhibit_size_directive && DECL_SIZE (decl)) 6094169689Skan { 6095169689Skan HOST_WIDE_INT size; 6096169689Skan 6097169689Skan size_directive_output = 1; 6098169689Skan size = int_size_in_bytes (TREE_TYPE (decl)); 6099169689Skan ASM_OUTPUT_SIZE_DIRECTIVE (stream, name, size); 6100169689Skan } 6101169689Skan 6102169689Skan mips_declare_object (stream, name, "", ":\n"); 6103169689Skan} 6104169689Skan 6105169689Skan/* Implement ASM_FINISH_DECLARE_OBJECT. This is generic ELF stuff. */ 6106169689Skan 6107169689Skanvoid 6108169689Skanmips_finish_declare_object (FILE *stream, tree decl, int top_level, int at_end) 6109169689Skan{ 6110169689Skan const char *name; 6111169689Skan 6112169689Skan name = XSTR (XEXP (DECL_RTL (decl), 0), 0); 6113169689Skan if (!flag_inhibit_size_directive 6114169689Skan && DECL_SIZE (decl) != 0 6115169689Skan && !at_end && top_level 6116169689Skan && DECL_INITIAL (decl) == error_mark_node 6117169689Skan && !size_directive_output) 6118169689Skan { 6119169689Skan HOST_WIDE_INT size; 6120169689Skan 6121169689Skan size_directive_output = 1; 6122169689Skan size = int_size_in_bytes (TREE_TYPE (decl)); 6123169689Skan ASM_OUTPUT_SIZE_DIRECTIVE (stream, name, size); 6124169689Skan } 6125169689Skan} 6126169689Skan#endif 6127169689Skan 6128169689Skan/* Return true if X is a small data address that can be rewritten 6129169689Skan as a LO_SUM. */ 6130169689Skan 6131169689Skanstatic bool 6132169689Skanmips_rewrite_small_data_p (rtx x) 6133169689Skan{ 6134169689Skan enum mips_symbol_type symbol_type; 6135169689Skan 6136169689Skan return (TARGET_EXPLICIT_RELOCS 6137169689Skan && mips_symbolic_constant_p (x, &symbol_type) 6138169689Skan && symbol_type == SYMBOL_SMALL_DATA); 6139169689Skan} 6140169689Skan 6141169689Skan 6142169689Skan/* A for_each_rtx callback for mips_small_data_pattern_p. */ 6143169689Skan 6144169689Skanstatic int 6145169689Skanmips_small_data_pattern_1 (rtx *loc, void *data ATTRIBUTE_UNUSED) 6146169689Skan{ 6147169689Skan if (GET_CODE (*loc) == LO_SUM) 6148169689Skan return -1; 6149169689Skan 6150169689Skan return mips_rewrite_small_data_p (*loc); 6151169689Skan} 6152169689Skan 6153169689Skan/* Return true if OP refers to small data symbols directly, not through 6154169689Skan a LO_SUM. */ 6155169689Skan 6156169689Skanbool 6157169689Skanmips_small_data_pattern_p (rtx op) 6158169689Skan{ 6159169689Skan return for_each_rtx (&op, mips_small_data_pattern_1, 0); 6160169689Skan} 6161169689Skan 6162169689Skan/* A for_each_rtx callback, used by mips_rewrite_small_data. */ 6163169689Skan 6164169689Skanstatic int 6165169689Skanmips_rewrite_small_data_1 (rtx *loc, void *data ATTRIBUTE_UNUSED) 6166169689Skan{ 6167169689Skan if (mips_rewrite_small_data_p (*loc)) 6168169689Skan *loc = gen_rtx_LO_SUM (Pmode, pic_offset_table_rtx, *loc); 6169169689Skan 6170169689Skan if (GET_CODE (*loc) == LO_SUM) 6171169689Skan return -1; 6172169689Skan 6173169689Skan return 0; 6174169689Skan} 6175169689Skan 6176169689Skan/* If possible, rewrite OP so that it refers to small data using 6177169689Skan explicit relocations. */ 6178169689Skan 6179169689Skanrtx 6180169689Skanmips_rewrite_small_data (rtx op) 6181169689Skan{ 6182169689Skan op = copy_insn (op); 6183169689Skan for_each_rtx (&op, mips_rewrite_small_data_1, 0); 6184169689Skan return op; 6185169689Skan} 6186169689Skan 6187169689Skan/* Return true if the current function has an insn that implicitly 6188169689Skan refers to $gp. */ 6189169689Skan 6190169689Skanstatic bool 6191169689Skanmips_function_has_gp_insn (void) 6192169689Skan{ 6193169689Skan /* Don't bother rechecking if we found one last time. */ 6194169689Skan if (!cfun->machine->has_gp_insn_p) 6195169689Skan { 6196169689Skan rtx insn; 6197169689Skan 6198169689Skan push_topmost_sequence (); 6199169689Skan for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) 6200169689Skan if (INSN_P (insn) 6201169689Skan && GET_CODE (PATTERN (insn)) != USE 6202169689Skan && GET_CODE (PATTERN (insn)) != CLOBBER 6203169689Skan && (get_attr_got (insn) != GOT_UNSET 6204169689Skan || small_data_pattern (PATTERN (insn), VOIDmode))) 6205169689Skan break; 6206169689Skan pop_topmost_sequence (); 6207169689Skan 6208169689Skan cfun->machine->has_gp_insn_p = (insn != 0); 6209169689Skan } 6210169689Skan return cfun->machine->has_gp_insn_p; 6211169689Skan} 6212169689Skan 6213169689Skan 6214169689Skan/* Return the register that should be used as the global pointer 6215169689Skan within this function. Return 0 if the function doesn't need 6216169689Skan a global pointer. */ 6217169689Skan 6218169689Skanstatic unsigned int 6219169689Skanmips_global_pointer (void) 6220169689Skan{ 6221169689Skan unsigned int regno; 6222169689Skan 6223169689Skan /* $gp is always available in non-abicalls code. */ 6224169689Skan if (!TARGET_ABICALLS) 6225169689Skan return GLOBAL_POINTER_REGNUM; 6226169689Skan 6227169689Skan /* We must always provide $gp when it is used implicitly. */ 6228169689Skan if (!TARGET_EXPLICIT_RELOCS) 6229169689Skan return GLOBAL_POINTER_REGNUM; 6230169689Skan 6231169689Skan /* FUNCTION_PROFILER includes a jal macro, so we need to give it 6232169689Skan a valid gp. */ 6233169689Skan if (current_function_profile) 6234169689Skan return GLOBAL_POINTER_REGNUM; 6235169689Skan 6236169689Skan /* If the function has a nonlocal goto, $gp must hold the correct 6237169689Skan global pointer for the target function. */ 6238169689Skan if (current_function_has_nonlocal_goto) 6239169689Skan return GLOBAL_POINTER_REGNUM; 6240169689Skan 6241169689Skan /* If the gp is never referenced, there's no need to initialize it. 6242169689Skan Note that reload can sometimes introduce constant pool references 6243169689Skan into a function that otherwise didn't need them. For example, 6244169689Skan suppose we have an instruction like: 6245169689Skan 6246169689Skan (set (reg:DF R1) (float:DF (reg:SI R2))) 6247169689Skan 6248169689Skan If R2 turns out to be constant such as 1, the instruction may have a 6249169689Skan REG_EQUAL note saying that R1 == 1.0. Reload then has the option of 6250169689Skan using this constant if R2 doesn't get allocated to a register. 6251169689Skan 6252169689Skan In cases like these, reload will have added the constant to the pool 6253169689Skan but no instruction will yet refer to it. */ 6254169689Skan if (!regs_ever_live[GLOBAL_POINTER_REGNUM] 6255169689Skan && !current_function_uses_const_pool 6256169689Skan && !mips_function_has_gp_insn ()) 6257169689Skan return 0; 6258169689Skan 6259169689Skan /* We need a global pointer, but perhaps we can use a call-clobbered 6260169689Skan register instead of $gp. */ 6261169689Skan if (TARGET_NEWABI && current_function_is_leaf) 6262169689Skan for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) 6263169689Skan if (!regs_ever_live[regno] 6264169689Skan && call_used_regs[regno] 6265169689Skan && !fixed_regs[regno] 6266169689Skan && regno != PIC_FUNCTION_ADDR_REGNUM) 6267169689Skan return regno; 6268169689Skan 6269169689Skan return GLOBAL_POINTER_REGNUM; 6270169689Skan} 6271169689Skan 6272169689Skan 6273169689Skan/* Return true if the current function must save REGNO. */ 6274169689Skan 6275169689Skanstatic bool 6276169689Skanmips_save_reg_p (unsigned int regno) 6277169689Skan{ 6278169689Skan /* We only need to save $gp for NewABI PIC. */ 6279169689Skan if (regno == GLOBAL_POINTER_REGNUM) 6280169689Skan return (TARGET_ABICALLS && TARGET_NEWABI 6281169689Skan && cfun->machine->global_pointer == regno); 6282169689Skan 6283169689Skan /* Check call-saved registers. */ 6284169689Skan if (regs_ever_live[regno] && !call_used_regs[regno]) 6285169689Skan return true; 6286169689Skan 6287169689Skan /* We need to save the old frame pointer before setting up a new one. */ 6288169689Skan if (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed) 6289169689Skan return true; 6290169689Skan 6291169689Skan /* We need to save the incoming return address if it is ever clobbered 6292169689Skan within the function. */ 6293169689Skan if (regno == GP_REG_FIRST + 31 && regs_ever_live[regno]) 6294169689Skan return true; 6295169689Skan 6296169689Skan if (TARGET_MIPS16) 6297169689Skan { 6298169689Skan tree return_type; 6299169689Skan 6300169689Skan return_type = DECL_RESULT (current_function_decl); 6301169689Skan 6302169689Skan /* $18 is a special case in mips16 code. It may be used to call 6303169689Skan a function which returns a floating point value, but it is 6304169689Skan marked in call_used_regs. */ 6305169689Skan if (regno == GP_REG_FIRST + 18 && regs_ever_live[regno]) 6306169689Skan return true; 6307169689Skan 6308169689Skan /* $31 is also a special case. It will be used to copy a return 6309169689Skan value into the floating point registers if the return value is 6310169689Skan floating point. */ 6311169689Skan if (regno == GP_REG_FIRST + 31 6312169689Skan && mips16_hard_float 6313169689Skan && !aggregate_value_p (return_type, current_function_decl) 6314169689Skan && GET_MODE_CLASS (DECL_MODE (return_type)) == MODE_FLOAT 6315169689Skan && GET_MODE_SIZE (DECL_MODE (return_type)) <= UNITS_PER_FPVALUE) 6316169689Skan return true; 6317169689Skan } 6318169689Skan 6319169689Skan return false; 6320169689Skan} 6321169689Skan 6322169689Skan 6323169689Skan/* Return the bytes needed to compute the frame pointer from the current 6324169689Skan stack pointer. SIZE is the size (in bytes) of the local variables. 6325169689Skan 6326169689Skan MIPS stack frames look like: 6327169689Skan 6328169689Skan Before call After call 6329169689Skan +-----------------------+ +-----------------------+ 6330169689Skan high | | | | 6331169689Skan mem. | | | | 6332169689Skan | caller's temps. | | caller's temps. | 6333169689Skan | | | | 6334169689Skan +-----------------------+ +-----------------------+ 6335169689Skan | | | | 6336169689Skan | arguments on stack. | | arguments on stack. | 6337169689Skan | | | | 6338169689Skan +-----------------------+ +-----------------------+ 6339169689Skan | 4 words to save | | 4 words to save | 6340169689Skan | arguments passed | | arguments passed | 6341169689Skan | in registers, even | | in registers, even | 6342169689Skan SP->| if not passed. | VFP->| if not passed. | 6343169689Skan +-----------------------+ +-----------------------+ 6344169689Skan | | 6345169689Skan | fp register save | 6346169689Skan | | 6347169689Skan +-----------------------+ 6348169689Skan | | 6349169689Skan | gp register save | 6350169689Skan | | 6351169689Skan +-----------------------+ 6352169689Skan | | 6353169689Skan | local variables | 6354169689Skan | | 6355169689Skan +-----------------------+ 6356169689Skan | | 6357169689Skan | alloca allocations | 6358169689Skan | | 6359169689Skan +-----------------------+ 6360169689Skan | | 6361169689Skan | GP save for V.4 abi | 6362169689Skan | | 6363169689Skan +-----------------------+ 6364169689Skan | | 6365169689Skan | arguments on stack | 6366169689Skan | | 6367169689Skan +-----------------------+ 6368169689Skan | 4 words to save | 6369169689Skan | arguments passed | 6370169689Skan | in registers, even | 6371169689Skan low SP->| if not passed. | 6372169689Skan memory +-----------------------+ 6373169689Skan 6374169689Skan*/ 6375169689Skan 6376169689SkanHOST_WIDE_INT 6377169689Skancompute_frame_size (HOST_WIDE_INT size) 6378169689Skan{ 6379169689Skan unsigned int regno; 6380169689Skan HOST_WIDE_INT total_size; /* # bytes that the entire frame takes up */ 6381169689Skan HOST_WIDE_INT var_size; /* # bytes that variables take up */ 6382169689Skan HOST_WIDE_INT args_size; /* # bytes that outgoing arguments take up */ 6383169689Skan HOST_WIDE_INT cprestore_size; /* # bytes that the cprestore slot takes up */ 6384169689Skan HOST_WIDE_INT gp_reg_rounded; /* # bytes needed to store gp after rounding */ 6385169689Skan HOST_WIDE_INT gp_reg_size; /* # bytes needed to store gp regs */ 6386169689Skan HOST_WIDE_INT fp_reg_size; /* # bytes needed to store fp regs */ 6387169689Skan unsigned int mask; /* mask of saved gp registers */ 6388169689Skan unsigned int fmask; /* mask of saved fp registers */ 6389169689Skan 6390169689Skan cfun->machine->global_pointer = mips_global_pointer (); 6391169689Skan 6392169689Skan gp_reg_size = 0; 6393169689Skan fp_reg_size = 0; 6394169689Skan mask = 0; 6395169689Skan fmask = 0; 6396169689Skan var_size = MIPS_STACK_ALIGN (size); 6397169689Skan args_size = current_function_outgoing_args_size; 6398169689Skan cprestore_size = MIPS_STACK_ALIGN (STARTING_FRAME_OFFSET) - args_size; 6399169689Skan 6400169689Skan /* The space set aside by STARTING_FRAME_OFFSET isn't needed in leaf 6401169689Skan functions. If the function has local variables, we're committed 6402169689Skan to allocating it anyway. Otherwise reclaim it here. */ 6403169689Skan if (var_size == 0 && current_function_is_leaf) 6404169689Skan cprestore_size = args_size = 0; 6405169689Skan 6406169689Skan /* The MIPS 3.0 linker does not like functions that dynamically 6407169689Skan allocate the stack and have 0 for STACK_DYNAMIC_OFFSET, since it 6408169689Skan looks like we are trying to create a second frame pointer to the 6409169689Skan function, so allocate some stack space to make it happy. */ 6410169689Skan 6411169689Skan if (args_size == 0 && current_function_calls_alloca) 6412169689Skan args_size = 4 * UNITS_PER_WORD; 6413169689Skan 6414169689Skan total_size = var_size + args_size + cprestore_size; 6415169689Skan 6416169689Skan /* Calculate space needed for gp registers. */ 6417169689Skan for (regno = GP_REG_FIRST; regno <= GP_REG_LAST; regno++) 6418169689Skan if (mips_save_reg_p (regno)) 6419169689Skan { 6420169689Skan gp_reg_size += GET_MODE_SIZE (gpr_mode); 6421169689Skan mask |= 1 << (regno - GP_REG_FIRST); 6422169689Skan } 6423169689Skan 6424169689Skan /* We need to restore these for the handler. */ 6425169689Skan if (current_function_calls_eh_return) 6426169689Skan { 6427169689Skan unsigned int i; 6428169689Skan for (i = 0; ; ++i) 6429169689Skan { 6430169689Skan regno = EH_RETURN_DATA_REGNO (i); 6431169689Skan if (regno == INVALID_REGNUM) 6432169689Skan break; 6433169689Skan gp_reg_size += GET_MODE_SIZE (gpr_mode); 6434169689Skan mask |= 1 << (regno - GP_REG_FIRST); 6435169689Skan } 6436169689Skan } 6437169689Skan 6438169689Skan /* This loop must iterate over the same space as its companion in 6439169689Skan save_restore_insns. */ 6440169689Skan for (regno = (FP_REG_LAST - FP_INC + 1); 6441169689Skan regno >= FP_REG_FIRST; 6442169689Skan regno -= FP_INC) 6443169689Skan { 6444169689Skan if (mips_save_reg_p (regno)) 6445169689Skan { 6446169689Skan fp_reg_size += FP_INC * UNITS_PER_FPREG; 6447169689Skan fmask |= ((1 << FP_INC) - 1) << (regno - FP_REG_FIRST); 6448169689Skan } 6449169689Skan } 6450169689Skan 6451169689Skan gp_reg_rounded = MIPS_STACK_ALIGN (gp_reg_size); 6452169689Skan total_size += gp_reg_rounded + MIPS_STACK_ALIGN (fp_reg_size); 6453169689Skan 6454169689Skan /* Add in the space required for saving incoming register arguments. */ 6455169689Skan total_size += current_function_pretend_args_size; 6456169689Skan total_size += MIPS_STACK_ALIGN (cfun->machine->varargs_size); 6457169689Skan 6458169689Skan /* Save other computed information. */ 6459169689Skan cfun->machine->frame.total_size = total_size; 6460169689Skan cfun->machine->frame.var_size = var_size; 6461169689Skan cfun->machine->frame.args_size = args_size; 6462169689Skan cfun->machine->frame.cprestore_size = cprestore_size; 6463169689Skan cfun->machine->frame.gp_reg_size = gp_reg_size; 6464169689Skan cfun->machine->frame.fp_reg_size = fp_reg_size; 6465169689Skan cfun->machine->frame.mask = mask; 6466169689Skan cfun->machine->frame.fmask = fmask; 6467169689Skan cfun->machine->frame.initialized = reload_completed; 6468169689Skan cfun->machine->frame.num_gp = gp_reg_size / UNITS_PER_WORD; 6469169689Skan cfun->machine->frame.num_fp = fp_reg_size / (FP_INC * UNITS_PER_FPREG); 6470169689Skan 6471169689Skan if (mask) 6472169689Skan { 6473169689Skan HOST_WIDE_INT offset; 6474169689Skan 6475169689Skan offset = (args_size + cprestore_size + var_size 6476169689Skan + gp_reg_size - GET_MODE_SIZE (gpr_mode)); 6477169689Skan cfun->machine->frame.gp_sp_offset = offset; 6478169689Skan cfun->machine->frame.gp_save_offset = offset - total_size; 6479169689Skan } 6480169689Skan else 6481169689Skan { 6482169689Skan cfun->machine->frame.gp_sp_offset = 0; 6483169689Skan cfun->machine->frame.gp_save_offset = 0; 6484169689Skan } 6485169689Skan 6486169689Skan if (fmask) 6487169689Skan { 6488169689Skan HOST_WIDE_INT offset; 6489169689Skan 6490169689Skan offset = (args_size + cprestore_size + var_size 6491169689Skan + gp_reg_rounded + fp_reg_size 6492169689Skan - FP_INC * UNITS_PER_FPREG); 6493169689Skan cfun->machine->frame.fp_sp_offset = offset; 6494169689Skan cfun->machine->frame.fp_save_offset = offset - total_size; 6495169689Skan } 6496169689Skan else 6497169689Skan { 6498169689Skan cfun->machine->frame.fp_sp_offset = 0; 6499169689Skan cfun->machine->frame.fp_save_offset = 0; 6500169689Skan } 6501169689Skan 6502169689Skan /* Ok, we're done. */ 6503169689Skan return total_size; 6504169689Skan} 6505169689Skan 6506169689Skan/* Implement INITIAL_ELIMINATION_OFFSET. FROM is either the frame 6507169689Skan pointer or argument pointer. TO is either the stack pointer or 6508169689Skan hard frame pointer. */ 6509169689Skan 6510169689SkanHOST_WIDE_INT 6511169689Skanmips_initial_elimination_offset (int from, int to) 6512169689Skan{ 6513169689Skan HOST_WIDE_INT offset; 6514169689Skan 6515169689Skan compute_frame_size (get_frame_size ()); 6516169689Skan 6517169689Skan /* Set OFFSET to the offset from the stack pointer. */ 6518169689Skan switch (from) 6519169689Skan { 6520169689Skan case FRAME_POINTER_REGNUM: 6521169689Skan offset = 0; 6522169689Skan break; 6523169689Skan 6524169689Skan case ARG_POINTER_REGNUM: 6525169689Skan offset = (cfun->machine->frame.total_size 6526169689Skan - current_function_pretend_args_size); 6527169689Skan break; 6528169689Skan 6529169689Skan default: 6530169689Skan gcc_unreachable (); 6531169689Skan } 6532169689Skan 6533169689Skan if (TARGET_MIPS16 && to == HARD_FRAME_POINTER_REGNUM) 6534169689Skan offset -= cfun->machine->frame.args_size; 6535169689Skan 6536169689Skan return offset; 6537169689Skan} 6538169689Skan 6539169689Skan/* Implement RETURN_ADDR_RTX. Note, we do not support moving 6540169689Skan back to a previous frame. */ 6541169689Skanrtx 6542169689Skanmips_return_addr (int count, rtx frame ATTRIBUTE_UNUSED) 6543169689Skan{ 6544169689Skan if (count != 0) 6545169689Skan return const0_rtx; 6546169689Skan 6547169689Skan return get_hard_reg_initial_val (Pmode, GP_REG_FIRST + 31); 6548169689Skan} 6549169689Skan 6550169689Skan/* Use FN to save or restore register REGNO. MODE is the register's 6551169689Skan mode and OFFSET is the offset of its save slot from the current 6552169689Skan stack pointer. */ 6553169689Skan 6554169689Skanstatic void 6555169689Skanmips_save_restore_reg (enum machine_mode mode, int regno, 6556169689Skan HOST_WIDE_INT offset, mips_save_restore_fn fn) 6557169689Skan{ 6558169689Skan rtx mem; 6559169689Skan 6560169689Skan mem = gen_frame_mem (mode, plus_constant (stack_pointer_rtx, offset)); 6561169689Skan 6562169689Skan fn (gen_rtx_REG (mode, regno), mem); 6563169689Skan} 6564169689Skan 6565169689Skan 6566169689Skan/* Call FN for each register that is saved by the current function. 6567169689Skan SP_OFFSET is the offset of the current stack pointer from the start 6568169689Skan of the frame. */ 6569169689Skan 6570169689Skanstatic void 6571169689Skanmips_for_each_saved_reg (HOST_WIDE_INT sp_offset, mips_save_restore_fn fn) 6572169689Skan{ 6573169689Skan#define BITSET_P(VALUE, BIT) (((VALUE) & (1L << (BIT))) != 0) 6574169689Skan 6575169689Skan enum machine_mode fpr_mode; 6576169689Skan HOST_WIDE_INT offset; 6577169689Skan int regno; 6578169689Skan 6579169689Skan /* Save registers starting from high to low. The debuggers prefer at least 6580169689Skan the return register be stored at func+4, and also it allows us not to 6581169689Skan need a nop in the epilog if at least one register is reloaded in 6582169689Skan addition to return address. */ 6583169689Skan offset = cfun->machine->frame.gp_sp_offset - sp_offset; 6584169689Skan for (regno = GP_REG_LAST; regno >= GP_REG_FIRST; regno--) 6585169689Skan if (BITSET_P (cfun->machine->frame.mask, regno - GP_REG_FIRST)) 6586169689Skan { 6587169689Skan mips_save_restore_reg (gpr_mode, regno, offset, fn); 6588169689Skan offset -= GET_MODE_SIZE (gpr_mode); 6589169689Skan } 6590169689Skan 6591169689Skan /* This loop must iterate over the same space as its companion in 6592169689Skan compute_frame_size. */ 6593169689Skan offset = cfun->machine->frame.fp_sp_offset - sp_offset; 6594169689Skan fpr_mode = (TARGET_SINGLE_FLOAT ? SFmode : DFmode); 6595169689Skan for (regno = (FP_REG_LAST - FP_INC + 1); 6596169689Skan regno >= FP_REG_FIRST; 6597169689Skan regno -= FP_INC) 6598169689Skan if (BITSET_P (cfun->machine->frame.fmask, regno - FP_REG_FIRST)) 6599169689Skan { 6600169689Skan mips_save_restore_reg (fpr_mode, regno, offset, fn); 6601169689Skan offset -= GET_MODE_SIZE (fpr_mode); 6602169689Skan } 6603169689Skan#undef BITSET_P 6604169689Skan} 6605169689Skan 6606169689Skan/* If we're generating n32 or n64 abicalls, and the current function 6607169689Skan does not use $28 as its global pointer, emit a cplocal directive. 6608169689Skan Use pic_offset_table_rtx as the argument to the directive. */ 6609169689Skan 6610169689Skanstatic void 6611169689Skanmips_output_cplocal (void) 6612169689Skan{ 6613169689Skan if (!TARGET_EXPLICIT_RELOCS 6614169689Skan && cfun->machine->global_pointer > 0 6615169689Skan && cfun->machine->global_pointer != GLOBAL_POINTER_REGNUM) 6616169689Skan output_asm_insn (".cplocal %+", 0); 6617169689Skan} 6618169689Skan 6619169689Skan/* Return the style of GP load sequence that is being used for the 6620169689Skan current function. */ 6621169689Skan 6622169689Skanenum mips_loadgp_style 6623169689Skanmips_current_loadgp_style (void) 6624169689Skan{ 6625169689Skan if (!TARGET_ABICALLS || cfun->machine->global_pointer == 0) 6626169689Skan return LOADGP_NONE; 6627169689Skan 6628169689Skan if (TARGET_ABSOLUTE_ABICALLS) 6629169689Skan return LOADGP_ABSOLUTE; 6630169689Skan 6631169689Skan return TARGET_NEWABI ? LOADGP_NEWABI : LOADGP_OLDABI; 6632169689Skan} 6633169689Skan 6634169689Skan/* The __gnu_local_gp symbol. */ 6635169689Skan 6636169689Skanstatic GTY(()) rtx mips_gnu_local_gp; 6637169689Skan 6638169689Skan/* If we're generating n32 or n64 abicalls, emit instructions 6639169689Skan to set up the global pointer. */ 6640169689Skan 6641169689Skanstatic void 6642169689Skanmips_emit_loadgp (void) 6643169689Skan{ 6644169689Skan rtx addr, offset, incoming_address; 6645169689Skan 6646169689Skan switch (mips_current_loadgp_style ()) 6647169689Skan { 6648169689Skan case LOADGP_ABSOLUTE: 6649169689Skan if (mips_gnu_local_gp == NULL) 6650169689Skan { 6651169689Skan mips_gnu_local_gp = gen_rtx_SYMBOL_REF (Pmode, "__gnu_local_gp"); 6652169689Skan SYMBOL_REF_FLAGS (mips_gnu_local_gp) |= SYMBOL_FLAG_LOCAL; 6653169689Skan } 6654169689Skan emit_insn (gen_loadgp_noshared (mips_gnu_local_gp)); 6655169689Skan break; 6656169689Skan 6657169689Skan case LOADGP_NEWABI: 6658169689Skan addr = XEXP (DECL_RTL (current_function_decl), 0); 6659169689Skan offset = mips_unspec_address (addr, SYMBOL_GOTOFF_LOADGP); 6660169689Skan incoming_address = gen_rtx_REG (Pmode, PIC_FUNCTION_ADDR_REGNUM); 6661169689Skan emit_insn (gen_loadgp (offset, incoming_address)); 6662169689Skan if (!TARGET_EXPLICIT_RELOCS) 6663169689Skan emit_insn (gen_loadgp_blockage ()); 6664169689Skan break; 6665169689Skan 6666169689Skan default: 6667169689Skan break; 6668169689Skan } 6669169689Skan} 6670169689Skan 6671169689Skan/* Set up the stack and frame (if desired) for the function. */ 6672169689Skan 6673169689Skanstatic void 6674169689Skanmips_output_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED) 6675169689Skan{ 6676169689Skan const char *fnname; 6677169689Skan HOST_WIDE_INT tsize = cfun->machine->frame.total_size; 6678169689Skan 6679169689Skan#ifdef SDB_DEBUGGING_INFO 6680169689Skan if (debug_info_level != DINFO_LEVEL_TERSE && write_symbols == SDB_DEBUG) 6681169689Skan SDB_OUTPUT_SOURCE_LINE (file, DECL_SOURCE_LINE (current_function_decl)); 6682169689Skan#endif 6683169689Skan 6684169689Skan /* In mips16 mode, we may need to generate a 32 bit to handle 6685169689Skan floating point arguments. The linker will arrange for any 32 bit 6686169689Skan functions to call this stub, which will then jump to the 16 bit 6687169689Skan function proper. */ 6688169689Skan if (TARGET_MIPS16 && !TARGET_SOFT_FLOAT 6689169689Skan && current_function_args_info.fp_code != 0) 6690169689Skan build_mips16_function_stub (file); 6691169689Skan 6692169689Skan if (!FUNCTION_NAME_ALREADY_DECLARED) 6693169689Skan { 6694169689Skan /* Get the function name the same way that toplev.c does before calling 6695169689Skan assemble_start_function. This is needed so that the name used here 6696169689Skan exactly matches the name used in ASM_DECLARE_FUNCTION_NAME. */ 6697169689Skan fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0); 6698169689Skan 6699169689Skan if (!flag_inhibit_size_directive) 6700169689Skan { 6701169689Skan fputs ("\t.ent\t", file); 6702169689Skan assemble_name (file, fnname); 6703169689Skan fputs ("\n", file); 6704169689Skan } 6705169689Skan 6706169689Skan assemble_name (file, fnname); 6707169689Skan fputs (":\n", file); 6708169689Skan } 6709169689Skan 6710169689Skan /* Stop mips_file_end from treating this function as external. */ 6711169689Skan if (TARGET_IRIX && mips_abi == ABI_32) 6712169689Skan TREE_ASM_WRITTEN (DECL_NAME (cfun->decl)) = 1; 6713169689Skan 6714169689Skan if (!flag_inhibit_size_directive) 6715169689Skan { 6716169689Skan /* .frame FRAMEREG, FRAMESIZE, RETREG */ 6717169689Skan fprintf (file, 6718169689Skan "\t.frame\t%s," HOST_WIDE_INT_PRINT_DEC ",%s\t\t" 6719169689Skan "# vars= " HOST_WIDE_INT_PRINT_DEC ", regs= %d/%d" 6720169689Skan ", args= " HOST_WIDE_INT_PRINT_DEC 6721169689Skan ", gp= " HOST_WIDE_INT_PRINT_DEC "\n", 6722169689Skan (reg_names[(frame_pointer_needed) 6723169689Skan ? HARD_FRAME_POINTER_REGNUM : STACK_POINTER_REGNUM]), 6724169689Skan ((frame_pointer_needed && TARGET_MIPS16) 6725169689Skan ? tsize - cfun->machine->frame.args_size 6726169689Skan : tsize), 6727169689Skan reg_names[GP_REG_FIRST + 31], 6728169689Skan cfun->machine->frame.var_size, 6729169689Skan cfun->machine->frame.num_gp, 6730169689Skan cfun->machine->frame.num_fp, 6731169689Skan cfun->machine->frame.args_size, 6732169689Skan cfun->machine->frame.cprestore_size); 6733169689Skan 6734169689Skan /* .mask MASK, GPOFFSET; .fmask FPOFFSET */ 6735169689Skan fprintf (file, "\t.mask\t0x%08x," HOST_WIDE_INT_PRINT_DEC "\n", 6736169689Skan cfun->machine->frame.mask, 6737169689Skan cfun->machine->frame.gp_save_offset); 6738169689Skan fprintf (file, "\t.fmask\t0x%08x," HOST_WIDE_INT_PRINT_DEC "\n", 6739169689Skan cfun->machine->frame.fmask, 6740169689Skan cfun->machine->frame.fp_save_offset); 6741169689Skan 6742169689Skan /* Require: 6743169689Skan OLD_SP == *FRAMEREG + FRAMESIZE => can find old_sp from nominated FP reg. 6744169689Skan HIGHEST_GP_SAVED == *FRAMEREG + FRAMESIZE + GPOFFSET => can find saved regs. */ 6745169689Skan } 6746169689Skan 6747169689Skan if (mips_current_loadgp_style () == LOADGP_OLDABI) 6748169689Skan { 6749169689Skan /* Handle the initialization of $gp for SVR4 PIC. */ 6750169689Skan if (!cfun->machine->all_noreorder_p) 6751169689Skan output_asm_insn ("%(.cpload\t%^%)", 0); 6752169689Skan else 6753169689Skan output_asm_insn ("%(.cpload\t%^\n\t%<", 0); 6754169689Skan } 6755169689Skan else if (cfun->machine->all_noreorder_p) 6756169689Skan output_asm_insn ("%(%<", 0); 6757169689Skan 6758169689Skan /* Tell the assembler which register we're using as the global 6759169689Skan pointer. This is needed for thunks, since they can use either 6760169689Skan explicit relocs or assembler macros. */ 6761169689Skan mips_output_cplocal (); 6762169689Skan} 6763169689Skan 6764169689Skan/* Make the last instruction frame related and note that it performs 6765169689Skan the operation described by FRAME_PATTERN. */ 6766169689Skan 6767169689Skanstatic void 6768169689Skanmips_set_frame_expr (rtx frame_pattern) 6769169689Skan{ 6770169689Skan rtx insn; 6771169689Skan 6772169689Skan insn = get_last_insn (); 6773169689Skan RTX_FRAME_RELATED_P (insn) = 1; 6774169689Skan REG_NOTES (insn) = alloc_EXPR_LIST (REG_FRAME_RELATED_EXPR, 6775169689Skan frame_pattern, 6776169689Skan REG_NOTES (insn)); 6777169689Skan} 6778169689Skan 6779169689Skan 6780169689Skan/* Return a frame-related rtx that stores REG at MEM. 6781169689Skan REG must be a single register. */ 6782169689Skan 6783169689Skanstatic rtx 6784169689Skanmips_frame_set (rtx mem, rtx reg) 6785169689Skan{ 6786169689Skan rtx set; 6787169689Skan 6788169689Skan /* If we're saving the return address register and the dwarf return 6789169689Skan address column differs from the hard register number, adjust the 6790169689Skan note reg to refer to the former. */ 6791169689Skan if (REGNO (reg) == GP_REG_FIRST + 31 6792169689Skan && DWARF_FRAME_RETURN_COLUMN != GP_REG_FIRST + 31) 6793169689Skan reg = gen_rtx_REG (GET_MODE (reg), DWARF_FRAME_RETURN_COLUMN); 6794169689Skan 6795169689Skan set = gen_rtx_SET (VOIDmode, mem, reg); 6796169689Skan RTX_FRAME_RELATED_P (set) = 1; 6797169689Skan 6798169689Skan return set; 6799169689Skan} 6800169689Skan 6801169689Skan 6802169689Skan/* Save register REG to MEM. Make the instruction frame-related. */ 6803169689Skan 6804169689Skanstatic void 6805169689Skanmips_save_reg (rtx reg, rtx mem) 6806169689Skan{ 6807169689Skan if (GET_MODE (reg) == DFmode && !TARGET_FLOAT64) 6808169689Skan { 6809169689Skan rtx x1, x2; 6810169689Skan 6811169689Skan if (mips_split_64bit_move_p (mem, reg)) 6812169689Skan mips_split_64bit_move (mem, reg); 6813169689Skan else 6814169689Skan emit_move_insn (mem, reg); 6815169689Skan 6816169689Skan x1 = mips_frame_set (mips_subword (mem, 0), mips_subword (reg, 0)); 6817169689Skan x2 = mips_frame_set (mips_subword (mem, 1), mips_subword (reg, 1)); 6818169689Skan mips_set_frame_expr (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, x1, x2))); 6819169689Skan } 6820169689Skan else 6821169689Skan { 6822169689Skan if (TARGET_MIPS16 6823169689Skan && REGNO (reg) != GP_REG_FIRST + 31 6824169689Skan && !M16_REG_P (REGNO (reg))) 6825169689Skan { 6826169689Skan /* Save a non-mips16 register by moving it through a temporary. 6827169689Skan We don't need to do this for $31 since there's a special 6828169689Skan instruction for it. */ 6829169689Skan emit_move_insn (MIPS_PROLOGUE_TEMP (GET_MODE (reg)), reg); 6830169689Skan emit_move_insn (mem, MIPS_PROLOGUE_TEMP (GET_MODE (reg))); 6831169689Skan } 6832169689Skan else 6833169689Skan emit_move_insn (mem, reg); 6834169689Skan 6835169689Skan mips_set_frame_expr (mips_frame_set (mem, reg)); 6836169689Skan } 6837169689Skan} 6838169689Skan 6839169689Skan 6840169689Skan/* Expand the prologue into a bunch of separate insns. */ 6841169689Skan 6842169689Skanvoid 6843169689Skanmips_expand_prologue (void) 6844169689Skan{ 6845169689Skan HOST_WIDE_INT size; 6846169689Skan 6847169689Skan if (cfun->machine->global_pointer > 0) 6848169689Skan REGNO (pic_offset_table_rtx) = cfun->machine->global_pointer; 6849169689Skan 6850169689Skan size = compute_frame_size (get_frame_size ()); 6851169689Skan 6852169689Skan /* Save the registers. Allocate up to MIPS_MAX_FIRST_STACK_STEP 6853169689Skan bytes beforehand; this is enough to cover the register save area 6854169689Skan without going out of range. */ 6855169689Skan if ((cfun->machine->frame.mask | cfun->machine->frame.fmask) != 0) 6856169689Skan { 6857169689Skan HOST_WIDE_INT step1; 6858169689Skan 6859169689Skan step1 = MIN (size, MIPS_MAX_FIRST_STACK_STEP); 6860169689Skan RTX_FRAME_RELATED_P (emit_insn (gen_add3_insn (stack_pointer_rtx, 6861169689Skan stack_pointer_rtx, 6862169689Skan GEN_INT (-step1)))) = 1; 6863169689Skan size -= step1; 6864169689Skan mips_for_each_saved_reg (size, mips_save_reg); 6865169689Skan } 6866169689Skan 6867169689Skan /* Allocate the rest of the frame. */ 6868169689Skan if (size > 0) 6869169689Skan { 6870169689Skan if (SMALL_OPERAND (-size)) 6871169689Skan RTX_FRAME_RELATED_P (emit_insn (gen_add3_insn (stack_pointer_rtx, 6872169689Skan stack_pointer_rtx, 6873169689Skan GEN_INT (-size)))) = 1; 6874169689Skan else 6875169689Skan { 6876169689Skan emit_move_insn (MIPS_PROLOGUE_TEMP (Pmode), GEN_INT (size)); 6877169689Skan if (TARGET_MIPS16) 6878169689Skan { 6879169689Skan /* There are no instructions to add or subtract registers 6880169689Skan from the stack pointer, so use the frame pointer as a 6881169689Skan temporary. We should always be using a frame pointer 6882169689Skan in this case anyway. */ 6883169689Skan gcc_assert (frame_pointer_needed); 6884169689Skan emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx); 6885169689Skan emit_insn (gen_sub3_insn (hard_frame_pointer_rtx, 6886169689Skan hard_frame_pointer_rtx, 6887169689Skan MIPS_PROLOGUE_TEMP (Pmode))); 6888169689Skan emit_move_insn (stack_pointer_rtx, hard_frame_pointer_rtx); 6889169689Skan } 6890169689Skan else 6891169689Skan emit_insn (gen_sub3_insn (stack_pointer_rtx, 6892169689Skan stack_pointer_rtx, 6893169689Skan MIPS_PROLOGUE_TEMP (Pmode))); 6894169689Skan 6895169689Skan /* Describe the combined effect of the previous instructions. */ 6896169689Skan mips_set_frame_expr 6897169689Skan (gen_rtx_SET (VOIDmode, stack_pointer_rtx, 6898169689Skan plus_constant (stack_pointer_rtx, -size))); 6899169689Skan } 6900169689Skan } 6901169689Skan 6902169689Skan /* Set up the frame pointer, if we're using one. In mips16 code, 6903169689Skan we point the frame pointer ahead of the outgoing argument area. 6904169689Skan This should allow more variables & incoming arguments to be 6905169689Skan accessed with unextended instructions. */ 6906169689Skan if (frame_pointer_needed) 6907169689Skan { 6908169689Skan if (TARGET_MIPS16 && cfun->machine->frame.args_size != 0) 6909169689Skan { 6910169689Skan rtx offset = GEN_INT (cfun->machine->frame.args_size); 6911169689Skan if (SMALL_OPERAND (cfun->machine->frame.args_size)) 6912169689Skan RTX_FRAME_RELATED_P 6913169689Skan (emit_insn (gen_add3_insn (hard_frame_pointer_rtx, 6914169689Skan stack_pointer_rtx, 6915169689Skan offset))) = 1; 6916169689Skan else 6917169689Skan { 6918169689Skan emit_move_insn (MIPS_PROLOGUE_TEMP (Pmode), offset); 6919169689Skan emit_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx); 6920169689Skan emit_insn (gen_add3_insn (hard_frame_pointer_rtx, 6921169689Skan hard_frame_pointer_rtx, 6922169689Skan MIPS_PROLOGUE_TEMP (Pmode))); 6923169689Skan mips_set_frame_expr 6924169689Skan (gen_rtx_SET (VOIDmode, hard_frame_pointer_rtx, 6925169689Skan plus_constant (stack_pointer_rtx, 6926169689Skan cfun->machine->frame.args_size))); 6927169689Skan } 6928169689Skan } 6929169689Skan else 6930169689Skan RTX_FRAME_RELATED_P (emit_move_insn (hard_frame_pointer_rtx, 6931169689Skan stack_pointer_rtx)) = 1; 6932169689Skan } 6933169689Skan 6934169689Skan mips_emit_loadgp (); 6935169689Skan 6936169689Skan /* If generating o32/o64 abicalls, save $gp on the stack. */ 6937169689Skan if (TARGET_ABICALLS && !TARGET_NEWABI && !current_function_is_leaf) 6938169689Skan emit_insn (gen_cprestore (GEN_INT (current_function_outgoing_args_size))); 6939169689Skan 6940169689Skan /* If we are profiling, make sure no instructions are scheduled before 6941169689Skan the call to mcount. */ 6942169689Skan 6943169689Skan if (current_function_profile) 6944169689Skan emit_insn (gen_blockage ()); 6945169689Skan} 6946169689Skan 6947169689Skan/* Do any necessary cleanup after a function to restore stack, frame, 6948169689Skan and regs. */ 6949169689Skan 6950169689Skan#define RA_MASK BITMASK_HIGH /* 1 << 31 */ 6951169689Skan 6952169689Skanstatic void 6953169689Skanmips_output_function_epilogue (FILE *file ATTRIBUTE_UNUSED, 6954169689Skan HOST_WIDE_INT size ATTRIBUTE_UNUSED) 6955169689Skan{ 6956169689Skan /* Reinstate the normal $gp. */ 6957169689Skan REGNO (pic_offset_table_rtx) = GLOBAL_POINTER_REGNUM; 6958169689Skan mips_output_cplocal (); 6959169689Skan 6960169689Skan if (cfun->machine->all_noreorder_p) 6961169689Skan { 6962169689Skan /* Avoid using %>%) since it adds excess whitespace. */ 6963169689Skan output_asm_insn (".set\tmacro", 0); 6964169689Skan output_asm_insn (".set\treorder", 0); 6965169689Skan set_noreorder = set_nomacro = 0; 6966169689Skan } 6967169689Skan 6968169689Skan if (!FUNCTION_NAME_ALREADY_DECLARED && !flag_inhibit_size_directive) 6969169689Skan { 6970169689Skan const char *fnname; 6971169689Skan 6972169689Skan /* Get the function name the same way that toplev.c does before calling 6973169689Skan assemble_start_function. This is needed so that the name used here 6974169689Skan exactly matches the name used in ASM_DECLARE_FUNCTION_NAME. */ 6975169689Skan fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0); 6976169689Skan fputs ("\t.end\t", file); 6977169689Skan assemble_name (file, fnname); 6978169689Skan fputs ("\n", file); 6979169689Skan } 6980169689Skan} 6981169689Skan 6982169689Skan/* Emit instructions to restore register REG from slot MEM. */ 6983169689Skan 6984169689Skanstatic void 6985169689Skanmips_restore_reg (rtx reg, rtx mem) 6986169689Skan{ 6987169689Skan /* There's no mips16 instruction to load $31 directly. Load into 6988169689Skan $7 instead and adjust the return insn appropriately. */ 6989169689Skan if (TARGET_MIPS16 && REGNO (reg) == GP_REG_FIRST + 31) 6990169689Skan reg = gen_rtx_REG (GET_MODE (reg), 7); 6991169689Skan 6992169689Skan if (TARGET_MIPS16 && !M16_REG_P (REGNO (reg))) 6993169689Skan { 6994169689Skan /* Can't restore directly; move through a temporary. */ 6995169689Skan emit_move_insn (MIPS_EPILOGUE_TEMP (GET_MODE (reg)), mem); 6996169689Skan emit_move_insn (reg, MIPS_EPILOGUE_TEMP (GET_MODE (reg))); 6997169689Skan } 6998169689Skan else 6999169689Skan emit_move_insn (reg, mem); 7000169689Skan} 7001169689Skan 7002169689Skan 7003169689Skan/* Expand the epilogue into a bunch of separate insns. SIBCALL_P is true 7004169689Skan if this epilogue precedes a sibling call, false if it is for a normal 7005169689Skan "epilogue" pattern. */ 7006169689Skan 7007169689Skanvoid 7008169689Skanmips_expand_epilogue (int sibcall_p) 7009169689Skan{ 7010169689Skan HOST_WIDE_INT step1, step2; 7011169689Skan rtx base, target; 7012169689Skan 7013169689Skan if (!sibcall_p && mips_can_use_return_insn ()) 7014169689Skan { 7015169689Skan emit_jump_insn (gen_return ()); 7016169689Skan return; 7017169689Skan } 7018169689Skan 7019169689Skan /* Split the frame into two. STEP1 is the amount of stack we should 7020169689Skan deallocate before restoring the registers. STEP2 is the amount we 7021169689Skan should deallocate afterwards. 7022169689Skan 7023169689Skan Start off by assuming that no registers need to be restored. */ 7024169689Skan step1 = cfun->machine->frame.total_size; 7025169689Skan step2 = 0; 7026169689Skan 7027169689Skan /* Work out which register holds the frame address. Account for the 7028169689Skan frame pointer offset used by mips16 code. */ 7029169689Skan if (!frame_pointer_needed) 7030169689Skan base = stack_pointer_rtx; 7031169689Skan else 7032169689Skan { 7033169689Skan base = hard_frame_pointer_rtx; 7034169689Skan if (TARGET_MIPS16) 7035169689Skan step1 -= cfun->machine->frame.args_size; 7036169689Skan } 7037169689Skan 7038169689Skan /* If we need to restore registers, deallocate as much stack as 7039169689Skan possible in the second step without going out of range. */ 7040169689Skan if ((cfun->machine->frame.mask | cfun->machine->frame.fmask) != 0) 7041169689Skan { 7042169689Skan step2 = MIN (step1, MIPS_MAX_FIRST_STACK_STEP); 7043169689Skan step1 -= step2; 7044169689Skan } 7045169689Skan 7046169689Skan /* Set TARGET to BASE + STEP1. */ 7047169689Skan target = base; 7048169689Skan if (step1 > 0) 7049169689Skan { 7050169689Skan rtx adjust; 7051169689Skan 7052169689Skan /* Get an rtx for STEP1 that we can add to BASE. */ 7053169689Skan adjust = GEN_INT (step1); 7054169689Skan if (!SMALL_OPERAND (step1)) 7055169689Skan { 7056169689Skan emit_move_insn (MIPS_EPILOGUE_TEMP (Pmode), adjust); 7057169689Skan adjust = MIPS_EPILOGUE_TEMP (Pmode); 7058169689Skan } 7059169689Skan 7060169689Skan /* Normal mode code can copy the result straight into $sp. */ 7061169689Skan if (!TARGET_MIPS16) 7062169689Skan target = stack_pointer_rtx; 7063169689Skan 7064169689Skan emit_insn (gen_add3_insn (target, base, adjust)); 7065169689Skan } 7066169689Skan 7067169689Skan /* Copy TARGET into the stack pointer. */ 7068169689Skan if (target != stack_pointer_rtx) 7069169689Skan emit_move_insn (stack_pointer_rtx, target); 7070169689Skan 7071169689Skan /* If we're using addressing macros for n32/n64 abicalls, $gp is 7072169689Skan implicitly used by all SYMBOL_REFs. We must emit a blockage 7073169689Skan insn before restoring it. */ 7074169689Skan if (TARGET_ABICALLS && TARGET_NEWABI && !TARGET_EXPLICIT_RELOCS) 7075169689Skan emit_insn (gen_blockage ()); 7076169689Skan 7077169689Skan /* Restore the registers. */ 7078169689Skan mips_for_each_saved_reg (cfun->machine->frame.total_size - step2, 7079169689Skan mips_restore_reg); 7080169689Skan 7081169689Skan /* Deallocate the final bit of the frame. */ 7082169689Skan if (step2 > 0) 7083169689Skan emit_insn (gen_add3_insn (stack_pointer_rtx, 7084169689Skan stack_pointer_rtx, 7085169689Skan GEN_INT (step2))); 7086169689Skan 7087169689Skan /* Add in the __builtin_eh_return stack adjustment. We need to 7088169689Skan use a temporary in mips16 code. */ 7089169689Skan if (current_function_calls_eh_return) 7090169689Skan { 7091169689Skan if (TARGET_MIPS16) 7092169689Skan { 7093169689Skan emit_move_insn (MIPS_EPILOGUE_TEMP (Pmode), stack_pointer_rtx); 7094169689Skan emit_insn (gen_add3_insn (MIPS_EPILOGUE_TEMP (Pmode), 7095169689Skan MIPS_EPILOGUE_TEMP (Pmode), 7096169689Skan EH_RETURN_STACKADJ_RTX)); 7097169689Skan emit_move_insn (stack_pointer_rtx, MIPS_EPILOGUE_TEMP (Pmode)); 7098169689Skan } 7099169689Skan else 7100169689Skan emit_insn (gen_add3_insn (stack_pointer_rtx, 7101169689Skan stack_pointer_rtx, 7102169689Skan EH_RETURN_STACKADJ_RTX)); 7103169689Skan } 7104169689Skan 7105169689Skan if (!sibcall_p) 7106169689Skan { 7107169689Skan /* The mips16 loads the return address into $7, not $31. */ 7108169689Skan if (TARGET_MIPS16 && (cfun->machine->frame.mask & RA_MASK) != 0) 7109169689Skan emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, 7110169689Skan GP_REG_FIRST + 7))); 7111169689Skan else 7112169689Skan emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, 7113169689Skan GP_REG_FIRST + 31))); 7114169689Skan } 7115169689Skan} 7116169689Skan 7117169689Skan/* Return nonzero if this function is known to have a null epilogue. 7118169689Skan This allows the optimizer to omit jumps to jumps if no stack 7119169689Skan was created. */ 7120169689Skan 7121169689Skanint 7122169689Skanmips_can_use_return_insn (void) 7123169689Skan{ 7124169689Skan tree return_type; 7125169689Skan 7126169689Skan if (! reload_completed) 7127169689Skan return 0; 7128169689Skan 7129169689Skan if (regs_ever_live[31] || current_function_profile) 7130169689Skan return 0; 7131169689Skan 7132169689Skan return_type = DECL_RESULT (current_function_decl); 7133169689Skan 7134169689Skan /* In mips16 mode, a function which returns a floating point value 7135169689Skan needs to arrange to copy the return value into the floating point 7136169689Skan registers. */ 7137169689Skan if (TARGET_MIPS16 7138169689Skan && mips16_hard_float 7139169689Skan && ! aggregate_value_p (return_type, current_function_decl) 7140169689Skan && GET_MODE_CLASS (DECL_MODE (return_type)) == MODE_FLOAT 7141169689Skan && GET_MODE_SIZE (DECL_MODE (return_type)) <= UNITS_PER_FPVALUE) 7142169689Skan return 0; 7143169689Skan 7144169689Skan if (cfun->machine->frame.initialized) 7145169689Skan return cfun->machine->frame.total_size == 0; 7146169689Skan 7147169689Skan return compute_frame_size (get_frame_size ()) == 0; 7148169689Skan} 7149169689Skan 7150169689Skan/* Implement TARGET_ASM_OUTPUT_MI_THUNK. Generate rtl rather than asm text 7151169689Skan in order to avoid duplicating too much logic from elsewhere. */ 7152169689Skan 7153169689Skanstatic void 7154169689Skanmips_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED, 7155169689Skan HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset, 7156169689Skan tree function) 7157169689Skan{ 7158169689Skan rtx this, temp1, temp2, insn, fnaddr; 7159169689Skan 7160169689Skan /* Pretend to be a post-reload pass while generating rtl. */ 7161169689Skan no_new_pseudos = 1; 7162169689Skan reload_completed = 1; 7163169689Skan reset_block_changes (); 7164169689Skan 7165169689Skan /* Pick a global pointer for -mabicalls. Use $15 rather than $28 7166169689Skan for TARGET_NEWABI since the latter is a call-saved register. */ 7167169689Skan if (TARGET_ABICALLS) 7168169689Skan cfun->machine->global_pointer 7169169689Skan = REGNO (pic_offset_table_rtx) 7170169689Skan = TARGET_NEWABI ? 15 : GLOBAL_POINTER_REGNUM; 7171169689Skan 7172169689Skan /* Set up the global pointer for n32 or n64 abicalls. */ 7173169689Skan mips_emit_loadgp (); 7174169689Skan 7175169689Skan /* We need two temporary registers in some cases. */ 7176169689Skan temp1 = gen_rtx_REG (Pmode, 2); 7177169689Skan temp2 = gen_rtx_REG (Pmode, 3); 7178169689Skan 7179169689Skan /* Find out which register contains the "this" pointer. */ 7180169689Skan if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)) 7181169689Skan this = gen_rtx_REG (Pmode, GP_ARG_FIRST + 1); 7182169689Skan else 7183169689Skan this = gen_rtx_REG (Pmode, GP_ARG_FIRST); 7184169689Skan 7185169689Skan /* Add DELTA to THIS. */ 7186169689Skan if (delta != 0) 7187169689Skan { 7188169689Skan rtx offset = GEN_INT (delta); 7189169689Skan if (!SMALL_OPERAND (delta)) 7190169689Skan { 7191169689Skan emit_move_insn (temp1, offset); 7192169689Skan offset = temp1; 7193169689Skan } 7194169689Skan emit_insn (gen_add3_insn (this, this, offset)); 7195169689Skan } 7196169689Skan 7197169689Skan /* If needed, add *(*THIS + VCALL_OFFSET) to THIS. */ 7198169689Skan if (vcall_offset != 0) 7199169689Skan { 7200169689Skan rtx addr; 7201169689Skan 7202169689Skan /* Set TEMP1 to *THIS. */ 7203169689Skan emit_move_insn (temp1, gen_rtx_MEM (Pmode, this)); 7204169689Skan 7205169689Skan /* Set ADDR to a legitimate address for *THIS + VCALL_OFFSET. */ 7206169689Skan addr = mips_add_offset (temp2, temp1, vcall_offset); 7207169689Skan 7208169689Skan /* Load the offset and add it to THIS. */ 7209169689Skan emit_move_insn (temp1, gen_rtx_MEM (Pmode, addr)); 7210169689Skan emit_insn (gen_add3_insn (this, this, temp1)); 7211169689Skan } 7212169689Skan 7213169689Skan /* Jump to the target function. Use a sibcall if direct jumps are 7214169689Skan allowed, otherwise load the address into a register first. */ 7215169689Skan fnaddr = XEXP (DECL_RTL (function), 0); 7216169689Skan if (TARGET_MIPS16 || TARGET_ABICALLS || TARGET_LONG_CALLS) 7217169689Skan { 7218169689Skan /* This is messy. gas treats "la $25,foo" as part of a call 7219169689Skan sequence and may allow a global "foo" to be lazily bound. 7220169689Skan The general move patterns therefore reject this combination. 7221169689Skan 7222169689Skan In this context, lazy binding would actually be OK for o32 and o64, 7223169689Skan but it's still wrong for n32 and n64; see mips_load_call_address. 7224169689Skan We must therefore load the address via a temporary register if 7225169689Skan mips_dangerous_for_la25_p. 7226169689Skan 7227169689Skan If we jump to the temporary register rather than $25, the assembler 7228169689Skan can use the move insn to fill the jump's delay slot. */ 7229169689Skan if (TARGET_ABICALLS && !mips_dangerous_for_la25_p (fnaddr)) 7230169689Skan temp1 = gen_rtx_REG (Pmode, PIC_FUNCTION_ADDR_REGNUM); 7231169689Skan mips_load_call_address (temp1, fnaddr, true); 7232169689Skan 7233169689Skan if (TARGET_ABICALLS && REGNO (temp1) != PIC_FUNCTION_ADDR_REGNUM) 7234169689Skan emit_move_insn (gen_rtx_REG (Pmode, PIC_FUNCTION_ADDR_REGNUM), temp1); 7235169689Skan emit_jump_insn (gen_indirect_jump (temp1)); 7236169689Skan } 7237169689Skan else 7238169689Skan { 7239169689Skan insn = emit_call_insn (gen_sibcall_internal (fnaddr, const0_rtx)); 7240169689Skan SIBLING_CALL_P (insn) = 1; 7241169689Skan } 7242169689Skan 7243169689Skan /* Run just enough of rest_of_compilation. This sequence was 7244169689Skan "borrowed" from alpha.c. */ 7245169689Skan insn = get_insns (); 7246169689Skan insn_locators_initialize (); 7247169689Skan split_all_insns_noflow (); 7248169689Skan if (TARGET_MIPS16) 7249169689Skan mips16_lay_out_constants (); 7250169689Skan shorten_branches (insn); 7251169689Skan final_start_function (insn, file, 1); 7252169689Skan final (insn, file, 1); 7253169689Skan final_end_function (); 7254169689Skan 7255169689Skan /* Clean up the vars set above. Note that final_end_function resets 7256169689Skan the global pointer for us. */ 7257169689Skan reload_completed = 0; 7258169689Skan no_new_pseudos = 0; 7259169689Skan} 7260169689Skan 7261169689Skan/* Returns nonzero if X contains a SYMBOL_REF. */ 7262169689Skan 7263169689Skanstatic int 7264169689Skansymbolic_expression_p (rtx x) 7265169689Skan{ 7266169689Skan if (GET_CODE (x) == SYMBOL_REF) 7267169689Skan return 1; 7268169689Skan 7269169689Skan if (GET_CODE (x) == CONST) 7270169689Skan return symbolic_expression_p (XEXP (x, 0)); 7271169689Skan 7272169689Skan if (UNARY_P (x)) 7273169689Skan return symbolic_expression_p (XEXP (x, 0)); 7274169689Skan 7275169689Skan if (ARITHMETIC_P (x)) 7276169689Skan return (symbolic_expression_p (XEXP (x, 0)) 7277169689Skan || symbolic_expression_p (XEXP (x, 1))); 7278169689Skan 7279169689Skan return 0; 7280169689Skan} 7281169689Skan 7282169689Skan/* Choose the section to use for the constant rtx expression X that has 7283169689Skan mode MODE. */ 7284169689Skan 7285169689Skanstatic section * 7286169689Skanmips_select_rtx_section (enum machine_mode mode, rtx x, 7287169689Skan unsigned HOST_WIDE_INT align) 7288169689Skan{ 7289169689Skan if (TARGET_MIPS16) 7290169689Skan { 7291169689Skan /* In mips16 mode, the constant table always goes in the same section 7292169689Skan as the function, so that constants can be loaded using PC relative 7293169689Skan addressing. */ 7294169689Skan return function_section (current_function_decl); 7295169689Skan } 7296169689Skan else if (TARGET_EMBEDDED_DATA) 7297169689Skan { 7298169689Skan /* For embedded applications, always put constants in read-only data, 7299169689Skan in order to reduce RAM usage. */ 7300169689Skan return mergeable_constant_section (mode, align, 0); 7301169689Skan } 7302169689Skan else 7303169689Skan { 7304169689Skan /* For hosted applications, always put constants in small data if 7305169689Skan possible, as this gives the best performance. */ 7306169689Skan /* ??? Consider using mergeable small data sections. */ 7307169689Skan 7308169689Skan if (GET_MODE_SIZE (mode) <= (unsigned) mips_section_threshold 7309169689Skan && mips_section_threshold > 0) 7310169689Skan return get_named_section (NULL, ".sdata", 0); 7311169689Skan else if (flag_pic && symbolic_expression_p (x)) 7312169689Skan return get_named_section (NULL, ".data.rel.ro", 3); 7313169689Skan else 7314169689Skan return mergeable_constant_section (mode, align, 0); 7315169689Skan } 7316169689Skan} 7317169689Skan 7318169689Skan/* Implement TARGET_ASM_FUNCTION_RODATA_SECTION. 7319169689Skan 7320169689Skan The complication here is that, with the combination TARGET_ABICALLS 7321169689Skan && !TARGET_GPWORD, jump tables will use absolute addresses, and should 7322169689Skan therefore not be included in the read-only part of a DSO. Handle such 7323169689Skan cases by selecting a normal data section instead of a read-only one. 7324169689Skan The logic apes that in default_function_rodata_section. */ 7325169689Skan 7326169689Skanstatic section * 7327169689Skanmips_function_rodata_section (tree decl) 7328169689Skan{ 7329169689Skan if (!TARGET_ABICALLS || TARGET_GPWORD) 7330169689Skan return default_function_rodata_section (decl); 7331169689Skan 7332169689Skan if (decl && DECL_SECTION_NAME (decl)) 7333169689Skan { 7334169689Skan const char *name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl)); 7335169689Skan if (DECL_ONE_ONLY (decl) && strncmp (name, ".gnu.linkonce.t.", 16) == 0) 7336169689Skan { 7337169689Skan char *rname = ASTRDUP (name); 7338169689Skan rname[14] = 'd'; 7339169689Skan return get_section (rname, SECTION_LINKONCE | SECTION_WRITE, decl); 7340169689Skan } 7341169689Skan else if (flag_function_sections && flag_data_sections 7342169689Skan && strncmp (name, ".text.", 6) == 0) 7343169689Skan { 7344169689Skan char *rname = ASTRDUP (name); 7345169689Skan memcpy (rname + 1, "data", 4); 7346169689Skan return get_section (rname, SECTION_WRITE, decl); 7347169689Skan } 7348169689Skan } 7349169689Skan return data_section; 7350169689Skan} 7351169689Skan 7352169689Skan/* Implement TARGET_IN_SMALL_DATA_P. This function controls whether 7353169689Skan locally-defined objects go in a small data section. It also controls 7354169689Skan the setting of the SYMBOL_REF_SMALL_P flag, which in turn helps 7355169689Skan mips_classify_symbol decide when to use %gp_rel(...)($gp) accesses. */ 7356169689Skan 7357169689Skanstatic bool 7358169689Skanmips_in_small_data_p (tree decl) 7359169689Skan{ 7360169689Skan HOST_WIDE_INT size; 7361169689Skan 7362169689Skan if (TREE_CODE (decl) == STRING_CST || TREE_CODE (decl) == FUNCTION_DECL) 7363169689Skan return false; 7364169689Skan 7365169689Skan /* We don't yet generate small-data references for -mabicalls. See related 7366169689Skan -G handling in override_options. */ 7367169689Skan if (TARGET_ABICALLS) 7368169689Skan return false; 7369169689Skan 7370169689Skan if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl) != 0) 7371169689Skan { 7372169689Skan const char *name; 7373169689Skan 7374169689Skan /* Reject anything that isn't in a known small-data section. */ 7375169689Skan name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl)); 7376169689Skan if (strcmp (name, ".sdata") != 0 && strcmp (name, ".sbss") != 0) 7377169689Skan return false; 7378169689Skan 7379169689Skan /* If a symbol is defined externally, the assembler will use the 7380169689Skan usual -G rules when deciding how to implement macros. */ 7381169689Skan if (TARGET_EXPLICIT_RELOCS || !DECL_EXTERNAL (decl)) 7382169689Skan return true; 7383169689Skan } 7384169689Skan else if (TARGET_EMBEDDED_DATA) 7385169689Skan { 7386169689Skan /* Don't put constants into the small data section: we want them 7387169689Skan to be in ROM rather than RAM. */ 7388169689Skan if (TREE_CODE (decl) != VAR_DECL) 7389169689Skan return false; 7390169689Skan 7391169689Skan if (TREE_READONLY (decl) 7392169689Skan && !TREE_SIDE_EFFECTS (decl) 7393169689Skan && (!DECL_INITIAL (decl) || TREE_CONSTANT (DECL_INITIAL (decl)))) 7394169689Skan return false; 7395169689Skan } 7396169689Skan 7397169689Skan size = int_size_in_bytes (TREE_TYPE (decl)); 7398169689Skan return (size > 0 && size <= mips_section_threshold); 7399169689Skan} 7400169689Skan 7401169689Skan/* Implement TARGET_USE_ANCHORS_FOR_SYMBOL_P. We don't want to use 7402169689Skan anchors for small data: the GP register acts as an anchor in that 7403169689Skan case. We also don't want to use them for PC-relative accesses, 7404169689Skan where the PC acts as an anchor. */ 7405169689Skan 7406169689Skanstatic bool 7407169689Skanmips_use_anchors_for_symbol_p (rtx symbol) 7408169689Skan{ 7409169689Skan switch (mips_classify_symbol (symbol)) 7410169689Skan { 7411169689Skan case SYMBOL_CONSTANT_POOL: 7412169689Skan case SYMBOL_SMALL_DATA: 7413169689Skan return false; 7414169689Skan 7415169689Skan default: 7416169689Skan return true; 7417169689Skan } 7418169689Skan} 7419169689Skan 7420169689Skan/* See whether VALTYPE is a record whose fields should be returned in 7421169689Skan floating-point registers. If so, return the number of fields and 7422169689Skan list them in FIELDS (which should have two elements). Return 0 7423169689Skan otherwise. 7424169689Skan 7425169689Skan For n32 & n64, a structure with one or two fields is returned in 7426169689Skan floating-point registers as long as every field has a floating-point 7427169689Skan type. */ 7428169689Skan 7429169689Skanstatic int 7430169689Skanmips_fpr_return_fields (tree valtype, tree *fields) 7431169689Skan{ 7432169689Skan tree field; 7433169689Skan int i; 7434169689Skan 7435169689Skan if (!TARGET_NEWABI) 7436169689Skan return 0; 7437169689Skan 7438169689Skan if (TREE_CODE (valtype) != RECORD_TYPE) 7439169689Skan return 0; 7440169689Skan 7441169689Skan i = 0; 7442169689Skan for (field = TYPE_FIELDS (valtype); field != 0; field = TREE_CHAIN (field)) 7443169689Skan { 7444169689Skan if (TREE_CODE (field) != FIELD_DECL) 7445169689Skan continue; 7446169689Skan 7447169689Skan if (TREE_CODE (TREE_TYPE (field)) != REAL_TYPE) 7448169689Skan return 0; 7449169689Skan 7450169689Skan if (i == 2) 7451169689Skan return 0; 7452169689Skan 7453169689Skan fields[i++] = field; 7454169689Skan } 7455169689Skan return i; 7456169689Skan} 7457169689Skan 7458169689Skan 7459169689Skan/* Implement TARGET_RETURN_IN_MSB. For n32 & n64, we should return 7460169689Skan a value in the most significant part of $2/$3 if: 7461169689Skan 7462169689Skan - the target is big-endian; 7463169689Skan 7464169689Skan - the value has a structure or union type (we generalize this to 7465169689Skan cover aggregates from other languages too); and 7466169689Skan 7467169689Skan - the structure is not returned in floating-point registers. */ 7468169689Skan 7469169689Skanstatic bool 7470169689Skanmips_return_in_msb (tree valtype) 7471169689Skan{ 7472169689Skan tree fields[2]; 7473169689Skan 7474169689Skan return (TARGET_NEWABI 7475169689Skan && TARGET_BIG_ENDIAN 7476169689Skan && AGGREGATE_TYPE_P (valtype) 7477169689Skan && mips_fpr_return_fields (valtype, fields) == 0); 7478169689Skan} 7479169689Skan 7480169689Skan 7481169689Skan/* Return a composite value in a pair of floating-point registers. 7482169689Skan MODE1 and OFFSET1 are the mode and byte offset for the first value, 7483169689Skan likewise MODE2 and OFFSET2 for the second. MODE is the mode of the 7484169689Skan complete value. 7485169689Skan 7486169689Skan For n32 & n64, $f0 always holds the first value and $f2 the second. 7487169689Skan Otherwise the values are packed together as closely as possible. */ 7488169689Skan 7489169689Skanstatic rtx 7490169689Skanmips_return_fpr_pair (enum machine_mode mode, 7491169689Skan enum machine_mode mode1, HOST_WIDE_INT offset1, 7492169689Skan enum machine_mode mode2, HOST_WIDE_INT offset2) 7493169689Skan{ 7494169689Skan int inc; 7495169689Skan 7496169689Skan inc = (TARGET_NEWABI ? 2 : FP_INC); 7497169689Skan return gen_rtx_PARALLEL 7498169689Skan (mode, 7499169689Skan gen_rtvec (2, 7500169689Skan gen_rtx_EXPR_LIST (VOIDmode, 7501169689Skan gen_rtx_REG (mode1, FP_RETURN), 7502169689Skan GEN_INT (offset1)), 7503169689Skan gen_rtx_EXPR_LIST (VOIDmode, 7504169689Skan gen_rtx_REG (mode2, FP_RETURN + inc), 7505169689Skan GEN_INT (offset2)))); 7506169689Skan 7507169689Skan} 7508169689Skan 7509169689Skan 7510169689Skan/* Implement FUNCTION_VALUE and LIBCALL_VALUE. For normal calls, 7511169689Skan VALTYPE is the return type and MODE is VOIDmode. For libcalls, 7512169689Skan VALTYPE is null and MODE is the mode of the return value. */ 7513169689Skan 7514169689Skanrtx 7515169689Skanmips_function_value (tree valtype, tree func ATTRIBUTE_UNUSED, 7516169689Skan enum machine_mode mode) 7517169689Skan{ 7518169689Skan if (valtype) 7519169689Skan { 7520169689Skan tree fields[2]; 7521169689Skan int unsignedp; 7522169689Skan 7523169689Skan mode = TYPE_MODE (valtype); 7524169689Skan unsignedp = TYPE_UNSIGNED (valtype); 7525169689Skan 7526169689Skan /* Since we define TARGET_PROMOTE_FUNCTION_RETURN that returns 7527169689Skan true, we must promote the mode just as PROMOTE_MODE does. */ 7528169689Skan mode = promote_mode (valtype, mode, &unsignedp, 1); 7529169689Skan 7530169689Skan /* Handle structures whose fields are returned in $f0/$f2. */ 7531169689Skan switch (mips_fpr_return_fields (valtype, fields)) 7532169689Skan { 7533169689Skan case 1: 7534169689Skan return gen_rtx_REG (mode, FP_RETURN); 7535169689Skan 7536169689Skan case 2: 7537169689Skan return mips_return_fpr_pair (mode, 7538169689Skan TYPE_MODE (TREE_TYPE (fields[0])), 7539169689Skan int_byte_position (fields[0]), 7540169689Skan TYPE_MODE (TREE_TYPE (fields[1])), 7541169689Skan int_byte_position (fields[1])); 7542169689Skan } 7543169689Skan 7544169689Skan /* If a value is passed in the most significant part of a register, see 7545169689Skan whether we have to round the mode up to a whole number of words. */ 7546169689Skan if (mips_return_in_msb (valtype)) 7547169689Skan { 7548169689Skan HOST_WIDE_INT size = int_size_in_bytes (valtype); 7549169689Skan if (size % UNITS_PER_WORD != 0) 7550169689Skan { 7551169689Skan size += UNITS_PER_WORD - size % UNITS_PER_WORD; 7552169689Skan mode = mode_for_size (size * BITS_PER_UNIT, MODE_INT, 0); 7553169689Skan } 7554169689Skan } 7555169689Skan 7556169689Skan /* For EABI, the class of return register depends entirely on MODE. 7557169689Skan For example, "struct { some_type x; }" and "union { some_type x; }" 7558169689Skan are returned in the same way as a bare "some_type" would be. 7559169689Skan Other ABIs only use FPRs for scalar, complex or vector types. */ 7560169689Skan if (mips_abi != ABI_EABI && !FLOAT_TYPE_P (valtype)) 7561169689Skan return gen_rtx_REG (mode, GP_RETURN); 7562169689Skan } 7563169689Skan 7564169689Skan if ((GET_MODE_CLASS (mode) == MODE_FLOAT 7565169689Skan || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT) 7566169689Skan && GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE) 7567169689Skan return gen_rtx_REG (mode, FP_RETURN); 7568169689Skan 7569169689Skan /* Handle long doubles for n32 & n64. */ 7570169689Skan if (mode == TFmode) 7571169689Skan return mips_return_fpr_pair (mode, 7572169689Skan DImode, 0, 7573169689Skan DImode, GET_MODE_SIZE (mode) / 2); 7574169689Skan 7575169689Skan if (GET_MODE_CLASS (mode) == MODE_COMPLEX_FLOAT 7576169689Skan && GET_MODE_SIZE (mode) <= UNITS_PER_HWFPVALUE * 2) 7577169689Skan return mips_return_fpr_pair (mode, 7578169689Skan GET_MODE_INNER (mode), 0, 7579169689Skan GET_MODE_INNER (mode), 7580169689Skan GET_MODE_SIZE (mode) / 2); 7581169689Skan 7582169689Skan return gen_rtx_REG (mode, GP_RETURN); 7583169689Skan} 7584169689Skan 7585169689Skan/* Return nonzero when an argument must be passed by reference. */ 7586169689Skan 7587169689Skanstatic bool 7588169689Skanmips_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED, 7589169689Skan enum machine_mode mode, tree type, 7590169689Skan bool named ATTRIBUTE_UNUSED) 7591169689Skan{ 7592169689Skan if (mips_abi == ABI_EABI) 7593169689Skan { 7594169689Skan int size; 7595169689Skan 7596169689Skan /* ??? How should SCmode be handled? */ 7597169689Skan if (mode == DImode || mode == DFmode) 7598169689Skan return 0; 7599169689Skan 7600169689Skan size = type ? int_size_in_bytes (type) : GET_MODE_SIZE (mode); 7601169689Skan return size == -1 || size > UNITS_PER_WORD; 7602169689Skan } 7603169689Skan else 7604169689Skan { 7605169689Skan /* If we have a variable-sized parameter, we have no choice. */ 7606169689Skan return targetm.calls.must_pass_in_stack (mode, type); 7607169689Skan } 7608169689Skan} 7609169689Skan 7610169689Skanstatic bool 7611169689Skanmips_callee_copies (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED, 7612169689Skan enum machine_mode mode ATTRIBUTE_UNUSED, 7613169689Skan tree type ATTRIBUTE_UNUSED, bool named) 7614169689Skan{ 7615169689Skan return mips_abi == ABI_EABI && named; 7616169689Skan} 7617169689Skan 7618169689Skan/* Return true if registers of class CLASS cannot change from mode FROM 7619169689Skan to mode TO. */ 7620169689Skan 7621169689Skanbool 7622169689Skanmips_cannot_change_mode_class (enum machine_mode from, 7623169689Skan enum machine_mode to, enum reg_class class) 7624169689Skan{ 7625169689Skan if (MIN (GET_MODE_SIZE (from), GET_MODE_SIZE (to)) <= UNITS_PER_WORD 7626169689Skan && MAX (GET_MODE_SIZE (from), GET_MODE_SIZE (to)) > UNITS_PER_WORD) 7627169689Skan { 7628169689Skan if (TARGET_BIG_ENDIAN) 7629169689Skan { 7630169689Skan /* When a multi-word value is stored in paired floating-point 7631169689Skan registers, the first register always holds the low word. 7632169689Skan We therefore can't allow FPRs to change between single-word 7633169689Skan and multi-word modes. */ 7634169689Skan if (FP_INC > 1 && reg_classes_intersect_p (FP_REGS, class)) 7635169689Skan return true; 7636169689Skan } 7637169689Skan else 7638169689Skan { 7639169689Skan /* LO_REGNO == HI_REGNO + 1, so if a multi-word value is stored 7640169689Skan in LO and HI, the high word always comes first. We therefore 7641169689Skan can't allow values stored in HI to change between single-word 7642169689Skan and multi-word modes. 7643169689Skan This rule applies to both the original HI/LO pair and the new 7644169689Skan DSP accumulators. */ 7645169689Skan if (reg_classes_intersect_p (ACC_REGS, class)) 7646169689Skan return true; 7647169689Skan } 7648169689Skan } 7649169689Skan /* Loading a 32-bit value into a 64-bit floating-point register 7650169689Skan will not sign-extend the value, despite what LOAD_EXTEND_OP says. 7651169689Skan We can't allow 64-bit float registers to change from SImode to 7652169689Skan to a wider mode. */ 7653169689Skan if (TARGET_FLOAT64 7654169689Skan && from == SImode 7655169689Skan && GET_MODE_SIZE (to) >= UNITS_PER_WORD 7656169689Skan && reg_classes_intersect_p (FP_REGS, class)) 7657169689Skan return true; 7658169689Skan return false; 7659169689Skan} 7660169689Skan 7661169689Skan/* Return true if X should not be moved directly into register $25. 7662169689Skan We need this because many versions of GAS will treat "la $25,foo" as 7663169689Skan part of a call sequence and so allow a global "foo" to be lazily bound. */ 7664169689Skan 7665169689Skanbool 7666169689Skanmips_dangerous_for_la25_p (rtx x) 7667169689Skan{ 7668169689Skan HOST_WIDE_INT offset; 7669169689Skan 7670169689Skan if (TARGET_EXPLICIT_RELOCS) 7671169689Skan return false; 7672169689Skan 7673169689Skan mips_split_const (x, &x, &offset); 7674169689Skan return global_got_operand (x, VOIDmode); 7675169689Skan} 7676169689Skan 7677169689Skan/* Implement PREFERRED_RELOAD_CLASS. */ 7678169689Skan 7679169689Skanenum reg_class 7680169689Skanmips_preferred_reload_class (rtx x, enum reg_class class) 7681169689Skan{ 7682169689Skan if (mips_dangerous_for_la25_p (x) && reg_class_subset_p (LEA_REGS, class)) 7683169689Skan return LEA_REGS; 7684169689Skan 7685169689Skan if (TARGET_HARD_FLOAT 7686169689Skan && FLOAT_MODE_P (GET_MODE (x)) 7687169689Skan && reg_class_subset_p (FP_REGS, class)) 7688169689Skan return FP_REGS; 7689169689Skan 7690169689Skan if (reg_class_subset_p (GR_REGS, class)) 7691169689Skan class = GR_REGS; 7692169689Skan 7693169689Skan if (TARGET_MIPS16 && reg_class_subset_p (M16_REGS, class)) 7694169689Skan class = M16_REGS; 7695169689Skan 7696169689Skan return class; 7697169689Skan} 7698169689Skan 7699169689Skan/* This function returns the register class required for a secondary 7700169689Skan register when copying between one of the registers in CLASS, and X, 7701169689Skan using MODE. If IN_P is nonzero, the copy is going from X to the 7702169689Skan register, otherwise the register is the source. A return value of 7703169689Skan NO_REGS means that no secondary register is required. */ 7704169689Skan 7705169689Skanenum reg_class 7706169689Skanmips_secondary_reload_class (enum reg_class class, 7707169689Skan enum machine_mode mode, rtx x, int in_p) 7708169689Skan{ 7709169689Skan enum reg_class gr_regs = TARGET_MIPS16 ? M16_REGS : GR_REGS; 7710169689Skan int regno = -1; 7711169689Skan int gp_reg_p; 7712169689Skan 7713169689Skan if (REG_P (x)|| GET_CODE (x) == SUBREG) 7714169689Skan regno = true_regnum (x); 7715169689Skan 7716169689Skan gp_reg_p = TARGET_MIPS16 ? M16_REG_P (regno) : GP_REG_P (regno); 7717169689Skan 7718169689Skan if (mips_dangerous_for_la25_p (x)) 7719169689Skan { 7720169689Skan gr_regs = LEA_REGS; 7721169689Skan if (TEST_HARD_REG_BIT (reg_class_contents[(int) class], 25)) 7722169689Skan return gr_regs; 7723169689Skan } 7724169689Skan 7725169689Skan /* Copying from HI or LO to anywhere other than a general register 7726169689Skan requires a general register. 7727169689Skan This rule applies to both the original HI/LO pair and the new 7728169689Skan DSP accumulators. */ 7729169689Skan if (reg_class_subset_p (class, ACC_REGS)) 7730169689Skan { 7731169689Skan if (TARGET_MIPS16 && in_p) 7732169689Skan { 7733169689Skan /* We can't really copy to HI or LO at all in mips16 mode. */ 7734169689Skan return M16_REGS; 7735169689Skan } 7736169689Skan return gp_reg_p ? NO_REGS : gr_regs; 7737169689Skan } 7738169689Skan if (ACC_REG_P (regno)) 7739169689Skan { 7740169689Skan if (TARGET_MIPS16 && ! in_p) 7741169689Skan { 7742169689Skan /* We can't really copy to HI or LO at all in mips16 mode. */ 7743169689Skan return M16_REGS; 7744169689Skan } 7745169689Skan return class == gr_regs ? NO_REGS : gr_regs; 7746169689Skan } 7747169689Skan 7748169689Skan /* We can only copy a value to a condition code register from a 7749169689Skan floating point register, and even then we require a scratch 7750169689Skan floating point register. We can only copy a value out of a 7751169689Skan condition code register into a general register. */ 7752169689Skan if (class == ST_REGS) 7753169689Skan { 7754169689Skan if (in_p) 7755169689Skan return FP_REGS; 7756169689Skan return gp_reg_p ? NO_REGS : gr_regs; 7757169689Skan } 7758169689Skan if (ST_REG_P (regno)) 7759169689Skan { 7760169689Skan if (! in_p) 7761169689Skan return FP_REGS; 7762169689Skan return class == gr_regs ? NO_REGS : gr_regs; 7763169689Skan } 7764169689Skan 7765169689Skan if (class == FP_REGS) 7766169689Skan { 7767169689Skan if (MEM_P (x)) 7768169689Skan { 7769169689Skan /* In this case we can use lwc1, swc1, ldc1 or sdc1. */ 7770169689Skan return NO_REGS; 7771169689Skan } 7772169689Skan else if (CONSTANT_P (x) && GET_MODE_CLASS (mode) == MODE_FLOAT) 7773169689Skan { 7774169689Skan /* We can use the l.s and l.d macros to load floating-point 7775169689Skan constants. ??? For l.s, we could probably get better 7776169689Skan code by returning GR_REGS here. */ 7777169689Skan return NO_REGS; 7778169689Skan } 7779169689Skan else if (gp_reg_p || x == CONST0_RTX (mode)) 7780169689Skan { 7781169689Skan /* In this case we can use mtc1, mfc1, dmtc1 or dmfc1. */ 7782169689Skan return NO_REGS; 7783169689Skan } 7784169689Skan else if (FP_REG_P (regno)) 7785169689Skan { 7786169689Skan /* In this case we can use mov.s or mov.d. */ 7787169689Skan return NO_REGS; 7788169689Skan } 7789169689Skan else 7790169689Skan { 7791169689Skan /* Otherwise, we need to reload through an integer register. */ 7792169689Skan return gr_regs; 7793169689Skan } 7794169689Skan } 7795169689Skan 7796169689Skan /* In mips16 mode, going between memory and anything but M16_REGS 7797169689Skan requires an M16_REG. */ 7798169689Skan if (TARGET_MIPS16) 7799169689Skan { 7800169689Skan if (class != M16_REGS && class != M16_NA_REGS) 7801169689Skan { 7802169689Skan if (gp_reg_p) 7803169689Skan return NO_REGS; 7804169689Skan return M16_REGS; 7805169689Skan } 7806169689Skan if (! gp_reg_p) 7807169689Skan { 7808169689Skan if (class == M16_REGS || class == M16_NA_REGS) 7809169689Skan return NO_REGS; 7810169689Skan return M16_REGS; 7811169689Skan } 7812169689Skan } 7813169689Skan 7814169689Skan return NO_REGS; 7815169689Skan} 7816169689Skan 7817169689Skan/* Implement CLASS_MAX_NREGS. 7818169689Skan 7819169689Skan Usually all registers are word-sized. The only supported exception 7820169689Skan is -mgp64 -msingle-float, which has 64-bit words but 32-bit float 7821169689Skan registers. A word-based calculation is correct even in that case, 7822169689Skan since -msingle-float disallows multi-FPR values. 7823169689Skan 7824169689Skan The FP status registers are an exception to this rule. They are always 7825169689Skan 4 bytes wide as they only hold condition code modes, and CCmode is always 7826169689Skan considered to be 4 bytes wide. */ 7827169689Skan 7828169689Skanint 7829169689Skanmips_class_max_nregs (enum reg_class class ATTRIBUTE_UNUSED, 7830169689Skan enum machine_mode mode) 7831169689Skan{ 7832169689Skan if (class == ST_REGS) 7833169689Skan return (GET_MODE_SIZE (mode) + 3) / 4; 7834169689Skan else 7835169689Skan return (GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD; 7836169689Skan} 7837169689Skan 7838169689Skanstatic bool 7839169689Skanmips_valid_pointer_mode (enum machine_mode mode) 7840169689Skan{ 7841169689Skan return (mode == SImode || (TARGET_64BIT && mode == DImode)); 7842169689Skan} 7843169689Skan 7844169689Skan/* Target hook for vector_mode_supported_p. */ 7845169689Skan 7846169689Skanstatic bool 7847169689Skanmips_vector_mode_supported_p (enum machine_mode mode) 7848169689Skan{ 7849169689Skan switch (mode) 7850169689Skan { 7851169689Skan case V2SFmode: 7852169689Skan return TARGET_PAIRED_SINGLE_FLOAT; 7853169689Skan 7854169689Skan case V2HImode: 7855169689Skan case V4QImode: 7856169689Skan return TARGET_DSP; 7857169689Skan 7858169689Skan default: 7859169689Skan return false; 7860169689Skan } 7861169689Skan} 7862169689Skan 7863169689Skan/* If we can access small data directly (using gp-relative relocation 7864169689Skan operators) return the small data pointer, otherwise return null. 7865169689Skan 7866169689Skan For each mips16 function which refers to GP relative symbols, we 7867169689Skan use a pseudo register, initialized at the start of the function, to 7868169689Skan hold the $gp value. */ 7869169689Skan 7870169689Skanstatic rtx 7871169689Skanmips16_gp_pseudo_reg (void) 7872169689Skan{ 7873169689Skan if (cfun->machine->mips16_gp_pseudo_rtx == NULL_RTX) 7874169689Skan { 7875169689Skan rtx unspec; 7876169689Skan rtx insn, scan; 7877169689Skan 7878169689Skan cfun->machine->mips16_gp_pseudo_rtx = gen_reg_rtx (Pmode); 7879169689Skan 7880169689Skan /* We want to initialize this to a value which gcc will believe 7881169689Skan is constant. */ 7882169689Skan start_sequence (); 7883169689Skan unspec = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, const0_rtx), UNSPEC_GP); 7884169689Skan emit_move_insn (cfun->machine->mips16_gp_pseudo_rtx, 7885169689Skan gen_rtx_CONST (Pmode, unspec)); 7886169689Skan insn = get_insns (); 7887169689Skan end_sequence (); 7888169689Skan 7889169689Skan push_topmost_sequence (); 7890169689Skan /* We need to emit the initialization after the FUNCTION_BEG 7891169689Skan note, so that it will be integrated. */ 7892169689Skan for (scan = get_insns (); scan != NULL_RTX; scan = NEXT_INSN (scan)) 7893169689Skan if (NOTE_P (scan) 7894169689Skan && NOTE_LINE_NUMBER (scan) == NOTE_INSN_FUNCTION_BEG) 7895169689Skan break; 7896169689Skan if (scan == NULL_RTX) 7897169689Skan scan = get_insns (); 7898169689Skan insn = emit_insn_after (insn, scan); 7899169689Skan pop_topmost_sequence (); 7900169689Skan } 7901169689Skan 7902169689Skan return cfun->machine->mips16_gp_pseudo_rtx; 7903169689Skan} 7904169689Skan 7905169689Skan/* Write out code to move floating point arguments in or out of 7906169689Skan general registers. Output the instructions to FILE. FP_CODE is 7907169689Skan the code describing which arguments are present (see the comment at 7908169689Skan the definition of CUMULATIVE_ARGS in mips.h). FROM_FP_P is nonzero if 7909169689Skan we are copying from the floating point registers. */ 7910169689Skan 7911169689Skanstatic void 7912169689Skanmips16_fp_args (FILE *file, int fp_code, int from_fp_p) 7913169689Skan{ 7914169689Skan const char *s; 7915169689Skan int gparg, fparg; 7916169689Skan unsigned int f; 7917169689Skan 7918169689Skan /* This code only works for the original 32 bit ABI and the O64 ABI. */ 7919169689Skan gcc_assert (TARGET_OLDABI); 7920169689Skan 7921169689Skan if (from_fp_p) 7922169689Skan s = "mfc1"; 7923169689Skan else 7924169689Skan s = "mtc1"; 7925169689Skan gparg = GP_ARG_FIRST; 7926169689Skan fparg = FP_ARG_FIRST; 7927169689Skan for (f = (unsigned int) fp_code; f != 0; f >>= 2) 7928169689Skan { 7929169689Skan if ((f & 3) == 1) 7930169689Skan { 7931169689Skan if ((fparg & 1) != 0) 7932169689Skan ++fparg; 7933169689Skan fprintf (file, "\t%s\t%s,%s\n", s, 7934169689Skan reg_names[gparg], reg_names[fparg]); 7935169689Skan } 7936169689Skan else if ((f & 3) == 2) 7937169689Skan { 7938169689Skan if (TARGET_64BIT) 7939169689Skan fprintf (file, "\td%s\t%s,%s\n", s, 7940169689Skan reg_names[gparg], reg_names[fparg]); 7941169689Skan else 7942169689Skan { 7943169689Skan if ((fparg & 1) != 0) 7944169689Skan ++fparg; 7945169689Skan if (TARGET_BIG_ENDIAN) 7946169689Skan fprintf (file, "\t%s\t%s,%s\n\t%s\t%s,%s\n", s, 7947169689Skan reg_names[gparg], reg_names[fparg + 1], s, 7948169689Skan reg_names[gparg + 1], reg_names[fparg]); 7949169689Skan else 7950169689Skan fprintf (file, "\t%s\t%s,%s\n\t%s\t%s,%s\n", s, 7951169689Skan reg_names[gparg], reg_names[fparg], s, 7952169689Skan reg_names[gparg + 1], reg_names[fparg + 1]); 7953169689Skan ++gparg; 7954169689Skan ++fparg; 7955169689Skan } 7956169689Skan } 7957169689Skan else 7958169689Skan gcc_unreachable (); 7959169689Skan 7960169689Skan ++gparg; 7961169689Skan ++fparg; 7962169689Skan } 7963169689Skan} 7964169689Skan 7965169689Skan/* Build a mips16 function stub. This is used for functions which 7966169689Skan take arguments in the floating point registers. It is 32 bit code 7967169689Skan that moves the floating point args into the general registers, and 7968169689Skan then jumps to the 16 bit code. */ 7969169689Skan 7970169689Skanstatic void 7971169689Skanbuild_mips16_function_stub (FILE *file) 7972169689Skan{ 7973169689Skan const char *fnname; 7974169689Skan char *secname, *stubname; 7975169689Skan tree stubid, stubdecl; 7976169689Skan int need_comma; 7977169689Skan unsigned int f; 7978169689Skan 7979169689Skan fnname = XSTR (XEXP (DECL_RTL (current_function_decl), 0), 0); 7980169689Skan secname = (char *) alloca (strlen (fnname) + 20); 7981169689Skan sprintf (secname, ".mips16.fn.%s", fnname); 7982169689Skan stubname = (char *) alloca (strlen (fnname) + 20); 7983169689Skan sprintf (stubname, "__fn_stub_%s", fnname); 7984169689Skan stubid = get_identifier (stubname); 7985169689Skan stubdecl = build_decl (FUNCTION_DECL, stubid, 7986169689Skan build_function_type (void_type_node, NULL_TREE)); 7987169689Skan DECL_SECTION_NAME (stubdecl) = build_string (strlen (secname), secname); 7988169689Skan 7989169689Skan fprintf (file, "\t# Stub function for %s (", current_function_name ()); 7990169689Skan need_comma = 0; 7991169689Skan for (f = (unsigned int) current_function_args_info.fp_code; f != 0; f >>= 2) 7992169689Skan { 7993169689Skan fprintf (file, "%s%s", 7994169689Skan need_comma ? ", " : "", 7995169689Skan (f & 3) == 1 ? "float" : "double"); 7996169689Skan need_comma = 1; 7997169689Skan } 7998169689Skan fprintf (file, ")\n"); 7999169689Skan 8000169689Skan fprintf (file, "\t.set\tnomips16\n"); 8001169689Skan switch_to_section (function_section (stubdecl)); 8002169689Skan ASM_OUTPUT_ALIGN (file, floor_log2 (FUNCTION_BOUNDARY / BITS_PER_UNIT)); 8003169689Skan 8004169689Skan /* ??? If FUNCTION_NAME_ALREADY_DECLARED is defined, then we are 8005169689Skan within a .ent, and we cannot emit another .ent. */ 8006169689Skan if (!FUNCTION_NAME_ALREADY_DECLARED) 8007169689Skan { 8008169689Skan fputs ("\t.ent\t", file); 8009169689Skan assemble_name (file, stubname); 8010169689Skan fputs ("\n", file); 8011169689Skan } 8012169689Skan 8013169689Skan assemble_name (file, stubname); 8014169689Skan fputs (":\n", file); 8015169689Skan 8016169689Skan /* We don't want the assembler to insert any nops here. */ 8017169689Skan fprintf (file, "\t.set\tnoreorder\n"); 8018169689Skan 8019169689Skan mips16_fp_args (file, current_function_args_info.fp_code, 1); 8020169689Skan 8021169689Skan fprintf (asm_out_file, "\t.set\tnoat\n"); 8022169689Skan fprintf (asm_out_file, "\tla\t%s,", reg_names[GP_REG_FIRST + 1]); 8023169689Skan assemble_name (file, fnname); 8024169689Skan fprintf (file, "\n"); 8025169689Skan fprintf (asm_out_file, "\tjr\t%s\n", reg_names[GP_REG_FIRST + 1]); 8026169689Skan fprintf (asm_out_file, "\t.set\tat\n"); 8027169689Skan 8028169689Skan /* Unfortunately, we can't fill the jump delay slot. We can't fill 8029169689Skan with one of the mfc1 instructions, because the result is not 8030169689Skan available for one instruction, so if the very first instruction 8031169689Skan in the function refers to the register, it will see the wrong 8032169689Skan value. */ 8033169689Skan fprintf (file, "\tnop\n"); 8034169689Skan 8035169689Skan fprintf (file, "\t.set\treorder\n"); 8036169689Skan 8037169689Skan if (!FUNCTION_NAME_ALREADY_DECLARED) 8038169689Skan { 8039169689Skan fputs ("\t.end\t", file); 8040169689Skan assemble_name (file, stubname); 8041169689Skan fputs ("\n", file); 8042169689Skan } 8043169689Skan 8044169689Skan fprintf (file, "\t.set\tmips16\n"); 8045169689Skan 8046169689Skan switch_to_section (function_section (current_function_decl)); 8047169689Skan} 8048169689Skan 8049169689Skan/* We keep a list of functions for which we have already built stubs 8050169689Skan in build_mips16_call_stub. */ 8051169689Skan 8052169689Skanstruct mips16_stub 8053169689Skan{ 8054169689Skan struct mips16_stub *next; 8055169689Skan char *name; 8056169689Skan int fpret; 8057169689Skan}; 8058169689Skan 8059169689Skanstatic struct mips16_stub *mips16_stubs; 8060169689Skan 8061169689Skan/* Build a call stub for a mips16 call. A stub is needed if we are 8062169689Skan passing any floating point values which should go into the floating 8063169689Skan point registers. If we are, and the call turns out to be to a 32 8064169689Skan bit function, the stub will be used to move the values into the 8065169689Skan floating point registers before calling the 32 bit function. The 8066169689Skan linker will magically adjust the function call to either the 16 bit 8067169689Skan function or the 32 bit stub, depending upon where the function call 8068169689Skan is actually defined. 8069169689Skan 8070169689Skan Similarly, we need a stub if the return value might come back in a 8071169689Skan floating point register. 8072169689Skan 8073169689Skan RETVAL is the location of the return value, or null if this is 8074169689Skan a call rather than a call_value. FN is the address of the 8075169689Skan function and ARG_SIZE is the size of the arguments. FP_CODE 8076169689Skan is the code built by function_arg. This function returns a nonzero 8077169689Skan value if it builds the call instruction itself. */ 8078169689Skan 8079169689Skanint 8080169689Skanbuild_mips16_call_stub (rtx retval, rtx fn, rtx arg_size, int fp_code) 8081169689Skan{ 8082169689Skan int fpret; 8083169689Skan const char *fnname; 8084169689Skan char *secname, *stubname; 8085169689Skan struct mips16_stub *l; 8086169689Skan tree stubid, stubdecl; 8087169689Skan int need_comma; 8088169689Skan unsigned int f; 8089169689Skan 8090169689Skan /* We don't need to do anything if we aren't in mips16 mode, or if 8091169689Skan we were invoked with the -msoft-float option. */ 8092169689Skan if (! TARGET_MIPS16 || ! mips16_hard_float) 8093169689Skan return 0; 8094169689Skan 8095169689Skan /* Figure out whether the value might come back in a floating point 8096169689Skan register. */ 8097169689Skan fpret = (retval != 0 8098169689Skan && GET_MODE_CLASS (GET_MODE (retval)) == MODE_FLOAT 8099169689Skan && GET_MODE_SIZE (GET_MODE (retval)) <= UNITS_PER_FPVALUE); 8100169689Skan 8101169689Skan /* We don't need to do anything if there were no floating point 8102169689Skan arguments and the value will not be returned in a floating point 8103169689Skan register. */ 8104169689Skan if (fp_code == 0 && ! fpret) 8105169689Skan return 0; 8106169689Skan 8107169689Skan /* We don't need to do anything if this is a call to a special 8108169689Skan mips16 support function. */ 8109169689Skan if (GET_CODE (fn) == SYMBOL_REF 8110169689Skan && strncmp (XSTR (fn, 0), "__mips16_", 9) == 0) 8111169689Skan return 0; 8112169689Skan 8113169689Skan /* This code will only work for o32 and o64 abis. The other ABI's 8114169689Skan require more sophisticated support. */ 8115169689Skan gcc_assert (TARGET_OLDABI); 8116169689Skan 8117169689Skan /* We can only handle SFmode and DFmode floating point return 8118169689Skan values. */ 8119169689Skan if (fpret) 8120169689Skan gcc_assert (GET_MODE (retval) == SFmode || GET_MODE (retval) == DFmode); 8121169689Skan 8122169689Skan /* If we're calling via a function pointer, then we must always call 8123169689Skan via a stub. There are magic stubs provided in libgcc.a for each 8124169689Skan of the required cases. Each of them expects the function address 8125169689Skan to arrive in register $2. */ 8126169689Skan 8127169689Skan if (GET_CODE (fn) != SYMBOL_REF) 8128169689Skan { 8129169689Skan char buf[30]; 8130169689Skan tree id; 8131169689Skan rtx stub_fn, insn; 8132169689Skan 8133169689Skan /* ??? If this code is modified to support other ABI's, we need 8134169689Skan to handle PARALLEL return values here. */ 8135169689Skan 8136169689Skan sprintf (buf, "__mips16_call_stub_%s%d", 8137169689Skan (fpret 8138169689Skan ? (GET_MODE (retval) == SFmode ? "sf_" : "df_") 8139169689Skan : ""), 8140169689Skan fp_code); 8141169689Skan id = get_identifier (buf); 8142169689Skan stub_fn = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (id)); 8143169689Skan 8144169689Skan emit_move_insn (gen_rtx_REG (Pmode, 2), fn); 8145169689Skan 8146169689Skan if (retval == NULL_RTX) 8147169689Skan insn = gen_call_internal (stub_fn, arg_size); 8148169689Skan else 8149169689Skan insn = gen_call_value_internal (retval, stub_fn, arg_size); 8150169689Skan insn = emit_call_insn (insn); 8151169689Skan 8152169689Skan /* Put the register usage information on the CALL. */ 8153169689Skan CALL_INSN_FUNCTION_USAGE (insn) = 8154169689Skan gen_rtx_EXPR_LIST (VOIDmode, 8155169689Skan gen_rtx_USE (VOIDmode, gen_rtx_REG (Pmode, 2)), 8156169689Skan CALL_INSN_FUNCTION_USAGE (insn)); 8157169689Skan 8158169689Skan /* If we are handling a floating point return value, we need to 8159169689Skan save $18 in the function prologue. Putting a note on the 8160169689Skan call will mean that regs_ever_live[$18] will be true if the 8161169689Skan call is not eliminated, and we can check that in the prologue 8162169689Skan code. */ 8163169689Skan if (fpret) 8164169689Skan CALL_INSN_FUNCTION_USAGE (insn) = 8165169689Skan gen_rtx_EXPR_LIST (VOIDmode, 8166169689Skan gen_rtx_USE (VOIDmode, 8167169689Skan gen_rtx_REG (word_mode, 18)), 8168169689Skan CALL_INSN_FUNCTION_USAGE (insn)); 8169169689Skan 8170169689Skan /* Return 1 to tell the caller that we've generated the call 8171169689Skan insn. */ 8172169689Skan return 1; 8173169689Skan } 8174169689Skan 8175169689Skan /* We know the function we are going to call. If we have already 8176169689Skan built a stub, we don't need to do anything further. */ 8177169689Skan 8178169689Skan fnname = XSTR (fn, 0); 8179169689Skan for (l = mips16_stubs; l != NULL; l = l->next) 8180169689Skan if (strcmp (l->name, fnname) == 0) 8181169689Skan break; 8182169689Skan 8183169689Skan if (l == NULL) 8184169689Skan { 8185169689Skan /* Build a special purpose stub. When the linker sees a 8186169689Skan function call in mips16 code, it will check where the target 8187169689Skan is defined. If the target is a 32 bit call, the linker will 8188169689Skan search for the section defined here. It can tell which 8189169689Skan symbol this section is associated with by looking at the 8190169689Skan relocation information (the name is unreliable, since this 8191169689Skan might be a static function). If such a section is found, the 8192169689Skan linker will redirect the call to the start of the magic 8193169689Skan section. 8194169689Skan 8195169689Skan If the function does not return a floating point value, the 8196169689Skan special stub section is named 8197169689Skan .mips16.call.FNNAME 8198169689Skan 8199169689Skan If the function does return a floating point value, the stub 8200169689Skan section is named 8201169689Skan .mips16.call.fp.FNNAME 8202169689Skan */ 8203169689Skan 8204169689Skan secname = (char *) alloca (strlen (fnname) + 40); 8205169689Skan sprintf (secname, ".mips16.call.%s%s", 8206169689Skan fpret ? "fp." : "", 8207169689Skan fnname); 8208169689Skan stubname = (char *) alloca (strlen (fnname) + 20); 8209169689Skan sprintf (stubname, "__call_stub_%s%s", 8210169689Skan fpret ? "fp_" : "", 8211169689Skan fnname); 8212169689Skan stubid = get_identifier (stubname); 8213169689Skan stubdecl = build_decl (FUNCTION_DECL, stubid, 8214169689Skan build_function_type (void_type_node, NULL_TREE)); 8215169689Skan DECL_SECTION_NAME (stubdecl) = build_string (strlen (secname), secname); 8216169689Skan 8217169689Skan fprintf (asm_out_file, "\t# Stub function to call %s%s (", 8218169689Skan (fpret 8219169689Skan ? (GET_MODE (retval) == SFmode ? "float " : "double ") 8220169689Skan : ""), 8221169689Skan fnname); 8222169689Skan need_comma = 0; 8223169689Skan for (f = (unsigned int) fp_code; f != 0; f >>= 2) 8224169689Skan { 8225169689Skan fprintf (asm_out_file, "%s%s", 8226169689Skan need_comma ? ", " : "", 8227169689Skan (f & 3) == 1 ? "float" : "double"); 8228169689Skan need_comma = 1; 8229169689Skan } 8230169689Skan fprintf (asm_out_file, ")\n"); 8231169689Skan 8232169689Skan fprintf (asm_out_file, "\t.set\tnomips16\n"); 8233169689Skan assemble_start_function (stubdecl, stubname); 8234169689Skan 8235169689Skan if (!FUNCTION_NAME_ALREADY_DECLARED) 8236169689Skan { 8237169689Skan fputs ("\t.ent\t", asm_out_file); 8238169689Skan assemble_name (asm_out_file, stubname); 8239169689Skan fputs ("\n", asm_out_file); 8240169689Skan 8241169689Skan assemble_name (asm_out_file, stubname); 8242169689Skan fputs (":\n", asm_out_file); 8243169689Skan } 8244169689Skan 8245169689Skan /* We build the stub code by hand. That's the only way we can 8246169689Skan do it, since we can't generate 32 bit code during a 16 bit 8247169689Skan compilation. */ 8248169689Skan 8249169689Skan /* We don't want the assembler to insert any nops here. */ 8250169689Skan fprintf (asm_out_file, "\t.set\tnoreorder\n"); 8251169689Skan 8252169689Skan mips16_fp_args (asm_out_file, fp_code, 0); 8253169689Skan 8254169689Skan if (! fpret) 8255169689Skan { 8256169689Skan fprintf (asm_out_file, "\t.set\tnoat\n"); 8257169689Skan fprintf (asm_out_file, "\tla\t%s,%s\n", reg_names[GP_REG_FIRST + 1], 8258169689Skan fnname); 8259169689Skan fprintf (asm_out_file, "\tjr\t%s\n", reg_names[GP_REG_FIRST + 1]); 8260169689Skan fprintf (asm_out_file, "\t.set\tat\n"); 8261169689Skan /* Unfortunately, we can't fill the jump delay slot. We 8262169689Skan can't fill with one of the mtc1 instructions, because the 8263169689Skan result is not available for one instruction, so if the 8264169689Skan very first instruction in the function refers to the 8265169689Skan register, it will see the wrong value. */ 8266169689Skan fprintf (asm_out_file, "\tnop\n"); 8267169689Skan } 8268169689Skan else 8269169689Skan { 8270169689Skan fprintf (asm_out_file, "\tmove\t%s,%s\n", 8271169689Skan reg_names[GP_REG_FIRST + 18], reg_names[GP_REG_FIRST + 31]); 8272169689Skan fprintf (asm_out_file, "\tjal\t%s\n", fnname); 8273169689Skan /* As above, we can't fill the delay slot. */ 8274169689Skan fprintf (asm_out_file, "\tnop\n"); 8275169689Skan if (GET_MODE (retval) == SFmode) 8276169689Skan fprintf (asm_out_file, "\tmfc1\t%s,%s\n", 8277169689Skan reg_names[GP_REG_FIRST + 2], reg_names[FP_REG_FIRST + 0]); 8278169689Skan else 8279169689Skan { 8280169689Skan if (TARGET_BIG_ENDIAN) 8281169689Skan { 8282169689Skan fprintf (asm_out_file, "\tmfc1\t%s,%s\n", 8283169689Skan reg_names[GP_REG_FIRST + 2], 8284169689Skan reg_names[FP_REG_FIRST + 1]); 8285169689Skan fprintf (asm_out_file, "\tmfc1\t%s,%s\n", 8286169689Skan reg_names[GP_REG_FIRST + 3], 8287169689Skan reg_names[FP_REG_FIRST + 0]); 8288169689Skan } 8289169689Skan else 8290169689Skan { 8291169689Skan fprintf (asm_out_file, "\tmfc1\t%s,%s\n", 8292169689Skan reg_names[GP_REG_FIRST + 2], 8293169689Skan reg_names[FP_REG_FIRST + 0]); 8294169689Skan fprintf (asm_out_file, "\tmfc1\t%s,%s\n", 8295169689Skan reg_names[GP_REG_FIRST + 3], 8296169689Skan reg_names[FP_REG_FIRST + 1]); 8297169689Skan } 8298169689Skan } 8299169689Skan fprintf (asm_out_file, "\tj\t%s\n", reg_names[GP_REG_FIRST + 18]); 8300169689Skan /* As above, we can't fill the delay slot. */ 8301169689Skan fprintf (asm_out_file, "\tnop\n"); 8302169689Skan } 8303169689Skan 8304169689Skan fprintf (asm_out_file, "\t.set\treorder\n"); 8305169689Skan 8306169689Skan#ifdef ASM_DECLARE_FUNCTION_SIZE 8307169689Skan ASM_DECLARE_FUNCTION_SIZE (asm_out_file, stubname, stubdecl); 8308169689Skan#endif 8309169689Skan 8310169689Skan if (!FUNCTION_NAME_ALREADY_DECLARED) 8311169689Skan { 8312169689Skan fputs ("\t.end\t", asm_out_file); 8313169689Skan assemble_name (asm_out_file, stubname); 8314169689Skan fputs ("\n", asm_out_file); 8315169689Skan } 8316169689Skan 8317169689Skan fprintf (asm_out_file, "\t.set\tmips16\n"); 8318169689Skan 8319169689Skan /* Record this stub. */ 8320169689Skan l = (struct mips16_stub *) xmalloc (sizeof *l); 8321169689Skan l->name = xstrdup (fnname); 8322169689Skan l->fpret = fpret; 8323169689Skan l->next = mips16_stubs; 8324169689Skan mips16_stubs = l; 8325169689Skan } 8326169689Skan 8327169689Skan /* If we expect a floating point return value, but we've built a 8328169689Skan stub which does not expect one, then we're in trouble. We can't 8329169689Skan use the existing stub, because it won't handle the floating point 8330169689Skan value. We can't build a new stub, because the linker won't know 8331169689Skan which stub to use for the various calls in this object file. 8332169689Skan Fortunately, this case is illegal, since it means that a function 8333169689Skan was declared in two different ways in a single compilation. */ 8334169689Skan if (fpret && ! l->fpret) 8335169689Skan error ("cannot handle inconsistent calls to %qs", fnname); 8336169689Skan 8337169689Skan /* If we are calling a stub which handles a floating point return 8338169689Skan value, we need to arrange to save $18 in the prologue. We do 8339169689Skan this by marking the function call as using the register. The 8340169689Skan prologue will later see that it is used, and emit code to save 8341169689Skan it. */ 8342169689Skan 8343169689Skan if (l->fpret) 8344169689Skan { 8345169689Skan rtx insn; 8346169689Skan 8347169689Skan if (retval == NULL_RTX) 8348169689Skan insn = gen_call_internal (fn, arg_size); 8349169689Skan else 8350169689Skan insn = gen_call_value_internal (retval, fn, arg_size); 8351169689Skan insn = emit_call_insn (insn); 8352169689Skan 8353169689Skan CALL_INSN_FUNCTION_USAGE (insn) = 8354169689Skan gen_rtx_EXPR_LIST (VOIDmode, 8355169689Skan gen_rtx_USE (VOIDmode, gen_rtx_REG (word_mode, 18)), 8356169689Skan CALL_INSN_FUNCTION_USAGE (insn)); 8357169689Skan 8358169689Skan /* Return 1 to tell the caller that we've generated the call 8359169689Skan insn. */ 8360169689Skan return 1; 8361169689Skan } 8362169689Skan 8363169689Skan /* Return 0 to let the caller generate the call insn. */ 8364169689Skan return 0; 8365169689Skan} 8366169689Skan 8367169689Skan/* An entry in the mips16 constant pool. VALUE is the pool constant, 8368169689Skan MODE is its mode, and LABEL is the CODE_LABEL associated with it. */ 8369169689Skan 8370169689Skanstruct mips16_constant { 8371169689Skan struct mips16_constant *next; 8372169689Skan rtx value; 8373169689Skan rtx label; 8374169689Skan enum machine_mode mode; 8375169689Skan}; 8376169689Skan 8377169689Skan/* Information about an incomplete mips16 constant pool. FIRST is the 8378169689Skan first constant, HIGHEST_ADDRESS is the highest address that the first 8379169689Skan byte of the pool can have, and INSN_ADDRESS is the current instruction 8380169689Skan address. */ 8381169689Skan 8382169689Skanstruct mips16_constant_pool { 8383169689Skan struct mips16_constant *first; 8384169689Skan int highest_address; 8385169689Skan int insn_address; 8386169689Skan}; 8387169689Skan 8388169689Skan/* Add constant VALUE to POOL and return its label. MODE is the 8389169689Skan value's mode (used for CONST_INTs, etc.). */ 8390169689Skan 8391169689Skanstatic rtx 8392169689Skanadd_constant (struct mips16_constant_pool *pool, 8393169689Skan rtx value, enum machine_mode mode) 8394169689Skan{ 8395169689Skan struct mips16_constant **p, *c; 8396169689Skan bool first_of_size_p; 8397169689Skan 8398169689Skan /* See whether the constant is already in the pool. If so, return the 8399169689Skan existing label, otherwise leave P pointing to the place where the 8400169689Skan constant should be added. 8401169689Skan 8402169689Skan Keep the pool sorted in increasing order of mode size so that we can 8403169689Skan reduce the number of alignments needed. */ 8404169689Skan first_of_size_p = true; 8405169689Skan for (p = &pool->first; *p != 0; p = &(*p)->next) 8406169689Skan { 8407169689Skan if (mode == (*p)->mode && rtx_equal_p (value, (*p)->value)) 8408169689Skan return (*p)->label; 8409169689Skan if (GET_MODE_SIZE (mode) < GET_MODE_SIZE ((*p)->mode)) 8410169689Skan break; 8411169689Skan if (GET_MODE_SIZE (mode) == GET_MODE_SIZE ((*p)->mode)) 8412169689Skan first_of_size_p = false; 8413169689Skan } 8414169689Skan 8415169689Skan /* In the worst case, the constant needed by the earliest instruction 8416169689Skan will end up at the end of the pool. The entire pool must then be 8417169689Skan accessible from that instruction. 8418169689Skan 8419169689Skan When adding the first constant, set the pool's highest address to 8420169689Skan the address of the first out-of-range byte. Adjust this address 8421169689Skan downwards each time a new constant is added. */ 8422169689Skan if (pool->first == 0) 8423169689Skan /* For pc-relative lw, addiu and daddiu instructions, the base PC value 8424169689Skan is the address of the instruction with the lowest two bits clear. 8425169689Skan The base PC value for ld has the lowest three bits clear. Assume 8426169689Skan the worst case here. */ 8427169689Skan pool->highest_address = pool->insn_address - (UNITS_PER_WORD - 2) + 0x8000; 8428169689Skan pool->highest_address -= GET_MODE_SIZE (mode); 8429169689Skan if (first_of_size_p) 8430169689Skan /* Take into account the worst possible padding due to alignment. */ 8431169689Skan pool->highest_address -= GET_MODE_SIZE (mode) - 1; 8432169689Skan 8433169689Skan /* Create a new entry. */ 8434169689Skan c = (struct mips16_constant *) xmalloc (sizeof *c); 8435169689Skan c->value = value; 8436169689Skan c->mode = mode; 8437169689Skan c->label = gen_label_rtx (); 8438169689Skan c->next = *p; 8439169689Skan *p = c; 8440169689Skan 8441169689Skan return c->label; 8442169689Skan} 8443169689Skan 8444169689Skan/* Output constant VALUE after instruction INSN and return the last 8445169689Skan instruction emitted. MODE is the mode of the constant. */ 8446169689Skan 8447169689Skanstatic rtx 8448169689Skandump_constants_1 (enum machine_mode mode, rtx value, rtx insn) 8449169689Skan{ 8450169689Skan switch (GET_MODE_CLASS (mode)) 8451169689Skan { 8452169689Skan case MODE_INT: 8453169689Skan { 8454169689Skan rtx size = GEN_INT (GET_MODE_SIZE (mode)); 8455169689Skan return emit_insn_after (gen_consttable_int (value, size), insn); 8456169689Skan } 8457169689Skan 8458169689Skan case MODE_FLOAT: 8459169689Skan return emit_insn_after (gen_consttable_float (value), insn); 8460169689Skan 8461169689Skan case MODE_VECTOR_FLOAT: 8462169689Skan case MODE_VECTOR_INT: 8463169689Skan { 8464169689Skan int i; 8465169689Skan for (i = 0; i < CONST_VECTOR_NUNITS (value); i++) 8466169689Skan insn = dump_constants_1 (GET_MODE_INNER (mode), 8467169689Skan CONST_VECTOR_ELT (value, i), insn); 8468169689Skan return insn; 8469169689Skan } 8470169689Skan 8471169689Skan default: 8472169689Skan gcc_unreachable (); 8473169689Skan } 8474169689Skan} 8475169689Skan 8476169689Skan 8477169689Skan/* Dump out the constants in CONSTANTS after INSN. */ 8478169689Skan 8479169689Skanstatic void 8480169689Skandump_constants (struct mips16_constant *constants, rtx insn) 8481169689Skan{ 8482169689Skan struct mips16_constant *c, *next; 8483169689Skan int align; 8484169689Skan 8485169689Skan align = 0; 8486169689Skan for (c = constants; c != NULL; c = next) 8487169689Skan { 8488169689Skan /* If necessary, increase the alignment of PC. */ 8489169689Skan if (align < GET_MODE_SIZE (c->mode)) 8490169689Skan { 8491169689Skan int align_log = floor_log2 (GET_MODE_SIZE (c->mode)); 8492169689Skan insn = emit_insn_after (gen_align (GEN_INT (align_log)), insn); 8493169689Skan } 8494169689Skan align = GET_MODE_SIZE (c->mode); 8495169689Skan 8496169689Skan insn = emit_label_after (c->label, insn); 8497169689Skan insn = dump_constants_1 (c->mode, c->value, insn); 8498169689Skan 8499169689Skan next = c->next; 8500169689Skan free (c); 8501169689Skan } 8502169689Skan 8503169689Skan emit_barrier_after (insn); 8504169689Skan} 8505169689Skan 8506169689Skan/* Return the length of instruction INSN. */ 8507169689Skan 8508169689Skanstatic int 8509169689Skanmips16_insn_length (rtx insn) 8510169689Skan{ 8511169689Skan if (JUMP_P (insn)) 8512169689Skan { 8513169689Skan rtx body = PATTERN (insn); 8514169689Skan if (GET_CODE (body) == ADDR_VEC) 8515169689Skan return GET_MODE_SIZE (GET_MODE (body)) * XVECLEN (body, 0); 8516169689Skan if (GET_CODE (body) == ADDR_DIFF_VEC) 8517169689Skan return GET_MODE_SIZE (GET_MODE (body)) * XVECLEN (body, 1); 8518169689Skan } 8519169689Skan return get_attr_length (insn); 8520169689Skan} 8521169689Skan 8522169689Skan/* Rewrite *X so that constant pool references refer to the constant's 8523169689Skan label instead. DATA points to the constant pool structure. */ 8524169689Skan 8525169689Skanstatic int 8526169689Skanmips16_rewrite_pool_refs (rtx *x, void *data) 8527169689Skan{ 8528169689Skan struct mips16_constant_pool *pool = data; 8529169689Skan if (GET_CODE (*x) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (*x)) 8530169689Skan *x = gen_rtx_LABEL_REF (Pmode, add_constant (pool, 8531169689Skan get_pool_constant (*x), 8532169689Skan get_pool_mode (*x))); 8533169689Skan return 0; 8534169689Skan} 8535169689Skan 8536169689Skan/* Build MIPS16 constant pools. */ 8537169689Skan 8538169689Skanstatic void 8539169689Skanmips16_lay_out_constants (void) 8540169689Skan{ 8541169689Skan struct mips16_constant_pool pool; 8542169689Skan rtx insn, barrier; 8543169689Skan 8544169689Skan barrier = 0; 8545169689Skan memset (&pool, 0, sizeof (pool)); 8546169689Skan for (insn = get_insns (); insn; insn = NEXT_INSN (insn)) 8547169689Skan { 8548169689Skan /* Rewrite constant pool references in INSN. */ 8549169689Skan if (INSN_P (insn)) 8550169689Skan for_each_rtx (&PATTERN (insn), mips16_rewrite_pool_refs, &pool); 8551169689Skan 8552169689Skan pool.insn_address += mips16_insn_length (insn); 8553169689Skan 8554169689Skan if (pool.first != NULL) 8555169689Skan { 8556169689Skan /* If there are no natural barriers between the first user of 8557169689Skan the pool and the highest acceptable address, we'll need to 8558169689Skan create a new instruction to jump around the constant pool. 8559169689Skan In the worst case, this instruction will be 4 bytes long. 8560169689Skan 8561169689Skan If it's too late to do this transformation after INSN, 8562169689Skan do it immediately before INSN. */ 8563169689Skan if (barrier == 0 && pool.insn_address + 4 > pool.highest_address) 8564169689Skan { 8565169689Skan rtx label, jump; 8566169689Skan 8567169689Skan label = gen_label_rtx (); 8568169689Skan 8569169689Skan jump = emit_jump_insn_before (gen_jump (label), insn); 8570169689Skan JUMP_LABEL (jump) = label; 8571169689Skan LABEL_NUSES (label) = 1; 8572169689Skan barrier = emit_barrier_after (jump); 8573169689Skan 8574169689Skan emit_label_after (label, barrier); 8575169689Skan pool.insn_address += 4; 8576169689Skan } 8577169689Skan 8578169689Skan /* See whether the constant pool is now out of range of the first 8579169689Skan user. If so, output the constants after the previous barrier. 8580169689Skan Note that any instructions between BARRIER and INSN (inclusive) 8581169689Skan will use negative offsets to refer to the pool. */ 8582169689Skan if (pool.insn_address > pool.highest_address) 8583169689Skan { 8584169689Skan dump_constants (pool.first, barrier); 8585169689Skan pool.first = NULL; 8586169689Skan barrier = 0; 8587169689Skan } 8588169689Skan else if (BARRIER_P (insn)) 8589169689Skan barrier = insn; 8590169689Skan } 8591169689Skan } 8592169689Skan dump_constants (pool.first, get_last_insn ()); 8593169689Skan} 8594169689Skan 8595169689Skan/* A temporary variable used by for_each_rtx callbacks, etc. */ 8596169689Skanstatic rtx mips_sim_insn; 8597169689Skan 8598169689Skan/* A structure representing the state of the processor pipeline. 8599169689Skan Used by the mips_sim_* family of functions. */ 8600169689Skanstruct mips_sim { 8601169689Skan /* The maximum number of instructions that can be issued in a cycle. 8602169689Skan (Caches mips_issue_rate.) */ 8603169689Skan unsigned int issue_rate; 8604169689Skan 8605169689Skan /* The current simulation time. */ 8606169689Skan unsigned int time; 8607169689Skan 8608169689Skan /* How many more instructions can be issued in the current cycle. */ 8609169689Skan unsigned int insns_left; 8610169689Skan 8611169689Skan /* LAST_SET[X].INSN is the last instruction to set register X. 8612169689Skan LAST_SET[X].TIME is the time at which that instruction was issued. 8613169689Skan INSN is null if no instruction has yet set register X. */ 8614169689Skan struct { 8615169689Skan rtx insn; 8616169689Skan unsigned int time; 8617169689Skan } last_set[FIRST_PSEUDO_REGISTER]; 8618169689Skan 8619169689Skan /* The pipeline's current DFA state. */ 8620169689Skan state_t dfa_state; 8621169689Skan}; 8622169689Skan 8623169689Skan/* Reset STATE to the initial simulation state. */ 8624169689Skan 8625169689Skanstatic void 8626169689Skanmips_sim_reset (struct mips_sim *state) 8627169689Skan{ 8628169689Skan state->time = 0; 8629169689Skan state->insns_left = state->issue_rate; 8630169689Skan memset (&state->last_set, 0, sizeof (state->last_set)); 8631169689Skan state_reset (state->dfa_state); 8632169689Skan} 8633169689Skan 8634169689Skan/* Initialize STATE before its first use. DFA_STATE points to an 8635169689Skan allocated but uninitialized DFA state. */ 8636169689Skan 8637169689Skanstatic void 8638169689Skanmips_sim_init (struct mips_sim *state, state_t dfa_state) 8639169689Skan{ 8640169689Skan state->issue_rate = mips_issue_rate (); 8641169689Skan state->dfa_state = dfa_state; 8642169689Skan mips_sim_reset (state); 8643169689Skan} 8644169689Skan 8645169689Skan/* Advance STATE by one clock cycle. */ 8646169689Skan 8647169689Skanstatic void 8648169689Skanmips_sim_next_cycle (struct mips_sim *state) 8649169689Skan{ 8650169689Skan state->time++; 8651169689Skan state->insns_left = state->issue_rate; 8652169689Skan state_transition (state->dfa_state, 0); 8653169689Skan} 8654169689Skan 8655169689Skan/* Advance simulation state STATE until instruction INSN can read 8656169689Skan register REG. */ 8657169689Skan 8658169689Skanstatic void 8659169689Skanmips_sim_wait_reg (struct mips_sim *state, rtx insn, rtx reg) 8660169689Skan{ 8661169689Skan unsigned int i; 8662169689Skan 8663169689Skan for (i = 0; i < HARD_REGNO_NREGS (REGNO (reg), GET_MODE (reg)); i++) 8664169689Skan if (state->last_set[REGNO (reg) + i].insn != 0) 8665169689Skan { 8666169689Skan unsigned int t; 8667169689Skan 8668169689Skan t = state->last_set[REGNO (reg) + i].time; 8669169689Skan t += insn_latency (state->last_set[REGNO (reg) + i].insn, insn); 8670169689Skan while (state->time < t) 8671169689Skan mips_sim_next_cycle (state); 8672169689Skan } 8673169689Skan} 8674169689Skan 8675169689Skan/* A for_each_rtx callback. If *X is a register, advance simulation state 8676169689Skan DATA until mips_sim_insn can read the register's value. */ 8677169689Skan 8678169689Skanstatic int 8679169689Skanmips_sim_wait_regs_2 (rtx *x, void *data) 8680169689Skan{ 8681169689Skan if (REG_P (*x)) 8682169689Skan mips_sim_wait_reg (data, mips_sim_insn, *x); 8683169689Skan return 0; 8684169689Skan} 8685169689Skan 8686169689Skan/* Call mips_sim_wait_regs_2 (R, DATA) for each register R mentioned in *X. */ 8687169689Skan 8688169689Skanstatic void 8689169689Skanmips_sim_wait_regs_1 (rtx *x, void *data) 8690169689Skan{ 8691169689Skan for_each_rtx (x, mips_sim_wait_regs_2, data); 8692169689Skan} 8693169689Skan 8694169689Skan/* Advance simulation state STATE until all of INSN's register 8695169689Skan dependencies are satisfied. */ 8696169689Skan 8697169689Skanstatic void 8698169689Skanmips_sim_wait_regs (struct mips_sim *state, rtx insn) 8699169689Skan{ 8700169689Skan mips_sim_insn = insn; 8701169689Skan note_uses (&PATTERN (insn), mips_sim_wait_regs_1, state); 8702169689Skan} 8703169689Skan 8704169689Skan/* Advance simulation state STATE until the units required by 8705169689Skan instruction INSN are available. */ 8706169689Skan 8707169689Skanstatic void 8708169689Skanmips_sim_wait_units (struct mips_sim *state, rtx insn) 8709169689Skan{ 8710169689Skan state_t tmp_state; 8711169689Skan 8712169689Skan tmp_state = alloca (state_size ()); 8713169689Skan while (state->insns_left == 0 8714169689Skan || (memcpy (tmp_state, state->dfa_state, state_size ()), 8715169689Skan state_transition (tmp_state, insn) >= 0)) 8716169689Skan mips_sim_next_cycle (state); 8717169689Skan} 8718169689Skan 8719169689Skan/* Advance simulation state STATE until INSN is ready to issue. */ 8720169689Skan 8721169689Skanstatic void 8722169689Skanmips_sim_wait_insn (struct mips_sim *state, rtx insn) 8723169689Skan{ 8724169689Skan mips_sim_wait_regs (state, insn); 8725169689Skan mips_sim_wait_units (state, insn); 8726169689Skan} 8727169689Skan 8728169689Skan/* mips_sim_insn has just set X. Update the LAST_SET array 8729169689Skan in simulation state DATA. */ 8730169689Skan 8731169689Skanstatic void 8732169689Skanmips_sim_record_set (rtx x, rtx pat ATTRIBUTE_UNUSED, void *data) 8733169689Skan{ 8734169689Skan struct mips_sim *state; 8735169689Skan unsigned int i; 8736169689Skan 8737169689Skan state = data; 8738169689Skan if (REG_P (x)) 8739169689Skan for (i = 0; i < HARD_REGNO_NREGS (REGNO (x), GET_MODE (x)); i++) 8740169689Skan { 8741169689Skan state->last_set[REGNO (x) + i].insn = mips_sim_insn; 8742169689Skan state->last_set[REGNO (x) + i].time = state->time; 8743169689Skan } 8744169689Skan} 8745169689Skan 8746169689Skan/* Issue instruction INSN in scheduler state STATE. Assume that INSN 8747169689Skan can issue immediately (i.e., that mips_sim_wait_insn has already 8748169689Skan been called). */ 8749169689Skan 8750169689Skanstatic void 8751169689Skanmips_sim_issue_insn (struct mips_sim *state, rtx insn) 8752169689Skan{ 8753169689Skan state_transition (state->dfa_state, insn); 8754169689Skan state->insns_left--; 8755169689Skan 8756169689Skan mips_sim_insn = insn; 8757169689Skan note_stores (PATTERN (insn), mips_sim_record_set, state); 8758169689Skan} 8759169689Skan 8760169689Skan/* Simulate issuing a NOP in state STATE. */ 8761169689Skan 8762169689Skanstatic void 8763169689Skanmips_sim_issue_nop (struct mips_sim *state) 8764169689Skan{ 8765169689Skan if (state->insns_left == 0) 8766169689Skan mips_sim_next_cycle (state); 8767169689Skan state->insns_left--; 8768169689Skan} 8769169689Skan 8770169689Skan/* Update simulation state STATE so that it's ready to accept the instruction 8771169689Skan after INSN. INSN should be part of the main rtl chain, not a member of a 8772169689Skan SEQUENCE. */ 8773169689Skan 8774169689Skanstatic void 8775169689Skanmips_sim_finish_insn (struct mips_sim *state, rtx insn) 8776169689Skan{ 8777169689Skan /* If INSN is a jump with an implicit delay slot, simulate a nop. */ 8778169689Skan if (JUMP_P (insn)) 8779169689Skan mips_sim_issue_nop (state); 8780169689Skan 8781169689Skan switch (GET_CODE (SEQ_BEGIN (insn))) 8782169689Skan { 8783169689Skan case CODE_LABEL: 8784169689Skan case CALL_INSN: 8785169689Skan /* We can't predict the processor state after a call or label. */ 8786169689Skan mips_sim_reset (state); 8787169689Skan break; 8788169689Skan 8789169689Skan case JUMP_INSN: 8790169689Skan /* The delay slots of branch likely instructions are only executed 8791169689Skan when the branch is taken. Therefore, if the caller has simulated 8792169689Skan the delay slot instruction, STATE does not really reflect the state 8793169689Skan of the pipeline for the instruction after the delay slot. Also, 8794169689Skan branch likely instructions tend to incur a penalty when not taken, 8795169689Skan so there will probably be an extra delay between the branch and 8796169689Skan the instruction after the delay slot. */ 8797169689Skan if (INSN_ANNULLED_BRANCH_P (SEQ_BEGIN (insn))) 8798169689Skan mips_sim_reset (state); 8799169689Skan break; 8800169689Skan 8801169689Skan default: 8802169689Skan break; 8803169689Skan } 8804169689Skan} 8805169689Skan 8806169689Skan/* The VR4130 pipeline issues aligned pairs of instructions together, 8807169689Skan but it stalls the second instruction if it depends on the first. 8808169689Skan In order to cut down the amount of logic required, this dependence 8809169689Skan check is not based on a full instruction decode. Instead, any non-SPECIAL 8810169689Skan instruction is assumed to modify the register specified by bits 20-16 8811169689Skan (which is usually the "rt" field). 8812169689Skan 8813169689Skan In beq, beql, bne and bnel instructions, the rt field is actually an 8814169689Skan input, so we can end up with a false dependence between the branch 8815169689Skan and its delay slot. If this situation occurs in instruction INSN, 8816169689Skan try to avoid it by swapping rs and rt. */ 8817169689Skan 8818169689Skanstatic void 8819169689Skanvr4130_avoid_branch_rt_conflict (rtx insn) 8820169689Skan{ 8821169689Skan rtx first, second; 8822169689Skan 8823169689Skan first = SEQ_BEGIN (insn); 8824169689Skan second = SEQ_END (insn); 8825169689Skan if (JUMP_P (first) 8826169689Skan && NONJUMP_INSN_P (second) 8827169689Skan && GET_CODE (PATTERN (first)) == SET 8828169689Skan && GET_CODE (SET_DEST (PATTERN (first))) == PC 8829169689Skan && GET_CODE (SET_SRC (PATTERN (first))) == IF_THEN_ELSE) 8830169689Skan { 8831169689Skan /* Check for the right kind of condition. */ 8832169689Skan rtx cond = XEXP (SET_SRC (PATTERN (first)), 0); 8833169689Skan if ((GET_CODE (cond) == EQ || GET_CODE (cond) == NE) 8834169689Skan && REG_P (XEXP (cond, 0)) 8835169689Skan && REG_P (XEXP (cond, 1)) 8836169689Skan && reg_referenced_p (XEXP (cond, 1), PATTERN (second)) 8837169689Skan && !reg_referenced_p (XEXP (cond, 0), PATTERN (second))) 8838169689Skan { 8839169689Skan /* SECOND mentions the rt register but not the rs register. */ 8840169689Skan rtx tmp = XEXP (cond, 0); 8841169689Skan XEXP (cond, 0) = XEXP (cond, 1); 8842169689Skan XEXP (cond, 1) = tmp; 8843169689Skan } 8844169689Skan } 8845169689Skan} 8846169689Skan 8847169689Skan/* Implement -mvr4130-align. Go through each basic block and simulate the 8848169689Skan processor pipeline. If we find that a pair of instructions could execute 8849169689Skan in parallel, and the first of those instruction is not 8-byte aligned, 8850169689Skan insert a nop to make it aligned. */ 8851169689Skan 8852169689Skanstatic void 8853169689Skanvr4130_align_insns (void) 8854169689Skan{ 8855169689Skan struct mips_sim state; 8856169689Skan rtx insn, subinsn, last, last2, next; 8857169689Skan bool aligned_p; 8858169689Skan 8859169689Skan dfa_start (); 8860169689Skan 8861169689Skan /* LAST is the last instruction before INSN to have a nonzero length. 8862169689Skan LAST2 is the last such instruction before LAST. */ 8863169689Skan last = 0; 8864169689Skan last2 = 0; 8865169689Skan 8866169689Skan /* ALIGNED_P is true if INSN is known to be at an aligned address. */ 8867169689Skan aligned_p = true; 8868169689Skan 8869169689Skan mips_sim_init (&state, alloca (state_size ())); 8870169689Skan for (insn = get_insns (); insn != 0; insn = next) 8871169689Skan { 8872169689Skan unsigned int length; 8873169689Skan 8874169689Skan next = NEXT_INSN (insn); 8875169689Skan 8876169689Skan /* See the comment above vr4130_avoid_branch_rt_conflict for details. 8877169689Skan This isn't really related to the alignment pass, but we do it on 8878169689Skan the fly to avoid a separate instruction walk. */ 8879169689Skan vr4130_avoid_branch_rt_conflict (insn); 8880169689Skan 8881169689Skan if (USEFUL_INSN_P (insn)) 8882169689Skan FOR_EACH_SUBINSN (subinsn, insn) 8883169689Skan { 8884169689Skan mips_sim_wait_insn (&state, subinsn); 8885169689Skan 8886169689Skan /* If we want this instruction to issue in parallel with the 8887169689Skan previous one, make sure that the previous instruction is 8888169689Skan aligned. There are several reasons why this isn't worthwhile 8889169689Skan when the second instruction is a call: 8890169689Skan 8891169689Skan - Calls are less likely to be performance critical, 8892169689Skan - There's a good chance that the delay slot can execute 8893169689Skan in parallel with the call. 8894169689Skan - The return address would then be unaligned. 8895169689Skan 8896169689Skan In general, if we're going to insert a nop between instructions 8897169689Skan X and Y, it's better to insert it immediately after X. That 8898169689Skan way, if the nop makes Y aligned, it will also align any labels 8899169689Skan between X and Y. */ 8900169689Skan if (state.insns_left != state.issue_rate 8901169689Skan && !CALL_P (subinsn)) 8902169689Skan { 8903169689Skan if (subinsn == SEQ_BEGIN (insn) && aligned_p) 8904169689Skan { 8905169689Skan /* SUBINSN is the first instruction in INSN and INSN is 8906169689Skan aligned. We want to align the previous instruction 8907169689Skan instead, so insert a nop between LAST2 and LAST. 8908169689Skan 8909169689Skan Note that LAST could be either a single instruction 8910169689Skan or a branch with a delay slot. In the latter case, 8911169689Skan LAST, like INSN, is already aligned, but the delay 8912169689Skan slot must have some extra delay that stops it from 8913169689Skan issuing at the same time as the branch. We therefore 8914169689Skan insert a nop before the branch in order to align its 8915169689Skan delay slot. */ 8916169689Skan emit_insn_after (gen_nop (), last2); 8917169689Skan aligned_p = false; 8918169689Skan } 8919169689Skan else if (subinsn != SEQ_BEGIN (insn) && !aligned_p) 8920169689Skan { 8921169689Skan /* SUBINSN is the delay slot of INSN, but INSN is 8922169689Skan currently unaligned. Insert a nop between 8923169689Skan LAST and INSN to align it. */ 8924169689Skan emit_insn_after (gen_nop (), last); 8925169689Skan aligned_p = true; 8926169689Skan } 8927169689Skan } 8928169689Skan mips_sim_issue_insn (&state, subinsn); 8929169689Skan } 8930169689Skan mips_sim_finish_insn (&state, insn); 8931169689Skan 8932169689Skan /* Update LAST, LAST2 and ALIGNED_P for the next instruction. */ 8933169689Skan length = get_attr_length (insn); 8934169689Skan if (length > 0) 8935169689Skan { 8936169689Skan /* If the instruction is an asm statement or multi-instruction 8937169689Skan mips.md patern, the length is only an estimate. Insert an 8938169689Skan 8 byte alignment after it so that the following instructions 8939169689Skan can be handled correctly. */ 8940169689Skan if (NONJUMP_INSN_P (SEQ_BEGIN (insn)) 8941169689Skan && (recog_memoized (insn) < 0 || length >= 8)) 8942169689Skan { 8943169689Skan next = emit_insn_after (gen_align (GEN_INT (3)), insn); 8944169689Skan next = NEXT_INSN (next); 8945169689Skan mips_sim_next_cycle (&state); 8946169689Skan aligned_p = true; 8947169689Skan } 8948169689Skan else if (length & 4) 8949169689Skan aligned_p = !aligned_p; 8950169689Skan last2 = last; 8951169689Skan last = insn; 8952169689Skan } 8953169689Skan 8954169689Skan /* See whether INSN is an aligned label. */ 8955169689Skan if (LABEL_P (insn) && label_to_alignment (insn) >= 3) 8956169689Skan aligned_p = true; 8957169689Skan } 8958169689Skan dfa_finish (); 8959169689Skan} 8960169689Skan 8961169689Skan/* Subroutine of mips_reorg. If there is a hazard between INSN 8962169689Skan and a previous instruction, avoid it by inserting nops after 8963169689Skan instruction AFTER. 8964169689Skan 8965169689Skan *DELAYED_REG and *HILO_DELAY describe the hazards that apply at 8966169689Skan this point. If *DELAYED_REG is non-null, INSN must wait a cycle 8967169689Skan before using the value of that register. *HILO_DELAY counts the 8968169689Skan number of instructions since the last hilo hazard (that is, 8969169689Skan the number of instructions since the last mflo or mfhi). 8970169689Skan 8971169689Skan After inserting nops for INSN, update *DELAYED_REG and *HILO_DELAY 8972169689Skan for the next instruction. 8973169689Skan 8974169689Skan LO_REG is an rtx for the LO register, used in dependence checking. */ 8975169689Skan 8976169689Skanstatic void 8977169689Skanmips_avoid_hazard (rtx after, rtx insn, int *hilo_delay, 8978169689Skan rtx *delayed_reg, rtx lo_reg) 8979169689Skan{ 8980169689Skan rtx pattern, set; 8981169689Skan int nops, ninsns; 8982169689Skan 8983169689Skan if (!INSN_P (insn)) 8984169689Skan return; 8985169689Skan 8986169689Skan pattern = PATTERN (insn); 8987169689Skan 8988169689Skan /* Do not put the whole function in .set noreorder if it contains 8989169689Skan an asm statement. We don't know whether there will be hazards 8990169689Skan between the asm statement and the gcc-generated code. */ 8991169689Skan if (GET_CODE (pattern) == ASM_INPUT || asm_noperands (pattern) >= 0) 8992169689Skan cfun->machine->all_noreorder_p = false; 8993169689Skan 8994169689Skan /* Ignore zero-length instructions (barriers and the like). */ 8995169689Skan ninsns = get_attr_length (insn) / 4; 8996169689Skan if (ninsns == 0) 8997169689Skan return; 8998169689Skan 8999169689Skan /* Work out how many nops are needed. Note that we only care about 9000169689Skan registers that are explicitly mentioned in the instruction's pattern. 9001169689Skan It doesn't matter that calls use the argument registers or that they 9002169689Skan clobber hi and lo. */ 9003169689Skan if (*hilo_delay < 2 && reg_set_p (lo_reg, pattern)) 9004169689Skan nops = 2 - *hilo_delay; 9005169689Skan else if (*delayed_reg != 0 && reg_referenced_p (*delayed_reg, pattern)) 9006169689Skan nops = 1; 9007169689Skan else 9008169689Skan nops = 0; 9009169689Skan 9010169689Skan /* Insert the nops between this instruction and the previous one. 9011169689Skan Each new nop takes us further from the last hilo hazard. */ 9012169689Skan *hilo_delay += nops; 9013169689Skan while (nops-- > 0) 9014169689Skan emit_insn_after (gen_hazard_nop (), after); 9015169689Skan 9016169689Skan /* Set up the state for the next instruction. */ 9017169689Skan *hilo_delay += ninsns; 9018169689Skan *delayed_reg = 0; 9019169689Skan if (INSN_CODE (insn) >= 0) 9020169689Skan switch (get_attr_hazard (insn)) 9021169689Skan { 9022169689Skan case HAZARD_NONE: 9023169689Skan break; 9024169689Skan 9025169689Skan case HAZARD_HILO: 9026169689Skan *hilo_delay = 0; 9027169689Skan break; 9028169689Skan 9029169689Skan case HAZARD_DELAY: 9030169689Skan set = single_set (insn); 9031169689Skan gcc_assert (set != 0); 9032169689Skan *delayed_reg = SET_DEST (set); 9033169689Skan break; 9034169689Skan } 9035169689Skan} 9036169689Skan 9037169689Skan 9038169689Skan/* Go through the instruction stream and insert nops where necessary. 9039169689Skan See if the whole function can then be put into .set noreorder & 9040169689Skan .set nomacro. */ 9041169689Skan 9042169689Skanstatic void 9043169689Skanmips_avoid_hazards (void) 9044169689Skan{ 9045169689Skan rtx insn, last_insn, lo_reg, delayed_reg; 9046169689Skan int hilo_delay, i; 9047169689Skan 9048169689Skan /* Force all instructions to be split into their final form. */ 9049169689Skan split_all_insns_noflow (); 9050169689Skan 9051169689Skan /* Recalculate instruction lengths without taking nops into account. */ 9052169689Skan cfun->machine->ignore_hazard_length_p = true; 9053169689Skan shorten_branches (get_insns ()); 9054169689Skan 9055169689Skan cfun->machine->all_noreorder_p = true; 9056169689Skan 9057169689Skan /* Profiled functions can't be all noreorder because the profiler 9058169689Skan support uses assembler macros. */ 9059169689Skan if (current_function_profile) 9060169689Skan cfun->machine->all_noreorder_p = false; 9061169689Skan 9062169689Skan /* Code compiled with -mfix-vr4120 can't be all noreorder because 9063169689Skan we rely on the assembler to work around some errata. */ 9064169689Skan if (TARGET_FIX_VR4120) 9065169689Skan cfun->machine->all_noreorder_p = false; 9066169689Skan 9067169689Skan /* The same is true for -mfix-vr4130 if we might generate mflo or 9068169689Skan mfhi instructions. Note that we avoid using mflo and mfhi if 9069169689Skan the VR4130 macc and dmacc instructions are available instead; 9070169689Skan see the *mfhilo_{si,di}_macc patterns. */ 9071169689Skan if (TARGET_FIX_VR4130 && !ISA_HAS_MACCHI) 9072169689Skan cfun->machine->all_noreorder_p = false; 9073169689Skan 9074169689Skan last_insn = 0; 9075169689Skan hilo_delay = 2; 9076169689Skan delayed_reg = 0; 9077169689Skan lo_reg = gen_rtx_REG (SImode, LO_REGNUM); 9078169689Skan 9079169689Skan for (insn = get_insns (); insn != 0; insn = NEXT_INSN (insn)) 9080169689Skan if (INSN_P (insn)) 9081169689Skan { 9082169689Skan if (GET_CODE (PATTERN (insn)) == SEQUENCE) 9083169689Skan for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++) 9084169689Skan mips_avoid_hazard (last_insn, XVECEXP (PATTERN (insn), 0, i), 9085169689Skan &hilo_delay, &delayed_reg, lo_reg); 9086169689Skan else 9087169689Skan mips_avoid_hazard (last_insn, insn, &hilo_delay, 9088169689Skan &delayed_reg, lo_reg); 9089169689Skan 9090169689Skan last_insn = insn; 9091169689Skan } 9092169689Skan} 9093169689Skan 9094169689Skan 9095169689Skan/* Implement TARGET_MACHINE_DEPENDENT_REORG. */ 9096169689Skan 9097169689Skanstatic void 9098169689Skanmips_reorg (void) 9099169689Skan{ 9100169689Skan if (TARGET_MIPS16) 9101169689Skan mips16_lay_out_constants (); 9102169689Skan else if (TARGET_EXPLICIT_RELOCS) 9103169689Skan { 9104169689Skan if (mips_flag_delayed_branch) 9105169689Skan dbr_schedule (get_insns ()); 9106169689Skan mips_avoid_hazards (); 9107169689Skan if (TUNE_MIPS4130 && TARGET_VR4130_ALIGN) 9108169689Skan vr4130_align_insns (); 9109169689Skan } 9110169689Skan} 9111169689Skan 9112169689Skan/* This function does three things: 9113169689Skan 9114169689Skan - Register the special divsi3 and modsi3 functions if -mfix-vr4120. 9115169689Skan - Register the mips16 hardware floating point stubs. 9116169689Skan - Register the gofast functions if selected using --enable-gofast. */ 9117169689Skan 9118169689Skan#include "config/gofast.h" 9119169689Skan 9120169689Skanstatic void 9121169689Skanmips_init_libfuncs (void) 9122169689Skan{ 9123169689Skan if (TARGET_FIX_VR4120) 9124169689Skan { 9125169689Skan set_optab_libfunc (sdiv_optab, SImode, "__vr4120_divsi3"); 9126169689Skan set_optab_libfunc (smod_optab, SImode, "__vr4120_modsi3"); 9127169689Skan } 9128169689Skan 9129169689Skan if (TARGET_MIPS16 && mips16_hard_float) 9130169689Skan { 9131169689Skan set_optab_libfunc (add_optab, SFmode, "__mips16_addsf3"); 9132169689Skan set_optab_libfunc (sub_optab, SFmode, "__mips16_subsf3"); 9133169689Skan set_optab_libfunc (smul_optab, SFmode, "__mips16_mulsf3"); 9134169689Skan set_optab_libfunc (sdiv_optab, SFmode, "__mips16_divsf3"); 9135169689Skan 9136169689Skan set_optab_libfunc (eq_optab, SFmode, "__mips16_eqsf2"); 9137169689Skan set_optab_libfunc (ne_optab, SFmode, "__mips16_nesf2"); 9138169689Skan set_optab_libfunc (gt_optab, SFmode, "__mips16_gtsf2"); 9139169689Skan set_optab_libfunc (ge_optab, SFmode, "__mips16_gesf2"); 9140169689Skan set_optab_libfunc (lt_optab, SFmode, "__mips16_ltsf2"); 9141169689Skan set_optab_libfunc (le_optab, SFmode, "__mips16_lesf2"); 9142169689Skan 9143169689Skan set_conv_libfunc (sfix_optab, SImode, SFmode, "__mips16_fix_truncsfsi"); 9144169689Skan set_conv_libfunc (sfloat_optab, SFmode, SImode, "__mips16_floatsisf"); 9145169689Skan 9146169689Skan if (TARGET_DOUBLE_FLOAT) 9147169689Skan { 9148169689Skan set_optab_libfunc (add_optab, DFmode, "__mips16_adddf3"); 9149169689Skan set_optab_libfunc (sub_optab, DFmode, "__mips16_subdf3"); 9150169689Skan set_optab_libfunc (smul_optab, DFmode, "__mips16_muldf3"); 9151169689Skan set_optab_libfunc (sdiv_optab, DFmode, "__mips16_divdf3"); 9152169689Skan 9153169689Skan set_optab_libfunc (eq_optab, DFmode, "__mips16_eqdf2"); 9154169689Skan set_optab_libfunc (ne_optab, DFmode, "__mips16_nedf2"); 9155169689Skan set_optab_libfunc (gt_optab, DFmode, "__mips16_gtdf2"); 9156169689Skan set_optab_libfunc (ge_optab, DFmode, "__mips16_gedf2"); 9157169689Skan set_optab_libfunc (lt_optab, DFmode, "__mips16_ltdf2"); 9158169689Skan set_optab_libfunc (le_optab, DFmode, "__mips16_ledf2"); 9159169689Skan 9160169689Skan set_conv_libfunc (sext_optab, DFmode, SFmode, "__mips16_extendsfdf2"); 9161169689Skan set_conv_libfunc (trunc_optab, SFmode, DFmode, "__mips16_truncdfsf2"); 9162169689Skan 9163169689Skan set_conv_libfunc (sfix_optab, SImode, DFmode, "__mips16_fix_truncdfsi"); 9164169689Skan set_conv_libfunc (sfloat_optab, DFmode, SImode, "__mips16_floatsidf"); 9165169689Skan } 9166169689Skan } 9167169689Skan else 9168169689Skan gofast_maybe_init_libfuncs (); 9169169689Skan} 9170169689Skan 9171169689Skan/* Return a number assessing the cost of moving a register in class 9172169689Skan FROM to class TO. The classes are expressed using the enumeration 9173169689Skan values such as `GENERAL_REGS'. A value of 2 is the default; other 9174169689Skan values are interpreted relative to that. 9175169689Skan 9176169689Skan It is not required that the cost always equal 2 when FROM is the 9177169689Skan same as TO; on some machines it is expensive to move between 9178169689Skan registers if they are not general registers. 9179169689Skan 9180169689Skan If reload sees an insn consisting of a single `set' between two 9181169689Skan hard registers, and if `REGISTER_MOVE_COST' applied to their 9182169689Skan classes returns a value of 2, reload does not check to ensure that 9183169689Skan the constraints of the insn are met. Setting a cost of other than 9184169689Skan 2 will allow reload to verify that the constraints are met. You 9185169689Skan should do this if the `movM' pattern's constraints do not allow 9186169689Skan such copying. 9187169689Skan 9188169689Skan ??? We make the cost of moving from HI/LO into general 9189169689Skan registers the same as for one of moving general registers to 9190169689Skan HI/LO for TARGET_MIPS16 in order to prevent allocating a 9191169689Skan pseudo to HI/LO. This might hurt optimizations though, it 9192169689Skan isn't clear if it is wise. And it might not work in all cases. We 9193169689Skan could solve the DImode LO reg problem by using a multiply, just 9194169689Skan like reload_{in,out}si. We could solve the SImode/HImode HI reg 9195169689Skan problem by using divide instructions. divu puts the remainder in 9196169689Skan the HI reg, so doing a divide by -1 will move the value in the HI 9197169689Skan reg for all values except -1. We could handle that case by using a 9198169689Skan signed divide, e.g. -1 / 2 (or maybe 1 / -2?). We'd have to emit 9199169689Skan a compare/branch to test the input value to see which instruction 9200169689Skan we need to use. This gets pretty messy, but it is feasible. */ 9201169689Skan 9202169689Skanint 9203169689Skanmips_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED, 9204169689Skan enum reg_class to, enum reg_class from) 9205169689Skan{ 9206169689Skan if (from == M16_REGS && GR_REG_CLASS_P (to)) 9207169689Skan return 2; 9208169689Skan else if (from == M16_NA_REGS && GR_REG_CLASS_P (to)) 9209169689Skan return 2; 9210169689Skan else if (GR_REG_CLASS_P (from)) 9211169689Skan { 9212169689Skan if (to == M16_REGS) 9213169689Skan return 2; 9214169689Skan else if (to == M16_NA_REGS) 9215169689Skan return 2; 9216169689Skan else if (GR_REG_CLASS_P (to)) 9217169689Skan { 9218169689Skan if (TARGET_MIPS16) 9219169689Skan return 4; 9220169689Skan else 9221169689Skan return 2; 9222169689Skan } 9223169689Skan else if (to == FP_REGS) 9224169689Skan return 4; 9225169689Skan else if (reg_class_subset_p (to, ACC_REGS)) 9226169689Skan { 9227169689Skan if (TARGET_MIPS16) 9228169689Skan return 12; 9229169689Skan else 9230169689Skan return 6; 9231169689Skan } 9232169689Skan else if (COP_REG_CLASS_P (to)) 9233169689Skan { 9234169689Skan return 5; 9235169689Skan } 9236169689Skan } 9237169689Skan else if (from == FP_REGS) 9238169689Skan { 9239169689Skan if (GR_REG_CLASS_P (to)) 9240169689Skan return 4; 9241169689Skan else if (to == FP_REGS) 9242169689Skan return 2; 9243169689Skan else if (to == ST_REGS) 9244169689Skan return 8; 9245169689Skan } 9246169689Skan else if (reg_class_subset_p (from, ACC_REGS)) 9247169689Skan { 9248169689Skan if (GR_REG_CLASS_P (to)) 9249169689Skan { 9250169689Skan if (TARGET_MIPS16) 9251169689Skan return 12; 9252169689Skan else 9253169689Skan return 6; 9254169689Skan } 9255169689Skan } 9256169689Skan else if (from == ST_REGS && GR_REG_CLASS_P (to)) 9257169689Skan return 4; 9258169689Skan else if (COP_REG_CLASS_P (from)) 9259169689Skan { 9260169689Skan return 5; 9261169689Skan } 9262169689Skan 9263169689Skan /* Fall through. 9264169689Skan ??? What cases are these? Shouldn't we return 2 here? */ 9265169689Skan 9266169689Skan return 12; 9267169689Skan} 9268169689Skan 9269169689Skan/* Return the length of INSN. LENGTH is the initial length computed by 9270169689Skan attributes in the machine-description file. */ 9271169689Skan 9272169689Skanint 9273169689Skanmips_adjust_insn_length (rtx insn, int length) 9274169689Skan{ 9275169689Skan /* A unconditional jump has an unfilled delay slot if it is not part 9276169689Skan of a sequence. A conditional jump normally has a delay slot, but 9277169689Skan does not on MIPS16. */ 9278169689Skan if (CALL_P (insn) || (TARGET_MIPS16 ? simplejump_p (insn) : JUMP_P (insn))) 9279169689Skan length += 4; 9280169689Skan 9281169689Skan /* See how many nops might be needed to avoid hardware hazards. */ 9282169689Skan if (!cfun->machine->ignore_hazard_length_p && INSN_CODE (insn) >= 0) 9283169689Skan switch (get_attr_hazard (insn)) 9284169689Skan { 9285169689Skan case HAZARD_NONE: 9286169689Skan break; 9287169689Skan 9288169689Skan case HAZARD_DELAY: 9289169689Skan length += 4; 9290169689Skan break; 9291169689Skan 9292169689Skan case HAZARD_HILO: 9293169689Skan length += 8; 9294169689Skan break; 9295169689Skan } 9296169689Skan 9297169689Skan /* All MIPS16 instructions are a measly two bytes. */ 9298169689Skan if (TARGET_MIPS16) 9299169689Skan length /= 2; 9300169689Skan 9301169689Skan return length; 9302169689Skan} 9303169689Skan 9304169689Skan 9305169689Skan/* Return an asm sequence to start a noat block and load the address 9306169689Skan of a label into $1. */ 9307169689Skan 9308169689Skanconst char * 9309169689Skanmips_output_load_label (void) 9310169689Skan{ 9311169689Skan if (TARGET_EXPLICIT_RELOCS) 9312169689Skan switch (mips_abi) 9313169689Skan { 9314169689Skan case ABI_N32: 9315169689Skan return "%[lw\t%@,%%got_page(%0)(%+)\n\taddiu\t%@,%@,%%got_ofst(%0)"; 9316169689Skan 9317169689Skan case ABI_64: 9318169689Skan return "%[ld\t%@,%%got_page(%0)(%+)\n\tdaddiu\t%@,%@,%%got_ofst(%0)"; 9319169689Skan 9320169689Skan default: 9321169689Skan if (ISA_HAS_LOAD_DELAY) 9322169689Skan return "%[lw\t%@,%%got(%0)(%+)%#\n\taddiu\t%@,%@,%%lo(%0)"; 9323169689Skan return "%[lw\t%@,%%got(%0)(%+)\n\taddiu\t%@,%@,%%lo(%0)"; 9324169689Skan } 9325169689Skan else 9326169689Skan { 9327169689Skan if (Pmode == DImode) 9328169689Skan return "%[dla\t%@,%0"; 9329169689Skan else 9330169689Skan return "%[la\t%@,%0"; 9331169689Skan } 9332169689Skan} 9333169689Skan 9334169689Skan/* Return the assembly code for INSN, which has the operands given by 9335169689Skan OPERANDS, and which branches to OPERANDS[1] if some condition is true. 9336169689Skan BRANCH_IF_TRUE is the asm template that should be used if OPERANDS[1] 9337169689Skan is in range of a direct branch. BRANCH_IF_FALSE is an inverted 9338169689Skan version of BRANCH_IF_TRUE. */ 9339169689Skan 9340169689Skanconst char * 9341169689Skanmips_output_conditional_branch (rtx insn, rtx *operands, 9342169689Skan const char *branch_if_true, 9343169689Skan const char *branch_if_false) 9344169689Skan{ 9345169689Skan unsigned int length; 9346169689Skan rtx taken, not_taken; 9347169689Skan 9348169689Skan length = get_attr_length (insn); 9349169689Skan if (length <= 8) 9350169689Skan { 9351169689Skan /* Just a simple conditional branch. */ 9352169689Skan mips_branch_likely = (final_sequence && INSN_ANNULLED_BRANCH_P (insn)); 9353169689Skan return branch_if_true; 9354169689Skan } 9355169689Skan 9356169689Skan /* Generate a reversed branch around a direct jump. This fallback does 9357169689Skan not use branch-likely instructions. */ 9358169689Skan mips_branch_likely = false; 9359169689Skan not_taken = gen_label_rtx (); 9360169689Skan taken = operands[1]; 9361169689Skan 9362169689Skan /* Generate the reversed branch to NOT_TAKEN. */ 9363169689Skan operands[1] = not_taken; 9364169689Skan output_asm_insn (branch_if_false, operands); 9365169689Skan 9366169689Skan /* If INSN has a delay slot, we must provide delay slots for both the 9367169689Skan branch to NOT_TAKEN and the conditional jump. We must also ensure 9368169689Skan that INSN's delay slot is executed in the appropriate cases. */ 9369169689Skan if (final_sequence) 9370169689Skan { 9371169689Skan /* This first delay slot will always be executed, so use INSN's 9372169689Skan delay slot if is not annulled. */ 9373169689Skan if (!INSN_ANNULLED_BRANCH_P (insn)) 9374169689Skan { 9375169689Skan final_scan_insn (XVECEXP (final_sequence, 0, 1), 9376169689Skan asm_out_file, optimize, 1, NULL); 9377169689Skan INSN_DELETED_P (XVECEXP (final_sequence, 0, 1)) = 1; 9378169689Skan } 9379169689Skan else 9380169689Skan output_asm_insn ("nop", 0); 9381169689Skan fprintf (asm_out_file, "\n"); 9382169689Skan } 9383169689Skan 9384169689Skan /* Output the unconditional branch to TAKEN. */ 9385169689Skan if (length <= 16) 9386169689Skan output_asm_insn ("j\t%0%/", &taken); 9387169689Skan else 9388169689Skan { 9389169689Skan output_asm_insn (mips_output_load_label (), &taken); 9390169689Skan output_asm_insn ("jr\t%@%]%/", 0); 9391169689Skan } 9392169689Skan 9393169689Skan /* Now deal with its delay slot; see above. */ 9394169689Skan if (final_sequence) 9395169689Skan { 9396169689Skan /* This delay slot will only be executed if the branch is taken. 9397169689Skan Use INSN's delay slot if is annulled. */ 9398169689Skan if (INSN_ANNULLED_BRANCH_P (insn)) 9399169689Skan { 9400169689Skan final_scan_insn (XVECEXP (final_sequence, 0, 1), 9401169689Skan asm_out_file, optimize, 1, NULL); 9402169689Skan INSN_DELETED_P (XVECEXP (final_sequence, 0, 1)) = 1; 9403169689Skan } 9404169689Skan else 9405169689Skan output_asm_insn ("nop", 0); 9406169689Skan fprintf (asm_out_file, "\n"); 9407169689Skan } 9408169689Skan 9409169689Skan /* Output NOT_TAKEN. */ 9410169689Skan (*targetm.asm_out.internal_label) (asm_out_file, "L", 9411169689Skan CODE_LABEL_NUMBER (not_taken)); 9412169689Skan return ""; 9413169689Skan} 9414169689Skan 9415169689Skan/* Return the assembly code for INSN, which branches to OPERANDS[1] 9416169689Skan if some ordered condition is true. The condition is given by 9417169689Skan OPERANDS[0] if !INVERTED_P, otherwise it is the inverse of 9418169689Skan OPERANDS[0]. OPERANDS[2] is the comparison's first operand; 9419169689Skan its second is always zero. */ 9420169689Skan 9421169689Skanconst char * 9422169689Skanmips_output_order_conditional_branch (rtx insn, rtx *operands, bool inverted_p) 9423169689Skan{ 9424169689Skan const char *branch[2]; 9425169689Skan 9426169689Skan /* Make BRANCH[1] branch to OPERANDS[1] when the condition is true. 9427169689Skan Make BRANCH[0] branch on the inverse condition. */ 9428169689Skan switch (GET_CODE (operands[0])) 9429169689Skan { 9430169689Skan /* These cases are equivalent to comparisons against zero. */ 9431169689Skan case LEU: 9432169689Skan inverted_p = !inverted_p; 9433169689Skan /* Fall through. */ 9434169689Skan case GTU: 9435169689Skan branch[!inverted_p] = MIPS_BRANCH ("bne", "%2,%.,%1"); 9436169689Skan branch[inverted_p] = MIPS_BRANCH ("beq", "%2,%.,%1"); 9437169689Skan break; 9438169689Skan 9439169689Skan /* These cases are always true or always false. */ 9440169689Skan case LTU: 9441169689Skan inverted_p = !inverted_p; 9442169689Skan /* Fall through. */ 9443169689Skan case GEU: 9444169689Skan branch[!inverted_p] = MIPS_BRANCH ("beq", "%.,%.,%1"); 9445169689Skan branch[inverted_p] = MIPS_BRANCH ("bne", "%.,%.,%1"); 9446169689Skan break; 9447169689Skan 9448169689Skan default: 9449169689Skan branch[!inverted_p] = MIPS_BRANCH ("b%C0z", "%2,%1"); 9450169689Skan branch[inverted_p] = MIPS_BRANCH ("b%N0z", "%2,%1"); 9451169689Skan break; 9452169689Skan } 9453169689Skan return mips_output_conditional_branch (insn, operands, branch[1], branch[0]); 9454169689Skan} 9455169689Skan 9456169689Skan/* Used to output div or ddiv instruction DIVISION, which has the operands 9457169689Skan given by OPERANDS. Add in a divide-by-zero check if needed. 9458169689Skan 9459169689Skan When working around R4000 and R4400 errata, we need to make sure that 9460169689Skan the division is not immediately followed by a shift[1][2]. We also 9461169689Skan need to stop the division from being put into a branch delay slot[3]. 9462169689Skan The easiest way to avoid both problems is to add a nop after the 9463169689Skan division. When a divide-by-zero check is needed, this nop can be 9464169689Skan used to fill the branch delay slot. 9465169689Skan 9466169689Skan [1] If a double-word or a variable shift executes immediately 9467169689Skan after starting an integer division, the shift may give an 9468169689Skan incorrect result. See quotations of errata #16 and #28 from 9469169689Skan "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0" 9470169689Skan in mips.md for details. 9471169689Skan 9472169689Skan [2] A similar bug to [1] exists for all revisions of the 9473169689Skan R4000 and the R4400 when run in an MC configuration. 9474169689Skan From "MIPS R4000MC Errata, Processor Revision 2.2 and 3.0": 9475169689Skan 9476169689Skan "19. In this following sequence: 9477169689Skan 9478169689Skan ddiv (or ddivu or div or divu) 9479169689Skan dsll32 (or dsrl32, dsra32) 9480169689Skan 9481169689Skan if an MPT stall occurs, while the divide is slipping the cpu 9482169689Skan pipeline, then the following double shift would end up with an 9483169689Skan incorrect result. 9484169689Skan 9485169689Skan Workaround: The compiler needs to avoid generating any 9486169689Skan sequence with divide followed by extended double shift." 9487169689Skan 9488169689Skan This erratum is also present in "MIPS R4400MC Errata, Processor 9489169689Skan Revision 1.0" and "MIPS R4400MC Errata, Processor Revision 2.0 9490169689Skan & 3.0" as errata #10 and #4, respectively. 9491169689Skan 9492169689Skan [3] From "MIPS R4000PC/SC Errata, Processor Revision 2.2 and 3.0" 9493169689Skan (also valid for MIPS R4000MC processors): 9494169689Skan 9495169689Skan "52. R4000SC: This bug does not apply for the R4000PC. 9496169689Skan 9497169689Skan There are two flavors of this bug: 9498169689Skan 9499169689Skan 1) If the instruction just after divide takes an RF exception 9500169689Skan (tlb-refill, tlb-invalid) and gets an instruction cache 9501169689Skan miss (both primary and secondary) and the line which is 9502169689Skan currently in secondary cache at this index had the first 9503169689Skan data word, where the bits 5..2 are set, then R4000 would 9504169689Skan get a wrong result for the div. 9505169689Skan 9506169689Skan ##1 9507169689Skan nop 9508169689Skan div r8, r9 9509169689Skan ------------------- # end-of page. -tlb-refill 9510169689Skan nop 9511169689Skan ##2 9512169689Skan nop 9513169689Skan div r8, r9 9514169689Skan ------------------- # end-of page. -tlb-invalid 9515169689Skan nop 9516169689Skan 9517169689Skan 2) If the divide is in the taken branch delay slot, where the 9518169689Skan target takes RF exception and gets an I-cache miss for the 9519169689Skan exception vector or where I-cache miss occurs for the 9520169689Skan target address, under the above mentioned scenarios, the 9521169689Skan div would get wrong results. 9522169689Skan 9523169689Skan ##1 9524169689Skan j r2 # to next page mapped or unmapped 9525169689Skan div r8,r9 # this bug would be there as long 9526169689Skan # as there is an ICache miss and 9527169689Skan nop # the "data pattern" is present 9528169689Skan 9529169689Skan ##2 9530169689Skan beq r0, r0, NextPage # to Next page 9531169689Skan div r8,r9 9532169689Skan nop 9533169689Skan 9534169689Skan This bug is present for div, divu, ddiv, and ddivu 9535169689Skan instructions. 9536169689Skan 9537169689Skan Workaround: For item 1), OS could make sure that the next page 9538169689Skan after the divide instruction is also mapped. For item 2), the 9539169689Skan compiler could make sure that the divide instruction is not in 9540169689Skan the branch delay slot." 9541169689Skan 9542169689Skan These processors have PRId values of 0x00004220 and 0x00004300 for 9543169689Skan the R4000 and 0x00004400, 0x00004500 and 0x00004600 for the R4400. */ 9544169689Skan 9545169689Skanconst char * 9546169689Skanmips_output_division (const char *division, rtx *operands) 9547169689Skan{ 9548169689Skan const char *s; 9549169689Skan 9550169689Skan s = division; 9551169689Skan if (TARGET_FIX_R4000 || TARGET_FIX_R4400) 9552169689Skan { 9553169689Skan output_asm_insn (s, operands); 9554169689Skan s = "nop"; 9555169689Skan } 9556169689Skan if (TARGET_CHECK_ZERO_DIV) 9557169689Skan { 9558169689Skan if (TARGET_MIPS16) 9559169689Skan { 9560169689Skan output_asm_insn (s, operands); 9561169689Skan s = "bnez\t%2,1f\n\tbreak\t7\n1:"; 9562169689Skan } 9563169689Skan else if (GENERATE_DIVIDE_TRAPS) 9564169689Skan { 9565169689Skan output_asm_insn (s, operands); 9566169689Skan s = "teq\t%2,%.,7"; 9567169689Skan } 9568169689Skan else 9569169689Skan { 9570169689Skan output_asm_insn ("%(bne\t%2,%.,1f", operands); 9571169689Skan output_asm_insn (s, operands); 9572169689Skan s = "break\t7%)\n1:"; 9573169689Skan } 9574169689Skan } 9575169689Skan return s; 9576169689Skan} 9577169689Skan 9578169689Skan/* Return true if GIVEN is the same as CANONICAL, or if it is CANONICAL 9579169689Skan with a final "000" replaced by "k". Ignore case. 9580169689Skan 9581169689Skan Note: this function is shared between GCC and GAS. */ 9582169689Skan 9583169689Skanstatic bool 9584169689Skanmips_strict_matching_cpu_name_p (const char *canonical, const char *given) 9585169689Skan{ 9586169689Skan while (*given != 0 && TOLOWER (*given) == TOLOWER (*canonical)) 9587169689Skan given++, canonical++; 9588169689Skan 9589169689Skan return ((*given == 0 && *canonical == 0) 9590169689Skan || (strcmp (canonical, "000") == 0 && strcasecmp (given, "k") == 0)); 9591169689Skan} 9592169689Skan 9593169689Skan 9594169689Skan/* Return true if GIVEN matches CANONICAL, where GIVEN is a user-supplied 9595169689Skan CPU name. We've traditionally allowed a lot of variation here. 9596169689Skan 9597169689Skan Note: this function is shared between GCC and GAS. */ 9598169689Skan 9599169689Skanstatic bool 9600169689Skanmips_matching_cpu_name_p (const char *canonical, const char *given) 9601169689Skan{ 9602169689Skan /* First see if the name matches exactly, or with a final "000" 9603169689Skan turned into "k". */ 9604169689Skan if (mips_strict_matching_cpu_name_p (canonical, given)) 9605169689Skan return true; 9606169689Skan 9607169689Skan /* If not, try comparing based on numerical designation alone. 9608169689Skan See if GIVEN is an unadorned number, or 'r' followed by a number. */ 9609169689Skan if (TOLOWER (*given) == 'r') 9610169689Skan given++; 9611169689Skan if (!ISDIGIT (*given)) 9612169689Skan return false; 9613169689Skan 9614169689Skan /* Skip over some well-known prefixes in the canonical name, 9615169689Skan hoping to find a number there too. */ 9616169689Skan if (TOLOWER (canonical[0]) == 'v' && TOLOWER (canonical[1]) == 'r') 9617169689Skan canonical += 2; 9618169689Skan else if (TOLOWER (canonical[0]) == 'r' && TOLOWER (canonical[1]) == 'm') 9619169689Skan canonical += 2; 9620169689Skan else if (TOLOWER (canonical[0]) == 'r') 9621169689Skan canonical += 1; 9622169689Skan 9623169689Skan return mips_strict_matching_cpu_name_p (canonical, given); 9624169689Skan} 9625169689Skan 9626169689Skan 9627169689Skan/* Return the mips_cpu_info entry for the processor or ISA given 9628169689Skan by CPU_STRING. Return null if the string isn't recognized. 9629169689Skan 9630169689Skan A similar function exists in GAS. */ 9631169689Skan 9632169689Skanstatic const struct mips_cpu_info * 9633169689Skanmips_parse_cpu (const char *cpu_string) 9634169689Skan{ 9635169689Skan const struct mips_cpu_info *p; 9636169689Skan const char *s; 9637169689Skan 9638169689Skan /* In the past, we allowed upper-case CPU names, but it doesn't 9639169689Skan work well with the multilib machinery. */ 9640169689Skan for (s = cpu_string; *s != 0; s++) 9641169689Skan if (ISUPPER (*s)) 9642169689Skan { 9643169689Skan warning (0, "the cpu name must be lower case"); 9644169689Skan break; 9645169689Skan } 9646169689Skan 9647169689Skan /* 'from-abi' selects the most compatible architecture for the given 9648169689Skan ABI: MIPS I for 32-bit ABIs and MIPS III for 64-bit ABIs. For the 9649169689Skan EABIs, we have to decide whether we're using the 32-bit or 64-bit 9650169689Skan version. Look first at the -mgp options, if given, otherwise base 9651169689Skan the choice on MASK_64BIT in TARGET_DEFAULT. */ 9652169689Skan if (strcasecmp (cpu_string, "from-abi") == 0) 9653169689Skan return mips_cpu_info_from_isa (ABI_NEEDS_32BIT_REGS ? 1 9654169689Skan : ABI_NEEDS_64BIT_REGS ? 3 9655169689Skan : (TARGET_64BIT ? 3 : 1)); 9656169689Skan 9657169689Skan /* 'default' has traditionally been a no-op. Probably not very useful. */ 9658169689Skan if (strcasecmp (cpu_string, "default") == 0) 9659169689Skan return 0; 9660169689Skan 9661169689Skan for (p = mips_cpu_info_table; p->name != 0; p++) 9662169689Skan if (mips_matching_cpu_name_p (p->name, cpu_string)) 9663169689Skan return p; 9664169689Skan 9665169689Skan return 0; 9666169689Skan} 9667169689Skan 9668169689Skan 9669169689Skan/* Return the processor associated with the given ISA level, or null 9670169689Skan if the ISA isn't valid. */ 9671169689Skan 9672169689Skanstatic const struct mips_cpu_info * 9673169689Skanmips_cpu_info_from_isa (int isa) 9674169689Skan{ 9675169689Skan const struct mips_cpu_info *p; 9676169689Skan 9677169689Skan for (p = mips_cpu_info_table; p->name != 0; p++) 9678169689Skan if (p->isa == isa) 9679169689Skan return p; 9680169689Skan 9681169689Skan return 0; 9682169689Skan} 9683169689Skan 9684169689Skan/* Implement HARD_REGNO_NREGS. The size of FP registers is controlled 9685169689Skan by UNITS_PER_FPREG. The size of FP status registers is always 4, because 9686169689Skan they only hold condition code modes, and CCmode is always considered to 9687169689Skan be 4 bytes wide. All other registers are word sized. */ 9688169689Skan 9689169689Skanunsigned int 9690169689Skanmips_hard_regno_nregs (int regno, enum machine_mode mode) 9691169689Skan{ 9692169689Skan if (ST_REG_P (regno)) 9693169689Skan return ((GET_MODE_SIZE (mode) + 3) / 4); 9694169689Skan else if (! FP_REG_P (regno)) 9695169689Skan return ((GET_MODE_SIZE (mode) + UNITS_PER_WORD - 1) / UNITS_PER_WORD); 9696169689Skan else 9697169689Skan return ((GET_MODE_SIZE (mode) + UNITS_PER_FPREG - 1) / UNITS_PER_FPREG); 9698169689Skan} 9699169689Skan 9700169689Skan/* Implement TARGET_RETURN_IN_MEMORY. Under the old (i.e., 32 and O64 ABIs) 9701169689Skan all BLKmode objects are returned in memory. Under the new (N32 and 9702169689Skan 64-bit MIPS ABIs) small structures are returned in a register. 9703169689Skan Objects with varying size must still be returned in memory, of 9704169689Skan course. */ 9705169689Skan 9706169689Skanstatic bool 9707169689Skanmips_return_in_memory (tree type, tree fndecl ATTRIBUTE_UNUSED) 9708169689Skan{ 9709169689Skan if (TARGET_OLDABI) 9710169689Skan return (TYPE_MODE (type) == BLKmode); 9711169689Skan else 9712169689Skan return ((int_size_in_bytes (type) > (2 * UNITS_PER_WORD)) 9713169689Skan || (int_size_in_bytes (type) == -1)); 9714169689Skan} 9715169689Skan 9716169689Skanstatic bool 9717169689Skanmips_strict_argument_naming (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED) 9718169689Skan{ 9719169689Skan return !TARGET_OLDABI; 9720169689Skan} 9721169689Skan 9722169689Skan/* Return true if INSN is a multiply-add or multiply-subtract 9723169689Skan instruction and PREV assigns to the accumulator operand. */ 9724169689Skan 9725169689Skanbool 9726169689Skanmips_linked_madd_p (rtx prev, rtx insn) 9727169689Skan{ 9728169689Skan rtx x; 9729169689Skan 9730169689Skan x = single_set (insn); 9731169689Skan if (x == 0) 9732169689Skan return false; 9733169689Skan 9734169689Skan x = SET_SRC (x); 9735169689Skan 9736169689Skan if (GET_CODE (x) == PLUS 9737169689Skan && GET_CODE (XEXP (x, 0)) == MULT 9738169689Skan && reg_set_p (XEXP (x, 1), prev)) 9739169689Skan return true; 9740169689Skan 9741169689Skan if (GET_CODE (x) == MINUS 9742169689Skan && GET_CODE (XEXP (x, 1)) == MULT 9743169689Skan && reg_set_p (XEXP (x, 0), prev)) 9744169689Skan return true; 9745169689Skan 9746169689Skan return false; 9747169689Skan} 9748169689Skan 9749169689Skan/* Used by TUNE_MACC_CHAINS to record the last scheduled instruction 9750169689Skan that may clobber hi or lo. */ 9751169689Skan 9752169689Skanstatic rtx mips_macc_chains_last_hilo; 9753169689Skan 9754169689Skan/* A TUNE_MACC_CHAINS helper function. Record that instruction INSN has 9755169689Skan been scheduled, updating mips_macc_chains_last_hilo appropriately. */ 9756169689Skan 9757169689Skanstatic void 9758169689Skanmips_macc_chains_record (rtx insn) 9759169689Skan{ 9760169689Skan if (get_attr_may_clobber_hilo (insn)) 9761169689Skan mips_macc_chains_last_hilo = insn; 9762169689Skan} 9763169689Skan 9764169689Skan/* A TUNE_MACC_CHAINS helper function. Search ready queue READY, which 9765169689Skan has NREADY elements, looking for a multiply-add or multiply-subtract 9766169689Skan instruction that is cumulative with mips_macc_chains_last_hilo. 9767169689Skan If there is one, promote it ahead of anything else that might 9768169689Skan clobber hi or lo. */ 9769169689Skan 9770169689Skanstatic void 9771169689Skanmips_macc_chains_reorder (rtx *ready, int nready) 9772169689Skan{ 9773169689Skan int i, j; 9774169689Skan 9775169689Skan if (mips_macc_chains_last_hilo != 0) 9776169689Skan for (i = nready - 1; i >= 0; i--) 9777169689Skan if (mips_linked_madd_p (mips_macc_chains_last_hilo, ready[i])) 9778169689Skan { 9779169689Skan for (j = nready - 1; j > i; j--) 9780169689Skan if (recog_memoized (ready[j]) >= 0 9781169689Skan && get_attr_may_clobber_hilo (ready[j])) 9782169689Skan { 9783169689Skan mips_promote_ready (ready, i, j); 9784169689Skan break; 9785169689Skan } 9786169689Skan break; 9787169689Skan } 9788169689Skan} 9789169689Skan 9790169689Skan/* The last instruction to be scheduled. */ 9791169689Skan 9792169689Skanstatic rtx vr4130_last_insn; 9793169689Skan 9794169689Skan/* A note_stores callback used by vr4130_true_reg_dependence_p. DATA 9795169689Skan points to an rtx that is initially an instruction. Nullify the rtx 9796169689Skan if the instruction uses the value of register X. */ 9797169689Skan 9798169689Skanstatic void 9799169689Skanvr4130_true_reg_dependence_p_1 (rtx x, rtx pat ATTRIBUTE_UNUSED, void *data) 9800169689Skan{ 9801169689Skan rtx *insn_ptr = data; 9802169689Skan if (REG_P (x) 9803169689Skan && *insn_ptr != 0 9804169689Skan && reg_referenced_p (x, PATTERN (*insn_ptr))) 9805169689Skan *insn_ptr = 0; 9806169689Skan} 9807169689Skan 9808169689Skan/* Return true if there is true register dependence between vr4130_last_insn 9809169689Skan and INSN. */ 9810169689Skan 9811169689Skanstatic bool 9812169689Skanvr4130_true_reg_dependence_p (rtx insn) 9813169689Skan{ 9814169689Skan note_stores (PATTERN (vr4130_last_insn), 9815169689Skan vr4130_true_reg_dependence_p_1, &insn); 9816169689Skan return insn == 0; 9817169689Skan} 9818169689Skan 9819169689Skan/* A TUNE_MIPS4130 helper function. Given that INSN1 is at the head of 9820169689Skan the ready queue and that INSN2 is the instruction after it, return 9821169689Skan true if it is worth promoting INSN2 ahead of INSN1. Look for cases 9822169689Skan in which INSN1 and INSN2 can probably issue in parallel, but for 9823169689Skan which (INSN2, INSN1) should be less sensitive to instruction 9824169689Skan alignment than (INSN1, INSN2). See 4130.md for more details. */ 9825169689Skan 9826169689Skanstatic bool 9827169689Skanvr4130_swap_insns_p (rtx insn1, rtx insn2) 9828169689Skan{ 9829169689Skan rtx dep; 9830169689Skan 9831169689Skan /* Check for the following case: 9832169689Skan 9833169689Skan 1) there is some other instruction X with an anti dependence on INSN1; 9834169689Skan 2) X has a higher priority than INSN2; and 9835169689Skan 3) X is an arithmetic instruction (and thus has no unit restrictions). 9836169689Skan 9837169689Skan If INSN1 is the last instruction blocking X, it would better to 9838169689Skan choose (INSN1, X) over (INSN2, INSN1). */ 9839169689Skan for (dep = INSN_DEPEND (insn1); dep != 0; dep = XEXP (dep, 1)) 9840169689Skan if (REG_NOTE_KIND (dep) == REG_DEP_ANTI 9841169689Skan && INSN_PRIORITY (XEXP (dep, 0)) > INSN_PRIORITY (insn2) 9842169689Skan && recog_memoized (XEXP (dep, 0)) >= 0 9843169689Skan && get_attr_vr4130_class (XEXP (dep, 0)) == VR4130_CLASS_ALU) 9844169689Skan return false; 9845169689Skan 9846169689Skan if (vr4130_last_insn != 0 9847169689Skan && recog_memoized (insn1) >= 0 9848169689Skan && recog_memoized (insn2) >= 0) 9849169689Skan { 9850169689Skan /* See whether INSN1 and INSN2 use different execution units, 9851169689Skan or if they are both ALU-type instructions. If so, they can 9852169689Skan probably execute in parallel. */ 9853169689Skan enum attr_vr4130_class class1 = get_attr_vr4130_class (insn1); 9854169689Skan enum attr_vr4130_class class2 = get_attr_vr4130_class (insn2); 9855169689Skan if (class1 != class2 || class1 == VR4130_CLASS_ALU) 9856169689Skan { 9857169689Skan /* If only one of the instructions has a dependence on 9858169689Skan vr4130_last_insn, prefer to schedule the other one first. */ 9859169689Skan bool dep1 = vr4130_true_reg_dependence_p (insn1); 9860169689Skan bool dep2 = vr4130_true_reg_dependence_p (insn2); 9861169689Skan if (dep1 != dep2) 9862169689Skan return dep1; 9863169689Skan 9864169689Skan /* Prefer to schedule INSN2 ahead of INSN1 if vr4130_last_insn 9865169689Skan is not an ALU-type instruction and if INSN1 uses the same 9866169689Skan execution unit. (Note that if this condition holds, we already 9867169689Skan know that INSN2 uses a different execution unit.) */ 9868169689Skan if (class1 != VR4130_CLASS_ALU 9869169689Skan && recog_memoized (vr4130_last_insn) >= 0 9870169689Skan && class1 == get_attr_vr4130_class (vr4130_last_insn)) 9871169689Skan return true; 9872169689Skan } 9873169689Skan } 9874169689Skan return false; 9875169689Skan} 9876169689Skan 9877169689Skan/* A TUNE_MIPS4130 helper function. (READY, NREADY) describes a ready 9878169689Skan queue with at least two instructions. Swap the first two if 9879169689Skan vr4130_swap_insns_p says that it could be worthwhile. */ 9880169689Skan 9881169689Skanstatic void 9882169689Skanvr4130_reorder (rtx *ready, int nready) 9883169689Skan{ 9884169689Skan if (vr4130_swap_insns_p (ready[nready - 1], ready[nready - 2])) 9885169689Skan mips_promote_ready (ready, nready - 2, nready - 1); 9886169689Skan} 9887169689Skan 9888169689Skan/* Remove the instruction at index LOWER from ready queue READY and 9889169689Skan reinsert it in front of the instruction at index HIGHER. LOWER must 9890169689Skan be <= HIGHER. */ 9891169689Skan 9892169689Skanstatic void 9893169689Skanmips_promote_ready (rtx *ready, int lower, int higher) 9894169689Skan{ 9895169689Skan rtx new_head; 9896169689Skan int i; 9897169689Skan 9898169689Skan new_head = ready[lower]; 9899169689Skan for (i = lower; i < higher; i++) 9900169689Skan ready[i] = ready[i + 1]; 9901169689Skan ready[i] = new_head; 9902169689Skan} 9903169689Skan 9904169689Skan/* Implement TARGET_SCHED_REORDER. */ 9905169689Skan 9906169689Skanstatic int 9907169689Skanmips_sched_reorder (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED, 9908169689Skan rtx *ready, int *nreadyp, int cycle) 9909169689Skan{ 9910169689Skan if (!reload_completed && TUNE_MACC_CHAINS) 9911169689Skan { 9912169689Skan if (cycle == 0) 9913169689Skan mips_macc_chains_last_hilo = 0; 9914169689Skan if (*nreadyp > 0) 9915169689Skan mips_macc_chains_reorder (ready, *nreadyp); 9916169689Skan } 9917169689Skan if (reload_completed && TUNE_MIPS4130 && !TARGET_VR4130_ALIGN) 9918169689Skan { 9919169689Skan if (cycle == 0) 9920169689Skan vr4130_last_insn = 0; 9921169689Skan if (*nreadyp > 1) 9922169689Skan vr4130_reorder (ready, *nreadyp); 9923169689Skan } 9924169689Skan return mips_issue_rate (); 9925169689Skan} 9926169689Skan 9927169689Skan/* Implement TARGET_SCHED_VARIABLE_ISSUE. */ 9928169689Skan 9929169689Skanstatic int 9930169689Skanmips_variable_issue (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED, 9931169689Skan rtx insn, int more) 9932169689Skan{ 9933169689Skan switch (GET_CODE (PATTERN (insn))) 9934169689Skan { 9935169689Skan case USE: 9936169689Skan case CLOBBER: 9937169689Skan /* Don't count USEs and CLOBBERs against the issue rate. */ 9938169689Skan break; 9939169689Skan 9940169689Skan default: 9941169689Skan more--; 9942169689Skan if (!reload_completed && TUNE_MACC_CHAINS) 9943169689Skan mips_macc_chains_record (insn); 9944169689Skan vr4130_last_insn = insn; 9945169689Skan break; 9946169689Skan } 9947169689Skan return more; 9948169689Skan} 9949169689Skan 9950169689Skan/* Implement TARGET_SCHED_ADJUST_COST. We assume that anti and output 9951169689Skan dependencies have no cost. */ 9952169689Skan 9953169689Skanstatic int 9954169689Skanmips_adjust_cost (rtx insn ATTRIBUTE_UNUSED, rtx link, 9955169689Skan rtx dep ATTRIBUTE_UNUSED, int cost) 9956169689Skan{ 9957169689Skan if (REG_NOTE_KIND (link) != 0) 9958169689Skan return 0; 9959169689Skan return cost; 9960169689Skan} 9961169689Skan 9962169689Skan/* Return the number of instructions that can be issued per cycle. */ 9963169689Skan 9964169689Skanstatic int 9965169689Skanmips_issue_rate (void) 9966169689Skan{ 9967169689Skan switch (mips_tune) 9968169689Skan { 9969169689Skan case PROCESSOR_R4130: 9970169689Skan case PROCESSOR_R5400: 9971169689Skan case PROCESSOR_R5500: 9972169689Skan case PROCESSOR_R7000: 9973169689Skan case PROCESSOR_R9000: 9974208737Sjmallett case PROCESSOR_OCTEON: 9975169689Skan return 2; 9976169689Skan 9977169689Skan case PROCESSOR_SB1: 9978169689Skan case PROCESSOR_SB1A: 9979169689Skan /* This is actually 4, but we get better performance if we claim 3. 9980169689Skan This is partly because of unwanted speculative code motion with the 9981169689Skan larger number, and partly because in most common cases we can't 9982169689Skan reach the theoretical max of 4. */ 9983169689Skan return 3; 9984169689Skan 9985169689Skan default: 9986169689Skan return 1; 9987169689Skan } 9988169689Skan} 9989169689Skan 9990169689Skan/* Implements TARGET_SCHED_FIRST_CYCLE_MULTIPASS_DFA_LOOKAHEAD. This should 9991169689Skan be as wide as the scheduling freedom in the DFA. */ 9992169689Skan 9993169689Skanstatic int 9994169689Skanmips_multipass_dfa_lookahead (void) 9995169689Skan{ 9996169689Skan /* Can schedule up to 4 of the 6 function units in any one cycle. */ 9997169689Skan if (TUNE_SB1) 9998169689Skan return 4; 9999169689Skan 10000169689Skan return 0; 10001169689Skan} 10002169689Skan 10003169689Skan/* Implements a store data bypass check. We need this because the cprestore 10004169689Skan pattern is type store, but defined using an UNSPEC. This UNSPEC causes the 10005169689Skan default routine to abort. We just return false for that case. */ 10006169689Skan/* ??? Should try to give a better result here than assuming false. */ 10007169689Skan 10008169689Skanint 10009169689Skanmips_store_data_bypass_p (rtx out_insn, rtx in_insn) 10010169689Skan{ 10011169689Skan if (GET_CODE (PATTERN (in_insn)) == UNSPEC_VOLATILE) 10012169689Skan return false; 10013169689Skan 10014169689Skan return ! store_data_bypass_p (out_insn, in_insn); 10015169689Skan} 10016169689Skan 10017169689Skan/* Given that we have an rtx of the form (prefetch ... WRITE LOCALITY), 10018169689Skan return the first operand of the associated "pref" or "prefx" insn. */ 10019169689Skan 10020169689Skanrtx 10021169689Skanmips_prefetch_cookie (rtx write, rtx locality) 10022169689Skan{ 10023169689Skan /* store_streamed / load_streamed. */ 10024169689Skan if (INTVAL (locality) <= 0) 10025169689Skan return GEN_INT (INTVAL (write) + 4); 10026169689Skan 10027169689Skan /* store / load. */ 10028169689Skan if (INTVAL (locality) <= 2) 10029169689Skan return write; 10030169689Skan 10031169689Skan /* store_retained / load_retained. */ 10032169689Skan return GEN_INT (INTVAL (write) + 6); 10033169689Skan} 10034169689Skan 10035169689Skan/* MIPS builtin function support. */ 10036169689Skan 10037169689Skanstruct builtin_description 10038169689Skan{ 10039169689Skan /* The code of the main .md file instruction. See mips_builtin_type 10040169689Skan for more information. */ 10041169689Skan enum insn_code icode; 10042169689Skan 10043169689Skan /* The floating-point comparison code to use with ICODE, if any. */ 10044169689Skan enum mips_fp_condition cond; 10045169689Skan 10046169689Skan /* The name of the builtin function. */ 10047169689Skan const char *name; 10048169689Skan 10049169689Skan /* Specifies how the function should be expanded. */ 10050169689Skan enum mips_builtin_type builtin_type; 10051169689Skan 10052169689Skan /* The function's prototype. */ 10053169689Skan enum mips_function_type function_type; 10054169689Skan 10055169689Skan /* The target flags required for this function. */ 10056169689Skan int target_flags; 10057169689Skan}; 10058169689Skan 10059169689Skan/* Define a MIPS_BUILTIN_DIRECT function for instruction CODE_FOR_mips_<INSN>. 10060169689Skan FUNCTION_TYPE and TARGET_FLAGS are builtin_description fields. */ 10061169689Skan#define DIRECT_BUILTIN(INSN, FUNCTION_TYPE, TARGET_FLAGS) \ 10062169689Skan { CODE_FOR_mips_ ## INSN, 0, "__builtin_mips_" #INSN, \ 10063169689Skan MIPS_BUILTIN_DIRECT, FUNCTION_TYPE, TARGET_FLAGS } 10064169689Skan 10065169689Skan/* Define __builtin_mips_<INSN>_<COND>_{s,d}, both of which require 10066169689Skan TARGET_FLAGS. */ 10067169689Skan#define CMP_SCALAR_BUILTINS(INSN, COND, TARGET_FLAGS) \ 10068169689Skan { CODE_FOR_mips_ ## INSN ## _cond_s, MIPS_FP_COND_ ## COND, \ 10069169689Skan "__builtin_mips_" #INSN "_" #COND "_s", \ 10070169689Skan MIPS_BUILTIN_CMP_SINGLE, MIPS_INT_FTYPE_SF_SF, TARGET_FLAGS }, \ 10071169689Skan { CODE_FOR_mips_ ## INSN ## _cond_d, MIPS_FP_COND_ ## COND, \ 10072169689Skan "__builtin_mips_" #INSN "_" #COND "_d", \ 10073169689Skan MIPS_BUILTIN_CMP_SINGLE, MIPS_INT_FTYPE_DF_DF, TARGET_FLAGS } 10074169689Skan 10075169689Skan/* Define __builtin_mips_{any,all,upper,lower}_<INSN>_<COND>_ps. 10076169689Skan The lower and upper forms require TARGET_FLAGS while the any and all 10077169689Skan forms require MASK_MIPS3D. */ 10078169689Skan#define CMP_PS_BUILTINS(INSN, COND, TARGET_FLAGS) \ 10079169689Skan { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \ 10080169689Skan "__builtin_mips_any_" #INSN "_" #COND "_ps", \ 10081169689Skan MIPS_BUILTIN_CMP_ANY, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D }, \ 10082169689Skan { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \ 10083169689Skan "__builtin_mips_all_" #INSN "_" #COND "_ps", \ 10084169689Skan MIPS_BUILTIN_CMP_ALL, MIPS_INT_FTYPE_V2SF_V2SF, MASK_MIPS3D }, \ 10085169689Skan { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \ 10086169689Skan "__builtin_mips_lower_" #INSN "_" #COND "_ps", \ 10087169689Skan MIPS_BUILTIN_CMP_LOWER, MIPS_INT_FTYPE_V2SF_V2SF, TARGET_FLAGS }, \ 10088169689Skan { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \ 10089169689Skan "__builtin_mips_upper_" #INSN "_" #COND "_ps", \ 10090169689Skan MIPS_BUILTIN_CMP_UPPER, MIPS_INT_FTYPE_V2SF_V2SF, TARGET_FLAGS } 10091169689Skan 10092169689Skan/* Define __builtin_mips_{any,all}_<INSN>_<COND>_4s. The functions 10093169689Skan require MASK_MIPS3D. */ 10094169689Skan#define CMP_4S_BUILTINS(INSN, COND) \ 10095169689Skan { CODE_FOR_mips_ ## INSN ## _cond_4s, MIPS_FP_COND_ ## COND, \ 10096169689Skan "__builtin_mips_any_" #INSN "_" #COND "_4s", \ 10097169689Skan MIPS_BUILTIN_CMP_ANY, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF, \ 10098169689Skan MASK_MIPS3D }, \ 10099169689Skan { CODE_FOR_mips_ ## INSN ## _cond_4s, MIPS_FP_COND_ ## COND, \ 10100169689Skan "__builtin_mips_all_" #INSN "_" #COND "_4s", \ 10101169689Skan MIPS_BUILTIN_CMP_ALL, MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF, \ 10102169689Skan MASK_MIPS3D } 10103169689Skan 10104169689Skan/* Define __builtin_mips_mov{t,f}_<INSN>_<COND>_ps. The comparison 10105169689Skan instruction requires TARGET_FLAGS. */ 10106169689Skan#define MOVTF_BUILTINS(INSN, COND, TARGET_FLAGS) \ 10107169689Skan { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \ 10108169689Skan "__builtin_mips_movt_" #INSN "_" #COND "_ps", \ 10109169689Skan MIPS_BUILTIN_MOVT, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF, \ 10110169689Skan TARGET_FLAGS }, \ 10111169689Skan { CODE_FOR_mips_ ## INSN ## _cond_ps, MIPS_FP_COND_ ## COND, \ 10112169689Skan "__builtin_mips_movf_" #INSN "_" #COND "_ps", \ 10113169689Skan MIPS_BUILTIN_MOVF, MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF, \ 10114169689Skan TARGET_FLAGS } 10115169689Skan 10116169689Skan/* Define all the builtins related to c.cond.fmt condition COND. */ 10117169689Skan#define CMP_BUILTINS(COND) \ 10118169689Skan MOVTF_BUILTINS (c, COND, MASK_PAIRED_SINGLE_FLOAT), \ 10119169689Skan MOVTF_BUILTINS (cabs, COND, MASK_MIPS3D), \ 10120169689Skan CMP_SCALAR_BUILTINS (cabs, COND, MASK_MIPS3D), \ 10121169689Skan CMP_PS_BUILTINS (c, COND, MASK_PAIRED_SINGLE_FLOAT), \ 10122169689Skan CMP_PS_BUILTINS (cabs, COND, MASK_MIPS3D), \ 10123169689Skan CMP_4S_BUILTINS (c, COND), \ 10124169689Skan CMP_4S_BUILTINS (cabs, COND) 10125169689Skan 10126169689Skanstatic const struct builtin_description mips_bdesc[] = 10127169689Skan{ 10128169689Skan DIRECT_BUILTIN (pll_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE_FLOAT), 10129169689Skan DIRECT_BUILTIN (pul_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE_FLOAT), 10130169689Skan DIRECT_BUILTIN (plu_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE_FLOAT), 10131169689Skan DIRECT_BUILTIN (puu_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_PAIRED_SINGLE_FLOAT), 10132169689Skan DIRECT_BUILTIN (cvt_ps_s, MIPS_V2SF_FTYPE_SF_SF, MASK_PAIRED_SINGLE_FLOAT), 10133169689Skan DIRECT_BUILTIN (cvt_s_pl, MIPS_SF_FTYPE_V2SF, MASK_PAIRED_SINGLE_FLOAT), 10134169689Skan DIRECT_BUILTIN (cvt_s_pu, MIPS_SF_FTYPE_V2SF, MASK_PAIRED_SINGLE_FLOAT), 10135169689Skan DIRECT_BUILTIN (abs_ps, MIPS_V2SF_FTYPE_V2SF, MASK_PAIRED_SINGLE_FLOAT), 10136169689Skan 10137169689Skan DIRECT_BUILTIN (alnv_ps, MIPS_V2SF_FTYPE_V2SF_V2SF_INT, 10138169689Skan MASK_PAIRED_SINGLE_FLOAT), 10139169689Skan DIRECT_BUILTIN (addr_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_MIPS3D), 10140169689Skan DIRECT_BUILTIN (mulr_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_MIPS3D), 10141169689Skan DIRECT_BUILTIN (cvt_pw_ps, MIPS_V2SF_FTYPE_V2SF, MASK_MIPS3D), 10142169689Skan DIRECT_BUILTIN (cvt_ps_pw, MIPS_V2SF_FTYPE_V2SF, MASK_MIPS3D), 10143169689Skan 10144169689Skan DIRECT_BUILTIN (recip1_s, MIPS_SF_FTYPE_SF, MASK_MIPS3D), 10145169689Skan DIRECT_BUILTIN (recip1_d, MIPS_DF_FTYPE_DF, MASK_MIPS3D), 10146169689Skan DIRECT_BUILTIN (recip1_ps, MIPS_V2SF_FTYPE_V2SF, MASK_MIPS3D), 10147169689Skan DIRECT_BUILTIN (recip2_s, MIPS_SF_FTYPE_SF_SF, MASK_MIPS3D), 10148169689Skan DIRECT_BUILTIN (recip2_d, MIPS_DF_FTYPE_DF_DF, MASK_MIPS3D), 10149169689Skan DIRECT_BUILTIN (recip2_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_MIPS3D), 10150169689Skan 10151169689Skan DIRECT_BUILTIN (rsqrt1_s, MIPS_SF_FTYPE_SF, MASK_MIPS3D), 10152169689Skan DIRECT_BUILTIN (rsqrt1_d, MIPS_DF_FTYPE_DF, MASK_MIPS3D), 10153169689Skan DIRECT_BUILTIN (rsqrt1_ps, MIPS_V2SF_FTYPE_V2SF, MASK_MIPS3D), 10154169689Skan DIRECT_BUILTIN (rsqrt2_s, MIPS_SF_FTYPE_SF_SF, MASK_MIPS3D), 10155169689Skan DIRECT_BUILTIN (rsqrt2_d, MIPS_DF_FTYPE_DF_DF, MASK_MIPS3D), 10156169689Skan DIRECT_BUILTIN (rsqrt2_ps, MIPS_V2SF_FTYPE_V2SF_V2SF, MASK_MIPS3D), 10157169689Skan 10158169689Skan MIPS_FP_CONDITIONS (CMP_BUILTINS) 10159169689Skan}; 10160169689Skan 10161169689Skan/* Builtin functions for the SB-1 processor. */ 10162169689Skan 10163169689Skan#define CODE_FOR_mips_sqrt_ps CODE_FOR_sqrtv2sf2 10164169689Skan 10165169689Skanstatic const struct builtin_description sb1_bdesc[] = 10166169689Skan{ 10167169689Skan DIRECT_BUILTIN (sqrt_ps, MIPS_V2SF_FTYPE_V2SF, MASK_PAIRED_SINGLE_FLOAT) 10168169689Skan}; 10169169689Skan 10170169689Skan/* Builtin functions for DSP ASE. */ 10171169689Skan 10172169689Skan#define CODE_FOR_mips_addq_ph CODE_FOR_addv2hi3 10173169689Skan#define CODE_FOR_mips_addu_qb CODE_FOR_addv4qi3 10174169689Skan#define CODE_FOR_mips_subq_ph CODE_FOR_subv2hi3 10175169689Skan#define CODE_FOR_mips_subu_qb CODE_FOR_subv4qi3 10176169689Skan 10177169689Skan/* Define a MIPS_BUILTIN_DIRECT_NO_TARGET function for instruction 10178169689Skan CODE_FOR_mips_<INSN>. FUNCTION_TYPE and TARGET_FLAGS are 10179169689Skan builtin_description fields. */ 10180169689Skan#define DIRECT_NO_TARGET_BUILTIN(INSN, FUNCTION_TYPE, TARGET_FLAGS) \ 10181169689Skan { CODE_FOR_mips_ ## INSN, 0, "__builtin_mips_" #INSN, \ 10182169689Skan MIPS_BUILTIN_DIRECT_NO_TARGET, FUNCTION_TYPE, TARGET_FLAGS } 10183169689Skan 10184169689Skan/* Define __builtin_mips_bposge<VALUE>. <VALUE> is 32 for the MIPS32 DSP 10185169689Skan branch instruction. TARGET_FLAGS is a builtin_description field. */ 10186169689Skan#define BPOSGE_BUILTIN(VALUE, TARGET_FLAGS) \ 10187169689Skan { CODE_FOR_mips_bposge, 0, "__builtin_mips_bposge" #VALUE, \ 10188169689Skan MIPS_BUILTIN_BPOSGE ## VALUE, MIPS_SI_FTYPE_VOID, TARGET_FLAGS } 10189169689Skan 10190169689Skanstatic const struct builtin_description dsp_bdesc[] = 10191169689Skan{ 10192169689Skan DIRECT_BUILTIN (addq_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP), 10193169689Skan DIRECT_BUILTIN (addq_s_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP), 10194169689Skan DIRECT_BUILTIN (addq_s_w, MIPS_SI_FTYPE_SI_SI, MASK_DSP), 10195169689Skan DIRECT_BUILTIN (addu_qb, MIPS_V4QI_FTYPE_V4QI_V4QI, MASK_DSP), 10196169689Skan DIRECT_BUILTIN (addu_s_qb, MIPS_V4QI_FTYPE_V4QI_V4QI, MASK_DSP), 10197169689Skan DIRECT_BUILTIN (subq_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP), 10198169689Skan DIRECT_BUILTIN (subq_s_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP), 10199169689Skan DIRECT_BUILTIN (subq_s_w, MIPS_SI_FTYPE_SI_SI, MASK_DSP), 10200169689Skan DIRECT_BUILTIN (subu_qb, MIPS_V4QI_FTYPE_V4QI_V4QI, MASK_DSP), 10201169689Skan DIRECT_BUILTIN (subu_s_qb, MIPS_V4QI_FTYPE_V4QI_V4QI, MASK_DSP), 10202169689Skan DIRECT_BUILTIN (addsc, MIPS_SI_FTYPE_SI_SI, MASK_DSP), 10203169689Skan DIRECT_BUILTIN (addwc, MIPS_SI_FTYPE_SI_SI, MASK_DSP), 10204169689Skan DIRECT_BUILTIN (modsub, MIPS_SI_FTYPE_SI_SI, MASK_DSP), 10205169689Skan DIRECT_BUILTIN (raddu_w_qb, MIPS_SI_FTYPE_V4QI, MASK_DSP), 10206169689Skan DIRECT_BUILTIN (absq_s_ph, MIPS_V2HI_FTYPE_V2HI, MASK_DSP), 10207169689Skan DIRECT_BUILTIN (absq_s_w, MIPS_SI_FTYPE_SI, MASK_DSP), 10208169689Skan DIRECT_BUILTIN (precrq_qb_ph, MIPS_V4QI_FTYPE_V2HI_V2HI, MASK_DSP), 10209169689Skan DIRECT_BUILTIN (precrq_ph_w, MIPS_V2HI_FTYPE_SI_SI, MASK_DSP), 10210169689Skan DIRECT_BUILTIN (precrq_rs_ph_w, MIPS_V2HI_FTYPE_SI_SI, MASK_DSP), 10211169689Skan DIRECT_BUILTIN (precrqu_s_qb_ph, MIPS_V4QI_FTYPE_V2HI_V2HI, MASK_DSP), 10212169689Skan DIRECT_BUILTIN (preceq_w_phl, MIPS_SI_FTYPE_V2HI, MASK_DSP), 10213169689Skan DIRECT_BUILTIN (preceq_w_phr, MIPS_SI_FTYPE_V2HI, MASK_DSP), 10214169689Skan DIRECT_BUILTIN (precequ_ph_qbl, MIPS_V2HI_FTYPE_V4QI, MASK_DSP), 10215169689Skan DIRECT_BUILTIN (precequ_ph_qbr, MIPS_V2HI_FTYPE_V4QI, MASK_DSP), 10216169689Skan DIRECT_BUILTIN (precequ_ph_qbla, MIPS_V2HI_FTYPE_V4QI, MASK_DSP), 10217169689Skan DIRECT_BUILTIN (precequ_ph_qbra, MIPS_V2HI_FTYPE_V4QI, MASK_DSP), 10218169689Skan DIRECT_BUILTIN (preceu_ph_qbl, MIPS_V2HI_FTYPE_V4QI, MASK_DSP), 10219169689Skan DIRECT_BUILTIN (preceu_ph_qbr, MIPS_V2HI_FTYPE_V4QI, MASK_DSP), 10220169689Skan DIRECT_BUILTIN (preceu_ph_qbla, MIPS_V2HI_FTYPE_V4QI, MASK_DSP), 10221169689Skan DIRECT_BUILTIN (preceu_ph_qbra, MIPS_V2HI_FTYPE_V4QI, MASK_DSP), 10222169689Skan DIRECT_BUILTIN (shll_qb, MIPS_V4QI_FTYPE_V4QI_SI, MASK_DSP), 10223169689Skan DIRECT_BUILTIN (shll_ph, MIPS_V2HI_FTYPE_V2HI_SI, MASK_DSP), 10224169689Skan DIRECT_BUILTIN (shll_s_ph, MIPS_V2HI_FTYPE_V2HI_SI, MASK_DSP), 10225169689Skan DIRECT_BUILTIN (shll_s_w, MIPS_SI_FTYPE_SI_SI, MASK_DSP), 10226169689Skan DIRECT_BUILTIN (shrl_qb, MIPS_V4QI_FTYPE_V4QI_SI, MASK_DSP), 10227169689Skan DIRECT_BUILTIN (shra_ph, MIPS_V2HI_FTYPE_V2HI_SI, MASK_DSP), 10228169689Skan DIRECT_BUILTIN (shra_r_ph, MIPS_V2HI_FTYPE_V2HI_SI, MASK_DSP), 10229169689Skan DIRECT_BUILTIN (shra_r_w, MIPS_SI_FTYPE_SI_SI, MASK_DSP), 10230169689Skan DIRECT_BUILTIN (muleu_s_ph_qbl, MIPS_V2HI_FTYPE_V4QI_V2HI, MASK_DSP), 10231169689Skan DIRECT_BUILTIN (muleu_s_ph_qbr, MIPS_V2HI_FTYPE_V4QI_V2HI, MASK_DSP), 10232169689Skan DIRECT_BUILTIN (mulq_rs_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP), 10233169689Skan DIRECT_BUILTIN (muleq_s_w_phl, MIPS_SI_FTYPE_V2HI_V2HI, MASK_DSP), 10234169689Skan DIRECT_BUILTIN (muleq_s_w_phr, MIPS_SI_FTYPE_V2HI_V2HI, MASK_DSP), 10235169689Skan DIRECT_BUILTIN (dpau_h_qbl, MIPS_DI_FTYPE_DI_V4QI_V4QI, MASK_DSP), 10236169689Skan DIRECT_BUILTIN (dpau_h_qbr, MIPS_DI_FTYPE_DI_V4QI_V4QI, MASK_DSP), 10237169689Skan DIRECT_BUILTIN (dpsu_h_qbl, MIPS_DI_FTYPE_DI_V4QI_V4QI, MASK_DSP), 10238169689Skan DIRECT_BUILTIN (dpsu_h_qbr, MIPS_DI_FTYPE_DI_V4QI_V4QI, MASK_DSP), 10239169689Skan DIRECT_BUILTIN (dpaq_s_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP), 10240169689Skan DIRECT_BUILTIN (dpsq_s_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP), 10241169689Skan DIRECT_BUILTIN (mulsaq_s_w_ph, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP), 10242169689Skan DIRECT_BUILTIN (dpaq_sa_l_w, MIPS_DI_FTYPE_DI_SI_SI, MASK_DSP), 10243169689Skan DIRECT_BUILTIN (dpsq_sa_l_w, MIPS_DI_FTYPE_DI_SI_SI, MASK_DSP), 10244169689Skan DIRECT_BUILTIN (maq_s_w_phl, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP), 10245169689Skan DIRECT_BUILTIN (maq_s_w_phr, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP), 10246169689Skan DIRECT_BUILTIN (maq_sa_w_phl, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP), 10247169689Skan DIRECT_BUILTIN (maq_sa_w_phr, MIPS_DI_FTYPE_DI_V2HI_V2HI, MASK_DSP), 10248169689Skan DIRECT_BUILTIN (bitrev, MIPS_SI_FTYPE_SI, MASK_DSP), 10249169689Skan DIRECT_BUILTIN (insv, MIPS_SI_FTYPE_SI_SI, MASK_DSP), 10250169689Skan DIRECT_BUILTIN (repl_qb, MIPS_V4QI_FTYPE_SI, MASK_DSP), 10251169689Skan DIRECT_BUILTIN (repl_ph, MIPS_V2HI_FTYPE_SI, MASK_DSP), 10252169689Skan DIRECT_NO_TARGET_BUILTIN (cmpu_eq_qb, MIPS_VOID_FTYPE_V4QI_V4QI, MASK_DSP), 10253169689Skan DIRECT_NO_TARGET_BUILTIN (cmpu_lt_qb, MIPS_VOID_FTYPE_V4QI_V4QI, MASK_DSP), 10254169689Skan DIRECT_NO_TARGET_BUILTIN (cmpu_le_qb, MIPS_VOID_FTYPE_V4QI_V4QI, MASK_DSP), 10255169689Skan DIRECT_BUILTIN (cmpgu_eq_qb, MIPS_SI_FTYPE_V4QI_V4QI, MASK_DSP), 10256169689Skan DIRECT_BUILTIN (cmpgu_lt_qb, MIPS_SI_FTYPE_V4QI_V4QI, MASK_DSP), 10257169689Skan DIRECT_BUILTIN (cmpgu_le_qb, MIPS_SI_FTYPE_V4QI_V4QI, MASK_DSP), 10258169689Skan DIRECT_NO_TARGET_BUILTIN (cmp_eq_ph, MIPS_VOID_FTYPE_V2HI_V2HI, MASK_DSP), 10259169689Skan DIRECT_NO_TARGET_BUILTIN (cmp_lt_ph, MIPS_VOID_FTYPE_V2HI_V2HI, MASK_DSP), 10260169689Skan DIRECT_NO_TARGET_BUILTIN (cmp_le_ph, MIPS_VOID_FTYPE_V2HI_V2HI, MASK_DSP), 10261169689Skan DIRECT_BUILTIN (pick_qb, MIPS_V4QI_FTYPE_V4QI_V4QI, MASK_DSP), 10262169689Skan DIRECT_BUILTIN (pick_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP), 10263169689Skan DIRECT_BUILTIN (packrl_ph, MIPS_V2HI_FTYPE_V2HI_V2HI, MASK_DSP), 10264169689Skan DIRECT_BUILTIN (extr_w, MIPS_SI_FTYPE_DI_SI, MASK_DSP), 10265169689Skan DIRECT_BUILTIN (extr_r_w, MIPS_SI_FTYPE_DI_SI, MASK_DSP), 10266169689Skan DIRECT_BUILTIN (extr_rs_w, MIPS_SI_FTYPE_DI_SI, MASK_DSP), 10267169689Skan DIRECT_BUILTIN (extr_s_h, MIPS_SI_FTYPE_DI_SI, MASK_DSP), 10268169689Skan DIRECT_BUILTIN (extp, MIPS_SI_FTYPE_DI_SI, MASK_DSP), 10269169689Skan DIRECT_BUILTIN (extpdp, MIPS_SI_FTYPE_DI_SI, MASK_DSP), 10270169689Skan DIRECT_BUILTIN (shilo, MIPS_DI_FTYPE_DI_SI, MASK_DSP), 10271169689Skan DIRECT_BUILTIN (mthlip, MIPS_DI_FTYPE_DI_SI, MASK_DSP), 10272169689Skan DIRECT_NO_TARGET_BUILTIN (wrdsp, MIPS_VOID_FTYPE_SI_SI, MASK_DSP), 10273169689Skan DIRECT_BUILTIN (rddsp, MIPS_SI_FTYPE_SI, MASK_DSP), 10274169689Skan DIRECT_BUILTIN (lbux, MIPS_SI_FTYPE_PTR_SI, MASK_DSP), 10275169689Skan DIRECT_BUILTIN (lhx, MIPS_SI_FTYPE_PTR_SI, MASK_DSP), 10276169689Skan DIRECT_BUILTIN (lwx, MIPS_SI_FTYPE_PTR_SI, MASK_DSP), 10277169689Skan BPOSGE_BUILTIN (32, MASK_DSP) 10278169689Skan}; 10279169689Skan 10280169689Skan/* This helps provide a mapping from builtin function codes to bdesc 10281169689Skan arrays. */ 10282169689Skan 10283169689Skanstruct bdesc_map 10284169689Skan{ 10285169689Skan /* The builtin function table that this entry describes. */ 10286169689Skan const struct builtin_description *bdesc; 10287169689Skan 10288169689Skan /* The number of entries in the builtin function table. */ 10289169689Skan unsigned int size; 10290169689Skan 10291169689Skan /* The target processor that supports these builtin functions. 10292169689Skan PROCESSOR_MAX means we enable them for all processors. */ 10293169689Skan enum processor_type proc; 10294169689Skan}; 10295169689Skan 10296169689Skanstatic const struct bdesc_map bdesc_arrays[] = 10297169689Skan{ 10298169689Skan { mips_bdesc, ARRAY_SIZE (mips_bdesc), PROCESSOR_MAX }, 10299169689Skan { sb1_bdesc, ARRAY_SIZE (sb1_bdesc), PROCESSOR_SB1 }, 10300169689Skan { dsp_bdesc, ARRAY_SIZE (dsp_bdesc), PROCESSOR_MAX } 10301169689Skan}; 10302169689Skan 10303169689Skan/* Take the head of argument list *ARGLIST and convert it into a form 10304169689Skan suitable for input operand OP of instruction ICODE. Return the value 10305169689Skan and point *ARGLIST at the next element of the list. */ 10306169689Skan 10307169689Skanstatic rtx 10308169689Skanmips_prepare_builtin_arg (enum insn_code icode, 10309169689Skan unsigned int op, tree *arglist) 10310169689Skan{ 10311169689Skan rtx value; 10312169689Skan enum machine_mode mode; 10313169689Skan 10314169689Skan value = expand_normal (TREE_VALUE (*arglist)); 10315169689Skan mode = insn_data[icode].operand[op].mode; 10316169689Skan if (!insn_data[icode].operand[op].predicate (value, mode)) 10317169689Skan { 10318169689Skan value = copy_to_mode_reg (mode, value); 10319169689Skan /* Check the predicate again. */ 10320169689Skan if (!insn_data[icode].operand[op].predicate (value, mode)) 10321169689Skan { 10322169689Skan error ("invalid argument to builtin function"); 10323169689Skan return const0_rtx; 10324169689Skan } 10325169689Skan } 10326169689Skan 10327169689Skan *arglist = TREE_CHAIN (*arglist); 10328169689Skan return value; 10329169689Skan} 10330169689Skan 10331169689Skan/* Return an rtx suitable for output operand OP of instruction ICODE. 10332169689Skan If TARGET is non-null, try to use it where possible. */ 10333169689Skan 10334169689Skanstatic rtx 10335169689Skanmips_prepare_builtin_target (enum insn_code icode, unsigned int op, rtx target) 10336169689Skan{ 10337169689Skan enum machine_mode mode; 10338169689Skan 10339169689Skan mode = insn_data[icode].operand[op].mode; 10340169689Skan if (target == 0 || !insn_data[icode].operand[op].predicate (target, mode)) 10341169689Skan target = gen_reg_rtx (mode); 10342169689Skan 10343169689Skan return target; 10344169689Skan} 10345169689Skan 10346169689Skan/* Expand builtin functions. This is called from TARGET_EXPAND_BUILTIN. */ 10347169689Skan 10348169689Skanrtx 10349169689Skanmips_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED, 10350169689Skan enum machine_mode mode ATTRIBUTE_UNUSED, 10351169689Skan int ignore ATTRIBUTE_UNUSED) 10352169689Skan{ 10353169689Skan enum insn_code icode; 10354169689Skan enum mips_builtin_type type; 10355169689Skan tree fndecl, arglist; 10356169689Skan unsigned int fcode; 10357169689Skan const struct builtin_description *bdesc; 10358169689Skan const struct bdesc_map *m; 10359169689Skan 10360169689Skan fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0); 10361169689Skan arglist = TREE_OPERAND (exp, 1); 10362169689Skan fcode = DECL_FUNCTION_CODE (fndecl); 10363169689Skan 10364169689Skan bdesc = NULL; 10365169689Skan for (m = bdesc_arrays; m < &bdesc_arrays[ARRAY_SIZE (bdesc_arrays)]; m++) 10366169689Skan { 10367169689Skan if (fcode < m->size) 10368169689Skan { 10369169689Skan bdesc = m->bdesc; 10370169689Skan icode = bdesc[fcode].icode; 10371169689Skan type = bdesc[fcode].builtin_type; 10372169689Skan break; 10373169689Skan } 10374169689Skan fcode -= m->size; 10375169689Skan } 10376169689Skan if (bdesc == NULL) 10377169689Skan return 0; 10378169689Skan 10379169689Skan switch (type) 10380169689Skan { 10381169689Skan case MIPS_BUILTIN_DIRECT: 10382169689Skan return mips_expand_builtin_direct (icode, target, arglist, true); 10383169689Skan 10384169689Skan case MIPS_BUILTIN_DIRECT_NO_TARGET: 10385169689Skan return mips_expand_builtin_direct (icode, target, arglist, false); 10386169689Skan 10387169689Skan case MIPS_BUILTIN_MOVT: 10388169689Skan case MIPS_BUILTIN_MOVF: 10389169689Skan return mips_expand_builtin_movtf (type, icode, bdesc[fcode].cond, 10390169689Skan target, arglist); 10391169689Skan 10392169689Skan case MIPS_BUILTIN_CMP_ANY: 10393169689Skan case MIPS_BUILTIN_CMP_ALL: 10394169689Skan case MIPS_BUILTIN_CMP_UPPER: 10395169689Skan case MIPS_BUILTIN_CMP_LOWER: 10396169689Skan case MIPS_BUILTIN_CMP_SINGLE: 10397169689Skan return mips_expand_builtin_compare (type, icode, bdesc[fcode].cond, 10398169689Skan target, arglist); 10399169689Skan 10400169689Skan case MIPS_BUILTIN_BPOSGE32: 10401169689Skan return mips_expand_builtin_bposge (type, target); 10402169689Skan 10403169689Skan default: 10404169689Skan return 0; 10405169689Skan } 10406169689Skan} 10407169689Skan 10408169689Skan/* Init builtin functions. This is called from TARGET_INIT_BUILTIN. */ 10409169689Skan 10410169689Skanvoid 10411169689Skanmips_init_builtins (void) 10412169689Skan{ 10413169689Skan const struct builtin_description *d; 10414169689Skan const struct bdesc_map *m; 10415169689Skan tree types[(int) MIPS_MAX_FTYPE_MAX]; 10416169689Skan tree V2SF_type_node; 10417169689Skan tree V2HI_type_node; 10418169689Skan tree V4QI_type_node; 10419169689Skan unsigned int offset; 10420169689Skan 10421169689Skan /* We have only builtins for -mpaired-single, -mips3d and -mdsp. */ 10422169689Skan if (!TARGET_PAIRED_SINGLE_FLOAT && !TARGET_DSP) 10423169689Skan return; 10424169689Skan 10425169689Skan if (TARGET_PAIRED_SINGLE_FLOAT) 10426169689Skan { 10427169689Skan V2SF_type_node = build_vector_type_for_mode (float_type_node, V2SFmode); 10428169689Skan 10429169689Skan types[MIPS_V2SF_FTYPE_V2SF] 10430169689Skan = build_function_type_list (V2SF_type_node, V2SF_type_node, NULL_TREE); 10431169689Skan 10432169689Skan types[MIPS_V2SF_FTYPE_V2SF_V2SF] 10433169689Skan = build_function_type_list (V2SF_type_node, 10434169689Skan V2SF_type_node, V2SF_type_node, NULL_TREE); 10435169689Skan 10436169689Skan types[MIPS_V2SF_FTYPE_V2SF_V2SF_INT] 10437169689Skan = build_function_type_list (V2SF_type_node, 10438169689Skan V2SF_type_node, V2SF_type_node, 10439169689Skan integer_type_node, NULL_TREE); 10440169689Skan 10441169689Skan types[MIPS_V2SF_FTYPE_V2SF_V2SF_V2SF_V2SF] 10442169689Skan = build_function_type_list (V2SF_type_node, 10443169689Skan V2SF_type_node, V2SF_type_node, 10444169689Skan V2SF_type_node, V2SF_type_node, NULL_TREE); 10445169689Skan 10446169689Skan types[MIPS_V2SF_FTYPE_SF_SF] 10447169689Skan = build_function_type_list (V2SF_type_node, 10448169689Skan float_type_node, float_type_node, NULL_TREE); 10449169689Skan 10450169689Skan types[MIPS_INT_FTYPE_V2SF_V2SF] 10451169689Skan = build_function_type_list (integer_type_node, 10452169689Skan V2SF_type_node, V2SF_type_node, NULL_TREE); 10453169689Skan 10454169689Skan types[MIPS_INT_FTYPE_V2SF_V2SF_V2SF_V2SF] 10455169689Skan = build_function_type_list (integer_type_node, 10456169689Skan V2SF_type_node, V2SF_type_node, 10457169689Skan V2SF_type_node, V2SF_type_node, NULL_TREE); 10458169689Skan 10459169689Skan types[MIPS_INT_FTYPE_SF_SF] 10460169689Skan = build_function_type_list (integer_type_node, 10461169689Skan float_type_node, float_type_node, NULL_TREE); 10462169689Skan 10463169689Skan types[MIPS_INT_FTYPE_DF_DF] 10464169689Skan = build_function_type_list (integer_type_node, 10465169689Skan double_type_node, double_type_node, NULL_TREE); 10466169689Skan 10467169689Skan types[MIPS_SF_FTYPE_V2SF] 10468169689Skan = build_function_type_list (float_type_node, V2SF_type_node, NULL_TREE); 10469169689Skan 10470169689Skan types[MIPS_SF_FTYPE_SF] 10471169689Skan = build_function_type_list (float_type_node, 10472169689Skan float_type_node, NULL_TREE); 10473169689Skan 10474169689Skan types[MIPS_SF_FTYPE_SF_SF] 10475169689Skan = build_function_type_list (float_type_node, 10476169689Skan float_type_node, float_type_node, NULL_TREE); 10477169689Skan 10478169689Skan types[MIPS_DF_FTYPE_DF] 10479169689Skan = build_function_type_list (double_type_node, 10480169689Skan double_type_node, NULL_TREE); 10481169689Skan 10482169689Skan types[MIPS_DF_FTYPE_DF_DF] 10483169689Skan = build_function_type_list (double_type_node, 10484169689Skan double_type_node, double_type_node, NULL_TREE); 10485169689Skan } 10486169689Skan 10487169689Skan if (TARGET_DSP) 10488169689Skan { 10489169689Skan V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode); 10490169689Skan V4QI_type_node = build_vector_type_for_mode (intQI_type_node, V4QImode); 10491169689Skan 10492169689Skan types[MIPS_V2HI_FTYPE_V2HI_V2HI] 10493169689Skan = build_function_type_list (V2HI_type_node, 10494169689Skan V2HI_type_node, V2HI_type_node, 10495169689Skan NULL_TREE); 10496169689Skan 10497169689Skan types[MIPS_SI_FTYPE_SI_SI] 10498169689Skan = build_function_type_list (intSI_type_node, 10499169689Skan intSI_type_node, intSI_type_node, 10500169689Skan NULL_TREE); 10501169689Skan 10502169689Skan types[MIPS_V4QI_FTYPE_V4QI_V4QI] 10503169689Skan = build_function_type_list (V4QI_type_node, 10504169689Skan V4QI_type_node, V4QI_type_node, 10505169689Skan NULL_TREE); 10506169689Skan 10507169689Skan types[MIPS_SI_FTYPE_V4QI] 10508169689Skan = build_function_type_list (intSI_type_node, 10509169689Skan V4QI_type_node, 10510169689Skan NULL_TREE); 10511169689Skan 10512169689Skan types[MIPS_V2HI_FTYPE_V2HI] 10513169689Skan = build_function_type_list (V2HI_type_node, 10514169689Skan V2HI_type_node, 10515169689Skan NULL_TREE); 10516169689Skan 10517169689Skan types[MIPS_SI_FTYPE_SI] 10518169689Skan = build_function_type_list (intSI_type_node, 10519169689Skan intSI_type_node, 10520169689Skan NULL_TREE); 10521169689Skan 10522169689Skan types[MIPS_V4QI_FTYPE_V2HI_V2HI] 10523169689Skan = build_function_type_list (V4QI_type_node, 10524169689Skan V2HI_type_node, V2HI_type_node, 10525169689Skan NULL_TREE); 10526169689Skan 10527169689Skan types[MIPS_V2HI_FTYPE_SI_SI] 10528169689Skan = build_function_type_list (V2HI_type_node, 10529169689Skan intSI_type_node, intSI_type_node, 10530169689Skan NULL_TREE); 10531169689Skan 10532169689Skan types[MIPS_SI_FTYPE_V2HI] 10533169689Skan = build_function_type_list (intSI_type_node, 10534169689Skan V2HI_type_node, 10535169689Skan NULL_TREE); 10536169689Skan 10537169689Skan types[MIPS_V2HI_FTYPE_V4QI] 10538169689Skan = build_function_type_list (V2HI_type_node, 10539169689Skan V4QI_type_node, 10540169689Skan NULL_TREE); 10541169689Skan 10542169689Skan types[MIPS_V4QI_FTYPE_V4QI_SI] 10543169689Skan = build_function_type_list (V4QI_type_node, 10544169689Skan V4QI_type_node, intSI_type_node, 10545169689Skan NULL_TREE); 10546169689Skan 10547169689Skan types[MIPS_V2HI_FTYPE_V2HI_SI] 10548169689Skan = build_function_type_list (V2HI_type_node, 10549169689Skan V2HI_type_node, intSI_type_node, 10550169689Skan NULL_TREE); 10551169689Skan 10552169689Skan types[MIPS_V2HI_FTYPE_V4QI_V2HI] 10553169689Skan = build_function_type_list (V2HI_type_node, 10554169689Skan V4QI_type_node, V2HI_type_node, 10555169689Skan NULL_TREE); 10556169689Skan 10557169689Skan types[MIPS_SI_FTYPE_V2HI_V2HI] 10558169689Skan = build_function_type_list (intSI_type_node, 10559169689Skan V2HI_type_node, V2HI_type_node, 10560169689Skan NULL_TREE); 10561169689Skan 10562169689Skan types[MIPS_DI_FTYPE_DI_V4QI_V4QI] 10563169689Skan = build_function_type_list (intDI_type_node, 10564169689Skan intDI_type_node, V4QI_type_node, V4QI_type_node, 10565169689Skan NULL_TREE); 10566169689Skan 10567169689Skan types[MIPS_DI_FTYPE_DI_V2HI_V2HI] 10568169689Skan = build_function_type_list (intDI_type_node, 10569169689Skan intDI_type_node, V2HI_type_node, V2HI_type_node, 10570169689Skan NULL_TREE); 10571169689Skan 10572169689Skan types[MIPS_DI_FTYPE_DI_SI_SI] 10573169689Skan = build_function_type_list (intDI_type_node, 10574169689Skan intDI_type_node, intSI_type_node, intSI_type_node, 10575169689Skan NULL_TREE); 10576169689Skan 10577169689Skan types[MIPS_V4QI_FTYPE_SI] 10578169689Skan = build_function_type_list (V4QI_type_node, 10579169689Skan intSI_type_node, 10580169689Skan NULL_TREE); 10581169689Skan 10582169689Skan types[MIPS_V2HI_FTYPE_SI] 10583169689Skan = build_function_type_list (V2HI_type_node, 10584169689Skan intSI_type_node, 10585169689Skan NULL_TREE); 10586169689Skan 10587169689Skan types[MIPS_VOID_FTYPE_V4QI_V4QI] 10588169689Skan = build_function_type_list (void_type_node, 10589169689Skan V4QI_type_node, V4QI_type_node, 10590169689Skan NULL_TREE); 10591169689Skan 10592169689Skan types[MIPS_SI_FTYPE_V4QI_V4QI] 10593169689Skan = build_function_type_list (intSI_type_node, 10594169689Skan V4QI_type_node, V4QI_type_node, 10595169689Skan NULL_TREE); 10596169689Skan 10597169689Skan types[MIPS_VOID_FTYPE_V2HI_V2HI] 10598169689Skan = build_function_type_list (void_type_node, 10599169689Skan V2HI_type_node, V2HI_type_node, 10600169689Skan NULL_TREE); 10601169689Skan 10602169689Skan types[MIPS_SI_FTYPE_DI_SI] 10603169689Skan = build_function_type_list (intSI_type_node, 10604169689Skan intDI_type_node, intSI_type_node, 10605169689Skan NULL_TREE); 10606169689Skan 10607169689Skan types[MIPS_DI_FTYPE_DI_SI] 10608169689Skan = build_function_type_list (intDI_type_node, 10609169689Skan intDI_type_node, intSI_type_node, 10610169689Skan NULL_TREE); 10611169689Skan 10612169689Skan types[MIPS_VOID_FTYPE_SI_SI] 10613169689Skan = build_function_type_list (void_type_node, 10614169689Skan intSI_type_node, intSI_type_node, 10615169689Skan NULL_TREE); 10616169689Skan 10617169689Skan types[MIPS_SI_FTYPE_PTR_SI] 10618169689Skan = build_function_type_list (intSI_type_node, 10619169689Skan ptr_type_node, intSI_type_node, 10620169689Skan NULL_TREE); 10621169689Skan 10622169689Skan types[MIPS_SI_FTYPE_VOID] 10623169689Skan = build_function_type (intSI_type_node, void_list_node); 10624169689Skan } 10625169689Skan 10626169689Skan /* Iterate through all of the bdesc arrays, initializing all of the 10627169689Skan builtin functions. */ 10628169689Skan 10629169689Skan offset = 0; 10630169689Skan for (m = bdesc_arrays; m < &bdesc_arrays[ARRAY_SIZE (bdesc_arrays)]; m++) 10631169689Skan { 10632169689Skan if (m->proc == PROCESSOR_MAX || (m->proc == mips_arch)) 10633169689Skan for (d = m->bdesc; d < &m->bdesc[m->size]; d++) 10634169689Skan if ((d->target_flags & target_flags) == d->target_flags) 10635169689Skan lang_hooks.builtin_function (d->name, types[d->function_type], 10636169689Skan d - m->bdesc + offset, 10637169689Skan BUILT_IN_MD, NULL, NULL); 10638169689Skan offset += m->size; 10639169689Skan } 10640169689Skan} 10641169689Skan 10642169689Skan/* Expand a MIPS_BUILTIN_DIRECT function. ICODE is the code of the 10643169689Skan .md pattern and ARGLIST is the list of function arguments. TARGET, 10644169689Skan if nonnull, suggests a good place to put the result. 10645169689Skan HAS_TARGET indicates the function must return something. */ 10646169689Skan 10647169689Skanstatic rtx 10648169689Skanmips_expand_builtin_direct (enum insn_code icode, rtx target, tree arglist, 10649169689Skan bool has_target) 10650169689Skan{ 10651169689Skan rtx ops[MAX_RECOG_OPERANDS]; 10652169689Skan int i = 0; 10653169689Skan 10654169689Skan if (has_target) 10655169689Skan { 10656169689Skan /* We save target to ops[0]. */ 10657169689Skan ops[0] = mips_prepare_builtin_target (icode, 0, target); 10658169689Skan i = 1; 10659169689Skan } 10660169689Skan 10661169689Skan /* We need to test if arglist is not zero. Some instructions have extra 10662169689Skan clobber registers. */ 10663169689Skan for (; i < insn_data[icode].n_operands && arglist != 0; i++) 10664169689Skan ops[i] = mips_prepare_builtin_arg (icode, i, &arglist); 10665169689Skan 10666169689Skan switch (i) 10667169689Skan { 10668169689Skan case 2: 10669169689Skan emit_insn (GEN_FCN (icode) (ops[0], ops[1])); 10670169689Skan break; 10671169689Skan 10672169689Skan case 3: 10673169689Skan emit_insn (GEN_FCN (icode) (ops[0], ops[1], ops[2])); 10674169689Skan break; 10675169689Skan 10676169689Skan case 4: 10677169689Skan emit_insn (GEN_FCN (icode) (ops[0], ops[1], ops[2], ops[3])); 10678169689Skan break; 10679169689Skan 10680169689Skan default: 10681169689Skan gcc_unreachable (); 10682169689Skan } 10683169689Skan return target; 10684169689Skan} 10685169689Skan 10686169689Skan/* Expand a __builtin_mips_movt_*_ps() or __builtin_mips_movf_*_ps() 10687169689Skan function (TYPE says which). ARGLIST is the list of arguments to the 10688169689Skan function, ICODE is the instruction that should be used to compare 10689169689Skan the first two arguments, and COND is the condition it should test. 10690169689Skan TARGET, if nonnull, suggests a good place to put the result. */ 10691169689Skan 10692169689Skanstatic rtx 10693169689Skanmips_expand_builtin_movtf (enum mips_builtin_type type, 10694169689Skan enum insn_code icode, enum mips_fp_condition cond, 10695169689Skan rtx target, tree arglist) 10696169689Skan{ 10697169689Skan rtx cmp_result, op0, op1; 10698169689Skan 10699169689Skan cmp_result = mips_prepare_builtin_target (icode, 0, 0); 10700169689Skan op0 = mips_prepare_builtin_arg (icode, 1, &arglist); 10701169689Skan op1 = mips_prepare_builtin_arg (icode, 2, &arglist); 10702169689Skan emit_insn (GEN_FCN (icode) (cmp_result, op0, op1, GEN_INT (cond))); 10703169689Skan 10704169689Skan icode = CODE_FOR_mips_cond_move_tf_ps; 10705169689Skan target = mips_prepare_builtin_target (icode, 0, target); 10706169689Skan if (type == MIPS_BUILTIN_MOVT) 10707169689Skan { 10708169689Skan op1 = mips_prepare_builtin_arg (icode, 2, &arglist); 10709169689Skan op0 = mips_prepare_builtin_arg (icode, 1, &arglist); 10710169689Skan } 10711169689Skan else 10712169689Skan { 10713169689Skan op0 = mips_prepare_builtin_arg (icode, 1, &arglist); 10714169689Skan op1 = mips_prepare_builtin_arg (icode, 2, &arglist); 10715169689Skan } 10716169689Skan emit_insn (gen_mips_cond_move_tf_ps (target, op0, op1, cmp_result)); 10717169689Skan return target; 10718169689Skan} 10719169689Skan 10720169689Skan/* Move VALUE_IF_TRUE into TARGET if CONDITION is true; move VALUE_IF_FALSE 10721169689Skan into TARGET otherwise. Return TARGET. */ 10722169689Skan 10723169689Skanstatic rtx 10724169689Skanmips_builtin_branch_and_move (rtx condition, rtx target, 10725169689Skan rtx value_if_true, rtx value_if_false) 10726169689Skan{ 10727169689Skan rtx true_label, done_label; 10728169689Skan 10729169689Skan true_label = gen_label_rtx (); 10730169689Skan done_label = gen_label_rtx (); 10731169689Skan 10732169689Skan /* First assume that CONDITION is false. */ 10733169689Skan emit_move_insn (target, value_if_false); 10734169689Skan 10735169689Skan /* Branch to TRUE_LABEL if CONDITION is true and DONE_LABEL otherwise. */ 10736169689Skan emit_jump_insn (gen_condjump (condition, true_label)); 10737169689Skan emit_jump_insn (gen_jump (done_label)); 10738169689Skan emit_barrier (); 10739169689Skan 10740169689Skan /* Fix TARGET if CONDITION is true. */ 10741169689Skan emit_label (true_label); 10742169689Skan emit_move_insn (target, value_if_true); 10743169689Skan 10744169689Skan emit_label (done_label); 10745169689Skan return target; 10746169689Skan} 10747169689Skan 10748169689Skan/* Expand a comparison builtin of type BUILTIN_TYPE. ICODE is the code 10749169689Skan of the comparison instruction and COND is the condition it should test. 10750169689Skan ARGLIST is the list of function arguments and TARGET, if nonnull, 10751169689Skan suggests a good place to put the boolean result. */ 10752169689Skan 10753169689Skanstatic rtx 10754169689Skanmips_expand_builtin_compare (enum mips_builtin_type builtin_type, 10755169689Skan enum insn_code icode, enum mips_fp_condition cond, 10756169689Skan rtx target, tree arglist) 10757169689Skan{ 10758169689Skan rtx offset, condition, cmp_result, ops[MAX_RECOG_OPERANDS]; 10759169689Skan int i; 10760169689Skan 10761169689Skan if (target == 0 || GET_MODE (target) != SImode) 10762169689Skan target = gen_reg_rtx (SImode); 10763169689Skan 10764169689Skan /* Prepare the operands to the comparison. */ 10765169689Skan cmp_result = mips_prepare_builtin_target (icode, 0, 0); 10766169689Skan for (i = 1; i < insn_data[icode].n_operands - 1; i++) 10767169689Skan ops[i] = mips_prepare_builtin_arg (icode, i, &arglist); 10768169689Skan 10769169689Skan switch (insn_data[icode].n_operands) 10770169689Skan { 10771169689Skan case 4: 10772169689Skan emit_insn (GEN_FCN (icode) (cmp_result, ops[1], ops[2], GEN_INT (cond))); 10773169689Skan break; 10774169689Skan 10775169689Skan case 6: 10776169689Skan emit_insn (GEN_FCN (icode) (cmp_result, ops[1], ops[2], 10777169689Skan ops[3], ops[4], GEN_INT (cond))); 10778169689Skan break; 10779169689Skan 10780169689Skan default: 10781169689Skan gcc_unreachable (); 10782169689Skan } 10783169689Skan 10784169689Skan /* If the comparison sets more than one register, we define the result 10785169689Skan to be 0 if all registers are false and -1 if all registers are true. 10786169689Skan The value of the complete result is indeterminate otherwise. */ 10787169689Skan switch (builtin_type) 10788169689Skan { 10789169689Skan case MIPS_BUILTIN_CMP_ALL: 10790169689Skan condition = gen_rtx_NE (VOIDmode, cmp_result, constm1_rtx); 10791169689Skan return mips_builtin_branch_and_move (condition, target, 10792169689Skan const0_rtx, const1_rtx); 10793169689Skan 10794169689Skan case MIPS_BUILTIN_CMP_UPPER: 10795169689Skan case MIPS_BUILTIN_CMP_LOWER: 10796169689Skan offset = GEN_INT (builtin_type == MIPS_BUILTIN_CMP_UPPER); 10797169689Skan condition = gen_single_cc (cmp_result, offset); 10798169689Skan return mips_builtin_branch_and_move (condition, target, 10799169689Skan const1_rtx, const0_rtx); 10800169689Skan 10801169689Skan default: 10802169689Skan condition = gen_rtx_NE (VOIDmode, cmp_result, const0_rtx); 10803169689Skan return mips_builtin_branch_and_move (condition, target, 10804169689Skan const1_rtx, const0_rtx); 10805169689Skan } 10806169689Skan} 10807169689Skan 10808169689Skan/* Expand a bposge builtin of type BUILTIN_TYPE. TARGET, if nonnull, 10809169689Skan suggests a good place to put the boolean result. */ 10810169689Skan 10811169689Skanstatic rtx 10812169689Skanmips_expand_builtin_bposge (enum mips_builtin_type builtin_type, rtx target) 10813169689Skan{ 10814169689Skan rtx condition, cmp_result; 10815169689Skan int cmp_value; 10816169689Skan 10817169689Skan if (target == 0 || GET_MODE (target) != SImode) 10818169689Skan target = gen_reg_rtx (SImode); 10819169689Skan 10820169689Skan cmp_result = gen_rtx_REG (CCDSPmode, CCDSP_PO_REGNUM); 10821169689Skan 10822169689Skan if (builtin_type == MIPS_BUILTIN_BPOSGE32) 10823169689Skan cmp_value = 32; 10824169689Skan else 10825169689Skan gcc_assert (0); 10826169689Skan 10827169689Skan condition = gen_rtx_GE (VOIDmode, cmp_result, GEN_INT (cmp_value)); 10828169689Skan return mips_builtin_branch_and_move (condition, target, 10829169689Skan const1_rtx, const0_rtx); 10830169689Skan} 10831169689Skan 10832169689Skan/* Set SYMBOL_REF_FLAGS for the SYMBOL_REF inside RTL, which belongs to DECL. 10833169689Skan FIRST is true if this is the first time handling this decl. */ 10834169689Skan 10835169689Skanstatic void 10836169689Skanmips_encode_section_info (tree decl, rtx rtl, int first) 10837169689Skan{ 10838169689Skan default_encode_section_info (decl, rtl, first); 10839169689Skan 10840169689Skan if (TREE_CODE (decl) == FUNCTION_DECL 10841169689Skan && lookup_attribute ("long_call", TYPE_ATTRIBUTES (TREE_TYPE (decl)))) 10842169689Skan { 10843169689Skan rtx symbol = XEXP (rtl, 0); 10844169689Skan SYMBOL_REF_FLAGS (symbol) |= SYMBOL_FLAG_LONG_CALL; 10845169689Skan } 10846169689Skan} 10847169689Skan 10848169689Skan/* Implement TARGET_EXTRA_LIVE_ON_ENTRY. PIC_FUNCTION_ADDR_REGNUM is live 10849169689Skan on entry to a function when generating -mshared abicalls code. */ 10850169689Skan 10851169689Skanstatic void 10852169689Skanmips_extra_live_on_entry (bitmap regs) 10853169689Skan{ 10854169689Skan if (TARGET_ABICALLS && !TARGET_ABSOLUTE_ABICALLS) 10855169689Skan bitmap_set_bit (regs, PIC_FUNCTION_ADDR_REGNUM); 10856169689Skan} 10857169689Skan 10858169689Skan/* SImode values are represented as sign-extended to DImode. */ 10859169689Skan 10860169689Skanint 10861169689Skanmips_mode_rep_extended (enum machine_mode mode, enum machine_mode mode_rep) 10862169689Skan{ 10863169689Skan if (TARGET_64BIT && mode == SImode && mode_rep == DImode) 10864169689Skan return SIGN_EXTEND; 10865169689Skan 10866169689Skan return UNKNOWN; 10867169689Skan} 10868169689Skan 10869169689Skan#include "gt-mips.h" 10870