1 /* Subroutines used for code generation on the EPIPHANY cpu.
2 Copyright (C) 1994-2015 Free Software Foundation, Inc.
3 Contributed by Embecosm on behalf of Adapteva, Inc.
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)
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/>. */
23 #include "coretypes.h"
29 #include "fold-const.h"
30 #include "stor-layout.h"
33 #include "stringpool.h"
35 #include "insn-config.h"
36 #include "conditions.h"
38 #include "insn-attr.h"
40 #include "insn-codes.h"
48 #include "diagnostic-core.h"
57 #include "cfgcleanup.h"
58 #include "langhooks.h"
59 #include "tm-constrs.h"
60 #include "tree-pass.h" /* for current_pass */
62 #include "pass_manager.h"
65 /* Which cpu we're compiling for. */
66 int epiphany_cpu_type
;
68 /* Name of mangle string to add to symbols to separate code compiled for each
70 const char *epiphany_mangle_cpu
;
72 /* Array of valid operand punctuation characters. */
73 char epiphany_punct_chars
[256];
75 /* The rounding mode that we generally use for floating point. */
76 int epiphany_normal_fp_rounding
;
78 /* The pass instance, for use in epiphany_optimize_mode_switching. */
79 static opt_pass
*pass_mode_switch_use
;
81 static void epiphany_init_reg_tables (void);
82 static int get_epiphany_condition_code (rtx
);
83 static tree
epiphany_handle_interrupt_attribute (tree
*, tree
, tree
, int, bool *);
84 static tree
epiphany_handle_forwarder_attribute (tree
*, tree
, tree
, int,
86 static bool epiphany_pass_by_reference (cumulative_args_t
, machine_mode
,
88 static rtx_insn
*frame_insn (rtx
);
90 /* defines for the initialization of the GCC target structure. */
91 #define TARGET_ATTRIBUTE_TABLE epiphany_attribute_table
93 #define TARGET_PRINT_OPERAND epiphany_print_operand
94 #define TARGET_PRINT_OPERAND_ADDRESS epiphany_print_operand_address
96 #define TARGET_RTX_COSTS epiphany_rtx_costs
97 #define TARGET_ADDRESS_COST epiphany_address_cost
98 #define TARGET_MEMORY_MOVE_COST epiphany_memory_move_cost
100 #define TARGET_PROMOTE_FUNCTION_MODE epiphany_promote_function_mode
101 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
103 #define TARGET_RETURN_IN_MEMORY epiphany_return_in_memory
104 #define TARGET_PASS_BY_REFERENCE epiphany_pass_by_reference
105 #define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true
106 #define TARGET_FUNCTION_VALUE epiphany_function_value
107 #define TARGET_LIBCALL_VALUE epiphany_libcall_value
108 #define TARGET_FUNCTION_VALUE_REGNO_P epiphany_function_value_regno_p
110 #define TARGET_SETUP_INCOMING_VARARGS epiphany_setup_incoming_varargs
112 /* Using the simplistic varags handling forces us to do partial reg/stack
113 argument passing for types with larger size (> 4 bytes) than alignemnt. */
114 #define TARGET_ARG_PARTIAL_BYTES epiphany_arg_partial_bytes
116 #define TARGET_FUNCTION_OK_FOR_SIBCALL epiphany_function_ok_for_sibcall
118 #define TARGET_SCHED_ISSUE_RATE epiphany_issue_rate
119 #define TARGET_SCHED_ADJUST_COST epiphany_adjust_cost
121 #define TARGET_LEGITIMATE_ADDRESS_P epiphany_legitimate_address_p
123 #define TARGET_SECONDARY_RELOAD epiphany_secondary_reload
125 #define TARGET_OPTION_OVERRIDE epiphany_override_options
127 #define TARGET_CONDITIONAL_REGISTER_USAGE epiphany_conditional_register_usage
129 #define TARGET_FUNCTION_ARG epiphany_function_arg
131 #define TARGET_FUNCTION_ARG_ADVANCE epiphany_function_arg_advance
133 #define TARGET_FUNCTION_ARG_BOUNDARY epiphany_function_arg_boundary
135 #define TARGET_TRAMPOLINE_INIT epiphany_trampoline_init
137 /* Nonzero if the constant rtx value is a legitimate general operand.
138 We can handle any 32- or 64-bit constant. */
139 #define TARGET_LEGITIMATE_CONSTANT_P hook_bool_mode_rtx_true
141 #define TARGET_MIN_DIVISIONS_FOR_RECIP_MUL \
142 epiphany_min_divisions_for_recip_mul
144 #define TARGET_VECTORIZE_PREFERRED_SIMD_MODE epiphany_preferred_simd_mode
146 #define TARGET_VECTOR_MODE_SUPPORTED_P epiphany_vector_mode_supported_p
148 #define TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE \
149 epiphany_vector_alignment_reachable
151 #define TARGET_VECTORIZE_SUPPORT_VECTOR_MISALIGNMENT \
152 epiphany_support_vector_misalignment
154 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK \
155 hook_bool_const_tree_hwi_hwi_const_tree_true
156 #define TARGET_ASM_OUTPUT_MI_THUNK epiphany_output_mi_thunk
158 /* ??? we can use larger offsets for wider-mode sized accesses, but there
159 is no concept of anchors being dependent on the modes that they are used
160 for, so we can only use an offset range that would suit all modes. */
161 #define TARGET_MAX_ANCHOR_OFFSET (optimize_size ? 31 : 2047)
162 /* We further restrict the minimum to be a multiple of eight. */
163 #define TARGET_MIN_ANCHOR_OFFSET (optimize_size ? 0 : -2040)
165 /* Mode switching hooks. */
167 #define TARGET_MODE_EMIT emit_set_fp_mode
169 #define TARGET_MODE_NEEDED epiphany_mode_needed
171 #define TARGET_MODE_PRIORITY epiphany_mode_priority
173 #define TARGET_MODE_ENTRY epiphany_mode_entry
175 #define TARGET_MODE_EXIT epiphany_mode_exit
177 #define TARGET_MODE_AFTER epiphany_mode_after
179 #include "target-def.h"
181 #undef TARGET_ASM_ALIGNED_HI_OP
182 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
183 #undef TARGET_ASM_ALIGNED_SI_OP
184 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
187 epiphany_is_interrupt_p (tree decl
)
191 attrs
= DECL_ATTRIBUTES (decl
);
192 if (lookup_attribute ("interrupt", attrs
))
198 /* Called from epiphany_override_options.
199 We use this to initialize various things. */
204 /* N.B. this pass must not run before the first optimize_mode_switching
205 pass because of the side offect of epiphany_mode_needed on
206 MACHINE_FUNCTION(cfun)->unknown_mode_uses. But it must run before
207 pass_resolve_sw_modes. */
208 pass_mode_switch_use
= make_pass_mode_switch_use (g
);
209 struct register_pass_info insert_use_info
210 = { pass_mode_switch_use
, "mode_sw",
211 1, PASS_POS_INSERT_AFTER
214 = g
->get_passes()->get_pass_mode_switching ()->clone ();
215 struct register_pass_info mode_sw2_info
216 = { mode_sw2
, "mode_sw",
217 1, PASS_POS_INSERT_AFTER
219 opt_pass
*mode_sw3
= make_pass_resolve_sw_modes (g
);
220 struct register_pass_info mode_sw3_info
221 = { mode_sw3
, "mode_sw",
222 1, PASS_POS_INSERT_AFTER
225 = g
->get_passes()->get_pass_split_all_insns ()->clone ();
226 struct register_pass_info mode_sw4_info
227 = { mode_sw4
, "mode_sw",
228 1, PASS_POS_INSERT_AFTER
230 static const int num_modes
[] = NUM_MODES_FOR_MODE_SWITCHING
;
231 #define N_ENTITIES ARRAY_SIZE (num_modes)
233 epiphany_init_reg_tables ();
235 /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P. */
236 memset (epiphany_punct_chars
, 0, sizeof (epiphany_punct_chars
));
237 epiphany_punct_chars
['-'] = 1;
239 epiphany_normal_fp_rounding
240 = (epiphany_normal_fp_mode
== FP_MODE_ROUND_TRUNC
241 ? FP_MODE_ROUND_TRUNC
: FP_MODE_ROUND_NEAREST
);
242 register_pass (&mode_sw4_info
);
243 register_pass (&mode_sw2_info
);
244 register_pass (&mode_sw3_info
);
245 register_pass (&insert_use_info
);
246 register_pass (&mode_sw2_info
);
247 /* Verify that NUM_MODES_FOR_MODE_SWITCHING has one value per entity. */
248 gcc_assert (N_ENTITIES
== EPIPHANY_MSW_ENTITY_NUM
);
250 #if 1 /* As long as peep2_rescan is not implemented,
251 (see http://gcc.gnu.org/ml/gcc-patches/2011-10/msg02819.html,)
252 we need a second peephole2 pass to get reasonable code. */
254 opt_pass
*extra_peephole2
255 = g
->get_passes ()->get_pass_peephole2 ()->clone ();
256 struct register_pass_info peep2_2_info
257 = { extra_peephole2
, "peephole2",
258 1, PASS_POS_INSERT_AFTER
261 register_pass (&peep2_2_info
);
266 /* The condition codes of the EPIPHANY, and the inverse function. */
267 static const char *const epiphany_condition_codes
[] =
268 { /* 0 1 2 3 4 5 6 7 8 9 */
269 "eq", "ne", "ltu", "gteu", "gt", "lte", "gte", "lt", "gtu", "lteu",
271 "beq","bne","blt", "blte",
274 #define EPIPHANY_INVERSE_CONDITION_CODE(X) ((X) ^ 1)
276 /* Returns the index of the EPIPHANY condition code string in
277 `epiphany_condition_codes'. COMPARISON should be an rtx like
278 `(eq (...) (...))'. */
281 get_epiphany_condition_code (rtx comparison
)
283 switch (GET_MODE (XEXP (comparison
, 0)))
286 switch (GET_CODE (comparison
))
299 default : gcc_unreachable ();
302 switch (GET_CODE (comparison
))
306 default: gcc_unreachable ();
309 switch (GET_CODE (comparison
))
313 default: gcc_unreachable ();
316 switch (GET_CODE (comparison
))
320 default: gcc_unreachable ();
323 switch (GET_CODE (comparison
))
329 default: gcc_unreachable ();
332 switch (GET_CODE (comparison
))
336 default: gcc_unreachable ();
339 switch (GET_CODE (comparison
))
345 case UNLE
: return 5;
346 case UNLT
: return 7;
347 default: gcc_unreachable ();
350 switch (GET_CODE (comparison
))
352 case ORDERED
: return 9;
353 case UNORDERED
: return 8;
354 default: gcc_unreachable ();
357 switch (GET_CODE (comparison
))
361 default: gcc_unreachable ();
363 default: gcc_unreachable ();
370 /* Return 1 if hard register REGNO can hold a value of machine_mode MODE. */
372 hard_regno_mode_ok (int regno
, machine_mode mode
)
374 if (GET_MODE_SIZE (mode
) > UNITS_PER_WORD
)
375 return (regno
& 1) == 0 && GPR_P (regno
);
380 /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
381 return the mode to be used for the comparison. */
384 epiphany_select_cc_mode (enum rtx_code op
,
385 rtx x ATTRIBUTE_UNUSED
,
386 rtx y ATTRIBUTE_UNUSED
)
388 if (GET_MODE_CLASS (GET_MODE (x
)) == MODE_FLOAT
)
390 if (TARGET_SOFT_CMPSF
391 || op
== ORDERED
|| op
== UNORDERED
)
393 if (op
== EQ
|| op
== NE
)
395 if (op
== ORDERED
|| op
== UNORDERED
)
396 return CC_FP_ORDmode
;
397 if (op
== UNEQ
|| op
== LTGT
)
398 return CC_FP_UNEQmode
;
399 return CC_FP_GTEmode
;
403 /* recognize combiner pattern ashlsi_btst:
405 (set (reg:N_NE 65 cc1)
406 (compare:N_NE (zero_extract:SI (reg/v:SI 75 [ a ])
409 (const_int 0 [0x0])))
410 (clobber (scratch:SI)) */
411 else if ((op
== EQ
|| op
== NE
)
412 && GET_CODE (x
) == ZERO_EXTRACT
413 && XEXP (x
, 1) == const1_rtx
414 && CONST_INT_P (XEXP (x
, 2)))
416 else if ((op
== GEU
|| op
== LTU
) && GET_CODE (x
) == PLUS
)
418 else if ((op
== LEU
|| op
== GTU
) && GET_CODE (x
) == MINUS
)
424 enum reg_class epiphany_regno_reg_class
[FIRST_PSEUDO_REGISTER
];
427 epiphany_init_reg_tables (void)
431 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
434 epiphany_regno_reg_class
[i
] = LR_REGS
;
435 else if (i
<= 7 && TARGET_PREFER_SHORT_INSN_REGS
)
436 epiphany_regno_reg_class
[i
] = SHORT_INSN_REGS
;
437 else if (call_used_regs
[i
]
438 && TEST_HARD_REG_BIT (reg_class_contents
[GENERAL_REGS
], i
))
439 epiphany_regno_reg_class
[i
] = SIBCALL_REGS
;
440 else if (i
>= CORE_CONTROL_FIRST
&& i
<= CORE_CONTROL_LAST
)
441 epiphany_regno_reg_class
[i
] = CORE_CONTROL_REGS
;
442 else if (i
< (GPR_LAST
+1)
443 || i
== ARG_POINTER_REGNUM
|| i
== FRAME_POINTER_REGNUM
)
444 epiphany_regno_reg_class
[i
] = GENERAL_REGS
;
445 else if (i
== CC_REGNUM
)
446 epiphany_regno_reg_class
[i
] = NO_REGS
/* CC_REG: must be NO_REGS */;
448 epiphany_regno_reg_class
[i
] = NO_REGS
;
452 /* EPIPHANY specific attribute support.
454 The EPIPHANY has these attributes:
455 interrupt - for interrupt functions.
456 short_call - the function is assumed to be reachable with the b / bl
458 long_call - the function address is loaded into a register before use.
459 disinterrupt - functions which mask interrupts throughout.
460 They unmask them while calling an interruptible
463 static const struct attribute_spec epiphany_attribute_table
[] =
465 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
466 { "interrupt", 0, 9, true, false, false, epiphany_handle_interrupt_attribute
, true },
467 { "forwarder_section", 1, 1, true, false, false, epiphany_handle_forwarder_attribute
, false },
468 { "long_call", 0, 0, false, true, true, NULL
, false },
469 { "short_call", 0, 0, false, true, true, NULL
, false },
470 { "disinterrupt", 0, 0, false, true, true, NULL
, true },
471 { NULL
, 0, 0, false, false, false, NULL
, false }
474 /* Handle an "interrupt" attribute; arguments as in
475 struct attribute_spec.handler. */
477 epiphany_handle_interrupt_attribute (tree
*node
, tree name
, tree args
,
478 int flags ATTRIBUTE_UNUSED
,
485 gcc_assert (DECL_P (*node
));
486 tree t
= TREE_TYPE (*node
);
487 if (TREE_CODE (t
) != FUNCTION_TYPE
)
488 warning (OPT_Wattributes
, "%qE attribute only applies to functions",
490 /* Argument handling and the stack layout for interrupt handlers
491 don't mix. It makes no sense in the first place, so emit an
493 else if (TYPE_ARG_TYPES (t
)
494 && TREE_VALUE (TYPE_ARG_TYPES (t
)) != void_type_node
)
495 error_at (DECL_SOURCE_LOCATION (*node
),
496 "interrupt handlers cannot have arguments");
500 value
= TREE_VALUE (args
);
502 if (TREE_CODE (value
) != STRING_CST
)
504 warning (OPT_Wattributes
,
505 "argument of %qE attribute is not a string constant", name
);
506 *no_add_attrs
= true;
508 else if (strcmp (TREE_STRING_POINTER (value
), "reset")
509 && strcmp (TREE_STRING_POINTER (value
), "software_exception")
510 && strcmp (TREE_STRING_POINTER (value
), "page_miss")
511 && strcmp (TREE_STRING_POINTER (value
), "timer0")
512 && strcmp (TREE_STRING_POINTER (value
), "timer1")
513 && strcmp (TREE_STRING_POINTER (value
), "message")
514 && strcmp (TREE_STRING_POINTER (value
), "dma0")
515 && strcmp (TREE_STRING_POINTER (value
), "dma1")
516 && strcmp (TREE_STRING_POINTER (value
), "wand")
517 && strcmp (TREE_STRING_POINTER (value
), "swi"))
519 warning (OPT_Wattributes
,
520 "argument of %qE attribute is not \"reset\", \"software_exception\", \"page_miss\", \"timer0\", \"timer1\", \"message\", \"dma0\", \"dma1\", \"wand\" or \"swi\"",
522 *no_add_attrs
= true;
526 return epiphany_handle_interrupt_attribute (node
, name
, TREE_CHAIN (args
),
527 flags
, no_add_attrs
);
530 /* Handle a "forwarder_section" attribute; arguments as in
531 struct attribute_spec.handler. */
533 epiphany_handle_forwarder_attribute (tree
*node ATTRIBUTE_UNUSED
,
534 tree name
, tree args
,
535 int flags ATTRIBUTE_UNUSED
,
540 value
= TREE_VALUE (args
);
542 if (TREE_CODE (value
) != STRING_CST
)
544 warning (OPT_Wattributes
,
545 "argument of %qE attribute is not a string constant", name
);
546 *no_add_attrs
= true;
552 /* Misc. utilities. */
554 /* Generate a SYMBOL_REF for the special function NAME. When the address
555 can't be placed directly into a call instruction, and if possible, copy
556 it to a register so that cse / code hoisting is possible. */
558 sfunc_symbol (const char *name
)
560 rtx sym
= gen_rtx_SYMBOL_REF (Pmode
, name
);
562 /* These sfuncs should be hidden, and every dso should get a copy. */
563 SYMBOL_REF_FLAGS (sym
) = SYMBOL_FLAG_FUNCTION
| SYMBOL_FLAG_LOCAL
;
564 if (TARGET_SHORT_CALLS
)
565 ; /* Nothing to be done. */
566 else if (can_create_pseudo_p ())
567 sym
= copy_to_mode_reg (Pmode
, sym
);
568 else /* We rely on reload to fix this up. */
569 gcc_assert (!reload_in_progress
|| reload_completed
);
573 /* X and Y are two things to compare using CODE in IN_MODE.
574 Emit the compare insn, construct the the proper cc reg in the proper
575 mode, and return the rtx for the cc reg comparison in CMODE. */
578 gen_compare_reg (machine_mode cmode
, enum rtx_code code
,
579 machine_mode in_mode
, rtx x
, rtx y
)
581 machine_mode mode
= SELECT_CC_MODE (code
, x
, y
);
582 rtx cc_reg
, pat
, clob0
, clob1
, clob2
;
584 if (in_mode
== VOIDmode
)
585 in_mode
= GET_MODE (x
);
586 if (in_mode
== VOIDmode
)
587 in_mode
= GET_MODE (y
);
589 if (mode
== CC_FPmode
)
591 /* The epiphany has only EQ / NE / LT / LE conditions for
592 hardware floating point. */
593 if (code
== GT
|| code
== GE
|| code
== UNLE
|| code
== UNLT
)
595 rtx tmp
= x
; x
= y
; y
= tmp
;
596 code
= swap_condition (code
);
598 cc_reg
= gen_rtx_REG (mode
, CCFP_REGNUM
);
599 y
= force_reg (in_mode
, y
);
603 if (mode
== CC_FP_GTEmode
604 && (code
== LE
|| code
== LT
|| code
== UNGT
|| code
== UNGE
))
606 if (flag_finite_math_only
607 && ((REG_P (x
) && REGNO (x
) == GPR_0
)
608 || (REG_P (y
) && REGNO (y
) == GPR_1
)))
611 case LE
: code
= UNLE
; break;
612 case LT
: code
= UNLT
; break;
613 case UNGT
: code
= GT
; break;
614 case UNGE
: code
= GE
; break;
615 default: gcc_unreachable ();
619 rtx tmp
= x
; x
= y
; y
= tmp
;
620 code
= swap_condition (code
);
623 cc_reg
= gen_rtx_REG (mode
, CC_REGNUM
);
625 if ((mode
== CC_FP_EQmode
|| mode
== CC_FP_GTEmode
626 || mode
== CC_FP_ORDmode
|| mode
== CC_FP_UNEQmode
)
627 /* mov<mode>cc might want to re-emit a comparison during ifcvt. */
628 && (!REG_P (x
) || REGNO (x
) != GPR_0
629 || !REG_P (y
) || REGNO (y
) != GPR_1
))
634 /* ??? We should really do the r0/r1 clobber only during rtl expansion,
635 but just like the flag clobber of movsicc, we have to allow
636 this for ifcvt to work, on the assumption that we'll only want
637 to do this if these registers have been used before by the
639 gcc_assert (currently_expanding_to_rtl
);
641 reg
= gen_rtx_REG (in_mode
, GPR_0
);
642 if (reg_overlap_mentioned_p (reg
, y
))
644 emit_move_insn (reg
, x
);
646 reg
= gen_rtx_REG (in_mode
, GPR_1
);
647 emit_move_insn (reg
, y
);
651 x
= force_reg (in_mode
, x
);
653 pat
= gen_rtx_SET (cc_reg
, gen_rtx_COMPARE (mode
, x
, y
));
654 if (mode
== CC_FP_EQmode
|| mode
== CC_FP_GTEmode
)
656 const char *name
= mode
== CC_FP_EQmode
? "__eqsf2" : "__gtesf2";
657 rtx use
= gen_rtx_USE (VOIDmode
, sfunc_symbol (name
));
659 clob0
= gen_rtx_CLOBBER (VOIDmode
, gen_rtx_REG (SImode
, GPR_IP
));
660 clob1
= gen_rtx_CLOBBER (VOIDmode
, gen_rtx_REG (SImode
, GPR_LR
));
661 pat
= gen_rtx_PARALLEL (VOIDmode
, gen_rtvec (4, pat
, use
, clob0
, clob1
));
663 else if (mode
== CC_FP_ORDmode
|| mode
== CC_FP_UNEQmode
)
665 const char *name
= mode
== CC_FP_ORDmode
? "__ordsf2" : "__uneqsf2";
666 rtx use
= gen_rtx_USE (VOIDmode
, sfunc_symbol (name
));
668 clob0
= gen_rtx_CLOBBER (VOIDmode
, gen_rtx_REG (SImode
, GPR_IP
));
669 clob1
= gen_rtx_CLOBBER (VOIDmode
, gen_rtx_REG (SImode
, GPR_16
));
670 clob2
= gen_rtx_CLOBBER (VOIDmode
, gen_rtx_REG (SImode
, GPR_LR
));
671 pat
= gen_rtx_PARALLEL (VOIDmode
, gen_rtvec (5, pat
, use
,
672 clob0
, clob1
, clob2
));
676 clob0
= gen_rtx_CLOBBER (VOIDmode
, gen_rtx_SCRATCH (in_mode
));
677 pat
= gen_rtx_PARALLEL (VOIDmode
, gen_rtvec (2, pat
, clob0
));
680 return gen_rtx_fmt_ee (code
, cmode
, cc_reg
, const0_rtx
);
683 /* The ROUND_ADVANCE* macros are local to this file. */
684 /* Round SIZE up to a word boundary. */
685 #define ROUND_ADVANCE(SIZE) \
686 (((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
688 /* Round arg MODE/TYPE up to the next word boundary. */
689 #define ROUND_ADVANCE_ARG(MODE, TYPE) \
691 ? ROUND_ADVANCE (int_size_in_bytes (TYPE)) \
692 : ROUND_ADVANCE (GET_MODE_SIZE (MODE)))
694 /* Round CUM up to the necessary point for argument MODE/TYPE. */
695 #define ROUND_ADVANCE_CUM(CUM, MODE, TYPE) \
696 (epiphany_function_arg_boundary ((MODE), (TYPE)) > BITS_PER_WORD \
697 ? (((CUM) + 1) & ~1) \
701 epiphany_function_arg_boundary (machine_mode mode
, const_tree type
)
703 if ((type
? TYPE_ALIGN (type
) : GET_MODE_BITSIZE (mode
)) <= PARM_BOUNDARY
)
704 return PARM_BOUNDARY
;
705 return 2 * PARM_BOUNDARY
;
708 /* Do any needed setup for a variadic function. For the EPIPHANY, we
709 actually emit the code in epiphany_expand_prologue.
711 CUM has not been updated for the last named argument which has type TYPE
712 and mode MODE, and we rely on this fact. */
716 epiphany_setup_incoming_varargs (cumulative_args_t cum
, machine_mode mode
,
717 tree type
, int *pretend_size
, int no_rtl
)
720 CUMULATIVE_ARGS next_cum
;
721 machine_function_t
*mf
= MACHINE_FUNCTION (cfun
);
723 /* All BLKmode values are passed by reference. */
724 gcc_assert (mode
!= BLKmode
);
726 next_cum
= *get_cumulative_args (cum
);
728 = ROUND_ADVANCE_CUM (next_cum
, mode
, type
) + ROUND_ADVANCE_ARG (mode
, type
);
729 first_anon_arg
= next_cum
;
731 if (first_anon_arg
< MAX_EPIPHANY_PARM_REGS
&& !no_rtl
)
733 /* Note that first_reg_offset < MAX_EPIPHANY_PARM_REGS. */
734 int first_reg_offset
= first_anon_arg
;
736 *pretend_size
= ((MAX_EPIPHANY_PARM_REGS
- first_reg_offset
)
740 mf
->pretend_args_odd
= ((*pretend_size
& UNITS_PER_WORD
) ? 1 : 0);
744 epiphany_arg_partial_bytes (cumulative_args_t cum
, machine_mode mode
,
745 tree type
, bool named ATTRIBUTE_UNUSED
)
747 int words
= 0, rounded_cum
;
749 gcc_assert (!epiphany_pass_by_reference (cum
, mode
, type
, /* named */ true));
751 rounded_cum
= ROUND_ADVANCE_CUM (*get_cumulative_args (cum
), mode
, type
);
752 if (rounded_cum
< MAX_EPIPHANY_PARM_REGS
)
754 words
= MAX_EPIPHANY_PARM_REGS
- rounded_cum
;
755 if (words
>= ROUND_ADVANCE_ARG (mode
, type
))
758 return words
* UNITS_PER_WORD
;
761 /* Cost functions. */
763 /* Compute a (partial) cost for rtx X. Return true if the complete
764 cost has been computed, and false if subexpressions should be
765 scanned. In either case, *TOTAL contains the cost result. */
768 epiphany_rtx_costs (rtx x
, machine_mode mode
, int outer_code
,
769 int opno ATTRIBUTE_UNUSED
,
770 int *total
, bool speed ATTRIBUTE_UNUSED
)
772 int code
= GET_CODE (x
);
776 /* Small integers in the right context are as cheap as registers. */
778 if ((outer_code
== PLUS
|| outer_code
== MINUS
)
779 && SIMM11 (INTVAL (x
)))
784 if (IMM16 (INTVAL (x
)))
786 *total
= outer_code
== SET
? 0 : COSTS_N_INSNS (1);
794 *total
= COSTS_N_INSNS ((epiphany_small16 (x
) ? 0 : 1)
795 + (outer_code
== SET
? 0 : 1));
801 split_double (x
, &high
, &low
);
802 *total
= COSTS_N_INSNS (!IMM16 (INTVAL (high
))
803 + !IMM16 (INTVAL (low
)));
810 *total
= COSTS_N_INSNS (1);
816 /* There are a number of single-insn combiner patterns that use
817 the flag side effects of arithmetic. */
829 rtx src
= SET_SRC (x
);
841 /* Provide the costs of an addressing mode that contains ADDR.
842 If ADDR is not a valid address, its cost is irrelevant. */
845 epiphany_address_cost (rtx addr
, machine_mode mode
,
846 addr_space_t as ATTRIBUTE_UNUSED
, bool speed
)
849 rtx off
= const0_rtx
;
854 /* Return 0 for addresses valid in short insns, 1 for addresses only valid
856 switch (GET_CODE (addr
))
859 reg
= XEXP (addr
, 0);
860 off
= XEXP (addr
, 1);
863 reg
= XEXP (addr
, 0);
864 off
= XEXP (addr
, 1);
865 gcc_assert (GET_CODE (off
) == PLUS
&& rtx_equal_p (reg
, XEXP (off
, 0)));
867 if (satisfies_constraint_Rgs (reg
) && satisfies_constraint_Rgs (off
))
875 if (!satisfies_constraint_Rgs (reg
))
877 /* The offset range available for short instructions depends on the mode
878 of the memory access. */
879 /* First, make sure we have a valid integer. */
880 if (!satisfies_constraint_L (off
))
883 switch (GET_MODE_SIZE (mode
))
897 return i
< -7 || i
> 7;
901 /* Compute the cost of moving data between registers and memory.
902 For integer, load latency is twice as long as register-register moves,
903 but issue pich is the same. For floating point, load latency is three
904 times as much as a reg-reg move. */
906 epiphany_memory_move_cost (machine_mode mode
,
907 reg_class_t rclass ATTRIBUTE_UNUSED
,
908 bool in ATTRIBUTE_UNUSED
)
910 return GET_MODE_CLASS (mode
) == MODE_INT
? 3 : 4;
913 /* Function prologue/epilogue handlers. */
915 /* EPIPHANY stack frames look like:
917 Before call After call
918 +-----------------------+ +-----------------------+
920 high | local variables, | | local variables, |
921 mem | reg save area, etc. | | reg save area, etc. |
923 +-----------------------+ +-----------------------+
925 | arguments on stack. | | arguments on stack. |
927 SP+8->+-----------------------+FP+8m->+-----------------------+
928 | 2 word save area for | | reg parm save area, |
929 | leaf funcs / flags | | only created for |
930 SP+0->+-----------------------+ | variable argument |
932 FP+8n->+-----------------------+
934 | register save area |
936 +-----------------------+
940 FP+0->+-----------------------+
942 | alloca allocations |
944 +-----------------------+
946 | arguments on stack |
948 SP+8->+-----------------------+
949 low | 2 word save area for |
950 memory | leaf funcs / flags |
951 SP+0->+-----------------------+
954 1) The "reg parm save area" does not exist for non variable argument fns.
955 The "reg parm save area" could be eliminated if we created our
956 own TARGET_GIMPLIFY_VA_ARG_EXPR, but that has tradeoffs as well
957 (so it's not done). */
959 /* Structure to be filled in by epiphany_compute_frame_size with register
960 save masks, and offsets for the current function. */
961 struct epiphany_frame_info
963 unsigned int total_size
; /* # bytes that the entire frame takes up. */
964 unsigned int pretend_size
; /* # bytes we push and pretend caller did. */
965 unsigned int args_size
; /* # bytes that outgoing arguments take up. */
966 unsigned int reg_size
; /* # bytes needed to store regs. */
967 unsigned int var_size
; /* # bytes that variables take up. */
968 HARD_REG_SET gmask
; /* Set of saved gp registers. */
969 int initialized
; /* Nonzero if frame size already calculated. */
970 int stld_sz
; /* Current load/store data size for offset
972 int need_fp
; /* value to override "frame_pointer_needed */
973 /* FIRST_SLOT is the slot that is saved first, at the very start of
974 the frame, with a POST_MODIFY to allocate the frame, if the size fits,
975 or at least the parm and register save areas, otherwise.
976 In the case of a large frame, LAST_SLOT is the slot that is saved last,
977 with a POST_MODIFY to allocate the rest of the frame. */
978 int first_slot
, last_slot
, first_slot_offset
, last_slot_offset
;
983 /* Current frame information calculated by epiphany_compute_frame_size. */
984 static struct epiphany_frame_info current_frame_info
;
986 /* Zero structure to initialize current_frame_info. */
987 static struct epiphany_frame_info zero_frame_info
;
989 /* The usual; we set up our machine_function data. */
990 static struct machine_function
*
991 epiphany_init_machine_status (void)
993 struct machine_function
*machine
;
995 /* Reset state info for each function. */
996 current_frame_info
= zero_frame_info
;
998 machine
= ggc_cleared_alloc
<machine_function_t
> ();
1003 /* Implements INIT_EXPANDERS. We just set up to call the above
1006 epiphany_init_expanders (void)
1008 init_machine_status
= epiphany_init_machine_status
;
1011 /* Type of function DECL.
1013 The result is cached. To reset the cache at the end of a function,
1014 call with DECL = NULL_TREE. */
1016 static enum epiphany_function_type
1017 epiphany_compute_function_type (tree decl
)
1021 static enum epiphany_function_type fn_type
= EPIPHANY_FUNCTION_UNKNOWN
;
1022 /* Last function we were called for. */
1023 static tree last_fn
= NULL_TREE
;
1025 /* Resetting the cached value? */
1026 if (decl
== NULL_TREE
)
1028 fn_type
= EPIPHANY_FUNCTION_UNKNOWN
;
1029 last_fn
= NULL_TREE
;
1033 if (decl
== last_fn
&& fn_type
!= EPIPHANY_FUNCTION_UNKNOWN
)
1036 /* Assume we have a normal function (not an interrupt handler). */
1037 fn_type
= EPIPHANY_FUNCTION_NORMAL
;
1039 /* Now see if this is an interrupt handler. */
1040 for (a
= DECL_ATTRIBUTES (decl
);
1044 tree name
= TREE_PURPOSE (a
);
1046 if (name
== get_identifier ("interrupt"))
1047 fn_type
= EPIPHANY_FUNCTION_INTERRUPT
;
1054 #define RETURN_ADDR_REGNUM GPR_LR
1055 #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
1056 #define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM))
1058 /* Tell prologue and epilogue if register REGNO should be saved / restored.
1059 The return address and frame pointer are treated separately.
1060 Don't consider them here. */
1061 #define MUST_SAVE_REGISTER(regno, interrupt_p) \
1062 ((df_regs_ever_live_p (regno) \
1063 || (interrupt_p && !crtl->is_leaf \
1064 && call_used_regs[regno] && !fixed_regs[regno])) \
1065 && (!call_used_regs[regno] || regno == GPR_LR \
1066 || (interrupt_p && regno != GPR_SP)))
1068 #define MUST_SAVE_RETURN_ADDR 0
1070 /* Return the bytes needed to compute the frame pointer from the current
1073 SIZE is the size needed for local variables. */
1076 epiphany_compute_frame_size (int size
/* # of var. bytes allocated. */)
1079 unsigned int total_size
, var_size
, args_size
, pretend_size
, reg_size
;
1081 enum epiphany_function_type fn_type
;
1083 int first_slot
, last_slot
, first_slot_offset
, last_slot_offset
;
1084 int first_slot_size
;
1085 int small_slots
= 0;
1088 args_size
= crtl
->outgoing_args_size
;
1089 pretend_size
= crtl
->args
.pretend_args_size
;
1090 total_size
= args_size
+ var_size
;
1092 CLEAR_HARD_REG_SET (gmask
);
1094 first_slot_offset
= 0;
1096 last_slot_offset
= 0;
1097 first_slot_size
= UNITS_PER_WORD
;
1099 /* See if this is an interrupt handler. Call used registers must be saved
1101 fn_type
= epiphany_compute_function_type (current_function_decl
);
1102 interrupt_p
= EPIPHANY_INTERRUPT_P (fn_type
);
1104 /* Calculate space needed for registers. */
1106 for (regno
= MAX_EPIPHANY_PARM_REGS
- 1; pretend_size
> reg_size
; regno
--)
1108 reg_size
+= UNITS_PER_WORD
;
1109 SET_HARD_REG_BIT (gmask
, regno
);
1110 if (epiphany_stack_offset
- reg_size
== 0)
1115 reg_size
+= 2 * UNITS_PER_WORD
;
1117 small_slots
= epiphany_stack_offset
/ UNITS_PER_WORD
;
1119 if (frame_pointer_needed
)
1121 current_frame_info
.need_fp
= 1;
1122 if (!interrupt_p
&& first_slot
< 0)
1123 first_slot
= GPR_FP
;
1126 current_frame_info
.need_fp
= 0;
1127 for (regno
= 0; regno
<= GPR_LAST
; regno
++)
1129 if (MUST_SAVE_REGISTER (regno
, interrupt_p
))
1131 gcc_assert (!TEST_HARD_REG_BIT (gmask
, regno
));
1132 reg_size
+= UNITS_PER_WORD
;
1133 SET_HARD_REG_BIT (gmask
, regno
);
1134 /* FIXME: when optimizing for speed, take schedling into account
1135 when selecting these registers. */
1136 if (regno
== first_slot
)
1137 gcc_assert (regno
== GPR_FP
&& frame_pointer_needed
);
1138 else if (!interrupt_p
&& first_slot
< 0)
1140 else if (last_slot
< 0
1141 && (first_slot
^ regno
) != 1
1142 && (!interrupt_p
|| regno
> GPR_1
))
1146 if (TEST_HARD_REG_BIT (gmask
, GPR_LR
))
1147 MACHINE_FUNCTION (cfun
)->lr_clobbered
= 1;
1148 /* ??? Could sometimes do better than that. */
1149 current_frame_info
.small_threshold
1150 = (optimize
>= 3 || interrupt_p
? 0
1151 : pretend_size
? small_slots
1152 : 4 + small_slots
- (first_slot
== GPR_FP
));
1154 /* If there might be variables with 64-bit alignment requirement, align the
1155 start of the variables. */
1156 if (var_size
>= 2 * UNITS_PER_WORD
1157 /* We don't want to split a double reg save/restore across two unpaired
1158 stack slots when optimizing. This rounding could be avoided with
1159 more complex reordering of the register saves, but that would seem
1160 to be a lot of code complexity for little gain. */
1161 || (reg_size
> 8 && optimize
))
1162 reg_size
= EPIPHANY_STACK_ALIGN (reg_size
);
1163 if (((total_size
+ reg_size
1164 /* Reserve space for UNKNOWN_REGNUM. */
1165 + EPIPHANY_STACK_ALIGN (4))
1166 <= (unsigned) epiphany_stack_offset
)
1168 && crtl
->is_leaf
&& !frame_pointer_needed
)
1176 && reg_size
< (unsigned HOST_WIDE_INT
) epiphany_stack_offset
)
1177 reg_size
= epiphany_stack_offset
;
1180 if (total_size
+ reg_size
< 0x3fc)
1182 first_slot_offset
= EPIPHANY_STACK_ALIGN (total_size
+ reg_size
);
1183 first_slot_offset
+= EPIPHANY_STACK_ALIGN (epiphany_stack_offset
);
1188 first_slot_offset
= EPIPHANY_STACK_ALIGN (reg_size
);
1189 last_slot_offset
= EPIPHANY_STACK_ALIGN (total_size
);
1190 last_slot_offset
+= EPIPHANY_STACK_ALIGN (epiphany_stack_offset
);
1192 CLEAR_HARD_REG_BIT (gmask
, last_slot
);
1195 else if (total_size
+ reg_size
< 0x1ffc && first_slot
>= 0)
1197 first_slot_offset
= EPIPHANY_STACK_ALIGN (total_size
+ reg_size
);
1202 if (total_size
+ reg_size
<= (unsigned) epiphany_stack_offset
)
1204 gcc_assert (first_slot
< 0);
1205 gcc_assert (reg_size
== 0 || (int) reg_size
== epiphany_stack_offset
);
1206 last_slot_offset
= EPIPHANY_STACK_ALIGN (total_size
+ reg_size
);
1212 ? EPIPHANY_STACK_ALIGN (reg_size
- epiphany_stack_offset
) : 0);
1213 if (!first_slot_offset
)
1215 if (first_slot
!= GPR_FP
|| !current_frame_info
.need_fp
)
1216 last_slot
= first_slot
;
1219 last_slot_offset
= EPIPHANY_STACK_ALIGN (total_size
);
1221 last_slot_offset
+= EPIPHANY_STACK_ALIGN (epiphany_stack_offset
);
1224 CLEAR_HARD_REG_BIT (gmask
, last_slot
);
1227 if (first_slot
>= 0)
1229 CLEAR_HARD_REG_BIT (gmask
, first_slot
);
1230 if (TEST_HARD_REG_BIT (gmask
, first_slot
^ 1)
1231 && epiphany_stack_offset
- pretend_size
>= 2 * UNITS_PER_WORD
)
1233 CLEAR_HARD_REG_BIT (gmask
, first_slot
^ 1);
1234 first_slot_size
= 2 * UNITS_PER_WORD
;
1238 total_size
= first_slot_offset
+ last_slot_offset
;
1240 /* Save computed information. */
1241 current_frame_info
.total_size
= total_size
;
1242 current_frame_info
.pretend_size
= pretend_size
;
1243 current_frame_info
.var_size
= var_size
;
1244 current_frame_info
.args_size
= args_size
;
1245 current_frame_info
.reg_size
= reg_size
;
1246 COPY_HARD_REG_SET (current_frame_info
.gmask
, gmask
);
1247 current_frame_info
.first_slot
= first_slot
;
1248 current_frame_info
.last_slot
= last_slot
;
1249 current_frame_info
.first_slot_offset
= first_slot_offset
;
1250 current_frame_info
.first_slot_size
= first_slot_size
;
1251 current_frame_info
.last_slot_offset
= last_slot_offset
;
1253 current_frame_info
.initialized
= reload_completed
;
1255 /* Ok, we're done. */
1259 /* Print operand X (an rtx) in assembler syntax to file FILE.
1260 CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
1261 For `%' followed by punctuation, CODE is the punctuation and X is null. */
1264 epiphany_print_operand (FILE *file
, rtx x
, int code
)
1269 fputs (epiphany_condition_codes
[get_epiphany_condition_code (x
)], file
);
1272 fputs (epiphany_condition_codes
[EPIPHANY_INVERSE_CONDITION_CODE
1273 (get_epiphany_condition_code (x
))],
1278 current_frame_info
.stld_sz
= 8;
1282 current_frame_info
.stld_sz
= 4;
1286 current_frame_info
.stld_sz
= 2;
1290 fputs (REG_P (x
) ? "jalr " : "bl ", file
);
1294 fprintf (file
, "r%d", epiphany_m1reg
);
1298 /* Do nothing special. */
1302 output_operand_lossage ("invalid operand output code");
1305 switch (GET_CODE (x
))
1311 fputs (reg_names
[REGNO (x
)], file
);
1315 current_frame_info
.stld_sz
= 1;
1318 switch (GET_CODE (addr
))
1321 offset
= GEN_INT (GET_MODE_SIZE (GET_MODE (x
)));
1322 addr
= XEXP (addr
, 0);
1325 offset
= GEN_INT (-GET_MODE_SIZE (GET_MODE (x
)));
1326 addr
= XEXP (addr
, 0);
1329 offset
= XEXP (XEXP (addr
, 1), 1);
1330 addr
= XEXP (addr
, 0);
1336 output_address (addr
);
1341 if (CONST_INT_P (offset
)) switch (GET_MODE_SIZE (GET_MODE (x
)))
1346 offset
= GEN_INT (INTVAL (offset
) >> 3);
1349 offset
= GEN_INT (INTVAL (offset
) >> 2);
1352 offset
= GEN_INT (INTVAL (offset
) >> 1);
1357 output_address (offset
);
1361 /* We handle SFmode constants here as output_addr_const doesn't. */
1362 if (GET_MODE (x
) == SFmode
)
1367 REAL_VALUE_FROM_CONST_DOUBLE (d
, x
);
1368 REAL_VALUE_TO_TARGET_SINGLE (d
, l
);
1369 fprintf (file
, "%s0x%08lx", IMMEDIATE_PREFIX
, l
);
1372 /* Fall through. Let output_addr_const deal with it. */
1374 fprintf(file
,"%s",IMMEDIATE_PREFIX
);
1375 if (code
== 'C' || code
== 'X')
1377 fprintf (file
, "%ld",
1378 (long) (INTVAL (x
) / current_frame_info
.stld_sz
));
1383 output_addr_const (file
, x
);
1388 /* Print a memory address as an operand to reference that memory location. */
1391 epiphany_print_operand_address (FILE *file
, rtx addr
)
1393 register rtx base
, index
= 0;
1396 switch (GET_CODE (addr
))
1399 fputs (reg_names
[REGNO (addr
)], file
);
1402 if (/*???*/ 0 && SYMBOL_REF_FUNCTION_P (addr
))
1404 output_addr_const (file
, addr
);
1408 output_addr_const (file
, addr
);
1412 if (GET_CODE (XEXP (addr
, 0)) == CONST_INT
)
1413 offset
= INTVAL (XEXP (addr
, 0)), base
= XEXP (addr
, 1);
1414 else if (GET_CODE (XEXP (addr
, 1)) == CONST_INT
)
1415 offset
= INTVAL (XEXP (addr
, 1)), base
= XEXP (addr
, 0);
1417 base
= XEXP (addr
, 0), index
= XEXP (addr
, 1);
1418 gcc_assert (GET_CODE (base
) == REG
);
1419 fputs (reg_names
[REGNO (base
)], file
);
1423 ** ++rk quirky method to scale offset for ld/str.......
1425 fprintf (file
, ",%s%d", IMMEDIATE_PREFIX
,
1426 offset
/current_frame_info
.stld_sz
);
1430 switch (GET_CODE (index
))
1433 fprintf (file
, ",%s", reg_names
[REGNO (index
)]);
1436 fputc (',', file
), output_addr_const (file
, index
);
1443 case PRE_INC
: case PRE_DEC
: case POST_INC
: case POST_DEC
: case POST_MODIFY
:
1444 /* We shouldn't get here as we've lost the mode of the memory object
1445 (which says how much to inc/dec by. */
1449 output_addr_const (file
, addr
);
1455 epiphany_final_prescan_insn (rtx_insn
*insn ATTRIBUTE_UNUSED
,
1456 rtx
*opvec ATTRIBUTE_UNUSED
,
1457 int noperands ATTRIBUTE_UNUSED
)
1459 int i
= epiphany_n_nops
;
1460 rtx pat ATTRIBUTE_UNUSED
;
1463 fputs ("\tnop\n", asm_out_file
);
1467 /* Worker function for TARGET_RETURN_IN_MEMORY. */
1470 epiphany_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
1472 HOST_WIDE_INT size
= int_size_in_bytes (type
);
1474 if (AGGREGATE_TYPE_P (type
)
1475 && (TYPE_MODE (type
) == BLKmode
|| TYPE_NEEDS_CONSTRUCTING (type
)))
1477 return (size
== -1 || size
> 8);
1480 /* For EPIPHANY, All aggregates and arguments greater than 8 bytes are
1481 passed by reference. */
1484 epiphany_pass_by_reference (cumulative_args_t ca ATTRIBUTE_UNUSED
,
1485 machine_mode mode
, const_tree type
,
1486 bool named ATTRIBUTE_UNUSED
)
1490 if (AGGREGATE_TYPE_P (type
)
1491 && (mode
== BLKmode
|| TYPE_NEEDS_CONSTRUCTING (type
)))
1499 epiphany_function_value (const_tree ret_type
,
1500 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
1501 bool outgoing ATTRIBUTE_UNUSED
)
1505 mode
= TYPE_MODE (ret_type
);
1506 /* We must change the mode like PROMOTE_MODE does.
1507 ??? PROMOTE_MODE is ignored for non-scalar types.
1508 The set of types tested here has to be kept in sync
1509 with the one in explow.c:promote_mode. */
1510 if (GET_MODE_CLASS (mode
) == MODE_INT
1511 && GET_MODE_SIZE (mode
) < 4
1512 && (TREE_CODE (ret_type
) == INTEGER_TYPE
1513 || TREE_CODE (ret_type
) == ENUMERAL_TYPE
1514 || TREE_CODE (ret_type
) == BOOLEAN_TYPE
1515 || TREE_CODE (ret_type
) == OFFSET_TYPE
))
1517 return gen_rtx_REG (mode
, 0);
1521 epiphany_libcall_value (machine_mode mode
, const_rtx fun ATTRIBUTE_UNUSED
)
1523 return gen_rtx_REG (mode
, 0);
1527 epiphany_function_value_regno_p (const unsigned int regno ATTRIBUTE_UNUSED
)
1532 /* Fix up invalid option settings. */
1534 epiphany_override_options (void)
1536 if (epiphany_stack_offset
< 4)
1537 error ("stack_offset must be at least 4");
1538 if (epiphany_stack_offset
& 3)
1539 error ("stack_offset must be a multiple of 4");
1540 epiphany_stack_offset
= (epiphany_stack_offset
+ 3) & -4;
1541 if (!TARGET_SOFT_CMPSF
)
1542 flag_finite_math_only
= 1;
1544 /* This needs to be done at start up. It's convenient to do it here. */
1548 /* For a DImode load / store SET, make a SImode set for a
1549 REG_FRAME_RELATED_EXPR note, using OFFSET to create a high or lowpart
1552 frame_subreg_note (rtx set
, int offset
)
1554 rtx src
= simplify_gen_subreg (SImode
, SET_SRC (set
), DImode
, offset
);
1555 rtx dst
= simplify_gen_subreg (SImode
, SET_DEST (set
), DImode
, offset
);
1557 set
= gen_rtx_SET (dst
,src
);
1558 RTX_FRAME_RELATED_P (set
) = 1;
1566 rtx note
= NULL_RTX
;
1569 if (GET_CODE (x
) == PARALLEL
)
1571 rtx part
= XVECEXP (x
, 0, 0);
1573 if (GET_MODE (SET_DEST (part
)) == DImode
)
1575 note
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (XVECLEN (x
, 0) + 1));
1576 XVECEXP (note
, 0, 0) = frame_subreg_note (part
, 0);
1577 XVECEXP (note
, 0, 1) = frame_subreg_note (part
, UNITS_PER_WORD
);
1578 for (i
= XVECLEN (x
, 0) - 1; i
>= 1; i
--)
1580 part
= copy_rtx (XVECEXP (x
, 0, i
));
1582 if (GET_CODE (part
) == SET
)
1583 RTX_FRAME_RELATED_P (part
) = 1;
1584 XVECEXP (note
, 0, i
+ 1) = part
;
1589 for (i
= XVECLEN (x
, 0) - 1; i
>= 0; i
--)
1591 part
= XVECEXP (x
, 0, i
);
1593 if (GET_CODE (part
) == SET
)
1594 RTX_FRAME_RELATED_P (part
) = 1;
1598 else if (GET_CODE (x
) == SET
&& GET_MODE (SET_DEST (x
)) == DImode
)
1599 note
= gen_rtx_PARALLEL (VOIDmode
,
1600 gen_rtvec (2, frame_subreg_note (x
, 0),
1601 frame_subreg_note (x
, UNITS_PER_WORD
)));
1602 insn
= emit_insn (x
);
1603 RTX_FRAME_RELATED_P (insn
) = 1;
1605 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
, note
);
1610 frame_move_insn (rtx to
, rtx from
)
1612 return frame_insn (gen_rtx_SET (to
, from
));
1615 /* Generate a MEM referring to a varargs argument slot. */
1618 gen_varargs_mem (machine_mode mode
, rtx addr
)
1620 rtx mem
= gen_rtx_MEM (mode
, addr
);
1621 MEM_NOTRAP_P (mem
) = 1;
1622 set_mem_alias_set (mem
, get_varargs_alias_set ());
1626 /* Emit instructions to save or restore registers in the range [MIN..LIMIT) .
1627 If EPILOGUE_P is 0, save; if it is one, restore.
1628 ADDR is the stack slot to save the first register to; subsequent
1629 registers are written to lower addresses.
1630 However, the order of register pairs can be reversed in order to
1631 use double-word load-store instructions. Likewise, an unpaired single
1632 word save slot can be skipped while double saves are carried out, and
1633 reused when a single register is to be saved. */
1636 epiphany_emit_save_restore (int min
, int limit
, rtx addr
, int epilogue_p
)
1640 = current_frame_info
.first_slot
>= 0 ? epiphany_stack_offset
: 0;
1641 rtx skipped_mem
= NULL_RTX
;
1642 int last_saved
= limit
- 1;
1645 while (last_saved
>= 0
1646 && !TEST_HARD_REG_BIT (current_frame_info
.gmask
, last_saved
))
1648 for (i
= 0; i
< limit
; i
++)
1650 machine_mode mode
= word_mode
;
1653 rtx (*gen_mem
) (machine_mode
, rtx
) = gen_frame_mem
;
1655 /* Make sure we push the arguments in the right order. */
1656 if (n
< MAX_EPIPHANY_PARM_REGS
&& crtl
->args
.pretend_args_size
)
1658 n
= MAX_EPIPHANY_PARM_REGS
- 1 - n
;
1659 gen_mem
= gen_varargs_mem
;
1661 if (stack_offset
== current_frame_info
.first_slot_size
1662 && current_frame_info
.first_slot
>= 0)
1664 if (current_frame_info
.first_slot_size
> UNITS_PER_WORD
)
1667 addr
= plus_constant (Pmode
, addr
,
1668 - (HOST_WIDE_INT
) UNITS_PER_WORD
);
1670 if (i
-- < min
|| !epilogue_p
)
1672 n
= current_frame_info
.first_slot
;
1673 gen_mem
= gen_frame_mem
;
1675 else if (n
== UNKNOWN_REGNUM
1676 && stack_offset
> current_frame_info
.first_slot_size
)
1681 else if (!TEST_HARD_REG_BIT (current_frame_info
.gmask
, n
))
1686 /* Check for a register pair to save. */
1688 && (n
>= MAX_EPIPHANY_PARM_REGS
|| crtl
->args
.pretend_args_size
== 0)
1689 && (n
& 1) == 0 && n
+1 < limit
1690 && TEST_HARD_REG_BIT (current_frame_info
.gmask
, n
+1))
1692 /* If it fits in the current stack slot pair, place it there. */
1693 if (GET_CODE (addr
) == PLUS
&& (stack_offset
& 7) == 0
1694 && stack_offset
!= 2 * UNITS_PER_WORD
1695 && (current_frame_info
.last_slot
< 0
1696 || INTVAL (XEXP (addr
, 1)) != UNITS_PER_WORD
)
1697 && (n
+1 != last_saved
|| !skipped_mem
))
1701 addr
= plus_constant (Pmode
, addr
,
1702 - (HOST_WIDE_INT
) UNITS_PER_WORD
);
1704 /* If it fits in the following stack slot pair, that's fine, too. */
1705 else if (GET_CODE (addr
) == PLUS
&& (stack_offset
& 7) == 4
1706 && stack_offset
!= 2 * UNITS_PER_WORD
1707 && stack_offset
!= 3 * UNITS_PER_WORD
1708 && (current_frame_info
.last_slot
< 0
1709 || INTVAL (XEXP (addr
, 1)) != 2 * UNITS_PER_WORD
)
1710 && n
+ 1 != last_saved
)
1712 gcc_assert (!skipped_mem
);
1713 stack_offset
-= GET_MODE_SIZE (mode
);
1714 skipped_mem
= gen_mem (mode
, addr
);
1717 addr
= plus_constant (Pmode
, addr
,
1718 - (HOST_WIDE_INT
) 2 * UNITS_PER_WORD
);
1721 reg
= gen_rtx_REG (mode
, n
);
1722 if (mode
!= DImode
&& skipped_mem
)
1725 mem
= gen_mem (mode
, addr
);
1727 /* If we are loading / storing LR, note the offset that
1728 gen_reload_insi_ra requires. Since GPR_LR is even,
1729 we only need to test n, even if mode is DImode. */
1730 gcc_assert ((GPR_LR
& 1) == 0);
1733 long lr_slot_offset
= 0;
1734 rtx m_addr
= XEXP (mem
, 0);
1736 if (GET_CODE (m_addr
) == PLUS
)
1737 lr_slot_offset
= INTVAL (XEXP (m_addr
, 1));
1738 if (frame_pointer_needed
)
1739 lr_slot_offset
+= (current_frame_info
.first_slot_offset
1740 - current_frame_info
.total_size
);
1741 if (MACHINE_FUNCTION (cfun
)->lr_slot_known
)
1742 gcc_assert (MACHINE_FUNCTION (cfun
)->lr_slot_offset
1744 MACHINE_FUNCTION (cfun
)->lr_slot_offset
= lr_slot_offset
;
1745 MACHINE_FUNCTION (cfun
)->lr_slot_known
= 1;
1749 frame_move_insn (mem
, reg
);
1750 else if (n
>= MAX_EPIPHANY_PARM_REGS
|| !crtl
->args
.pretend_args_size
)
1751 emit_move_insn (reg
, mem
);
1752 if (mem
== skipped_mem
)
1754 skipped_mem
= NULL_RTX
;
1758 addr
= plus_constant (Pmode
, addr
, -(HOST_WIDE_INT
) UNITS_PER_WORD
);
1759 stack_offset
-= GET_MODE_SIZE (mode
);
1764 epiphany_expand_prologue (void)
1767 enum epiphany_function_type fn_type
;
1768 rtx addr
, mem
, off
, reg
;
1770 if (!current_frame_info
.initialized
)
1771 epiphany_compute_frame_size (get_frame_size ());
1773 /* It is debatable if we should adjust this by epiphany_stack_offset. */
1774 if (flag_stack_usage_info
)
1775 current_function_static_stack_size
= current_frame_info
.total_size
;
1777 fn_type
= epiphany_compute_function_type (current_function_decl
);
1778 interrupt_p
= EPIPHANY_INTERRUPT_P (fn_type
);
1782 addr
= plus_constant (Pmode
, stack_pointer_rtx
,
1783 - (HOST_WIDE_INT
) 2 * UNITS_PER_WORD
);
1784 if (!lookup_attribute ("forwarder_section",
1785 DECL_ATTRIBUTES (current_function_decl
))
1786 || !epiphany_is_long_call_p (XEXP (DECL_RTL (current_function_decl
),
1788 frame_move_insn (gen_frame_mem (DImode
, addr
),
1789 gen_rtx_REG (DImode
, GPR_0
));
1790 frame_move_insn (gen_rtx_REG (SImode
, GPR_0
),
1791 gen_rtx_REG (word_mode
, STATUS_REGNUM
));
1792 frame_move_insn (gen_rtx_REG (SImode
, GPR_1
),
1793 gen_rtx_REG (word_mode
, IRET_REGNUM
));
1794 mem
= gen_frame_mem (BLKmode
, stack_pointer_rtx
);
1795 off
= GEN_INT (-current_frame_info
.first_slot_offset
);
1796 frame_insn (gen_stack_adjust_add (off
, mem
));
1797 if (!epiphany_uninterruptible_p (current_function_decl
))
1798 emit_insn (gen_gie ());
1799 addr
= plus_constant (Pmode
, stack_pointer_rtx
,
1800 current_frame_info
.first_slot_offset
1801 - (HOST_WIDE_INT
) 3 * UNITS_PER_WORD
);
1805 addr
= plus_constant (Pmode
, stack_pointer_rtx
,
1806 epiphany_stack_offset
1807 - (HOST_WIDE_INT
) UNITS_PER_WORD
);
1808 epiphany_emit_save_restore (0, current_frame_info
.small_threshold
,
1810 /* Allocate register save area; for small to medium size frames,
1811 allocate the entire frame; this is joint with one register save. */
1812 if (current_frame_info
.first_slot
>= 0)
1815 = (current_frame_info
.first_slot_size
== UNITS_PER_WORD
1816 ? word_mode
: DImode
);
1818 off
= GEN_INT (-current_frame_info
.first_slot_offset
);
1819 mem
= gen_frame_mem (BLKmode
,
1820 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
, off
));
1821 frame_insn (gen_stack_adjust_str
1822 (gen_frame_mem (mode
, stack_pointer_rtx
),
1823 gen_rtx_REG (mode
, current_frame_info
.first_slot
),
1825 addr
= plus_constant (Pmode
, addr
,
1826 current_frame_info
.first_slot_offset
);
1829 epiphany_emit_save_restore (current_frame_info
.small_threshold
,
1830 FIRST_PSEUDO_REGISTER
, addr
, 0);
1831 if (current_frame_info
.need_fp
)
1832 frame_move_insn (hard_frame_pointer_rtx
, stack_pointer_rtx
);
1833 /* For large frames, allocate bulk of frame. This is usually joint with one
1835 if (current_frame_info
.last_slot
>= 0)
1840 gcc_assert (current_frame_info
.last_slot
!= GPR_FP
1841 || (!current_frame_info
.need_fp
1842 && current_frame_info
.first_slot
< 0));
1843 off
= GEN_INT (-current_frame_info
.last_slot_offset
);
1844 mem
= gen_frame_mem (BLKmode
,
1845 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
, off
));
1846 ip
= gen_rtx_REG (Pmode
, GPR_IP
);
1847 frame_move_insn (ip
, off
);
1848 reg
= gen_rtx_REG (word_mode
, current_frame_info
.last_slot
),
1849 mem2
= gen_frame_mem (word_mode
, stack_pointer_rtx
),
1850 insn
= frame_insn (gen_stack_adjust_str (mem2
, reg
, ip
, mem
));
1851 /* Instruction scheduling can separate the instruction setting IP from
1852 INSN so that dwarf2out_frame_debug_expr becomes confused what the
1853 temporary register is. Example: _gcov.o */
1854 note
= gen_rtx_SET (stack_pointer_rtx
,
1855 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
, off
));
1856 note
= gen_rtx_PARALLEL (VOIDmode
,
1857 gen_rtvec (2, gen_rtx_SET (mem2
, reg
), note
));
1858 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
, note
);
1860 /* If there is only one or no register to save, yet we have a large frame,
1862 else if (current_frame_info
.last_slot_offset
)
1864 mem
= gen_frame_mem (BLKmode
,
1865 plus_constant (Pmode
, stack_pointer_rtx
,
1866 current_frame_info
.last_slot_offset
));
1867 off
= GEN_INT (-current_frame_info
.last_slot_offset
);
1868 if (!SIMM11 (INTVAL (off
)))
1870 reg
= gen_rtx_REG (Pmode
, GPR_IP
);
1871 frame_move_insn (reg
, off
);
1874 frame_insn (gen_stack_adjust_add (off
, mem
));
1879 epiphany_expand_epilogue (int sibcall_p
)
1882 enum epiphany_function_type fn_type
;
1883 rtx mem
, addr
, reg
, off
;
1884 HOST_WIDE_INT restore_offset
;
1886 fn_type
= epiphany_compute_function_type( current_function_decl
);
1887 interrupt_p
= EPIPHANY_INTERRUPT_P (fn_type
);
1889 /* For variable frames, deallocate bulk of frame. */
1890 if (current_frame_info
.need_fp
)
1892 mem
= gen_frame_mem (BLKmode
, stack_pointer_rtx
);
1893 emit_insn (gen_stack_adjust_mov (mem
));
1895 /* Else for large static frames, deallocate bulk of frame. */
1896 else if (current_frame_info
.last_slot_offset
)
1898 mem
= gen_frame_mem (BLKmode
, stack_pointer_rtx
);
1899 reg
= gen_rtx_REG (Pmode
, GPR_IP
);
1900 emit_move_insn (reg
, GEN_INT (current_frame_info
.last_slot_offset
));
1901 emit_insn (gen_stack_adjust_add (reg
, mem
));
1903 restore_offset
= (interrupt_p
1904 ? - 3 * UNITS_PER_WORD
1905 : epiphany_stack_offset
- (HOST_WIDE_INT
) UNITS_PER_WORD
);
1906 addr
= plus_constant (Pmode
, stack_pointer_rtx
,
1907 (current_frame_info
.first_slot_offset
1909 epiphany_emit_save_restore (current_frame_info
.small_threshold
,
1910 FIRST_PSEUDO_REGISTER
, addr
, 1);
1912 if (interrupt_p
&& !epiphany_uninterruptible_p (current_function_decl
))
1913 emit_insn (gen_gid ());
1915 off
= GEN_INT (current_frame_info
.first_slot_offset
);
1916 mem
= gen_frame_mem (BLKmode
, stack_pointer_rtx
);
1917 /* For large / variable size frames, deallocating the register save area is
1918 joint with one register restore; for medium size frames, we use a
1919 dummy post-increment load to dealloacte the whole frame. */
1920 if (!SIMM11 (INTVAL (off
)) || current_frame_info
.last_slot
>= 0)
1922 emit_insn (gen_stack_adjust_ldr
1923 (gen_rtx_REG (word_mode
,
1924 (current_frame_info
.last_slot
>= 0
1925 ? current_frame_info
.last_slot
: GPR_IP
)),
1926 gen_frame_mem (word_mode
, stack_pointer_rtx
),
1930 /* While for small frames, we deallocate the entire frame with one add. */
1931 else if (INTVAL (off
))
1933 emit_insn (gen_stack_adjust_add (off
, mem
));
1937 emit_move_insn (gen_rtx_REG (word_mode
, STATUS_REGNUM
),
1938 gen_rtx_REG (SImode
, GPR_0
));
1939 emit_move_insn (gen_rtx_REG (word_mode
, IRET_REGNUM
),
1940 gen_rtx_REG (SImode
, GPR_1
));
1941 addr
= plus_constant (Pmode
, stack_pointer_rtx
,
1942 - (HOST_WIDE_INT
) 2 * UNITS_PER_WORD
);
1943 emit_move_insn (gen_rtx_REG (DImode
, GPR_0
),
1944 gen_frame_mem (DImode
, addr
));
1946 addr
= plus_constant (Pmode
, stack_pointer_rtx
,
1947 epiphany_stack_offset
- (HOST_WIDE_INT
) UNITS_PER_WORD
);
1948 epiphany_emit_save_restore (0, current_frame_info
.small_threshold
, addr
, 1);
1952 emit_jump_insn (gen_return_internal_interrupt());
1954 emit_jump_insn (gen_return_i ());
1959 epiphany_initial_elimination_offset (int from
, int to
)
1961 epiphany_compute_frame_size (get_frame_size ());
1962 if (from
== FRAME_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
1963 return current_frame_info
.total_size
- current_frame_info
.reg_size
;
1964 if (from
== FRAME_POINTER_REGNUM
&& to
== HARD_FRAME_POINTER_REGNUM
)
1965 return current_frame_info
.first_slot_offset
- current_frame_info
.reg_size
;
1966 if (from
== ARG_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
1967 return (current_frame_info
.total_size
1968 - ((current_frame_info
.pretend_size
+ 4) & -8));
1969 if (from
== ARG_POINTER_REGNUM
&& to
== HARD_FRAME_POINTER_REGNUM
)
1970 return (current_frame_info
.first_slot_offset
1971 - ((current_frame_info
.pretend_size
+ 4) & -8));
1976 epiphany_regno_rename_ok (unsigned, unsigned dst
)
1978 enum epiphany_function_type fn_type
;
1980 fn_type
= epiphany_compute_function_type (current_function_decl
);
1981 if (!EPIPHANY_INTERRUPT_P (fn_type
))
1983 if (df_regs_ever_live_p (dst
))
1989 epiphany_issue_rate (void)
1994 /* Function to update the integer COST
1995 based on the relationship between INSN that is dependent on
1996 DEP_INSN through the dependence LINK. The default is to make no
1997 adjustment to COST. This can be used for example to specify to
1998 the scheduler that an output- or anti-dependence does not incur
1999 the same cost as a data-dependence. The return value should be
2000 the new value for COST. */
2002 epiphany_adjust_cost (rtx_insn
*insn
, rtx link
, rtx_insn
*dep_insn
, int cost
)
2004 if (REG_NOTE_KIND (link
) == 0)
2008 if (recog_memoized (insn
) < 0
2009 || recog_memoized (dep_insn
) < 0)
2012 dep_set
= single_set (dep_insn
);
2014 /* The latency that we specify in the scheduling description refers
2015 to the actual output, not to an auto-increment register; for that,
2016 the latency is one. */
2017 if (dep_set
&& MEM_P (SET_SRC (dep_set
)) && cost
> 1)
2019 rtx set
= single_set (insn
);
2022 && !reg_overlap_mentioned_p (SET_DEST (dep_set
), SET_SRC (set
))
2023 && (!MEM_P (SET_DEST (set
))
2024 || !reg_overlap_mentioned_p (SET_DEST (dep_set
),
2025 XEXP (SET_DEST (set
), 0))))
2032 #define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_BASE_P (X)
2034 #define RTX_OK_FOR_BASE_P(X) \
2035 (REG_P (X) && REG_OK_FOR_BASE_P (X))
2037 #define RTX_OK_FOR_INDEX_P(MODE, X) \
2038 ((GET_MODE_CLASS (MODE) != MODE_VECTOR_INT \
2039 || epiphany_vect_align >= GET_MODE_SIZE (MODE)) \
2040 && (REG_P (X) && REG_OK_FOR_INDEX_P (X)))
2042 #define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X) \
2043 (GET_CODE (X) == PLUS \
2044 && RTX_OK_FOR_BASE_P (XEXP (X, 0)) \
2045 && (RTX_OK_FOR_INDEX_P (MODE, XEXP (X, 1)) \
2046 || RTX_OK_FOR_OFFSET_P (MODE, XEXP (X, 1))))
2049 epiphany_legitimate_address_p (machine_mode mode
, rtx x
, bool strict
)
2051 #define REG_OK_FOR_BASE_P(X) \
2052 (strict ? GPR_P (REGNO (X)) : GPR_AP_OR_PSEUDO_P (REGNO (X)))
2053 if (RTX_OK_FOR_BASE_P (x
))
2055 if (RTX_FRAME_OFFSET_P (x
))
2057 if (LEGITIMATE_OFFSET_ADDRESS_P (mode
, x
))
2059 /* If this is a misaligned stack access, don't force it to reg+index. */
2060 if (GET_MODE_SIZE (mode
) == 8
2061 && GET_CODE (x
) == PLUS
&& XEXP (x
, 0) == stack_pointer_rtx
2062 /* Decomposed to SImode; GET_MODE_SIZE (SImode) == 4 */
2063 && !(INTVAL (XEXP (x
, 1)) & 3)
2064 && INTVAL (XEXP (x
, 1)) >= -2047 * 4
2065 && INTVAL (XEXP (x
, 1)) <= 2046 * 4)
2068 && (GET_CODE (x
) == POST_DEC
|| GET_CODE (x
) == POST_INC
)
2069 && RTX_OK_FOR_BASE_P (XEXP ((x
), 0)))
2071 if ((TARGET_POST_MODIFY
|| reload_completed
)
2072 && GET_CODE (x
) == POST_MODIFY
2073 && GET_CODE (XEXP ((x
), 1)) == PLUS
2074 && rtx_equal_p (XEXP ((x
), 0), XEXP (XEXP ((x
), 1), 0))
2075 && LEGITIMATE_OFFSET_ADDRESS_P (mode
, XEXP ((x
), 1)))
2077 if (mode
== BLKmode
)
2078 return epiphany_legitimate_address_p (SImode
, x
, strict
);
2083 epiphany_secondary_reload (bool in_p
, rtx x
, reg_class_t rclass
,
2084 machine_mode mode ATTRIBUTE_UNUSED
,
2085 secondary_reload_info
*sri
)
2087 /* This could give more reload inheritance, but we are missing some
2088 reload infrastructure. */
2090 if (in_p
&& GET_CODE (x
) == UNSPEC
2091 && satisfies_constraint_Sra (x
) && !satisfies_constraint_Rra (x
))
2093 gcc_assert (rclass
== GENERAL_REGS
);
2094 sri
->icode
= CODE_FOR_reload_insi_ra
;
2101 epiphany_is_long_call_p (rtx x
)
2103 tree decl
= SYMBOL_REF_DECL (x
);
2104 bool ret_val
= !TARGET_SHORT_CALLS
;
2107 /* ??? Is it safe to default to ret_val if decl is NULL? We should
2108 probably encode information via encode_section_info, and also
2109 have (an) option(s) to take SYMBOL_FLAG_LOCAL and/or SYMBOL_FLAG_EXTERNAL
2113 attrs
= TYPE_ATTRIBUTES (TREE_TYPE (decl
));
2114 if (lookup_attribute ("long_call", attrs
))
2116 else if (lookup_attribute ("short_call", attrs
))
2123 epiphany_small16 (rtx x
)
2126 rtx offs ATTRIBUTE_UNUSED
= const0_rtx
;
2128 if (GET_CODE (x
) == CONST
&& GET_CODE (XEXP (x
, 0)) == PLUS
)
2130 base
= XEXP (XEXP (x
, 0), 0);
2131 offs
= XEXP (XEXP (x
, 0), 1);
2133 if (GET_CODE (base
) == SYMBOL_REF
&& SYMBOL_REF_FUNCTION_P (base
)
2134 && epiphany_is_long_call_p (base
))
2136 return TARGET_SMALL16
!= 0;
2139 /* Return nonzero if it is ok to make a tail-call to DECL. */
2141 epiphany_function_ok_for_sibcall (tree decl
, tree exp
)
2143 bool cfun_interrupt_p
, call_interrupt_p
;
2145 cfun_interrupt_p
= EPIPHANY_INTERRUPT_P (epiphany_compute_function_type
2146 (current_function_decl
));
2148 call_interrupt_p
= EPIPHANY_INTERRUPT_P (epiphany_compute_function_type (decl
));
2151 tree fn_type
= TREE_TYPE (CALL_EXPR_FN (exp
));
2153 gcc_assert (POINTER_TYPE_P (fn_type
));
2154 fn_type
= TREE_TYPE (fn_type
);
2155 gcc_assert (TREE_CODE (fn_type
) == FUNCTION_TYPE
2156 || TREE_CODE (fn_type
) == METHOD_TYPE
);
2158 = lookup_attribute ("interrupt", TYPE_ATTRIBUTES (fn_type
)) != NULL
;
2161 /* Don't tailcall from or to an ISR routine - although we could in
2162 principle tailcall from one ISR routine to another, we'd need to
2163 handle this in sibcall_epilogue to make it work. */
2164 if (cfun_interrupt_p
|| call_interrupt_p
)
2167 /* Everything else is ok. */
2171 /* T is a function declaration or the MEM_EXPR of a MEM passed to a call
2173 Return true iff the type of T has the uninterruptible attribute.
2174 If T is NULL, return false. */
2176 epiphany_uninterruptible_p (tree t
)
2182 attrs
= TYPE_ATTRIBUTES (TREE_TYPE (t
));
2183 if (lookup_attribute ("disinterrupt", attrs
))
2190 epiphany_call_uninterruptible_p (rtx mem
)
2192 rtx addr
= XEXP (mem
, 0);
2195 if (GET_CODE (addr
) == SYMBOL_REF
)
2196 t
= SYMBOL_REF_DECL (addr
);
2199 return epiphany_uninterruptible_p (t
);
2203 epiphany_promote_function_mode (const_tree type
, machine_mode mode
,
2204 int *punsignedp ATTRIBUTE_UNUSED
,
2205 const_tree funtype ATTRIBUTE_UNUSED
,
2206 int for_return ATTRIBUTE_UNUSED
)
2210 return promote_mode (type
, mode
, &dummy
);
2214 epiphany_conditional_register_usage (void)
2218 if (PIC_OFFSET_TABLE_REGNUM
!= INVALID_REGNUM
)
2220 fixed_regs
[PIC_OFFSET_TABLE_REGNUM
] = 1;
2221 call_used_regs
[PIC_OFFSET_TABLE_REGNUM
] = 1;
2223 if (TARGET_HALF_REG_FILE
)
2225 for (i
= 32; i
<= 63; i
++)
2228 call_used_regs
[i
] = 1;
2231 if (epiphany_m1reg
>= 0)
2233 fixed_regs
[epiphany_m1reg
] = 1;
2234 call_used_regs
[epiphany_m1reg
] = 1;
2236 if (!TARGET_PREFER_SHORT_INSN_REGS
)
2237 CLEAR_HARD_REG_SET (reg_class_contents
[SHORT_INSN_REGS
]);
2238 COPY_HARD_REG_SET (reg_class_contents
[SIBCALL_REGS
],
2239 reg_class_contents
[GENERAL_REGS
]);
2240 /* It would be simpler and quicker if we could just use
2241 AND_COMPL_HARD_REG_SET, alas, call_used_reg_set is yet uninitialized;
2242 it is set up later by our caller. */
2243 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
2244 if (!call_used_regs
[i
])
2245 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], i
);
2248 /* Determine where to put an argument to a function.
2249 Value is zero to push the argument on the stack,
2250 or a hard register in which to store the argument.
2252 MODE is the argument's machine mode.
2253 TYPE is the data type of the argument (as a tree).
2254 This is null for libcalls where that information may
2256 CUM is a variable of type CUMULATIVE_ARGS which gives info about
2257 the preceding args and about the function being called.
2258 NAMED is nonzero if this argument is a named parameter
2259 (otherwise it is an extra parameter matching an ellipsis). */
2260 /* On the EPIPHANY the first MAX_EPIPHANY_PARM_REGS args are normally in
2261 registers and the rest are pushed. */
2263 epiphany_function_arg (cumulative_args_t cum_v
, machine_mode mode
,
2264 const_tree type
, bool named ATTRIBUTE_UNUSED
)
2266 CUMULATIVE_ARGS cum
= *get_cumulative_args (cum_v
);
2268 if (PASS_IN_REG_P (cum
, mode
, type
))
2269 return gen_rtx_REG (mode
, ROUND_ADVANCE_CUM (cum
, mode
, type
));
2273 /* Update the data in CUM to advance over an argument
2274 of mode MODE and data type TYPE.
2275 (TYPE is null for libcalls where that information may not be available.) */
2277 epiphany_function_arg_advance (cumulative_args_t cum_v
, machine_mode mode
,
2278 const_tree type
, bool named ATTRIBUTE_UNUSED
)
2280 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
2282 *cum
= ROUND_ADVANCE_CUM (*cum
, mode
, type
) + ROUND_ADVANCE_ARG (mode
, type
);
2285 /* Nested function support.
2286 An epiphany trampoline looks like this:
2287 mov r16,%low(fnaddr)
2288 movt r16,%high(fnaddr)
2293 #define EPIPHANY_LOW_RTX(X) \
2294 (gen_rtx_IOR (SImode, \
2295 gen_rtx_ASHIFT (SImode, \
2296 gen_rtx_AND (SImode, (X), GEN_INT (0xff)), GEN_INT (5)), \
2297 gen_rtx_ASHIFT (SImode, \
2298 gen_rtx_AND (SImode, (X), GEN_INT (0xff00)), GEN_INT (12))))
2299 #define EPIPHANY_HIGH_RTX(X) \
2300 EPIPHANY_LOW_RTX (gen_rtx_LSHIFTRT (SImode, (X), GEN_INT (16)))
2302 /* Emit RTL insns to initialize the variable parts of a trampoline.
2303 FNADDR is an RTX for the address of the function's pure code.
2304 CXT is an RTX for the static chain value for the function. */
2306 epiphany_trampoline_init (rtx tramp_mem
, tree fndecl
, rtx cxt
)
2308 rtx fnaddr
= XEXP (DECL_RTL (fndecl
), 0);
2309 rtx tramp
= force_reg (Pmode
, XEXP (tramp_mem
, 0));
2311 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, tramp
, 0)),
2312 gen_rtx_IOR (SImode
, GEN_INT (0x4002000b),
2313 EPIPHANY_LOW_RTX (fnaddr
)));
2314 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, tramp
, 4)),
2315 gen_rtx_IOR (SImode
, GEN_INT (0x5002000b),
2316 EPIPHANY_HIGH_RTX (fnaddr
)));
2317 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, tramp
, 8)),
2318 gen_rtx_IOR (SImode
, GEN_INT (0x2002800b),
2319 EPIPHANY_LOW_RTX (cxt
)));
2320 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, tramp
, 12)),
2321 gen_rtx_IOR (SImode
, GEN_INT (0x3002800b),
2322 EPIPHANY_HIGH_RTX (cxt
)));
2323 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, tramp
, 16)),
2324 GEN_INT (0x0802014f));
2328 epiphany_optimize_mode_switching (int entity
)
2330 if (MACHINE_FUNCTION (cfun
)->sw_entities_processed
& (1 << entity
))
2334 case EPIPHANY_MSW_ENTITY_AND
:
2335 case EPIPHANY_MSW_ENTITY_OR
:
2336 case EPIPHANY_MSW_ENTITY_CONFIG
:
2338 case EPIPHANY_MSW_ENTITY_NEAREST
:
2339 case EPIPHANY_MSW_ENTITY_TRUNC
:
2340 return optimize
> 0;
2341 case EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN
:
2342 return MACHINE_FUNCTION (cfun
)->unknown_mode_uses
!= 0;
2343 case EPIPHANY_MSW_ENTITY_ROUND_KNOWN
:
2344 return (MACHINE_FUNCTION (cfun
)->sw_entities_processed
2345 & (1 << EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN
)) != 0;
2346 case EPIPHANY_MSW_ENTITY_FPU_OMNIBUS
:
2347 return optimize
== 0 || current_pass
== pass_mode_switch_use
;
2353 epiphany_mode_priority (int entity
, int priority
)
2355 if (entity
== EPIPHANY_MSW_ENTITY_AND
|| entity
== EPIPHANY_MSW_ENTITY_OR
2356 || entity
== EPIPHANY_MSW_ENTITY_CONFIG
)
2361 case 4: return FP_MODE_ROUND_UNKNOWN
;
2362 case 5: return FP_MODE_NONE
;
2363 default: gcc_unreachable ();
2365 switch ((enum attr_fp_mode
) epiphany_normal_fp_mode
)
2370 case 0: return FP_MODE_INT
;
2371 case 1: return epiphany_normal_fp_rounding
;
2372 case 2: return (epiphany_normal_fp_rounding
== FP_MODE_ROUND_NEAREST
2373 ? FP_MODE_ROUND_TRUNC
: FP_MODE_ROUND_NEAREST
);
2374 case 3: return FP_MODE_CALLER
;
2376 case FP_MODE_ROUND_NEAREST
:
2377 case FP_MODE_CALLER
:
2380 case 0: return FP_MODE_ROUND_NEAREST
;
2381 case 1: return FP_MODE_ROUND_TRUNC
;
2382 case 2: return FP_MODE_INT
;
2383 case 3: return FP_MODE_CALLER
;
2385 case FP_MODE_ROUND_TRUNC
:
2388 case 0: return FP_MODE_ROUND_TRUNC
;
2389 case 1: return FP_MODE_ROUND_NEAREST
;
2390 case 2: return FP_MODE_INT
;
2391 case 3: return FP_MODE_CALLER
;
2393 case FP_MODE_ROUND_UNKNOWN
:
2401 epiphany_mode_needed (int entity
, rtx_insn
*insn
)
2403 enum attr_fp_mode mode
;
2405 if (recog_memoized (insn
) < 0)
2407 if (entity
== EPIPHANY_MSW_ENTITY_AND
2408 || entity
== EPIPHANY_MSW_ENTITY_OR
2409 || entity
== EPIPHANY_MSW_ENTITY_CONFIG
)
2411 return FP_MODE_NONE
;
2413 mode
= get_attr_fp_mode (insn
);
2417 case EPIPHANY_MSW_ENTITY_AND
:
2418 return mode
!= FP_MODE_NONE
&& mode
!= FP_MODE_INT
? 1 : 2;
2419 case EPIPHANY_MSW_ENTITY_OR
:
2420 return mode
== FP_MODE_INT
? 1 : 2;
2421 case EPIPHANY_MSW_ENTITY_CONFIG
:
2422 /* We must know/save config before we set it to something else.
2423 Where we need the original value, we are fine with having it
2424 just unchanged from the function start.
2425 Because of the nature of the mode switching optimization,
2426 a restore will be dominated by a clobber. */
2427 if (mode
!= FP_MODE_NONE
&& mode
!= FP_MODE_CALLER
)
2429 /* A cpecial case are abnormal edges, which are deemed to clobber
2430 the mode as well. We need to pin this effect on a actually
2431 dominating insn, and one where the frame can be accessed, too, in
2432 case the pseudo used to save CONFIG doesn't get a hard register. */
2433 if (CALL_P (insn
) && find_reg_note (insn
, REG_EH_REGION
, NULL_RTX
))
2436 case EPIPHANY_MSW_ENTITY_ROUND_KNOWN
:
2437 if (recog_memoized (insn
) == CODE_FOR_set_fp_mode
)
2438 mode
= (enum attr_fp_mode
) epiphany_mode_after (entity
, mode
, insn
);
2440 case EPIPHANY_MSW_ENTITY_NEAREST
:
2441 case EPIPHANY_MSW_ENTITY_TRUNC
:
2442 if (mode
== FP_MODE_ROUND_UNKNOWN
)
2444 MACHINE_FUNCTION (cfun
)->unknown_mode_uses
++;
2445 return FP_MODE_NONE
;
2448 case EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN
:
2449 if (mode
== FP_MODE_ROUND_NEAREST
|| mode
== FP_MODE_ROUND_TRUNC
)
2450 return FP_MODE_ROUND_UNKNOWN
;
2452 case EPIPHANY_MSW_ENTITY_FPU_OMNIBUS
:
2453 if (mode
== FP_MODE_ROUND_UNKNOWN
)
2454 return epiphany_normal_fp_rounding
;
2462 epiphany_mode_entry_exit (int entity
, bool exit
)
2464 int normal_mode
= epiphany_normal_fp_mode
;
2466 MACHINE_FUNCTION (cfun
)->sw_entities_processed
|= (1 << entity
);
2467 if (epiphany_is_interrupt_p (current_function_decl
))
2468 normal_mode
= FP_MODE_CALLER
;
2471 case EPIPHANY_MSW_ENTITY_AND
:
2473 return normal_mode
!= FP_MODE_INT
? 1 : 2;
2475 case EPIPHANY_MSW_ENTITY_OR
:
2477 return normal_mode
== FP_MODE_INT
? 1 : 2;
2479 case EPIPHANY_MSW_ENTITY_CONFIG
:
2482 return normal_mode
== FP_MODE_CALLER
? 0 : 1;
2483 case EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN
:
2484 if (normal_mode
== FP_MODE_ROUND_NEAREST
2485 || normal_mode
== FP_MODE_ROUND_TRUNC
)
2486 return FP_MODE_ROUND_UNKNOWN
;
2488 case EPIPHANY_MSW_ENTITY_NEAREST
:
2489 case EPIPHANY_MSW_ENTITY_TRUNC
:
2490 case EPIPHANY_MSW_ENTITY_ROUND_KNOWN
:
2491 case EPIPHANY_MSW_ENTITY_FPU_OMNIBUS
:
2499 epiphany_mode_after (int entity
, int last_mode
, rtx_insn
*insn
)
2501 /* We have too few call-saved registers to hope to keep the masks across
2503 if (entity
== EPIPHANY_MSW_ENTITY_AND
|| entity
== EPIPHANY_MSW_ENTITY_OR
)
2509 /* If there is an abnormal edge, we don't want the config register to
2510 be 'saved' again at the destination.
2511 The frame pointer adjustment is inside a PARALLEL because of the
2513 if (entity
== EPIPHANY_MSW_ENTITY_CONFIG
&& NONJUMP_INSN_P (insn
)
2514 && GET_CODE (PATTERN (insn
)) == PARALLEL
2515 && GET_CODE (XVECEXP (PATTERN (insn
), 0, 0)) == SET
2516 && SET_DEST (XVECEXP (PATTERN (insn
), 0, 0)) == frame_pointer_rtx
)
2518 gcc_assert (cfun
->has_nonlocal_label
);
2521 if (recog_memoized (insn
) < 0)
2523 if (get_attr_fp_mode (insn
) == FP_MODE_ROUND_UNKNOWN
2524 && last_mode
!= FP_MODE_ROUND_NEAREST
&& last_mode
!= FP_MODE_ROUND_TRUNC
)
2526 if (entity
== EPIPHANY_MSW_ENTITY_NEAREST
)
2527 return FP_MODE_ROUND_NEAREST
;
2528 if (entity
== EPIPHANY_MSW_ENTITY_TRUNC
)
2529 return FP_MODE_ROUND_TRUNC
;
2531 if (recog_memoized (insn
) == CODE_FOR_set_fp_mode
)
2533 rtx src
= SET_SRC (XVECEXP (PATTERN (insn
), 0, 0));
2537 return FP_MODE_CALLER
;
2538 fp_mode
= INTVAL (XVECEXP (XEXP (src
, 0), 0, 0));
2539 if (entity
== EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN
2540 && (fp_mode
== FP_MODE_ROUND_NEAREST
2541 || fp_mode
== EPIPHANY_MSW_ENTITY_TRUNC
))
2542 return FP_MODE_ROUND_UNKNOWN
;
2549 epiphany_mode_entry (int entity
)
2551 return epiphany_mode_entry_exit (entity
, false);
2555 epiphany_mode_exit (int entity
)
2557 return epiphany_mode_entry_exit (entity
, true);
2561 emit_set_fp_mode (int entity
, int mode
, int prev_mode ATTRIBUTE_UNUSED
,
2562 HARD_REG_SET regs_live ATTRIBUTE_UNUSED
)
2564 rtx save_cc
, cc_reg
, mask
, src
, src2
;
2565 enum attr_fp_mode fp_mode
;
2567 if (!MACHINE_FUNCTION (cfun
)->and_mask
)
2569 MACHINE_FUNCTION (cfun
)->and_mask
= gen_reg_rtx (SImode
);
2570 MACHINE_FUNCTION (cfun
)->or_mask
= gen_reg_rtx (SImode
);
2572 if (entity
== EPIPHANY_MSW_ENTITY_AND
)
2574 gcc_assert (mode
>= 0 && mode
<= 2);
2576 emit_move_insn (MACHINE_FUNCTION (cfun
)->and_mask
,
2577 gen_int_mode (0xfff1fffe, SImode
));
2580 else if (entity
== EPIPHANY_MSW_ENTITY_OR
)
2582 gcc_assert (mode
>= 0 && mode
<= 2);
2584 emit_move_insn (MACHINE_FUNCTION (cfun
)->or_mask
, GEN_INT(0x00080000));
2587 else if (entity
== EPIPHANY_MSW_ENTITY_CONFIG
)
2589 /* Mode switching optimization is done after emit_initial_value_sets,
2590 so we have to take care of CONFIG_REGNUM here. */
2591 gcc_assert (mode
>= 0 && mode
<= 2);
2592 rtx save
= get_hard_reg_initial_val (SImode
, CONFIG_REGNUM
);
2594 emit_insn (gen_save_config (save
));
2597 fp_mode
= (enum attr_fp_mode
) mode
;
2602 case FP_MODE_CALLER
:
2603 /* The EPIPHANY_MSW_ENTITY_CONFIG processing must come later
2604 so that the config save gets inserted before the first use. */
2605 gcc_assert (entity
> EPIPHANY_MSW_ENTITY_CONFIG
);
2606 src
= get_hard_reg_initial_val (SImode
, CONFIG_REGNUM
);
2607 mask
= MACHINE_FUNCTION (cfun
)->and_mask
;
2609 case FP_MODE_ROUND_UNKNOWN
:
2610 MACHINE_FUNCTION (cfun
)->unknown_mode_sets
++;
2611 mask
= MACHINE_FUNCTION (cfun
)->and_mask
;
2613 case FP_MODE_ROUND_NEAREST
:
2614 if (entity
== EPIPHANY_MSW_ENTITY_TRUNC
)
2616 mask
= MACHINE_FUNCTION (cfun
)->and_mask
;
2618 case FP_MODE_ROUND_TRUNC
:
2619 if (entity
== EPIPHANY_MSW_ENTITY_NEAREST
)
2621 mask
= MACHINE_FUNCTION (cfun
)->and_mask
;
2624 mask
= MACHINE_FUNCTION (cfun
)->or_mask
;
2630 save_cc
= gen_reg_rtx (CCmode
);
2631 cc_reg
= gen_rtx_REG (CCmode
, CC_REGNUM
);
2632 emit_move_insn (save_cc
, cc_reg
);
2633 mask
= force_reg (SImode
, mask
);
2636 rtvec v
= gen_rtvec (1, GEN_INT (fp_mode
));
2638 src
= gen_rtx_CONST (SImode
, gen_rtx_UNSPEC (SImode
, v
, UNSPEC_FP_MODE
));
2640 if (entity
== EPIPHANY_MSW_ENTITY_ROUND_KNOWN
2641 || entity
== EPIPHANY_MSW_ENTITY_FPU_OMNIBUS
)
2642 src2
= copy_rtx (src
);
2645 rtvec v
= gen_rtvec (1, GEN_INT (FP_MODE_ROUND_UNKNOWN
));
2647 src2
= gen_rtx_CONST (SImode
, gen_rtx_UNSPEC (SImode
, v
, UNSPEC_FP_MODE
));
2649 emit_insn (gen_set_fp_mode (src
, src2
, mask
));
2650 emit_move_insn (cc_reg
, save_cc
);
2654 epiphany_expand_set_fp_mode (rtx
*operands
)
2656 rtx ctrl
= gen_rtx_REG (SImode
, CONFIG_REGNUM
);
2657 rtx src
= operands
[0];
2658 rtx mask_reg
= operands
[2];
2659 rtx scratch
= operands
[3];
2660 enum attr_fp_mode fp_mode
;
2663 gcc_assert (rtx_equal_p (src
, operands
[1])
2664 /* Sometimes reload gets silly and reloads the same pseudo
2665 into different registers. */
2666 || (REG_P (src
) && REG_P (operands
[1])));
2668 if (!epiphany_uninterruptible_p (current_function_decl
))
2669 emit_insn (gen_gid ());
2670 emit_move_insn (scratch
, ctrl
);
2672 if (GET_CODE (src
) == REG
)
2674 /* FP_MODE_CALLER */
2675 emit_insn (gen_xorsi3 (scratch
, scratch
, src
));
2676 emit_insn (gen_andsi3 (scratch
, scratch
, mask_reg
));
2677 emit_insn (gen_xorsi3 (scratch
, scratch
, src
));
2681 gcc_assert (GET_CODE (src
) == CONST
);
2682 src
= XEXP (src
, 0);
2683 fp_mode
= (enum attr_fp_mode
) INTVAL (XVECEXP (src
, 0, 0));
2686 case FP_MODE_ROUND_NEAREST
:
2687 emit_insn (gen_andsi3 (scratch
, scratch
, mask_reg
));
2689 case FP_MODE_ROUND_TRUNC
:
2690 emit_insn (gen_andsi3 (scratch
, scratch
, mask_reg
));
2691 emit_insn (gen_add2_insn (scratch
, const1_rtx
));
2694 emit_insn (gen_iorsi3 (scratch
, scratch
, mask_reg
));
2696 case FP_MODE_CALLER
:
2697 case FP_MODE_ROUND_UNKNOWN
:
2702 emit_move_insn (ctrl
, scratch
);
2703 if (!epiphany_uninterruptible_p (current_function_decl
))
2704 emit_insn (gen_gie ());
2708 epiphany_insert_mode_switch_use (rtx_insn
*insn
,
2709 int entity ATTRIBUTE_UNUSED
,
2710 int mode ATTRIBUTE_UNUSED
)
2712 rtx pat
= PATTERN (insn
);
2715 rtx near
= gen_rtx_REG (SImode
, FP_NEAREST_REGNUM
);
2716 rtx trunc
= gen_rtx_REG (SImode
, FP_TRUNCATE_REGNUM
);
2718 if (entity
!= EPIPHANY_MSW_ENTITY_FPU_OMNIBUS
)
2720 switch ((enum attr_fp_mode
) get_attr_fp_mode (insn
))
2722 case FP_MODE_ROUND_NEAREST
:
2723 near
= gen_rtx_USE (VOIDmode
, near
);
2724 trunc
= gen_rtx_CLOBBER (VOIDmode
, trunc
);
2726 case FP_MODE_ROUND_TRUNC
:
2727 near
= gen_rtx_CLOBBER (VOIDmode
, near
);
2728 trunc
= gen_rtx_USE (VOIDmode
, trunc
);
2730 case FP_MODE_ROUND_UNKNOWN
:
2731 near
= gen_rtx_USE (VOIDmode
, gen_rtx_REG (SImode
, FP_ANYFP_REGNUM
));
2732 trunc
= copy_rtx (near
);
2735 case FP_MODE_CALLER
:
2736 near
= gen_rtx_USE (VOIDmode
, near
);
2737 trunc
= gen_rtx_USE (VOIDmode
, trunc
);
2742 gcc_assert (GET_CODE (pat
) == PARALLEL
);
2743 len
= XVECLEN (pat
, 0);
2744 v
= rtvec_alloc (len
+ 2);
2745 for (i
= 0; i
< len
; i
++)
2746 RTVEC_ELT (v
, i
) = XVECEXP (pat
, 0, i
);
2747 RTVEC_ELT (v
, len
) = near
;
2748 RTVEC_ELT (v
, len
+ 1) = trunc
;
2749 pat
= gen_rtx_PARALLEL (VOIDmode
, v
);
2750 PATTERN (insn
) = pat
;
2751 MACHINE_FUNCTION (cfun
)->control_use_inserted
= true;
2755 epiphany_epilogue_uses (int regno
)
2757 if (regno
== GPR_LR
)
2759 if (reload_completed
&& epiphany_is_interrupt_p (current_function_decl
))
2761 if (fixed_regs
[regno
]
2762 && regno
!= STATUS_REGNUM
&& regno
!= IRET_REGNUM
2763 && regno
!= FP_NEAREST_REGNUM
&& regno
!= FP_TRUNCATE_REGNUM
)
2767 if (regno
== FP_NEAREST_REGNUM
2768 && epiphany_normal_fp_mode
!= FP_MODE_ROUND_TRUNC
)
2770 if (regno
== FP_TRUNCATE_REGNUM
2771 && epiphany_normal_fp_mode
!= FP_MODE_ROUND_NEAREST
)
2777 epiphany_min_divisions_for_recip_mul (machine_mode mode
)
2779 if (flag_reciprocal_math
&& mode
== SFmode
)
2780 /* We'll expand into a multiply-by-reciprocal anyway, so we might a well do
2781 it already at the tree level and expose it to further optimizations. */
2783 return default_min_divisions_for_recip_mul (mode
);
2787 epiphany_preferred_simd_mode (machine_mode mode ATTRIBUTE_UNUSED
)
2789 return TARGET_VECT_DOUBLE
? DImode
: SImode
;
2793 epiphany_vector_mode_supported_p (machine_mode mode
)
2795 if (mode
== V2SFmode
)
2797 if (GET_MODE_CLASS (mode
) == MODE_VECTOR_INT
2798 && (GET_MODE_SIZE (mode
) == 4 || GET_MODE_SIZE (mode
) == 8))
2804 epiphany_vector_alignment_reachable (const_tree type
, bool is_packed
)
2806 /* Vectors which aren't in packed structures will not be less aligned than
2807 the natural alignment of their element type, so this is safe. */
2808 if (TYPE_ALIGN_UNIT (type
) == 4)
2811 return default_builtin_vector_alignment_reachable (type
, is_packed
);
2815 epiphany_support_vector_misalignment (machine_mode mode
, const_tree type
,
2816 int misalignment
, bool is_packed
)
2818 if (GET_MODE_SIZE (mode
) == 8 && misalignment
% 4 == 0)
2820 return default_builtin_support_vector_misalignment (mode
, type
, misalignment
,
2824 /* STRUCTURE_SIZE_BOUNDARY seems a bit crude in how it enlarges small
2825 structs. Make structs double-word-aligned it they are a double word or
2826 (potentially) larger; failing that, do the same for a size of 32 bits. */
2828 epiphany_special_round_type_align (tree type
, unsigned computed
,
2831 unsigned align
= MAX (computed
, specified
);
2833 HOST_WIDE_INT total
, max
;
2834 unsigned try_align
= FASTEST_ALIGNMENT
;
2836 if (maximum_field_alignment
&& try_align
> maximum_field_alignment
)
2837 try_align
= maximum_field_alignment
;
2838 if (align
>= try_align
)
2840 for (max
= 0, field
= TYPE_FIELDS (type
); field
; field
= DECL_CHAIN (field
))
2844 if (TREE_CODE (field
) != FIELD_DECL
2845 || TREE_TYPE (field
) == error_mark_node
)
2847 offset
= bit_position (field
);
2848 size
= DECL_SIZE (field
);
2849 if (!tree_fits_uhwi_p (offset
) || !tree_fits_uhwi_p (size
)
2850 || tree_to_uhwi (offset
) >= try_align
2851 || tree_to_uhwi (size
) >= try_align
)
2853 total
= tree_to_uhwi (offset
) + tree_to_uhwi (size
);
2857 if (max
>= (HOST_WIDE_INT
) try_align
)
2859 else if (try_align
> 32 && max
>= 32)
2860 align
= max
> 32 ? 64 : 32;
2864 /* Upping the alignment of arrays in structs is not only a performance
2865 enhancement, it also helps preserve assumptions about how
2866 arrays-at-the-end-of-structs work, like for struct gcov_fn_info in
2869 epiphany_adjust_field_align (tree field
, unsigned computed
)
2872 && TREE_CODE (TREE_TYPE (field
)) == ARRAY_TYPE
)
2874 tree elmsz
= TYPE_SIZE (TREE_TYPE (TREE_TYPE (field
)));
2876 if (!tree_fits_uhwi_p (elmsz
) || tree_to_uhwi (elmsz
) >= 32)
2882 /* Output code to add DELTA to the first argument, and then jump
2883 to FUNCTION. Used for C++ multiple inheritance. */
2885 epiphany_output_mi_thunk (FILE *file
, tree thunk ATTRIBUTE_UNUSED
,
2886 HOST_WIDE_INT delta
,
2887 HOST_WIDE_INT vcall_offset
,
2891 = aggregate_value_p (TREE_TYPE (TREE_TYPE (function
)), function
) ? 1 : 0;
2892 const char *this_name
= reg_names
[this_regno
];
2895 /* We use IP and R16 as a scratch registers. */
2896 gcc_assert (call_used_regs
[GPR_IP
]);
2897 gcc_assert (call_used_regs
[GPR_16
]);
2899 /* Add DELTA. When possible use a plain add, otherwise load it into
2900 a register first. */
2903 else if (SIMM11 (delta
))
2904 asm_fprintf (file
, "\tadd\t%s,%s,%d\n", this_name
, this_name
, (int) delta
);
2905 else if (delta
< 0 && delta
>= -0xffff)
2907 asm_fprintf (file
, "\tmov\tip,%d\n", (int) -delta
);
2908 asm_fprintf (file
, "\tsub\t%s,%s,ip\n", this_name
, this_name
);
2912 asm_fprintf (file
, "\tmov\tip,%%low(%ld)\n", (long) delta
);
2913 if (delta
& ~0xffff)
2914 asm_fprintf (file
, "\tmovt\tip,%%high(%ld)\n", (long) delta
);
2915 asm_fprintf (file
, "\tadd\t%s,%s,ip\n", this_name
, this_name
);
2918 /* If needed, add *(*THIS + VCALL_OFFSET) to THIS. */
2919 if (vcall_offset
!= 0)
2921 /* ldr ip,[this] --> temp = *this
2922 ldr ip,[ip,vcall_offset] > temp = *(*this + vcall_offset)
2923 add this,this,ip --> this+ = *(*this + vcall_offset) */
2924 asm_fprintf (file
, "\tldr\tip, [%s]\n", this_name
);
2925 if (vcall_offset
< -0x7ff * 4 || vcall_offset
> 0x7ff * 4
2926 || (vcall_offset
& 3) != 0)
2928 asm_fprintf (file
, "\tmov\tr16, %%low(%ld)\n", (long) vcall_offset
);
2929 asm_fprintf (file
, "\tmovt\tr16, %%high(%ld)\n", (long) vcall_offset
);
2930 asm_fprintf (file
, "\tldr\tip, [ip,r16]\n");
2933 asm_fprintf (file
, "\tldr\tip, [ip,%d]\n", (int) vcall_offset
/ 4);
2934 asm_fprintf (file
, "\tadd\t%s, %s, ip\n", this_name
, this_name
);
2937 fname
= XSTR (XEXP (DECL_RTL (function
), 0), 0);
2938 if (epiphany_is_long_call_p (XEXP (DECL_RTL (function
), 0)))
2940 fputs ("\tmov\tip,%low(", file
);
2941 assemble_name (file
, fname
);
2942 fputs (")\n\tmovt\tip,%high(", file
);
2943 assemble_name (file
, fname
);
2944 fputs (")\n\tjr ip\n", file
);
2948 fputs ("\tb\t", file
);
2949 assemble_name (file
, fname
);
2955 epiphany_start_function (FILE *file
, const char *name
, tree decl
)
2957 /* If the function doesn't fit into the on-chip memory, it will have a
2958 section attribute - or lack of it - that denotes it goes somewhere else.
2959 But the architecture spec says that an interrupt vector still has to
2960 point to on-chip memory. So we must place a jump there to get to the
2961 actual function implementation. The forwarder_section attribute
2962 specifies the section where this jump goes.
2963 This mechanism can also be useful to have a shortcall destination for
2964 a function that is actually placed much farther away. */
2965 tree attrs
, int_attr
, int_names
, int_name
, forwarder_attr
;
2967 attrs
= DECL_ATTRIBUTES (decl
);
2968 int_attr
= lookup_attribute ("interrupt", attrs
);
2970 for (int_names
= TREE_VALUE (int_attr
); int_names
;
2971 int_names
= TREE_CHAIN (int_names
))
2975 int_name
= TREE_VALUE (int_names
);
2976 sprintf (buf
, "ivt_entry_%.80s", TREE_STRING_POINTER (int_name
));
2977 switch_to_section (get_section (buf
, SECTION_CODE
, decl
));
2978 fputs ("\tb\t", file
);
2979 assemble_name (file
, name
);
2982 forwarder_attr
= lookup_attribute ("forwarder_section", attrs
);
2985 const char *prefix
= "__forwarder_dst_";
2986 char *dst_name
= (char *) alloca (strlen (prefix
) + strlen (name
) + 1);
2988 strcpy (dst_name
, prefix
);
2989 strcat (dst_name
, name
);
2990 forwarder_attr
= TREE_VALUE (TREE_VALUE (forwarder_attr
));
2991 switch_to_section (get_section (TREE_STRING_POINTER (forwarder_attr
),
2992 SECTION_CODE
, decl
));
2993 ASM_OUTPUT_FUNCTION_LABEL (file
, name
, decl
);
2994 if (epiphany_is_long_call_p (XEXP (DECL_RTL (decl
), 0)))
2999 fputs ("\tstrd r0,[sp,-1]\n", file
);
3002 gcc_assert (call_used_regs
[tmp
]);
3003 fprintf (file
, "\tmov r%d,%%low(", tmp
);
3004 assemble_name (file
, dst_name
);
3005 fprintf (file
, ")\n"
3006 "\tmovt r%d,%%high(", tmp
);
3007 assemble_name (file
, dst_name
);
3008 fprintf (file
, ")\n"
3013 fputs ("\tb\t", file
);
3014 assemble_name (file
, dst_name
);
3019 switch_to_section (function_section (decl
));
3020 ASM_OUTPUT_FUNCTION_LABEL (file
, name
, decl
);
3023 struct gcc_target targetm
= TARGET_INITIALIZER
;