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