1 /* Subroutines used for code generation on the Synopsys DesignWare ARC cpu.
2 Copyright (C) 1994-2025 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 hook_bool_void_true
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 || arg
.type
!= NULL_TREE
)
2357 arc_function_arg_advance (pack_cumulative_args (&next_cum
), arg
);
2358 first_anon_arg
= next_cum
;
2360 if (FUNCTION_ARG_REGNO_P (first_anon_arg
))
2362 /* First anonymous (unnamed) argument is in a reg. */
2364 /* Note that first_reg_offset < MAX_ARC_PARM_REGS. */
2365 int first_reg_offset
= first_anon_arg
;
2370 = gen_rtx_MEM (BLKmode
, plus_constant (Pmode
, arg_pointer_rtx
,
2371 FIRST_PARM_OFFSET (0)));
2372 move_block_from_reg (first_reg_offset
, regblock
,
2373 MAX_ARC_PARM_REGS
- first_reg_offset
);
2377 = ((MAX_ARC_PARM_REGS
- first_reg_offset
) * UNITS_PER_WORD
);
2381 /* Return TRUE if reg is ok for short instrcutions. */
2384 arc_check_short_reg_p (rtx op
)
2389 if (IN_RANGE (REGNO (op
) ^ 4, 4, 11))
2395 /* Cost functions. */
2397 /* Provide the costs of an addressing mode that contains ADDR.
2398 If ADDR is not a valid address, its cost is irrelevant. */
2401 arc_address_cost (rtx addr
, machine_mode
, addr_space_t
, bool speed
)
2403 switch (GET_CODE (addr
))
2406 return speed
|| arc_check_short_reg_p (addr
) ? 0 : 1;
2407 case PRE_INC
: case PRE_DEC
: case POST_INC
: case POST_DEC
:
2408 case PRE_MODIFY
: case POST_MODIFY
:
2414 if (TARGET_NPS_CMEM
&& cmem_address (addr
, SImode
))
2416 /* Most likely needs a LIMM. */
2417 return COSTS_N_INSNS (1);
2421 rtx plus0
= XEXP (addr
, 0);
2422 rtx plus1
= XEXP (addr
, 1);
2424 if (GET_CODE (plus0
) != REG
2425 && (GET_CODE (plus0
) != MULT
2426 || !CONST_INT_P (XEXP (plus0
, 1))
2427 || (INTVAL (XEXP (plus0
, 1)) != 2
2428 && INTVAL (XEXP (plus0
, 1)) != 4)))
2431 switch (GET_CODE (plus1
))
2434 return (!RTX_OK_FOR_OFFSET_P (SImode
, plus1
)
2438 : (arc_check_short_reg_p (plus0
)
2439 && satisfies_constraint_O (plus1
))
2443 return (speed
< 1 ? 0
2444 : (arc_check_short_reg_p (plus0
)
2445 && arc_check_short_reg_p (plus1
))
2450 return COSTS_N_INSNS (1);
2463 /* Emit instruction X with the frame related bit set. */
2469 RTX_FRAME_RELATED_P (x
) = 1;
2473 /* Emit a frame insn to move SRC to DST. */
2476 frame_move (rtx dst
, rtx src
)
2478 rtx tmp
= gen_rtx_SET (dst
, src
);
2479 RTX_FRAME_RELATED_P (tmp
) = 1;
2480 return frame_insn (tmp
);
2483 /* Like frame_move, but add a REG_INC note for REG if ADDR contains an
2484 auto increment address, or is zero. */
2487 frame_move_inc (rtx dst
, rtx src
, rtx reg
, rtx addr
)
2489 rtx insn
= frame_move (dst
, src
);
2492 || GET_CODE (addr
) == PRE_DEC
|| GET_CODE (addr
) == POST_INC
2493 || GET_CODE (addr
) == PRE_MODIFY
|| GET_CODE (addr
) == POST_MODIFY
)
2494 add_reg_note (insn
, REG_INC
, reg
);
2498 /* Emit a frame insn which adjusts a frame address register REG by OFFSET. */
2501 frame_add (rtx reg
, HOST_WIDE_INT offset
)
2503 gcc_assert ((offset
& 0x3) == 0);
2506 return frame_move (reg
, plus_constant (Pmode
, reg
, offset
));
2509 /* Emit a frame insn which adjusts stack pointer by OFFSET. */
2512 frame_stack_add (HOST_WIDE_INT offset
)
2514 return frame_add (stack_pointer_rtx
, offset
);
2517 /* Helper function to wrap FRAME_POINTER_NEEDED. We do this as
2518 FRAME_POINTER_NEEDED will not be true until the IRA (Integrated
2519 Register Allocator) pass, while we want to get the frame size
2520 correct earlier than the IRA pass.
2522 When a function uses eh_return we must ensure that the fp register
2523 is saved and then restored so that the unwinder can restore the
2524 correct value for the frame we are going to jump to.
2526 To do this we force all frames that call eh_return to require a
2527 frame pointer (see arc_frame_pointer_required), this
2528 will ensure that the previous frame pointer is stored on entry to
2529 the function, and will then be reloaded at function exit.
2531 As the frame pointer is handled as a special case in our prologue
2532 and epilogue code it must not be saved and restored using the
2533 MUST_SAVE_REGISTER mechanism otherwise we run into issues where GCC
2534 believes that the function is not using a frame pointer and that
2535 the value in the fp register is the frame pointer, while the
2536 prologue and epilogue are busy saving and restoring the fp
2539 During compilation of a function the frame size is evaluated
2540 multiple times, it is not until the reload pass is complete the
2541 frame size is considered fixed (it is at this point that space for
2542 all spills has been allocated). However the frame_pointer_needed
2543 variable is not set true until the register allocation pass, as a
2544 result in the early stages the frame size does not include space
2545 for the frame pointer to be spilled.
2547 The problem that this causes is that the rtl generated for
2548 EH_RETURN_HANDLER_RTX uses the details of the frame size to compute
2549 the offset from the frame pointer at which the return address
2550 lives. However, in early passes GCC has not yet realised we need a
2551 frame pointer, and so has not included space for the frame pointer
2552 in the frame size, and so gets the offset of the return address
2553 wrong. This should not be an issue as in later passes GCC has
2554 realised that the frame pointer needs to be spilled, and has
2555 increased the frame size. However, the rtl for the
2556 EH_RETURN_HANDLER_RTX is not regenerated to use the newer, larger
2557 offset, and the wrong smaller offset is used. */
2560 arc_frame_pointer_needed (void)
2562 return (frame_pointer_needed
|| crtl
->calls_eh_return
);
2565 /* Tell prologue and epilogue if register REGNO should be saved /
2566 restored. The SPECIAL_P is true when the register may need special
2567 ld/st sequence. The return address, and stack pointer are treated
2568 separately. Don't consider them here. */
2571 arc_must_save_register (int regno
, struct function
*func
, bool special_p
)
2573 unsigned int fn_type
= arc_compute_function_type (func
);
2574 bool irq_auto_save_p
= ((irq_ctrl_saved
.irq_save_last_reg
>= regno
)
2575 && ARC_AUTO_IRQ_P (fn_type
));
2576 bool firq_auto_save_p
= ARC_FAST_INTERRUPT_P (fn_type
);
2578 switch (rgf_banked_register_count
)
2581 firq_auto_save_p
&= (regno
< 4);
2584 firq_auto_save_p
&= ((regno
< 4) || ((regno
> 11) && (regno
< 16)));
2587 firq_auto_save_p
&= ((regno
< 4) || ((regno
> 9) && (regno
< 16))
2588 || ((regno
> 25) && (regno
< 29))
2589 || ((regno
> 29) && (regno
< 32)));
2592 firq_auto_save_p
&= (regno
!= 29) && (regno
< 32);
2595 firq_auto_save_p
= false;
2602 case RETURN_ADDR_REGNUM
:
2603 case STACK_POINTER_REGNUM
:
2604 /* The stack pointer and the return address are handled
2609 /* r30 is either used as ilink2 by ARCv1 or as a free register
2620 /* If those ones are used by the FPX machinery, we handle them
2622 if (TARGET_DPFP
&& !special_p
)
2647 /* The Extension Registers. */
2648 if (ARC_INTERRUPT_P (fn_type
)
2649 && (df_regs_ever_live_p (RETURN_ADDR_REGNUM
)
2650 || df_regs_ever_live_p (regno
))
2651 /* Not all extension registers are available, choose the
2653 && !fixed_regs
[regno
])
2659 /* ARC600 specifies those ones as mlo/mhi registers, otherwise
2660 just handle them like any other extension register. */
2661 if (ARC_INTERRUPT_P (fn_type
)
2662 && (df_regs_ever_live_p (RETURN_ADDR_REGNUM
)
2663 || df_regs_ever_live_p (regno
))
2664 /* Not all extension registers are available, choose the
2666 && ((!fixed_regs
[regno
] && !special_p
)
2667 || (TARGET_MUL64_SET
&& special_p
)))
2674 /* Fixed/control register, nothing to do. LP_COUNT is
2678 case HARD_FRAME_POINTER_REGNUM
:
2679 /* If we need FP reg as a frame pointer then don't save it as a
2681 if (arc_frame_pointer_needed ())
2689 if (((df_regs_ever_live_p (regno
) && !call_used_or_fixed_reg_p (regno
))
2690 /* In an interrupt save everything. */
2691 || (ARC_INTERRUPT_P (fn_type
)
2692 && (df_regs_ever_live_p (RETURN_ADDR_REGNUM
)
2693 || df_regs_ever_live_p (regno
))))
2694 /* Do not emit code for auto saved regs. */
2696 && !firq_auto_save_p
)
2701 /* Return true if the return address must be saved in the current function,
2702 otherwise return false. */
2705 arc_must_save_return_addr (struct function
*func
)
2707 if (func
->machine
->frame_info
.save_return_addr
)
2713 /* Return non-zero if there are registers to be saved or loaded using
2714 millicode thunks. We can only use consecutive sequences starting
2715 with r13, and not going beyond r25.
2716 GMASK is a bitmask of registers to save. This function sets
2717 FRAME->millicod_start_reg .. FRAME->millicode_end_reg to the range
2718 of registers to be saved / restored with a millicode call. */
2721 arc_compute_millicode_save_restore_regs (uint64_t gmask
,
2722 struct arc_frame_info
*frame
)
2726 int start_reg
= 13, end_reg
= 25;
2728 for (regno
= start_reg
; regno
<= end_reg
&& (gmask
& (1ULL << regno
));)
2730 end_reg
= regno
- 1;
2731 /* There is no point in using millicode thunks if we don't save/restore
2732 at least three registers. For non-leaf functions we also have the
2734 if (regno
- start_reg
>= 3 - (crtl
->is_leaf
== 0))
2736 frame
->millicode_start_reg
= 13;
2737 frame
->millicode_end_reg
= regno
- 1;
2743 /* Return the bytes needed to compute the frame pointer from the
2744 current stack pointer. */
2747 arc_compute_frame_size (void)
2750 unsigned int total_size
, var_size
, args_size
, pretend_size
, extra_size
;
2751 unsigned int reg_size
;
2753 struct arc_frame_info
*frame_info
;
2755 unsigned int extra_plus_reg_size
;
2756 unsigned int extra_plus_reg_size_aligned
;
2757 unsigned int fn_type
= arc_compute_function_type (cfun
);
2759 /* The answer might already be known. */
2760 if (cfun
->machine
->frame_info
.initialized
)
2761 return cfun
->machine
->frame_info
.total_size
;
2763 frame_info
= &cfun
->machine
->frame_info
;
2764 size
= ARC_STACK_ALIGN (get_frame_size ());
2766 /* 1) Size of locals and temporaries. */
2769 /* 2) Size of outgoing arguments. */
2770 args_size
= crtl
->outgoing_args_size
;
2772 /* 3) Calculate space needed for saved registers.
2773 ??? We ignore the extension registers for now. */
2775 /* See if this is an interrupt handler. Call used registers must be saved
2781 /* The last 4 regs are special, avoid them. */
2782 for (regno
= 0; regno
<= (GMASK_LEN
- 4); regno
++)
2784 if (arc_must_save_register (regno
, cfun
, false))
2786 reg_size
+= UNITS_PER_WORD
;
2787 gmask
|= 1ULL << regno
;
2791 /* In a frame that calls __builtin_eh_return two data registers are
2792 used to pass values back to the exception handler.
2794 Ensure that these registers are spilled to the stack so that the
2795 exception throw code can find them, and update the saved values.
2796 The handling code will then consume these reloaded values to
2797 handle the exception. */
2798 if (crtl
->calls_eh_return
)
2799 for (regno
= 0; EH_RETURN_DATA_REGNO (regno
) != INVALID_REGNUM
; regno
++)
2801 reg_size
+= UNITS_PER_WORD
;
2802 gmask
|= 1ULL << regno
;
2805 /* Check if we need to save the return address. */
2806 frame_info
->save_return_addr
= (!crtl
->is_leaf
2807 || df_regs_ever_live_p (RETURN_ADDR_REGNUM
)
2808 || crtl
->calls_eh_return
);
2810 /* Saving blink reg for millicode thunk calls. */
2811 if (TARGET_MILLICODE_THUNK_SET
2812 && !ARC_INTERRUPT_P (fn_type
)
2813 && !crtl
->calls_eh_return
)
2815 if (arc_compute_millicode_save_restore_regs (gmask
, frame_info
))
2816 frame_info
->save_return_addr
= true;
2819 /* Save lp_count, lp_start and lp_end. */
2820 if (arc_lpcwidth
!= 0 && arc_must_save_register (LP_COUNT
, cfun
, true))
2821 reg_size
+= UNITS_PER_WORD
* 3;
2823 /* Check for the special R40-R44 regs used by FPX extension. */
2824 if (arc_must_save_register (TARGET_BIG_ENDIAN
? R41_REG
: R40_REG
,
2826 reg_size
+= UNITS_PER_WORD
* 2;
2827 if (arc_must_save_register (TARGET_BIG_ENDIAN
? R43_REG
: R42_REG
,
2829 reg_size
+= UNITS_PER_WORD
* 2;
2831 /* Check if R58 is used. */
2832 if (arc_must_save_register (R58_REG
, cfun
, true))
2833 reg_size
+= UNITS_PER_WORD
* 2;
2835 /* 4) Calculate extra size made up of the blink + fp size. */
2837 if (arc_must_save_return_addr (cfun
))
2839 /* Add FP size only when it is not autosaved. */
2840 if (arc_frame_pointer_needed ()
2841 && !ARC_AUTOFP_IRQ_P (fn_type
))
2844 /* 5) Space for variable arguments passed in registers */
2845 pretend_size
= crtl
->args
.pretend_args_size
;
2847 /* Ensure everything before the locals is aligned appropriately. */
2848 extra_plus_reg_size
= extra_size
+ reg_size
;
2849 extra_plus_reg_size_aligned
= ARC_STACK_ALIGN (extra_plus_reg_size
);
2850 reg_size
= extra_plus_reg_size_aligned
- extra_size
;
2852 /* Compute total frame size. */
2853 total_size
= var_size
+ args_size
+ extra_size
+ pretend_size
+ reg_size
;
2855 /* It used to be the case that the alignment was forced at this
2856 point. However, that is dangerous, calculations based on
2857 total_size would be wrong. Given that this has never cropped up
2858 as an issue I've changed this to an assert for now. */
2859 gcc_assert (total_size
== ARC_STACK_ALIGN (total_size
));
2861 /* Save computed information. */
2862 frame_info
->total_size
= total_size
;
2863 frame_info
->extra_size
= extra_size
;
2864 frame_info
->pretend_size
= pretend_size
;
2865 frame_info
->var_size
= var_size
;
2866 frame_info
->args_size
= args_size
;
2867 frame_info
->reg_size
= reg_size
;
2868 frame_info
->gmask
= gmask
;
2869 frame_info
->initialized
= reload_completed
;
2871 /* Ok, we're done. */
2875 /* Build dwarf information when the context is saved via AUX_IRQ_CTRL
2879 arc_dwarf_emit_irq_save_regs (void)
2881 rtx tmp
, par
, insn
, reg
;
2884 par
= gen_rtx_SEQUENCE (VOIDmode
,
2885 rtvec_alloc (irq_ctrl_saved
.irq_save_last_reg
+ 1
2886 + irq_ctrl_saved
.irq_save_blink
2887 + irq_ctrl_saved
.irq_save_lpcount
2890 /* Build the stack adjustment note for unwind info. */
2892 offset
= UNITS_PER_WORD
* (irq_ctrl_saved
.irq_save_last_reg
+ 1
2893 + irq_ctrl_saved
.irq_save_blink
2894 + irq_ctrl_saved
.irq_save_lpcount
);
2895 tmp
= plus_constant (Pmode
, stack_pointer_rtx
, -1 * offset
);
2896 tmp
= gen_rtx_SET (stack_pointer_rtx
, tmp
);
2897 RTX_FRAME_RELATED_P (tmp
) = 1;
2898 XVECEXP (par
, 0, j
++) = tmp
;
2900 offset
-= UNITS_PER_WORD
;
2902 /* 1st goes LP_COUNT. */
2903 if (irq_ctrl_saved
.irq_save_lpcount
)
2905 reg
= gen_rtx_REG (SImode
, 60);
2906 tmp
= plus_constant (Pmode
, stack_pointer_rtx
, offset
);
2907 tmp
= gen_frame_mem (SImode
, tmp
);
2908 tmp
= gen_rtx_SET (tmp
, reg
);
2909 RTX_FRAME_RELATED_P (tmp
) = 1;
2910 XVECEXP (par
, 0, j
++) = tmp
;
2911 offset
-= UNITS_PER_WORD
;
2914 /* 2nd goes BLINK. */
2915 if (irq_ctrl_saved
.irq_save_blink
)
2917 reg
= gen_rtx_REG (SImode
, 31);
2918 tmp
= plus_constant (Pmode
, stack_pointer_rtx
, offset
);
2919 tmp
= gen_frame_mem (SImode
, tmp
);
2920 tmp
= gen_rtx_SET (tmp
, reg
);
2921 RTX_FRAME_RELATED_P (tmp
) = 1;
2922 XVECEXP (par
, 0, j
++) = tmp
;
2923 offset
-= UNITS_PER_WORD
;
2926 /* Build the parallel of the remaining registers recorded as saved
2928 for (i
= irq_ctrl_saved
.irq_save_last_reg
; i
>= 0; i
--)
2930 reg
= gen_rtx_REG (SImode
, i
);
2931 tmp
= plus_constant (Pmode
, stack_pointer_rtx
, offset
);
2932 tmp
= gen_frame_mem (SImode
, tmp
);
2933 tmp
= gen_rtx_SET (tmp
, reg
);
2934 RTX_FRAME_RELATED_P (tmp
) = 1;
2935 XVECEXP (par
, 0, j
++) = tmp
;
2936 offset
-= UNITS_PER_WORD
;
2939 /* Dummy insn used to anchor the dwarf info. */
2940 insn
= emit_insn (gen_stack_irq_dwarf());
2941 add_reg_note (insn
, REG_FRAME_RELATED_EXPR
, par
);
2942 RTX_FRAME_RELATED_P (insn
) = 1;
2945 /* Helper for prologue: emit frame store with pre_modify or pre_dec to
2946 save register REG on stack. An initial offset OFFSET can be passed
2950 frame_save_reg (rtx reg
, HOST_WIDE_INT offset
)
2956 rtx tmp
= plus_constant (Pmode
, stack_pointer_rtx
,
2957 offset
- GET_MODE_SIZE (GET_MODE (reg
)));
2958 addr
= gen_frame_mem (GET_MODE (reg
),
2959 gen_rtx_PRE_MODIFY (Pmode
,
2964 addr
= gen_frame_mem (GET_MODE (reg
), gen_rtx_PRE_DEC (Pmode
,
2965 stack_pointer_rtx
));
2966 frame_move_inc (addr
, reg
, stack_pointer_rtx
, 0);
2968 return GET_MODE_SIZE (GET_MODE (reg
)) - offset
;
2971 /* Helper used when saving AUX regs during ISR. */
2976 rtx stkslot
= gen_rtx_MEM (GET_MODE (reg
), gen_rtx_PRE_DEC (Pmode
,
2977 stack_pointer_rtx
));
2978 rtx insn
= emit_move_insn (stkslot
, reg
);
2979 RTX_FRAME_RELATED_P (insn
) = 1;
2980 add_reg_note (insn
, REG_CFA_ADJUST_CFA
,
2981 gen_rtx_SET (stack_pointer_rtx
,
2982 plus_constant (Pmode
, stack_pointer_rtx
,
2983 -GET_MODE_SIZE (GET_MODE (reg
)))));
2984 return GET_MODE_SIZE (GET_MODE (reg
));
2987 /* Helper for epilogue: emit frame load with post_modify or post_inc
2988 to restore register REG from stack. The initial offset is passed
2992 frame_restore_reg (rtx reg
, HOST_WIDE_INT offset
)
2998 rtx tmp
= plus_constant (Pmode
, stack_pointer_rtx
,
2999 offset
+ GET_MODE_SIZE (GET_MODE (reg
)));
3000 addr
= gen_frame_mem (GET_MODE (reg
),
3001 gen_rtx_POST_MODIFY (Pmode
,
3006 addr
= gen_frame_mem (GET_MODE (reg
), gen_rtx_POST_INC (Pmode
,
3007 stack_pointer_rtx
));
3008 insn
= frame_move_inc (reg
, addr
, stack_pointer_rtx
, 0);
3009 add_reg_note (insn
, REG_CFA_RESTORE
, reg
);
3011 if (reg
== hard_frame_pointer_rtx
)
3012 add_reg_note (insn
, REG_CFA_DEF_CFA
,
3013 plus_constant (Pmode
, stack_pointer_rtx
,
3014 GET_MODE_SIZE (GET_MODE (reg
)) + offset
));
3016 add_reg_note (insn
, REG_CFA_ADJUST_CFA
,
3017 gen_rtx_SET (stack_pointer_rtx
,
3018 plus_constant (Pmode
, stack_pointer_rtx
,
3019 GET_MODE_SIZE (GET_MODE (reg
))
3022 return GET_MODE_SIZE (GET_MODE (reg
)) + offset
;
3025 /* Helper used when restoring AUX regs during ISR. */
3030 rtx stkslot
= gen_rtx_MEM (GET_MODE (reg
), gen_rtx_POST_INC (Pmode
,
3031 stack_pointer_rtx
));
3032 rtx insn
= emit_move_insn (reg
, stkslot
);
3033 RTX_FRAME_RELATED_P (insn
) = 1;
3034 add_reg_note (insn
, REG_CFA_ADJUST_CFA
,
3035 gen_rtx_SET (stack_pointer_rtx
,
3036 plus_constant (Pmode
, stack_pointer_rtx
,
3037 GET_MODE_SIZE (GET_MODE (reg
)))));
3038 return GET_MODE_SIZE (GET_MODE (reg
));
3041 /* Check if we have a continous range to be save/restored with the
3042 help of enter/leave instructions. A vaild register range starts
3043 from $r13 and is up to (including) $r26. */
3046 arc_enter_leave_p (uint64_t gmask
)
3049 unsigned int rmask
= 0;
3054 for (regno
= ENTER_LEAVE_START_REG
;
3055 regno
<= ENTER_LEAVE_END_REG
&& (gmask
& (1ULL << regno
)); regno
++)
3056 rmask
|= 1ULL << regno
;
3064 /* ARC's prologue, save any needed call-saved regs (and call-used if
3065 this is an interrupt handler) for ARCompact ISA, using ST/STD
3069 arc_save_callee_saves (uint64_t gmask
,
3072 HOST_WIDE_INT offset
,
3076 int frame_allocated
= 0;
3079 /* The home-grown ABI says link register is saved first. */
3082 reg
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
3083 frame_allocated
+= frame_save_reg (reg
, offset
);
3087 /* N.B. FRAME_POINTER_MASK and RETURN_ADDR_MASK are cleared in gmask. */
3089 for (i
= GMASK_LEN
; i
>= 0; i
--)
3091 machine_mode save_mode
= SImode
;
3094 && ((i
- 1) % 2 == 0)
3095 && ((gmask
& (1ULL << i
)) != 0)
3096 && ((gmask
& (1ULL << (i
- 1))) != 0))
3101 else if ((gmask
& (1ULL << i
)) == 0)
3104 reg
= gen_rtx_REG (save_mode
, i
);
3105 frame_allocated
+= frame_save_reg (reg
, offset
);
3109 /* Save frame pointer if needed. First save the FP on stack, if not
3110 autosaved. Unfortunately, I cannot add it to gmask and use the
3111 above loop to save fp because our ABI states fp goes aftert all
3112 registers are saved. */
3115 frame_allocated
+= frame_save_reg (hard_frame_pointer_rtx
, offset
);
3119 /* Emit mov fp,sp. */
3121 frame_move (hard_frame_pointer_rtx
, stack_pointer_rtx
);
3123 return frame_allocated
;
3126 /* ARC's epilogue, restore any required call-saved regs (and call-used
3127 if it is for an interrupt handler) using LD/LDD instructions. */
3130 arc_restore_callee_saves (uint64_t gmask
,
3133 HOST_WIDE_INT offset
,
3134 HOST_WIDE_INT allocated
)
3137 int frame_deallocated
= 0;
3138 HOST_WIDE_INT offs
= cfun
->machine
->frame_info
.reg_size
;
3139 unsigned int fn_type
= arc_compute_function_type (cfun
);
3140 bool early_blink_restore
;
3143 /* Emit mov fp,sp. */
3144 if (arc_frame_pointer_needed () && offset
)
3146 frame_move (stack_pointer_rtx
, hard_frame_pointer_rtx
);
3147 frame_deallocated
+= offset
;
3153 /* Any offset is taken care by previous if-statement. */
3154 gcc_assert (offset
== 0);
3155 frame_deallocated
+= frame_restore_reg (hard_frame_pointer_rtx
, 0);
3160 /* No $fp involved, we need to do an add to set the $sp to the
3161 location of the first register. */
3162 frame_stack_add (offset
);
3163 frame_deallocated
+= offset
;
3167 /* When we do not optimize for size or we aren't in an interrupt,
3168 restore first blink. */
3169 early_blink_restore
= restore_blink
&& !optimize_size
&& offs
3170 && !ARC_INTERRUPT_P (fn_type
);
3171 if (early_blink_restore
)
3173 rtx addr
= plus_constant (Pmode
, stack_pointer_rtx
, offs
);
3174 reg
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
3175 rtx insn
= frame_move_inc (reg
, gen_frame_mem (Pmode
, addr
),
3176 stack_pointer_rtx
, NULL_RTX
);
3177 add_reg_note (insn
, REG_CFA_RESTORE
, reg
);
3178 restore_blink
= false;
3181 /* N.B. FRAME_POINTER_MASK and RETURN_ADDR_MASK are cleared in gmask. */
3183 for (i
= 0; i
<= GMASK_LEN
; i
++)
3185 machine_mode restore_mode
= SImode
;
3189 && ((gmask
& (1ULL << i
)) != 0)
3190 && ((gmask
& (1ULL << (i
+ 1))) != 0))
3191 restore_mode
= DImode
;
3192 else if ((gmask
& (1ULL << i
)) == 0)
3195 reg
= gen_rtx_REG (restore_mode
, i
);
3197 switch (restore_mode
)
3200 if ((GMASK_LEN
- __builtin_clzll (gmask
)) == (i
+ 1)
3201 && early_blink_restore
)
3205 if ((GMASK_LEN
- __builtin_clzll (gmask
)) == i
3206 && early_blink_restore
)
3212 frame_deallocated
+= frame_restore_reg (reg
, offs
);
3215 if (restore_mode
== DImode
)
3221 reg
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
3222 frame_deallocated
+= frame_restore_reg (reg
, allocated
3224 /* Consider as well the
3230 return frame_deallocated
;
3233 /* ARC prologue, save the registers using enter instruction. Leave
3234 instruction can also save $blink (SAVE_BLINK) and $fp (SAVE_FP)
3238 arc_save_callee_enter (uint64_t gmask
,
3241 HOST_WIDE_INT offset
)
3243 int start_reg
= ENTER_LEAVE_START_REG
;
3244 int end_reg
= ENTER_LEAVE_END_REG
;
3245 int regno
, indx
, off
, nregs
;
3247 int frame_allocated
= 0;
3249 for (regno
= start_reg
; regno
<= end_reg
&& (gmask
& (1ULL << regno
));)
3252 end_reg
= regno
- 1;
3253 nregs
= end_reg
- start_reg
+ 1;
3254 nregs
+= save_blink
? 1 : 0;
3255 nregs
+= save_fp
? 1 : 0;
3258 frame_stack_add (offset
);
3260 insn
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (nregs
+ (save_fp
? 1 : 0)
3264 reg
= gen_rtx_SET (stack_pointer_rtx
,
3265 plus_constant (Pmode
,
3267 -nregs
* UNITS_PER_WORD
));
3268 RTX_FRAME_RELATED_P (reg
) = 1;
3269 XVECEXP (insn
, 0, indx
++) = reg
;
3270 off
= nregs
* UNITS_PER_WORD
;
3274 reg
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
3275 mem
= gen_frame_mem (Pmode
, plus_constant (Pmode
,
3278 XVECEXP (insn
, 0, indx
) = gen_rtx_SET (mem
, reg
);
3279 RTX_FRAME_RELATED_P (XVECEXP (insn
, 0, indx
++)) = 1;
3280 off
-= UNITS_PER_WORD
;
3284 for (regno
= start_reg
;
3286 regno
++, indx
++, off
-= UNITS_PER_WORD
)
3288 reg
= gen_rtx_REG (SImode
, regno
);
3289 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
3292 XVECEXP (insn
, 0, indx
) = gen_rtx_SET (mem
, reg
);
3293 RTX_FRAME_RELATED_P (XVECEXP (insn
, 0, indx
)) = 1;
3294 gmask
= gmask
& ~(1ULL << regno
);
3299 mem
= gen_frame_mem (Pmode
, plus_constant (Pmode
,
3302 XVECEXP (insn
, 0, indx
) = gen_rtx_SET (mem
, hard_frame_pointer_rtx
);
3303 RTX_FRAME_RELATED_P (XVECEXP (insn
, 0, indx
++)) = 1;
3304 off
-= UNITS_PER_WORD
;
3306 XVECEXP (insn
, 0, indx
) = gen_rtx_SET (hard_frame_pointer_rtx
,
3308 RTX_FRAME_RELATED_P (XVECEXP (insn
, 0, indx
++)) = 1;
3312 gcc_assert (off
== 0);
3313 insn
= frame_insn (insn
);
3315 add_reg_note (insn
, REG_INC
, stack_pointer_rtx
);
3317 frame_allocated
= nregs
* UNITS_PER_WORD
;
3319 /* offset is a negative number, make sure we add it. */
3320 return frame_allocated
- offset
;
3323 /* ARC epilogue, restore the registers using leave instruction. An
3324 initial offset is passed in OFFSET. Besides restoring an register
3325 range, leave can also restore $blink (RESTORE_BLINK), or $fp
3326 (RESTORE_FP), and can automatic return (RETURN_P). */
3329 arc_restore_callee_leave (uint64_t gmask
,
3333 HOST_WIDE_INT offset
)
3335 int start_reg
= ENTER_LEAVE_START_REG
;
3336 int end_reg
= ENTER_LEAVE_END_REG
;
3337 int regno
, indx
, off
, nregs
;
3339 int frame_allocated
= 0;
3341 for (regno
= start_reg
; regno
<= end_reg
&& (gmask
& (1ULL << regno
));)
3344 end_reg
= regno
- 1;
3345 nregs
= end_reg
- start_reg
+ 1;
3346 nregs
+= restore_blink
? 1 : 0;
3347 nregs
+= restore_fp
? 1 : 0;
3349 insn
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (nregs
+ 1
3350 + (return_p
? 1 : 0)));
3354 XVECEXP (insn
, 0, indx
++) = ret_rtx
;
3358 /* I cannot emit set (sp, fp) here as cselib expects a single sp
3359 set and not two. Thus, use the offset, and change sp adjust
3361 frame_allocated
+= offset
;
3364 if (offset
&& !restore_fp
)
3366 /* This add is only emmited when we do not restore fp with leave
3368 frame_stack_add (offset
);
3369 frame_allocated
+= offset
;
3373 reg
= gen_rtx_SET (stack_pointer_rtx
,
3374 plus_constant (Pmode
,
3376 offset
+ nregs
* UNITS_PER_WORD
));
3377 RTX_FRAME_RELATED_P (reg
) = 1;
3378 XVECEXP (insn
, 0, indx
++) = reg
;
3379 off
= nregs
* UNITS_PER_WORD
;
3383 reg
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
3384 mem
= gen_frame_mem (Pmode
, plus_constant (Pmode
,
3387 XVECEXP (insn
, 0, indx
) = gen_rtx_SET (reg
, mem
);
3388 RTX_FRAME_RELATED_P (XVECEXP (insn
, 0, indx
++)) = 1;
3389 off
-= UNITS_PER_WORD
;
3392 for (regno
= start_reg
;
3394 regno
++, indx
++, off
-= UNITS_PER_WORD
)
3396 reg
= gen_rtx_REG (SImode
, regno
);
3397 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
3400 XVECEXP (insn
, 0, indx
) = gen_rtx_SET (reg
, mem
);
3401 RTX_FRAME_RELATED_P (XVECEXP (insn
, 0, indx
)) = 1;
3402 gmask
= gmask
& ~(1ULL << regno
);
3407 mem
= gen_frame_mem (Pmode
, plus_constant (Pmode
,
3410 XVECEXP (insn
, 0, indx
) = gen_rtx_SET (hard_frame_pointer_rtx
, mem
);
3411 RTX_FRAME_RELATED_P (XVECEXP (insn
, 0, indx
++)) = 1;
3412 off
-= UNITS_PER_WORD
;
3415 gcc_assert (off
== 0);
3418 insn
= emit_jump_insn (insn
);
3419 RTX_FRAME_RELATED_P (insn
) = 1;
3422 insn
= frame_insn (insn
);
3424 add_reg_note (insn
, REG_INC
, stack_pointer_rtx
);
3426 /* Dwarf related info. */
3429 add_reg_note (insn
, REG_CFA_RESTORE
, hard_frame_pointer_rtx
);
3430 add_reg_note (insn
, REG_CFA_DEF_CFA
,
3431 plus_constant (Pmode
, stack_pointer_rtx
,
3432 offset
+ nregs
* UNITS_PER_WORD
));
3436 add_reg_note (insn
, REG_CFA_ADJUST_CFA
,
3437 gen_rtx_SET (stack_pointer_rtx
,
3438 plus_constant (Pmode
, stack_pointer_rtx
,
3439 nregs
* UNITS_PER_WORD
)));
3442 add_reg_note (insn
, REG_CFA_RESTORE
,
3443 gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
));
3444 for (regno
= start_reg
; regno
<= end_reg
; regno
++)
3445 add_reg_note (insn
, REG_CFA_RESTORE
, gen_rtx_REG (SImode
, regno
));
3447 frame_allocated
+= nregs
* UNITS_PER_WORD
;
3449 return frame_allocated
;
3452 /* Millicode thunks implementation:
3453 Generates calls to millicodes for registers starting from r13 to r25
3454 Present Limitations:
3455 - Only one range supported. The remaining regs will have the ordinary
3456 st and ld instructions for store and loads. Hence a gmask asking
3457 to store r13-14, r16-r25 will only generate calls to store and
3458 load r13 to r14 while store and load insns will be generated for
3459 r16 to r25 in the prologue and epilogue respectively.
3461 - Presently library only supports register ranges starting from r13.
3465 arc_save_callee_milli (uint64_t gmask
,
3468 HOST_WIDE_INT offset
,
3469 HOST_WIDE_INT reg_size
)
3473 int regno
, indx
, off
, nregs
;
3475 int frame_allocated
= 0;
3477 for (regno
= start_reg
; regno
<= end_reg
&& (gmask
& (1ULL << regno
));)
3480 end_reg
= regno
- 1;
3481 nregs
= end_reg
- start_reg
+ 1;
3482 gcc_assert (end_reg
> 14);
3485 /* Allocate space on stack for the registers, and take into account
3486 also the initial offset. The registers will be saved using
3487 offsets. N.B. OFFSET is a negative number. */
3490 reg
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
3491 frame_allocated
+= frame_save_reg (reg
, offset
);
3495 if (reg_size
|| offset
)
3497 frame_stack_add (offset
- reg_size
);
3498 frame_allocated
+= nregs
* UNITS_PER_WORD
- offset
;
3502 /* Start generate millicode call. */
3503 insn
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (nregs
+ 1));
3506 /* This is a call, we clobber blink. */
3507 XVECEXP (insn
, 0, nregs
) =
3508 gen_rtx_CLOBBER (VOIDmode
, gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
));
3510 for (regno
= start_reg
, indx
= 0, off
= 0;
3512 regno
++, indx
++, off
+= UNITS_PER_WORD
)
3514 reg
= gen_rtx_REG (SImode
, regno
);
3515 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
3518 XVECEXP (insn
, 0, indx
) = gen_rtx_SET (mem
, reg
);
3519 RTX_FRAME_RELATED_P (XVECEXP (insn
, 0, indx
)) = 1;
3520 gmask
= gmask
& ~(1ULL << regno
);
3522 insn
= frame_insn (insn
);
3524 /* Add DWARF info. */
3525 for (regno
= start_reg
, off
= 0;
3527 regno
++, off
+= UNITS_PER_WORD
)
3529 reg
= gen_rtx_REG (SImode
, regno
);
3530 mem
= gen_rtx_MEM (SImode
, plus_constant (Pmode
,
3531 stack_pointer_rtx
, off
));
3532 add_reg_note (insn
, REG_CFA_OFFSET
, gen_rtx_SET (mem
, reg
));
3536 /* In the case of millicode thunk, we need to restore the
3537 clobbered blink register. */
3538 if (arc_must_save_return_addr (cfun
))
3540 emit_insn (gen_rtx_SET (gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
),
3542 plus_constant (Pmode
,
3547 /* Save remaining registers using st instructions. */
3548 for (regno
= 0; regno
<= GMASK_LEN
; regno
++)
3550 if ((gmask
& (1ULL << regno
)) == 0)
3553 reg
= gen_rtx_REG (SImode
, regno
);
3554 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
3557 frame_move_inc (mem
, reg
, stack_pointer_rtx
, 0);
3558 frame_allocated
+= UNITS_PER_WORD
;
3559 off
+= UNITS_PER_WORD
;
3562 /* Save frame pointer if needed. First save the FP on stack, if not
3563 autosaved. Unfortunately, I cannot add it to gmask and use the
3564 above loop to save fp because our ABI states fp goes aftert all
3565 registers are saved. */
3567 frame_allocated
+= frame_save_reg (hard_frame_pointer_rtx
, offset
);
3569 /* Emit mov fp,sp. */
3570 if (arc_frame_pointer_needed ())
3571 frame_move (hard_frame_pointer_rtx
, stack_pointer_rtx
);
3573 return frame_allocated
;
3576 /* Like the previous function but restore. */
3579 arc_restore_callee_milli (uint64_t gmask
,
3583 HOST_WIDE_INT offset
)
3587 int regno
, indx
, off
, nregs
;
3589 int frame_allocated
= 0;
3591 for (regno
= start_reg
; regno
<= end_reg
&& (gmask
& (1ULL << regno
));)
3594 end_reg
= regno
- 1;
3595 nregs
= end_reg
- start_reg
+ 1;
3596 gcc_assert (end_reg
> 14);
3598 /* Emit mov fp,sp. */
3599 if (arc_frame_pointer_needed () && offset
)
3601 frame_move (stack_pointer_rtx
, hard_frame_pointer_rtx
);
3602 frame_allocated
= offset
;
3607 frame_allocated
+= frame_restore_reg (hard_frame_pointer_rtx
, 0);
3611 /* No fp involved, hence, we need to adjust the sp via an
3613 frame_stack_add (offset
);
3614 frame_allocated
+= offset
;
3618 /* Start generate millicode call. */
3619 insn
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc ((return_p
? 1 : 0)
3625 /* sibling call, the blink is restored with the help of the
3626 value held into r12. */
3627 reg
= gen_rtx_REG (Pmode
, 12);
3628 XVECEXP (insn
, 0, indx
++) = ret_rtx
;
3629 XVECEXP (insn
, 0, indx
++) =
3630 gen_rtx_SET (stack_pointer_rtx
,
3631 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
, reg
));
3632 frame_allocated
+= UNITS_PER_WORD
;
3636 /* This is a call, we clobber blink. */
3637 XVECEXP (insn
, 0, nregs
) =
3638 gen_rtx_CLOBBER (VOIDmode
, gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
));
3641 for (regno
= start_reg
, off
= 0;
3643 regno
++, indx
++, off
+= UNITS_PER_WORD
)
3645 reg
= gen_rtx_REG (SImode
, regno
);
3646 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
3649 XVECEXP (insn
, 0, indx
) = gen_rtx_SET (reg
, mem
);
3650 RTX_FRAME_RELATED_P (XVECEXP (insn
, 0, indx
)) = 1;
3651 gmask
= gmask
& ~(1ULL << regno
);
3654 /* Restore remaining registers using LD instructions. */
3655 for (regno
= 0; regno
<= GMASK_LEN
; regno
++)
3657 if ((gmask
& (1ULL << regno
)) == 0)
3660 reg
= gen_rtx_REG (SImode
, regno
);
3661 mem
= gen_frame_mem (SImode
, plus_constant (Pmode
,
3664 rtx tmp
= frame_move_inc (reg
, mem
, stack_pointer_rtx
, 0);
3665 add_reg_note (tmp
, REG_CFA_RESTORE
, reg
);
3666 off
+= UNITS_PER_WORD
;
3669 /* Emit millicode call. */
3672 reg
= gen_rtx_REG (Pmode
, 12);
3673 frame_insn (gen_rtx_SET (reg
, GEN_INT (off
)));
3674 frame_allocated
+= off
;
3675 insn
= emit_jump_insn (insn
);
3676 RTX_FRAME_RELATED_P (insn
) = 1;
3679 insn
= frame_insn (insn
);
3681 /* Add DWARF info. */
3682 for (regno
= start_reg
; regno
<= end_reg
; regno
++)
3684 reg
= gen_rtx_REG (SImode
, regno
);
3685 add_reg_note (insn
, REG_CFA_RESTORE
, reg
);
3689 if (restore_blink
&& !return_p
)
3691 reg
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
3692 mem
= gen_frame_mem (Pmode
, plus_constant (Pmode
, stack_pointer_rtx
,
3694 insn
= frame_insn (gen_rtx_SET (reg
, mem
));
3695 add_reg_note (insn
, REG_CFA_RESTORE
, reg
);
3698 return frame_allocated
;
3701 /* Set up the stack and frame pointer (if desired) for the function. */
3704 arc_expand_prologue (void)
3707 uint64_t gmask
= cfun
->machine
->frame_info
.gmask
;
3708 struct arc_frame_info
*frame
= &cfun
->machine
->frame_info
;
3709 unsigned int frame_size_to_allocate
;
3710 int first_offset
= 0;
3711 unsigned int fn_type
= arc_compute_function_type (cfun
);
3712 bool save_blink
= false;
3713 bool save_fp
= false;
3714 bool emit_move
= false;
3716 /* Naked functions don't have prologue. */
3717 if (ARC_NAKED_P (fn_type
))
3719 if (flag_stack_usage_info
)
3720 current_function_static_stack_size
= 0;
3724 /* Compute total frame size. */
3725 size
= arc_compute_frame_size ();
3727 if (flag_stack_usage_info
)
3728 current_function_static_stack_size
= size
;
3730 /* Keep track of frame size to be allocated. */
3731 frame_size_to_allocate
= size
;
3733 /* These cases shouldn't happen. Catch them now. */
3734 gcc_assert (!(size
== 0 && gmask
));
3736 /* Allocate space for register arguments if this is a variadic function. */
3737 if (frame
->pretend_size
!= 0)
3738 first_offset
= -frame
->pretend_size
;
3740 /* IRQ using automatic save mechanism will save the register before
3742 if (ARC_AUTO_IRQ_P (fn_type
)
3743 && !ARC_FAST_INTERRUPT_P (fn_type
))
3745 frame_stack_add (first_offset
);
3747 arc_dwarf_emit_irq_save_regs ();
3750 save_blink
= arc_must_save_return_addr (cfun
)
3751 && !ARC_AUTOBLINK_IRQ_P (fn_type
);
3752 save_fp
= arc_frame_pointer_needed () && !ARC_AUTOFP_IRQ_P (fn_type
)
3753 && !ARC_INTERRUPT_P (fn_type
);
3754 emit_move
= arc_frame_pointer_needed () && !ARC_INTERRUPT_P (fn_type
);
3756 /* Use enter/leave only for non-interrupt functions. */
3757 if (TARGET_CODE_DENSITY
3758 && TARGET_CODE_DENSITY_FRAME
3759 && !ARC_AUTOFP_IRQ_P (fn_type
)
3760 && !ARC_AUTOBLINK_IRQ_P (fn_type
)
3761 && !ARC_INTERRUPT_P (fn_type
)
3762 && arc_enter_leave_p (gmask
))
3763 frame_size_to_allocate
-= arc_save_callee_enter (gmask
, save_blink
,
3766 else if (frame
->millicode_end_reg
> 14)
3767 frame_size_to_allocate
-= arc_save_callee_milli (gmask
, save_blink
,
3772 frame_size_to_allocate
-= arc_save_callee_saves (gmask
, save_blink
, save_fp
,
3773 first_offset
, emit_move
);
3775 /* Check if we need to save the ZOL machinery. */
3776 if (arc_lpcwidth
!= 0 && arc_must_save_register (LP_COUNT
, cfun
, true))
3778 rtx reg0
= gen_rtx_REG (SImode
, R0_REG
);
3779 emit_insn (gen_rtx_SET (reg0
,
3780 gen_rtx_UNSPEC_VOLATILE
3781 (Pmode
, gen_rtvec (1, GEN_INT (AUX_LP_START
)),
3783 frame_size_to_allocate
-= push_reg (reg0
);
3784 emit_insn (gen_rtx_SET (reg0
,
3785 gen_rtx_UNSPEC_VOLATILE
3786 (Pmode
, gen_rtvec (1, GEN_INT (AUX_LP_END
)),
3788 frame_size_to_allocate
-= push_reg (reg0
);
3789 emit_move_insn (reg0
, gen_rtx_REG (SImode
, LP_COUNT
));
3790 frame_size_to_allocate
-= push_reg (reg0
);
3793 /* Save AUX regs used by FPX machinery. */
3794 if (arc_must_save_register (TARGET_BIG_ENDIAN
? R41_REG
: R40_REG
,
3797 rtx reg0
= gen_rtx_REG (SImode
, R0_REG
);
3800 for (i
= 0; i
< 4; i
++)
3802 emit_insn (gen_rtx_SET (reg0
,
3803 gen_rtx_UNSPEC_VOLATILE
3804 (Pmode
, gen_rtvec (1, GEN_INT (AUX_DPFP_START
3807 frame_size_to_allocate
-= push_reg (reg0
);
3811 /* Save accumulator registers. */
3812 if (arc_must_save_register (R58_REG
, cfun
, true))
3813 frame_size_to_allocate
-= arc_save_callee_saves (3ULL << 58,
3814 false, false, 0, false);
3816 if (arc_frame_pointer_needed () && ARC_INTERRUPT_P (fn_type
))
3818 /* Just save fp at the end of the saving context. */
3819 frame_size_to_allocate
-=
3820 arc_save_callee_saves (0, false, !ARC_AUTOFP_IRQ_P (fn_type
), 0, true);
3823 /* Allocate the stack frame. */
3824 if (frame_size_to_allocate
> 0)
3825 frame_stack_add ((HOST_WIDE_INT
) 0 - frame_size_to_allocate
);
3827 /* Emit a blockage to avoid delay slot scheduling. */
3828 emit_insn (gen_blockage ());
3831 /* Return the register number of the register holding the return address
3832 for a function of type TYPE. */
3835 arc_return_address_register (unsigned int fn_type
)
3839 if (ARC_INTERRUPT_P (fn_type
))
3841 if ((fn_type
& (ARC_FUNCTION_ILINK1
| ARC_FUNCTION_FIRQ
)) != 0)
3843 else if ((fn_type
& ARC_FUNCTION_ILINK2
) != 0)
3848 else if (ARC_NORMAL_P (fn_type
) || ARC_NAKED_P (fn_type
))
3849 regno
= RETURN_ADDR_REGNUM
;
3851 gcc_assert (regno
!= 0);
3855 /* Do any necessary cleanup after a function to restore stack, frame,
3859 arc_expand_epilogue (int sibcall_p
)
3862 unsigned int fn_type
= arc_compute_function_type (cfun
);
3863 unsigned int size_to_deallocate
;
3865 int can_trust_sp_p
= !cfun
->calls_alloca
;
3867 bool restore_fp
= arc_frame_pointer_needed () && !ARC_AUTOFP_IRQ_P (fn_type
);
3868 bool restore_blink
= arc_must_save_return_addr (cfun
)
3869 && !ARC_AUTOBLINK_IRQ_P (fn_type
);
3870 uint64_t gmask
= cfun
->machine
->frame_info
.gmask
;
3871 bool return_p
= !sibcall_p
&& fn_type
== ARC_FUNCTION_NORMAL
3872 && !cfun
->machine
->frame_info
.pretend_size
;
3873 struct arc_frame_info
*frame
= &cfun
->machine
->frame_info
;
3875 /* Naked functions don't have epilogue. */
3876 if (ARC_NAKED_P (fn_type
))
3879 size
= arc_compute_frame_size ();
3880 size_to_deallocate
= size
;
3882 first_offset
= size
- (frame
->pretend_size
+ frame
->reg_size
3883 + frame
->extra_size
);
3885 if (!can_trust_sp_p
)
3886 gcc_assert (arc_frame_pointer_needed ());
3888 /* Emit a blockage to avoid/flush all pending sp operations. */
3890 emit_insn (gen_blockage ());
3892 if (ARC_INTERRUPT_P (fn_type
))
3894 /* We need to restore FP before any SP operation in an
3896 size_to_deallocate
-= arc_restore_callee_saves (0, false,
3899 size_to_deallocate
);
3904 /* Restore accumulator registers. */
3905 if (arc_must_save_register (R58_REG
, cfun
, true))
3908 rtx reg0
= gen_rtx_REG (SImode
, R0_REG
);
3909 rtx reg1
= gen_rtx_REG (SImode
, R1_REG
);
3910 size_to_deallocate
-= pop_reg (reg0
);
3911 size_to_deallocate
-= pop_reg (reg1
);
3913 insn
= emit_insn (gen_mulu64 (reg0
, const1_rtx
));
3914 add_reg_note (insn
, REG_CFA_RESTORE
, gen_rtx_REG (SImode
, R58_REG
));
3915 RTX_FRAME_RELATED_P (insn
) = 1;
3916 emit_insn (gen_arc600_stall ());
3917 insn
= emit_insn (gen_rtx_UNSPEC_VOLATILE
3918 (VOIDmode
, gen_rtvec (2, reg1
, GEN_INT (AUX_MULHI
)),
3920 add_reg_note (insn
, REG_CFA_RESTORE
, gen_rtx_REG (SImode
, R59_REG
));
3921 RTX_FRAME_RELATED_P (insn
) = 1;
3924 /* Restore AUX-regs used by FPX machinery. */
3925 if (arc_must_save_register (TARGET_BIG_ENDIAN
? R41_REG
: R40_REG
,
3928 rtx reg0
= gen_rtx_REG (SImode
, R0_REG
);
3931 for (i
= 0; i
< 4; i
++)
3933 size_to_deallocate
-= pop_reg (reg0
);
3934 emit_insn (gen_rtx_UNSPEC_VOLATILE
3935 (VOIDmode
, gen_rtvec (2, reg0
, GEN_INT (AUX_DPFP_START
3941 /* Check if we need to restore the ZOL machinery. */
3942 if (arc_lpcwidth
!=0 && arc_must_save_register (LP_COUNT
, cfun
, true))
3944 rtx reg0
= gen_rtx_REG (SImode
, R0_REG
);
3946 size_to_deallocate
-= pop_reg (reg0
);
3947 emit_move_insn (gen_rtx_REG (SImode
, LP_COUNT
), reg0
);
3949 size_to_deallocate
-= pop_reg (reg0
);
3950 emit_insn (gen_rtx_UNSPEC_VOLATILE
3951 (VOIDmode
, gen_rtvec (2, reg0
, GEN_INT (AUX_LP_END
)),
3954 size_to_deallocate
-= pop_reg (reg0
);
3955 emit_insn (gen_rtx_UNSPEC_VOLATILE
3956 (VOIDmode
, gen_rtvec (2, reg0
, GEN_INT (AUX_LP_START
)),
3960 if (TARGET_CODE_DENSITY
3961 && TARGET_CODE_DENSITY_FRAME
3962 && !ARC_AUTOFP_IRQ_P (fn_type
)
3963 && !ARC_AUTOBLINK_IRQ_P (fn_type
)
3964 && !ARC_INTERRUPT_P (fn_type
)
3965 && arc_enter_leave_p (gmask
))
3967 /* Using leave instruction. */
3968 size_to_deallocate
-= arc_restore_callee_leave (gmask
, restore_blink
,
3974 gcc_assert (size_to_deallocate
== 0);
3978 else if (frame
->millicode_end_reg
> 14)
3980 /* Using millicode calls. */
3981 size_to_deallocate
-= arc_restore_callee_milli (gmask
, restore_blink
,
3987 gcc_assert (size_to_deallocate
== 0);
3992 size_to_deallocate
-= arc_restore_callee_saves (gmask
, restore_blink
,
3995 size_to_deallocate
);
3997 /* Keep track of how much of the stack pointer we've restored. It
3998 makes the following a lot more readable. */
3999 restored
= size
- size_to_deallocate
;
4001 if (size
> restored
)
4002 frame_stack_add (size
- restored
);
4004 /* For frames that use __builtin_eh_return, the register defined by
4005 EH_RETURN_STACKADJ_RTX is set to 0 for all standard return paths.
4006 On eh_return paths however, the register is set to the value that
4007 should be added to the stack pointer in order to restore the
4008 correct stack pointer for the exception handling frame.
4010 For ARC we are going to use r2 for EH_RETURN_STACKADJ_RTX, add
4011 this onto the stack for eh_return frames. */
4012 if (crtl
->calls_eh_return
)
4013 emit_insn (gen_add2_insn (stack_pointer_rtx
,
4014 EH_RETURN_STACKADJ_RTX
));
4016 /* Emit the return instruction. */
4017 if (ARC_INTERRUPT_P (fn_type
))
4019 rtx ra
= gen_rtx_REG (Pmode
, arc_return_address_register (fn_type
));
4022 emit_jump_insn (gen_rtie ());
4023 else if (TARGET_ARC700
)
4024 emit_jump_insn (gen_rtie ());
4026 emit_jump_insn (gen_arc600_rtie (ra
));
4028 else if (sibcall_p
== FALSE
)
4029 emit_jump_insn (gen_simple_return ());
4032 /* Helper for {push/pop}_multi_operand: check if rtx OP is a suitable
4033 construct to match either enter or leave instruction. Which one
4034 which is selected by PUSH_P argument. */
4037 arc_check_multi (rtx op
, bool push_p
)
4039 HOST_WIDE_INT len
= XVECLEN (op
, 0);
4040 unsigned int regno
, i
, start
;
4041 unsigned int memp
= push_p
? 0 : 1;
4048 elt
= XVECEXP (op
, 0, 0);
4049 if (!push_p
&& GET_CODE (elt
) == RETURN
)
4052 for (i
= start
, regno
= ENTER_LEAVE_START_REG
; i
< len
; i
++, regno
++)
4054 rtx elt
= XVECEXP (op
, 0, i
);
4057 if (GET_CODE (elt
) != SET
)
4059 mem
= XEXP (elt
, memp
);
4060 reg
= XEXP (elt
, 1 - memp
);
4066 /* Check for blink. */
4067 if (REGNO (reg
) == RETURN_ADDR_REGNUM
4070 else if (REGNO (reg
) == HARD_FRAME_POINTER_REGNUM
)
4072 else if (REGNO (reg
) != regno
)
4075 addr
= XEXP (mem
, 0);
4076 if (GET_CODE (addr
) == PLUS
)
4078 if (!rtx_equal_p (stack_pointer_rtx
, XEXP (addr
, 0))
4079 || !CONST_INT_P (XEXP (addr
, 1)))
4084 if (!rtx_equal_p (stack_pointer_rtx
, addr
))
4091 /* Return rtx for the location of the return address on the stack,
4092 suitable for use in __builtin_eh_return. The new return address
4093 will be written to this location in order to redirect the return to
4094 the exception handler. Our ABI says the blink is pushed first on
4095 stack followed by an unknown number of register saves, and finally
4096 by fp. Hence we cannot use the EH_RETURN_ADDRESS macro as the
4097 stack is not finalized. */
4100 arc_eh_return_address_location (rtx source
)
4104 struct arc_frame_info
*afi
;
4106 arc_compute_frame_size ();
4107 afi
= &cfun
->machine
->frame_info
;
4109 gcc_assert (crtl
->calls_eh_return
);
4110 gcc_assert (afi
->save_return_addr
);
4111 gcc_assert (afi
->extra_size
>= 4);
4113 /* The '-4' removes the size of the return address, which is
4114 included in the 'extra_size' field. */
4115 offset
= afi
->reg_size
+ afi
->extra_size
- 4;
4116 mem
= gen_frame_mem (Pmode
,
4117 plus_constant (Pmode
, hard_frame_pointer_rtx
, offset
));
4119 /* The following should not be needed, and is, really a hack. The
4120 issue being worked around here is that the DSE (Dead Store
4121 Elimination) pass will remove this write to the stack as it sees
4122 a single store and no corresponding read. The read however
4123 occurs in the epilogue code, which is not added into the function
4124 rtl until a later pass. So, at the time of DSE, the decision to
4125 remove this store seems perfectly sensible. Marking the memory
4126 address as volatile obviously has the effect of preventing DSE
4127 from removing the store. */
4128 MEM_VOLATILE_P (mem
) = true;
4129 emit_move_insn (mem
, source
);
4134 /* Helper to generate unspec constant. */
4137 arc_unspec_offset (rtx loc
, int unspec
)
4139 return gen_rtx_CONST (Pmode
, gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, loc
),
4143 /* Predicate for pre-reload splitters with associated instructions,
4144 which can match any time before the split1 pass (usually combine),
4145 then are unconditionally split in that pass and should not be
4146 matched again afterwards. */
4149 arc_pre_reload_split (void)
4151 return (can_create_pseudo_p ()
4152 && !(cfun
->curr_properties
& PROP_rtl_split_insns
));
4155 /* Output the assembler code for a zero-overhead loop doing a shift
4156 or rotate. We know OPERANDS[0] == OPERANDS[1], and the bit count
4160 output_shift_loop (enum rtx_code code
, rtx
*operands
)
4162 bool twice_p
= false;
4163 gcc_assert (GET_MODE (operands
[0]) == SImode
);
4165 if (GET_CODE (operands
[2]) != CONST_INT
)
4167 output_asm_insn ("and.f\tlp_count,%2,0x1f", operands
);
4168 output_asm_insn ("lpnz\t2f", operands
);
4172 int n
= INTVAL (operands
[2]) & 31;
4175 output_asm_insn ("mov\t%0,%1",operands
);
4179 if ((n
& 1) == 0 && code
!= ROTATE
)
4184 operands
[2] = GEN_INT (n
);
4185 output_asm_insn ("mov\tlp_count,%2", operands
);
4186 output_asm_insn ("lp\t2f", operands
);
4192 output_asm_insn ("add\t%0,%1,%1", operands
);
4194 output_asm_insn ("add\t%0,%1,%1", operands
);
4197 output_asm_insn ("asr\t%0,%1", operands
);
4199 output_asm_insn ("asr\t%0,%1", operands
);
4202 output_asm_insn ("lsr\t%0,%1", operands
);
4204 output_asm_insn ("lsr\t%0,%1", operands
);
4207 output_asm_insn ("ror\t%0,%1", operands
);
4209 output_asm_insn ("ror\t%0,%1", operands
);
4212 output_asm_insn ("add.f\t%0,%1,%1", operands
);
4213 output_asm_insn ("adc\t%0,%0,0", operands
);
4221 output_asm_insn ("nop", operands
);
4222 fprintf (asm_out_file
, "2:\t%s end single insn loop\n", ASM_COMMENT_START
);
4226 /* See below where shifts are handled for explanation of this enum. */
4229 SHIFT_MOVE
, /* Register-to-register move. */
4230 SHIFT_LOOP
, /* Zero-overhead loop implementation. */
4231 SHIFT_INLINE
, /* Mmultiple LSHIFTs and LSHIFT-PLUSs. */
4232 SHIFT_AND_ROT
, /* Bitwise AND, then ROTATERTs. */
4233 SHIFT_SWAP
, /* SWAP then multiple LSHIFTs/LSHIFT-PLUSs. */
4234 SHIFT_AND_SWAP_ROT
/* Bitwise AND, then SWAP, then ROTATERTs. */
4237 struct arc_shift_info
{
4238 enum arc_shift_alg alg
;
4242 /* Return shift algorithm context, an index into the following tables.
4243 * 0 for -Os (optimize for size) 3 for -O2 (optimized for speed)
4244 * 1 for -Os -mswap TARGET_V2 4 for -O2 -mswap TARGET_V2
4245 * 2 for -Os -mswap !TARGET_V2 5 for -O2 -mswap !TARGET_V2 */
4247 arc_shift_context_idx ()
4249 if (optimize_function_for_size_p (cfun
))
4267 static const arc_shift_info arc_ashl_alg
[6][32] = {
4269 { SHIFT_MOVE
, COSTS_N_INSNS (1) }, /* 0 */
4270 { SHIFT_INLINE
, COSTS_N_INSNS (1) }, /* 1 */
4271 { SHIFT_INLINE
, COSTS_N_INSNS (2) }, /* 2 */
4272 { SHIFT_INLINE
, COSTS_N_INSNS (2) }, /* 3 */
4273 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 4 */
4274 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 5 */
4275 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 6 */
4276 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 7 */
4277 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 8 */
4278 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 9 */
4279 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 10 */
4280 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 11 */
4281 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 12 */
4282 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 13 */
4283 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 14 */
4284 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 15 */
4285 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 16 */
4286 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 17 */
4287 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 18 */
4288 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 19 */
4289 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 20 */
4290 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 21 */
4291 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 22 */
4292 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 23 */
4293 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 24 */
4294 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 25 */
4295 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 26 */
4296 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 27 */
4297 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 28 */
4298 { SHIFT_AND_ROT
, COSTS_N_INSNS (4) }, /* 29 */
4299 { SHIFT_AND_ROT
, COSTS_N_INSNS (3) }, /* 30 */
4300 { SHIFT_AND_ROT
, COSTS_N_INSNS (2) } /* 31 */
4302 { /* 1: -Os -mswap TARGET_V2. */
4303 { SHIFT_MOVE
, COSTS_N_INSNS (1) }, /* 0 */
4304 { SHIFT_INLINE
, COSTS_N_INSNS (1) }, /* 1 */
4305 { SHIFT_INLINE
, COSTS_N_INSNS (2) }, /* 2 */
4306 { SHIFT_INLINE
, COSTS_N_INSNS (2) }, /* 3 */
4307 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 4 */
4308 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 5 */
4309 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 6 */
4310 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 7 */
4311 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 8 */
4312 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 9 */
4313 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 10 */
4314 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 11 */
4315 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 12 */
4316 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 13 */
4317 { SHIFT_AND_SWAP_ROT
, COSTS_N_INSNS (4) }, /* 14 */
4318 { SHIFT_AND_SWAP_ROT
, COSTS_N_INSNS (3) }, /* 15 */
4319 { SHIFT_SWAP
, COSTS_N_INSNS (1) }, /* 16 */
4320 { SHIFT_SWAP
, COSTS_N_INSNS (2) }, /* 17 */
4321 { SHIFT_SWAP
, COSTS_N_INSNS (3) }, /* 18 */
4322 { SHIFT_SWAP
, COSTS_N_INSNS (3) }, /* 19 */
4323 { SHIFT_SWAP
, COSTS_N_INSNS (4) }, /* 20 */
4324 { SHIFT_SWAP
, COSTS_N_INSNS (4) }, /* 21 */
4325 { SHIFT_SWAP
, COSTS_N_INSNS (4) }, /* 22 */
4326 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 23 */
4327 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 24 */
4328 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 25 */
4329 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 26 */
4330 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 27 */
4331 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 28 */
4332 { SHIFT_AND_ROT
, COSTS_N_INSNS (4) }, /* 29 */
4333 { SHIFT_AND_ROT
, COSTS_N_INSNS (3) }, /* 30 */
4334 { SHIFT_AND_ROT
, COSTS_N_INSNS (2) } /* 31 */
4336 { /* 2: -Os -mswap !TARGET_V2. */
4337 { SHIFT_MOVE
, COSTS_N_INSNS (1) }, /* 0 */
4338 { SHIFT_INLINE
, COSTS_N_INSNS (1) }, /* 1 */
4339 { SHIFT_INLINE
, COSTS_N_INSNS (2) }, /* 2 */
4340 { SHIFT_INLINE
, COSTS_N_INSNS (2) }, /* 3 */
4341 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 4 */
4342 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 5 */
4343 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 6 */
4344 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 7 */
4345 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 8 */
4346 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 9 */
4347 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 10 */
4348 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 11 */
4349 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 12 */
4350 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 13 */
4351 { SHIFT_AND_SWAP_ROT
, COSTS_N_INSNS (4) }, /* 14 */
4352 { SHIFT_AND_SWAP_ROT
, COSTS_N_INSNS (3) }, /* 15 */
4353 { SHIFT_SWAP
, COSTS_N_INSNS (2) }, /* 16 */
4354 { SHIFT_SWAP
, COSTS_N_INSNS (3) }, /* 17 */
4355 { SHIFT_SWAP
, COSTS_N_INSNS (4) }, /* 18 */
4356 { SHIFT_SWAP
, COSTS_N_INSNS (4) }, /* 19 */
4357 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 20 */
4358 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 21 */
4359 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 22 */
4360 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 23 */
4361 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 24 */
4362 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 25 */
4363 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 26 */
4364 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 27 */
4365 { SHIFT_LOOP
, COSTS_N_INSNS (4) }, /* 28 */
4366 { SHIFT_AND_ROT
, COSTS_N_INSNS (4) }, /* 29 */
4367 { SHIFT_AND_ROT
, COSTS_N_INSNS (3) }, /* 30 */
4368 { SHIFT_AND_ROT
, COSTS_N_INSNS (2) } /* 31 */
4371 { SHIFT_MOVE
, COSTS_N_INSNS (1) }, /* 0 */
4372 { SHIFT_INLINE
, COSTS_N_INSNS (1) }, /* 1 */
4373 { SHIFT_INLINE
, COSTS_N_INSNS (2) }, /* 2 */
4374 { SHIFT_INLINE
, COSTS_N_INSNS (2) }, /* 3 */
4375 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 4 */
4376 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 5 */
4377 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 6 */
4378 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 7 */
4379 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 8 */
4380 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 9 */
4381 { SHIFT_INLINE
, COSTS_N_INSNS (5) }, /* 10 */
4382 { SHIFT_INLINE
, COSTS_N_INSNS (5) }, /* 11 */
4383 { SHIFT_INLINE
, COSTS_N_INSNS (5) }, /* 12 */
4384 { SHIFT_INLINE
, COSTS_N_INSNS (6) }, /* 13 */
4385 { SHIFT_INLINE
, COSTS_N_INSNS (6) }, /* 14 */
4386 { SHIFT_INLINE
, COSTS_N_INSNS (6) }, /* 15 */
4387 { SHIFT_INLINE
, COSTS_N_INSNS (7) }, /* 16 */
4388 { SHIFT_INLINE
, COSTS_N_INSNS (7) }, /* 17 */
4389 { SHIFT_INLINE
, COSTS_N_INSNS (7) }, /* 18 */
4390 { SHIFT_INLINE
, COSTS_N_INSNS (8) }, /* 19 */
4391 { SHIFT_INLINE
, COSTS_N_INSNS (8) }, /* 20 */
4392 { SHIFT_INLINE
, COSTS_N_INSNS (8) }, /* 21 */
4393 { SHIFT_INLINE
, COSTS_N_INSNS (9) }, /* 22 */
4394 { SHIFT_INLINE
, COSTS_N_INSNS (9) }, /* 23 */
4395 { SHIFT_AND_ROT
, COSTS_N_INSNS (9) }, /* 24 */
4396 { SHIFT_AND_ROT
, COSTS_N_INSNS (8) }, /* 25 */
4397 { SHIFT_AND_ROT
, COSTS_N_INSNS (7) }, /* 26 */
4398 { SHIFT_AND_ROT
, COSTS_N_INSNS (6) }, /* 27 */
4399 { SHIFT_AND_ROT
, COSTS_N_INSNS (5) }, /* 28 */
4400 { SHIFT_AND_ROT
, COSTS_N_INSNS (4) }, /* 29 */
4401 { SHIFT_AND_ROT
, COSTS_N_INSNS (3) }, /* 30 */
4402 { SHIFT_AND_ROT
, COSTS_N_INSNS (2) } /* 31 */
4404 { /* 4: -O2 -mswap TARGET_V2. */
4405 { SHIFT_MOVE
, COSTS_N_INSNS (1) }, /* 0 */
4406 { SHIFT_INLINE
, COSTS_N_INSNS (1) }, /* 1 */
4407 { SHIFT_INLINE
, COSTS_N_INSNS (2) }, /* 2 */
4408 { SHIFT_INLINE
, COSTS_N_INSNS (2) }, /* 3 */
4409 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 4 */
4410 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 5 */
4411 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 6 */
4412 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 7 */
4413 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 8 */
4414 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 9 */
4415 { SHIFT_INLINE
, COSTS_N_INSNS (5) }, /* 10 */
4416 { SHIFT_INLINE
, COSTS_N_INSNS (5) }, /* 11 */
4417 { SHIFT_INLINE
, COSTS_N_INSNS (5) }, /* 12 */
4418 { SHIFT_AND_SWAP_ROT
, COSTS_N_INSNS (5) }, /* 13 */
4419 { SHIFT_AND_SWAP_ROT
, COSTS_N_INSNS (4) }, /* 14 */
4420 { SHIFT_AND_SWAP_ROT
, COSTS_N_INSNS (3) }, /* 15 */
4421 { SHIFT_SWAP
, COSTS_N_INSNS (1) }, /* 16 */
4422 { SHIFT_SWAP
, COSTS_N_INSNS (2) }, /* 17 */
4423 { SHIFT_SWAP
, COSTS_N_INSNS (3) }, /* 18 */
4424 { SHIFT_SWAP
, COSTS_N_INSNS (3) }, /* 19 */
4425 { SHIFT_SWAP
, COSTS_N_INSNS (4) }, /* 20 */
4426 { SHIFT_SWAP
, COSTS_N_INSNS (4) }, /* 21 */
4427 { SHIFT_SWAP
, COSTS_N_INSNS (4) }, /* 22 */
4428 { SHIFT_SWAP
, COSTS_N_INSNS (5) }, /* 23 */
4429 { SHIFT_SWAP
, COSTS_N_INSNS (5) }, /* 24 */
4430 { SHIFT_SWAP
, COSTS_N_INSNS (5) }, /* 25 */
4431 { SHIFT_SWAP
, COSTS_N_INSNS (6) }, /* 26 */
4432 { SHIFT_AND_ROT
, COSTS_N_INSNS (6) }, /* 27 */
4433 { SHIFT_AND_ROT
, COSTS_N_INSNS (5) }, /* 28 */
4434 { SHIFT_AND_ROT
, COSTS_N_INSNS (4) }, /* 29 */
4435 { SHIFT_AND_ROT
, COSTS_N_INSNS (3) }, /* 30 */
4436 { SHIFT_AND_ROT
, COSTS_N_INSNS (2) } /* 31 */
4438 { /* 5: -O2 -mswap !TARGET_V2. */
4439 { SHIFT_MOVE
, COSTS_N_INSNS (1) }, /* 0 */
4440 { SHIFT_INLINE
, COSTS_N_INSNS (1) }, /* 1 */
4441 { SHIFT_INLINE
, COSTS_N_INSNS (2) }, /* 2 */
4442 { SHIFT_INLINE
, COSTS_N_INSNS (2) }, /* 3 */
4443 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 4 */
4444 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 5 */
4445 { SHIFT_INLINE
, COSTS_N_INSNS (3) }, /* 6 */
4446 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 7 */
4447 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 8 */
4448 { SHIFT_INLINE
, COSTS_N_INSNS (4) }, /* 9 */
4449 { SHIFT_INLINE
, COSTS_N_INSNS (5) }, /* 10 */
4450 { SHIFT_INLINE
, COSTS_N_INSNS (5) }, /* 11 */
4451 { SHIFT_INLINE
, COSTS_N_INSNS (5) }, /* 12 */
4452 { SHIFT_AND_SWAP_ROT
, COSTS_N_INSNS (5) }, /* 13 */
4453 { SHIFT_AND_SWAP_ROT
, COSTS_N_INSNS (4) }, /* 14 */
4454 { SHIFT_AND_SWAP_ROT
, COSTS_N_INSNS (3) }, /* 15 */
4455 { SHIFT_SWAP
, COSTS_N_INSNS (2) }, /* 16 */
4456 { SHIFT_SWAP
, COSTS_N_INSNS (3) }, /* 17 */
4457 { SHIFT_SWAP
, COSTS_N_INSNS (4) }, /* 18 */
4458 { SHIFT_SWAP
, COSTS_N_INSNS (4) }, /* 19 */
4459 { SHIFT_SWAP
, COSTS_N_INSNS (5) }, /* 20 */
4460 { SHIFT_SWAP
, COSTS_N_INSNS (5) }, /* 21 */
4461 { SHIFT_SWAP
, COSTS_N_INSNS (5) }, /* 22 */
4462 { SHIFT_SWAP
, COSTS_N_INSNS (6) }, /* 23 */
4463 { SHIFT_SWAP
, COSTS_N_INSNS (6) }, /* 24 */
4464 { SHIFT_SWAP
, COSTS_N_INSNS (6) }, /* 25 */
4465 { SHIFT_AND_ROT
, COSTS_N_INSNS (7) }, /* 26 */
4466 { SHIFT_AND_ROT
, COSTS_N_INSNS (6) }, /* 27 */
4467 { SHIFT_AND_ROT
, COSTS_N_INSNS (5) }, /* 28 */
4468 { SHIFT_AND_ROT
, COSTS_N_INSNS (4) }, /* 29 */
4469 { SHIFT_AND_ROT
, COSTS_N_INSNS (3) }, /* 30 */
4470 { SHIFT_AND_ROT
, COSTS_N_INSNS (2) } /* 31 */
4474 /* Split SImode left shift instruction. */
4476 arc_split_ashl (rtx
*operands
)
4478 if (CONST_INT_P (operands
[2]))
4480 int n
= INTVAL (operands
[2]) & 0x1f;
4481 switch (arc_ashl_alg
[arc_shift_context_idx ()][n
].alg
)
4484 emit_move_insn (operands
[0], operands
[1]);
4490 emit_insn (gen_andsi3_i (operands
[0], operands
[1],
4492 emit_insn (gen_rotrsi2_cnt16 (operands
[0], operands
[0]));
4495 emit_insn (gen_ashlsi2_cnt16 (operands
[0], operands
[1]));
4499 operands
[1] = operands
[0];
4505 emit_insn (gen_ashlsi3_cnt1 (operands
[0], operands
[1]));
4507 emit_insn (gen_ashlsi3_cnt1 (operands
[0], operands
[0]));
4511 rtx zero
= gen_reg_rtx (SImode
);
4512 emit_move_insn (zero
, const0_rtx
);
4513 emit_insn (gen_add_shift (operands
[0], operands
[1],
4514 GEN_INT (3), zero
));
4515 for (n
-= 3; n
>= 3; n
-= 3)
4516 emit_insn (gen_add_shift (operands
[0], operands
[0],
4517 GEN_INT (3), zero
));
4519 emit_insn (gen_add_shift (operands
[0], operands
[0],
4522 emit_insn (gen_ashlsi3_cnt1 (operands
[0], operands
[0]));
4527 emit_insn (gen_andsi3_i (operands
[0], operands
[1],
4528 GEN_INT ((1 << (32 - n
)) - 1)));
4530 emit_insn (gen_rotrsi3_cnt1 (operands
[0], operands
[0]));
4533 case SHIFT_AND_SWAP_ROT
:
4534 emit_insn (gen_andsi3_i (operands
[0], operands
[1],
4535 GEN_INT ((1 << (32 - n
)) - 1)));
4536 emit_insn (gen_rotrsi2_cnt16 (operands
[0], operands
[0]));
4538 emit_insn (gen_rotrsi3_cnt1 (operands
[0], operands
[0]));
4549 emit_insn (gen_ashlsi3_loop (operands
[0], operands
[1], operands
[2]));
4552 /* Split SImode arithmetic right shift instruction. */
4554 arc_split_ashr (rtx
*operands
)
4556 if (CONST_INT_P (operands
[2]))
4558 int n
= INTVAL (operands
[2]) & 0x1f;
4563 emit_insn (gen_ashrsi3_cnt1 (operands
[0], operands
[1]));
4565 emit_insn (gen_ashrsi3_cnt1 (operands
[0], operands
[0]));
4568 emit_move_insn (operands
[0], operands
[1]);
4571 else if (n
>= 16 && n
<= 18 && TARGET_SWAP
)
4573 emit_insn (gen_rotrsi2_cnt16 (operands
[0], operands
[1]));
4574 emit_insn (gen_extendhisi2 (operands
[0],
4575 gen_lowpart (HImode
, operands
[0])));
4577 emit_insn (gen_ashrsi3_cnt1 (operands
[0], operands
[0]));
4582 rtx tmp
= gen_reg_rtx (SImode
);
4583 emit_insn (gen_add_f (tmp
, operands
[1], operands
[1]));
4584 emit_insn (gen_sbc (operands
[0], operands
[0], operands
[0]));
4585 emit_insn (gen_addsi_compare_2 (tmp
, tmp
));
4586 emit_insn (gen_adc (operands
[0], operands
[0], operands
[0]));
4591 emit_insn (gen_addsi_compare_2 (operands
[1], operands
[1]));
4592 emit_insn (gen_sbc (operands
[0], operands
[0], operands
[0]));
4597 emit_insn (gen_ashrsi3_loop (operands
[0], operands
[1], operands
[2]));
4600 /* Split SImode logical right shift instruction. */
4602 arc_split_lshr (rtx
*operands
)
4604 if (CONST_INT_P (operands
[2]))
4606 int n
= INTVAL (operands
[2]) & 0x1f;
4611 emit_insn (gen_lshrsi3_cnt1 (operands
[0], operands
[1]));
4613 emit_insn (gen_lshrsi3_cnt1 (operands
[0], operands
[0]));
4616 emit_move_insn (operands
[0], operands
[1]);
4619 else if (n
>= 16 && n
<= 19 && TARGET_SWAP
&& TARGET_V2
)
4621 emit_insn (gen_lshrsi2_cnt16 (operands
[0], operands
[1]));
4623 emit_insn (gen_lshrsi3_cnt1 (operands
[0], operands
[0]));
4628 rtx tmp
= gen_reg_rtx (SImode
);
4629 emit_insn (gen_add_f (tmp
, operands
[1], operands
[1]));
4630 emit_insn (gen_scc_ltu_cc_c (operands
[0]));
4631 emit_insn (gen_addsi_compare_2 (tmp
, tmp
));
4632 emit_insn (gen_adc (operands
[0], operands
[0], operands
[0]));
4637 emit_insn (gen_addsi_compare_2 (operands
[1], operands
[1]));
4638 emit_insn (gen_scc_ltu_cc_c (operands
[0]));
4643 emit_insn (gen_lshrsi3_loop (operands
[0], operands
[1], operands
[2]));
4646 /* Split SImode rotate left instruction. */
4648 arc_split_rotl (rtx
*operands
)
4650 if (CONST_INT_P (operands
[2]))
4652 int n
= INTVAL (operands
[2]) & 0x1f;
4657 emit_insn (gen_rotlsi3_cnt1 (operands
[0], operands
[1]));
4659 emit_insn (gen_rotlsi3_cnt1 (operands
[0], operands
[0]));
4662 emit_move_insn (operands
[0], operands
[1]);
4667 emit_insn (gen_rotrsi3_cnt1 (operands
[0], operands
[1]));
4669 emit_insn (gen_rotrsi3_cnt1 (operands
[0], operands
[0]));
4672 else if (n
>= 13 && n
<= 16 && TARGET_SWAP
)
4674 emit_insn (gen_rotlsi2_cnt16 (operands
[0], operands
[1]));
4676 emit_insn (gen_rotrsi3_cnt1 (operands
[0], operands
[0]));
4679 else if (n
== 17 && TARGET_SWAP
)
4681 emit_insn (gen_rotlsi2_cnt16 (operands
[0], operands
[1]));
4682 emit_insn (gen_rotlsi3_cnt1 (operands
[0], operands
[0]));
4685 else if (n
>= 16 || n
== 12 || n
== 14)
4687 emit_insn (gen_rotrsi3_loop (operands
[0], operands
[1],
4693 emit_insn (gen_rotlsi3_loop (operands
[0], operands
[1], operands
[2]));
4696 /* Split SImode rotate right instruction. */
4698 arc_split_rotr (rtx
*operands
)
4700 if (CONST_INT_P (operands
[2]))
4702 int n
= INTVAL (operands
[2]) & 0x1f;
4707 emit_insn (gen_rotrsi3_cnt1 (operands
[0], operands
[1]));
4709 emit_insn (gen_rotrsi3_cnt1 (operands
[0], operands
[0]));
4712 emit_move_insn (operands
[0], operands
[1]);
4715 else if (n
== 15 && TARGET_SWAP
)
4717 emit_insn (gen_rotrsi2_cnt16 (operands
[0], operands
[1]));
4718 emit_insn (gen_rotlsi3_cnt1 (operands
[0], operands
[0]));
4721 else if (n
>= 16 && n
<= 19 && TARGET_SWAP
)
4723 emit_insn (gen_rotrsi2_cnt16 (operands
[0], operands
[1]));
4725 emit_insn (gen_rotrsi3_cnt1 (operands
[0], operands
[0]));
4730 emit_insn (gen_rotlsi3_cnt1 (operands
[0], operands
[1]));
4732 emit_insn (gen_rotlsi3_cnt1 (operands
[1], operands
[1]));
4735 else if (n
>= 21 || n
== 17 || n
== 19)
4737 emit_insn (gen_rotrsi3_loop (operands
[0], operands
[1],
4743 emit_insn (gen_rotrsi3_loop (operands
[0], operands
[1], operands
[2]));
4746 /* Nested function support. */
4748 /* Output assembler code for a block containing the constant parts of
4749 a trampoline, leaving space for variable parts. A trampoline looks
4755 .word function's address
4756 .word static chain value
4761 arc_asm_trampoline_template (FILE *f
)
4763 asm_fprintf (f
, "\tld_s\t%s,[pcl,8]\n", ARC_TEMP_SCRATCH_REG
);
4764 asm_fprintf (f
, "\tld\t%s,[pcl,12]\n", reg_names
[STATIC_CHAIN_REGNUM
]);
4765 asm_fprintf (f
, "\tj_s\t[%s]\n", ARC_TEMP_SCRATCH_REG
);
4766 assemble_aligned_integer (UNITS_PER_WORD
, const0_rtx
);
4767 assemble_aligned_integer (UNITS_PER_WORD
, const0_rtx
);
4770 /* Emit RTL insns to initialize the variable parts of a trampoline.
4771 FNADDR is an RTX for the address of the function's pure code. CXT
4772 is an RTX for the static chain value for the function.
4774 The fastest trampoline to execute for trampolines within +-8KB of CTX
4778 j [limm] 0x20200f80 limm
4780 and that would also be faster to write to the stack by computing
4781 the offset from CTX to TRAMP at compile time. However, it would
4782 really be better to get rid of the high cost of cache invalidation
4783 when generating trampolines, which requires that the code part of
4784 trampolines stays constant, and additionally either making sure
4785 that no executable code but trampolines is on the stack, no icache
4786 entries linger for the area of the stack from when before the stack
4787 was allocated, and allocating trampolines in trampoline-only cache
4788 lines or allocate trampolines fram a special pool of pre-allocated
4792 arc_initialize_trampoline (rtx tramp
, tree fndecl
, rtx cxt
)
4794 rtx fnaddr
= XEXP (DECL_RTL (fndecl
), 0);
4796 emit_block_move (tramp
, assemble_trampoline_template (),
4797 GEN_INT (TRAMPOLINE_SIZE
), BLOCK_OP_NORMAL
);
4798 emit_move_insn (adjust_address (tramp
, SImode
, 8), fnaddr
);
4799 emit_move_insn (adjust_address (tramp
, SImode
, 12), cxt
);
4800 maybe_emit_call_builtin___clear_cache (XEXP (tramp
, 0),
4801 plus_constant (Pmode
,
4806 /* Add the given function declaration to emit code in JLI section. */
4809 arc_add_jli_section (rtx pat
)
4813 arc_jli_section
*sec
= arc_jli_sections
, *new_section
;
4814 tree decl
= SYMBOL_REF_DECL (pat
);
4821 /* For fixed locations do not generate the jli table entry. It
4822 should be provided by the user as an asm file. */
4823 attrs
= TYPE_ATTRIBUTES (TREE_TYPE (decl
));
4824 if (lookup_attribute ("jli_fixed", attrs
))
4828 name
= XSTR (pat
, 0);
4830 /* Don't insert the same symbol twice. */
4833 if(strcmp (name
, sec
->name
) == 0)
4838 /* New name, insert it. */
4839 new_section
= (arc_jli_section
*) xmalloc (sizeof (arc_jli_section
));
4840 gcc_assert (new_section
!= NULL
);
4841 new_section
->name
= name
;
4842 new_section
->next
= arc_jli_sections
;
4843 arc_jli_sections
= new_section
;
4846 /* This is set briefly to 1 when we output a ".as" address modifer, and then
4847 reset when we output the scaled address. */
4848 static int output_scaled
= 0;
4850 /* Set when we force sdata output. */
4851 static int output_sdata
= 0;
4853 /* Print operand X (an rtx) in assembler syntax to file FILE.
4854 CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
4855 For `%' followed by punctuation, CODE is the punctuation and X is null.
4856 In final.cc:output_asm_insn:
4859 'c' : constant address if CONSTANT_ADDRESS_P
4865 'p': bit Position of lsb
4866 's': scalled immediate
4867 'S': Scalled immediate, to be used in pair with 's'.
4868 'N': Negative immediate, to be used in pair with 's'.
4869 'x': size of bit field
4870 '*': jump delay slot suffix
4871 '?' : nonjump-insn suffix for conditional execution or short instruction
4875 'J': JLI instruction
4876 'j': used by mov instruction to properly emit jli related labels.
4877 'B': Branch comparison operand - suppress sda reference
4878 'H': Most significant word
4879 'L': Least significant word
4880 'A': ASCII decimal representation of floating point value
4881 'U': Load/store update or scaling indicator
4882 'V': cache bypass indicator for volatile
4886 'o': original symbol - no @ prepending. */
4889 arc_print_operand (FILE *file
, rtx x
, int code
)
4892 unsigned scalled
= 0;
4898 if (GET_CODE (x
) == CONST_INT
)
4899 fprintf (file
, "%d",exact_log2(INTVAL (x
) + 1) - 1 );
4901 output_operand_lossage ("invalid operand to %%Z code");
4906 if (GET_CODE (x
) == CONST_INT
)
4907 fprintf (file
, "%d",exact_log2 (INTVAL (x
) & 0xffffffff));
4909 output_operand_lossage ("invalid operand to %%z code");
4914 if (GET_CODE (x
) == CONST_INT
)
4915 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
) );
4917 output_operand_lossage ("invalid operands to %%c code");
4922 if (GET_CODE (x
) == CONST_INT
)
4923 fprintf (file
, "%d",exact_log2(~INTVAL (x
)) );
4925 output_operand_lossage ("invalid operand to %%M code");
4930 if (GET_CODE (x
) == CONST_INT
)
4931 fprintf (file
, "%d", exact_log2 (INTVAL (x
) & -INTVAL (x
)));
4933 output_operand_lossage ("invalid operand to %%p code");
4939 if (!CONST_INT_P (x
))
4941 output_operand_lossage ("invalid operand for %%s code");
4945 if ((ival
& 0x07) == 0)
4947 else if ((ival
& 0x03) == 0)
4949 else if ((ival
& 0x01) == 0)
4953 asm_fprintf (file
, "%d", scalled
);
4959 output_operand_lossage ("invalid operand for %%N code");
4967 asm_fprintf (file
, "%s", reg_names
[REGNO (x
)]);
4970 if (!CONST_INT_P (x
))
4972 output_operand_lossage ("invalid operand for %%N or %%S code");
4975 ival
= sign
* INTVAL (x
);
4976 if ((ival
& 0x07) == 0)
4978 else if ((ival
& 0x03) == 0)
4980 else if ((ival
& 0x01) == 0)
4983 asm_fprintf (file
, "%wd", (ival
>> scalled
));
4987 if (GET_CODE (x
) == CONST_INT
)
4989 HOST_WIDE_INT i
= INTVAL (x
);
4990 HOST_WIDE_INT s
= exact_log2 (i
& -i
);
4991 fprintf (file
, "%d", exact_log2 (((0xffffffffUL
& i
) >> s
) + 1));
4994 output_operand_lossage ("invalid operand to %%s code");
4998 /* Unconditional branches / branches not depending on condition codes.
4999 This could also be a CALL_INSN.
5000 Output the appropriate delay slot suffix. */
5001 if (final_sequence
&& final_sequence
->len () != 1)
5003 rtx_insn
*delay
= final_sequence
->insn (1);
5005 /* For TARGET_PAD_RETURN we might have grabbed the delay insn. */
5006 if (delay
->deleted ())
5012 case '?' : /* with leading "." */
5013 case '!' : /* without leading "." */
5014 if (current_insn_predicate
)
5016 int cc
= get_arc_condition_code (current_insn_predicate
);
5017 /* Is this insn in a delay slot sequence? */
5018 if (!final_sequence
|| XVECLEN (final_sequence
, 0) < 2
5019 || current_insn_predicate
5020 || CALL_P (final_sequence
->insn (0))
5021 || simplejump_p (final_sequence
->insn (0)))
5023 /* This insn isn't in a delay slot sequence, or conditionalized
5024 independently of its position in a delay slot. */
5025 fprintf (file
, "%s%s",
5026 code
== '?' ? "." : "", arc_condition_codes
[cc
]);
5027 /* If this is a jump, there are still short variants. However,
5028 only beq_s / bne_s have the same offset range as b_s,
5029 and the only short conditional returns are jeq_s and jne_s. */
5031 && (cc
== ARC_CC_EQ
|| cc
== ARC_CC_NE
))
5032 output_short_suffix (file
);
5034 else if (code
== '!') /* Jump with delay slot. */
5035 fputs (arc_condition_codes
[cc
], file
);
5036 else /* An Instruction in a delay slot of a jump or call. */
5038 rtx jump
= XVECEXP (final_sequence
, 0, 0);
5039 rtx insn
= XVECEXP (final_sequence
, 0, 1);
5041 /* If the insn is annulled and is from the target path, we need
5042 to inverse the condition test. */
5043 if (JUMP_P (jump
) && INSN_ANNULLED_BRANCH_P (jump
))
5045 if (INSN_FROM_TARGET_P (insn
))
5046 fprintf (file
, "%s%s",
5047 code
== '?' ? "." : "",
5048 arc_condition_codes
[ARC_INVERSE_CONDITION_CODE (cc
)]);
5050 fprintf (file
, "%s%s",
5051 code
== '?' ? "." : "",
5052 arc_condition_codes
[cc
]);
5056 /* This insn is executed for either path, so don't
5057 conditionalize it at all. */
5058 output_short_suffix (file
);
5063 output_short_suffix (file
);
5067 fputs (arc_condition_codes
[get_arc_condition_code (x
)], file
);
5070 fputs (arc_condition_codes
[ARC_INVERSE_CONDITION_CODE
5071 (get_arc_condition_code (x
))],
5075 /* Write second word of DImode or DFmode reference,
5076 register or memory. */
5077 if (GET_CODE (x
) == REG
)
5078 fputs (reg_names
[REGNO (x
)+1], file
);
5079 else if (GET_CODE (x
) == MEM
)
5083 /* Handle possible auto-increment. For PRE_INC / PRE_DEC /
5084 PRE_MODIFY, we will have handled the first word already;
5085 For POST_INC / POST_DEC / POST_MODIFY, the access to the
5086 first word will be done later. In either case, the access
5087 to the first word will do the modify, and we only have
5088 to add an offset of four here. */
5089 if (GET_CODE (XEXP (x
, 0)) == PRE_INC
5090 || GET_CODE (XEXP (x
, 0)) == PRE_DEC
5091 || GET_CODE (XEXP (x
, 0)) == PRE_MODIFY
5092 || GET_CODE (XEXP (x
, 0)) == POST_INC
5093 || GET_CODE (XEXP (x
, 0)) == POST_DEC
5094 || GET_CODE (XEXP (x
, 0)) == POST_MODIFY
)
5095 output_address (VOIDmode
,
5096 plus_constant (Pmode
, XEXP (XEXP (x
, 0), 0), 4));
5097 else if (output_scaled
)
5099 rtx addr
= XEXP (x
, 0);
5100 int size
= GET_MODE_SIZE (GET_MODE (x
));
5102 output_address (VOIDmode
,
5103 plus_constant (Pmode
, XEXP (addr
, 0),
5104 ((INTVAL (XEXP (addr
, 1)) + 4)
5105 >> (size
== 2 ? 1 : 2))));
5109 output_address (VOIDmode
,
5110 plus_constant (Pmode
, XEXP (x
, 0), 4));
5114 output_operand_lossage ("invalid operand to %%R code");
5118 if (GET_CODE (x
) == SYMBOL_REF
5119 && arc_is_jli_call_p (x
))
5121 if (SYMBOL_REF_DECL (x
))
5123 tree attrs
= (TREE_TYPE (SYMBOL_REF_DECL (x
)) != error_mark_node
5124 ? TYPE_ATTRIBUTES (TREE_TYPE (SYMBOL_REF_DECL (x
)))
5126 if (lookup_attribute ("jli_fixed", attrs
))
5128 /* No special treatment for jli_fixed functions. */
5131 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
"\t; @",
5132 TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attrs
))));
5133 assemble_name (file
, XSTR (x
, 0));
5137 fprintf (file
, "@__jli.");
5138 assemble_name (file
, XSTR (x
, 0));
5140 arc_add_jli_section (x
);
5143 if (GET_CODE (x
) == SYMBOL_REF
5144 && arc_is_secure_call_p (x
))
5146 /* No special treatment for secure functions. */
5149 tree attrs
= (TREE_TYPE (SYMBOL_REF_DECL (x
)) != error_mark_node
5150 ? TYPE_ATTRIBUTES (TREE_TYPE (SYMBOL_REF_DECL (x
)))
5152 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
"\t; @",
5153 TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attrs
))));
5154 assemble_name (file
, XSTR (x
, 0));
5158 case 'B' /* Branch or other LIMM ref - must not use sda references. */ :
5161 output_addr_const (file
, x
);
5167 if (GET_CODE (x
) == REG
)
5169 /* L = least significant word, H = most significant word. */
5170 if ((WORDS_BIG_ENDIAN
!= 0) ^ (code
== 'L'))
5171 fputs (reg_names
[REGNO (x
)], file
);
5173 fputs (reg_names
[REGNO (x
)+1], file
);
5175 else if (GET_CODE (x
) == CONST_INT
5176 || GET_CODE (x
) == CONST_DOUBLE
)
5178 rtx first
, second
, word
;
5180 split_double (x
, &first
, &second
);
5182 if((WORDS_BIG_ENDIAN
) == 0)
5183 word
= (code
== 'L' ? first
: second
);
5185 word
= (code
== 'L' ? second
: first
);
5187 fprintf (file
, "0x%08" PRIx32
, ((uint32_t) INTVAL (word
)));
5190 output_operand_lossage ("invalid operand to %%H/%%L code");
5196 gcc_assert (GET_CODE (x
) == CONST_DOUBLE
5197 && GET_MODE_CLASS (GET_MODE (x
)) == MODE_FLOAT
);
5199 real_to_decimal (str
, CONST_DOUBLE_REAL_VALUE (x
), sizeof (str
), 0, 1);
5200 fprintf (file
, "%s", str
);
5204 /* Output a load/store with update indicator if appropriate. */
5205 if (GET_CODE (x
) == MEM
)
5207 rtx addr
= XEXP (x
, 0);
5208 switch (GET_CODE (addr
))
5210 case PRE_INC
: case PRE_DEC
: case PRE_MODIFY
:
5211 fputs (".a", file
); break;
5212 case POST_INC
: case POST_DEC
: case POST_MODIFY
:
5213 fputs (".ab", file
); break;
5215 /* Are we using a scaled index? */
5216 if (GET_CODE (XEXP (addr
, 0)) == MULT
)
5217 fputs (".as", file
);
5218 /* Can we use a scaled offset? */
5219 else if (CONST_INT_P (XEXP (addr
, 1))
5220 && GET_MODE_SIZE (GET_MODE (x
)) > 1
5221 && (!(INTVAL (XEXP (addr
, 1))
5222 & (GET_MODE_SIZE (GET_MODE (x
)) - 1) & 3))
5223 /* Does it make a difference? */
5224 && !SMALL_INT_RANGE(INTVAL (XEXP (addr
, 1)),
5225 GET_MODE_SIZE (GET_MODE (x
)) - 2, 0))
5227 fputs (".as", file
);
5233 if (legitimate_small_data_address_p (addr
, GET_MODE (x
))
5234 && GET_MODE_SIZE (GET_MODE (x
)) > 1)
5236 int align
= get_symbol_alignment (addr
);
5238 switch (GET_MODE (x
))
5247 if (align
&& ((align
& mask
) == 0))
5248 fputs (".as", file
);
5254 gcc_assert (CONSTANT_P (addr
)); break;
5258 output_operand_lossage ("invalid operand to %%U code");
5261 /* Output cache bypass indicator for a load/store insn. Volatile memory
5262 refs are defined to use the cache bypass mechanism. */
5263 if (GET_CODE (x
) == MEM
)
5265 if ((MEM_VOLATILE_P (x
) && !TARGET_VOLATILE_CACHE_SET
)
5266 || arc_is_uncached_mem_p (x
))
5267 fputs (".di", file
);
5270 output_operand_lossage ("invalid operand to %%V code");
5275 /* Do nothing special. */
5278 fputs (reg_names
[REGNO (x
)]+1, file
);
5282 /* Output an operator. */
5283 switch (GET_CODE (x
))
5285 case PLUS
: fputs ("add", file
); return;
5286 case SS_PLUS
: fputs ("adds", file
); return;
5287 case AND
: fputs ("and", file
); return;
5288 case IOR
: fputs ("or", file
); return;
5289 case XOR
: fputs ("xor", file
); return;
5290 case MINUS
: fputs ("sub", file
); return;
5291 case SS_MINUS
: fputs ("subs", file
); return;
5292 case ASHIFT
: fputs ("asl", file
); return;
5293 case ASHIFTRT
: fputs ("asr", file
); return;
5294 case LSHIFTRT
: fputs ("lsr", file
); return;
5295 case ROTATERT
: fputs ("ror", file
); return;
5296 case MULT
: fputs ("mpy", file
); return;
5297 case ABS
: fputs ("abs", file
); return; /* Unconditional. */
5298 case NEG
: fputs ("neg", file
); return;
5299 case SS_NEG
: fputs ("negs", file
); return;
5300 case NOT
: fputs ("not", file
); return; /* Unconditional. */
5302 fputs ("ext", file
); /* bmsk allows predication. */
5304 case SIGN_EXTEND
: /* Unconditional. */
5305 fputs ("sex", file
);
5307 switch (GET_MODE (XEXP (x
, 0)))
5309 case E_QImode
: fputs ("b", file
); return;
5310 case E_HImode
: fputs ("w", file
); return;
5315 if (GET_MODE (x
) != HImode
)
5317 fputs ("sat16", file
);
5320 output_operand_lossage ("invalid operand to %%O code"); return;
5322 if (GET_CODE (x
) == SYMBOL_REF
)
5324 assemble_name (file
, XSTR (x
, 0));
5343 output_operand_lossage ("invalid operand output code");
5346 switch (GET_CODE (x
))
5349 fputs (reg_names
[REGNO (x
)], file
);
5353 rtx addr
= XEXP (x
, 0);
5354 int size
= GET_MODE_SIZE (GET_MODE (x
));
5356 if (legitimate_small_data_address_p (addr
, GET_MODE (x
)))
5361 switch (GET_CODE (addr
))
5363 case PRE_INC
: case POST_INC
:
5364 output_address (VOIDmode
,
5365 plus_constant (Pmode
, XEXP (addr
, 0), size
)); break;
5366 case PRE_DEC
: case POST_DEC
:
5367 output_address (VOIDmode
,
5368 plus_constant (Pmode
, XEXP (addr
, 0), -size
));
5370 case PRE_MODIFY
: case POST_MODIFY
:
5371 output_address (VOIDmode
, XEXP (addr
, 1)); break;
5375 output_address (VOIDmode
,
5376 plus_constant (Pmode
, XEXP (addr
, 0),
5377 (INTVAL (XEXP (addr
, 1))
5378 >> (size
== 2 ? 1 : 2))));
5382 output_address (VOIDmode
, addr
);
5385 if (flag_pic
&& CONSTANT_ADDRESS_P (addr
))
5386 arc_output_pic_addr_const (file
, addr
, code
);
5388 output_address (VOIDmode
, addr
);
5395 /* We handle SFmode constants here as output_addr_const doesn't. */
5396 if (GET_MODE (x
) == SFmode
)
5400 REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (x
), l
);
5401 fprintf (file
, "0x%08lx", l
);
5405 /* Let output_addr_const deal with it. */
5408 || (GET_CODE (x
) == CONST
5409 && GET_CODE (XEXP (x
, 0)) == UNSPEC
5410 && (XINT (XEXP (x
, 0), 1) == UNSPEC_TLS_OFF
5411 || XINT (XEXP (x
, 0), 1) == UNSPEC_TLS_GD
))
5412 || (GET_CODE (x
) == CONST
5413 && GET_CODE (XEXP (x
, 0)) == PLUS
5414 && GET_CODE (XEXP (XEXP (x
, 0), 0)) == UNSPEC
5415 && (XINT (XEXP (XEXP (x
, 0), 0), 1) == UNSPEC_TLS_OFF
5416 || XINT (XEXP (XEXP (x
, 0), 0), 1) == UNSPEC_TLS_GD
)))
5417 arc_output_pic_addr_const (file
, x
, code
);
5419 output_addr_const (file
, x
);
5424 /* Print a memory address as an operand to reference that memory location. */
5427 arc_print_operand_address (FILE *file
, rtx addr
)
5429 rtx base
, index
= 0;
5431 switch (GET_CODE (addr
))
5434 fputs (reg_names
[REGNO (addr
)], file
);
5438 fputs ("gp,", file
);
5439 output_addr_const (file
, addr
);
5441 fputs ("@sda", file
);
5445 if (GET_CODE (XEXP (addr
, 0)) == MULT
)
5446 index
= XEXP (XEXP (addr
, 0), 0), base
= XEXP (addr
, 1);
5447 else if (CONST_INT_P (XEXP (addr
, 0)))
5448 index
= XEXP (addr
, 0), base
= XEXP (addr
, 1);
5450 base
= XEXP (addr
, 0), index
= XEXP (addr
, 1);
5452 gcc_assert (OBJECT_P (base
));
5453 arc_print_operand_address (file
, base
);
5454 if (CONSTANT_P (base
) && CONST_INT_P (index
))
5458 gcc_assert (OBJECT_P (index
));
5459 arc_print_operand_address (file
, index
);
5463 rtx c
= XEXP (addr
, 0);
5465 if ((GET_CODE (c
) == UNSPEC
5466 && (XINT (c
, 1) == UNSPEC_TLS_OFF
5467 || XINT (c
, 1) == UNSPEC_TLS_IE
))
5468 || (GET_CODE (c
) == PLUS
5469 && GET_CODE (XEXP (c
, 0)) == UNSPEC
5470 && (XINT (XEXP (c
, 0), 1) == UNSPEC_TLS_OFF
5471 || XINT (XEXP (c
, 0), 1) == ARC_UNSPEC_GOTOFFPC
)))
5473 arc_output_pic_addr_const (file
, c
, 0);
5476 gcc_assert (GET_CODE (c
) == PLUS
);
5477 gcc_assert (GET_CODE (XEXP (c
, 0)) == SYMBOL_REF
);
5478 gcc_assert (GET_CODE (XEXP (c
, 1)) == CONST_INT
);
5480 output_address (VOIDmode
, XEXP (addr
, 0));
5486 /* We shouldn't get here as we've lost the mode of the memory object
5487 (which says how much to inc/dec by. */
5492 arc_output_pic_addr_const (file
, addr
, 0);
5494 output_addr_const (file
, addr
);
5499 /* Return non-zero if INSN should be output as a short insn. UNALIGN is
5500 zero if the current insn is aligned to a 4-byte-boundary, two otherwise.
5501 If CHECK_ATTR is greater than 0, check the iscompact attribute first. */
5504 arc_verify_short (rtx_insn
*insn
, int check_attr
)
5506 enum attr_iscompact iscompact
;
5510 iscompact
= get_attr_iscompact (insn
);
5511 if (iscompact
== ISCOMPACT_FALSE
)
5515 return (get_attr_length (insn
) & 2) != 0;
5518 /* When outputting an instruction (alternative) that can potentially be short,
5519 output the short suffix if the insn is in fact short. */
5522 output_short_suffix (FILE *file
)
5524 rtx_insn
*insn
= current_output_insn
;
5528 if (arc_verify_short (insn
, 1))
5530 fprintf (file
, "_s");
5532 /* Restore recog_operand. */
5533 extract_insn_cached (insn
);
5536 /* Implement FINAL_PRESCAN_INSN. */
5539 arc_final_prescan_insn (rtx_insn
*insn
, rtx
*opvec ATTRIBUTE_UNUSED
,
5540 int noperands ATTRIBUTE_UNUSED
)
5542 if (TARGET_DUMPISIZE
)
5543 fprintf (asm_out_file
, "\n; at %04x\n", INSN_ADDRESSES (INSN_UID (insn
)));
5546 /* Given FROM and TO register numbers, say whether this elimination is allowed.
5547 Frame pointer elimination is automatically handled.
5549 All eliminations are permissible. If we need a frame
5550 pointer, we must eliminate ARG_POINTER_REGNUM into
5551 FRAME_POINTER_REGNUM and not into STACK_POINTER_REGNUM. */
5554 arc_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to
)
5556 return ((to
== HARD_FRAME_POINTER_REGNUM
) || (to
== STACK_POINTER_REGNUM
));
5559 /* Define the offset between two registers, one to be eliminated, and
5560 the other its replacement, at the start of a routine. */
5563 arc_initial_elimination_offset (int from
, int to
)
5565 if (!cfun
->machine
->frame_info
.initialized
)
5566 arc_compute_frame_size ();
5568 if (from
== ARG_POINTER_REGNUM
&& to
== HARD_FRAME_POINTER_REGNUM
)
5570 return (cfun
->machine
->frame_info
.extra_size
5571 + cfun
->machine
->frame_info
.reg_size
);
5574 if (from
== ARG_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
5576 return (cfun
->machine
->frame_info
.total_size
5577 - cfun
->machine
->frame_info
.pretend_size
);
5580 if ((from
== FRAME_POINTER_REGNUM
) && (to
== STACK_POINTER_REGNUM
))
5582 return (cfun
->machine
->frame_info
.total_size
5583 - (cfun
->machine
->frame_info
.pretend_size
5584 + cfun
->machine
->frame_info
.extra_size
5585 + cfun
->machine
->frame_info
.reg_size
));
5587 if ((from
== FRAME_POINTER_REGNUM
) && (to
== HARD_FRAME_POINTER_REGNUM
))
5594 arc_frame_pointer_required (void)
5596 return cfun
->calls_alloca
|| crtl
->calls_eh_return
;
5600 /* Return the destination address of a branch. */
5603 branch_dest (rtx branch
)
5605 rtx pat
= PATTERN (branch
);
5606 rtx dest
= (GET_CODE (pat
) == PARALLEL
5607 ? SET_SRC (XVECEXP (pat
, 0, 0)) : SET_SRC (pat
));
5610 if (GET_CODE (dest
) == IF_THEN_ELSE
)
5611 dest
= XEXP (dest
, XEXP (dest
, 1) == pc_rtx
? 2 : 1);
5613 dest
= XEXP (dest
, 0);
5614 dest_uid
= INSN_UID (dest
);
5616 return INSN_ADDRESSES (dest_uid
);
5620 /* Implement TARGET_ENCODE_SECTION_INFO hook. */
5623 arc_encode_section_info (tree decl
, rtx rtl
, int first
)
5625 /* For sdata, SYMBOL_FLAG_LOCAL and SYMBOL_FLAG_FUNCTION.
5626 This clears machine specific flags, so has to come first. */
5627 default_encode_section_info (decl
, rtl
, first
);
5629 /* Check if it is a function, and whether it has the
5630 [long/medium/short]_call attribute specified. */
5631 if (TREE_CODE (decl
) == FUNCTION_DECL
)
5633 rtx symbol
= XEXP (rtl
, 0);
5634 int flags
= SYMBOL_REF_FLAGS (symbol
);
5636 tree attr
= (TREE_TYPE (decl
) != error_mark_node
5637 ? TYPE_ATTRIBUTES (TREE_TYPE (decl
)) : NULL_TREE
);
5638 tree long_call_attr
= lookup_attribute ("long_call", attr
);
5639 tree medium_call_attr
= lookup_attribute ("medium_call", attr
);
5640 tree short_call_attr
= lookup_attribute ("short_call", attr
);
5642 if (long_call_attr
!= NULL_TREE
)
5643 flags
|= SYMBOL_FLAG_LONG_CALL
;
5644 else if (medium_call_attr
!= NULL_TREE
)
5645 flags
|= SYMBOL_FLAG_MEDIUM_CALL
;
5646 else if (short_call_attr
!= NULL_TREE
)
5647 flags
|= SYMBOL_FLAG_SHORT_CALL
;
5649 SYMBOL_REF_FLAGS (symbol
) = flags
;
5651 else if (VAR_P (decl
))
5653 rtx symbol
= XEXP (rtl
, 0);
5655 tree attr
= (TREE_TYPE (decl
) != error_mark_node
5656 ? DECL_ATTRIBUTES (decl
) : NULL_TREE
);
5658 tree sec_attr
= lookup_attribute ("section", attr
);
5661 const char *sec_name
5662 = TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (sec_attr
)));
5663 if (strcmp (sec_name
, ".cmem") == 0
5664 || strcmp (sec_name
, ".cmem_shared") == 0
5665 || strcmp (sec_name
, ".cmem_private") == 0)
5666 SYMBOL_REF_FLAGS (symbol
) |= SYMBOL_FLAG_CMEM
;
5671 /* This is how to output a definition of an internal numbered label where
5672 PREFIX is the class of label and NUM is the number within the class. */
5674 static void arc_internal_label (FILE *stream
, const char *prefix
, unsigned long labelno
)
5676 default_internal_label (stream
, prefix
, labelno
);
5679 /* Set the cpu type and print out other fancy things,
5680 at the top of the file. */
5682 static void arc_file_start (void)
5684 default_file_start ();
5685 fprintf (asm_out_file
, "\t.cpu %s\n", arc_cpu_string
);
5687 /* Set some want to have build attributes. */
5688 asm_fprintf (asm_out_file
, "\t.arc_attribute Tag_ARC_PCS_config, %d\n",
5690 asm_fprintf (asm_out_file
, "\t.arc_attribute Tag_ARC_ABI_rf16, %d\n",
5691 TARGET_RF16
? 1 : 0);
5692 asm_fprintf (asm_out_file
, "\t.arc_attribute Tag_ARC_ABI_pic, %d\n",
5694 asm_fprintf (asm_out_file
, "\t.arc_attribute Tag_ARC_ABI_tls, %d\n",
5695 (arc_tp_regno
!= -1) ? 1 : 0);
5696 asm_fprintf (asm_out_file
, "\t.arc_attribute Tag_ARC_ABI_sda, %d\n",
5697 TARGET_NO_SDATA_SET
? 0 : 2);
5698 asm_fprintf (asm_out_file
, "\t.arc_attribute Tag_ARC_ABI_exceptions, %d\n",
5699 TARGET_OPTFPE
? 1 : 0);
5701 asm_fprintf (asm_out_file
, "\t.arc_attribute Tag_ARC_CPU_variation, %d\n",
5702 (arc_tune
< ARC_TUNE_CORE_3
) ? 2 :
5703 (arc_tune
== ARC_TUNE_CORE_3
? 3 : 4));
5706 /* Implement `TARGET_ASM_FILE_END'. */
5707 /* Outputs to the stdio stream FILE jli related text. */
5709 void arc_file_end (void)
5711 arc_jli_section
*sec
= arc_jli_sections
;
5715 fprintf (asm_out_file
, "\n");
5716 fprintf (asm_out_file
, "# JLI entry for function ");
5717 assemble_name (asm_out_file
, sec
->name
);
5718 fprintf (asm_out_file
, "\n\t.section .jlitab, \"axG\", @progbits, "
5720 assemble_name (asm_out_file
, sec
->name
);
5721 fprintf (asm_out_file
,", comdat\n");
5723 fprintf (asm_out_file
, "\t.align\t4\n");
5724 fprintf (asm_out_file
, "__jli.");
5725 assemble_name (asm_out_file
, sec
->name
);
5726 fprintf (asm_out_file
, ":\n\t.weak __jli.");
5727 assemble_name (asm_out_file
, sec
->name
);
5728 fprintf (asm_out_file
, "\n\tb\t@");
5729 assemble_name (asm_out_file
, sec
->name
);
5730 fprintf (asm_out_file
, "\n");
5733 file_end_indicate_exec_stack ();
5736 /* Cost functions. */
5738 /* Compute a (partial) cost for rtx X. Return true if the complete
5739 cost has been computed, and false if subexpressions should be
5740 scanned. In either case, *TOTAL contains the cost result. */
5743 arc_rtx_costs (rtx x
, machine_mode mode
, int outer_code
,
5744 int opno ATTRIBUTE_UNUSED
, int *total
, bool speed
)
5746 int code
= GET_CODE (x
);
5750 /* Small integers are as cheap as registers. */
5753 bool nolimm
= false; /* Can we do without long immediate? */
5756 if (UNSIGNED_INT6 (INTVAL (x
)))
5762 case AND
: /* bclr, bmsk, ext[bw] */
5763 if (satisfies_constraint_Ccp (x
) /* bclr */
5764 || satisfies_constraint_C1p (x
) /* bmsk */)
5767 case IOR
: /* bset */
5768 if (satisfies_constraint_C0p (x
)) /* bset */
5772 if (satisfies_constraint_C0p (x
)) /* bxor */
5776 if (UNSIGNED_INT8 (INTVAL (x
)))
5778 if (satisfies_constraint_Chi (x
))
5780 if (satisfies_constraint_Clo (x
))
5784 if (TARGET_MUL64_SET
)
5785 if (SIGNED_INT12 (INTVAL (x
)))
5800 /* 4 byte values can be fetched as immediate constants -
5801 let's give that the cost of an extra insn. */
5805 *total
= speed
? COSTS_N_INSNS (1) : COSTS_N_BYTES (4);
5814 *total
= COSTS_N_INSNS (1);
5817 split_double (x
, &first
, &second
);
5818 *total
= COSTS_N_INSNS (!SMALL_INT (INTVAL (first
))
5819 + !SMALL_INT (INTVAL (second
)));
5823 /* Encourage synth_mult to find a synthetic multiply when reasonable.
5824 If we need more than 12 insns to do a multiply, then go out-of-line,
5825 since the call overhead will be < 10% of the cost of the multiply. */
5829 if (XEXP (x
, 1) == const1_rtx
)
5831 *total
+= rtx_cost (XEXP (x
, 0), mode
, ASHIFT
, 0, speed
)
5832 + COSTS_N_INSNS (2);
5837 if (TARGET_BARREL_SHIFTER
)
5839 *total
= COSTS_N_INSNS (1);
5840 if (CONST_INT_P (XEXP (x
, 1)))
5842 *total
+= rtx_cost (XEXP (x
, 0), mode
, ASHIFT
, 0, speed
);
5846 else if (CONST_INT_P (XEXP (x
, 1)))
5848 unsigned int n
= INTVAL (XEXP (x
, 1)) & 0x1f;
5849 *total
= arc_ashl_alg
[arc_shift_context_idx ()][n
].cost
5850 + rtx_cost (XEXP (x
, 0), mode
, ASHIFT
, 0, speed
);
5854 /* Variable shift loop takes 2 * n + 2 cycles. */
5855 *total
= speed
? COSTS_N_INSNS (64) : COSTS_N_INSNS (4);
5864 if (TARGET_BARREL_SHIFTER
)
5866 *total
= COSTS_N_INSNS (1);
5867 if (CONSTANT_P (XEXP (x
, 1)))
5869 *total
+= rtx_cost (XEXP (x
, 0), mode
, (enum rtx_code
) code
,
5874 else if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5875 *total
= speed
? COSTS_N_INSNS (16) : COSTS_N_INSNS (4);
5878 int n
= INTVAL (XEXP (x
, 1)) & 31;
5880 *total
= COSTS_N_INSNS (n
);
5882 *total
= speed
? COSTS_N_INSNS (n
+ 2) : COSTS_N_INSNS (4);
5883 *total
+= rtx_cost (XEXP (x
, 0), mode
, (enum rtx_code
) code
,
5891 if (GET_MODE_CLASS (mode
) == MODE_FLOAT
5892 && (TARGET_FP_SP_SQRT
|| TARGET_FP_DP_SQRT
))
5893 *total
= COSTS_N_INSNS(1);
5894 else if (GET_MODE_CLASS (mode
) == MODE_INT
5896 *total
= COSTS_N_INSNS(1);
5898 *total
= COSTS_N_INSNS(30);
5900 *total
= COSTS_N_INSNS(1);
5904 if ((TARGET_DPFP
&& GET_MODE (x
) == DFmode
))
5905 *total
= COSTS_N_INSNS (1);
5907 *total
= arc_multcost
;
5908 /* We do not want synth_mult sequences when optimizing
5910 else if (TARGET_ANY_MPY
)
5911 *total
= COSTS_N_INSNS (1);
5913 *total
= COSTS_N_INSNS (2);
5919 if (outer_code
== MEM
&& CONST_INT_P (XEXP (x
, 1))
5920 && RTX_OK_FOR_OFFSET_P (mode
, XEXP (x
, 1)))
5926 if ((GET_CODE (XEXP (x
, 0)) == ASHIFT
5927 && _1_2_3_operand (XEXP (XEXP (x
, 0), 1), VOIDmode
))
5928 || (GET_CODE (XEXP (x
, 0)) == MULT
5929 && _2_4_8_operand (XEXP (XEXP (x
, 0), 1), VOIDmode
)))
5931 if (CONSTANT_P (XEXP (x
, 1)) && !speed
)
5932 *total
+= COSTS_N_INSNS (4);
5933 *total
+= rtx_cost (XEXP (XEXP (x
, 0), 0), mode
, PLUS
, 1, speed
);
5938 if ((GET_CODE (XEXP (x
, 1)) == ASHIFT
5939 && _1_2_3_operand (XEXP (XEXP (x
, 1), 1), VOIDmode
))
5940 || (GET_CODE (XEXP (x
, 1)) == MULT
5941 && _2_4_8_operand (XEXP (XEXP (x
, 1), 1), VOIDmode
)))
5943 if (CONSTANT_P (XEXP (x
, 0)) && !speed
)
5944 *total
+= COSTS_N_INSNS (4);
5945 *total
+= rtx_cost (XEXP (XEXP (x
, 1), 0), mode
, PLUS
, 1, speed
);
5952 rtx op0
= XEXP (x
, 0);
5953 rtx op1
= XEXP (x
, 1);
5955 if (GET_CODE (op0
) == ZERO_EXTRACT
&& op1
== const0_rtx
5956 && XEXP (op0
, 1) == const1_rtx
)
5958 /* btst / bbit0 / bbit1:
5959 Small integers and registers are free; everything else can
5960 be put in a register. */
5961 mode
= GET_MODE (XEXP (op0
, 0));
5962 *total
= (rtx_cost (XEXP (op0
, 0), mode
, SET
, 1, speed
)
5963 + rtx_cost (XEXP (op0
, 2), mode
, SET
, 1, speed
));
5966 if (GET_CODE (op0
) == AND
&& op1
== const0_rtx
5967 && satisfies_constraint_C1p (XEXP (op0
, 1)))
5970 *total
= rtx_cost (XEXP (op0
, 0), VOIDmode
, SET
, 1, speed
);
5974 if (GET_CODE (op1
) == NEG
)
5976 /* op0 might be constant, the inside of op1 is rather
5977 unlikely to be so. So swapping the operands might lower
5979 mode
= GET_MODE (op0
);
5980 *total
= (rtx_cost (op0
, mode
, PLUS
, 1, speed
)
5981 + rtx_cost (XEXP (op1
, 0), mode
, PLUS
, 0, speed
));
5986 if (outer_code
== IF_THEN_ELSE
5987 && GET_CODE (XEXP (x
, 0)) == ZERO_EXTRACT
5988 && XEXP (x
, 1) == const0_rtx
5989 && XEXP (XEXP (x
, 0), 1) == const1_rtx
)
5991 /* btst / bbit0 / bbit1:
5992 Small integers and registers are free; everything else can
5993 be put in a register. */
5994 rtx op0
= XEXP (x
, 0);
5996 mode
= GET_MODE (XEXP (op0
, 0));
5997 *total
= (rtx_cost (XEXP (op0
, 0), mode
, SET
, 1, speed
)
5998 + rtx_cost (XEXP (op0
, 2), mode
, SET
, 1, speed
));
6002 /* scc_insn expands into two insns. */
6003 case GTU
: case GEU
: case LEU
:
6005 *total
+= COSTS_N_INSNS (1);
6007 case LTU
: /* might use adc. */
6009 *total
+= COSTS_N_INSNS (1) - 1;
6016 /* Return true if ADDR is a valid pic address.
6017 A valid pic address on arc should look like
6018 const (unspec (SYMBOL_REF/LABEL) (ARC_UNSPEC_GOTOFF/ARC_UNSPEC_GOT)) */
6021 arc_legitimate_pic_addr_p (rtx addr
)
6023 if (GET_CODE (addr
) != CONST
)
6026 addr
= XEXP (addr
, 0);
6029 if (GET_CODE (addr
) == PLUS
)
6031 if (GET_CODE (XEXP (addr
, 1)) != CONST_INT
)
6033 addr
= XEXP (addr
, 0);
6036 if (GET_CODE (addr
) != UNSPEC
6037 || XVECLEN (addr
, 0) != 1)
6040 /* Must be one of @GOT, @GOTOFF, @GOTOFFPC, @tlsgd, tlsie. */
6041 if (XINT (addr
, 1) != ARC_UNSPEC_GOT
6042 && XINT (addr
, 1) != ARC_UNSPEC_GOTOFF
6043 && XINT (addr
, 1) != ARC_UNSPEC_GOTOFFPC
6044 && XINT (addr
, 1) != UNSPEC_TLS_GD
6045 && XINT (addr
, 1) != UNSPEC_TLS_IE
)
6048 if (GET_CODE (XVECEXP (addr
, 0, 0)) != SYMBOL_REF
6049 && GET_CODE (XVECEXP (addr
, 0, 0)) != LABEL_REF
)
6057 /* Return true if OP contains a symbol reference. */
6060 symbolic_reference_mentioned_p (rtx op
)
6065 if (GET_CODE (op
) == SYMBOL_REF
|| GET_CODE (op
) == LABEL_REF
)
6068 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
6069 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
6075 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
6076 if (symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
)))
6080 else if (fmt
[i
] == 'e' && symbolic_reference_mentioned_p (XEXP (op
, i
)))
6087 /* Return true if OP contains a SYMBOL_REF that is not wrapped in an unspec.
6088 If SKIP_LOCAL is true, skip symbols that bind locally.
6089 This is used further down in this file, and, without SKIP_LOCAL,
6090 in the addsi3 / subsi3 expanders when generating PIC code. */
6093 arc_raw_symbolic_reference_mentioned_p (rtx op
, bool skip_local
)
6098 if (GET_CODE(op
) == UNSPEC
)
6101 if (GET_CODE (op
) == SYMBOL_REF
)
6103 if (SYMBOL_REF_TLS_MODEL (op
))
6107 tree decl
= SYMBOL_REF_DECL (op
);
6108 return !skip_local
|| !decl
|| !default_binds_local_p (decl
);
6111 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
6112 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
6118 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
6119 if (arc_raw_symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
),
6124 else if (fmt
[i
] == 'e'
6125 && arc_raw_symbolic_reference_mentioned_p (XEXP (op
, i
),
6133 /* The __tls_get_attr symbol. */
6134 static GTY(()) rtx arc_tls_symbol
;
6136 /* Emit a call to __tls_get_addr. TI is the argument to this function.
6137 RET is an RTX for the return value location. The entire insn sequence
6141 arc_call_tls_get_addr (rtx ti
)
6143 rtx arg
= gen_rtx_REG (Pmode
, R0_REG
);
6144 rtx ret
= gen_rtx_REG (Pmode
, R0_REG
);
6148 if (!arc_tls_symbol
)
6149 arc_tls_symbol
= init_one_libfunc ("__tls_get_addr");
6151 emit_move_insn (arg
, ti
);
6152 fn
= gen_rtx_MEM (SImode
, arc_tls_symbol
);
6153 insn
= emit_call_insn (gen_call_value (ret
, fn
, const0_rtx
));
6154 RTL_CONST_CALL_P (insn
) = 1;
6155 use_reg (&CALL_INSN_FUNCTION_USAGE (insn
), ret
);
6156 use_reg (&CALL_INSN_FUNCTION_USAGE (insn
), arg
);
6161 /* Return a legitimized address for ADDR,
6162 which is a SYMBOL_REF with tls_model MODEL. */
6165 arc_legitimize_tls_address (rtx addr
, enum tls_model model
)
6169 /* The TP pointer needs to be set. */
6170 gcc_assert (arc_tp_regno
!= -1);
6174 case TLS_MODEL_GLOBAL_DYNAMIC
:
6175 case TLS_MODEL_LOCAL_DYNAMIC
:
6176 tmp
= gen_reg_rtx (Pmode
);
6177 emit_move_insn (tmp
, arc_unspec_offset (addr
, UNSPEC_TLS_GD
));
6178 return arc_call_tls_get_addr (tmp
);
6180 case TLS_MODEL_INITIAL_EXEC
:
6181 addr
= arc_unspec_offset (addr
, UNSPEC_TLS_IE
);
6182 addr
= copy_to_mode_reg (Pmode
, gen_const_mem (Pmode
, addr
));
6183 return gen_rtx_PLUS (Pmode
, gen_rtx_REG (Pmode
, arc_tp_regno
), addr
);
6185 case TLS_MODEL_LOCAL_EXEC
:
6186 addr
= arc_unspec_offset (addr
, UNSPEC_TLS_OFF
);
6187 return gen_rtx_PLUS (Pmode
, gen_rtx_REG (Pmode
, arc_tp_regno
), addr
);
6194 /* Return true if SYMBOL_REF X binds locally. */
6197 arc_symbol_binds_local_p (const_rtx x
)
6199 return (SYMBOL_REF_DECL (x
)
6200 ? targetm
.binds_local_p (SYMBOL_REF_DECL (x
))
6201 : SYMBOL_REF_LOCAL_P (x
));
6204 /* Legitimize a pic address reference in ADDR. The return value is
6205 the legitimated address. */
6208 arc_legitimize_pic_address (rtx addr
)
6213 switch (GET_CODE (addr
))
6216 /* Can be one or our GOT or GOTOFFPC unspecs. This situation
6217 happens when an address is not a legitimate constant and we
6218 need the resolve it via force_reg in
6219 prepare_move_operands. */
6220 switch (XINT (addr
, 1))
6222 case ARC_UNSPEC_GOT
:
6223 case ARC_UNSPEC_GOTOFFPC
:
6224 /* Recover the symbol ref. */
6225 addr
= XVECEXP (addr
, 0, 0);
6232 /* TLS symbols are handled in different place. */
6233 if (SYMBOL_REF_TLS_MODEL (addr
))
6236 /* This symbol must be referenced via a load from the Global
6237 Offset Table (@GOTPC). */
6238 if (!arc_symbol_binds_local_p (addr
))
6239 return gen_const_mem (Pmode
, arc_unspec_offset (addr
, ARC_UNSPEC_GOT
));
6241 /* Local symb: use @pcl to access it. */
6244 return arc_unspec_offset (addr
, ARC_UNSPEC_GOTOFFPC
);
6253 /* Output address constant X to FILE, taking PIC into account. */
6256 arc_output_pic_addr_const (FILE * file
, rtx x
, int code
)
6261 switch (GET_CODE (x
))
6271 output_addr_const (file
, x
);
6273 /* Local functions do not get references through the PLT. */
6274 if (code
== 'P' && ! SYMBOL_REF_LOCAL_P (x
))
6275 fputs ("@plt", file
);
6279 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (XEXP (x
, 0)));
6280 assemble_name (file
, buf
);
6284 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (x
));
6285 assemble_name (file
, buf
);
6289 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
));
6293 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
6297 if (GET_MODE (x
) == VOIDmode
)
6299 /* We can use %d if the number is one word and positive. */
6300 if (CONST_DOUBLE_HIGH (x
))
6301 fprintf (file
, HOST_WIDE_INT_PRINT_DOUBLE_HEX
,
6302 CONST_DOUBLE_HIGH (x
), CONST_DOUBLE_LOW (x
));
6303 else if (CONST_DOUBLE_LOW (x
) < 0)
6304 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, CONST_DOUBLE_LOW (x
));
6306 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, CONST_DOUBLE_LOW (x
));
6309 /* We can't handle floating point constants;
6310 PRINT_OPERAND must handle them. */
6311 output_operand_lossage ("floating constant misused");
6315 /* FIXME: Not needed here. */
6316 /* Some assemblers need integer constants to appear last (eg masm). */
6317 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
6319 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
6320 fprintf (file
, "+");
6321 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
6323 else if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
6325 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
6326 if (INTVAL (XEXP (x
, 1)) >= 0)
6327 fprintf (file
, "+");
6328 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
6335 /* Avoid outputting things like x-x or x+5-x,
6336 since some assemblers can't handle that. */
6337 x
= simplify_subtraction (x
);
6338 if (GET_CODE (x
) != MINUS
)
6341 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
6342 fprintf (file
, "-");
6343 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
6344 && INTVAL (XEXP (x
, 1)) < 0)
6346 fprintf (file
, "(");
6347 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
6348 fprintf (file
, ")");
6351 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
6356 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
6362 bool pcrel
; pcrel
= false;
6363 rtx base
; base
= NULL
;
6364 gcc_assert (XVECLEN (x
, 0) >= 1);
6365 switch (XINT (x
, 1))
6367 case ARC_UNSPEC_GOT
:
6368 suffix
= "@gotpc", pcrel
= true;
6370 case ARC_UNSPEC_GOTOFF
:
6373 case ARC_UNSPEC_GOTOFFPC
:
6374 suffix
= "@pcl", pcrel
= true;
6376 case ARC_UNSPEC_PLT
:
6380 suffix
= "@tlsgd", pcrel
= true;
6383 suffix
= "@tlsie", pcrel
= true;
6385 case UNSPEC_TLS_OFF
:
6386 if (XVECLEN (x
, 0) == 2)
6387 base
= XVECEXP (x
, 0, 1);
6388 if (SYMBOL_REF_TLS_MODEL (XVECEXP (x
, 0, 0)) == TLS_MODEL_LOCAL_EXEC
6389 || (!flag_pic
&& !base
))
6395 suffix
= "@invalid";
6396 output_operand_lossage ("invalid UNSPEC as operand: %d", XINT (x
,1));
6400 fputs ("pcl,", file
);
6401 arc_output_pic_addr_const (file
, XVECEXP (x
, 0, 0), code
);
6402 fputs (suffix
, file
);
6404 arc_output_pic_addr_const (file
, base
, code
);
6408 output_operand_lossage ("invalid expression as operand");
6412 /* The function returning the number of words, at the beginning of an
6413 argument, must be put in registers. The returned value must be
6414 zero for arguments that are passed entirely in registers or that
6415 are entirely pushed on the stack.
6417 On some machines, certain arguments must be passed partially in
6418 registers and partially in memory. On these machines, typically
6419 the first N words of arguments are passed in registers, and the
6420 rest on the stack. If a multi-word argument (a `double' or a
6421 structure) crosses that boundary, its first few words must be
6422 passed in registers and the rest must be pushed. This function
6423 tells the compiler when this occurs, and how many of the words
6424 should go in registers.
6426 `FUNCTION_ARG' for these arguments should return the first register
6427 to be used by the caller for this argument; likewise
6428 `FUNCTION_INCOMING_ARG', for the called function.
6430 The function is used to implement macro FUNCTION_ARG_PARTIAL_NREGS. */
6432 /* If REGNO is the least arg reg available then what is the total number of arg
6434 #define GPR_REST_ARG_REGS(REGNO) \
6435 ((REGNO) <= MAX_ARC_PARM_REGS ? MAX_ARC_PARM_REGS - (REGNO) : 0 )
6437 /* Since arc parm regs are contiguous. */
6438 #define ARC_NEXT_ARG_REG(REGNO) ( (REGNO) + 1 )
6440 /* Implement TARGET_ARG_PARTIAL_BYTES. */
6443 arc_arg_partial_bytes (cumulative_args_t cum_v
, const function_arg_info
&arg
)
6445 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
6446 int bytes
= arg
.promoted_size_in_bytes ();
6447 int words
= (bytes
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
6451 arg_num
= ROUND_ADVANCE_CUM (arg_num
, arg
.mode
, arg
.type
);
6452 ret
= GPR_REST_ARG_REGS (arg_num
);
6454 /* ICEd at function.cc:2361, and ret is copied to data->partial */
6455 ret
= (ret
>= words
? 0 : ret
* UNITS_PER_WORD
);
6460 /* Implement TARGET_FUNCTION_ARG. On the ARC the first MAX_ARC_PARM_REGS
6461 args are normally in registers and the rest are pushed. */
6464 arc_function_arg (cumulative_args_t cum_v
, const function_arg_info
&arg
)
6466 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
6469 const char *debstr ATTRIBUTE_UNUSED
;
6471 arg_num
= ROUND_ADVANCE_CUM (arg_num
, arg
.mode
, arg
.type
);
6472 /* Return a marker for use in the call instruction. */
6473 if (arg
.end_marker_p ())
6478 else if (GPR_REST_ARG_REGS (arg_num
) > 0)
6480 ret
= gen_rtx_REG (arg
.mode
, arg_num
);
6481 debstr
= reg_names
[arg_num
];
6491 /* Implement TARGET_FUNCTION_ARG_ADVANCE. */
6492 /* For the ARC: the cum set here is passed on to function_arg where we
6493 look at its value and say which reg to use. Strategy: advance the
6494 regnumber here till we run out of arg regs, then set *cum to last
6495 reg. In function_arg, since *cum > last arg reg we would return 0
6496 and thus the arg will end up on the stack. For straddling args of
6497 course function_arg_partial_nregs will come into play. */
6500 arc_function_arg_advance (cumulative_args_t cum_v
,
6501 const function_arg_info
&arg
)
6503 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
6504 int bytes
= arg
.promoted_size_in_bytes ();
6505 int words
= (bytes
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
6509 *cum
= ROUND_ADVANCE_CUM (*cum
, arg
.mode
, arg
.type
);
6510 for (i
= 0; i
< words
; i
++)
6511 *cum
= ARC_NEXT_ARG_REG (*cum
);
6515 /* Define how to find the value returned by a function.
6516 VALTYPE is the data type of the value (as a tree).
6517 If the precise function being called is known, FN_DECL_OR_TYPE is its
6518 FUNCTION_DECL; otherwise, FN_DECL_OR_TYPE is its type. */
6521 arc_function_value (const_tree valtype
,
6522 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
6523 bool outgoing ATTRIBUTE_UNUSED
)
6525 machine_mode mode
= TYPE_MODE (valtype
);
6526 int unsignedp ATTRIBUTE_UNUSED
;
6528 unsignedp
= TYPE_UNSIGNED (valtype
);
6529 if (INTEGRAL_TYPE_P (valtype
) || TREE_CODE (valtype
) == OFFSET_TYPE
)
6530 PROMOTE_MODE (mode
, unsignedp
, valtype
);
6531 return gen_rtx_REG (mode
, 0);
6534 /* Returns the return address that is used by builtin_return_address. */
6537 arc_return_addr_rtx (int count
, ATTRIBUTE_UNUSED rtx frame
)
6542 return get_hard_reg_initial_val (Pmode
, RETURN_ADDR_REGNUM
);
6545 /* Determine if a given RTX is a valid constant. We already know this
6546 satisfies CONSTANT_P. */
6549 arc_legitimate_constant_p (machine_mode mode
, rtx x
)
6551 switch (GET_CODE (x
))
6556 if (arc_legitimate_pic_addr_p (x
))
6559 return arc_legitimate_constant_p (mode
, XEXP (x
, 0));
6562 if (SYMBOL_REF_TLS_MODEL (x
))
6574 return arc_legitimate_constant_p (mode
, XEXP (x
, 0));
6579 bool t1
= arc_legitimate_constant_p (mode
, XEXP (x
, 0));
6580 bool t2
= arc_legitimate_constant_p (mode
, XEXP (x
, 1));
6589 return TARGET_PLUS_DMPY
;
6592 return TARGET_PLUS_QMACW
;
6598 switch (XINT (x
, 1))
6601 case UNSPEC_TLS_OFF
:
6605 /* Any other unspec ending here are pic related, hence the above
6606 constant pic address checking returned false. */
6612 fatal_insn ("unrecognized supposed constant", x
);
6619 arc_legitimate_address_p (machine_mode mode
, rtx x
, bool strict
,
6620 code_helper
= ERROR_MARK
)
6622 if (RTX_OK_FOR_BASE_P (x
, strict
))
6624 if (legitimate_offset_address_p (mode
, x
, TARGET_INDEXED_LOADS
, strict
))
6626 if (legitimate_scaled_address_p (mode
, x
, strict
))
6628 if (legitimate_small_data_address_p (x
, mode
))
6630 if (GET_CODE (x
) == CONST_INT
&& LARGE_INT (INTVAL (x
)))
6633 /* When we compile for size avoid const (@sym + offset)
6635 if (!flag_pic
&& optimize_size
&& !reload_completed
6636 && (GET_CODE (x
) == CONST
)
6637 && (GET_CODE (XEXP (x
, 0)) == PLUS
)
6638 && (GET_CODE (XEXP (XEXP (x
, 0), 0)) == SYMBOL_REF
)
6639 && SYMBOL_REF_TLS_MODEL (XEXP (XEXP (x
, 0), 0)) == 0
6640 && !SYMBOL_REF_FUNCTION_P (XEXP (XEXP (x
, 0), 0)))
6642 rtx addend
= XEXP (XEXP (x
, 0), 1);
6643 gcc_assert (CONST_INT_P (addend
));
6644 HOST_WIDE_INT offset
= INTVAL (addend
);
6646 /* Allow addresses having a large offset to pass. Anyhow they
6647 will end in a limm. */
6648 return !(offset
> -1024 && offset
< 1020);
6651 if ((GET_MODE_SIZE (mode
) != 16) && CONSTANT_P (x
))
6653 return arc_legitimate_constant_p (mode
, x
);
6655 if ((GET_CODE (x
) == PRE_DEC
|| GET_CODE (x
) == PRE_INC
6656 || GET_CODE (x
) == POST_DEC
|| GET_CODE (x
) == POST_INC
)
6657 && RTX_OK_FOR_BASE_P (XEXP (x
, 0), strict
))
6659 /* We're restricted here by the `st' insn. */
6660 if ((GET_CODE (x
) == PRE_MODIFY
|| GET_CODE (x
) == POST_MODIFY
)
6661 && GET_CODE (XEXP ((x
), 1)) == PLUS
6662 && rtx_equal_p (XEXP ((x
), 0), XEXP (XEXP (x
, 1), 0))
6663 && legitimate_offset_address_p (QImode
, XEXP (x
, 1),
6664 TARGET_AUTO_MODIFY_REG
, strict
))
6669 /* Return true iff ADDR (a legitimate address expression)
6670 has an effect that depends on the machine mode it is used for. */
6673 arc_mode_dependent_address_p (const_rtx addr
, addr_space_t
)
6675 /* SYMBOL_REF is not mode dependent: it is either a small data reference,
6676 which is valid for loads and stores, or a limm offset, which is valid for
6677 loads. Scaled indices are scaled by the access mode. */
6678 if (GET_CODE (addr
) == PLUS
6679 && GET_CODE (XEXP ((addr
), 0)) == MULT
)
6684 /* Determine if it's legal to put X into the constant pool. */
6687 arc_cannot_force_const_mem (machine_mode mode
, rtx x
)
6689 return !arc_legitimate_constant_p (mode
, x
);
6692 /* IDs for all the ARC builtins. */
6696 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, ICODE, MASK) \
6697 ARC_BUILTIN_ ## NAME,
6698 #include "builtins.def"
6704 struct GTY(()) arc_builtin_description
6706 enum insn_code icode
;
6711 static GTY(()) struct arc_builtin_description
6712 arc_bdesc
[ARC_BUILTIN_COUNT
] =
6714 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, ICODE, MASK) \
6715 { (enum insn_code) CODE_FOR_ ## ICODE, N_ARGS, NULL_TREE },
6716 #include "builtins.def"
6720 /* Transform UP into lowercase and write the result to LO.
6721 You must provide enough space for LO. Return LO. */
6724 arc_tolower (char *lo
, const char *up
)
6728 for (; *up
; up
++, lo
++)
6729 *lo
= TOLOWER (*up
);
6736 /* Implement `TARGET_BUILTIN_DECL'. */
6739 arc_builtin_decl (unsigned id
, bool initialize_p ATTRIBUTE_UNUSED
)
6741 if (id
< ARC_BUILTIN_COUNT
)
6742 return arc_bdesc
[id
].fndecl
;
6744 return error_mark_node
;
6748 arc_init_builtins (void)
6750 tree V4HI_type_node
;
6751 tree V2SI_type_node
;
6752 tree V2HI_type_node
;
6754 /* Vector types based on HS SIMD elements. */
6755 V4HI_type_node
= build_vector_type_for_mode (intHI_type_node
, V4HImode
);
6756 V2SI_type_node
= build_vector_type_for_mode (intSI_type_node
, V2SImode
);
6757 V2HI_type_node
= build_vector_type_for_mode (intHI_type_node
, V2HImode
);
6759 tree pcvoid_type_node
6760 = build_pointer_type (build_qualified_type (void_type_node
,
6762 tree V8HI_type_node
= build_vector_type_for_mode (intHI_type_node
,
6765 tree void_ftype_void
6766 = build_function_type_list (void_type_node
, NULL_TREE
);
6768 = build_function_type_list (integer_type_node
, integer_type_node
,
6770 tree int_ftype_pcvoid_int
6771 = build_function_type_list (integer_type_node
, pcvoid_type_node
,
6772 integer_type_node
, NULL_TREE
);
6773 tree void_ftype_usint_usint
6774 = build_function_type_list (void_type_node
, long_unsigned_type_node
,
6775 long_unsigned_type_node
, NULL_TREE
);
6776 tree int_ftype_int_int
6777 = build_function_type_list (integer_type_node
, integer_type_node
,
6778 integer_type_node
, NULL_TREE
);
6779 tree usint_ftype_usint
6780 = build_function_type_list (long_unsigned_type_node
,
6781 long_unsigned_type_node
, NULL_TREE
);
6782 tree void_ftype_usint
6783 = build_function_type_list (void_type_node
, long_unsigned_type_node
,
6786 = build_function_type_list (integer_type_node
, void_type_node
,
6789 = build_function_type_list (void_type_node
, integer_type_node
,
6791 tree int_ftype_short
6792 = build_function_type_list (integer_type_node
, short_integer_type_node
,
6795 /* Old ARC SIMD types. */
6796 tree v8hi_ftype_v8hi_v8hi
6797 = build_function_type_list (V8HI_type_node
, V8HI_type_node
,
6798 V8HI_type_node
, NULL_TREE
);
6799 tree v8hi_ftype_v8hi_int
6800 = build_function_type_list (V8HI_type_node
, V8HI_type_node
,
6801 integer_type_node
, NULL_TREE
);
6802 tree v8hi_ftype_v8hi_int_int
6803 = build_function_type_list (V8HI_type_node
, V8HI_type_node
,
6804 integer_type_node
, integer_type_node
,
6806 tree void_ftype_v8hi_int_int
6807 = build_function_type_list (void_type_node
, V8HI_type_node
,
6808 integer_type_node
, integer_type_node
,
6810 tree void_ftype_v8hi_int_int_int
6811 = build_function_type_list (void_type_node
, V8HI_type_node
,
6812 integer_type_node
, integer_type_node
,
6813 integer_type_node
, NULL_TREE
);
6814 tree v8hi_ftype_int_int
6815 = build_function_type_list (V8HI_type_node
, integer_type_node
,
6816 integer_type_node
, NULL_TREE
);
6817 tree void_ftype_int_int
6818 = build_function_type_list (void_type_node
, integer_type_node
,
6819 integer_type_node
, NULL_TREE
);
6820 tree v8hi_ftype_v8hi
6821 = build_function_type_list (V8HI_type_node
, V8HI_type_node
,
6823 /* ARCv2 SIMD types. */
6824 tree long_ftype_v4hi_v4hi
6825 = build_function_type_list (long_long_integer_type_node
,
6826 V4HI_type_node
, V4HI_type_node
, NULL_TREE
);
6827 tree int_ftype_v2hi_v2hi
6828 = build_function_type_list (integer_type_node
,
6829 V2HI_type_node
, V2HI_type_node
, NULL_TREE
);
6830 tree v2si_ftype_v2hi_v2hi
6831 = build_function_type_list (V2SI_type_node
,
6832 V2HI_type_node
, V2HI_type_node
, NULL_TREE
);
6833 tree v2hi_ftype_v2hi_v2hi
6834 = build_function_type_list (V2HI_type_node
,
6835 V2HI_type_node
, V2HI_type_node
, NULL_TREE
);
6836 tree v2si_ftype_v2si_v2si
6837 = build_function_type_list (V2SI_type_node
,
6838 V2SI_type_node
, V2SI_type_node
, NULL_TREE
);
6839 tree v4hi_ftype_v4hi_v4hi
6840 = build_function_type_list (V4HI_type_node
,
6841 V4HI_type_node
, V4HI_type_node
, NULL_TREE
);
6842 tree long_ftype_v2si_v2hi
6843 = build_function_type_list (long_long_integer_type_node
,
6844 V2SI_type_node
, V2HI_type_node
, NULL_TREE
);
6846 /* Add the builtins. */
6847 #define DEF_BUILTIN(NAME, N_ARGS, TYPE, ICODE, MASK) \
6849 int id = ARC_BUILTIN_ ## NAME; \
6850 const char *Name = "__builtin_arc_" #NAME; \
6851 char *name = (char*) alloca (1 + strlen (Name)); \
6853 gcc_assert (id < ARC_BUILTIN_COUNT); \
6855 arc_bdesc[id].fndecl \
6856 = add_builtin_function (arc_tolower(name, Name), TYPE, id, \
6857 BUILT_IN_MD, NULL, NULL_TREE); \
6859 #include "builtins.def"
6863 /* Helper to expand __builtin_arc_aligned (void* val, int
6867 arc_expand_builtin_aligned (tree exp
)
6869 tree arg0
= CALL_EXPR_ARG (exp
, 0);
6870 tree arg1
= CALL_EXPR_ARG (exp
, 1);
6872 rtx op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
6873 rtx op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
6875 if (!CONST_INT_P (op1
))
6877 /* If we can't fold the alignment to a constant integer
6878 whilst optimizing, this is probably a user error. */
6880 warning (0, "%<__builtin_arc_aligned%> with non-constant alignment");
6884 HOST_WIDE_INT alignTest
= INTVAL (op1
);
6885 /* Check alignTest is positive, and a power of two. */
6886 if (alignTest
<= 0 || alignTest
!= (alignTest
& -alignTest
))
6888 error ("invalid alignment value for %<__builtin_arc_aligned%>");
6892 if (CONST_INT_P (op0
))
6894 HOST_WIDE_INT pnt
= INTVAL (op0
);
6896 if ((pnt
& (alignTest
- 1)) == 0)
6901 unsigned align
= get_pointer_alignment (arg0
);
6902 unsigned numBits
= alignTest
* BITS_PER_UNIT
;
6904 if (align
&& align
>= numBits
)
6906 /* Another attempt to ascertain alignment. Check the type
6907 we are pointing to. */
6908 if (POINTER_TYPE_P (TREE_TYPE (arg0
))
6909 && TYPE_ALIGN (TREE_TYPE (TREE_TYPE (arg0
))) >= numBits
)
6914 /* Default to false. */
6918 /* Helper arc_expand_builtin, generates a pattern for the given icode
6922 apply_GEN_FCN (enum insn_code icode
, rtx
*arg
)
6924 switch (insn_data
[icode
].n_generator_args
)
6927 return GEN_FCN (icode
) ();
6929 return GEN_FCN (icode
) (arg
[0]);
6931 return GEN_FCN (icode
) (arg
[0], arg
[1]);
6933 return GEN_FCN (icode
) (arg
[0], arg
[1], arg
[2]);
6935 return GEN_FCN (icode
) (arg
[0], arg
[1], arg
[2], arg
[3]);
6937 return GEN_FCN (icode
) (arg
[0], arg
[1], arg
[2], arg
[3], arg
[4]);
6943 /* Expand an expression EXP that calls a built-in function,
6944 with result going to TARGET if that's convenient
6945 (and in mode MODE if that's convenient).
6946 SUBTARGET may be used as the target for computing one of EXP's operands.
6947 IGNORE is nonzero if the value is to be ignored. */
6950 arc_expand_builtin (tree exp
,
6952 rtx subtarget ATTRIBUTE_UNUSED
,
6953 machine_mode mode ATTRIBUTE_UNUSED
,
6954 int ignore ATTRIBUTE_UNUSED
)
6956 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
6957 unsigned int id
= DECL_MD_FUNCTION_CODE (fndecl
);
6958 const struct arc_builtin_description
*d
= &arc_bdesc
[id
];
6959 int i
, j
, n_args
= call_expr_nargs (exp
);
6962 enum insn_code icode
= d
->icode
;
6963 machine_mode tmode
= insn_data
[icode
].operand
[0].mode
;
6980 if (id
>= ARC_BUILTIN_COUNT
)
6981 internal_error ("bad builtin fcode");
6983 /* 1st part: Expand special builtins. */
6986 case ARC_BUILTIN_NOP
:
6987 emit_insn (gen_nopv ());
6990 case ARC_BUILTIN_RTIE
:
6991 case ARC_BUILTIN_SYNC
:
6992 case ARC_BUILTIN_BRK
:
6993 case ARC_BUILTIN_SWI
:
6994 case ARC_BUILTIN_UNIMP_S
:
6995 gcc_assert (icode
!= 0);
6996 emit_insn (GEN_FCN (icode
) (const1_rtx
));
6999 case ARC_BUILTIN_ALIGNED
:
7000 return arc_expand_builtin_aligned (exp
);
7002 case ARC_BUILTIN_CLRI
:
7003 target
= gen_reg_rtx (SImode
);
7004 emit_insn (gen_clri (target
, const1_rtx
));
7007 case ARC_BUILTIN_TRAP_S
:
7008 case ARC_BUILTIN_SLEEP
:
7009 arg0
= CALL_EXPR_ARG (exp
, 0);
7011 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
7013 gcc_assert (icode
!= 0);
7014 emit_insn (GEN_FCN (icode
) (op0
));
7017 case ARC_BUILTIN_VDORUN
:
7018 case ARC_BUILTIN_VDIRUN
:
7019 arg0
= CALL_EXPR_ARG (exp
, 0);
7020 arg1
= CALL_EXPR_ARG (exp
, 1);
7021 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7022 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7024 target
= gen_rtx_REG (SImode
, (id
== ARC_BUILTIN_VDIRUN
) ? 131 : 139);
7026 mode0
= insn_data
[icode
].operand
[1].mode
;
7027 mode1
= insn_data
[icode
].operand
[2].mode
;
7029 if (!insn_data
[icode
].operand
[1].predicate (op0
, mode0
))
7030 op0
= copy_to_mode_reg (mode0
, op0
);
7032 if (!insn_data
[icode
].operand
[2].predicate (op1
, mode1
))
7033 op1
= copy_to_mode_reg (mode1
, op1
);
7035 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
7042 case ARC_BUILTIN_VDIWR
:
7043 case ARC_BUILTIN_VDOWR
:
7044 arg0
= CALL_EXPR_ARG (exp
, 0);
7045 arg1
= CALL_EXPR_ARG (exp
, 1);
7046 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7047 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7049 if (!CONST_INT_P (op0
)
7050 || !(UNSIGNED_INT3 (INTVAL (op0
))))
7051 error ("operand 1 should be an unsigned 3-bit immediate");
7053 mode1
= insn_data
[icode
].operand
[1].mode
;
7055 if (icode
== CODE_FOR_vdiwr_insn
)
7056 target
= gen_rtx_REG (SImode
,
7057 ARC_FIRST_SIMD_DMA_CONFIG_IN_REG
+ INTVAL (op0
));
7058 else if (icode
== CODE_FOR_vdowr_insn
)
7059 target
= gen_rtx_REG (SImode
,
7060 ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG
+ INTVAL (op0
));
7064 if (!insn_data
[icode
].operand
[2].predicate (op1
, mode1
))
7065 op1
= copy_to_mode_reg (mode1
, op1
);
7067 pat
= GEN_FCN (icode
) (target
, op1
);
7074 case ARC_BUILTIN_VASRW
:
7075 case ARC_BUILTIN_VSR8
:
7076 case ARC_BUILTIN_VSR8AW
:
7077 arg0
= CALL_EXPR_ARG (exp
, 0);
7078 arg1
= CALL_EXPR_ARG (exp
, 1);
7079 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
7080 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7081 op2
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
);
7083 target
= gen_reg_rtx (V8HImode
);
7084 mode0
= insn_data
[icode
].operand
[1].mode
;
7085 mode1
= insn_data
[icode
].operand
[2].mode
;
7087 if (!insn_data
[icode
].operand
[1].predicate (op0
, mode0
))
7088 op0
= copy_to_mode_reg (mode0
, op0
);
7090 if ((!insn_data
[icode
].operand
[2].predicate (op1
, mode1
))
7091 || !(UNSIGNED_INT3 (INTVAL (op1
))))
7092 error ("operand 2 should be an unsigned 3-bit value (I0-I7)");
7094 pat
= GEN_FCN (icode
) (target
, op0
, op1
, op2
);
7101 case ARC_BUILTIN_VLD32WH
:
7102 case ARC_BUILTIN_VLD32WL
:
7103 case ARC_BUILTIN_VLD64
:
7104 case ARC_BUILTIN_VLD32
:
7107 arg0
= CALL_EXPR_ARG (exp
, 0); /* source vreg. */
7108 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7. */
7109 arg2
= CALL_EXPR_ARG (exp
, 2); /* u8. */
7111 src_vreg
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
7112 op0
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7113 op1
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7114 op2
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
);
7116 /* target <- src vreg. */
7117 emit_insn (gen_move_insn (target
, src_vreg
));
7119 /* target <- vec_concat: target, mem (Ib, u8). */
7120 mode0
= insn_data
[icode
].operand
[3].mode
;
7121 mode1
= insn_data
[icode
].operand
[1].mode
;
7123 if ((!insn_data
[icode
].operand
[3].predicate (op0
, mode0
))
7124 || !(UNSIGNED_INT3 (INTVAL (op0
))))
7125 error ("operand 1 should be an unsigned 3-bit value (I0-I7)");
7127 if ((!insn_data
[icode
].operand
[1].predicate (op1
, mode1
))
7128 || !(UNSIGNED_INT8 (INTVAL (op1
))))
7129 error ("operand 2 should be an unsigned 8-bit value");
7131 pat
= GEN_FCN (icode
) (target
, op1
, op2
, op0
);
7138 case ARC_BUILTIN_VLD64W
:
7139 case ARC_BUILTIN_VLD128
:
7140 arg0
= CALL_EXPR_ARG (exp
, 0); /* dest vreg. */
7141 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7. */
7143 op0
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
);
7144 op1
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7145 op2
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7147 /* target <- src vreg. */
7148 target
= gen_reg_rtx (V8HImode
);
7150 /* target <- vec_concat: target, mem (Ib, u8). */
7151 mode0
= insn_data
[icode
].operand
[1].mode
;
7152 mode1
= insn_data
[icode
].operand
[2].mode
;
7153 mode2
= insn_data
[icode
].operand
[3].mode
;
7155 if ((!insn_data
[icode
].operand
[2].predicate (op1
, mode1
))
7156 || !(UNSIGNED_INT3 (INTVAL (op1
))))
7157 error ("operand 1 should be an unsigned 3-bit value (I0-I7)");
7159 if ((!insn_data
[icode
].operand
[3].predicate (op2
, mode2
))
7160 || !(UNSIGNED_INT8 (INTVAL (op2
))))
7161 error ("operand 2 should be an unsigned 8-bit value");
7163 pat
= GEN_FCN (icode
) (target
, op0
, op1
, op2
);
7171 case ARC_BUILTIN_VST128
:
7172 case ARC_BUILTIN_VST64
:
7173 arg0
= CALL_EXPR_ARG (exp
, 0); /* src vreg. */
7174 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7. */
7175 arg2
= CALL_EXPR_ARG (exp
, 2); /* u8. */
7177 op0
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
);
7178 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7179 op2
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7180 op3
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
7182 mode0
= insn_data
[icode
].operand
[0].mode
;
7183 mode1
= insn_data
[icode
].operand
[1].mode
;
7184 mode2
= insn_data
[icode
].operand
[2].mode
;
7185 mode3
= insn_data
[icode
].operand
[3].mode
;
7187 if ((!insn_data
[icode
].operand
[1].predicate (op1
, mode1
))
7188 || !(UNSIGNED_INT3 (INTVAL (op1
))))
7189 error ("operand 2 should be an unsigned 3-bit value (I0-I7)");
7191 if ((!insn_data
[icode
].operand
[2].predicate (op2
, mode2
))
7192 || !(UNSIGNED_INT8 (INTVAL (op2
))))
7193 error ("operand 3 should be an unsigned 8-bit value");
7195 if (!insn_data
[icode
].operand
[3].predicate (op3
, mode3
))
7196 op3
= copy_to_mode_reg (mode3
, op3
);
7198 pat
= GEN_FCN (icode
) (op0
, op1
, op2
, op3
);
7205 case ARC_BUILTIN_VST16_N
:
7206 case ARC_BUILTIN_VST32_N
:
7207 arg0
= CALL_EXPR_ARG (exp
, 0); /* source vreg. */
7208 arg1
= CALL_EXPR_ARG (exp
, 1); /* u3. */
7209 arg2
= CALL_EXPR_ARG (exp
, 2); /* [I]0-7. */
7210 arg3
= CALL_EXPR_ARG (exp
, 3); /* u8. */
7212 op0
= expand_expr (arg3
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7213 op1
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
);
7214 op2
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7215 op3
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
7216 op4
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7218 mode0
= insn_data
[icode
].operand
[0].mode
;
7219 mode2
= insn_data
[icode
].operand
[2].mode
;
7220 mode3
= insn_data
[icode
].operand
[3].mode
;
7221 mode4
= insn_data
[icode
].operand
[4].mode
;
7223 /* Do some correctness checks for the operands. */
7224 if ((!insn_data
[icode
].operand
[0].predicate (op0
, mode0
))
7225 || !(UNSIGNED_INT8 (INTVAL (op0
))))
7226 error ("operand 4 should be an unsigned 8-bit value (0-255)");
7228 if ((!insn_data
[icode
].operand
[2].predicate (op2
, mode2
))
7229 || !(UNSIGNED_INT3 (INTVAL (op2
))))
7230 error ("operand 3 should be an unsigned 3-bit value (I0-I7)");
7232 if (!insn_data
[icode
].operand
[3].predicate (op3
, mode3
))
7233 op3
= copy_to_mode_reg (mode3
, op3
);
7235 if ((!insn_data
[icode
].operand
[4].predicate (op4
, mode4
))
7236 || !(UNSIGNED_INT3 (INTVAL (op4
))))
7237 error ("operand 2 should be an unsigned 3-bit value (subreg 0-7)");
7238 else if (icode
== CODE_FOR_vst32_n_insn
7239 && ((INTVAL (op4
) % 2) != 0))
7240 error ("operand 2 should be an even 3-bit value (subreg 0,2,4,6)");
7242 pat
= GEN_FCN (icode
) (op0
, op1
, op2
, op3
, op4
);
7253 /* 2nd part: Expand regular builtins. */
7255 internal_error ("bad builtin fcode");
7257 nonvoid
= TREE_TYPE (TREE_TYPE (fndecl
)) != void_type_node
;
7262 if (target
== NULL_RTX
7263 || GET_MODE (target
) != tmode
7264 || !insn_data
[icode
].operand
[0].predicate (target
, tmode
))
7266 target
= gen_reg_rtx (tmode
);
7271 gcc_assert (n_args
<= 4);
7272 for (i
= 0; i
< n_args
; i
++, j
++)
7274 tree arg
= CALL_EXPR_ARG (exp
, i
);
7275 machine_mode mode
= insn_data
[icode
].operand
[j
].mode
;
7276 rtx op
= expand_expr (arg
, NULL_RTX
, mode
, EXPAND_NORMAL
);
7277 machine_mode opmode
= GET_MODE (op
);
7278 char c
= insn_data
[icode
].operand
[j
].constraint
[0];
7280 /* SIMD extension requires exact immediate operand match. */
7281 if ((id
> ARC_BUILTIN_SIMD_BEGIN
)
7282 && (id
< ARC_BUILTIN_SIMD_END
)
7286 if (!CONST_INT_P (op
))
7287 error ("builtin requires an immediate for operand %d", j
);
7291 if (!satisfies_constraint_L (op
))
7292 error ("operand %d should be a 6 bit unsigned immediate", j
);
7295 if (!satisfies_constraint_P (op
))
7296 error ("operand %d should be a 8 bit unsigned immediate", j
);
7299 if (!satisfies_constraint_K (op
))
7300 error ("operand %d should be a 3 bit unsigned immediate", j
);
7303 error ("unknown builtin immediate operand type for operand %d",
7308 if (CONST_INT_P (op
))
7311 if ((opmode
== SImode
) && (mode
== HImode
))
7314 op
= gen_lowpart (HImode
, op
);
7317 /* In case the insn wants input operands in modes different from
7318 the result, abort. */
7319 gcc_assert (opmode
== mode
|| opmode
== VOIDmode
);
7321 if (!insn_data
[icode
].operand
[i
+ nonvoid
].predicate (op
, mode
))
7322 op
= copy_to_mode_reg (mode
, op
);
7327 pat
= apply_GEN_FCN (icode
, xop
);
7328 if (pat
== NULL_RTX
)
7339 /* Implement TARGET_FOLD_BUILTIN. */
7342 arc_fold_builtin (tree fndecl
, int n_args ATTRIBUTE_UNUSED
, tree
*arg
,
7343 bool ignore ATTRIBUTE_UNUSED
)
7345 unsigned int fcode
= DECL_MD_FUNCTION_CODE (fndecl
);
7352 case ARC_BUILTIN_SWAP
:
7353 return fold_build2 (LROTATE_EXPR
, integer_type_node
, arg
[0],
7354 build_int_cst (integer_type_node
, 16));
7356 case ARC_BUILTIN_NORM
:
7357 if (TREE_CODE (arg
[0]) == INTEGER_CST
7358 && !TREE_OVERFLOW (arg
[0]))
7360 wide_int arg0
= wi::to_wide (arg
[0], 32);
7361 wide_int result
= wi::shwi (wi::clrsb (arg0
), 32);
7362 return wide_int_to_tree (integer_type_node
, result
);
7366 case ARC_BUILTIN_NORMW
:
7367 if (TREE_CODE (arg
[0]) == INTEGER_CST
7368 && !TREE_OVERFLOW (arg
[0]))
7370 wide_int arg0
= wi::to_wide (arg
[0], 16);
7371 wide_int result
= wi::shwi (wi::clrsb (arg0
), 32);
7372 return wide_int_to_tree (integer_type_node
, result
);
7379 /* Returns true if the operands[opno] is a valid compile-time constant to be
7380 used as register number in the code for builtins. Else it flags an error
7381 and returns false. */
7384 check_if_valid_regno_const (rtx
*operands
, int opno
)
7387 switch (GET_CODE (operands
[opno
]))
7394 error ("register number must be a compile-time constant. "
7395 "Try giving higher optimization levels");
7401 /* Return true if it is ok to make a tail-call to DECL. */
7404 arc_function_ok_for_sibcall (tree decl
,
7405 tree exp ATTRIBUTE_UNUSED
)
7407 tree attrs
= NULL_TREE
;
7409 /* Never tailcall from an ISR routine - it needs a special exit sequence. */
7410 if (ARC_INTERRUPT_P (arc_compute_function_type (cfun
)))
7415 attrs
= TYPE_ATTRIBUTES (TREE_TYPE (decl
));
7417 if (lookup_attribute ("jli_always", attrs
))
7419 if (lookup_attribute ("jli_fixed", attrs
))
7421 if (lookup_attribute ("secure_call", attrs
))
7425 /* Everything else is ok. */
7429 /* Output code to add DELTA to the first argument, and then jump
7430 to FUNCTION. Used for C++ multiple inheritance. */
7433 arc_output_mi_thunk (FILE *file
, tree thunk ATTRIBUTE_UNUSED
,
7434 HOST_WIDE_INT delta
,
7435 HOST_WIDE_INT vcall_offset
,
7438 const char *fnname
= IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk
));
7439 int mi_delta
= delta
;
7440 const char *const mi_op
= mi_delta
< 0 ? "sub" : "add";
7443 = aggregate_value_p (TREE_TYPE (TREE_TYPE (function
)), function
) ? 1 : 0;
7446 assemble_start_function (thunk
, fnname
);
7449 mi_delta
= - mi_delta
;
7451 /* Add DELTA. When possible use a plain add, otherwise load it into
7452 a register first. */
7454 while (mi_delta
!= 0)
7456 if ((mi_delta
& (3 << shift
)) == 0)
7460 asm_fprintf (file
, "\t%s\t%s, %s, %d\n",
7461 mi_op
, reg_names
[this_regno
], reg_names
[this_regno
],
7462 mi_delta
& (0xff << shift
));
7463 mi_delta
&= ~(0xff << shift
);
7468 /* If needed, add *(*THIS + VCALL_OFFSET) to THIS. */
7469 if (vcall_offset
!= 0)
7471 /* ld r12,[this] --> temp = *this
7472 add r12,r12,vcall_offset --> temp = *(*this + vcall_offset)
7474 add this,this,r12 --> this+ = *(*this + vcall_offset) */
7475 asm_fprintf (file
, "\tld\t%s, [%s]\n",
7476 ARC_TEMP_SCRATCH_REG
, reg_names
[this_regno
]);
7477 asm_fprintf (file
, "\tadd\t%s, %s, " HOST_WIDE_INT_PRINT_DEC
"\n",
7478 ARC_TEMP_SCRATCH_REG
, ARC_TEMP_SCRATCH_REG
, vcall_offset
);
7479 asm_fprintf (file
, "\tld\t%s, [%s]\n",
7480 ARC_TEMP_SCRATCH_REG
, ARC_TEMP_SCRATCH_REG
);
7481 asm_fprintf (file
, "\tadd\t%s, %s, %s\n", reg_names
[this_regno
],
7482 reg_names
[this_regno
], ARC_TEMP_SCRATCH_REG
);
7485 fnaddr
= XEXP (DECL_RTL (function
), 0);
7487 if (arc_is_longcall_p (fnaddr
))
7491 asm_fprintf (file
, "\tld\t%s, [pcl, @",
7492 ARC_TEMP_SCRATCH_REG
);
7493 assemble_name (file
, XSTR (fnaddr
, 0));
7494 fputs ("@gotpc]\n", file
);
7495 asm_fprintf (file
, "\tj\t[%s]", ARC_TEMP_SCRATCH_REG
);
7499 fputs ("\tj\t@", file
);
7500 assemble_name (file
, XSTR (fnaddr
, 0));
7505 fputs ("\tb\t@", file
);
7506 assemble_name (file
, XSTR (fnaddr
, 0));
7508 fputs ("@plt\n", file
);
7511 assemble_end_function (thunk
, fnname
);
7514 /* Return true if a 32 bit "long_call" should be generated for
7515 this calling SYM_REF. We generate a long_call if the function:
7517 a. has an __attribute__((long call))
7518 or b. the -mlong-calls command line switch has been specified
7520 However we do not generate a long call if the function has an
7521 __attribute__ ((short_call)) or __attribute__ ((medium_call))
7523 This function will be called by C fragments contained in the machine
7524 description file. */
7527 arc_is_longcall_p (rtx sym_ref
)
7529 if (GET_CODE (sym_ref
) != SYMBOL_REF
)
7532 return (SYMBOL_REF_LONG_CALL_P (sym_ref
)
7533 || (TARGET_LONG_CALLS_SET
7534 && !SYMBOL_REF_SHORT_CALL_P (sym_ref
)
7535 && !SYMBOL_REF_MEDIUM_CALL_P (sym_ref
)));
7539 /* Likewise for short calls. */
7542 arc_is_shortcall_p (rtx sym_ref
)
7544 if (GET_CODE (sym_ref
) != SYMBOL_REF
)
7547 return (SYMBOL_REF_SHORT_CALL_P (sym_ref
)
7548 || (!TARGET_LONG_CALLS_SET
&& !TARGET_MEDIUM_CALLS
7549 && !SYMBOL_REF_LONG_CALL_P (sym_ref
)
7550 && !SYMBOL_REF_MEDIUM_CALL_P (sym_ref
)));
7554 /* Worker function for TARGET_RETURN_IN_MEMORY. */
7557 arc_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
7559 if (AGGREGATE_TYPE_P (type
) || TREE_ADDRESSABLE (type
))
7563 HOST_WIDE_INT size
= int_size_in_bytes (type
);
7564 return (size
== -1 || size
> (TARGET_V2
? 16 : 8));
7569 arc_pass_by_reference (cumulative_args_t
, const function_arg_info
&arg
)
7571 return (arg
.type
!= 0
7572 && (TREE_CODE (TYPE_SIZE (arg
.type
)) != INTEGER_CST
7573 || TREE_ADDRESSABLE (arg
.type
)));
7576 /* Implement TARGET_CAN_USE_DOLOOP_P. */
7579 arc_can_use_doloop_p (const widest_int
&,
7580 const widest_int
&iterations_max
,
7581 unsigned int loop_depth
, bool entered_at_top
)
7583 /* Considering limitations in the hardware, only use doloop
7584 for innermost loops which must be entered from the top. */
7585 if (loop_depth
> 1 || !entered_at_top
)
7588 /* Check for lp_count width boundary. */
7589 if (arc_lpcwidth
!= 32
7590 && (wi::gtu_p (iterations_max
, ((1 << arc_lpcwidth
) - 1))
7591 || wi::eq_p (iterations_max
, 0)))
7596 /* NULL if INSN insn is valid within a low-overhead loop. Otherwise
7597 return why doloop cannot be applied. */
7600 arc_invalid_within_doloop (const rtx_insn
*insn
)
7603 return "Function call in the loop.";
7605 /* FIXME! add here all the ZOL exceptions. */
7609 /* Return the next active insn, skiping the inline assembly code. */
7612 arc_active_insn (rtx_insn
*insn
)
7616 insn
= NEXT_INSN (insn
);
7618 || (active_insn_p (insn
)
7619 && NONDEBUG_INSN_P (insn
)
7621 && GET_CODE (PATTERN (insn
)) != UNSPEC_VOLATILE
7622 && GET_CODE (PATTERN (insn
)) != PARALLEL
))
7628 /* Search for a sequence made out of two stores and a given number of
7629 loads, insert a nop if required. */
7632 check_store_cacheline_hazard (void)
7634 rtx_insn
*insn
, *succ0
, *insn1
;
7637 for (insn
= get_insns (); insn
; insn
= arc_active_insn (insn
))
7639 succ0
= arc_active_insn (insn
);
7644 if (!single_set (insn
))
7647 if ((get_attr_type (insn
) != TYPE_STORE
))
7650 /* Found at least two consecutive stores. Goto the end of the
7652 for (insn1
= succ0
; insn1
; insn1
= arc_active_insn (insn1
))
7653 if (!single_set (insn1
) || get_attr_type (insn1
) != TYPE_STORE
)
7656 /* Save were we are. */
7659 /* Now, check the next two instructions for the following cases:
7660 1. next instruction is a LD => insert 2 nops between store
7662 2. next-next instruction is a LD => inset 1 nop after the store
7664 if (insn1
&& single_set (insn1
)
7665 && (get_attr_type (insn1
) == TYPE_LOAD
))
7668 emit_insn_before (gen_nopv (), insn1
);
7669 emit_insn_before (gen_nopv (), insn1
);
7673 if (insn1
&& (get_attr_type (insn1
) == TYPE_COMPARE
))
7675 /* REG_SAVE_NOTE is used by Haifa scheduler, we are in
7676 reorg, so it is safe to reuse it for avoiding the
7677 current compare insn to be part of a BRcc
7679 add_reg_note (insn1
, REG_SAVE_NOTE
, GEN_INT (3));
7681 insn1
= arc_active_insn (insn1
);
7682 if (insn1
&& single_set (insn1
)
7683 && (get_attr_type (insn1
) == TYPE_LOAD
))
7686 emit_insn_before (gen_nopv (), insn1
);
7700 /* Return true if a load instruction (CONSUMER) uses the same address as a
7701 store instruction (PRODUCER). This function is used to avoid st/ld
7702 address hazard in ARC700 cores. */
7705 arc_store_addr_hazard_internal_p (rtx_insn
* producer
, rtx_insn
* consumer
)
7707 rtx in_set
, out_set
;
7708 rtx out_addr
, in_addr
;
7716 /* Peel the producer and the consumer for the address. */
7717 out_set
= single_set (producer
);
7720 out_addr
= SET_DEST (out_set
);
7723 if (GET_CODE (out_addr
) == ZERO_EXTEND
7724 || GET_CODE (out_addr
) == SIGN_EXTEND
)
7725 out_addr
= XEXP (out_addr
, 0);
7727 if (!MEM_P (out_addr
))
7730 in_set
= single_set (consumer
);
7733 in_addr
= SET_SRC (in_set
);
7736 if (GET_CODE (in_addr
) == ZERO_EXTEND
7737 || GET_CODE (in_addr
) == SIGN_EXTEND
)
7738 in_addr
= XEXP (in_addr
, 0);
7740 if (!MEM_P (in_addr
))
7742 /* Get rid of the MEM and check if the addresses are
7744 in_addr
= XEXP (in_addr
, 0);
7745 out_addr
= XEXP (out_addr
, 0);
7747 return exp_equiv_p (in_addr
, out_addr
, 0, true);
7753 /* Return TRUE is we have an store address hazard. */
7756 arc_store_addr_hazard_p (rtx_insn
* producer
, rtx_insn
* consumer
)
7758 if (TARGET_ARC700
&& (arc_tune
!= ARC_TUNE_ARC7XX
))
7760 return arc_store_addr_hazard_internal_p (producer
, consumer
);
7763 /* Return length adjustment for INSN.
7765 A write to a core reg greater or equal to 32 must not be immediately
7766 followed by a use. Anticipate the length requirement to insert a nop
7767 between PRED and SUCC to prevent a hazard. */
7770 arc600_corereg_hazard (rtx_insn
*pred
, rtx_insn
*succ
)
7774 if (GET_CODE (PATTERN (pred
)) == SEQUENCE
)
7775 pred
= as_a
<rtx_sequence
*> (PATTERN (pred
))->insn (1);
7776 if (GET_CODE (PATTERN (succ
)) == SEQUENCE
)
7777 succ
= as_a
<rtx_sequence
*> (PATTERN (succ
))->insn (0);
7778 if (recog_memoized (pred
) == CODE_FOR_mulsi_600
7779 || recog_memoized (pred
) == CODE_FOR_umul_600
7780 || recog_memoized (pred
) == CODE_FOR_mac_600
7781 || recog_memoized (pred
) == CODE_FOR_mul64_600
7782 || recog_memoized (pred
) == CODE_FOR_mac64_600
7783 || recog_memoized (pred
) == CODE_FOR_umul64_600
7784 || recog_memoized (pred
) == CODE_FOR_umac64_600
)
7786 subrtx_iterator::array_type array
;
7787 FOR_EACH_SUBRTX (iter
, array
, PATTERN (pred
), NONCONST
)
7789 const_rtx x
= *iter
;
7790 switch (GET_CODE (x
))
7792 case SET
: case POST_INC
: case POST_DEC
: case PRE_INC
: case PRE_DEC
:
7795 /* This is also fine for PRE/POST_MODIFY, because they
7799 rtx dest
= XEXP (x
, 0);
7800 /* Check if this sets a an extension register. N.B. we use 61 for the
7801 condition codes, which is definitely not an extension register. */
7802 if (REG_P (dest
) && REGNO (dest
) >= 32 && REGNO (dest
) < 61
7803 /* Check if the same register is used by the PAT. */
7804 && (refers_to_regno_p
7806 REGNO (dest
) + (GET_MODE_SIZE (GET_MODE (dest
)) + 3) / 4U,
7807 PATTERN (succ
), 0)))
7814 A write to a core reg greater or equal to 32 must not be immediately
7815 followed by a use. Anticipate the length requirement to insert a nop
7816 between PRED and SUCC to prevent a hazard. */
7819 arc_hazard (rtx_insn
*pred
, rtx_insn
*succ
)
7821 if (!pred
|| !INSN_P (pred
) || !succ
|| !INSN_P (succ
))
7825 return arc600_corereg_hazard (pred
, succ
);
7830 /* When compiling for release 310a, insert a nop before any
7831 conditional jump. */
7834 arc_check_release31a (rtx_insn
*pred
, rtx_insn
*succ
)
7836 if (!pred
|| !INSN_P (pred
) || !succ
|| !INSN_P (succ
))
7839 if (!JUMP_P (pred
) && !single_set (pred
))
7842 if (!JUMP_P (succ
) && !single_set (succ
))
7845 if (TARGET_HS
&& (arc_tune
== ARC_TUNE_ARCHS4X_REL31A
))
7846 switch (get_attr_type (pred
))
7849 switch (get_attr_type (succ
))
7852 case TYPE_BRCC_NO_DELAY_SLOT
:
7860 case TYPE_BRCC_NO_DELAY_SLOT
:
7862 if (get_attr_type (succ
) == TYPE_STORE
)
7872 /* The same functionality as arc_hazard. It is called in machine
7873 reorg before any other optimization. Hence, the NOP size is taken
7874 into account when doing branch shortening. */
7877 workaround_arc_anomaly (void)
7879 rtx_insn
*insn
, *succ0
;
7881 /* For any architecture: call arc_hazard here. */
7882 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
7884 succ0
= next_real_insn (insn
);
7885 if (arc_hazard (insn
, succ0
) || arc_check_release31a (insn
, succ0
))
7886 emit_insn_before (gen_nopv (), succ0
);
7892 /* Old A7 are suffering of a cache hazard, and we need to insert two
7893 nops between any sequence of stores and a load. */
7894 if (arc_tune
!= ARC_TUNE_ARC7XX
)
7895 check_store_cacheline_hazard ();
7898 /* A callback for the hw-doloop pass. Called when a loop we have discovered
7899 turns out not to be optimizable; we have to split the loop_end pattern into
7900 a subtract and a test. */
7903 hwloop_fail (hwloop_info loop
)
7906 rtx insn
= loop
->loop_end
;
7909 && (loop
->length
&& (loop
->length
<= ARC_MAX_LOOP_LENGTH
))
7910 && REG_P (loop
->iter_reg
))
7912 /* TARGET_V2 core3 has dbnz instructions. */
7913 test
= gen_dbnz (loop
->iter_reg
, loop
->start_label
);
7914 insn
= emit_jump_insn_before (test
, loop
->loop_end
);
7916 else if (REG_P (loop
->iter_reg
) && (REGNO (loop
->iter_reg
) == LP_COUNT
))
7918 /* We have the lp_count as loop iterator, try to use it. */
7919 emit_insn_before (gen_loop_fail (), loop
->loop_end
);
7920 test
= gen_rtx_NE (VOIDmode
, gen_rtx_REG (CC_ZNmode
, CC_REG
),
7922 test
= gen_rtx_IF_THEN_ELSE (VOIDmode
, test
,
7923 gen_rtx_LABEL_REF (Pmode
, loop
->start_label
),
7925 insn
= emit_jump_insn_before (gen_rtx_SET (pc_rtx
, test
),
7930 emit_insn_before (gen_addsi3 (loop
->iter_reg
,
7934 test
= gen_rtx_NE (VOIDmode
, loop
->iter_reg
, const0_rtx
);
7935 insn
= emit_jump_insn_before (gen_cbranchsi4 (test
,
7941 JUMP_LABEL (insn
) = loop
->start_label
;
7942 LABEL_NUSES (loop
->start_label
)++;
7943 delete_insn (loop
->loop_end
);
7946 /* Return the next insn after INSN that is not a NOTE, but stop the
7947 search before we enter another basic block. This routine does not
7948 look inside SEQUENCEs. */
7951 next_nonnote_insn_bb (rtx_insn
*insn
)
7955 insn
= NEXT_INSN (insn
);
7956 if (insn
== 0 || !NOTE_P (insn
))
7958 if (NOTE_INSN_BASIC_BLOCK_P (insn
))
7965 /* Optimize LOOP. */
7968 hwloop_optimize (hwloop_info loop
)
7972 basic_block entry_bb
, bb
;
7974 rtx_insn
*insn
, *seq
, *entry_after
, *last_insn
, *end_label
;
7975 unsigned int length
;
7976 bool need_fix
= false;
7977 rtx lp_reg
= gen_rtx_REG (SImode
, LP_COUNT
);
7979 if (loop
->depth
> 1)
7982 fprintf (dump_file
, ";; loop %d is not innermost\n",
7987 if (!loop
->incoming_dest
)
7990 fprintf (dump_file
, ";; loop %d has more than one entry\n",
7995 if (loop
->incoming_dest
!= loop
->head
)
7998 fprintf (dump_file
, ";; loop %d is not entered from head\n",
8003 if (loop
->has_call
|| loop
->has_asm
)
8006 fprintf (dump_file
, ";; loop %d has invalid insn\n",
8011 /* Scan all the blocks to make sure they don't use iter_reg. */
8012 if (loop
->iter_reg_used
|| loop
->iter_reg_used_outside
)
8015 fprintf (dump_file
, ";; loop %d uses iterator\n",
8020 /* Check if start_label appears before doloop_end. */
8022 for (insn
= loop
->start_label
;
8023 insn
&& insn
!= loop
->loop_end
;
8024 insn
= NEXT_INSN (insn
))
8026 length
+= NONDEBUG_INSN_P (insn
) ? get_attr_length (insn
) : 0;
8027 if (JUMP_TABLES_IN_TEXT_SECTION
8028 && JUMP_TABLE_DATA_P (insn
))
8031 fprintf (dump_file
, ";; loop %d has a jump table\n",
8040 fprintf (dump_file
, ";; loop %d start_label not before loop_end\n",
8045 loop
->length
= length
;
8046 if (loop
->length
> ARC_MAX_LOOP_LENGTH
)
8049 fprintf (dump_file
, ";; loop %d too long\n", loop
->loop_no
);
8052 else if (!loop
->length
)
8055 fprintf (dump_file
, ";; loop %d is empty\n", loop
->loop_no
);
8059 /* Check if we use a register or not. */
8060 if (!REG_P (loop
->iter_reg
))
8063 fprintf (dump_file
, ";; loop %d iterator is MEM\n",
8068 /* Check if we use a register or not. */
8069 if (!REG_P (loop
->iter_reg
))
8072 fprintf (dump_file
, ";; loop %d iterator is MEM\n",
8077 /* Check if loop register is lpcount. */
8078 if (REG_P (loop
->iter_reg
) && (REGNO (loop
->iter_reg
)) != LP_COUNT
)
8081 fprintf (dump_file
, ";; loop %d doesn't use lp_count as loop"
8084 /* This loop doesn't use the lp_count, check though if we can
8086 if (TEST_HARD_REG_BIT (loop
->regs_set_in_loop
, LP_COUNT
)
8087 /* In very unique cases we may have LP_COUNT alive. */
8088 || (loop
->incoming_src
8089 && REGNO_REG_SET_P (df_get_live_out (loop
->incoming_src
),
8093 fprintf (dump_file
, ";; loop %d, lp_count is alive", loop
->loop_no
);
8100 /* Check for control like instruction as the last instruction of a
8103 last_insn
= PREV_INSN (loop
->loop_end
);
8107 for (; last_insn
!= BB_HEAD (bb
);
8108 last_insn
= PREV_INSN (last_insn
))
8109 if (NONDEBUG_INSN_P (last_insn
))
8112 if (last_insn
!= BB_HEAD (bb
))
8115 if (single_pred_p (bb
)
8116 && single_pred_edge (bb
)->flags
& EDGE_FALLTHRU
8117 && single_pred (bb
) != ENTRY_BLOCK_PTR_FOR_FN (cfun
))
8119 bb
= single_pred (bb
);
8120 last_insn
= BB_END (bb
);
8133 fprintf (dump_file
, ";; loop %d has no last instruction\n",
8138 if ((TARGET_ARC600_FAMILY
|| TARGET_HS
)
8139 && INSN_P (last_insn
)
8140 && (JUMP_P (last_insn
) || CALL_P (last_insn
)
8141 || GET_CODE (PATTERN (last_insn
)) == SEQUENCE
8142 /* At this stage we can have (insn (clobber (mem:BLK
8143 (reg)))) instructions, ignore them. */
8144 || (GET_CODE (PATTERN (last_insn
)) != CLOBBER
8145 && (get_attr_type (last_insn
) == TYPE_BRCC
8146 || get_attr_type (last_insn
) == TYPE_BRCC_NO_DELAY_SLOT
))))
8148 if (loop
->length
+ 2 > ARC_MAX_LOOP_LENGTH
)
8151 fprintf (dump_file
, ";; loop %d too long\n", loop
->loop_no
);
8155 fprintf (dump_file
, ";; loop %d has a control like last insn; "
8159 last_insn
= emit_insn_after (gen_nopv (), last_insn
);
8162 if (LABEL_P (last_insn
))
8165 fprintf (dump_file
, ";; loop %d has a label as last insn; "
8168 last_insn
= emit_insn_after (gen_nopv (), last_insn
);
8171 /* SAVE_NOTE is used by haifa scheduler. However, we are after it
8172 and we can use it to indicate the last ZOL instruction cannot be
8173 part of a delay slot. */
8174 add_reg_note (last_insn
, REG_SAVE_NOTE
, GEN_INT (2));
8176 loop
->last_insn
= last_insn
;
8178 /* Get the loop iteration register. */
8179 iter_reg
= loop
->iter_reg
;
8181 gcc_assert (REG_P (iter_reg
));
8185 FOR_EACH_VEC_SAFE_ELT (loop
->incoming
, i
, entry_edge
)
8186 if (entry_edge
->flags
& EDGE_FALLTHRU
)
8189 if (entry_edge
== NULL
)
8192 fprintf (dump_file
, ";; loop %d has no fallthru edge jumping "
8197 /* The loop is good. */
8198 end_label
= gen_label_rtx ();
8199 loop
->end_label
= end_label
;
8201 /* Place the zero_cost_loop_start instruction before the loop. */
8202 entry_bb
= entry_edge
->src
;
8208 /* The loop uses a R-register, but the lp_count is free, thus
8210 emit_insn (gen_rtx_SET (lp_reg
, iter_reg
));
8211 SET_HARD_REG_BIT (loop
->regs_set_in_loop
, LP_COUNT
);
8215 fprintf (dump_file
, ";; fix loop %d to use lp_count\n",
8220 insn
= emit_insn (gen_arc_lp (loop
->start_label
,
8226 entry_after
= BB_END (entry_bb
);
8227 if (!single_succ_p (entry_bb
) || vec_safe_length (loop
->incoming
) > 1
8234 emit_insn_before (seq
, BB_HEAD (loop
->head
));
8235 seq
= emit_label_before (gen_label_rtx (), seq
);
8236 new_bb
= create_basic_block (seq
, insn
, entry_bb
);
8237 FOR_EACH_EDGE (e
, ei
, loop
->incoming
)
8239 if (!(e
->flags
& EDGE_FALLTHRU
))
8240 redirect_edge_and_branch_force (e
, new_bb
);
8242 redirect_edge_succ (e
, new_bb
);
8245 make_edge (new_bb
, loop
->head
, 0);
8250 while (DEBUG_INSN_P (entry_after
)
8251 || (NOTE_P (entry_after
)
8252 && NOTE_KIND (entry_after
) != NOTE_INSN_BASIC_BLOCK
8253 /* Make sure we don't split a call and its corresponding
8254 CALL_ARG_LOCATION note. */
8255 && NOTE_KIND (entry_after
) != NOTE_INSN_CALL_ARG_LOCATION
))
8256 entry_after
= NEXT_INSN (entry_after
);
8258 entry_after
= next_nonnote_insn_bb (entry_after
);
8260 gcc_assert (entry_after
);
8261 emit_insn_before (seq
, entry_after
);
8264 /* Insert the loop end label before the last instruction of the
8266 emit_label_after (end_label
, loop
->last_insn
);
8267 /* Make sure we mark the begining and end label as used. */
8268 LABEL_NUSES (loop
->end_label
)++;
8269 LABEL_NUSES (loop
->start_label
)++;
8274 /* A callback for the hw-doloop pass. This function examines INSN; if
8275 it is a loop_end pattern we recognize, return the reg rtx for the
8276 loop counter. Otherwise, return NULL_RTX. */
8279 hwloop_pattern_reg (rtx_insn
*insn
)
8283 if (!JUMP_P (insn
) || recog_memoized (insn
) != CODE_FOR_loop_end
)
8286 reg
= SET_DEST (XVECEXP (PATTERN (insn
), 0, 1));
8292 static struct hw_doloop_hooks arc_doloop_hooks
=
8299 /* Run from machine_dependent_reorg, this pass looks for doloop_end insns
8300 and tries to rewrite the RTL of these loops so that proper Blackfin
8301 hardware loops are generated. */
8304 arc_reorg_loops (void)
8306 reorg_loops (true, &arc_doloop_hooks
);
8309 /* Scan all calls and add symbols to be emitted in the jli section if
8313 jli_call_scan (void)
8317 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
8322 rtx pat
= PATTERN (insn
);
8323 if (GET_CODE (pat
) == COND_EXEC
)
8324 pat
= COND_EXEC_CODE (pat
);
8325 pat
= XVECEXP (pat
, 0, 0);
8326 if (GET_CODE (pat
) == SET
)
8327 pat
= SET_SRC (pat
);
8329 pat
= XEXP (XEXP (pat
, 0), 0);
8330 if (GET_CODE (pat
) == SYMBOL_REF
8331 && arc_is_jli_call_p (pat
))
8332 arc_add_jli_section (pat
);
8336 /* Add padding if necessary to avoid a mispredict. A return could
8337 happen immediately after the function start. A call/return and
8338 return/return must be 6 bytes apart to avoid mispredict. */
8346 if (!TARGET_PAD_RETURN
)
8349 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
8351 rtx_insn
*prev0
= prev_active_insn (insn
);
8352 bool wantlong
= false;
8354 if (!INSN_P (insn
) || GET_CODE (PATTERN (insn
)) != SIMPLE_RETURN
)
8359 prev0
= emit_insn_before (gen_nopv (), insn
);
8360 /* REG_SAVE_NOTE is used by Haifa scheduler, we are in reorg
8361 so it is safe to reuse it for forcing a particular length
8362 for an instruction. */
8363 add_reg_note (prev0
, REG_SAVE_NOTE
, GEN_INT (1));
8364 emit_insn_before (gen_nopv (), insn
);
8367 offset
= get_attr_length (prev0
);
8369 if (get_attr_length (prev0
) == 2
8370 && get_attr_iscompact (prev0
) != ISCOMPACT_TRUE
)
8372 /* Force long version of the insn. */
8377 rtx_insn
*prev
= prev_active_insn (prev0
);
8379 offset
+= get_attr_length (prev
);
8381 prev
= prev_active_insn (prev
);
8383 offset
+= get_attr_length (prev
);
8388 prev
= emit_insn_before (gen_nopv (), insn
);
8389 add_reg_note (prev
, REG_SAVE_NOTE
, GEN_INT (1));
8392 emit_insn_before (gen_nopv (), insn
);
8399 add_reg_note (prev0
, REG_SAVE_NOTE
, GEN_INT (1));
8401 /* Emit a blockage to avoid delay slot scheduling. */
8402 emit_insn_before (gen_blockage (), insn
);
8406 static int arc_reorg_in_progress
= 0;
8408 /* ARC's machince specific reorg function. */
8419 cfun
->machine
->arc_reorg_started
= 1;
8420 arc_reorg_in_progress
= 1;
8422 compute_bb_for_insn ();
8426 /* Doloop optimization. */
8429 workaround_arc_anomaly ();
8433 /* There are cases when conditional execution is only possible after
8434 delay slot scheduling:
8436 - If a delay slot is filled with a nocond/set insn from above, the previous
8437 basic block can become elegible for conditional execution.
8438 - If a delay slot is filled with a nocond insn from the fall-through path,
8439 the branch with that delay slot can become eligble for conditional
8440 execution (however, with the same sort of data flow analysis that dbr
8441 does, we could have figured out before that we don't need to
8442 conditionalize this insn.)
8443 - If a delay slot insn is filled with an insn from the target, the
8444 target label gets its uses decremented (even deleted if falling to zero),
8445 thus possibly creating more condexec opportunities there.
8446 Therefore, we should still be prepared to apply condexec optimization on
8447 non-prepared branches if the size increase of conditionalized insns is no
8448 more than the size saved from eliminating the branch. An invocation option
8449 could also be used to reserve a bit of extra size for condbranches so that
8450 this'll work more often (could also test in arc_reorg if the block is
8451 'close enough' to be eligible for condexec to make this likely, and
8452 estimate required size increase). */
8453 /* Generate BRcc insns, by combining cmp and Bcc insns wherever possible. */
8454 if (TARGET_NO_BRCC_SET
)
8459 init_insn_lengths();
8462 /* Call shorten_branches to calculate the insn lengths. */
8463 shorten_branches (get_insns());
8465 if (!INSN_ADDRESSES_SET_P())
8466 fatal_error (input_location
,
8467 "insn addresses not set after shorten branches");
8469 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
8472 enum attr_type insn_type
;
8474 /* If a non-jump insn (or a casesi jump table), continue. */
8475 if (GET_CODE (insn
) != JUMP_INSN
||
8476 GET_CODE (PATTERN (insn
)) == ADDR_VEC
8477 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
8480 /* If we already have a brcc, note if it is suitable for brcc_s.
8481 Be a bit generous with the brcc_s range so that we can take
8482 advantage of any code shortening from delay slot scheduling. */
8483 if (recog_memoized (insn
) == CODE_FOR_cbranchsi4_scratch
)
8485 rtx pat
= PATTERN (insn
);
8486 rtx op
= XEXP (SET_SRC (XVECEXP (pat
, 0, 0)), 0);
8487 rtx
*ccp
= &XEXP (XVECEXP (pat
, 0, 1), 0);
8489 offset
= branch_dest (insn
) - INSN_ADDRESSES (INSN_UID (insn
));
8490 if ((offset
>= -140 && offset
< 140)
8491 && rtx_equal_p (XEXP (op
, 1), const0_rtx
)
8492 && compact_register_operand (XEXP (op
, 0), VOIDmode
)
8493 && equality_comparison_operator (op
, VOIDmode
))
8494 PUT_MODE (*ccp
, CC_Zmode
);
8495 else if (GET_MODE (*ccp
) == CC_Zmode
)
8496 PUT_MODE (*ccp
, CC_ZNmode
);
8499 if ((insn_type
= get_attr_type (insn
)) == TYPE_BRCC
8500 || insn_type
== TYPE_BRCC_NO_DELAY_SLOT
)
8503 /* OK. so we have a jump insn. */
8504 /* We need to check that it is a bcc. */
8505 /* Bcc => set (pc) (if_then_else ) */
8506 pattern
= PATTERN (insn
);
8507 if (GET_CODE (pattern
) != SET
8508 || GET_CODE (SET_SRC (pattern
)) != IF_THEN_ELSE
8509 || ANY_RETURN_P (XEXP (SET_SRC (pattern
), 1)))
8512 /* Now check if the jump is beyond the s9 range. */
8513 if (CROSSING_JUMP_P (insn
))
8515 offset
= branch_dest (insn
) - INSN_ADDRESSES (INSN_UID (insn
));
8517 if(offset
> 253 || offset
< -254)
8520 pc_target
= SET_SRC (pattern
);
8522 /* Avoid FPU instructions. */
8523 if ((GET_MODE (XEXP (XEXP (pc_target
, 0), 0)) == CC_FPUmode
)
8524 || (GET_MODE (XEXP (XEXP (pc_target
, 0), 0)) == CC_FPUEmode
)
8525 || (GET_MODE (XEXP (XEXP (pc_target
, 0), 0)) == CC_FPU_UNEQmode
))
8528 /* Now go back and search for the set cc insn. */
8530 label
= XEXP (pc_target
, 1);
8534 rtx_insn
*scan
, *link_insn
= NULL
;
8536 for (scan
= PREV_INSN (insn
);
8537 scan
&& GET_CODE (scan
) != CODE_LABEL
;
8538 scan
= PREV_INSN (scan
))
8540 if (! INSN_P (scan
))
8542 pat
= PATTERN (scan
);
8543 if (GET_CODE (pat
) == SET
8544 && cc_register (SET_DEST (pat
), VOIDmode
))
8554 /* Check if this is a data dependency. */
8555 rtx op
, cc_clob_rtx
, op0
, op1
, brcc_insn
, note
;
8558 /* Make sure we can use it for brcc insns. */
8559 if (find_reg_note (link_insn
, REG_SAVE_NOTE
, GEN_INT (3)))
8562 /* Ok this is the set cc. copy args here. */
8563 op
= XEXP (pc_target
, 0);
8565 op0
= cmp0
= XEXP (SET_SRC (pat
), 0);
8566 op1
= cmp1
= XEXP (SET_SRC (pat
), 1);
8567 if (GET_CODE (op0
) == ZERO_EXTRACT
8568 && XEXP (op0
, 1) == const1_rtx
8569 && (GET_CODE (op
) == EQ
8570 || GET_CODE (op
) == NE
))
8572 /* btst / b{eq,ne} -> bbit{0,1} */
8573 op0
= XEXP (cmp0
, 0);
8574 op1
= XEXP (cmp0
, 2);
8576 else if (!register_operand (op0
, VOIDmode
)
8577 || !general_operand (op1
, VOIDmode
))
8579 /* Be careful not to break what cmpsfpx_raw is
8580 trying to create for checking equality of
8581 single-precision floats. */
8582 else if (TARGET_SPFP
8583 && GET_MODE (op0
) == SFmode
8584 && GET_MODE (op1
) == SFmode
)
8587 /* None of the two cmp operands should be set between the
8588 cmp and the branch. */
8589 if (reg_set_between_p (op0
, link_insn
, insn
))
8592 if (reg_set_between_p (op1
, link_insn
, insn
))
8595 /* Since the MODE check does not work, check that this is
8596 CC reg's last set location before insn, and also no
8597 instruction between the cmp and branch uses the
8599 if ((reg_set_between_p (SET_DEST (pat
), link_insn
, insn
))
8600 || (reg_used_between_p (SET_DEST (pat
), link_insn
, insn
)))
8603 /* CC reg should be dead after insn. */
8604 if (!find_regno_note (insn
, REG_DEAD
, CC_REG
))
8607 op
= gen_rtx_fmt_ee (GET_CODE (op
),
8608 GET_MODE (op
), cmp0
, cmp1
);
8609 /* If we create a LIMM where there was none before,
8610 we only benefit if we can avoid a scheduling bubble
8611 for the ARC600. Otherwise, we'd only forgo chances
8612 at short insn generation, and risk out-of-range
8614 if (!brcc_nolimm_operator (op
, VOIDmode
)
8615 && !long_immediate_operand (op1
, VOIDmode
)
8617 || (TARGET_V2
&& optimize_size
)
8618 || next_active_insn (link_insn
) != insn
))
8621 /* Emit bbit / brcc (or brcc_s if possible).
8622 CC_Zmode indicates that brcc_s is possible. */
8625 cc_clob_rtx
= gen_rtx_REG (CC_ZNmode
, CC_REG
);
8626 else if ((offset
>= -140 && offset
< 140)
8627 && rtx_equal_p (op1
, const0_rtx
)
8628 && compact_register_operand (op0
, VOIDmode
)
8629 && (GET_CODE (op
) == EQ
8630 || GET_CODE (op
) == NE
))
8631 cc_clob_rtx
= gen_rtx_REG (CC_Zmode
, CC_REG
);
8633 cc_clob_rtx
= gen_rtx_REG (CCmode
, CC_REG
);
8636 = gen_rtx_IF_THEN_ELSE (VOIDmode
, op
, label
, pc_rtx
);
8637 brcc_insn
= gen_rtx_SET (pc_rtx
, brcc_insn
);
8638 cc_clob_rtx
= gen_rtx_CLOBBER (VOIDmode
, cc_clob_rtx
);
8641 (VOIDmode
, gen_rtvec (2, brcc_insn
, cc_clob_rtx
));
8642 brcc_insn
= emit_jump_insn_before (brcc_insn
, insn
);
8644 JUMP_LABEL (brcc_insn
) = JUMP_LABEL (insn
);
8645 note
= find_reg_note (insn
, REG_BR_PROB
, 0);
8648 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
8649 REG_NOTES (brcc_insn
) = note
;
8651 note
= find_reg_note (link_insn
, REG_DEAD
, op0
);
8654 remove_note (link_insn
, note
);
8655 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
8656 REG_NOTES (brcc_insn
) = note
;
8658 note
= find_reg_note (link_insn
, REG_DEAD
, op1
);
8661 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
8662 REG_NOTES (brcc_insn
) = note
;
8667 /* Delete the bcc insn. */
8668 set_insn_deleted (insn
);
8670 /* Delete the cmp insn. */
8671 set_insn_deleted (link_insn
);
8676 /* Clear out insn_addresses. */
8677 INSN_ADDRESSES_FREE ();
8681 if (INSN_ADDRESSES_SET_P())
8682 fatal_error (input_location
, "insn addresses not freed");
8684 arc_reorg_in_progress
= 0;
8687 /* Check if the operands are valid for BRcc.d generation
8688 Valid Brcc.d patterns are
8692 For cc={GT, LE, GTU, LEU}, u6=63 cannot be allowed,
8693 since they are encoded by the assembler as {GE, LT, HS, LS} 64, which
8694 does not have a delay slot
8696 Assumed precondition: Second operand is either a register or a u6 value. */
8699 valid_brcc_with_delay_p (rtx
*operands
)
8701 if (optimize_size
&& GET_MODE (operands
[4]) == CC_Zmode
)
8703 return brcc_nolimm_operator (operands
[0], VOIDmode
);
8706 /* Implement TARGET_IN_SMALL_DATA_P. Return true if it would be safe to
8707 access DECL using %gp_rel(...)($gp). */
8710 arc_in_small_data_p (const_tree decl
)
8715 /* Only variables are going into small data area. */
8716 if (TREE_CODE (decl
) != VAR_DECL
)
8719 if (TARGET_NO_SDATA_SET
)
8722 /* Disable sdata references to weak variables. */
8723 if (DECL_WEAK (decl
))
8726 /* Don't put constants into the small data section: we want them to
8727 be in ROM rather than RAM. */
8728 if (TREE_READONLY (decl
))
8731 /* To ensure -mvolatile-cache works ld.di does not have a
8732 gp-relative variant. */
8733 if (!TARGET_VOLATILE_CACHE_SET
8734 && TREE_THIS_VOLATILE (decl
))
8737 /* Likewise for uncached data. */
8738 attr
= TYPE_ATTRIBUTES (TREE_TYPE (decl
));
8739 if (lookup_attribute ("uncached", attr
))
8742 /* and for aux regs. */
8743 attr
= DECL_ATTRIBUTES (decl
);
8744 if (lookup_attribute ("aux", attr
))
8747 if (DECL_SECTION_NAME (decl
) != 0)
8749 const char *name
= DECL_SECTION_NAME (decl
);
8750 if (strcmp (name
, ".sdata") == 0
8751 || strcmp (name
, ".sbss") == 0)
8754 /* If it's not public, there's no need to put it in the small data
8756 else if (TREE_PUBLIC (decl
))
8758 size
= int_size_in_bytes (TREE_TYPE (decl
));
8759 return (size
> 0 && size
<= g_switch_value
);
8764 /* Return true if OP is an acceptable memory operand for ARCompact
8765 16-bit gp-relative load instructions.
8767 /* volatile cache option still to be handled. */
8770 compact_sda_memory_operand (rtx op
, machine_mode mode
, bool short_p
)
8777 /* Eliminate non-memory operations. */
8778 if (GET_CODE (op
) != MEM
)
8781 if (mode
== VOIDmode
)
8782 mode
= GET_MODE (op
);
8784 size
= GET_MODE_SIZE (mode
);
8786 /* dword operations really put out 2 instructions, so eliminate them. */
8787 if (size
> UNITS_PER_WORD
)
8790 /* Decode the address now. */
8791 addr
= XEXP (op
, 0);
8793 if (!legitimate_small_data_address_p (addr
, mode
))
8796 if (!short_p
|| size
== 1)
8799 /* Now check for the alignment, the short loads using gp require the
8800 addresses to be aligned. */
8801 align
= get_symbol_alignment (addr
);
8812 if (align
&& ((align
& mask
) == 0))
8817 /* Return TRUE if PAT is accessing an aux-reg. */
8820 arc_is_aux_reg_p (rtx pat
)
8822 tree attrs
= NULL_TREE
;
8828 /* Get the memory attributes. */
8829 addr
= MEM_EXPR (pat
);
8833 /* Get the attributes. */
8835 attrs
= DECL_ATTRIBUTES (addr
);
8836 else if (TREE_CODE (addr
) == MEM_REF
)
8837 attrs
= TYPE_ATTRIBUTES (TREE_TYPE (TREE_OPERAND (addr
, 0)));
8841 if (lookup_attribute ("aux", attrs
))
8846 /* Implement ASM_OUTPUT_ALIGNED_DECL_LOCAL. */
8849 arc_asm_output_aligned_decl_local (FILE * stream
, tree decl
, const char * name
,
8850 unsigned HOST_WIDE_INT size
,
8851 unsigned HOST_WIDE_INT align
,
8852 unsigned HOST_WIDE_INT globalize_p
)
8854 int in_small_data
= arc_in_small_data_p (decl
);
8855 rtx mem
= decl
== NULL_TREE
? NULL_RTX
: DECL_RTL (decl
);
8857 /* Don't output aux-reg symbols. */
8858 if (mem
!= NULL_RTX
&& MEM_P (mem
)
8859 && SYMBOL_REF_P (XEXP (mem
, 0))
8860 && arc_is_aux_reg_p (mem
))
8864 switch_to_section (get_named_section (NULL
, ".sbss", 0));
8865 /* named_section (0,".sbss",0); */
8867 switch_to_section (bss_section
);
8870 (*targetm
.asm_out
.globalize_label
) (stream
, name
);
8872 ASM_OUTPUT_ALIGN (stream
, floor_log2 ((align
) / BITS_PER_UNIT
));
8873 ASM_OUTPUT_TYPE_DIRECTIVE (stream
, name
, "object");
8874 ASM_OUTPUT_SIZE_DIRECTIVE (stream
, name
, size
);
8875 ASM_OUTPUT_LABEL (stream
, name
);
8878 ASM_OUTPUT_SKIP (stream
, size
);
8882 arc_preserve_reload_p (rtx in
)
8884 return (GET_CODE (in
) == PLUS
8885 && RTX_OK_FOR_BASE_P (XEXP (in
, 0), true)
8886 && CONST_INT_P (XEXP (in
, 1))
8887 && !((INTVAL (XEXP (in
, 1)) & 511)));
8890 /* Implement TARGET_REGISTER_MOVE_COST. */
8893 arc_register_move_cost (machine_mode
,
8894 reg_class_t from_class
, reg_class_t to_class
)
8896 /* Force an attempt to 'mov Dy,Dx' to spill. */
8897 if ((TARGET_ARC700
|| TARGET_EM
) && TARGET_DPFP
8898 && from_class
== DOUBLE_REGS
&& to_class
== DOUBLE_REGS
)
8904 /* Emit code for an addsi3 instruction with OPERANDS.
8905 COND_P indicates if this will use conditional execution.
8906 Return the length of the instruction.
8907 If OUTPUT_P is false, don't actually output the instruction, just return
8910 arc_output_addsi (rtx
*operands
, bool cond_p
, bool output_p
)
8914 int match
= operands_match_p (operands
[0], operands
[1]);
8915 int match2
= operands_match_p (operands
[0], operands
[2]);
8916 int intval
= (REG_P (operands
[2]) ? 1
8917 : CONST_INT_P (operands
[2]) ? INTVAL (operands
[2]) : 0xbadc057);
8918 int neg_intval
= -intval
;
8919 int short_0
= arc_check_short_reg_p (operands
[0]);
8920 int short_p
= (!cond_p
&& short_0
&& arc_check_short_reg_p (operands
[1]));
8923 #define REG_H_P(OP) (REG_P (OP) && ((TARGET_V2 && REGNO (OP) <= 31 \
8924 && REGNO (OP) != 30) \
8927 #define ADDSI_OUTPUT1(FORMAT) do {\
8929 output_asm_insn (FORMAT, operands);\
8932 #define ADDSI_OUTPUT(LIST) do {\
8935 ADDSI_OUTPUT1 (format);\
8939 /* First try to emit a 16 bit insn. */
8942 /* If we are actually about to output this insn, don't try a 16 bit
8943 variant if we already decided that we don't want that
8944 (I.e. we upsized this insn to align some following insn.)
8945 E.g. add_s r0,sp,70 is 16 bit, but add r0,sp,70 requires a LIMM -
8946 but add1 r0,sp,35 doesn't. */
8947 && (!output_p
|| (get_attr_length (current_output_insn
) & 2)))
8949 /* Generate add_s a,b,c; add_s b,b,u7; add_s c,b,u3; add_s b,b,h
8952 && ((REG_H_P (operands
[2])
8953 && (match
|| arc_check_short_reg_p (operands
[2])))
8954 || (CONST_INT_P (operands
[2])
8955 && ((unsigned) intval
<= (match
? 127 : 7)))))
8956 ADDSI_OUTPUT1 ("add%? %0,%1,%2 ;1");
8958 /* Generate add_s b,b,h patterns. */
8959 if (short_0
&& match2
&& REG_H_P (operands
[1]))
8960 ADDSI_OUTPUT1 ("add%? %0,%2,%1 ;2");
8962 /* Generate add_s b,sp,u7; add_s sp,sp,u7 patterns. */
8963 if ((short_0
|| REGNO (operands
[0]) == STACK_POINTER_REGNUM
)
8964 && REGNO (operands
[1]) == STACK_POINTER_REGNUM
&& !(intval
& ~124))
8965 ADDSI_OUTPUT1 ("add%? %0,%1,%2 ;3");
8967 if ((short_p
&& (unsigned) neg_intval
<= (match
? 31 : 7))
8968 || (REGNO (operands
[0]) == STACK_POINTER_REGNUM
8969 && match
&& !(neg_intval
& ~124)))
8970 ADDSI_OUTPUT1 ("sub%? %0,%1,%n2 ;4");
8972 /* Generate add_s h,h,s3 patterns. */
8973 if (REG_H_P (operands
[0]) && match
&& TARGET_V2
8974 && CONST_INT_P (operands
[2]) && ((intval
>= -1) && (intval
<= 6)))
8975 ADDSI_OUTPUT1 ("add%? %0,%1,%2 ;5");
8977 /* Generate add_s r0,b,u6; add_s r1,b,u6 patterns. */
8978 if (TARGET_CODE_DENSITY
&& REG_P (operands
[0]) && REG_P (operands
[1])
8979 && ((REGNO (operands
[0]) == 0) || (REGNO (operands
[0]) == 1))
8980 && arc_check_short_reg_p (operands
[1])
8981 && satisfies_constraint_L (operands
[2]))
8982 ADDSI_OUTPUT1 ("add%? %0,%1,%2 ;6");
8985 /* Now try to emit a 32 bit insn without long immediate. */
8987 if (!match
&& match2
&& REG_P (operands
[1]))
8988 ADDSI_OUTPUT1 ("add%? %0,%2,%1");
8989 if (match
|| !cond_p
)
8991 int limit
= (match
&& !cond_p
) ? 0x7ff : 0x3f;
8992 int range_factor
= neg_intval
& intval
;
8995 if (intval
== (HOST_WIDE_INT
) (HOST_WIDE_INT_M1U
<< 31))
8996 ADDSI_OUTPUT1 ("bxor%? %0,%1,31");
8998 /* If we can use a straight add / sub instead of a {add,sub}[123] of
8999 same size, do, so - the insn latency is lower. */
9000 /* -0x800 is a 12-bit constant for add /add3 / sub / sub3, but
9002 if ((intval
>= 0 && intval
<= limit
)
9003 || (intval
== -0x800 && limit
== 0x7ff))
9004 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
9005 else if ((intval
< 0 && neg_intval
<= limit
)
9006 || (intval
== 0x800 && limit
== 0x7ff))
9007 ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
9008 shift
= range_factor
>= 8 ? 3 : (range_factor
>> 1);
9009 gcc_assert (shift
== 0 || shift
== 1 || shift
== 2 || shift
== 3);
9010 gcc_assert ((((1 << shift
) - 1) & intval
) == 0);
9011 if (((intval
< 0 && intval
!= -0x4000)
9012 /* sub[123] is slower than add_s / sub, only use it if it
9013 avoids a long immediate. */
9014 && neg_intval
<= limit
<< shift
)
9015 || (intval
== 0x4000 && limit
== 0x7ff))
9016 ADDSI_OUTPUT ((format
, "sub%d%%? %%0,%%1,%d",
9017 shift
, neg_intval
>> shift
));
9018 else if ((intval
>= 0 && intval
<= limit
<< shift
)
9019 || (intval
== -0x4000 && limit
== 0x7ff))
9020 ADDSI_OUTPUT ((format
, "add%d%%? %%0,%%1,%d", shift
, intval
>> shift
));
9022 /* Try to emit a 16 bit opcode with long immediate. */
9024 if (short_p
&& match
)
9025 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
9027 /* We have to use a 32 bit opcode, and with a long immediate. */
9029 ADDSI_OUTPUT1 (intval
< 0 ? "sub%? %0,%1,%n2" : "add%? %0,%1,%2");
9032 /* Emit code for an commutative_cond_exec instruction with OPERANDS.
9033 Return the length of the instruction.
9034 If OUTPUT_P is false, don't actually output the instruction, just return
9037 arc_output_commutative_cond_exec (rtx
*operands
, bool output_p
)
9039 enum rtx_code commutative_op
= GET_CODE (operands
[3]);
9040 const char *pat
= NULL
;
9042 /* Canonical rtl should not have a constant in the first operand position. */
9043 gcc_assert (!CONSTANT_P (operands
[1]));
9045 switch (commutative_op
)
9048 if (satisfies_constraint_C1p (operands
[2]))
9049 pat
= "bmsk%? %0,%1,%Z2";
9050 else if (satisfies_constraint_C2p (operands
[2]))
9052 operands
[2] = GEN_INT ((~INTVAL (operands
[2])));
9053 pat
= "bmskn%? %0,%1,%Z2";
9055 else if (satisfies_constraint_Ccp (operands
[2]))
9056 pat
= "bclr%? %0,%1,%M2";
9057 else if (satisfies_constraint_CnL (operands
[2]))
9058 pat
= "bic%? %0,%1,%n2-1";
9061 if (satisfies_constraint_C0p (operands
[2]))
9062 pat
= "bset%? %0,%1,%z2";
9065 if (satisfies_constraint_C0p (operands
[2]))
9066 pat
= "bxor%? %0,%1,%z2";
9069 return arc_output_addsi (operands
, true, output_p
);
9073 output_asm_insn (pat
? pat
: "%O3.%d5 %0,%1,%2", operands
);
9074 if (pat
|| REG_P (operands
[2]) || satisfies_constraint_L (operands
[2]))
9079 /* Helper function of arc_expand_cpymem. ADDR points to a chunk of memory.
9080 Emit code and return an potentially modified address such that offsets
9081 up to SIZE are can be added to yield a legitimate address.
9082 if REUSE is set, ADDR is a register that may be modified. */
9085 force_offsettable (rtx addr
, HOST_WIDE_INT size
, bool reuse
)
9088 rtx offs
= const0_rtx
;
9090 if (GET_CODE (base
) == PLUS
)
9092 offs
= XEXP (base
, 1);
9093 base
= XEXP (base
, 0);
9096 || (REGNO (base
) != STACK_POINTER_REGNUM
9097 && REGNO_PTR_FRAME_P (REGNO (base
)))
9098 || !CONST_INT_P (offs
) || !SMALL_INT (INTVAL (offs
))
9099 || !SMALL_INT (INTVAL (offs
) + size
))
9102 emit_insn (gen_add2_insn (addr
, offs
));
9104 addr
= copy_to_mode_reg (Pmode
, addr
);
9109 /* Like move_by_pieces, but take account of load latency, and actual
9110 offset ranges. Return true on success. */
9113 arc_expand_cpymem (rtx
*operands
)
9115 rtx dst
= operands
[0];
9116 rtx src
= operands
[1];
9117 rtx dst_addr
, src_addr
;
9119 int align
= INTVAL (operands
[3]);
9126 if (!CONST_INT_P (operands
[2]))
9128 size
= INTVAL (operands
[2]);
9129 /* move_by_pieces_ninsns is static, so we can't use it. */
9133 n_pieces
= (size
+ 4) / 8U + ((size
>> 1) & 1) + (size
& 1);
9135 n_pieces
= (size
+ 2) / 4U + (size
& 1);
9137 else if (align
== 2)
9138 n_pieces
= (size
+ 1) / 2U;
9141 if (n_pieces
>= (unsigned int) (optimize_size
? 3 : 15))
9143 /* Force 32 bit aligned and larger datum to use 64 bit transfers, if
9145 if (TARGET_LL64
&& (piece
>= 4) && (size
>= 8))
9149 dst_addr
= force_offsettable (XEXP (operands
[0], 0), size
, 0);
9150 src_addr
= force_offsettable (XEXP (operands
[1], 0), size
, 0);
9151 store
[0] = store
[1] = NULL_RTX
;
9152 tmpx
[0] = tmpx
[1] = NULL_RTX
;
9153 for (i
= 0; size
> 0; i
^= 1, size
-= piece
)
9158 while (piece
> size
)
9160 mode
= smallest_int_mode_for_size (piece
* BITS_PER_UNIT
).require ();
9161 /* If we don't re-use temporaries, the scheduler gets carried away,
9162 and the register pressure gets unnecessarily high. */
9163 if (0 && tmpx
[i
] && GET_MODE (tmpx
[i
]) == mode
)
9166 tmpx
[i
] = tmp
= gen_reg_rtx (mode
);
9167 dst_addr
= force_offsettable (dst_addr
, piece
, 1);
9168 src_addr
= force_offsettable (src_addr
, piece
, 1);
9170 emit_insn (store
[i
]);
9171 emit_move_insn (tmp
, change_address (src
, mode
, src_addr
));
9172 store
[i
] = gen_move_insn (change_address (dst
, mode
, dst_addr
), tmp
);
9173 dst_addr
= plus_constant (Pmode
, dst_addr
, piece
);
9174 src_addr
= plus_constant (Pmode
, src_addr
, piece
);
9177 emit_insn (store
[i
]);
9179 emit_insn (store
[i
^1]);
9184 arc_get_aux_arg (rtx pat
, int *auxr
)
9186 tree attr
, addr
= MEM_EXPR (pat
);
9187 if (TREE_CODE (addr
) != VAR_DECL
)
9190 attr
= DECL_ATTRIBUTES (addr
);
9191 if (lookup_attribute ("aux", attr
))
9193 tree arg
= TREE_VALUE (attr
);
9196 *auxr
= TREE_INT_CST_LOW (TREE_VALUE (arg
));
9204 /* Prepare operands for move in MODE. Return true iff the move has
9208 prepare_move_operands (rtx
*operands
, machine_mode mode
)
9210 if ((MEM_P (operands
[0]) || MEM_P (operands
[1]))
9211 && SCALAR_INT_MODE_P (mode
))
9213 /* First handle aux attribute. */
9218 if (MEM_P (operands
[0]) && arc_is_aux_reg_p (operands
[0]))
9220 /* Save operation. */
9221 if (arc_get_aux_arg (operands
[0], &auxr
))
9223 tmp
= gen_reg_rtx (SImode
);
9224 emit_move_insn (tmp
, GEN_INT (auxr
));
9227 tmp
= XEXP (operands
[0], 0);
9229 operands
[1] = force_reg (SImode
, operands
[1]);
9230 emit_insn (gen_rtx_UNSPEC_VOLATILE
9231 (VOIDmode
, gen_rtvec (2, operands
[1], tmp
),
9235 if (MEM_P (operands
[1]) && arc_is_aux_reg_p (operands
[1]))
9237 if (arc_get_aux_arg (operands
[1], &auxr
))
9239 tmp
= gen_reg_rtx (SImode
);
9240 emit_move_insn (tmp
, GEN_INT (auxr
));
9244 tmp
= XEXP (operands
[1], 0);
9245 gcc_assert (GET_CODE (tmp
) == SYMBOL_REF
);
9247 /* Load operation. */
9248 gcc_assert (REG_P (operands
[0]));
9249 emit_insn (gen_rtx_SET (operands
[0],
9250 gen_rtx_UNSPEC_VOLATILE
9251 (SImode
, gen_rtvec (1, tmp
),
9256 /* Second, we check for the uncached. */
9257 if (arc_is_uncached_mem_p (operands
[0]))
9259 if (!REG_P (operands
[1]))
9260 operands
[1] = force_reg (mode
, operands
[1]);
9261 emit_insn (gen_rtx_UNSPEC_VOLATILE
9262 (VOIDmode
, gen_rtvec (2, operands
[0], operands
[1]),
9266 if (arc_is_uncached_mem_p (operands
[1]))
9268 rtx tmp
= operands
[0];
9270 if (MEM_P (operands
[0]))
9271 tmp
= gen_reg_rtx (mode
);
9273 emit_insn (gen_rtx_SET
9275 gen_rtx_UNSPEC_VOLATILE
9276 (mode
, gen_rtvec (1, operands
[1]),
9277 VUNSPEC_ARC_LDDI
)));
9278 if (MEM_P (operands
[0]))
9287 if (GET_CODE (operands
[1]) == SYMBOL_REF
)
9289 enum tls_model model
= SYMBOL_REF_TLS_MODEL (operands
[1]);
9290 if (MEM_P (operands
[0]))
9291 operands
[1] = force_reg (mode
, operands
[1]);
9293 operands
[1] = arc_legitimize_tls_address (operands
[1], model
);
9296 operands
[1] = arc_legitimize_pic_address (operands
[1]);
9298 /* Store instructions are limited, they only accept as address an
9299 immediate, a register or a register plus a small immediate. */
9300 if (MEM_P (operands
[0])
9301 && !move_dest_operand (operands
[0], mode
))
9303 rtx tmp0
= copy_to_mode_reg (Pmode
, XEXP (operands
[0], 0));
9304 rtx tmp1
= change_address (operands
[0], mode
, tmp0
);
9305 MEM_COPY_ATTRIBUTES (tmp1
, operands
[0]);
9309 /* Check if it is constant but it is not legitimized. */
9310 if (CONSTANT_P (operands
[1])
9311 && !arc_legitimate_constant_p (mode
, operands
[1]))
9312 operands
[1] = force_reg (mode
, XEXP (operands
[1], 0));
9313 else if (MEM_P (operands
[0])
9314 && ((CONSTANT_P (operands
[1])
9315 && !satisfies_constraint_Cm3 (operands
[1]))
9316 || MEM_P (operands
[1])))
9317 operands
[1] = force_reg (mode
, operands
[1]);
9322 /* Output a library call to a function called FNAME that has been arranged
9323 to be local to any dso. */
9326 arc_output_libcall (const char *fname
)
9328 unsigned len
= strlen (fname
);
9329 static char buf
[64];
9331 gcc_assert (len
< sizeof buf
- 35);
9332 if (TARGET_LONG_CALLS_SET
)
9335 sprintf (buf
, "add r12,pcl,@%s@pcl\n\tjl%%!%%* [r12]", fname
);
9337 sprintf (buf
, "jl%%! @%s", fname
);
9340 sprintf (buf
, "bl%%!%%* @%s", fname
);
9344 /* Return the SImode highpart of the DImode value IN. */
9347 disi_highpart (rtx in
)
9349 return simplify_gen_subreg (SImode
, in
, DImode
, TARGET_BIG_ENDIAN
? 0 : 4);
9352 /* Given a rtx, check if it is an assembly instruction or not. */
9355 arc_asm_insn_p (rtx x
)
9362 switch (GET_CODE (x
))
9369 return arc_asm_insn_p (SET_SRC (x
));
9373 for (i
= XVECLEN (x
, 0) - 1; i
>= 0; i
--)
9374 j
+= arc_asm_insn_p (XVECEXP (x
, 0, i
));
9386 /* Return length adjustment for INSN. */
9389 arc_adjust_insn_length (rtx_insn
*insn
, int len
, bool)
9393 /* We already handle sequences by ignoring the delay sequence flag. */
9394 if (GET_CODE (PATTERN (insn
)) == SEQUENCE
)
9397 /* Check for return with but one preceding insn since function
9399 if (TARGET_PAD_RETURN
9401 && GET_CODE (PATTERN (insn
)) != ADDR_VEC
9402 && GET_CODE (PATTERN (insn
)) != ADDR_DIFF_VEC
9403 && get_attr_type (insn
) == TYPE_RETURN
)
9405 rtx_insn
*prev
= prev_active_insn (insn
);
9407 if (!prev
|| !(prev
= prev_active_insn (prev
))
9408 || ((NONJUMP_INSN_P (prev
)
9409 && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
9410 ? CALL_ATTR (as_a
<rtx_sequence
*> (PATTERN (prev
))->insn (0),
9412 : CALL_ATTR (prev
, NON_SIBCALL
)))
9417 rtx_insn
*succ
= next_real_insn (insn
);
9419 /* One the ARC600, a write to an extension register must be separated
9421 if (succ
&& INSN_P (succ
))
9422 len
+= arc600_corereg_hazard (insn
, succ
);
9425 /* Restore extracted operands - otherwise splitters like the addsi3_mixed one
9427 extract_constrain_insn_cached (insn
);
9432 /* Return version of PAT conditionalized with COND, which is part of INSN.
9433 ANNULLED indicates if INSN is an annulled delay-slot insn.
9434 Register further changes if necessary. */
9436 conditionalize_nonjump (rtx pat
, rtx cond
, rtx insn
, bool annulled
)
9438 /* For commutative operators, we generally prefer to have
9439 the first source match the destination. */
9440 if (GET_CODE (pat
) == SET
)
9442 rtx src
= SET_SRC (pat
);
9444 if (COMMUTATIVE_P (src
))
9446 rtx src0
= XEXP (src
, 0);
9447 rtx src1
= XEXP (src
, 1);
9448 rtx dst
= SET_DEST (pat
);
9450 if (rtx_equal_p (src1
, dst
) && !rtx_equal_p (src0
, dst
)
9451 /* Leave add_n alone - the canonical form is to
9452 have the complex summand first. */
9454 pat
= gen_rtx_SET (dst
,
9455 gen_rtx_fmt_ee (GET_CODE (src
), GET_MODE (src
),
9460 /* dwarf2out.cc:dwarf2out_frame_debug_expr doesn't know
9461 what to do with COND_EXEC. */
9462 if (RTX_FRAME_RELATED_P (insn
))
9464 /* If this is the delay slot insn of an anulled branch,
9465 dwarf2out.cc:scan_trace understands the anulling semantics
9466 without the COND_EXEC. */
9467 gcc_assert (annulled
);
9468 rtx note
= alloc_reg_note (REG_FRAME_RELATED_EXPR
, pat
,
9470 validate_change (insn
, ®_NOTES (insn
), note
, 1);
9472 pat
= gen_rtx_COND_EXEC (VOIDmode
, cond
, pat
);
9477 /* Find annulled delay insns and convert them to use the appropriate predicate.
9478 This allows branch shortening to size up these insns properly. */
9481 arc_predicate_delay_insns (void)
9483 for (rtx_insn
*insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
9485 rtx pat
, jump
, dlay
, src
, cond
, *patp
;
9488 if (!NONJUMP_INSN_P (insn
)
9489 || GET_CODE (pat
= PATTERN (insn
)) != SEQUENCE
)
9491 jump
= XVECEXP (pat
, 0, 0);
9492 dlay
= XVECEXP (pat
, 0, 1);
9493 if (!JUMP_P (jump
) || !INSN_ANNULLED_BRANCH_P (jump
))
9495 /* If the branch insn does the annulling, leave the delay insn alone. */
9496 if (!TARGET_AT_DBR_CONDEXEC
&& !INSN_FROM_TARGET_P (dlay
))
9498 /* ??? Could also leave DLAY un-conditionalized if its target is dead
9499 on the other path. */
9500 gcc_assert (GET_CODE (PATTERN (jump
)) == SET
);
9501 gcc_assert (SET_DEST (PATTERN (jump
)) == pc_rtx
);
9502 src
= SET_SRC (PATTERN (jump
));
9503 gcc_assert (GET_CODE (src
) == IF_THEN_ELSE
);
9504 cond
= XEXP (src
, 0);
9505 if (XEXP (src
, 2) == pc_rtx
)
9507 else if (XEXP (src
, 1) == pc_rtx
)
9511 if (reverse
!= !INSN_FROM_TARGET_P (dlay
))
9513 machine_mode ccm
= GET_MODE (XEXP (cond
, 0));
9514 enum rtx_code code
= reverse_condition (GET_CODE (cond
));
9515 if (code
== UNKNOWN
|| ccm
== CC_FP_GTmode
|| ccm
== CC_FP_GEmode
)
9516 code
= reverse_condition_maybe_unordered (GET_CODE (cond
));
9518 cond
= gen_rtx_fmt_ee (code
, GET_MODE (cond
),
9519 copy_rtx (XEXP (cond
, 0)),
9520 copy_rtx (XEXP (cond
, 1)));
9523 cond
= copy_rtx (cond
);
9524 patp
= &PATTERN (dlay
);
9526 pat
= conditionalize_nonjump (pat
, cond
, dlay
, true);
9527 validate_change (dlay
, patp
, pat
, 1);
9528 if (!apply_change_group ())
9534 /* For ARC600: If a write to a core reg >=32 appears in a delay slot
9535 (other than of a forward brcc), it creates a hazard when there is a read
9536 of the same register at the branch target. We can't know what is at the
9537 branch target of calls, and for branches, we don't really know before the
9538 end of delay slot scheduling, either. Not only can individual instruction
9539 be hoisted out into a delay slot, a basic block can also be emptied this
9540 way, and branch and/or fall through targets be redirected. Hence we don't
9541 want such writes in a delay slot. */
9543 /* Return nonzreo iff INSN writes to an extension core register. */
9546 arc_write_ext_corereg (rtx insn
)
9548 subrtx_iterator::array_type array
;
9549 FOR_EACH_SUBRTX (iter
, array
, PATTERN (insn
), NONCONST
)
9551 const_rtx x
= *iter
;
9552 switch (GET_CODE (x
))
9554 case SET
: case POST_INC
: case POST_DEC
: case PRE_INC
: case PRE_DEC
:
9557 /* This is also fine for PRE/POST_MODIFY, because they
9561 const_rtx dest
= XEXP (x
, 0);
9562 if (REG_P (dest
) && REGNO (dest
) >= 32 && REGNO (dest
) < 61)
9568 /* This is like the hook, but returns NULL when it can't / won't generate
9569 a legitimate address. */
9572 arc_legitimize_address_0 (rtx x
, rtx oldx ATTRIBUTE_UNUSED
,
9578 if (GET_CODE (addr
) == CONST
)
9579 addr
= XEXP (addr
, 0);
9581 if (GET_CODE (addr
) == PLUS
9582 && CONST_INT_P (XEXP (addr
, 1))
9583 && ((GET_CODE (XEXP (addr
, 0)) == SYMBOL_REF
9584 && !SYMBOL_REF_FUNCTION_P (XEXP (addr
, 0)))
9585 || (REG_P (XEXP (addr
, 0))
9586 && (INTVAL (XEXP (addr
, 1)) & 252))))
9588 HOST_WIDE_INT offs
, upper
;
9589 int size
= GET_MODE_SIZE (mode
);
9591 offs
= INTVAL (XEXP (addr
, 1));
9592 upper
= (offs
+ 256 * size
) & ~511 * size
;
9593 inner
= plus_constant (Pmode
, XEXP (addr
, 0), upper
);
9594 #if 0 /* ??? this produces worse code for EEMBC idctrn01 */
9595 if (GET_CODE (x
) == CONST
)
9596 inner
= gen_rtx_CONST (Pmode
, inner
);
9598 addr
= plus_constant (Pmode
, force_reg (Pmode
, inner
), offs
- upper
);
9601 else if (GET_CODE (addr
) == SYMBOL_REF
&& !SYMBOL_REF_FUNCTION_P (addr
))
9602 x
= force_reg (Pmode
, x
);
9603 if (memory_address_p ((machine_mode
) mode
, x
))
9609 arc_legitimize_address (rtx orig_x
, rtx oldx
, machine_mode mode
)
9611 rtx new_x
= arc_legitimize_address_0 (orig_x
, oldx
, mode
);
9619 arc_delegitimize_address_0 (rtx op
)
9621 switch (GET_CODE (op
))
9624 return arc_delegitimize_address_0 (XEXP (op
, 0));
9627 switch (XINT (op
, 1))
9629 case ARC_UNSPEC_GOT
:
9630 case ARC_UNSPEC_GOTOFFPC
:
9631 return XVECEXP (op
, 0, 0);
9639 rtx t1
= arc_delegitimize_address_0 (XEXP (op
, 0));
9640 rtx t2
= XEXP (op
, 1);
9643 return gen_rtx_PLUS (GET_MODE (op
), t1
, t2
);
9654 arc_delegitimize_address (rtx orig_x
)
9661 x
= arc_delegitimize_address_0 (x
);
9666 x
= replace_equiv_address_nv (orig_x
, x
);
9670 /* Return a REG rtx for acc1. N.B. the gcc-internal representation may
9671 differ from the hardware register number in order to allow the generic
9672 code to correctly split the concatenation of acc1 and acc2. */
9677 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 56 : 57);
9680 /* Return a REG rtx for acc2. N.B. the gcc-internal representation may
9681 differ from the hardware register number in order to allow the generic
9682 code to correctly split the concatenation of acc1 and acc2. */
9687 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 57 : 56);
9690 /* When estimating sizes during arc_reorg, when optimizing for speed, there
9691 are three reasons why we need to consider branches to be length 6:
9692 - annull-false delay slot insns are implemented using conditional execution,
9693 thus preventing short insn formation where used.
9694 - for ARC600: annul-true delay slot insns are implemented where possible
9695 using conditional execution, preventing short insn formation where used.
9696 - for ARC700: likely or somewhat likely taken branches are made long and
9697 unaligned if possible to avoid branch penalty. */
9700 arc_branch_size_unknown_p (void)
9702 return !optimize_size
&& arc_reorg_in_progress
;
9705 /* The usual; we set up our machine_function data. */
9707 static struct machine_function
*
9708 arc_init_machine_status (void)
9710 struct machine_function
*machine
;
9711 machine
= ggc_cleared_alloc
<machine_function
> ();
9712 machine
->fn_type
= ARC_FUNCTION_UNKNOWN
;
9717 /* Implements INIT_EXPANDERS. We just set up to call the above
9721 arc_init_expanders (void)
9723 init_machine_status
= arc_init_machine_status
;
9726 /* Check if OP is a proper parallel of a millicode call pattern. OFFSET
9727 indicates a number of elements to ignore - that allows to have a
9728 sibcall pattern that starts with (return). LOAD_P is zero for store
9729 multiple (for prologues), and one for load multiples (for epilogues),
9730 and two for load multiples where no final clobber of blink is required.
9731 We also skip the first load / store element since this is supposed to
9732 be checked in the instruction pattern. */
9735 arc_check_millicode (rtx op
, int offset
, int load_p
)
9737 int len
= XVECLEN (op
, 0) - offset
;
9742 if (len
< 2 || len
> 13)
9748 rtx elt
= XVECEXP (op
, 0, --len
);
9750 if (GET_CODE (elt
) != CLOBBER
9751 || !REG_P (XEXP (elt
, 0))
9752 || REGNO (XEXP (elt
, 0)) != RETURN_ADDR_REGNUM
9753 || len
< 3 || len
> 13)
9756 for (i
= 1; i
< len
; i
++)
9758 rtx elt
= XVECEXP (op
, 0, i
+ offset
);
9761 if (GET_CODE (elt
) != SET
)
9763 mem
= XEXP (elt
, load_p
);
9764 reg
= XEXP (elt
, 1-load_p
);
9765 if (!REG_P (reg
) || REGNO (reg
) != 13U+i
|| !MEM_P (mem
))
9767 addr
= XEXP (mem
, 0);
9768 if (GET_CODE (addr
) != PLUS
9769 || !rtx_equal_p (stack_pointer_rtx
, XEXP (addr
, 0))
9770 || !CONST_INT_P (XEXP (addr
, 1)) || INTVAL (XEXP (addr
, 1)) != i
*4)
9776 /* Operands 0..2 are the operands of a subsi which uses a 12 bit
9777 constant in operand 1, but which would require a LIMM because of
9779 operands 3 and 4 are new SET_SRCs for operands 0. */
9782 split_subsi (rtx
*operands
)
9784 int val
= INTVAL (operands
[1]);
9786 /* Try for two short insns first. Lengths being equal, we prefer
9787 expansions with shorter register lifetimes. */
9788 if (arc_check_short_reg_p (operands
[0])
9789 && arc_check_short_reg_p (operands
[2]))
9791 if (val
>= -31 && val
<= 127)
9793 operands
[3] = gen_rtx_NEG (SImode
, operands
[2]);
9794 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[1]);
9797 else if (val
>= 0 && val
< 255)
9799 operands
[3] = operands
[1];
9800 operands
[4] = gen_rtx_MINUS (SImode
, operands
[0], operands
[2]);
9804 /* If the destination is not an ARCompact16 register, we might
9805 still have a chance to make a short insn if the source is;
9806 we need to start with a reg-reg move for this. */
9807 operands
[3] = operands
[2];
9808 operands
[4] = gen_rtx_MINUS (SImode
, operands
[1], operands
[0]);
9811 /* Handle DOUBLE_REGS uses.
9812 Operand 0: destination register
9813 Operand 1: source register */
9816 arc_process_double_reg_moves (rtx
*operands
)
9818 enum usesDxState
{ none
, srcDx
, destDx
, maxDx
};
9819 enum usesDxState state
= none
;
9820 rtx dest
= operands
[0];
9821 rtx src
= operands
[1];
9823 if (refers_to_regno_p (40, 44, src
, 0))
9826 gcc_assert (REG_P (dest
));
9828 if (refers_to_regno_p (40, 44, dest
, 0))
9830 /* Via arc_register_move_cost, we should never see D,D moves. */
9831 gcc_assert (REG_P (src
));
9832 gcc_assert (state
== none
);
9841 /* Without the LR insn, we need to split this into a
9842 sequence of insns which will use the DEXCLx and DADDHxy
9843 insns to be able to read the Dx register in question. */
9844 if (TARGET_DPFP_DISABLE_LRSR
)
9846 /* gen *movdf_insn_nolrsr */
9847 rtx set
= gen_rtx_SET (dest
, src
);
9848 rtx use1
= gen_rtx_USE (VOIDmode
, const1_rtx
);
9849 emit_insn (gen_rtx_PARALLEL (VOIDmode
, gen_rtvec (2, set
, use1
)));
9853 /* When we have 'mov D, r' or 'mov D, D' then get the target
9854 register pair for use with LR insn. */
9855 rtx destHigh
= simplify_gen_subreg (SImode
, dest
, DFmode
,
9856 TARGET_BIG_ENDIAN
? 0 : 4);
9857 rtx destLow
= simplify_gen_subreg (SImode
, dest
, DFmode
,
9858 TARGET_BIG_ENDIAN
? 4 : 0);
9860 /* Produce the two LR insns to get the high and low parts. */
9861 emit_insn (gen_rtx_SET (destHigh
,
9862 gen_rtx_UNSPEC_VOLATILE (Pmode
,
9864 VUNSPEC_ARC_LR_HIGH
)));
9865 emit_insn (gen_rtx_SET (destLow
,
9866 gen_rtx_UNSPEC_VOLATILE (Pmode
,
9871 else if (state
== destDx
)
9873 /* When we have 'mov r, D' or 'mov D, D' and we have access to the
9874 LR insn get the target register pair. */
9875 rtx srcHigh
= simplify_gen_subreg (SImode
, src
, DFmode
,
9876 TARGET_BIG_ENDIAN
? 0 : 4);
9877 rtx srcLow
= simplify_gen_subreg (SImode
, src
, DFmode
,
9878 TARGET_BIG_ENDIAN
? 4 : 0);
9880 emit_insn (gen_dexcl_2op (dest
, srcHigh
, srcLow
));
9889 /* Check if we need to split a 64bit move. We do not need to split it if we can
9890 use vadd2 or ldd/std instructions. */
9893 arc_split_move_p (rtx
*operands
)
9895 machine_mode mode
= GET_MODE (operands
[0]);
9898 && ((memory_operand (operands
[0], mode
)
9899 && (even_register_operand (operands
[1], mode
)
9900 || satisfies_constraint_Cm3 (operands
[1])))
9901 || (memory_operand (operands
[1], mode
)
9902 && even_register_operand (operands
[0], mode
))))
9905 if (TARGET_PLUS_QMACW
9906 && even_register_operand (operands
[0], mode
)
9907 && even_register_operand (operands
[1], mode
))
9913 /* operands 0..1 are the operands of a 64 bit move instruction.
9914 split it into two moves with operands 2/3 and 4/5. */
9917 arc_split_move (rtx
*operands
)
9919 machine_mode mode
= GET_MODE (operands
[0]);
9926 if (arc_process_double_reg_moves (operands
))
9930 if (TARGET_PLUS_QMACW
9931 && GET_CODE (operands
[1]) == CONST_VECTOR
)
9933 HOST_WIDE_INT intval0
, intval1
;
9934 if (GET_MODE (operands
[1]) == V2SImode
)
9936 intval0
= INTVAL (XVECEXP (operands
[1], 0, 0));
9937 intval1
= INTVAL (XVECEXP (operands
[1], 0, 1));
9941 intval1
= INTVAL (XVECEXP (operands
[1], 0, 3)) << 16;
9942 intval1
|= INTVAL (XVECEXP (operands
[1], 0, 2)) & 0xFFFF;
9943 intval0
= INTVAL (XVECEXP (operands
[1], 0, 1)) << 16;
9944 intval0
|= INTVAL (XVECEXP (operands
[1], 0, 0)) & 0xFFFF;
9946 xop
[0] = gen_rtx_REG (SImode
, REGNO (operands
[0]));
9947 xop
[3] = gen_rtx_REG (SImode
, REGNO (operands
[0]) + 1);
9948 xop
[2] = GEN_INT (trunc_int_for_mode (intval0
, SImode
));
9949 xop
[1] = GEN_INT (trunc_int_for_mode (intval1
, SImode
));
9950 emit_move_insn (xop
[0], xop
[2]);
9951 emit_move_insn (xop
[3], xop
[1]);
9955 for (i
= 0; i
< 2; i
++)
9957 if (MEM_P (operands
[i
]) && auto_inc_p (XEXP (operands
[i
], 0)))
9959 rtx addr
= XEXP (operands
[i
], 0);
9963 gcc_assert (!reg_overlap_mentioned_p (operands
[0], addr
));
9964 switch (GET_CODE (addr
))
9966 case PRE_DEC
: o
= GEN_INT (-8); goto pre_modify
;
9967 case PRE_INC
: o
= GEN_INT (8); goto pre_modify
;
9968 case PRE_MODIFY
: o
= XEXP (XEXP (addr
, 1), 1);
9972 case POST_DEC
: o
= GEN_INT (-8); goto post_modify
;
9973 case POST_INC
: o
= GEN_INT (8); goto post_modify
;
9974 case POST_MODIFY
: o
= XEXP (XEXP (addr
, 1), 1);
9983 xop
[0+i
] = adjust_automodify_address_nv
9984 (operands
[i
], SImode
,
9985 gen_rtx_fmt_ee (code
, Pmode
, r
,
9986 gen_rtx_PLUS (Pmode
, r
, o
)),
9988 xop
[2+i
] = adjust_automodify_address_nv
9989 (operands
[i
], SImode
, plus_constant (Pmode
, r
, 4), 4);
9993 xop
[0+i
] = operand_subword (operands
[i
], 0, 0, mode
);
9994 xop
[2+i
] = operand_subword (operands
[i
], 1, 0, mode
);
9997 if (reg_overlap_mentioned_p (xop
[0], xop
[3]))
10000 gcc_assert (!reg_overlap_mentioned_p (xop
[2], xop
[1]));
10003 emit_move_insn (xop
[0 + swap
], xop
[1 + swap
]);
10004 emit_move_insn (xop
[2 - swap
], xop
[3 - swap
]);
10008 /* Select between the instruction output templates s_tmpl (for short INSNs)
10009 and l_tmpl (for long INSNs). */
10012 arc_short_long (rtx_insn
*insn
, const char *s_tmpl
, const char *l_tmpl
)
10014 int is_short
= arc_verify_short (insn
, -1);
10016 extract_constrain_insn_cached (insn
);
10017 return is_short
? s_tmpl
: l_tmpl
;
10020 /* Searches X for any reference to REGNO, returning the rtx of the
10021 reference found if any. Otherwise, returns NULL_RTX. */
10024 arc_regno_use_in (unsigned int regno
, rtx x
)
10030 if (REG_P (x
) && refers_to_regno_p (regno
, x
))
10033 fmt
= GET_RTX_FORMAT (GET_CODE (x
));
10034 for (i
= GET_RTX_LENGTH (GET_CODE (x
)) - 1; i
>= 0; i
--)
10038 if ((tem
= regno_use_in (regno
, XEXP (x
, i
))))
10041 else if (fmt
[i
] == 'E')
10042 for (j
= XVECLEN (x
, i
) - 1; j
>= 0; j
--)
10043 if ((tem
= regno_use_in (regno
, XVECEXP (x
, i
, j
))))
10050 /* Code has a minimum p2 alignment of 1, which we must restore after
10051 an ADDR_DIFF_VEC. */
10054 arc_label_align (rtx_insn
*label
)
10056 if (align_labels
.levels
[0].log
< 1)
10058 rtx_insn
*next
= next_nonnote_nondebug_insn (label
);
10059 if (INSN_P (next
) && recog_memoized (next
) >= 0)
10062 return align_labels
.levels
[0].log
;
10065 /* Return true if LABEL is in executable code. */
10068 arc_text_label (rtx_insn
*label
)
10072 /* ??? We use deleted labels like they were still there, see
10073 gcc.c-torture/compile/20000326-2.c . */
10074 gcc_assert (GET_CODE (label
) == CODE_LABEL
10075 || (GET_CODE (label
) == NOTE
10076 && NOTE_KIND (label
) == NOTE_INSN_DELETED_LABEL
));
10077 next
= next_nonnote_insn (label
);
10079 return (!JUMP_TABLE_DATA_P (next
)
10080 || GET_CODE (PATTERN (next
)) != ADDR_VEC
);
10081 else if (!PREV_INSN (label
))
10082 /* ??? sometimes text labels get inserted very late, see
10083 gcc.dg/torture/stackalign/comp-goto-1.c */
10088 /* Without this, gcc.dg/tree-prof/bb-reorg.c fails to assemble
10089 when compiling with -O2 -freorder-blocks-and-partition -fprofile-use
10090 -D_PROFILE_USE; delay branch scheduling then follows a crossing jump
10091 to redirect two breqs. */
10094 arc_can_follow_jump (const rtx_insn
*follower
, const rtx_insn
*followee
)
10096 /* ??? get_attr_type is declared to take an rtx. */
10097 union { const rtx_insn
*c
; rtx_insn
*r
; } u
;
10100 if (CROSSING_JUMP_P (followee
))
10101 switch (get_attr_type (u
.r
))
10104 if (get_attr_length (u
.r
) != 2)
10106 /* Fall through. */
10108 case TYPE_BRCC_NO_DELAY_SLOT
:
10117 /* Implement EPILOGUE_USES.
10118 Return true if REGNO should be added to the deemed uses of the epilogue.
10120 We have to make sure all the register restore instructions are
10121 known to be live in interrupt functions, plus the blink register if
10122 it is clobbered by the isr. */
10125 arc_epilogue_uses (int regno
)
10127 unsigned int fn_type
;
10128 fn_type
= arc_compute_function_type (cfun
);
10130 if (regno
== arc_tp_regno
)
10133 if (regno
== RETURN_ADDR_REGNUM
)
10136 if (regno
== arc_return_address_register (fn_type
))
10139 if (epilogue_completed
&& ARC_INTERRUPT_P (fn_type
))
10141 /* An interrupt function restores more registers. */
10142 if (df_regs_ever_live_p (regno
) || call_used_or_fixed_reg_p (regno
))
10149 /* Helper for EH_USES macro. */
10152 arc_eh_uses (int regno
)
10154 if (regno
== arc_tp_regno
)
10159 /* ??? Should we define TARGET_REGISTER_PRIORITY? We might perfer to
10160 use q registers, because some insn are shorter with them. OTOH we
10161 already have separate alternatives for this purpose, and other
10162 insns don't mind, so maybe we should rather prefer the other
10163 registers? We need more data, and we can only get that if we allow
10164 people to try all options. */
10166 arc_register_priority (int r
)
10168 switch (arc_lra_priority_tag
)
10170 case ARC_LRA_PRIORITY_NONE
:
10172 case ARC_LRA_PRIORITY_NONCOMPACT
:
10173 return ((((r
& 7) ^ 4) - 4) & 15) != r
;
10174 case ARC_LRA_PRIORITY_COMPACT
:
10175 return ((((r
& 7) ^ 4) - 4) & 15) == r
;
10177 gcc_unreachable ();
10182 arc_spill_class (reg_class_t
/* orig_class */, machine_mode
)
10184 return GENERAL_REGS
;
10188 arc_legitimize_reload_address (rtx
*p
, machine_mode mode
, int opnum
,
10192 enum reload_type type
= (enum reload_type
) itype
;
10194 if (GET_CODE (x
) == PLUS
10195 && CONST_INT_P (XEXP (x
, 1))
10196 && (RTX_OK_FOR_BASE_P (XEXP (x
, 0), true)
10197 || (REG_P (XEXP (x
, 0))
10198 && reg_equiv_constant (REGNO (XEXP (x
, 0))))))
10200 int scale
= GET_MODE_SIZE (mode
);
10202 rtx index_rtx
= XEXP (x
, 1);
10203 HOST_WIDE_INT offset
= INTVAL (index_rtx
), offset_base
;
10204 rtx reg
, sum
, sum2
;
10208 if ((scale
-1) & offset
)
10210 shift
= scale
>> 1;
10212 = ((offset
+ (256 << shift
))
10213 & ((HOST_WIDE_INT
)((unsigned HOST_WIDE_INT
) -512 << shift
)));
10214 /* Sometimes the normal form does not suit DImode. We
10215 could avoid that by using smaller ranges, but that
10216 would give less optimized code when SImode is
10218 if (GET_MODE_SIZE (mode
) + offset
- offset_base
<= (256 << shift
))
10223 regno
= REGNO (reg
);
10224 sum2
= sum
= plus_constant (Pmode
, reg
, offset_base
);
10226 if (reg_equiv_constant (regno
))
10228 sum2
= plus_constant (Pmode
, reg_equiv_constant (regno
),
10230 if (GET_CODE (sum2
) == PLUS
)
10231 sum2
= gen_rtx_CONST (Pmode
, sum2
);
10233 *p
= gen_rtx_PLUS (Pmode
, sum
, GEN_INT (offset
- offset_base
));
10234 push_reload (sum2
, NULL_RTX
, &XEXP (*p
, 0), NULL
,
10235 BASE_REG_CLASS
, Pmode
, VOIDmode
, 0, 0, opnum
,
10240 /* We must re-recognize what we created before. */
10241 else if (GET_CODE (x
) == PLUS
10242 && GET_CODE (XEXP (x
, 0)) == PLUS
10243 && CONST_INT_P (XEXP (XEXP (x
, 0), 1))
10244 && REG_P (XEXP (XEXP (x
, 0), 0))
10245 && CONST_INT_P (XEXP (x
, 1)))
10247 /* Because this address is so complex, we know it must have
10248 been created by LEGITIMIZE_RELOAD_ADDRESS before; thus,
10249 it is already unshared, and needs no further unsharing. */
10250 push_reload (XEXP (x
, 0), NULL_RTX
, &XEXP (x
, 0), NULL
,
10251 BASE_REG_CLASS
, Pmode
, VOIDmode
, 0, 0, opnum
, type
);
10257 /* Implement TARGET_USE_BY_PIECES_INFRASTRUCTURE_P. */
10260 arc_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size
,
10261 unsigned int align
,
10262 enum by_pieces_operation op
,
10265 /* Let the cpymem expander handle small block moves. */
10266 if (op
== MOVE_BY_PIECES
)
10269 return default_use_by_pieces_infrastructure_p (size
, align
, op
, speed_p
);
10272 /* Emit a (pre) memory barrier around an atomic sequence according to
10276 arc_pre_atomic_barrier (enum memmodel model
)
10278 if (need_atomic_barrier_p (model
, true))
10279 emit_insn (gen_memory_barrier ());
10282 /* Emit a (post) memory barrier around an atomic sequence according to
10286 arc_post_atomic_barrier (enum memmodel model
)
10288 if (need_atomic_barrier_p (model
, false))
10289 emit_insn (gen_memory_barrier ());
10292 /* Expand a compare and swap pattern. */
10295 emit_unlikely_jump (rtx insn
)
10297 rtx_insn
*jump
= emit_jump_insn (insn
);
10298 add_reg_br_prob_note (jump
, profile_probability::very_unlikely ());
10301 /* Expand code to perform a 8 or 16-bit compare and swap by doing
10302 32-bit compare and swap on the word containing the byte or
10303 half-word. The difference between a weak and a strong CAS is that
10304 the weak version may simply fail. The strong version relies on two
10305 loops, one checks if the SCOND op is succsfully or not, the other
10306 checks if the 32 bit accessed location which contains the 8 or 16
10307 bit datum is not changed by other thread. The first loop is
10308 implemented by the atomic_compare_and_swapsi_1 pattern. The second
10309 loops is implemented by this routine. */
10312 arc_expand_compare_and_swap_qh (rtx bool_result
, rtx result
, rtx mem
,
10313 rtx oldval
, rtx newval
, rtx weak
,
10314 rtx mod_s
, rtx mod_f
)
10316 rtx addr1
= force_reg (Pmode
, XEXP (mem
, 0));
10317 rtx addr
= gen_reg_rtx (Pmode
);
10318 rtx off
= gen_reg_rtx (SImode
);
10319 rtx oldv
= gen_reg_rtx (SImode
);
10320 rtx newv
= gen_reg_rtx (SImode
);
10321 rtx oldvalue
= gen_reg_rtx (SImode
);
10322 rtx newvalue
= gen_reg_rtx (SImode
);
10323 rtx res
= gen_reg_rtx (SImode
);
10324 rtx resv
= gen_reg_rtx (SImode
);
10325 rtx memsi
, val
, mask
, end_label
, loop_label
, cc
, x
;
10327 bool is_weak
= (weak
!= const0_rtx
);
10329 /* Truncate the address. */
10330 emit_insn (gen_rtx_SET (addr
,
10331 gen_rtx_AND (Pmode
, addr1
, GEN_INT (-4))));
10333 /* Compute the datum offset. */
10334 emit_insn (gen_rtx_SET (off
,
10335 gen_rtx_AND (SImode
, addr1
, GEN_INT (3))));
10336 if (TARGET_BIG_ENDIAN
)
10337 emit_insn (gen_rtx_SET (off
,
10338 gen_rtx_MINUS (SImode
,
10339 (GET_MODE (mem
) == QImode
) ?
10340 GEN_INT (3) : GEN_INT (2), off
)));
10342 /* Normal read from truncated address. */
10343 memsi
= gen_rtx_MEM (SImode
, addr
);
10344 set_mem_alias_set (memsi
, ALIAS_SET_MEMORY_BARRIER
);
10345 MEM_VOLATILE_P (memsi
) = MEM_VOLATILE_P (mem
);
10347 val
= copy_to_reg (memsi
);
10349 /* Convert the offset in bits. */
10350 emit_insn (gen_rtx_SET (off
,
10351 gen_rtx_ASHIFT (SImode
, off
, GEN_INT (3))));
10353 /* Get the proper mask. */
10354 if (GET_MODE (mem
) == QImode
)
10355 mask
= force_reg (SImode
, GEN_INT (0xff));
10357 mask
= force_reg (SImode
, GEN_INT (0xffff));
10359 emit_insn (gen_rtx_SET (mask
,
10360 gen_rtx_ASHIFT (SImode
, mask
, off
)));
10362 /* Prepare the old and new values. */
10363 emit_insn (gen_rtx_SET (val
,
10364 gen_rtx_AND (SImode
, gen_rtx_NOT (SImode
, mask
),
10367 oldval
= gen_lowpart (SImode
, oldval
);
10368 emit_insn (gen_rtx_SET (oldv
,
10369 gen_rtx_ASHIFT (SImode
, oldval
, off
)));
10371 newval
= gen_lowpart_common (SImode
, newval
);
10372 emit_insn (gen_rtx_SET (newv
,
10373 gen_rtx_ASHIFT (SImode
, newval
, off
)));
10375 emit_insn (gen_rtx_SET (oldv
,
10376 gen_rtx_AND (SImode
, oldv
, mask
)));
10378 emit_insn (gen_rtx_SET (newv
,
10379 gen_rtx_AND (SImode
, newv
, mask
)));
10383 end_label
= gen_label_rtx ();
10384 loop_label
= gen_label_rtx ();
10385 emit_label (loop_label
);
10388 /* Make the old and new values. */
10389 emit_insn (gen_rtx_SET (oldvalue
,
10390 gen_rtx_IOR (SImode
, oldv
, val
)));
10392 emit_insn (gen_rtx_SET (newvalue
,
10393 gen_rtx_IOR (SImode
, newv
, val
)));
10395 /* Try an 32bit atomic compare and swap. It clobbers the CC
10397 emit_insn (gen_atomic_compare_and_swapsi_1 (res
, memsi
, oldvalue
, newvalue
,
10398 weak
, mod_s
, mod_f
));
10400 /* Regardless of the weakness of the operation, a proper boolean
10401 result needs to be provided. */
10402 x
= gen_rtx_REG (CC_Zmode
, CC_REG
);
10403 x
= gen_rtx_EQ (SImode
, x
, const0_rtx
);
10404 emit_insn (gen_rtx_SET (bool_result
, x
));
10408 /* Check the results: if the atomic op is successfully the goto
10410 x
= gen_rtx_REG (CC_Zmode
, CC_REG
);
10411 x
= gen_rtx_EQ (VOIDmode
, x
, const0_rtx
);
10412 x
= gen_rtx_IF_THEN_ELSE (VOIDmode
, x
,
10413 gen_rtx_LABEL_REF (Pmode
, end_label
), pc_rtx
);
10414 emit_jump_insn (gen_rtx_SET (pc_rtx
, x
));
10416 /* Wait for the right moment when the accessed 32-bit location
10418 emit_insn (gen_rtx_SET (resv
,
10419 gen_rtx_AND (SImode
, gen_rtx_NOT (SImode
, mask
),
10421 mode
= SELECT_CC_MODE (NE
, resv
, val
);
10422 cc
= gen_rtx_REG (mode
, CC_REG
);
10423 emit_insn (gen_rtx_SET (cc
, gen_rtx_COMPARE (mode
, resv
, val
)));
10425 /* Set the new value of the 32 bit location, proper masked. */
10426 emit_insn (gen_rtx_SET (val
, resv
));
10428 /* Try again if location is unstable. Fall through if only
10429 scond op failed. */
10430 x
= gen_rtx_NE (VOIDmode
, cc
, const0_rtx
);
10431 x
= gen_rtx_IF_THEN_ELSE (VOIDmode
, x
,
10432 gen_rtx_LABEL_REF (Pmode
, loop_label
), pc_rtx
);
10433 emit_unlikely_jump (gen_rtx_SET (pc_rtx
, x
));
10435 emit_label (end_label
);
10438 /* End: proper return the result for the given mode. */
10439 emit_insn (gen_rtx_SET (res
,
10440 gen_rtx_AND (SImode
, res
, mask
)));
10442 emit_insn (gen_rtx_SET (res
,
10443 gen_rtx_LSHIFTRT (SImode
, res
, off
)));
10445 emit_move_insn (result
, gen_lowpart (GET_MODE (result
), res
));
10448 /* Helper function used by "atomic_compare_and_swap" expand
10452 arc_expand_compare_and_swap (rtx operands
[])
10454 rtx bval
, rval
, mem
, oldval
, newval
, is_weak
, mod_s
, mod_f
, x
;
10457 bval
= operands
[0];
10458 rval
= operands
[1];
10460 oldval
= operands
[3];
10461 newval
= operands
[4];
10462 is_weak
= operands
[5];
10463 mod_s
= operands
[6];
10464 mod_f
= operands
[7];
10465 mode
= GET_MODE (mem
);
10467 if (reg_overlap_mentioned_p (rval
, oldval
))
10468 oldval
= copy_to_reg (oldval
);
10470 if (mode
== SImode
)
10472 emit_insn (gen_atomic_compare_and_swapsi_1 (rval
, mem
, oldval
, newval
,
10473 is_weak
, mod_s
, mod_f
));
10474 x
= gen_rtx_REG (CC_Zmode
, CC_REG
);
10475 x
= gen_rtx_EQ (SImode
, x
, const0_rtx
);
10476 emit_insn (gen_rtx_SET (bval
, x
));
10480 arc_expand_compare_and_swap_qh (bval
, rval
, mem
, oldval
, newval
,
10481 is_weak
, mod_s
, mod_f
);
10485 /* Helper function used by the "atomic_compare_and_swapsi_1"
10489 arc_split_compare_and_swap (rtx operands
[])
10491 rtx rval
, mem
, oldval
, newval
;
10493 enum memmodel mod_s
, mod_f
;
10495 rtx label1
, label2
, x
, cond
;
10497 rval
= operands
[0];
10499 oldval
= operands
[2];
10500 newval
= operands
[3];
10501 is_weak
= (operands
[4] != const0_rtx
);
10502 mod_s
= (enum memmodel
) INTVAL (operands
[5]);
10503 mod_f
= (enum memmodel
) INTVAL (operands
[6]);
10504 mode
= GET_MODE (mem
);
10506 /* ARC atomic ops work only with 32-bit aligned memories. */
10507 gcc_assert (mode
== SImode
);
10509 arc_pre_atomic_barrier (mod_s
);
10514 label1
= gen_label_rtx ();
10515 emit_label (label1
);
10517 label2
= gen_label_rtx ();
10519 /* Load exclusive. */
10520 emit_insn (gen_arc_load_exclusivesi (rval
, mem
));
10522 /* Check if it is oldval. */
10523 mode
= SELECT_CC_MODE (NE
, rval
, oldval
);
10524 cond
= gen_rtx_REG (mode
, CC_REG
);
10525 emit_insn (gen_rtx_SET (cond
, gen_rtx_COMPARE (mode
, rval
, oldval
)));
10527 x
= gen_rtx_NE (VOIDmode
, cond
, const0_rtx
);
10528 x
= gen_rtx_IF_THEN_ELSE (VOIDmode
, x
,
10529 gen_rtx_LABEL_REF (Pmode
, label2
), pc_rtx
);
10530 emit_unlikely_jump (gen_rtx_SET (pc_rtx
, x
));
10532 /* Exclusively store new item. Store clobbers CC reg. */
10533 emit_insn (gen_arc_store_exclusivesi (mem
, newval
));
10537 /* Check the result of the store. */
10538 cond
= gen_rtx_REG (CC_Zmode
, CC_REG
);
10539 x
= gen_rtx_NE (VOIDmode
, cond
, const0_rtx
);
10540 x
= gen_rtx_IF_THEN_ELSE (VOIDmode
, x
,
10541 gen_rtx_LABEL_REF (Pmode
, label1
), pc_rtx
);
10542 emit_unlikely_jump (gen_rtx_SET (pc_rtx
, x
));
10545 if (mod_f
!= MEMMODEL_RELAXED
)
10546 emit_label (label2
);
10548 arc_post_atomic_barrier (mod_s
);
10550 if (mod_f
== MEMMODEL_RELAXED
)
10551 emit_label (label2
);
10554 /* Expand an atomic fetch-and-operate pattern. CODE is the binary operation
10555 to perform. MEM is the memory on which to operate. VAL is the second
10556 operand of the binary operator. BEFORE and AFTER are optional locations to
10557 return the value of MEM either before of after the operation. MODEL_RTX
10558 is a CONST_INT containing the memory model to use. */
10561 arc_expand_atomic_op (enum rtx_code code
, rtx mem
, rtx val
,
10562 rtx orig_before
, rtx orig_after
, rtx model_rtx
)
10564 enum memmodel model
= (enum memmodel
) INTVAL (model_rtx
);
10565 machine_mode mode
= GET_MODE (mem
);
10566 rtx label
, x
, cond
;
10567 rtx before
= orig_before
, after
= orig_after
;
10569 /* ARC atomic ops work only with 32-bit aligned memories. */
10570 gcc_assert (mode
== SImode
);
10572 arc_pre_atomic_barrier (model
);
10574 label
= gen_label_rtx ();
10575 emit_label (label
);
10576 label
= gen_rtx_LABEL_REF (VOIDmode
, label
);
10578 if (before
== NULL_RTX
)
10579 before
= gen_reg_rtx (mode
);
10581 if (after
== NULL_RTX
)
10582 after
= gen_reg_rtx (mode
);
10584 /* Load exclusive. */
10585 emit_insn (gen_arc_load_exclusivesi (before
, mem
));
10590 x
= gen_rtx_AND (mode
, before
, val
);
10591 emit_insn (gen_rtx_SET (after
, x
));
10592 x
= gen_rtx_NOT (mode
, after
);
10593 emit_insn (gen_rtx_SET (after
, x
));
10597 if (CONST_INT_P (val
))
10599 val
= GEN_INT (-INTVAL (val
));
10605 x
= gen_rtx_fmt_ee (code
, mode
, before
, val
);
10606 emit_insn (gen_rtx_SET (after
, x
));
10610 /* Exclusively store new item. Store clobbers CC reg. */
10611 emit_insn (gen_arc_store_exclusivesi (mem
, after
));
10613 /* Check the result of the store. */
10614 cond
= gen_rtx_REG (CC_Zmode
, CC_REG
);
10615 x
= gen_rtx_NE (VOIDmode
, cond
, const0_rtx
);
10616 x
= gen_rtx_IF_THEN_ELSE (VOIDmode
, x
,
10618 emit_unlikely_jump (gen_rtx_SET (pc_rtx
, x
));
10620 arc_post_atomic_barrier (model
);
10623 /* Implement TARGET_NO_SPECULATION_IN_DELAY_SLOTS_P. */
10626 arc_no_speculation_in_delay_slots_p ()
10631 /* Return a parallel of registers to represent where to find the
10632 register pieces if required, otherwise NULL_RTX. */
10635 arc_dwarf_register_span (rtx rtl
)
10637 machine_mode mode
= GET_MODE (rtl
);
10641 if (GET_MODE_SIZE (mode
) != 8)
10644 p
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (2));
10645 regno
= REGNO (rtl
);
10646 XVECEXP (p
, 0, 0) = gen_rtx_REG (SImode
, regno
);
10647 XVECEXP (p
, 0, 1) = gen_rtx_REG (SImode
, regno
+ 1);
10652 /* Return true if OP is an acceptable memory operand for ARCompact
10653 16-bit load instructions of MODE.
10655 AV2SHORT: TRUE if address needs to fit into the new ARCv2 short
10656 non scaled instructions.
10658 SCALED: TRUE if address can be scaled. */
10661 compact_memory_operand_p (rtx op
, machine_mode mode
,
10662 bool av2short
, bool scaled
)
10664 rtx addr
, plus0
, plus1
;
10667 /* Eliminate non-memory operations. */
10668 if (GET_CODE (op
) != MEM
)
10671 /* .di instructions have no 16-bit form. */
10672 if (MEM_VOLATILE_P (op
) && !TARGET_VOLATILE_CACHE_SET
)
10675 /* likewise for uncached types. */
10676 if (arc_is_uncached_mem_p (op
))
10679 if (mode
== VOIDmode
)
10680 mode
= GET_MODE (op
);
10682 size
= GET_MODE_SIZE (mode
);
10684 /* dword operations really put out 2 instructions, so eliminate
10686 if (size
> UNITS_PER_WORD
)
10689 /* Decode the address now. */
10690 addr
= XEXP (op
, 0);
10691 switch (GET_CODE (addr
))
10694 return (REGNO (addr
) >= FIRST_PSEUDO_REGISTER
10695 || COMPACT_GP_REG_P (REGNO (addr
))
10696 || (SP_REG_P (REGNO (addr
)) && (size
!= 2)));
10698 plus0
= XEXP (addr
, 0);
10699 plus1
= XEXP (addr
, 1);
10701 if ((GET_CODE (plus0
) == REG
)
10702 && ((REGNO (plus0
) >= FIRST_PSEUDO_REGISTER
)
10703 || COMPACT_GP_REG_P (REGNO (plus0
)))
10704 && ((GET_CODE (plus1
) == REG
)
10705 && ((REGNO (plus1
) >= FIRST_PSEUDO_REGISTER
)
10706 || COMPACT_GP_REG_P (REGNO (plus1
)))))
10711 if ((GET_CODE (plus0
) == REG
)
10712 && ((REGNO (plus0
) >= FIRST_PSEUDO_REGISTER
)
10713 || (COMPACT_GP_REG_P (REGNO (plus0
)) && !av2short
)
10714 || (IN_RANGE (REGNO (plus0
), 0, 31) && av2short
))
10715 && (GET_CODE (plus1
) == CONST_INT
))
10717 bool valid
= false;
10719 off
= INTVAL (plus1
);
10721 /* Negative offset is not supported in 16-bit load/store insns. */
10725 /* Only u5 immediates allowed in code density instructions. */
10733 /* This is an ldh_s.x instruction, check the u6
10735 if (COMPACT_GP_REG_P (REGNO (plus0
)))
10739 /* Only u5 immediates allowed in 32bit access code
10740 density instructions. */
10741 if (REGNO (plus0
) <= 31)
10742 return ((off
< 32) && (off
% 4 == 0));
10749 if (COMPACT_GP_REG_P (REGNO (plus0
)))
10760 /* The 6-bit constant get shifted to fit the real
10761 5-bits field. Check also for the alignment. */
10762 return ((off
< 64) && (off
% 2 == 0));
10764 return ((off
< 128) && (off
% 4 == 0));
10771 if (REG_P (plus0
) && CONST_INT_P (plus1
)
10772 && ((REGNO (plus0
) >= FIRST_PSEUDO_REGISTER
)
10773 || SP_REG_P (REGNO (plus0
)))
10776 off
= INTVAL (plus1
);
10777 return ((size
!= 2) && (off
>= 0 && off
< 128) && (off
% 4 == 0));
10780 if ((GET_CODE (plus0
) == MULT
)
10781 && (GET_CODE (XEXP (plus0
, 0)) == REG
)
10782 && ((REGNO (XEXP (plus0
, 0)) >= FIRST_PSEUDO_REGISTER
)
10783 || COMPACT_GP_REG_P (REGNO (XEXP (plus0
, 0))))
10784 && (GET_CODE (plus1
) == REG
)
10785 && ((REGNO (plus1
) >= FIRST_PSEUDO_REGISTER
)
10786 || COMPACT_GP_REG_P (REGNO (plus1
))))
10790 /* TODO: 'gp' and 'pcl' are to supported as base address operand
10791 for 16-bit load instructions. */
10796 /* Return nonzero if a jli call should be generated for a call from
10797 the current function to DECL. */
10800 arc_is_jli_call_p (rtx pat
)
10803 tree decl
= SYMBOL_REF_DECL (pat
);
10805 /* If it is not a well defined public function then return false. */
10806 if (!decl
|| !SYMBOL_REF_FUNCTION_P (pat
) || !TREE_PUBLIC (decl
))
10809 attrs
= TYPE_ATTRIBUTES (TREE_TYPE (decl
));
10810 if (lookup_attribute ("jli_always", attrs
))
10813 if (lookup_attribute ("jli_fixed", attrs
))
10816 return TARGET_JLI_ALWAYS
;
10819 /* Handle and "jli" attribute; arguments as in struct
10820 attribute_spec.handler. */
10823 arc_handle_jli_attribute (tree
*node ATTRIBUTE_UNUSED
,
10824 tree name
, tree args
, int,
10825 bool *no_add_attrs
)
10829 warning (OPT_Wattributes
,
10830 "%qE attribute only valid for ARCv2 architecture",
10832 *no_add_attrs
= true;
10835 if (args
== NULL_TREE
)
10837 warning (OPT_Wattributes
,
10838 "argument of %qE attribute is missing",
10840 *no_add_attrs
= true;
10844 if (TREE_CODE (TREE_VALUE (args
)) == NON_LVALUE_EXPR
)
10845 TREE_VALUE (args
) = TREE_OPERAND (TREE_VALUE (args
), 0);
10846 tree arg
= TREE_VALUE (args
);
10847 if (TREE_CODE (arg
) != INTEGER_CST
)
10849 warning (0, "%qE attribute allows only an integer constant argument",
10851 *no_add_attrs
= true;
10853 /* FIXME! add range check. TREE_INT_CST_LOW (arg) */
10858 /* Handle and "scure" attribute; arguments as in struct
10859 attribute_spec.handler. */
10862 arc_handle_secure_attribute (tree
*node ATTRIBUTE_UNUSED
,
10863 tree name
, tree args
, int,
10864 bool *no_add_attrs
)
10868 warning (OPT_Wattributes
,
10869 "%qE attribute only valid for ARC EM architecture",
10871 *no_add_attrs
= true;
10874 if (args
== NULL_TREE
)
10876 warning (OPT_Wattributes
,
10877 "argument of %qE attribute is missing",
10879 *no_add_attrs
= true;
10883 if (TREE_CODE (TREE_VALUE (args
)) == NON_LVALUE_EXPR
)
10884 TREE_VALUE (args
) = TREE_OPERAND (TREE_VALUE (args
), 0);
10885 tree arg
= TREE_VALUE (args
);
10886 if (TREE_CODE (arg
) != INTEGER_CST
)
10888 warning (0, "%qE attribute allows only an integer constant argument",
10890 *no_add_attrs
= true;
10896 /* Return nonzero if the symbol is a secure function. */
10899 arc_is_secure_call_p (rtx pat
)
10902 tree decl
= SYMBOL_REF_DECL (pat
);
10907 attrs
= TYPE_ATTRIBUTES (TREE_TYPE (decl
));
10908 if (lookup_attribute ("secure_call", attrs
))
10914 /* Handle "uncached" qualifier. */
10917 arc_handle_uncached_attribute (tree
*node
,
10918 tree name
, tree args
,
10919 int flags ATTRIBUTE_UNUSED
,
10920 bool *no_add_attrs
)
10922 if (DECL_P (*node
) && TREE_CODE (*node
) != TYPE_DECL
)
10924 error ("%qE attribute only applies to types",
10926 *no_add_attrs
= true;
10930 warning (OPT_Wattributes
, "argument of %qE attribute ignored", name
);
10935 /* Return TRUE if PAT is a memory addressing an uncached data. */
10938 arc_is_uncached_mem_p (rtx pat
)
10940 tree attrs
= NULL_TREE
;
10946 /* Get the memory attributes. */
10947 addr
= MEM_EXPR (pat
);
10951 /* Get the attributes. */
10952 if (TREE_CODE (addr
) == MEM_REF
10955 attrs
= TYPE_ATTRIBUTES (TREE_TYPE (addr
));
10956 if (lookup_attribute ("uncached", attrs
))
10959 if (TREE_CODE (addr
) == MEM_REF
)
10961 attrs
= TYPE_ATTRIBUTES (TREE_TYPE (TREE_OPERAND (addr
, 0)));
10962 if (lookup_attribute ("uncached", attrs
))
10964 attrs
= TYPE_ATTRIBUTES (TREE_TYPE (TREE_OPERAND (addr
, 1)));
10965 if (lookup_attribute ("uncached", attrs
))
10969 /* Check the definitions of the structs. */
10970 while (handled_component_p (addr
))
10972 if (TREE_CODE (addr
) == COMPONENT_REF
)
10974 attrs
= TYPE_ATTRIBUTES (TREE_TYPE (addr
));
10975 if (lookup_attribute ("uncached", attrs
))
10977 attrs
= TYPE_ATTRIBUTES (TREE_TYPE (TREE_OPERAND (addr
, 0)));
10978 if (lookup_attribute ("uncached", attrs
))
10980 attrs
= TYPE_ATTRIBUTES (TREE_TYPE (TREE_OPERAND (addr
, 1)));
10981 if (lookup_attribute ("uncached", attrs
))
10984 addr
= TREE_OPERAND (addr
, 0);
10989 /* Handle aux attribute. The auxiliary registers are addressed using
10990 special instructions lr and sr. The attribute 'aux' indicates if a
10991 variable refers to the aux-regs and what is the register number
10995 arc_handle_aux_attribute (tree
*node
,
10996 tree name
, tree args
, int,
10997 bool *no_add_attrs
)
10999 /* Isn't it better to use address spaces for the aux-regs? */
11000 if (DECL_P (*node
))
11002 if (TREE_CODE (*node
) != VAR_DECL
)
11004 error ("%qE attribute only applies to variables", name
);
11005 *no_add_attrs
= true;
11009 if (TREE_CODE (TREE_VALUE (args
)) == NON_LVALUE_EXPR
)
11010 TREE_VALUE (args
) = TREE_OPERAND (TREE_VALUE (args
), 0);
11011 tree arg
= TREE_VALUE (args
);
11012 if (TREE_CODE (arg
) != INTEGER_CST
)
11014 warning (OPT_Wattributes
, "%qE attribute allows only an integer "
11015 "constant argument", name
);
11016 *no_add_attrs
= true;
11018 /* FIXME! add range check. TREE_INT_CST_LOW (arg) */
11023 tree fntype
= TREE_TYPE (*node
);
11024 if (fntype
&& TREE_CODE (fntype
) == POINTER_TYPE
)
11026 tree attrs
= tree_cons (get_identifier ("aux"), NULL_TREE
,
11027 TYPE_ATTRIBUTES (fntype
));
11028 TYPE_ATTRIBUTES (fntype
) = attrs
;
11035 /* Implement TARGET_USE_ANCHORS_FOR_SYMBOL_P. We don't want to use
11036 anchors for small data: the GP register acts as an anchor in that
11037 case. We also don't want to use them for PC-relative accesses,
11038 where the PC acts as an anchor. Prohibit also TLS symbols to use
11042 arc_use_anchors_for_symbol_p (const_rtx symbol
)
11044 if (SYMBOL_REF_TLS_MODEL (symbol
))
11050 if (SYMBOL_REF_SMALL_P (symbol
))
11053 return default_use_anchors_for_symbol_p (symbol
);
11056 /* Return true if SUBST can't safely replace its equivalent during RA. */
11058 arc_cannot_substitute_mem_equiv_p (rtx
)
11060 /* If SUBST is mem[base+index], the address may not fit ISA,
11061 thus return true. */
11065 /* Checks whether the operands are valid for use in an LDD/STD
11066 instruction. Assumes that RT, and RT2 are REG. This is guaranteed
11067 by the patterns. Assumes that the address in the base register RN
11068 is word aligned. Pattern guarantees that both memory accesses use
11069 the same base register, the offsets are constants within the range,
11070 and the gap between the offsets is 4. If reload complete then
11071 check that registers are legal. */
11074 operands_ok_ldd_std (rtx rt
, rtx rt2
, HOST_WIDE_INT offset
)
11076 unsigned int t
, t2
;
11078 if (!reload_completed
)
11081 if (!(SMALL_INT_RANGE (offset
, (GET_MODE_SIZE (DImode
) - 1) & (~0x03),
11082 (offset
& (GET_MODE_SIZE (DImode
) - 1) & 3
11083 ? 0 : -(-GET_MODE_SIZE (DImode
) | (~0x03)) >> 1))))
11089 if ((t2
== PCL_REG
)
11090 || (t
% 2 != 0) /* First destination register is not even. */
11097 /* Helper for gen_operands_ldd_std. Returns true iff the memory
11098 operand MEM's address contains an immediate offset from the base
11099 register and has no side effects, in which case it sets BASE and
11100 OFFSET accordingly. */
11103 mem_ok_for_ldd_std (rtx mem
, rtx
*base
, rtx
*offset
)
11107 gcc_assert (base
!= NULL
&& offset
!= NULL
);
11109 /* TODO: Handle more general memory operand patterns, such as
11110 PRE_DEC and PRE_INC. */
11112 if (side_effects_p (mem
))
11115 /* Can't deal with subregs. */
11116 if (GET_CODE (mem
) == SUBREG
)
11119 gcc_assert (MEM_P (mem
));
11121 *offset
= const0_rtx
;
11123 addr
= XEXP (mem
, 0);
11125 /* If addr isn't valid for DImode, then we can't handle it. */
11126 if (!arc_legitimate_address_p (DImode
, addr
,
11127 reload_in_progress
|| reload_completed
))
11135 else if (GET_CODE (addr
) == PLUS
|| GET_CODE (addr
) == MINUS
)
11137 *base
= XEXP (addr
, 0);
11138 *offset
= XEXP (addr
, 1);
11139 return (REG_P (*base
) && CONST_INT_P (*offset
));
11145 /* Called from peephole2 to replace two word-size accesses with a
11146 single LDD/STD instruction. Returns true iff we can generate a new
11147 instruction sequence. That is, both accesses use the same base
11148 register and the gap between constant offsets is 4. OPERANDS are
11149 the operands found by the peephole matcher; OPERANDS[0,1] are
11150 register operands, and OPERANDS[2,3] are the corresponding memory
11151 operands. LOAD indicates whether the access is load or store. */
11154 gen_operands_ldd_std (rtx
*operands
, bool load
, bool commute
)
11157 HOST_WIDE_INT offsets
[2], offset
;
11159 rtx cur_base
, cur_offset
, tmp
;
11160 rtx base
= NULL_RTX
;
11162 /* Check that the memory references are immediate offsets from the
11163 same base register. Extract the base register, the destination
11164 registers, and the corresponding memory offsets. */
11165 for (i
= 0; i
< nops
; i
++)
11167 if (!mem_ok_for_ldd_std (operands
[nops
+i
], &cur_base
, &cur_offset
))
11172 else if (REGNO (base
) != REGNO (cur_base
))
11175 offsets
[i
] = INTVAL (cur_offset
);
11176 if (GET_CODE (operands
[i
]) == SUBREG
)
11178 tmp
= SUBREG_REG (operands
[i
]);
11179 gcc_assert (GET_MODE (operands
[i
]) == GET_MODE (tmp
));
11184 /* Make sure there is no dependency between the individual loads. */
11185 if (load
&& REGNO (operands
[0]) == REGNO (base
))
11186 return false; /* RAW. */
11188 if (load
&& REGNO (operands
[0]) == REGNO (operands
[1]))
11189 return false; /* WAW. */
11191 /* Make sure the instructions are ordered with lower memory access first. */
11192 if (offsets
[0] > offsets
[1])
11194 gap
= offsets
[0] - offsets
[1];
11195 offset
= offsets
[1];
11197 /* Swap the instructions such that lower memory is accessed first. */
11198 std::swap (operands
[0], operands
[1]);
11199 std::swap (operands
[2], operands
[3]);
11203 gap
= offsets
[1] - offsets
[0];
11204 offset
= offsets
[0];
11207 /* Make sure accesses are to consecutive memory locations. */
11211 /* Make sure we generate legal instructions. */
11212 if (operands_ok_ldd_std (operands
[0], operands
[1], offset
))
11215 if (load
&& commute
)
11217 /* Try reordering registers. */
11218 std::swap (operands
[0], operands
[1]);
11219 if (operands_ok_ldd_std (operands
[0], operands
[1], offset
))
11226 /* This order of allocation is used when we compile for size. It
11227 allocates first the registers which are most probably to end up in
11228 a short instruction. */
11229 static const int size_alloc_order
[] =
11231 0, 1, 2, 3, 12, 13, 14, 15,
11232 4, 5, 6, 7, 8, 9, 10, 11
11235 /* Adjust register allocation order when compiling for size. */
11237 arc_adjust_reg_alloc_order (void)
11239 const int arc_default_alloc_order
[] = REG_ALLOC_ORDER
;
11240 memcpy (reg_alloc_order
, arc_default_alloc_order
, sizeof (reg_alloc_order
));
11242 memcpy (reg_alloc_order
, size_alloc_order
, sizeof (size_alloc_order
));
11245 /* Implement TARGET_MEMORY_MOVE_COST. */
11248 arc_memory_move_cost (machine_mode mode
,
11249 reg_class_t rclass ATTRIBUTE_UNUSED
,
11250 bool in ATTRIBUTE_UNUSED
)
11252 if ((GET_MODE_SIZE (mode
) <= UNITS_PER_WORD
)
11253 || ((GET_MODE_SIZE (mode
) <= UNITS_PER_WORD
* 2) && TARGET_LL64
))
11256 return (2 * GET_MODE_SIZE (mode
));
11259 /* Split an OR instruction into multiple BSET/OR instructions in a
11260 attempt to avoid long immediate constants. The next strategies are
11261 employed when destination is 'q' reg.
11263 1. if there are up to three bits set in the mask, a succession of
11264 three bset instruction will be emitted:
11266 BSET(_S) rA,rB,mask1/BSET_S rA,rA,mask2/BSET_S rA,rA,mask3
11268 2. if the lower 6 bits of the mask is set and there is only one
11269 bit set in the upper remaining bits then we will emit one bset and
11270 one OR instruction:
11271 OR rA, rB, mask -> OR rA,rB,mask1/BSET_S rA,mask2
11273 3. otherwise an OR with limm will be emmitted. */
11276 arc_split_ior (rtx
*operands
)
11278 unsigned HOST_WIDE_INT mask
, maskx
;
11279 rtx op1
= operands
[1];
11281 gcc_assert (CONST_INT_P (operands
[2]));
11282 mask
= INTVAL (operands
[2]) & 0xffffffff;
11284 if (__builtin_popcount (mask
) > 3 || (mask
& 0x3f))
11286 maskx
= mask
& 0x3f;
11287 emit_insn (gen_rtx_SET (operands
[0],
11288 gen_rtx_IOR (SImode
, op1
, GEN_INT (maskx
))));
11293 switch (__builtin_popcount (mask
))
11296 maskx
= 1 << (__builtin_ffs (mask
) - 1);
11297 emit_insn (gen_rtx_SET (operands
[0],
11298 gen_rtx_IOR (SImode
, op1
, GEN_INT (maskx
))));
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 gcc_unreachable ();
11321 /* Helper to check C0x constraint. */
11324 arc_check_ior_const (HOST_WIDE_INT ival
)
11326 unsigned int mask
= (unsigned int) (ival
& 0xffffffff);
11328 if (UNSIGNED_INT6 (ival
)
11329 || IS_POWEROF2_P (mask
))
11331 if (__builtin_popcount (mask
) <= 3)
11333 if (__builtin_popcount (mask
& ~0x3f) <= 1)
11338 /* Split a mov with long immediate instruction into smaller, size
11339 friendly instructions. */
11342 arc_split_mov_const (rtx
*operands
)
11344 unsigned HOST_WIDE_INT ival
;
11345 HOST_WIDE_INT shimm
;
11346 machine_mode mode
= GET_MODE (operands
[0]);
11348 /* Manage a constant. */
11349 gcc_assert (CONST_INT_P (operands
[1]));
11350 ival
= INTVAL (operands
[1]) & 0xffffffff;
11352 /* 1. Check if we can just rotate limm by 8 but using ROR8. */
11353 if (TARGET_BARREL_SHIFTER
&& TARGET_V2
11354 && ((ival
& ~0x3f000000) == 0))
11356 shimm
= (ival
>> 24) & 0x3f;
11357 emit_insn (gen_rtx_SET (operands
[0],
11358 gen_rtx_ROTATERT (mode
, GEN_INT (shimm
),
11362 /* 2. Check if we can just shift by 8 to fit into the u6 of LSL8. */
11363 if (TARGET_BARREL_SHIFTER
&& TARGET_V2
11364 && ((ival
& ~0x3f00) == 0))
11366 shimm
= (ival
>> 8) & 0x3f;
11367 emit_insn (gen_rtx_SET (operands
[0],
11368 gen_rtx_ASHIFT (mode
, GEN_INT (shimm
),
11373 /* 3. Check if we can just shift by 16 to fit into the u6 of LSL16. */
11374 if (TARGET_SWAP
&& TARGET_V2
11375 && ((ival
& ~0x3f0000) == 0))
11377 shimm
= (ival
>> 16) & 0x3f;
11378 emit_insn (gen_rtx_SET (operands
[0],
11379 gen_rtx_ASHIFT (mode
, GEN_INT (shimm
),
11384 /* 4. Check if we can do something like mov_s h,u8 / asl_s ra,h,#nb. */
11385 if (((ival
>> (__builtin_ffs (ival
) - 1)) & 0xffffff00) == 0
11386 && TARGET_BARREL_SHIFTER
)
11388 HOST_WIDE_INT shift
= __builtin_ffs (ival
);
11389 shimm
= (ival
>> (shift
- 1)) & 0xff;
11390 emit_insn (gen_rtx_SET (operands
[0], GEN_INT (shimm
)));
11391 emit_insn (gen_rtx_SET (operands
[0],
11392 gen_rtx_ASHIFT (mode
, operands
[0],
11393 GEN_INT (shift
- 1))));
11397 /* 5. Check if we can just rotate the limm, useful when no barrel
11398 shifter is present. */
11399 if ((ival
& ~0x8000001f) == 0)
11401 shimm
= (ival
* 2 + 1) & 0x3f;
11402 emit_insn (gen_rtx_SET (operands
[0],
11403 gen_rtx_ROTATERT (mode
, GEN_INT (shimm
),
11408 /* 6. Check if we can do something with bmask. */
11409 if (IS_POWEROF2_P (ival
+ 1))
11411 emit_insn (gen_rtx_SET (operands
[0], constm1_rtx
));
11412 emit_insn (gen_rtx_SET (operands
[0],
11413 gen_rtx_AND (mode
, operands
[0],
11418 gcc_unreachable ();
11421 /* Helper to check Cax constraint. */
11424 arc_check_mov_const (HOST_WIDE_INT ival
)
11426 ival
= ival
& 0xffffffff;
11428 if (SIGNED_INT12 (ival
))
11431 if ((ival
& ~0x8000001f) == 0)
11434 if (IS_POWEROF2_P (ival
+ 1))
11437 /* The next rules requires a barrel shifter. */
11438 if (!TARGET_BARREL_SHIFTER
)
11441 if (((ival
>> (__builtin_ffs (ival
) - 1)) & 0xffffff00) == 0)
11444 if ((ival
& ~0x3f00) == 0)
11447 if ((ival
& ~0x3f0000) == 0)
11450 if ((ival
& ~0x3f000000) == 0)
11456 /* Return nonzero if this function is known to have a null epilogue.
11457 This allows the optimizer to omit jumps to jumps if no stack
11461 arc_can_use_return_insn (void)
11463 return (reload_completed
&& cfun
->machine
->frame_info
.total_size
== 0
11464 && !ARC_INTERRUPT_P (arc_compute_function_type (cfun
)));
11467 /* Helper for INSN_COST.
11469 Per Segher Boessenkool: rtx_costs computes the cost for any rtx (an
11470 insn, a set, a set source, any random piece of one). set_src_cost,
11471 set_rtx_cost, etc. are helper functions that use that.
11473 Those functions do not work for parallels. Also, costs are not
11474 additive like this simplified model assumes. Also, more complex
11475 backends tend to miss many cases in their rtx_costs function.
11477 Many passes that want costs want to know the cost of a full insn. Like
11478 combine. That's why I created insn_cost: it solves all of the above
11482 arc_insn_cost (rtx_insn
*insn
, bool speed
)
11485 enum attr_type type
;
11486 if (recog_memoized (insn
) >= 0)
11490 /* Use cost if provided. */
11491 cost
= get_attr_cost (insn
);
11494 /* For speed make a simple cost model: memory access is more
11495 expensive than any other instruction. */
11496 type
= get_attr_type (insn
);
11497 if (type
== TYPE_LOAD
|| type
== TYPE_STORE
)
11498 return COSTS_N_INSNS (2);
11502 /* If optimizing for size, we want the insn size. */
11503 type
= get_attr_type (insn
);
11504 if (type
!= TYPE_MULTI
)
11505 return get_attr_length (insn
);
11509 if (rtx set
= single_set (insn
))
11510 cost
= set_rtx_cost (set
, speed
);
11512 cost
= pattern_cost (PATTERN (insn
), speed
);
11513 /* If the cost is zero, then it's likely a complex insn. We don't
11514 want the cost of these to be less than something we know about. */
11515 return cost
? cost
: COSTS_N_INSNS (2);
11519 arc_libm_function_max_error (unsigned cfn
, machine_mode mode
,
11522 #ifdef OPTION_GLIBC
11523 bool glibc_p
= OPTION_GLIBC
;
11525 bool glibc_p
= false;
11529 int rnd
= flag_rounding_math
? 4 : 0;
11534 if (!boundary_p
&& mode
== DFmode
)
11539 if (!boundary_p
&& mode
== DFmode
)
11544 return glibc_linux_libm_function_max_error (cfn
, mode
, boundary_p
);
11546 return default_libm_function_max_error (cfn
, mode
, boundary_p
);
11549 #undef TARGET_USE_ANCHORS_FOR_SYMBOL_P
11550 #define TARGET_USE_ANCHORS_FOR_SYMBOL_P arc_use_anchors_for_symbol_p
11552 #undef TARGET_CONSTANT_ALIGNMENT
11553 #define TARGET_CONSTANT_ALIGNMENT constant_alignment_word_strings
11555 #undef TARGET_CANNOT_SUBSTITUTE_MEM_EQUIV_P
11556 #define TARGET_CANNOT_SUBSTITUTE_MEM_EQUIV_P arc_cannot_substitute_mem_equiv_p
11558 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
11559 #define TARGET_ASM_TRAMPOLINE_TEMPLATE arc_asm_trampoline_template
11561 #undef TARGET_HAVE_SPECULATION_SAFE_VALUE
11562 #define TARGET_HAVE_SPECULATION_SAFE_VALUE speculation_safe_value_not_needed
11564 #undef TARGET_REGISTER_MOVE_COST
11565 #define TARGET_REGISTER_MOVE_COST arc_register_move_cost
11567 #undef TARGET_MEMORY_MOVE_COST
11568 #define TARGET_MEMORY_MOVE_COST arc_memory_move_cost
11570 #undef TARGET_INSN_COST
11571 #define TARGET_INSN_COST arc_insn_cost
11573 #undef TARGET_LIBM_FUNCTION_MAX_ERROR
11574 #define TARGET_LIBM_FUNCTION_MAX_ERROR arc_libm_function_max_error
11576 #undef TARGET_DOCUMENTATION_NAME
11577 #define TARGET_DOCUMENTATION_NAME "ARC"
11579 struct gcc_target targetm
= TARGET_INITIALIZER
;
11581 #include "gt-arc.h"