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