1 /* Subroutines used for code generation on the EPIPHANY cpu.
2 Copyright (C) 1994-2017 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"
31 #include "stringpool.h"
36 #include "diagnostic-core.h"
38 #include "stor-layout.h"
42 #include "insn-attr.h"
45 #include "tm-constrs.h"
46 #include "tree-pass.h" /* for current_pass */
48 #include "pass_manager.h"
51 /* Which cpu we're compiling for. */
52 int epiphany_cpu_type
;
54 /* Name of mangle string to add to symbols to separate code compiled for each
56 const char *epiphany_mangle_cpu
;
58 /* Array of valid operand punctuation characters. */
59 char epiphany_punct_chars
[256];
61 /* The rounding mode that we generally use for floating point. */
62 int epiphany_normal_fp_rounding
;
64 /* The pass instance, for use in epiphany_optimize_mode_switching. */
65 static opt_pass
*pass_mode_switch_use
;
67 static void epiphany_init_reg_tables (void);
68 static int get_epiphany_condition_code (rtx
);
69 static tree
epiphany_handle_interrupt_attribute (tree
*, tree
, tree
, int, bool *);
70 static tree
epiphany_handle_forwarder_attribute (tree
*, tree
, tree
, int,
72 static bool epiphany_pass_by_reference (cumulative_args_t
, machine_mode
,
74 static rtx_insn
*frame_insn (rtx
);
76 /* defines for the initialization of the GCC target structure. */
77 #define TARGET_ATTRIBUTE_TABLE epiphany_attribute_table
79 #define TARGET_PRINT_OPERAND epiphany_print_operand
80 #define TARGET_PRINT_OPERAND_ADDRESS epiphany_print_operand_address
82 #define TARGET_RTX_COSTS epiphany_rtx_costs
83 #define TARGET_ADDRESS_COST epiphany_address_cost
84 #define TARGET_MEMORY_MOVE_COST epiphany_memory_move_cost
86 #define TARGET_PROMOTE_FUNCTION_MODE epiphany_promote_function_mode
87 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
89 #define TARGET_RETURN_IN_MEMORY epiphany_return_in_memory
90 #define TARGET_PASS_BY_REFERENCE epiphany_pass_by_reference
91 #define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_mode_tree_bool_true
92 #define TARGET_FUNCTION_VALUE epiphany_function_value
93 #define TARGET_LIBCALL_VALUE epiphany_libcall_value
94 #define TARGET_FUNCTION_VALUE_REGNO_P epiphany_function_value_regno_p
96 #define TARGET_SETUP_INCOMING_VARARGS epiphany_setup_incoming_varargs
98 /* Using the simplistic varags handling forces us to do partial reg/stack
99 argument passing for types with larger size (> 4 bytes) than alignment. */
100 #define TARGET_ARG_PARTIAL_BYTES epiphany_arg_partial_bytes
102 #define TARGET_FUNCTION_OK_FOR_SIBCALL epiphany_function_ok_for_sibcall
104 #define TARGET_SCHED_ISSUE_RATE epiphany_issue_rate
105 #define TARGET_SCHED_ADJUST_COST epiphany_adjust_cost
107 #define TARGET_LRA_P hook_bool_void_false
109 #define TARGET_LEGITIMATE_ADDRESS_P epiphany_legitimate_address_p
111 #define TARGET_SECONDARY_RELOAD epiphany_secondary_reload
113 #define TARGET_OPTION_OVERRIDE epiphany_override_options
115 #define TARGET_CONDITIONAL_REGISTER_USAGE epiphany_conditional_register_usage
117 #define TARGET_FUNCTION_ARG epiphany_function_arg
119 #define TARGET_FUNCTION_ARG_ADVANCE epiphany_function_arg_advance
121 #define TARGET_FUNCTION_ARG_BOUNDARY epiphany_function_arg_boundary
123 #define TARGET_TRAMPOLINE_INIT epiphany_trampoline_init
125 /* Nonzero if the constant rtx value is a legitimate general operand.
126 We can handle any 32- or 64-bit constant. */
127 #define TARGET_LEGITIMATE_CONSTANT_P hook_bool_mode_rtx_true
129 #define TARGET_MIN_DIVISIONS_FOR_RECIP_MUL \
130 epiphany_min_divisions_for_recip_mul
132 #define TARGET_VECTORIZE_PREFERRED_SIMD_MODE epiphany_preferred_simd_mode
134 #define TARGET_VECTOR_MODE_SUPPORTED_P epiphany_vector_mode_supported_p
136 #define TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE \
137 epiphany_vector_alignment_reachable
139 #define TARGET_VECTORIZE_SUPPORT_VECTOR_MISALIGNMENT \
140 epiphany_support_vector_misalignment
142 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK \
143 hook_bool_const_tree_hwi_hwi_const_tree_true
144 #define TARGET_ASM_OUTPUT_MI_THUNK epiphany_output_mi_thunk
146 /* ??? we can use larger offsets for wider-mode sized accesses, but there
147 is no concept of anchors being dependent on the modes that they are used
148 for, so we can only use an offset range that would suit all modes. */
149 #define TARGET_MAX_ANCHOR_OFFSET (optimize_size ? 31 : 2047)
150 /* We further restrict the minimum to be a multiple of eight. */
151 #define TARGET_MIN_ANCHOR_OFFSET (optimize_size ? 0 : -2040)
153 /* Mode switching hooks. */
155 #define TARGET_MODE_EMIT emit_set_fp_mode
157 #define TARGET_MODE_NEEDED epiphany_mode_needed
159 #define TARGET_MODE_PRIORITY epiphany_mode_priority
161 #define TARGET_MODE_ENTRY epiphany_mode_entry
163 #define TARGET_MODE_EXIT epiphany_mode_exit
165 #define TARGET_MODE_AFTER epiphany_mode_after
167 #include "target-def.h"
169 #undef TARGET_ASM_ALIGNED_HI_OP
170 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
171 #undef TARGET_ASM_ALIGNED_SI_OP
172 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
175 epiphany_is_interrupt_p (tree decl
)
179 attrs
= DECL_ATTRIBUTES (decl
);
180 if (lookup_attribute ("interrupt", attrs
))
186 /* Called from epiphany_override_options.
187 We use this to initialize various things. */
192 /* N.B. this pass must not run before the first optimize_mode_switching
193 pass because of the side offect of epiphany_mode_needed on
194 MACHINE_FUNCTION(cfun)->unknown_mode_uses. But it must run before
195 pass_resolve_sw_modes. */
196 pass_mode_switch_use
= make_pass_mode_switch_use (g
);
197 struct register_pass_info insert_use_info
198 = { pass_mode_switch_use
, "mode_sw",
199 1, PASS_POS_INSERT_AFTER
202 = g
->get_passes()->get_pass_mode_switching ()->clone ();
203 struct register_pass_info mode_sw2_info
204 = { mode_sw2
, "mode_sw",
205 1, PASS_POS_INSERT_AFTER
207 opt_pass
*mode_sw3
= make_pass_resolve_sw_modes (g
);
208 struct register_pass_info mode_sw3_info
209 = { mode_sw3
, "mode_sw",
210 1, PASS_POS_INSERT_AFTER
213 = g
->get_passes()->get_pass_split_all_insns ()->clone ();
214 struct register_pass_info mode_sw4_info
215 = { mode_sw4
, "mode_sw",
216 1, PASS_POS_INSERT_AFTER
218 static const int num_modes
[] = NUM_MODES_FOR_MODE_SWITCHING
;
219 #define N_ENTITIES ARRAY_SIZE (num_modes)
221 epiphany_init_reg_tables ();
223 /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P. */
224 memset (epiphany_punct_chars
, 0, sizeof (epiphany_punct_chars
));
225 epiphany_punct_chars
['-'] = 1;
227 epiphany_normal_fp_rounding
228 = (epiphany_normal_fp_mode
== FP_MODE_ROUND_TRUNC
229 ? FP_MODE_ROUND_TRUNC
: FP_MODE_ROUND_NEAREST
);
230 register_pass (&mode_sw4_info
);
231 register_pass (&mode_sw2_info
);
232 register_pass (&mode_sw3_info
);
233 register_pass (&insert_use_info
);
234 register_pass (&mode_sw2_info
);
235 /* Verify that NUM_MODES_FOR_MODE_SWITCHING has one value per entity. */
236 gcc_assert (N_ENTITIES
== EPIPHANY_MSW_ENTITY_NUM
);
238 #if 1 /* As long as peep2_rescan is not implemented,
239 (see http://gcc.gnu.org/ml/gcc-patches/2011-10/msg02819.html,)
240 we need a second peephole2 pass to get reasonable code. */
242 opt_pass
*extra_peephole2
243 = g
->get_passes ()->get_pass_peephole2 ()->clone ();
244 struct register_pass_info peep2_2_info
245 = { extra_peephole2
, "peephole2",
246 1, PASS_POS_INSERT_AFTER
249 register_pass (&peep2_2_info
);
254 /* The condition codes of the EPIPHANY, and the inverse function. */
255 static const char *const epiphany_condition_codes
[] =
256 { /* 0 1 2 3 4 5 6 7 8 9 */
257 "eq", "ne", "ltu", "gteu", "gt", "lte", "gte", "lt", "gtu", "lteu",
259 "beq","bne","blt", "blte",
262 #define EPIPHANY_INVERSE_CONDITION_CODE(X) ((X) ^ 1)
264 /* Returns the index of the EPIPHANY condition code string in
265 `epiphany_condition_codes'. COMPARISON should be an rtx like
266 `(eq (...) (...))'. */
269 get_epiphany_condition_code (rtx comparison
)
271 switch (GET_MODE (XEXP (comparison
, 0)))
274 switch (GET_CODE (comparison
))
287 default : gcc_unreachable ();
290 switch (GET_CODE (comparison
))
294 default: gcc_unreachable ();
297 switch (GET_CODE (comparison
))
301 default: gcc_unreachable ();
304 switch (GET_CODE (comparison
))
308 default: gcc_unreachable ();
311 switch (GET_CODE (comparison
))
317 default: gcc_unreachable ();
320 switch (GET_CODE (comparison
))
324 default: gcc_unreachable ();
326 case E_CC_FP_GTEmode
:
327 switch (GET_CODE (comparison
))
333 case UNLE
: return 5;
334 case UNLT
: return 7;
335 default: gcc_unreachable ();
337 case E_CC_FP_ORDmode
:
338 switch (GET_CODE (comparison
))
340 case ORDERED
: return 9;
341 case UNORDERED
: return 8;
342 default: gcc_unreachable ();
344 case E_CC_FP_UNEQmode
:
345 switch (GET_CODE (comparison
))
349 default: gcc_unreachable ();
351 default: gcc_unreachable ();
358 /* Return 1 if hard register REGNO can hold a value of machine_mode MODE. */
360 hard_regno_mode_ok (int regno
, machine_mode mode
)
362 if (GET_MODE_SIZE (mode
) > UNITS_PER_WORD
)
363 return (regno
& 1) == 0 && GPR_P (regno
);
368 /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
369 return the mode to be used for the comparison. */
372 epiphany_select_cc_mode (enum rtx_code op
,
373 rtx x ATTRIBUTE_UNUSED
,
374 rtx y ATTRIBUTE_UNUSED
)
376 if (GET_MODE_CLASS (GET_MODE (x
)) == MODE_FLOAT
)
378 if (TARGET_SOFT_CMPSF
379 || op
== ORDERED
|| op
== UNORDERED
)
381 if (op
== EQ
|| op
== NE
)
383 if (op
== ORDERED
|| op
== UNORDERED
)
384 return CC_FP_ORDmode
;
385 if (op
== UNEQ
|| op
== LTGT
)
386 return CC_FP_UNEQmode
;
387 return CC_FP_GTEmode
;
391 /* recognize combiner pattern ashlsi_btst:
393 (set (reg:N_NE 65 cc1)
394 (compare:N_NE (zero_extract:SI (reg/v:SI 75 [ a ])
397 (const_int 0 [0x0])))
398 (clobber (scratch:SI)) */
399 else if ((op
== EQ
|| op
== NE
)
400 && GET_CODE (x
) == ZERO_EXTRACT
401 && XEXP (x
, 1) == const1_rtx
402 && CONST_INT_P (XEXP (x
, 2)))
404 else if ((op
== GEU
|| op
== LTU
) && GET_CODE (x
) == PLUS
)
406 else if ((op
== LEU
|| op
== GTU
) && GET_CODE (x
) == MINUS
)
412 enum reg_class epiphany_regno_reg_class
[FIRST_PSEUDO_REGISTER
];
415 epiphany_init_reg_tables (void)
419 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
422 epiphany_regno_reg_class
[i
] = LR_REGS
;
423 else if (i
<= 7 && TARGET_PREFER_SHORT_INSN_REGS
)
424 epiphany_regno_reg_class
[i
] = SHORT_INSN_REGS
;
425 else if (call_used_regs
[i
]
426 && TEST_HARD_REG_BIT (reg_class_contents
[GENERAL_REGS
], i
))
427 epiphany_regno_reg_class
[i
] = SIBCALL_REGS
;
428 else if (i
>= CORE_CONTROL_FIRST
&& i
<= CORE_CONTROL_LAST
)
429 epiphany_regno_reg_class
[i
] = CORE_CONTROL_REGS
;
430 else if (i
< (GPR_LAST
+1)
431 || i
== ARG_POINTER_REGNUM
|| i
== FRAME_POINTER_REGNUM
)
432 epiphany_regno_reg_class
[i
] = GENERAL_REGS
;
433 else if (i
== CC_REGNUM
)
434 epiphany_regno_reg_class
[i
] = NO_REGS
/* CC_REG: must be NO_REGS */;
436 epiphany_regno_reg_class
[i
] = NO_REGS
;
440 /* EPIPHANY specific attribute support.
442 The EPIPHANY has these attributes:
443 interrupt - for interrupt functions.
444 short_call - the function is assumed to be reachable with the b / bl
446 long_call - the function address is loaded into a register before use.
447 disinterrupt - functions which mask interrupts throughout.
448 They unmask them while calling an interruptible
451 static const struct attribute_spec epiphany_attribute_table
[] =
453 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
454 { "interrupt", 0, 9, true, false, false, epiphany_handle_interrupt_attribute
, true },
455 { "forwarder_section", 1, 1, true, false, false, epiphany_handle_forwarder_attribute
, false },
456 { "long_call", 0, 0, false, true, true, NULL
, false },
457 { "short_call", 0, 0, false, true, true, NULL
, false },
458 { "disinterrupt", 0, 0, false, true, true, NULL
, true },
459 { NULL
, 0, 0, false, false, false, NULL
, false }
462 /* Handle an "interrupt" attribute; arguments as in
463 struct attribute_spec.handler. */
465 epiphany_handle_interrupt_attribute (tree
*node
, tree name
, tree args
,
466 int flags ATTRIBUTE_UNUSED
,
473 gcc_assert (DECL_P (*node
));
474 tree t
= TREE_TYPE (*node
);
475 if (TREE_CODE (t
) != FUNCTION_TYPE
)
476 warning (OPT_Wattributes
, "%qE attribute only applies to functions",
478 /* Argument handling and the stack layout for interrupt handlers
479 don't mix. It makes no sense in the first place, so emit an
481 else if (TYPE_ARG_TYPES (t
)
482 && TREE_VALUE (TYPE_ARG_TYPES (t
)) != void_type_node
)
483 error_at (DECL_SOURCE_LOCATION (*node
),
484 "interrupt handlers cannot have arguments");
488 value
= TREE_VALUE (args
);
490 if (TREE_CODE (value
) != STRING_CST
)
492 warning (OPT_Wattributes
,
493 "argument of %qE attribute is not a string constant", name
);
494 *no_add_attrs
= true;
496 else if (strcmp (TREE_STRING_POINTER (value
), "reset")
497 && strcmp (TREE_STRING_POINTER (value
), "software_exception")
498 && strcmp (TREE_STRING_POINTER (value
), "page_miss")
499 && strcmp (TREE_STRING_POINTER (value
), "timer0")
500 && strcmp (TREE_STRING_POINTER (value
), "timer1")
501 && strcmp (TREE_STRING_POINTER (value
), "message")
502 && strcmp (TREE_STRING_POINTER (value
), "dma0")
503 && strcmp (TREE_STRING_POINTER (value
), "dma1")
504 && strcmp (TREE_STRING_POINTER (value
), "wand")
505 && strcmp (TREE_STRING_POINTER (value
), "swi"))
507 warning (OPT_Wattributes
,
508 "argument of %qE attribute is not \"reset\", \"software_exception\", \"page_miss\", \"timer0\", \"timer1\", \"message\", \"dma0\", \"dma1\", \"wand\" or \"swi\"",
510 *no_add_attrs
= true;
514 return epiphany_handle_interrupt_attribute (node
, name
, TREE_CHAIN (args
),
515 flags
, no_add_attrs
);
518 /* Handle a "forwarder_section" attribute; arguments as in
519 struct attribute_spec.handler. */
521 epiphany_handle_forwarder_attribute (tree
*node ATTRIBUTE_UNUSED
,
522 tree name
, tree args
,
523 int flags ATTRIBUTE_UNUSED
,
528 value
= TREE_VALUE (args
);
530 if (TREE_CODE (value
) != STRING_CST
)
532 warning (OPT_Wattributes
,
533 "argument of %qE attribute is not a string constant", name
);
534 *no_add_attrs
= true;
540 /* Misc. utilities. */
542 /* Generate a SYMBOL_REF for the special function NAME. When the address
543 can't be placed directly into a call instruction, and if possible, copy
544 it to a register so that cse / code hoisting is possible. */
546 sfunc_symbol (const char *name
)
548 rtx sym
= gen_rtx_SYMBOL_REF (Pmode
, name
);
550 /* These sfuncs should be hidden, and every dso should get a copy. */
551 SYMBOL_REF_FLAGS (sym
) = SYMBOL_FLAG_FUNCTION
| SYMBOL_FLAG_LOCAL
;
552 if (TARGET_SHORT_CALLS
)
553 ; /* Nothing to be done. */
554 else if (can_create_pseudo_p ())
555 sym
= copy_to_mode_reg (Pmode
, sym
);
556 else /* We rely on reload to fix this up. */
557 gcc_assert (!reload_in_progress
|| reload_completed
);
561 /* X and Y are two things to compare using CODE in IN_MODE.
562 Emit the compare insn, construct the proper cc reg in the proper
563 mode, and return the rtx for the cc reg comparison in CMODE. */
566 gen_compare_reg (machine_mode cmode
, enum rtx_code code
,
567 machine_mode in_mode
, rtx x
, rtx y
)
569 machine_mode mode
= SELECT_CC_MODE (code
, x
, y
);
570 rtx cc_reg
, pat
, clob0
, clob1
, clob2
;
572 if (in_mode
== VOIDmode
)
573 in_mode
= GET_MODE (x
);
574 if (in_mode
== VOIDmode
)
575 in_mode
= GET_MODE (y
);
577 if (mode
== CC_FPmode
)
579 /* The epiphany has only EQ / NE / LT / LE conditions for
580 hardware floating point. */
581 if (code
== GT
|| code
== GE
|| code
== UNLE
|| code
== UNLT
)
583 rtx tmp
= x
; x
= y
; y
= tmp
;
584 code
= swap_condition (code
);
586 cc_reg
= gen_rtx_REG (mode
, CCFP_REGNUM
);
587 y
= force_reg (in_mode
, y
);
591 if (mode
== CC_FP_GTEmode
592 && (code
== LE
|| code
== LT
|| code
== UNGT
|| code
== UNGE
))
594 if (flag_finite_math_only
595 && ((REG_P (x
) && REGNO (x
) == GPR_0
)
596 || (REG_P (y
) && REGNO (y
) == GPR_1
)))
599 case LE
: code
= UNLE
; break;
600 case LT
: code
= UNLT
; break;
601 case UNGT
: code
= GT
; break;
602 case UNGE
: code
= GE
; break;
603 default: gcc_unreachable ();
607 rtx tmp
= x
; x
= y
; y
= tmp
;
608 code
= swap_condition (code
);
611 cc_reg
= gen_rtx_REG (mode
, CC_REGNUM
);
613 if ((mode
== CC_FP_EQmode
|| mode
== CC_FP_GTEmode
614 || mode
== CC_FP_ORDmode
|| mode
== CC_FP_UNEQmode
)
615 /* mov<mode>cc might want to re-emit a comparison during ifcvt. */
616 && (!REG_P (x
) || REGNO (x
) != GPR_0
617 || !REG_P (y
) || REGNO (y
) != GPR_1
))
622 /* ??? We should really do the r0/r1 clobber only during rtl expansion,
623 but just like the flag clobber of movsicc, we have to allow
624 this for ifcvt to work, on the assumption that we'll only want
625 to do this if these registers have been used before by the
627 gcc_assert (currently_expanding_to_rtl
);
629 reg
= gen_rtx_REG (in_mode
, GPR_0
);
630 if (reg_overlap_mentioned_p (reg
, y
))
632 emit_move_insn (reg
, x
);
634 reg
= gen_rtx_REG (in_mode
, GPR_1
);
635 emit_move_insn (reg
, y
);
639 x
= force_reg (in_mode
, x
);
641 pat
= gen_rtx_SET (cc_reg
, gen_rtx_COMPARE (mode
, x
, y
));
642 if (mode
== CC_FP_EQmode
|| mode
== CC_FP_GTEmode
)
644 const char *name
= mode
== CC_FP_EQmode
? "__eqsf2" : "__gtesf2";
645 rtx use
= gen_rtx_USE (VOIDmode
, sfunc_symbol (name
));
647 clob0
= gen_rtx_CLOBBER (VOIDmode
, gen_rtx_REG (SImode
, GPR_IP
));
648 clob1
= gen_rtx_CLOBBER (VOIDmode
, gen_rtx_REG (SImode
, GPR_LR
));
649 pat
= gen_rtx_PARALLEL (VOIDmode
, gen_rtvec (4, pat
, use
, clob0
, clob1
));
651 else if (mode
== CC_FP_ORDmode
|| mode
== CC_FP_UNEQmode
)
653 const char *name
= mode
== CC_FP_ORDmode
? "__ordsf2" : "__uneqsf2";
654 rtx use
= gen_rtx_USE (VOIDmode
, sfunc_symbol (name
));
656 clob0
= gen_rtx_CLOBBER (VOIDmode
, gen_rtx_REG (SImode
, GPR_IP
));
657 clob1
= gen_rtx_CLOBBER (VOIDmode
, gen_rtx_REG (SImode
, GPR_16
));
658 clob2
= gen_rtx_CLOBBER (VOIDmode
, gen_rtx_REG (SImode
, GPR_LR
));
659 pat
= gen_rtx_PARALLEL (VOIDmode
, gen_rtvec (5, pat
, use
,
660 clob0
, clob1
, clob2
));
664 clob0
= gen_rtx_CLOBBER (VOIDmode
, gen_rtx_SCRATCH (in_mode
));
665 pat
= gen_rtx_PARALLEL (VOIDmode
, gen_rtvec (2, pat
, clob0
));
668 return gen_rtx_fmt_ee (code
, cmode
, cc_reg
, const0_rtx
);
671 /* The ROUND_ADVANCE* macros are local to this file. */
672 /* Round SIZE up to a word boundary. */
673 #define ROUND_ADVANCE(SIZE) \
674 (((SIZE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
676 /* Round arg MODE/TYPE up to the next word boundary. */
677 #define ROUND_ADVANCE_ARG(MODE, TYPE) \
679 ? ROUND_ADVANCE (int_size_in_bytes (TYPE)) \
680 : ROUND_ADVANCE (GET_MODE_SIZE (MODE)))
682 /* Round CUM up to the necessary point for argument MODE/TYPE. */
683 #define ROUND_ADVANCE_CUM(CUM, MODE, TYPE) \
684 (epiphany_function_arg_boundary ((MODE), (TYPE)) > BITS_PER_WORD \
685 ? (((CUM) + 1) & ~1) \
689 epiphany_function_arg_boundary (machine_mode mode
, const_tree type
)
691 if ((type
? TYPE_ALIGN (type
) : GET_MODE_BITSIZE (mode
)) <= PARM_BOUNDARY
)
692 return PARM_BOUNDARY
;
693 return 2 * PARM_BOUNDARY
;
696 /* Do any needed setup for a variadic function. For the EPIPHANY, we
697 actually emit the code in epiphany_expand_prologue.
699 CUM has not been updated for the last named argument which has type TYPE
700 and mode MODE, and we rely on this fact. */
704 epiphany_setup_incoming_varargs (cumulative_args_t cum
, machine_mode mode
,
705 tree type
, int *pretend_size
, int no_rtl
)
708 CUMULATIVE_ARGS next_cum
;
709 machine_function_t
*mf
= MACHINE_FUNCTION (cfun
);
711 /* All BLKmode values are passed by reference. */
712 gcc_assert (mode
!= BLKmode
);
714 next_cum
= *get_cumulative_args (cum
);
716 = ROUND_ADVANCE_CUM (next_cum
, mode
, type
) + ROUND_ADVANCE_ARG (mode
, type
);
717 first_anon_arg
= next_cum
;
719 if (first_anon_arg
< MAX_EPIPHANY_PARM_REGS
&& !no_rtl
)
721 /* Note that first_reg_offset < MAX_EPIPHANY_PARM_REGS. */
722 int first_reg_offset
= first_anon_arg
;
724 *pretend_size
= ((MAX_EPIPHANY_PARM_REGS
- first_reg_offset
)
728 mf
->pretend_args_odd
= ((*pretend_size
& UNITS_PER_WORD
) ? 1 : 0);
732 epiphany_arg_partial_bytes (cumulative_args_t cum
, machine_mode mode
,
733 tree type
, bool named ATTRIBUTE_UNUSED
)
735 int words
= 0, rounded_cum
;
737 gcc_assert (!epiphany_pass_by_reference (cum
, mode
, type
, /* named */ true));
739 rounded_cum
= ROUND_ADVANCE_CUM (*get_cumulative_args (cum
), mode
, type
);
740 if (rounded_cum
< MAX_EPIPHANY_PARM_REGS
)
742 words
= MAX_EPIPHANY_PARM_REGS
- rounded_cum
;
743 if (words
>= ROUND_ADVANCE_ARG (mode
, type
))
746 return words
* UNITS_PER_WORD
;
749 /* Cost functions. */
751 /* Compute a (partial) cost for rtx X. Return true if the complete
752 cost has been computed, and false if subexpressions should be
753 scanned. In either case, *TOTAL contains the cost result. */
756 epiphany_rtx_costs (rtx x
, machine_mode mode
, int outer_code
,
757 int opno ATTRIBUTE_UNUSED
,
758 int *total
, bool speed ATTRIBUTE_UNUSED
)
760 int code
= GET_CODE (x
);
764 /* Small integers in the right context are as cheap as registers. */
766 if ((outer_code
== PLUS
|| outer_code
== MINUS
)
767 && SIMM11 (INTVAL (x
)))
772 if (IMM16 (INTVAL (x
)))
774 *total
= outer_code
== SET
? 0 : COSTS_N_INSNS (1);
782 *total
= COSTS_N_INSNS ((epiphany_small16 (x
) ? 0 : 1)
783 + (outer_code
== SET
? 0 : 1));
789 split_double (x
, &high
, &low
);
790 *total
= COSTS_N_INSNS (!IMM16 (INTVAL (high
))
791 + !IMM16 (INTVAL (low
)));
798 *total
= COSTS_N_INSNS (1);
804 /* There are a number of single-insn combiner patterns that use
805 the flag side effects of arithmetic. */
817 rtx src
= SET_SRC (x
);
829 /* Provide the costs of an addressing mode that contains ADDR.
830 If ADDR is not a valid address, its cost is irrelevant. */
833 epiphany_address_cost (rtx addr
, machine_mode mode
,
834 addr_space_t as ATTRIBUTE_UNUSED
, bool speed
)
837 rtx off
= const0_rtx
;
842 /* Return 0 for addresses valid in short insns, 1 for addresses only valid
844 switch (GET_CODE (addr
))
847 reg
= XEXP (addr
, 0);
848 off
= XEXP (addr
, 1);
851 reg
= XEXP (addr
, 0);
852 off
= XEXP (addr
, 1);
853 gcc_assert (GET_CODE (off
) == PLUS
&& rtx_equal_p (reg
, XEXP (off
, 0)));
855 if (satisfies_constraint_Rgs (reg
) && satisfies_constraint_Rgs (off
))
863 if (!satisfies_constraint_Rgs (reg
))
865 /* The offset range available for short instructions depends on the mode
866 of the memory access. */
867 /* First, make sure we have a valid integer. */
868 if (!satisfies_constraint_L (off
))
871 switch (GET_MODE_SIZE (mode
))
885 return i
< -7 || i
> 7;
889 /* Compute the cost of moving data between registers and memory.
890 For integer, load latency is twice as long as register-register moves,
891 but issue pich is the same. For floating point, load latency is three
892 times as much as a reg-reg move. */
894 epiphany_memory_move_cost (machine_mode mode
,
895 reg_class_t rclass ATTRIBUTE_UNUSED
,
896 bool in ATTRIBUTE_UNUSED
)
898 return GET_MODE_CLASS (mode
) == MODE_INT
? 3 : 4;
901 /* Function prologue/epilogue handlers. */
903 /* EPIPHANY stack frames look like:
905 Before call After call
906 +-----------------------+ +-----------------------+
908 high | local variables, | | local variables, |
909 mem | reg save area, etc. | | reg save area, etc. |
911 +-----------------------+ +-----------------------+
913 | arguments on stack. | | arguments on stack. |
915 SP+8->+-----------------------+FP+8m->+-----------------------+
916 | 2 word save area for | | reg parm save area, |
917 | leaf funcs / flags | | only created for |
918 SP+0->+-----------------------+ | variable argument |
920 FP+8n->+-----------------------+
922 | register save area |
924 +-----------------------+
928 FP+0->+-----------------------+
930 | alloca allocations |
932 +-----------------------+
934 | arguments on stack |
936 SP+8->+-----------------------+
937 low | 2 word save area for |
938 memory | leaf funcs / flags |
939 SP+0->+-----------------------+
942 1) The "reg parm save area" does not exist for non variable argument fns.
943 The "reg parm save area" could be eliminated if we created our
944 own TARGET_GIMPLIFY_VA_ARG_EXPR, but that has tradeoffs as well
945 (so it's not done). */
947 /* Structure to be filled in by epiphany_compute_frame_size with register
948 save masks, and offsets for the current function. */
949 struct epiphany_frame_info
951 unsigned int total_size
; /* # bytes that the entire frame takes up. */
952 unsigned int pretend_size
; /* # bytes we push and pretend caller did. */
953 unsigned int args_size
; /* # bytes that outgoing arguments take up. */
954 unsigned int reg_size
; /* # bytes needed to store regs. */
955 unsigned int var_size
; /* # bytes that variables take up. */
956 HARD_REG_SET gmask
; /* Set of saved gp registers. */
957 int initialized
; /* Nonzero if frame size already calculated. */
958 int stld_sz
; /* Current load/store data size for offset
960 int need_fp
; /* value to override "frame_pointer_needed */
961 /* FIRST_SLOT is the slot that is saved first, at the very start of
962 the frame, with a POST_MODIFY to allocate the frame, if the size fits,
963 or at least the parm and register save areas, otherwise.
964 In the case of a large frame, LAST_SLOT is the slot that is saved last,
965 with a POST_MODIFY to allocate the rest of the frame. */
966 int first_slot
, last_slot
, first_slot_offset
, last_slot_offset
;
971 /* Current frame information calculated by epiphany_compute_frame_size. */
972 static struct epiphany_frame_info current_frame_info
;
974 /* Zero structure to initialize current_frame_info. */
975 static struct epiphany_frame_info zero_frame_info
;
977 /* The usual; we set up our machine_function data. */
978 static struct machine_function
*
979 epiphany_init_machine_status (void)
981 struct machine_function
*machine
;
983 /* Reset state info for each function. */
984 current_frame_info
= zero_frame_info
;
986 machine
= ggc_cleared_alloc
<machine_function_t
> ();
991 /* Implements INIT_EXPANDERS. We just set up to call the above
994 epiphany_init_expanders (void)
996 init_machine_status
= epiphany_init_machine_status
;
999 /* Type of function DECL.
1001 The result is cached. To reset the cache at the end of a function,
1002 call with DECL = NULL_TREE. */
1004 static enum epiphany_function_type
1005 epiphany_compute_function_type (tree decl
)
1009 static enum epiphany_function_type fn_type
= EPIPHANY_FUNCTION_UNKNOWN
;
1010 /* Last function we were called for. */
1011 static tree last_fn
= NULL_TREE
;
1013 /* Resetting the cached value? */
1014 if (decl
== NULL_TREE
)
1016 fn_type
= EPIPHANY_FUNCTION_UNKNOWN
;
1017 last_fn
= NULL_TREE
;
1021 if (decl
== last_fn
&& fn_type
!= EPIPHANY_FUNCTION_UNKNOWN
)
1024 /* Assume we have a normal function (not an interrupt handler). */
1025 fn_type
= EPIPHANY_FUNCTION_NORMAL
;
1027 /* Now see if this is an interrupt handler. */
1028 for (a
= DECL_ATTRIBUTES (decl
);
1032 tree name
= TREE_PURPOSE (a
);
1034 if (name
== get_identifier ("interrupt"))
1035 fn_type
= EPIPHANY_FUNCTION_INTERRUPT
;
1042 #define RETURN_ADDR_REGNUM GPR_LR
1043 #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
1044 #define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM))
1046 /* Tell prologue and epilogue if register REGNO should be saved / restored.
1047 The return address and frame pointer are treated separately.
1048 Don't consider them here. */
1049 #define MUST_SAVE_REGISTER(regno, interrupt_p) \
1050 ((df_regs_ever_live_p (regno) \
1051 || (interrupt_p && !crtl->is_leaf \
1052 && call_used_regs[regno] && !fixed_regs[regno])) \
1053 && (!call_used_regs[regno] || regno == GPR_LR \
1054 || (interrupt_p && regno != GPR_SP)))
1056 #define MUST_SAVE_RETURN_ADDR 0
1058 /* Return the bytes needed to compute the frame pointer from the current
1061 SIZE is the size needed for local variables. */
1064 epiphany_compute_frame_size (int size
/* # of var. bytes allocated. */)
1067 unsigned int total_size
, var_size
, args_size
, pretend_size
, reg_size
;
1069 enum epiphany_function_type fn_type
;
1071 int first_slot
, last_slot
, first_slot_offset
, last_slot_offset
;
1072 int first_slot_size
;
1073 int small_slots
= 0;
1076 args_size
= crtl
->outgoing_args_size
;
1077 pretend_size
= crtl
->args
.pretend_args_size
;
1078 total_size
= args_size
+ var_size
;
1080 CLEAR_HARD_REG_SET (gmask
);
1082 first_slot_offset
= 0;
1084 last_slot_offset
= 0;
1085 first_slot_size
= UNITS_PER_WORD
;
1087 /* See if this is an interrupt handler. Call used registers must be saved
1089 fn_type
= epiphany_compute_function_type (current_function_decl
);
1090 interrupt_p
= EPIPHANY_INTERRUPT_P (fn_type
);
1092 /* Calculate space needed for registers. */
1094 for (regno
= MAX_EPIPHANY_PARM_REGS
- 1; pretend_size
> reg_size
; regno
--)
1096 reg_size
+= UNITS_PER_WORD
;
1097 SET_HARD_REG_BIT (gmask
, regno
);
1098 if (epiphany_stack_offset
- reg_size
== 0)
1103 reg_size
+= 2 * UNITS_PER_WORD
;
1105 small_slots
= epiphany_stack_offset
/ UNITS_PER_WORD
;
1107 if (frame_pointer_needed
)
1109 current_frame_info
.need_fp
= 1;
1110 if (!interrupt_p
&& first_slot
< 0)
1111 first_slot
= GPR_FP
;
1114 current_frame_info
.need_fp
= 0;
1115 for (regno
= 0; regno
<= GPR_LAST
; regno
++)
1117 if (MUST_SAVE_REGISTER (regno
, interrupt_p
))
1119 gcc_assert (!TEST_HARD_REG_BIT (gmask
, regno
));
1120 reg_size
+= UNITS_PER_WORD
;
1121 SET_HARD_REG_BIT (gmask
, regno
);
1122 /* FIXME: when optimizing for speed, take schedling into account
1123 when selecting these registers. */
1124 if (regno
== first_slot
)
1125 gcc_assert (regno
== GPR_FP
&& frame_pointer_needed
);
1126 else if (!interrupt_p
&& first_slot
< 0)
1128 else if (last_slot
< 0
1129 && (first_slot
^ regno
) != 1
1130 && (!interrupt_p
|| regno
> GPR_1
))
1134 if (TEST_HARD_REG_BIT (gmask
, GPR_LR
))
1135 MACHINE_FUNCTION (cfun
)->lr_clobbered
= 1;
1136 /* ??? Could sometimes do better than that. */
1137 current_frame_info
.small_threshold
1138 = (optimize
>= 3 || interrupt_p
? 0
1139 : pretend_size
? small_slots
1140 : 4 + small_slots
- (first_slot
== GPR_FP
));
1142 /* If there might be variables with 64-bit alignment requirement, align the
1143 start of the variables. */
1144 if (var_size
>= 2 * UNITS_PER_WORD
1145 /* We don't want to split a double reg save/restore across two unpaired
1146 stack slots when optimizing. This rounding could be avoided with
1147 more complex reordering of the register saves, but that would seem
1148 to be a lot of code complexity for little gain. */
1149 || (reg_size
> 8 && optimize
))
1150 reg_size
= EPIPHANY_STACK_ALIGN (reg_size
);
1151 if (((total_size
+ reg_size
1152 /* Reserve space for UNKNOWN_REGNUM. */
1153 + EPIPHANY_STACK_ALIGN (4))
1154 <= (unsigned) epiphany_stack_offset
)
1156 && crtl
->is_leaf
&& !frame_pointer_needed
)
1164 && reg_size
< (unsigned HOST_WIDE_INT
) epiphany_stack_offset
)
1165 reg_size
= epiphany_stack_offset
;
1168 if (total_size
+ reg_size
< 0x3fc)
1170 first_slot_offset
= EPIPHANY_STACK_ALIGN (total_size
+ reg_size
);
1171 first_slot_offset
+= EPIPHANY_STACK_ALIGN (epiphany_stack_offset
);
1176 first_slot_offset
= EPIPHANY_STACK_ALIGN (reg_size
);
1177 last_slot_offset
= EPIPHANY_STACK_ALIGN (total_size
);
1178 last_slot_offset
+= EPIPHANY_STACK_ALIGN (epiphany_stack_offset
);
1180 CLEAR_HARD_REG_BIT (gmask
, last_slot
);
1183 else if (total_size
+ reg_size
< 0x1ffc && first_slot
>= 0)
1185 first_slot_offset
= EPIPHANY_STACK_ALIGN (total_size
+ reg_size
);
1190 if (total_size
+ reg_size
<= (unsigned) epiphany_stack_offset
)
1192 gcc_assert (first_slot
< 0);
1193 gcc_assert (reg_size
== 0 || (int) reg_size
== epiphany_stack_offset
);
1194 last_slot_offset
= EPIPHANY_STACK_ALIGN (total_size
+ reg_size
);
1200 ? EPIPHANY_STACK_ALIGN (reg_size
- epiphany_stack_offset
) : 0);
1201 if (!first_slot_offset
)
1203 if (first_slot
!= GPR_FP
|| !current_frame_info
.need_fp
)
1204 last_slot
= first_slot
;
1207 last_slot_offset
= EPIPHANY_STACK_ALIGN (total_size
);
1209 last_slot_offset
+= EPIPHANY_STACK_ALIGN (epiphany_stack_offset
);
1212 CLEAR_HARD_REG_BIT (gmask
, last_slot
);
1215 if (first_slot
>= 0)
1217 CLEAR_HARD_REG_BIT (gmask
, first_slot
);
1218 if (TEST_HARD_REG_BIT (gmask
, first_slot
^ 1)
1219 && epiphany_stack_offset
- pretend_size
>= 2 * UNITS_PER_WORD
)
1221 CLEAR_HARD_REG_BIT (gmask
, first_slot
^ 1);
1222 first_slot_size
= 2 * UNITS_PER_WORD
;
1226 total_size
= first_slot_offset
+ last_slot_offset
;
1228 /* Save computed information. */
1229 current_frame_info
.total_size
= total_size
;
1230 current_frame_info
.pretend_size
= pretend_size
;
1231 current_frame_info
.var_size
= var_size
;
1232 current_frame_info
.args_size
= args_size
;
1233 current_frame_info
.reg_size
= reg_size
;
1234 COPY_HARD_REG_SET (current_frame_info
.gmask
, gmask
);
1235 current_frame_info
.first_slot
= first_slot
;
1236 current_frame_info
.last_slot
= last_slot
;
1237 current_frame_info
.first_slot_offset
= first_slot_offset
;
1238 current_frame_info
.first_slot_size
= first_slot_size
;
1239 current_frame_info
.last_slot_offset
= last_slot_offset
;
1241 current_frame_info
.initialized
= reload_completed
;
1243 /* Ok, we're done. */
1247 /* Print operand X (an rtx) in assembler syntax to file FILE.
1248 CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
1249 For `%' followed by punctuation, CODE is the punctuation and X is null. */
1252 epiphany_print_operand (FILE *file
, rtx x
, int code
)
1257 fputs (epiphany_condition_codes
[get_epiphany_condition_code (x
)], file
);
1260 fputs (epiphany_condition_codes
[EPIPHANY_INVERSE_CONDITION_CODE
1261 (get_epiphany_condition_code (x
))],
1266 current_frame_info
.stld_sz
= 8;
1270 current_frame_info
.stld_sz
= 4;
1274 current_frame_info
.stld_sz
= 2;
1278 fputs (REG_P (x
) ? "jalr " : "bl ", file
);
1282 fprintf (file
, "r%d", epiphany_m1reg
);
1286 /* Do nothing special. */
1290 output_operand_lossage ("invalid operand output code");
1293 switch (GET_CODE (x
))
1299 fputs (reg_names
[REGNO (x
)], file
);
1303 current_frame_info
.stld_sz
= 1;
1306 switch (GET_CODE (addr
))
1309 offset
= GEN_INT (GET_MODE_SIZE (GET_MODE (x
)));
1310 addr
= XEXP (addr
, 0);
1313 offset
= GEN_INT (-GET_MODE_SIZE (GET_MODE (x
)));
1314 addr
= XEXP (addr
, 0);
1317 offset
= XEXP (XEXP (addr
, 1), 1);
1318 addr
= XEXP (addr
, 0);
1324 output_address (GET_MODE (x
), addr
);
1329 if (CONST_INT_P (offset
)) switch (GET_MODE_SIZE (GET_MODE (x
)))
1334 offset
= GEN_INT (INTVAL (offset
) >> 3);
1337 offset
= GEN_INT (INTVAL (offset
) >> 2);
1340 offset
= GEN_INT (INTVAL (offset
) >> 1);
1345 output_address (GET_MODE (x
), offset
);
1349 /* We handle SFmode constants here as output_addr_const doesn't. */
1350 if (GET_MODE (x
) == SFmode
)
1354 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x
), l
);
1355 fprintf (file
, "%s0x%08lx", IMMEDIATE_PREFIX
, l
);
1359 /* Let output_addr_const deal with it. */
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
));
1370 output_addr_const (file
, x
);
1375 /* Print a memory address as an operand to reference that memory location. */
1378 epiphany_print_operand_address (FILE *file
, machine_mode
/*mode*/, rtx addr
)
1380 register rtx base
, index
= 0;
1383 switch (GET_CODE (addr
))
1386 fputs (reg_names
[REGNO (addr
)], file
);
1389 if (/*???*/ 0 && SYMBOL_REF_FUNCTION_P (addr
))
1391 output_addr_const (file
, addr
);
1395 output_addr_const (file
, addr
);
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);
1404 base
= XEXP (addr
, 0), index
= XEXP (addr
, 1);
1405 gcc_assert (GET_CODE (base
) == REG
);
1406 fputs (reg_names
[REGNO (base
)], file
);
1410 ** ++rk quirky method to scale offset for ld/str.......
1412 fprintf (file
, ",%s%d", IMMEDIATE_PREFIX
,
1413 offset
/current_frame_info
.stld_sz
);
1417 switch (GET_CODE (index
))
1420 fprintf (file
, ",%s", reg_names
[REGNO (index
)]);
1423 fputc (',', file
), output_addr_const (file
, index
);
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 FIXME: We have the mode now, address printing can be moved into this
1438 output_addr_const (file
, addr
);
1444 epiphany_final_prescan_insn (rtx_insn
*insn ATTRIBUTE_UNUSED
,
1445 rtx
*opvec ATTRIBUTE_UNUSED
,
1446 int noperands ATTRIBUTE_UNUSED
)
1448 int i
= epiphany_n_nops
;
1449 rtx pat ATTRIBUTE_UNUSED
;
1452 fputs ("\tnop\n", asm_out_file
);
1456 /* Worker function for TARGET_RETURN_IN_MEMORY. */
1459 epiphany_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
1461 HOST_WIDE_INT size
= int_size_in_bytes (type
);
1463 if (AGGREGATE_TYPE_P (type
)
1464 && (TYPE_MODE (type
) == BLKmode
|| TYPE_NEEDS_CONSTRUCTING (type
)))
1466 return (size
== -1 || size
> 8);
1469 /* For EPIPHANY, All aggregates and arguments greater than 8 bytes are
1470 passed by reference. */
1473 epiphany_pass_by_reference (cumulative_args_t ca ATTRIBUTE_UNUSED
,
1474 machine_mode mode
, const_tree type
,
1475 bool named ATTRIBUTE_UNUSED
)
1479 if (AGGREGATE_TYPE_P (type
)
1480 && (mode
== BLKmode
|| TYPE_NEEDS_CONSTRUCTING (type
)))
1488 epiphany_function_value (const_tree ret_type
,
1489 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
1490 bool outgoing ATTRIBUTE_UNUSED
)
1494 mode
= TYPE_MODE (ret_type
);
1495 /* We must change the mode like PROMOTE_MODE does.
1496 ??? PROMOTE_MODE is ignored for non-scalar types.
1497 The set of types tested here has to be kept in sync
1498 with the one in explow.c:promote_mode. */
1499 if (GET_MODE_CLASS (mode
) == MODE_INT
1500 && GET_MODE_SIZE (mode
) < 4
1501 && (TREE_CODE (ret_type
) == INTEGER_TYPE
1502 || TREE_CODE (ret_type
) == ENUMERAL_TYPE
1503 || TREE_CODE (ret_type
) == BOOLEAN_TYPE
1504 || TREE_CODE (ret_type
) == OFFSET_TYPE
))
1506 return gen_rtx_REG (mode
, 0);
1510 epiphany_libcall_value (machine_mode mode
, const_rtx fun ATTRIBUTE_UNUSED
)
1512 return gen_rtx_REG (mode
, 0);
1516 epiphany_function_value_regno_p (const unsigned int regno ATTRIBUTE_UNUSED
)
1521 /* Fix up invalid option settings. */
1523 epiphany_override_options (void)
1525 if (epiphany_stack_offset
< 4)
1526 error ("stack_offset must be at least 4");
1527 if (epiphany_stack_offset
& 3)
1528 error ("stack_offset must be a multiple of 4");
1529 epiphany_stack_offset
= (epiphany_stack_offset
+ 3) & -4;
1530 if (!TARGET_SOFT_CMPSF
)
1531 flag_finite_math_only
= 1;
1533 /* This needs to be done at start up. It's convenient to do it here. */
1537 /* For a DImode load / store SET, make a SImode set for a
1538 REG_FRAME_RELATED_EXPR note, using OFFSET to create a high or lowpart
1541 frame_subreg_note (rtx set
, int offset
)
1543 rtx src
= simplify_gen_subreg (SImode
, SET_SRC (set
), DImode
, offset
);
1544 rtx dst
= simplify_gen_subreg (SImode
, SET_DEST (set
), DImode
, offset
);
1546 set
= gen_rtx_SET (dst
,src
);
1547 RTX_FRAME_RELATED_P (set
) = 1;
1555 rtx note
= NULL_RTX
;
1558 if (GET_CODE (x
) == PARALLEL
)
1560 rtx part
= XVECEXP (x
, 0, 0);
1562 if (GET_MODE (SET_DEST (part
)) == DImode
)
1564 note
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (XVECLEN (x
, 0) + 1));
1565 XVECEXP (note
, 0, 0) = frame_subreg_note (part
, 0);
1566 XVECEXP (note
, 0, 1) = frame_subreg_note (part
, UNITS_PER_WORD
);
1567 for (i
= XVECLEN (x
, 0) - 1; i
>= 1; i
--)
1569 part
= copy_rtx (XVECEXP (x
, 0, i
));
1571 if (GET_CODE (part
) == SET
)
1572 RTX_FRAME_RELATED_P (part
) = 1;
1573 XVECEXP (note
, 0, i
+ 1) = part
;
1578 for (i
= XVECLEN (x
, 0) - 1; i
>= 0; i
--)
1580 part
= XVECEXP (x
, 0, i
);
1582 if (GET_CODE (part
) == SET
)
1583 RTX_FRAME_RELATED_P (part
) = 1;
1587 else if (GET_CODE (x
) == SET
&& GET_MODE (SET_DEST (x
)) == DImode
)
1588 note
= gen_rtx_PARALLEL (VOIDmode
,
1589 gen_rtvec (2, frame_subreg_note (x
, 0),
1590 frame_subreg_note (x
, UNITS_PER_WORD
)));
1591 insn
= emit_insn (x
);
1592 RTX_FRAME_RELATED_P (insn
) = 1;
1594 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
, note
);
1599 frame_move_insn (rtx to
, rtx from
)
1601 return frame_insn (gen_rtx_SET (to
, from
));
1604 /* Generate a MEM referring to a varargs argument slot. */
1607 gen_varargs_mem (machine_mode mode
, rtx addr
)
1609 rtx mem
= gen_rtx_MEM (mode
, addr
);
1610 MEM_NOTRAP_P (mem
) = 1;
1611 set_mem_alias_set (mem
, get_varargs_alias_set ());
1615 /* Emit instructions to save or restore registers in the range [MIN..LIMIT) .
1616 If EPILOGUE_P is 0, save; if it is one, restore.
1617 ADDR is the stack slot to save the first register to; subsequent
1618 registers are written to lower addresses.
1619 However, the order of register pairs can be reversed in order to
1620 use double-word load-store instructions. Likewise, an unpaired single
1621 word save slot can be skipped while double saves are carried out, and
1622 reused when a single register is to be saved. */
1625 epiphany_emit_save_restore (int min
, int limit
, rtx addr
, int epilogue_p
)
1629 = current_frame_info
.first_slot
>= 0 ? epiphany_stack_offset
: 0;
1630 rtx skipped_mem
= NULL_RTX
;
1631 int last_saved
= limit
- 1;
1634 while (last_saved
>= 0
1635 && !TEST_HARD_REG_BIT (current_frame_info
.gmask
, last_saved
))
1637 for (i
= 0; i
< limit
; i
++)
1639 machine_mode mode
= word_mode
;
1642 rtx (*gen_mem
) (machine_mode
, rtx
) = gen_frame_mem
;
1644 /* Make sure we push the arguments in the right order. */
1645 if (n
< MAX_EPIPHANY_PARM_REGS
&& crtl
->args
.pretend_args_size
)
1647 n
= MAX_EPIPHANY_PARM_REGS
- 1 - n
;
1648 gen_mem
= gen_varargs_mem
;
1650 if (stack_offset
== current_frame_info
.first_slot_size
1651 && current_frame_info
.first_slot
>= 0)
1653 if (current_frame_info
.first_slot_size
> UNITS_PER_WORD
)
1656 addr
= plus_constant (Pmode
, addr
,
1657 - (HOST_WIDE_INT
) UNITS_PER_WORD
);
1659 if (i
-- < min
|| !epilogue_p
)
1661 n
= current_frame_info
.first_slot
;
1662 gen_mem
= gen_frame_mem
;
1664 else if (n
== UNKNOWN_REGNUM
1665 && stack_offset
> current_frame_info
.first_slot_size
)
1670 else if (!TEST_HARD_REG_BIT (current_frame_info
.gmask
, n
))
1675 /* Check for a register pair to save. */
1677 && (n
>= MAX_EPIPHANY_PARM_REGS
|| crtl
->args
.pretend_args_size
== 0)
1678 && (n
& 1) == 0 && n
+1 < limit
1679 && TEST_HARD_REG_BIT (current_frame_info
.gmask
, n
+1))
1681 /* If it fits in the current stack slot pair, place it there. */
1682 if (GET_CODE (addr
) == PLUS
&& (stack_offset
& 7) == 0
1683 && stack_offset
!= 2 * UNITS_PER_WORD
1684 && (current_frame_info
.last_slot
< 0
1685 || INTVAL (XEXP (addr
, 1)) != UNITS_PER_WORD
)
1686 && (n
+1 != last_saved
|| !skipped_mem
))
1690 addr
= plus_constant (Pmode
, addr
,
1691 - (HOST_WIDE_INT
) UNITS_PER_WORD
);
1693 /* If it fits in the following stack slot pair, that's fine, too. */
1694 else if (GET_CODE (addr
) == PLUS
&& (stack_offset
& 7) == 4
1695 && stack_offset
!= 2 * UNITS_PER_WORD
1696 && stack_offset
!= 3 * UNITS_PER_WORD
1697 && (current_frame_info
.last_slot
< 0
1698 || INTVAL (XEXP (addr
, 1)) != 2 * UNITS_PER_WORD
)
1699 && n
+ 1 != last_saved
)
1701 gcc_assert (!skipped_mem
);
1702 stack_offset
-= GET_MODE_SIZE (mode
);
1703 skipped_mem
= gen_mem (mode
, addr
);
1706 addr
= plus_constant (Pmode
, addr
,
1707 - (HOST_WIDE_INT
) 2 * UNITS_PER_WORD
);
1710 reg
= gen_rtx_REG (mode
, n
);
1711 if (mode
!= DImode
&& skipped_mem
)
1714 mem
= gen_mem (mode
, addr
);
1716 /* If we are loading / storing LR, note the offset that
1717 gen_reload_insi_ra requires. Since GPR_LR is even,
1718 we only need to test n, even if mode is DImode. */
1719 gcc_assert ((GPR_LR
& 1) == 0);
1722 long lr_slot_offset
= 0;
1723 rtx m_addr
= XEXP (mem
, 0);
1725 if (GET_CODE (m_addr
) == PLUS
)
1726 lr_slot_offset
= INTVAL (XEXP (m_addr
, 1));
1727 if (frame_pointer_needed
)
1728 lr_slot_offset
+= (current_frame_info
.first_slot_offset
1729 - current_frame_info
.total_size
);
1730 if (MACHINE_FUNCTION (cfun
)->lr_slot_known
)
1731 gcc_assert (MACHINE_FUNCTION (cfun
)->lr_slot_offset
1733 MACHINE_FUNCTION (cfun
)->lr_slot_offset
= lr_slot_offset
;
1734 MACHINE_FUNCTION (cfun
)->lr_slot_known
= 1;
1738 frame_move_insn (mem
, reg
);
1739 else if (n
>= MAX_EPIPHANY_PARM_REGS
|| !crtl
->args
.pretend_args_size
)
1740 emit_move_insn (reg
, mem
);
1741 if (mem
== skipped_mem
)
1743 skipped_mem
= NULL_RTX
;
1747 addr
= plus_constant (Pmode
, addr
, -(HOST_WIDE_INT
) UNITS_PER_WORD
);
1748 stack_offset
-= GET_MODE_SIZE (mode
);
1753 epiphany_expand_prologue (void)
1756 enum epiphany_function_type fn_type
;
1757 rtx addr
, mem
, off
, reg
;
1759 if (!current_frame_info
.initialized
)
1760 epiphany_compute_frame_size (get_frame_size ());
1762 /* It is debatable if we should adjust this by epiphany_stack_offset. */
1763 if (flag_stack_usage_info
)
1764 current_function_static_stack_size
= current_frame_info
.total_size
;
1766 fn_type
= epiphany_compute_function_type (current_function_decl
);
1767 interrupt_p
= EPIPHANY_INTERRUPT_P (fn_type
);
1771 addr
= plus_constant (Pmode
, stack_pointer_rtx
,
1772 - (HOST_WIDE_INT
) 2 * UNITS_PER_WORD
);
1773 if (!lookup_attribute ("forwarder_section",
1774 DECL_ATTRIBUTES (current_function_decl
))
1775 || !epiphany_is_long_call_p (XEXP (DECL_RTL (current_function_decl
),
1777 frame_move_insn (gen_frame_mem (DImode
, addr
),
1778 gen_rtx_REG (DImode
, GPR_0
));
1779 frame_move_insn (gen_rtx_REG (SImode
, GPR_0
),
1780 gen_rtx_REG (word_mode
, STATUS_REGNUM
));
1781 frame_move_insn (gen_rtx_REG (SImode
, GPR_1
),
1782 gen_rtx_REG (word_mode
, IRET_REGNUM
));
1783 mem
= gen_frame_mem (BLKmode
, stack_pointer_rtx
);
1784 off
= GEN_INT (-current_frame_info
.first_slot_offset
);
1785 frame_insn (gen_stack_adjust_add (off
, mem
));
1786 if (!epiphany_uninterruptible_p (current_function_decl
))
1787 emit_insn (gen_gie ());
1788 addr
= plus_constant (Pmode
, stack_pointer_rtx
,
1789 current_frame_info
.first_slot_offset
1790 - (HOST_WIDE_INT
) 3 * UNITS_PER_WORD
);
1794 addr
= plus_constant (Pmode
, stack_pointer_rtx
,
1795 epiphany_stack_offset
1796 - (HOST_WIDE_INT
) UNITS_PER_WORD
);
1797 epiphany_emit_save_restore (0, current_frame_info
.small_threshold
,
1799 /* Allocate register save area; for small to medium size frames,
1800 allocate the entire frame; this is joint with one register save. */
1801 if (current_frame_info
.first_slot
>= 0)
1804 = (current_frame_info
.first_slot_size
== UNITS_PER_WORD
1805 ? word_mode
: DImode
);
1807 off
= GEN_INT (-current_frame_info
.first_slot_offset
);
1808 mem
= gen_frame_mem (BLKmode
,
1809 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
, off
));
1810 frame_insn (gen_stack_adjust_str
1811 (gen_frame_mem (mode
, stack_pointer_rtx
),
1812 gen_rtx_REG (mode
, current_frame_info
.first_slot
),
1814 addr
= plus_constant (Pmode
, addr
,
1815 current_frame_info
.first_slot_offset
);
1818 epiphany_emit_save_restore (current_frame_info
.small_threshold
,
1819 FIRST_PSEUDO_REGISTER
, addr
, 0);
1820 if (current_frame_info
.need_fp
)
1821 frame_move_insn (hard_frame_pointer_rtx
, stack_pointer_rtx
);
1822 /* For large frames, allocate bulk of frame. This is usually joint with one
1824 if (current_frame_info
.last_slot
>= 0)
1829 gcc_assert (current_frame_info
.last_slot
!= GPR_FP
1830 || (!current_frame_info
.need_fp
1831 && current_frame_info
.first_slot
< 0));
1832 off
= GEN_INT (-current_frame_info
.last_slot_offset
);
1833 mem
= gen_frame_mem (BLKmode
,
1834 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
, off
));
1835 ip
= gen_rtx_REG (Pmode
, GPR_IP
);
1836 frame_move_insn (ip
, off
);
1837 reg
= gen_rtx_REG (word_mode
, current_frame_info
.last_slot
),
1838 mem2
= gen_frame_mem (word_mode
, stack_pointer_rtx
),
1839 insn
= frame_insn (gen_stack_adjust_str (mem2
, reg
, ip
, mem
));
1840 /* Instruction scheduling can separate the instruction setting IP from
1841 INSN so that dwarf2out_frame_debug_expr becomes confused what the
1842 temporary register is. Example: _gcov.o */
1843 note
= gen_rtx_SET (stack_pointer_rtx
,
1844 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
, off
));
1845 note
= gen_rtx_PARALLEL (VOIDmode
,
1846 gen_rtvec (2, gen_rtx_SET (mem2
, reg
), note
));
1847 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
, note
);
1849 /* If there is only one or no register to save, yet we have a large frame,
1851 else if (current_frame_info
.last_slot_offset
)
1853 mem
= gen_frame_mem (BLKmode
,
1854 plus_constant (Pmode
, stack_pointer_rtx
,
1855 current_frame_info
.last_slot_offset
));
1856 off
= GEN_INT (-current_frame_info
.last_slot_offset
);
1857 if (!SIMM11 (INTVAL (off
)))
1859 reg
= gen_rtx_REG (Pmode
, GPR_IP
);
1860 frame_move_insn (reg
, off
);
1863 frame_insn (gen_stack_adjust_add (off
, mem
));
1868 epiphany_expand_epilogue (int sibcall_p
)
1871 enum epiphany_function_type fn_type
;
1872 rtx mem
, addr
, reg
, off
;
1873 HOST_WIDE_INT restore_offset
;
1875 fn_type
= epiphany_compute_function_type( current_function_decl
);
1876 interrupt_p
= EPIPHANY_INTERRUPT_P (fn_type
);
1878 /* For variable frames, deallocate bulk of frame. */
1879 if (current_frame_info
.need_fp
)
1881 mem
= gen_frame_mem (BLKmode
, stack_pointer_rtx
);
1882 emit_insn (gen_stack_adjust_mov (mem
));
1884 /* Else for large static frames, deallocate bulk of frame. */
1885 else if (current_frame_info
.last_slot_offset
)
1887 mem
= gen_frame_mem (BLKmode
, stack_pointer_rtx
);
1888 reg
= gen_rtx_REG (Pmode
, GPR_IP
);
1889 emit_move_insn (reg
, GEN_INT (current_frame_info
.last_slot_offset
));
1890 emit_insn (gen_stack_adjust_add (reg
, mem
));
1892 restore_offset
= (interrupt_p
1893 ? - 3 * UNITS_PER_WORD
1894 : epiphany_stack_offset
- (HOST_WIDE_INT
) UNITS_PER_WORD
);
1895 addr
= plus_constant (Pmode
, stack_pointer_rtx
,
1896 (current_frame_info
.first_slot_offset
1898 epiphany_emit_save_restore (current_frame_info
.small_threshold
,
1899 FIRST_PSEUDO_REGISTER
, addr
, 1);
1901 if (interrupt_p
&& !epiphany_uninterruptible_p (current_function_decl
))
1902 emit_insn (gen_gid ());
1904 off
= GEN_INT (current_frame_info
.first_slot_offset
);
1905 mem
= gen_frame_mem (BLKmode
, stack_pointer_rtx
);
1906 /* For large / variable size frames, deallocating the register save area is
1907 joint with one register restore; for medium size frames, we use a
1908 dummy post-increment load to dealloacte the whole frame. */
1909 if (!SIMM11 (INTVAL (off
)) || current_frame_info
.last_slot
>= 0)
1911 emit_insn (gen_stack_adjust_ldr
1912 (gen_rtx_REG (word_mode
,
1913 (current_frame_info
.last_slot
>= 0
1914 ? current_frame_info
.last_slot
: GPR_IP
)),
1915 gen_frame_mem (word_mode
, stack_pointer_rtx
),
1919 /* While for small frames, we deallocate the entire frame with one add. */
1920 else if (INTVAL (off
))
1922 emit_insn (gen_stack_adjust_add (off
, mem
));
1926 emit_move_insn (gen_rtx_REG (word_mode
, STATUS_REGNUM
),
1927 gen_rtx_REG (SImode
, GPR_0
));
1928 emit_move_insn (gen_rtx_REG (word_mode
, IRET_REGNUM
),
1929 gen_rtx_REG (SImode
, GPR_1
));
1930 addr
= plus_constant (Pmode
, stack_pointer_rtx
,
1931 - (HOST_WIDE_INT
) 2 * UNITS_PER_WORD
);
1932 emit_move_insn (gen_rtx_REG (DImode
, GPR_0
),
1933 gen_frame_mem (DImode
, addr
));
1935 addr
= plus_constant (Pmode
, stack_pointer_rtx
,
1936 epiphany_stack_offset
- (HOST_WIDE_INT
) UNITS_PER_WORD
);
1937 epiphany_emit_save_restore (0, current_frame_info
.small_threshold
, addr
, 1);
1941 emit_jump_insn (gen_return_internal_interrupt());
1943 emit_jump_insn (gen_return_i ());
1948 epiphany_initial_elimination_offset (int from
, int to
)
1950 epiphany_compute_frame_size (get_frame_size ());
1951 if (from
== FRAME_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
1952 return current_frame_info
.total_size
- current_frame_info
.reg_size
;
1953 if (from
== FRAME_POINTER_REGNUM
&& to
== HARD_FRAME_POINTER_REGNUM
)
1954 return current_frame_info
.first_slot_offset
- current_frame_info
.reg_size
;
1955 if (from
== ARG_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
1956 return (current_frame_info
.total_size
1957 - ((current_frame_info
.pretend_size
+ 4) & -8));
1958 if (from
== ARG_POINTER_REGNUM
&& to
== HARD_FRAME_POINTER_REGNUM
)
1959 return (current_frame_info
.first_slot_offset
1960 - ((current_frame_info
.pretend_size
+ 4) & -8));
1965 epiphany_regno_rename_ok (unsigned, unsigned dst
)
1967 enum epiphany_function_type fn_type
;
1969 fn_type
= epiphany_compute_function_type (current_function_decl
);
1970 if (!EPIPHANY_INTERRUPT_P (fn_type
))
1972 if (df_regs_ever_live_p (dst
))
1978 epiphany_issue_rate (void)
1983 /* Function to update the integer COST
1984 based on the relationship between INSN that is dependent on
1985 DEP_INSN through the dependence LINK. The default is to make no
1986 adjustment to COST. This can be used for example to specify to
1987 the scheduler that an output- or anti-dependence does not incur
1988 the same cost as a data-dependence. The return value should be
1989 the new value for COST. */
1991 epiphany_adjust_cost (rtx_insn
*insn
, int dep_type
, rtx_insn
*dep_insn
,
1992 int cost
, unsigned int)
1998 if (recog_memoized (insn
) < 0
1999 || recog_memoized (dep_insn
) < 0)
2002 dep_set
= single_set (dep_insn
);
2004 /* The latency that we specify in the scheduling description refers
2005 to the actual output, not to an auto-increment register; for that,
2006 the latency is one. */
2007 if (dep_set
&& MEM_P (SET_SRC (dep_set
)) && cost
> 1)
2009 rtx set
= single_set (insn
);
2012 && !reg_overlap_mentioned_p (SET_DEST (dep_set
), SET_SRC (set
))
2013 && (!MEM_P (SET_DEST (set
))
2014 || !reg_overlap_mentioned_p (SET_DEST (dep_set
),
2015 XEXP (SET_DEST (set
), 0))))
2022 #define REG_OK_FOR_INDEX_P(X) REG_OK_FOR_BASE_P (X)
2024 #define RTX_OK_FOR_BASE_P(X) \
2025 (REG_P (X) && REG_OK_FOR_BASE_P (X))
2027 #define RTX_OK_FOR_INDEX_P(MODE, X) \
2028 ((GET_MODE_CLASS (MODE) != MODE_VECTOR_INT \
2029 || epiphany_vect_align >= GET_MODE_SIZE (MODE)) \
2030 && (REG_P (X) && REG_OK_FOR_INDEX_P (X)))
2032 #define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X) \
2033 (GET_CODE (X) == PLUS \
2034 && RTX_OK_FOR_BASE_P (XEXP (X, 0)) \
2035 && (RTX_OK_FOR_INDEX_P (MODE, XEXP (X, 1)) \
2036 || RTX_OK_FOR_OFFSET_P (MODE, XEXP (X, 1))))
2039 epiphany_legitimate_address_p (machine_mode mode
, rtx x
, bool strict
)
2041 #define REG_OK_FOR_BASE_P(X) \
2042 (strict ? GPR_P (REGNO (X)) : GPR_AP_OR_PSEUDO_P (REGNO (X)))
2043 if (RTX_OK_FOR_BASE_P (x
))
2045 if (RTX_FRAME_OFFSET_P (x
))
2047 if (LEGITIMATE_OFFSET_ADDRESS_P (mode
, x
))
2049 /* If this is a misaligned stack access, don't force it to reg+index. */
2050 if (GET_MODE_SIZE (mode
) == 8
2051 && GET_CODE (x
) == PLUS
&& XEXP (x
, 0) == stack_pointer_rtx
2052 /* Decomposed to SImode; GET_MODE_SIZE (SImode) == 4 */
2053 && !(INTVAL (XEXP (x
, 1)) & 3)
2054 && INTVAL (XEXP (x
, 1)) >= -2047 * 4
2055 && INTVAL (XEXP (x
, 1)) <= 2046 * 4)
2058 && (GET_CODE (x
) == POST_DEC
|| GET_CODE (x
) == POST_INC
)
2059 && RTX_OK_FOR_BASE_P (XEXP ((x
), 0)))
2061 if ((TARGET_POST_MODIFY
|| reload_completed
)
2062 && GET_CODE (x
) == POST_MODIFY
2063 && GET_CODE (XEXP ((x
), 1)) == PLUS
2064 && rtx_equal_p (XEXP ((x
), 0), XEXP (XEXP ((x
), 1), 0))
2065 && LEGITIMATE_OFFSET_ADDRESS_P (mode
, XEXP ((x
), 1)))
2067 if (mode
== BLKmode
)
2068 return epiphany_legitimate_address_p (SImode
, x
, strict
);
2073 epiphany_secondary_reload (bool in_p
, rtx x
, reg_class_t rclass
,
2074 machine_mode mode ATTRIBUTE_UNUSED
,
2075 secondary_reload_info
*sri
)
2077 /* This could give more reload inheritance, but we are missing some
2078 reload infrastructure. */
2080 if (in_p
&& GET_CODE (x
) == UNSPEC
2081 && satisfies_constraint_Sra (x
) && !satisfies_constraint_Rra (x
))
2083 gcc_assert (rclass
== GENERAL_REGS
);
2084 sri
->icode
= CODE_FOR_reload_insi_ra
;
2091 epiphany_is_long_call_p (rtx x
)
2093 tree decl
= SYMBOL_REF_DECL (x
);
2094 bool ret_val
= !TARGET_SHORT_CALLS
;
2097 /* ??? Is it safe to default to ret_val if decl is NULL? We should
2098 probably encode information via encode_section_info, and also
2099 have (an) option(s) to take SYMBOL_FLAG_LOCAL and/or SYMBOL_FLAG_EXTERNAL
2103 attrs
= TYPE_ATTRIBUTES (TREE_TYPE (decl
));
2104 if (lookup_attribute ("long_call", attrs
))
2106 else if (lookup_attribute ("short_call", attrs
))
2113 epiphany_small16 (rtx x
)
2116 rtx offs ATTRIBUTE_UNUSED
= const0_rtx
;
2118 if (GET_CODE (x
) == CONST
&& GET_CODE (XEXP (x
, 0)) == PLUS
)
2120 base
= XEXP (XEXP (x
, 0), 0);
2121 offs
= XEXP (XEXP (x
, 0), 1);
2123 if (GET_CODE (base
) == SYMBOL_REF
&& SYMBOL_REF_FUNCTION_P (base
)
2124 && epiphany_is_long_call_p (base
))
2126 return TARGET_SMALL16
!= 0;
2129 /* Return nonzero if it is ok to make a tail-call to DECL. */
2131 epiphany_function_ok_for_sibcall (tree decl
, tree exp
)
2133 bool cfun_interrupt_p
, call_interrupt_p
;
2135 cfun_interrupt_p
= EPIPHANY_INTERRUPT_P (epiphany_compute_function_type
2136 (current_function_decl
));
2138 call_interrupt_p
= EPIPHANY_INTERRUPT_P (epiphany_compute_function_type (decl
));
2141 tree fn_type
= TREE_TYPE (CALL_EXPR_FN (exp
));
2143 gcc_assert (POINTER_TYPE_P (fn_type
));
2144 fn_type
= TREE_TYPE (fn_type
);
2145 gcc_assert (TREE_CODE (fn_type
) == FUNCTION_TYPE
2146 || TREE_CODE (fn_type
) == METHOD_TYPE
);
2148 = lookup_attribute ("interrupt", TYPE_ATTRIBUTES (fn_type
)) != NULL
;
2151 /* Don't tailcall from or to an ISR routine - although we could in
2152 principle tailcall from one ISR routine to another, we'd need to
2153 handle this in sibcall_epilogue to make it work. */
2154 if (cfun_interrupt_p
|| call_interrupt_p
)
2157 /* Everything else is ok. */
2161 /* T is a function declaration or the MEM_EXPR of a MEM passed to a call
2163 Return true iff the type of T has the uninterruptible attribute.
2164 If T is NULL, return false. */
2166 epiphany_uninterruptible_p (tree t
)
2172 attrs
= TYPE_ATTRIBUTES (TREE_TYPE (t
));
2173 if (lookup_attribute ("disinterrupt", attrs
))
2180 epiphany_call_uninterruptible_p (rtx mem
)
2182 rtx addr
= XEXP (mem
, 0);
2185 if (GET_CODE (addr
) == SYMBOL_REF
)
2186 t
= SYMBOL_REF_DECL (addr
);
2189 return epiphany_uninterruptible_p (t
);
2193 epiphany_promote_function_mode (const_tree type
, machine_mode mode
,
2194 int *punsignedp ATTRIBUTE_UNUSED
,
2195 const_tree funtype ATTRIBUTE_UNUSED
,
2196 int for_return ATTRIBUTE_UNUSED
)
2200 return promote_mode (type
, mode
, &dummy
);
2204 epiphany_conditional_register_usage (void)
2208 if (PIC_OFFSET_TABLE_REGNUM
!= INVALID_REGNUM
)
2210 fixed_regs
[PIC_OFFSET_TABLE_REGNUM
] = 1;
2211 call_used_regs
[PIC_OFFSET_TABLE_REGNUM
] = 1;
2213 if (TARGET_HALF_REG_FILE
)
2215 for (i
= 32; i
<= 63; i
++)
2218 call_used_regs
[i
] = 1;
2221 if (epiphany_m1reg
>= 0)
2223 fixed_regs
[epiphany_m1reg
] = 1;
2224 call_used_regs
[epiphany_m1reg
] = 1;
2226 if (!TARGET_PREFER_SHORT_INSN_REGS
)
2227 CLEAR_HARD_REG_SET (reg_class_contents
[SHORT_INSN_REGS
]);
2228 COPY_HARD_REG_SET (reg_class_contents
[SIBCALL_REGS
],
2229 reg_class_contents
[GENERAL_REGS
]);
2230 /* It would be simpler and quicker if we could just use
2231 AND_COMPL_HARD_REG_SET, alas, call_used_reg_set is yet uninitialized;
2232 it is set up later by our caller. */
2233 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
2234 if (!call_used_regs
[i
])
2235 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], i
);
2238 /* Determine where to put an argument to a function.
2239 Value is zero to push the argument on the stack,
2240 or a hard register in which to store the argument.
2242 MODE is the argument's machine mode.
2243 TYPE is the data type of the argument (as a tree).
2244 This is null for libcalls where that information may
2246 CUM is a variable of type CUMULATIVE_ARGS which gives info about
2247 the preceding args and about the function being called.
2248 NAMED is nonzero if this argument is a named parameter
2249 (otherwise it is an extra parameter matching an ellipsis). */
2250 /* On the EPIPHANY the first MAX_EPIPHANY_PARM_REGS args are normally in
2251 registers and the rest are pushed. */
2253 epiphany_function_arg (cumulative_args_t cum_v
, machine_mode mode
,
2254 const_tree type
, bool named ATTRIBUTE_UNUSED
)
2256 CUMULATIVE_ARGS cum
= *get_cumulative_args (cum_v
);
2258 if (PASS_IN_REG_P (cum
, mode
, type
))
2259 return gen_rtx_REG (mode
, ROUND_ADVANCE_CUM (cum
, mode
, type
));
2263 /* Update the data in CUM to advance over an argument
2264 of mode MODE and data type TYPE.
2265 (TYPE is null for libcalls where that information may not be available.) */
2267 epiphany_function_arg_advance (cumulative_args_t cum_v
, machine_mode mode
,
2268 const_tree type
, bool named ATTRIBUTE_UNUSED
)
2270 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
2272 *cum
= ROUND_ADVANCE_CUM (*cum
, mode
, type
) + ROUND_ADVANCE_ARG (mode
, type
);
2275 /* Nested function support.
2276 An epiphany trampoline looks like this:
2277 mov r16,%low(fnaddr)
2278 movt r16,%high(fnaddr)
2283 #define EPIPHANY_LOW_RTX(X) \
2284 (gen_rtx_IOR (SImode, \
2285 gen_rtx_ASHIFT (SImode, \
2286 gen_rtx_AND (SImode, (X), GEN_INT (0xff)), GEN_INT (5)), \
2287 gen_rtx_ASHIFT (SImode, \
2288 gen_rtx_AND (SImode, (X), GEN_INT (0xff00)), GEN_INT (12))))
2289 #define EPIPHANY_HIGH_RTX(X) \
2290 EPIPHANY_LOW_RTX (gen_rtx_LSHIFTRT (SImode, (X), GEN_INT (16)))
2292 /* Emit RTL insns to initialize the variable parts of a trampoline.
2293 FNADDR is an RTX for the address of the function's pure code.
2294 CXT is an RTX for the static chain value for the function. */
2296 epiphany_trampoline_init (rtx tramp_mem
, tree fndecl
, rtx cxt
)
2298 rtx fnaddr
= XEXP (DECL_RTL (fndecl
), 0);
2299 rtx tramp
= force_reg (Pmode
, XEXP (tramp_mem
, 0));
2301 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, tramp
, 0)),
2302 gen_rtx_IOR (SImode
, GEN_INT (0x4002000b),
2303 EPIPHANY_LOW_RTX (fnaddr
)));
2304 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, tramp
, 4)),
2305 gen_rtx_IOR (SImode
, GEN_INT (0x5002000b),
2306 EPIPHANY_HIGH_RTX (fnaddr
)));
2307 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, tramp
, 8)),
2308 gen_rtx_IOR (SImode
, GEN_INT (0x2002800b),
2309 EPIPHANY_LOW_RTX (cxt
)));
2310 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, tramp
, 12)),
2311 gen_rtx_IOR (SImode
, GEN_INT (0x3002800b),
2312 EPIPHANY_HIGH_RTX (cxt
)));
2313 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (Pmode
, tramp
, 16)),
2314 GEN_INT (0x0802014f));
2318 epiphany_optimize_mode_switching (int entity
)
2320 if (MACHINE_FUNCTION (cfun
)->sw_entities_processed
& (1 << entity
))
2324 case EPIPHANY_MSW_ENTITY_AND
:
2325 case EPIPHANY_MSW_ENTITY_OR
:
2326 case EPIPHANY_MSW_ENTITY_CONFIG
:
2328 case EPIPHANY_MSW_ENTITY_NEAREST
:
2329 case EPIPHANY_MSW_ENTITY_TRUNC
:
2330 return optimize
> 0;
2331 case EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN
:
2332 return MACHINE_FUNCTION (cfun
)->unknown_mode_uses
!= 0;
2333 case EPIPHANY_MSW_ENTITY_ROUND_KNOWN
:
2334 return (MACHINE_FUNCTION (cfun
)->sw_entities_processed
2335 & (1 << EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN
)) != 0;
2336 case EPIPHANY_MSW_ENTITY_FPU_OMNIBUS
:
2337 return optimize
== 0 || current_pass
== pass_mode_switch_use
;
2343 epiphany_mode_priority (int entity
, int priority
)
2345 if (entity
== EPIPHANY_MSW_ENTITY_AND
|| entity
== EPIPHANY_MSW_ENTITY_OR
2346 || entity
== EPIPHANY_MSW_ENTITY_CONFIG
)
2351 case 4: return FP_MODE_ROUND_UNKNOWN
;
2352 case 5: return FP_MODE_NONE
;
2353 default: gcc_unreachable ();
2355 switch ((enum attr_fp_mode
) epiphany_normal_fp_mode
)
2360 case 0: return FP_MODE_INT
;
2361 case 1: return epiphany_normal_fp_rounding
;
2362 case 2: return (epiphany_normal_fp_rounding
== FP_MODE_ROUND_NEAREST
2363 ? FP_MODE_ROUND_TRUNC
: FP_MODE_ROUND_NEAREST
);
2364 case 3: return FP_MODE_CALLER
;
2366 case FP_MODE_ROUND_NEAREST
:
2367 case FP_MODE_CALLER
:
2370 case 0: return FP_MODE_ROUND_NEAREST
;
2371 case 1: return FP_MODE_ROUND_TRUNC
;
2372 case 2: return FP_MODE_INT
;
2373 case 3: return FP_MODE_CALLER
;
2375 case FP_MODE_ROUND_TRUNC
:
2378 case 0: return FP_MODE_ROUND_TRUNC
;
2379 case 1: return FP_MODE_ROUND_NEAREST
;
2380 case 2: return FP_MODE_INT
;
2381 case 3: return FP_MODE_CALLER
;
2383 case FP_MODE_ROUND_UNKNOWN
:
2391 epiphany_mode_needed (int entity
, rtx_insn
*insn
)
2393 enum attr_fp_mode mode
;
2395 if (recog_memoized (insn
) < 0)
2397 if (entity
== EPIPHANY_MSW_ENTITY_AND
2398 || entity
== EPIPHANY_MSW_ENTITY_OR
2399 || entity
== EPIPHANY_MSW_ENTITY_CONFIG
)
2401 return FP_MODE_NONE
;
2403 mode
= get_attr_fp_mode (insn
);
2407 case EPIPHANY_MSW_ENTITY_AND
:
2408 return mode
!= FP_MODE_NONE
&& mode
!= FP_MODE_INT
? 1 : 2;
2409 case EPIPHANY_MSW_ENTITY_OR
:
2410 return mode
== FP_MODE_INT
? 1 : 2;
2411 case EPIPHANY_MSW_ENTITY_CONFIG
:
2412 /* We must know/save config before we set it to something else.
2413 Where we need the original value, we are fine with having it
2414 just unchanged from the function start.
2415 Because of the nature of the mode switching optimization,
2416 a restore will be dominated by a clobber. */
2417 if (mode
!= FP_MODE_NONE
&& mode
!= FP_MODE_CALLER
)
2419 /* A cpecial case are abnormal edges, which are deemed to clobber
2420 the mode as well. We need to pin this effect on a actually
2421 dominating insn, and one where the frame can be accessed, too, in
2422 case the pseudo used to save CONFIG doesn't get a hard register. */
2423 if (CALL_P (insn
) && find_reg_note (insn
, REG_EH_REGION
, NULL_RTX
))
2426 case EPIPHANY_MSW_ENTITY_ROUND_KNOWN
:
2427 if (recog_memoized (insn
) == CODE_FOR_set_fp_mode
)
2428 mode
= (enum attr_fp_mode
) epiphany_mode_after (entity
, mode
, insn
);
2430 case EPIPHANY_MSW_ENTITY_NEAREST
:
2431 case EPIPHANY_MSW_ENTITY_TRUNC
:
2432 if (mode
== FP_MODE_ROUND_UNKNOWN
)
2434 MACHINE_FUNCTION (cfun
)->unknown_mode_uses
++;
2435 return FP_MODE_NONE
;
2438 case EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN
:
2439 if (mode
== FP_MODE_ROUND_NEAREST
|| mode
== FP_MODE_ROUND_TRUNC
)
2440 return FP_MODE_ROUND_UNKNOWN
;
2442 case EPIPHANY_MSW_ENTITY_FPU_OMNIBUS
:
2443 if (mode
== FP_MODE_ROUND_UNKNOWN
)
2444 return epiphany_normal_fp_rounding
;
2452 epiphany_mode_entry_exit (int entity
, bool exit
)
2454 int normal_mode
= epiphany_normal_fp_mode
;
2456 MACHINE_FUNCTION (cfun
)->sw_entities_processed
|= (1 << entity
);
2457 if (epiphany_is_interrupt_p (current_function_decl
))
2458 normal_mode
= FP_MODE_CALLER
;
2461 case EPIPHANY_MSW_ENTITY_AND
:
2463 return normal_mode
!= FP_MODE_INT
? 1 : 2;
2465 case EPIPHANY_MSW_ENTITY_OR
:
2467 return normal_mode
== FP_MODE_INT
? 1 : 2;
2469 case EPIPHANY_MSW_ENTITY_CONFIG
:
2472 return normal_mode
== FP_MODE_CALLER
? 0 : 1;
2473 case EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN
:
2474 if (normal_mode
== FP_MODE_ROUND_NEAREST
2475 || normal_mode
== FP_MODE_ROUND_TRUNC
)
2476 return FP_MODE_ROUND_UNKNOWN
;
2478 case EPIPHANY_MSW_ENTITY_NEAREST
:
2479 case EPIPHANY_MSW_ENTITY_TRUNC
:
2480 case EPIPHANY_MSW_ENTITY_ROUND_KNOWN
:
2481 case EPIPHANY_MSW_ENTITY_FPU_OMNIBUS
:
2489 epiphany_mode_after (int entity
, int last_mode
, rtx_insn
*insn
)
2491 /* We have too few call-saved registers to hope to keep the masks across
2493 if (entity
== EPIPHANY_MSW_ENTITY_AND
|| entity
== EPIPHANY_MSW_ENTITY_OR
)
2499 /* If there is an abnormal edge, we don't want the config register to
2500 be 'saved' again at the destination.
2501 The frame pointer adjustment is inside a PARALLEL because of the
2503 if (entity
== EPIPHANY_MSW_ENTITY_CONFIG
&& NONJUMP_INSN_P (insn
)
2504 && GET_CODE (PATTERN (insn
)) == PARALLEL
2505 && GET_CODE (XVECEXP (PATTERN (insn
), 0, 0)) == SET
2506 && SET_DEST (XVECEXP (PATTERN (insn
), 0, 0)) == frame_pointer_rtx
)
2508 gcc_assert (cfun
->has_nonlocal_label
);
2511 if (recog_memoized (insn
) < 0)
2513 if (get_attr_fp_mode (insn
) == FP_MODE_ROUND_UNKNOWN
2514 && last_mode
!= FP_MODE_ROUND_NEAREST
&& last_mode
!= FP_MODE_ROUND_TRUNC
)
2516 if (entity
== EPIPHANY_MSW_ENTITY_NEAREST
)
2517 return FP_MODE_ROUND_NEAREST
;
2518 if (entity
== EPIPHANY_MSW_ENTITY_TRUNC
)
2519 return FP_MODE_ROUND_TRUNC
;
2521 if (recog_memoized (insn
) == CODE_FOR_set_fp_mode
)
2523 rtx src
= SET_SRC (XVECEXP (PATTERN (insn
), 0, 0));
2527 return FP_MODE_CALLER
;
2528 fp_mode
= INTVAL (XVECEXP (XEXP (src
, 0), 0, 0));
2529 if (entity
== EPIPHANY_MSW_ENTITY_ROUND_UNKNOWN
2530 && (fp_mode
== FP_MODE_ROUND_NEAREST
2531 || fp_mode
== EPIPHANY_MSW_ENTITY_TRUNC
))
2532 return FP_MODE_ROUND_UNKNOWN
;
2539 epiphany_mode_entry (int entity
)
2541 return epiphany_mode_entry_exit (entity
, false);
2545 epiphany_mode_exit (int entity
)
2547 return epiphany_mode_entry_exit (entity
, true);
2551 emit_set_fp_mode (int entity
, int mode
, int prev_mode ATTRIBUTE_UNUSED
,
2552 HARD_REG_SET regs_live ATTRIBUTE_UNUSED
)
2554 rtx save_cc
, cc_reg
, mask
, src
, src2
;
2555 enum attr_fp_mode fp_mode
;
2557 if (!MACHINE_FUNCTION (cfun
)->and_mask
)
2559 MACHINE_FUNCTION (cfun
)->and_mask
= gen_reg_rtx (SImode
);
2560 MACHINE_FUNCTION (cfun
)->or_mask
= gen_reg_rtx (SImode
);
2562 if (entity
== EPIPHANY_MSW_ENTITY_AND
)
2564 gcc_assert (mode
>= 0 && mode
<= 2);
2566 emit_move_insn (MACHINE_FUNCTION (cfun
)->and_mask
,
2567 gen_int_mode (0xfff1fffe, SImode
));
2570 else if (entity
== EPIPHANY_MSW_ENTITY_OR
)
2572 gcc_assert (mode
>= 0 && mode
<= 2);
2574 emit_move_insn (MACHINE_FUNCTION (cfun
)->or_mask
, GEN_INT(0x00080000));
2577 else if (entity
== EPIPHANY_MSW_ENTITY_CONFIG
)
2579 /* Mode switching optimization is done after emit_initial_value_sets,
2580 so we have to take care of CONFIG_REGNUM here. */
2581 gcc_assert (mode
>= 0 && mode
<= 2);
2582 rtx save
= get_hard_reg_initial_val (SImode
, CONFIG_REGNUM
);
2584 emit_insn (gen_save_config (save
));
2587 fp_mode
= (enum attr_fp_mode
) mode
;
2592 case FP_MODE_CALLER
:
2593 /* The EPIPHANY_MSW_ENTITY_CONFIG processing must come later
2594 so that the config save gets inserted before the first use. */
2595 gcc_assert (entity
> EPIPHANY_MSW_ENTITY_CONFIG
);
2596 src
= get_hard_reg_initial_val (SImode
, CONFIG_REGNUM
);
2597 mask
= MACHINE_FUNCTION (cfun
)->and_mask
;
2599 case FP_MODE_ROUND_UNKNOWN
:
2600 MACHINE_FUNCTION (cfun
)->unknown_mode_sets
++;
2601 mask
= MACHINE_FUNCTION (cfun
)->and_mask
;
2603 case FP_MODE_ROUND_NEAREST
:
2604 if (entity
== EPIPHANY_MSW_ENTITY_TRUNC
)
2606 mask
= MACHINE_FUNCTION (cfun
)->and_mask
;
2608 case FP_MODE_ROUND_TRUNC
:
2609 if (entity
== EPIPHANY_MSW_ENTITY_NEAREST
)
2611 mask
= MACHINE_FUNCTION (cfun
)->and_mask
;
2614 mask
= MACHINE_FUNCTION (cfun
)->or_mask
;
2620 save_cc
= gen_reg_rtx (CCmode
);
2621 cc_reg
= gen_rtx_REG (CCmode
, CC_REGNUM
);
2622 emit_move_insn (save_cc
, cc_reg
);
2623 mask
= force_reg (SImode
, mask
);
2626 rtvec v
= gen_rtvec (1, GEN_INT (fp_mode
));
2628 src
= gen_rtx_CONST (SImode
, gen_rtx_UNSPEC (SImode
, v
, UNSPEC_FP_MODE
));
2630 if (entity
== EPIPHANY_MSW_ENTITY_ROUND_KNOWN
2631 || entity
== EPIPHANY_MSW_ENTITY_FPU_OMNIBUS
)
2632 src2
= copy_rtx (src
);
2635 rtvec v
= gen_rtvec (1, GEN_INT (FP_MODE_ROUND_UNKNOWN
));
2637 src2
= gen_rtx_CONST (SImode
, gen_rtx_UNSPEC (SImode
, v
, UNSPEC_FP_MODE
));
2639 emit_insn (gen_set_fp_mode (src
, src2
, mask
));
2640 emit_move_insn (cc_reg
, save_cc
);
2644 epiphany_expand_set_fp_mode (rtx
*operands
)
2646 rtx ctrl
= gen_rtx_REG (SImode
, CONFIG_REGNUM
);
2647 rtx src
= operands
[0];
2648 rtx mask_reg
= operands
[2];
2649 rtx scratch
= operands
[3];
2650 enum attr_fp_mode fp_mode
;
2653 gcc_assert (rtx_equal_p (src
, operands
[1])
2654 /* Sometimes reload gets silly and reloads the same pseudo
2655 into different registers. */
2656 || (REG_P (src
) && REG_P (operands
[1])));
2658 if (!epiphany_uninterruptible_p (current_function_decl
))
2659 emit_insn (gen_gid ());
2660 emit_move_insn (scratch
, ctrl
);
2662 if (GET_CODE (src
) == REG
)
2664 /* FP_MODE_CALLER */
2665 emit_insn (gen_xorsi3 (scratch
, scratch
, src
));
2666 emit_insn (gen_andsi3 (scratch
, scratch
, mask_reg
));
2667 emit_insn (gen_xorsi3 (scratch
, scratch
, src
));
2671 gcc_assert (GET_CODE (src
) == CONST
);
2672 src
= XEXP (src
, 0);
2673 fp_mode
= (enum attr_fp_mode
) INTVAL (XVECEXP (src
, 0, 0));
2676 case FP_MODE_ROUND_NEAREST
:
2677 emit_insn (gen_andsi3 (scratch
, scratch
, mask_reg
));
2679 case FP_MODE_ROUND_TRUNC
:
2680 emit_insn (gen_andsi3 (scratch
, scratch
, mask_reg
));
2681 emit_insn (gen_add2_insn (scratch
, const1_rtx
));
2684 emit_insn (gen_iorsi3 (scratch
, scratch
, mask_reg
));
2686 case FP_MODE_CALLER
:
2687 case FP_MODE_ROUND_UNKNOWN
:
2692 emit_move_insn (ctrl
, scratch
);
2693 if (!epiphany_uninterruptible_p (current_function_decl
))
2694 emit_insn (gen_gie ());
2698 epiphany_insert_mode_switch_use (rtx_insn
*insn
,
2699 int entity ATTRIBUTE_UNUSED
,
2700 int mode ATTRIBUTE_UNUSED
)
2702 rtx pat
= PATTERN (insn
);
2705 rtx near
= gen_rtx_REG (SImode
, FP_NEAREST_REGNUM
);
2706 rtx trunc
= gen_rtx_REG (SImode
, FP_TRUNCATE_REGNUM
);
2708 if (entity
!= EPIPHANY_MSW_ENTITY_FPU_OMNIBUS
)
2710 switch ((enum attr_fp_mode
) get_attr_fp_mode (insn
))
2712 case FP_MODE_ROUND_NEAREST
:
2713 near
= gen_rtx_USE (VOIDmode
, near
);
2714 trunc
= gen_rtx_CLOBBER (VOIDmode
, trunc
);
2716 case FP_MODE_ROUND_TRUNC
:
2717 near
= gen_rtx_CLOBBER (VOIDmode
, near
);
2718 trunc
= gen_rtx_USE (VOIDmode
, trunc
);
2720 case FP_MODE_ROUND_UNKNOWN
:
2721 near
= gen_rtx_USE (VOIDmode
, gen_rtx_REG (SImode
, FP_ANYFP_REGNUM
));
2722 trunc
= copy_rtx (near
);
2725 case FP_MODE_CALLER
:
2726 near
= gen_rtx_USE (VOIDmode
, near
);
2727 trunc
= gen_rtx_USE (VOIDmode
, trunc
);
2732 gcc_assert (GET_CODE (pat
) == PARALLEL
);
2733 len
= XVECLEN (pat
, 0);
2734 v
= rtvec_alloc (len
+ 2);
2735 for (i
= 0; i
< len
; i
++)
2736 RTVEC_ELT (v
, i
) = XVECEXP (pat
, 0, i
);
2737 RTVEC_ELT (v
, len
) = near
;
2738 RTVEC_ELT (v
, len
+ 1) = trunc
;
2739 pat
= gen_rtx_PARALLEL (VOIDmode
, v
);
2740 PATTERN (insn
) = pat
;
2741 MACHINE_FUNCTION (cfun
)->control_use_inserted
= true;
2745 epiphany_epilogue_uses (int regno
)
2747 if (regno
== GPR_LR
)
2749 if (reload_completed
&& epiphany_is_interrupt_p (current_function_decl
))
2751 if (fixed_regs
[regno
]
2752 && regno
!= STATUS_REGNUM
&& regno
!= IRET_REGNUM
2753 && regno
!= FP_NEAREST_REGNUM
&& regno
!= FP_TRUNCATE_REGNUM
)
2757 if (regno
== FP_NEAREST_REGNUM
2758 && epiphany_normal_fp_mode
!= FP_MODE_ROUND_TRUNC
)
2760 if (regno
== FP_TRUNCATE_REGNUM
2761 && epiphany_normal_fp_mode
!= FP_MODE_ROUND_NEAREST
)
2767 epiphany_min_divisions_for_recip_mul (machine_mode mode
)
2769 if (flag_reciprocal_math
&& mode
== SFmode
)
2770 /* We'll expand into a multiply-by-reciprocal anyway, so we might a well do
2771 it already at the tree level and expose it to further optimizations. */
2773 return default_min_divisions_for_recip_mul (mode
);
2777 epiphany_preferred_simd_mode (machine_mode mode ATTRIBUTE_UNUSED
)
2779 return TARGET_VECT_DOUBLE
? DImode
: SImode
;
2783 epiphany_vector_mode_supported_p (machine_mode mode
)
2785 if (mode
== V2SFmode
)
2787 if (GET_MODE_CLASS (mode
) == MODE_VECTOR_INT
2788 && (GET_MODE_SIZE (mode
) == 4 || GET_MODE_SIZE (mode
) == 8))
2794 epiphany_vector_alignment_reachable (const_tree type
, bool is_packed
)
2796 /* Vectors which aren't in packed structures will not be less aligned than
2797 the natural alignment of their element type, so this is safe. */
2798 if (TYPE_ALIGN_UNIT (type
) == 4)
2801 return default_builtin_vector_alignment_reachable (type
, is_packed
);
2805 epiphany_support_vector_misalignment (machine_mode mode
, const_tree type
,
2806 int misalignment
, bool is_packed
)
2808 if (GET_MODE_SIZE (mode
) == 8 && misalignment
% 4 == 0)
2810 return default_builtin_support_vector_misalignment (mode
, type
, misalignment
,
2814 /* STRUCTURE_SIZE_BOUNDARY seems a bit crude in how it enlarges small
2815 structs. Make structs double-word-aligned it they are a double word or
2816 (potentially) larger; failing that, do the same for a size of 32 bits. */
2818 epiphany_special_round_type_align (tree type
, unsigned computed
,
2821 unsigned align
= MAX (computed
, specified
);
2823 HOST_WIDE_INT total
, max
;
2824 unsigned try_align
= FASTEST_ALIGNMENT
;
2826 if (maximum_field_alignment
&& try_align
> maximum_field_alignment
)
2827 try_align
= maximum_field_alignment
;
2828 if (align
>= try_align
)
2830 for (max
= 0, field
= TYPE_FIELDS (type
); field
; field
= DECL_CHAIN (field
))
2834 if (TREE_CODE (field
) != FIELD_DECL
2835 || TREE_TYPE (field
) == error_mark_node
)
2837 offset
= bit_position (field
);
2838 size
= DECL_SIZE (field
);
2839 if (!tree_fits_uhwi_p (offset
) || !tree_fits_uhwi_p (size
)
2840 || tree_to_uhwi (offset
) >= try_align
2841 || tree_to_uhwi (size
) >= try_align
)
2843 total
= tree_to_uhwi (offset
) + tree_to_uhwi (size
);
2847 if (max
>= (HOST_WIDE_INT
) try_align
)
2849 else if (try_align
> 32 && max
>= 32)
2850 align
= max
> 32 ? 64 : 32;
2854 /* Upping the alignment of arrays in structs is not only a performance
2855 enhancement, it also helps preserve assumptions about how
2856 arrays-at-the-end-of-structs work, like for struct gcov_fn_info in
2859 epiphany_adjust_field_align (tree type
, unsigned computed
)
2862 && TREE_CODE (type
) == ARRAY_TYPE
)
2864 tree elmsz
= TYPE_SIZE (TREE_TYPE (type
));
2866 if (!tree_fits_uhwi_p (elmsz
) || tree_to_uhwi (elmsz
) >= 32)
2872 /* Output code to add DELTA to the first argument, and then jump
2873 to FUNCTION. Used for C++ multiple inheritance. */
2875 epiphany_output_mi_thunk (FILE *file
, tree thunk ATTRIBUTE_UNUSED
,
2876 HOST_WIDE_INT delta
,
2877 HOST_WIDE_INT vcall_offset
,
2881 = aggregate_value_p (TREE_TYPE (TREE_TYPE (function
)), function
) ? 1 : 0;
2882 const char *this_name
= reg_names
[this_regno
];
2885 /* We use IP and R16 as a scratch registers. */
2886 gcc_assert (call_used_regs
[GPR_IP
]);
2887 gcc_assert (call_used_regs
[GPR_16
]);
2889 /* Add DELTA. When possible use a plain add, otherwise load it into
2890 a register first. */
2893 else if (SIMM11 (delta
))
2894 asm_fprintf (file
, "\tadd\t%s,%s,%d\n", this_name
, this_name
, (int) delta
);
2895 else if (delta
< 0 && delta
>= -0xffff)
2897 asm_fprintf (file
, "\tmov\tip,%d\n", (int) -delta
);
2898 asm_fprintf (file
, "\tsub\t%s,%s,ip\n", this_name
, this_name
);
2902 asm_fprintf (file
, "\tmov\tip,%%low(%ld)\n", (long) delta
);
2903 if (delta
& ~0xffff)
2904 asm_fprintf (file
, "\tmovt\tip,%%high(%ld)\n", (long) delta
);
2905 asm_fprintf (file
, "\tadd\t%s,%s,ip\n", this_name
, this_name
);
2908 /* If needed, add *(*THIS + VCALL_OFFSET) to THIS. */
2909 if (vcall_offset
!= 0)
2911 /* ldr ip,[this] --> temp = *this
2912 ldr ip,[ip,vcall_offset] > temp = *(*this + vcall_offset)
2913 add this,this,ip --> this+ = *(*this + vcall_offset) */
2914 asm_fprintf (file
, "\tldr\tip, [%s]\n", this_name
);
2915 if (vcall_offset
< -0x7ff * 4 || vcall_offset
> 0x7ff * 4
2916 || (vcall_offset
& 3) != 0)
2918 asm_fprintf (file
, "\tmov\tr16, %%low(%ld)\n", (long) vcall_offset
);
2919 asm_fprintf (file
, "\tmovt\tr16, %%high(%ld)\n", (long) vcall_offset
);
2920 asm_fprintf (file
, "\tldr\tip, [ip,r16]\n");
2923 asm_fprintf (file
, "\tldr\tip, [ip,%d]\n", (int) vcall_offset
/ 4);
2924 asm_fprintf (file
, "\tadd\t%s, %s, ip\n", this_name
, this_name
);
2927 fname
= XSTR (XEXP (DECL_RTL (function
), 0), 0);
2928 if (epiphany_is_long_call_p (XEXP (DECL_RTL (function
), 0)))
2930 fputs ("\tmov\tip,%low(", file
);
2931 assemble_name (file
, fname
);
2932 fputs (")\n\tmovt\tip,%high(", file
);
2933 assemble_name (file
, fname
);
2934 fputs (")\n\tjr ip\n", file
);
2938 fputs ("\tb\t", file
);
2939 assemble_name (file
, fname
);
2945 epiphany_start_function (FILE *file
, const char *name
, tree decl
)
2947 /* If the function doesn't fit into the on-chip memory, it will have a
2948 section attribute - or lack of it - that denotes it goes somewhere else.
2949 But the architecture spec says that an interrupt vector still has to
2950 point to on-chip memory. So we must place a jump there to get to the
2951 actual function implementation. The forwarder_section attribute
2952 specifies the section where this jump goes.
2953 This mechanism can also be useful to have a shortcall destination for
2954 a function that is actually placed much farther away. */
2955 tree attrs
, int_attr
, int_names
, int_name
, forwarder_attr
;
2957 attrs
= DECL_ATTRIBUTES (decl
);
2958 int_attr
= lookup_attribute ("interrupt", attrs
);
2960 for (int_names
= TREE_VALUE (int_attr
); int_names
;
2961 int_names
= TREE_CHAIN (int_names
))
2965 int_name
= TREE_VALUE (int_names
);
2966 sprintf (buf
, "ivt_entry_%.80s", TREE_STRING_POINTER (int_name
));
2967 switch_to_section (get_section (buf
, SECTION_CODE
, decl
));
2968 fputs ("\tb\t", file
);
2969 assemble_name (file
, name
);
2972 forwarder_attr
= lookup_attribute ("forwarder_section", attrs
);
2975 const char *prefix
= "__forwarder_dst_";
2976 char *dst_name
= (char *) alloca (strlen (prefix
) + strlen (name
) + 1);
2978 strcpy (dst_name
, prefix
);
2979 strcat (dst_name
, name
);
2980 forwarder_attr
= TREE_VALUE (TREE_VALUE (forwarder_attr
));
2981 switch_to_section (get_section (TREE_STRING_POINTER (forwarder_attr
),
2982 SECTION_CODE
, decl
));
2983 ASM_OUTPUT_FUNCTION_LABEL (file
, name
, decl
);
2984 if (epiphany_is_long_call_p (XEXP (DECL_RTL (decl
), 0)))
2989 fputs ("\tstrd r0,[sp,-1]\n", file
);
2992 gcc_assert (call_used_regs
[tmp
]);
2993 fprintf (file
, "\tmov r%d,%%low(", tmp
);
2994 assemble_name (file
, dst_name
);
2995 fprintf (file
, ")\n"
2996 "\tmovt r%d,%%high(", tmp
);
2997 assemble_name (file
, dst_name
);
2998 fprintf (file
, ")\n"
3003 fputs ("\tb\t", file
);
3004 assemble_name (file
, dst_name
);
3009 switch_to_section (function_section (decl
));
3010 ASM_OUTPUT_FUNCTION_LABEL (file
, name
, decl
);
3013 struct gcc_target targetm
= TARGET_INITIALIZER
;