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