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