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