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