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