1 1.1 mrg /* Subroutines used for code generation on the EPIPHANY cpu. 2 1.1 mrg Copyright (C) 1994-2022 Free Software Foundation, Inc. 3 1.1 mrg Contributed by Embecosm on behalf of Adapteva, Inc. 4 1.1 mrg 5 1.1 mrg This file is part of GCC. 6 1.1 mrg 7 1.1 mrg GCC is free software; you can redistribute it and/or modify 8 1.1 mrg it under the terms of the GNU General Public License as published by 9 1.1 mrg the Free Software Foundation; either version 3, or (at your option) 10 1.1 mrg any later version. 11 1.1 mrg 12 1.1 mrg GCC is distributed in the hope that it will be useful, 13 1.1 mrg but WITHOUT ANY WARRANTY; without even the implied warranty of 14 1.1 mrg MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 1.1 mrg GNU General Public License for more details. 16 1.1 mrg 17 1.1 mrg You should have received a copy of the GNU General Public License 18 1.1 mrg along with GCC; see the file COPYING3. If not see 19 1.1 mrg <http://www.gnu.org/licenses/>. */ 20 1.1 mrg 21 1.1 mrg #define IN_TARGET_CODE 1 22 1.1 mrg 23 1.1 mrg #include "config.h" 24 1.1 mrg #include "system.h" 25 1.1 mrg #include "coretypes.h" 26 1.1 mrg #include "backend.h" 27 1.1 mrg #include "target.h" 28 1.1 mrg #include "rtl.h" 29 1.1 mrg #include "tree.h" 30 1.1 mrg #include "df.h" 31 1.1 mrg #include "memmodel.h" 32 1.1 mrg #include "tm_p.h" 33 1.1 mrg #include "stringpool.h" 34 1.1 mrg #include "attribs.h" 35 1.1 mrg #include "optabs.h" 36 1.1 mrg #include "emit-rtl.h" 37 1.1 mrg #include "recog.h" 38 1.1 mrg #include "diagnostic-core.h" 39 1.1 mrg #include "alias.h" 40 1.1 mrg #include "stor-layout.h" 41 1.1 mrg #include "varasm.h" 42 1.1 mrg #include "calls.h" 43 1.1 mrg #include "output.h" 44 1.1 mrg #include "insn-attr.h" 45 1.1 mrg #include "explow.h" 46 1.1 mrg #include "expr.h" 47 1.1 mrg #include "tm-constrs.h" 48 1.1 mrg #include "tree-pass.h" /* for current_pass */ 49 1.1 mrg #include "context.h" 50 1.1 mrg #include "pass_manager.h" 51 1.1 mrg #include "builtins.h" 52 1.1 mrg 53 1.1 mrg /* Which cpu we're compiling for. */ 54 1.1 mrg int epiphany_cpu_type; 55 1.1 mrg 56 1.1 mrg /* Name of mangle string to add to symbols to separate code compiled for each 57 1.1 mrg cpu (or NULL). */ 58 1.1 mrg const char *epiphany_mangle_cpu; 59 1.1 mrg 60 1.1 mrg /* Array of valid operand punctuation characters. */ 61 1.1 mrg char epiphany_punct_chars[256]; 62 1.1 mrg 63 1.1 mrg /* The rounding mode that we generally use for floating point. */ 64 1.1 mrg int epiphany_normal_fp_rounding; 65 1.1 mrg 66 1.1 mrg /* The pass instance, for use in epiphany_optimize_mode_switching. */ 67 1.1 mrg static opt_pass *pass_mode_switch_use; 68 1.1 mrg 69 1.1 mrg static void epiphany_init_reg_tables (void); 70 1.1 mrg static int get_epiphany_condition_code (rtx); 71 1.1 mrg static tree epiphany_handle_interrupt_attribute (tree *, tree, tree, int, bool *); 72 1.1 mrg static tree epiphany_handle_forwarder_attribute (tree *, tree, tree, int, 73 1.1 mrg bool *); 74 1.1 mrg static bool epiphany_pass_by_reference (cumulative_args_t, 75 1.1 mrg const function_arg_info &); 76 1.1 mrg static rtx_insn *frame_insn (rtx); 77 1.1 mrg 78 1.1 mrg /* defines for the initialization of the GCC target structure. */ 80 1.1 mrg #define TARGET_ATTRIBUTE_TABLE epiphany_attribute_table 81 1.1 mrg 82 1.1 mrg #define TARGET_PRINT_OPERAND epiphany_print_operand 83 1.1 mrg #define TARGET_PRINT_OPERAND_ADDRESS epiphany_print_operand_address 84 1.1 mrg 85 1.1 mrg #define TARGET_RTX_COSTS epiphany_rtx_costs 86 1.1 mrg #define TARGET_ADDRESS_COST epiphany_address_cost 87 1.1 mrg #define TARGET_MEMORY_MOVE_COST epiphany_memory_move_cost 88 1.1 mrg 89 1.1 mrg #define TARGET_PROMOTE_FUNCTION_MODE epiphany_promote_function_mode 90 1.1 mrg #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true 91 1.1 mrg 92 1.1 mrg #define TARGET_RETURN_IN_MEMORY epiphany_return_in_memory 93 1.1 mrg #define TARGET_PASS_BY_REFERENCE epiphany_pass_by_reference 94 1.1 mrg #define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_arg_info_true 95 1.1 mrg #define TARGET_FUNCTION_VALUE epiphany_function_value 96 1.1 mrg #define TARGET_LIBCALL_VALUE epiphany_libcall_value 97 1.1 mrg #define TARGET_FUNCTION_VALUE_REGNO_P epiphany_function_value_regno_p 98 1.1 mrg 99 1.1 mrg #define TARGET_SETUP_INCOMING_VARARGS epiphany_setup_incoming_varargs 100 1.1 mrg 101 1.1 mrg /* Using the simplistic varags handling forces us to do partial reg/stack 102 1.1 mrg argument passing for types with larger size (> 4 bytes) than alignment. */ 103 1.1 mrg #define TARGET_ARG_PARTIAL_BYTES epiphany_arg_partial_bytes 104 1.1 mrg 105 1.1 mrg #define TARGET_FUNCTION_OK_FOR_SIBCALL epiphany_function_ok_for_sibcall 106 1.1 mrg 107 1.1 mrg #define TARGET_SCHED_ISSUE_RATE epiphany_issue_rate 108 1.1 mrg #define TARGET_SCHED_ADJUST_COST epiphany_adjust_cost 109 1.1 mrg 110 1.1 mrg #define TARGET_LRA_P hook_bool_void_false 111 1.1 mrg 112 1.1 mrg #define TARGET_LEGITIMATE_ADDRESS_P epiphany_legitimate_address_p 113 1.1 mrg 114 1.1 mrg #define TARGET_SECONDARY_RELOAD epiphany_secondary_reload 115 1.1 mrg 116 1.1 mrg #define TARGET_OPTION_OVERRIDE epiphany_override_options 117 1.1 mrg 118 1.1 mrg #define TARGET_CONDITIONAL_REGISTER_USAGE epiphany_conditional_register_usage 119 1.1 mrg 120 1.1 mrg #define TARGET_FUNCTION_ARG epiphany_function_arg 121 1.1 mrg 122 1.1 mrg #define TARGET_FUNCTION_ARG_ADVANCE epiphany_function_arg_advance 123 1.1 mrg 124 1.1 mrg #define TARGET_FUNCTION_ARG_BOUNDARY epiphany_function_arg_boundary 125 1.1 mrg 126 1.1 mrg #define TARGET_TRAMPOLINE_INIT epiphany_trampoline_init 127 1.1 mrg 128 1.1 mrg /* Nonzero if the constant rtx value is a legitimate general operand. 129 1.1 mrg We can handle any 32- or 64-bit constant. */ 130 1.1 mrg #define TARGET_LEGITIMATE_CONSTANT_P hook_bool_mode_rtx_true 131 1.1 mrg 132 1.1 mrg #define TARGET_MIN_DIVISIONS_FOR_RECIP_MUL \ 133 1.1 mrg epiphany_min_divisions_for_recip_mul 134 1.1 mrg 135 1.1 mrg #define TARGET_VECTORIZE_PREFERRED_SIMD_MODE epiphany_preferred_simd_mode 136 1.1 mrg 137 1.1 mrg #define TARGET_VECTOR_MODE_SUPPORTED_P epiphany_vector_mode_supported_p 138 1.1 mrg 139 1.1 mrg #define TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE \ 140 1.1 mrg epiphany_vector_alignment_reachable 141 1.1 mrg 142 1.1 mrg #define TARGET_VECTORIZE_SUPPORT_VECTOR_MISALIGNMENT \ 143 1.1 mrg epiphany_support_vector_misalignment 144 1.1 mrg 145 1.1 mrg #define TARGET_ASM_CAN_OUTPUT_MI_THUNK \ 146 1.1 mrg hook_bool_const_tree_hwi_hwi_const_tree_true 147 1.1 mrg #define TARGET_ASM_OUTPUT_MI_THUNK epiphany_output_mi_thunk 148 1.1 mrg 149 1.1 mrg /* ??? we can use larger offsets for wider-mode sized accesses, but there 150 1.1 mrg is no concept of anchors being dependent on the modes that they are used 151 1.1 mrg for, so we can only use an offset range that would suit all modes. */ 152 1.1 mrg #define TARGET_MAX_ANCHOR_OFFSET (optimize_size ? 31 : 2047) 153 1.1 mrg /* We further restrict the minimum to be a multiple of eight. */ 154 1.1 mrg #define TARGET_MIN_ANCHOR_OFFSET (optimize_size ? 0 : -2040) 155 1.1 mrg 156 1.1 mrg /* Mode switching hooks. */ 157 1.1 mrg 158 1.1 mrg #define TARGET_MODE_EMIT emit_set_fp_mode 159 1.1 mrg 160 1.1 mrg #define TARGET_MODE_NEEDED epiphany_mode_needed 161 1.1 mrg 162 1.1 mrg #define TARGET_MODE_PRIORITY epiphany_mode_priority 163 1.1 mrg 164 1.1 mrg #define TARGET_MODE_ENTRY epiphany_mode_entry 165 1.1 mrg 166 1.1 mrg #define TARGET_MODE_EXIT epiphany_mode_exit 167 1.1 mrg 168 1.1 mrg #define TARGET_MODE_AFTER epiphany_mode_after 169 1.1 mrg 170 1.1 mrg #include "target-def.h" 171 1.1 mrg 172 1.1 mrg #undef TARGET_ASM_ALIGNED_HI_OP 173 1.1 mrg #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t" 174 1.1 mrg #undef TARGET_ASM_ALIGNED_SI_OP 175 1.1 mrg #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t" 176 1.1 mrg 177 1.1 mrg #undef TARGET_HARD_REGNO_MODE_OK 178 1.1 mrg #define TARGET_HARD_REGNO_MODE_OK epiphany_hard_regno_mode_ok 179 1.1 mrg 180 1.1 mrg #undef TARGET_CONSTANT_ALIGNMENT 181 1.1 mrg #define TARGET_CONSTANT_ALIGNMENT epiphany_constant_alignment 182 1.1 mrg 183 1.1 mrg #undef TARGET_STARTING_FRAME_OFFSET 184 1.1 mrg #define TARGET_STARTING_FRAME_OFFSET epiphany_starting_frame_offset 185 1.1 mrg 186 1.1 mrg bool 188 1.1 mrg epiphany_is_interrupt_p (tree decl) 189 1.1 mrg { 190 1.1 mrg tree attrs; 191 1.1 mrg 192 1.1 mrg attrs = DECL_ATTRIBUTES (decl); 193 1.1 mrg if (lookup_attribute ("interrupt", attrs)) 194 1.1 mrg return true; 195 1.1 mrg else 196 1.1 mrg return false; 197 1.1 mrg } 198 1.1 mrg 199 1.1 mrg /* Called from epiphany_override_options. 200 1.1 mrg We use this to initialize various things. */ 201 1.1 mrg 202 1.1 mrg static void 203 1.1 mrg epiphany_init (void) 204 1.1 mrg { 205 1.1 mrg /* N.B. this pass must not run before the first optimize_mode_switching 206 1.1 mrg pass because of the side offect of epiphany_mode_needed on 207 1.1 mrg MACHINE_FUNCTION(cfun)->unknown_mode_uses. But it must run before 208 1.1 mrg pass_resolve_sw_modes. */ 209 1.1 mrg pass_mode_switch_use = make_pass_mode_switch_use (g); 210 1.1 mrg struct register_pass_info insert_use_info 211 1.1 mrg = { pass_mode_switch_use, "mode_sw", 212 1.1 mrg 1, PASS_POS_INSERT_AFTER 213 1.1 mrg }; 214 1.1 mrg opt_pass *mode_sw2 215 1.1 mrg = g->get_passes()->get_pass_mode_switching ()->clone (); 216 1.1 mrg struct register_pass_info mode_sw2_info 217 1.1 mrg = { mode_sw2, "mode_sw", 218 1.1 mrg 1, PASS_POS_INSERT_AFTER 219 1.1 mrg }; 220 1.1 mrg opt_pass *mode_sw3 = make_pass_resolve_sw_modes (g); 221 1.1 mrg struct register_pass_info mode_sw3_info 222 1.1 mrg = { mode_sw3, "mode_sw", 223 1.1 mrg 1, PASS_POS_INSERT_AFTER 224 1.1 mrg }; 225 1.1 mrg opt_pass *mode_sw4 226 1.1 mrg = g->get_passes()->get_pass_split_all_insns ()->clone (); 227 1.1 mrg struct register_pass_info mode_sw4_info 228 1.1 mrg = { mode_sw4, "mode_sw", 229 1.1 mrg 1, PASS_POS_INSERT_AFTER 230 1.1 mrg }; 231 1.1 mrg static const int num_modes[] = NUM_MODES_FOR_MODE_SWITCHING; 232 1.1 mrg #define N_ENTITIES ARRAY_SIZE (num_modes) 233 1.1 mrg 234 1.1 mrg epiphany_init_reg_tables (); 235 1.1 mrg 236 1.1 mrg /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P. */ 237 1.1 mrg memset (epiphany_punct_chars, 0, sizeof (epiphany_punct_chars)); 238 1.1 mrg epiphany_punct_chars['-'] = 1; 239 1.1 mrg 240 1.1 mrg epiphany_normal_fp_rounding 241 1.1 mrg = (epiphany_normal_fp_mode == FP_MODE_ROUND_TRUNC 242 1.1 mrg ? FP_MODE_ROUND_TRUNC : FP_MODE_ROUND_NEAREST); 243 1.1 mrg register_pass (&mode_sw4_info); 244 1.1 mrg register_pass (&mode_sw2_info); 245 1.1 mrg register_pass (&mode_sw3_info); 246 1.1 mrg register_pass (&insert_use_info); 247 1.1 mrg register_pass (&mode_sw2_info); 248 1.1 mrg /* Verify that NUM_MODES_FOR_MODE_SWITCHING has one value per entity. */ 249 1.1 mrg gcc_assert (N_ENTITIES == EPIPHANY_MSW_ENTITY_NUM); 250 1.1 mrg 251 1.1 mrg #if 1 /* As long as peep2_rescan is not implemented, 252 1.1 mrg (see http://gcc.gnu.org/ml/gcc-patches/2011-10/msg02819.html,) 253 1.1 mrg we need a second peephole2 pass to get reasonable code. */ 254 1.1 mrg { 255 1.1 mrg opt_pass *extra_peephole2 256 1.1 mrg = g->get_passes ()->get_pass_peephole2 ()->clone (); 257 1.1 mrg struct register_pass_info peep2_2_info 258 1.1 mrg = { extra_peephole2, "peephole2", 259 1.1 mrg 1, PASS_POS_INSERT_AFTER 260 1.1 mrg }; 261 1.1 mrg 262 1.1 mrg register_pass (&peep2_2_info); 263 1.1 mrg } 264 1.1 mrg #endif 265 1.1 mrg } 266 1.1 mrg 267 1.1 mrg /* The condition codes of the EPIPHANY, and the inverse function. */ 268 1.1 mrg static const char *const epiphany_condition_codes[] = 269 1.1 mrg { /* 0 1 2 3 4 5 6 7 8 9 */ 270 1.1 mrg "eq", "ne", "ltu", "gteu", "gt", "lte", "gte", "lt", "gtu", "lteu", 271 1.1 mrg /* 10 11 12 13 */ 272 1.1 mrg "beq","bne","blt", "blte", 273 1.1 mrg }; 274 1.1 mrg 275 1.1 mrg #define EPIPHANY_INVERSE_CONDITION_CODE(X) ((X) ^ 1) 276 1.1 mrg 277 1.1 mrg /* Returns the index of the EPIPHANY condition code string in 278 1.1 mrg `epiphany_condition_codes'. COMPARISON should be an rtx like 279 1.1 mrg `(eq (...) (...))'. */ 280 1.1 mrg 281 1.1 mrg static int 282 1.1 mrg get_epiphany_condition_code (rtx comparison) 283 1.1 mrg { 284 1.1 mrg switch (GET_MODE (XEXP (comparison, 0))) 285 1.1 mrg { 286 1.1 mrg case E_CCmode: 287 1.1 mrg switch (GET_CODE (comparison)) 288 1.1 mrg { 289 1.1 mrg case EQ : return 0; 290 1.1 mrg case NE : return 1; 291 1.1 mrg case LTU : return 2; 292 1.1 mrg case GEU : return 3; 293 1.1 mrg case GT : return 4; 294 1.1 mrg case LE : return 5; 295 1.1 mrg case GE : return 6; 296 1.1 mrg case LT : return 7; 297 1.1 mrg case GTU : return 8; 298 1.1 mrg case LEU : return 9; 299 1.1 mrg 300 1.1 mrg default : gcc_unreachable (); 301 1.1 mrg } 302 1.1 mrg case E_CC_N_NEmode: 303 1.1 mrg switch (GET_CODE (comparison)) 304 1.1 mrg { 305 1.1 mrg case EQ: return 6; 306 1.1 mrg case NE: return 7; 307 1.1 mrg default: gcc_unreachable (); 308 1.1 mrg } 309 1.1 mrg case E_CC_C_LTUmode: 310 1.1 mrg switch (GET_CODE (comparison)) 311 1.1 mrg { 312 1.1 mrg case GEU: return 2; 313 1.1 mrg case LTU: return 3; 314 1.1 mrg default: gcc_unreachable (); 315 1.1 mrg } 316 1.1 mrg case E_CC_C_GTUmode: 317 1.1 mrg switch (GET_CODE (comparison)) 318 1.1 mrg { 319 1.1 mrg case LEU: return 3; 320 1.1 mrg case GTU: return 2; 321 1.1 mrg default: gcc_unreachable (); 322 1.1 mrg } 323 1.1 mrg case E_CC_FPmode: 324 1.1 mrg switch (GET_CODE (comparison)) 325 1.1 mrg { 326 1.1 mrg case EQ: return 10; 327 1.1 mrg case NE: return 11; 328 1.1 mrg case LT: return 12; 329 1.1 mrg case LE: return 13; 330 1.1 mrg default: gcc_unreachable (); 331 1.1 mrg } 332 1.1 mrg case E_CC_FP_EQmode: 333 1.1 mrg switch (GET_CODE (comparison)) 334 1.1 mrg { 335 1.1 mrg case EQ: return 0; 336 1.1 mrg case NE: return 1; 337 1.1 mrg default: gcc_unreachable (); 338 1.1 mrg } 339 1.1 mrg case E_CC_FP_GTEmode: 340 1.1 mrg switch (GET_CODE (comparison)) 341 1.1 mrg { 342 1.1 mrg case EQ: return 0; 343 1.1 mrg case NE: return 1; 344 1.1 mrg case GT : return 4; 345 1.1 mrg case GE : return 6; 346 1.1 mrg case UNLE : return 5; 347 1.1 mrg case UNLT : return 7; 348 1.1 mrg default: gcc_unreachable (); 349 1.1 mrg } 350 1.1 mrg case E_CC_FP_ORDmode: 351 1.1 mrg switch (GET_CODE (comparison)) 352 1.1 mrg { 353 1.1 mrg case ORDERED: return 9; 354 1.1 mrg case UNORDERED: return 8; 355 1.1 mrg default: gcc_unreachable (); 356 1.1 mrg } 357 1.1 mrg case E_CC_FP_UNEQmode: 358 1.1 mrg switch (GET_CODE (comparison)) 359 1.1 mrg { 360 1.1 mrg case UNEQ: return 9; 361 1.1 mrg case LTGT: return 8; 362 1.1 mrg default: gcc_unreachable (); 363 1.1 mrg } 364 1.1 mrg default: gcc_unreachable (); 365 1.1 mrg } 366 1.1 mrg /*NOTREACHED*/ 367 1.1 mrg return (42); 368 1.1 mrg } 369 1.1 mrg 370 1.1 mrg 371 1.1 mrg /* Implement TARGET_HARD_REGNO_MODE_OK. */ 372 1.1 mrg 373 1.1 mrg static bool 374 1.1 mrg epiphany_hard_regno_mode_ok (unsigned int regno, machine_mode mode) 375 1.1 mrg { 376 1.1 mrg if (GET_MODE_SIZE (mode) > UNITS_PER_WORD) 377 1.1 mrg return (regno & 1) == 0 && GPR_P (regno); 378 1.1 mrg else 379 1.1 mrg return true; 380 1.1 mrg } 381 1.1 mrg 382 1.1 mrg /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE, 383 1.1 mrg return the mode to be used for the comparison. */ 384 1.1 mrg 385 1.1 mrg machine_mode 386 1.1 mrg epiphany_select_cc_mode (enum rtx_code op, 387 1.1 mrg rtx x ATTRIBUTE_UNUSED, 388 1.1 mrg rtx y ATTRIBUTE_UNUSED) 389 1.1 mrg { 390 1.1 mrg if (GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT) 391 1.1 mrg { 392 1.1 mrg if (TARGET_SOFT_CMPSF 393 1.1 mrg || op == ORDERED || op == UNORDERED) 394 1.1 mrg { 395 1.1 mrg if (op == EQ || op == NE) 396 1.1 mrg return CC_FP_EQmode; 397 1.1 mrg if (op == ORDERED || op == UNORDERED) 398 1.1 mrg return CC_FP_ORDmode; 399 1.1 mrg if (op == UNEQ || op == LTGT) 400 1.1 mrg return CC_FP_UNEQmode; 401 1.1 mrg return CC_FP_GTEmode; 402 1.1 mrg } 403 1.1 mrg return CC_FPmode; 404 1.1 mrg } 405 1.1 mrg /* recognize combiner pattern ashlsi_btst: 406 1.1 mrg (parallel [ 407 1.1 mrg (set (reg:N_NE 65 cc1) 408 1.1 mrg (compare:N_NE (zero_extract:SI (reg/v:SI 75 [ a ]) 409 1.1 mrg (const_int 1 [0x1]) 410 1.1 mrg (const_int 0 [0x0])) 411 1.1 mrg (const_int 0 [0x0]))) 412 1.1 mrg (clobber (scratch:SI)) */ 413 1.1 mrg else if ((op == EQ || op == NE) 414 1.1 mrg && GET_CODE (x) == ZERO_EXTRACT 415 1.1 mrg && XEXP (x, 1) == const1_rtx 416 1.1 mrg && CONST_INT_P (XEXP (x, 2))) 417 1.1 mrg return CC_N_NEmode; 418 1.1 mrg else if ((op == GEU || op == LTU) && GET_CODE (x) == PLUS) 419 1.1 mrg return CC_C_LTUmode; 420 1.1 mrg else if ((op == LEU || op == GTU) && GET_CODE (x) == MINUS) 421 1.1 mrg return CC_C_GTUmode; 422 1.1 mrg else 423 1.1 mrg return CCmode; 424 1.1 mrg } 425 1.1 mrg 426 1.1 mrg enum reg_class epiphany_regno_reg_class[FIRST_PSEUDO_REGISTER]; 427 1.1 mrg 428 1.1 mrg static void 429 1.1 mrg epiphany_init_reg_tables (void) 430 1.1 mrg { 431 1.1 mrg int i; 432 1.1 mrg 433 1.1 mrg for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 434 1.1 mrg { 435 1.1 mrg if (i == GPR_LR) 436 1.1 mrg epiphany_regno_reg_class[i] = LR_REGS; 437 1.1 mrg else if (i <= 7 && TARGET_PREFER_SHORT_INSN_REGS) 438 1.1 mrg epiphany_regno_reg_class[i] = SHORT_INSN_REGS; 439 1.1 mrg else if (call_used_or_fixed_reg_p (i) 440 1.1 mrg && TEST_HARD_REG_BIT (reg_class_contents[GENERAL_REGS], i)) 441 1.1 mrg epiphany_regno_reg_class[i] = SIBCALL_REGS; 442 1.1 mrg else if (i >= CORE_CONTROL_FIRST && i <= CORE_CONTROL_LAST) 443 1.1 mrg epiphany_regno_reg_class[i] = CORE_CONTROL_REGS; 444 1.1 mrg else if (i < (GPR_LAST+1) 445 1.1 mrg || i == ARG_POINTER_REGNUM || i == FRAME_POINTER_REGNUM) 446 1.1 mrg epiphany_regno_reg_class[i] = GENERAL_REGS; 447 1.1 mrg else if (i == CC_REGNUM) 448 1.1 mrg epiphany_regno_reg_class[i] = NO_REGS /* CC_REG: must be NO_REGS */; 449 1.1 mrg else 450 1.1 mrg epiphany_regno_reg_class[i] = NO_REGS; 451 1.1 mrg } 452 1.1 mrg } 453 1.1 mrg 454 1.1 mrg /* EPIPHANY specific attribute support. 456 1.1 mrg 457 1.1 mrg The EPIPHANY has these attributes: 458 1.1 mrg interrupt - for interrupt functions. 459 1.1 mrg short_call - the function is assumed to be reachable with the b / bl 460 1.1 mrg instructions. 461 1.1 mrg long_call - the function address is loaded into a register before use. 462 1.1 mrg disinterrupt - functions which mask interrupts throughout. 463 1.1 mrg They unmask them while calling an interruptible 464 1.1 mrg function, though. */ 465 1.1 mrg 466 1.1 mrg static const struct attribute_spec epiphany_attribute_table[] = 467 1.1 mrg { 468 1.1 mrg /* { name, min_len, max_len, decl_req, type_req, fn_type_req, 469 1.1 mrg affects_type_identity, handler, exclude } */ 470 1.1 mrg { "interrupt", 0, 9, true, false, false, true, 471 1.1 mrg epiphany_handle_interrupt_attribute, NULL }, 472 1.1 mrg { "forwarder_section", 1, 1, true, false, false, false, 473 1.1 mrg epiphany_handle_forwarder_attribute, NULL }, 474 1.1 mrg { "long_call", 0, 0, false, true, true, false, NULL, NULL }, 475 1.1 mrg { "short_call", 0, 0, false, true, true, false, NULL, NULL }, 476 1.1 mrg { "disinterrupt", 0, 0, false, true, true, true, NULL, NULL }, 477 1.1 mrg { NULL, 0, 0, false, false, false, false, NULL, NULL } 478 1.1 mrg }; 479 1.1 mrg 480 1.1 mrg /* Handle an "interrupt" attribute; arguments as in 481 1.1 mrg struct attribute_spec.handler. */ 482 1.1 mrg static tree 483 1.1 mrg epiphany_handle_interrupt_attribute (tree *node, tree name, tree args, 484 1.1 mrg int flags ATTRIBUTE_UNUSED, 485 1.1 mrg bool *no_add_attrs) 486 1.1 mrg { 487 1.1 mrg tree value; 488 1.1 mrg 489 1.1 mrg if (!args) 490 1.1 mrg { 491 1.1 mrg gcc_assert (DECL_P (*node)); 492 1.1 mrg tree t = TREE_TYPE (*node); 493 1.1 mrg if (TREE_CODE (t) != FUNCTION_TYPE) 494 1.1 mrg warning (OPT_Wattributes, "%qE attribute only applies to functions", 495 1.1 mrg name); 496 1.1 mrg /* Argument handling and the stack layout for interrupt handlers 497 1.1 mrg don't mix. It makes no sense in the first place, so emit an 498 1.1 mrg error for this. */ 499 1.1 mrg else if (TYPE_ARG_TYPES (t) 500 1.1 mrg && TREE_VALUE (TYPE_ARG_TYPES (t)) != void_type_node) 501 1.1 mrg error_at (DECL_SOURCE_LOCATION (*node), 502 1.1 mrg "interrupt handlers cannot have arguments"); 503 1.1 mrg return NULL_TREE; 504 1.1 mrg } 505 1.1 mrg 506 1.1 mrg value = TREE_VALUE (args); 507 1.1 mrg 508 1.1 mrg if (TREE_CODE (value) != STRING_CST) 509 1.1 mrg { 510 1.1 mrg warning (OPT_Wattributes, 511 1.1 mrg "argument of %qE attribute is not a string constant", name); 512 1.1 mrg *no_add_attrs = true; 513 1.1 mrg } 514 1.1 mrg else if (strcmp (TREE_STRING_POINTER (value), "reset") 515 1.1 mrg && strcmp (TREE_STRING_POINTER (value), "software_exception") 516 1.1 mrg && strcmp (TREE_STRING_POINTER (value), "page_miss") 517 1.1 mrg && strcmp (TREE_STRING_POINTER (value), "timer0") 518 1.1 mrg && strcmp (TREE_STRING_POINTER (value), "timer1") 519 1.1 mrg && strcmp (TREE_STRING_POINTER (value), "message") 520 1.1 mrg && strcmp (TREE_STRING_POINTER (value), "dma0") 521 1.1 mrg && strcmp (TREE_STRING_POINTER (value), "dma1") 522 1.1 mrg && strcmp (TREE_STRING_POINTER (value), "wand") 523 1.1 mrg && strcmp (TREE_STRING_POINTER (value), "swi")) 524 1.1 mrg { 525 1.1 mrg warning (OPT_Wattributes, 526 1.1 mrg "argument of %qE attribute is not %qs, %qs %qs, %qs, %qs, " 527 1.1 mrg "%qs, %qs, %qs, %qs or %qs", name, 528 1.1 mrg "reset", "software_exception", "page_miss", "timer0", "timer1", 529 1.1 mrg "message", "dma0", "dma1", "wand", "swi"); 530 1.1 mrg *no_add_attrs = true; 531 1.1 mrg return NULL_TREE; 532 1.1 mrg } 533 1.1 mrg 534 1.1 mrg return epiphany_handle_interrupt_attribute (node, name, TREE_CHAIN (args), 535 1.1 mrg flags, no_add_attrs); 536 1.1 mrg } 537 1.1 mrg 538 1.1 mrg /* Handle a "forwarder_section" attribute; arguments as in 539 1.1 mrg struct attribute_spec.handler. */ 540 1.1 mrg static tree 541 1.1 mrg epiphany_handle_forwarder_attribute (tree *node ATTRIBUTE_UNUSED, 542 1.1 mrg tree name, tree args, 543 1.1 mrg int flags ATTRIBUTE_UNUSED, 544 1.1 mrg bool *no_add_attrs) 545 1.1 mrg { 546 1.1 mrg tree value; 547 1.1 mrg 548 1.1 mrg value = TREE_VALUE (args); 549 1.1 mrg 550 1.1 mrg if (TREE_CODE (value) != STRING_CST) 551 1.1 mrg { 552 1.1 mrg warning (OPT_Wattributes, 553 1.1 mrg "argument of %qE attribute is not a string constant", name); 554 1.1 mrg *no_add_attrs = true; 555 1.1 mrg } 556 1.1 mrg return NULL_TREE; 557 1.1 mrg } 558 1.1 mrg 559 1.1 mrg 560 1.1 mrg /* Misc. utilities. */ 562 1.1 mrg 563 1.1 mrg /* Generate a SYMBOL_REF for the special function NAME. When the address 564 1.1 mrg can't be placed directly into a call instruction, and if possible, copy 565 1.1 mrg it to a register so that cse / code hoisting is possible. */ 566 1.1 mrg rtx 567 1.1 mrg sfunc_symbol (const char *name) 568 1.1 mrg { 569 1.1 mrg rtx sym = gen_rtx_SYMBOL_REF (Pmode, name); 570 1.1 mrg 571 1.1 mrg /* These sfuncs should be hidden, and every dso should get a copy. */ 572 1.1 mrg SYMBOL_REF_FLAGS (sym) = SYMBOL_FLAG_FUNCTION | SYMBOL_FLAG_LOCAL; 573 1.1 mrg if (TARGET_SHORT_CALLS) 574 1.1 mrg ; /* Nothing to be done. */ 575 1.1 mrg else if (can_create_pseudo_p ()) 576 1.1 mrg sym = copy_to_mode_reg (Pmode, sym); 577 1.1 mrg else /* We rely on reload to fix this up. */ 578 1.1 mrg gcc_assert (!reload_in_progress || reload_completed); 579 1.1 mrg return sym; 580 1.1 mrg } 581 1.1 mrg 582 1.1 mrg /* X and Y are two things to compare using CODE in IN_MODE. 583 1.1 mrg Emit the compare insn, construct the proper cc reg in the proper 584 1.1 mrg mode, and return the rtx for the cc reg comparison in CMODE. */ 585 1.1 mrg 586 1.1 mrg rtx 587 1.1 mrg gen_compare_reg (machine_mode cmode, enum rtx_code code, 588 1.1 mrg machine_mode in_mode, rtx x, rtx y) 589 1.1 mrg { 590 1.1 mrg machine_mode mode = SELECT_CC_MODE (code, x, y); 591 1.1 mrg rtx cc_reg, pat, clob0, clob1, clob2; 592 1.1 mrg 593 1.1 mrg if (in_mode == VOIDmode) 594 1.1 mrg in_mode = GET_MODE (x); 595 1.1 mrg if (in_mode == VOIDmode) 596 1.1 mrg in_mode = GET_MODE (y); 597 1.1 mrg 598 1.1 mrg if (mode == CC_FPmode) 599 1.1 mrg { 600 1.1 mrg /* The epiphany has only EQ / NE / LT / LE conditions for 601 1.1 mrg hardware floating point. */ 602 1.1 mrg if (code == GT || code == GE || code == UNLE || code == UNLT) 603 1.1 mrg { 604 1.1 mrg rtx tmp = x; x = y; y = tmp; 605 1.1 mrg code = swap_condition (code); 606 1.1 mrg } 607 1.1 mrg cc_reg = gen_rtx_REG (mode, CCFP_REGNUM); 608 1.1 mrg y = force_reg (in_mode, y); 609 1.1 mrg } 610 1.1 mrg else 611 1.1 mrg { 612 1.1 mrg if (mode == CC_FP_GTEmode 613 1.1 mrg && (code == LE || code == LT || code == UNGT || code == UNGE)) 614 1.1 mrg { 615 1.1 mrg if (flag_finite_math_only 616 1.1 mrg && ((REG_P (x) && REGNO (x) == GPR_0) 617 1.1 mrg || (REG_P (y) && REGNO (y) == GPR_1))) 618 1.1 mrg switch (code) 619 1.1 mrg { 620 1.1 mrg case LE: code = UNLE; break; 621 1.1 mrg case LT: code = UNLT; break; 622 1.1 mrg case UNGT: code = GT; break; 623 1.1 mrg case UNGE: code = GE; break; 624 1.1 mrg default: gcc_unreachable (); 625 1.1 mrg } 626 1.1 mrg else 627 1.1 mrg { 628 1.1 mrg rtx tmp = x; x = y; y = tmp; 629 1.1 mrg code = swap_condition (code); 630 1.1 mrg } 631 1.1 mrg } 632 1.1 mrg cc_reg = gen_rtx_REG (mode, CC_REGNUM); 633 1.1 mrg } 634 1.1 mrg if ((mode == CC_FP_EQmode || mode == CC_FP_GTEmode 635 1.1 mrg || mode == CC_FP_ORDmode || mode == CC_FP_UNEQmode) 636 1.1 mrg /* mov<mode>cc might want to re-emit a comparison during ifcvt. */ 637 1.1 mrg && (!REG_P (x) || REGNO (x) != GPR_0 638 1.1 mrg || !REG_P (y) || REGNO (y) != GPR_1)) 639 1.1 mrg { 640 1.1 mrg rtx reg; 641 1.1 mrg 642 1.1 mrg #if 0 643 1.1 mrg /* ??? We should really do the r0/r1 clobber only during rtl expansion, 644 1.1 mrg but just like the flag clobber of movsicc, we have to allow 645 1.1 mrg this for ifcvt to work, on the assumption that we'll only want 646 1.1 mrg to do this if these registers have been used before by the 647 1.1 mrg pre-ifcvt code. */ 648 1.1 mrg gcc_assert (currently_expanding_to_rtl); 649 1.1 mrg #endif 650 1.1 mrg reg = gen_rtx_REG (in_mode, GPR_0); 651 1.1 mrg if (reg_overlap_mentioned_p (reg, y)) 652 1.1 mrg return 0; 653 1.1 mrg emit_move_insn (reg, x); 654 1.1 mrg x = reg; 655 1.1 mrg reg = gen_rtx_REG (in_mode, GPR_1); 656 1.1 mrg emit_move_insn (reg, y); 657 1.1 mrg y = reg; 658 1.1 mrg } 659 1.1 mrg else 660 1.1 mrg x = force_reg (in_mode, x); 661 1.1 mrg 662 1.1 mrg pat = gen_rtx_SET (cc_reg, gen_rtx_COMPARE (mode, x, y)); 663 1.1 mrg if (mode == CC_FP_EQmode || mode == CC_FP_GTEmode) 664 1.1 mrg { 665 1.1 mrg const char *name = mode == CC_FP_EQmode ? "__eqsf2" : "__gtesf2"; 666 1.1 mrg rtx use = gen_rtx_USE (VOIDmode, sfunc_symbol (name)); 667 1.1 mrg 668 1.1 mrg clob0 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, GPR_IP)); 669 1.1 mrg clob1 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, GPR_LR)); 670 1.1 mrg pat = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (4, pat, use, clob0, clob1)); 671 1.1 mrg } 672 1.1 mrg else if (mode == CC_FP_ORDmode || mode == CC_FP_UNEQmode) 673 1.1 mrg { 674 1.1 mrg const char *name = mode == CC_FP_ORDmode ? "__ordsf2" : "__uneqsf2"; 675 1.1 mrg rtx use = gen_rtx_USE (VOIDmode, sfunc_symbol (name)); 676 1.1 mrg 677 1.1 mrg clob0 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, GPR_IP)); 678 1.1 mrg clob1 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, GPR_16)); 679 1.1 mrg clob2 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (SImode, GPR_LR)); 680 1.1 mrg pat = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (5, pat, use, 681 1.1 mrg clob0, clob1, clob2)); 682 1.1 mrg } 683 1.1 mrg else 684 1.1 mrg { 685 1.1 mrg clob0 = gen_rtx_CLOBBER (VOIDmode, gen_rtx_SCRATCH (in_mode)); 686 1.1 mrg pat = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, pat, clob0)); 687 1.1 mrg } 688 1.1 mrg emit_insn (pat); 689 1.1 mrg return gen_rtx_fmt_ee (code, cmode, cc_reg, const0_rtx); 690 1.1 mrg } 691 1.1 mrg 692 1.1 mrg /* The ROUND_ADVANCE* macros are local to this file. */ 694 1.1 mrg /* Round SIZE up to a word boundary. */ 695 1.1 mrg #define ROUND_ADVANCE(SIZE) \ 696 1.1 mrg (((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD) 697 1.1 mrg 698 1.1 mrg /* Round arg MODE/TYPE up to the next word boundary. */ 699 1.1 mrg #define ROUND_ADVANCE_ARG(MODE, TYPE) \ 700 1.1 mrg ((MODE) == BLKmode \ 701 1.1 mrg ? ROUND_ADVANCE (int_size_in_bytes (TYPE)) \ 702 1.1 mrg : ROUND_ADVANCE (GET_MODE_SIZE (MODE))) 703 1.1 mrg 704 1.1 mrg /* Round CUM up to the necessary point for argument MODE/TYPE. */ 705 1.1 mrg #define ROUND_ADVANCE_CUM(CUM, MODE, TYPE) \ 706 1.1 mrg (epiphany_function_arg_boundary ((MODE), (TYPE)) > BITS_PER_WORD \ 707 1.1 mrg ? (((CUM) + 1) & ~1) \ 708 1.1 mrg : (CUM)) 709 1.1 mrg 710 1.1 mrg static unsigned int 711 1.1 mrg epiphany_function_arg_boundary (machine_mode mode, const_tree type) 712 1.1 mrg { 713 1.1 mrg if ((type ? TYPE_ALIGN (type) : GET_MODE_BITSIZE (mode)) <= PARM_BOUNDARY) 714 1.1 mrg return PARM_BOUNDARY; 715 1.1 mrg return 2 * PARM_BOUNDARY; 716 1.1 mrg } 717 1.1 mrg 718 1.1 mrg /* Do any needed setup for a variadic function. For the EPIPHANY, we 719 1.1 mrg actually emit the code in epiphany_expand_prologue. 720 1.1 mrg 721 1.1 mrg CUM has not been updated for the last named argument (which is given 722 1.1 mrg by ARG), and we rely on this fact. */ 723 1.1 mrg 724 1.1 mrg 725 1.1 mrg static void 726 1.1 mrg epiphany_setup_incoming_varargs (cumulative_args_t cum, 727 1.1 mrg const function_arg_info &arg, 728 1.1 mrg int *pretend_size, int no_rtl) 729 1.1 mrg { 730 1.1 mrg int first_anon_arg; 731 1.1 mrg CUMULATIVE_ARGS next_cum; 732 1.1 mrg machine_function_t *mf = MACHINE_FUNCTION (cfun); 733 1.1 mrg 734 1.1 mrg /* All BLKmode values are passed by reference. */ 735 1.1 mrg gcc_assert (arg.mode != BLKmode); 736 1.1 mrg 737 1.1 mrg next_cum = *get_cumulative_args (cum); 738 1.1 mrg next_cum = (ROUND_ADVANCE_CUM (next_cum, arg.mode, arg.type) 739 1.1 mrg + ROUND_ADVANCE_ARG (arg.mode, arg.type)); 740 1.1 mrg first_anon_arg = next_cum; 741 1.1 mrg 742 1.1 mrg if (first_anon_arg < MAX_EPIPHANY_PARM_REGS && !no_rtl) 743 1.1 mrg { 744 1.1 mrg /* Note that first_reg_offset < MAX_EPIPHANY_PARM_REGS. */ 745 1.1 mrg int first_reg_offset = first_anon_arg; 746 1.1 mrg 747 1.1 mrg *pretend_size = ((MAX_EPIPHANY_PARM_REGS - first_reg_offset) 748 1.1 mrg * UNITS_PER_WORD); 749 1.1 mrg } 750 1.1 mrg mf->args_parsed = 1; 751 1.1 mrg mf->pretend_args_odd = ((*pretend_size & UNITS_PER_WORD) ? 1 : 0); 752 1.1 mrg } 753 1.1 mrg 754 1.1 mrg static int 755 1.1 mrg epiphany_arg_partial_bytes (cumulative_args_t cum, 756 1.1 mrg const function_arg_info &arg) 757 1.1 mrg { 758 1.1 mrg int words = 0, rounded_cum; 759 1.1 mrg 760 1.1 mrg gcc_assert (!epiphany_pass_by_reference (cum, arg)); 761 1.1 mrg 762 1.1 mrg rounded_cum = ROUND_ADVANCE_CUM (*get_cumulative_args (cum), 763 1.1 mrg arg.mode, arg.type); 764 1.1 mrg if (rounded_cum < MAX_EPIPHANY_PARM_REGS) 765 1.1 mrg { 766 1.1 mrg words = MAX_EPIPHANY_PARM_REGS - rounded_cum; 767 1.1 mrg if (words >= ROUND_ADVANCE_ARG (arg.mode, arg.type)) 768 1.1 mrg words = 0; 769 1.1 mrg } 770 1.1 mrg return words * UNITS_PER_WORD; 771 1.1 mrg } 772 1.1 mrg 773 1.1 mrg /* Cost functions. */ 775 1.1 mrg 776 1.1 mrg /* Compute a (partial) cost for rtx X. Return true if the complete 777 1.1 mrg cost has been computed, and false if subexpressions should be 778 1.1 mrg scanned. In either case, *TOTAL contains the cost result. */ 779 1.1 mrg 780 1.1 mrg static bool 781 1.1 mrg epiphany_rtx_costs (rtx x, machine_mode mode, int outer_code, 782 1.1 mrg int opno ATTRIBUTE_UNUSED, 783 1.1 mrg int *total, bool speed ATTRIBUTE_UNUSED) 784 1.1 mrg { 785 1.1 mrg int code = GET_CODE (x); 786 1.1 mrg 787 1.1 mrg switch (code) 788 1.1 mrg { 789 1.1 mrg /* Small integers in the right context are as cheap as registers. */ 790 1.1 mrg case CONST_INT: 791 1.1 mrg if ((outer_code == PLUS || outer_code == MINUS) 792 1.1 mrg && SIMM11 (INTVAL (x))) 793 1.1 mrg { 794 1.1 mrg *total = 0; 795 1.1 mrg return true; 796 1.1 mrg } 797 1.1 mrg if (IMM16 (INTVAL (x))) 798 1.1 mrg { 799 1.1 mrg *total = outer_code == SET ? 0 : COSTS_N_INSNS (1); 800 1.1 mrg return true; 801 1.1 mrg } 802 1.1 mrg /* FALLTHRU */ 803 1.1 mrg 804 1.1 mrg case CONST: 805 1.1 mrg case LABEL_REF: 806 1.1 mrg case SYMBOL_REF: 807 1.1 mrg *total = COSTS_N_INSNS ((epiphany_small16 (x) ? 0 : 1) 808 1.1 mrg + (outer_code == SET ? 0 : 1)); 809 1.1 mrg return true; 810 1.1 mrg 811 1.1 mrg case CONST_DOUBLE: 812 1.1 mrg { 813 1.1 mrg rtx high, low; 814 1.1 mrg split_double (x, &high, &low); 815 1.1 mrg *total = COSTS_N_INSNS (!IMM16 (INTVAL (high)) 816 1.1 mrg + !IMM16 (INTVAL (low))); 817 1.1 mrg return true; 818 1.1 mrg } 819 1.1 mrg 820 1.1 mrg case ASHIFT: 821 1.1 mrg case ASHIFTRT: 822 1.1 mrg case LSHIFTRT: 823 1.1 mrg *total = COSTS_N_INSNS (1); 824 1.1 mrg return true; 825 1.1 mrg 826 1.1 mrg case COMPARE: 827 1.1 mrg switch (mode) 828 1.1 mrg { 829 1.1 mrg /* There are a number of single-insn combiner patterns that use 830 1.1 mrg the flag side effects of arithmetic. */ 831 1.1 mrg case E_CC_N_NEmode: 832 1.1 mrg case E_CC_C_LTUmode: 833 1.1 mrg case E_CC_C_GTUmode: 834 1.1 mrg return true; 835 1.1 mrg default: 836 1.1 mrg return false; 837 1.1 mrg } 838 1.1 mrg 839 1.1 mrg 840 1.1 mrg case SET: 841 1.1 mrg { 842 1.1 mrg rtx src = SET_SRC (x); 843 1.1 mrg if (BINARY_P (src)) 844 1.1 mrg *total = 0; 845 1.1 mrg return false; 846 1.1 mrg } 847 1.1 mrg 848 1.1 mrg default: 849 1.1 mrg return false; 850 1.1 mrg } 851 1.1 mrg } 852 1.1 mrg 853 1.1 mrg 854 1.1 mrg /* Provide the costs of an addressing mode that contains ADDR. 855 1.1 mrg If ADDR is not a valid address, its cost is irrelevant. */ 856 1.1 mrg 857 1.1 mrg static int 858 1.1 mrg epiphany_address_cost (rtx addr, machine_mode mode, 859 1.1 mrg addr_space_t as ATTRIBUTE_UNUSED, bool speed) 860 1.1 mrg { 861 1.1 mrg rtx reg; 862 1.1 mrg rtx off = const0_rtx; 863 1.1 mrg int i; 864 1.1 mrg 865 1.1 mrg if (speed) 866 1.1 mrg return 0; 867 1.1 mrg /* Return 0 for addresses valid in short insns, 1 for addresses only valid 868 1.1 mrg in long insns. */ 869 1.1 mrg switch (GET_CODE (addr)) 870 1.1 mrg { 871 1.1 mrg case PLUS : 872 1.1 mrg reg = XEXP (addr, 0); 873 1.1 mrg off = XEXP (addr, 1); 874 1.1 mrg break; 875 1.1 mrg case POST_MODIFY: 876 1.1 mrg reg = XEXP (addr, 0); 877 1.1 mrg off = XEXP (addr, 1); 878 1.1 mrg gcc_assert (GET_CODE (off) == PLUS && rtx_equal_p (reg, XEXP (off, 0))); 879 1.1 mrg off = XEXP (off, 1); 880 1.1 mrg if (satisfies_constraint_Rgs (reg) && satisfies_constraint_Rgs (off)) 881 1.1 mrg return 0; 882 1.1 mrg return 1; 883 1.1 mrg case REG: 884 1.1 mrg default: 885 1.1 mrg reg = addr; 886 1.1 mrg break; 887 1.1 mrg } 888 1.1 mrg if (!satisfies_constraint_Rgs (reg)) 889 1.1 mrg return 1; 890 1.1 mrg /* The offset range available for short instructions depends on the mode 891 1.1 mrg of the memory access. */ 892 1.1 mrg /* First, make sure we have a valid integer. */ 893 1.1 mrg if (!satisfies_constraint_L (off)) 894 1.1 mrg return 1; 895 1.1 mrg i = INTVAL (off); 896 1.1 mrg switch (GET_MODE_SIZE (mode)) 897 1.1 mrg { 898 1.1 mrg default: 899 1.1 mrg case 4: 900 1.1 mrg if (i & 1) 901 1.1 mrg return 1; 902 1.1 mrg i >>= 1; 903 1.1 mrg /* Fall through. */ 904 1.1 mrg case 2: 905 1.1 mrg if (i & 1) 906 1.1 mrg return 1; 907 1.1 mrg i >>= 1; 908 1.1 mrg /* Fall through. */ 909 1.1 mrg case 1: 910 1.1 mrg return i < -7 || i > 7; 911 1.1 mrg } 912 1.1 mrg } 913 1.1 mrg 914 1.1 mrg /* Compute the cost of moving data between registers and memory. 915 1.1 mrg For integer, load latency is twice as long as register-register moves, 916 1.1 mrg but issue pich is the same. For floating point, load latency is three 917 1.1 mrg times as much as a reg-reg move. */ 918 1.1 mrg static int 919 1.1 mrg epiphany_memory_move_cost (machine_mode mode, 920 1.1 mrg reg_class_t rclass ATTRIBUTE_UNUSED, 921 1.1 mrg bool in ATTRIBUTE_UNUSED) 922 1.1 mrg { 923 1.1 mrg return GET_MODE_CLASS (mode) == MODE_INT ? 3 : 4; 924 1.1 mrg } 925 1.1 mrg 926 1.1 mrg /* Function prologue/epilogue handlers. */ 928 1.1 mrg 929 1.1 mrg /* EPIPHANY stack frames look like: 930 1.1 mrg 931 1.1 mrg Before call After call 932 1.1 mrg +-----------------------+ +-----------------------+ 933 1.1 mrg | | | | 934 1.1 mrg high | local variables, | | local variables, | 935 1.1 mrg mem | reg save area, etc. | | reg save area, etc. | 936 1.1 mrg | | | | 937 1.1 mrg +-----------------------+ +-----------------------+ 938 1.1 mrg | | | | 939 1.1 mrg | arguments on stack. | | arguments on stack. | 940 1.1 mrg | | | | 941 1.1 mrg SP+8->+-----------------------+FP+8m->+-----------------------+ 942 1.1 mrg | 2 word save area for | | reg parm save area, | 943 1.1 mrg | leaf funcs / flags | | only created for | 944 1.1 mrg SP+0->+-----------------------+ | variable argument | 945 1.1 mrg | functions | 946 1.1 mrg FP+8n->+-----------------------+ 947 1.1 mrg | | 948 1.1 mrg | register save area | 949 1.1 mrg | | 950 1.1 mrg +-----------------------+ 951 1.1 mrg | | 952 1.1 mrg | local variables | 953 1.1 mrg | | 954 1.1 mrg FP+0->+-----------------------+ 955 1.1 mrg | | 956 1.1 mrg | alloca allocations | 957 1.1 mrg | | 958 1.1 mrg +-----------------------+ 959 1.1 mrg | | 960 1.1 mrg | arguments on stack | 961 1.1 mrg | | 962 1.1 mrg SP+8->+-----------------------+ 963 1.1 mrg low | 2 word save area for | 964 1.1 mrg memory | leaf funcs / flags | 965 1.1 mrg SP+0->+-----------------------+ 966 1.1 mrg 967 1.1 mrg Notes: 968 1.1 mrg 1) The "reg parm save area" does not exist for non variable argument fns. 969 1.1 mrg The "reg parm save area" could be eliminated if we created our 970 1.1 mrg own TARGET_GIMPLIFY_VA_ARG_EXPR, but that has tradeoffs as well 971 1.1 mrg (so it's not done). */ 972 1.1 mrg 973 1.1 mrg /* Structure to be filled in by epiphany_compute_frame_size with register 974 1.1 mrg save masks, and offsets for the current function. */ 975 1.1 mrg struct epiphany_frame_info 976 1.1 mrg { 977 1.1 mrg unsigned int total_size; /* # bytes that the entire frame takes up. */ 978 1.1 mrg unsigned int pretend_size; /* # bytes we push and pretend caller did. */ 979 1.1 mrg unsigned int args_size; /* # bytes that outgoing arguments take up. */ 980 1.1 mrg unsigned int reg_size; /* # bytes needed to store regs. */ 981 1.1 mrg unsigned int var_size; /* # bytes that variables take up. */ 982 1.1 mrg HARD_REG_SET gmask; /* Set of saved gp registers. */ 983 1.1 mrg int initialized; /* Nonzero if frame size already calculated. */ 984 1.1 mrg int stld_sz; /* Current load/store data size for offset 985 1.1 mrg adjustment. */ 986 1.1 mrg int need_fp; /* value to override "frame_pointer_needed */ 987 1.1 mrg /* FIRST_SLOT is the slot that is saved first, at the very start of 988 1.1 mrg the frame, with a POST_MODIFY to allocate the frame, if the size fits, 989 1.1 mrg or at least the parm and register save areas, otherwise. 990 1.1 mrg In the case of a large frame, LAST_SLOT is the slot that is saved last, 991 1.1 mrg with a POST_MODIFY to allocate the rest of the frame. */ 992 1.1 mrg int first_slot, last_slot, first_slot_offset, last_slot_offset; 993 1.1 mrg int first_slot_size; 994 1.1 mrg int small_threshold; 995 1.1 mrg }; 996 1.1 mrg 997 1.1 mrg /* Current frame information calculated by epiphany_compute_frame_size. */ 998 1.1 mrg static struct epiphany_frame_info current_frame_info; 999 1.1 mrg 1000 1.1 mrg /* Zero structure to initialize current_frame_info. */ 1001 1.1 mrg static struct epiphany_frame_info zero_frame_info; 1002 1.1 mrg 1003 1.1 mrg /* The usual; we set up our machine_function data. */ 1004 1.1 mrg static struct machine_function * 1005 1.1 mrg epiphany_init_machine_status (void) 1006 1.1 mrg { 1007 1.1 mrg struct machine_function *machine; 1008 1.1 mrg 1009 1.1 mrg /* Reset state info for each function. */ 1010 1.1 mrg current_frame_info = zero_frame_info; 1011 1.1 mrg 1012 1.1 mrg machine = ggc_cleared_alloc<machine_function_t> (); 1013 1.1 mrg 1014 1.1 mrg return machine; 1015 1.1 mrg } 1016 1.1 mrg 1017 1.1 mrg /* Implements INIT_EXPANDERS. We just set up to call the above 1018 1.1 mrg * function. */ 1019 1.1 mrg void 1020 1.1 mrg epiphany_init_expanders (void) 1021 1.1 mrg { 1022 1.1 mrg init_machine_status = epiphany_init_machine_status; 1023 1.1 mrg } 1024 1.1 mrg 1025 1.1 mrg /* Type of function DECL. 1026 1.1 mrg 1027 1.1 mrg The result is cached. To reset the cache at the end of a function, 1028 1.1 mrg call with DECL = NULL_TREE. */ 1029 1.1 mrg 1030 1.1 mrg static enum epiphany_function_type 1031 1.1 mrg epiphany_compute_function_type (tree decl) 1032 1.1 mrg { 1033 1.1 mrg tree a; 1034 1.1 mrg /* Cached value. */ 1035 1.1 mrg static enum epiphany_function_type fn_type = EPIPHANY_FUNCTION_UNKNOWN; 1036 1.1 mrg /* Last function we were called for. */ 1037 1.1 mrg static tree last_fn = NULL_TREE; 1038 1.1 mrg 1039 1.1 mrg /* Resetting the cached value? */ 1040 1.1 mrg if (decl == NULL_TREE) 1041 1.1 mrg { 1042 1.1 mrg fn_type = EPIPHANY_FUNCTION_UNKNOWN; 1043 1.1 mrg last_fn = NULL_TREE; 1044 1.1 mrg return fn_type; 1045 1.1 mrg } 1046 1.1 mrg 1047 1.1 mrg if (decl == last_fn && fn_type != EPIPHANY_FUNCTION_UNKNOWN) 1048 1.1 mrg return fn_type; 1049 1.1 mrg 1050 1.1 mrg /* Assume we have a normal function (not an interrupt handler). */ 1051 1.1 mrg fn_type = EPIPHANY_FUNCTION_NORMAL; 1052 1.1 mrg 1053 1.1 mrg /* Now see if this is an interrupt handler. */ 1054 1.1 mrg for (a = DECL_ATTRIBUTES (decl); 1055 1.1 mrg a; 1056 1.1 mrg a = TREE_CHAIN (a)) 1057 1.1 mrg { 1058 1.1 mrg tree name = TREE_PURPOSE (a); 1059 1.1 mrg 1060 1.1 mrg if (name == get_identifier ("interrupt")) 1061 1.1 mrg fn_type = EPIPHANY_FUNCTION_INTERRUPT; 1062 1.1 mrg } 1063 1.1 mrg 1064 1.1 mrg last_fn = decl; 1065 1.1 mrg return fn_type; 1066 1.1 mrg } 1067 1.1 mrg 1068 1.1 mrg #define RETURN_ADDR_REGNUM GPR_LR 1069 1.1 mrg #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM)) 1070 1.1 mrg #define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM)) 1071 1.1 mrg 1072 1.1 mrg /* Tell prologue and epilogue if register REGNO should be saved / restored. 1073 1.1 mrg The return address and frame pointer are treated separately. 1074 1.1 mrg Don't consider them here. */ 1075 1.1 mrg #define MUST_SAVE_REGISTER(regno, interrupt_p) \ 1076 1.1 mrg ((df_regs_ever_live_p (regno) \ 1077 1.1 mrg || (interrupt_p && !crtl->is_leaf \ 1078 1.1 mrg && call_used_or_fixed_reg_p (regno) && !fixed_regs[regno])) \ 1079 1.1 mrg && (!call_used_or_fixed_reg_p (regno) || regno == GPR_LR \ 1080 1.1 mrg || (interrupt_p && regno != GPR_SP))) 1081 1.1 mrg 1082 1.1 mrg #define MUST_SAVE_RETURN_ADDR 0 1083 1.1 mrg 1084 1.1 mrg /* Return the bytes needed to compute the frame pointer from the current 1085 1.1 mrg stack pointer. 1086 1.1 mrg 1087 1.1 mrg SIZE is the size needed for local variables. */ 1088 1.1 mrg 1089 1.1 mrg static unsigned int 1090 1.1 mrg epiphany_compute_frame_size (int size /* # of var. bytes allocated. */) 1091 1.1 mrg { 1092 1.1 mrg int regno; 1093 1.1 mrg unsigned int total_size, var_size, args_size, pretend_size, reg_size; 1094 1.1 mrg HARD_REG_SET gmask; 1095 1.1 mrg enum epiphany_function_type fn_type; 1096 1.1 mrg int interrupt_p; 1097 1.1 mrg int first_slot, last_slot, first_slot_offset, last_slot_offset; 1098 1.1 mrg int first_slot_size; 1099 1.1 mrg int small_slots = 0; 1100 1.1 mrg 1101 1.1 mrg var_size = size; 1102 1.1 mrg args_size = crtl->outgoing_args_size; 1103 1.1 mrg pretend_size = crtl->args.pretend_args_size; 1104 1.1 mrg total_size = args_size + var_size; 1105 1.1 mrg reg_size = 0; 1106 1.1 mrg CLEAR_HARD_REG_SET (gmask); 1107 1.1 mrg first_slot = -1; 1108 1.1 mrg first_slot_offset = 0; 1109 1.1 mrg last_slot = -1; 1110 1.1 mrg last_slot_offset = 0; 1111 1.1 mrg first_slot_size = UNITS_PER_WORD; 1112 1.1 mrg 1113 1.1 mrg /* See if this is an interrupt handler. Call used registers must be saved 1114 1.1 mrg for them too. */ 1115 1.1 mrg fn_type = epiphany_compute_function_type (current_function_decl); 1116 1.1 mrg interrupt_p = EPIPHANY_INTERRUPT_P (fn_type); 1117 1.1 mrg 1118 1.1 mrg /* Calculate space needed for registers. */ 1119 1.1 mrg 1120 1.1 mrg for (regno = MAX_EPIPHANY_PARM_REGS - 1; pretend_size > reg_size; regno--) 1121 1.1 mrg { 1122 1.1 mrg reg_size += UNITS_PER_WORD; 1123 1.1 mrg SET_HARD_REG_BIT (gmask, regno); 1124 1.1 mrg if (epiphany_stack_offset - reg_size == 0) 1125 1.1 mrg first_slot = regno; 1126 1.1 mrg } 1127 1.1 mrg 1128 1.1 mrg if (interrupt_p) 1129 1.1 mrg reg_size += 2 * UNITS_PER_WORD; 1130 1.1 mrg else 1131 1.1 mrg small_slots = epiphany_stack_offset / UNITS_PER_WORD; 1132 1.1 mrg 1133 1.1 mrg if (frame_pointer_needed) 1134 1.1 mrg { 1135 1.1 mrg current_frame_info.need_fp = 1; 1136 1.1 mrg if (!interrupt_p && first_slot < 0) 1137 1.1 mrg first_slot = GPR_FP; 1138 1.1 mrg } 1139 1.1 mrg else 1140 1.1 mrg current_frame_info.need_fp = 0; 1141 1.1 mrg for (regno = 0; regno <= GPR_LAST; regno++) 1142 1.1 mrg { 1143 1.1 mrg if (MUST_SAVE_REGISTER (regno, interrupt_p)) 1144 1.1 mrg { 1145 1.1 mrg gcc_assert (!TEST_HARD_REG_BIT (gmask, regno)); 1146 1.1 mrg reg_size += UNITS_PER_WORD; 1147 1.1 mrg SET_HARD_REG_BIT (gmask, regno); 1148 1.1 mrg /* FIXME: when optimizing for speed, take schedling into account 1149 1.1 mrg when selecting these registers. */ 1150 1.1 mrg if (regno == first_slot) 1151 1.1 mrg gcc_assert (regno == GPR_FP && frame_pointer_needed); 1152 1.1 mrg else if (!interrupt_p && first_slot < 0) 1153 1.1 mrg first_slot = regno; 1154 1.1 mrg else if (last_slot < 0 1155 1.1 mrg && (first_slot ^ regno) != 1 1156 1.1 mrg && (!interrupt_p || regno > GPR_1)) 1157 1.1 mrg last_slot = regno; 1158 1.1 mrg } 1159 1.1 mrg } 1160 1.1 mrg if (TEST_HARD_REG_BIT (gmask, GPR_LR)) 1161 1.1 mrg MACHINE_FUNCTION (cfun)->lr_clobbered = 1; 1162 1.1 mrg /* ??? Could sometimes do better than that. */ 1163 1.1 mrg current_frame_info.small_threshold 1164 1.1 mrg = (optimize >= 3 || interrupt_p ? 0 1165 1.1 mrg : pretend_size ? small_slots 1166 1.1 mrg : 4 + small_slots - (first_slot == GPR_FP)); 1167 1.1 mrg 1168 1.1 mrg /* If there might be variables with 64-bit alignment requirement, align the 1169 1.1 mrg start of the variables. */ 1170 1.1 mrg if (var_size >= 2 * UNITS_PER_WORD 1171 1.1 mrg /* We don't want to split a double reg save/restore across two unpaired 1172 1.1 mrg stack slots when optimizing. This rounding could be avoided with 1173 1.1 mrg more complex reordering of the register saves, but that would seem 1174 1.1 mrg to be a lot of code complexity for little gain. */ 1175 1.1 mrg || (reg_size > 8 && optimize)) 1176 1.1 mrg reg_size = EPIPHANY_STACK_ALIGN (reg_size); 1177 1.1 mrg if (((total_size + reg_size 1178 1.1 mrg /* Reserve space for UNKNOWN_REGNUM. */ 1179 1.1 mrg + EPIPHANY_STACK_ALIGN (4)) 1180 1.1 mrg <= (unsigned) epiphany_stack_offset) 1181 1.1 mrg && !interrupt_p 1182 1.1 mrg && crtl->is_leaf && !frame_pointer_needed) 1183 1.1 mrg { 1184 1.1 mrg first_slot = -1; 1185 1.1 mrg last_slot = -1; 1186 1.1 mrg goto alloc_done; 1187 1.1 mrg } 1188 1.1 mrg else if (reg_size 1189 1.1 mrg && !interrupt_p 1190 1.1 mrg && reg_size < (unsigned HOST_WIDE_INT) epiphany_stack_offset) 1191 1.1 mrg reg_size = epiphany_stack_offset; 1192 1.1 mrg if (interrupt_p) 1193 1.1 mrg { 1194 1.1 mrg if (total_size + reg_size < 0x3fc) 1195 1.1 mrg { 1196 1.1 mrg first_slot_offset = EPIPHANY_STACK_ALIGN (total_size + reg_size); 1197 1.1 mrg first_slot_offset += EPIPHANY_STACK_ALIGN (epiphany_stack_offset); 1198 1.1 mrg last_slot = -1; 1199 1.1 mrg } 1200 1.1 mrg else 1201 1.1 mrg { 1202 1.1 mrg first_slot_offset = EPIPHANY_STACK_ALIGN (reg_size); 1203 1.1 mrg last_slot_offset = EPIPHANY_STACK_ALIGN (total_size); 1204 1.1 mrg last_slot_offset += EPIPHANY_STACK_ALIGN (epiphany_stack_offset); 1205 1.1 mrg if (last_slot >= 0) 1206 1.1 mrg CLEAR_HARD_REG_BIT (gmask, last_slot); 1207 1.1 mrg } 1208 1.1 mrg } 1209 1.1 mrg else if (total_size + reg_size < 0x1ffc && first_slot >= 0) 1210 1.1 mrg { 1211 1.1 mrg first_slot_offset = EPIPHANY_STACK_ALIGN (total_size + reg_size); 1212 1.1 mrg last_slot = -1; 1213 1.1 mrg } 1214 1.1 mrg else 1215 1.1 mrg { 1216 1.1 mrg if (total_size + reg_size <= (unsigned) epiphany_stack_offset) 1217 1.1 mrg { 1218 1.1 mrg gcc_assert (first_slot < 0); 1219 1.1 mrg gcc_assert (reg_size == 0 || (int) reg_size == epiphany_stack_offset); 1220 1.1 mrg last_slot_offset = EPIPHANY_STACK_ALIGN (total_size + reg_size); 1221 1.1 mrg } 1222 1.1 mrg else 1223 1.1 mrg { 1224 1.1 mrg first_slot_offset 1225 1.1 mrg = (reg_size 1226 1.1 mrg ? EPIPHANY_STACK_ALIGN (reg_size - epiphany_stack_offset) : 0); 1227 1.1 mrg if (!first_slot_offset) 1228 1.1 mrg { 1229 1.1 mrg if (first_slot != GPR_FP || !current_frame_info.need_fp) 1230 1.1 mrg last_slot = first_slot; 1231 1.1 mrg first_slot = -1; 1232 1.1 mrg } 1233 1.1 mrg last_slot_offset = EPIPHANY_STACK_ALIGN (total_size); 1234 1.1 mrg if (reg_size) 1235 1.1 mrg last_slot_offset += EPIPHANY_STACK_ALIGN (epiphany_stack_offset); 1236 1.1 mrg } 1237 1.1 mrg if (last_slot >= 0) 1238 1.1 mrg CLEAR_HARD_REG_BIT (gmask, last_slot); 1239 1.1 mrg } 1240 1.1 mrg alloc_done: 1241 1.1 mrg if (first_slot >= 0) 1242 1.1 mrg { 1243 1.1 mrg CLEAR_HARD_REG_BIT (gmask, first_slot); 1244 1.1 mrg if (TEST_HARD_REG_BIT (gmask, first_slot ^ 1) 1245 1.1 mrg && epiphany_stack_offset - pretend_size >= 2 * UNITS_PER_WORD) 1246 1.1 mrg { 1247 1.1 mrg CLEAR_HARD_REG_BIT (gmask, first_slot ^ 1); 1248 1.1 mrg first_slot_size = 2 * UNITS_PER_WORD; 1249 1.1 mrg first_slot &= ~1; 1250 1.1 mrg } 1251 1.1 mrg } 1252 1.1 mrg total_size = first_slot_offset + last_slot_offset; 1253 1.1 mrg 1254 1.1 mrg /* Save computed information. */ 1255 1.1 mrg current_frame_info.total_size = total_size; 1256 1.1 mrg current_frame_info.pretend_size = pretend_size; 1257 1.1 mrg current_frame_info.var_size = var_size; 1258 1.1 mrg current_frame_info.args_size = args_size; 1259 1.1 mrg current_frame_info.reg_size = reg_size; 1260 1.1 mrg current_frame_info.gmask = gmask; 1261 1.1 mrg current_frame_info.first_slot = first_slot; 1262 1.1 mrg current_frame_info.last_slot = last_slot; 1263 1.1 mrg current_frame_info.first_slot_offset = first_slot_offset; 1264 1.1 mrg current_frame_info.first_slot_size = first_slot_size; 1265 1.1 mrg current_frame_info.last_slot_offset = last_slot_offset; 1266 1.1 mrg 1267 1.1 mrg current_frame_info.initialized = reload_completed; 1268 1.1 mrg 1269 1.1 mrg /* Ok, we're done. */ 1270 1.1 mrg return total_size; 1271 1.1 mrg } 1272 1.1 mrg 1273 1.1 mrg /* Print operand X (an rtx) in assembler syntax to file FILE. 1275 1.1 mrg CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified. 1276 1.1 mrg For `%' followed by punctuation, CODE is the punctuation and X is null. */ 1277 1.1 mrg 1278 1.1 mrg static void 1279 1.1 mrg epiphany_print_operand (FILE *file, rtx x, int code) 1280 1.1 mrg { 1281 1.1 mrg switch (code) 1282 1.1 mrg { 1283 1.1 mrg case 'd': 1284 1.1 mrg fputs (epiphany_condition_codes[get_epiphany_condition_code (x)], file); 1285 1.1 mrg return; 1286 1.1 mrg case 'D': 1287 1.1 mrg fputs (epiphany_condition_codes[EPIPHANY_INVERSE_CONDITION_CODE 1288 1.1 mrg (get_epiphany_condition_code (x))], 1289 1.1 mrg file); 1290 1.1 mrg return; 1291 1.1 mrg 1292 1.1 mrg case 'X': 1293 1.1 mrg current_frame_info.stld_sz = 8; 1294 1.1 mrg break; 1295 1.1 mrg 1296 1.1 mrg case 'C' : 1297 1.1 mrg current_frame_info.stld_sz = 4; 1298 1.1 mrg break; 1299 1.1 mrg 1300 1.1 mrg case 'c' : 1301 1.1 mrg current_frame_info.stld_sz = 2; 1302 1.1 mrg break; 1303 1.1 mrg 1304 1.1 mrg case 'f': 1305 1.1 mrg fputs (REG_P (x) ? "jalr " : "bl ", file); 1306 1.1 mrg break; 1307 1.1 mrg 1308 1.1 mrg case '-': 1309 1.1 mrg fprintf (file, "r%d", epiphany_m1reg); 1310 1.1 mrg return; 1311 1.1 mrg 1312 1.1 mrg case 0 : 1313 1.1 mrg /* Do nothing special. */ 1314 1.1 mrg break; 1315 1.1 mrg default : 1316 1.1 mrg /* Unknown flag. */ 1317 1.1 mrg output_operand_lossage ("invalid operand output code"); 1318 1.1 mrg } 1319 1.1 mrg 1320 1.1 mrg switch (GET_CODE (x)) 1321 1.1 mrg { 1322 1.1 mrg rtx addr; 1323 1.1 mrg rtx offset; 1324 1.1 mrg 1325 1.1 mrg case REG : 1326 1.1 mrg fputs (reg_names[REGNO (x)], file); 1327 1.1 mrg break; 1328 1.1 mrg case MEM : 1329 1.1 mrg if (code == 0) 1330 1.1 mrg current_frame_info.stld_sz = 1; 1331 1.1 mrg fputc ('[', file); 1332 1.1 mrg addr = XEXP (x, 0); 1333 1.1 mrg switch (GET_CODE (addr)) 1334 1.1 mrg { 1335 1.1 mrg case POST_INC: 1336 1.1 mrg offset = GEN_INT (GET_MODE_SIZE (GET_MODE (x))); 1337 1.1 mrg addr = XEXP (addr, 0); 1338 1.1 mrg break; 1339 1.1 mrg case POST_DEC: 1340 1.1 mrg offset = GEN_INT (-GET_MODE_SIZE (GET_MODE (x))); 1341 1.1 mrg addr = XEXP (addr, 0); 1342 1.1 mrg break; 1343 1.1 mrg case POST_MODIFY: 1344 1.1 mrg offset = XEXP (XEXP (addr, 1), 1); 1345 1.1 mrg addr = XEXP (addr, 0); 1346 1.1 mrg break; 1347 1.1 mrg default: 1348 1.1 mrg offset = 0; 1349 1.1 mrg break; 1350 1.1 mrg } 1351 1.1 mrg output_address (GET_MODE (x), addr); 1352 1.1 mrg fputc (']', file); 1353 1.1 mrg if (offset) 1354 1.1 mrg { 1355 1.1 mrg fputc (',', file); 1356 1.1 mrg if (CONST_INT_P (offset)) switch (GET_MODE_SIZE (GET_MODE (x))) 1357 1.1 mrg { 1358 1.1 mrg default: 1359 1.1 mrg gcc_unreachable (); 1360 1.1 mrg case 8: 1361 1.1 mrg offset = GEN_INT (INTVAL (offset) >> 3); 1362 1.1 mrg break; 1363 1.1 mrg case 4: 1364 1.1 mrg offset = GEN_INT (INTVAL (offset) >> 2); 1365 1.1 mrg break; 1366 1.1 mrg case 2: 1367 1.1 mrg offset = GEN_INT (INTVAL (offset) >> 1); 1368 1.1 mrg break; 1369 1.1 mrg case 1: 1370 1.1 mrg break; 1371 1.1 mrg } 1372 1.1 mrg output_address (GET_MODE (x), offset); 1373 1.1 mrg } 1374 1.1 mrg break; 1375 1.1 mrg case CONST_DOUBLE : 1376 1.1 mrg /* We handle SFmode constants here as output_addr_const doesn't. */ 1377 1.1 mrg if (GET_MODE (x) == SFmode) 1378 1.1 mrg { 1379 1.1 mrg long l; 1380 1.1 mrg 1381 1.1 mrg REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x), l); 1382 1.1 mrg fprintf (file, "%s0x%08lx", IMMEDIATE_PREFIX, l); 1383 1.1 mrg break; 1384 1.1 mrg } 1385 1.1 mrg /* FALLTHRU */ 1386 1.1 mrg /* Let output_addr_const deal with it. */ 1387 1.1 mrg case CONST_INT: 1388 1.1 mrg fprintf(file,"%s",IMMEDIATE_PREFIX); 1389 1.1 mrg if (code == 'C' || code == 'X') 1390 1.1 mrg { 1391 1.1 mrg fprintf (file, "%ld", 1392 1.1 mrg (long) (INTVAL (x) / current_frame_info.stld_sz)); 1393 1.1 mrg break; 1394 1.1 mrg } 1395 1.1 mrg /* Fall through */ 1396 1.1 mrg default : 1397 1.1 mrg output_addr_const (file, x); 1398 1.1 mrg break; 1399 1.1 mrg } 1400 1.1 mrg } 1401 1.1 mrg 1402 1.1 mrg /* Print a memory address as an operand to reference that memory location. */ 1403 1.1 mrg 1404 1.1 mrg static void 1405 1.1 mrg epiphany_print_operand_address (FILE *file, machine_mode /*mode*/, rtx addr) 1406 1.1 mrg { 1407 1.1 mrg rtx base, index = 0; 1408 1.1 mrg int offset = 0; 1409 1.1 mrg 1410 1.1 mrg switch (GET_CODE (addr)) 1411 1.1 mrg { 1412 1.1 mrg case REG : 1413 1.1 mrg fputs (reg_names[REGNO (addr)], file); 1414 1.1 mrg break; 1415 1.1 mrg case SYMBOL_REF : 1416 1.1 mrg if (/*???*/ 0 && SYMBOL_REF_FUNCTION_P (addr)) 1417 1.1 mrg { 1418 1.1 mrg output_addr_const (file, addr); 1419 1.1 mrg } 1420 1.1 mrg else 1421 1.1 mrg { 1422 1.1 mrg output_addr_const (file, addr); 1423 1.1 mrg } 1424 1.1 mrg break; 1425 1.1 mrg case PLUS : 1426 1.1 mrg if (GET_CODE (XEXP (addr, 0)) == CONST_INT) 1427 1.1 mrg offset = INTVAL (XEXP (addr, 0)), base = XEXP (addr, 1); 1428 1.1 mrg else if (GET_CODE (XEXP (addr, 1)) == CONST_INT) 1429 1.1 mrg offset = INTVAL (XEXP (addr, 1)), base = XEXP (addr, 0); 1430 1.1 mrg else 1431 1.1 mrg base = XEXP (addr, 0), index = XEXP (addr, 1); 1432 1.1 mrg gcc_assert (GET_CODE (base) == REG); 1433 1.1 mrg fputs (reg_names[REGNO (base)], file); 1434 1.1 mrg if (index == 0) 1435 1.1 mrg { 1436 1.1 mrg /* 1437 1.1 mrg ** ++rk quirky method to scale offset for ld/str....... 1438 1.1 mrg */ 1439 1.1 mrg fprintf (file, ",%s%d", IMMEDIATE_PREFIX, 1440 1.1 mrg offset/current_frame_info.stld_sz); 1441 1.1 mrg } 1442 1.1 mrg else 1443 1.1 mrg { 1444 1.1 mrg switch (GET_CODE (index)) 1445 1.1 mrg { 1446 1.1 mrg case REG: 1447 1.1 mrg fprintf (file, ",%s", reg_names[REGNO (index)]); 1448 1.1 mrg break; 1449 1.1 mrg case SYMBOL_REF: 1450 1.1 mrg fputc (',', file), output_addr_const (file, index); 1451 1.1 mrg break; 1452 1.1 mrg default: 1453 1.1 mrg gcc_unreachable (); 1454 1.1 mrg } 1455 1.1 mrg } 1456 1.1 mrg break; 1457 1.1 mrg case PRE_INC: case PRE_DEC: case POST_INC: case POST_DEC: case POST_MODIFY: 1458 1.1 mrg /* We shouldn't get here as we've lost the mode of the memory object 1459 1.1 mrg (which says how much to inc/dec by. 1460 1.1 mrg FIXME: We have the mode now, address printing can be moved into this 1461 1.1 mrg function. */ 1462 1.1 mrg gcc_unreachable (); 1463 1.1 mrg break; 1464 1.1 mrg default: 1465 1.1 mrg output_addr_const (file, addr); 1466 1.1 mrg break; 1467 1.1 mrg } 1468 1.1 mrg } 1469 1.1 mrg 1470 1.1 mrg void 1471 1.1 mrg epiphany_final_prescan_insn (rtx_insn *insn ATTRIBUTE_UNUSED, 1472 1.1 mrg rtx *opvec ATTRIBUTE_UNUSED, 1473 1.1 mrg int noperands ATTRIBUTE_UNUSED) 1474 1.1 mrg { 1475 1.1 mrg int i = epiphany_n_nops; 1476 1.1 mrg rtx pat ATTRIBUTE_UNUSED; 1477 1.1 mrg 1478 1.1 mrg while (i--) 1479 1.1 mrg fputs ("\tnop\n", asm_out_file); 1480 1.1 mrg } 1481 1.1 mrg 1482 1.1 mrg 1483 1.1 mrg /* Worker function for TARGET_RETURN_IN_MEMORY. */ 1485 1.1 mrg 1486 1.1 mrg static bool 1487 1.1 mrg epiphany_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED) 1488 1.1 mrg { 1489 1.1 mrg HOST_WIDE_INT size = int_size_in_bytes (type); 1490 1.1 mrg 1491 1.1 mrg if (AGGREGATE_TYPE_P (type) 1492 1.1 mrg && (TYPE_MODE (type) == BLKmode || TYPE_NEEDS_CONSTRUCTING (type))) 1493 1.1 mrg return true; 1494 1.1 mrg return (size == -1 || size > 8); 1495 1.1 mrg } 1496 1.1 mrg 1497 1.1 mrg /* For EPIPHANY, All aggregates and arguments greater than 8 bytes are 1498 1.1 mrg passed by reference. */ 1499 1.1 mrg 1500 1.1 mrg static bool 1501 1.1 mrg epiphany_pass_by_reference (cumulative_args_t, const function_arg_info &arg) 1502 1.1 mrg { 1503 1.1 mrg if (tree type = arg.type) 1504 1.1 mrg { 1505 1.1 mrg if (AGGREGATE_TYPE_P (type) 1506 1.1 mrg && (arg.mode == BLKmode || TYPE_NEEDS_CONSTRUCTING (type))) 1507 1.1 mrg return true; 1508 1.1 mrg } 1509 1.1 mrg return false; 1510 1.1 mrg } 1511 1.1 mrg 1512 1.1 mrg 1513 1.1 mrg static rtx 1514 1.1 mrg epiphany_function_value (const_tree ret_type, 1515 1.1 mrg const_tree fn_decl_or_type ATTRIBUTE_UNUSED, 1516 1.1 mrg bool outgoing ATTRIBUTE_UNUSED) 1517 1.1 mrg { 1518 1.1 mrg machine_mode mode; 1519 1.1 mrg 1520 1.1 mrg mode = TYPE_MODE (ret_type); 1521 1.1 mrg /* We must change the mode like PROMOTE_MODE does. 1522 1.1 mrg ??? PROMOTE_MODE is ignored for non-scalar types. 1523 1.1 mrg The set of types tested here has to be kept in sync 1524 1.1 mrg with the one in explow.cc:promote_mode. */ 1525 1.1 mrg if (GET_MODE_CLASS (mode) == MODE_INT 1526 1.1 mrg && GET_MODE_SIZE (mode) < 4 1527 1.1 mrg && (TREE_CODE (ret_type) == INTEGER_TYPE 1528 1.1 mrg || TREE_CODE (ret_type) == ENUMERAL_TYPE 1529 1.1 mrg || TREE_CODE (ret_type) == BOOLEAN_TYPE 1530 1.1 mrg || TREE_CODE (ret_type) == OFFSET_TYPE)) 1531 1.1 mrg mode = SImode; 1532 1.1 mrg return gen_rtx_REG (mode, 0); 1533 1.1 mrg } 1534 1.1 mrg 1535 1.1 mrg static rtx 1536 1.1 mrg epiphany_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED) 1537 1.1 mrg { 1538 1.1 mrg return gen_rtx_REG (mode, 0); 1539 1.1 mrg } 1540 1.1 mrg 1541 1.1 mrg static bool 1542 1.1 mrg epiphany_function_value_regno_p (const unsigned int regno ATTRIBUTE_UNUSED) 1543 1.1 mrg { 1544 1.1 mrg return regno == 0; 1545 1.1 mrg } 1546 1.1 mrg 1547 1.1 mrg /* Fix up invalid option settings. */ 1548 1.1 mrg static void 1549 1.1 mrg epiphany_override_options (void) 1550 1.1 mrg { 1551 1.1 mrg if (epiphany_stack_offset < 4) 1552 1.1 mrg error ("%<stack_offset%> must be at least 4"); 1553 1.1 mrg if (epiphany_stack_offset & 3) 1554 1.1 mrg error ("%<stack_offset%> must be a multiple of 4"); 1555 1.1 mrg epiphany_stack_offset = (epiphany_stack_offset + 3) & -4; 1556 1.1 mrg if (!TARGET_SOFT_CMPSF) 1557 1.1 mrg flag_finite_math_only = 1; 1558 1.1 mrg 1559 1.1 mrg /* This needs to be done at start up. It's convenient to do it here. */ 1560 1.1 mrg epiphany_init (); 1561 1.1 mrg } 1562 1.1 mrg 1563 1.1 mrg /* For a DImode load / store SET, make a SImode set for a 1564 1.1 mrg REG_FRAME_RELATED_EXPR note, using OFFSET to create a high or lowpart 1565 1.1 mrg subreg. */ 1566 1.1 mrg static rtx 1567 1.1 mrg frame_subreg_note (rtx set, int offset) 1568 1.1 mrg { 1569 1.1 mrg rtx src = simplify_gen_subreg (SImode, SET_SRC (set), DImode, offset); 1570 1.1 mrg rtx dst = simplify_gen_subreg (SImode, SET_DEST (set), DImode, offset); 1571 1.1 mrg 1572 1.1 mrg set = gen_rtx_SET (dst ,src); 1573 1.1 mrg RTX_FRAME_RELATED_P (set) = 1; 1574 1.1 mrg return set; 1575 1.1 mrg } 1576 1.1 mrg 1577 1.1 mrg static rtx_insn * 1578 1.1 mrg frame_insn (rtx x) 1579 1.1 mrg { 1580 1.1 mrg int i; 1581 1.1 mrg rtx note = NULL_RTX; 1582 1.1 mrg rtx_insn *insn; 1583 1.1 mrg 1584 1.1 mrg if (GET_CODE (x) == PARALLEL) 1585 1.1 mrg { 1586 1.1 mrg rtx part = XVECEXP (x, 0, 0); 1587 1.1 mrg 1588 1.1 mrg if (GET_MODE (SET_DEST (part)) == DImode) 1589 1.1 mrg { 1590 1.1 mrg note = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (XVECLEN (x, 0) + 1)); 1591 1.1 mrg XVECEXP (note, 0, 0) = frame_subreg_note (part, 0); 1592 1.1 mrg XVECEXP (note, 0, 1) = frame_subreg_note (part, UNITS_PER_WORD); 1593 1.1 mrg for (i = XVECLEN (x, 0) - 1; i >= 1; i--) 1594 1.1 mrg { 1595 1.1 mrg part = copy_rtx (XVECEXP (x, 0, i)); 1596 1.1 mrg 1597 1.1 mrg if (GET_CODE (part) == SET) 1598 1.1 mrg RTX_FRAME_RELATED_P (part) = 1; 1599 1.1 mrg XVECEXP (note, 0, i + 1) = part; 1600 1.1 mrg } 1601 1.1 mrg } 1602 1.1 mrg else 1603 1.1 mrg { 1604 1.1 mrg for (i = XVECLEN (x, 0) - 1; i >= 0; i--) 1605 1.1 mrg { 1606 1.1 mrg part = XVECEXP (x, 0, i); 1607 1.1 mrg 1608 1.1 mrg if (GET_CODE (part) == SET) 1609 1.1 mrg RTX_FRAME_RELATED_P (part) = 1; 1610 1.1 mrg } 1611 1.1 mrg } 1612 1.1 mrg } 1613 1.1 mrg else if (GET_CODE (x) == SET && GET_MODE (SET_DEST (x)) == DImode) 1614 1.1 mrg note = gen_rtx_PARALLEL (VOIDmode, 1615 1.1 mrg gen_rtvec (2, frame_subreg_note (x, 0), 1616 1.1 mrg frame_subreg_note (x, UNITS_PER_WORD))); 1617 1.1 mrg insn = emit_insn (x); 1618 1.1 mrg RTX_FRAME_RELATED_P (insn) = 1; 1619 1.1 mrg if (note) 1620 1.1 mrg add_reg_note (insn, REG_FRAME_RELATED_EXPR, note); 1621 1.1 mrg return insn; 1622 1.1 mrg } 1623 1.1 mrg 1624 1.1 mrg static rtx_insn * 1625 1.1 mrg frame_move_insn (rtx to, rtx from) 1626 1.1 mrg { 1627 1.1 mrg return frame_insn (gen_rtx_SET (to, from)); 1628 1.1 mrg } 1629 1.1 mrg 1630 1.1 mrg /* Generate a MEM referring to a varargs argument slot. */ 1631 1.1 mrg 1632 1.1 mrg static rtx 1633 1.1 mrg gen_varargs_mem (machine_mode mode, rtx addr) 1634 1.1 mrg { 1635 1.1 mrg rtx mem = gen_rtx_MEM (mode, addr); 1636 1.1 mrg MEM_NOTRAP_P (mem) = 1; 1637 1.1 mrg set_mem_alias_set (mem, get_varargs_alias_set ()); 1638 1.1 mrg return mem; 1639 1.1 mrg } 1640 1.1 mrg 1641 1.1 mrg /* Emit instructions to save or restore registers in the range [MIN..LIMIT) . 1642 1.1 mrg If EPILOGUE_P is 0, save; if it is one, restore. 1643 1.1 mrg ADDR is the stack slot to save the first register to; subsequent 1644 1.1 mrg registers are written to lower addresses. 1645 1.1 mrg However, the order of register pairs can be reversed in order to 1646 1.1 mrg use double-word load-store instructions. Likewise, an unpaired single 1647 1.1 mrg word save slot can be skipped while double saves are carried out, and 1648 1.1 mrg reused when a single register is to be saved. */ 1649 1.1 mrg 1650 1.1 mrg static void 1651 1.1 mrg epiphany_emit_save_restore (int min, int limit, rtx addr, int epilogue_p) 1652 1.1 mrg { 1653 1.1 mrg int i; 1654 1.1 mrg int stack_offset 1655 1.1 mrg = current_frame_info.first_slot >= 0 ? epiphany_stack_offset : 0; 1656 1.1 mrg rtx skipped_mem = NULL_RTX; 1657 1.1 mrg int last_saved = limit - 1; 1658 1.1 mrg 1659 1.1 mrg if (!optimize) 1660 1.1 mrg while (last_saved >= 0 1661 1.1 mrg && !TEST_HARD_REG_BIT (current_frame_info.gmask, last_saved)) 1662 1.1 mrg last_saved--; 1663 1.1 mrg for (i = 0; i < limit; i++) 1664 1.1 mrg { 1665 1.1 mrg machine_mode mode = word_mode; 1666 1.1 mrg rtx mem, reg; 1667 1.1 mrg int n = i; 1668 1.1 mrg rtx (*gen_mem) (machine_mode, rtx) = gen_frame_mem; 1669 1.1 mrg 1670 1.1 mrg /* Make sure we push the arguments in the right order. */ 1671 1.1 mrg if (n < MAX_EPIPHANY_PARM_REGS && crtl->args.pretend_args_size) 1672 1.1 mrg { 1673 1.1 mrg n = MAX_EPIPHANY_PARM_REGS - 1 - n; 1674 1.1 mrg gen_mem = gen_varargs_mem; 1675 1.1 mrg } 1676 1.1 mrg if (stack_offset == current_frame_info.first_slot_size 1677 1.1 mrg && current_frame_info.first_slot >= 0) 1678 1.1 mrg { 1679 1.1 mrg if (current_frame_info.first_slot_size > UNITS_PER_WORD) 1680 1.1 mrg { 1681 1.1 mrg mode = DImode; 1682 1.1 mrg addr = plus_constant (Pmode, addr, 1683 1.1 mrg - (HOST_WIDE_INT) UNITS_PER_WORD); 1684 1.1 mrg } 1685 1.1 mrg if (i-- < min || !epilogue_p) 1686 1.1 mrg goto next_slot; 1687 1.1 mrg n = current_frame_info.first_slot; 1688 1.1 mrg gen_mem = gen_frame_mem; 1689 1.1 mrg } 1690 1.1 mrg else if (n == UNKNOWN_REGNUM 1691 1.1 mrg && stack_offset > current_frame_info.first_slot_size) 1692 1.1 mrg { 1693 1.1 mrg i--; 1694 1.1 mrg goto next_slot; 1695 1.1 mrg } 1696 1.1 mrg else if (!TEST_HARD_REG_BIT (current_frame_info.gmask, n)) 1697 1.1 mrg continue; 1698 1.1 mrg else if (i < min) 1699 1.1 mrg goto next_slot; 1700 1.1 mrg 1701 1.1 mrg /* Check for a register pair to save. */ 1702 1.1 mrg if (n == i 1703 1.1 mrg && (n >= MAX_EPIPHANY_PARM_REGS || crtl->args.pretend_args_size == 0) 1704 1.1 mrg && (n & 1) == 0 && n+1 < limit 1705 1.1 mrg && TEST_HARD_REG_BIT (current_frame_info.gmask, n+1)) 1706 1.1 mrg { 1707 1.1 mrg /* If it fits in the current stack slot pair, place it there. */ 1708 1.1 mrg if (GET_CODE (addr) == PLUS && (stack_offset & 7) == 0 1709 1.1 mrg && stack_offset != 2 * UNITS_PER_WORD 1710 1.1 mrg && (current_frame_info.last_slot < 0 1711 1.1 mrg || INTVAL (XEXP (addr, 1)) != UNITS_PER_WORD) 1712 1.1 mrg && (n+1 != last_saved || !skipped_mem)) 1713 1.1 mrg { 1714 1.1 mrg mode = DImode; 1715 1.1 mrg i++; 1716 1.1 mrg addr = plus_constant (Pmode, addr, 1717 1.1 mrg - (HOST_WIDE_INT) UNITS_PER_WORD); 1718 1.1 mrg } 1719 1.1 mrg /* If it fits in the following stack slot pair, that's fine, too. */ 1720 1.1 mrg else if (GET_CODE (addr) == PLUS && (stack_offset & 7) == 4 1721 1.1 mrg && stack_offset != 2 * UNITS_PER_WORD 1722 1.1 mrg && stack_offset != 3 * UNITS_PER_WORD 1723 1.1 mrg && (current_frame_info.last_slot < 0 1724 1.1 mrg || INTVAL (XEXP (addr, 1)) != 2 * UNITS_PER_WORD) 1725 1.1 mrg && n + 1 != last_saved) 1726 1.1 mrg { 1727 1.1 mrg gcc_assert (!skipped_mem); 1728 1.1 mrg stack_offset -= GET_MODE_SIZE (mode); 1729 1.1 mrg skipped_mem = gen_mem (mode, addr); 1730 1.1 mrg mode = DImode; 1731 1.1 mrg i++; 1732 1.1 mrg addr = plus_constant (Pmode, addr, 1733 1.1 mrg - (HOST_WIDE_INT) 2 * UNITS_PER_WORD); 1734 1.1 mrg } 1735 1.1 mrg } 1736 1.1 mrg reg = gen_rtx_REG (mode, n); 1737 1.1 mrg if (mode != DImode && skipped_mem) 1738 1.1 mrg mem = skipped_mem; 1739 1.1 mrg else 1740 1.1 mrg mem = gen_mem (mode, addr); 1741 1.1 mrg 1742 1.1 mrg /* If we are loading / storing LR, note the offset that 1743 1.1 mrg gen_reload_insi_ra requires. Since GPR_LR is even, 1744 1.1 mrg we only need to test n, even if mode is DImode. */ 1745 1.1 mrg gcc_assert ((GPR_LR & 1) == 0); 1746 1.1 mrg if (n == GPR_LR) 1747 1.1 mrg { 1748 1.1 mrg long lr_slot_offset = 0; 1749 1.1 mrg rtx m_addr = XEXP (mem, 0); 1750 1.1 mrg 1751 1.1 mrg if (GET_CODE (m_addr) == PLUS) 1752 1.1 mrg lr_slot_offset = INTVAL (XEXP (m_addr, 1)); 1753 1.1 mrg if (frame_pointer_needed) 1754 1.1 mrg lr_slot_offset += (current_frame_info.first_slot_offset 1755 1.1 mrg - current_frame_info.total_size); 1756 1.1 mrg if (MACHINE_FUNCTION (cfun)->lr_slot_known) 1757 1.1 mrg gcc_assert (MACHINE_FUNCTION (cfun)->lr_slot_offset 1758 1.1 mrg == lr_slot_offset); 1759 1.1 mrg MACHINE_FUNCTION (cfun)->lr_slot_offset = lr_slot_offset; 1760 1.1 mrg MACHINE_FUNCTION (cfun)->lr_slot_known = 1; 1761 1.1 mrg } 1762 1.1 mrg 1763 1.1 mrg if (!epilogue_p) 1764 1.1 mrg frame_move_insn (mem, reg); 1765 1.1 mrg else if (n >= MAX_EPIPHANY_PARM_REGS || !crtl->args.pretend_args_size) 1766 1.1 mrg emit_move_insn (reg, mem); 1767 1.1 mrg if (mem == skipped_mem) 1768 1.1 mrg { 1769 1.1 mrg skipped_mem = NULL_RTX; 1770 1.1 mrg continue; 1771 1.1 mrg } 1772 1.1 mrg next_slot: 1773 1.1 mrg addr = plus_constant (Pmode, addr, -(HOST_WIDE_INT) UNITS_PER_WORD); 1774 1.1 mrg stack_offset -= GET_MODE_SIZE (mode); 1775 1.1 mrg } 1776 1.1 mrg } 1777 1.1 mrg 1778 1.1 mrg void 1779 1.1 mrg epiphany_expand_prologue (void) 1780 1.1 mrg { 1781 1.1 mrg int interrupt_p; 1782 1.1 mrg enum epiphany_function_type fn_type; 1783 1.1 mrg rtx addr, mem, off, reg; 1784 1.1 mrg 1785 1.1 mrg if (!current_frame_info.initialized) 1786 1.1 mrg epiphany_compute_frame_size (get_frame_size ()); 1787 1.1 mrg 1788 1.1 mrg /* It is debatable if we should adjust this by epiphany_stack_offset. */ 1789 1.1 mrg if (flag_stack_usage_info) 1790 1.1 mrg current_function_static_stack_size = current_frame_info.total_size; 1791 1.1 mrg 1792 1.1 mrg fn_type = epiphany_compute_function_type (current_function_decl); 1793 1.1 mrg interrupt_p = EPIPHANY_INTERRUPT_P (fn_type); 1794 1.1 mrg 1795 1.1 mrg if (interrupt_p) 1796 1.1 mrg { 1797 1.1 mrg addr = plus_constant (Pmode, stack_pointer_rtx, 1798 1.1 mrg - (HOST_WIDE_INT) 2 * UNITS_PER_WORD); 1799 1.1 mrg if (!lookup_attribute ("forwarder_section", 1800 1.1 mrg DECL_ATTRIBUTES (current_function_decl)) 1801 1.1 mrg || !epiphany_is_long_call_p (XEXP (DECL_RTL (current_function_decl), 1802 1.1 mrg 0))) 1803 1.1 mrg frame_move_insn (gen_frame_mem (DImode, addr), 1804 1.1 mrg gen_rtx_REG (DImode, GPR_0)); 1805 1.1 mrg frame_move_insn (gen_rtx_REG (SImode, GPR_0), 1806 1.1 mrg gen_rtx_REG (word_mode, STATUS_REGNUM)); 1807 1.1 mrg frame_move_insn (gen_rtx_REG (SImode, GPR_1), 1808 1.1 mrg gen_rtx_REG (word_mode, IRET_REGNUM)); 1809 1.1 mrg mem = gen_frame_mem (BLKmode, stack_pointer_rtx); 1810 1.1 mrg off = GEN_INT (-current_frame_info.first_slot_offset); 1811 1.1 mrg frame_insn (gen_stack_adjust_add (off, mem)); 1812 1.1 mrg if (!epiphany_uninterruptible_p (current_function_decl)) 1813 1.1 mrg emit_insn (gen_gie ()); 1814 1.1 mrg addr = plus_constant (Pmode, stack_pointer_rtx, 1815 1.1 mrg current_frame_info.first_slot_offset 1816 1.1 mrg - (HOST_WIDE_INT) 3 * UNITS_PER_WORD); 1817 1.1 mrg } 1818 1.1 mrg else 1819 1.1 mrg { 1820 1.1 mrg addr = plus_constant (Pmode, stack_pointer_rtx, 1821 1.1 mrg epiphany_stack_offset 1822 1.1 mrg - (HOST_WIDE_INT) UNITS_PER_WORD); 1823 1.1 mrg epiphany_emit_save_restore (0, current_frame_info.small_threshold, 1824 1.1 mrg addr, 0); 1825 1.1 mrg /* Allocate register save area; for small to medium size frames, 1826 1.1 mrg allocate the entire frame; this is joint with one register save. */ 1827 1.1 mrg if (current_frame_info.first_slot >= 0) 1828 1.1 mrg { 1829 1.1 mrg machine_mode mode 1830 1.1 mrg = (current_frame_info.first_slot_size == UNITS_PER_WORD 1831 1.1 mrg ? word_mode : DImode); 1832 1.1 mrg 1833 1.1 mrg off = GEN_INT (-current_frame_info.first_slot_offset); 1834 1.1 mrg mem = gen_frame_mem (BLKmode, 1835 1.1 mrg gen_rtx_PLUS (Pmode, stack_pointer_rtx, off)); 1836 1.1 mrg frame_insn (gen_stack_adjust_str 1837 1.1 mrg (gen_frame_mem (mode, stack_pointer_rtx), 1838 1.1 mrg gen_rtx_REG (mode, current_frame_info.first_slot), 1839 1.1 mrg off, mem)); 1840 1.1 mrg addr = plus_constant (Pmode, addr, 1841 1.1 mrg current_frame_info.first_slot_offset); 1842 1.1 mrg } 1843 1.1 mrg } 1844 1.1 mrg epiphany_emit_save_restore (current_frame_info.small_threshold, 1845 1.1 mrg FIRST_PSEUDO_REGISTER, addr, 0); 1846 1.1 mrg if (current_frame_info.need_fp) 1847 1.1 mrg frame_move_insn (hard_frame_pointer_rtx, stack_pointer_rtx); 1848 1.1 mrg /* For large frames, allocate bulk of frame. This is usually joint with one 1849 1.1 mrg register save. */ 1850 1.1 mrg if (current_frame_info.last_slot >= 0) 1851 1.1 mrg { 1852 1.1 mrg rtx ip, mem2, note; 1853 1.1 mrg rtx_insn *insn; 1854 1.1 mrg 1855 1.1 mrg gcc_assert (current_frame_info.last_slot != GPR_FP 1856 1.1 mrg || (!current_frame_info.need_fp 1857 1.1 mrg && current_frame_info.first_slot < 0)); 1858 1.1 mrg off = GEN_INT (-current_frame_info.last_slot_offset); 1859 1.1 mrg mem = gen_frame_mem (BLKmode, 1860 1.1 mrg gen_rtx_PLUS (Pmode, stack_pointer_rtx, off)); 1861 1.1 mrg ip = gen_rtx_REG (Pmode, GPR_IP); 1862 1.1 mrg frame_move_insn (ip, off); 1863 1.1 mrg reg = gen_rtx_REG (word_mode, current_frame_info.last_slot), 1864 1.1 mrg mem2 = gen_frame_mem (word_mode, stack_pointer_rtx), 1865 1.1 mrg insn = frame_insn (gen_stack_adjust_str (mem2, reg, ip, mem)); 1866 1.1 mrg /* Instruction scheduling can separate the instruction setting IP from 1867 1.1 mrg INSN so that dwarf2out_frame_debug_expr becomes confused what the 1868 1.1 mrg temporary register is. Example: _gcov.o */ 1869 1.1 mrg note = gen_rtx_SET (stack_pointer_rtx, 1870 1.1 mrg gen_rtx_PLUS (Pmode, stack_pointer_rtx, off)); 1871 1.1 mrg note = gen_rtx_PARALLEL (VOIDmode, 1872 1.1 mrg gen_rtvec (2, gen_rtx_SET (mem2, reg), note)); 1873 1.1 mrg add_reg_note (insn, REG_FRAME_RELATED_EXPR, note); 1874 1.1 mrg } 1875 1.1 mrg /* If there is only one or no register to save, yet we have a large frame, 1876 1.1 mrg use an add. */ 1877 1.1 mrg else if (current_frame_info.last_slot_offset) 1878 1.1 mrg { 1879 1.1 mrg mem = gen_frame_mem (BLKmode, 1880 1.1 mrg plus_constant (Pmode, stack_pointer_rtx, 1881 1.1 mrg current_frame_info.last_slot_offset)); 1882 1.1 mrg off = GEN_INT (-current_frame_info.last_slot_offset); 1883 1.1 mrg if (!SIMM11 (INTVAL (off))) 1884 1.1 mrg { 1885 1.1 mrg reg = gen_rtx_REG (Pmode, GPR_IP); 1886 1.1 mrg frame_move_insn (reg, off); 1887 1.1 mrg off = reg; 1888 1.1 mrg } 1889 1.1 mrg frame_insn (gen_stack_adjust_add (off, mem)); 1890 1.1 mrg } 1891 1.1 mrg } 1892 1.1 mrg 1893 1.1 mrg void 1894 1.1 mrg epiphany_expand_epilogue (int sibcall_p) 1895 1.1 mrg { 1896 1.1 mrg int interrupt_p; 1897 1.1 mrg enum epiphany_function_type fn_type; 1898 1.1 mrg rtx mem, addr, reg, off; 1899 1.1 mrg HOST_WIDE_INT restore_offset; 1900 1.1 mrg 1901 1.1 mrg fn_type = epiphany_compute_function_type( current_function_decl); 1902 1.1 mrg interrupt_p = EPIPHANY_INTERRUPT_P (fn_type); 1903 1.1 mrg 1904 1.1 mrg /* For variable frames, deallocate bulk of frame. */ 1905 1.1 mrg if (current_frame_info.need_fp) 1906 1.1 mrg { 1907 1.1 mrg mem = gen_frame_mem (BLKmode, stack_pointer_rtx); 1908 1.1 mrg emit_insn (gen_stack_adjust_mov (mem)); 1909 1.1 mrg } 1910 1.1 mrg /* Else for large static frames, deallocate bulk of frame. */ 1911 1.1 mrg else if (current_frame_info.last_slot_offset) 1912 1.1 mrg { 1913 1.1 mrg mem = gen_frame_mem (BLKmode, stack_pointer_rtx); 1914 1.1 mrg reg = gen_rtx_REG (Pmode, GPR_IP); 1915 1.1 mrg emit_move_insn (reg, GEN_INT (current_frame_info.last_slot_offset)); 1916 1.1 mrg emit_insn (gen_stack_adjust_add (reg, mem)); 1917 1.1 mrg } 1918 1.1 mrg restore_offset = (interrupt_p 1919 1.1 mrg ? - 3 * UNITS_PER_WORD 1920 1.1 mrg : epiphany_stack_offset - (HOST_WIDE_INT) UNITS_PER_WORD); 1921 1.1 mrg addr = plus_constant (Pmode, stack_pointer_rtx, 1922 1.1 mrg (current_frame_info.first_slot_offset 1923 1.1 mrg + restore_offset)); 1924 1.1 mrg epiphany_emit_save_restore (current_frame_info.small_threshold, 1925 1.1 mrg FIRST_PSEUDO_REGISTER, addr, 1); 1926 1.1 mrg 1927 1.1 mrg if (interrupt_p && !epiphany_uninterruptible_p (current_function_decl)) 1928 1.1 mrg emit_insn (gen_gid ()); 1929 1.1 mrg 1930 1.1 mrg off = GEN_INT (current_frame_info.first_slot_offset); 1931 1.1 mrg mem = gen_frame_mem (BLKmode, stack_pointer_rtx); 1932 1.1 mrg /* For large / variable size frames, deallocating the register save area is 1933 1.1 mrg joint with one register restore; for medium size frames, we use a 1934 1.1 mrg dummy post-increment load to dealloacte the whole frame. */ 1935 1.1 mrg if (!SIMM11 (INTVAL (off)) || current_frame_info.last_slot >= 0) 1936 1.1 mrg { 1937 1.1 mrg emit_insn (gen_stack_adjust_ldr 1938 1.1 mrg (gen_rtx_REG (word_mode, 1939 1.1 mrg (current_frame_info.last_slot >= 0 1940 1.1 mrg ? current_frame_info.last_slot : GPR_IP)), 1941 1.1 mrg gen_frame_mem (word_mode, stack_pointer_rtx), 1942 1.1 mrg off, 1943 1.1 mrg mem)); 1944 1.1 mrg } 1945 1.1 mrg /* While for small frames, we deallocate the entire frame with one add. */ 1946 1.1 mrg else if (INTVAL (off)) 1947 1.1 mrg { 1948 1.1 mrg emit_insn (gen_stack_adjust_add (off, mem)); 1949 1.1 mrg } 1950 1.1 mrg if (interrupt_p) 1951 1.1 mrg { 1952 1.1 mrg emit_move_insn (gen_rtx_REG (word_mode, STATUS_REGNUM), 1953 1.1 mrg gen_rtx_REG (SImode, GPR_0)); 1954 1.1 mrg emit_move_insn (gen_rtx_REG (word_mode, IRET_REGNUM), 1955 1.1 mrg gen_rtx_REG (SImode, GPR_1)); 1956 1.1 mrg addr = plus_constant (Pmode, stack_pointer_rtx, 1957 1.1 mrg - (HOST_WIDE_INT) 2 * UNITS_PER_WORD); 1958 1.1 mrg emit_move_insn (gen_rtx_REG (DImode, GPR_0), 1959 1.1 mrg gen_frame_mem (DImode, addr)); 1960 1.1 mrg } 1961 1.1 mrg addr = plus_constant (Pmode, stack_pointer_rtx, 1962 1.1 mrg epiphany_stack_offset - (HOST_WIDE_INT) UNITS_PER_WORD); 1963 1.1 mrg epiphany_emit_save_restore (0, current_frame_info.small_threshold, addr, 1); 1964 1.1 mrg if (!sibcall_p) 1965 1.1 mrg { 1966 1.1 mrg if (interrupt_p) 1967 1.1 mrg emit_jump_insn (gen_return_internal_interrupt()); 1968 1.1 mrg else 1969 1.1 mrg emit_jump_insn (gen_return_i ()); 1970 1.1 mrg } 1971 1.1 mrg } 1972 1.1 mrg 1973 1.1 mrg int 1974 1.1 mrg epiphany_initial_elimination_offset (int from, int to) 1975 1.1 mrg { 1976 1.1 mrg epiphany_compute_frame_size (get_frame_size ()); 1977 1.1 mrg if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM) 1978 1.1 mrg return current_frame_info.total_size - current_frame_info.reg_size; 1979 1.1 mrg if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM) 1980 1.1 mrg return current_frame_info.first_slot_offset - current_frame_info.reg_size; 1981 1.1 mrg if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM) 1982 1.1 mrg return (current_frame_info.total_size 1983 1.1 mrg - ((current_frame_info.pretend_size + 4) & -8)); 1984 1.1 mrg if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM) 1985 1.1 mrg return (current_frame_info.first_slot_offset 1986 1.1 mrg - ((current_frame_info.pretend_size + 4) & -8)); 1987 1.1 mrg gcc_unreachable (); 1988 1.1 mrg } 1989 1.1 mrg 1990 1.1 mrg bool 1991 1.1 mrg epiphany_regno_rename_ok (unsigned, unsigned dst) 1992 1.1 mrg { 1993 1.1 mrg enum epiphany_function_type fn_type; 1994 1.1 mrg 1995 1.1 mrg fn_type = epiphany_compute_function_type (current_function_decl); 1996 1.1 mrg if (!EPIPHANY_INTERRUPT_P (fn_type)) 1997 1.1 mrg return true; 1998 1.1 mrg if (df_regs_ever_live_p (dst)) 1999 1.1 mrg return true; 2000 1.1 mrg return false; 2001 1.1 mrg } 2002 1.1 mrg 2003 1.1 mrg static int 2004 1.1 mrg epiphany_issue_rate (void) 2005 1.1 mrg { 2006 1.1 mrg return 2; 2007 1.1 mrg } 2008 1.1 mrg 2009 1.1 mrg /* Function to update the integer COST 2010 1.1 mrg based on the relationship between INSN that is dependent on 2011 1.1 mrg DEP_INSN through the dependence LINK. The default is to make no 2012 1.1 mrg adjustment to COST. This can be used for example to specify to 2013 1.1 mrg the scheduler that an output- or anti-dependence does not incur 2014 1.1 mrg the same cost as a data-dependence. The return value should be 2015 1.1 mrg the new value for COST. */ 2016 1.1 mrg static int 2017 1.1 mrg epiphany_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn, 2018 1.1 mrg int cost, unsigned int) 2019 1.1 mrg { 2020 1.1 mrg if (dep_type == 0) 2021 1.1 mrg { 2022 1.1 mrg rtx dep_set; 2023 1.1 mrg 2024 1.1 mrg if (recog_memoized (insn) < 0 2025 1.1 mrg || recog_memoized (dep_insn) < 0) 2026 1.1 mrg return cost; 2027 1.1 mrg 2028 1.1 mrg dep_set = single_set (dep_insn); 2029 1.1 mrg 2030 1.1 mrg /* The latency that we specify in the scheduling description refers 2031 1.1 mrg to the actual output, not to an auto-increment register; for that, 2032 1.1 mrg the latency is one. */ 2033 1.1 mrg if (dep_set && MEM_P (SET_SRC (dep_set)) && cost > 1) 2034 1.1 mrg { 2035 1.1 mrg rtx set = single_set (insn); 2036 1.1 mrg 2037 1.1 mrg if (set 2038 1.1 mrg && !reg_overlap_mentioned_p (SET_DEST (dep_set), SET_SRC (set)) 2039 1.1 mrg && (!MEM_P (SET_DEST (set)) 2040 1.1 mrg || !reg_overlap_mentioned_p (SET_DEST (dep_set), 2041 1.1 mrg XEXP (SET_DEST (set), 0)))) 2042 1.1 mrg cost = 1; 2043 1.1 mrg } 2044 1.1 mrg } 2045 1.1 mrg return cost; 2046 1.1 mrg } 2047 1.1 mrg 2048 1.1 mrg #define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_BASE_P (X) 2049 1.1 mrg 2050 1.1 mrg #define RTX_OK_FOR_BASE_P(X) \ 2051 1.1 mrg (REG_P (X) && REG_OK_FOR_BASE_P (X)) 2052 1.1 mrg 2053 1.1 mrg #define RTX_OK_FOR_INDEX_P(MODE, X) \ 2054 1.1 mrg ((GET_MODE_CLASS (MODE) != MODE_VECTOR_INT \ 2055 1.1 mrg || epiphany_vect_align >= GET_MODE_SIZE (MODE)) \ 2056 1.1 mrg && (REG_P (X) && REG_OK_FOR_INDEX_P (X))) 2057 1.1 mrg 2058 1.1 mrg #define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X) \ 2059 1.1 mrg (GET_CODE (X) == PLUS \ 2060 1.1 mrg && RTX_OK_FOR_BASE_P (XEXP (X, 0)) \ 2061 1.1 mrg && (RTX_OK_FOR_INDEX_P (MODE, XEXP (X, 1)) \ 2062 1.1 mrg || RTX_OK_FOR_OFFSET_P (MODE, XEXP (X, 1)))) 2063 1.1 mrg 2064 1.1 mrg static bool 2065 1.1 mrg epiphany_legitimate_address_p (machine_mode mode, rtx x, bool strict) 2066 1.1 mrg { 2067 1.1 mrg #define REG_OK_FOR_BASE_P(X) \ 2068 1.1 mrg (strict ? GPR_P (REGNO (X)) : GPR_AP_OR_PSEUDO_P (REGNO (X))) 2069 1.1 mrg if (RTX_OK_FOR_BASE_P (x)) 2070 1.1 mrg return true; 2071 1.1 mrg if (RTX_FRAME_OFFSET_P (x)) 2072 1.1 mrg return true; 2073 1.1 mrg if (LEGITIMATE_OFFSET_ADDRESS_P (mode, x)) 2074 1.1 mrg return true; 2075 1.1 mrg /* If this is a misaligned stack access, don't force it to reg+index. */ 2076 1.1 mrg if (GET_MODE_SIZE (mode) == 8 2077 1.1 mrg && GET_CODE (x) == PLUS && XEXP (x, 0) == stack_pointer_rtx 2078 1.1 mrg /* Decomposed to SImode; GET_MODE_SIZE (SImode) == 4 */ 2079 1.1 mrg && !(INTVAL (XEXP (x, 1)) & 3) 2080 1.1 mrg && INTVAL (XEXP (x, 1)) >= -2047 * 4 2081 1.1 mrg && INTVAL (XEXP (x, 1)) <= 2046 * 4) 2082 1.1 mrg return true; 2083 1.1 mrg if (TARGET_POST_INC 2084 1.1 mrg && (GET_CODE (x) == POST_DEC || GET_CODE (x) == POST_INC) 2085 1.1 mrg && RTX_OK_FOR_BASE_P (XEXP ((x), 0))) 2086 1.1 mrg return true; 2087 1.1 mrg if ((TARGET_POST_MODIFY || reload_completed) 2088 1.1 mrg && GET_CODE (x) == POST_MODIFY 2089 1.1 mrg && GET_CODE (XEXP ((x), 1)) == PLUS 2090 1.1 mrg && rtx_equal_p (XEXP ((x), 0), XEXP (XEXP ((x), 1), 0)) 2091 1.1 mrg && LEGITIMATE_OFFSET_ADDRESS_P (mode, XEXP ((x), 1))) 2092 1.1 mrg return true; 2093 1.1 mrg if (mode == BLKmode) 2094 1.1 mrg return epiphany_legitimate_address_p (SImode, x, strict); 2095 1.1 mrg return false; 2096 1.1 mrg } 2097 1.1 mrg 2098 1.1 mrg static reg_class_t 2099 1.1 mrg epiphany_secondary_reload (bool in_p, rtx x, reg_class_t rclass, 2100 1.1 mrg machine_mode mode ATTRIBUTE_UNUSED, 2101 1.1 mrg secondary_reload_info *sri) 2102 1.1 mrg { 2103 1.1 mrg /* This could give more reload inheritance, but we are missing some 2104 1.1 mrg reload infrastructure. */ 2105 1.1 mrg if (0) 2106 1.1 mrg if (in_p && GET_CODE (x) == UNSPEC 2107 1.1 mrg && satisfies_constraint_Sra (x) && !satisfies_constraint_Rra (x)) 2108 1.1 mrg { 2109 1.1 mrg gcc_assert (rclass == GENERAL_REGS); 2110 1.1 mrg sri->icode = CODE_FOR_reload_insi_ra; 2111 1.1 mrg return NO_REGS; 2112 1.1 mrg } 2113 1.1 mrg return NO_REGS; 2114 1.1 mrg } 2115 1.1 mrg 2116 1.1 mrg bool 2117 1.1 mrg epiphany_is_long_call_p (rtx x) 2118 1.1 mrg { 2119 1.1 mrg tree decl = SYMBOL_REF_DECL (x); 2120 1.1 mrg bool ret_val = !TARGET_SHORT_CALLS; 2121 1.1 mrg tree attrs; 2122 1.1 mrg 2123 1.1 mrg /* ??? Is it safe to default to ret_val if decl is NULL? We should 2124 1.1 mrg probably encode information via encode_section_info, and also 2125 1.1 mrg have (an) option(s) to take SYMBOL_FLAG_LOCAL and/or SYMBOL_FLAG_EXTERNAL 2126 1.1 mrg into account. */ 2127 1.1 mrg if (decl) 2128 1.1 mrg { 2129 1.1 mrg attrs = TYPE_ATTRIBUTES (TREE_TYPE (decl)); 2130 1.1 mrg if (lookup_attribute ("long_call", attrs)) 2131 1.1 mrg ret_val = true; 2132 1.1 mrg else if (lookup_attribute ("short_call", attrs)) 2133 1.1 mrg ret_val = false; 2134 1.1 mrg } 2135 1.1 mrg return ret_val; 2136 1.1 mrg } 2137 1.1 mrg 2138 1.1 mrg bool 2139 1.1 mrg epiphany_small16 (rtx x) 2140 1.1 mrg { 2141 1.1 mrg rtx base = x; 2142 1.1 mrg rtx offs ATTRIBUTE_UNUSED = const0_rtx; 2143 1.1 mrg 2144 1.1 mrg if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS) 2145 1.1 mrg { 2146 1.1 mrg base = XEXP (XEXP (x, 0), 0); 2147 1.1 mrg offs = XEXP (XEXP (x, 0), 1); 2148 1.1 mrg } 2149 1.1 mrg if (GET_CODE (base) == SYMBOL_REF && SYMBOL_REF_FUNCTION_P (base) 2150 1.1 mrg && epiphany_is_long_call_p (base)) 2151 1.1 mrg return false; 2152 1.1 mrg return TARGET_SMALL16 != 0; 2153 1.1 mrg } 2154 1.1 mrg 2155 1.1 mrg /* Return nonzero if it is ok to make a tail-call to DECL. */ 2156 1.1 mrg static bool 2157 1.1 mrg epiphany_function_ok_for_sibcall (tree decl, tree exp) 2158 1.1 mrg { 2159 1.1 mrg bool cfun_interrupt_p, call_interrupt_p; 2160 1.1 mrg 2161 1.1 mrg cfun_interrupt_p = EPIPHANY_INTERRUPT_P (epiphany_compute_function_type 2162 1.1 mrg (current_function_decl)); 2163 1.1 mrg if (decl) 2164 1.1 mrg call_interrupt_p = EPIPHANY_INTERRUPT_P (epiphany_compute_function_type (decl)); 2165 1.1 mrg else 2166 1.1 mrg { 2167 1.1 mrg tree fn_type = TREE_TYPE (CALL_EXPR_FN (exp)); 2168 1.1 mrg 2169 1.1 mrg gcc_assert (POINTER_TYPE_P (fn_type)); 2170 1.1 mrg fn_type = TREE_TYPE (fn_type); 2171 1.1 mrg gcc_assert (TREE_CODE (fn_type) == FUNCTION_TYPE 2172 1.1 mrg || TREE_CODE (fn_type) == METHOD_TYPE); 2173 1.1 mrg call_interrupt_p 2174 1.1 mrg = lookup_attribute ("interrupt", TYPE_ATTRIBUTES (fn_type)) != NULL; 2175 1.1 mrg } 2176 1.1 mrg 2177 1.1 mrg /* Don't tailcall from or to an ISR routine - although we could in 2178 1.1 mrg principle tailcall from one ISR routine to another, we'd need to 2179 1.1 mrg handle this in sibcall_epilogue to make it work. */ 2180 1.1 mrg if (cfun_interrupt_p || call_interrupt_p) 2181 1.1 mrg return false; 2182 1.1 mrg 2183 1.1 mrg /* Everything else is ok. */ 2184 1.1 mrg return true; 2185 1.1 mrg } 2186 1.1 mrg 2187 1.1 mrg /* T is a function declaration or the MEM_EXPR of a MEM passed to a call 2188 1.1 mrg expander. 2189 1.1 mrg Return true iff the type of T has the uninterruptible attribute. 2190 1.1 mrg If T is NULL, return false. */ 2191 1.1 mrg bool 2192 1.1 mrg epiphany_uninterruptible_p (tree t) 2193 1.1 mrg { 2194 1.1 mrg tree attrs; 2195 1.1 mrg 2196 1.1 mrg if (t) 2197 1.1 mrg { 2198 1.1 mrg attrs = TYPE_ATTRIBUTES (TREE_TYPE (t)); 2199 1.1 mrg if (lookup_attribute ("disinterrupt", attrs)) 2200 1.1 mrg return true; 2201 1.1 mrg } 2202 1.1 mrg return false; 2203 1.1 mrg } 2204 1.1 mrg 2205 1.1 mrg bool 2206 1.1 mrg epiphany_call_uninterruptible_p (rtx mem) 2207 1.1 mrg { 2208 1.1 mrg rtx addr = XEXP (mem, 0); 2209 1.1 mrg tree t = NULL_TREE; 2210 1.1 mrg 2211 1.1 mrg if (GET_CODE (addr) == SYMBOL_REF) 2212 1.1 mrg t = SYMBOL_REF_DECL (addr); 2213 1.1 mrg if (!t) 2214 1.1 mrg t = MEM_EXPR (mem); 2215 1.1 mrg return epiphany_uninterruptible_p (t); 2216 1.1 mrg } 2217 1.1 mrg 2218 1.1 mrg static machine_mode 2219 1.1 mrg epiphany_promote_function_mode (const_tree type, machine_mode mode, 2220 1.1 mrg int *punsignedp ATTRIBUTE_UNUSED, 2221 1.1 mrg const_tree funtype ATTRIBUTE_UNUSED, 2222 1.1 mrg int for_return ATTRIBUTE_UNUSED) 2223 1.1 mrg { 2224 1.1 mrg int dummy; 2225 1.1 mrg 2226 1.1 mrg return promote_mode (type, mode, &dummy); 2227 1.1 mrg } 2228 1.1 mrg 2229 1.1 mrg static void 2230 1.1 mrg epiphany_conditional_register_usage (void) 2231 1.1 mrg { 2232 1.1 mrg int i; 2233 1.1 mrg 2234 1.1 mrg if (PIC_OFFSET_TABLE_REGNUM != INVALID_REGNUM) 2235 1.1 mrg { 2236 1.1 mrg fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1; 2237 1.1 mrg call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1; 2238 1.1 mrg } 2239 1.1 mrg if (TARGET_HALF_REG_FILE) 2240 1.1 mrg { 2241 1.1 mrg for (i = 32; i <= 63; i++) 2242 1.1 mrg { 2243 1.1 mrg fixed_regs[i] = 1; 2244 1.1 mrg call_used_regs[i] = 1; 2245 1.1 mrg } 2246 1.1 mrg } 2247 1.1 mrg if (epiphany_m1reg >= 0) 2248 1.1 mrg { 2249 1.1 mrg fixed_regs[epiphany_m1reg] = 1; 2250 1.1 mrg call_used_regs[epiphany_m1reg] = 1; 2251 1.1 mrg } 2252 1.1 mrg if (!TARGET_PREFER_SHORT_INSN_REGS) 2253 1.1 mrg CLEAR_HARD_REG_SET (reg_class_contents[SHORT_INSN_REGS]); 2254 1.1 mrg reg_class_contents[SIBCALL_REGS] = reg_class_contents[GENERAL_REGS]; 2255 1.1 mrg /* It would be simpler and quicker if we could just use 2256 1.1 mrg &~, alas, call_used_or_fixed_regs is yet uninitialized; 2257 1.1 mrg it is set up later by our caller. */ 2258 1.1 mrg for (i = 0; i < FIRST_PSEUDO_REGISTER; i++) 2259 1.1 mrg if (!call_used_regs[i]) 2260 1.1 mrg CLEAR_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], i); 2261 1.1 mrg } 2262 1.1 mrg 2263 1.1 mrg /* Determine where to put an argument to a function. 2264 1.1 mrg Value is zero to push the argument on the stack, 2265 1.1 mrg or a hard register in which to store the argument. 2266 1.1 mrg 2267 1.1 mrg CUM is a variable of type CUMULATIVE_ARGS which gives info about 2268 1.1 mrg the preceding args and about the function being called. 2269 1.1 mrg ARG is a description of the argument. */ 2270 1.1 mrg /* On the EPIPHANY the first MAX_EPIPHANY_PARM_REGS args are normally in 2271 1.1 mrg registers and the rest are pushed. */ 2272 1.1 mrg static rtx 2273 1.1 mrg epiphany_function_arg (cumulative_args_t cum_v, const function_arg_info &arg) 2274 1.1 mrg { 2275 1.1 mrg CUMULATIVE_ARGS cum = *get_cumulative_args (cum_v); 2276 1.1 mrg 2277 1.1 mrg if (PASS_IN_REG_P (cum, arg.mode, arg.type)) 2278 1.1 mrg return gen_rtx_REG (arg.mode, ROUND_ADVANCE_CUM (cum, arg.mode, arg.type)); 2279 1.1 mrg return 0; 2280 1.1 mrg } 2281 1.1 mrg 2282 1.1 mrg /* Update the data in CUM to advance over argument ARG. */ 2283 1.1 mrg static void 2284 1.1 mrg epiphany_function_arg_advance (cumulative_args_t cum_v, 2285 1.1 mrg const function_arg_info &arg) 2286 1.1 mrg { 2287 1.1 mrg CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v); 2288 1.1 mrg 2289 1.1 mrg *cum = (ROUND_ADVANCE_CUM (*cum, arg.mode, arg.type) 2290 1.1 mrg + ROUND_ADVANCE_ARG (arg.mode, arg.type)); 2291 1.1 mrg } 2292 1.1 mrg 2293 1.1 mrg /* Nested function support. 2295 1.1 mrg An epiphany trampoline looks like this: 2296 1.1 mrg mov r16,%low(fnaddr) 2297 1.1 mrg movt r16,%high(fnaddr) 2298 1.1 mrg mov ip,%low(cxt) 2299 1.1 mrg movt ip,%high(cxt) 2300 1.1 mrg jr r16 */ 2301 1.1 mrg 2302 1.1 mrg #define EPIPHANY_LOW_RTX(X) \ 2303 1.1 mrg (gen_rtx_IOR (SImode, \ 2304 1.1 mrg gen_rtx_ASHIFT (SImode, \ 2305 1.1 mrg gen_rtx_AND (SImode, (X), GEN_INT (0xff)), GEN_INT (5)), \ 2306 1.1 mrg gen_rtx_ASHIFT (SImode, \ 2307 1.1 mrg gen_rtx_AND (SImode, (X), GEN_INT (0xff00)), GEN_INT (12)))) 2308 1.1 mrg #define EPIPHANY_HIGH_RTX(X) \ 2309 1.1 mrg EPIPHANY_LOW_RTX (gen_rtx_LSHIFTRT (SImode, (X), GEN_INT (16))) 2310 1.1 mrg 2311 1.1 mrg /* Emit RTL insns to initialize the variable parts of a trampoline. 2312 1.1 mrg FNADDR is an RTX for the address of the function's pure code. 2313 1.1 mrg CXT is an RTX for the static chain value for the function. */ 2314 1.1 mrg static void 2315 1.1 mrg epiphany_trampoline_init (rtx tramp_mem, tree fndecl, rtx cxt) 2316 1.1 mrg { 2317 1.1 mrg rtx fnaddr = XEXP (DECL_RTL (fndecl), 0); 2318 1.1 mrg rtx tramp = force_reg (Pmode, XEXP (tramp_mem, 0)); 2319 1.1 mrg 2320 1.1 mrg emit_move_insn (gen_rtx_MEM (SImode, plus_constant (Pmode, tramp, 0)), 2321 1.1 mrg gen_rtx_IOR (SImode, GEN_INT (0x4002000b), 2322 1.1 mrg EPIPHANY_LOW_RTX (fnaddr))); 2323 1.1 mrg emit_move_insn (gen_rtx_MEM (SImode, plus_constant (Pmode, tramp, 4)), 2324 1.1 mrg gen_rtx_IOR (SImode, GEN_INT (0x5002000b), 2325 1.1 mrg EPIPHANY_HIGH_RTX (fnaddr))); 2326 1.1 mrg emit_move_insn (gen_rtx_MEM (SImode, plus_constant (Pmode, tramp, 8)), 2327 1.1 mrg gen_rtx_IOR (SImode, GEN_INT (0x2002800b), 2328 1.1 mrg EPIPHANY_LOW_RTX (cxt))); 2329 1.1 mrg emit_move_insn (gen_rtx_MEM (SImode, plus_constant (Pmode, tramp, 12)), 2330 1.1 mrg gen_rtx_IOR (SImode, GEN_INT (0x3002800b), 2331 1.1 mrg EPIPHANY_HIGH_RTX (cxt))); 2332 1.1 mrg emit_move_insn (gen_rtx_MEM (SImode, plus_constant (Pmode, tramp, 16)), 2333 1.1 mrg GEN_INT (0x0802014f)); 2334 1.1 mrg } 2335 1.1 mrg 2336 1.1 mrg bool 2338 1.1 mrg epiphany_optimize_mode_switching (int entity) 2339 1.1 mrg { 2340 1.1 mrg if (MACHINE_FUNCTION (cfun)->sw_entities_processed & (1 << entity)) 2341 1.1 mrg return false; 2342 1.1 mrg switch (entity) 2343 1.1 mrg { 2344 1.1 mrg case EPIPHANY_MSW_ENTITY_AND: 2345 1.1 mrg case EPIPHANY_MSW_ENTITY_OR: 2346 1.1 mrg case EPIPHANY_MSW_ENTITY_CONFIG: 2347 1.1 mrg return true; 2348 1.1 mrg case EPIPHANY_MSW_ENTITY_NEAREST: 2349 1.1 mrg case EPIPHANY_MSW_ENTITY_TRUNC: 2350 1.1 mrg return optimize > 0; 2351 1.1 mrg case EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN: 2352 1.1 mrg return MACHINE_FUNCTION (cfun)->unknown_mode_uses != 0; 2353 1.1 mrg case EPIPHANY_MSW_ENTITY_ROUND_KNOWN: 2354 1.1 mrg return (MACHINE_FUNCTION (cfun)->sw_entities_processed 2355 1.1 mrg & (1 << EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN)) != 0; 2356 1.1 mrg case EPIPHANY_MSW_ENTITY_FPU_OMNIBUS: 2357 1.1 mrg return optimize == 0 || current_pass == pass_mode_switch_use; 2358 1.1 mrg } 2359 1.1 mrg gcc_unreachable (); 2360 1.1 mrg } 2361 1.1 mrg 2362 1.1 mrg static int 2363 1.1 mrg epiphany_mode_priority (int entity, int priority) 2364 1.1 mrg { 2365 1.1 mrg if (entity == EPIPHANY_MSW_ENTITY_AND || entity == EPIPHANY_MSW_ENTITY_OR 2366 1.1 mrg || entity== EPIPHANY_MSW_ENTITY_CONFIG) 2367 1.1 mrg return priority; 2368 1.1 mrg if (priority > 3) 2369 1.1 mrg switch (priority) 2370 1.1 mrg { 2371 1.1 mrg case 4: return FP_MODE_ROUND_UNKNOWN; 2372 1.1 mrg case 5: return FP_MODE_NONE; 2373 1.1 mrg default: gcc_unreachable (); 2374 1.1 mrg } 2375 1.1 mrg switch ((enum attr_fp_mode) epiphany_normal_fp_mode) 2376 1.1 mrg { 2377 1.1 mrg case FP_MODE_INT: 2378 1.1 mrg switch (priority) 2379 1.1 mrg { 2380 1.1 mrg case 0: return FP_MODE_INT; 2381 1.1 mrg case 1: return epiphany_normal_fp_rounding; 2382 1.1 mrg case 2: return (epiphany_normal_fp_rounding == FP_MODE_ROUND_NEAREST 2383 1.1 mrg ? FP_MODE_ROUND_TRUNC : FP_MODE_ROUND_NEAREST); 2384 1.1 mrg case 3: return FP_MODE_CALLER; 2385 1.1 mrg default: gcc_unreachable (); 2386 1.1 mrg } 2387 1.1 mrg case FP_MODE_ROUND_NEAREST: 2388 1.1 mrg case FP_MODE_CALLER: 2389 1.1 mrg switch (priority) 2390 1.1 mrg { 2391 1.1 mrg case 0: return FP_MODE_ROUND_NEAREST; 2392 1.1 mrg case 1: return FP_MODE_ROUND_TRUNC; 2393 1.1 mrg case 2: return FP_MODE_INT; 2394 1.1 mrg case 3: return FP_MODE_CALLER; 2395 1.1 mrg default: gcc_unreachable (); 2396 1.1 mrg } 2397 1.1 mrg case FP_MODE_ROUND_TRUNC: 2398 1.1 mrg switch (priority) 2399 1.1 mrg { 2400 1.1 mrg case 0: return FP_MODE_ROUND_TRUNC; 2401 1.1 mrg case 1: return FP_MODE_ROUND_NEAREST; 2402 1.1 mrg case 2: return FP_MODE_INT; 2403 1.1 mrg case 3: return FP_MODE_CALLER; 2404 1.1 mrg default: gcc_unreachable (); 2405 1.1 mrg } 2406 1.1 mrg case FP_MODE_ROUND_UNKNOWN: 2407 1.1 mrg case FP_MODE_NONE: 2408 1.1 mrg gcc_unreachable (); 2409 1.1 mrg } 2410 1.1 mrg gcc_unreachable (); 2411 1.1 mrg } 2412 1.1 mrg 2413 1.1 mrg int 2414 1.1 mrg epiphany_mode_needed (int entity, rtx_insn *insn) 2415 1.1 mrg { 2416 1.1 mrg enum attr_fp_mode mode; 2417 1.1 mrg 2418 1.1 mrg if (recog_memoized (insn) < 0) 2419 1.1 mrg { 2420 1.1 mrg if (entity == EPIPHANY_MSW_ENTITY_AND 2421 1.1 mrg || entity == EPIPHANY_MSW_ENTITY_OR 2422 1.1 mrg || entity == EPIPHANY_MSW_ENTITY_CONFIG) 2423 1.1 mrg return 2; 2424 1.1 mrg return FP_MODE_NONE; 2425 1.1 mrg } 2426 1.1 mrg mode = get_attr_fp_mode (insn); 2427 1.1 mrg 2428 1.1 mrg switch (entity) 2429 1.1 mrg { 2430 1.1 mrg case EPIPHANY_MSW_ENTITY_AND: 2431 1.1 mrg return mode != FP_MODE_NONE && mode != FP_MODE_INT ? 1 : 2; 2432 1.1 mrg case EPIPHANY_MSW_ENTITY_OR: 2433 1.1 mrg return mode == FP_MODE_INT ? 1 : 2; 2434 1.1 mrg case EPIPHANY_MSW_ENTITY_CONFIG: 2435 1.1 mrg /* We must know/save config before we set it to something else. 2436 1.1 mrg Where we need the original value, we are fine with having it 2437 1.1 mrg just unchanged from the function start. 2438 1.1 mrg Because of the nature of the mode switching optimization, 2439 1.1 mrg a restore will be dominated by a clobber. */ 2440 1.1 mrg if (mode != FP_MODE_NONE && mode != FP_MODE_CALLER) 2441 1.1 mrg return 1; 2442 1.1 mrg /* A cpecial case are abnormal edges, which are deemed to clobber 2443 1.1 mrg the mode as well. We need to pin this effect on a actually 2444 1.1 mrg dominating insn, and one where the frame can be accessed, too, in 2445 1.1 mrg case the pseudo used to save CONFIG doesn't get a hard register. */ 2446 1.1 mrg if (CALL_P (insn) && find_reg_note (insn, REG_EH_REGION, NULL_RTX)) 2447 1.1 mrg return 1; 2448 1.1 mrg return 2; 2449 1.1 mrg case EPIPHANY_MSW_ENTITY_ROUND_KNOWN: 2450 1.1 mrg if (recog_memoized (insn) == CODE_FOR_set_fp_mode) 2451 1.1 mrg mode = (enum attr_fp_mode) epiphany_mode_after (entity, mode, insn); 2452 1.1 mrg /* Fall through. */ 2453 1.1 mrg case EPIPHANY_MSW_ENTITY_NEAREST: 2454 1.1 mrg case EPIPHANY_MSW_ENTITY_TRUNC: 2455 1.1 mrg if (mode == FP_MODE_ROUND_UNKNOWN) 2456 1.1 mrg { 2457 1.1 mrg MACHINE_FUNCTION (cfun)->unknown_mode_uses++; 2458 1.1 mrg return FP_MODE_NONE; 2459 1.1 mrg } 2460 1.1 mrg return mode; 2461 1.1 mrg case EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN: 2462 1.1 mrg if (mode == FP_MODE_ROUND_NEAREST || mode == FP_MODE_ROUND_TRUNC) 2463 1.1 mrg return FP_MODE_ROUND_UNKNOWN; 2464 1.1 mrg return mode; 2465 1.1 mrg case EPIPHANY_MSW_ENTITY_FPU_OMNIBUS: 2466 1.1 mrg if (mode == FP_MODE_ROUND_UNKNOWN) 2467 1.1 mrg return epiphany_normal_fp_rounding; 2468 1.1 mrg return mode; 2469 1.1 mrg default: 2470 1.1 mrg gcc_unreachable (); 2471 1.1 mrg } 2472 1.1 mrg } 2473 1.1 mrg 2474 1.1 mrg static int 2475 1.1 mrg epiphany_mode_entry_exit (int entity, bool exit) 2476 1.1 mrg { 2477 1.1 mrg int normal_mode = epiphany_normal_fp_mode ; 2478 1.1 mrg 2479 1.1 mrg MACHINE_FUNCTION (cfun)->sw_entities_processed |= (1 << entity); 2480 1.1 mrg if (epiphany_is_interrupt_p (current_function_decl)) 2481 1.1 mrg normal_mode = FP_MODE_CALLER; 2482 1.1 mrg switch (entity) 2483 1.1 mrg { 2484 1.1 mrg case EPIPHANY_MSW_ENTITY_AND: 2485 1.1 mrg if (exit) 2486 1.1 mrg return normal_mode != FP_MODE_INT ? 1 : 2; 2487 1.1 mrg return 0; 2488 1.1 mrg case EPIPHANY_MSW_ENTITY_OR: 2489 1.1 mrg if (exit) 2490 1.1 mrg return normal_mode == FP_MODE_INT ? 1 : 2; 2491 1.1 mrg return 0; 2492 1.1 mrg case EPIPHANY_MSW_ENTITY_CONFIG: 2493 1.1 mrg if (exit) 2494 1.1 mrg return 2; 2495 1.1 mrg return normal_mode == FP_MODE_CALLER ? 0 : 1; 2496 1.1 mrg case EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN: 2497 1.1 mrg if (normal_mode == FP_MODE_ROUND_NEAREST 2498 1.1 mrg || normal_mode == FP_MODE_ROUND_TRUNC) 2499 1.1 mrg return FP_MODE_ROUND_UNKNOWN; 2500 1.1 mrg /* Fall through. */ 2501 1.1 mrg case EPIPHANY_MSW_ENTITY_NEAREST: 2502 1.1 mrg case EPIPHANY_MSW_ENTITY_TRUNC: 2503 1.1 mrg case EPIPHANY_MSW_ENTITY_ROUND_KNOWN: 2504 1.1 mrg case EPIPHANY_MSW_ENTITY_FPU_OMNIBUS: 2505 1.1 mrg return normal_mode; 2506 1.1 mrg default: 2507 1.1 mrg gcc_unreachable (); 2508 1.1 mrg } 2509 1.1 mrg } 2510 1.1 mrg 2511 1.1 mrg int 2512 1.1 mrg epiphany_mode_after (int entity, int last_mode, rtx_insn *insn) 2513 1.1 mrg { 2514 1.1 mrg /* We have too few call-saved registers to hope to keep the masks across 2515 1.1 mrg calls. */ 2516 1.1 mrg if (entity == EPIPHANY_MSW_ENTITY_AND || entity == EPIPHANY_MSW_ENTITY_OR) 2517 1.1 mrg { 2518 1.1 mrg if (CALL_P (insn)) 2519 1.1 mrg return 0; 2520 1.1 mrg return last_mode; 2521 1.1 mrg } 2522 1.1 mrg /* If there is an abnormal edge, we don't want the config register to 2523 1.1 mrg be 'saved' again at the destination. 2524 1.1 mrg The frame pointer adjustment is inside a PARALLEL because of the 2525 1.1 mrg flags clobber. */ 2526 1.1 mrg if (entity == EPIPHANY_MSW_ENTITY_CONFIG && NONJUMP_INSN_P (insn) 2527 1.1 mrg && GET_CODE (PATTERN (insn)) == PARALLEL 2528 1.1 mrg && GET_CODE (XVECEXP (PATTERN (insn), 0, 0)) == SET 2529 1.1 mrg && SET_DEST (XVECEXP (PATTERN (insn), 0, 0)) == frame_pointer_rtx) 2530 1.1 mrg { 2531 1.1 mrg gcc_assert (cfun->has_nonlocal_label); 2532 1.1 mrg return 1; 2533 1.1 mrg } 2534 1.1 mrg if (recog_memoized (insn) < 0) 2535 1.1 mrg return last_mode; 2536 1.1 mrg if (get_attr_fp_mode (insn) == FP_MODE_ROUND_UNKNOWN 2537 1.1 mrg && last_mode != FP_MODE_ROUND_NEAREST && last_mode != FP_MODE_ROUND_TRUNC) 2538 1.1 mrg { 2539 1.1 mrg if (entity == EPIPHANY_MSW_ENTITY_NEAREST) 2540 1.1 mrg return FP_MODE_ROUND_NEAREST; 2541 1.1 mrg if (entity == EPIPHANY_MSW_ENTITY_TRUNC) 2542 1.1 mrg return FP_MODE_ROUND_TRUNC; 2543 1.1 mrg } 2544 1.1 mrg if (recog_memoized (insn) == CODE_FOR_set_fp_mode) 2545 1.1 mrg { 2546 1.1 mrg rtx src = SET_SRC (XVECEXP (PATTERN (insn), 0, 0)); 2547 1.1 mrg int fp_mode; 2548 1.1 mrg 2549 1.1 mrg if (REG_P (src)) 2550 1.1 mrg return FP_MODE_CALLER; 2551 1.1 mrg fp_mode = INTVAL (XVECEXP (XEXP (src, 0), 0, 0)); 2552 1.1 mrg if (entity == EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN 2553 1.1 mrg && (fp_mode == FP_MODE_ROUND_NEAREST 2554 1.1 mrg || fp_mode == EPIPHANY_MSW_ENTITY_TRUNC)) 2555 1.1 mrg return FP_MODE_ROUND_UNKNOWN; 2556 1.1 mrg return fp_mode; 2557 1.1 mrg } 2558 1.1 mrg return last_mode; 2559 1.1 mrg } 2560 1.1 mrg 2561 1.1 mrg static int 2562 1.1 mrg epiphany_mode_entry (int entity) 2563 1.1 mrg { 2564 1.1 mrg return epiphany_mode_entry_exit (entity, false); 2565 1.1 mrg } 2566 1.1 mrg 2567 1.1 mrg static int 2568 1.1 mrg epiphany_mode_exit (int entity) 2569 1.1 mrg { 2570 1.1 mrg return epiphany_mode_entry_exit (entity, true); 2571 1.1 mrg } 2572 1.1 mrg 2573 1.1 mrg void 2574 1.1 mrg emit_set_fp_mode (int entity, int mode, int prev_mode ATTRIBUTE_UNUSED, 2575 1.1 mrg HARD_REG_SET regs_live ATTRIBUTE_UNUSED) 2576 1.1 mrg { 2577 1.1 mrg rtx save_cc, cc_reg, mask, src, src2; 2578 1.1 mrg enum attr_fp_mode fp_mode; 2579 1.1 mrg 2580 1.1 mrg if (!MACHINE_FUNCTION (cfun)->and_mask) 2581 1.1 mrg { 2582 1.1 mrg MACHINE_FUNCTION (cfun)->and_mask = gen_reg_rtx (SImode); 2583 1.1 mrg MACHINE_FUNCTION (cfun)->or_mask = gen_reg_rtx (SImode); 2584 1.1 mrg } 2585 1.1 mrg if (entity == EPIPHANY_MSW_ENTITY_AND) 2586 1.1 mrg { 2587 1.1 mrg gcc_assert (mode >= 0 && mode <= 2); 2588 1.1 mrg if (mode == 1) 2589 1.1 mrg emit_move_insn (MACHINE_FUNCTION (cfun)->and_mask, 2590 1.1 mrg gen_int_mode (0xfff1fffe, SImode)); 2591 1.1 mrg return; 2592 1.1 mrg } 2593 1.1 mrg else if (entity == EPIPHANY_MSW_ENTITY_OR) 2594 1.1 mrg { 2595 1.1 mrg gcc_assert (mode >= 0 && mode <= 2); 2596 1.1 mrg if (mode == 1) 2597 1.1 mrg emit_move_insn (MACHINE_FUNCTION (cfun)->or_mask, GEN_INT(0x00080000)); 2598 1.1 mrg return; 2599 1.1 mrg } 2600 1.1 mrg else if (entity == EPIPHANY_MSW_ENTITY_CONFIG) 2601 1.1 mrg { 2602 1.1 mrg /* Mode switching optimization is done after emit_initial_value_sets, 2603 1.1 mrg so we have to take care of CONFIG_REGNUM here. */ 2604 1.1 mrg gcc_assert (mode >= 0 && mode <= 2); 2605 1.1 mrg rtx save = get_hard_reg_initial_val (SImode, CONFIG_REGNUM); 2606 1.1 mrg if (mode == 1) 2607 1.1 mrg emit_insn (gen_save_config (save)); 2608 1.1 mrg return; 2609 1.1 mrg } 2610 1.1 mrg fp_mode = (enum attr_fp_mode) mode; 2611 1.1 mrg src = NULL_RTX; 2612 1.1 mrg 2613 1.1 mrg switch (fp_mode) 2614 1.1 mrg { 2615 1.1 mrg case FP_MODE_CALLER: 2616 1.1 mrg /* The EPIPHANY_MSW_ENTITY_CONFIG processing must come later 2617 1.1 mrg so that the config save gets inserted before the first use. */ 2618 1.1 mrg gcc_assert (entity > EPIPHANY_MSW_ENTITY_CONFIG); 2619 1.1 mrg src = get_hard_reg_initial_val (SImode, CONFIG_REGNUM); 2620 1.1 mrg mask = MACHINE_FUNCTION (cfun)->and_mask; 2621 1.1 mrg break; 2622 1.1 mrg case FP_MODE_ROUND_UNKNOWN: 2623 1.1 mrg MACHINE_FUNCTION (cfun)->unknown_mode_sets++; 2624 1.1 mrg mask = MACHINE_FUNCTION (cfun)->and_mask; 2625 1.1 mrg break; 2626 1.1 mrg case FP_MODE_ROUND_NEAREST: 2627 1.1 mrg if (entity == EPIPHANY_MSW_ENTITY_TRUNC) 2628 1.1 mrg return; 2629 1.1 mrg mask = MACHINE_FUNCTION (cfun)->and_mask; 2630 1.1 mrg break; 2631 1.1 mrg case FP_MODE_ROUND_TRUNC: 2632 1.1 mrg if (entity == EPIPHANY_MSW_ENTITY_NEAREST) 2633 1.1 mrg return; 2634 1.1 mrg mask = MACHINE_FUNCTION (cfun)->and_mask; 2635 1.1 mrg break; 2636 1.1 mrg case FP_MODE_INT: 2637 1.1 mrg mask = MACHINE_FUNCTION (cfun)->or_mask; 2638 1.1 mrg break; 2639 1.1 mrg case FP_MODE_NONE: 2640 1.1 mrg default: 2641 1.1 mrg gcc_unreachable (); 2642 1.1 mrg } 2643 1.1 mrg save_cc = gen_reg_rtx (CCmode); 2644 1.1 mrg cc_reg = gen_rtx_REG (CCmode, CC_REGNUM); 2645 1.1 mrg emit_move_insn (save_cc, cc_reg); 2646 1.1 mrg mask = force_reg (SImode, mask); 2647 1.1 mrg if (!src) 2648 1.1 mrg { 2649 1.1 mrg rtvec v = gen_rtvec (1, GEN_INT (fp_mode)); 2650 1.1 mrg 2651 1.1 mrg src = gen_rtx_CONST (SImode, gen_rtx_UNSPEC (SImode, v, UNSPEC_FP_MODE)); 2652 1.1 mrg } 2653 1.1 mrg if (entity == EPIPHANY_MSW_ENTITY_ROUND_KNOWN 2654 1.1 mrg || entity == EPIPHANY_MSW_ENTITY_FPU_OMNIBUS) 2655 1.1 mrg src2 = copy_rtx (src); 2656 1.1 mrg else 2657 1.1 mrg { 2658 1.1 mrg rtvec v = gen_rtvec (1, GEN_INT (FP_MODE_ROUND_UNKNOWN)); 2659 1.1 mrg 2660 1.1 mrg src2 = gen_rtx_CONST (SImode, gen_rtx_UNSPEC (SImode, v, UNSPEC_FP_MODE)); 2661 1.1 mrg } 2662 1.1 mrg emit_insn (gen_set_fp_mode (src, src2, mask)); 2663 1.1 mrg emit_move_insn (cc_reg, save_cc); 2664 1.1 mrg } 2665 1.1 mrg 2666 1.1 mrg void 2667 1.1 mrg epiphany_expand_set_fp_mode (rtx *operands) 2668 1.1 mrg { 2669 1.1 mrg rtx ctrl = gen_rtx_REG (SImode, CONFIG_REGNUM); 2670 1.1 mrg rtx src = operands[0]; 2671 1.1 mrg rtx mask_reg = operands[2]; 2672 1.1 mrg rtx scratch = operands[3]; 2673 1.1 mrg enum attr_fp_mode fp_mode; 2674 1.1 mrg 2675 1.1 mrg 2676 1.1 mrg gcc_assert (rtx_equal_p (src, operands[1]) 2677 1.1 mrg /* Sometimes reload gets silly and reloads the same pseudo 2678 1.1 mrg into different registers. */ 2679 1.1 mrg || (REG_P (src) && REG_P (operands[1]))); 2680 1.1 mrg 2681 1.1 mrg if (!epiphany_uninterruptible_p (current_function_decl)) 2682 1.1 mrg emit_insn (gen_gid ()); 2683 1.1 mrg emit_move_insn (scratch, ctrl); 2684 1.1 mrg 2685 1.1 mrg if (GET_CODE (src) == REG) 2686 1.1 mrg { 2687 1.1 mrg /* FP_MODE_CALLER */ 2688 1.1 mrg emit_insn (gen_xorsi3 (scratch, scratch, src)); 2689 1.1 mrg emit_insn (gen_andsi3 (scratch, scratch, mask_reg)); 2690 1.1 mrg emit_insn (gen_xorsi3 (scratch, scratch, src)); 2691 1.1 mrg } 2692 1.1 mrg else 2693 1.1 mrg { 2694 1.1 mrg gcc_assert (GET_CODE (src) == CONST); 2695 1.1 mrg src = XEXP (src, 0); 2696 1.1 mrg fp_mode = (enum attr_fp_mode) INTVAL (XVECEXP (src, 0, 0)); 2697 1.1 mrg switch (fp_mode) 2698 1.1 mrg { 2699 1.1 mrg case FP_MODE_ROUND_NEAREST: 2700 1.1 mrg emit_insn (gen_andsi3 (scratch, scratch, mask_reg)); 2701 1.1 mrg break; 2702 1.1 mrg case FP_MODE_ROUND_TRUNC: 2703 1.1 mrg emit_insn (gen_andsi3 (scratch, scratch, mask_reg)); 2704 1.1 mrg emit_insn (gen_add2_insn (scratch, const1_rtx)); 2705 1.1 mrg break; 2706 1.1 mrg case FP_MODE_INT: 2707 1.1 mrg emit_insn (gen_iorsi3 (scratch, scratch, mask_reg)); 2708 1.1 mrg break; 2709 1.1 mrg case FP_MODE_CALLER: 2710 1.1 mrg case FP_MODE_ROUND_UNKNOWN: 2711 1.1 mrg case FP_MODE_NONE: 2712 1.1 mrg gcc_unreachable (); 2713 1.1 mrg } 2714 1.1 mrg } 2715 1.1 mrg emit_move_insn (ctrl, scratch); 2716 1.1 mrg if (!epiphany_uninterruptible_p (current_function_decl)) 2717 1.1 mrg emit_insn (gen_gie ()); 2718 1.1 mrg } 2719 1.1 mrg 2720 1.1 mrg void 2721 1.1 mrg epiphany_insert_mode_switch_use (rtx_insn *insn, 2722 1.1 mrg int entity ATTRIBUTE_UNUSED, 2723 1.1 mrg int mode ATTRIBUTE_UNUSED) 2724 1.1 mrg { 2725 1.1 mrg rtx pat = PATTERN (insn); 2726 1.1 mrg rtvec v; 2727 1.1 mrg int len, i; 2728 1.1 mrg rtx near = gen_rtx_REG (SImode, FP_NEAREST_REGNUM); 2729 1.1 mrg rtx trunc = gen_rtx_REG (SImode, FP_TRUNCATE_REGNUM); 2730 1.1 mrg 2731 1.1 mrg if (entity != EPIPHANY_MSW_ENTITY_FPU_OMNIBUS) 2732 1.1 mrg return; 2733 1.1 mrg switch ((enum attr_fp_mode) get_attr_fp_mode (insn)) 2734 1.1 mrg { 2735 1.1 mrg case FP_MODE_ROUND_NEAREST: 2736 1.1 mrg near = gen_rtx_USE (VOIDmode, near); 2737 1.1 mrg trunc = gen_rtx_CLOBBER (VOIDmode, trunc); 2738 1.1 mrg break; 2739 1.1 mrg case FP_MODE_ROUND_TRUNC: 2740 1.1 mrg near = gen_rtx_CLOBBER (VOIDmode, near); 2741 1.1 mrg trunc = gen_rtx_USE (VOIDmode, trunc); 2742 1.1 mrg break; 2743 1.1 mrg case FP_MODE_ROUND_UNKNOWN: 2744 1.1 mrg near = gen_rtx_USE (VOIDmode, gen_rtx_REG (SImode, FP_ANYFP_REGNUM)); 2745 1.1 mrg trunc = copy_rtx (near); 2746 1.1 mrg /* Fall through. */ 2747 1.1 mrg case FP_MODE_INT: 2748 1.1 mrg case FP_MODE_CALLER: 2749 1.1 mrg near = gen_rtx_USE (VOIDmode, near); 2750 1.1 mrg trunc = gen_rtx_USE (VOIDmode, trunc); 2751 1.1 mrg break; 2752 1.1 mrg case FP_MODE_NONE: 2753 1.1 mrg gcc_unreachable (); 2754 1.1 mrg } 2755 1.1 mrg gcc_assert (GET_CODE (pat) == PARALLEL); 2756 1.1 mrg len = XVECLEN (pat, 0); 2757 1.1 mrg v = rtvec_alloc (len + 2); 2758 1.1 mrg for (i = 0; i < len; i++) 2759 1.1 mrg RTVEC_ELT (v, i) = XVECEXP (pat, 0, i); 2760 1.1 mrg RTVEC_ELT (v, len) = near; 2761 1.1 mrg RTVEC_ELT (v, len + 1) = trunc; 2762 1.1 mrg pat = gen_rtx_PARALLEL (VOIDmode, v); 2763 1.1 mrg PATTERN (insn) = pat; 2764 1.1 mrg MACHINE_FUNCTION (cfun)->control_use_inserted = true; 2765 1.1 mrg } 2766 1.1 mrg 2767 1.1 mrg bool 2768 1.1 mrg epiphany_epilogue_uses (int regno) 2769 1.1 mrg { 2770 1.1 mrg if (regno == GPR_LR) 2771 1.1 mrg return true; 2772 1.1 mrg if (reload_completed && epiphany_is_interrupt_p (current_function_decl)) 2773 1.1 mrg { 2774 1.1 mrg if (fixed_regs[regno] 2775 1.1 mrg && regno != STATUS_REGNUM && regno != IRET_REGNUM 2776 1.1 mrg && regno != FP_NEAREST_REGNUM && regno != FP_TRUNCATE_REGNUM) 2777 1.1 mrg return false; 2778 1.1 mrg return true; 2779 1.1 mrg } 2780 1.1 mrg if (regno == FP_NEAREST_REGNUM 2781 1.1 mrg && epiphany_normal_fp_mode != FP_MODE_ROUND_TRUNC) 2782 1.1 mrg return true; 2783 1.1 mrg if (regno == FP_TRUNCATE_REGNUM 2784 1.1 mrg && epiphany_normal_fp_mode != FP_MODE_ROUND_NEAREST) 2785 1.1 mrg return true; 2786 1.1 mrg return false; 2787 1.1 mrg } 2788 1.1 mrg 2789 1.1 mrg static unsigned int 2790 1.1 mrg epiphany_min_divisions_for_recip_mul (machine_mode mode) 2791 1.1 mrg { 2792 1.1 mrg if (flag_reciprocal_math && mode == SFmode) 2793 1.1 mrg /* We'll expand into a multiply-by-reciprocal anyway, so we might a well do 2794 1.1 mrg it already at the tree level and expose it to further optimizations. */ 2795 1.1 mrg return 1; 2796 1.1 mrg return default_min_divisions_for_recip_mul (mode); 2797 1.1 mrg } 2798 1.1 mrg 2799 1.1 mrg static machine_mode 2800 1.1 mrg epiphany_preferred_simd_mode (scalar_mode mode ATTRIBUTE_UNUSED) 2801 1.1 mrg { 2802 1.1 mrg return TARGET_VECT_DOUBLE ? DImode : SImode; 2803 1.1 mrg } 2804 1.1 mrg 2805 1.1 mrg static bool 2806 1.1 mrg epiphany_vector_mode_supported_p (machine_mode mode) 2807 1.1 mrg { 2808 1.1 mrg if (mode == V2SFmode) 2809 1.1 mrg return true; 2810 1.1 mrg if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT 2811 1.1 mrg && (GET_MODE_SIZE (mode) == 4 || GET_MODE_SIZE (mode) == 8)) 2812 1.1 mrg return true; 2813 1.1 mrg return false; 2814 1.1 mrg } 2815 1.1 mrg 2816 1.1 mrg static bool 2817 1.1 mrg epiphany_vector_alignment_reachable (const_tree type, bool is_packed) 2818 1.1 mrg { 2819 1.1 mrg /* Vectors which aren't in packed structures will not be less aligned than 2820 1.1 mrg the natural alignment of their element type, so this is safe. */ 2821 1.1 mrg if (TYPE_ALIGN_UNIT (type) == 4) 2822 1.1 mrg return !is_packed; 2823 1.1 mrg 2824 1.1 mrg return default_builtin_vector_alignment_reachable (type, is_packed); 2825 1.1 mrg } 2826 1.1 mrg 2827 1.1 mrg static bool 2828 1.1 mrg epiphany_support_vector_misalignment (machine_mode mode, const_tree type, 2829 1.1 mrg int misalignment, bool is_packed) 2830 1.1 mrg { 2831 1.1 mrg if (GET_MODE_SIZE (mode) == 8 && misalignment % 4 == 0) 2832 1.1 mrg return true; 2833 1.1 mrg return default_builtin_support_vector_misalignment (mode, type, misalignment, 2834 1.1 mrg is_packed); 2835 1.1 mrg } 2836 1.1 mrg 2837 1.1 mrg /* STRUCTURE_SIZE_BOUNDARY seems a bit crude in how it enlarges small 2838 1.1 mrg structs. Make structs double-word-aligned it they are a double word or 2839 1.1 mrg (potentially) larger; failing that, do the same for a size of 32 bits. */ 2840 1.1 mrg unsigned 2841 1.1 mrg epiphany_special_round_type_align (tree type, unsigned computed, 2842 1.1 mrg unsigned specified) 2843 1.1 mrg { 2844 1.1 mrg unsigned align = MAX (computed, specified); 2845 1.1 mrg tree field; 2846 1.1 mrg HOST_WIDE_INT total, max; 2847 1.1 mrg unsigned try_align = FASTEST_ALIGNMENT; 2848 1.1 mrg 2849 1.1 mrg if (maximum_field_alignment && try_align > maximum_field_alignment) 2850 1.1 mrg try_align = maximum_field_alignment; 2851 1.1 mrg if (align >= try_align) 2852 1.1 mrg return align; 2853 1.1 mrg for (max = 0, field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field)) 2854 1.1 mrg { 2855 1.1 mrg tree offset, size; 2856 1.1 mrg 2857 1.1 mrg if (TREE_CODE (field) != FIELD_DECL 2858 1.1 mrg || TREE_TYPE (field) == error_mark_node) 2859 1.1 mrg continue; 2860 1.1 mrg offset = bit_position (field); 2861 1.1 mrg size = DECL_SIZE (field); 2862 1.1 mrg if (!tree_fits_uhwi_p (offset) || !tree_fits_uhwi_p (size) 2863 1.1 mrg || tree_to_uhwi (offset) >= try_align 2864 1.1 mrg || tree_to_uhwi (size) >= try_align) 2865 1.1 mrg return try_align; 2866 1.1 mrg total = tree_to_uhwi (offset) + tree_to_uhwi (size); 2867 1.1 mrg if (total > max) 2868 1.1 mrg max = total; 2869 1.1 mrg } 2870 1.1 mrg if (max >= (HOST_WIDE_INT) try_align) 2871 1.1 mrg align = try_align; 2872 1.1 mrg else if (try_align > 32 && max >= 32) 2873 1.1 mrg align = max > 32 ? 64 : 32; 2874 1.1 mrg return align; 2875 1.1 mrg } 2876 1.1 mrg 2877 1.1 mrg /* Upping the alignment of arrays in structs is not only a performance 2878 1.1 mrg enhancement, it also helps preserve assumptions about how 2879 1.1 mrg arrays-at-the-end-of-structs work, like for struct gcov_fn_info in 2880 1.1 mrg libgcov.c . */ 2881 1.1 mrg unsigned 2882 1.1 mrg epiphany_adjust_field_align (tree type, unsigned computed) 2883 1.1 mrg { 2884 1.1 mrg if (computed == 32 2885 1.1 mrg && TREE_CODE (type) == ARRAY_TYPE) 2886 1.1 mrg { 2887 1.1 mrg tree elmsz = TYPE_SIZE (TREE_TYPE (type)); 2888 1.1 mrg 2889 1.1 mrg if (!tree_fits_uhwi_p (elmsz) || tree_to_uhwi (elmsz) >= 32) 2890 1.1 mrg return 64; 2891 1.1 mrg } 2892 1.1 mrg return computed; 2893 1.1 mrg } 2894 1.1 mrg 2895 1.1 mrg /* Output code to add DELTA to the first argument, and then jump 2896 1.1 mrg to FUNCTION. Used for C++ multiple inheritance. */ 2897 1.1 mrg static void 2898 1.1 mrg epiphany_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED, 2899 1.1 mrg HOST_WIDE_INT delta, 2900 1.1 mrg HOST_WIDE_INT vcall_offset, 2901 1.1 mrg tree function) 2902 1.1 mrg { 2903 1.1 mrg const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk)); 2904 1.1 mrg int this_regno 2905 1.1 mrg = aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function) ? 1 : 0; 2906 1.1 mrg const char *this_name = reg_names[this_regno]; 2907 1.1 mrg const char *fname; 2908 1.1 mrg 2909 1.1 mrg assemble_start_function (thunk, fnname); 2910 1.1 mrg /* We use IP and R16 as a scratch registers. */ 2911 1.1 mrg gcc_assert (call_used_or_fixed_reg_p (GPR_IP)); 2912 1.1 mrg gcc_assert (call_used_or_fixed_reg_p (GPR_16)); 2913 1.1 mrg 2914 1.1 mrg /* Add DELTA. When possible use a plain add, otherwise load it into 2915 1.1 mrg a register first. */ 2916 1.1 mrg if (delta == 0) 2917 1.1 mrg ; /* Done. */ 2918 1.1 mrg else if (SIMM11 (delta)) 2919 1.1 mrg asm_fprintf (file, "\tadd\t%s,%s,%d\n", this_name, this_name, (int) delta); 2920 1.1 mrg else if (delta < 0 && delta >= -0xffff) 2921 1.1 mrg { 2922 1.1 mrg asm_fprintf (file, "\tmov\tip,%d\n", (int) -delta); 2923 1.1 mrg asm_fprintf (file, "\tsub\t%s,%s,ip\n", this_name, this_name); 2924 1.1 mrg } 2925 1.1 mrg else 2926 1.1 mrg { 2927 1.1 mrg asm_fprintf (file, "\tmov\tip,%%low(%ld)\n", (long) delta); 2928 1.1 mrg if (delta & ~0xffff) 2929 1.1 mrg asm_fprintf (file, "\tmovt\tip,%%high(%ld)\n", (long) delta); 2930 1.1 mrg asm_fprintf (file, "\tadd\t%s,%s,ip\n", this_name, this_name); 2931 1.1 mrg } 2932 1.1 mrg 2933 1.1 mrg /* If needed, add *(*THIS + VCALL_OFFSET) to THIS. */ 2934 1.1 mrg if (vcall_offset != 0) 2935 1.1 mrg { 2936 1.1 mrg /* ldr ip,[this] --> temp = *this 2937 1.1 mrg ldr ip,[ip,vcall_offset] > temp = *(*this + vcall_offset) 2938 1.1 mrg add this,this,ip --> this+ = *(*this + vcall_offset) */ 2939 1.1 mrg asm_fprintf (file, "\tldr\tip, [%s]\n", this_name); 2940 1.1 mrg if (vcall_offset < -0x7ff * 4 || vcall_offset > 0x7ff * 4 2941 1.1 mrg || (vcall_offset & 3) != 0) 2942 1.1 mrg { 2943 1.1 mrg asm_fprintf (file, "\tmov\tr16, %%low(%ld)\n", (long) vcall_offset); 2944 1.1 mrg asm_fprintf (file, "\tmovt\tr16, %%high(%ld)\n", (long) vcall_offset); 2945 1.1 mrg asm_fprintf (file, "\tldr\tip, [ip,r16]\n"); 2946 1.1 mrg } 2947 1.1 mrg else 2948 1.1 mrg asm_fprintf (file, "\tldr\tip, [ip,%d]\n", (int) vcall_offset / 4); 2949 1.1 mrg asm_fprintf (file, "\tadd\t%s, %s, ip\n", this_name, this_name); 2950 1.1 mrg } 2951 1.1 mrg 2952 1.1 mrg fname = XSTR (XEXP (DECL_RTL (function), 0), 0); 2953 1.1 mrg if (epiphany_is_long_call_p (XEXP (DECL_RTL (function), 0))) 2954 1.1 mrg { 2955 1.1 mrg fputs ("\tmov\tip,%low(", file); 2956 1.1 mrg assemble_name (file, fname); 2957 1.1 mrg fputs (")\n\tmovt\tip,%high(", file); 2958 1.1 mrg assemble_name (file, fname); 2959 1.1 mrg fputs (")\n\tjr ip\n", file); 2960 1.1 mrg } 2961 1.1 mrg else 2962 1.1 mrg { 2963 1.1 mrg fputs ("\tb\t", file); 2964 1.1 mrg assemble_name (file, fname); 2965 1.1 mrg fputc ('\n', file); 2966 1.1 mrg } 2967 1.1 mrg assemble_end_function (thunk, fnname); 2968 1.1 mrg } 2969 1.1 mrg 2970 1.1 mrg void 2971 1.1 mrg epiphany_start_function (FILE *file, const char *name, tree decl) 2972 1.1 mrg { 2973 1.1 mrg /* If the function doesn't fit into the on-chip memory, it will have a 2974 1.1 mrg section attribute - or lack of it - that denotes it goes somewhere else. 2975 1.1 mrg But the architecture spec says that an interrupt vector still has to 2976 1.1 mrg point to on-chip memory. So we must place a jump there to get to the 2977 1.1 mrg actual function implementation. The forwarder_section attribute 2978 1.1 mrg specifies the section where this jump goes. 2979 1.1 mrg This mechanism can also be useful to have a shortcall destination for 2980 1.1 mrg a function that is actually placed much farther away. */ 2981 1.1 mrg tree attrs, int_attr, int_names, int_name, forwarder_attr; 2982 1.1 mrg 2983 1.1 mrg attrs = DECL_ATTRIBUTES (decl); 2984 1.1 mrg int_attr = lookup_attribute ("interrupt", attrs); 2985 1.1 mrg if (int_attr) 2986 1.1 mrg for (int_names = TREE_VALUE (int_attr); int_names; 2987 1.1 mrg int_names = TREE_CHAIN (int_names)) 2988 1.1 mrg { 2989 1.1 mrg char buf[99]; 2990 1.1 mrg 2991 1.1 mrg int_name = TREE_VALUE (int_names); 2992 1.1 mrg sprintf (buf, "ivt_entry_%.80s", TREE_STRING_POINTER (int_name)); 2993 1.1 mrg switch_to_section (get_section (buf, SECTION_CODE, decl)); 2994 1.1 mrg fputs ("\tb\t", file); 2995 1.1 mrg assemble_name (file, name); 2996 1.1 mrg fputc ('\n', file); 2997 1.1 mrg } 2998 1.1 mrg forwarder_attr = lookup_attribute ("forwarder_section", attrs); 2999 1.1 mrg if (forwarder_attr) 3000 1.1 mrg { 3001 1.1 mrg const char *prefix = "__forwarder_dst_"; 3002 1.1 mrg char *dst_name = (char *) alloca (strlen (prefix) + strlen (name) + 1); 3003 1.1 mrg 3004 1.1 mrg strcpy (dst_name, prefix); 3005 1.1 mrg strcat (dst_name, name); 3006 1.1 mrg forwarder_attr = TREE_VALUE (TREE_VALUE (forwarder_attr)); 3007 1.1 mrg switch_to_section (get_section (TREE_STRING_POINTER (forwarder_attr), 3008 1.1 mrg SECTION_CODE, decl)); 3009 1.1 mrg ASM_OUTPUT_FUNCTION_LABEL (file, name, decl); 3010 1.1 mrg if (epiphany_is_long_call_p (XEXP (DECL_RTL (decl), 0))) 3011 1.1 mrg { 3012 1.1 mrg int tmp = GPR_0; 3013 1.1 mrg 3014 1.1 mrg if (int_attr) 3015 1.1 mrg fputs ("\tstrd r0,[sp,-1]\n", file); 3016 1.1 mrg else 3017 1.1 mrg tmp = GPR_16; 3018 1.1 mrg gcc_assert (call_used_or_fixed_reg_p (tmp)); 3019 1.1 mrg fprintf (file, "\tmov r%d,%%low(", tmp); 3020 1.1 mrg assemble_name (file, dst_name); 3021 1.1 mrg fprintf (file, ")\n" 3022 1.1 mrg "\tmovt r%d,%%high(", tmp); 3023 1.1 mrg assemble_name (file, dst_name); 3024 1.1 mrg fprintf (file, ")\n" 3025 1.1 mrg "\tjr r%d\n", tmp); 3026 1.1 mrg } 3027 1.1 mrg else 3028 1.1 mrg { 3029 1.1 mrg fputs ("\tb\t", file); 3030 1.1 mrg assemble_name (file, dst_name); 3031 1.1 mrg fputc ('\n', file); 3032 1.1 mrg } 3033 1.1 mrg name = dst_name; 3034 1.1 mrg } 3035 1.1 mrg switch_to_section (function_section (decl)); 3036 1.1 mrg ASM_OUTPUT_FUNCTION_LABEL (file, name, decl); 3037 1.1 mrg } 3038 1.1 mrg 3039 1.1 mrg 3040 1.1 mrg /* Implement TARGET_CONSTANT_ALIGNMENT. */ 3041 1.1 mrg 3042 1.1 mrg static HOST_WIDE_INT 3043 1.1 mrg epiphany_constant_alignment (const_tree exp, HOST_WIDE_INT align) 3044 1.1 mrg { 3045 1.1 mrg if (TREE_CODE (exp) == STRING_CST) 3046 1.1 mrg return MAX (align, FASTEST_ALIGNMENT); 3047 1.1 mrg return align; 3048 } 3049 3050 /* Implement TARGET_STARTING_FRAME_OFFSET. */ 3051 3052 static HOST_WIDE_INT 3053 epiphany_starting_frame_offset (void) 3054 { 3055 return epiphany_stack_offset; 3056 } 3057 3058 struct gcc_target targetm = TARGET_INITIALIZER; 3059