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