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