1 /* Subroutines used for code generation on the Synopsys DesignWare ARC cpu.
2 Copyright (C) 1994-2024 Free Software Foundation, Inc.
4 Sources derived from work done by Sankhya Technologies (www.sankhya.com) on
5 behalf of Synopsys Inc.
7 Position Independent Code support added,Code cleaned up,
8 Comments and Support For ARC700 instructions added by
9 Saurabh Verma (saurabh.verma@codito.com)
10 Ramana Radhakrishnan(ramana.radhakrishnan@codito.com)
12 Fixing ABI inconsistencies, optimizations for ARC600 / ARC700 pipelines,
13 profiling support added by Joern Rennecke <joern.rennecke@embecosm.com>
15 This file is part of GCC.
17 GCC is free software; you can redistribute it and/or modify
18 it under the terms of the GNU General Public License as published by
19 the Free Software Foundation; either version 3, or (at your option)
22 GCC is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 GNU General Public License for more details.
27 You should have received a copy of the GNU General Public License
28 along with GCC; see the file COPYING3. If not see
29 <http://www.gnu.org/licenses/>. */
31 #define IN_TARGET_CODE 1
35 #include "coretypes.h"
44 #include "stringpool.h"
50 #include "diagnostic.h"
51 #include "fold-const.h"
53 #include "stor-layout.h"
56 #include "insn-attr.h"
60 #include "langhooks.h"
61 #include "tm-constrs.h"
62 #include "reload.h" /* For operands_match_p */
64 #include "tree-pass.h"
70 #include "hw-doloop.h"
71 #include "targhooks.h"
72 #include "case-cfn-macros.h"
74 /* Which cpu we're compiling for (ARC600, ARC601, ARC700). */
75 static char arc_cpu_name
[10] = "";
76 static const char *arc_cpu_string
= arc_cpu_name
;
78 typedef struct GTY (()) _arc_jli_section
81 struct _arc_jli_section
*next
;
84 static arc_jli_section
*arc_jli_sections
= NULL
;
86 /* Track which regs are set fixed/call saved/call used from commnad line. */
87 HARD_REG_SET overrideregs
;
89 /* Maximum size of a loop. */
90 #define ARC_MAX_LOOP_LENGTH 4095
92 /* Check if an rtx fits in the store instruction format. Loads can
93 handle any constant. */
94 #define RTX_OK_FOR_OFFSET_P(MODE, X) \
95 (GET_CODE (X) == CONST_INT \
96 && SMALL_INT_RANGE (INTVAL (X), (GET_MODE_SIZE (MODE) - 1) & (~0x03), \
97 (INTVAL (X) & (GET_MODE_SIZE (MODE) - 1) & 3 \
99 : -(-GET_MODE_SIZE (MODE) | (~0x03)) >> 1)))
101 /* Array of valid operand punctuation characters. */
102 char arc_punct_chars
[256];
104 /* Status of the IRQ_CTRL_AUX register. */
105 typedef struct irq_ctrl_saved_t
107 /* Last register number used by IRQ_CTRL_SAVED aux_reg. */
108 short irq_save_last_reg
;
109 /* True if BLINK is automatically saved. */
111 /* True if LPCOUNT is automatically saved. */
112 bool irq_save_lpcount
;
114 static irq_ctrl_saved_t irq_ctrl_saved
;
116 #define ARC_AUTOBLINK_IRQ_P(FNTYPE) \
117 ((ARC_INTERRUPT_P (FNTYPE) \
118 && irq_ctrl_saved.irq_save_blink) \
119 || (ARC_FAST_INTERRUPT_P (FNTYPE) \
120 && rgf_banked_register_count > 8))
122 #define ARC_AUTOFP_IRQ_P(FNTYPE) \
123 ((ARC_INTERRUPT_P (FNTYPE) \
124 && (irq_ctrl_saved.irq_save_last_reg > 26)) \
125 || (ARC_FAST_INTERRUPT_P (FNTYPE) \
126 && rgf_banked_register_count > 8))
128 #define ARC_AUTO_IRQ_P(FNTYPE) \
129 (ARC_INTERRUPT_P (FNTYPE) && !ARC_FAST_INTERRUPT_P (FNTYPE) \
130 && (irq_ctrl_saved.irq_save_blink \
131 || (irq_ctrl_saved.irq_save_last_reg >= 0)))
133 /* Number of registers in second bank for FIRQ support. */
134 static int rgf_banked_register_count
;
136 /* Start enter/leave register range. */
137 #define ENTER_LEAVE_START_REG 13
139 /* End enter/leave register range. */
140 #define ENTER_LEAVE_END_REG 26
142 /* The maximum number of insns skipped which will be conditionalised if
144 /* When optimizing for speed:
145 Let p be the probability that the potentially skipped insns need to
146 be executed, pn the cost of a correctly predicted non-taken branch,
147 mt the cost of a mis/non-predicted taken branch,
148 mn mispredicted non-taken, pt correctly predicted taken ;
149 costs expressed in numbers of instructions like the ones considered
151 Unfortunately we don't have a measure of predictability - this
152 is linked to probability only in that in the no-eviction-scenario
153 there is a lower bound 1 - 2 * min (p, 1-p), and a somewhat larger
154 value that can be assumed *if* the distribution is perfectly random.
155 A predictability of 1 is perfectly plausible not matter what p is,
156 because the decision could be dependent on an invocation parameter
158 For large p, we want MAX_INSNS_SKIPPED == pn/(1-p) + mt - pn
159 For small p, we want MAX_INSNS_SKIPPED == pt
161 When optimizing for size:
162 We want to skip insn unless we could use 16 opcodes for the
163 non-conditionalized insn to balance the branch length or more.
164 Performance can be tie-breaker. */
165 /* If the potentially-skipped insns are likely to be executed, we'll
166 generally save one non-taken branch
168 this to be no less than the 1/p */
169 #define MAX_INSNS_SKIPPED 3
171 /* ZOL control registers. */
172 #define AUX_LP_START 0x02
173 #define AUX_LP_END 0x03
175 /* FPX AUX registers. */
176 #define AUX_DPFP_START 0x301
178 /* ARC600 MULHI register. */
179 #define AUX_MULHI 0x12
181 static int get_arc_condition_code (rtx
);
183 static tree
arc_handle_interrupt_attribute (tree
*, tree
, tree
, int, bool *);
184 static tree
arc_handle_fndecl_attribute (tree
*, tree
, tree
, int, bool *);
185 static tree
arc_handle_jli_attribute (tree
*, tree
, tree
, int, bool *);
186 static tree
arc_handle_secure_attribute (tree
*, tree
, tree
, int, bool *);
187 static tree
arc_handle_uncached_attribute (tree
*, tree
, tree
, int, bool *);
188 static tree
arc_handle_aux_attribute (tree
*, tree
, tree
, int, bool *);
190 static int arc_comp_type_attributes (const_tree
, const_tree
);
191 static void arc_file_start (void);
192 static void arc_internal_label (FILE *, const char *, unsigned long);
193 static void arc_output_mi_thunk (FILE *, tree
, HOST_WIDE_INT
, HOST_WIDE_INT
,
195 static int arc_address_cost (rtx
, machine_mode
, addr_space_t
, bool);
196 static void arc_encode_section_info (tree decl
, rtx rtl
, int first
);
198 static void arc_init_builtins (void);
199 static rtx
arc_expand_builtin (tree
, rtx
, rtx
, machine_mode
, int);
201 static int branch_dest (rtx
);
203 static void arc_output_pic_addr_const (FILE *, rtx
, int);
204 static bool arc_function_ok_for_sibcall (tree
, tree
);
205 static rtx
arc_function_value (const_tree
, const_tree
, bool);
206 static void arc_reorg (void);
207 static bool arc_in_small_data_p (const_tree
);
209 static void arc_init_reg_tables (void);
210 static bool arc_return_in_memory (const_tree
, const_tree
);
211 static bool arc_vector_mode_supported_p (machine_mode
);
213 static bool arc_can_use_doloop_p (const widest_int
&, const widest_int
&,
215 static const char *arc_invalid_within_doloop (const rtx_insn
*);
217 static void output_short_suffix (FILE *file
);
219 static bool arc_frame_pointer_required (void);
221 static bool arc_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT
,
223 enum by_pieces_operation op
,
226 /* Globally visible information about currently selected cpu. */
227 const arc_cpu_t
*arc_selected_cpu
;
229 /* Traditionally, we push saved registers first in the prologue,
230 then we allocate the rest of the frame - and reverse in the epilogue.
231 This has still its merits for ease of debugging, or saving code size
232 or even execution time if the stack frame is so large that some accesses
233 can't be encoded anymore with offsets in the instruction code when using
235 Also, it would be a good starting point if we got instructions to help
236 with register save/restore.
238 However, often stack frames are small, and the pushing / popping has
240 - the stack modification prevents a lot of scheduling.
241 - frame allocation / deallocation may need extra instructions.
242 - we need to place a memory barrier after frame allocation to avoid
243 the delay slot scheduler to reschedule a frame related info and
244 messing up with dwarf unwinding. The barrier before deallocation
245 is for flushing all pending sp operations.
247 Thus, for small frames, we'd like to use a different scheme:
248 - The frame is allocated in full with the first prologue instruction,
249 and deallocated in full with the last epilogue instruction.
250 Thus, the instructions in-between can be freely scheduled.
251 - If the function has no outgoing arguments on the stack, we can allocate
252 one register save slot at the top of the stack. This register can then
253 be saved simultaneously with frame allocation, and restored with
255 This register can be picked depending on scheduling considerations,
256 although same though should go into having some set of registers
257 to be potentially lingering after a call, and others to be available
258 immediately - i.e. in the absence of interprocedual optimization, we
259 can use an ABI-like convention for register allocation to reduce
260 stalls after function return. */
262 /* ARCompact stack frames look like:
264 Before call After call
265 high +-----------------------+ +-----------------------+
266 mem | reg parm save area | | reg parm save area |
267 | only created for | | only created for |
268 | variable arg fns | | variable arg fns |
269 AP +-----------------------+ +-----------------------+
270 | return addr register | | return addr register |
271 | (if required) | | (if required) |
272 +-----------------------+ +-----------------------+
274 | reg save area | | reg save area |
276 +-----------------------+ +-----------------------+
277 | frame pointer | | frame pointer |
278 | (if required) | | (if required) |
279 FP +-----------------------+ +-----------------------+
281 | local/temp variables | | local/temp variables |
283 +-----------------------+ +-----------------------+
285 | arguments on stack | | arguments on stack |
287 SP +-----------------------+ +-----------------------+
288 | reg parm save area |
291 AP +-----------------------+
292 | return addr register |
294 +-----------------------+
298 +-----------------------+
301 FP +-----------------------+
303 | local/temp variables |
305 +-----------------------+
307 | arguments on stack |
309 mem SP +-----------------------+
312 1) The "reg parm save area" does not exist for non variable argument fns.
313 The "reg parm save area" can be eliminated completely if we created our
314 own va-arc.h, but that has tradeoffs as well (so it's not done). */
316 /* Structure to be filled in by arc_compute_frame_size with register
317 save masks, and offsets for the current function. */
318 struct GTY (()) arc_frame_info
320 unsigned int total_size
; /* # bytes that the entire frame takes up. */
321 unsigned int extra_size
; /* # bytes of extra stuff. */
322 unsigned int pretend_size
; /* # bytes we push and pretend caller did. */
323 unsigned int args_size
; /* # bytes that outgoing arguments take up. */
324 unsigned int reg_size
; /* # bytes needed to store regs. */
325 unsigned int var_size
; /* # bytes that variables take up. */
326 uint64_t gmask
; /* Mask of saved gp registers. */
327 bool initialized
; /* FALSE if frame size already calculated. */
328 short millicode_start_reg
;
329 short millicode_end_reg
;
330 bool save_return_addr
;
333 /* GMASK bit length -1. */
336 /* Defining data structures for per-function information. */
338 typedef struct GTY (()) machine_function
340 unsigned int fn_type
;
341 struct arc_frame_info frame_info
;
342 char arc_reorg_started
;
343 char prescan_initialized
;
347 /* Given a symbol RTX (const (symb <+ const_int>), returns its
351 get_symbol_alignment (rtx x
)
353 tree decl
= NULL_TREE
;
356 switch (GET_CODE (x
))
359 decl
= SYMBOL_REF_DECL (x
);
362 return get_symbol_alignment (XEXP (x
, 0));
364 gcc_assert (CONST_INT_P (XEXP (x
, 1)));
365 return get_symbol_alignment (XEXP (x
, 0));
371 align
= DECL_ALIGN (decl
);
372 align
= align
/ BITS_PER_UNIT
;
376 /* Return true if x is ok to be used as a small data address. */
379 legitimate_small_data_address_p (rtx x
, machine_mode mode
)
381 switch (GET_CODE (x
))
384 return legitimate_small_data_address_p (XEXP (x
, 0), mode
);
386 return SYMBOL_REF_SMALL_P (x
);
389 bool p0
= (GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
)
390 && SYMBOL_REF_SMALL_P (XEXP (x
, 0));
392 /* If no constant then we cannot do small data. */
393 if (!CONST_INT_P (XEXP (x
, 1)))
396 /* Small data relocs works with scalled addresses, check if
397 the immediate fits the requirements. */
398 switch (GET_MODE_SIZE (mode
))
403 return p0
&& ((INTVAL (XEXP (x
, 1)) & 0x1) == 0);
406 return p0
&& ((INTVAL (XEXP (x
, 1)) & 0x3) == 0);
416 /* TRUE if op is an scaled address. */
418 legitimate_scaled_address_p (machine_mode mode
, rtx op
, bool strict
)
420 if (GET_CODE (op
) != PLUS
)
423 if (GET_CODE (XEXP (op
, 0)) != MULT
)
426 /* Check multiplication operands. */
427 if (!RTX_OK_FOR_INDEX_P (XEXP (XEXP (op
, 0), 0), strict
))
430 if (!CONST_INT_P (XEXP (XEXP (op
, 0), 1)))
433 switch (GET_MODE_SIZE (mode
))
436 if (INTVAL (XEXP (XEXP (op
, 0), 1)) != 2)
444 if (INTVAL (XEXP (XEXP (op
, 0), 1)) != 4)
451 /* Check the base. */
452 if (RTX_OK_FOR_BASE_P (XEXP (op
, 1), (strict
)))
457 if (CONST_INT_P (XEXP (op
, 1)))
462 /* Scalled addresses for sdata is done other places. */
463 if (legitimate_small_data_address_p (op
, mode
))
466 if (CONSTANT_P (XEXP (op
, 1)))
472 /* Check for constructions like REG + OFFS, where OFFS can be a
473 register, an immediate or an long immediate. */
476 legitimate_offset_address_p (machine_mode mode
, rtx x
, bool index
, bool strict
)
478 if (GET_CODE (x
) != PLUS
)
481 if (!RTX_OK_FOR_BASE_P (XEXP (x
, 0), (strict
)))
484 /* Check for: [Rx + small offset] or [Rx + Ry]. */
485 if (((index
&& RTX_OK_FOR_INDEX_P (XEXP (x
, 1), (strict
))
486 && GET_MODE_SIZE ((mode
)) <= 4)
487 || RTX_OK_FOR_OFFSET_P (mode
, XEXP (x
, 1))))
490 /* Check for [Rx + symbol]. */
492 && (GET_CODE (XEXP (x
, 1)) == SYMBOL_REF
)
493 /* Avoid this type of address for double or larger modes. */
494 && (GET_MODE_SIZE (mode
) <= 4)
495 /* Avoid small data which ends in something like GP +
497 && (!SYMBOL_REF_SMALL_P (XEXP (x
, 1))))
503 /* Implements target hook vector_mode_supported_p. */
506 arc_vector_mode_supported_p (machine_mode mode
)
511 return TARGET_PLUS_DMPY
;
514 return TARGET_PLUS_QMACW
;
517 return TARGET_SIMD_SET
;
524 /* Implements target hook TARGET_VECTORIZE_PREFERRED_SIMD_MODE. */
527 arc_preferred_simd_mode (scalar_mode mode
)
532 return TARGET_PLUS_QMACW
? V4HImode
: V2HImode
;
541 /* Implements target hook
542 TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES. */
545 arc_autovectorize_vector_modes (vector_modes
*modes
, bool)
547 if (TARGET_PLUS_QMACW
)
549 modes
->quick_push (V4HImode
);
550 modes
->quick_push (V2HImode
);
556 /* Implements target hook TARGET_SCHED_ISSUE_RATE. */
558 arc_sched_issue_rate (void)
562 case ARC_TUNE_ARCHS4X
:
563 case ARC_TUNE_ARCHS4XD
:
571 /* TARGET_PRESERVE_RELOAD_P is still awaiting patch re-evaluation / review. */
572 static bool arc_preserve_reload_p (rtx in
) ATTRIBUTE_UNUSED
;
573 static rtx
arc_delegitimize_address (rtx
);
574 static bool arc_can_follow_jump (const rtx_insn
*follower
,
575 const rtx_insn
*followee
);
577 static rtx
frame_insn (rtx
);
578 static void arc_function_arg_advance (cumulative_args_t
,
579 const function_arg_info
&);
580 static rtx
arc_legitimize_address_0 (rtx
, rtx
, machine_mode mode
);
582 /* initialize the GCC target structure. */
583 #undef TARGET_COMP_TYPE_ATTRIBUTES
584 #define TARGET_COMP_TYPE_ATTRIBUTES arc_comp_type_attributes
585 #undef TARGET_ASM_FILE_START
586 #define TARGET_ASM_FILE_START arc_file_start
587 #undef TARGET_ATTRIBUTE_TABLE
588 #define TARGET_ATTRIBUTE_TABLE arc_attribute_table
589 #undef TARGET_ASM_INTERNAL_LABEL
590 #define TARGET_ASM_INTERNAL_LABEL arc_internal_label
591 #undef TARGET_RTX_COSTS
592 #define TARGET_RTX_COSTS arc_rtx_costs
593 #undef TARGET_ADDRESS_COST
594 #define TARGET_ADDRESS_COST arc_address_cost
596 #undef TARGET_ENCODE_SECTION_INFO
597 #define TARGET_ENCODE_SECTION_INFO arc_encode_section_info
599 #undef TARGET_CANNOT_FORCE_CONST_MEM
600 #define TARGET_CANNOT_FORCE_CONST_MEM arc_cannot_force_const_mem
602 #undef TARGET_INIT_BUILTINS
603 #define TARGET_INIT_BUILTINS arc_init_builtins
605 #undef TARGET_EXPAND_BUILTIN
606 #define TARGET_EXPAND_BUILTIN arc_expand_builtin
608 #undef TARGET_FOLD_BUILTIN
609 #define TARGET_FOLD_BUILTIN arc_fold_builtin
611 #undef TARGET_BUILTIN_DECL
612 #define TARGET_BUILTIN_DECL arc_builtin_decl
614 #undef TARGET_ASM_OUTPUT_MI_THUNK
615 #define TARGET_ASM_OUTPUT_MI_THUNK arc_output_mi_thunk
617 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
618 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
620 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
621 #define TARGET_FUNCTION_OK_FOR_SIBCALL arc_function_ok_for_sibcall
623 #undef TARGET_MACHINE_DEPENDENT_REORG
624 #define TARGET_MACHINE_DEPENDENT_REORG arc_reorg
626 #undef TARGET_IN_SMALL_DATA_P
627 #define TARGET_IN_SMALL_DATA_P arc_in_small_data_p
629 #undef TARGET_PROMOTE_FUNCTION_MODE
630 #define TARGET_PROMOTE_FUNCTION_MODE \
631 default_promote_function_mode_always_promote
633 #undef TARGET_PROMOTE_PROTOTYPES
634 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
636 #undef TARGET_RETURN_IN_MEMORY
637 #define TARGET_RETURN_IN_MEMORY arc_return_in_memory
638 #undef TARGET_PASS_BY_REFERENCE
639 #define TARGET_PASS_BY_REFERENCE arc_pass_by_reference
641 #undef TARGET_SETUP_INCOMING_VARARGS
642 #define TARGET_SETUP_INCOMING_VARARGS arc_setup_incoming_varargs
644 #undef TARGET_ARG_PARTIAL_BYTES
645 #define TARGET_ARG_PARTIAL_BYTES arc_arg_partial_bytes
647 #undef TARGET_MUST_PASS_IN_STACK
648 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
650 #undef TARGET_FUNCTION_VALUE
651 #define TARGET_FUNCTION_VALUE arc_function_value
653 #undef TARGET_SCHED_ADJUST_PRIORITY
654 #define TARGET_SCHED_ADJUST_PRIORITY arc_sched_adjust_priority
656 #undef TARGET_SCHED_ISSUE_RATE
657 #define TARGET_SCHED_ISSUE_RATE arc_sched_issue_rate
659 #undef TARGET_VECTOR_MODE_SUPPORTED_P
660 #define TARGET_VECTOR_MODE_SUPPORTED_P arc_vector_mode_supported_p
662 #undef TARGET_VECTORIZE_PREFERRED_SIMD_MODE
663 #define TARGET_VECTORIZE_PREFERRED_SIMD_MODE arc_preferred_simd_mode
665 #undef TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES
666 #define TARGET_VECTORIZE_AUTOVECTORIZE_VECTOR_MODES arc_autovectorize_vector_modes
668 #undef TARGET_CAN_USE_DOLOOP_P
669 #define TARGET_CAN_USE_DOLOOP_P arc_can_use_doloop_p
671 #undef TARGET_INVALID_WITHIN_DOLOOP
672 #define TARGET_INVALID_WITHIN_DOLOOP arc_invalid_within_doloop
674 #undef TARGET_PRESERVE_RELOAD_P
675 #define TARGET_PRESERVE_RELOAD_P arc_preserve_reload_p
677 #undef TARGET_CAN_FOLLOW_JUMP
678 #define TARGET_CAN_FOLLOW_JUMP arc_can_follow_jump
680 #undef TARGET_DELEGITIMIZE_ADDRESS
681 #define TARGET_DELEGITIMIZE_ADDRESS arc_delegitimize_address
683 #undef TARGET_USE_BY_PIECES_INFRASTRUCTURE_P
684 #define TARGET_USE_BY_PIECES_INFRASTRUCTURE_P \
685 arc_use_by_pieces_infrastructure_p
687 /* Usually, we will be able to scale anchor offsets.
688 When this fails, we want LEGITIMIZE_ADDRESS to kick in. */
689 #undef TARGET_MIN_ANCHOR_OFFSET
690 #define TARGET_MIN_ANCHOR_OFFSET (-1024)
691 #undef TARGET_MAX_ANCHOR_OFFSET
692 #define TARGET_MAX_ANCHOR_OFFSET (1020)
694 #undef TARGET_SECONDARY_RELOAD
695 #define TARGET_SECONDARY_RELOAD arc_secondary_reload
697 #define TARGET_OPTION_OVERRIDE arc_override_options
699 #define TARGET_CONDITIONAL_REGISTER_USAGE arc_conditional_register_usage
701 #define TARGET_TRAMPOLINE_INIT arc_initialize_trampoline
703 #define TARGET_CAN_ELIMINATE arc_can_eliminate
705 #define TARGET_FRAME_POINTER_REQUIRED arc_frame_pointer_required
707 #define TARGET_FUNCTION_ARG arc_function_arg
709 #define TARGET_FUNCTION_ARG_ADVANCE arc_function_arg_advance
711 #define TARGET_LEGITIMATE_CONSTANT_P arc_legitimate_constant_p
713 #define TARGET_LEGITIMATE_ADDRESS_P arc_legitimate_address_p
715 #define TARGET_MODE_DEPENDENT_ADDRESS_P arc_mode_dependent_address_p
717 #define TARGET_LEGITIMIZE_ADDRESS arc_legitimize_address
719 #undef TARGET_NO_SPECULATION_IN_DELAY_SLOTS_P
720 #define TARGET_NO_SPECULATION_IN_DELAY_SLOTS_P \
721 arc_no_speculation_in_delay_slots_p
724 #define TARGET_LRA_P arc_lra_p
725 #define TARGET_REGISTER_PRIORITY arc_register_priority
726 /* Stores with scaled offsets have different displacement ranges. */
727 #define TARGET_DIFFERENT_ADDR_DISPLACEMENT_P hook_bool_void_true
728 #define TARGET_SPILL_CLASS arc_spill_class
730 #undef TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS
731 #define TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS arc_allocate_stack_slots_for_args
733 #undef TARGET_WARN_FUNC_RETURN
734 #define TARGET_WARN_FUNC_RETURN arc_warn_func_return
736 #include "target-def.h"
738 TARGET_GNU_ATTRIBUTES (arc_attribute_table
,
740 /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
741 affects_type_identity, handler, exclude } */
742 { "interrupt", 1, 1, true, false, false, true,
743 arc_handle_interrupt_attribute
, NULL
},
744 /* Function calls made to this symbol must be done indirectly, because
745 it may lie outside of the 21/25 bit addressing range of a normal function
747 { "long_call", 0, 0, false, true, true, false, NULL
, NULL
},
748 /* Whereas these functions are always known to reside within the 25 bit
749 addressing range of unconditionalized bl. */
750 { "medium_call", 0, 0, false, true, true, false, NULL
, NULL
},
751 /* And these functions are always known to reside within the 21 bit
752 addressing range of blcc. */
753 { "short_call", 0, 0, false, true, true, false, NULL
, NULL
},
754 /* Function which are not having the prologue and epilogue generated
756 { "naked", 0, 0, true, false, false, false, arc_handle_fndecl_attribute
,
758 /* Functions calls made using jli instruction. The pointer in JLI
759 table is found latter. */
760 { "jli_always", 0, 0, false, true, true, false, NULL
, NULL
},
761 /* Functions calls made using jli instruction. The pointer in JLI
762 table is given as input parameter. */
763 { "jli_fixed", 1, 1, false, true, true, false, arc_handle_jli_attribute
,
765 /* Call a function using secure-mode. */
766 { "secure_call", 1, 1, false, true, true, false, arc_handle_secure_attribute
,
768 /* Bypass caches using .di flag. */
769 { "uncached", 0, 0, false, true, false, false, arc_handle_uncached_attribute
,
771 { "aux", 0, 1, true, false, false, false, arc_handle_aux_attribute
, NULL
}
774 #undef TARGET_ASM_ALIGNED_HI_OP
775 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
776 #undef TARGET_ASM_ALIGNED_SI_OP
777 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
780 #undef TARGET_HAVE_TLS
781 #define TARGET_HAVE_TLS HAVE_AS_TLS
784 #undef TARGET_DWARF_REGISTER_SPAN
785 #define TARGET_DWARF_REGISTER_SPAN arc_dwarf_register_span
787 #undef TARGET_HARD_REGNO_NREGS
788 #define TARGET_HARD_REGNO_NREGS arc_hard_regno_nregs
789 #undef TARGET_HARD_REGNO_MODE_OK
790 #define TARGET_HARD_REGNO_MODE_OK arc_hard_regno_mode_ok
792 #undef TARGET_MODES_TIEABLE_P
793 #define TARGET_MODES_TIEABLE_P arc_modes_tieable_p
795 /* Try to keep the (mov:DF _, reg) as early as possible so
796 that the d<add/sub/mul>h-lr insns appear together and can
797 use the peephole2 pattern. */
800 arc_sched_adjust_priority (rtx_insn
*insn
, int priority
)
802 rtx set
= single_set (insn
);
804 && GET_MODE (SET_SRC(set
)) == DFmode
805 && GET_CODE (SET_SRC(set
)) == REG
)
807 /* Incrementing priority by 20 (empirically derived). */
808 return priority
+ 20;
814 /* For ARC base register + offset addressing, the validity of the
815 address is mode-dependent for most of the offset range, as the
816 offset can be scaled by the access size.
817 We don't expose these as mode-dependent addresses in the
818 mode_dependent_address_p target hook, because that would disable
819 lots of optimizations, and most uses of these addresses are for 32
820 or 64 bit accesses anyways, which are fine.
821 However, that leaves some addresses for 8 / 16 bit values not
822 properly reloaded by the generic code, which is why we have to
823 schedule secondary reloads for these. */
826 arc_secondary_reload (bool in_p
,
830 secondary_reload_info
*sri
)
832 enum rtx_code code
= GET_CODE (x
);
834 if (cl
== DOUBLE_REGS
)
837 /* If we have a subreg (reg), where reg is a pseudo (that will end in
838 a memory location), then we may need a scratch register to handle
839 the fp/sp+largeoffset address. */
847 int regno
= REGNO (x
);
848 if (regno
>= FIRST_PSEUDO_REGISTER
)
849 regno
= reg_renumber
[regno
];
854 /* It is a pseudo that ends in a stack location. This
855 procedure only works with the old reload step. */
856 if (!lra_in_progress
&& reg_equiv_mem (REGNO (x
)))
858 /* Get the equivalent address and check the range of the
860 rtx mem
= reg_equiv_mem (REGNO (x
));
861 addr
= find_replacement (&XEXP (mem
, 0));
866 gcc_assert (MEM_P (x
));
868 addr
= simplify_rtx (addr
);
870 if (addr
&& GET_CODE (addr
) == PLUS
871 && CONST_INT_P (XEXP (addr
, 1))
872 && (!RTX_OK_FOR_OFFSET_P (mode
, XEXP (addr
, 1))))
878 in_p
? CODE_FOR_reload_qi_load
: CODE_FOR_reload_qi_store
;
882 in_p
? CODE_FOR_reload_hi_load
: CODE_FOR_reload_hi_store
;
892 /* Convert reloads using offsets that are too large to use indirect
896 arc_secondary_reload_conv (rtx reg
, rtx mem
, rtx scratch
, bool store_p
)
900 gcc_assert (GET_CODE (mem
) == MEM
);
901 addr
= XEXP (mem
, 0);
903 /* Large offset: use a move. FIXME: ld ops accepts limms as
904 offsets. Hence, the following move insn is not required. */
905 emit_move_insn (scratch
, addr
);
906 mem
= replace_equiv_address_nv (mem
, scratch
);
908 /* Now create the move. */
910 emit_insn (gen_rtx_SET (mem
, reg
));
912 emit_insn (gen_rtx_SET (reg
, mem
));
917 static unsigned arc_predicate_delay_insns (void);
921 const pass_data pass_data_arc_predicate_delay_insns
=
924 "arc_predicate_delay_insns", /* name */
925 OPTGROUP_NONE
, /* optinfo_flags */
926 TV_IFCVT2
, /* tv_id */
927 0, /* properties_required */
928 0, /* properties_provided */
929 0, /* properties_destroyed */
930 0, /* todo_flags_start */
931 TODO_df_finish
/* todo_flags_finish */
934 class pass_arc_predicate_delay_insns
: public rtl_opt_pass
937 pass_arc_predicate_delay_insns(gcc::context
*ctxt
)
938 : rtl_opt_pass(pass_data_arc_predicate_delay_insns
, ctxt
)
941 /* opt_pass methods: */
942 virtual unsigned int execute (function
*)
944 return arc_predicate_delay_insns ();
946 virtual bool gate (function
*)
948 return flag_delayed_branch
;
955 make_pass_arc_predicate_delay_insns (gcc::context
*ctxt
)
957 return new pass_arc_predicate_delay_insns (ctxt
);
960 /* Called by OVERRIDE_OPTIONS to initialize various things. */
967 /* I have the multiplier, then use it*/
968 if (TARGET_MPYW
|| TARGET_MULTI
)
969 arc_multcost
= COSTS_N_INSNS (1);
971 /* Note: arc_multcost is only used in rtx_cost if speed is true. */
972 if (arc_multcost
< 0)
975 case ARC_TUNE_ARC700_4_2_STD
:
977 max throughput (1 multiply + 4 other insns) / 5 cycles. */
978 arc_multcost
= COSTS_N_INSNS (4);
979 if (TARGET_NOMPY_SET
)
980 arc_multcost
= COSTS_N_INSNS (30);
982 case ARC_TUNE_ARC700_4_2_XMAC
:
984 max throughput (1 multiply + 2 other insns) / 3 cycles. */
985 arc_multcost
= COSTS_N_INSNS (3);
986 if (TARGET_NOMPY_SET
)
987 arc_multcost
= COSTS_N_INSNS (30);
989 case ARC_TUNE_ARC600
:
990 if (TARGET_MUL64_SET
)
992 arc_multcost
= COSTS_N_INSNS (4);
997 arc_multcost
= COSTS_N_INSNS (30);
1001 /* MPY instructions valid only for ARC700 or ARCv2. */
1002 if (TARGET_NOMPY_SET
&& TARGET_ARC600_FAMILY
)
1003 error ("%<-mno-mpy%> supported only for ARC700 or ARCv2");
1005 if (!TARGET_DPFP
&& TARGET_DPFP_DISABLE_LRSR
)
1006 error ("%<-mno-dpfp-lrsr%> supported only with %<-mdpfp%>");
1008 /* FPX-1. No fast and compact together. */
1009 if ((TARGET_DPFP_FAST_SET
&& TARGET_DPFP_COMPACT_SET
)
1010 || (TARGET_SPFP_FAST_SET
&& TARGET_SPFP_COMPACT_SET
))
1011 error ("FPX fast and compact options cannot be specified together");
1013 /* FPX-2. No fast-spfp for arc600 or arc601. */
1014 if (TARGET_SPFP_FAST_SET
&& TARGET_ARC600_FAMILY
)
1015 error ("%<-mspfp_fast%> not available on ARC600 or ARC601");
1017 /* FPX-4. No FPX extensions mixed with FPU extensions. */
1018 if ((TARGET_DPFP_FAST_SET
|| TARGET_DPFP_COMPACT_SET
|| TARGET_SPFP
)
1019 && TARGET_HARD_FLOAT
)
1020 error ("no FPX/FPU mixing allowed");
1022 /* Warn for unimplemented PIC in pre-ARC700 cores, and disable flag_pic. */
1023 if (flag_pic
&& TARGET_ARC600_FAMILY
)
1025 warning (0, "PIC is not supported for %qs",
1030 arc_init_reg_tables ();
1032 /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P. */
1033 memset (arc_punct_chars
, 0, sizeof (arc_punct_chars
));
1034 arc_punct_chars
['*'] = 1;
1035 arc_punct_chars
['?'] = 1;
1036 arc_punct_chars
['!'] = 1;
1037 arc_punct_chars
['+'] = 1;
1038 arc_punct_chars
['_'] = 1;
1041 /* Parse -mirq-ctrl-saved=RegisterRange, blink, lp_copunt. The
1042 register range is specified as two registers separated by a dash.
1043 It always starts with r0, and its upper limit is fp register.
1044 blink and lp_count registers are optional. */
1047 irq_range (const char *cstr
)
1049 int i
, first
, last
, blink
, lpcount
, xreg
;
1050 char *str
, *dash
, *comma
;
1053 str
= (char *) alloca (i
+ 1);
1054 memcpy (str
, cstr
, i
+ 1);
1058 dash
= strchr (str
, '-');
1061 warning (OPT_mirq_ctrl_saved_
, "missing dash");
1066 comma
= strchr (dash
+ 1, ',');
1070 first
= decode_reg_name (str
);
1073 warning (OPT_mirq_ctrl_saved_
, "first register must be R0");
1077 /* At this moment we do not have the register names initialized
1079 if (!strcmp (dash
+ 1, "ilink"))
1082 last
= decode_reg_name (dash
+ 1);
1086 warning (OPT_mirq_ctrl_saved_
, "unknown register name: %s", dash
+ 1);
1092 warning (OPT_mirq_ctrl_saved_
,
1093 "last register name %s must be an odd register", dash
+ 1);
1101 warning (OPT_mirq_ctrl_saved_
,
1102 "%s-%s is an empty range", str
, dash
+ 1);
1111 comma
= strchr (str
, ',');
1115 xreg
= decode_reg_name (str
);
1127 warning (OPT_mirq_ctrl_saved_
,
1128 "unknown register name: %s", str
);
1133 irq_ctrl_saved
.irq_save_last_reg
= last
;
1134 irq_ctrl_saved
.irq_save_blink
= (blink
== 31) || (last
== 31);
1135 irq_ctrl_saved
.irq_save_lpcount
= (lpcount
== 60);
1138 /* Parse -mrgf-banked-regs=NUM option string. Valid values for NUM are 4,
1142 parse_mrgf_banked_regs_option (const char *arg
)
1148 val
= strtol (arg
, &end_ptr
, 10);
1149 if (errno
!= 0 || *arg
== '\0' || *end_ptr
!= '\0'
1150 || (val
!= 0 && val
!= 4 && val
!= 8 && val
!= 16 && val
!= 32))
1152 error ("invalid number in %<-mrgf-banked-regs=%s%> "
1153 "valid values are 0, 4, 8, 16, or 32", arg
);
1156 rgf_banked_register_count
= (int) val
;
1159 /* Check ARC options, generate derived target attributes. */
1162 arc_override_options (void)
1165 cl_deferred_option
*opt
;
1166 vec
<cl_deferred_option
> *vopt
1167 = (vec
<cl_deferred_option
> *) arc_deferred_options
;
1169 if (arc_cpu
== PROCESSOR_NONE
)
1170 arc_cpu
= TARGET_CPU_DEFAULT
;
1172 /* Set the default cpu options. */
1173 arc_selected_cpu
= &arc_cpu_types
[(int) arc_cpu
];
1175 /* Set the architectures. */
1176 switch (arc_selected_cpu
->arch_info
->arch_id
)
1179 arc_cpu_string
= "EM";
1182 arc_cpu_string
= "HS";
1185 if (arc_selected_cpu
->processor
== PROCESSOR_nps400
)
1186 arc_cpu_string
= "NPS400";
1188 arc_cpu_string
= "ARC700";
1191 arc_cpu_string
= "ARC600";
1197 irq_ctrl_saved
.irq_save_last_reg
= -1;
1198 irq_ctrl_saved
.irq_save_blink
= false;
1199 irq_ctrl_saved
.irq_save_lpcount
= false;
1201 rgf_banked_register_count
= 0;
1203 /* Handle the deferred options. */
1205 FOR_EACH_VEC_ELT (*vopt
, i
, opt
)
1207 switch (opt
->opt_index
)
1209 case OPT_mirq_ctrl_saved_
:
1211 irq_range (opt
->arg
);
1213 warning (OPT_mirq_ctrl_saved_
,
1214 "option %<-mirq-ctrl-saved%> valid only "
1215 "for ARC v2 processors");
1218 case OPT_mrgf_banked_regs_
:
1220 parse_mrgf_banked_regs_option (opt
->arg
);
1222 warning (OPT_mrgf_banked_regs_
,
1223 "option %<-mrgf-banked-regs%> valid only for "
1224 "ARC v2 processors");
1232 CLEAR_HARD_REG_SET (overrideregs
);
1233 if (common_deferred_options
)
1235 vec
<cl_deferred_option
> v
=
1236 *((vec
<cl_deferred_option
> *) common_deferred_options
);
1239 FOR_EACH_VEC_ELT (v
, i
, opt
)
1241 switch (opt
->opt_index
)
1244 case OPT_fcall_used_
:
1245 case OPT_fcall_saved_
:
1246 if ((reg
= decode_reg_name_and_count (opt
->arg
, &nregs
)) >= 0)
1247 for (j
= reg
; j
< reg
+ nregs
; j
++)
1248 SET_HARD_REG_BIT (overrideregs
, j
);
1256 /* Check options against architecture options. Throw an error if
1257 option is not allowed. Extra, check options against default
1258 architecture/cpu flags and throw an warning if we find a
1260 /* TRANSLATORS: the DOC/DOC0/DOC1 are strings which shouldn't be
1261 translated. They are like keywords which one can relate with the
1262 architectural choices taken for an ARC CPU implementation. */
1263 #define ARC_OPTX(NAME, CODE, VAR, VAL, DOC0, DOC1) \
1265 if ((!(arc_selected_cpu->arch_info->flags & CODE)) \
1267 error ("option %<%s=%s%> is not available for %qs CPU", \
1268 DOC0, DOC1, arc_selected_cpu->name); \
1269 if ((arc_selected_cpu->arch_info->dflags & CODE) \
1270 && (VAR != DEFAULT_##VAR) \
1272 warning (0, "option %qs is ignored, the default value %qs" \
1273 " is considered for %qs CPU", DOC0, DOC1, \
1274 arc_selected_cpu->name); \
1276 #define ARC_OPT(NAME, CODE, MASK, DOC) \
1278 if ((!(arc_selected_cpu->arch_info->flags & CODE)) \
1279 && (target_flags & MASK)) \
1280 error ("option %qs is not available for %qs CPU", \
1281 DOC, arc_selected_cpu->name); \
1282 if ((arc_selected_cpu->arch_info->dflags & CODE) \
1283 && (target_flags_explicit & MASK) \
1284 && (!(target_flags & MASK))) \
1285 warning (0, "unset option %qs is ignored, it is always" \
1286 " enabled for %qs CPU", DOC, \
1287 arc_selected_cpu->name); \
1290 #include "arc-options.def"
1295 /* Set cpu flags accordingly to architecture/selected cpu. The cpu
1296 specific flags are set in arc-common.cc. The architecture forces
1297 the default hardware configurations in, regardless what command
1298 line options are saying. The CPU optional hw options can be
1299 turned on or off. */
1300 #define ARC_OPT(NAME, CODE, MASK, DOC) \
1302 if ((arc_selected_cpu->flags & CODE) \
1303 && ((target_flags_explicit & MASK) == 0)) \
1304 target_flags |= MASK; \
1305 if (arc_selected_cpu->arch_info->dflags & CODE) \
1306 target_flags |= MASK; \
1308 #define ARC_OPTX(NAME, CODE, VAR, VAL, DOC0, DOC1) \
1310 if ((arc_selected_cpu->flags & CODE) \
1311 && (VAR == DEFAULT_##VAR)) \
1313 if (arc_selected_cpu->arch_info->dflags & CODE) \
1317 #include "arc-options.def"
1323 switch (arc_selected_cpu
->extra
)
1325 case HAS_LPCOUNT_16
:
1332 /* Set Tune option. */
1333 if (arc_tune
== ARC_TUNE_NONE
)
1334 arc_tune
= (enum arc_tune_attr
) arc_selected_cpu
->tune
;
1336 if (arc_size_opt_level
== 3)
1339 if (TARGET_V2
&& optimize_size
&& (ATTRIBUTE_PCS
== 2))
1340 TARGET_CODE_DENSITY_FRAME
= 1;
1343 target_flags
|= MASK_NO_SDATA_SET
;
1345 /* Check for small data option */
1346 if (!OPTION_SET_P (g_switch_value
) && !TARGET_NO_SDATA_SET
)
1347 g_switch_value
= TARGET_LL64
? 8 : 4;
1349 /* A7 has an issue with delay slots. */
1350 if (TARGET_ARC700
&& (arc_tune
!= ARC_TUNE_ARC7XX
))
1351 flag_delayed_branch
= 0;
1353 /* Millicode thunks doesn't work for long calls. */
1354 if (TARGET_LONG_CALLS_SET
1355 /* neither for RF16. */
1357 target_flags
&= ~MASK_MILLICODE_THUNK_SET
;
1359 /* Set unaligned to all HS cpus. */
1360 if (!OPTION_SET_P (unaligned_access
) && TARGET_HS
)
1361 unaligned_access
= 1;
1363 if (TARGET_HS
&& (arc_tune
== ARC_TUNE_ARCHS4X_REL31A
))
1365 TARGET_CODE_DENSITY_FRAME
= 0;
1366 flag_delayed_branch
= 0;
1369 /* These need to be done at start up. It's convenient to do them here. */
1373 /* The condition codes of the ARC, and the inverse function. */
1374 /* For short branches, the "c" / "nc" names are not defined in the ARC
1375 Programmers manual, so we have to use "lo" / "hs"" instead. */
1376 static const char *arc_condition_codes
[] =
1378 "al", 0, "eq", "ne", "p", "n", "lo", "hs", "v", "nv",
1379 "gt", "le", "ge", "lt", "hi", "ls", "pnz", 0
1382 enum arc_cc_code_index
1384 ARC_CC_AL
, ARC_CC_EQ
= ARC_CC_AL
+2, ARC_CC_NE
, ARC_CC_P
, ARC_CC_N
,
1385 ARC_CC_C
, ARC_CC_NC
, ARC_CC_V
, ARC_CC_NV
,
1386 ARC_CC_GT
, ARC_CC_LE
, ARC_CC_GE
, ARC_CC_LT
, ARC_CC_HI
, ARC_CC_LS
, ARC_CC_PNZ
,
1387 ARC_CC_LO
= ARC_CC_C
, ARC_CC_HS
= ARC_CC_NC
1390 #define ARC_INVERSE_CONDITION_CODE(X) ((X) ^ 1)
1392 /* Returns the index of the ARC condition code string in
1393 `arc_condition_codes'. COMPARISON should be an rtx like
1394 `(eq (...) (...))'. */
1397 get_arc_condition_code (rtx comparison
)
1399 switch (GET_MODE (XEXP (comparison
, 0)))
1402 case E_SImode
: /* For BRcc. */
1403 switch (GET_CODE (comparison
))
1405 case EQ
: return ARC_CC_EQ
;
1406 case NE
: return ARC_CC_NE
;
1407 case GT
: return ARC_CC_GT
;
1408 case LE
: return ARC_CC_LE
;
1409 case GE
: return ARC_CC_GE
;
1410 case LT
: return ARC_CC_LT
;
1411 case GTU
: return ARC_CC_HI
;
1412 case LEU
: return ARC_CC_LS
;
1413 case LTU
: return ARC_CC_LO
;
1414 case GEU
: return ARC_CC_HS
;
1415 default : gcc_unreachable ();
1418 switch (GET_CODE (comparison
))
1420 case EQ
: return ARC_CC_EQ
;
1421 case NE
: return ARC_CC_NE
;
1422 case GE
: return ARC_CC_P
;
1423 case LT
: return ARC_CC_N
;
1424 case GT
: return ARC_CC_PNZ
;
1425 default : gcc_unreachable ();
1428 switch (GET_CODE (comparison
))
1430 case EQ
: return ARC_CC_EQ
;
1431 case NE
: return ARC_CC_NE
;
1432 default : gcc_unreachable ();
1435 switch (GET_CODE (comparison
))
1437 case LTU
: return ARC_CC_C
;
1438 case GEU
: return ARC_CC_NC
;
1439 default : gcc_unreachable ();
1441 case E_CC_FP_GTmode
:
1442 if (TARGET_ARGONAUT_SET
&& TARGET_SPFP
)
1443 switch (GET_CODE (comparison
))
1445 case GT
: return ARC_CC_N
;
1446 case UNLE
: return ARC_CC_P
;
1447 default : gcc_unreachable ();
1450 switch (GET_CODE (comparison
))
1452 case GT
: return ARC_CC_HI
;
1453 case UNLE
: return ARC_CC_LS
;
1454 default : gcc_unreachable ();
1456 case E_CC_FP_GEmode
:
1457 /* Same for FPX and non-FPX. */
1458 switch (GET_CODE (comparison
))
1460 case GE
: return ARC_CC_HS
;
1461 case UNLT
: return ARC_CC_LO
;
1462 default : gcc_unreachable ();
1464 case E_CC_FP_UNEQmode
:
1465 switch (GET_CODE (comparison
))
1467 case UNEQ
: return ARC_CC_EQ
;
1468 case LTGT
: return ARC_CC_NE
;
1469 default : gcc_unreachable ();
1471 case E_CC_FP_ORDmode
:
1472 switch (GET_CODE (comparison
))
1474 case UNORDERED
: return ARC_CC_C
;
1475 case ORDERED
: return ARC_CC_NC
;
1476 default : gcc_unreachable ();
1479 switch (GET_CODE (comparison
))
1481 case EQ
: return ARC_CC_EQ
;
1482 case NE
: return ARC_CC_NE
;
1483 case UNORDERED
: return ARC_CC_C
;
1484 case ORDERED
: return ARC_CC_NC
;
1485 case LTGT
: return ARC_CC_HI
;
1486 case UNEQ
: return ARC_CC_LS
;
1487 default : gcc_unreachable ();
1491 switch (GET_CODE (comparison
))
1493 case EQ
: return ARC_CC_EQ
;
1494 case NE
: return ARC_CC_NE
;
1495 case GT
: return ARC_CC_GT
;
1496 case GE
: return ARC_CC_GE
;
1497 case LT
: return ARC_CC_C
;
1498 case LE
: return ARC_CC_LS
;
1499 case UNORDERED
: return ARC_CC_V
;
1500 case ORDERED
: return ARC_CC_NV
;
1501 case UNGT
: return ARC_CC_HI
;
1502 case UNGE
: return ARC_CC_HS
;
1503 case UNLT
: return ARC_CC_LT
;
1504 case UNLE
: return ARC_CC_LE
;
1505 /* UNEQ and LTGT do not have representation. */
1506 case LTGT
: /* Fall through. */
1507 case UNEQ
: /* Fall through. */
1508 default : gcc_unreachable ();
1510 case E_CC_FPU_UNEQmode
:
1511 switch (GET_CODE (comparison
))
1513 case LTGT
: return ARC_CC_NE
;
1514 case UNEQ
: return ARC_CC_EQ
;
1515 default : gcc_unreachable ();
1517 default : gcc_unreachable ();
1523 /* Return true if COMPARISON has a short form that can accomodate OFFSET. */
1526 arc_short_comparison_p (rtx comparison
, int offset
)
1528 gcc_assert (ARC_CC_NC
== ARC_CC_HS
);
1529 gcc_assert (ARC_CC_C
== ARC_CC_LO
);
1530 switch (get_arc_condition_code (comparison
))
1532 case ARC_CC_EQ
: case ARC_CC_NE
:
1533 return offset
>= -512 && offset
<= 506;
1534 case ARC_CC_GT
: case ARC_CC_LE
: case ARC_CC_GE
: case ARC_CC_LT
:
1535 case ARC_CC_HI
: case ARC_CC_LS
: case ARC_CC_LO
: case ARC_CC_HS
:
1536 return offset
>= -64 && offset
<= 58;
1542 /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
1543 return the mode to be used for the comparison. */
1546 arc_select_cc_mode (enum rtx_code op
, rtx x
, rtx y
)
1548 machine_mode mode
= GET_MODE (x
);
1551 /* For an operation that sets the condition codes as a side-effect, the
1552 C and V flags is not set as for cmp, so we can only use comparisons where
1553 this doesn't matter. (For LT and GE we can use "mi" and "pl"
1555 /* ??? We could use "pnz" for greater than zero, however, we could then
1556 get into trouble because the comparison could not be reversed. */
1557 if (GET_MODE_CLASS (mode
) == MODE_INT
1559 && (op
== EQ
|| op
== NE
1560 || ((op
== LT
|| op
== GE
) && GET_MODE_SIZE (GET_MODE (x
)) <= 4)))
1563 /* add.f for if (a+b) */
1565 && GET_CODE (x
) == NEG
1566 && (op
== EQ
|| op
== NE
))
1569 /* Check if this is a test suitable for bxor.f . */
1570 if (mode
== SImode
&& (op
== EQ
|| op
== NE
) && CONST_INT_P (y
)
1571 && ((INTVAL (y
) - 1) & INTVAL (y
)) == 0
1575 /* Check if this is a test suitable for add / bmsk.f . */
1576 if (mode
== SImode
&& (op
== EQ
|| op
== NE
) && CONST_INT_P (y
)
1577 && GET_CODE (x
) == AND
&& CONST_INT_P ((x1
= XEXP (x
, 1)))
1578 && ((INTVAL (x1
) + 1) & INTVAL (x1
)) == 0
1579 && (~INTVAL (x1
) | INTVAL (y
)) < 0
1580 && (~INTVAL (x1
) | INTVAL (y
)) > -0x800)
1583 if (GET_MODE (x
) == SImode
&& (op
== LTU
|| op
== GEU
)
1584 && GET_CODE (x
) == PLUS
1585 && (rtx_equal_p (XEXP (x
, 0), y
) || rtx_equal_p (XEXP (x
, 1), y
)))
1588 if (TARGET_ARGONAUT_SET
1589 && ((mode
== SFmode
&& TARGET_SPFP
) || (mode
== DFmode
&& TARGET_DPFP
)))
1592 case EQ
: case NE
: case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1594 case LT
: case UNGE
: case GT
: case UNLE
:
1595 return CC_FP_GTmode
;
1596 case LE
: case UNGT
: case GE
: case UNLT
:
1597 return CC_FP_GEmode
;
1598 default: gcc_unreachable ();
1600 else if (TARGET_HARD_FLOAT
1601 && ((mode
== SFmode
&& TARGET_FP_SP_BASE
)
1602 || (mode
== DFmode
&& TARGET_FP_DP_BASE
)))
1623 return CC_FPU_UNEQmode
;
1628 else if (GET_MODE_CLASS (mode
) == MODE_FLOAT
&& TARGET_OPTFPE
)
1632 case EQ
: case NE
: return CC_Zmode
;
1634 case GT
: case UNLE
: return CC_FP_GTmode
;
1636 case GE
: case UNLT
: return CC_FP_GEmode
;
1637 case UNEQ
: case LTGT
: return CC_FP_UNEQmode
;
1638 case ORDERED
: case UNORDERED
: return CC_FP_ORDmode
;
1639 default: gcc_unreachable ();
1645 /* Vectors to keep interesting information about registers where it can easily
1646 be got. We use to use the actual mode value as the bit number, but there
1647 is (or may be) more than 32 modes now. Instead we use two tables: one
1648 indexed by hard register number, and one indexed by mode. */
1650 /* The purpose of arc_mode_class is to shrink the range of modes so that
1651 they all fit (as bit numbers) in a 32-bit word (again). Each real mode is
1652 mapped into one arc_mode_class mode. */
1654 enum arc_mode_class
{
1656 S_MODE
, D_MODE
, T_MODE
, O_MODE
,
1657 SF_MODE
, DF_MODE
, TF_MODE
, OF_MODE
,
1661 /* Modes for condition codes. */
1662 #define C_MODES (1 << (int) C_MODE)
1664 /* Modes for single-word and smaller quantities. */
1665 #define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
1667 /* Modes for double-word and smaller quantities. */
1668 #define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))
1670 /* Mode for 8-byte DF values only. */
1671 #define DF_MODES (1 << DF_MODE)
1673 /* Modes for quad-word and smaller quantities. */
1674 #define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE))
1676 /* Modes for 128-bit vectors. */
1677 #define V_MODES (1 << (int) V_MODE)
1679 /* Value is 1 if register/mode pair is acceptable on arc. */
1681 static unsigned int arc_hard_regno_modes
[] = {
1682 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
,
1683 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
,
1684 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, D_MODES
,
1685 D_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1687 /* ??? Leave these as S_MODES for now. */
1688 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1689 DF_MODES
, 0, DF_MODES
, 0, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1690 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1691 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, C_MODES
, S_MODES
,
1693 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1694 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1695 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1696 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1698 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1699 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1700 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1701 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1703 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1704 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1708 static unsigned int arc_mode_class
[NUM_MACHINE_MODES
];
1710 enum reg_class arc_regno_reg_class
[FIRST_PSEUDO_REGISTER
];
1713 arc_preferred_reload_class (rtx
, enum reg_class cl
)
1718 /* Initialize the arc_mode_class array. */
1721 arc_init_reg_tables (void)
1725 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
1727 machine_mode m
= (machine_mode
) i
;
1729 switch (GET_MODE_CLASS (m
))
1732 case MODE_PARTIAL_INT
:
1733 case MODE_COMPLEX_INT
:
1734 if (GET_MODE_SIZE (m
) <= 4)
1735 arc_mode_class
[i
] = 1 << (int) S_MODE
;
1736 else if (GET_MODE_SIZE (m
) == 8)
1737 arc_mode_class
[i
] = 1 << (int) D_MODE
;
1738 else if (GET_MODE_SIZE (m
) == 16)
1739 arc_mode_class
[i
] = 1 << (int) T_MODE
;
1740 else if (GET_MODE_SIZE (m
) == 32)
1741 arc_mode_class
[i
] = 1 << (int) O_MODE
;
1743 arc_mode_class
[i
] = 0;
1746 case MODE_COMPLEX_FLOAT
:
1747 if (GET_MODE_SIZE (m
) <= 4)
1748 arc_mode_class
[i
] = 1 << (int) SF_MODE
;
1749 else if (GET_MODE_SIZE (m
) == 8)
1750 arc_mode_class
[i
] = 1 << (int) DF_MODE
;
1751 else if (GET_MODE_SIZE (m
) == 16)
1752 arc_mode_class
[i
] = 1 << (int) TF_MODE
;
1753 else if (GET_MODE_SIZE (m
) == 32)
1754 arc_mode_class
[i
] = 1 << (int) OF_MODE
;
1756 arc_mode_class
[i
] = 0;
1758 case MODE_VECTOR_INT
:
1759 if (GET_MODE_SIZE (m
) == 4)
1760 arc_mode_class
[i
] = (1 << (int) S_MODE
);
1761 else if (GET_MODE_SIZE (m
) == 8)
1762 arc_mode_class
[i
] = (1 << (int) D_MODE
);
1764 arc_mode_class
[i
] = (1 << (int) V_MODE
);
1768 /* mode_class hasn't been initialized yet for EXTRA_CC_MODES, so
1769 we must explicitly check for them here. */
1770 if (i
== (int) CCmode
|| i
== (int) CC_ZNmode
|| i
== (int) CC_Zmode
1771 || i
== (int) CC_Cmode
1772 || i
== CC_FP_GTmode
|| i
== CC_FP_GEmode
|| i
== CC_FP_ORDmode
1773 || i
== CC_FPUmode
|| i
== CC_FPUEmode
|| i
== CC_FPU_UNEQmode
)
1774 arc_mode_class
[i
] = 1 << (int) C_MODE
;
1776 arc_mode_class
[i
] = 0;
1782 /* Core registers 56..59 are used for multiply extension options.
1783 The dsp option uses r56 and r57, these are then named acc1 and acc2.
1784 acc1 is the highpart, and acc2 the lowpart, so which register gets which
1785 number depends on endianness.
1786 The mul64 multiplier options use r57 for mlo, r58 for mmid and r59 for mhi.
1787 Because mlo / mhi form a 64 bit value, we use different gcc internal
1788 register numbers to make them form a register pair as the gcc internals
1789 know it. mmid gets number 57, if still available, and mlo / mhi get
1790 number 58 and 59, depending on endianness. We use DEBUGGER_REGNO
1791 to map this back. */
1792 char rname56
[5] = "r56";
1793 char rname57
[5] = "r57";
1794 char rname58
[5] = "r58";
1795 char rname59
[5] = "r59";
1796 char rname29
[7] = "ilink1";
1797 char rname30
[7] = "ilink2";
1800 arc_conditional_register_usage (void)
1804 int fix_start
= 60, fix_end
= 55;
1808 /* For ARCv2 the core register set is changed. */
1809 strcpy (rname29
, "ilink");
1810 strcpy (rname30
, "r30");
1812 if (!TEST_HARD_REG_BIT (overrideregs
, R30_REG
))
1814 /* No user interference. Set the r30 to be used by the
1816 call_used_regs
[R30_REG
] = 1;
1817 fixed_regs
[R30_REG
] = 0;
1819 arc_regno_reg_class
[R30_REG
] = GENERAL_REGS
;
1823 if (TARGET_MUL64_SET
)
1825 fix_start
= R57_REG
;
1828 /* We don't provide a name for mmed. In rtl / assembly resource lists,
1829 you are supposed to refer to it as mlo & mhi, e.g
1830 (zero_extract:SI (reg:DI 58) (const_int 32) (16)) .
1831 In an actual asm instruction, you are of course use mmed.
1832 The point of avoiding having a separate register for mmed is that
1833 this way, we don't have to carry clobbers of that reg around in every
1834 isntruction that modifies mlo and/or mhi. */
1835 strcpy (rname57
, "");
1836 strcpy (rname58
, "mlo");
1837 strcpy (rname59
, "mhi");
1840 /* The nature of arc_tp_regno is actually something more like a global
1841 register, however globalize_reg requires a declaration.
1842 We use EPILOGUE_USES to compensate so that sets from
1843 __builtin_set_frame_pointer are not deleted. */
1844 if (arc_tp_regno
!= -1)
1845 fixed_regs
[arc_tp_regno
] = call_used_regs
[arc_tp_regno
] = 1;
1847 if (TARGET_MULMAC_32BY16_SET
)
1849 fix_start
= MUL32x16_REG
;
1850 fix_end
= fix_end
> R57_REG
? fix_end
: R57_REG
;
1851 strcpy (rname56
, TARGET_BIG_ENDIAN
? "acc1" : "acc2");
1852 strcpy (rname57
, TARGET_BIG_ENDIAN
? "acc2" : "acc1");
1854 for (regno
= fix_start
; regno
<= fix_end
; regno
++)
1856 if (!fixed_regs
[regno
])
1857 warning (0, "multiply option implies r%d is fixed", regno
);
1858 fixed_regs
[regno
] = call_used_regs
[regno
] = 1;
1861 /* Reduced configuration: don't use r4-r9, r16-r25. */
1864 for (i
= R4_REG
; i
<= R9_REG
; i
++)
1865 fixed_regs
[i
] = call_used_regs
[i
] = 1;
1866 for (i
= R16_REG
; i
<= R25_REG
; i
++)
1867 fixed_regs
[i
] = call_used_regs
[i
] = 1;
1870 /* ARCHS has 64-bit data-path which makes use of the even-odd paired
1873 for (regno
= R1_REG
; regno
< R32_REG
; regno
+=2)
1874 arc_hard_regno_modes
[regno
] = S_MODES
;
1876 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1879 if ((i
<= R3_REG
) || ((i
>= R12_REG
) && (i
<= R15_REG
)))
1880 arc_regno_reg_class
[i
] = ARCOMPACT16_REGS
;
1882 arc_regno_reg_class
[i
] = GENERAL_REGS
;
1884 else if (i
< LP_COUNT
)
1885 arc_regno_reg_class
[i
] = GENERAL_REGS
;
1887 arc_regno_reg_class
[i
] = NO_REGS
;
1889 /* Handle Special Registers. */
1890 arc_regno_reg_class
[CC_REG
] = NO_REGS
; /* CC_REG: must be NO_REGS. */
1891 arc_regno_reg_class
[FRAME_POINTER_REGNUM
] = GENERAL_REGS
;
1892 arc_regno_reg_class
[ARG_POINTER_REGNUM
] = GENERAL_REGS
;
1895 for (i
= R40_REG
; i
< R44_REG
; ++i
)
1897 arc_regno_reg_class
[i
] = DOUBLE_REGS
;
1898 if (!TARGET_ARGONAUT_SET
)
1899 CLEAR_HARD_REG_BIT (reg_class_contents
[GENERAL_REGS
], i
);
1903 /* Disable all DOUBLE_REGISTER settings, if not generating DPFP
1905 arc_regno_reg_class
[R40_REG
] = ALL_REGS
;
1906 arc_regno_reg_class
[R41_REG
] = ALL_REGS
;
1907 arc_regno_reg_class
[R42_REG
] = ALL_REGS
;
1908 arc_regno_reg_class
[R43_REG
] = ALL_REGS
;
1910 fixed_regs
[R40_REG
] = 1;
1911 fixed_regs
[R41_REG
] = 1;
1912 fixed_regs
[R42_REG
] = 1;
1913 fixed_regs
[R43_REG
] = 1;
1915 arc_hard_regno_modes
[R40_REG
] = 0;
1916 arc_hard_regno_modes
[R42_REG
] = 0;
1919 if (TARGET_SIMD_SET
)
1921 gcc_assert (ARC_FIRST_SIMD_VR_REG
== 64);
1922 gcc_assert (ARC_LAST_SIMD_VR_REG
== 127);
1924 for (i
= ARC_FIRST_SIMD_VR_REG
; i
<= ARC_LAST_SIMD_VR_REG
; i
++)
1925 arc_regno_reg_class
[i
] = SIMD_VR_REGS
;
1927 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_REG
== 128);
1928 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_IN_REG
== 128);
1929 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG
== 136);
1930 gcc_assert (ARC_LAST_SIMD_DMA_CONFIG_REG
== 143);
1932 for (i
= ARC_FIRST_SIMD_DMA_CONFIG_REG
;
1933 i
<= ARC_LAST_SIMD_DMA_CONFIG_REG
; i
++)
1934 arc_regno_reg_class
[i
] = SIMD_DMA_CONFIG_REGS
;
1938 arc_regno_reg_class
[PCL_REG
] = NO_REGS
;
1940 /*ARCV2 Accumulator. */
1942 && (TARGET_FP_DP_FUSED
|| TARGET_FP_SP_FUSED
))
1943 || TARGET_PLUS_DMPY
)
1945 arc_regno_reg_class
[ACCL_REGNO
] = GENERAL_REGS
;
1946 arc_regno_reg_class
[ACCH_REGNO
] = GENERAL_REGS
;
1948 /* Allow the compiler to freely use them. */
1949 if (!TEST_HARD_REG_BIT (overrideregs
, ACCL_REGNO
))
1950 fixed_regs
[ACCL_REGNO
] = 0;
1951 if (!TEST_HARD_REG_BIT (overrideregs
, ACCH_REGNO
))
1952 fixed_regs
[ACCH_REGNO
] = 0;
1954 if (!fixed_regs
[ACCH_REGNO
] && !fixed_regs
[ACCL_REGNO
])
1955 arc_hard_regno_modes
[ACC_REG_FIRST
] = D_MODES
;
1959 /* Implement TARGET_HARD_REGNO_NREGS. */
1962 arc_hard_regno_nregs (unsigned int regno
, machine_mode mode
)
1964 if (GET_MODE_SIZE (mode
) == 16
1965 && regno
>= ARC_FIRST_SIMD_VR_REG
1966 && regno
<= ARC_LAST_SIMD_VR_REG
)
1969 return CEIL (GET_MODE_SIZE (mode
), UNITS_PER_WORD
);
1972 /* Implement TARGET_HARD_REGNO_MODE_OK. */
1975 arc_hard_regno_mode_ok (unsigned int regno
, machine_mode mode
)
1977 return (arc_hard_regno_modes
[regno
] & arc_mode_class
[mode
]) != 0;
1980 /* Implement TARGET_MODES_TIEABLE_P. Tie QI/HI/SI modes together. */
1983 arc_modes_tieable_p (machine_mode mode1
, machine_mode mode2
)
1985 return (GET_MODE_CLASS (mode1
) == MODE_INT
1986 && GET_MODE_CLASS (mode2
) == MODE_INT
1987 && GET_MODE_SIZE (mode1
) <= UNITS_PER_WORD
1988 && GET_MODE_SIZE (mode2
) <= UNITS_PER_WORD
);
1991 /* Handle an "interrupt" attribute; arguments as in
1992 struct attribute_spec.handler. */
1995 arc_handle_interrupt_attribute (tree
*, tree name
, tree args
, int,
2000 tree value
= TREE_VALUE (args
);
2002 if (TREE_CODE (value
) != STRING_CST
)
2004 warning (OPT_Wattributes
,
2005 "argument of %qE attribute is not a string constant",
2007 *no_add_attrs
= true;
2010 && strcmp (TREE_STRING_POINTER (value
), "ilink1")
2011 && strcmp (TREE_STRING_POINTER (value
), "ilink2"))
2013 warning (OPT_Wattributes
,
2014 "argument of %qE attribute is not \"ilink1\" or \"ilink2\"",
2016 *no_add_attrs
= true;
2019 && strcmp (TREE_STRING_POINTER (value
), "ilink")
2020 && strcmp (TREE_STRING_POINTER (value
), "firq"))
2022 warning (OPT_Wattributes
,
2023 "argument of %qE attribute is not \"ilink\" or \"firq\"",
2025 *no_add_attrs
= true;
2032 arc_handle_fndecl_attribute (tree
*node
, tree name
, tree args ATTRIBUTE_UNUSED
,
2033 int flags ATTRIBUTE_UNUSED
, bool *no_add_attrs
)
2035 if (TREE_CODE (*node
) != FUNCTION_DECL
)
2037 warning (OPT_Wattributes
, "%qE attribute only applies to functions",
2039 *no_add_attrs
= true;
2045 /* Type of function DECL.
2047 The result is cached. To reset the cache at the end of a function,
2048 call with DECL = NULL_TREE. */
2051 arc_compute_function_type (struct function
*fun
)
2053 tree attr
, decl
= fun
->decl
;
2054 unsigned int fn_type
= fun
->machine
->fn_type
;
2056 if (fn_type
!= ARC_FUNCTION_UNKNOWN
)
2059 /* Check if it is a naked function. */
2060 if (lookup_attribute ("naked", DECL_ATTRIBUTES (decl
)) != NULL_TREE
)
2061 fn_type
|= ARC_FUNCTION_NAKED
;
2063 fn_type
|= ARC_FUNCTION_NORMAL
;
2065 /* Now see if this is an interrupt handler. */
2066 attr
= lookup_attribute ("interrupt", DECL_ATTRIBUTES (decl
));
2067 if (attr
!= NULL_TREE
)
2069 tree value
, args
= TREE_VALUE (attr
);
2071 gcc_assert (list_length (args
) == 1);
2072 value
= TREE_VALUE (args
);
2073 gcc_assert (TREE_CODE (value
) == STRING_CST
);
2075 if (!strcmp (TREE_STRING_POINTER (value
), "ilink1")
2076 || !strcmp (TREE_STRING_POINTER (value
), "ilink"))
2077 fn_type
|= ARC_FUNCTION_ILINK1
;
2078 else if (!strcmp (TREE_STRING_POINTER (value
), "ilink2"))
2079 fn_type
|= ARC_FUNCTION_ILINK2
;
2080 else if (!strcmp (TREE_STRING_POINTER (value
), "firq"))
2081 fn_type
|= ARC_FUNCTION_FIRQ
;
2086 return fun
->machine
->fn_type
= fn_type
;
2089 /* Implement `TARGET_ALLOCATE_STACK_SLOTS_FOR_ARGS' */
2092 arc_allocate_stack_slots_for_args (void)
2094 /* Naked functions should not allocate stack slots for arguments. */
2095 unsigned int fn_type
= arc_compute_function_type (cfun
);
2097 return !ARC_NAKED_P(fn_type
);
2100 /* Implement `TARGET_WARN_FUNC_RETURN'. */
2103 arc_warn_func_return (tree decl
)
2105 struct function
*func
= DECL_STRUCT_FUNCTION (decl
);
2106 unsigned int fn_type
= arc_compute_function_type (func
);
2108 return !ARC_NAKED_P (fn_type
);
2111 /* Return zero if TYPE1 and TYPE are incompatible, one if they are compatible,
2112 and two if they are nearly compatible (which causes a warning to be
2116 arc_comp_type_attributes (const_tree type1
,
2119 int l1
, l2
, m1
, m2
, s1
, s2
;
2121 /* Check for mismatch of non-default calling convention. */
2122 if (TREE_CODE (type1
) != FUNCTION_TYPE
)
2125 /* Check for mismatched call attributes. */
2126 l1
= lookup_attribute ("long_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
2127 l2
= lookup_attribute ("long_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
2128 m1
= lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
2129 m2
= lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
2130 s1
= lookup_attribute ("short_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
2131 s2
= lookup_attribute ("short_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
2133 /* Only bother to check if an attribute is defined. */
2134 if (l1
| l2
| m1
| m2
| s1
| s2
)
2136 /* If one type has an attribute, the other must have the same attribute. */
2137 if ((l1
!= l2
) || (m1
!= m2
) || (s1
!= s2
))
2140 /* Disallow mixed attributes. */
2141 if (l1
+ m1
+ s1
> 1)
2149 /* Misc. utilities. */
2151 /* X and Y are two things to compare using CODE. Emit the compare insn and
2152 return the rtx for the cc reg in the proper mode. */
2155 gen_compare_reg (rtx comparison
, machine_mode omode
)
2157 enum rtx_code code
= GET_CODE (comparison
);
2158 rtx x
= XEXP (comparison
, 0);
2159 rtx y
= XEXP (comparison
, 1);
2161 machine_mode mode
, cmode
;
2164 cmode
= GET_MODE (x
);
2165 if (cmode
== VOIDmode
)
2166 cmode
= GET_MODE (y
);
2168 /* If ifcvt passed us a MODE_CC comparison we can
2169 just return it. It should be in the proper form already. */
2170 if (GET_MODE_CLASS (cmode
) == MODE_CC
)
2173 if (cmode
!= SImode
&& cmode
!= SFmode
&& cmode
!= DFmode
)
2175 if (cmode
== SImode
)
2177 if (!register_operand (x
, SImode
))
2179 if (register_operand (y
, SImode
))
2184 code
= swap_condition (code
);
2187 x
= copy_to_mode_reg (SImode
, x
);
2189 if (GET_CODE (y
) == SYMBOL_REF
&& flag_pic
)
2190 y
= copy_to_mode_reg (SImode
, y
);
2194 x
= force_reg (cmode
, x
);
2195 y
= force_reg (cmode
, y
);
2197 mode
= SELECT_CC_MODE (code
, x
, y
);
2199 cc_reg
= gen_rtx_REG (mode
, CC_REG
);
2201 /* ??? FIXME (x-y)==0, as done by both cmpsfpx_raw and
2202 cmpdfpx_raw, is not a correct comparison for floats:
2203 http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
2205 if (TARGET_ARGONAUT_SET
2206 && ((cmode
== SFmode
&& TARGET_SPFP
) || (cmode
== DFmode
&& TARGET_DPFP
)))
2210 case NE
: case EQ
: case LT
: case UNGE
: case LE
: case UNGT
:
2211 case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
2213 case GT
: case UNLE
: case GE
: case UNLT
:
2214 code
= swap_condition (code
);
2222 if (cmode
== SFmode
)
2224 emit_insn (gen_cmpsfpx_raw (x
, y
));
2228 /* Accepts Dx regs directly by insns. */
2229 emit_insn (gen_cmpdfpx_raw (x
, y
));
2232 if (mode
!= CC_FPXmode
)
2233 emit_insn (gen_rtx_SET (cc_reg
,
2234 gen_rtx_COMPARE (mode
,
2235 gen_rtx_REG (CC_FPXmode
, 61),
2238 else if (TARGET_FPX_QUARK
&& (cmode
== SFmode
))
2242 case NE
: case EQ
: case GT
: case UNLE
: case GE
: case UNLT
:
2243 case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
2245 case LT
: case UNGE
: case LE
: case UNGT
:
2246 code
= swap_condition (code
);
2255 emit_insn (gen_cmp_quark (cc_reg
,
2256 gen_rtx_COMPARE (mode
, x
, y
)));
2258 else if (TARGET_HARD_FLOAT
2259 && ((cmode
== SFmode
&& TARGET_FP_SP_BASE
)
2260 || (cmode
== DFmode
&& TARGET_FP_DP_BASE
)))
2261 emit_insn (gen_rtx_SET (cc_reg
, gen_rtx_COMPARE (mode
, x
, y
)));
2262 else if (GET_MODE_CLASS (cmode
) == MODE_FLOAT
&& TARGET_OPTFPE
)
2264 rtx op0
= gen_rtx_REG (cmode
, 0);
2265 rtx op1
= gen_rtx_REG (cmode
, GET_MODE_SIZE (cmode
) / UNITS_PER_WORD
);
2270 case NE
: case EQ
: case GT
: case UNLE
: case GE
: case UNLT
:
2271 case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
2273 case LT
: case UNGE
: case LE
: case UNGT
:
2274 code
= swap_condition (code
);
2280 if (currently_expanding_to_rtl
)
2288 emit_move_insn (op0
, x
);
2289 emit_move_insn (op1
, y
);
2293 gcc_assert (rtx_equal_p (op0
, x
));
2294 gcc_assert (rtx_equal_p (op1
, y
));
2301 emit_insn (gen_cmp_float (cc_reg
, gen_rtx_COMPARE (mode
, op0
, op1
)));
2304 emit_insn (gen_rtx_SET (cc_reg
, gen_rtx_COMPARE (mode
, x
, y
)));
2305 return gen_rtx_fmt_ee (code
, omode
, cc_reg
, const0_rtx
);
2308 /* Return true if VALUE, a const_double, will fit in a limm (4 byte number).
2309 We assume the value can be either signed or unsigned. */
2312 arc_double_limm_p (rtx value
)
2314 HOST_WIDE_INT low
, high
;
2316 gcc_assert (GET_CODE (value
) == CONST_DOUBLE
);
2321 low
= CONST_DOUBLE_LOW (value
);
2322 high
= CONST_DOUBLE_HIGH (value
);
2324 if (low
& 0x80000000)
2326 return (((unsigned HOST_WIDE_INT
) low
<= 0xffffffff && high
== 0)
2327 || (((low
& - (unsigned HOST_WIDE_INT
) 0x80000000)
2328 == - (unsigned HOST_WIDE_INT
) 0x80000000)
2333 return (unsigned HOST_WIDE_INT
) low
<= 0x7fffffff && high
== 0;
2337 /* Do any needed setup for a variadic function. For the ARC, we must
2338 create a register parameter block, and then copy any anonymous arguments
2339 in registers to memory.
2341 CUM has not been updated for the last named argument (which is given
2342 by ARG), and we rely on this fact. */
2345 arc_setup_incoming_varargs (cumulative_args_t args_so_far
,
2346 const function_arg_info
&arg
,
2347 int *pretend_size
, int no_rtl
)
2350 CUMULATIVE_ARGS next_cum
;
2352 /* We must treat `__builtin_va_alist' as an anonymous arg. */
2354 next_cum
= *get_cumulative_args (args_so_far
);
2355 if (!TYPE_NO_NAMED_ARGS_STDARG_P (TREE_TYPE (current_function_decl
)))
2356 arc_function_arg_advance (pack_cumulative_args (&next_cum
), arg
);
2357 first_anon_arg
= next_cum
;
2359 if (FUNCTION_ARG_REGNO_P (first_anon_arg
))
2361 /* First anonymous (unnamed) argument is in a reg. */
2363 /* Note that first_reg_offset < MAX_ARC_PARM_REGS. */
2364 int first_reg_offset
= first_anon_arg
;
2369 = gen_rtx_MEM (BLKmode
, plus_constant (Pmode
, arg_pointer_rtx
,
2370 FIRST_PARM_OFFSET (0)));
2371 move_block_from_reg (first_reg_offset
, regblock
,
2372 MAX_ARC_PARM_REGS
- first_reg_offset
);
2376 = ((MAX_ARC_PARM_REGS
- first_reg_offset
) * UNITS_PER_WORD
);
2380 /* Return TRUE if reg is ok for short instrcutions. */
2383 arc_check_short_reg_p (rtx op
)
2388 if (IN_RANGE (REGNO (op
) ^ 4, 4, 11))
2394 /* Cost functions. */
2396 /* Provide the costs of an addressing mode that contains ADDR.
2397 If ADDR is not a valid address, its cost is irrelevant. */
2400 arc_address_cost (rtx addr
, machine_mode
, addr_space_t
, bool speed
)
2402 switch (GET_CODE (addr
))
2405 return speed
|| arc_check_short_reg_p (addr
) ? 0 : 1;
2406 case PRE_INC
: case PRE_DEC
: case POST_INC
: case POST_DEC
:
2407 case PRE_MODIFY
: case POST_MODIFY
:
2413 if (TARGET_NPS_CMEM
&& cmem_address (addr
, SImode
))
2415 /* Most likely needs a LIMM. */
2416 return COSTS_N_INSNS (1);
2420 rtx plus0
= XEXP (addr
, 0);
2421 rtx plus1
= XEXP (addr
, 1);
2423 if (GET_CODE (plus0
) != REG
2424 && (GET_CODE (plus0
) != MULT
2425 || !CONST_INT_P (XEXP (plus0
, 1))
2426 || (INTVAL (XEXP (plus0
, 1)) != 2
2427 && INTVAL (XEXP (plus0
, 1)) != 4)))
2430 switch (GET_CODE (plus1
))
2433 return (!RTX_OK_FOR_OFFSET_P (SImode
, plus1
)
2437 : (arc_check_short_reg_p (plus0
)
2438 && satisfies_constraint_O (plus1
))
2442 return (speed
< 1 ? 0
2443 : (arc_check_short_reg_p (plus0
)
2444 && arc_check_short_reg_p (plus1
))
2449 return COSTS_N_INSNS (1);
2462 /* Emit instruction X with the frame related bit set. */
2468 RTX_FRAME_RELATED_P (x
) = 1;
2472 /* Emit a frame insn to move SRC to DST. */
2475 frame_move (rtx dst
, rtx src
)
2477 rtx tmp
= gen_rtx_SET (dst
, src
);
2478 RTX_FRAME_RELATED_P (tmp
) = 1;
2479 return frame_insn (tmp
);
2482 /* Like frame_move, but add a REG_INC note for REG if ADDR contains an
2483 auto increment address, or is zero. */
2486 frame_move_inc (rtx dst
, rtx src
, rtx reg
, rtx addr
)
2488 rtx insn
= frame_move (dst
, src
);
2491 || GET_CODE (addr
) == PRE_DEC
|| GET_CODE (addr
) == POST_INC
2492 || GET_CODE (addr
) == PRE_MODIFY
|| GET_CODE (addr
) == POST_MODIFY
)
2493 add_reg_note (insn
, REG_INC
, reg
);
2497 /* Emit a frame insn which adjusts a frame address register REG by OFFSET. */
2500 frame_add (rtx reg
, HOST_WIDE_INT offset
)
2502 gcc_assert ((offset
& 0x3) == 0);
2505 return frame_move (reg
, plus_constant (Pmode
, reg
, offset
));
2508 /* Emit a frame insn which adjusts stack pointer by OFFSET. */
2511 frame_stack_add (HOST_WIDE_INT offset
)
2513 return frame_add (stack_pointer_rtx
, offset
);
2516 /* Helper function to wrap FRAME_POINTER_NEEDED. We do this as
2517 FRAME_POINTER_NEEDED will not be true until the IRA (Integrated
2518 Register Allocator) pass, while we want to get the frame size
2519 correct earlier than the IRA pass.
2521 When a function uses eh_return we must ensure that the fp register
2522 is saved and then restored so that the unwinder can restore the
2523 correct value for the frame we are going to jump to.
2525 To do this we force all frames that call eh_return to require a
2526 frame pointer (see arc_frame_pointer_required), this
2527 will ensure that the previous frame pointer is stored on entry to
2528 the function, and will then be reloaded at function exit.
2530 As the frame pointer is handled as a special case in our prologue
2531 and epilogue code it must not be saved and restored using the
2532 MUST_SAVE_REGISTER mechanism otherwise we run into issues where GCC
2533 believes that the function is not using a frame pointer and that
2534 the value in the fp register is the frame pointer, while the
2535 prologue and epilogue are busy saving and restoring the fp
2538 During compilation of a function the frame size is evaluated
2539 multiple times, it is not until the reload pass is complete the
2540 frame size is considered fixed (it is at this point that space for
2541 all spills has been allocated). However the frame_pointer_needed
2542 variable is not set true until the register allocation pass, as a
2543 result in the early stages the frame size does not include space
2544 for the frame pointer to be spilled.
2546 The problem that this causes is that the rtl generated for
2547 EH_RETURN_HANDLER_RTX uses the details of the frame size to compute
2548 the offset from the frame pointer at which the return address
2549 lives. However, in early passes GCC has not yet realised we need a
2550 frame pointer, and so has not included space for the frame pointer
2551 in the frame size, and so gets the offset of the return address
2552 wrong. This should not be an issue as in later passes GCC has
2553 realised that the frame pointer needs to be spilled, and has
2554 increased the frame size. However, the rtl for the
2555 EH_RETURN_HANDLER_RTX is not regenerated to use the newer, larger
2556 offset, and the wrong smaller offset is used. */
2559 arc_frame_pointer_needed (void)
2561 return (frame_pointer_needed
|| crtl
->calls_eh_return
);
2564 /* Tell prologue and epilogue if register REGNO should be saved /
2565 restored. The SPECIAL_P is true when the register may need special
2566 ld/st sequence. The return address, and stack pointer are treated
2567 separately. Don't consider them here. */
2570 arc_must_save_register (int regno
, struct function
*func
, bool special_p
)
2572 unsigned int fn_type
= arc_compute_function_type (func
);
2573 bool irq_auto_save_p
= ((irq_ctrl_saved
.irq_save_last_reg
>= regno
)
2574 && ARC_AUTO_IRQ_P (fn_type
));
2575 bool firq_auto_save_p
= ARC_FAST_INTERRUPT_P (fn_type
);
2577 switch (rgf_banked_register_count
)
2580 firq_auto_save_p
&= (regno
< 4);
2583 firq_auto_save_p
&= ((regno
< 4) || ((regno
> 11) && (regno
< 16)));
2586 firq_auto_save_p
&= ((regno
< 4) || ((regno
> 9) && (regno
< 16))
2587 || ((regno
> 25) && (regno
< 29))
2588 || ((regno
> 29) && (regno
< 32)));
2591 firq_auto_save_p
&= (regno
!= 29) && (regno
< 32);
2594 firq_auto_save_p
= false;
2601 case RETURN_ADDR_REGNUM
:
2602 case STACK_POINTER_REGNUM
:
2603 /* The stack pointer and the return address are handled
2608 /* r30 is either used as ilink2 by ARCv1 or as a free register
2619 /* If those ones are used by the FPX machinery, we handle them
2621 if (TARGET_DPFP
&& !special_p
)
2646 /* The Extension Registers. */
2647 if (ARC_INTERRUPT_P (fn_type
)
2648 && (df_regs_ever_live_p (RETURN_ADDR_REGNUM
)
2649 || df_regs_ever_live_p (regno
))
2650 /* Not all extension registers are available, choose the
2652 && !fixed_regs
[regno
])
2658 /* ARC600 specifies those ones as mlo/mhi registers, otherwise
2659 just handle them like any other extension register. */
2660 if (ARC_INTERRUPT_P (fn_type
)
2661 && (df_regs_ever_live_p (RETURN_ADDR_REGNUM
)
2662 || df_regs_ever_live_p (regno
))
2663 /* Not all extension registers are available, choose the
2665 && ((!fixed_regs
[regno
] && !special_p
)
2666 || (TARGET_MUL64_SET
&& special_p
)))
2673 /* Fixed/control register, nothing to do. LP_COUNT is
2677 case HARD_FRAME_POINTER_REGNUM
:
2678 /* If we need FP reg as a frame pointer then don't save it as a
2680 if (arc_frame_pointer_needed ())
2688 if (((df_regs_ever_live_p (regno
) && !call_used_or_fixed_reg_p (regno
))
2689 /* In an interrupt save everything. */
2690 || (ARC_INTERRUPT_P (fn_type
)
2691 && (df_regs_ever_live_p (RETURN_ADDR_REGNUM
)
2692 || df_regs_ever_live_p (regno
))))
2693 /* Do not emit code for auto saved regs. */
2695 && !firq_auto_save_p
)
2700 /* Return true if the return address must be saved in the current function,
2701 otherwise return false. */
2704 arc_must_save_return_addr (struct function
*func
)
2706 if (func
->machine
->frame_info
.save_return_addr
)
2712 /* Return non-zero if there are registers to be saved or loaded using
2713 millicode thunks. We can only use consecutive sequences starting
2714 with r13, and not going beyond r25.
2715 GMASK is a bitmask of registers to save. This function sets
2716 FRAME->millicod_start_reg .. FRAME->millicode_end_reg to the range
2717 of registers to be saved / restored with a millicode call. */
2720 arc_compute_millicode_save_restore_regs (uint64_t gmask
,
2721 struct arc_frame_info
*frame
)
2725 int start_reg
= 13, end_reg
= 25;
2727 for (regno
= start_reg
; regno
<= end_reg
&& (gmask
& (1ULL << regno
));)
2729 end_reg
= regno
- 1;
2730 /* There is no point in using millicode thunks if we don't save/restore
2731 at least three registers. For non-leaf functions we also have the
2733 if (regno
- start_reg
>= 3 - (crtl
->is_leaf
== 0))
2735 frame
->millicode_start_reg
= 13;
2736 frame
->millicode_end_reg
= regno
- 1;
2742 /* Return the bytes needed to compute the frame pointer from the
2743 current stack pointer. */
2746 arc_compute_frame_size (void)
2749 unsigned int total_size
, var_size
, args_size
, pretend_size
, extra_size
;
2750 unsigned int reg_size
;
2752 struct arc_frame_info
*frame_info
;
2754 unsigned int extra_plus_reg_size
;
2755 unsigned int extra_plus_reg_size_aligned
;
2756 unsigned int fn_type
= arc_compute_function_type (cfun
);
2758 /* The answer might already be known. */
2759 if (cfun
->machine
->frame_info
.initialized
)
2760 return cfun
->machine
->frame_info
.total_size
;
2762 frame_info
= &cfun
->machine
->frame_info
;
2763 size
= ARC_STACK_ALIGN (get_frame_size ());
2765 /* 1) Size of locals and temporaries. */
2768 /* 2) Size of outgoing arguments. */
2769 args_size
= crtl
->outgoing_args_size
;
2771 /* 3) Calculate space needed for saved registers.
2772 ??? We ignore the extension registers for now. */
2774 /* See if this is an interrupt handler. Call used registers must be saved
2780 /* The last 4 regs are special, avoid them. */
2781 for (regno
= 0; regno
<= (GMASK_LEN
- 4); regno
++)
2783 if (arc_must_save_register (regno
, cfun
, false))
2785 reg_size
+= UNITS_PER_WORD
;
2786 gmask
|= 1ULL << regno
;
2790 /* In a frame that calls __builtin_eh_return two data registers are
2791 used to pass values back to the exception handler.
2793 Ensure that these registers are spilled to the stack so that the
2794 exception throw code can find them, and update the saved values.
2795 The handling code will then consume these reloaded values to
2796 handle the exception. */
2797 if (crtl
->calls_eh_return
)
2798 for (regno
= 0; EH_RETURN_DATA_REGNO (regno
) != INVALID_REGNUM
; regno
++)
2800 reg_size
+= UNITS_PER_WORD
;
2801 gmask
|= 1ULL << regno
;
2804 /* Check if we need to save the return address. */
2805 frame_info
->save_return_addr
= (!crtl
->is_leaf
2806 || df_regs_ever_live_p (RETURN_ADDR_REGNUM
)
2807 || crtl
->calls_eh_return
);
2809 /* Saving blink reg for millicode thunk calls. */
2810 if (TARGET_MILLICODE_THUNK_SET
2811 && !ARC_INTERRUPT_P (fn_type
)
2812 && !crtl
->calls_eh_return
)
2814 if (arc_compute_millicode_save_restore_regs (gmask
, frame_info
))
2815 frame_info
->save_return_addr
= true;
2818 /* Save lp_count, lp_start and lp_end. */
2819 if (arc_lpcwidth
!= 0 && arc_must_save_register (LP_COUNT
, cfun
, true))
2820 reg_size
+= UNITS_PER_WORD
* 3;
2822 /* Check for the special R40-R44 regs used by FPX extension. */
2823 if (arc_must_save_register (TARGET_BIG_ENDIAN
? R41_REG
: R40_REG
,
2825 reg_size
+= UNITS_PER_WORD
* 2;
2826 if (arc_must_save_register (TARGET_BIG_ENDIAN
? R43_REG
: R42_REG
,
2828 reg_size
+= UNITS_PER_WORD
* 2;
2830 /* Check if R58 is used. */
2831 if (arc_must_save_register (R58_REG
, cfun
, true))
2832 reg_size
+= UNITS_PER_WORD
* 2;
2834 /* 4) Calculate extra size made up of the blink + fp size. */
2836 if (arc_must_save_return_addr (cfun
))
2838 /* Add FP size only when it is not autosaved. */
2839 if (arc_frame_pointer_needed ()
2840 && !ARC_AUTOFP_IRQ_P (fn_type
))
2843 /* 5) Space for variable arguments passed in registers */
2844 pretend_size
= crtl
->args
.pretend_args_size
;
2846 /* Ensure everything before the locals is aligned appropriately. */
2847 extra_plus_reg_size
= extra_size
+ reg_size
;
2848 extra_plus_reg_size_aligned
= ARC_STACK_ALIGN (extra_plus_reg_size
);
2849 reg_size
= extra_plus_reg_size_aligned
- extra_size
;
2851 /* Compute total frame size. */
2852 total_size
= var_size
+ args_size
+ extra_size
+ pretend_size
+ reg_size
;
2854 /* It used to be the case that the alignment was forced at this
2855 point. However, that is dangerous, calculations based on
2856 total_size would be wrong. Given that this has never cropped up
2857 as an issue I've changed this to an assert for now. */
2858 gcc_assert (total_size
== ARC_STACK_ALIGN (total_size
));
2860 /* Save computed information. */
2861 frame_info
->total_size
= total_size
;
2862 frame_info
->extra_size
= extra_size
;
2863 frame_info
->pretend_size
= pretend_size
;
2864 frame_info
->var_size
= var_size
;
2865 frame_info
->args_size
= args_size
;
2866 frame_info
->reg_size
= reg_size
;
2867 frame_info
->gmask
= gmask
;
2868 frame_info
->initialized
= reload_completed
;
2870 /* Ok, we're done. */
2874 /* Build dwarf information when the context is saved via AUX_IRQ_CTRL
2878 arc_dwarf_emit_irq_save_regs (void)
2880 rtx tmp
, par
, insn
, reg
;
2883 par
= gen_rtx_SEQUENCE (VOIDmode
,
2884 rtvec_alloc (irq_ctrl_saved
.irq_save_last_reg
+ 1
2885 + irq_ctrl_saved
.irq_save_blink
2886 + irq_ctrl_saved
.irq_save_lpcount
2889 /* Build the stack adjustment note for unwind info. */
2891 offset
= UNITS_PER_WORD
* (irq_ctrl_saved
.irq_save_last_reg
+ 1
2892 + irq_ctrl_saved
.irq_save_blink
2893 + irq_ctrl_saved
.irq_save_lpcount
);
2894 tmp
= plus_constant (Pmode
, stack_pointer_rtx
, -1 * offset
);
2895 tmp
= gen_rtx_SET (stack_pointer_rtx
, tmp
);
2896 RTX_FRAME_RELATED_P (tmp
) = 1;
2897 XVECEXP (par
, 0, j
++) = tmp
;
2899 offset
-= UNITS_PER_WORD
;
2901 /* 1st goes LP_COUNT. */
2902 if (irq_ctrl_saved
.irq_save_lpcount
)
2904 reg
= gen_rtx_REG (SImode
, 60);
2905 tmp
= plus_constant (Pmode
, stack_pointer_rtx
, offset
);
2906 tmp
= gen_frame_mem (SImode
, tmp
);
2907 tmp
= gen_rtx_SET (tmp
, reg
);
2908 RTX_FRAME_RELATED_P (tmp
) = 1;
2909 XVECEXP (par
, 0, j
++) = tmp
;
2910 offset
-= UNITS_PER_WORD
;
2913 /* 2nd goes BLINK. */
2914 if (irq_ctrl_saved
.irq_save_blink
)
2916 reg
= gen_rtx_REG (SImode
, 31);
2917 tmp
= plus_constant (Pmode
, stack_pointer_rtx
, offset
);
2918 tmp
= gen_frame_mem (SImode
, tmp
);
2919 tmp
= gen_rtx_SET (tmp
, reg
);
2920 RTX_FRAME_RELATED_P (tmp
) = 1;
2921 XVECEXP (par
, 0, j
++) = tmp
;
2922 offset
-= UNITS_PER_WORD
;
2925 /* Build the parallel of the remaining registers recorded as saved
2927 for (i
= irq_ctrl_saved
.irq_save_last_reg
; i
>= 0; i
--)
2929 reg
= gen_rtx_REG (SImode
, i
);
2930 tmp
= plus_constant (Pmode
, stack_pointer_rtx
, offset
);
2931 tmp
= gen_frame_mem (SImode
, tmp
);
2932 tmp
= gen_rtx_SET (tmp
, reg
);
2933 RTX_FRAME_RELATED_P (tmp
) = 1;
2934 XVECEXP (par
, 0, j
++) = tmp
;
2935 offset
-= UNITS_PER_WORD
;
2938 /* Dummy insn used to anchor the dwarf info. */
2939 insn
= emit_insn (gen_stack_irq_dwarf());
2940 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
, par
);
2941 RTX_FRAME_RELATED_P (insn
) = 1;
2944 /* Helper for prologue: emit frame store with pre_modify or pre_dec to
2945 save register REG on stack. An initial offset OFFSET can be passed
2949 frame_save_reg (rtx reg
, HOST_WIDE_INT offset
)
2955 rtx tmp
= plus_constant (Pmode
, stack_pointer_rtx
,
2956 offset
- GET_MODE_SIZE (GET_MODE (reg
)));
2957 addr
= gen_frame_mem (GET_MODE (reg
),
2958 gen_rtx_PRE_MODIFY (Pmode
,
2963 addr
= gen_frame_mem (GET_MODE (reg
), gen_rtx_PRE_DEC (Pmode
,
2964 stack_pointer_rtx
));
2965 frame_move_inc (addr
, reg
, stack_pointer_rtx
, 0);
2967 return GET_MODE_SIZE (GET_MODE (reg
)) - offset
;
2970 /* Helper used when saving AUX regs during ISR. */
2975 rtx stkslot
= gen_rtx_MEM (GET_MODE (reg
), gen_rtx_PRE_DEC (Pmode
,
2976 stack_pointer_rtx
));
2977 rtx insn
= emit_move_insn (stkslot
, reg
);
2978 RTX_FRAME_RELATED_P (insn
) = 1;
2979 add_reg_note (insn
, REG_CFA_ADJUST_CFA
,
2980 gen_rtx_SET (stack_pointer_rtx
,
2981 plus_constant (Pmode
, stack_pointer_rtx
,
2982 -GET_MODE_SIZE (GET_MODE (reg
)))));
2983 return GET_MODE_SIZE (GET_MODE (reg
));
2986 /* Helper for epilogue: emit frame load with post_modify or post_inc
2987 to restore register REG from stack. The initial offset is passed
2991 frame_restore_reg (rtx reg
, HOST_WIDE_INT offset
)
2997 rtx tmp
= plus_constant (Pmode
, stack_pointer_rtx
,
2998 offset
+ GET_MODE_SIZE (GET_MODE (reg
)));
2999 addr
= gen_frame_mem (GET_MODE (reg
),
3000 gen_rtx_POST_MODIFY (Pmode
,
3005 addr
= gen_frame_mem (GET_MODE (reg
), gen_rtx_POST_INC (Pmode
,
3006 stack_pointer_rtx
));
3007 insn
= frame_move_inc (reg
, addr
, stack_pointer_rtx
, 0);
3008 add_reg_note (insn
, REG_CFA_RESTORE
, reg
);
3010 if (reg
== hard_frame_pointer_rtx
)
3011 add_reg_note (insn
, REG_CFA_DEF_CFA
,
3012 plus_constant (Pmode
, stack_pointer_rtx
,
3013 GET_MODE_SIZE (GET_MODE (reg
)) + offset
));
3015 add_reg_note (insn
, REG_CFA_ADJUST_CFA
,
3016 gen_rtx_SET (stack_pointer_rtx
,
3017 plus_constant (Pmode
, stack_pointer_rtx
,
3018 GET_MODE_SIZE (GET_MODE (reg
))
3021 return GET_MODE_SIZE (GET_MODE (reg
)) + offset
;
3024 /* Helper used when restoring AUX regs during ISR. */
3029 rtx stkslot
= gen_rtx_MEM (GET_MODE (reg
), gen_rtx_POST_INC (Pmode
,
3030 stack_pointer_rtx
));
3031 rtx insn
= emit_move_insn (reg
, stkslot
);
3032 RTX_FRAME_RELATED_P (insn
) = 1;
3033 add_reg_note (insn
, REG_CFA_ADJUST_CFA
,
3034 gen_rtx_SET (stack_pointer_rtx
,
3035 plus_constant (Pmode
, stack_pointer_rtx
,
3036 GET_MODE_SIZE (GET_MODE (reg
)))));
3037 return GET_MODE_SIZE (GET_MODE (reg
));
3040 /* Check if we have a continous range to be save/restored with the
3041 help of enter/leave instructions. A vaild register range starts
3042 from $r13 and is up to (including) $r26. */
3045 arc_enter_leave_p (uint64_t gmask
)
3048 unsigned int rmask
= 0;
3053 for (regno
= ENTER_LEAVE_START_REG
;
3054 regno
<= ENTER_LEAVE_END_REG
&& (gmask
& (1ULL << regno
)); regno
++)
3055 rmask
|= 1ULL << regno
;
3063 /* ARC's prologue, save any needed call-saved regs (and call-used if
3064 this is an interrupt handler) for ARCompact ISA, using ST/STD
3068 arc_save_callee_saves (uint64_t gmask
,
3071 HOST_WIDE_INT offset
,
3075 int frame_allocated
= 0;
3078 /* The home-grown ABI says link register is saved first. */
3081 reg
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
3082 frame_allocated
+= frame_save_reg (reg
, offset
);
3086 /* N.B. FRAME_POINTER_MASK and RETURN_ADDR_MASK are cleared in gmask. */
3088 for (i
= GMASK_LEN
; i
>= 0; i
--)
3090 machine_mode save_mode
= SImode
;
3093 && ((i
- 1) % 2 == 0)
3094 && ((gmask
& (1ULL << i
)) != 0)
3095 && ((gmask
& (1ULL << (i
- 1))) != 0))
3100 else if ((gmask
& (1ULL << i
)) == 0)
3103 reg
= gen_rtx_REG (save_mode
, i
);
3104 frame_allocated
+= frame_save_reg (reg
, offset
);
3108 /* Save frame pointer if needed. First save the FP on stack, if not
3109 autosaved. Unfortunately, I cannot add it to gmask and use the
3110 above loop to save fp because our ABI states fp goes aftert all
3111 registers are saved. */
3114 frame_allocated
+= frame_save_reg (hard_frame_pointer_rtx
, offset
);
3118 /* Emit mov fp,sp. */
3120 frame_move (hard_frame_pointer_rtx
, stack_pointer_rtx
);
3122 return frame_allocated
;
3125 /* ARC's epilogue, restore any required call-saved regs (and call-used
3126 if it is for an interrupt handler) using LD/LDD instructions. */
3129 arc_restore_callee_saves (uint64_t gmask
,
3132 HOST_WIDE_INT offset
,
3133 HOST_WIDE_INT allocated
)
3136 int frame_deallocated
= 0;
3137 HOST_WIDE_INT offs
= cfun
->machine
->frame_info
.reg_size
;
3138 unsigned int fn_type
= arc_compute_function_type (cfun
);
3139 bool early_blink_restore
;
3142 /* Emit mov fp,sp. */
3143 if (arc_frame_pointer_needed () && offset
)
3145 frame_move (stack_pointer_rtx
, hard_frame_pointer_rtx
);
3146 frame_deallocated
+= offset
;
3152 /* Any offset is taken care by previous if-statement. */
3153 gcc_assert (offset
== 0);
3154 frame_deallocated
+= frame_restore_reg (hard_frame_pointer_rtx
, 0);
3159 /* No $fp involved, we need to do an add to set the $sp to the
3160 location of the first register. */
3161 frame_stack_add (offset
);
3162 frame_deallocated
+= offset
;
3166 /* When we do not optimize for size or we aren't in an interrupt,
3167 restore first blink. */
3168 early_blink_restore
= restore_blink
&& !optimize_size
&& offs
3169 && !ARC_INTERRUPT_P (fn_type
);
3170 if (early_blink_restore
)
3172 rtx addr
= plus_constant (Pmode
, stack_pointer_rtx
, offs
);
3173 reg
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
3174 rtx insn
= frame_move_inc (reg
, gen_frame_mem (Pmode
, addr
),
3175 stack_pointer_rtx
, NULL_RTX
);
3176 add_reg_note (insn
, REG_CFA_RESTORE
, reg
);
3177 restore_blink
= false;
3180 /* N.B. FRAME_POINTER_MASK and RETURN_ADDR_MASK are cleared in gmask. */
3182 for (i
= 0; i
<= GMASK_LEN
; i
++)
3184 machine_mode restore_mode
= SImode
;
3188 && ((gmask
& (1ULL << i
)) != 0)
3189 && ((gmask
& (1ULL << (i
+ 1))) != 0))
3190 restore_mode
= DImode
;
3191 else if ((gmask
& (1ULL << i
)) == 0)
3194 reg
= gen_rtx_REG (restore_mode
, i
);
3196 switch (restore_mode
)
3199 if ((GMASK_LEN
- __builtin_clzll (gmask
)) == (i
+ 1)
3200 && early_blink_restore
)
3204 if ((GMASK_LEN
- __builtin_clzll (gmask
)) == i
3205 && early_blink_restore
)
3211 frame_deallocated
+= frame_restore_reg (reg
, offs
);
3214 if (restore_mode
== DImode
)
3220 reg
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
3221 frame_deallocated
+= frame_restore_reg (reg
, allocated
3223 /* Consider as well the
3229 return frame_deallocated
;
3232 /* ARC prologue, save the registers using enter instruction. Leave
3233 instruction can also save $blink (SAVE_BLINK) and $fp (SAVE_FP)
3237 arc_save_callee_enter (uint64_t gmask
,
3240 HOST_WIDE_INT offset
)
3242 int start_reg
= ENTER_LEAVE_START_REG
;
3243 int end_reg
= ENTER_LEAVE_END_REG
;
3244 int regno
, indx
, off
, nregs
;
3246 int frame_allocated
= 0;
3248 for (regno
= start_reg
; regno
<= end_reg
&& (gmask
& (1ULL << regno
));)
3251 end_reg
= regno
- 1;
3252 nregs
= end_reg
- start_reg
+ 1;
3253 nregs
+= save_blink
? 1 : 0;
3254 nregs
+= save_fp
? 1 : 0;
3257 frame_stack_add (offset
);
3259 insn
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (nregs
+ (save_fp
? 1 : 0)
3263 reg
= gen_rtx_SET (stack_pointer_rtx
,
3264 plus_constant (Pmode
,
3266 -nregs
* UNITS_PER_WORD
));
3267 RTX_FRAME_RELATED_P (reg
) = 1;
3268 XVECEXP (insn
, 0, indx
++) = reg
;
3269 off
= nregs
* UNITS_PER_WORD
;
3273 reg
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
3274 mem
= gen_frame_mem (Pmode
, plus_constant (Pmode
,
3277 XVECEXP (insn
, 0, indx
) = gen_rtx_SET (mem
, reg
);
3278 RTX_FRAME_RELATED_P (XVECEXP (insn
, 0, indx
++)) = 1;
3279 off
-= UNITS_PER_WORD
;
3283 for (regno
= start_reg
;
3285 regno
++, indx
++, off
-= UNITS_PER_WORD
)
3287 reg
= gen_rtx_REG (SImode
, regno
);
3288 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
3291 XVECEXP (insn
, 0, indx
) = gen_rtx_SET (mem
, reg
);
3292 RTX_FRAME_RELATED_P (XVECEXP (insn
, 0, indx
)) = 1;
3293 gmask
= gmask
& ~(1ULL << regno
);
3298 mem
= gen_frame_mem (Pmode
, plus_constant (Pmode
,
3301 XVECEXP (insn
, 0, indx
) = gen_rtx_SET (mem
, hard_frame_pointer_rtx
);
3302 RTX_FRAME_RELATED_P (XVECEXP (insn
, 0, indx
++)) = 1;
3303 off
-= UNITS_PER_WORD
;
3305 XVECEXP (insn
, 0, indx
) = gen_rtx_SET (hard_frame_pointer_rtx
,
3307 RTX_FRAME_RELATED_P (XVECEXP (insn
, 0, indx
++)) = 1;
3311 gcc_assert (off
== 0);
3312 insn
= frame_insn (insn
);
3314 add_reg_note (insn
, REG_INC
, stack_pointer_rtx
);
3316 frame_allocated
= nregs
* UNITS_PER_WORD
;
3318 /* offset is a negative number, make sure we add it. */
3319 return frame_allocated
- offset
;
3322 /* ARC epilogue, restore the registers using leave instruction. An
3323 initial offset is passed in OFFSET. Besides restoring an register
3324 range, leave can also restore $blink (RESTORE_BLINK), or $fp
3325 (RESTORE_FP), and can automatic return (RETURN_P). */
3328 arc_restore_callee_leave (uint64_t gmask
,
3332 HOST_WIDE_INT offset
)
3334 int start_reg
= ENTER_LEAVE_START_REG
;
3335 int end_reg
= ENTER_LEAVE_END_REG
;
3336 int regno
, indx
, off
, nregs
;
3338 int frame_allocated
= 0;
3340 for (regno
= start_reg
; regno
<= end_reg
&& (gmask
& (1ULL << regno
));)
3343 end_reg
= regno
- 1;
3344 nregs
= end_reg
- start_reg
+ 1;
3345 nregs
+= restore_blink
? 1 : 0;
3346 nregs
+= restore_fp
? 1 : 0;
3348 insn
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (nregs
+ 1
3349 + (return_p
? 1 : 0)));
3353 XVECEXP (insn
, 0, indx
++) = ret_rtx
;
3357 /* I cannot emit set (sp, fp) here as cselib expects a single sp
3358 set and not two. Thus, use the offset, and change sp adjust
3360 frame_allocated
+= offset
;
3363 if (offset
&& !restore_fp
)
3365 /* This add is only emmited when we do not restore fp with leave
3367 frame_stack_add (offset
);
3368 frame_allocated
+= offset
;
3372 reg
= gen_rtx_SET (stack_pointer_rtx
,
3373 plus_constant (Pmode
,
3375 offset
+ nregs
* UNITS_PER_WORD
));
3376 RTX_FRAME_RELATED_P (reg
) = 1;
3377 XVECEXP (insn
, 0, indx
++) = reg
;
3378 off
= nregs
* UNITS_PER_WORD
;
3382 reg
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
3383 mem
= gen_frame_mem (Pmode
, plus_constant (Pmode
,
3386 XVECEXP (insn
, 0, indx
) = gen_rtx_SET (reg
, mem
);
3387 RTX_FRAME_RELATED_P (XVECEXP (insn
, 0, indx
++)) = 1;
3388 off
-= UNITS_PER_WORD
;
3391 for (regno
= start_reg
;
3393 regno
++, indx
++, off
-= UNITS_PER_WORD
)
3395 reg
= gen_rtx_REG (SImode
, regno
);
3396 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
3399 XVECEXP (insn
, 0, indx
) = gen_rtx_SET (reg
, mem
);
3400 RTX_FRAME_RELATED_P (XVECEXP (insn
, 0, indx
)) = 1;
3401 gmask
= gmask
& ~(1ULL << regno
);
3406 mem
= gen_frame_mem (Pmode
, plus_constant (Pmode
,
3409 XVECEXP (insn
, 0, indx
) = gen_rtx_SET (hard_frame_pointer_rtx
, mem
);
3410 RTX_FRAME_RELATED_P (XVECEXP (insn
, 0, indx
++)) = 1;
3411 off
-= UNITS_PER_WORD
;
3414 gcc_assert (off
== 0);
3417 insn
= emit_jump_insn (insn
);
3418 RTX_FRAME_RELATED_P (insn
) = 1;
3421 insn
= frame_insn (insn
);
3423 add_reg_note (insn
, REG_INC
, stack_pointer_rtx
);
3425 /* Dwarf related info. */
3428 add_reg_note (insn
, REG_CFA_RESTORE
, hard_frame_pointer_rtx
);
3429 add_reg_note (insn
, REG_CFA_DEF_CFA
,
3430 plus_constant (Pmode
, stack_pointer_rtx
,
3431 offset
+ nregs
* UNITS_PER_WORD
));
3435 add_reg_note (insn
, REG_CFA_ADJUST_CFA
,
3436 gen_rtx_SET (stack_pointer_rtx
,
3437 plus_constant (Pmode
, stack_pointer_rtx
,
3438 nregs
* UNITS_PER_WORD
)));
3441 add_reg_note (insn
, REG_CFA_RESTORE
,
3442 gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
));
3443 for (regno
= start_reg
; regno
<= end_reg
; regno
++)
3444 add_reg_note (insn
, REG_CFA_RESTORE
, gen_rtx_REG (SImode
, regno
));
3446 frame_allocated
+= nregs
* UNITS_PER_WORD
;
3448 return frame_allocated
;
3451 /* Millicode thunks implementation:
3452 Generates calls to millicodes for registers starting from r13 to r25
3453 Present Limitations:
3454 - Only one range supported. The remaining regs will have the ordinary
3455 st and ld instructions for store and loads. Hence a gmask asking
3456 to store r13-14, r16-r25 will only generate calls to store and
3457 load r13 to r14 while store and load insns will be generated for
3458 r16 to r25 in the prologue and epilogue respectively.
3460 - Presently library only supports register ranges starting from r13.
3464 arc_save_callee_milli (uint64_t gmask
,
3467 HOST_WIDE_INT offset
,
3468 HOST_WIDE_INT reg_size
)
3472 int regno
, indx
, off
, nregs
;
3474 int frame_allocated
= 0;
3476 for (regno
= start_reg
; regno
<= end_reg
&& (gmask
& (1ULL << regno
));)
3479 end_reg
= regno
- 1;
3480 nregs
= end_reg
- start_reg
+ 1;
3481 gcc_assert (end_reg
> 14);
3484 /* Allocate space on stack for the registers, and take into account
3485 also the initial offset. The registers will be saved using
3486 offsets. N.B. OFFSET is a negative number. */
3489 reg
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
3490 frame_allocated
+= frame_save_reg (reg
, offset
);
3494 if (reg_size
|| offset
)
3496 frame_stack_add (offset
- reg_size
);
3497 frame_allocated
+= nregs
* UNITS_PER_WORD
- offset
;
3501 /* Start generate millicode call. */
3502 insn
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (nregs
+ 1));
3505 /* This is a call, we clobber blink. */
3506 XVECEXP (insn
, 0, nregs
) =
3507 gen_rtx_CLOBBER (VOIDmode
, gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
));
3509 for (regno
= start_reg
, indx
= 0, off
= 0;
3511 regno
++, indx
++, off
+= UNITS_PER_WORD
)
3513 reg
= gen_rtx_REG (SImode
, regno
);
3514 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
3517 XVECEXP (insn
, 0, indx
) = gen_rtx_SET (mem
, reg
);
3518 RTX_FRAME_RELATED_P (XVECEXP (insn
, 0, indx
)) = 1;
3519 gmask
= gmask
& ~(1ULL << regno
);
3521 insn
= frame_insn (insn
);
3523 /* Add DWARF info. */
3524 for (regno
= start_reg
, off
= 0;
3526 regno
++, off
+= UNITS_PER_WORD
)
3528 reg
= gen_rtx_REG (SImode
, regno
);
3529 mem
= gen_rtx_MEM (SImode
, plus_constant (Pmode
,
3530 stack_pointer_rtx
, off
));
3531 add_reg_note (insn
, REG_CFA_OFFSET
, gen_rtx_SET (mem
, reg
));
3535 /* In the case of millicode thunk, we need to restore the
3536 clobbered blink register. */
3537 if (arc_must_save_return_addr (cfun
))
3539 emit_insn (gen_rtx_SET (gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
),
3541 plus_constant (Pmode
,
3546 /* Save remaining registers using st instructions. */
3547 for (regno
= 0; regno
<= GMASK_LEN
; regno
++)
3549 if ((gmask
& (1ULL << regno
)) == 0)
3552 reg
= gen_rtx_REG (SImode
, regno
);
3553 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
3556 frame_move_inc (mem
, reg
, stack_pointer_rtx
, 0);
3557 frame_allocated
+= UNITS_PER_WORD
;
3558 off
+= UNITS_PER_WORD
;
3561 /* Save frame pointer if needed. First save the FP on stack, if not
3562 autosaved. Unfortunately, I cannot add it to gmask and use the
3563 above loop to save fp because our ABI states fp goes aftert all
3564 registers are saved. */
3566 frame_allocated
+= frame_save_reg (hard_frame_pointer_rtx
, offset
);
3568 /* Emit mov fp,sp. */
3569 if (arc_frame_pointer_needed ())
3570 frame_move (hard_frame_pointer_rtx
, stack_pointer_rtx
);
3572 return frame_allocated
;
3575 /* Like the previous function but restore. */
3578 arc_restore_callee_milli (uint64_t gmask
,
3582 HOST_WIDE_INT offset
)
3586 int regno
, indx
, off
, nregs
;
3588 int frame_allocated
= 0;
3590 for (regno
= start_reg
; regno
<= end_reg
&& (gmask
& (1ULL << regno
));)
3593 end_reg
= regno
- 1;
3594 nregs
= end_reg
- start_reg
+ 1;
3595 gcc_assert (end_reg
> 14);
3597 /* Emit mov fp,sp. */
3598 if (arc_frame_pointer_needed () && offset
)
3600 frame_move (stack_pointer_rtx
, hard_frame_pointer_rtx
);
3601 frame_allocated
= offset
;
3606 frame_allocated
+= frame_restore_reg (hard_frame_pointer_rtx
, 0);
3610 /* No fp involved, hence, we need to adjust the sp via an
3612 frame_stack_add (offset
);
3613 frame_allocated
+= offset
;
3617 /* Start generate millicode call. */
3618 insn
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc ((return_p
? 1 : 0)
3624 /* sibling call, the blink is restored with the help of the
3625 value held into r12. */
3626 reg
= gen_rtx_REG (Pmode
, 12);
3627 XVECEXP (insn
, 0, indx
++) = ret_rtx
;
3628 XVECEXP (insn
, 0, indx
++) =
3629 gen_rtx_SET (stack_pointer_rtx
,
3630 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
, reg
));
3631 frame_allocated
+= UNITS_PER_WORD
;
3635 /* This is a call, we clobber blink. */
3636 XVECEXP (insn
, 0, nregs
) =
3637 gen_rtx_CLOBBER (VOIDmode
, gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
));
3640 for (regno
= start_reg
, off
= 0;
3642 regno
++, indx
++, off
+= UNITS_PER_WORD
)
3644 reg
= gen_rtx_REG (SImode
, regno
);
3645 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
3648 XVECEXP (insn
, 0, indx
) = gen_rtx_SET (reg
, mem
);
3649 RTX_FRAME_RELATED_P (XVECEXP (insn
, 0, indx
)) = 1;
3650 gmask
= gmask
& ~(1ULL << regno
);
3653 /* Restore remaining registers using LD instructions. */
3654 for (regno
= 0; regno
<= GMASK_LEN
; regno
++)
3656 if ((gmask
& (1ULL << regno
)) == 0)
3659 reg
= gen_rtx_REG (SImode
, regno
);
3660 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
3663 rtx tmp
= frame_move_inc (reg
, mem
, stack_pointer_rtx
, 0);
3664 add_reg_note (tmp
, REG_CFA_RESTORE
, reg
);
3665 off
+= UNITS_PER_WORD
;
3668 /* Emit millicode call. */
3671 reg
= gen_rtx_REG (Pmode
, 12);
3672 frame_insn (gen_rtx_SET (reg
, GEN_INT (off
)));
3673 frame_allocated
+= off
;
3674 insn
= emit_jump_insn (insn
);
3675 RTX_FRAME_RELATED_P (insn
) = 1;
3678 insn
= frame_insn (insn
);
3680 /* Add DWARF info. */
3681 for (regno
= start_reg
; regno
<= end_reg
; regno
++)
3683 reg
= gen_rtx_REG (SImode
, regno
);
3684 add_reg_note (insn
, REG_CFA_RESTORE
, reg
);
3688 if (restore_blink
&& !return_p
)
3690 reg
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
3691 mem
= gen_frame_mem (Pmode
, plus_constant (Pmode
, stack_pointer_rtx
,
3693 insn
= frame_insn (gen_rtx_SET (reg
, mem
));
3694 add_reg_note (insn
, REG_CFA_RESTORE
, reg
);
3697 return frame_allocated
;
3700 /* Set up the stack and frame pointer (if desired) for the function. */
3703 arc_expand_prologue (void)
3706 uint64_t gmask
= cfun
->machine
->frame_info
.gmask
;
3707 struct arc_frame_info
*frame
= &cfun
->machine
->frame_info
;
3708 unsigned int frame_size_to_allocate
;
3709 int first_offset
= 0;
3710 unsigned int fn_type
= arc_compute_function_type (cfun
);
3711 bool save_blink
= false;
3712 bool save_fp
= false;
3713 bool emit_move
= false;
3715 /* Naked functions don't have prologue. */
3716 if (ARC_NAKED_P (fn_type
))
3718 if (flag_stack_usage_info
)
3719 current_function_static_stack_size
= 0;
3723 /* Compute total frame size. */
3724 size
= arc_compute_frame_size ();
3726 if (flag_stack_usage_info
)
3727 current_function_static_stack_size
= size
;
3729 /* Keep track of frame size to be allocated. */
3730 frame_size_to_allocate
= size
;
3732 /* These cases shouldn't happen. Catch them now. */
3733 gcc_assert (!(size
== 0 && gmask
));
3735 /* Allocate space for register arguments if this is a variadic function. */
3736 if (frame
->pretend_size
!= 0)
3737 first_offset
= -frame
->pretend_size
;
3739 /* IRQ using automatic save mechanism will save the register before
3741 if (ARC_AUTO_IRQ_P (fn_type
)
3742 && !ARC_FAST_INTERRUPT_P (fn_type
))
3744 frame_stack_add (first_offset
);
3746 arc_dwarf_emit_irq_save_regs ();
3749 save_blink
= arc_must_save_return_addr (cfun
)
3750 && !ARC_AUTOBLINK_IRQ_P (fn_type
);
3751 save_fp
= arc_frame_pointer_needed () && !ARC_AUTOFP_IRQ_P (fn_type
)
3752 && !ARC_INTERRUPT_P (fn_type
);
3753 emit_move
= arc_frame_pointer_needed () && !ARC_INTERRUPT_P (fn_type
);
3755 /* Use enter/leave only for non-interrupt functions. */
3756 if (TARGET_CODE_DENSITY
3757 && TARGET_CODE_DENSITY_FRAME
3758 && !ARC_AUTOFP_IRQ_P (fn_type
)
3759 && !ARC_AUTOBLINK_IRQ_P (fn_type
)
3760 && !ARC_INTERRUPT_P (fn_type
)
3761 && arc_enter_leave_p (gmask
))
3762 frame_size_to_allocate
-= arc_save_callee_enter (gmask
, save_blink
,
3765 else if (frame
->millicode_end_reg
> 14)
3766 frame_size_to_allocate
-= arc_save_callee_milli (gmask
, save_blink
,
3771 frame_size_to_allocate
-= arc_save_callee_saves (gmask
, save_blink
, save_fp
,
3772 first_offset
, emit_move
);
3774 /* Check if we need to save the ZOL machinery. */
3775 if (arc_lpcwidth
!= 0 && arc_must_save_register (LP_COUNT
, cfun
, true))
3777 rtx reg0
= gen_rtx_REG (SImode
, R0_REG
);
3778 emit_insn (gen_rtx_SET (reg0
,
3779 gen_rtx_UNSPEC_VOLATILE
3780 (Pmode
, gen_rtvec (1, GEN_INT (AUX_LP_START
)),
3782 frame_size_to_allocate
-= push_reg (reg0
);
3783 emit_insn (gen_rtx_SET (reg0
,
3784 gen_rtx_UNSPEC_VOLATILE
3785 (Pmode
, gen_rtvec (1, GEN_INT (AUX_LP_END
)),
3787 frame_size_to_allocate
-= push_reg (reg0
);
3788 emit_move_insn (reg0
, gen_rtx_REG (SImode
, LP_COUNT
));
3789 frame_size_to_allocate
-= push_reg (reg0
);
3792 /* Save AUX regs used by FPX machinery. */
3793 if (arc_must_save_register (TARGET_BIG_ENDIAN
? R41_REG
: R40_REG
,
3796 rtx reg0
= gen_rtx_REG (SImode
, R0_REG
);
3799 for (i
= 0; i
< 4; i
++)
3801 emit_insn (gen_rtx_SET (reg0
,
3802 gen_rtx_UNSPEC_VOLATILE
3803 (Pmode
, gen_rtvec (1, GEN_INT (AUX_DPFP_START
3806 frame_size_to_allocate
-= push_reg (reg0
);
3810 /* Save accumulator registers. */
3811 if (arc_must_save_register (R58_REG
, cfun
, true))
3812 frame_size_to_allocate
-= arc_save_callee_saves (3ULL << 58,
3813 false, false, 0, false);
3815 if (arc_frame_pointer_needed () && ARC_INTERRUPT_P (fn_type
))
3817 /* Just save fp at the end of the saving context. */
3818 frame_size_to_allocate
-=
3819 arc_save_callee_saves (0, false, !ARC_AUTOFP_IRQ_P (fn_type
), 0, true);
3822 /* Allocate the stack frame. */
3823 if (frame_size_to_allocate
> 0)
3824 frame_stack_add ((HOST_WIDE_INT
) 0 - frame_size_to_allocate
);
3826 /* Emit a blockage to avoid delay slot scheduling. */
3827 emit_insn (gen_blockage ());
3830 /* Return the register number of the register holding the return address
3831 for a function of type TYPE. */
3834 arc_return_address_register (unsigned int fn_type
)
3838 if (ARC_INTERRUPT_P (fn_type
))
3840 if ((fn_type
& (ARC_FUNCTION_ILINK1
| ARC_FUNCTION_FIRQ
)) != 0)
3842 else if ((fn_type
& ARC_FUNCTION_ILINK2
) != 0)
3847 else if (ARC_NORMAL_P (fn_type
) || ARC_NAKED_P (fn_type
))
3848 regno
= RETURN_ADDR_REGNUM
;
3850 gcc_assert (regno
!= 0);
3854 /* Do any necessary cleanup after a function to restore stack, frame,
3858 arc_expand_epilogue (int sibcall_p
)
3861 unsigned int fn_type
= arc_compute_function_type (cfun
);
3862 unsigned int size_to_deallocate
;
3864 int can_trust_sp_p
= !cfun
->calls_alloca
;
3866 bool restore_fp
= arc_frame_pointer_needed () && !ARC_AUTOFP_IRQ_P (fn_type
);
3867 bool restore_blink
= arc_must_save_return_addr (cfun
)
3868 && !ARC_AUTOBLINK_IRQ_P (fn_type
);
3869 uint64_t gmask
= cfun
->machine
->frame_info
.gmask
;
3870 bool return_p
= !sibcall_p
&& fn_type
== ARC_FUNCTION_NORMAL
3871 && !cfun
->machine
->frame_info
.pretend_size
;
3872 struct arc_frame_info
*frame
= &cfun
->machine
->frame_info
;
3874 /* Naked functions don't have epilogue. */
3875 if (ARC_NAKED_P (fn_type
))
3878 size
= arc_compute_frame_size ();
3879 size_to_deallocate
= size
;
3881 first_offset
= size
- (frame
->pretend_size
+ frame
->reg_size
3882 + frame
->extra_size
);
3884 if (!can_trust_sp_p
)
3885 gcc_assert (arc_frame_pointer_needed ());
3887 /* Emit a blockage to avoid/flush all pending sp operations. */
3889 emit_insn (gen_blockage ());
3891 if (ARC_INTERRUPT_P (fn_type
))
3893 /* We need to restore FP before any SP operation in an
3895 size_to_deallocate
-= arc_restore_callee_saves (0, false,
3898 size_to_deallocate
);
3903 /* Restore accumulator registers. */
3904 if (arc_must_save_register (R58_REG
, cfun
, true))
3907 rtx reg0
= gen_rtx_REG (SImode
, R0_REG
);
3908 rtx reg1
= gen_rtx_REG (SImode
, R1_REG
);
3909 size_to_deallocate
-= pop_reg (reg0
);
3910 size_to_deallocate
-= pop_reg (reg1
);
3912 insn
= emit_insn (gen_mulu64 (reg0
, const1_rtx
));
3913 add_reg_note (insn
, REG_CFA_RESTORE
, gen_rtx_REG (SImode
, R58_REG
));
3914 RTX_FRAME_RELATED_P (insn
) = 1;
3915 emit_insn (gen_arc600_stall ());
3916 insn
= emit_insn (gen_rtx_UNSPEC_VOLATILE
3917 (VOIDmode
, gen_rtvec (2, reg1
, GEN_INT (AUX_MULHI
)),
3919 add_reg_note (insn
, REG_CFA_RESTORE
, gen_rtx_REG (SImode
, R59_REG
));
3920 RTX_FRAME_RELATED_P (insn
) = 1;
3923 /* Restore AUX-regs used by FPX machinery. */
3924 if (arc_must_save_register (TARGET_BIG_ENDIAN
? R41_REG
: R40_REG
,
3927 rtx reg0
= gen_rtx_REG (SImode
, R0_REG
);
3930 for (i
= 0; i
< 4; i
++)
3932 size_to_deallocate
-= pop_reg (reg0
);
3933 emit_insn (gen_rtx_UNSPEC_VOLATILE
3934 (VOIDmode
, gen_rtvec (2, reg0
, GEN_INT (AUX_DPFP_START
3940 /* Check if we need to restore the ZOL machinery. */
3941 if (arc_lpcwidth
!=0 && arc_must_save_register (LP_COUNT
, cfun
, true))
3943 rtx reg0
= gen_rtx_REG (SImode
, R0_REG
);
3945 size_to_deallocate
-= pop_reg (reg0
);
3946 emit_move_insn (gen_rtx_REG (SImode
, LP_COUNT
), reg0
);
3948 size_to_deallocate
-= pop_reg (reg0
);
3949 emit_insn (gen_rtx_UNSPEC_VOLATILE
3950 (VOIDmode
, gen_rtvec (2, reg0
, GEN_INT (AUX_LP_END
)),
3953 size_to_deallocate
-= pop_reg (reg0
);
3954 emit_insn (gen_rtx_UNSPEC_VOLATILE
3955 (VOIDmode
, gen_rtvec (2, reg0
, GEN_INT (AUX_LP_START
)),
3959 if (TARGET_CODE_DENSITY
3960 && TARGET_CODE_DENSITY_FRAME
3961 && !ARC_AUTOFP_IRQ_P (fn_type
)
3962 && !ARC_AUTOBLINK_IRQ_P (fn_type
)
3963 && !ARC_INTERRUPT_P (fn_type
)
3964 && arc_enter_leave_p (gmask
))
3966 /* Using leave instruction. */
3967 size_to_deallocate
-= arc_restore_callee_leave (gmask
, restore_blink
,
3973 gcc_assert (size_to_deallocate
== 0);
3977 else if (frame
->millicode_end_reg
> 14)
3979 /* Using millicode calls. */
3980 size_to_deallocate
-= arc_restore_callee_milli (gmask
, restore_blink
,
3986 gcc_assert (size_to_deallocate
== 0);
3991 size_to_deallocate
-= arc_restore_callee_saves (gmask
, restore_blink
,
3994 size_to_deallocate
);
3996 /* Keep track of how much of the stack pointer we've restored. It
3997 makes the following a lot more readable. */
3998 restored
= size
- size_to_deallocate
;
4000 if (size
> restored
)
4001 frame_stack_add (size
- restored
);
4003 /* For frames that use __builtin_eh_return, the register defined by
4004 EH_RETURN_STACKADJ_RTX is set to 0 for all standard return paths.
4005 On eh_return paths however, the register is set to the value that
4006 should be added to the stack pointer in order to restore the
4007 correct stack pointer for the exception handling frame.
4009 For ARC we are going to use r2 for EH_RETURN_STACKADJ_RTX, add
4010 this onto the stack for eh_return frames. */
4011 if (crtl
->calls_eh_return
)
4012 emit_insn (gen_add2_insn (stack_pointer_rtx
,
4013 EH_RETURN_STACKADJ_RTX
));
4015 /* Emit the return instruction. */
4016 if (ARC_INTERRUPT_P (fn_type
))
4018 rtx ra
= gen_rtx_REG (Pmode
, arc_return_address_register (fn_type
));
4021 emit_jump_insn (gen_rtie ());
4022 else if (TARGET_ARC700
)
4023 emit_jump_insn (gen_rtie ());
4025 emit_jump_insn (gen_arc600_rtie (ra
));
4027 else if (sibcall_p
== FALSE
)
4028 emit_jump_insn (gen_simple_return ());
4031 /* Helper for {push/pop}_multi_operand: check if rtx OP is a suitable
4032 construct to match either enter or leave instruction. Which one
4033 which is selected by PUSH_P argument. */
4036 arc_check_multi (rtx op
, bool push_p
)
4038 HOST_WIDE_INT len
= XVECLEN (op
, 0);
4039 unsigned int regno
, i
, start
;
4040 unsigned int memp
= push_p
? 0 : 1;
4047 elt
= XVECEXP (op
, 0, 0);
4048 if (!push_p
&& GET_CODE (elt
) == RETURN
)
4051 for (i
= start
, regno
= ENTER_LEAVE_START_REG
; i
< len
; i
++, regno
++)
4053 rtx elt
= XVECEXP (op
, 0, i
);
4056 if (GET_CODE (elt
) != SET
)
4058 mem
= XEXP (elt
, memp
);
4059 reg
= XEXP (elt
, 1 - memp
);
4065 /* Check for blink. */
4066 if (REGNO (reg
) == RETURN_ADDR_REGNUM
4069 else if (REGNO (reg
) == HARD_FRAME_POINTER_REGNUM
)
4071 else if (REGNO (reg
) != regno
)
4074 addr
= XEXP (mem
, 0);
4075 if (GET_CODE (addr
) == PLUS
)
4077 if (!rtx_equal_p (stack_pointer_rtx
, XEXP (addr
, 0))
4078 || !CONST_INT_P (XEXP (addr
, 1)))
4083 if (!rtx_equal_p (stack_pointer_rtx
, addr
))
4090 /* Return rtx for the location of the return address on the stack,
4091 suitable for use in __builtin_eh_return. The new return address
4092 will be written to this location in order to redirect the return to
4093 the exception handler. Our ABI says the blink is pushed first on
4094 stack followed by an unknown number of register saves, and finally
4095 by fp. Hence we cannot use the EH_RETURN_ADDRESS macro as the
4096 stack is not finalized. */
4099 arc_eh_return_address_location (rtx source
)
4103 struct arc_frame_info
*afi
;
4105 arc_compute_frame_size ();
4106 afi
= &cfun
->machine
->frame_info
;
4108 gcc_assert (crtl
->calls_eh_return
);
4109 gcc_assert (afi
->save_return_addr
);
4110 gcc_assert (afi
->extra_size
>= 4);
4112 /* The '-4' removes the size of the return address, which is
4113 included in the 'extra_size' field. */
4114 offset
= afi
->reg_size
+ afi
->extra_size
- 4;
4115 mem
= gen_frame_mem (Pmode
,
4116 plus_constant (Pmode
, hard_frame_pointer_rtx
, offset
));
4118 /* The following should not be needed, and is, really a hack. The
4119 issue being worked around here is that the DSE (Dead Store
4120 Elimination) pass will remove this write to the stack as it sees
4121 a single store and no corresponding read. The read however
4122 occurs in the epilogue code, which is not added into the function
4123 rtl until a later pass. So, at the time of DSE, the decision to
4124 remove this store seems perfectly sensible. Marking the memory
4125 address as volatile obviously has the effect of preventing DSE
4126 from removing the store. */
4127 MEM_VOLATILE_P (mem
) = true;
4128 emit_move_insn (mem
, source
);
4133 /* Helper to generate unspec constant. */
4136 arc_unspec_offset (rtx loc
, int unspec
)
4138 return gen_rtx_CONST (Pmode
, gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, loc
),
4142 /* Predicate for pre-reload splitters with associated instructions,
4143 which can match any time before the split1 pass (usually combine),
4144 then are unconditionally split in that pass and should not be
4145 matched again afterwards. */
4148 arc_pre_reload_split (void)
4150 return (can_create_pseudo_p ()
4151 && !(cfun
->curr_properties
& PROP_rtl_split_insns
));
4154 /* Output the assembler code for a zero-overhead loop doing a shift
4155 or rotate. We know OPERANDS[0] == OPERANDS[1], and the bit count
4159 output_shift_loop (enum rtx_code code
, rtx
*operands
)
4161 bool twice_p
= false;
4162 gcc_assert (GET_MODE (operands
[0]) == SImode
);
4164 if (GET_CODE (operands
[2]) != CONST_INT
)
4166 output_asm_insn ("and.f\tlp_count,%2,0x1f", operands
);
4167 output_asm_insn ("lpnz\t2f", operands
);
4171 int n
= INTVAL (operands
[2]) & 31;
4174 output_asm_insn ("mov\t%0,%1",operands
);
4178 if ((n
& 1) == 0 && code
!= ROTATE
)
4183 operands
[2] = GEN_INT (n
);
4184 output_asm_insn ("mov\tlp_count,%2", operands
);
4185 output_asm_insn ("lp\t2f", operands
);
4191 output_asm_insn ("add\t%0,%1,%1", operands
);
4193 output_asm_insn ("add\t%0,%1,%1", operands
);
4196 output_asm_insn ("asr\t%0,%1", operands
);
4198 output_asm_insn ("asr\t%0,%1", operands
);
4201 output_asm_insn ("lsr\t%0,%1", operands
);
4203 output_asm_insn ("lsr\t%0,%1", operands
);
4206 output_asm_insn ("ror\t%0,%1", operands
);
4208 output_asm_insn ("ror\t%0,%1", operands
);
4211 output_asm_insn ("add.f\t%0,%1,%1", operands
);
4212 output_asm_insn ("adc\t%0,%0,0", operands
);
4220 output_asm_insn ("nop", operands
);
4221 fprintf (asm_out_file
, "2:\t%s end single insn loop\n", ASM_COMMENT_START
);
4225 /* See below where shifts are handled for explanation of this enum. */
4228 SHIFT_MOVE
, /* Register-to-register move. */
4229 SHIFT_LOOP
, /* Zero-overhead loop implementation. */
4230 SHIFT_INLINE
, /* Mmultiple LSHIFTs and LSHIFT-PLUSs. */
4231 SHIFT_AND_ROT
, /* Bitwise AND, then ROTATERTs. */
4232 SHIFT_SWAP
, /* SWAP then multiple LSHIFTs/LSHIFT-PLUSs. */
4233 SHIFT_AND_SWAP_ROT
/* Bitwise AND, then SWAP, then ROTATERTs. */
4236 struct arc_shift_info
{
4237 enum arc_shift_alg alg
;
4241 /* Return shift algorithm context, an index into the following tables.
4242 * 0 for -Os (optimize for size) 3 for -O2 (optimized for speed)
4243 * 1 for -Os -mswap TARGET_V2 4 for -O2 -mswap TARGET_V2
4244 * 2 for -Os -mswap !TARGET_V2 5 for -O2 -mswap !TARGET_V2 */
4246 arc_shift_context_idx ()
4248 if (optimize_function_for_size_p (cfun
))
4266 static const arc_shift_info arc_ashl_alg
[6][32] = {
4268 { SHIFT_MOVE
, COSTS_N_INSNS (1) }, /* 0 */
4269 { SHIFT_INLINE
, COSTS_N_INSNS (1) }, /* 1 */
4270 { SHIFT_INLINE
, COSTS_N_INSNS (2) }, /* 2 */
4271 { SHIFT_INLINE
, COSTS_N_INSNS (2) }, /* 3 */
4272 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 4 */
4273 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 5 */
4274 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 6 */
4275 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 7 */
4276 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 8 */
4277 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 9 */
4278 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 10 */
4279 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 11 */
4280 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 12 */
4281 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 13 */
4282 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 14 */
4283 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 15 */
4284 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 16 */
4285 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 17 */
4286 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 18 */
4287 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 19 */
4288 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 20 */
4289 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 21 */
4290 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 22 */
4291 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 23 */
4292 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 24 */
4293 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 25 */
4294 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 26 */
4295 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 27 */
4296 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 28 */
4297 { SHIFT_AND_ROT
, COSTS_N_INSNS (4) }, /* 29 */
4298 { SHIFT_AND_ROT
, COSTS_N_INSNS (3) }, /* 30 */
4299 { SHIFT_AND_ROT
, COSTS_N_INSNS (2) } /* 31 */
4301 { /* 1: -Os -mswap TARGET_V2. */
4302 { SHIFT_MOVE
, COSTS_N_INSNS (1) }, /* 0 */
4303 { SHIFT_INLINE
, COSTS_N_INSNS (1) }, /* 1 */
4304 { SHIFT_INLINE
, COSTS_N_INSNS (2) }, /* 2 */
4305 { SHIFT_INLINE
, COSTS_N_INSNS (2) }, /* 3 */
4306 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 4 */
4307 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 5 */
4308 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 6 */
4309 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 7 */
4310 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 8 */
4311 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 9 */
4312 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 10 */
4313 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 11 */
4314 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 12 */
4315 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 13 */
4316 { SHIFT_AND_SWAP_ROT
, COSTS_N_INSNS (4) }, /* 14 */
4317 { SHIFT_AND_SWAP_ROT
, COSTS_N_INSNS (3) }, /* 15 */
4318 { SHIFT_SWAP
, COSTS_N_INSNS (1) }, /* 16 */
4319 { SHIFT_SWAP
, COSTS_N_INSNS (2) }, /* 17 */
4320 { SHIFT_SWAP
, COSTS_N_INSNS (3) }, /* 18 */
4321 { SHIFT_SWAP
, COSTS_N_INSNS (3) }, /* 19 */
4322 { SHIFT_SWAP
, COSTS_N_INSNS (4) }, /* 20 */
4323 { SHIFT_SWAP
, COSTS_N_INSNS (4) }, /* 21 */
4324 { SHIFT_SWAP
, COSTS_N_INSNS (4) }, /* 22 */
4325 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 23 */
4326 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 24 */
4327 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 25 */
4328 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 26 */
4329 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 27 */
4330 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 28 */
4331 { SHIFT_AND_ROT
, COSTS_N_INSNS (4) }, /* 29 */
4332 { SHIFT_AND_ROT
, COSTS_N_INSNS (3) }, /* 30 */
4333 { SHIFT_AND_ROT
, COSTS_N_INSNS (2) } /* 31 */
4335 { /* 2: -Os -mswap !TARGET_V2. */
4336 { SHIFT_MOVE
, COSTS_N_INSNS (1) }, /* 0 */
4337 { SHIFT_INLINE
, COSTS_N_INSNS (1) }, /* 1 */
4338 { SHIFT_INLINE
, COSTS_N_INSNS (2) }, /* 2 */
4339 { SHIFT_INLINE
, COSTS_N_INSNS (2) }, /* 3 */
4340 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 4 */
4341 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 5 */
4342 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 6 */
4343 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 7 */
4344 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 8 */
4345 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 9 */
4346 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 10 */
4347 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 11 */
4348 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 12 */
4349 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 13 */
4350 { SHIFT_AND_SWAP_ROT
, COSTS_N_INSNS (4) }, /* 14 */
4351 { SHIFT_AND_SWAP_ROT
, COSTS_N_INSNS (3) }, /* 15 */
4352 { SHIFT_SWAP
, COSTS_N_INSNS (2) }, /* 16 */
4353 { SHIFT_SWAP
, COSTS_N_INSNS (3) }, /* 17 */
4354 { SHIFT_SWAP
, COSTS_N_INSNS (4) }, /* 18 */
4355 { SHIFT_SWAP
, COSTS_N_INSNS (4) }, /* 19 */
4356 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 20 */
4357 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 21 */
4358 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 22 */
4359 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 23 */
4360 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 24 */
4361 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 25 */
4362 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 26 */
4363 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 27 */
4364 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 28 */
4365 { SHIFT_AND_ROT
, COSTS_N_INSNS (4) }, /* 29 */
4366 { SHIFT_AND_ROT
, COSTS_N_INSNS (3) }, /* 30 */
4367 { SHIFT_AND_ROT
, COSTS_N_INSNS (2) } /* 31 */
4370 { SHIFT_MOVE
, COSTS_N_INSNS (1) }, /* 0 */
4371 { SHIFT_INLINE
, COSTS_N_INSNS (1) }, /* 1 */
4372 { SHIFT_INLINE
, COSTS_N_INSNS (2) }, /* 2 */
4373 { SHIFT_INLINE
, COSTS_N_INSNS (2) }, /* 3 */
4374 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 4 */
4375 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 5 */
4376 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 6 */
4377 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 7 */
4378 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 8 */
4379 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 9 */
4380 { SHIFT_INLINE
, COSTS_N_INSNS (5) }, /* 10 */
4381 { SHIFT_INLINE
, COSTS_N_INSNS (5) }, /* 11 */
4382 { SHIFT_INLINE
, COSTS_N_INSNS (5) }, /* 12 */
4383 { SHIFT_INLINE
, COSTS_N_INSNS (6) }, /* 13 */
4384 { SHIFT_INLINE
, COSTS_N_INSNS (6) }, /* 14 */
4385 { SHIFT_INLINE
, COSTS_N_INSNS (6) }, /* 15 */
4386 { SHIFT_INLINE
, COSTS_N_INSNS (7) }, /* 16 */
4387 { SHIFT_INLINE
, COSTS_N_INSNS (7) }, /* 17 */
4388 { SHIFT_INLINE
, COSTS_N_INSNS (7) }, /* 18 */
4389 { SHIFT_INLINE
, COSTS_N_INSNS (8) }, /* 19 */
4390 { SHIFT_INLINE
, COSTS_N_INSNS (8) }, /* 20 */
4391 { SHIFT_INLINE
, COSTS_N_INSNS (8) }, /* 21 */
4392 { SHIFT_INLINE
, COSTS_N_INSNS (9) }, /* 22 */
4393 { SHIFT_INLINE
, COSTS_N_INSNS (9) }, /* 23 */
4394 { SHIFT_AND_ROT
, COSTS_N_INSNS (9) }, /* 24 */
4395 { SHIFT_AND_ROT
, COSTS_N_INSNS (8) }, /* 25 */
4396 { SHIFT_AND_ROT
, COSTS_N_INSNS (7) }, /* 26 */
4397 { SHIFT_AND_ROT
, COSTS_N_INSNS (6) }, /* 27 */
4398 { SHIFT_AND_ROT
, COSTS_N_INSNS (5) }, /* 28 */
4399 { SHIFT_AND_ROT
, COSTS_N_INSNS (4) }, /* 29 */
4400 { SHIFT_AND_ROT
, COSTS_N_INSNS (3) }, /* 30 */
4401 { SHIFT_AND_ROT
, COSTS_N_INSNS (2) } /* 31 */
4403 { /* 4: -O2 -mswap TARGET_V2. */
4404 { SHIFT_MOVE
, COSTS_N_INSNS (1) }, /* 0 */
4405 { SHIFT_INLINE
, COSTS_N_INSNS (1) }, /* 1 */
4406 { SHIFT_INLINE
, COSTS_N_INSNS (2) }, /* 2 */
4407 { SHIFT_INLINE
, COSTS_N_INSNS (2) }, /* 3 */
4408 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 4 */
4409 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 5 */
4410 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 6 */
4411 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 7 */
4412 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 8 */
4413 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 9 */
4414 { SHIFT_INLINE
, COSTS_N_INSNS (5) }, /* 10 */
4415 { SHIFT_INLINE
, COSTS_N_INSNS (5) }, /* 11 */
4416 { SHIFT_INLINE
, COSTS_N_INSNS (5) }, /* 12 */
4417 { SHIFT_AND_SWAP_ROT
, COSTS_N_INSNS (5) }, /* 13 */
4418 { SHIFT_AND_SWAP_ROT
, COSTS_N_INSNS (4) }, /* 14 */
4419 { SHIFT_AND_SWAP_ROT
, COSTS_N_INSNS (3) }, /* 15 */
4420 { SHIFT_SWAP
, COSTS_N_INSNS (1) }, /* 16 */
4421 { SHIFT_SWAP
, COSTS_N_INSNS (2) }, /* 17 */
4422 { SHIFT_SWAP
, COSTS_N_INSNS (3) }, /* 18 */
4423 { SHIFT_SWAP
, COSTS_N_INSNS (3) }, /* 19 */
4424 { SHIFT_SWAP
, COSTS_N_INSNS (4) }, /* 20 */
4425 { SHIFT_SWAP
, COSTS_N_INSNS (4) }, /* 21 */
4426 { SHIFT_SWAP
, COSTS_N_INSNS (4) }, /* 22 */
4427 { SHIFT_SWAP
, COSTS_N_INSNS (5) }, /* 23 */
4428 { SHIFT_SWAP
, COSTS_N_INSNS (5) }, /* 24 */
4429 { SHIFT_SWAP
, COSTS_N_INSNS (5) }, /* 25 */
4430 { SHIFT_SWAP
, COSTS_N_INSNS (6) }, /* 26 */
4431 { SHIFT_AND_ROT
, COSTS_N_INSNS (6) }, /* 27 */
4432 { SHIFT_AND_ROT
, COSTS_N_INSNS (5) }, /* 28 */
4433 { SHIFT_AND_ROT
, COSTS_N_INSNS (4) }, /* 29 */
4434 { SHIFT_AND_ROT
, COSTS_N_INSNS (3) }, /* 30 */
4435 { SHIFT_AND_ROT
, COSTS_N_INSNS (2) } /* 31 */
4437 { /* 5: -O2 -mswap !TARGET_V2. */
4438 { SHIFT_MOVE
, COSTS_N_INSNS (1) }, /* 0 */
4439 { SHIFT_INLINE
, COSTS_N_INSNS (1) }, /* 1 */
4440 { SHIFT_INLINE
, COSTS_N_INSNS (2) }, /* 2 */
4441 { SHIFT_INLINE
, COSTS_N_INSNS (2) }, /* 3 */
4442 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 4 */
4443 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 5 */
4444 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 6 */
4445 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 7 */
4446 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 8 */
4447 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 9 */
4448 { SHIFT_INLINE
, COSTS_N_INSNS (5) }, /* 10 */
4449 { SHIFT_INLINE
, COSTS_N_INSNS (5) }, /* 11 */
4450 { SHIFT_INLINE
, COSTS_N_INSNS (5) }, /* 12 */
4451 { SHIFT_AND_SWAP_ROT
, COSTS_N_INSNS (5) }, /* 13 */
4452 { SHIFT_AND_SWAP_ROT
, COSTS_N_INSNS (4) }, /* 14 */
4453 { SHIFT_AND_SWAP_ROT
, COSTS_N_INSNS (3) }, /* 15 */
4454 { SHIFT_SWAP
, COSTS_N_INSNS (2) }, /* 16 */
4455 { SHIFT_SWAP
, COSTS_N_INSNS (3) }, /* 17 */
4456 { SHIFT_SWAP
, COSTS_N_INSNS (4) }, /* 18 */
4457 { SHIFT_SWAP
, COSTS_N_INSNS (4) }, /* 19 */
4458 { SHIFT_SWAP
, COSTS_N_INSNS (5) }, /* 20 */
4459 { SHIFT_SWAP
, COSTS_N_INSNS (5) }, /* 21 */
4460 { SHIFT_SWAP
, COSTS_N_INSNS (5) }, /* 22 */
4461 { SHIFT_SWAP
, COSTS_N_INSNS (6) }, /* 23 */
4462 { SHIFT_SWAP
, COSTS_N_INSNS (6) }, /* 24 */
4463 { SHIFT_SWAP
, COSTS_N_INSNS (6) }, /* 25 */
4464 { SHIFT_AND_ROT
, COSTS_N_INSNS (7) }, /* 26 */
4465 { SHIFT_AND_ROT
, COSTS_N_INSNS (6) }, /* 27 */
4466 { SHIFT_AND_ROT
, COSTS_N_INSNS (5) }, /* 28 */
4467 { SHIFT_AND_ROT
, COSTS_N_INSNS (4) }, /* 29 */
4468 { SHIFT_AND_ROT
, COSTS_N_INSNS (3) }, /* 30 */
4469 { SHIFT_AND_ROT
, COSTS_N_INSNS (2) } /* 31 */
4473 /* Split SImode left shift instruction. */
4475 arc_split_ashl (rtx
*operands
)
4477 if (CONST_INT_P (operands
[2]))
4479 int n
= INTVAL (operands
[2]) & 0x1f;
4480 switch (arc_ashl_alg
[arc_shift_context_idx ()][n
].alg
)
4483 emit_move_insn (operands
[0], operands
[1]);
4489 emit_insn (gen_andsi3_i (operands
[0], operands
[1],
4491 emit_insn (gen_rotrsi2_cnt16 (operands
[0], operands
[0]));
4494 emit_insn (gen_ashlsi2_cnt16 (operands
[0], operands
[1]));
4498 operands
[1] = operands
[0];
4504 emit_insn (gen_ashlsi3_cnt1 (operands
[0], operands
[1]));
4506 emit_insn (gen_ashlsi3_cnt1 (operands
[0], operands
[0]));
4510 rtx zero
= gen_reg_rtx (SImode
);
4511 emit_move_insn (zero
, const0_rtx
);
4512 emit_insn (gen_add_shift (operands
[0], operands
[1],
4513 GEN_INT (3), zero
));
4514 for (n
-= 3; n
>= 3; n
-= 3)
4515 emit_insn (gen_add_shift (operands
[0], operands
[0],
4516 GEN_INT (3), zero
));
4518 emit_insn (gen_add_shift (operands
[0], operands
[0],
4521 emit_insn (gen_ashlsi3_cnt1 (operands
[0], operands
[0]));
4526 emit_insn (gen_andsi3_i (operands
[0], operands
[1],
4527 GEN_INT ((1 << (32 - n
)) - 1)));
4529 emit_insn (gen_rotrsi3_cnt1 (operands
[0], operands
[0]));
4532 case SHIFT_AND_SWAP_ROT
:
4533 emit_insn (gen_andsi3_i (operands
[0], operands
[1],
4534 GEN_INT ((1 << (32 - n
)) - 1)));
4535 emit_insn (gen_rotrsi2_cnt16 (operands
[0], operands
[0]));
4537 emit_insn (gen_rotrsi3_cnt1 (operands
[0], operands
[0]));
4548 emit_insn (gen_ashlsi3_loop (operands
[0], operands
[1], operands
[2]));
4551 /* Split SImode arithmetic right shift instruction. */
4553 arc_split_ashr (rtx
*operands
)
4555 if (CONST_INT_P (operands
[2]))
4557 int n
= INTVAL (operands
[2]) & 0x1f;
4562 emit_insn (gen_ashrsi3_cnt1 (operands
[0], operands
[1]));
4564 emit_insn (gen_ashrsi3_cnt1 (operands
[0], operands
[0]));
4567 emit_move_insn (operands
[0], operands
[1]);
4570 else if (n
>= 16 && n
<= 18 && TARGET_SWAP
)
4572 emit_insn (gen_rotrsi2_cnt16 (operands
[0], operands
[1]));
4573 emit_insn (gen_extendhisi2 (operands
[0],
4574 gen_lowpart (HImode
, operands
[0])));
4576 emit_insn (gen_ashrsi3_cnt1 (operands
[0], operands
[0]));
4581 rtx tmp
= gen_reg_rtx (SImode
);
4582 emit_insn (gen_add_f (tmp
, operands
[1], operands
[1]));
4583 emit_insn (gen_sbc (operands
[0], operands
[0], operands
[0]));
4584 emit_insn (gen_addsi_compare_2 (tmp
, tmp
));
4585 emit_insn (gen_adc (operands
[0], operands
[0], operands
[0]));
4590 emit_insn (gen_addsi_compare_2 (operands
[1], operands
[1]));
4591 emit_insn (gen_sbc (operands
[0], operands
[0], operands
[0]));
4596 emit_insn (gen_ashrsi3_loop (operands
[0], operands
[1], operands
[2]));
4599 /* Split SImode logical right shift instruction. */
4601 arc_split_lshr (rtx
*operands
)
4603 if (CONST_INT_P (operands
[2]))
4605 int n
= INTVAL (operands
[2]) & 0x1f;
4610 emit_insn (gen_lshrsi3_cnt1 (operands
[0], operands
[1]));
4612 emit_insn (gen_lshrsi3_cnt1 (operands
[0], operands
[0]));
4615 emit_move_insn (operands
[0], operands
[1]);
4618 else if (n
>= 16 && n
<= 19 && TARGET_SWAP
&& TARGET_V2
)
4620 emit_insn (gen_lshrsi2_cnt16 (operands
[0], operands
[1]));
4622 emit_insn (gen_lshrsi3_cnt1 (operands
[0], operands
[0]));
4627 rtx tmp
= gen_reg_rtx (SImode
);
4628 emit_insn (gen_add_f (tmp
, operands
[1], operands
[1]));
4629 emit_insn (gen_scc_ltu_cc_c (operands
[0]));
4630 emit_insn (gen_addsi_compare_2 (tmp
, tmp
));
4631 emit_insn (gen_adc (operands
[0], operands
[0], operands
[0]));
4636 emit_insn (gen_addsi_compare_2 (operands
[1], operands
[1]));
4637 emit_insn (gen_scc_ltu_cc_c (operands
[0]));
4642 emit_insn (gen_lshrsi3_loop (operands
[0], operands
[1], operands
[2]));
4645 /* Split SImode rotate left instruction. */
4647 arc_split_rotl (rtx
*operands
)
4649 if (CONST_INT_P (operands
[2]))
4651 int n
= INTVAL (operands
[2]) & 0x1f;
4656 emit_insn (gen_rotlsi3_cnt1 (operands
[0], operands
[1]));
4658 emit_insn (gen_rotlsi3_cnt1 (operands
[0], operands
[0]));
4661 emit_move_insn (operands
[0], operands
[1]);
4666 emit_insn (gen_rotrsi3_cnt1 (operands
[0], operands
[1]));
4668 emit_insn (gen_rotrsi3_cnt1 (operands
[0], operands
[0]));
4671 else if (n
>= 13 && n
<= 16 && TARGET_SWAP
)
4673 emit_insn (gen_rotlsi2_cnt16 (operands
[0], operands
[1]));
4675 emit_insn (gen_rotrsi3_cnt1 (operands
[0], operands
[0]));
4678 else if (n
== 17 && TARGET_SWAP
)
4680 emit_insn (gen_rotlsi2_cnt16 (operands
[0], operands
[1]));
4681 emit_insn (gen_rotlsi3_cnt1 (operands
[0], operands
[0]));
4684 else if (n
>= 16 || n
== 12 || n
== 14)
4686 emit_insn (gen_rotrsi3_loop (operands
[0], operands
[1],
4692 emit_insn (gen_rotlsi3_loop (operands
[0], operands
[1], operands
[2]));
4695 /* Split SImode rotate right instruction. */
4697 arc_split_rotr (rtx
*operands
)
4699 if (CONST_INT_P (operands
[2]))
4701 int n
= INTVAL (operands
[2]) & 0x1f;
4706 emit_insn (gen_rotrsi3_cnt1 (operands
[0], operands
[1]));
4708 emit_insn (gen_rotrsi3_cnt1 (operands
[0], operands
[0]));
4711 emit_move_insn (operands
[0], operands
[1]);
4714 else if (n
== 15 && TARGET_SWAP
)
4716 emit_insn (gen_rotrsi2_cnt16 (operands
[0], operands
[1]));
4717 emit_insn (gen_rotlsi3_cnt1 (operands
[0], operands
[0]));
4720 else if (n
>= 16 && n
<= 19 && TARGET_SWAP
)
4722 emit_insn (gen_rotrsi2_cnt16 (operands
[0], operands
[1]));
4724 emit_insn (gen_rotrsi3_cnt1 (operands
[0], operands
[0]));
4729 emit_insn (gen_rotlsi3_cnt1 (operands
[0], operands
[1]));
4731 emit_insn (gen_rotlsi3_cnt1 (operands
[1], operands
[1]));
4734 else if (n
>= 21 || n
== 17 || n
== 19)
4736 emit_insn (gen_rotrsi3_loop (operands
[0], operands
[1],
4742 emit_insn (gen_rotrsi3_loop (operands
[0], operands
[1], operands
[2]));
4745 /* Nested function support. */
4747 /* Output assembler code for a block containing the constant parts of
4748 a trampoline, leaving space for variable parts. A trampoline looks
4754 .word function's address
4755 .word static chain value
4760 arc_asm_trampoline_template (FILE *f
)
4762 asm_fprintf (f
, "\tld_s\t%s,[pcl,8]\n", ARC_TEMP_SCRATCH_REG
);
4763 asm_fprintf (f
, "\tld\t%s,[pcl,12]\n", reg_names
[STATIC_CHAIN_REGNUM
]);
4764 asm_fprintf (f
, "\tj_s\t[%s]\n", ARC_TEMP_SCRATCH_REG
);
4765 assemble_aligned_integer (UNITS_PER_WORD
, const0_rtx
);
4766 assemble_aligned_integer (UNITS_PER_WORD
, const0_rtx
);
4769 /* Emit RTL insns to initialize the variable parts of a trampoline.
4770 FNADDR is an RTX for the address of the function's pure code. CXT
4771 is an RTX for the static chain value for the function.
4773 The fastest trampoline to execute for trampolines within +-8KB of CTX
4777 j [limm] 0x20200f80 limm
4779 and that would also be faster to write to the stack by computing
4780 the offset from CTX to TRAMP at compile time. However, it would
4781 really be better to get rid of the high cost of cache invalidation
4782 when generating trampolines, which requires that the code part of
4783 trampolines stays constant, and additionally either making sure
4784 that no executable code but trampolines is on the stack, no icache
4785 entries linger for the area of the stack from when before the stack
4786 was allocated, and allocating trampolines in trampoline-only cache
4787 lines or allocate trampolines fram a special pool of pre-allocated
4791 arc_initialize_trampoline (rtx tramp
, tree fndecl
, rtx cxt
)
4793 rtx fnaddr
= XEXP (DECL_RTL (fndecl
), 0);
4795 emit_block_move (tramp
, assemble_trampoline_template (),
4796 GEN_INT (TRAMPOLINE_SIZE
), BLOCK_OP_NORMAL
);
4797 emit_move_insn (adjust_address (tramp
, SImode
, 8), fnaddr
);
4798 emit_move_insn (adjust_address (tramp
, SImode
, 12), cxt
);
4799 maybe_emit_call_builtin___clear_cache (XEXP (tramp
, 0),
4800 plus_constant (Pmode
,
4805 /* Add the given function declaration to emit code in JLI section. */
4808 arc_add_jli_section (rtx pat
)
4812 arc_jli_section
*sec
= arc_jli_sections
, *new_section
;
4813 tree decl
= SYMBOL_REF_DECL (pat
);
4820 /* For fixed locations do not generate the jli table entry. It
4821 should be provided by the user as an asm file. */
4822 attrs
= TYPE_ATTRIBUTES (TREE_TYPE (decl
));
4823 if (lookup_attribute ("jli_fixed", attrs
))
4827 name
= XSTR (pat
, 0);
4829 /* Don't insert the same symbol twice. */
4832 if(strcmp (name
, sec
->name
) == 0)
4837 /* New name, insert it. */
4838 new_section
= (arc_jli_section
*) xmalloc (sizeof (arc_jli_section
));
4839 gcc_assert (new_section
!= NULL
);
4840 new_section
->name
= name
;
4841 new_section
->next
= arc_jli_sections
;
4842 arc_jli_sections
= new_section
;
4845 /* This is set briefly to 1 when we output a ".as" address modifer, and then
4846 reset when we output the scaled address. */
4847 static int output_scaled
= 0;
4849 /* Set when we force sdata output. */
4850 static int output_sdata
= 0;
4852 /* Print operand X (an rtx) in assembler syntax to file FILE.
4853 CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
4854 For `%' followed by punctuation, CODE is the punctuation and X is null.
4855 In final.cc:output_asm_insn:
4858 'c' : constant address if CONSTANT_ADDRESS_P
4864 'p': bit Position of lsb
4865 's': scalled immediate
4866 'S': Scalled immediate, to be used in pair with 's'.
4867 'N': Negative immediate, to be used in pair with 's'.
4868 'x': size of bit field
4869 '*': jump delay slot suffix
4870 '?' : nonjump-insn suffix for conditional execution or short instruction
4874 'J': JLI instruction
4875 'j': used by mov instruction to properly emit jli related labels.
4876 'B': Branch comparison operand - suppress sda reference
4877 'H': Most significant word
4878 'L': Least significant word
4879 'A': ASCII decimal representation of floating point value
4880 'U': Load/store update or scaling indicator
4881 'V': cache bypass indicator for volatile
4885 'o': original symbol - no @ prepending. */
4888 arc_print_operand (FILE *file
, rtx x
, int code
)
4891 unsigned scalled
= 0;
4897 if (GET_CODE (x
) == CONST_INT
)
4898 fprintf (file
, "%d",exact_log2(INTVAL (x
) + 1) - 1 );
4900 output_operand_lossage ("invalid operand to %%Z code");
4905 if (GET_CODE (x
) == CONST_INT
)
4906 fprintf (file
, "%d",exact_log2 (INTVAL (x
) & 0xffffffff));
4908 output_operand_lossage ("invalid operand to %%z code");
4913 if (GET_CODE (x
) == CONST_INT
)
4914 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
) );
4916 output_operand_lossage ("invalid operands to %%c code");
4921 if (GET_CODE (x
) == CONST_INT
)
4922 fprintf (file
, "%d",exact_log2(~INTVAL (x
)) );
4924 output_operand_lossage ("invalid operand to %%M code");
4929 if (GET_CODE (x
) == CONST_INT
)
4930 fprintf (file
, "%d", exact_log2 (INTVAL (x
) & -INTVAL (x
)));
4932 output_operand_lossage ("invalid operand to %%p code");
4938 if (!CONST_INT_P (x
))
4940 output_operand_lossage ("invalid operand for %%s code");
4944 if ((ival
& 0x07) == 0)
4946 else if ((ival
& 0x03) == 0)
4948 else if ((ival
& 0x01) == 0)
4952 asm_fprintf (file
, "%d", scalled
);
4958 output_operand_lossage ("invalid operand for %%N code");
4966 asm_fprintf (file
, "%s", reg_names
[REGNO (x
)]);
4969 if (!CONST_INT_P (x
))
4971 output_operand_lossage ("invalid operand for %%N or %%S code");
4974 ival
= sign
* INTVAL (x
);
4975 if ((ival
& 0x07) == 0)
4977 else if ((ival
& 0x03) == 0)
4979 else if ((ival
& 0x01) == 0)
4982 asm_fprintf (file
, "%wd", (ival
>> scalled
));
4986 if (GET_CODE (x
) == CONST_INT
)
4988 HOST_WIDE_INT i
= INTVAL (x
);
4989 HOST_WIDE_INT s
= exact_log2 (i
& -i
);
4990 fprintf (file
, "%d", exact_log2 (((0xffffffffUL
& i
) >> s
) + 1));
4993 output_operand_lossage ("invalid operand to %%s code");
4997 /* Unconditional branches / branches not depending on condition codes.
4998 This could also be a CALL_INSN.
4999 Output the appropriate delay slot suffix. */
5000 if (final_sequence
&& final_sequence
->len () != 1)
5002 rtx_insn
*delay
= final_sequence
->insn (1);
5004 /* For TARGET_PAD_RETURN we might have grabbed the delay insn. */
5005 if (delay
->deleted ())
5011 case '?' : /* with leading "." */
5012 case '!' : /* without leading "." */
5013 if (current_insn_predicate
)
5015 int cc
= get_arc_condition_code (current_insn_predicate
);
5016 /* Is this insn in a delay slot sequence? */
5017 if (!final_sequence
|| XVECLEN (final_sequence
, 0) < 2
5018 || current_insn_predicate
5019 || CALL_P (final_sequence
->insn (0))
5020 || simplejump_p (final_sequence
->insn (0)))
5022 /* This insn isn't in a delay slot sequence, or conditionalized
5023 independently of its position in a delay slot. */
5024 fprintf (file
, "%s%s",
5025 code
== '?' ? "." : "", arc_condition_codes
[cc
]);
5026 /* If this is a jump, there are still short variants. However,
5027 only beq_s / bne_s have the same offset range as b_s,
5028 and the only short conditional returns are jeq_s and jne_s. */
5030 && (cc
== ARC_CC_EQ
|| cc
== ARC_CC_NE
))
5031 output_short_suffix (file
);
5033 else if (code
== '!') /* Jump with delay slot. */
5034 fputs (arc_condition_codes
[cc
], file
);
5035 else /* An Instruction in a delay slot of a jump or call. */
5037 rtx jump
= XVECEXP (final_sequence
, 0, 0);
5038 rtx insn
= XVECEXP (final_sequence
, 0, 1);
5040 /* If the insn is annulled and is from the target path, we need
5041 to inverse the condition test. */
5042 if (JUMP_P (jump
) && INSN_ANNULLED_BRANCH_P (jump
))
5044 if (INSN_FROM_TARGET_P (insn
))
5045 fprintf (file
, "%s%s",
5046 code
== '?' ? "." : "",
5047 arc_condition_codes
[ARC_INVERSE_CONDITION_CODE (cc
)]);
5049 fprintf (file
, "%s%s",
5050 code
== '?' ? "." : "",
5051 arc_condition_codes
[cc
]);
5055 /* This insn is executed for either path, so don't
5056 conditionalize it at all. */
5057 output_short_suffix (file
);
5062 output_short_suffix (file
);
5066 fputs (arc_condition_codes
[get_arc_condition_code (x
)], file
);
5069 fputs (arc_condition_codes
[ARC_INVERSE_CONDITION_CODE
5070 (get_arc_condition_code (x
))],
5074 /* Write second word of DImode or DFmode reference,
5075 register or memory. */
5076 if (GET_CODE (x
) == REG
)
5077 fputs (reg_names
[REGNO (x
)+1], file
);
5078 else if (GET_CODE (x
) == MEM
)
5082 /* Handle possible auto-increment. For PRE_INC / PRE_DEC /
5083 PRE_MODIFY, we will have handled the first word already;
5084 For POST_INC / POST_DEC / POST_MODIFY, the access to the
5085 first word will be done later. In either case, the access
5086 to the first word will do the modify, and we only have
5087 to add an offset of four here. */
5088 if (GET_CODE (XEXP (x
, 0)) == PRE_INC
5089 || GET_CODE (XEXP (x
, 0)) == PRE_DEC
5090 || GET_CODE (XEXP (x
, 0)) == PRE_MODIFY
5091 || GET_CODE (XEXP (x
, 0)) == POST_INC
5092 || GET_CODE (XEXP (x
, 0)) == POST_DEC
5093 || GET_CODE (XEXP (x
, 0)) == POST_MODIFY
)
5094 output_address (VOIDmode
,
5095 plus_constant (Pmode
, XEXP (XEXP (x
, 0), 0), 4));
5096 else if (output_scaled
)
5098 rtx addr
= XEXP (x
, 0);
5099 int size
= GET_MODE_SIZE (GET_MODE (x
));
5101 output_address (VOIDmode
,
5102 plus_constant (Pmode
, XEXP (addr
, 0),
5103 ((INTVAL (XEXP (addr
, 1)) + 4)
5104 >> (size
== 2 ? 1 : 2))));
5108 output_address (VOIDmode
,
5109 plus_constant (Pmode
, XEXP (x
, 0), 4));
5113 output_operand_lossage ("invalid operand to %%R code");
5117 if (GET_CODE (x
) == SYMBOL_REF
5118 && arc_is_jli_call_p (x
))
5120 if (SYMBOL_REF_DECL (x
))
5122 tree attrs
= (TREE_TYPE (SYMBOL_REF_DECL (x
)) != error_mark_node
5123 ? TYPE_ATTRIBUTES (TREE_TYPE (SYMBOL_REF_DECL (x
)))
5125 if (lookup_attribute ("jli_fixed", attrs
))
5127 /* No special treatment for jli_fixed functions. */
5130 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
"\t; @",
5131 TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attrs
))));
5132 assemble_name (file
, XSTR (x
, 0));
5136 fprintf (file
, "@__jli.");
5137 assemble_name (file
, XSTR (x
, 0));
5139 arc_add_jli_section (x
);
5142 if (GET_CODE (x
) == SYMBOL_REF
5143 && arc_is_secure_call_p (x
))
5145 /* No special treatment for secure functions. */
5148 tree attrs
= (TREE_TYPE (SYMBOL_REF_DECL (x
)) != error_mark_node
5149 ? TYPE_ATTRIBUTES (TREE_TYPE (SYMBOL_REF_DECL (x
)))
5151 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
"\t; @",
5152 TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attrs
))));
5153 assemble_name (file
, XSTR (x
, 0));
5157 case 'B' /* Branch or other LIMM ref - must not use sda references. */ :
5160 output_addr_const (file
, x
);
5166 if (GET_CODE (x
) == REG
)
5168 /* L = least significant word, H = most significant word. */
5169 if ((WORDS_BIG_ENDIAN
!= 0) ^ (code
== 'L'))
5170 fputs (reg_names
[REGNO (x
)], file
);
5172 fputs (reg_names
[REGNO (x
)+1], file
);
5174 else if (GET_CODE (x
) == CONST_INT
5175 || GET_CODE (x
) == CONST_DOUBLE
)
5177 rtx first
, second
, word
;
5179 split_double (x
, &first
, &second
);
5181 if((WORDS_BIG_ENDIAN
) == 0)
5182 word
= (code
== 'L' ? first
: second
);
5184 word
= (code
== 'L' ? second
: first
);
5186 fprintf (file
, "0x%08" PRIx32
, ((uint32_t) INTVAL (word
)));
5189 output_operand_lossage ("invalid operand to %%H/%%L code");
5195 gcc_assert (GET_CODE (x
) == CONST_DOUBLE
5196 && GET_MODE_CLASS (GET_MODE (x
)) == MODE_FLOAT
);
5198 real_to_decimal (str
, CONST_DOUBLE_REAL_VALUE (x
), sizeof (str
), 0, 1);
5199 fprintf (file
, "%s", str
);
5203 /* Output a load/store with update indicator if appropriate. */
5204 if (GET_CODE (x
) == MEM
)
5206 rtx addr
= XEXP (x
, 0);
5207 switch (GET_CODE (addr
))
5209 case PRE_INC
: case PRE_DEC
: case PRE_MODIFY
:
5210 fputs (".a", file
); break;
5211 case POST_INC
: case POST_DEC
: case POST_MODIFY
:
5212 fputs (".ab", file
); break;
5214 /* Are we using a scaled index? */
5215 if (GET_CODE (XEXP (addr
, 0)) == MULT
)
5216 fputs (".as", file
);
5217 /* Can we use a scaled offset? */
5218 else if (CONST_INT_P (XEXP (addr
, 1))
5219 && GET_MODE_SIZE (GET_MODE (x
)) > 1
5220 && (!(INTVAL (XEXP (addr
, 1))
5221 & (GET_MODE_SIZE (GET_MODE (x
)) - 1) & 3))
5222 /* Does it make a difference? */
5223 && !SMALL_INT_RANGE(INTVAL (XEXP (addr
, 1)),
5224 GET_MODE_SIZE (GET_MODE (x
)) - 2, 0))
5226 fputs (".as", file
);
5232 if (legitimate_small_data_address_p (addr
, GET_MODE (x
))
5233 && GET_MODE_SIZE (GET_MODE (x
)) > 1)
5235 int align
= get_symbol_alignment (addr
);
5237 switch (GET_MODE (x
))
5246 if (align
&& ((align
& mask
) == 0))
5247 fputs (".as", file
);
5253 gcc_assert (CONSTANT_P (addr
)); break;
5257 output_operand_lossage ("invalid operand to %%U code");
5260 /* Output cache bypass indicator for a load/store insn. Volatile memory
5261 refs are defined to use the cache bypass mechanism. */
5262 if (GET_CODE (x
) == MEM
)
5264 if ((MEM_VOLATILE_P (x
) && !TARGET_VOLATILE_CACHE_SET
)
5265 || arc_is_uncached_mem_p (x
))
5266 fputs (".di", file
);
5269 output_operand_lossage ("invalid operand to %%V code");
5274 /* Do nothing special. */
5277 fputs (reg_names
[REGNO (x
)]+1, file
);
5281 /* Output an operator. */
5282 switch (GET_CODE (x
))
5284 case PLUS
: fputs ("add", file
); return;
5285 case SS_PLUS
: fputs ("adds", file
); return;
5286 case AND
: fputs ("and", file
); return;
5287 case IOR
: fputs ("or", file
); return;
5288 case XOR
: fputs ("xor", file
); return;
5289 case MINUS
: fputs ("sub", file
); return;
5290 case SS_MINUS
: fputs ("subs", file
); return;
5291 case ASHIFT
: fputs ("asl", file
); return;
5292 case ASHIFTRT
: fputs ("asr", file
); return;
5293 case LSHIFTRT
: fputs ("lsr", file
); return;
5294 case ROTATERT
: fputs ("ror", file
); return;
5295 case MULT
: fputs ("mpy", file
); return;
5296 case ABS
: fputs ("abs", file
); return; /* Unconditional. */
5297 case NEG
: fputs ("neg", file
); return;
5298 case SS_NEG
: fputs ("negs", file
); return;
5299 case NOT
: fputs ("not", file
); return; /* Unconditional. */
5301 fputs ("ext", file
); /* bmsk allows predication. */
5303 case SIGN_EXTEND
: /* Unconditional. */
5304 fputs ("sex", file
);
5306 switch (GET_MODE (XEXP (x
, 0)))
5308 case E_QImode
: fputs ("b", file
); return;
5309 case E_HImode
: fputs ("w", file
); return;
5314 if (GET_MODE (x
) != HImode
)
5316 fputs ("sat16", file
);
5319 output_operand_lossage ("invalid operand to %%O code"); return;
5321 if (GET_CODE (x
) == SYMBOL_REF
)
5323 assemble_name (file
, XSTR (x
, 0));
5342 output_operand_lossage ("invalid operand output code");
5345 switch (GET_CODE (x
))
5348 fputs (reg_names
[REGNO (x
)], file
);
5352 rtx addr
= XEXP (x
, 0);
5353 int size
= GET_MODE_SIZE (GET_MODE (x
));
5355 if (legitimate_small_data_address_p (addr
, GET_MODE (x
)))
5360 switch (GET_CODE (addr
))
5362 case PRE_INC
: case POST_INC
:
5363 output_address (VOIDmode
,
5364 plus_constant (Pmode
, XEXP (addr
, 0), size
)); break;
5365 case PRE_DEC
: case POST_DEC
:
5366 output_address (VOIDmode
,
5367 plus_constant (Pmode
, XEXP (addr
, 0), -size
));
5369 case PRE_MODIFY
: case POST_MODIFY
:
5370 output_address (VOIDmode
, XEXP (addr
, 1)); break;
5374 output_address (VOIDmode
,
5375 plus_constant (Pmode
, XEXP (addr
, 0),
5376 (INTVAL (XEXP (addr
, 1))
5377 >> (size
== 2 ? 1 : 2))));
5381 output_address (VOIDmode
, addr
);
5384 if (flag_pic
&& CONSTANT_ADDRESS_P (addr
))
5385 arc_output_pic_addr_const (file
, addr
, code
);
5387 output_address (VOIDmode
, addr
);
5394 /* We handle SFmode constants here as output_addr_const doesn't. */
5395 if (GET_MODE (x
) == SFmode
)
5399 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x
), l
);
5400 fprintf (file
, "0x%08lx", l
);
5404 /* Let output_addr_const deal with it. */
5407 || (GET_CODE (x
) == CONST
5408 && GET_CODE (XEXP (x
, 0)) == UNSPEC
5409 && (XINT (XEXP (x
, 0), 1) == UNSPEC_TLS_OFF
5410 || XINT (XEXP (x
, 0), 1) == UNSPEC_TLS_GD
))
5411 || (GET_CODE (x
) == CONST
5412 && GET_CODE (XEXP (x
, 0)) == PLUS
5413 && GET_CODE (XEXP (XEXP (x
, 0), 0)) == UNSPEC
5414 && (XINT (XEXP (XEXP (x
, 0), 0), 1) == UNSPEC_TLS_OFF
5415 || XINT (XEXP (XEXP (x
, 0), 0), 1) == UNSPEC_TLS_GD
)))
5416 arc_output_pic_addr_const (file
, x
, code
);
5418 output_addr_const (file
, x
);
5423 /* Print a memory address as an operand to reference that memory location. */
5426 arc_print_operand_address (FILE *file
, rtx addr
)
5428 rtx base
, index
= 0;
5430 switch (GET_CODE (addr
))
5433 fputs (reg_names
[REGNO (addr
)], file
);
5437 fputs ("gp,", file
);
5438 output_addr_const (file
, addr
);
5440 fputs ("@sda", file
);
5444 if (GET_CODE (XEXP (addr
, 0)) == MULT
)
5445 index
= XEXP (XEXP (addr
, 0), 0), base
= XEXP (addr
, 1);
5446 else if (CONST_INT_P (XEXP (addr
, 0)))
5447 index
= XEXP (addr
, 0), base
= XEXP (addr
, 1);
5449 base
= XEXP (addr
, 0), index
= XEXP (addr
, 1);
5451 gcc_assert (OBJECT_P (base
));
5452 arc_print_operand_address (file
, base
);
5453 if (CONSTANT_P (base
) && CONST_INT_P (index
))
5457 gcc_assert (OBJECT_P (index
));
5458 arc_print_operand_address (file
, index
);
5462 rtx c
= XEXP (addr
, 0);
5464 if ((GET_CODE (c
) == UNSPEC
5465 && (XINT (c
, 1) == UNSPEC_TLS_OFF
5466 || XINT (c
, 1) == UNSPEC_TLS_IE
))
5467 || (GET_CODE (c
) == PLUS
5468 && GET_CODE (XEXP (c
, 0)) == UNSPEC
5469 && (XINT (XEXP (c
, 0), 1) == UNSPEC_TLS_OFF
5470 || XINT (XEXP (c
, 0), 1) == ARC_UNSPEC_GOTOFFPC
)))
5472 arc_output_pic_addr_const (file
, c
, 0);
5475 gcc_assert (GET_CODE (c
) == PLUS
);
5476 gcc_assert (GET_CODE (XEXP (c
, 0)) == SYMBOL_REF
);
5477 gcc_assert (GET_CODE (XEXP (c
, 1)) == CONST_INT
);
5479 output_address (VOIDmode
, XEXP (addr
, 0));
5485 /* We shouldn't get here as we've lost the mode of the memory object
5486 (which says how much to inc/dec by. */
5491 arc_output_pic_addr_const (file
, addr
, 0);
5493 output_addr_const (file
, addr
);
5498 /* Return non-zero if INSN should be output as a short insn. UNALIGN is
5499 zero if the current insn is aligned to a 4-byte-boundary, two otherwise.
5500 If CHECK_ATTR is greater than 0, check the iscompact attribute first. */
5503 arc_verify_short (rtx_insn
*insn
, int check_attr
)
5505 enum attr_iscompact iscompact
;
5509 iscompact
= get_attr_iscompact (insn
);
5510 if (iscompact
== ISCOMPACT_FALSE
)
5514 return (get_attr_length (insn
) & 2) != 0;
5517 /* When outputting an instruction (alternative) that can potentially be short,
5518 output the short suffix if the insn is in fact short. */
5521 output_short_suffix (FILE *file
)
5523 rtx_insn
*insn
= current_output_insn
;
5527 if (arc_verify_short (insn
, 1))
5529 fprintf (file
, "_s");
5531 /* Restore recog_operand. */
5532 extract_insn_cached (insn
);
5535 /* Implement FINAL_PRESCAN_INSN. */
5538 arc_final_prescan_insn (rtx_insn
*insn
, rtx
*opvec ATTRIBUTE_UNUSED
,
5539 int noperands ATTRIBUTE_UNUSED
)
5541 if (TARGET_DUMPISIZE
)
5542 fprintf (asm_out_file
, "\n; at %04x\n", INSN_ADDRESSES (INSN_UID (insn
)));
5545 /* Given FROM and TO register numbers, say whether this elimination is allowed.
5546 Frame pointer elimination is automatically handled.
5548 All eliminations are permissible. If we need a frame
5549 pointer, we must eliminate ARG_POINTER_REGNUM into
5550 FRAME_POINTER_REGNUM and not into STACK_POINTER_REGNUM. */
5553 arc_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to
)
5555 return ((to
== HARD_FRAME_POINTER_REGNUM
) || (to
== STACK_POINTER_REGNUM
));
5558 /* Define the offset between two registers, one to be eliminated, and
5559 the other its replacement, at the start of a routine. */
5562 arc_initial_elimination_offset (int from
, int to
)
5564 if (!cfun
->machine
->frame_info
.initialized
)
5565 arc_compute_frame_size ();
5567 if (from
== ARG_POINTER_REGNUM
&& to
== HARD_FRAME_POINTER_REGNUM
)
5569 return (cfun
->machine
->frame_info
.extra_size
5570 + cfun
->machine
->frame_info
.reg_size
);
5573 if (from
== ARG_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
5575 return (cfun
->machine
->frame_info
.total_size
5576 - cfun
->machine
->frame_info
.pretend_size
);
5579 if ((from
== FRAME_POINTER_REGNUM
) && (to
== STACK_POINTER_REGNUM
))
5581 return (cfun
->machine
->frame_info
.total_size
5582 - (cfun
->machine
->frame_info
.pretend_size
5583 + cfun
->machine
->frame_info
.extra_size
5584 + cfun
->machine
->frame_info
.reg_size
));
5586 if ((from
== FRAME_POINTER_REGNUM
) && (to
== HARD_FRAME_POINTER_REGNUM
))
5593 arc_frame_pointer_required (void)
5595 return cfun
->calls_alloca
|| crtl
->calls_eh_return
;
5599 /* Return the destination address of a branch. */
5602 branch_dest (rtx branch
)
5604 rtx pat
= PATTERN (branch
);
5605 rtx dest
= (GET_CODE (pat
) == PARALLEL
5606 ? SET_SRC (XVECEXP (pat
, 0, 0)) : SET_SRC (pat
));
5609 if (GET_CODE (dest
) == IF_THEN_ELSE
)
5610 dest
= XEXP (dest
, XEXP (dest
, 1) == pc_rtx
? 2 : 1);
5612 dest
= XEXP (dest
, 0);
5613 dest_uid
= INSN_UID (dest
);
5615 return INSN_ADDRESSES (dest_uid
);
5619 /* Implement TARGET_ENCODE_SECTION_INFO hook. */
5622 arc_encode_section_info (tree decl
, rtx rtl
, int first
)
5624 /* For sdata, SYMBOL_FLAG_LOCAL and SYMBOL_FLAG_FUNCTION.
5625 This clears machine specific flags, so has to come first. */
5626 default_encode_section_info (decl
, rtl
, first
);
5628 /* Check if it is a function, and whether it has the
5629 [long/medium/short]_call attribute specified. */
5630 if (TREE_CODE (decl
) == FUNCTION_DECL
)
5632 rtx symbol
= XEXP (rtl
, 0);
5633 int flags
= SYMBOL_REF_FLAGS (symbol
);
5635 tree attr
= (TREE_TYPE (decl
) != error_mark_node
5636 ? TYPE_ATTRIBUTES (TREE_TYPE (decl
)) : NULL_TREE
);
5637 tree long_call_attr
= lookup_attribute ("long_call", attr
);
5638 tree medium_call_attr
= lookup_attribute ("medium_call", attr
);
5639 tree short_call_attr
= lookup_attribute ("short_call", attr
);
5641 if (long_call_attr
!= NULL_TREE
)
5642 flags
|= SYMBOL_FLAG_LONG_CALL
;
5643 else if (medium_call_attr
!= NULL_TREE
)
5644 flags
|= SYMBOL_FLAG_MEDIUM_CALL
;
5645 else if (short_call_attr
!= NULL_TREE
)
5646 flags
|= SYMBOL_FLAG_SHORT_CALL
;
5648 SYMBOL_REF_FLAGS (symbol
) = flags
;
5650 else if (VAR_P (decl
))
5652 rtx symbol
= XEXP (rtl
, 0);
5654 tree attr
= (TREE_TYPE (decl
) != error_mark_node
5655 ? DECL_ATTRIBUTES (decl
) : NULL_TREE
);
5657 tree sec_attr
= lookup_attribute ("section", attr
);
5660 const char *sec_name
5661 = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (sec_attr
)));
5662 if (strcmp (sec_name
, ".cmem") == 0
5663 || strcmp (sec_name
, ".cmem_shared") == 0
5664 || strcmp (sec_name
, ".cmem_private") == 0)
5665 SYMBOL_REF_FLAGS (symbol
) |= SYMBOL_FLAG_CMEM
;
5670 /* This is how to output a definition of an internal numbered label where
5671 PREFIX is the class of label and NUM is the number within the class. */
5673 static void arc_internal_label (FILE *stream
, const char *prefix
, unsigned long labelno
)
5675 default_internal_label (stream
, prefix
, labelno
);
5678 /* Set the cpu type and print out other fancy things,
5679 at the top of the file. */
5681 static void arc_file_start (void)
5683 default_file_start ();
5684 fprintf (asm_out_file
, "\t.cpu %s\n", arc_cpu_string
);
5686 /* Set some want to have build attributes. */
5687 asm_fprintf (asm_out_file
, "\t.arc_attribute Tag_ARC_PCS_config, %d\n",
5689 asm_fprintf (asm_out_file
, "\t.arc_attribute Tag_ARC_ABI_rf16, %d\n",
5690 TARGET_RF16
? 1 : 0);
5691 asm_fprintf (asm_out_file
, "\t.arc_attribute Tag_ARC_ABI_pic, %d\n",
5693 asm_fprintf (asm_out_file
, "\t.arc_attribute Tag_ARC_ABI_tls, %d\n",
5694 (arc_tp_regno
!= -1) ? 1 : 0);
5695 asm_fprintf (asm_out_file
, "\t.arc_attribute Tag_ARC_ABI_sda, %d\n",
5696 TARGET_NO_SDATA_SET
? 0 : 2);
5697 asm_fprintf (asm_out_file
, "\t.arc_attribute Tag_ARC_ABI_exceptions, %d\n",
5698 TARGET_OPTFPE
? 1 : 0);
5700 asm_fprintf (asm_out_file
, "\t.arc_attribute Tag_ARC_CPU_variation, %d\n",
5701 (arc_tune
< ARC_TUNE_CORE_3
) ? 2 :
5702 (arc_tune
== ARC_TUNE_CORE_3
? 3 : 4));
5705 /* Implement `TARGET_ASM_FILE_END'. */
5706 /* Outputs to the stdio stream FILE jli related text. */
5708 void arc_file_end (void)
5710 arc_jli_section
*sec
= arc_jli_sections
;
5714 fprintf (asm_out_file
, "\n");
5715 fprintf (asm_out_file
, "# JLI entry for function ");
5716 assemble_name (asm_out_file
, sec
->name
);
5717 fprintf (asm_out_file
, "\n\t.section .jlitab, \"axG\", @progbits, "
5719 assemble_name (asm_out_file
, sec
->name
);
5720 fprintf (asm_out_file
,", comdat\n");
5722 fprintf (asm_out_file
, "\t.align\t4\n");
5723 fprintf (asm_out_file
, "__jli.");
5724 assemble_name (asm_out_file
, sec
->name
);
5725 fprintf (asm_out_file
, ":\n\t.weak __jli.");
5726 assemble_name (asm_out_file
, sec
->name
);
5727 fprintf (asm_out_file
, "\n\tb\t@");
5728 assemble_name (asm_out_file
, sec
->name
);
5729 fprintf (asm_out_file
, "\n");
5732 file_end_indicate_exec_stack ();
5735 /* Cost functions. */
5737 /* Compute a (partial) cost for rtx X. Return true if the complete
5738 cost has been computed, and false if subexpressions should be
5739 scanned. In either case, *TOTAL contains the cost result. */
5742 arc_rtx_costs (rtx x
, machine_mode mode
, int outer_code
,
5743 int opno ATTRIBUTE_UNUSED
, int *total
, bool speed
)
5745 int code
= GET_CODE (x
);
5749 /* Small integers are as cheap as registers. */
5752 bool nolimm
= false; /* Can we do without long immediate? */
5755 if (UNSIGNED_INT6 (INTVAL (x
)))
5761 case AND
: /* bclr, bmsk, ext[bw] */
5762 if (satisfies_constraint_Ccp (x
) /* bclr */
5763 || satisfies_constraint_C1p (x
) /* bmsk */)
5766 case IOR
: /* bset */
5767 if (satisfies_constraint_C0p (x
)) /* bset */
5771 if (satisfies_constraint_C0p (x
)) /* bxor */
5775 if (UNSIGNED_INT8 (INTVAL (x
)))
5777 if (satisfies_constraint_Chi (x
))
5779 if (satisfies_constraint_Clo (x
))
5783 if (TARGET_MUL64_SET
)
5784 if (SIGNED_INT12 (INTVAL (x
)))
5799 /* 4 byte values can be fetched as immediate constants -
5800 let's give that the cost of an extra insn. */
5804 *total
= speed
? COSTS_N_INSNS (1) : COSTS_N_BYTES (4);
5813 *total
= COSTS_N_INSNS (1);
5816 split_double (x
, &first
, &second
);
5817 *total
= COSTS_N_INSNS (!SMALL_INT (INTVAL (first
))
5818 + !SMALL_INT (INTVAL (second
)));
5822 /* Encourage synth_mult to find a synthetic multiply when reasonable.
5823 If we need more than 12 insns to do a multiply, then go out-of-line,
5824 since the call overhead will be < 10% of the cost of the multiply. */
5828 if (XEXP (x
, 1) == const1_rtx
)
5830 *total
+= rtx_cost (XEXP (x
, 0), mode
, ASHIFT
, 0, speed
)
5831 + COSTS_N_INSNS (2);
5836 if (TARGET_BARREL_SHIFTER
)
5838 *total
= COSTS_N_INSNS (1);
5839 if (CONST_INT_P (XEXP (x
, 1)))
5841 *total
+= rtx_cost (XEXP (x
, 0), mode
, ASHIFT
, 0, speed
);
5845 else if (CONST_INT_P (XEXP (x
, 1)))
5847 unsigned int n
= INTVAL (XEXP (x
, 1)) & 0x1f;
5848 *total
= arc_ashl_alg
[arc_shift_context_idx ()][n
].cost
5849 + rtx_cost (XEXP (x
, 0), mode
, ASHIFT
, 0, speed
);
5853 /* Variable shift loop takes 2 * n + 2 cycles. */
5854 *total
= speed
? COSTS_N_INSNS (64) : COSTS_N_INSNS (4);
5863 if (TARGET_BARREL_SHIFTER
)
5865 *total
= COSTS_N_INSNS (1);
5866 if (CONSTANT_P (XEXP (x
, 1)))
5868 *total
+= rtx_cost (XEXP (x
, 0), mode
, (enum rtx_code
) code
,
5873 else if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5874 *total
= speed
? COSTS_N_INSNS (16) : COSTS_N_INSNS (4);
5877 int n
= INTVAL (XEXP (x
, 1)) & 31;
5879 *total
= COSTS_N_INSNS (n
);
5881 *total
= speed
? COSTS_N_INSNS (n
+ 2) : COSTS_N_INSNS (4);
5882 *total
+= rtx_cost (XEXP (x
, 0), mode
, (enum rtx_code
) code
,
5890 if (GET_MODE_CLASS (mode
) == MODE_FLOAT
5891 && (TARGET_FP_SP_SQRT
|| TARGET_FP_DP_SQRT
))
5892 *total
= COSTS_N_INSNS(1);
5893 else if (GET_MODE_CLASS (mode
) == MODE_INT
5895 *total
= COSTS_N_INSNS(1);
5897 *total
= COSTS_N_INSNS(30);
5899 *total
= COSTS_N_INSNS(1);
5903 if ((TARGET_DPFP
&& GET_MODE (x
) == DFmode
))
5904 *total
= COSTS_N_INSNS (1);
5906 *total
= arc_multcost
;
5907 /* We do not want synth_mult sequences when optimizing
5909 else if (TARGET_ANY_MPY
)
5910 *total
= COSTS_N_INSNS (1);
5912 *total
= COSTS_N_INSNS (2);
5918 if (outer_code
== MEM
&& CONST_INT_P (XEXP (x
, 1))
5919 && RTX_OK_FOR_OFFSET_P (mode
, XEXP (x
, 1)))
5925 if ((GET_CODE (XEXP (x
, 0)) == ASHIFT
5926 && _1_2_3_operand (XEXP (XEXP (x
, 0), 1), VOIDmode
))
5927 || (GET_CODE (XEXP (x
, 0)) == MULT
5928 && _2_4_8_operand (XEXP (XEXP (x
, 0), 1), VOIDmode
)))
5930 if (CONSTANT_P (XEXP (x
, 1)) && !speed
)
5931 *total
+= COSTS_N_INSNS (4);
5932 *total
+= rtx_cost (XEXP (XEXP (x
, 0), 0), mode
, PLUS
, 1, speed
);
5937 if ((GET_CODE (XEXP (x
, 1)) == ASHIFT
5938 && _1_2_3_operand (XEXP (XEXP (x
, 1), 1), VOIDmode
))
5939 || (GET_CODE (XEXP (x
, 1)) == MULT
5940 && _2_4_8_operand (XEXP (XEXP (x
, 1), 1), VOIDmode
)))
5942 if (CONSTANT_P (XEXP (x
, 0)) && !speed
)
5943 *total
+= COSTS_N_INSNS (4);
5944 *total
+= rtx_cost (XEXP (XEXP (x
, 1), 0), mode
, PLUS
, 1, speed
);
5951 rtx op0
= XEXP (x
, 0);
5952 rtx op1
= XEXP (x
, 1);
5954 if (GET_CODE (op0
) == ZERO_EXTRACT
&& op1
== const0_rtx
5955 && XEXP (op0
, 1) == const1_rtx
)
5957 /* btst / bbit0 / bbit1:
5958 Small integers and registers are free; everything else can
5959 be put in a register. */
5960 mode
= GET_MODE (XEXP (op0
, 0));
5961 *total
= (rtx_cost (XEXP (op0
, 0), mode
, SET
, 1, speed
)
5962 + rtx_cost (XEXP (op0
, 2), mode
, SET
, 1, speed
));
5965 if (GET_CODE (op0
) == AND
&& op1
== const0_rtx
5966 && satisfies_constraint_C1p (XEXP (op0
, 1)))
5969 *total
= rtx_cost (XEXP (op0
, 0), VOIDmode
, SET
, 1, speed
);
5973 if (GET_CODE (op1
) == NEG
)
5975 /* op0 might be constant, the inside of op1 is rather
5976 unlikely to be so. So swapping the operands might lower
5978 mode
= GET_MODE (op0
);
5979 *total
= (rtx_cost (op0
, mode
, PLUS
, 1, speed
)
5980 + rtx_cost (XEXP (op1
, 0), mode
, PLUS
, 0, speed
));
5985 if (outer_code
== IF_THEN_ELSE
5986 && GET_CODE (XEXP (x
, 0)) == ZERO_EXTRACT
5987 && XEXP (x
, 1) == const0_rtx
5988 && XEXP (XEXP (x
, 0), 1) == const1_rtx
)
5990 /* btst / bbit0 / bbit1:
5991 Small integers and registers are free; everything else can
5992 be put in a register. */
5993 rtx op0
= XEXP (x
, 0);
5995 mode
= GET_MODE (XEXP (op0
, 0));
5996 *total
= (rtx_cost (XEXP (op0
, 0), mode
, SET
, 1, speed
)
5997 + rtx_cost (XEXP (op0
, 2), mode
, SET
, 1, speed
));
6001 /* scc_insn expands into two insns. */
6002 case GTU
: case GEU
: case LEU
:
6004 *total
+= COSTS_N_INSNS (1);
6006 case LTU
: /* might use adc. */
6008 *total
+= COSTS_N_INSNS (1) - 1;
6015 /* Return true if ADDR is a valid pic address.
6016 A valid pic address on arc should look like
6017 const (unspec (SYMBOL_REF/LABEL) (ARC_UNSPEC_GOTOFF/ARC_UNSPEC_GOT)) */
6020 arc_legitimate_pic_addr_p (rtx addr
)
6022 if (GET_CODE (addr
) != CONST
)
6025 addr
= XEXP (addr
, 0);
6028 if (GET_CODE (addr
) == PLUS
)
6030 if (GET_CODE (XEXP (addr
, 1)) != CONST_INT
)
6032 addr
= XEXP (addr
, 0);
6035 if (GET_CODE (addr
) != UNSPEC
6036 || XVECLEN (addr
, 0) != 1)
6039 /* Must be one of @GOT, @GOTOFF, @GOTOFFPC, @tlsgd, tlsie. */
6040 if (XINT (addr
, 1) != ARC_UNSPEC_GOT
6041 && XINT (addr
, 1) != ARC_UNSPEC_GOTOFF
6042 && XINT (addr
, 1) != ARC_UNSPEC_GOTOFFPC
6043 && XINT (addr
, 1) != UNSPEC_TLS_GD
6044 && XINT (addr
, 1) != UNSPEC_TLS_IE
)
6047 if (GET_CODE (XVECEXP (addr
, 0, 0)) != SYMBOL_REF
6048 && GET_CODE (XVECEXP (addr
, 0, 0)) != LABEL_REF
)
6056 /* Return true if OP contains a symbol reference. */
6059 symbolic_reference_mentioned_p (rtx op
)
6064 if (GET_CODE (op
) == SYMBOL_REF
|| GET_CODE (op
) == LABEL_REF
)
6067 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
6068 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
6074 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
6075 if (symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
)))
6079 else if (fmt
[i
] == 'e' && symbolic_reference_mentioned_p (XEXP (op
, i
)))
6086 /* Return true if OP contains a SYMBOL_REF that is not wrapped in an unspec.
6087 If SKIP_LOCAL is true, skip symbols that bind locally.
6088 This is used further down in this file, and, without SKIP_LOCAL,
6089 in the addsi3 / subsi3 expanders when generating PIC code. */
6092 arc_raw_symbolic_reference_mentioned_p (rtx op
, bool skip_local
)
6097 if (GET_CODE(op
) == UNSPEC
)
6100 if (GET_CODE (op
) == SYMBOL_REF
)
6102 if (SYMBOL_REF_TLS_MODEL (op
))
6106 tree decl
= SYMBOL_REF_DECL (op
);
6107 return !skip_local
|| !decl
|| !default_binds_local_p (decl
);
6110 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
6111 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
6117 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
6118 if (arc_raw_symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
),
6123 else if (fmt
[i
] == 'e'
6124 && arc_raw_symbolic_reference_mentioned_p (XEXP (op
, i
),
6132 /* The __tls_get_attr symbol. */
6133 static GTY(()) rtx arc_tls_symbol
;
6135 /* Emit a call to __tls_get_addr. TI is the argument to this function.
6136 RET is an RTX for the return value location. The entire insn sequence
6140 arc_call_tls_get_addr (rtx ti
)
6142 rtx arg
= gen_rtx_REG (Pmode
, R0_REG
);
6143 rtx ret
= gen_rtx_REG (Pmode
, R0_REG
);
6147 if (!arc_tls_symbol
)
6148 arc_tls_symbol
= init_one_libfunc ("__tls_get_addr");
6150 emit_move_insn (arg
, ti
);
6151 fn
= gen_rtx_MEM (SImode
, arc_tls_symbol
);
6152 insn
= emit_call_insn (gen_call_value (ret
, fn
, const0_rtx
));
6153 RTL_CONST_CALL_P (insn
) = 1;
6154 use_reg (&CALL_INSN_FUNCTION_USAGE (insn
), ret
);
6155 use_reg (&CALL_INSN_FUNCTION_USAGE (insn
), arg
);
6160 /* Return a legitimized address for ADDR,
6161 which is a SYMBOL_REF with tls_model MODEL. */
6164 arc_legitimize_tls_address (rtx addr
, enum tls_model model
)
6168 /* The TP pointer needs to be set. */
6169 gcc_assert (arc_tp_regno
!= -1);
6173 case TLS_MODEL_GLOBAL_DYNAMIC
:
6174 case TLS_MODEL_LOCAL_DYNAMIC
:
6175 tmp
= gen_reg_rtx (Pmode
);
6176 emit_move_insn (tmp
, arc_unspec_offset (addr
, UNSPEC_TLS_GD
));
6177 return arc_call_tls_get_addr (tmp
);
6179 case TLS_MODEL_INITIAL_EXEC
:
6180 addr
= arc_unspec_offset (addr
, UNSPEC_TLS_IE
);
6181 addr
= copy_to_mode_reg (Pmode
, gen_const_mem (Pmode
, addr
));
6182 return gen_rtx_PLUS (Pmode
, gen_rtx_REG (Pmode
, arc_tp_regno
), addr
);
6184 case TLS_MODEL_LOCAL_EXEC
:
6185 addr
= arc_unspec_offset (addr
, UNSPEC_TLS_OFF
);
6186 return gen_rtx_PLUS (Pmode
, gen_rtx_REG (Pmode
, arc_tp_regno
), addr
);
6193 /* Return true if SYMBOL_REF X binds locally. */
6196 arc_symbol_binds_local_p (const_rtx x
)
6198 return (SYMBOL_REF_DECL (x
)
6199 ? targetm
.binds_local_p (SYMBOL_REF_DECL (x
))
6200 : SYMBOL_REF_LOCAL_P (x
));
6203 /* Legitimize a pic address reference in ADDR. The return value is
6204 the legitimated address. */
6207 arc_legitimize_pic_address (rtx addr
)
6212 switch (GET_CODE (addr
))
6215 /* Can be one or our GOT or GOTOFFPC unspecs. This situation
6216 happens when an address is not a legitimate constant and we
6217 need the resolve it via force_reg in
6218 prepare_move_operands. */
6219 switch (XINT (addr
, 1))
6221 case ARC_UNSPEC_GOT
:
6222 case ARC_UNSPEC_GOTOFFPC
:
6223 /* Recover the symbol ref. */
6224 addr
= XVECEXP (addr
, 0, 0);
6231 /* TLS symbols are handled in different place. */
6232 if (SYMBOL_REF_TLS_MODEL (addr
))
6235 /* This symbol must be referenced via a load from the Global
6236 Offset Table (@GOTPC). */
6237 if (!arc_symbol_binds_local_p (addr
))
6238 return gen_const_mem (Pmode
, arc_unspec_offset (addr
, ARC_UNSPEC_GOT
));
6240 /* Local symb: use @pcl to access it. */
6243 return arc_unspec_offset (addr
, ARC_UNSPEC_GOTOFFPC
);
6252 /* Output address constant X to FILE, taking PIC into account. */
6255 arc_output_pic_addr_const (FILE * file
, rtx x
, int code
)
6260 switch (GET_CODE (x
))
6270 output_addr_const (file
, x
);
6272 /* Local functions do not get references through the PLT. */
6273 if (code
== 'P' && ! SYMBOL_REF_LOCAL_P (x
))
6274 fputs ("@plt", file
);
6278 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (XEXP (x
, 0)));
6279 assemble_name (file
, buf
);
6283 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (x
));
6284 assemble_name (file
, buf
);
6288 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
));
6292 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
6296 if (GET_MODE (x
) == VOIDmode
)
6298 /* We can use %d if the number is one word and positive. */
6299 if (CONST_DOUBLE_HIGH (x
))
6300 fprintf (file
, HOST_WIDE_INT_PRINT_DOUBLE_HEX
,
6301 CONST_DOUBLE_HIGH (x
), CONST_DOUBLE_LOW (x
));
6302 else if (CONST_DOUBLE_LOW (x
) < 0)
6303 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, CONST_DOUBLE_LOW (x
));
6305 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, CONST_DOUBLE_LOW (x
));
6308 /* We can't handle floating point constants;
6309 PRINT_OPERAND must handle them. */
6310 output_operand_lossage ("floating constant misused");
6314 /* FIXME: Not needed here. */
6315 /* Some assemblers need integer constants to appear last (eg masm). */
6316 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
6318 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
6319 fprintf (file
, "+");
6320 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
6322 else if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
6324 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
6325 if (INTVAL (XEXP (x
, 1)) >= 0)
6326 fprintf (file
, "+");
6327 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
6334 /* Avoid outputting things like x-x or x+5-x,
6335 since some assemblers can't handle that. */
6336 x
= simplify_subtraction (x
);
6337 if (GET_CODE (x
) != MINUS
)
6340 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
6341 fprintf (file
, "-");
6342 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
6343 && INTVAL (XEXP (x
, 1)) < 0)
6345 fprintf (file
, "(");
6346 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
6347 fprintf (file
, ")");
6350 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
6355 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
6361 bool pcrel
; pcrel
= false;
6362 rtx base
; base
= NULL
;
6363 gcc_assert (XVECLEN (x
, 0) >= 1);
6364 switch (XINT (x
, 1))
6366 case ARC_UNSPEC_GOT
:
6367 suffix
= "@gotpc", pcrel
= true;
6369 case ARC_UNSPEC_GOTOFF
:
6372 case ARC_UNSPEC_GOTOFFPC
:
6373 suffix
= "@pcl", pcrel
= true;
6375 case ARC_UNSPEC_PLT
:
6379 suffix
= "@tlsgd", pcrel
= true;
6382 suffix
= "@tlsie", pcrel
= true;
6384 case UNSPEC_TLS_OFF
:
6385 if (XVECLEN (x
, 0) == 2)
6386 base
= XVECEXP (x
, 0, 1);
6387 if (SYMBOL_REF_TLS_MODEL (XVECEXP (x
, 0, 0)) == TLS_MODEL_LOCAL_EXEC
6388 || (!flag_pic
&& !base
))
6394 suffix
= "@invalid";
6395 output_operand_lossage ("invalid UNSPEC as operand: %d", XINT (x
,1));
6399 fputs ("pcl,", file
);
6400 arc_output_pic_addr_const (file
, XVECEXP (x
, 0, 0), code
);
6401 fputs (suffix
, file
);
6403 arc_output_pic_addr_const (file
, base
, code
);
6407 output_operand_lossage ("invalid expression as operand");
6411 /* The function returning the number of words, at the beginning of an
6412 argument, must be put in registers. The returned value must be
6413 zero for arguments that are passed entirely in registers or that
6414 are entirely pushed on the stack.
6416 On some machines, certain arguments must be passed partially in
6417 registers and partially in memory. On these machines, typically
6418 the first N words of arguments are passed in registers, and the
6419 rest on the stack. If a multi-word argument (a `double' or a
6420 structure) crosses that boundary, its first few words must be
6421 passed in registers and the rest must be pushed. This function
6422 tells the compiler when this occurs, and how many of the words
6423 should go in registers.
6425 `FUNCTION_ARG' for these arguments should return the first register
6426 to be used by the caller for this argument; likewise
6427 `FUNCTION_INCOMING_ARG', for the called function.
6429 The function is used to implement macro FUNCTION_ARG_PARTIAL_NREGS. */
6431 /* If REGNO is the least arg reg available then what is the total number of arg
6433 #define GPR_REST_ARG_REGS(REGNO) \
6434 ((REGNO) <= MAX_ARC_PARM_REGS ? MAX_ARC_PARM_REGS - (REGNO) : 0 )
6436 /* Since arc parm regs are contiguous. */
6437 #define ARC_NEXT_ARG_REG(REGNO) ( (REGNO) + 1 )
6439 /* Implement TARGET_ARG_PARTIAL_BYTES. */
6442 arc_arg_partial_bytes (cumulative_args_t cum_v
, const function_arg_info
&arg
)
6444 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
6445 int bytes
= arg
.promoted_size_in_bytes ();
6446 int words
= (bytes
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
6450 arg_num
= ROUND_ADVANCE_CUM (arg_num
, arg
.mode
, arg
.type
);
6451 ret
= GPR_REST_ARG_REGS (arg_num
);
6453 /* ICEd at function.cc:2361, and ret is copied to data->partial */
6454 ret
= (ret
>= words
? 0 : ret
* UNITS_PER_WORD
);
6459 /* Implement TARGET_FUNCTION_ARG. On the ARC the first MAX_ARC_PARM_REGS
6460 args are normally in registers and the rest are pushed. */
6463 arc_function_arg (cumulative_args_t cum_v
, const function_arg_info
&arg
)
6465 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
6468 const char *debstr ATTRIBUTE_UNUSED
;
6470 arg_num
= ROUND_ADVANCE_CUM (arg_num
, arg
.mode
, arg
.type
);
6471 /* Return a marker for use in the call instruction. */
6472 if (arg
.end_marker_p ())
6477 else if (GPR_REST_ARG_REGS (arg_num
) > 0)
6479 ret
= gen_rtx_REG (arg
.mode
, arg_num
);
6480 debstr
= reg_names
[arg_num
];
6490 /* Implement TARGET_FUNCTION_ARG_ADVANCE. */
6491 /* For the ARC: the cum set here is passed on to function_arg where we
6492 look at its value and say which reg to use. Strategy: advance the
6493 regnumber here till we run out of arg regs, then set *cum to last
6494 reg. In function_arg, since *cum > last arg reg we would return 0
6495 and thus the arg will end up on the stack. For straddling args of
6496 course function_arg_partial_nregs will come into play. */
6499 arc_function_arg_advance (cumulative_args_t cum_v
,
6500 const function_arg_info
&arg
)
6502 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
6503 int bytes
= arg
.promoted_size_in_bytes ();
6504 int words
= (bytes
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
6508 *cum
= ROUND_ADVANCE_CUM (*cum
, arg
.mode
, arg
.type
);
6509 for (i
= 0; i
< words
; i
++)
6510 *cum
= ARC_NEXT_ARG_REG (*cum
);
6514 /* Define how to find the value returned by a function.
6515 VALTYPE is the data type of the value (as a tree).
6516 If the precise function being called is known, FN_DECL_OR_TYPE is its
6517 FUNCTION_DECL; otherwise, FN_DECL_OR_TYPE is its type. */
6520 arc_function_value (const_tree valtype
,
6521 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
6522 bool outgoing ATTRIBUTE_UNUSED
)
6524 machine_mode mode
= TYPE_MODE (valtype
);
6525 int unsignedp ATTRIBUTE_UNUSED
;
6527 unsignedp
= TYPE_UNSIGNED (valtype
);
6528 if (INTEGRAL_TYPE_P (valtype
) || TREE_CODE (valtype
) == OFFSET_TYPE
)
6529 PROMOTE_MODE (mode
, unsignedp
, valtype
);
6530 return gen_rtx_REG (mode
, 0);
6533 /* Returns the return address that is used by builtin_return_address. */
6536 arc_return_addr_rtx (int count
, ATTRIBUTE_UNUSED rtx frame
)
6541 return get_hard_reg_initial_val (Pmode
, RETURN_ADDR_REGNUM
);
6544 /* Determine if a given RTX is a valid constant. We already know this
6545 satisfies CONSTANT_P. */
6548 arc_legitimate_constant_p (machine_mode mode
, rtx x
)
6550 switch (GET_CODE (x
))
6555 if (arc_legitimate_pic_addr_p (x
))
6558 return arc_legitimate_constant_p (mode
, XEXP (x
, 0));
6561 if (SYMBOL_REF_TLS_MODEL (x
))
6573 return arc_legitimate_constant_p (mode
, XEXP (x
, 0));
6578 bool t1
= arc_legitimate_constant_p (mode
, XEXP (x
, 0));
6579 bool t2
= arc_legitimate_constant_p (mode
, XEXP (x
, 1));
6588 return TARGET_PLUS_DMPY
;
6591 return TARGET_PLUS_QMACW
;
6597 switch (XINT (x
, 1))
6600 case UNSPEC_TLS_OFF
:
6604 /* Any other unspec ending here are pic related, hence the above
6605 constant pic address checking returned false. */
6611 fatal_insn ("unrecognized supposed constant", x
);
6618 arc_legitimate_address_p (machine_mode mode
, rtx x
, bool strict
,
6619 code_helper
= ERROR_MARK
)
6621 if (RTX_OK_FOR_BASE_P (x
, strict
))
6623 if (legitimate_offset_address_p (mode
, x
, TARGET_INDEXED_LOADS
, strict
))
6625 if (legitimate_scaled_address_p (mode
, x
, strict
))
6627 if (legitimate_small_data_address_p (x
, mode
))
6629 if (GET_CODE (x
) == CONST_INT
&& LARGE_INT (INTVAL (x
)))
6632 /* When we compile for size avoid const (@sym + offset)
6634 if (!flag_pic
&& optimize_size
&& !reload_completed
6635 && (GET_CODE (x
) == CONST
)
6636 && (GET_CODE (XEXP (x
, 0)) == PLUS
)
6637 && (GET_CODE (XEXP (XEXP (x
, 0), 0)) == SYMBOL_REF
)
6638 && SYMBOL_REF_TLS_MODEL (XEXP (XEXP (x
, 0), 0)) == 0
6639 && !SYMBOL_REF_FUNCTION_P (XEXP (XEXP (x
, 0), 0)))
6641 rtx addend
= XEXP (XEXP (x
, 0), 1);
6642 gcc_assert (CONST_INT_P (addend
));
6643 HOST_WIDE_INT offset
= INTVAL (addend
);
6645 /* Allow addresses having a large offset to pass. Anyhow they
6646 will end in a limm. */
6647 return !(offset
> -1024 && offset
< 1020);
6650 if ((GET_MODE_SIZE (mode
) != 16) && CONSTANT_P (x
))
6652 return arc_legitimate_constant_p (mode
, x
);
6654 if ((GET_CODE (x
) == PRE_DEC
|| GET_CODE (x
) == PRE_INC
6655 || GET_CODE (x
) == POST_DEC
|| GET_CODE (x
) == POST_INC
)
6656 && RTX_OK_FOR_BASE_P (XEXP (x
, 0), strict
))
6658 /* We're restricted here by the `st' insn. */
6659 if ((GET_CODE (x
) == PRE_MODIFY
|| GET_CODE (x
) == POST_MODIFY
)
6660 && GET_CODE (XEXP ((x
), 1)) == PLUS
6661 && rtx_equal_p (XEXP ((x
), 0), XEXP (XEXP (x
, 1), 0))
6662 && legitimate_offset_address_p (QImode
, XEXP (x
, 1),
6663 TARGET_AUTO_MODIFY_REG
, strict
))
6668 /* Return true iff ADDR (a legitimate address expression)
6669 has an effect that depends on the machine mode it is used for. */
6672 arc_mode_dependent_address_p (const_rtx addr
, addr_space_t
)
6674 /* SYMBOL_REF is not mode dependent: it is either a small data reference,
6675 which is valid for loads and stores, or a limm offset, which is valid for
6676 loads. Scaled indices are scaled by the access mode. */
6677 if (GET_CODE (addr
) == PLUS
6678 && GET_CODE (XEXP ((addr
), 0)) == MULT
)
6683 /* Determine if it's legal to put X into the constant pool. */
6686 arc_cannot_force_const_mem (machine_mode mode
, rtx x
)
6688 return !arc_legitimate_constant_p (mode
, x
);
6691 /* IDs for all the ARC builtins. */
6695 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, ICODE, MASK) \
6696 ARC_BUILTIN_ ## NAME,
6697 #include "builtins.def"
6703 struct GTY(()) arc_builtin_description
6705 enum insn_code icode
;
6710 static GTY(()) struct arc_builtin_description
6711 arc_bdesc
[ARC_BUILTIN_COUNT
] =
6713 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, ICODE, MASK) \
6714 { (enum insn_code) CODE_FOR_ ## ICODE, N_ARGS, NULL_TREE },
6715 #include "builtins.def"
6719 /* Transform UP into lowercase and write the result to LO.
6720 You must provide enough space for LO. Return LO. */
6723 arc_tolower (char *lo
, const char *up
)
6727 for (; *up
; up
++, lo
++)
6728 *lo
= TOLOWER (*up
);
6735 /* Implement `TARGET_BUILTIN_DECL'. */
6738 arc_builtin_decl (unsigned id
, bool initialize_p ATTRIBUTE_UNUSED
)
6740 if (id
< ARC_BUILTIN_COUNT
)
6741 return arc_bdesc
[id
].fndecl
;
6743 return error_mark_node
;
6747 arc_init_builtins (void)
6749 tree V4HI_type_node
;
6750 tree V2SI_type_node
;
6751 tree V2HI_type_node
;
6753 /* Vector types based on HS SIMD elements. */
6754 V4HI_type_node
= build_vector_type_for_mode (intHI_type_node
, V4HImode
);
6755 V2SI_type_node
= build_vector_type_for_mode (intSI_type_node
, V2SImode
);
6756 V2HI_type_node
= build_vector_type_for_mode (intHI_type_node
, V2HImode
);
6758 tree pcvoid_type_node
6759 = build_pointer_type (build_qualified_type (void_type_node
,
6761 tree V8HI_type_node
= build_vector_type_for_mode (intHI_type_node
,
6764 tree void_ftype_void
6765 = build_function_type_list (void_type_node
, NULL_TREE
);
6767 = build_function_type_list (integer_type_node
, integer_type_node
,
6769 tree int_ftype_pcvoid_int
6770 = build_function_type_list (integer_type_node
, pcvoid_type_node
,
6771 integer_type_node
, NULL_TREE
);
6772 tree void_ftype_usint_usint
6773 = build_function_type_list (void_type_node
, long_unsigned_type_node
,
6774 long_unsigned_type_node
, NULL_TREE
);
6775 tree int_ftype_int_int
6776 = build_function_type_list (integer_type_node
, integer_type_node
,
6777 integer_type_node
, NULL_TREE
);
6778 tree usint_ftype_usint
6779 = build_function_type_list (long_unsigned_type_node
,
6780 long_unsigned_type_node
, NULL_TREE
);
6781 tree void_ftype_usint
6782 = build_function_type_list (void_type_node
, long_unsigned_type_node
,
6785 = build_function_type_list (integer_type_node
, void_type_node
,
6788 = build_function_type_list (void_type_node
, integer_type_node
,
6790 tree int_ftype_short
6791 = build_function_type_list (integer_type_node
, short_integer_type_node
,
6794 /* Old ARC SIMD types. */
6795 tree v8hi_ftype_v8hi_v8hi
6796 = build_function_type_list (V8HI_type_node
, V8HI_type_node
,
6797 V8HI_type_node
, NULL_TREE
);
6798 tree v8hi_ftype_v8hi_int
6799 = build_function_type_list (V8HI_type_node
, V8HI_type_node
,
6800 integer_type_node
, NULL_TREE
);
6801 tree v8hi_ftype_v8hi_int_int
6802 = build_function_type_list (V8HI_type_node
, V8HI_type_node
,
6803 integer_type_node
, integer_type_node
,
6805 tree void_ftype_v8hi_int_int
6806 = build_function_type_list (void_type_node
, V8HI_type_node
,
6807 integer_type_node
, integer_type_node
,
6809 tree void_ftype_v8hi_int_int_int
6810 = build_function_type_list (void_type_node
, V8HI_type_node
,
6811 integer_type_node
, integer_type_node
,
6812 integer_type_node
, NULL_TREE
);
6813 tree v8hi_ftype_int_int
6814 = build_function_type_list (V8HI_type_node
, integer_type_node
,
6815 integer_type_node
, NULL_TREE
);
6816 tree void_ftype_int_int
6817 = build_function_type_list (void_type_node
, integer_type_node
,
6818 integer_type_node
, NULL_TREE
);
6819 tree v8hi_ftype_v8hi
6820 = build_function_type_list (V8HI_type_node
, V8HI_type_node
,
6822 /* ARCv2 SIMD types. */
6823 tree long_ftype_v4hi_v4hi
6824 = build_function_type_list (long_long_integer_type_node
,
6825 V4HI_type_node
, V4HI_type_node
, NULL_TREE
);
6826 tree int_ftype_v2hi_v2hi
6827 = build_function_type_list (integer_type_node
,
6828 V2HI_type_node
, V2HI_type_node
, NULL_TREE
);
6829 tree v2si_ftype_v2hi_v2hi
6830 = build_function_type_list (V2SI_type_node
,
6831 V2HI_type_node
, V2HI_type_node
, NULL_TREE
);
6832 tree v2hi_ftype_v2hi_v2hi
6833 = build_function_type_list (V2HI_type_node
,
6834 V2HI_type_node
, V2HI_type_node
, NULL_TREE
);
6835 tree v2si_ftype_v2si_v2si
6836 = build_function_type_list (V2SI_type_node
,
6837 V2SI_type_node
, V2SI_type_node
, NULL_TREE
);
6838 tree v4hi_ftype_v4hi_v4hi
6839 = build_function_type_list (V4HI_type_node
,
6840 V4HI_type_node
, V4HI_type_node
, NULL_TREE
);
6841 tree long_ftype_v2si_v2hi
6842 = build_function_type_list (long_long_integer_type_node
,
6843 V2SI_type_node
, V2HI_type_node
, NULL_TREE
);
6845 /* Add the builtins. */
6846 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, ICODE, MASK) \
6848 int id = ARC_BUILTIN_ ## NAME; \
6849 const char *Name = "__builtin_arc_" #NAME; \
6850 char *name = (char*) alloca (1 + strlen (Name)); \
6852 gcc_assert (id < ARC_BUILTIN_COUNT); \
6854 arc_bdesc[id].fndecl \
6855 = add_builtin_function (arc_tolower(name, Name), TYPE, id, \
6856 BUILT_IN_MD, NULL, NULL_TREE); \
6858 #include "builtins.def"
6862 /* Helper to expand __builtin_arc_aligned (void* val, int
6866 arc_expand_builtin_aligned (tree exp
)
6868 tree arg0
= CALL_EXPR_ARG (exp
, 0);
6869 tree arg1
= CALL_EXPR_ARG (exp
, 1);
6871 rtx op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
6872 rtx op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
6874 if (!CONST_INT_P (op1
))
6876 /* If we can't fold the alignment to a constant integer
6877 whilst optimizing, this is probably a user error. */
6879 warning (0, "%<__builtin_arc_aligned%> with non-constant alignment");
6883 HOST_WIDE_INT alignTest
= INTVAL (op1
);
6884 /* Check alignTest is positive, and a power of two. */
6885 if (alignTest
<= 0 || alignTest
!= (alignTest
& -alignTest
))
6887 error ("invalid alignment value for %<__builtin_arc_aligned%>");
6891 if (CONST_INT_P (op0
))
6893 HOST_WIDE_INT pnt
= INTVAL (op0
);
6895 if ((pnt
& (alignTest
- 1)) == 0)
6900 unsigned align
= get_pointer_alignment (arg0
);
6901 unsigned numBits
= alignTest
* BITS_PER_UNIT
;
6903 if (align
&& align
>= numBits
)
6905 /* Another attempt to ascertain alignment. Check the type
6906 we are pointing to. */
6907 if (POINTER_TYPE_P (TREE_TYPE (arg0
))
6908 && TYPE_ALIGN (TREE_TYPE (TREE_TYPE (arg0
))) >= numBits
)
6913 /* Default to false. */
6917 /* Helper arc_expand_builtin, generates a pattern for the given icode
6921 apply_GEN_FCN (enum insn_code icode
, rtx
*arg
)
6923 switch (insn_data
[icode
].n_generator_args
)
6926 return GEN_FCN (icode
) ();
6928 return GEN_FCN (icode
) (arg
[0]);
6930 return GEN_FCN (icode
) (arg
[0], arg
[1]);
6932 return GEN_FCN (icode
) (arg
[0], arg
[1], arg
[2]);
6934 return GEN_FCN (icode
) (arg
[0], arg
[1], arg
[2], arg
[3]);
6936 return GEN_FCN (icode
) (arg
[0], arg
[1], arg
[2], arg
[3], arg
[4]);
6942 /* Expand an expression EXP that calls a built-in function,
6943 with result going to TARGET if that's convenient
6944 (and in mode MODE if that's convenient).
6945 SUBTARGET may be used as the target for computing one of EXP's operands.
6946 IGNORE is nonzero if the value is to be ignored. */
6949 arc_expand_builtin (tree exp
,
6951 rtx subtarget ATTRIBUTE_UNUSED
,
6952 machine_mode mode ATTRIBUTE_UNUSED
,
6953 int ignore ATTRIBUTE_UNUSED
)
6955 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
6956 unsigned int id
= DECL_MD_FUNCTION_CODE (fndecl
);
6957 const struct arc_builtin_description
*d
= &arc_bdesc
[id
];
6958 int i
, j
, n_args
= call_expr_nargs (exp
);
6961 enum insn_code icode
= d
->icode
;
6962 machine_mode tmode
= insn_data
[icode
].operand
[0].mode
;
6979 if (id
>= ARC_BUILTIN_COUNT
)
6980 internal_error ("bad builtin fcode");
6982 /* 1st part: Expand special builtins. */
6985 case ARC_BUILTIN_NOP
:
6986 emit_insn (gen_nopv ());
6989 case ARC_BUILTIN_RTIE
:
6990 case ARC_BUILTIN_SYNC
:
6991 case ARC_BUILTIN_BRK
:
6992 case ARC_BUILTIN_SWI
:
6993 case ARC_BUILTIN_UNIMP_S
:
6994 gcc_assert (icode
!= 0);
6995 emit_insn (GEN_FCN (icode
) (const1_rtx
));
6998 case ARC_BUILTIN_ALIGNED
:
6999 return arc_expand_builtin_aligned (exp
);
7001 case ARC_BUILTIN_CLRI
:
7002 target
= gen_reg_rtx (SImode
);
7003 emit_insn (gen_clri (target
, const1_rtx
));
7006 case ARC_BUILTIN_TRAP_S
:
7007 case ARC_BUILTIN_SLEEP
:
7008 arg0
= CALL_EXPR_ARG (exp
, 0);
7010 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
7012 gcc_assert (icode
!= 0);
7013 emit_insn (GEN_FCN (icode
) (op0
));
7016 case ARC_BUILTIN_VDORUN
:
7017 case ARC_BUILTIN_VDIRUN
:
7018 arg0
= CALL_EXPR_ARG (exp
, 0);
7019 arg1
= CALL_EXPR_ARG (exp
, 1);
7020 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7021 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7023 target
= gen_rtx_REG (SImode
, (id
== ARC_BUILTIN_VDIRUN
) ? 131 : 139);
7025 mode0
= insn_data
[icode
].operand
[1].mode
;
7026 mode1
= insn_data
[icode
].operand
[2].mode
;
7028 if (!insn_data
[icode
].operand
[1].predicate (op0
, mode0
))
7029 op0
= copy_to_mode_reg (mode0
, op0
);
7031 if (!insn_data
[icode
].operand
[2].predicate (op1
, mode1
))
7032 op1
= copy_to_mode_reg (mode1
, op1
);
7034 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
7041 case ARC_BUILTIN_VDIWR
:
7042 case ARC_BUILTIN_VDOWR
:
7043 arg0
= CALL_EXPR_ARG (exp
, 0);
7044 arg1
= CALL_EXPR_ARG (exp
, 1);
7045 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7046 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7048 if (!CONST_INT_P (op0
)
7049 || !(UNSIGNED_INT3 (INTVAL (op0
))))
7050 error ("operand 1 should be an unsigned 3-bit immediate");
7052 mode1
= insn_data
[icode
].operand
[1].mode
;
7054 if (icode
== CODE_FOR_vdiwr_insn
)
7055 target
= gen_rtx_REG (SImode
,
7056 ARC_FIRST_SIMD_DMA_CONFIG_IN_REG
+ INTVAL (op0
));
7057 else if (icode
== CODE_FOR_vdowr_insn
)
7058 target
= gen_rtx_REG (SImode
,
7059 ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG
+ INTVAL (op0
));
7063 if (!insn_data
[icode
].operand
[2].predicate (op1
, mode1
))
7064 op1
= copy_to_mode_reg (mode1
, op1
);
7066 pat
= GEN_FCN (icode
) (target
, op1
);
7073 case ARC_BUILTIN_VASRW
:
7074 case ARC_BUILTIN_VSR8
:
7075 case ARC_BUILTIN_VSR8AW
:
7076 arg0
= CALL_EXPR_ARG (exp
, 0);
7077 arg1
= CALL_EXPR_ARG (exp
, 1);
7078 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
7079 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7080 op2
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
);
7082 target
= gen_reg_rtx (V8HImode
);
7083 mode0
= insn_data
[icode
].operand
[1].mode
;
7084 mode1
= insn_data
[icode
].operand
[2].mode
;
7086 if (!insn_data
[icode
].operand
[1].predicate (op0
, mode0
))
7087 op0
= copy_to_mode_reg (mode0
, op0
);
7089 if ((!insn_data
[icode
].operand
[2].predicate (op1
, mode1
))
7090 || !(UNSIGNED_INT3 (INTVAL (op1
))))
7091 error ("operand 2 should be an unsigned 3-bit value (I0-I7)");
7093 pat
= GEN_FCN (icode
) (target
, op0
, op1
, op2
);
7100 case ARC_BUILTIN_VLD32WH
:
7101 case ARC_BUILTIN_VLD32WL
:
7102 case ARC_BUILTIN_VLD64
:
7103 case ARC_BUILTIN_VLD32
:
7106 arg0
= CALL_EXPR_ARG (exp
, 0); /* source vreg. */
7107 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7. */
7108 arg2
= CALL_EXPR_ARG (exp
, 2); /* u8. */
7110 src_vreg
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
7111 op0
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7112 op1
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7113 op2
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
);
7115 /* target <- src vreg. */
7116 emit_insn (gen_move_insn (target
, src_vreg
));
7118 /* target <- vec_concat: target, mem (Ib, u8). */
7119 mode0
= insn_data
[icode
].operand
[3].mode
;
7120 mode1
= insn_data
[icode
].operand
[1].mode
;
7122 if ((!insn_data
[icode
].operand
[3].predicate (op0
, mode0
))
7123 || !(UNSIGNED_INT3 (INTVAL (op0
))))
7124 error ("operand 1 should be an unsigned 3-bit value (I0-I7)");
7126 if ((!insn_data
[icode
].operand
[1].predicate (op1
, mode1
))
7127 || !(UNSIGNED_INT8 (INTVAL (op1
))))
7128 error ("operand 2 should be an unsigned 8-bit value");
7130 pat
= GEN_FCN (icode
) (target
, op1
, op2
, op0
);
7137 case ARC_BUILTIN_VLD64W
:
7138 case ARC_BUILTIN_VLD128
:
7139 arg0
= CALL_EXPR_ARG (exp
, 0); /* dest vreg. */
7140 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7. */
7142 op0
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
);
7143 op1
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7144 op2
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7146 /* target <- src vreg. */
7147 target
= gen_reg_rtx (V8HImode
);
7149 /* target <- vec_concat: target, mem (Ib, u8). */
7150 mode0
= insn_data
[icode
].operand
[1].mode
;
7151 mode1
= insn_data
[icode
].operand
[2].mode
;
7152 mode2
= insn_data
[icode
].operand
[3].mode
;
7154 if ((!insn_data
[icode
].operand
[2].predicate (op1
, mode1
))
7155 || !(UNSIGNED_INT3 (INTVAL (op1
))))
7156 error ("operand 1 should be an unsigned 3-bit value (I0-I7)");
7158 if ((!insn_data
[icode
].operand
[3].predicate (op2
, mode2
))
7159 || !(UNSIGNED_INT8 (INTVAL (op2
))))
7160 error ("operand 2 should be an unsigned 8-bit value");
7162 pat
= GEN_FCN (icode
) (target
, op0
, op1
, op2
);
7170 case ARC_BUILTIN_VST128
:
7171 case ARC_BUILTIN_VST64
:
7172 arg0
= CALL_EXPR_ARG (exp
, 0); /* src vreg. */
7173 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7. */
7174 arg2
= CALL_EXPR_ARG (exp
, 2); /* u8. */
7176 op0
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
);
7177 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7178 op2
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7179 op3
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
7181 mode0
= insn_data
[icode
].operand
[0].mode
;
7182 mode1
= insn_data
[icode
].operand
[1].mode
;
7183 mode2
= insn_data
[icode
].operand
[2].mode
;
7184 mode3
= insn_data
[icode
].operand
[3].mode
;
7186 if ((!insn_data
[icode
].operand
[1].predicate (op1
, mode1
))
7187 || !(UNSIGNED_INT3 (INTVAL (op1
))))
7188 error ("operand 2 should be an unsigned 3-bit value (I0-I7)");
7190 if ((!insn_data
[icode
].operand
[2].predicate (op2
, mode2
))
7191 || !(UNSIGNED_INT8 (INTVAL (op2
))))
7192 error ("operand 3 should be an unsigned 8-bit value");
7194 if (!insn_data
[icode
].operand
[3].predicate (op3
, mode3
))
7195 op3
= copy_to_mode_reg (mode3
, op3
);
7197 pat
= GEN_FCN (icode
) (op0
, op1
, op2
, op3
);
7204 case ARC_BUILTIN_VST16_N
:
7205 case ARC_BUILTIN_VST32_N
:
7206 arg0
= CALL_EXPR_ARG (exp
, 0); /* source vreg. */
7207 arg1
= CALL_EXPR_ARG (exp
, 1); /* u3. */
7208 arg2
= CALL_EXPR_ARG (exp
, 2); /* [I]0-7. */
7209 arg3
= CALL_EXPR_ARG (exp
, 3); /* u8. */
7211 op0
= expand_expr (arg3
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7212 op1
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
);
7213 op2
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7214 op3
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
7215 op4
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7217 mode0
= insn_data
[icode
].operand
[0].mode
;
7218 mode2
= insn_data
[icode
].operand
[2].mode
;
7219 mode3
= insn_data
[icode
].operand
[3].mode
;
7220 mode4
= insn_data
[icode
].operand
[4].mode
;
7222 /* Do some correctness checks for the operands. */
7223 if ((!insn_data
[icode
].operand
[0].predicate (op0
, mode0
))
7224 || !(UNSIGNED_INT8 (INTVAL (op0
))))
7225 error ("operand 4 should be an unsigned 8-bit value (0-255)");
7227 if ((!insn_data
[icode
].operand
[2].predicate (op2
, mode2
))
7228 || !(UNSIGNED_INT3 (INTVAL (op2
))))
7229 error ("operand 3 should be an unsigned 3-bit value (I0-I7)");
7231 if (!insn_data
[icode
].operand
[3].predicate (op3
, mode3
))
7232 op3
= copy_to_mode_reg (mode3
, op3
);
7234 if ((!insn_data
[icode
].operand
[4].predicate (op4
, mode4
))
7235 || !(UNSIGNED_INT3 (INTVAL (op4
))))
7236 error ("operand 2 should be an unsigned 3-bit value (subreg 0-7)");
7237 else if (icode
== CODE_FOR_vst32_n_insn
7238 && ((INTVAL (op4
) % 2) != 0))
7239 error ("operand 2 should be an even 3-bit value (subreg 0,2,4,6)");
7241 pat
= GEN_FCN (icode
) (op0
, op1
, op2
, op3
, op4
);
7252 /* 2nd part: Expand regular builtins. */
7254 internal_error ("bad builtin fcode");
7256 nonvoid
= TREE_TYPE (TREE_TYPE (fndecl
)) != void_type_node
;
7261 if (target
== NULL_RTX
7262 || GET_MODE (target
) != tmode
7263 || !insn_data
[icode
].operand
[0].predicate (target
, tmode
))
7265 target
= gen_reg_rtx (tmode
);
7270 gcc_assert (n_args
<= 4);
7271 for (i
= 0; i
< n_args
; i
++, j
++)
7273 tree arg
= CALL_EXPR_ARG (exp
, i
);
7274 machine_mode mode
= insn_data
[icode
].operand
[j
].mode
;
7275 rtx op
= expand_expr (arg
, NULL_RTX
, mode
, EXPAND_NORMAL
);
7276 machine_mode opmode
= GET_MODE (op
);
7277 char c
= insn_data
[icode
].operand
[j
].constraint
[0];
7279 /* SIMD extension requires exact immediate operand match. */
7280 if ((id
> ARC_BUILTIN_SIMD_BEGIN
)
7281 && (id
< ARC_BUILTIN_SIMD_END
)
7285 if (!CONST_INT_P (op
))
7286 error ("builtin requires an immediate for operand %d", j
);
7290 if (!satisfies_constraint_L (op
))
7291 error ("operand %d should be a 6 bit unsigned immediate", j
);
7294 if (!satisfies_constraint_P (op
))
7295 error ("operand %d should be a 8 bit unsigned immediate", j
);
7298 if (!satisfies_constraint_K (op
))
7299 error ("operand %d should be a 3 bit unsigned immediate", j
);
7302 error ("unknown builtin immediate operand type for operand %d",
7307 if (CONST_INT_P (op
))
7310 if ((opmode
== SImode
) && (mode
== HImode
))
7313 op
= gen_lowpart (HImode
, op
);
7316 /* In case the insn wants input operands in modes different from
7317 the result, abort. */
7318 gcc_assert (opmode
== mode
|| opmode
== VOIDmode
);
7320 if (!insn_data
[icode
].operand
[i
+ nonvoid
].predicate (op
, mode
))
7321 op
= copy_to_mode_reg (mode
, op
);
7326 pat
= apply_GEN_FCN (icode
, xop
);
7327 if (pat
== NULL_RTX
)
7338 /* Implement TARGET_FOLD_BUILTIN. */
7341 arc_fold_builtin (tree fndecl
, int n_args ATTRIBUTE_UNUSED
, tree
*arg
,
7342 bool ignore ATTRIBUTE_UNUSED
)
7344 unsigned int fcode
= DECL_MD_FUNCTION_CODE (fndecl
);
7351 case ARC_BUILTIN_SWAP
:
7352 return fold_build2 (LROTATE_EXPR
, integer_type_node
, arg
[0],
7353 build_int_cst (integer_type_node
, 16));
7355 case ARC_BUILTIN_NORM
:
7356 if (TREE_CODE (arg
[0]) == INTEGER_CST
7357 && !TREE_OVERFLOW (arg
[0]))
7359 wide_int arg0
= wi::to_wide (arg
[0], 32);
7360 wide_int result
= wi::shwi (wi::clrsb (arg0
), 32);
7361 return wide_int_to_tree (integer_type_node
, result
);
7365 case ARC_BUILTIN_NORMW
:
7366 if (TREE_CODE (arg
[0]) == INTEGER_CST
7367 && !TREE_OVERFLOW (arg
[0]))
7369 wide_int arg0
= wi::to_wide (arg
[0], 16);
7370 wide_int result
= wi::shwi (wi::clrsb (arg0
), 32);
7371 return wide_int_to_tree (integer_type_node
, result
);
7378 /* Returns true if the operands[opno] is a valid compile-time constant to be
7379 used as register number in the code for builtins. Else it flags an error
7380 and returns false. */
7383 check_if_valid_regno_const (rtx
*operands
, int opno
)
7386 switch (GET_CODE (operands
[opno
]))
7393 error ("register number must be a compile-time constant. "
7394 "Try giving higher optimization levels");
7400 /* Return true if it is ok to make a tail-call to DECL. */
7403 arc_function_ok_for_sibcall (tree decl
,
7404 tree exp ATTRIBUTE_UNUSED
)
7406 tree attrs
= NULL_TREE
;
7408 /* Never tailcall from an ISR routine - it needs a special exit sequence. */
7409 if (ARC_INTERRUPT_P (arc_compute_function_type (cfun
)))
7414 attrs
= TYPE_ATTRIBUTES (TREE_TYPE (decl
));
7416 if (lookup_attribute ("jli_always", attrs
))
7418 if (lookup_attribute ("jli_fixed", attrs
))
7420 if (lookup_attribute ("secure_call", attrs
))
7424 /* Everything else is ok. */
7428 /* Output code to add DELTA to the first argument, and then jump
7429 to FUNCTION. Used for C++ multiple inheritance. */
7432 arc_output_mi_thunk (FILE *file
, tree thunk ATTRIBUTE_UNUSED
,
7433 HOST_WIDE_INT delta
,
7434 HOST_WIDE_INT vcall_offset
,
7437 const char *fnname
= IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk
));
7438 int mi_delta
= delta
;
7439 const char *const mi_op
= mi_delta
< 0 ? "sub" : "add";
7442 = aggregate_value_p (TREE_TYPE (TREE_TYPE (function
)), function
) ? 1 : 0;
7445 assemble_start_function (thunk
, fnname
);
7448 mi_delta
= - mi_delta
;
7450 /* Add DELTA. When possible use a plain add, otherwise load it into
7451 a register first. */
7453 while (mi_delta
!= 0)
7455 if ((mi_delta
& (3 << shift
)) == 0)
7459 asm_fprintf (file
, "\t%s\t%s, %s, %d\n",
7460 mi_op
, reg_names
[this_regno
], reg_names
[this_regno
],
7461 mi_delta
& (0xff << shift
));
7462 mi_delta
&= ~(0xff << shift
);
7467 /* If needed, add *(*THIS + VCALL_OFFSET) to THIS. */
7468 if (vcall_offset
!= 0)
7470 /* ld r12,[this] --> temp = *this
7471 add r12,r12,vcall_offset --> temp = *(*this + vcall_offset)
7473 add this,this,r12 --> this+ = *(*this + vcall_offset) */
7474 asm_fprintf (file
, "\tld\t%s, [%s]\n",
7475 ARC_TEMP_SCRATCH_REG
, reg_names
[this_regno
]);
7476 asm_fprintf (file
, "\tadd\t%s, %s, " HOST_WIDE_INT_PRINT_DEC
"\n",
7477 ARC_TEMP_SCRATCH_REG
, ARC_TEMP_SCRATCH_REG
, vcall_offset
);
7478 asm_fprintf (file
, "\tld\t%s, [%s]\n",
7479 ARC_TEMP_SCRATCH_REG
, ARC_TEMP_SCRATCH_REG
);
7480 asm_fprintf (file
, "\tadd\t%s, %s, %s\n", reg_names
[this_regno
],
7481 reg_names
[this_regno
], ARC_TEMP_SCRATCH_REG
);
7484 fnaddr
= XEXP (DECL_RTL (function
), 0);
7486 if (arc_is_longcall_p (fnaddr
))
7490 asm_fprintf (file
, "\tld\t%s, [pcl, @",
7491 ARC_TEMP_SCRATCH_REG
);
7492 assemble_name (file
, XSTR (fnaddr
, 0));
7493 fputs ("@gotpc]\n", file
);
7494 asm_fprintf (file
, "\tj\t[%s]", ARC_TEMP_SCRATCH_REG
);
7498 fputs ("\tj\t@", file
);
7499 assemble_name (file
, XSTR (fnaddr
, 0));
7504 fputs ("\tb\t@", file
);
7505 assemble_name (file
, XSTR (fnaddr
, 0));
7507 fputs ("@plt\n", file
);
7510 assemble_end_function (thunk
, fnname
);
7513 /* Return true if a 32 bit "long_call" should be generated for
7514 this calling SYM_REF. We generate a long_call if the function:
7516 a. has an __attribute__((long call))
7517 or b. the -mlong-calls command line switch has been specified
7519 However we do not generate a long call if the function has an
7520 __attribute__ ((short_call)) or __attribute__ ((medium_call))
7522 This function will be called by C fragments contained in the machine
7523 description file. */
7526 arc_is_longcall_p (rtx sym_ref
)
7528 if (GET_CODE (sym_ref
) != SYMBOL_REF
)
7531 return (SYMBOL_REF_LONG_CALL_P (sym_ref
)
7532 || (TARGET_LONG_CALLS_SET
7533 && !SYMBOL_REF_SHORT_CALL_P (sym_ref
)
7534 && !SYMBOL_REF_MEDIUM_CALL_P (sym_ref
)));
7538 /* Likewise for short calls. */
7541 arc_is_shortcall_p (rtx sym_ref
)
7543 if (GET_CODE (sym_ref
) != SYMBOL_REF
)
7546 return (SYMBOL_REF_SHORT_CALL_P (sym_ref
)
7547 || (!TARGET_LONG_CALLS_SET
&& !TARGET_MEDIUM_CALLS
7548 && !SYMBOL_REF_LONG_CALL_P (sym_ref
)
7549 && !SYMBOL_REF_MEDIUM_CALL_P (sym_ref
)));
7553 /* Worker function for TARGET_RETURN_IN_MEMORY. */
7556 arc_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
7558 if (AGGREGATE_TYPE_P (type
) || TREE_ADDRESSABLE (type
))
7562 HOST_WIDE_INT size
= int_size_in_bytes (type
);
7563 return (size
== -1 || size
> (TARGET_V2
? 16 : 8));
7568 arc_pass_by_reference (cumulative_args_t
, const function_arg_info
&arg
)
7570 return (arg
.type
!= 0
7571 && (TREE_CODE (TYPE_SIZE (arg
.type
)) != INTEGER_CST
7572 || TREE_ADDRESSABLE (arg
.type
)));
7575 /* Implement TARGET_CAN_USE_DOLOOP_P. */
7578 arc_can_use_doloop_p (const widest_int
&,
7579 const widest_int
&iterations_max
,
7580 unsigned int loop_depth
, bool entered_at_top
)
7582 /* Considering limitations in the hardware, only use doloop
7583 for innermost loops which must be entered from the top. */
7584 if (loop_depth
> 1 || !entered_at_top
)
7587 /* Check for lp_count width boundary. */
7588 if (arc_lpcwidth
!= 32
7589 && (wi::gtu_p (iterations_max
, ((1 << arc_lpcwidth
) - 1))
7590 || wi::eq_p (iterations_max
, 0)))
7595 /* NULL if INSN insn is valid within a low-overhead loop. Otherwise
7596 return why doloop cannot be applied. */
7599 arc_invalid_within_doloop (const rtx_insn
*insn
)
7602 return "Function call in the loop.";
7604 /* FIXME! add here all the ZOL exceptions. */
7608 /* Return the next active insn, skiping the inline assembly code. */
7611 arc_active_insn (rtx_insn
*insn
)
7615 insn
= NEXT_INSN (insn
);
7617 || (active_insn_p (insn
)
7618 && NONDEBUG_INSN_P (insn
)
7620 && GET_CODE (PATTERN (insn
)) != UNSPEC_VOLATILE
7621 && GET_CODE (PATTERN (insn
)) != PARALLEL
))
7627 /* Search for a sequence made out of two stores and a given number of
7628 loads, insert a nop if required. */
7631 check_store_cacheline_hazard (void)
7633 rtx_insn
*insn
, *succ0
, *insn1
;
7636 for (insn
= get_insns (); insn
; insn
= arc_active_insn (insn
))
7638 succ0
= arc_active_insn (insn
);
7643 if (!single_set (insn
))
7646 if ((get_attr_type (insn
) != TYPE_STORE
))
7649 /* Found at least two consecutive stores. Goto the end of the
7651 for (insn1
= succ0
; insn1
; insn1
= arc_active_insn (insn1
))
7652 if (!single_set (insn1
) || get_attr_type (insn1
) != TYPE_STORE
)
7655 /* Save were we are. */
7658 /* Now, check the next two instructions for the following cases:
7659 1. next instruction is a LD => insert 2 nops between store
7661 2. next-next instruction is a LD => inset 1 nop after the store
7663 if (insn1
&& single_set (insn1
)
7664 && (get_attr_type (insn1
) == TYPE_LOAD
))
7667 emit_insn_before (gen_nopv (), insn1
);
7668 emit_insn_before (gen_nopv (), insn1
);
7672 if (insn1
&& (get_attr_type (insn1
) == TYPE_COMPARE
))
7674 /* REG_SAVE_NOTE is used by Haifa scheduler, we are in
7675 reorg, so it is safe to reuse it for avoiding the
7676 current compare insn to be part of a BRcc
7678 add_reg_note (insn1
, REG_SAVE_NOTE
, GEN_INT (3));
7680 insn1
= arc_active_insn (insn1
);
7681 if (insn1
&& single_set (insn1
)
7682 && (get_attr_type (insn1
) == TYPE_LOAD
))
7685 emit_insn_before (gen_nopv (), insn1
);
7699 /* Return true if a load instruction (CONSUMER) uses the same address as a
7700 store instruction (PRODUCER). This function is used to avoid st/ld
7701 address hazard in ARC700 cores. */
7704 arc_store_addr_hazard_internal_p (rtx_insn
* producer
, rtx_insn
* consumer
)
7706 rtx in_set
, out_set
;
7707 rtx out_addr
, in_addr
;
7715 /* Peel the producer and the consumer for the address. */
7716 out_set
= single_set (producer
);
7719 out_addr
= SET_DEST (out_set
);
7722 if (GET_CODE (out_addr
) == ZERO_EXTEND
7723 || GET_CODE (out_addr
) == SIGN_EXTEND
)
7724 out_addr
= XEXP (out_addr
, 0);
7726 if (!MEM_P (out_addr
))
7729 in_set
= single_set (consumer
);
7732 in_addr
= SET_SRC (in_set
);
7735 if (GET_CODE (in_addr
) == ZERO_EXTEND
7736 || GET_CODE (in_addr
) == SIGN_EXTEND
)
7737 in_addr
= XEXP (in_addr
, 0);
7739 if (!MEM_P (in_addr
))
7741 /* Get rid of the MEM and check if the addresses are
7743 in_addr
= XEXP (in_addr
, 0);
7744 out_addr
= XEXP (out_addr
, 0);
7746 return exp_equiv_p (in_addr
, out_addr
, 0, true);
7752 /* Return TRUE is we have an store address hazard. */
7755 arc_store_addr_hazard_p (rtx_insn
* producer
, rtx_insn
* consumer
)
7757 if (TARGET_ARC700
&& (arc_tune
!= ARC_TUNE_ARC7XX
))
7759 return arc_store_addr_hazard_internal_p (producer
, consumer
);
7762 /* Return length adjustment for INSN.
7764 A write to a core reg greater or equal to 32 must not be immediately
7765 followed by a use. Anticipate the length requirement to insert a nop
7766 between PRED and SUCC to prevent a hazard. */
7769 arc600_corereg_hazard (rtx_insn
*pred
, rtx_insn
*succ
)
7773 if (GET_CODE (PATTERN (pred
)) == SEQUENCE
)
7774 pred
= as_a
<rtx_sequence
*> (PATTERN (pred
))->insn (1);
7775 if (GET_CODE (PATTERN (succ
)) == SEQUENCE
)
7776 succ
= as_a
<rtx_sequence
*> (PATTERN (succ
))->insn (0);
7777 if (recog_memoized (pred
) == CODE_FOR_mulsi_600
7778 || recog_memoized (pred
) == CODE_FOR_umul_600
7779 || recog_memoized (pred
) == CODE_FOR_mac_600
7780 || recog_memoized (pred
) == CODE_FOR_mul64_600
7781 || recog_memoized (pred
) == CODE_FOR_mac64_600
7782 || recog_memoized (pred
) == CODE_FOR_umul64_600
7783 || recog_memoized (pred
) == CODE_FOR_umac64_600
)
7785 subrtx_iterator::array_type array
;
7786 FOR_EACH_SUBRTX (iter
, array
, PATTERN (pred
), NONCONST
)
7788 const_rtx x
= *iter
;
7789 switch (GET_CODE (x
))
7791 case SET
: case POST_INC
: case POST_DEC
: case PRE_INC
: case PRE_DEC
:
7794 /* This is also fine for PRE/POST_MODIFY, because they
7798 rtx dest
= XEXP (x
, 0);
7799 /* Check if this sets a an extension register. N.B. we use 61 for the
7800 condition codes, which is definitely not an extension register. */
7801 if (REG_P (dest
) && REGNO (dest
) >= 32 && REGNO (dest
) < 61
7802 /* Check if the same register is used by the PAT. */
7803 && (refers_to_regno_p
7805 REGNO (dest
) + (GET_MODE_SIZE (GET_MODE (dest
)) + 3) / 4U,
7806 PATTERN (succ
), 0)))
7813 A write to a core reg greater or equal to 32 must not be immediately
7814 followed by a use. Anticipate the length requirement to insert a nop
7815 between PRED and SUCC to prevent a hazard. */
7818 arc_hazard (rtx_insn
*pred
, rtx_insn
*succ
)
7820 if (!pred
|| !INSN_P (pred
) || !succ
|| !INSN_P (succ
))
7824 return arc600_corereg_hazard (pred
, succ
);
7829 /* When compiling for release 310a, insert a nop before any
7830 conditional jump. */
7833 arc_check_release31a (rtx_insn
*pred
, rtx_insn
*succ
)
7835 if (!pred
|| !INSN_P (pred
) || !succ
|| !INSN_P (succ
))
7838 if (!JUMP_P (pred
) && !single_set (pred
))
7841 if (!JUMP_P (succ
) && !single_set (succ
))
7844 if (TARGET_HS
&& (arc_tune
== ARC_TUNE_ARCHS4X_REL31A
))
7845 switch (get_attr_type (pred
))
7848 switch (get_attr_type (succ
))
7851 case TYPE_BRCC_NO_DELAY_SLOT
:
7859 case TYPE_BRCC_NO_DELAY_SLOT
:
7861 if (get_attr_type (succ
) == TYPE_STORE
)
7871 /* The same functionality as arc_hazard. It is called in machine
7872 reorg before any other optimization. Hence, the NOP size is taken
7873 into account when doing branch shortening. */
7876 workaround_arc_anomaly (void)
7878 rtx_insn
*insn
, *succ0
;
7880 /* For any architecture: call arc_hazard here. */
7881 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
7883 succ0
= next_real_insn (insn
);
7884 if (arc_hazard (insn
, succ0
) || arc_check_release31a (insn
, succ0
))
7885 emit_insn_before (gen_nopv (), succ0
);
7891 /* Old A7 are suffering of a cache hazard, and we need to insert two
7892 nops between any sequence of stores and a load. */
7893 if (arc_tune
!= ARC_TUNE_ARC7XX
)
7894 check_store_cacheline_hazard ();
7897 /* A callback for the hw-doloop pass. Called when a loop we have discovered
7898 turns out not to be optimizable; we have to split the loop_end pattern into
7899 a subtract and a test. */
7902 hwloop_fail (hwloop_info loop
)
7905 rtx insn
= loop
->loop_end
;
7908 && (loop
->length
&& (loop
->length
<= ARC_MAX_LOOP_LENGTH
))
7909 && REG_P (loop
->iter_reg
))
7911 /* TARGET_V2 core3 has dbnz instructions. */
7912 test
= gen_dbnz (loop
->iter_reg
, loop
->start_label
);
7913 insn
= emit_jump_insn_before (test
, loop
->loop_end
);
7915 else if (REG_P (loop
->iter_reg
) && (REGNO (loop
->iter_reg
) == LP_COUNT
))
7917 /* We have the lp_count as loop iterator, try to use it. */
7918 emit_insn_before (gen_loop_fail (), loop
->loop_end
);
7919 test
= gen_rtx_NE (VOIDmode
, gen_rtx_REG (CC_ZNmode
, CC_REG
),
7921 test
= gen_rtx_IF_THEN_ELSE (VOIDmode
, test
,
7922 gen_rtx_LABEL_REF (Pmode
, loop
->start_label
),
7924 insn
= emit_jump_insn_before (gen_rtx_SET (pc_rtx
, test
),
7929 emit_insn_before (gen_addsi3 (loop
->iter_reg
,
7933 test
= gen_rtx_NE (VOIDmode
, loop
->iter_reg
, const0_rtx
);
7934 insn
= emit_jump_insn_before (gen_cbranchsi4 (test
,
7940 JUMP_LABEL (insn
) = loop
->start_label
;
7941 LABEL_NUSES (loop
->start_label
)++;
7942 delete_insn (loop
->loop_end
);
7945 /* Return the next insn after INSN that is not a NOTE, but stop the
7946 search before we enter another basic block. This routine does not
7947 look inside SEQUENCEs. */
7950 next_nonnote_insn_bb (rtx_insn
*insn
)
7954 insn
= NEXT_INSN (insn
);
7955 if (insn
== 0 || !NOTE_P (insn
))
7957 if (NOTE_INSN_BASIC_BLOCK_P (insn
))
7964 /* Optimize LOOP. */
7967 hwloop_optimize (hwloop_info loop
)
7971 basic_block entry_bb
, bb
;
7973 rtx_insn
*insn
, *seq
, *entry_after
, *last_insn
, *end_label
;
7974 unsigned int length
;
7975 bool need_fix
= false;
7976 rtx lp_reg
= gen_rtx_REG (SImode
, LP_COUNT
);
7978 if (loop
->depth
> 1)
7981 fprintf (dump_file
, ";; loop %d is not innermost\n",
7986 if (!loop
->incoming_dest
)
7989 fprintf (dump_file
, ";; loop %d has more than one entry\n",
7994 if (loop
->incoming_dest
!= loop
->head
)
7997 fprintf (dump_file
, ";; loop %d is not entered from head\n",
8002 if (loop
->has_call
|| loop
->has_asm
)
8005 fprintf (dump_file
, ";; loop %d has invalid insn\n",
8010 /* Scan all the blocks to make sure they don't use iter_reg. */
8011 if (loop
->iter_reg_used
|| loop
->iter_reg_used_outside
)
8014 fprintf (dump_file
, ";; loop %d uses iterator\n",
8019 /* Check if start_label appears before doloop_end. */
8021 for (insn
= loop
->start_label
;
8022 insn
&& insn
!= loop
->loop_end
;
8023 insn
= NEXT_INSN (insn
))
8025 length
+= NONDEBUG_INSN_P (insn
) ? get_attr_length (insn
) : 0;
8026 if (JUMP_TABLES_IN_TEXT_SECTION
8027 && JUMP_TABLE_DATA_P (insn
))
8030 fprintf (dump_file
, ";; loop %d has a jump table\n",
8039 fprintf (dump_file
, ";; loop %d start_label not before loop_end\n",
8044 loop
->length
= length
;
8045 if (loop
->length
> ARC_MAX_LOOP_LENGTH
)
8048 fprintf (dump_file
, ";; loop %d too long\n", loop
->loop_no
);
8051 else if (!loop
->length
)
8054 fprintf (dump_file
, ";; loop %d is empty\n", loop
->loop_no
);
8058 /* Check if we use a register or not. */
8059 if (!REG_P (loop
->iter_reg
))
8062 fprintf (dump_file
, ";; loop %d iterator is MEM\n",
8067 /* Check if we use a register or not. */
8068 if (!REG_P (loop
->iter_reg
))
8071 fprintf (dump_file
, ";; loop %d iterator is MEM\n",
8076 /* Check if loop register is lpcount. */
8077 if (REG_P (loop
->iter_reg
) && (REGNO (loop
->iter_reg
)) != LP_COUNT
)
8080 fprintf (dump_file
, ";; loop %d doesn't use lp_count as loop"
8083 /* This loop doesn't use the lp_count, check though if we can
8085 if (TEST_HARD_REG_BIT (loop
->regs_set_in_loop
, LP_COUNT
)
8086 /* In very unique cases we may have LP_COUNT alive. */
8087 || (loop
->incoming_src
8088 && REGNO_REG_SET_P (df_get_live_out (loop
->incoming_src
),
8092 fprintf (dump_file
, ";; loop %d, lp_count is alive", loop
->loop_no
);
8099 /* Check for control like instruction as the last instruction of a
8102 last_insn
= PREV_INSN (loop
->loop_end
);
8106 for (; last_insn
!= BB_HEAD (bb
);
8107 last_insn
= PREV_INSN (last_insn
))
8108 if (NONDEBUG_INSN_P (last_insn
))
8111 if (last_insn
!= BB_HEAD (bb
))
8114 if (single_pred_p (bb
)
8115 && single_pred_edge (bb
)->flags
& EDGE_FALLTHRU
8116 && single_pred (bb
) != ENTRY_BLOCK_PTR_FOR_FN (cfun
))
8118 bb
= single_pred (bb
);
8119 last_insn
= BB_END (bb
);
8132 fprintf (dump_file
, ";; loop %d has no last instruction\n",
8137 if ((TARGET_ARC600_FAMILY
|| TARGET_HS
)
8138 && INSN_P (last_insn
)
8139 && (JUMP_P (last_insn
) || CALL_P (last_insn
)
8140 || GET_CODE (PATTERN (last_insn
)) == SEQUENCE
8141 /* At this stage we can have (insn (clobber (mem:BLK
8142 (reg)))) instructions, ignore them. */
8143 || (GET_CODE (PATTERN (last_insn
)) != CLOBBER
8144 && (get_attr_type (last_insn
) == TYPE_BRCC
8145 || get_attr_type (last_insn
) == TYPE_BRCC_NO_DELAY_SLOT
))))
8147 if (loop
->length
+ 2 > ARC_MAX_LOOP_LENGTH
)
8150 fprintf (dump_file
, ";; loop %d too long\n", loop
->loop_no
);
8154 fprintf (dump_file
, ";; loop %d has a control like last insn; "
8158 last_insn
= emit_insn_after (gen_nopv (), last_insn
);
8161 if (LABEL_P (last_insn
))
8164 fprintf (dump_file
, ";; loop %d has a label as last insn; "
8167 last_insn
= emit_insn_after (gen_nopv (), last_insn
);
8170 /* SAVE_NOTE is used by haifa scheduler. However, we are after it
8171 and we can use it to indicate the last ZOL instruction cannot be
8172 part of a delay slot. */
8173 add_reg_note (last_insn
, REG_SAVE_NOTE
, GEN_INT (2));
8175 loop
->last_insn
= last_insn
;
8177 /* Get the loop iteration register. */
8178 iter_reg
= loop
->iter_reg
;
8180 gcc_assert (REG_P (iter_reg
));
8184 FOR_EACH_VEC_SAFE_ELT (loop
->incoming
, i
, entry_edge
)
8185 if (entry_edge
->flags
& EDGE_FALLTHRU
)
8188 if (entry_edge
== NULL
)
8191 fprintf (dump_file
, ";; loop %d has no fallthru edge jumping "
8196 /* The loop is good. */
8197 end_label
= gen_label_rtx ();
8198 loop
->end_label
= end_label
;
8200 /* Place the zero_cost_loop_start instruction before the loop. */
8201 entry_bb
= entry_edge
->src
;
8207 /* The loop uses a R-register, but the lp_count is free, thus
8209 emit_insn (gen_rtx_SET (lp_reg
, iter_reg
));
8210 SET_HARD_REG_BIT (loop
->regs_set_in_loop
, LP_COUNT
);
8214 fprintf (dump_file
, ";; fix loop %d to use lp_count\n",
8219 insn
= emit_insn (gen_arc_lp (loop
->start_label
,
8225 entry_after
= BB_END (entry_bb
);
8226 if (!single_succ_p (entry_bb
) || vec_safe_length (loop
->incoming
) > 1
8233 emit_insn_before (seq
, BB_HEAD (loop
->head
));
8234 seq
= emit_label_before (gen_label_rtx (), seq
);
8235 new_bb
= create_basic_block (seq
, insn
, entry_bb
);
8236 FOR_EACH_EDGE (e
, ei
, loop
->incoming
)
8238 if (!(e
->flags
& EDGE_FALLTHRU
))
8239 redirect_edge_and_branch_force (e
, new_bb
);
8241 redirect_edge_succ (e
, new_bb
);
8244 make_edge (new_bb
, loop
->head
, 0);
8249 while (DEBUG_INSN_P (entry_after
)
8250 || (NOTE_P (entry_after
)
8251 && NOTE_KIND (entry_after
) != NOTE_INSN_BASIC_BLOCK
8252 /* Make sure we don't split a call and its corresponding
8253 CALL_ARG_LOCATION note. */
8254 && NOTE_KIND (entry_after
) != NOTE_INSN_CALL_ARG_LOCATION
))
8255 entry_after
= NEXT_INSN (entry_after
);
8257 entry_after
= next_nonnote_insn_bb (entry_after
);
8259 gcc_assert (entry_after
);
8260 emit_insn_before (seq
, entry_after
);
8263 /* Insert the loop end label before the last instruction of the
8265 emit_label_after (end_label
, loop
->last_insn
);
8266 /* Make sure we mark the begining and end label as used. */
8267 LABEL_NUSES (loop
->end_label
)++;
8268 LABEL_NUSES (loop
->start_label
)++;
8273 /* A callback for the hw-doloop pass. This function examines INSN; if
8274 it is a loop_end pattern we recognize, return the reg rtx for the
8275 loop counter. Otherwise, return NULL_RTX. */
8278 hwloop_pattern_reg (rtx_insn
*insn
)
8282 if (!JUMP_P (insn
) || recog_memoized (insn
) != CODE_FOR_loop_end
)
8285 reg
= SET_DEST (XVECEXP (PATTERN (insn
), 0, 1));
8291 static struct hw_doloop_hooks arc_doloop_hooks
=
8298 /* Run from machine_dependent_reorg, this pass looks for doloop_end insns
8299 and tries to rewrite the RTL of these loops so that proper Blackfin
8300 hardware loops are generated. */
8303 arc_reorg_loops (void)
8305 reorg_loops (true, &arc_doloop_hooks
);
8308 /* Scan all calls and add symbols to be emitted in the jli section if
8312 jli_call_scan (void)
8316 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
8321 rtx pat
= PATTERN (insn
);
8322 if (GET_CODE (pat
) == COND_EXEC
)
8323 pat
= COND_EXEC_CODE (pat
);
8324 pat
= XVECEXP (pat
, 0, 0);
8325 if (GET_CODE (pat
) == SET
)
8326 pat
= SET_SRC (pat
);
8328 pat
= XEXP (XEXP (pat
, 0), 0);
8329 if (GET_CODE (pat
) == SYMBOL_REF
8330 && arc_is_jli_call_p (pat
))
8331 arc_add_jli_section (pat
);
8335 /* Add padding if necessary to avoid a mispredict. A return could
8336 happen immediately after the function start. A call/return and
8337 return/return must be 6 bytes apart to avoid mispredict. */
8345 if (!TARGET_PAD_RETURN
)
8348 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
8350 rtx_insn
*prev0
= prev_active_insn (insn
);
8351 bool wantlong
= false;
8353 if (!INSN_P (insn
) || GET_CODE (PATTERN (insn
)) != SIMPLE_RETURN
)
8358 prev0
= emit_insn_before (gen_nopv (), insn
);
8359 /* REG_SAVE_NOTE is used by Haifa scheduler, we are in reorg
8360 so it is safe to reuse it for forcing a particular length
8361 for an instruction. */
8362 add_reg_note (prev0
, REG_SAVE_NOTE
, GEN_INT (1));
8363 emit_insn_before (gen_nopv (), insn
);
8366 offset
= get_attr_length (prev0
);
8368 if (get_attr_length (prev0
) == 2
8369 && get_attr_iscompact (prev0
) != ISCOMPACT_TRUE
)
8371 /* Force long version of the insn. */
8376 rtx_insn
*prev
= prev_active_insn (prev0
);
8378 offset
+= get_attr_length (prev
);
8380 prev
= prev_active_insn (prev
);
8382 offset
+= get_attr_length (prev
);
8387 prev
= emit_insn_before (gen_nopv (), insn
);
8388 add_reg_note (prev
, REG_SAVE_NOTE
, GEN_INT (1));
8391 emit_insn_before (gen_nopv (), insn
);
8398 add_reg_note (prev0
, REG_SAVE_NOTE
, GEN_INT (1));
8400 /* Emit a blockage to avoid delay slot scheduling. */
8401 emit_insn_before (gen_blockage (), insn
);
8405 static int arc_reorg_in_progress
= 0;
8407 /* ARC's machince specific reorg function. */
8418 cfun
->machine
->arc_reorg_started
= 1;
8419 arc_reorg_in_progress
= 1;
8421 compute_bb_for_insn ();
8425 /* Doloop optimization. */
8428 workaround_arc_anomaly ();
8432 /* There are cases when conditional execution is only possible after
8433 delay slot scheduling:
8435 - If a delay slot is filled with a nocond/set insn from above, the previous
8436 basic block can become elegible for conditional execution.
8437 - If a delay slot is filled with a nocond insn from the fall-through path,
8438 the branch with that delay slot can become eligble for conditional
8439 execution (however, with the same sort of data flow analysis that dbr
8440 does, we could have figured out before that we don't need to
8441 conditionalize this insn.)
8442 - If a delay slot insn is filled with an insn from the target, the
8443 target label gets its uses decremented (even deleted if falling to zero),
8444 thus possibly creating more condexec opportunities there.
8445 Therefore, we should still be prepared to apply condexec optimization on
8446 non-prepared branches if the size increase of conditionalized insns is no
8447 more than the size saved from eliminating the branch. An invocation option
8448 could also be used to reserve a bit of extra size for condbranches so that
8449 this'll work more often (could also test in arc_reorg if the block is
8450 'close enough' to be eligible for condexec to make this likely, and
8451 estimate required size increase). */
8452 /* Generate BRcc insns, by combining cmp and Bcc insns wherever possible. */
8453 if (TARGET_NO_BRCC_SET
)
8458 init_insn_lengths();
8461 /* Call shorten_branches to calculate the insn lengths. */
8462 shorten_branches (get_insns());
8464 if (!INSN_ADDRESSES_SET_P())
8465 fatal_error (input_location
,
8466 "insn addresses not set after shorten branches");
8468 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
8471 enum attr_type insn_type
;
8473 /* If a non-jump insn (or a casesi jump table), continue. */
8474 if (GET_CODE (insn
) != JUMP_INSN
||
8475 GET_CODE (PATTERN (insn
)) == ADDR_VEC
8476 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
8479 /* If we already have a brcc, note if it is suitable for brcc_s.
8480 Be a bit generous with the brcc_s range so that we can take
8481 advantage of any code shortening from delay slot scheduling. */
8482 if (recog_memoized (insn
) == CODE_FOR_cbranchsi4_scratch
)
8484 rtx pat
= PATTERN (insn
);
8485 rtx op
= XEXP (SET_SRC (XVECEXP (pat
, 0, 0)), 0);
8486 rtx
*ccp
= &XEXP (XVECEXP (pat
, 0, 1), 0);
8488 offset
= branch_dest (insn
) - INSN_ADDRESSES (INSN_UID (insn
));
8489 if ((offset
>= -140 && offset
< 140)
8490 && rtx_equal_p (XEXP (op
, 1), const0_rtx
)
8491 && compact_register_operand (XEXP (op
, 0), VOIDmode
)
8492 && equality_comparison_operator (op
, VOIDmode
))
8493 PUT_MODE (*ccp
, CC_Zmode
);
8494 else if (GET_MODE (*ccp
) == CC_Zmode
)
8495 PUT_MODE (*ccp
, CC_ZNmode
);
8498 if ((insn_type
= get_attr_type (insn
)) == TYPE_BRCC
8499 || insn_type
== TYPE_BRCC_NO_DELAY_SLOT
)
8502 /* OK. so we have a jump insn. */
8503 /* We need to check that it is a bcc. */
8504 /* Bcc => set (pc) (if_then_else ) */
8505 pattern
= PATTERN (insn
);
8506 if (GET_CODE (pattern
) != SET
8507 || GET_CODE (SET_SRC (pattern
)) != IF_THEN_ELSE
8508 || ANY_RETURN_P (XEXP (SET_SRC (pattern
), 1)))
8511 /* Now check if the jump is beyond the s9 range. */
8512 if (CROSSING_JUMP_P (insn
))
8514 offset
= branch_dest (insn
) - INSN_ADDRESSES (INSN_UID (insn
));
8516 if(offset
> 253 || offset
< -254)
8519 pc_target
= SET_SRC (pattern
);
8521 /* Avoid FPU instructions. */
8522 if ((GET_MODE (XEXP (XEXP (pc_target
, 0), 0)) == CC_FPUmode
)
8523 || (GET_MODE (XEXP (XEXP (pc_target
, 0), 0)) == CC_FPUEmode
)
8524 || (GET_MODE (XEXP (XEXP (pc_target
, 0), 0)) == CC_FPU_UNEQmode
))
8527 /* Now go back and search for the set cc insn. */
8529 label
= XEXP (pc_target
, 1);
8533 rtx_insn
*scan
, *link_insn
= NULL
;
8535 for (scan
= PREV_INSN (insn
);
8536 scan
&& GET_CODE (scan
) != CODE_LABEL
;
8537 scan
= PREV_INSN (scan
))
8539 if (! INSN_P (scan
))
8541 pat
= PATTERN (scan
);
8542 if (GET_CODE (pat
) == SET
8543 && cc_register (SET_DEST (pat
), VOIDmode
))
8553 /* Check if this is a data dependency. */
8554 rtx op
, cc_clob_rtx
, op0
, op1
, brcc_insn
, note
;
8557 /* Make sure we can use it for brcc insns. */
8558 if (find_reg_note (link_insn
, REG_SAVE_NOTE
, GEN_INT (3)))
8561 /* Ok this is the set cc. copy args here. */
8562 op
= XEXP (pc_target
, 0);
8564 op0
= cmp0
= XEXP (SET_SRC (pat
), 0);
8565 op1
= cmp1
= XEXP (SET_SRC (pat
), 1);
8566 if (GET_CODE (op0
) == ZERO_EXTRACT
8567 && XEXP (op0
, 1) == const1_rtx
8568 && (GET_CODE (op
) == EQ
8569 || GET_CODE (op
) == NE
))
8571 /* btst / b{eq,ne} -> bbit{0,1} */
8572 op0
= XEXP (cmp0
, 0);
8573 op1
= XEXP (cmp0
, 2);
8575 else if (!register_operand (op0
, VOIDmode
)
8576 || !general_operand (op1
, VOIDmode
))
8578 /* Be careful not to break what cmpsfpx_raw is
8579 trying to create for checking equality of
8580 single-precision floats. */
8581 else if (TARGET_SPFP
8582 && GET_MODE (op0
) == SFmode
8583 && GET_MODE (op1
) == SFmode
)
8586 /* None of the two cmp operands should be set between the
8587 cmp and the branch. */
8588 if (reg_set_between_p (op0
, link_insn
, insn
))
8591 if (reg_set_between_p (op1
, link_insn
, insn
))
8594 /* Since the MODE check does not work, check that this is
8595 CC reg's last set location before insn, and also no
8596 instruction between the cmp and branch uses the
8598 if ((reg_set_between_p (SET_DEST (pat
), link_insn
, insn
))
8599 || (reg_used_between_p (SET_DEST (pat
), link_insn
, insn
)))
8602 /* CC reg should be dead after insn. */
8603 if (!find_regno_note (insn
, REG_DEAD
, CC_REG
))
8606 op
= gen_rtx_fmt_ee (GET_CODE (op
),
8607 GET_MODE (op
), cmp0
, cmp1
);
8608 /* If we create a LIMM where there was none before,
8609 we only benefit if we can avoid a scheduling bubble
8610 for the ARC600. Otherwise, we'd only forgo chances
8611 at short insn generation, and risk out-of-range
8613 if (!brcc_nolimm_operator (op
, VOIDmode
)
8614 && !long_immediate_operand (op1
, VOIDmode
)
8616 || (TARGET_V2
&& optimize_size
)
8617 || next_active_insn (link_insn
) != insn
))
8620 /* Emit bbit / brcc (or brcc_s if possible).
8621 CC_Zmode indicates that brcc_s is possible. */
8624 cc_clob_rtx
= gen_rtx_REG (CC_ZNmode
, CC_REG
);
8625 else if ((offset
>= -140 && offset
< 140)
8626 && rtx_equal_p (op1
, const0_rtx
)
8627 && compact_register_operand (op0
, VOIDmode
)
8628 && (GET_CODE (op
) == EQ
8629 || GET_CODE (op
) == NE
))
8630 cc_clob_rtx
= gen_rtx_REG (CC_Zmode
, CC_REG
);
8632 cc_clob_rtx
= gen_rtx_REG (CCmode
, CC_REG
);
8635 = gen_rtx_IF_THEN_ELSE (VOIDmode
, op
, label
, pc_rtx
);
8636 brcc_insn
= gen_rtx_SET (pc_rtx
, brcc_insn
);
8637 cc_clob_rtx
= gen_rtx_CLOBBER (VOIDmode
, cc_clob_rtx
);
8640 (VOIDmode
, gen_rtvec (2, brcc_insn
, cc_clob_rtx
));
8641 brcc_insn
= emit_jump_insn_before (brcc_insn
, insn
);
8643 JUMP_LABEL (brcc_insn
) = JUMP_LABEL (insn
);
8644 note
= find_reg_note (insn
, REG_BR_PROB
, 0);
8647 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
8648 REG_NOTES (brcc_insn
) = note
;
8650 note
= find_reg_note (link_insn
, REG_DEAD
, op0
);
8653 remove_note (link_insn
, note
);
8654 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
8655 REG_NOTES (brcc_insn
) = note
;
8657 note
= find_reg_note (link_insn
, REG_DEAD
, op1
);
8660 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
8661 REG_NOTES (brcc_insn
) = note
;
8666 /* Delete the bcc insn. */
8667 set_insn_deleted (insn
);
8669 /* Delete the cmp insn. */
8670 set_insn_deleted (link_insn
);
8675 /* Clear out insn_addresses. */
8676 INSN_ADDRESSES_FREE ();
8680 if (INSN_ADDRESSES_SET_P())
8681 fatal_error (input_location
, "insn addresses not freed");
8683 arc_reorg_in_progress
= 0;
8686 /* Check if the operands are valid for BRcc.d generation
8687 Valid Brcc.d patterns are
8691 For cc={GT, LE, GTU, LEU}, u6=63 cannot be allowed,
8692 since they are encoded by the assembler as {GE, LT, HS, LS} 64, which
8693 does not have a delay slot
8695 Assumed precondition: Second operand is either a register or a u6 value. */
8698 valid_brcc_with_delay_p (rtx
*operands
)
8700 if (optimize_size
&& GET_MODE (operands
[4]) == CC_Zmode
)
8702 return brcc_nolimm_operator (operands
[0], VOIDmode
);
8705 /* Implement TARGET_IN_SMALL_DATA_P. Return true if it would be safe to
8706 access DECL using %gp_rel(...)($gp). */
8709 arc_in_small_data_p (const_tree decl
)
8714 /* Only variables are going into small data area. */
8715 if (TREE_CODE (decl
) != VAR_DECL
)
8718 if (TARGET_NO_SDATA_SET
)
8721 /* Disable sdata references to weak variables. */
8722 if (DECL_WEAK (decl
))
8725 /* Don't put constants into the small data section: we want them to
8726 be in ROM rather than RAM. */
8727 if (TREE_READONLY (decl
))
8730 /* To ensure -mvolatile-cache works ld.di does not have a
8731 gp-relative variant. */
8732 if (!TARGET_VOLATILE_CACHE_SET
8733 && TREE_THIS_VOLATILE (decl
))
8736 /* Likewise for uncached data. */
8737 attr
= TYPE_ATTRIBUTES (TREE_TYPE (decl
));
8738 if (lookup_attribute ("uncached", attr
))
8741 /* and for aux regs. */
8742 attr
= DECL_ATTRIBUTES (decl
);
8743 if (lookup_attribute ("aux", attr
))
8746 if (DECL_SECTION_NAME (decl
) != 0)
8748 const char *name
= DECL_SECTION_NAME (decl
);
8749 if (strcmp (name
, ".sdata") == 0
8750 || strcmp (name
, ".sbss") == 0)
8753 /* If it's not public, there's no need to put it in the small data
8755 else if (TREE_PUBLIC (decl
))
8757 size
= int_size_in_bytes (TREE_TYPE (decl
));
8758 return (size
> 0 && size
<= g_switch_value
);
8763 /* Return true if OP is an acceptable memory operand for ARCompact
8764 16-bit gp-relative load instructions.
8766 /* volatile cache option still to be handled. */
8769 compact_sda_memory_operand (rtx op
, machine_mode mode
, bool short_p
)
8776 /* Eliminate non-memory operations. */
8777 if (GET_CODE (op
) != MEM
)
8780 if (mode
== VOIDmode
)
8781 mode
= GET_MODE (op
);
8783 size
= GET_MODE_SIZE (mode
);
8785 /* dword operations really put out 2 instructions, so eliminate them. */
8786 if (size
> UNITS_PER_WORD
)
8789 /* Decode the address now. */
8790 addr
= XEXP (op
, 0);
8792 if (!legitimate_small_data_address_p (addr
, mode
))
8795 if (!short_p
|| size
== 1)
8798 /* Now check for the alignment, the short loads using gp require the
8799 addresses to be aligned. */
8800 align
= get_symbol_alignment (addr
);
8811 if (align
&& ((align
& mask
) == 0))
8816 /* Return TRUE if PAT is accessing an aux-reg. */
8819 arc_is_aux_reg_p (rtx pat
)
8821 tree attrs
= NULL_TREE
;
8827 /* Get the memory attributes. */
8828 addr
= MEM_EXPR (pat
);
8832 /* Get the attributes. */
8834 attrs
= DECL_ATTRIBUTES (addr
);
8835 else if (TREE_CODE (addr
) == MEM_REF
)
8836 attrs
= TYPE_ATTRIBUTES (TREE_TYPE (TREE_OPERAND (addr
, 0)));
8840 if (lookup_attribute ("aux", attrs
))
8845 /* Implement ASM_OUTPUT_ALIGNED_DECL_LOCAL. */
8848 arc_asm_output_aligned_decl_local (FILE * stream
, tree decl
, const char * name
,
8849 unsigned HOST_WIDE_INT size
,
8850 unsigned HOST_WIDE_INT align
,
8851 unsigned HOST_WIDE_INT globalize_p
)
8853 int in_small_data
= arc_in_small_data_p (decl
);
8854 rtx mem
= decl
== NULL_TREE
? NULL_RTX
: DECL_RTL (decl
);
8856 /* Don't output aux-reg symbols. */
8857 if (mem
!= NULL_RTX
&& MEM_P (mem
)
8858 && SYMBOL_REF_P (XEXP (mem
, 0))
8859 && arc_is_aux_reg_p (mem
))
8863 switch_to_section (get_named_section (NULL
, ".sbss", 0));
8864 /* named_section (0,".sbss",0); */
8866 switch_to_section (bss_section
);
8869 (*targetm
.asm_out
.globalize_label
) (stream
, name
);
8871 ASM_OUTPUT_ALIGN (stream
, floor_log2 ((align
) / BITS_PER_UNIT
));
8872 ASM_OUTPUT_TYPE_DIRECTIVE (stream
, name
, "object");
8873 ASM_OUTPUT_SIZE_DIRECTIVE (stream
, name
, size
);
8874 ASM_OUTPUT_LABEL (stream
, name
);
8877 ASM_OUTPUT_SKIP (stream
, size
);
8881 arc_preserve_reload_p (rtx in
)
8883 return (GET_CODE (in
) == PLUS
8884 && RTX_OK_FOR_BASE_P (XEXP (in
, 0), true)
8885 && CONST_INT_P (XEXP (in
, 1))
8886 && !((INTVAL (XEXP (in
, 1)) & 511)));
8889 /* Implement TARGET_REGISTER_MOVE_COST. */
8892 arc_register_move_cost (machine_mode
,
8893 reg_class_t from_class
, reg_class_t to_class
)
8895 /* Force an attempt to 'mov Dy,Dx' to spill. */
8896 if ((TARGET_ARC700
|| TARGET_EM
) && TARGET_DPFP
8897 && from_class
== DOUBLE_REGS
&& to_class
== DOUBLE_REGS
)
8903 /* Emit code for an addsi3 instruction with OPERANDS.
8904 COND_P indicates if this will use conditional execution.
8905 Return the length of the instruction.
8906 If OUTPUT_P is false, don't actually output the instruction, just return
8909 arc_output_addsi (rtx
*operands
, bool cond_p
, bool output_p
)
8913 int match
= operands_match_p (operands
[0], operands
[1]);
8914 int match2
= operands_match_p (operands
[0], operands
[2]);
8915 int intval
= (REG_P (operands
[2]) ? 1
8916 : CONST_INT_P (operands
[2]) ? INTVAL (operands
[2]) : 0xbadc057);
8917 int neg_intval
= -intval
;
8918 int short_0
= arc_check_short_reg_p (operands
[0]);
8919 int short_p
= (!cond_p
&& short_0
&& arc_check_short_reg_p (operands
[1]));
8922 #define REG_H_P(OP) (REG_P (OP) && ((TARGET_V2 && REGNO (OP) <= 31 \
8923 && REGNO (OP) != 30) \
8926 #define ADDSI_OUTPUT1(FORMAT) do {\
8928 output_asm_insn (FORMAT, operands);\
8931 #define ADDSI_OUTPUT(LIST) do {\
8934 ADDSI_OUTPUT1 (format);\
8938 /* First try to emit a 16 bit insn. */
8941 /* If we are actually about to output this insn, don't try a 16 bit
8942 variant if we already decided that we don't want that
8943 (I.e. we upsized this insn to align some following insn.)
8944 E.g. add_s r0,sp,70 is 16 bit, but add r0,sp,70 requires a LIMM -
8945 but add1 r0,sp,35 doesn't. */
8946 && (!output_p
|| (get_attr_length (current_output_insn
) & 2)))
8948 /* Generate add_s a,b,c; add_s b,b,u7; add_s c,b,u3; add_s b,b,h
8951 && ((REG_H_P (operands
[2])
8952 && (match
|| arc_check_short_reg_p (operands
[2])))
8953 || (CONST_INT_P (operands
[2])
8954 && ((unsigned) intval
<= (match
? 127 : 7)))))
8955 ADDSI_OUTPUT1 ("add%? %0,%1,%2 ;1");
8957 /* Generate add_s b,b,h patterns. */
8958 if (short_0
&& match2
&& REG_H_P (operands
[1]))
8959 ADDSI_OUTPUT1 ("add%? %0,%2,%1 ;2");
8961 /* Generate add_s b,sp,u7; add_s sp,sp,u7 patterns. */
8962 if ((short_0
|| REGNO (operands
[0]) == STACK_POINTER_REGNUM
)
8963 && REGNO (operands
[1]) == STACK_POINTER_REGNUM
&& !(intval
& ~124))
8964 ADDSI_OUTPUT1 ("add%? %0,%1,%2 ;3");
8966 if ((short_p
&& (unsigned) neg_intval
<= (match
? 31 : 7))
8967 || (REGNO (operands
[0]) == STACK_POINTER_REGNUM
8968 && match
&& !(neg_intval
& ~124)))
8969 ADDSI_OUTPUT1 ("sub%? %0,%1,%n2 ;4");
8971 /* Generate add_s h,h,s3 patterns. */
8972 if (REG_H_P (operands
[0]) && match
&& TARGET_V2
8973 && CONST_INT_P (operands
[2]) && ((intval
>= -1) && (intval
<= 6)))
8974 ADDSI_OUTPUT1 ("add%? %0,%1,%2 ;5");
8976 /* Generate add_s r0,b,u6; add_s r1,b,u6 patterns. */
8977 if (TARGET_CODE_DENSITY
&& REG_P (operands
[0]) && REG_P (operands
[1])
8978 && ((REGNO (operands
[0]) == 0) || (REGNO (operands
[0]) == 1))
8979 && arc_check_short_reg_p (operands
[1])
8980 && satisfies_constraint_L (operands
[2]))
8981 ADDSI_OUTPUT1 ("add%? %0,%1,%2 ;6");
8984 /* Now try to emit a 32 bit insn without long immediate. */
8986 if (!match
&& match2
&& REG_P (operands
[1]))
8987 ADDSI_OUTPUT1 ("add%? %0,%2,%1");
8988 if (match
|| !cond_p
)
8990 int limit
= (match
&& !cond_p
) ? 0x7ff : 0x3f;
8991 int range_factor
= neg_intval
& intval
;
8994 if (intval
== (HOST_WIDE_INT
) (HOST_WIDE_INT_M1U
<< 31))
8995 ADDSI_OUTPUT1 ("bxor%? %0,%1,31");
8997 /* If we can use a straight add / sub instead of a {add,sub}[123] of
8998 same size, do, so - the insn latency is lower. */
8999 /* -0x800 is a 12-bit constant for add /add3 / sub / sub3, but
9001 if ((intval
>= 0 && intval
<= limit
)
9002 || (intval
== -0x800 && limit
== 0x7ff))
9003 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
9004 else if ((intval
< 0 && neg_intval
<= limit
)
9005 || (intval
== 0x800 && limit
== 0x7ff))
9006 ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
9007 shift
= range_factor
>= 8 ? 3 : (range_factor
>> 1);
9008 gcc_assert (shift
== 0 || shift
== 1 || shift
== 2 || shift
== 3);
9009 gcc_assert ((((1 << shift
) - 1) & intval
) == 0);
9010 if (((intval
< 0 && intval
!= -0x4000)
9011 /* sub[123] is slower than add_s / sub, only use it if it
9012 avoids a long immediate. */
9013 && neg_intval
<= limit
<< shift
)
9014 || (intval
== 0x4000 && limit
== 0x7ff))
9015 ADDSI_OUTPUT ((format
, "sub%d%%? %%0,%%1,%d",
9016 shift
, neg_intval
>> shift
));
9017 else if ((intval
>= 0 && intval
<= limit
<< shift
)
9018 || (intval
== -0x4000 && limit
== 0x7ff))
9019 ADDSI_OUTPUT ((format
, "add%d%%? %%0,%%1,%d", shift
, intval
>> shift
));
9021 /* Try to emit a 16 bit opcode with long immediate. */
9023 if (short_p
&& match
)
9024 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
9026 /* We have to use a 32 bit opcode, and with a long immediate. */
9028 ADDSI_OUTPUT1 (intval
< 0 ? "sub%? %0,%1,%n2" : "add%? %0,%1,%2");
9031 /* Emit code for an commutative_cond_exec instruction with OPERANDS.
9032 Return the length of the instruction.
9033 If OUTPUT_P is false, don't actually output the instruction, just return
9036 arc_output_commutative_cond_exec (rtx
*operands
, bool output_p
)
9038 enum rtx_code commutative_op
= GET_CODE (operands
[3]);
9039 const char *pat
= NULL
;
9041 /* Canonical rtl should not have a constant in the first operand position. */
9042 gcc_assert (!CONSTANT_P (operands
[1]));
9044 switch (commutative_op
)
9047 if (satisfies_constraint_C1p (operands
[2]))
9048 pat
= "bmsk%? %0,%1,%Z2";
9049 else if (satisfies_constraint_C2p (operands
[2]))
9051 operands
[2] = GEN_INT ((~INTVAL (operands
[2])));
9052 pat
= "bmskn%? %0,%1,%Z2";
9054 else if (satisfies_constraint_Ccp (operands
[2]))
9055 pat
= "bclr%? %0,%1,%M2";
9056 else if (satisfies_constraint_CnL (operands
[2]))
9057 pat
= "bic%? %0,%1,%n2-1";
9060 if (satisfies_constraint_C0p (operands
[2]))
9061 pat
= "bset%? %0,%1,%z2";
9064 if (satisfies_constraint_C0p (operands
[2]))
9065 pat
= "bxor%? %0,%1,%z2";
9068 return arc_output_addsi (operands
, true, output_p
);
9072 output_asm_insn (pat
? pat
: "%O3.%d5 %0,%1,%2", operands
);
9073 if (pat
|| REG_P (operands
[2]) || satisfies_constraint_L (operands
[2]))
9078 /* Helper function of arc_expand_cpymem. ADDR points to a chunk of memory.
9079 Emit code and return an potentially modified address such that offsets
9080 up to SIZE are can be added to yield a legitimate address.
9081 if REUSE is set, ADDR is a register that may be modified. */
9084 force_offsettable (rtx addr
, HOST_WIDE_INT size
, bool reuse
)
9087 rtx offs
= const0_rtx
;
9089 if (GET_CODE (base
) == PLUS
)
9091 offs
= XEXP (base
, 1);
9092 base
= XEXP (base
, 0);
9095 || (REGNO (base
) != STACK_POINTER_REGNUM
9096 && REGNO_PTR_FRAME_P (REGNO (base
)))
9097 || !CONST_INT_P (offs
) || !SMALL_INT (INTVAL (offs
))
9098 || !SMALL_INT (INTVAL (offs
) + size
))
9101 emit_insn (gen_add2_insn (addr
, offs
));
9103 addr
= copy_to_mode_reg (Pmode
, addr
);
9108 /* Like move_by_pieces, but take account of load latency, and actual
9109 offset ranges. Return true on success. */
9112 arc_expand_cpymem (rtx
*operands
)
9114 rtx dst
= operands
[0];
9115 rtx src
= operands
[1];
9116 rtx dst_addr
, src_addr
;
9118 int align
= INTVAL (operands
[3]);
9125 if (!CONST_INT_P (operands
[2]))
9127 size
= INTVAL (operands
[2]);
9128 /* move_by_pieces_ninsns is static, so we can't use it. */
9132 n_pieces
= (size
+ 4) / 8U + ((size
>> 1) & 1) + (size
& 1);
9134 n_pieces
= (size
+ 2) / 4U + (size
& 1);
9136 else if (align
== 2)
9137 n_pieces
= (size
+ 1) / 2U;
9140 if (n_pieces
>= (unsigned int) (optimize_size
? 3 : 15))
9142 /* Force 32 bit aligned and larger datum to use 64 bit transfers, if
9144 if (TARGET_LL64
&& (piece
>= 4) && (size
>= 8))
9148 dst_addr
= force_offsettable (XEXP (operands
[0], 0), size
, 0);
9149 src_addr
= force_offsettable (XEXP (operands
[1], 0), size
, 0);
9150 store
[0] = store
[1] = NULL_RTX
;
9151 tmpx
[0] = tmpx
[1] = NULL_RTX
;
9152 for (i
= 0; size
> 0; i
^= 1, size
-= piece
)
9157 while (piece
> size
)
9159 mode
= smallest_int_mode_for_size (piece
* BITS_PER_UNIT
);
9160 /* If we don't re-use temporaries, the scheduler gets carried away,
9161 and the register pressure gets unnecessarily high. */
9162 if (0 && tmpx
[i
] && GET_MODE (tmpx
[i
]) == mode
)
9165 tmpx
[i
] = tmp
= gen_reg_rtx (mode
);
9166 dst_addr
= force_offsettable (dst_addr
, piece
, 1);
9167 src_addr
= force_offsettable (src_addr
, piece
, 1);
9169 emit_insn (store
[i
]);
9170 emit_move_insn (tmp
, change_address (src
, mode
, src_addr
));
9171 store
[i
] = gen_move_insn (change_address (dst
, mode
, dst_addr
), tmp
);
9172 dst_addr
= plus_constant (Pmode
, dst_addr
, piece
);
9173 src_addr
= plus_constant (Pmode
, src_addr
, piece
);
9176 emit_insn (store
[i
]);
9178 emit_insn (store
[i
^1]);
9183 arc_get_aux_arg (rtx pat
, int *auxr
)
9185 tree attr
, addr
= MEM_EXPR (pat
);
9186 if (TREE_CODE (addr
) != VAR_DECL
)
9189 attr
= DECL_ATTRIBUTES (addr
);
9190 if (lookup_attribute ("aux", attr
))
9192 tree arg
= TREE_VALUE (attr
);
9195 *auxr
= TREE_INT_CST_LOW (TREE_VALUE (arg
));
9203 /* Prepare operands for move in MODE. Return true iff the move has
9207 prepare_move_operands (rtx
*operands
, machine_mode mode
)
9209 if ((MEM_P (operands
[0]) || MEM_P (operands
[1]))
9210 && SCALAR_INT_MODE_P (mode
))
9212 /* First handle aux attribute. */
9217 if (MEM_P (operands
[0]) && arc_is_aux_reg_p (operands
[0]))
9219 /* Save operation. */
9220 if (arc_get_aux_arg (operands
[0], &auxr
))
9222 tmp
= gen_reg_rtx (SImode
);
9223 emit_move_insn (tmp
, GEN_INT (auxr
));
9226 tmp
= XEXP (operands
[0], 0);
9228 operands
[1] = force_reg (SImode
, operands
[1]);
9229 emit_insn (gen_rtx_UNSPEC_VOLATILE
9230 (VOIDmode
, gen_rtvec (2, operands
[1], tmp
),
9234 if (MEM_P (operands
[1]) && arc_is_aux_reg_p (operands
[1]))
9236 if (arc_get_aux_arg (operands
[1], &auxr
))
9238 tmp
= gen_reg_rtx (SImode
);
9239 emit_move_insn (tmp
, GEN_INT (auxr
));
9243 tmp
= XEXP (operands
[1], 0);
9244 gcc_assert (GET_CODE (tmp
) == SYMBOL_REF
);
9246 /* Load operation. */
9247 gcc_assert (REG_P (operands
[0]));
9248 emit_insn (gen_rtx_SET (operands
[0],
9249 gen_rtx_UNSPEC_VOLATILE
9250 (SImode
, gen_rtvec (1, tmp
),
9255 /* Second, we check for the uncached. */
9256 if (arc_is_uncached_mem_p (operands
[0]))
9258 if (!REG_P (operands
[1]))
9259 operands
[1] = force_reg (mode
, operands
[1]);
9260 emit_insn (gen_rtx_UNSPEC_VOLATILE
9261 (VOIDmode
, gen_rtvec (2, operands
[0], operands
[1]),
9265 if (arc_is_uncached_mem_p (operands
[1]))
9267 rtx tmp
= operands
[0];
9269 if (MEM_P (operands
[0]))
9270 tmp
= gen_reg_rtx (mode
);
9272 emit_insn (gen_rtx_SET
9274 gen_rtx_UNSPEC_VOLATILE
9275 (mode
, gen_rtvec (1, operands
[1]),
9276 VUNSPEC_ARC_LDDI
)));
9277 if (MEM_P (operands
[0]))
9286 if (GET_CODE (operands
[1]) == SYMBOL_REF
)
9288 enum tls_model model
= SYMBOL_REF_TLS_MODEL (operands
[1]);
9289 if (MEM_P (operands
[0]))
9290 operands
[1] = force_reg (mode
, operands
[1]);
9292 operands
[1] = arc_legitimize_tls_address (operands
[1], model
);
9295 operands
[1] = arc_legitimize_pic_address (operands
[1]);
9297 /* Store instructions are limited, they only accept as address an
9298 immediate, a register or a register plus a small immediate. */
9299 if (MEM_P (operands
[0])
9300 && !move_dest_operand (operands
[0], mode
))
9302 rtx tmp0
= copy_to_mode_reg (Pmode
, XEXP (operands
[0], 0));
9303 rtx tmp1
= change_address (operands
[0], mode
, tmp0
);
9304 MEM_COPY_ATTRIBUTES (tmp1
, operands
[0]);
9308 /* Check if it is constant but it is not legitimized. */
9309 if (CONSTANT_P (operands
[1])
9310 && !arc_legitimate_constant_p (mode
, operands
[1]))
9311 operands
[1] = force_reg (mode
, XEXP (operands
[1], 0));
9312 else if (MEM_P (operands
[0])
9313 && ((CONSTANT_P (operands
[1])
9314 && !satisfies_constraint_Cm3 (operands
[1]))
9315 || MEM_P (operands
[1])))
9316 operands
[1] = force_reg (mode
, operands
[1]);
9321 /* Output a library call to a function called FNAME that has been arranged
9322 to be local to any dso. */
9325 arc_output_libcall (const char *fname
)
9327 unsigned len
= strlen (fname
);
9328 static char buf
[64];
9330 gcc_assert (len
< sizeof buf
- 35);
9331 if (TARGET_LONG_CALLS_SET
)
9334 sprintf (buf
, "add r12,pcl,@%s@pcl\n\tjl%%!%%* [r12]", fname
);
9336 sprintf (buf
, "jl%%! @%s", fname
);
9339 sprintf (buf
, "bl%%!%%* @%s", fname
);
9343 /* Return the SImode highpart of the DImode value IN. */
9346 disi_highpart (rtx in
)
9348 return simplify_gen_subreg (SImode
, in
, DImode
, TARGET_BIG_ENDIAN
? 0 : 4);
9351 /* Given a rtx, check if it is an assembly instruction or not. */
9354 arc_asm_insn_p (rtx x
)
9361 switch (GET_CODE (x
))
9368 return arc_asm_insn_p (SET_SRC (x
));
9372 for (i
= XVECLEN (x
, 0) - 1; i
>= 0; i
--)
9373 j
+= arc_asm_insn_p (XVECEXP (x
, 0, i
));
9385 /* Return length adjustment for INSN. */
9388 arc_adjust_insn_length (rtx_insn
*insn
, int len
, bool)
9392 /* We already handle sequences by ignoring the delay sequence flag. */
9393 if (GET_CODE (PATTERN (insn
)) == SEQUENCE
)
9396 /* Check for return with but one preceding insn since function
9398 if (TARGET_PAD_RETURN
9400 && GET_CODE (PATTERN (insn
)) != ADDR_VEC
9401 && GET_CODE (PATTERN (insn
)) != ADDR_DIFF_VEC
9402 && get_attr_type (insn
) == TYPE_RETURN
)
9404 rtx_insn
*prev
= prev_active_insn (insn
);
9406 if (!prev
|| !(prev
= prev_active_insn (prev
))
9407 || ((NONJUMP_INSN_P (prev
)
9408 && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
9409 ? CALL_ATTR (as_a
<rtx_sequence
*> (PATTERN (prev
))->insn (0),
9411 : CALL_ATTR (prev
, NON_SIBCALL
)))
9416 rtx_insn
*succ
= next_real_insn (insn
);
9418 /* One the ARC600, a write to an extension register must be separated
9420 if (succ
&& INSN_P (succ
))
9421 len
+= arc600_corereg_hazard (insn
, succ
);
9424 /* Restore extracted operands - otherwise splitters like the addsi3_mixed one
9426 extract_constrain_insn_cached (insn
);
9431 /* Return version of PAT conditionalized with COND, which is part of INSN.
9432 ANNULLED indicates if INSN is an annulled delay-slot insn.
9433 Register further changes if necessary. */
9435 conditionalize_nonjump (rtx pat
, rtx cond
, rtx insn
, bool annulled
)
9437 /* For commutative operators, we generally prefer to have
9438 the first source match the destination. */
9439 if (GET_CODE (pat
) == SET
)
9441 rtx src
= SET_SRC (pat
);
9443 if (COMMUTATIVE_P (src
))
9445 rtx src0
= XEXP (src
, 0);
9446 rtx src1
= XEXP (src
, 1);
9447 rtx dst
= SET_DEST (pat
);
9449 if (rtx_equal_p (src1
, dst
) && !rtx_equal_p (src0
, dst
)
9450 /* Leave add_n alone - the canonical form is to
9451 have the complex summand first. */
9453 pat
= gen_rtx_SET (dst
,
9454 gen_rtx_fmt_ee (GET_CODE (src
), GET_MODE (src
),
9459 /* dwarf2out.cc:dwarf2out_frame_debug_expr doesn't know
9460 what to do with COND_EXEC. */
9461 if (RTX_FRAME_RELATED_P (insn
))
9463 /* If this is the delay slot insn of an anulled branch,
9464 dwarf2out.cc:scan_trace understands the anulling semantics
9465 without the COND_EXEC. */
9466 gcc_assert (annulled
);
9467 rtx note
= alloc_reg_note (REG_FRAME_RELATED_EXPR
, pat
,
9469 validate_change (insn
, ®_NOTES (insn
), note
, 1);
9471 pat
= gen_rtx_COND_EXEC (VOIDmode
, cond
, pat
);
9476 /* Find annulled delay insns and convert them to use the appropriate predicate.
9477 This allows branch shortening to size up these insns properly. */
9480 arc_predicate_delay_insns (void)
9482 for (rtx_insn
*insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
9484 rtx pat
, jump
, dlay
, src
, cond
, *patp
;
9487 if (!NONJUMP_INSN_P (insn
)
9488 || GET_CODE (pat
= PATTERN (insn
)) != SEQUENCE
)
9490 jump
= XVECEXP (pat
, 0, 0);
9491 dlay
= XVECEXP (pat
, 0, 1);
9492 if (!JUMP_P (jump
) || !INSN_ANNULLED_BRANCH_P (jump
))
9494 /* If the branch insn does the annulling, leave the delay insn alone. */
9495 if (!TARGET_AT_DBR_CONDEXEC
&& !INSN_FROM_TARGET_P (dlay
))
9497 /* ??? Could also leave DLAY un-conditionalized if its target is dead
9498 on the other path. */
9499 gcc_assert (GET_CODE (PATTERN (jump
)) == SET
);
9500 gcc_assert (SET_DEST (PATTERN (jump
)) == pc_rtx
);
9501 src
= SET_SRC (PATTERN (jump
));
9502 gcc_assert (GET_CODE (src
) == IF_THEN_ELSE
);
9503 cond
= XEXP (src
, 0);
9504 if (XEXP (src
, 2) == pc_rtx
)
9506 else if (XEXP (src
, 1) == pc_rtx
)
9510 if (reverse
!= !INSN_FROM_TARGET_P (dlay
))
9512 machine_mode ccm
= GET_MODE (XEXP (cond
, 0));
9513 enum rtx_code code
= reverse_condition (GET_CODE (cond
));
9514 if (code
== UNKNOWN
|| ccm
== CC_FP_GTmode
|| ccm
== CC_FP_GEmode
)
9515 code
= reverse_condition_maybe_unordered (GET_CODE (cond
));
9517 cond
= gen_rtx_fmt_ee (code
, GET_MODE (cond
),
9518 copy_rtx (XEXP (cond
, 0)),
9519 copy_rtx (XEXP (cond
, 1)));
9522 cond
= copy_rtx (cond
);
9523 patp
= &PATTERN (dlay
);
9525 pat
= conditionalize_nonjump (pat
, cond
, dlay
, true);
9526 validate_change (dlay
, patp
, pat
, 1);
9527 if (!apply_change_group ())
9533 /* For ARC600: If a write to a core reg >=32 appears in a delay slot
9534 (other than of a forward brcc), it creates a hazard when there is a read
9535 of the same register at the branch target. We can't know what is at the
9536 branch target of calls, and for branches, we don't really know before the
9537 end of delay slot scheduling, either. Not only can individual instruction
9538 be hoisted out into a delay slot, a basic block can also be emptied this
9539 way, and branch and/or fall through targets be redirected. Hence we don't
9540 want such writes in a delay slot. */
9542 /* Return nonzreo iff INSN writes to an extension core register. */
9545 arc_write_ext_corereg (rtx insn
)
9547 subrtx_iterator::array_type array
;
9548 FOR_EACH_SUBRTX (iter
, array
, PATTERN (insn
), NONCONST
)
9550 const_rtx x
= *iter
;
9551 switch (GET_CODE (x
))
9553 case SET
: case POST_INC
: case POST_DEC
: case PRE_INC
: case PRE_DEC
:
9556 /* This is also fine for PRE/POST_MODIFY, because they
9560 const_rtx dest
= XEXP (x
, 0);
9561 if (REG_P (dest
) && REGNO (dest
) >= 32 && REGNO (dest
) < 61)
9567 /* This is like the hook, but returns NULL when it can't / won't generate
9568 a legitimate address. */
9571 arc_legitimize_address_0 (rtx x
, rtx oldx ATTRIBUTE_UNUSED
,
9577 if (GET_CODE (addr
) == CONST
)
9578 addr
= XEXP (addr
, 0);
9580 if (GET_CODE (addr
) == PLUS
9581 && CONST_INT_P (XEXP (addr
, 1))
9582 && ((GET_CODE (XEXP (addr
, 0)) == SYMBOL_REF
9583 && !SYMBOL_REF_FUNCTION_P (XEXP (addr
, 0)))
9584 || (REG_P (XEXP (addr
, 0))
9585 && (INTVAL (XEXP (addr
, 1)) & 252))))
9587 HOST_WIDE_INT offs
, upper
;
9588 int size
= GET_MODE_SIZE (mode
);
9590 offs
= INTVAL (XEXP (addr
, 1));
9591 upper
= (offs
+ 256 * size
) & ~511 * size
;
9592 inner
= plus_constant (Pmode
, XEXP (addr
, 0), upper
);
9593 #if 0 /* ??? this produces worse code for EEMBC idctrn01 */
9594 if (GET_CODE (x
) == CONST
)
9595 inner
= gen_rtx_CONST (Pmode
, inner
);
9597 addr
= plus_constant (Pmode
, force_reg (Pmode
, inner
), offs
- upper
);
9600 else if (GET_CODE (addr
) == SYMBOL_REF
&& !SYMBOL_REF_FUNCTION_P (addr
))
9601 x
= force_reg (Pmode
, x
);
9602 if (memory_address_p ((machine_mode
) mode
, x
))
9608 arc_legitimize_address (rtx orig_x
, rtx oldx
, machine_mode mode
)
9610 rtx new_x
= arc_legitimize_address_0 (orig_x
, oldx
, mode
);
9618 arc_delegitimize_address_0 (rtx op
)
9620 switch (GET_CODE (op
))
9623 return arc_delegitimize_address_0 (XEXP (op
, 0));
9626 switch (XINT (op
, 1))
9628 case ARC_UNSPEC_GOT
:
9629 case ARC_UNSPEC_GOTOFFPC
:
9630 return XVECEXP (op
, 0, 0);
9638 rtx t1
= arc_delegitimize_address_0 (XEXP (op
, 0));
9639 rtx t2
= XEXP (op
, 1);
9642 return gen_rtx_PLUS (GET_MODE (op
), t1
, t2
);
9653 arc_delegitimize_address (rtx orig_x
)
9660 x
= arc_delegitimize_address_0 (x
);
9665 x
= replace_equiv_address_nv (orig_x
, x
);
9669 /* Return a REG rtx for acc1. N.B. the gcc-internal representation may
9670 differ from the hardware register number in order to allow the generic
9671 code to correctly split the concatenation of acc1 and acc2. */
9676 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 56: 57);
9679 /* Return a REG rtx for acc2. N.B. the gcc-internal representation may
9680 differ from the hardware register number in order to allow the generic
9681 code to correctly split the concatenation of acc1 and acc2. */
9686 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 57: 56);
9689 /* When estimating sizes during arc_reorg, when optimizing for speed, there
9690 are three reasons why we need to consider branches to be length 6:
9691 - annull-false delay slot insns are implemented using conditional execution,
9692 thus preventing short insn formation where used.
9693 - for ARC600: annul-true delay slot insns are implemented where possible
9694 using conditional execution, preventing short insn formation where used.
9695 - for ARC700: likely or somewhat likely taken branches are made long and
9696 unaligned if possible to avoid branch penalty. */
9699 arc_branch_size_unknown_p (void)
9701 return !optimize_size
&& arc_reorg_in_progress
;
9704 /* The usual; we set up our machine_function data. */
9706 static struct machine_function
*
9707 arc_init_machine_status (void)
9709 struct machine_function
*machine
;
9710 machine
= ggc_cleared_alloc
<machine_function
> ();
9711 machine
->fn_type
= ARC_FUNCTION_UNKNOWN
;
9716 /* Implements INIT_EXPANDERS. We just set up to call the above
9720 arc_init_expanders (void)
9722 init_machine_status
= arc_init_machine_status
;
9725 /* Check if OP is a proper parallel of a millicode call pattern. OFFSET
9726 indicates a number of elements to ignore - that allows to have a
9727 sibcall pattern that starts with (return). LOAD_P is zero for store
9728 multiple (for prologues), and one for load multiples (for epilogues),
9729 and two for load multiples where no final clobber of blink is required.
9730 We also skip the first load / store element since this is supposed to
9731 be checked in the instruction pattern. */
9734 arc_check_millicode (rtx op
, int offset
, int load_p
)
9736 int len
= XVECLEN (op
, 0) - offset
;
9741 if (len
< 2 || len
> 13)
9747 rtx elt
= XVECEXP (op
, 0, --len
);
9749 if (GET_CODE (elt
) != CLOBBER
9750 || !REG_P (XEXP (elt
, 0))
9751 || REGNO (XEXP (elt
, 0)) != RETURN_ADDR_REGNUM
9752 || len
< 3 || len
> 13)
9755 for (i
= 1; i
< len
; i
++)
9757 rtx elt
= XVECEXP (op
, 0, i
+ offset
);
9760 if (GET_CODE (elt
) != SET
)
9762 mem
= XEXP (elt
, load_p
);
9763 reg
= XEXP (elt
, 1-load_p
);
9764 if (!REG_P (reg
) || REGNO (reg
) != 13U+i
|| !MEM_P (mem
))
9766 addr
= XEXP (mem
, 0);
9767 if (GET_CODE (addr
) != PLUS
9768 || !rtx_equal_p (stack_pointer_rtx
, XEXP (addr
, 0))
9769 || !CONST_INT_P (XEXP (addr
, 1)) || INTVAL (XEXP (addr
, 1)) != i
*4)
9775 /* Operands 0..2 are the operands of a subsi which uses a 12 bit
9776 constant in operand 1, but which would require a LIMM because of
9778 operands 3 and 4 are new SET_SRCs for operands 0. */
9781 split_subsi (rtx
*operands
)
9783 int val
= INTVAL (operands
[1]);
9785 /* Try for two short insns first. Lengths being equal, we prefer
9786 expansions with shorter register lifetimes. */
9787 if (arc_check_short_reg_p (operands
[0])
9788 && arc_check_short_reg_p (operands
[2]))
9790 if (val
>= -31 && val
<= 127)
9792 operands
[3] = gen_rtx_NEG (SImode
, operands
[2]);
9793 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[1]);
9796 else if (val
>= 0 && val
< 255)
9798 operands
[3] = operands
[1];
9799 operands
[4] = gen_rtx_MINUS (SImode
, operands
[0], operands
[2]);
9803 /* If the destination is not an ARCompact16 register, we might
9804 still have a chance to make a short insn if the source is;
9805 we need to start with a reg-reg move for this. */
9806 operands
[3] = operands
[2];
9807 operands
[4] = gen_rtx_MINUS (SImode
, operands
[1], operands
[0]);
9810 /* Handle DOUBLE_REGS uses.
9811 Operand 0: destination register
9812 Operand 1: source register */
9815 arc_process_double_reg_moves (rtx
*operands
)
9817 enum usesDxState
{ none
, srcDx
, destDx
, maxDx
};
9818 enum usesDxState state
= none
;
9819 rtx dest
= operands
[0];
9820 rtx src
= operands
[1];
9822 if (refers_to_regno_p (40, 44, src
, 0))
9825 gcc_assert (REG_P (dest
));
9827 if (refers_to_regno_p (40, 44, dest
, 0))
9829 /* Via arc_register_move_cost, we should never see D,D moves. */
9830 gcc_assert (REG_P (src
));
9831 gcc_assert (state
== none
);
9840 /* Without the LR insn, we need to split this into a
9841 sequence of insns which will use the DEXCLx and DADDHxy
9842 insns to be able to read the Dx register in question. */
9843 if (TARGET_DPFP_DISABLE_LRSR
)
9845 /* gen *movdf_insn_nolrsr */
9846 rtx set
= gen_rtx_SET (dest
, src
);
9847 rtx use1
= gen_rtx_USE (VOIDmode
, const1_rtx
);
9848 emit_insn (gen_rtx_PARALLEL (VOIDmode
, gen_rtvec (2, set
, use1
)));
9852 /* When we have 'mov D, r' or 'mov D, D' then get the target
9853 register pair for use with LR insn. */
9854 rtx destHigh
= simplify_gen_subreg (SImode
, dest
, DFmode
,
9855 TARGET_BIG_ENDIAN
? 0 : 4);
9856 rtx destLow
= simplify_gen_subreg (SImode
, dest
, DFmode
,
9857 TARGET_BIG_ENDIAN
? 4 : 0);
9859 /* Produce the two LR insns to get the high and low parts. */
9860 emit_insn (gen_rtx_SET (destHigh
,
9861 gen_rtx_UNSPEC_VOLATILE (Pmode
,
9863 VUNSPEC_ARC_LR_HIGH
)));
9864 emit_insn (gen_rtx_SET (destLow
,
9865 gen_rtx_UNSPEC_VOLATILE (Pmode
,
9870 else if (state
== destDx
)
9872 /* When we have 'mov r, D' or 'mov D, D' and we have access to the
9873 LR insn get the target register pair. */
9874 rtx srcHigh
= simplify_gen_subreg (SImode
, src
, DFmode
,
9875 TARGET_BIG_ENDIAN
? 0 : 4);
9876 rtx srcLow
= simplify_gen_subreg (SImode
, src
, DFmode
,
9877 TARGET_BIG_ENDIAN
? 4 : 0);
9879 emit_insn (gen_dexcl_2op (dest
, srcHigh
, srcLow
));
9888 /* Check if we need to split a 64bit move. We do not need to split it if we can
9889 use vadd2 or ldd/std instructions. */
9892 arc_split_move_p (rtx
*operands
)
9894 machine_mode mode
= GET_MODE (operands
[0]);
9897 && ((memory_operand (operands
[0], mode
)
9898 && (even_register_operand (operands
[1], mode
)
9899 || satisfies_constraint_Cm3 (operands
[1])))
9900 || (memory_operand (operands
[1], mode
)
9901 && even_register_operand (operands
[0], mode
))))
9904 if (TARGET_PLUS_QMACW
9905 && even_register_operand (operands
[0], mode
)
9906 && even_register_operand (operands
[1], mode
))
9912 /* operands 0..1 are the operands of a 64 bit move instruction.
9913 split it into two moves with operands 2/3 and 4/5. */
9916 arc_split_move (rtx
*operands
)
9918 machine_mode mode
= GET_MODE (operands
[0]);
9925 if (arc_process_double_reg_moves (operands
))
9929 if (TARGET_PLUS_QMACW
9930 && GET_CODE (operands
[1]) == CONST_VECTOR
)
9932 HOST_WIDE_INT intval0
, intval1
;
9933 if (GET_MODE (operands
[1]) == V2SImode
)
9935 intval0
= INTVAL (XVECEXP (operands
[1], 0, 0));
9936 intval1
= INTVAL (XVECEXP (operands
[1], 0, 1));
9940 intval1
= INTVAL (XVECEXP (operands
[1], 0, 3)) << 16;
9941 intval1
|= INTVAL (XVECEXP (operands
[1], 0, 2)) & 0xFFFF;
9942 intval0
= INTVAL (XVECEXP (operands
[1], 0, 1)) << 16;
9943 intval0
|= INTVAL (XVECEXP (operands
[1], 0, 0)) & 0xFFFF;
9945 xop
[0] = gen_rtx_REG (SImode
, REGNO (operands
[0]));
9946 xop
[3] = gen_rtx_REG (SImode
, REGNO (operands
[0]) + 1);
9947 xop
[2] = GEN_INT (trunc_int_for_mode (intval0
, SImode
));
9948 xop
[1] = GEN_INT (trunc_int_for_mode (intval1
, SImode
));
9949 emit_move_insn (xop
[0], xop
[2]);
9950 emit_move_insn (xop
[3], xop
[1]);
9954 for (i
= 0; i
< 2; i
++)
9956 if (MEM_P (operands
[i
]) && auto_inc_p (XEXP (operands
[i
], 0)))
9958 rtx addr
= XEXP (operands
[i
], 0);
9962 gcc_assert (!reg_overlap_mentioned_p (operands
[0], addr
));
9963 switch (GET_CODE (addr
))
9965 case PRE_DEC
: o
= GEN_INT (-8); goto pre_modify
;
9966 case PRE_INC
: o
= GEN_INT (8); goto pre_modify
;
9967 case PRE_MODIFY
: o
= XEXP (XEXP (addr
, 1), 1);
9971 case POST_DEC
: o
= GEN_INT (-8); goto post_modify
;
9972 case POST_INC
: o
= GEN_INT (8); goto post_modify
;
9973 case POST_MODIFY
: o
= XEXP (XEXP (addr
, 1), 1);
9982 xop
[0+i
] = adjust_automodify_address_nv
9983 (operands
[i
], SImode
,
9984 gen_rtx_fmt_ee (code
, Pmode
, r
,
9985 gen_rtx_PLUS (Pmode
, r
, o
)),
9987 xop
[2+i
] = adjust_automodify_address_nv
9988 (operands
[i
], SImode
, plus_constant (Pmode
, r
, 4), 4);
9992 xop
[0+i
] = operand_subword (operands
[i
], 0, 0, mode
);
9993 xop
[2+i
] = operand_subword (operands
[i
], 1, 0, mode
);
9996 if (reg_overlap_mentioned_p (xop
[0], xop
[3]))
9999 gcc_assert (!reg_overlap_mentioned_p (xop
[2], xop
[1]));
10002 emit_move_insn (xop
[0 + swap
], xop
[1 + swap
]);
10003 emit_move_insn (xop
[2 - swap
], xop
[3 - swap
]);
10007 /* Select between the instruction output templates s_tmpl (for short INSNs)
10008 and l_tmpl (for long INSNs). */
10011 arc_short_long (rtx_insn
*insn
, const char *s_tmpl
, const char *l_tmpl
)
10013 int is_short
= arc_verify_short (insn
, -1);
10015 extract_constrain_insn_cached (insn
);
10016 return is_short
? s_tmpl
: l_tmpl
;
10019 /* Searches X for any reference to REGNO, returning the rtx of the
10020 reference found if any. Otherwise, returns NULL_RTX. */
10023 arc_regno_use_in (unsigned int regno
, rtx x
)
10029 if (REG_P (x
) && refers_to_regno_p (regno
, x
))
10032 fmt
= GET_RTX_FORMAT (GET_CODE (x
));
10033 for (i
= GET_RTX_LENGTH (GET_CODE (x
)) - 1; i
>= 0; i
--)
10037 if ((tem
= regno_use_in (regno
, XEXP (x
, i
))))
10040 else if (fmt
[i
] == 'E')
10041 for (j
= XVECLEN (x
, i
) - 1; j
>= 0; j
--)
10042 if ((tem
= regno_use_in (regno
, XVECEXP (x
, i
, j
))))
10049 /* Code has a minimum p2 alignment of 1, which we must restore after
10050 an ADDR_DIFF_VEC. */
10053 arc_label_align (rtx_insn
*label
)
10055 if (align_labels
.levels
[0].log
< 1)
10057 rtx_insn
*next
= next_nonnote_nondebug_insn (label
);
10058 if (INSN_P (next
) && recog_memoized (next
) >= 0)
10061 return align_labels
.levels
[0].log
;
10064 /* Return true if LABEL is in executable code. */
10067 arc_text_label (rtx_insn
*label
)
10071 /* ??? We use deleted labels like they were still there, see
10072 gcc.c-torture/compile/20000326-2.c . */
10073 gcc_assert (GET_CODE (label
) == CODE_LABEL
10074 || (GET_CODE (label
) == NOTE
10075 && NOTE_KIND (label
) == NOTE_INSN_DELETED_LABEL
));
10076 next
= next_nonnote_insn (label
);
10078 return (!JUMP_TABLE_DATA_P (next
)
10079 || GET_CODE (PATTERN (next
)) != ADDR_VEC
);
10080 else if (!PREV_INSN (label
))
10081 /* ??? sometimes text labels get inserted very late, see
10082 gcc.dg/torture/stackalign/comp-goto-1.c */
10087 /* Without this, gcc.dg/tree-prof/bb-reorg.c fails to assemble
10088 when compiling with -O2 -freorder-blocks-and-partition -fprofile-use
10089 -D_PROFILE_USE; delay branch scheduling then follows a crossing jump
10090 to redirect two breqs. */
10093 arc_can_follow_jump (const rtx_insn
*follower
, const rtx_insn
*followee
)
10095 /* ??? get_attr_type is declared to take an rtx. */
10096 union { const rtx_insn
*c
; rtx_insn
*r
; } u
;
10099 if (CROSSING_JUMP_P (followee
))
10100 switch (get_attr_type (u
.r
))
10103 if (get_attr_length (u
.r
) != 2)
10105 /* Fall through. */
10107 case TYPE_BRCC_NO_DELAY_SLOT
:
10116 /* Implement EPILOGUE_USES.
10117 Return true if REGNO should be added to the deemed uses of the epilogue.
10119 We have to make sure all the register restore instructions are
10120 known to be live in interrupt functions, plus the blink register if
10121 it is clobbered by the isr. */
10124 arc_epilogue_uses (int regno
)
10126 unsigned int fn_type
;
10127 fn_type
= arc_compute_function_type (cfun
);
10129 if (regno
== arc_tp_regno
)
10132 if (regno
== RETURN_ADDR_REGNUM
)
10135 if (regno
== arc_return_address_register (fn_type
))
10138 if (epilogue_completed
&& ARC_INTERRUPT_P (fn_type
))
10140 /* An interrupt function restores more registers. */
10141 if (df_regs_ever_live_p (regno
) || call_used_or_fixed_reg_p (regno
))
10148 /* Helper for EH_USES macro. */
10151 arc_eh_uses (int regno
)
10153 if (regno
== arc_tp_regno
)
10158 /* Return true if we use LRA instead of reload pass. */
10163 return arc_lra_flag
;
10166 /* ??? Should we define TARGET_REGISTER_PRIORITY? We might perfer to
10167 use q registers, because some insn are shorter with them. OTOH we
10168 already have separate alternatives for this purpose, and other
10169 insns don't mind, so maybe we should rather prefer the other
10170 registers? We need more data, and we can only get that if we allow
10171 people to try all options. */
10173 arc_register_priority (int r
)
10175 switch (arc_lra_priority_tag
)
10177 case ARC_LRA_PRIORITY_NONE
:
10179 case ARC_LRA_PRIORITY_NONCOMPACT
:
10180 return ((((r
& 7) ^ 4) - 4) & 15) != r
;
10181 case ARC_LRA_PRIORITY_COMPACT
:
10182 return ((((r
& 7) ^ 4) - 4) & 15) == r
;
10184 gcc_unreachable ();
10189 arc_spill_class (reg_class_t
/* orig_class */, machine_mode
)
10191 return GENERAL_REGS
;
10195 arc_legitimize_reload_address (rtx
*p
, machine_mode mode
, int opnum
,
10199 enum reload_type type
= (enum reload_type
) itype
;
10201 if (GET_CODE (x
) == PLUS
10202 && CONST_INT_P (XEXP (x
, 1))
10203 && (RTX_OK_FOR_BASE_P (XEXP (x
, 0), true)
10204 || (REG_P (XEXP (x
, 0))
10205 && reg_equiv_constant (REGNO (XEXP (x
, 0))))))
10207 int scale
= GET_MODE_SIZE (mode
);
10209 rtx index_rtx
= XEXP (x
, 1);
10210 HOST_WIDE_INT offset
= INTVAL (index_rtx
), offset_base
;
10211 rtx reg
, sum
, sum2
;
10215 if ((scale
-1) & offset
)
10217 shift
= scale
>> 1;
10219 = ((offset
+ (256 << shift
))
10220 & ((HOST_WIDE_INT
)((unsigned HOST_WIDE_INT
) -512 << shift
)));
10221 /* Sometimes the normal form does not suit DImode. We
10222 could avoid that by using smaller ranges, but that
10223 would give less optimized code when SImode is
10225 if (GET_MODE_SIZE (mode
) + offset
- offset_base
<= (256 << shift
))
10230 regno
= REGNO (reg
);
10231 sum2
= sum
= plus_constant (Pmode
, reg
, offset_base
);
10233 if (reg_equiv_constant (regno
))
10235 sum2
= plus_constant (Pmode
, reg_equiv_constant (regno
),
10237 if (GET_CODE (sum2
) == PLUS
)
10238 sum2
= gen_rtx_CONST (Pmode
, sum2
);
10240 *p
= gen_rtx_PLUS (Pmode
, sum
, GEN_INT (offset
- offset_base
));
10241 push_reload (sum2
, NULL_RTX
, &XEXP (*p
, 0), NULL
,
10242 BASE_REG_CLASS
, Pmode
, VOIDmode
, 0, 0, opnum
,
10247 /* We must re-recognize what we created before. */
10248 else if (GET_CODE (x
) == PLUS
10249 && GET_CODE (XEXP (x
, 0)) == PLUS
10250 && CONST_INT_P (XEXP (XEXP (x
, 0), 1))
10251 && REG_P (XEXP (XEXP (x
, 0), 0))
10252 && CONST_INT_P (XEXP (x
, 1)))
10254 /* Because this address is so complex, we know it must have
10255 been created by LEGITIMIZE_RELOAD_ADDRESS before; thus,
10256 it is already unshared, and needs no further unsharing. */
10257 push_reload (XEXP (x
, 0), NULL_RTX
, &XEXP (x
, 0), NULL
,
10258 BASE_REG_CLASS
, Pmode
, VOIDmode
, 0, 0, opnum
, type
);
10264 /* Implement TARGET_USE_BY_PIECES_INFRASTRUCTURE_P. */
10267 arc_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size
,
10268 unsigned int align
,
10269 enum by_pieces_operation op
,
10272 /* Let the cpymem expander handle small block moves. */
10273 if (op
== MOVE_BY_PIECES
)
10276 return default_use_by_pieces_infrastructure_p (size
, align
, op
, speed_p
);
10279 /* Emit a (pre) memory barrier around an atomic sequence according to
10283 arc_pre_atomic_barrier (enum memmodel model
)
10285 if (need_atomic_barrier_p (model
, true))
10286 emit_insn (gen_memory_barrier ());
10289 /* Emit a (post) memory barrier around an atomic sequence according to
10293 arc_post_atomic_barrier (enum memmodel model
)
10295 if (need_atomic_barrier_p (model
, false))
10296 emit_insn (gen_memory_barrier ());
10299 /* Expand a compare and swap pattern. */
10302 emit_unlikely_jump (rtx insn
)
10304 rtx_insn
*jump
= emit_jump_insn (insn
);
10305 add_reg_br_prob_note (jump
, profile_probability::very_unlikely ());
10308 /* Expand code to perform a 8 or 16-bit compare and swap by doing
10309 32-bit compare and swap on the word containing the byte or
10310 half-word. The difference between a weak and a strong CAS is that
10311 the weak version may simply fail. The strong version relies on two
10312 loops, one checks if the SCOND op is succsfully or not, the other
10313 checks if the 32 bit accessed location which contains the 8 or 16
10314 bit datum is not changed by other thread. The first loop is
10315 implemented by the atomic_compare_and_swapsi_1 pattern. The second
10316 loops is implemented by this routine. */
10319 arc_expand_compare_and_swap_qh (rtx bool_result
, rtx result
, rtx mem
,
10320 rtx oldval
, rtx newval
, rtx weak
,
10321 rtx mod_s
, rtx mod_f
)
10323 rtx addr1
= force_reg (Pmode
, XEXP (mem
, 0));
10324 rtx addr
= gen_reg_rtx (Pmode
);
10325 rtx off
= gen_reg_rtx (SImode
);
10326 rtx oldv
= gen_reg_rtx (SImode
);
10327 rtx newv
= gen_reg_rtx (SImode
);
10328 rtx oldvalue
= gen_reg_rtx (SImode
);
10329 rtx newvalue
= gen_reg_rtx (SImode
);
10330 rtx res
= gen_reg_rtx (SImode
);
10331 rtx resv
= gen_reg_rtx (SImode
);
10332 rtx memsi
, val
, mask
, end_label
, loop_label
, cc
, x
;
10334 bool is_weak
= (weak
!= const0_rtx
);
10336 /* Truncate the address. */
10337 emit_insn (gen_rtx_SET (addr
,
10338 gen_rtx_AND (Pmode
, addr1
, GEN_INT (-4))));
10340 /* Compute the datum offset. */
10341 emit_insn (gen_rtx_SET (off
,
10342 gen_rtx_AND (SImode
, addr1
, GEN_INT (3))));
10343 if (TARGET_BIG_ENDIAN
)
10344 emit_insn (gen_rtx_SET (off
,
10345 gen_rtx_MINUS (SImode
,
10346 (GET_MODE (mem
) == QImode
) ?
10347 GEN_INT (3) : GEN_INT (2), off
)));
10349 /* Normal read from truncated address. */
10350 memsi
= gen_rtx_MEM (SImode
, addr
);
10351 set_mem_alias_set (memsi
, ALIAS_SET_MEMORY_BARRIER
);
10352 MEM_VOLATILE_P (memsi
) = MEM_VOLATILE_P (mem
);
10354 val
= copy_to_reg (memsi
);
10356 /* Convert the offset in bits. */
10357 emit_insn (gen_rtx_SET (off
,
10358 gen_rtx_ASHIFT (SImode
, off
, GEN_INT (3))));
10360 /* Get the proper mask. */
10361 if (GET_MODE (mem
) == QImode
)
10362 mask
= force_reg (SImode
, GEN_INT (0xff));
10364 mask
= force_reg (SImode
, GEN_INT (0xffff));
10366 emit_insn (gen_rtx_SET (mask
,
10367 gen_rtx_ASHIFT (SImode
, mask
, off
)));
10369 /* Prepare the old and new values. */
10370 emit_insn (gen_rtx_SET (val
,
10371 gen_rtx_AND (SImode
, gen_rtx_NOT (SImode
, mask
),
10374 oldval
= gen_lowpart (SImode
, oldval
);
10375 emit_insn (gen_rtx_SET (oldv
,
10376 gen_rtx_ASHIFT (SImode
, oldval
, off
)));
10378 newval
= gen_lowpart_common (SImode
, newval
);
10379 emit_insn (gen_rtx_SET (newv
,
10380 gen_rtx_ASHIFT (SImode
, newval
, off
)));
10382 emit_insn (gen_rtx_SET (oldv
,
10383 gen_rtx_AND (SImode
, oldv
, mask
)));
10385 emit_insn (gen_rtx_SET (newv
,
10386 gen_rtx_AND (SImode
, newv
, mask
)));
10390 end_label
= gen_label_rtx ();
10391 loop_label
= gen_label_rtx ();
10392 emit_label (loop_label
);
10395 /* Make the old and new values. */
10396 emit_insn (gen_rtx_SET (oldvalue
,
10397 gen_rtx_IOR (SImode
, oldv
, val
)));
10399 emit_insn (gen_rtx_SET (newvalue
,
10400 gen_rtx_IOR (SImode
, newv
, val
)));
10402 /* Try an 32bit atomic compare and swap. It clobbers the CC
10404 emit_insn (gen_atomic_compare_and_swapsi_1 (res
, memsi
, oldvalue
, newvalue
,
10405 weak
, mod_s
, mod_f
));
10407 /* Regardless of the weakness of the operation, a proper boolean
10408 result needs to be provided. */
10409 x
= gen_rtx_REG (CC_Zmode
, CC_REG
);
10410 x
= gen_rtx_EQ (SImode
, x
, const0_rtx
);
10411 emit_insn (gen_rtx_SET (bool_result
, x
));
10415 /* Check the results: if the atomic op is successfully the goto
10417 x
= gen_rtx_REG (CC_Zmode
, CC_REG
);
10418 x
= gen_rtx_EQ (VOIDmode
, x
, const0_rtx
);
10419 x
= gen_rtx_IF_THEN_ELSE (VOIDmode
, x
,
10420 gen_rtx_LABEL_REF (Pmode
, end_label
), pc_rtx
);
10421 emit_jump_insn (gen_rtx_SET (pc_rtx
, x
));
10423 /* Wait for the right moment when the accessed 32-bit location
10425 emit_insn (gen_rtx_SET (resv
,
10426 gen_rtx_AND (SImode
, gen_rtx_NOT (SImode
, mask
),
10428 mode
= SELECT_CC_MODE (NE
, resv
, val
);
10429 cc
= gen_rtx_REG (mode
, CC_REG
);
10430 emit_insn (gen_rtx_SET (cc
, gen_rtx_COMPARE (mode
, resv
, val
)));
10432 /* Set the new value of the 32 bit location, proper masked. */
10433 emit_insn (gen_rtx_SET (val
, resv
));
10435 /* Try again if location is unstable. Fall through if only
10436 scond op failed. */
10437 x
= gen_rtx_NE (VOIDmode
, cc
, const0_rtx
);
10438 x
= gen_rtx_IF_THEN_ELSE (VOIDmode
, x
,
10439 gen_rtx_LABEL_REF (Pmode
, loop_label
), pc_rtx
);
10440 emit_unlikely_jump (gen_rtx_SET (pc_rtx
, x
));
10442 emit_label (end_label
);
10445 /* End: proper return the result for the given mode. */
10446 emit_insn (gen_rtx_SET (res
,
10447 gen_rtx_AND (SImode
, res
, mask
)));
10449 emit_insn (gen_rtx_SET (res
,
10450 gen_rtx_LSHIFTRT (SImode
, res
, off
)));
10452 emit_move_insn (result
, gen_lowpart (GET_MODE (result
), res
));
10455 /* Helper function used by "atomic_compare_and_swap" expand
10459 arc_expand_compare_and_swap (rtx operands
[])
10461 rtx bval
, rval
, mem
, oldval
, newval
, is_weak
, mod_s
, mod_f
, x
;
10464 bval
= operands
[0];
10465 rval
= operands
[1];
10467 oldval
= operands
[3];
10468 newval
= operands
[4];
10469 is_weak
= operands
[5];
10470 mod_s
= operands
[6];
10471 mod_f
= operands
[7];
10472 mode
= GET_MODE (mem
);
10474 if (reg_overlap_mentioned_p (rval
, oldval
))
10475 oldval
= copy_to_reg (oldval
);
10477 if (mode
== SImode
)
10479 emit_insn (gen_atomic_compare_and_swapsi_1 (rval
, mem
, oldval
, newval
,
10480 is_weak
, mod_s
, mod_f
));
10481 x
= gen_rtx_REG (CC_Zmode
, CC_REG
);
10482 x
= gen_rtx_EQ (SImode
, x
, const0_rtx
);
10483 emit_insn (gen_rtx_SET (bval
, x
));
10487 arc_expand_compare_and_swap_qh (bval
, rval
, mem
, oldval
, newval
,
10488 is_weak
, mod_s
, mod_f
);
10492 /* Helper function used by the "atomic_compare_and_swapsi_1"
10496 arc_split_compare_and_swap (rtx operands
[])
10498 rtx rval
, mem
, oldval
, newval
;
10500 enum memmodel mod_s
, mod_f
;
10502 rtx label1
, label2
, x
, cond
;
10504 rval
= operands
[0];
10506 oldval
= operands
[2];
10507 newval
= operands
[3];
10508 is_weak
= (operands
[4] != const0_rtx
);
10509 mod_s
= (enum memmodel
) INTVAL (operands
[5]);
10510 mod_f
= (enum memmodel
) INTVAL (operands
[6]);
10511 mode
= GET_MODE (mem
);
10513 /* ARC atomic ops work only with 32-bit aligned memories. */
10514 gcc_assert (mode
== SImode
);
10516 arc_pre_atomic_barrier (mod_s
);
10521 label1
= gen_label_rtx ();
10522 emit_label (label1
);
10524 label2
= gen_label_rtx ();
10526 /* Load exclusive. */
10527 emit_insn (gen_arc_load_exclusivesi (rval
, mem
));
10529 /* Check if it is oldval. */
10530 mode
= SELECT_CC_MODE (NE
, rval
, oldval
);
10531 cond
= gen_rtx_REG (mode
, CC_REG
);
10532 emit_insn (gen_rtx_SET (cond
, gen_rtx_COMPARE (mode
, rval
, oldval
)));
10534 x
= gen_rtx_NE (VOIDmode
, cond
, const0_rtx
);
10535 x
= gen_rtx_IF_THEN_ELSE (VOIDmode
, x
,
10536 gen_rtx_LABEL_REF (Pmode
, label2
), pc_rtx
);
10537 emit_unlikely_jump (gen_rtx_SET (pc_rtx
, x
));
10539 /* Exclusively store new item. Store clobbers CC reg. */
10540 emit_insn (gen_arc_store_exclusivesi (mem
, newval
));
10544 /* Check the result of the store. */
10545 cond
= gen_rtx_REG (CC_Zmode
, CC_REG
);
10546 x
= gen_rtx_NE (VOIDmode
, cond
, const0_rtx
);
10547 x
= gen_rtx_IF_THEN_ELSE (VOIDmode
, x
,
10548 gen_rtx_LABEL_REF (Pmode
, label1
), pc_rtx
);
10549 emit_unlikely_jump (gen_rtx_SET (pc_rtx
, x
));
10552 if (mod_f
!= MEMMODEL_RELAXED
)
10553 emit_label (label2
);
10555 arc_post_atomic_barrier (mod_s
);
10557 if (mod_f
== MEMMODEL_RELAXED
)
10558 emit_label (label2
);
10561 /* Expand an atomic fetch-and-operate pattern. CODE is the binary operation
10562 to perform. MEM is the memory on which to operate. VAL is the second
10563 operand of the binary operator. BEFORE and AFTER are optional locations to
10564 return the value of MEM either before of after the operation. MODEL_RTX
10565 is a CONST_INT containing the memory model to use. */
10568 arc_expand_atomic_op (enum rtx_code code
, rtx mem
, rtx val
,
10569 rtx orig_before
, rtx orig_after
, rtx model_rtx
)
10571 enum memmodel model
= (enum memmodel
) INTVAL (model_rtx
);
10572 machine_mode mode
= GET_MODE (mem
);
10573 rtx label
, x
, cond
;
10574 rtx before
= orig_before
, after
= orig_after
;
10576 /* ARC atomic ops work only with 32-bit aligned memories. */
10577 gcc_assert (mode
== SImode
);
10579 arc_pre_atomic_barrier (model
);
10581 label
= gen_label_rtx ();
10582 emit_label (label
);
10583 label
= gen_rtx_LABEL_REF (VOIDmode
, label
);
10585 if (before
== NULL_RTX
)
10586 before
= gen_reg_rtx (mode
);
10588 if (after
== NULL_RTX
)
10589 after
= gen_reg_rtx (mode
);
10591 /* Load exclusive. */
10592 emit_insn (gen_arc_load_exclusivesi (before
, mem
));
10597 x
= gen_rtx_AND (mode
, before
, val
);
10598 emit_insn (gen_rtx_SET (after
, x
));
10599 x
= gen_rtx_NOT (mode
, after
);
10600 emit_insn (gen_rtx_SET (after
, x
));
10604 if (CONST_INT_P (val
))
10606 val
= GEN_INT (-INTVAL (val
));
10612 x
= gen_rtx_fmt_ee (code
, mode
, before
, val
);
10613 emit_insn (gen_rtx_SET (after
, x
));
10617 /* Exclusively store new item. Store clobbers CC reg. */
10618 emit_insn (gen_arc_store_exclusivesi (mem
, after
));
10620 /* Check the result of the store. */
10621 cond
= gen_rtx_REG (CC_Zmode
, CC_REG
);
10622 x
= gen_rtx_NE (VOIDmode
, cond
, const0_rtx
);
10623 x
= gen_rtx_IF_THEN_ELSE (VOIDmode
, x
,
10625 emit_unlikely_jump (gen_rtx_SET (pc_rtx
, x
));
10627 arc_post_atomic_barrier (model
);
10630 /* Implement TARGET_NO_SPECULATION_IN_DELAY_SLOTS_P. */
10633 arc_no_speculation_in_delay_slots_p ()
10638 /* Return a parallel of registers to represent where to find the
10639 register pieces if required, otherwise NULL_RTX. */
10642 arc_dwarf_register_span (rtx rtl
)
10644 machine_mode mode
= GET_MODE (rtl
);
10648 if (GET_MODE_SIZE (mode
) != 8)
10651 p
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (2));
10652 regno
= REGNO (rtl
);
10653 XVECEXP (p
, 0, 0) = gen_rtx_REG (SImode
, regno
);
10654 XVECEXP (p
, 0, 1) = gen_rtx_REG (SImode
, regno
+ 1);
10659 /* Return true if OP is an acceptable memory operand for ARCompact
10660 16-bit load instructions of MODE.
10662 AV2SHORT: TRUE if address needs to fit into the new ARCv2 short
10663 non scaled instructions.
10665 SCALED: TRUE if address can be scaled. */
10668 compact_memory_operand_p (rtx op
, machine_mode mode
,
10669 bool av2short
, bool scaled
)
10671 rtx addr
, plus0
, plus1
;
10674 /* Eliminate non-memory operations. */
10675 if (GET_CODE (op
) != MEM
)
10678 /* .di instructions have no 16-bit form. */
10679 if (MEM_VOLATILE_P (op
) && !TARGET_VOLATILE_CACHE_SET
)
10682 /* likewise for uncached types. */
10683 if (arc_is_uncached_mem_p (op
))
10686 if (mode
== VOIDmode
)
10687 mode
= GET_MODE (op
);
10689 size
= GET_MODE_SIZE (mode
);
10691 /* dword operations really put out 2 instructions, so eliminate
10693 if (size
> UNITS_PER_WORD
)
10696 /* Decode the address now. */
10697 addr
= XEXP (op
, 0);
10698 switch (GET_CODE (addr
))
10701 return (REGNO (addr
) >= FIRST_PSEUDO_REGISTER
10702 || COMPACT_GP_REG_P (REGNO (addr
))
10703 || (SP_REG_P (REGNO (addr
)) && (size
!= 2)));
10705 plus0
= XEXP (addr
, 0);
10706 plus1
= XEXP (addr
, 1);
10708 if ((GET_CODE (plus0
) == REG
)
10709 && ((REGNO (plus0
) >= FIRST_PSEUDO_REGISTER
)
10710 || COMPACT_GP_REG_P (REGNO (plus0
)))
10711 && ((GET_CODE (plus1
) == REG
)
10712 && ((REGNO (plus1
) >= FIRST_PSEUDO_REGISTER
)
10713 || COMPACT_GP_REG_P (REGNO (plus1
)))))
10718 if ((GET_CODE (plus0
) == REG
)
10719 && ((REGNO (plus0
) >= FIRST_PSEUDO_REGISTER
)
10720 || (COMPACT_GP_REG_P (REGNO (plus0
)) && !av2short
)
10721 || (IN_RANGE (REGNO (plus0
), 0, 31) && av2short
))
10722 && (GET_CODE (plus1
) == CONST_INT
))
10724 bool valid
= false;
10726 off
= INTVAL (plus1
);
10728 /* Negative offset is not supported in 16-bit load/store insns. */
10732 /* Only u5 immediates allowed in code density instructions. */
10740 /* This is an ldh_s.x instruction, check the u6
10742 if (COMPACT_GP_REG_P (REGNO (plus0
)))
10746 /* Only u5 immediates allowed in 32bit access code
10747 density instructions. */
10748 if (REGNO (plus0
) <= 31)
10749 return ((off
< 32) && (off
% 4 == 0));
10756 if (COMPACT_GP_REG_P (REGNO (plus0
)))
10767 /* The 6-bit constant get shifted to fit the real
10768 5-bits field. Check also for the alignment. */
10769 return ((off
< 64) && (off
% 2 == 0));
10771 return ((off
< 128) && (off
% 4 == 0));
10778 if (REG_P (plus0
) && CONST_INT_P (plus1
)
10779 && ((REGNO (plus0
) >= FIRST_PSEUDO_REGISTER
)
10780 || SP_REG_P (REGNO (plus0
)))
10783 off
= INTVAL (plus1
);
10784 return ((size
!= 2) && (off
>= 0 && off
< 128) && (off
% 4 == 0));
10787 if ((GET_CODE (plus0
) == MULT
)
10788 && (GET_CODE (XEXP (plus0
, 0)) == REG
)
10789 && ((REGNO (XEXP (plus0
, 0)) >= FIRST_PSEUDO_REGISTER
)
10790 || COMPACT_GP_REG_P (REGNO (XEXP (plus0
, 0))))
10791 && (GET_CODE (plus1
) == REG
)
10792 && ((REGNO (plus1
) >= FIRST_PSEUDO_REGISTER
)
10793 || COMPACT_GP_REG_P (REGNO (plus1
))))
10797 /* TODO: 'gp' and 'pcl' are to supported as base address operand
10798 for 16-bit load instructions. */
10803 /* Return nonzero if a jli call should be generated for a call from
10804 the current function to DECL. */
10807 arc_is_jli_call_p (rtx pat
)
10810 tree decl
= SYMBOL_REF_DECL (pat
);
10812 /* If it is not a well defined public function then return false. */
10813 if (!decl
|| !SYMBOL_REF_FUNCTION_P (pat
) || !TREE_PUBLIC (decl
))
10816 attrs
= TYPE_ATTRIBUTES (TREE_TYPE (decl
));
10817 if (lookup_attribute ("jli_always", attrs
))
10820 if (lookup_attribute ("jli_fixed", attrs
))
10823 return TARGET_JLI_ALWAYS
;
10826 /* Handle and "jli" attribute; arguments as in struct
10827 attribute_spec.handler. */
10830 arc_handle_jli_attribute (tree
*node ATTRIBUTE_UNUSED
,
10831 tree name
, tree args
, int,
10832 bool *no_add_attrs
)
10836 warning (OPT_Wattributes
,
10837 "%qE attribute only valid for ARCv2 architecture",
10839 *no_add_attrs
= true;
10842 if (args
== NULL_TREE
)
10844 warning (OPT_Wattributes
,
10845 "argument of %qE attribute is missing",
10847 *no_add_attrs
= true;
10851 if (TREE_CODE (TREE_VALUE (args
)) == NON_LVALUE_EXPR
)
10852 TREE_VALUE (args
) = TREE_OPERAND (TREE_VALUE (args
), 0);
10853 tree arg
= TREE_VALUE (args
);
10854 if (TREE_CODE (arg
) != INTEGER_CST
)
10856 warning (0, "%qE attribute allows only an integer constant argument",
10858 *no_add_attrs
= true;
10860 /* FIXME! add range check. TREE_INT_CST_LOW (arg) */
10865 /* Handle and "scure" attribute; arguments as in struct
10866 attribute_spec.handler. */
10869 arc_handle_secure_attribute (tree
*node ATTRIBUTE_UNUSED
,
10870 tree name
, tree args
, int,
10871 bool *no_add_attrs
)
10875 warning (OPT_Wattributes
,
10876 "%qE attribute only valid for ARC EM architecture",
10878 *no_add_attrs
= true;
10881 if (args
== NULL_TREE
)
10883 warning (OPT_Wattributes
,
10884 "argument of %qE attribute is missing",
10886 *no_add_attrs
= true;
10890 if (TREE_CODE (TREE_VALUE (args
)) == NON_LVALUE_EXPR
)
10891 TREE_VALUE (args
) = TREE_OPERAND (TREE_VALUE (args
), 0);
10892 tree arg
= TREE_VALUE (args
);
10893 if (TREE_CODE (arg
) != INTEGER_CST
)
10895 warning (0, "%qE attribute allows only an integer constant argument",
10897 *no_add_attrs
= true;
10903 /* Return nonzero if the symbol is a secure function. */
10906 arc_is_secure_call_p (rtx pat
)
10909 tree decl
= SYMBOL_REF_DECL (pat
);
10914 attrs
= TYPE_ATTRIBUTES (TREE_TYPE (decl
));
10915 if (lookup_attribute ("secure_call", attrs
))
10921 /* Handle "uncached" qualifier. */
10924 arc_handle_uncached_attribute (tree
*node
,
10925 tree name
, tree args
,
10926 int flags ATTRIBUTE_UNUSED
,
10927 bool *no_add_attrs
)
10929 if (DECL_P (*node
) && TREE_CODE (*node
) != TYPE_DECL
)
10931 error ("%qE attribute only applies to types",
10933 *no_add_attrs
= true;
10937 warning (OPT_Wattributes
, "argument of %qE attribute ignored", name
);
10942 /* Return TRUE if PAT is a memory addressing an uncached data. */
10945 arc_is_uncached_mem_p (rtx pat
)
10947 tree attrs
= NULL_TREE
;
10953 /* Get the memory attributes. */
10954 addr
= MEM_EXPR (pat
);
10958 /* Get the attributes. */
10959 if (TREE_CODE (addr
) == MEM_REF
10962 attrs
= TYPE_ATTRIBUTES (TREE_TYPE (addr
));
10963 if (lookup_attribute ("uncached", attrs
))
10966 if (TREE_CODE (addr
) == MEM_REF
)
10968 attrs
= TYPE_ATTRIBUTES (TREE_TYPE (TREE_OPERAND (addr
, 0)));
10969 if (lookup_attribute ("uncached", attrs
))
10971 attrs
= TYPE_ATTRIBUTES (TREE_TYPE (TREE_OPERAND (addr
, 1)));
10972 if (lookup_attribute ("uncached", attrs
))
10976 /* Check the definitions of the structs. */
10977 while (handled_component_p (addr
))
10979 if (TREE_CODE (addr
) == COMPONENT_REF
)
10981 attrs
= TYPE_ATTRIBUTES (TREE_TYPE (addr
));
10982 if (lookup_attribute ("uncached", attrs
))
10984 attrs
= TYPE_ATTRIBUTES (TREE_TYPE (TREE_OPERAND (addr
, 0)));
10985 if (lookup_attribute ("uncached", attrs
))
10987 attrs
= TYPE_ATTRIBUTES (TREE_TYPE (TREE_OPERAND (addr
, 1)));
10988 if (lookup_attribute ("uncached", attrs
))
10991 addr
= TREE_OPERAND (addr
, 0);
10996 /* Handle aux attribute. The auxiliary registers are addressed using
10997 special instructions lr and sr. The attribute 'aux' indicates if a
10998 variable refers to the aux-regs and what is the register number
11002 arc_handle_aux_attribute (tree
*node
,
11003 tree name
, tree args
, int,
11004 bool *no_add_attrs
)
11006 /* Isn't it better to use address spaces for the aux-regs? */
11007 if (DECL_P (*node
))
11009 if (TREE_CODE (*node
) != VAR_DECL
)
11011 error ("%qE attribute only applies to variables", name
);
11012 *no_add_attrs
= true;
11016 if (TREE_CODE (TREE_VALUE (args
)) == NON_LVALUE_EXPR
)
11017 TREE_VALUE (args
) = TREE_OPERAND (TREE_VALUE (args
), 0);
11018 tree arg
= TREE_VALUE (args
);
11019 if (TREE_CODE (arg
) != INTEGER_CST
)
11021 warning (OPT_Wattributes
, "%qE attribute allows only an integer "
11022 "constant argument", name
);
11023 *no_add_attrs
= true;
11025 /* FIXME! add range check. TREE_INT_CST_LOW (arg) */
11030 tree fntype
= TREE_TYPE (*node
);
11031 if (fntype
&& TREE_CODE (fntype
) == POINTER_TYPE
)
11033 tree attrs
= tree_cons (get_identifier ("aux"), NULL_TREE
,
11034 TYPE_ATTRIBUTES (fntype
));
11035 TYPE_ATTRIBUTES (fntype
) = attrs
;
11042 /* Implement TARGET_USE_ANCHORS_FOR_SYMBOL_P. We don't want to use
11043 anchors for small data: the GP register acts as an anchor in that
11044 case. We also don't want to use them for PC-relative accesses,
11045 where the PC acts as an anchor. Prohibit also TLS symbols to use
11049 arc_use_anchors_for_symbol_p (const_rtx symbol
)
11051 if (SYMBOL_REF_TLS_MODEL (symbol
))
11057 if (SYMBOL_REF_SMALL_P (symbol
))
11060 return default_use_anchors_for_symbol_p (symbol
);
11063 /* Return true if SUBST can't safely replace its equivalent during RA. */
11065 arc_cannot_substitute_mem_equiv_p (rtx
)
11067 /* If SUBST is mem[base+index], the address may not fit ISA,
11068 thus return true. */
11072 /* Checks whether the operands are valid for use in an LDD/STD
11073 instruction. Assumes that RT, and RT2 are REG. This is guaranteed
11074 by the patterns. Assumes that the address in the base register RN
11075 is word aligned. Pattern guarantees that both memory accesses use
11076 the same base register, the offsets are constants within the range,
11077 and the gap between the offsets is 4. If reload complete then
11078 check that registers are legal. */
11081 operands_ok_ldd_std (rtx rt
, rtx rt2
, HOST_WIDE_INT offset
)
11083 unsigned int t
, t2
;
11085 if (!reload_completed
)
11088 if (!(SMALL_INT_RANGE (offset
, (GET_MODE_SIZE (DImode
) - 1) & (~0x03),
11089 (offset
& (GET_MODE_SIZE (DImode
) - 1) & 3
11090 ? 0 : -(-GET_MODE_SIZE (DImode
) | (~0x03)) >> 1))))
11096 if ((t2
== PCL_REG
)
11097 || (t
% 2 != 0) /* First destination register is not even. */
11104 /* Helper for gen_operands_ldd_std. Returns true iff the memory
11105 operand MEM's address contains an immediate offset from the base
11106 register and has no side effects, in which case it sets BASE and
11107 OFFSET accordingly. */
11110 mem_ok_for_ldd_std (rtx mem
, rtx
*base
, rtx
*offset
)
11114 gcc_assert (base
!= NULL
&& offset
!= NULL
);
11116 /* TODO: Handle more general memory operand patterns, such as
11117 PRE_DEC and PRE_INC. */
11119 if (side_effects_p (mem
))
11122 /* Can't deal with subregs. */
11123 if (GET_CODE (mem
) == SUBREG
)
11126 gcc_assert (MEM_P (mem
));
11128 *offset
= const0_rtx
;
11130 addr
= XEXP (mem
, 0);
11132 /* If addr isn't valid for DImode, then we can't handle it. */
11133 if (!arc_legitimate_address_p (DImode
, addr
,
11134 reload_in_progress
|| reload_completed
))
11142 else if (GET_CODE (addr
) == PLUS
|| GET_CODE (addr
) == MINUS
)
11144 *base
= XEXP (addr
, 0);
11145 *offset
= XEXP (addr
, 1);
11146 return (REG_P (*base
) && CONST_INT_P (*offset
));
11152 /* Called from peephole2 to replace two word-size accesses with a
11153 single LDD/STD instruction. Returns true iff we can generate a new
11154 instruction sequence. That is, both accesses use the same base
11155 register and the gap between constant offsets is 4. OPERANDS are
11156 the operands found by the peephole matcher; OPERANDS[0,1] are
11157 register operands, and OPERANDS[2,3] are the corresponding memory
11158 operands. LOAD indicates whether the access is load or store. */
11161 gen_operands_ldd_std (rtx
*operands
, bool load
, bool commute
)
11164 HOST_WIDE_INT offsets
[2], offset
;
11166 rtx cur_base
, cur_offset
, tmp
;
11167 rtx base
= NULL_RTX
;
11169 /* Check that the memory references are immediate offsets from the
11170 same base register. Extract the base register, the destination
11171 registers, and the corresponding memory offsets. */
11172 for (i
= 0; i
< nops
; i
++)
11174 if (!mem_ok_for_ldd_std (operands
[nops
+i
], &cur_base
, &cur_offset
))
11179 else if (REGNO (base
) != REGNO (cur_base
))
11182 offsets
[i
] = INTVAL (cur_offset
);
11183 if (GET_CODE (operands
[i
]) == SUBREG
)
11185 tmp
= SUBREG_REG (operands
[i
]);
11186 gcc_assert (GET_MODE (operands
[i
]) == GET_MODE (tmp
));
11191 /* Make sure there is no dependency between the individual loads. */
11192 if (load
&& REGNO (operands
[0]) == REGNO (base
))
11193 return false; /* RAW. */
11195 if (load
&& REGNO (operands
[0]) == REGNO (operands
[1]))
11196 return false; /* WAW. */
11198 /* Make sure the instructions are ordered with lower memory access first. */
11199 if (offsets
[0] > offsets
[1])
11201 gap
= offsets
[0] - offsets
[1];
11202 offset
= offsets
[1];
11204 /* Swap the instructions such that lower memory is accessed first. */
11205 std::swap (operands
[0], operands
[1]);
11206 std::swap (operands
[2], operands
[3]);
11210 gap
= offsets
[1] - offsets
[0];
11211 offset
= offsets
[0];
11214 /* Make sure accesses are to consecutive memory locations. */
11218 /* Make sure we generate legal instructions. */
11219 if (operands_ok_ldd_std (operands
[0], operands
[1], offset
))
11222 if (load
&& commute
)
11224 /* Try reordering registers. */
11225 std::swap (operands
[0], operands
[1]);
11226 if (operands_ok_ldd_std (operands
[0], operands
[1], offset
))
11233 /* This order of allocation is used when we compile for size. It
11234 allocates first the registers which are most probably to end up in
11235 a short instruction. */
11236 static const int size_alloc_order
[] =
11238 0, 1, 2, 3, 12, 13, 14, 15,
11239 4, 5, 6, 7, 8, 9, 10, 11
11242 /* Adjust register allocation order when compiling for size. */
11244 arc_adjust_reg_alloc_order (void)
11246 const int arc_default_alloc_order
[] = REG_ALLOC_ORDER
;
11247 memcpy (reg_alloc_order
, arc_default_alloc_order
, sizeof (reg_alloc_order
));
11249 memcpy (reg_alloc_order
, size_alloc_order
, sizeof (size_alloc_order
));
11252 /* Implement TARGET_MEMORY_MOVE_COST. */
11255 arc_memory_move_cost (machine_mode mode
,
11256 reg_class_t rclass ATTRIBUTE_UNUSED
,
11257 bool in ATTRIBUTE_UNUSED
)
11259 if ((GET_MODE_SIZE (mode
) <= UNITS_PER_WORD
)
11260 || ((GET_MODE_SIZE (mode
) <= UNITS_PER_WORD
* 2) && TARGET_LL64
))
11263 return (2 * GET_MODE_SIZE (mode
));
11266 /* Split an OR instruction into multiple BSET/OR instructions in a
11267 attempt to avoid long immediate constants. The next strategies are
11268 employed when destination is 'q' reg.
11270 1. if there are up to three bits set in the mask, a succession of
11271 three bset instruction will be emitted:
11273 BSET(_S) rA,rB,mask1/BSET_S rA,rA,mask2/BSET_S rA,rA,mask3
11275 2. if the lower 6 bits of the mask is set and there is only one
11276 bit set in the upper remaining bits then we will emit one bset and
11277 one OR instruction:
11278 OR rA, rB, mask -> OR rA,rB,mask1/BSET_S rA,mask2
11280 3. otherwise an OR with limm will be emmitted. */
11283 arc_split_ior (rtx
*operands
)
11285 unsigned HOST_WIDE_INT mask
, maskx
;
11286 rtx op1
= operands
[1];
11288 gcc_assert (CONST_INT_P (operands
[2]));
11289 mask
= INTVAL (operands
[2]) & 0xffffffff;
11291 if (__builtin_popcount (mask
) > 3 || (mask
& 0x3f))
11293 maskx
= mask
& 0x3f;
11294 emit_insn (gen_rtx_SET (operands
[0],
11295 gen_rtx_IOR (SImode
, op1
, GEN_INT (maskx
))));
11300 switch (__builtin_popcount (mask
))
11303 maskx
= 1 << (__builtin_ffs (mask
) - 1);
11304 emit_insn (gen_rtx_SET (operands
[0],
11305 gen_rtx_IOR (SImode
, op1
, GEN_INT (maskx
))));
11310 maskx
= 1 << (__builtin_ffs (mask
) - 1);
11311 emit_insn (gen_rtx_SET (operands
[0],
11312 gen_rtx_IOR (SImode
, op1
, GEN_INT (maskx
))));
11317 maskx
= 1 << (__builtin_ffs (mask
) - 1);
11318 emit_insn (gen_rtx_SET (operands
[0],
11319 gen_rtx_IOR (SImode
, op1
, GEN_INT (maskx
))));
11324 gcc_unreachable ();
11328 /* Helper to check C0x constraint. */
11331 arc_check_ior_const (HOST_WIDE_INT ival
)
11333 unsigned int mask
= (unsigned int) (ival
& 0xffffffff);
11335 if (UNSIGNED_INT6 (ival
)
11336 || IS_POWEROF2_P (mask
))
11338 if (__builtin_popcount (mask
) <= 3)
11340 if (__builtin_popcount (mask
& ~0x3f) <= 1)
11345 /* Split a mov with long immediate instruction into smaller, size
11346 friendly instructions. */
11349 arc_split_mov_const (rtx
*operands
)
11351 unsigned HOST_WIDE_INT ival
;
11352 HOST_WIDE_INT shimm
;
11353 machine_mode mode
= GET_MODE (operands
[0]);
11355 /* Manage a constant. */
11356 gcc_assert (CONST_INT_P (operands
[1]));
11357 ival
= INTVAL (operands
[1]) & 0xffffffff;
11359 /* 1. Check if we can just rotate limm by 8 but using ROR8. */
11360 if (TARGET_BARREL_SHIFTER
&& TARGET_V2
11361 && ((ival
& ~0x3f000000) == 0))
11363 shimm
= (ival
>> 24) & 0x3f;
11364 emit_insn (gen_rtx_SET (operands
[0],
11365 gen_rtx_ROTATERT (mode
, GEN_INT (shimm
),
11369 /* 2. Check if we can just shift by 8 to fit into the u6 of LSL8. */
11370 if (TARGET_BARREL_SHIFTER
&& TARGET_V2
11371 && ((ival
& ~0x3f00) == 0))
11373 shimm
= (ival
>> 8) & 0x3f;
11374 emit_insn (gen_rtx_SET (operands
[0],
11375 gen_rtx_ASHIFT (mode
, GEN_INT (shimm
),
11380 /* 3. Check if we can just shift by 16 to fit into the u6 of LSL16. */
11381 if (TARGET_SWAP
&& TARGET_V2
11382 && ((ival
& ~0x3f0000) == 0))
11384 shimm
= (ival
>> 16) & 0x3f;
11385 emit_insn (gen_rtx_SET (operands
[0],
11386 gen_rtx_ASHIFT (mode
, GEN_INT (shimm
),
11391 /* 4. Check if we can do something like mov_s h,u8 / asl_s ra,h,#nb. */
11392 if (((ival
>> (__builtin_ffs (ival
) - 1)) & 0xffffff00) == 0
11393 && TARGET_BARREL_SHIFTER
)
11395 HOST_WIDE_INT shift
= __builtin_ffs (ival
);
11396 shimm
= (ival
>> (shift
- 1)) & 0xff;
11397 emit_insn (gen_rtx_SET (operands
[0], GEN_INT (shimm
)));
11398 emit_insn (gen_rtx_SET (operands
[0],
11399 gen_rtx_ASHIFT (mode
, operands
[0],
11400 GEN_INT (shift
- 1))));
11404 /* 5. Check if we can just rotate the limm, useful when no barrel
11405 shifter is present. */
11406 if ((ival
& ~0x8000001f) == 0)
11408 shimm
= (ival
* 2 + 1) & 0x3f;
11409 emit_insn (gen_rtx_SET (operands
[0],
11410 gen_rtx_ROTATERT (mode
, GEN_INT (shimm
),
11415 /* 6. Check if we can do something with bmask. */
11416 if (IS_POWEROF2_P (ival
+ 1))
11418 emit_insn (gen_rtx_SET (operands
[0], constm1_rtx
));
11419 emit_insn (gen_rtx_SET (operands
[0],
11420 gen_rtx_AND (mode
, operands
[0],
11425 gcc_unreachable ();
11428 /* Helper to check Cax constraint. */
11431 arc_check_mov_const (HOST_WIDE_INT ival
)
11433 ival
= ival
& 0xffffffff;
11435 if (SIGNED_INT12 (ival
))
11438 if ((ival
& ~0x8000001f) == 0)
11441 if (IS_POWEROF2_P (ival
+ 1))
11444 /* The next rules requires a barrel shifter. */
11445 if (!TARGET_BARREL_SHIFTER
)
11448 if (((ival
>> (__builtin_ffs (ival
) - 1)) & 0xffffff00) == 0)
11451 if ((ival
& ~0x3f00) == 0)
11454 if ((ival
& ~0x3f0000) == 0)
11457 if ((ival
& ~0x3f000000) == 0)
11463 /* Return nonzero if this function is known to have a null epilogue.
11464 This allows the optimizer to omit jumps to jumps if no stack
11468 arc_can_use_return_insn (void)
11470 return (reload_completed
&& cfun
->machine
->frame_info
.total_size
== 0
11471 && !ARC_INTERRUPT_P (arc_compute_function_type (cfun
)));
11474 /* Helper for INSN_COST.
11476 Per Segher Boessenkool: rtx_costs computes the cost for any rtx (an
11477 insn, a set, a set source, any random piece of one). set_src_cost,
11478 set_rtx_cost, etc. are helper functions that use that.
11480 Those functions do not work for parallels. Also, costs are not
11481 additive like this simplified model assumes. Also, more complex
11482 backends tend to miss many cases in their rtx_costs function.
11484 Many passes that want costs want to know the cost of a full insn. Like
11485 combine. That's why I created insn_cost: it solves all of the above
11489 arc_insn_cost (rtx_insn
*insn
, bool speed
)
11492 enum attr_type type
;
11493 if (recog_memoized (insn
) >= 0)
11497 /* Use cost if provided. */
11498 cost
= get_attr_cost (insn
);
11501 /* For speed make a simple cost model: memory access is more
11502 expensive than any other instruction. */
11503 type
= get_attr_type (insn
);
11504 if (type
== TYPE_LOAD
|| type
== TYPE_STORE
)
11505 return COSTS_N_INSNS (2);
11509 /* If optimizing for size, we want the insn size. */
11510 type
= get_attr_type (insn
);
11511 if (type
!= TYPE_MULTI
)
11512 return get_attr_length (insn
);
11516 if (rtx set
= single_set (insn
))
11517 cost
= set_rtx_cost (set
, speed
);
11519 cost
= pattern_cost (PATTERN (insn
), speed
);
11520 /* If the cost is zero, then it's likely a complex insn. We don't
11521 want the cost of these to be less than something we know about. */
11522 return cost
? cost
: COSTS_N_INSNS (2);
11526 arc_libm_function_max_error (unsigned cfn
, machine_mode mode
,
11529 #ifdef OPTION_GLIBC
11530 bool glibc_p
= OPTION_GLIBC
;
11532 bool glibc_p
= false;
11536 int rnd
= flag_rounding_math
? 4 : 0;
11541 if (!boundary_p
&& mode
== DFmode
)
11546 if (!boundary_p
&& mode
== DFmode
)
11551 return glibc_linux_libm_function_max_error (cfn
, mode
, boundary_p
);
11553 return default_libm_function_max_error (cfn
, mode
, boundary_p
);
11556 #undef TARGET_USE_ANCHORS_FOR_SYMBOL_P
11557 #define TARGET_USE_ANCHORS_FOR_SYMBOL_P arc_use_anchors_for_symbol_p
11559 #undef TARGET_CONSTANT_ALIGNMENT
11560 #define TARGET_CONSTANT_ALIGNMENT constant_alignment_word_strings
11562 #undef TARGET_CANNOT_SUBSTITUTE_MEM_EQUIV_P
11563 #define TARGET_CANNOT_SUBSTITUTE_MEM_EQUIV_P arc_cannot_substitute_mem_equiv_p
11565 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
11566 #define TARGET_ASM_TRAMPOLINE_TEMPLATE arc_asm_trampoline_template
11568 #undef TARGET_HAVE_SPECULATION_SAFE_VALUE
11569 #define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
11571 #undef TARGET_REGISTER_MOVE_COST
11572 #define TARGET_REGISTER_MOVE_COST arc_register_move_cost
11574 #undef TARGET_MEMORY_MOVE_COST
11575 #define TARGET_MEMORY_MOVE_COST arc_memory_move_cost
11577 #undef TARGET_INSN_COST
11578 #define TARGET_INSN_COST arc_insn_cost
11580 #undef TARGET_LIBM_FUNCTION_MAX_ERROR
11581 #define TARGET_LIBM_FUNCTION_MAX_ERROR arc_libm_function_max_error
11583 struct gcc_target targetm
= TARGET_INITIALIZER
;
11585 #include "gt-arc.h"