1 /* Subroutines used for code generation on the Synopsys DesignWare ARC cpu.
2 Copyright (C) 1994-2014 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/>. */
33 #include "coretypes.h"
37 #include "stor-layout.h"
38 #include "stringpool.h"
42 #include "hard-reg-set.h"
44 #include "insn-config.h"
45 #include "conditions.h"
46 #include "insn-flags.h"
53 #include "insn-attr.h"
58 #include "diagnostic.h"
59 #include "insn-codes.h"
60 #include "langhooks.h"
62 #include "tm-constrs.h"
63 #include "reload.h" /* For operands_match_p */
65 #include "tree-pass.h"
67 #include "pass_manager.h"
71 /* Which cpu we're compiling for (A5, ARC600, ARC601, ARC700). */
72 static const char *arc_cpu_string
= "";
74 /* ??? Loads can handle any constant, stores can only handle small ones. */
75 /* OTOH, LIMMs cost extra, so their usefulness is limited. */
76 #define RTX_OK_FOR_OFFSET_P(MODE, X) \
77 (GET_CODE (X) == CONST_INT \
78 && SMALL_INT_RANGE (INTVAL (X), (GET_MODE_SIZE (MODE) - 1) & -4, \
79 (INTVAL (X) & (GET_MODE_SIZE (MODE) - 1) & 3 \
81 : -(-GET_MODE_SIZE (MODE) | -4) >> 1)))
83 #define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X, INDEX, STRICT) \
84 (GET_CODE (X) == PLUS \
85 && RTX_OK_FOR_BASE_P (XEXP (X, 0), (STRICT)) \
86 && ((INDEX && RTX_OK_FOR_INDEX_P (XEXP (X, 1), (STRICT)) \
87 && GET_MODE_SIZE ((MODE)) <= 4) \
88 || RTX_OK_FOR_OFFSET_P (MODE, XEXP (X, 1))))
90 #define LEGITIMATE_SCALED_ADDRESS_P(MODE, X, STRICT) \
91 (GET_CODE (X) == PLUS \
92 && GET_CODE (XEXP (X, 0)) == MULT \
93 && RTX_OK_FOR_INDEX_P (XEXP (XEXP (X, 0), 0), (STRICT)) \
94 && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \
95 && ((GET_MODE_SIZE (MODE) == 2 && INTVAL (XEXP (XEXP (X, 0), 1)) == 2) \
96 || (GET_MODE_SIZE (MODE) == 4 && INTVAL (XEXP (XEXP (X, 0), 1)) == 4)) \
97 && (RTX_OK_FOR_BASE_P (XEXP (X, 1), (STRICT)) \
98 || (flag_pic ? CONST_INT_P (XEXP (X, 1)) : CONSTANT_P (XEXP (X, 1)))))
100 #define LEGITIMATE_SMALL_DATA_ADDRESS_P(X) \
101 (GET_CODE (X) == PLUS \
102 && (REG_P (XEXP ((X), 0)) && REGNO (XEXP ((X), 0)) == SDATA_BASE_REGNUM) \
103 && ((GET_CODE (XEXP((X),1)) == SYMBOL_REF \
104 && SYMBOL_REF_SMALL_P (XEXP ((X), 1))) \
105 || (GET_CODE (XEXP ((X), 1)) == CONST \
106 && GET_CODE (XEXP (XEXP ((X), 1), 0)) == PLUS \
107 && GET_CODE (XEXP (XEXP (XEXP ((X), 1), 0), 0)) == SYMBOL_REF \
108 && SYMBOL_REF_SMALL_P (XEXP (XEXP (XEXP ((X), 1), 0), 0)) \
109 && GET_CODE (XEXP(XEXP (XEXP ((X), 1), 0), 1)) == CONST_INT)))
111 /* Array of valid operand punctuation characters. */
112 char arc_punct_chars
[256];
114 /* State used by arc_ccfsm_advance to implement conditional execution. */
115 struct GTY (()) arc_ccfsm
124 #define arc_ccfsm_current cfun->machine->ccfsm_current
126 #define ARC_CCFSM_BRANCH_DELETED_P(STATE) \
127 ((STATE)->state == 1 || (STATE)->state == 2)
129 /* Indicate we're conditionalizing insns now. */
130 #define ARC_CCFSM_RECORD_BRANCH_DELETED(STATE) \
131 ((STATE)->state += 2)
133 #define ARC_CCFSM_COND_EXEC_P(STATE) \
134 ((STATE)->state == 3 || (STATE)->state == 4 || (STATE)->state == 5 \
135 || current_insn_predicate)
137 /* Check if INSN has a 16 bit opcode considering struct arc_ccfsm *STATE. */
138 #define CCFSM_ISCOMPACT(INSN,STATE) \
139 (ARC_CCFSM_COND_EXEC_P (STATE) \
140 ? (get_attr_iscompact (INSN) == ISCOMPACT_TRUE \
141 || get_attr_iscompact (INSN) == ISCOMPACT_TRUE_LIMM) \
142 : get_attr_iscompact (INSN) != ISCOMPACT_FALSE)
144 /* Likewise, but also consider that INSN might be in a delay slot of JUMP. */
145 #define CCFSM_DBR_ISCOMPACT(INSN,JUMP,STATE) \
146 ((ARC_CCFSM_COND_EXEC_P (STATE) \
148 && INSN_ANNULLED_BRANCH_P (JUMP) \
149 && (TARGET_AT_DBR_CONDEXEC || INSN_FROM_TARGET_P (INSN)))) \
150 ? (get_attr_iscompact (INSN) == ISCOMPACT_TRUE \
151 || get_attr_iscompact (INSN) == ISCOMPACT_TRUE_LIMM) \
152 : get_attr_iscompact (INSN) != ISCOMPACT_FALSE)
154 /* The maximum number of insns skipped which will be conditionalised if
156 /* When optimizing for speed:
157 Let p be the probability that the potentially skipped insns need to
158 be executed, pn the cost of a correctly predicted non-taken branch,
159 mt the cost of a mis/non-predicted taken branch,
160 mn mispredicted non-taken, pt correctly predicted taken ;
161 costs expressed in numbers of instructions like the ones considered
163 Unfortunately we don't have a measure of predictability - this
164 is linked to probability only in that in the no-eviction-scenario
165 there is a lower bound 1 - 2 * min (p, 1-p), and a somewhat larger
166 value that can be assumed *if* the distribution is perfectly random.
167 A predictability of 1 is perfectly plausible not matter what p is,
168 because the decision could be dependent on an invocation parameter
170 For large p, we want MAX_INSNS_SKIPPED == pn/(1-p) + mt - pn
171 For small p, we want MAX_INSNS_SKIPPED == pt
173 When optimizing for size:
174 We want to skip insn unless we could use 16 opcodes for the
175 non-conditionalized insn to balance the branch length or more.
176 Performance can be tie-breaker. */
177 /* If the potentially-skipped insns are likely to be executed, we'll
178 generally save one non-taken branch
180 this to be no less than the 1/p */
181 #define MAX_INSNS_SKIPPED 3
183 /* The values of unspec's first field. */
193 ARC_BUILTIN_NORM
= 3,
194 ARC_BUILTIN_NORMW
= 4,
195 ARC_BUILTIN_SWAP
= 5,
197 ARC_BUILTIN_DIVAW
= 7,
199 ARC_BUILTIN_MUL64
= 9,
200 ARC_BUILTIN_MULU64
= 10,
201 ARC_BUILTIN_RTIE
= 11,
202 ARC_BUILTIN_SYNC
= 12,
203 ARC_BUILTIN_CORE_READ
= 13,
204 ARC_BUILTIN_CORE_WRITE
= 14,
205 ARC_BUILTIN_FLAG
= 15,
208 ARC_BUILTIN_SLEEP
= 18,
209 ARC_BUILTIN_SWI
= 19,
210 ARC_BUILTIN_TRAP_S
= 20,
211 ARC_BUILTIN_UNIMP_S
= 21,
212 ARC_BUILTIN_ALIGNED
= 22,
214 /* Sentinel to mark start of simd builtins. */
215 ARC_SIMD_BUILTIN_BEGIN
= 1000,
217 ARC_SIMD_BUILTIN_VADDAW
= 1001,
218 ARC_SIMD_BUILTIN_VADDW
= 1002,
219 ARC_SIMD_BUILTIN_VAVB
= 1003,
220 ARC_SIMD_BUILTIN_VAVRB
= 1004,
221 ARC_SIMD_BUILTIN_VDIFAW
= 1005,
222 ARC_SIMD_BUILTIN_VDIFW
= 1006,
223 ARC_SIMD_BUILTIN_VMAXAW
= 1007,
224 ARC_SIMD_BUILTIN_VMAXW
= 1008,
225 ARC_SIMD_BUILTIN_VMINAW
= 1009,
226 ARC_SIMD_BUILTIN_VMINW
= 1010,
227 ARC_SIMD_BUILTIN_VMULAW
= 1011,
228 ARC_SIMD_BUILTIN_VMULFAW
= 1012,
229 ARC_SIMD_BUILTIN_VMULFW
= 1013,
230 ARC_SIMD_BUILTIN_VMULW
= 1014,
231 ARC_SIMD_BUILTIN_VSUBAW
= 1015,
232 ARC_SIMD_BUILTIN_VSUBW
= 1016,
233 ARC_SIMD_BUILTIN_VSUMMW
= 1017,
234 ARC_SIMD_BUILTIN_VAND
= 1018,
235 ARC_SIMD_BUILTIN_VANDAW
= 1019,
236 ARC_SIMD_BUILTIN_VBIC
= 1020,
237 ARC_SIMD_BUILTIN_VBICAW
= 1021,
238 ARC_SIMD_BUILTIN_VOR
= 1022,
239 ARC_SIMD_BUILTIN_VXOR
= 1023,
240 ARC_SIMD_BUILTIN_VXORAW
= 1024,
241 ARC_SIMD_BUILTIN_VEQW
= 1025,
242 ARC_SIMD_BUILTIN_VLEW
= 1026,
243 ARC_SIMD_BUILTIN_VLTW
= 1027,
244 ARC_SIMD_BUILTIN_VNEW
= 1028,
245 ARC_SIMD_BUILTIN_VMR1AW
= 1029,
246 ARC_SIMD_BUILTIN_VMR1W
= 1030,
247 ARC_SIMD_BUILTIN_VMR2AW
= 1031,
248 ARC_SIMD_BUILTIN_VMR2W
= 1032,
249 ARC_SIMD_BUILTIN_VMR3AW
= 1033,
250 ARC_SIMD_BUILTIN_VMR3W
= 1034,
251 ARC_SIMD_BUILTIN_VMR4AW
= 1035,
252 ARC_SIMD_BUILTIN_VMR4W
= 1036,
253 ARC_SIMD_BUILTIN_VMR5AW
= 1037,
254 ARC_SIMD_BUILTIN_VMR5W
= 1038,
255 ARC_SIMD_BUILTIN_VMR6AW
= 1039,
256 ARC_SIMD_BUILTIN_VMR6W
= 1040,
257 ARC_SIMD_BUILTIN_VMR7AW
= 1041,
258 ARC_SIMD_BUILTIN_VMR7W
= 1042,
259 ARC_SIMD_BUILTIN_VMRB
= 1043,
260 ARC_SIMD_BUILTIN_VH264F
= 1044,
261 ARC_SIMD_BUILTIN_VH264FT
= 1045,
262 ARC_SIMD_BUILTIN_VH264FW
= 1046,
263 ARC_SIMD_BUILTIN_VVC1F
= 1047,
264 ARC_SIMD_BUILTIN_VVC1FT
= 1048,
266 /* Va, Vb, rlimm instructions. */
267 ARC_SIMD_BUILTIN_VBADDW
= 1050,
268 ARC_SIMD_BUILTIN_VBMAXW
= 1051,
269 ARC_SIMD_BUILTIN_VBMINW
= 1052,
270 ARC_SIMD_BUILTIN_VBMULAW
= 1053,
271 ARC_SIMD_BUILTIN_VBMULFW
= 1054,
272 ARC_SIMD_BUILTIN_VBMULW
= 1055,
273 ARC_SIMD_BUILTIN_VBRSUBW
= 1056,
274 ARC_SIMD_BUILTIN_VBSUBW
= 1057,
276 /* Va, Vb, Ic instructions. */
277 ARC_SIMD_BUILTIN_VASRW
= 1060,
278 ARC_SIMD_BUILTIN_VSR8
= 1061,
279 ARC_SIMD_BUILTIN_VSR8AW
= 1062,
281 /* Va, Vb, u6 instructions. */
282 ARC_SIMD_BUILTIN_VASRRWi
= 1065,
283 ARC_SIMD_BUILTIN_VASRSRWi
= 1066,
284 ARC_SIMD_BUILTIN_VASRWi
= 1067,
285 ARC_SIMD_BUILTIN_VASRPWBi
= 1068,
286 ARC_SIMD_BUILTIN_VASRRPWBi
= 1069,
287 ARC_SIMD_BUILTIN_VSR8AWi
= 1070,
288 ARC_SIMD_BUILTIN_VSR8i
= 1071,
290 /* Va, Vb, u8 (simm) instructions. */
291 ARC_SIMD_BUILTIN_VMVAW
= 1075,
292 ARC_SIMD_BUILTIN_VMVW
= 1076,
293 ARC_SIMD_BUILTIN_VMVZW
= 1077,
294 ARC_SIMD_BUILTIN_VD6TAPF
= 1078,
296 /* Va, rlimm, u8 (simm) instructions. */
297 ARC_SIMD_BUILTIN_VMOVAW
= 1080,
298 ARC_SIMD_BUILTIN_VMOVW
= 1081,
299 ARC_SIMD_BUILTIN_VMOVZW
= 1082,
301 /* Va, Vb instructions. */
302 ARC_SIMD_BUILTIN_VABSAW
= 1085,
303 ARC_SIMD_BUILTIN_VABSW
= 1086,
304 ARC_SIMD_BUILTIN_VADDSUW
= 1087,
305 ARC_SIMD_BUILTIN_VSIGNW
= 1088,
306 ARC_SIMD_BUILTIN_VEXCH1
= 1089,
307 ARC_SIMD_BUILTIN_VEXCH2
= 1090,
308 ARC_SIMD_BUILTIN_VEXCH4
= 1091,
309 ARC_SIMD_BUILTIN_VUPBAW
= 1092,
310 ARC_SIMD_BUILTIN_VUPBW
= 1093,
311 ARC_SIMD_BUILTIN_VUPSBAW
= 1094,
312 ARC_SIMD_BUILTIN_VUPSBW
= 1095,
314 ARC_SIMD_BUILTIN_VDIRUN
= 1100,
315 ARC_SIMD_BUILTIN_VDORUN
= 1101,
316 ARC_SIMD_BUILTIN_VDIWR
= 1102,
317 ARC_SIMD_BUILTIN_VDOWR
= 1103,
319 ARC_SIMD_BUILTIN_VREC
= 1105,
320 ARC_SIMD_BUILTIN_VRUN
= 1106,
321 ARC_SIMD_BUILTIN_VRECRUN
= 1107,
322 ARC_SIMD_BUILTIN_VENDREC
= 1108,
324 ARC_SIMD_BUILTIN_VLD32WH
= 1110,
325 ARC_SIMD_BUILTIN_VLD32WL
= 1111,
326 ARC_SIMD_BUILTIN_VLD64
= 1112,
327 ARC_SIMD_BUILTIN_VLD32
= 1113,
328 ARC_SIMD_BUILTIN_VLD64W
= 1114,
329 ARC_SIMD_BUILTIN_VLD128
= 1115,
330 ARC_SIMD_BUILTIN_VST128
= 1116,
331 ARC_SIMD_BUILTIN_VST64
= 1117,
333 ARC_SIMD_BUILTIN_VST16_N
= 1120,
334 ARC_SIMD_BUILTIN_VST32_N
= 1121,
336 ARC_SIMD_BUILTIN_VINTI
= 1201,
341 /* A nop is needed between a 4 byte insn that sets the condition codes and
342 a branch that uses them (the same isn't true for an 8 byte insn that sets
343 the condition codes). Set by arc_ccfsm_advance. Used by
344 arc_print_operand. */
346 static int get_arc_condition_code (rtx
);
348 static tree
arc_handle_interrupt_attribute (tree
*, tree
, tree
, int, bool *);
350 /* Initialized arc_attribute_table to NULL since arc doesnot have any
351 machine specific supported attributes. */
352 const struct attribute_spec arc_attribute_table
[] =
354 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
355 affects_type_identity } */
356 { "interrupt", 1, 1, true, false, false, arc_handle_interrupt_attribute
, true },
357 /* Function calls made to this symbol must be done indirectly, because
358 it may lie outside of the 21/25 bit addressing range of a normal function
360 { "long_call", 0, 0, false, true, true, NULL
, false },
361 /* Whereas these functions are always known to reside within the 25 bit
362 addressing range of unconditionalized bl. */
363 { "medium_call", 0, 0, false, true, true, NULL
, false },
364 /* And these functions are always known to reside within the 21 bit
365 addressing range of blcc. */
366 { "short_call", 0, 0, false, true, true, NULL
, false },
367 { NULL
, 0, 0, false, false, false, NULL
, false }
369 static int arc_comp_type_attributes (const_tree
, const_tree
);
370 static void arc_file_start (void);
371 static void arc_internal_label (FILE *, const char *, unsigned long);
372 static void arc_output_mi_thunk (FILE *, tree
, HOST_WIDE_INT
, HOST_WIDE_INT
,
374 static int arc_address_cost (rtx
, enum machine_mode
, addr_space_t
, bool);
375 static void arc_encode_section_info (tree decl
, rtx rtl
, int first
);
377 static void arc_init_builtins (void);
378 static rtx
arc_expand_builtin (tree
, rtx
, rtx
, enum machine_mode
, int);
380 static int branch_dest (rtx
);
382 static void arc_output_pic_addr_const (FILE *, rtx
, int);
383 void emit_pic_move (rtx
*, enum machine_mode
);
384 bool arc_legitimate_pic_operand_p (rtx
);
385 static bool arc_function_ok_for_sibcall (tree
, tree
);
386 static rtx
arc_function_value (const_tree
, const_tree
, bool);
387 const char * output_shift (rtx
*);
388 static void arc_reorg (void);
389 static bool arc_in_small_data_p (const_tree
);
391 static void arc_init_reg_tables (void);
392 static bool arc_return_in_memory (const_tree
, const_tree
);
393 static void arc_init_simd_builtins (void);
394 static bool arc_vector_mode_supported_p (enum machine_mode
);
396 static bool arc_can_use_doloop_p (const widest_int
&, const widest_int
&,
398 static const char *arc_invalid_within_doloop (const_rtx
);
400 static void output_short_suffix (FILE *file
);
402 static bool arc_frame_pointer_required (void);
404 /* Implements target hook vector_mode_supported_p. */
407 arc_vector_mode_supported_p (enum machine_mode mode
)
409 if (!TARGET_SIMD_SET
)
412 if ((mode
== V4SImode
)
413 || (mode
== V8HImode
))
420 /* TARGET_PRESERVE_RELOAD_P is still awaiting patch re-evaluation / review. */
421 static bool arc_preserve_reload_p (rtx in
) ATTRIBUTE_UNUSED
;
422 static rtx
arc_delegitimize_address (rtx
);
423 static bool arc_can_follow_jump (const_rtx follower
, const_rtx followee
);
425 static rtx
frame_insn (rtx
);
426 static void arc_function_arg_advance (cumulative_args_t
, enum machine_mode
,
428 static rtx
arc_legitimize_address_0 (rtx
, rtx
, enum machine_mode mode
);
430 static void arc_finalize_pic (void);
432 /* initialize the GCC target structure. */
433 #undef TARGET_COMP_TYPE_ATTRIBUTES
434 #define TARGET_COMP_TYPE_ATTRIBUTES arc_comp_type_attributes
435 #undef TARGET_ASM_FILE_START
436 #define TARGET_ASM_FILE_START arc_file_start
437 #undef TARGET_ATTRIBUTE_TABLE
438 #define TARGET_ATTRIBUTE_TABLE arc_attribute_table
439 #undef TARGET_ASM_INTERNAL_LABEL
440 #define TARGET_ASM_INTERNAL_LABEL arc_internal_label
441 #undef TARGET_RTX_COSTS
442 #define TARGET_RTX_COSTS arc_rtx_costs
443 #undef TARGET_ADDRESS_COST
444 #define TARGET_ADDRESS_COST arc_address_cost
446 #undef TARGET_ENCODE_SECTION_INFO
447 #define TARGET_ENCODE_SECTION_INFO arc_encode_section_info
449 #undef TARGET_CANNOT_FORCE_CONST_MEM
450 #define TARGET_CANNOT_FORCE_CONST_MEM arc_cannot_force_const_mem
452 #undef TARGET_INIT_BUILTINS
453 #define TARGET_INIT_BUILTINS arc_init_builtins
455 #undef TARGET_EXPAND_BUILTIN
456 #define TARGET_EXPAND_BUILTIN arc_expand_builtin
458 #undef TARGET_ASM_OUTPUT_MI_THUNK
459 #define TARGET_ASM_OUTPUT_MI_THUNK arc_output_mi_thunk
461 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
462 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
464 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
465 #define TARGET_FUNCTION_OK_FOR_SIBCALL arc_function_ok_for_sibcall
467 #undef TARGET_MACHINE_DEPENDENT_REORG
468 #define TARGET_MACHINE_DEPENDENT_REORG arc_reorg
470 #undef TARGET_IN_SMALL_DATA_P
471 #define TARGET_IN_SMALL_DATA_P arc_in_small_data_p
473 #undef TARGET_PROMOTE_FUNCTION_MODE
474 #define TARGET_PROMOTE_FUNCTION_MODE \
475 default_promote_function_mode_always_promote
477 #undef TARGET_PROMOTE_PROTOTYPES
478 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
480 #undef TARGET_RETURN_IN_MEMORY
481 #define TARGET_RETURN_IN_MEMORY arc_return_in_memory
482 #undef TARGET_PASS_BY_REFERENCE
483 #define TARGET_PASS_BY_REFERENCE arc_pass_by_reference
485 #undef TARGET_SETUP_INCOMING_VARARGS
486 #define TARGET_SETUP_INCOMING_VARARGS arc_setup_incoming_varargs
488 #undef TARGET_ARG_PARTIAL_BYTES
489 #define TARGET_ARG_PARTIAL_BYTES arc_arg_partial_bytes
491 #undef TARGET_MUST_PASS_IN_STACK
492 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
494 #undef TARGET_FUNCTION_VALUE
495 #define TARGET_FUNCTION_VALUE arc_function_value
497 #undef TARGET_SCHED_ADJUST_PRIORITY
498 #define TARGET_SCHED_ADJUST_PRIORITY arc_sched_adjust_priority
500 #undef TARGET_VECTOR_MODE_SUPPORTED_P
501 #define TARGET_VECTOR_MODE_SUPPORTED_P arc_vector_mode_supported_p
503 #undef TARGET_CAN_USE_DOLOOP_P
504 #define TARGET_CAN_USE_DOLOOP_P arc_can_use_doloop_p
506 #undef TARGET_INVALID_WITHIN_DOLOOP
507 #define TARGET_INVALID_WITHIN_DOLOOP arc_invalid_within_doloop
509 #undef TARGET_PRESERVE_RELOAD_P
510 #define TARGET_PRESERVE_RELOAD_P arc_preserve_reload_p
512 #undef TARGET_CAN_FOLLOW_JUMP
513 #define TARGET_CAN_FOLLOW_JUMP arc_can_follow_jump
515 #undef TARGET_DELEGITIMIZE_ADDRESS
516 #define TARGET_DELEGITIMIZE_ADDRESS arc_delegitimize_address
518 /* Usually, we will be able to scale anchor offsets.
519 When this fails, we want LEGITIMIZE_ADDRESS to kick in. */
520 #undef TARGET_MIN_ANCHOR_OFFSET
521 #define TARGET_MIN_ANCHOR_OFFSET (-1024)
522 #undef TARGET_MAX_ANCHOR_OFFSET
523 #define TARGET_MAX_ANCHOR_OFFSET (1020)
525 #undef TARGET_SECONDARY_RELOAD
526 #define TARGET_SECONDARY_RELOAD arc_secondary_reload
528 #define TARGET_OPTION_OVERRIDE arc_override_options
530 #define TARGET_CONDITIONAL_REGISTER_USAGE arc_conditional_register_usage
532 #define TARGET_TRAMPOLINE_INIT arc_initialize_trampoline
534 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS arc_trampoline_adjust_address
536 #define TARGET_CAN_ELIMINATE arc_can_eliminate
538 #define TARGET_FRAME_POINTER_REQUIRED arc_frame_pointer_required
540 #define TARGET_FUNCTION_ARG arc_function_arg
542 #define TARGET_FUNCTION_ARG_ADVANCE arc_function_arg_advance
544 #define TARGET_LEGITIMATE_CONSTANT_P arc_legitimate_constant_p
546 #define TARGET_LEGITIMATE_ADDRESS_P arc_legitimate_address_p
548 #define TARGET_MODE_DEPENDENT_ADDRESS_P arc_mode_dependent_address_p
550 #define TARGET_LEGITIMIZE_ADDRESS arc_legitimize_address
552 #define TARGET_ADJUST_INSN_LENGTH arc_adjust_insn_length
554 #define TARGET_INSN_LENGTH_PARAMETERS arc_insn_length_parameters
557 #define TARGET_LRA_P arc_lra_p
558 #define TARGET_REGISTER_PRIORITY arc_register_priority
559 /* Stores with scaled offsets have different displacement ranges. */
560 #define TARGET_DIFFERENT_ADDR_DISPLACEMENT_P hook_bool_void_true
561 #define TARGET_SPILL_CLASS arc_spill_class
563 #include "target-def.h"
565 #undef TARGET_ASM_ALIGNED_HI_OP
566 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
567 #undef TARGET_ASM_ALIGNED_SI_OP
568 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
570 /* Try to keep the (mov:DF _, reg) as early as possible so
571 that the d<add/sub/mul>h-lr insns appear together and can
572 use the peephole2 pattern. */
575 arc_sched_adjust_priority (rtx insn
, int priority
)
577 rtx set
= single_set (insn
);
579 && GET_MODE (SET_SRC(set
)) == DFmode
580 && GET_CODE (SET_SRC(set
)) == REG
)
582 /* Incrementing priority by 20 (empirically derived). */
583 return priority
+ 20;
590 arc_secondary_reload (bool in_p
, rtx x
, reg_class_t cl
, enum machine_mode
,
591 secondary_reload_info
*)
593 if (cl
== DOUBLE_REGS
)
596 /* The loop counter register can be stored, but not loaded directly. */
597 if ((cl
== LPCOUNT_REG
|| cl
== WRITABLE_CORE_REGS
)
598 && in_p
&& MEM_P (x
))
603 static unsigned arc_ifcvt (void);
607 const pass_data pass_data_arc_ifcvt
=
610 "arc_ifcvt", /* name */
611 OPTGROUP_NONE
, /* optinfo_flags */
612 TV_IFCVT2
, /* tv_id */
613 0, /* properties_required */
614 0, /* properties_provided */
615 0, /* properties_destroyed */
616 0, /* todo_flags_start */
617 TODO_df_finish
/* todo_flags_finish */
620 class pass_arc_ifcvt
: public rtl_opt_pass
623 pass_arc_ifcvt(gcc::context
*ctxt
)
624 : rtl_opt_pass(pass_data_arc_ifcvt
, ctxt
)
627 /* opt_pass methods: */
628 opt_pass
* clone () { return new pass_arc_ifcvt (m_ctxt
); }
629 virtual unsigned int execute (function
*) { return arc_ifcvt (); }
635 make_pass_arc_ifcvt (gcc::context
*ctxt
)
637 return new pass_arc_ifcvt (ctxt
);
640 static unsigned arc_predicate_delay_insns (void);
644 const pass_data pass_data_arc_predicate_delay_insns
=
647 "arc_predicate_delay_insns", /* name */
648 OPTGROUP_NONE
, /* optinfo_flags */
649 TV_IFCVT2
, /* tv_id */
650 0, /* properties_required */
651 0, /* properties_provided */
652 0, /* properties_destroyed */
653 0, /* todo_flags_start */
654 TODO_df_finish
/* todo_flags_finish */
657 class pass_arc_predicate_delay_insns
: public rtl_opt_pass
660 pass_arc_predicate_delay_insns(gcc::context
*ctxt
)
661 : rtl_opt_pass(pass_data_arc_predicate_delay_insns
, ctxt
)
664 /* opt_pass methods: */
665 virtual unsigned int execute (function
*)
667 return arc_predicate_delay_insns ();
674 make_pass_arc_predicate_delay_insns (gcc::context
*ctxt
)
676 return new pass_arc_predicate_delay_insns (ctxt
);
679 /* Called by OVERRIDE_OPTIONS to initialize various things. */
684 enum attr_tune tune_dflt
= TUNE_NONE
;
688 arc_cpu_string
= "A5";
690 else if (TARGET_ARC600
)
692 arc_cpu_string
= "ARC600";
693 tune_dflt
= TUNE_ARC600
;
695 else if (TARGET_ARC601
)
697 arc_cpu_string
= "ARC601";
698 tune_dflt
= TUNE_ARC600
;
700 else if (TARGET_ARC700
)
702 arc_cpu_string
= "ARC700";
703 tune_dflt
= TUNE_ARC700_4_2_STD
;
707 if (arc_tune
== TUNE_NONE
)
708 arc_tune
= tune_dflt
;
709 /* Note: arc_multcost is only used in rtx_cost if speed is true. */
710 if (arc_multcost
< 0)
713 case TUNE_ARC700_4_2_STD
:
715 max throughput (1 multiply + 4 other insns) / 5 cycles. */
716 arc_multcost
= COSTS_N_INSNS (4);
717 if (TARGET_NOMPY_SET
)
718 arc_multcost
= COSTS_N_INSNS (30);
720 case TUNE_ARC700_4_2_XMAC
:
722 max throughput (1 multiply + 2 other insns) / 3 cycles. */
723 arc_multcost
= COSTS_N_INSNS (3);
724 if (TARGET_NOMPY_SET
)
725 arc_multcost
= COSTS_N_INSNS (30);
728 if (TARGET_MUL64_SET
)
730 arc_multcost
= COSTS_N_INSNS (4);
735 arc_multcost
= COSTS_N_INSNS (30);
739 /* Support mul64 generation only for A5 and ARC600. */
740 if (TARGET_MUL64_SET
&& TARGET_ARC700
)
741 error ("-mmul64 not supported for ARC700");
743 /* MPY instructions valid only for ARC700. */
744 if (TARGET_NOMPY_SET
&& !TARGET_ARC700
)
745 error ("-mno-mpy supported only for ARC700");
747 /* mul/mac instructions only for ARC600. */
748 if (TARGET_MULMAC_32BY16_SET
&& !(TARGET_ARC600
|| TARGET_ARC601
))
749 error ("-mmul32x16 supported only for ARC600 or ARC601");
751 if (!TARGET_DPFP
&& TARGET_DPFP_DISABLE_LRSR
)
752 error ("-mno-dpfp-lrsr supported only with -mdpfp");
754 /* FPX-1. No fast and compact together. */
755 if ((TARGET_DPFP_FAST_SET
&& TARGET_DPFP_COMPACT_SET
)
756 || (TARGET_SPFP_FAST_SET
&& TARGET_SPFP_COMPACT_SET
))
757 error ("FPX fast and compact options cannot be specified together");
759 /* FPX-2. No fast-spfp for arc600 or arc601. */
760 if (TARGET_SPFP_FAST_SET
&& (TARGET_ARC600
|| TARGET_ARC601
))
761 error ("-mspfp_fast not available on ARC600 or ARC601");
763 /* FPX-3. No FPX extensions on pre-ARC600 cores. */
764 if ((TARGET_DPFP
|| TARGET_SPFP
)
765 && !(TARGET_ARC600
|| TARGET_ARC601
|| TARGET_ARC700
))
766 error ("FPX extensions not available on pre-ARC600 cores");
768 /* Warn for unimplemented PIC in pre-ARC700 cores, and disable flag_pic. */
769 if (flag_pic
&& !TARGET_ARC700
)
771 warning (DK_WARNING
, "PIC is not supported for %s. Generating non-PIC code only..", arc_cpu_string
);
775 arc_init_reg_tables ();
777 /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P. */
778 memset (arc_punct_chars
, 0, sizeof (arc_punct_chars
));
779 arc_punct_chars
['#'] = 1;
780 arc_punct_chars
['*'] = 1;
781 arc_punct_chars
['?'] = 1;
782 arc_punct_chars
['!'] = 1;
783 arc_punct_chars
['^'] = 1;
784 arc_punct_chars
['&'] = 1;
786 if (optimize
> 1 && !TARGET_NO_COND_EXEC
)
788 /* There are two target-independent ifcvt passes, and arc_reorg may do
789 one or more arc_ifcvt calls. */
790 opt_pass
*pass_arc_ifcvt_4
= make_pass_arc_ifcvt (g
);
791 struct register_pass_info arc_ifcvt4_info
792 = { pass_arc_ifcvt_4
, "dbr", 1, PASS_POS_INSERT_AFTER
};
793 struct register_pass_info arc_ifcvt5_info
794 = { pass_arc_ifcvt_4
->clone (), "shorten", 1, PASS_POS_INSERT_BEFORE
};
796 register_pass (&arc_ifcvt4_info
);
797 register_pass (&arc_ifcvt5_info
);
800 if (flag_delayed_branch
)
802 opt_pass
*pass_arc_predicate_delay_insns
803 = make_pass_arc_predicate_delay_insns (g
);
804 struct register_pass_info arc_predicate_delay_info
805 = { pass_arc_predicate_delay_insns
, "dbr", 1, PASS_POS_INSERT_AFTER
};
807 register_pass (&arc_predicate_delay_info
);
811 /* Check ARC options, generate derived target attributes. */
814 arc_override_options (void)
816 if (arc_cpu
== PROCESSOR_NONE
)
817 arc_cpu
= PROCESSOR_ARC700
;
819 if (arc_size_opt_level
== 3)
823 target_flags
|= MASK_NO_SDATA_SET
;
825 if (flag_no_common
== 255)
826 flag_no_common
= !TARGET_NO_SDATA_SET
;
828 /* TARGET_COMPACT_CASESI needs the "q" register class. */ \
829 if (TARGET_MIXED_CODE
)
832 TARGET_COMPACT_CASESI
= 0;
833 if (TARGET_COMPACT_CASESI
)
834 TARGET_CASE_VECTOR_PC_RELATIVE
= 1;
836 /* These need to be done at start up. It's convenient to do them here. */
840 /* The condition codes of the ARC, and the inverse function. */
841 /* For short branches, the "c" / "nc" names are not defined in the ARC
842 Programmers manual, so we have to use "lo" / "hs"" instead. */
843 static const char *arc_condition_codes
[] =
845 "al", 0, "eq", "ne", "p", "n", "lo", "hs", "v", "nv",
846 "gt", "le", "ge", "lt", "hi", "ls", "pnz", 0
849 enum arc_cc_code_index
851 ARC_CC_AL
, ARC_CC_EQ
= ARC_CC_AL
+2, ARC_CC_NE
, ARC_CC_P
, ARC_CC_N
,
852 ARC_CC_C
, ARC_CC_NC
, ARC_CC_V
, ARC_CC_NV
,
853 ARC_CC_GT
, ARC_CC_LE
, ARC_CC_GE
, ARC_CC_LT
, ARC_CC_HI
, ARC_CC_LS
, ARC_CC_PNZ
,
854 ARC_CC_LO
= ARC_CC_C
, ARC_CC_HS
= ARC_CC_NC
857 #define ARC_INVERSE_CONDITION_CODE(X) ((X) ^ 1)
859 /* Returns the index of the ARC condition code string in
860 `arc_condition_codes'. COMPARISON should be an rtx like
861 `(eq (...) (...))'. */
864 get_arc_condition_code (rtx comparison
)
866 switch (GET_MODE (XEXP (comparison
, 0)))
869 case SImode
: /* For BRcc. */
870 switch (GET_CODE (comparison
))
872 case EQ
: return ARC_CC_EQ
;
873 case NE
: return ARC_CC_NE
;
874 case GT
: return ARC_CC_GT
;
875 case LE
: return ARC_CC_LE
;
876 case GE
: return ARC_CC_GE
;
877 case LT
: return ARC_CC_LT
;
878 case GTU
: return ARC_CC_HI
;
879 case LEU
: return ARC_CC_LS
;
880 case LTU
: return ARC_CC_LO
;
881 case GEU
: return ARC_CC_HS
;
882 default : gcc_unreachable ();
885 switch (GET_CODE (comparison
))
887 case EQ
: return ARC_CC_EQ
;
888 case NE
: return ARC_CC_NE
;
889 case GE
: return ARC_CC_P
;
890 case LT
: return ARC_CC_N
;
891 case GT
: return ARC_CC_PNZ
;
892 default : gcc_unreachable ();
895 switch (GET_CODE (comparison
))
897 case EQ
: return ARC_CC_EQ
;
898 case NE
: return ARC_CC_NE
;
899 default : gcc_unreachable ();
902 switch (GET_CODE (comparison
))
904 case LTU
: return ARC_CC_C
;
905 case GEU
: return ARC_CC_NC
;
906 default : gcc_unreachable ();
909 if (TARGET_ARGONAUT_SET
&& TARGET_SPFP
)
910 switch (GET_CODE (comparison
))
912 case GT
: return ARC_CC_N
;
913 case UNLE
: return ARC_CC_P
;
914 default : gcc_unreachable ();
917 switch (GET_CODE (comparison
))
919 case GT
: return ARC_CC_HI
;
920 case UNLE
: return ARC_CC_LS
;
921 default : gcc_unreachable ();
924 /* Same for FPX and non-FPX. */
925 switch (GET_CODE (comparison
))
927 case GE
: return ARC_CC_HS
;
928 case UNLT
: return ARC_CC_LO
;
929 default : gcc_unreachable ();
932 switch (GET_CODE (comparison
))
934 case UNEQ
: return ARC_CC_EQ
;
935 case LTGT
: return ARC_CC_NE
;
936 default : gcc_unreachable ();
939 switch (GET_CODE (comparison
))
941 case UNORDERED
: return ARC_CC_C
;
942 case ORDERED
: return ARC_CC_NC
;
943 default : gcc_unreachable ();
946 switch (GET_CODE (comparison
))
948 case EQ
: return ARC_CC_EQ
;
949 case NE
: return ARC_CC_NE
;
950 case UNORDERED
: return ARC_CC_C
;
951 case ORDERED
: return ARC_CC_NC
;
952 case LTGT
: return ARC_CC_HI
;
953 case UNEQ
: return ARC_CC_LS
;
954 default : gcc_unreachable ();
956 default : gcc_unreachable ();
962 /* Return true if COMPARISON has a short form that can accomodate OFFSET. */
965 arc_short_comparison_p (rtx comparison
, int offset
)
967 gcc_assert (ARC_CC_NC
== ARC_CC_HS
);
968 gcc_assert (ARC_CC_C
== ARC_CC_LO
);
969 switch (get_arc_condition_code (comparison
))
971 case ARC_CC_EQ
: case ARC_CC_NE
:
972 return offset
>= -512 && offset
<= 506;
973 case ARC_CC_GT
: case ARC_CC_LE
: case ARC_CC_GE
: case ARC_CC_LT
:
974 case ARC_CC_HI
: case ARC_CC_LS
: case ARC_CC_LO
: case ARC_CC_HS
:
975 return offset
>= -64 && offset
<= 58;
981 /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
982 return the mode to be used for the comparison. */
985 arc_select_cc_mode (enum rtx_code op
, rtx x
, rtx y
)
987 enum machine_mode mode
= GET_MODE (x
);
990 /* For an operation that sets the condition codes as a side-effect, the
991 C and V flags is not set as for cmp, so we can only use comparisons where
992 this doesn't matter. (For LT and GE we can use "mi" and "pl"
994 /* ??? We could use "pnz" for greater than zero, however, we could then
995 get into trouble because the comparison could not be reversed. */
996 if (GET_MODE_CLASS (mode
) == MODE_INT
998 && (op
== EQ
|| op
== NE
999 || ((op
== LT
|| op
== GE
) && GET_MODE_SIZE (GET_MODE (x
)) <= 4)))
1002 /* add.f for if (a+b) */
1004 && GET_CODE (y
) == NEG
1005 && (op
== EQ
|| op
== NE
))
1008 /* Check if this is a test suitable for bxor.f . */
1009 if (mode
== SImode
&& (op
== EQ
|| op
== NE
) && CONST_INT_P (y
)
1010 && ((INTVAL (y
) - 1) & INTVAL (y
)) == 0
1014 /* Check if this is a test suitable for add / bmsk.f . */
1015 if (mode
== SImode
&& (op
== EQ
|| op
== NE
) && CONST_INT_P (y
)
1016 && GET_CODE (x
) == AND
&& CONST_INT_P ((x1
= XEXP (x
, 1)))
1017 && ((INTVAL (x1
) + 1) & INTVAL (x1
)) == 0
1018 && (~INTVAL (x1
) | INTVAL (y
)) < 0
1019 && (~INTVAL (x1
) | INTVAL (y
)) > -0x800)
1022 if (GET_MODE (x
) == SImode
&& (op
== LTU
|| op
== GEU
)
1023 && GET_CODE (x
) == PLUS
1024 && (rtx_equal_p (XEXP (x
, 0), y
) || rtx_equal_p (XEXP (x
, 1), y
)))
1027 if (TARGET_ARGONAUT_SET
1028 && ((mode
== SFmode
&& TARGET_SPFP
) || (mode
== DFmode
&& TARGET_DPFP
)))
1031 case EQ
: case NE
: case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1033 case LT
: case UNGE
: case GT
: case UNLE
:
1034 return CC_FP_GTmode
;
1035 case LE
: case UNGT
: case GE
: case UNLT
:
1036 return CC_FP_GEmode
;
1037 default: gcc_unreachable ();
1039 else if (GET_MODE_CLASS (mode
) == MODE_FLOAT
&& TARGET_OPTFPE
)
1042 case EQ
: case NE
: return CC_Zmode
;
1044 case GT
: case UNLE
: return CC_FP_GTmode
;
1046 case GE
: case UNLT
: return CC_FP_GEmode
;
1047 case UNEQ
: case LTGT
: return CC_FP_UNEQmode
;
1048 case ORDERED
: case UNORDERED
: return CC_FP_ORDmode
;
1049 default: gcc_unreachable ();
1055 /* Vectors to keep interesting information about registers where it can easily
1056 be got. We use to use the actual mode value as the bit number, but there
1057 is (or may be) more than 32 modes now. Instead we use two tables: one
1058 indexed by hard register number, and one indexed by mode. */
1060 /* The purpose of arc_mode_class is to shrink the range of modes so that
1061 they all fit (as bit numbers) in a 32-bit word (again). Each real mode is
1062 mapped into one arc_mode_class mode. */
1064 enum arc_mode_class
{
1066 S_MODE
, D_MODE
, T_MODE
, O_MODE
,
1067 SF_MODE
, DF_MODE
, TF_MODE
, OF_MODE
,
1071 /* Modes for condition codes. */
1072 #define C_MODES (1 << (int) C_MODE)
1074 /* Modes for single-word and smaller quantities. */
1075 #define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
1077 /* Modes for double-word and smaller quantities. */
1078 #define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))
1080 /* Mode for 8-byte DF values only. */
1081 #define DF_MODES (1 << DF_MODE)
1083 /* Modes for quad-word and smaller quantities. */
1084 #define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE))
1086 /* Modes for 128-bit vectors. */
1087 #define V_MODES (1 << (int) V_MODE)
1089 /* Value is 1 if register/mode pair is acceptable on arc. */
1091 unsigned int arc_hard_regno_mode_ok
[] = {
1092 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
,
1093 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
,
1094 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, D_MODES
,
1095 D_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1097 /* ??? Leave these as S_MODES for now. */
1098 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1099 DF_MODES
, 0, DF_MODES
, 0, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1100 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1101 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, C_MODES
, S_MODES
,
1103 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1104 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1105 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1106 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1108 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1109 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1110 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1111 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1113 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1114 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
1117 unsigned int arc_mode_class
[NUM_MACHINE_MODES
];
1119 enum reg_class arc_regno_reg_class
[FIRST_PSEUDO_REGISTER
];
1122 arc_preferred_reload_class (rtx
, enum reg_class cl
)
1124 if ((cl
) == CHEAP_CORE_REGS
|| (cl
) == WRITABLE_CORE_REGS
)
1125 return GENERAL_REGS
;
1129 /* Initialize the arc_mode_class array. */
1132 arc_init_reg_tables (void)
1136 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
1138 enum machine_mode m
= (enum machine_mode
) i
;
1140 switch (GET_MODE_CLASS (m
))
1143 case MODE_PARTIAL_INT
:
1144 case MODE_COMPLEX_INT
:
1145 if (GET_MODE_SIZE (m
) <= 4)
1146 arc_mode_class
[i
] = 1 << (int) S_MODE
;
1147 else if (GET_MODE_SIZE (m
) == 8)
1148 arc_mode_class
[i
] = 1 << (int) D_MODE
;
1149 else if (GET_MODE_SIZE (m
) == 16)
1150 arc_mode_class
[i
] = 1 << (int) T_MODE
;
1151 else if (GET_MODE_SIZE (m
) == 32)
1152 arc_mode_class
[i
] = 1 << (int) O_MODE
;
1154 arc_mode_class
[i
] = 0;
1157 case MODE_COMPLEX_FLOAT
:
1158 if (GET_MODE_SIZE (m
) <= 4)
1159 arc_mode_class
[i
] = 1 << (int) SF_MODE
;
1160 else if (GET_MODE_SIZE (m
) == 8)
1161 arc_mode_class
[i
] = 1 << (int) DF_MODE
;
1162 else if (GET_MODE_SIZE (m
) == 16)
1163 arc_mode_class
[i
] = 1 << (int) TF_MODE
;
1164 else if (GET_MODE_SIZE (m
) == 32)
1165 arc_mode_class
[i
] = 1 << (int) OF_MODE
;
1167 arc_mode_class
[i
] = 0;
1169 case MODE_VECTOR_INT
:
1170 arc_mode_class
[i
] = (1<< (int) V_MODE
);
1174 /* mode_class hasn't been initialized yet for EXTRA_CC_MODES, so
1175 we must explicitly check for them here. */
1176 if (i
== (int) CCmode
|| i
== (int) CC_ZNmode
|| i
== (int) CC_Zmode
1177 || i
== (int) CC_Cmode
1178 || i
== CC_FP_GTmode
|| i
== CC_FP_GEmode
|| i
== CC_FP_ORDmode
)
1179 arc_mode_class
[i
] = 1 << (int) C_MODE
;
1181 arc_mode_class
[i
] = 0;
1187 /* Core registers 56..59 are used for multiply extension options.
1188 The dsp option uses r56 and r57, these are then named acc1 and acc2.
1189 acc1 is the highpart, and acc2 the lowpart, so which register gets which
1190 number depends on endianness.
1191 The mul64 multiplier options use r57 for mlo, r58 for mmid and r59 for mhi.
1192 Because mlo / mhi form a 64 bit value, we use different gcc internal
1193 register numbers to make them form a register pair as the gcc internals
1194 know it. mmid gets number 57, if still available, and mlo / mhi get
1195 number 58 and 59, depending on endianness. We use DBX_REGISTER_NUMBER
1196 to map this back. */
1197 char rname56
[5] = "r56";
1198 char rname57
[5] = "r57";
1199 char rname58
[5] = "r58";
1200 char rname59
[5] = "r59";
1203 arc_conditional_register_usage (void)
1207 int fix_start
= 60, fix_end
= 55;
1209 if (TARGET_MUL64_SET
)
1214 /* We don't provide a name for mmed. In rtl / assembly resource lists,
1215 you are supposed to refer to it as mlo & mhi, e.g
1216 (zero_extract:SI (reg:DI 58) (const_int 32) (16)) .
1217 In an actual asm instruction, you are of course use mmed.
1218 The point of avoiding having a separate register for mmed is that
1219 this way, we don't have to carry clobbers of that reg around in every
1220 isntruction that modifies mlo and/or mhi. */
1221 strcpy (rname57
, "");
1222 strcpy (rname58
, TARGET_BIG_ENDIAN
? "mhi" : "mlo");
1223 strcpy (rname59
, TARGET_BIG_ENDIAN
? "mlo" : "mhi");
1225 if (TARGET_MULMAC_32BY16_SET
)
1228 fix_end
= fix_end
> 57 ? fix_end
: 57;
1229 strcpy (rname56
, TARGET_BIG_ENDIAN
? "acc1" : "acc2");
1230 strcpy (rname57
, TARGET_BIG_ENDIAN
? "acc2" : "acc1");
1232 for (regno
= fix_start
; regno
<= fix_end
; regno
++)
1234 if (!fixed_regs
[regno
])
1235 warning (0, "multiply option implies r%d is fixed", regno
);
1236 fixed_regs
[regno
] = call_used_regs
[regno
] = 1;
1240 reg_alloc_order
[2] = 12;
1241 reg_alloc_order
[3] = 13;
1242 reg_alloc_order
[4] = 14;
1243 reg_alloc_order
[5] = 15;
1244 reg_alloc_order
[6] = 1;
1245 reg_alloc_order
[7] = 0;
1246 reg_alloc_order
[8] = 4;
1247 reg_alloc_order
[9] = 5;
1248 reg_alloc_order
[10] = 6;
1249 reg_alloc_order
[11] = 7;
1250 reg_alloc_order
[12] = 8;
1251 reg_alloc_order
[13] = 9;
1252 reg_alloc_order
[14] = 10;
1253 reg_alloc_order
[15] = 11;
1255 if (TARGET_SIMD_SET
)
1258 for (i
= ARC_FIRST_SIMD_VR_REG
; i
<= ARC_LAST_SIMD_VR_REG
; i
++)
1259 reg_alloc_order
[i
] = i
;
1260 for (i
= ARC_FIRST_SIMD_DMA_CONFIG_REG
;
1261 i
<= ARC_LAST_SIMD_DMA_CONFIG_REG
; i
++)
1262 reg_alloc_order
[i
] = i
;
1264 /* For Arctangent-A5 / ARC600, lp_count may not be read in an instruction
1265 following immediately after another one setting it to a new value.
1266 There was some discussion on how to enforce scheduling constraints for
1267 processors with missing interlocks on the gcc mailing list:
1268 http://gcc.gnu.org/ml/gcc/2008-05/msg00021.html .
1269 However, we can't actually use this approach, because for ARC the
1270 delay slot scheduling pass is active, which runs after
1271 machine_dependent_reorg. */
1273 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], LP_COUNT
);
1274 else if (!TARGET_ARC700
)
1275 fixed_regs
[LP_COUNT
] = 1;
1276 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
1277 if (!call_used_regs
[regno
])
1278 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], regno
);
1279 for (regno
= 32; regno
< 60; regno
++)
1280 if (!fixed_regs
[regno
])
1281 SET_HARD_REG_BIT (reg_class_contents
[WRITABLE_CORE_REGS
], regno
);
1284 for (regno
= 32; regno
<= 60; regno
++)
1285 CLEAR_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], regno
);
1287 /* If they have used -ffixed-lp_count, make sure it takes
1289 if (fixed_regs
[LP_COUNT
])
1291 CLEAR_HARD_REG_BIT (reg_class_contents
[LPCOUNT_REG
], LP_COUNT
);
1292 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], LP_COUNT
);
1293 CLEAR_HARD_REG_BIT (reg_class_contents
[WRITABLE_CORE_REGS
], LP_COUNT
);
1295 /* Instead of taking out SF_MODE like below, forbid it outright. */
1296 arc_hard_regno_mode_ok
[60] = 0;
1299 arc_hard_regno_mode_ok
[60] = 1 << (int) S_MODE
;
1302 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1306 if (TARGET_Q_CLASS
&& ((i
<= 3) || ((i
>= 12) && (i
<= 15))))
1307 arc_regno_reg_class
[i
] = ARCOMPACT16_REGS
;
1309 arc_regno_reg_class
[i
] = GENERAL_REGS
;
1312 arc_regno_reg_class
[i
]
1314 ? (TEST_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], i
)
1315 ? CHEAP_CORE_REGS
: ALL_CORE_REGS
)
1317 && TEST_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], i
))
1318 ? CHEAP_CORE_REGS
: WRITABLE_CORE_REGS
));
1320 arc_regno_reg_class
[i
] = NO_REGS
;
1323 /* ARCOMPACT16_REGS is empty, if TARGET_Q_CLASS has not been activated. */
1324 if (!TARGET_Q_CLASS
)
1326 CLEAR_HARD_REG_SET(reg_class_contents
[ARCOMPACT16_REGS
]);
1327 CLEAR_HARD_REG_SET(reg_class_contents
[AC16_BASE_REGS
]);
1330 gcc_assert (FIRST_PSEUDO_REGISTER
>= 144);
1332 /* Handle Special Registers. */
1333 arc_regno_reg_class
[29] = LINK_REGS
; /* ilink1 register. */
1334 arc_regno_reg_class
[30] = LINK_REGS
; /* ilink2 register. */
1335 arc_regno_reg_class
[31] = LINK_REGS
; /* blink register. */
1336 arc_regno_reg_class
[60] = LPCOUNT_REG
;
1337 arc_regno_reg_class
[61] = NO_REGS
; /* CC_REG: must be NO_REGS. */
1338 arc_regno_reg_class
[62] = GENERAL_REGS
;
1342 for (i
= 40; i
< 44; ++i
)
1344 arc_regno_reg_class
[i
] = DOUBLE_REGS
;
1346 /* Unless they want us to do 'mov d1, 0x00000000' make sure
1347 no attempt is made to use such a register as a destination
1348 operand in *movdf_insn. */
1349 if (!TARGET_ARGONAUT_SET
)
1351 /* Make sure no 'c', 'w', 'W', or 'Rac' constraint is
1352 interpreted to mean they can use D1 or D2 in their insn. */
1353 CLEAR_HARD_REG_BIT(reg_class_contents
[CHEAP_CORE_REGS
], i
);
1354 CLEAR_HARD_REG_BIT(reg_class_contents
[ALL_CORE_REGS
], i
);
1355 CLEAR_HARD_REG_BIT(reg_class_contents
[WRITABLE_CORE_REGS
], i
);
1356 CLEAR_HARD_REG_BIT(reg_class_contents
[MPY_WRITABLE_CORE_REGS
], i
);
1362 /* Disable all DOUBLE_REGISTER settings,
1363 if not generating DPFP code. */
1364 arc_regno_reg_class
[40] = ALL_REGS
;
1365 arc_regno_reg_class
[41] = ALL_REGS
;
1366 arc_regno_reg_class
[42] = ALL_REGS
;
1367 arc_regno_reg_class
[43] = ALL_REGS
;
1369 arc_hard_regno_mode_ok
[40] = 0;
1370 arc_hard_regno_mode_ok
[42] = 0;
1372 CLEAR_HARD_REG_SET(reg_class_contents
[DOUBLE_REGS
]);
1375 if (TARGET_SIMD_SET
)
1377 gcc_assert (ARC_FIRST_SIMD_VR_REG
== 64);
1378 gcc_assert (ARC_LAST_SIMD_VR_REG
== 127);
1380 for (i
= ARC_FIRST_SIMD_VR_REG
; i
<= ARC_LAST_SIMD_VR_REG
; i
++)
1381 arc_regno_reg_class
[i
] = SIMD_VR_REGS
;
1383 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_REG
== 128);
1384 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_IN_REG
== 128);
1385 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG
== 136);
1386 gcc_assert (ARC_LAST_SIMD_DMA_CONFIG_REG
== 143);
1388 for (i
= ARC_FIRST_SIMD_DMA_CONFIG_REG
;
1389 i
<= ARC_LAST_SIMD_DMA_CONFIG_REG
; i
++)
1390 arc_regno_reg_class
[i
] = SIMD_DMA_CONFIG_REGS
;
1394 arc_regno_reg_class
[PROGRAM_COUNTER_REGNO
] = GENERAL_REGS
;
1397 /* Handle an "interrupt" attribute; arguments as in
1398 struct attribute_spec.handler. */
1401 arc_handle_interrupt_attribute (tree
*, tree name
, tree args
, int,
1406 tree value
= TREE_VALUE (args
);
1408 if (TREE_CODE (value
) != STRING_CST
)
1410 warning (OPT_Wattributes
,
1411 "argument of %qE attribute is not a string constant",
1413 *no_add_attrs
= true;
1415 else if (strcmp (TREE_STRING_POINTER (value
), "ilink1")
1416 && strcmp (TREE_STRING_POINTER (value
), "ilink2"))
1418 warning (OPT_Wattributes
,
1419 "argument of %qE attribute is not \"ilink1\" or \"ilink2\"",
1421 *no_add_attrs
= true;
1426 /* Return zero if TYPE1 and TYPE are incompatible, one if they are compatible,
1427 and two if they are nearly compatible (which causes a warning to be
1431 arc_comp_type_attributes (const_tree type1
,
1434 int l1
, l2
, m1
, m2
, s1
, s2
;
1436 /* Check for mismatch of non-default calling convention. */
1437 if (TREE_CODE (type1
) != FUNCTION_TYPE
)
1440 /* Check for mismatched call attributes. */
1441 l1
= lookup_attribute ("long_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
1442 l2
= lookup_attribute ("long_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
1443 m1
= lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
1444 m2
= lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
1445 s1
= lookup_attribute ("short_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
1446 s2
= lookup_attribute ("short_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
1448 /* Only bother to check if an attribute is defined. */
1449 if (l1
| l2
| m1
| m2
| s1
| s2
)
1451 /* If one type has an attribute, the other must have the same attribute. */
1452 if ((l1
!= l2
) || (m1
!= m2
) || (s1
!= s2
))
1455 /* Disallow mixed attributes. */
1456 if (l1
+ m1
+ s1
> 1)
1464 /* Set the default attributes for TYPE. */
1467 arc_set_default_type_attributes (tree type ATTRIBUTE_UNUSED
)
1472 /* Misc. utilities. */
1474 /* X and Y are two things to compare using CODE. Emit the compare insn and
1475 return the rtx for the cc reg in the proper mode. */
1478 gen_compare_reg (rtx comparison
, enum machine_mode omode
)
1480 enum rtx_code code
= GET_CODE (comparison
);
1481 rtx x
= XEXP (comparison
, 0);
1482 rtx y
= XEXP (comparison
, 1);
1484 enum machine_mode mode
, cmode
;
1487 cmode
= GET_MODE (x
);
1488 if (cmode
== VOIDmode
)
1489 cmode
= GET_MODE (y
);
1490 gcc_assert (cmode
== SImode
|| cmode
== SFmode
|| cmode
== DFmode
);
1491 if (cmode
== SImode
)
1493 if (!register_operand (x
, SImode
))
1495 if (register_operand (y
, SImode
))
1500 code
= swap_condition (code
);
1503 x
= copy_to_mode_reg (SImode
, x
);
1505 if (GET_CODE (y
) == SYMBOL_REF
&& flag_pic
)
1506 y
= copy_to_mode_reg (SImode
, y
);
1510 x
= force_reg (cmode
, x
);
1511 y
= force_reg (cmode
, y
);
1513 mode
= SELECT_CC_MODE (code
, x
, y
);
1515 cc_reg
= gen_rtx_REG (mode
, CC_REG
);
1517 /* ??? FIXME (x-y)==0, as done by both cmpsfpx_raw and
1518 cmpdfpx_raw, is not a correct comparison for floats:
1519 http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
1521 if (TARGET_ARGONAUT_SET
1522 && ((cmode
== SFmode
&& TARGET_SPFP
) || (cmode
== DFmode
&& TARGET_DPFP
)))
1526 case NE
: case EQ
: case LT
: case UNGE
: case LE
: case UNGT
:
1527 case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1529 case GT
: case UNLE
: case GE
: case UNLT
:
1530 code
= swap_condition (code
);
1538 if (cmode
== SFmode
)
1540 emit_insn (gen_cmpsfpx_raw (x
, y
));
1544 /* Accepts Dx regs directly by insns. */
1545 emit_insn (gen_cmpdfpx_raw (x
, y
));
1548 if (mode
!= CC_FPXmode
)
1549 emit_insn (gen_rtx_SET (VOIDmode
, cc_reg
,
1550 gen_rtx_COMPARE (mode
,
1551 gen_rtx_REG (CC_FPXmode
, 61),
1554 else if (GET_MODE_CLASS (cmode
) == MODE_FLOAT
&& TARGET_OPTFPE
)
1556 rtx op0
= gen_rtx_REG (cmode
, 0);
1557 rtx op1
= gen_rtx_REG (cmode
, GET_MODE_SIZE (cmode
) / UNITS_PER_WORD
);
1561 case NE
: case EQ
: case GT
: case UNLE
: case GE
: case UNLT
:
1562 case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1564 case LT
: case UNGE
: case LE
: case UNGT
:
1565 code
= swap_condition (code
);
1573 if (currently_expanding_to_rtl
)
1575 emit_move_insn (op0
, x
);
1576 emit_move_insn (op1
, y
);
1580 gcc_assert (rtx_equal_p (op0
, x
));
1581 gcc_assert (rtx_equal_p (op1
, y
));
1583 emit_insn (gen_cmp_float (cc_reg
, gen_rtx_COMPARE (mode
, op0
, op1
)));
1586 emit_insn (gen_rtx_SET (omode
, cc_reg
,
1587 gen_rtx_COMPARE (mode
, x
, y
)));
1588 return gen_rtx_fmt_ee (code
, omode
, cc_reg
, const0_rtx
);
1591 /* Return true if VALUE, a const_double, will fit in a limm (4 byte number).
1592 We assume the value can be either signed or unsigned. */
1595 arc_double_limm_p (rtx value
)
1597 HOST_WIDE_INT low
, high
;
1599 gcc_assert (GET_CODE (value
) == CONST_DOUBLE
);
1604 low
= CONST_DOUBLE_LOW (value
);
1605 high
= CONST_DOUBLE_HIGH (value
);
1607 if (low
& 0x80000000)
1609 return (((unsigned HOST_WIDE_INT
) low
<= 0xffffffff && high
== 0)
1610 || (((low
& - (unsigned HOST_WIDE_INT
) 0x80000000)
1611 == - (unsigned HOST_WIDE_INT
) 0x80000000)
1616 return (unsigned HOST_WIDE_INT
) low
<= 0x7fffffff && high
== 0;
1620 /* Do any needed setup for a variadic function. For the ARC, we must
1621 create a register parameter block, and then copy any anonymous arguments
1622 in registers to memory.
1624 CUM has not been updated for the last named argument which has type TYPE
1625 and mode MODE, and we rely on this fact. */
1628 arc_setup_incoming_varargs (cumulative_args_t args_so_far
,
1629 enum machine_mode mode
, tree type
,
1630 int *pretend_size
, int no_rtl
)
1633 CUMULATIVE_ARGS next_cum
;
1635 /* We must treat `__builtin_va_alist' as an anonymous arg. */
1637 next_cum
= *get_cumulative_args (args_so_far
);
1638 arc_function_arg_advance (pack_cumulative_args (&next_cum
), mode
, type
, 1);
1639 first_anon_arg
= next_cum
;
1641 if (first_anon_arg
< MAX_ARC_PARM_REGS
)
1643 /* First anonymous (unnamed) argument is in a reg. */
1645 /* Note that first_reg_offset < MAX_ARC_PARM_REGS. */
1646 int first_reg_offset
= first_anon_arg
;
1651 = gen_rtx_MEM (BLKmode
, plus_constant (Pmode
, arg_pointer_rtx
,
1652 FIRST_PARM_OFFSET (0)));
1653 move_block_from_reg (first_reg_offset
, regblock
,
1654 MAX_ARC_PARM_REGS
- first_reg_offset
);
1658 = ((MAX_ARC_PARM_REGS
- first_reg_offset
) * UNITS_PER_WORD
);
1662 /* Cost functions. */
1664 /* Provide the costs of an addressing mode that contains ADDR.
1665 If ADDR is not a valid address, its cost is irrelevant. */
1668 arc_address_cost (rtx addr
, enum machine_mode
, addr_space_t
, bool speed
)
1670 switch (GET_CODE (addr
))
1673 return speed
|| satisfies_constraint_Rcq (addr
) ? 0 : 1;
1674 case PRE_INC
: case PRE_DEC
: case POST_INC
: case POST_DEC
:
1675 case PRE_MODIFY
: case POST_MODIFY
:
1681 /* Most likely needs a LIMM. */
1682 return COSTS_N_INSNS (1);
1686 register rtx plus0
= XEXP (addr
, 0);
1687 register rtx plus1
= XEXP (addr
, 1);
1689 if (GET_CODE (plus0
) != REG
1690 && (GET_CODE (plus0
) != MULT
1691 || !CONST_INT_P (XEXP (plus0
, 1))
1692 || (INTVAL (XEXP (plus0
, 1)) != 2
1693 && INTVAL (XEXP (plus0
, 1)) != 4)))
1696 switch (GET_CODE (plus1
))
1699 return (!RTX_OK_FOR_OFFSET_P (SImode
, plus1
)
1703 : (satisfies_constraint_Rcq (plus0
)
1704 && satisfies_constraint_O (plus1
))
1708 return (speed
< 1 ? 0
1709 : (satisfies_constraint_Rcq (plus0
)
1710 && satisfies_constraint_Rcq (plus1
))
1715 return COSTS_N_INSNS (1);
1728 /* Emit instruction X with the frame related bit set. */
1734 RTX_FRAME_RELATED_P (x
) = 1;
1738 /* Emit a frame insn to move SRC to DST. */
1741 frame_move (rtx dst
, rtx src
)
1743 return frame_insn (gen_rtx_SET (VOIDmode
, dst
, src
));
1746 /* Like frame_move, but add a REG_INC note for REG if ADDR contains an
1747 auto increment address, or is zero. */
1750 frame_move_inc (rtx dst
, rtx src
, rtx reg
, rtx addr
)
1752 rtx insn
= frame_move (dst
, src
);
1755 || GET_CODE (addr
) == PRE_DEC
|| GET_CODE (addr
) == POST_INC
1756 || GET_CODE (addr
) == PRE_MODIFY
|| GET_CODE (addr
) == POST_MODIFY
)
1757 add_reg_note (insn
, REG_INC
, reg
);
1761 /* Emit a frame insn which adjusts a frame address register REG by OFFSET. */
1764 frame_add (rtx reg
, HOST_WIDE_INT offset
)
1766 gcc_assert ((offset
& 0x3) == 0);
1769 return frame_move (reg
, plus_constant (Pmode
, reg
, offset
));
1772 /* Emit a frame insn which adjusts stack pointer by OFFSET. */
1775 frame_stack_add (HOST_WIDE_INT offset
)
1777 return frame_add (stack_pointer_rtx
, offset
);
1780 /* Traditionally, we push saved registers first in the prologue,
1781 then we allocate the rest of the frame - and reverse in the epilogue.
1782 This has still its merits for ease of debugging, or saving code size
1783 or even execution time if the stack frame is so large that some accesses
1784 can't be encoded anymore with offsets in the instruction code when using
1786 Also, it would be a good starting point if we got instructions to help
1787 with register save/restore.
1789 However, often stack frames are small, and the pushing / popping has
1791 - the stack modification prevents a lot of scheduling.
1792 - frame allocation / deallocation needs extra instructions.
1793 - unless we know that we compile ARC700 user code, we need to put
1794 a memory barrier after frame allocation / before deallocation to
1795 prevent interrupts clobbering our data in the frame.
1796 In particular, we don't have any such guarantees for library functions,
1797 which tend to, on the other hand, to have small frames.
1799 Thus, for small frames, we'd like to use a different scheme:
1800 - The frame is allocated in full with the first prologue instruction,
1801 and deallocated in full with the last epilogue instruction.
1802 Thus, the instructions in-betwen can be freely scheduled.
1803 - If the function has no outgoing arguments on the stack, we can allocate
1804 one register save slot at the top of the stack. This register can then
1805 be saved simultanously with frame allocation, and restored with
1807 This register can be picked depending on scheduling considerations,
1808 although same though should go into having some set of registers
1809 to be potentially lingering after a call, and others to be available
1810 immediately - i.e. in the absence of interprocedual optimization, we
1811 can use an ABI-like convention for register allocation to reduce
1812 stalls after function return. */
1813 /* Function prologue/epilogue handlers. */
1815 /* ARCompact stack frames look like:
1817 Before call After call
1818 high +-----------------------+ +-----------------------+
1819 mem | reg parm save area | | reg parm save area |
1820 | only created for | | only created for |
1821 | variable arg fns | | variable arg fns |
1822 AP +-----------------------+ +-----------------------+
1823 | return addr register | | return addr register |
1824 | (if required) | | (if required) |
1825 +-----------------------+ +-----------------------+
1827 | reg save area | | reg save area |
1829 +-----------------------+ +-----------------------+
1830 | frame pointer | | frame pointer |
1831 | (if required) | | (if required) |
1832 FP +-----------------------+ +-----------------------+
1834 | local/temp variables | | local/temp variables |
1836 +-----------------------+ +-----------------------+
1838 | arguments on stack | | arguments on stack |
1840 SP +-----------------------+ +-----------------------+
1841 | reg parm save area |
1842 | only created for |
1843 | variable arg fns |
1844 AP +-----------------------+
1845 | return addr register |
1847 +-----------------------+
1851 +-----------------------+
1854 FP +-----------------------+
1856 | local/temp variables |
1858 +-----------------------+
1860 | arguments on stack |
1862 mem SP +-----------------------+
1865 1) The "reg parm save area" does not exist for non variable argument fns.
1866 The "reg parm save area" can be eliminated completely if we created our
1867 own va-arc.h, but that has tradeoffs as well (so it's not done). */
1869 /* Structure to be filled in by arc_compute_frame_size with register
1870 save masks, and offsets for the current function. */
1871 struct GTY (()) arc_frame_info
1873 unsigned int total_size
; /* # bytes that the entire frame takes up. */
1874 unsigned int extra_size
; /* # bytes of extra stuff. */
1875 unsigned int pretend_size
; /* # bytes we push and pretend caller did. */
1876 unsigned int args_size
; /* # bytes that outgoing arguments take up. */
1877 unsigned int reg_size
; /* # bytes needed to store regs. */
1878 unsigned int var_size
; /* # bytes that variables take up. */
1879 unsigned int reg_offset
; /* Offset from new sp to store regs. */
1880 unsigned int gmask
; /* Mask of saved gp registers. */
1881 int initialized
; /* Nonzero if frame size already calculated. */
1882 short millicode_start_reg
;
1883 short millicode_end_reg
;
1884 bool save_return_addr
;
1887 /* Defining data structures for per-function information. */
1889 typedef struct GTY (()) machine_function
1891 enum arc_function_type fn_type
;
1892 struct arc_frame_info frame_info
;
1893 /* To keep track of unalignment caused by short insns. */
1895 int force_short_suffix
; /* Used when disgorging return delay slot insns. */
1896 const char *size_reason
;
1897 struct arc_ccfsm ccfsm_current
;
1898 /* Map from uid to ccfsm state during branch shortening. */
1899 rtx ccfsm_current_insn
;
1900 char arc_reorg_started
;
1901 char prescan_initialized
;
1904 /* Type of function DECL.
1906 The result is cached. To reset the cache at the end of a function,
1907 call with DECL = NULL_TREE. */
1909 enum arc_function_type
1910 arc_compute_function_type (struct function
*fun
)
1912 tree decl
= fun
->decl
;
1914 enum arc_function_type fn_type
= fun
->machine
->fn_type
;
1916 if (fn_type
!= ARC_FUNCTION_UNKNOWN
)
1919 /* Assume we have a normal function (not an interrupt handler). */
1920 fn_type
= ARC_FUNCTION_NORMAL
;
1922 /* Now see if this is an interrupt handler. */
1923 for (a
= DECL_ATTRIBUTES (decl
);
1927 tree name
= TREE_PURPOSE (a
), args
= TREE_VALUE (a
);
1929 if (name
== get_identifier ("interrupt")
1930 && list_length (args
) == 1
1931 && TREE_CODE (TREE_VALUE (args
)) == STRING_CST
)
1933 tree value
= TREE_VALUE (args
);
1935 if (!strcmp (TREE_STRING_POINTER (value
), "ilink1"))
1936 fn_type
= ARC_FUNCTION_ILINK1
;
1937 else if (!strcmp (TREE_STRING_POINTER (value
), "ilink2"))
1938 fn_type
= ARC_FUNCTION_ILINK2
;
1945 return fun
->machine
->fn_type
= fn_type
;
1948 #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
1949 #define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM))
1951 /* Tell prologue and epilogue if register REGNO should be saved / restored.
1952 The return address and frame pointer are treated separately.
1953 Don't consider them here.
1954 Addition for pic: The gp register needs to be saved if the current
1955 function changes it to access gotoff variables.
1956 FIXME: This will not be needed if we used some arbitrary register
1959 #define MUST_SAVE_REGISTER(regno, interrupt_p) \
1960 (((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \
1961 && (df_regs_ever_live_p (regno) && (!call_used_regs[regno] || interrupt_p))) \
1962 || (flag_pic && crtl->uses_pic_offset_table \
1963 && regno == PIC_OFFSET_TABLE_REGNUM) )
1965 #define MUST_SAVE_RETURN_ADDR \
1966 (cfun->machine->frame_info.save_return_addr)
1968 /* Return non-zero if there are registers to be saved or loaded using
1969 millicode thunks. We can only use consecutive sequences starting
1970 with r13, and not going beyond r25.
1971 GMASK is a bitmask of registers to save. This function sets
1972 FRAME->millicod_start_reg .. FRAME->millicode_end_reg to the range
1973 of registers to be saved / restored with a millicode call. */
1976 arc_compute_millicode_save_restore_regs (unsigned int gmask
,
1977 struct arc_frame_info
*frame
)
1981 int start_reg
= 13, end_reg
= 25;
1983 for (regno
= start_reg
; regno
<= end_reg
&& (gmask
& (1L << regno
));)
1985 end_reg
= regno
- 1;
1986 /* There is no point in using millicode thunks if we don't save/restore
1987 at least three registers. For non-leaf functions we also have the
1989 if (regno
- start_reg
>= 3 - (crtl
->is_leaf
== 0))
1991 frame
->millicode_start_reg
= 13;
1992 frame
->millicode_end_reg
= regno
- 1;
1998 /* Return the bytes needed to compute the frame pointer from the current
2001 SIZE is the size needed for local variables. */
2004 arc_compute_frame_size (int size
) /* size = # of var. bytes allocated. */
2007 unsigned int total_size
, var_size
, args_size
, pretend_size
, extra_size
;
2008 unsigned int reg_size
, reg_offset
;
2010 enum arc_function_type fn_type
;
2012 struct arc_frame_info
*frame_info
= &cfun
->machine
->frame_info
;
2014 size
= ARC_STACK_ALIGN (size
);
2016 /* 1) Size of locals and temporaries */
2019 /* 2) Size of outgoing arguments */
2020 args_size
= crtl
->outgoing_args_size
;
2022 /* 3) Calculate space needed for saved registers.
2023 ??? We ignore the extension registers for now. */
2025 /* See if this is an interrupt handler. Call used registers must be saved
2030 fn_type
= arc_compute_function_type (cfun
);
2031 interrupt_p
= ARC_INTERRUPT_P (fn_type
);
2033 for (regno
= 0; regno
<= 31; regno
++)
2035 if (MUST_SAVE_REGISTER (regno
, interrupt_p
))
2037 reg_size
+= UNITS_PER_WORD
;
2038 gmask
|= 1 << regno
;
2042 /* 4) Space for back trace data structure.
2043 <return addr reg size> (if required) + <fp size> (if required). */
2044 frame_info
->save_return_addr
2045 = (!crtl
->is_leaf
|| df_regs_ever_live_p (RETURN_ADDR_REGNUM
));
2046 /* Saving blink reg in case of leaf function for millicode thunk calls. */
2047 if (optimize_size
&& !TARGET_NO_MILLICODE_THUNK_SET
)
2049 if (arc_compute_millicode_save_restore_regs (gmask
, frame_info
))
2050 frame_info
->save_return_addr
= true;
2054 if (MUST_SAVE_RETURN_ADDR
)
2056 if (frame_pointer_needed
)
2059 /* 5) Space for variable arguments passed in registers */
2060 pretend_size
= crtl
->args
.pretend_args_size
;
2062 /* Ensure everything before the locals is aligned appropriately. */
2064 unsigned int extra_plus_reg_size
;
2065 unsigned int extra_plus_reg_size_aligned
;
2067 extra_plus_reg_size
= extra_size
+ reg_size
;
2068 extra_plus_reg_size_aligned
= ARC_STACK_ALIGN(extra_plus_reg_size
);
2069 reg_size
= extra_plus_reg_size_aligned
- extra_size
;
2072 /* Compute total frame size. */
2073 total_size
= var_size
+ args_size
+ extra_size
+ pretend_size
+ reg_size
;
2075 total_size
= ARC_STACK_ALIGN (total_size
);
2077 /* Compute offset of register save area from stack pointer:
2078 A5 Frame: pretend_size <blink> reg_size <fp> var_size args_size <--sp
2080 reg_offset
= (total_size
- (pretend_size
+ reg_size
+ extra_size
)
2081 + (frame_pointer_needed
? 4 : 0));
2083 /* Save computed information. */
2084 frame_info
->total_size
= total_size
;
2085 frame_info
->extra_size
= extra_size
;
2086 frame_info
->pretend_size
= pretend_size
;
2087 frame_info
->var_size
= var_size
;
2088 frame_info
->args_size
= args_size
;
2089 frame_info
->reg_size
= reg_size
;
2090 frame_info
->reg_offset
= reg_offset
;
2091 frame_info
->gmask
= gmask
;
2092 frame_info
->initialized
= reload_completed
;
2094 /* Ok, we're done. */
2098 /* Common code to save/restore registers. */
2099 /* BASE_REG is the base register to use for addressing and to adjust.
2100 GMASK is a bitmask of general purpose registers to save/restore.
2101 epilogue_p 0: prologue 1:epilogue 2:epilogue, sibling thunk
2102 If *FIRST_OFFSET is non-zero, add it first to BASE_REG - preferably
2103 using a pre-modify for the first memory access. *FIRST_OFFSET is then
2107 arc_save_restore (rtx base_reg
,
2108 unsigned int gmask
, int epilogue_p
, int *first_offset
)
2110 unsigned int offset
= 0;
2112 struct arc_frame_info
*frame
= &cfun
->machine
->frame_info
;
2113 rtx sibthunk_insn
= NULL_RTX
;
2117 /* Millicode thunks implementation:
2118 Generates calls to millicodes for registers starting from r13 to r25
2119 Present Limitations:
2120 - Only one range supported. The remaining regs will have the ordinary
2121 st and ld instructions for store and loads. Hence a gmask asking
2122 to store r13-14, r16-r25 will only generate calls to store and
2123 load r13 to r14 while store and load insns will be generated for
2124 r16 to r25 in the prologue and epilogue respectively.
2126 - Presently library only supports register ranges starting from r13.
2128 if (epilogue_p
== 2 || frame
->millicode_end_reg
> 14)
2130 int start_call
= frame
->millicode_start_reg
;
2131 int end_call
= frame
->millicode_end_reg
;
2132 int n_regs
= end_call
- start_call
+ 1;
2133 int i
= 0, r
, off
= 0;
2135 rtx ret_addr
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
2139 /* "reg_size" won't be more than 127 . */
2140 gcc_assert (epilogue_p
|| abs (*first_offset
) <= 127);
2141 frame_add (base_reg
, *first_offset
);
2144 insn
= gen_rtx_PARALLEL
2145 (VOIDmode
, rtvec_alloc ((epilogue_p
== 2) + n_regs
+ 1));
2146 if (epilogue_p
== 2)
2149 XVECEXP (insn
, 0, n_regs
) = gen_rtx_CLOBBER (VOIDmode
, ret_addr
);
2150 for (r
= start_call
; r
<= end_call
; r
++, off
+= UNITS_PER_WORD
, i
++)
2152 rtx reg
= gen_rtx_REG (SImode
, r
);
2154 = gen_frame_mem (SImode
, plus_constant (Pmode
, base_reg
, off
));
2157 XVECEXP (insn
, 0, i
) = gen_rtx_SET (VOIDmode
, reg
, mem
);
2159 XVECEXP (insn
, 0, i
) = gen_rtx_SET (VOIDmode
, mem
, reg
);
2160 gmask
= gmask
& ~(1L << r
);
2162 if (epilogue_p
== 2)
2163 sibthunk_insn
= insn
;
2169 for (regno
= 0; regno
<= 31; regno
++)
2171 if ((gmask
& (1L << regno
)) != 0)
2173 rtx reg
= gen_rtx_REG (SImode
, regno
);
2178 gcc_assert (!offset
);
2179 addr
= plus_constant (Pmode
, base_reg
, *first_offset
);
2180 addr
= gen_rtx_PRE_MODIFY (Pmode
, base_reg
, addr
);
2185 gcc_assert (SMALL_INT (offset
));
2186 addr
= plus_constant (Pmode
, base_reg
, offset
);
2188 mem
= gen_frame_mem (SImode
, addr
);
2190 frame_move_inc (reg
, mem
, base_reg
, addr
);
2192 frame_move_inc (mem
, reg
, base_reg
, addr
);
2193 offset
+= UNITS_PER_WORD
;
2199 rtx r12
= gen_rtx_REG (Pmode
, 12);
2201 frame_insn (gen_rtx_SET (VOIDmode
, r12
, GEN_INT (offset
)));
2202 XVECEXP (sibthunk_insn
, 0, 0) = ret_rtx
;
2203 XVECEXP (sibthunk_insn
, 0, 1)
2204 = gen_rtx_SET (VOIDmode
, stack_pointer_rtx
,
2205 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
, r12
));
2206 sibthunk_insn
= emit_jump_insn (sibthunk_insn
);
2207 RTX_FRAME_RELATED_P (sibthunk_insn
) = 1;
2209 } /* arc_save_restore */
2212 int arc_return_address_regs
[4]
2213 = {0, RETURN_ADDR_REGNUM
, ILINK1_REGNUM
, ILINK2_REGNUM
};
2215 /* Set up the stack and frame pointer (if desired) for the function. */
2218 arc_expand_prologue (void)
2220 int size
= get_frame_size ();
2221 unsigned int gmask
= cfun
->machine
->frame_info
.gmask
;
2222 /* unsigned int frame_pointer_offset;*/
2223 unsigned int frame_size_to_allocate
;
2224 /* (FIXME: The first store will use a PRE_MODIFY; this will usually be r13.
2225 Change the stack layout so that we rather store a high register with the
2226 PRE_MODIFY, thus enabling more short insn generation.) */
2227 int first_offset
= 0;
2229 size
= ARC_STACK_ALIGN (size
);
2231 /* Compute/get total frame size. */
2232 size
= (!cfun
->machine
->frame_info
.initialized
2233 ? arc_compute_frame_size (size
)
2234 : cfun
->machine
->frame_info
.total_size
);
2236 if (flag_stack_usage_info
)
2237 current_function_static_stack_size
= size
;
2239 /* Keep track of frame size to be allocated. */
2240 frame_size_to_allocate
= size
;
2242 /* These cases shouldn't happen. Catch them now. */
2243 gcc_assert (!(size
== 0 && gmask
));
2245 /* Allocate space for register arguments if this is a variadic function. */
2246 if (cfun
->machine
->frame_info
.pretend_size
!= 0)
2248 /* Ensure pretend_size is maximum of 8 * word_size. */
2249 gcc_assert (cfun
->machine
->frame_info
.pretend_size
<= 32);
2251 frame_stack_add (-(HOST_WIDE_INT
)cfun
->machine
->frame_info
.pretend_size
);
2252 frame_size_to_allocate
-= cfun
->machine
->frame_info
.pretend_size
;
2255 /* The home-grown ABI says link register is saved first. */
2256 if (MUST_SAVE_RETURN_ADDR
)
2258 rtx ra
= gen_rtx_REG (SImode
, RETURN_ADDR_REGNUM
);
2259 rtx mem
= gen_frame_mem (Pmode
, gen_rtx_PRE_DEC (Pmode
, stack_pointer_rtx
));
2261 frame_move_inc (mem
, ra
, stack_pointer_rtx
, 0);
2262 frame_size_to_allocate
-= UNITS_PER_WORD
;
2264 } /* MUST_SAVE_RETURN_ADDR */
2266 /* Save any needed call-saved regs (and call-used if this is an
2267 interrupt handler) for ARCompact ISA. */
2268 if (cfun
->machine
->frame_info
.reg_size
)
2270 first_offset
= -cfun
->machine
->frame_info
.reg_size
;
2271 /* N.B. FRAME_POINTER_MASK and RETURN_ADDR_MASK are cleared in gmask. */
2272 arc_save_restore (stack_pointer_rtx
, gmask
, 0, &first_offset
);
2273 frame_size_to_allocate
-= cfun
->machine
->frame_info
.reg_size
;
2277 /* Save frame pointer if needed. */
2278 if (frame_pointer_needed
)
2280 rtx addr
= gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
2281 GEN_INT (-UNITS_PER_WORD
+ first_offset
));
2282 rtx mem
= gen_frame_mem (Pmode
, gen_rtx_PRE_MODIFY (Pmode
,
2285 frame_move_inc (mem
, frame_pointer_rtx
, stack_pointer_rtx
, 0);
2286 frame_size_to_allocate
-= UNITS_PER_WORD
;
2288 frame_move (frame_pointer_rtx
, stack_pointer_rtx
);
2291 /* ??? We don't handle the case where the saved regs are more than 252
2292 bytes away from sp. This can be handled by decrementing sp once, saving
2293 the regs, and then decrementing it again. The epilogue doesn't have this
2294 problem as the `ld' insn takes reg+limm values (though it would be more
2295 efficient to avoid reg+limm). */
2297 frame_size_to_allocate
-= first_offset
;
2298 /* Allocate the stack frame. */
2299 if (frame_size_to_allocate
> 0)
2300 frame_stack_add ((HOST_WIDE_INT
) 0 - frame_size_to_allocate
);
2302 /* Setup the gp register, if needed. */
2303 if (crtl
->uses_pic_offset_table
)
2304 arc_finalize_pic ();
2307 /* Do any necessary cleanup after a function to restore stack, frame,
2311 arc_expand_epilogue (int sibcall_p
)
2313 int size
= get_frame_size ();
2314 enum arc_function_type fn_type
= arc_compute_function_type (cfun
);
2316 size
= ARC_STACK_ALIGN (size
);
2317 size
= (!cfun
->machine
->frame_info
.initialized
2318 ? arc_compute_frame_size (size
)
2319 : cfun
->machine
->frame_info
.total_size
);
2321 unsigned int pretend_size
= cfun
->machine
->frame_info
.pretend_size
;
2322 unsigned int frame_size
;
2323 unsigned int size_to_deallocate
;
2325 int can_trust_sp_p
= !cfun
->calls_alloca
;
2326 int first_offset
= 0;
2327 int millicode_p
= cfun
->machine
->frame_info
.millicode_end_reg
> 0;
2329 size_to_deallocate
= size
;
2331 frame_size
= size
- (pretend_size
+
2332 cfun
->machine
->frame_info
.reg_size
+
2333 cfun
->machine
->frame_info
.extra_size
);
2335 /* ??? There are lots of optimizations that can be done here.
2336 EG: Use fp to restore regs if it's closer.
2337 Maybe in time we'll do them all. For now, always restore regs from
2338 sp, but don't restore sp if we don't have to. */
2340 if (!can_trust_sp_p
)
2341 gcc_assert (frame_pointer_needed
);
2343 /* Restore stack pointer to the beginning of saved register area for
2347 if (frame_pointer_needed
)
2348 frame_move (stack_pointer_rtx
, frame_pointer_rtx
);
2350 first_offset
= frame_size
;
2351 size_to_deallocate
-= frame_size
;
2353 else if (!can_trust_sp_p
)
2354 frame_stack_add (-frame_size
);
2357 /* Restore any saved registers. */
2358 if (frame_pointer_needed
)
2360 rtx addr
= gen_rtx_POST_INC (Pmode
, stack_pointer_rtx
);
2362 frame_move_inc (frame_pointer_rtx
, gen_frame_mem (Pmode
, addr
),
2363 stack_pointer_rtx
, 0);
2364 size_to_deallocate
-= UNITS_PER_WORD
;
2367 /* Load blink after the calls to thunk calls in case of optimize size. */
2370 int sibthunk_p
= (!sibcall_p
2371 && fn_type
== ARC_FUNCTION_NORMAL
2372 && !cfun
->machine
->frame_info
.pretend_size
);
2374 gcc_assert (!(cfun
->machine
->frame_info
.gmask
2375 & (FRAME_POINTER_MASK
| RETURN_ADDR_MASK
)));
2376 arc_save_restore (stack_pointer_rtx
,
2377 cfun
->machine
->frame_info
.gmask
,
2378 1 + sibthunk_p
, &first_offset
);
2382 /* If we are to restore registers, and first_offset would require
2383 a limm to be encoded in a PRE_MODIFY, yet we can add it with a
2384 fast add to the stack pointer, do this now. */
2385 if ((!SMALL_INT (first_offset
)
2386 && cfun
->machine
->frame_info
.gmask
2387 && ((TARGET_ARC700
&& !optimize_size
)
2388 ? first_offset
<= 0x800
2389 : satisfies_constraint_C2a (GEN_INT (first_offset
))))
2390 /* Also do this if we have both gprs and return
2391 address to restore, and they both would need a LIMM. */
2392 || (MUST_SAVE_RETURN_ADDR
2393 && !SMALL_INT ((cfun
->machine
->frame_info
.reg_size
+ first_offset
) >> 2)
2394 && cfun
->machine
->frame_info
.gmask
))
2396 frame_stack_add (first_offset
);
2399 if (MUST_SAVE_RETURN_ADDR
)
2401 rtx ra
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
2402 int ra_offs
= cfun
->machine
->frame_info
.reg_size
+ first_offset
;
2403 rtx addr
= plus_constant (Pmode
, stack_pointer_rtx
, ra_offs
);
2405 /* If the load of blink would need a LIMM, but we can add
2406 the offset quickly to sp, do the latter. */
2407 if (!SMALL_INT (ra_offs
>> 2)
2408 && !cfun
->machine
->frame_info
.gmask
2409 && ((TARGET_ARC700
&& !optimize_size
)
2411 : satisfies_constraint_C2a (GEN_INT (ra_offs
))))
2413 size_to_deallocate
-= ra_offs
- first_offset
;
2415 frame_stack_add (ra_offs
);
2417 addr
= stack_pointer_rtx
;
2419 /* See if we can combine the load of the return address with the
2420 final stack adjustment.
2421 We need a separate load if there are still registers to
2422 restore. We also want a separate load if the combined insn
2423 would need a limm, but a separate load doesn't. */
2425 && !cfun
->machine
->frame_info
.gmask
2426 && (SMALL_INT (ra_offs
) || !SMALL_INT (ra_offs
>> 2)))
2428 addr
= gen_rtx_PRE_MODIFY (Pmode
, stack_pointer_rtx
, addr
);
2430 size_to_deallocate
-= cfun
->machine
->frame_info
.reg_size
;
2432 else if (!ra_offs
&& size_to_deallocate
== UNITS_PER_WORD
)
2434 addr
= gen_rtx_POST_INC (Pmode
, addr
);
2435 size_to_deallocate
= 0;
2437 frame_move_inc (ra
, gen_frame_mem (Pmode
, addr
), stack_pointer_rtx
, addr
);
2442 if (cfun
->machine
->frame_info
.reg_size
)
2443 arc_save_restore (stack_pointer_rtx
,
2444 /* The zeroing of these two bits is unnecessary, but leave this in for clarity. */
2445 cfun
->machine
->frame_info
.gmask
2446 & ~(FRAME_POINTER_MASK
| RETURN_ADDR_MASK
), 1, &first_offset
);
2450 /* The rest of this function does the following:
2451 ARCompact : handle epilogue_delay, restore sp (phase-2), return
2454 /* Keep track of how much of the stack pointer we've restored.
2455 It makes the following a lot more readable. */
2456 size_to_deallocate
+= first_offset
;
2457 restored
= size
- size_to_deallocate
;
2459 if (size
> restored
)
2460 frame_stack_add (size
- restored
);
2461 /* Emit the return instruction. */
2462 if (sibcall_p
== FALSE
)
2463 emit_jump_insn (gen_simple_return ());
2465 if (!TARGET_EPILOGUE_CFI
)
2469 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
2470 RTX_FRAME_RELATED_P (insn
) = 0;
2474 /* Return the offset relative to the stack pointer where the return address
2475 is stored, or -1 if it is not stored. */
2478 arc_return_slot_offset ()
2480 struct arc_frame_info
*afi
= &cfun
->machine
->frame_info
;
2482 return (afi
->save_return_addr
2483 ? afi
->total_size
- afi
->pretend_size
- afi
->extra_size
: -1);
2488 /* Emit special PIC prologues and epilogues. */
2489 /* If the function has any GOTOFF relocations, then the GOTBASE
2490 register has to be setup in the prologue
2491 The instruction needed at the function start for setting up the
2494 ----------------------------------------------------------
2495 The rtl to be emitted for this should be:
2498 (const (unspec (symref _DYNAMIC) 3)))
2499 ---------------------------------------------------------- */
2502 arc_finalize_pic (void)
2505 rtx baseptr_rtx
= gen_rtx_REG (Pmode
, PIC_OFFSET_TABLE_REGNUM
);
2507 if (crtl
->uses_pic_offset_table
== 0)
2510 gcc_assert (flag_pic
!= 0);
2512 pat
= gen_rtx_SYMBOL_REF (Pmode
, "_DYNAMIC");
2513 pat
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, pat
), ARC_UNSPEC_GOT
);
2514 pat
= gen_rtx_CONST (Pmode
, pat
);
2516 pat
= gen_rtx_SET (VOIDmode
, baseptr_rtx
, pat
);
2521 /* !TARGET_BARREL_SHIFTER support. */
2522 /* Emit a shift insn to set OP0 to OP1 shifted by OP2; CODE specifies what
2526 emit_shift (enum rtx_code code
, rtx op0
, rtx op1
, rtx op2
)
2528 rtx shift
= gen_rtx_fmt_ee (code
, SImode
, op1
, op2
);
2530 = ((shift4_operator (shift
, SImode
) ? gen_shift_si3
: gen_shift_si3_loop
)
2531 (op0
, op1
, op2
, shift
));
2535 /* Output the assembler code for doing a shift.
2536 We go to a bit of trouble to generate efficient code as the ARC601 only has
2537 single bit shifts. This is taken from the h8300 port. We only have one
2538 mode of shifting and can't access individual bytes like the h8300 can, so
2539 this is greatly simplified (at the expense of not generating hyper-
2542 This function is not used if the variable shift insns are present. */
2544 /* FIXME: This probably can be done using a define_split in arc.md.
2545 Alternately, generate rtx rather than output instructions. */
2548 output_shift (rtx
*operands
)
2550 /* static int loopend_lab;*/
2551 rtx shift
= operands
[3];
2552 enum machine_mode mode
= GET_MODE (shift
);
2553 enum rtx_code code
= GET_CODE (shift
);
2554 const char *shift_one
;
2556 gcc_assert (mode
== SImode
);
2560 case ASHIFT
: shift_one
= "add %0,%1,%1"; break;
2561 case ASHIFTRT
: shift_one
= "asr %0,%1"; break;
2562 case LSHIFTRT
: shift_one
= "lsr %0,%1"; break;
2563 default: gcc_unreachable ();
2566 if (GET_CODE (operands
[2]) != CONST_INT
)
2568 output_asm_insn ("and.f lp_count,%2, 0x1f", operands
);
2575 n
= INTVAL (operands
[2]);
2577 /* Only consider the lower 5 bits of the shift count. */
2580 /* First see if we can do them inline. */
2581 /* ??? We could get better scheduling & shorter code (using short insns)
2582 by using splitters. Alas, that'd be even more verbose. */
2583 if (code
== ASHIFT
&& n
<= 9 && n
> 2
2584 && dest_reg_operand (operands
[4], SImode
))
2586 output_asm_insn ("mov %4,0\n\tadd3 %0,%4,%1", operands
);
2587 for (n
-=3 ; n
>= 3; n
-= 3)
2588 output_asm_insn ("add3 %0,%4,%0", operands
);
2590 output_asm_insn ("add2 %0,%4,%0", operands
);
2592 output_asm_insn ("add %0,%0,%0", operands
);
2598 output_asm_insn (shift_one
, operands
);
2599 operands
[1] = operands
[0];
2602 /* See if we can use a rotate/and. */
2603 else if (n
== BITS_PER_WORD
- 1)
2608 output_asm_insn ("and %0,%1,1\n\tror %0,%0", operands
);
2611 /* The ARC doesn't have a rol insn. Use something else. */
2612 output_asm_insn ("add.f 0,%1,%1\n\tsbc %0,%0,%0", operands
);
2615 /* The ARC doesn't have a rol insn. Use something else. */
2616 output_asm_insn ("add.f 0,%1,%1\n\trlc %0,0", operands
);
2622 else if (n
== BITS_PER_WORD
- 2 && dest_reg_operand (operands
[4], SImode
))
2627 output_asm_insn ("and %0,%1,3\n\tror %0,%0\n\tror %0,%0", operands
);
2630 #if 1 /* Need some scheduling comparisons. */
2631 output_asm_insn ("add.f %4,%1,%1\n\tsbc %0,%0,%0\n\t"
2632 "add.f 0,%4,%4\n\trlc %0,%0", operands
);
2634 output_asm_insn ("add.f %4,%1,%1\n\tbxor %0,%4,31\n\t"
2635 "sbc.f %0,%0,%4\n\trlc %0,%0", operands
);
2640 output_asm_insn ("add.f %4,%1,%1\n\trlc %0,0\n\t"
2641 "add.f 0,%4,%4\n\trlc %0,%0", operands
);
2643 output_asm_insn ("add.f %0,%1,%1\n\trlc.f %0,0\n\t"
2644 "and %0,%0,1\n\trlc %0,%0", operands
);
2651 else if (n
== BITS_PER_WORD
- 3 && code
== ASHIFT
)
2652 output_asm_insn ("and %0,%1,7\n\tror %0,%0\n\tror %0,%0\n\tror %0,%0",
2657 operands
[2] = GEN_INT (n
);
2658 output_asm_insn ("mov.f lp_count, %2", operands
);
2662 output_asm_insn ("lpnz\t2f", operands
);
2663 output_asm_insn (shift_one
, operands
);
2664 output_asm_insn ("nop", operands
);
2665 fprintf (asm_out_file
, "2:\t%s end single insn loop\n",
2674 /* Nested function support. */
2676 /* Directly store VALUE into memory object BLOCK at OFFSET. */
2679 emit_store_direct (rtx block
, int offset
, int value
)
2681 emit_insn (gen_store_direct (adjust_address (block
, SImode
, offset
),
2683 gen_int_mode (value
, SImode
))));
2686 /* Emit RTL insns to initialize the variable parts of a trampoline.
2687 FNADDR is an RTX for the address of the function's pure code.
2688 CXT is an RTX for the static chain value for the function. */
2689 /* With potentially multiple shared objects loaded, and multiple stacks
2690 present for multiple thereds where trampolines might reside, a simple
2691 range check will likely not suffice for the profiler to tell if a callee
2692 is a trampoline. We a speedier check by making the trampoline start at
2693 an address that is not 4-byte aligned.
2694 A trampoline looks like this:
2698 ld_s r12,[pcl,12] 0xd403
2699 ld r11,[pcl,12] 0x170c 700b
2703 The fastest trampoline to execute for trampolines within +-8KB of CTX
2706 j [limm] 0x20200f80 limm
2707 and that would also be faster to write to the stack by computing the offset
2708 from CTX to TRAMP at compile time. However, it would really be better to
2709 get rid of the high cost of cache invalidation when generating trampolines,
2710 which requires that the code part of trampolines stays constant, and
2712 - making sure that no executable code but trampolines is on the stack,
2713 no icache entries linger for the area of the stack from when before the
2714 stack was allocated, and allocating trampolines in trampoline-only
2717 - allocate trampolines fram a special pool of pre-allocated trampolines. */
2720 arc_initialize_trampoline (rtx tramp
, tree fndecl
, rtx cxt
)
2722 rtx fnaddr
= XEXP (DECL_RTL (fndecl
), 0);
2724 emit_store_direct (tramp
, 0, TARGET_BIG_ENDIAN
? 0x78e0d403 : 0xd40378e0);
2725 emit_store_direct (tramp
, 4, TARGET_BIG_ENDIAN
? 0x170c700b : 0x700b170c);
2726 emit_store_direct (tramp
, 8, TARGET_BIG_ENDIAN
? 0x7c0078e0 : 0x78e07c00);
2727 emit_move_insn (adjust_address (tramp
, SImode
, 12), fnaddr
);
2728 emit_move_insn (adjust_address (tramp
, SImode
, 16), cxt
);
2729 emit_insn (gen_flush_icache (adjust_address (tramp
, SImode
, 0)));
2732 /* Allow the profiler to easily distinguish trampolines from normal
2736 arc_trampoline_adjust_address (rtx addr
)
2738 return plus_constant (Pmode
, addr
, 2);
2741 /* This is set briefly to 1 when we output a ".as" address modifer, and then
2742 reset when we output the scaled address. */
2743 static int output_scaled
= 0;
2745 /* Print operand X (an rtx) in assembler syntax to file FILE.
2746 CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
2747 For `%' followed by punctuation, CODE is the punctuation and X is null. */
2748 /* In final.c:output_asm_insn:
2751 'c' : constant address if CONSTANT_ADDRESS_P
2757 '#': condbranch delay slot suffix
2758 '*': jump delay slot suffix
2759 '?' : nonjump-insn suffix for conditional execution or short instruction
2760 '!' : jump / call suffix for conditional execution or short instruction
2761 '`': fold constant inside unary o-perator, re-recognize, and emit.
2766 'B': Branch comparison operand - suppress sda reference
2767 'H': Most significant word
2768 'L': Least significant word
2769 'A': ASCII decimal representation of floating point value
2770 'U': Load/store update or scaling indicator
2771 'V': cache bypass indicator for volatile
2776 'o': original symbol - no @ prepending. */
2779 arc_print_operand (FILE *file
, rtx x
, int code
)
2784 if (GET_CODE (x
) == CONST_INT
)
2785 fprintf (file
, "%d",exact_log2(INTVAL (x
) + 1) - 1 );
2787 output_operand_lossage ("invalid operand to %%Z code");
2792 if (GET_CODE (x
) == CONST_INT
)
2793 fprintf (file
, "%d",exact_log2(INTVAL (x
)) );
2795 output_operand_lossage ("invalid operand to %%z code");
2800 if (GET_CODE (x
) == CONST_INT
)
2801 fprintf (file
, "%d",exact_log2(~INTVAL (x
)) );
2803 output_operand_lossage ("invalid operand to %%M code");
2808 /* Conditional branches depending on condition codes.
2809 Note that this is only for branches that were known to depend on
2810 condition codes before delay slot scheduling;
2811 out-of-range brcc / bbit expansions should use '*'.
2812 This distinction is important because of the different
2813 allowable delay slot insns and the output of the delay suffix
2814 for TARGET_AT_DBR_COND_EXEC. */
2816 /* Unconditional branches / branches not depending on condition codes.
2817 This could also be a CALL_INSN.
2818 Output the appropriate delay slot suffix. */
2819 if (final_sequence
&& XVECLEN (final_sequence
, 0) != 1)
2821 rtx jump
= XVECEXP (final_sequence
, 0, 0);
2822 rtx delay
= XVECEXP (final_sequence
, 0, 1);
2824 /* For TARGET_PAD_RETURN we might have grabbed the delay insn. */
2825 if (INSN_DELETED_P (delay
))
2827 if (JUMP_P (jump
) && INSN_ANNULLED_BRANCH_P (jump
))
2828 fputs (INSN_FROM_TARGET_P (delay
) ? ".d"
2829 : TARGET_AT_DBR_CONDEXEC
&& code
== '#' ? ".d"
2830 : get_attr_type (jump
) == TYPE_RETURN
&& code
== '#' ? ""
2837 case '?' : /* with leading "." */
2838 case '!' : /* without leading "." */
2839 /* This insn can be conditionally executed. See if the ccfsm machinery
2840 says it should be conditionalized.
2841 If it shouldn't, we'll check the compact attribute if this insn
2842 has a short variant, which may be used depending on code size and
2843 alignment considerations. */
2844 if (current_insn_predicate
)
2845 arc_ccfsm_current
.cc
2846 = get_arc_condition_code (current_insn_predicate
);
2847 if (ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current
))
2849 /* Is this insn in a delay slot sequence? */
2850 if (!final_sequence
|| XVECLEN (final_sequence
, 0) < 2
2851 || current_insn_predicate
2852 || CALL_P (XVECEXP (final_sequence
, 0, 0))
2853 || simplejump_p (XVECEXP (final_sequence
, 0, 0)))
2855 /* This insn isn't in a delay slot sequence, or conditionalized
2856 independently of its position in a delay slot. */
2857 fprintf (file
, "%s%s",
2858 code
== '?' ? "." : "",
2859 arc_condition_codes
[arc_ccfsm_current
.cc
]);
2860 /* If this is a jump, there are still short variants. However,
2861 only beq_s / bne_s have the same offset range as b_s,
2862 and the only short conditional returns are jeq_s and jne_s. */
2864 && (arc_ccfsm_current
.cc
== ARC_CC_EQ
2865 || arc_ccfsm_current
.cc
== ARC_CC_NE
2866 || 0 /* FIXME: check if branch in 7 bit range. */))
2867 output_short_suffix (file
);
2869 else if (code
== '!') /* Jump with delay slot. */
2870 fputs (arc_condition_codes
[arc_ccfsm_current
.cc
], file
);
2871 else /* An Instruction in a delay slot of a jump or call. */
2873 rtx jump
= XVECEXP (final_sequence
, 0, 0);
2874 rtx insn
= XVECEXP (final_sequence
, 0, 1);
2876 /* If the insn is annulled and is from the target path, we need
2877 to inverse the condition test. */
2878 if (JUMP_P (jump
) && INSN_ANNULLED_BRANCH_P (jump
))
2880 if (INSN_FROM_TARGET_P (insn
))
2881 fprintf (file
, "%s%s",
2882 code
== '?' ? "." : "",
2883 arc_condition_codes
[ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current
.cc
)]);
2885 fprintf (file
, "%s%s",
2886 code
== '?' ? "." : "",
2887 arc_condition_codes
[arc_ccfsm_current
.cc
]);
2888 if (arc_ccfsm_current
.state
== 5)
2889 arc_ccfsm_current
.state
= 0;
2892 /* This insn is executed for either path, so don't
2893 conditionalize it at all. */
2894 output_short_suffix (file
);
2899 output_short_suffix (file
);
2902 /* FIXME: fold constant inside unary operator, re-recognize, and emit. */
2905 fputs (arc_condition_codes
[get_arc_condition_code (x
)], file
);
2908 fputs (arc_condition_codes
[ARC_INVERSE_CONDITION_CODE
2909 (get_arc_condition_code (x
))],
2913 /* Write second word of DImode or DFmode reference,
2914 register or memory. */
2915 if (GET_CODE (x
) == REG
)
2916 fputs (reg_names
[REGNO (x
)+1], file
);
2917 else if (GET_CODE (x
) == MEM
)
2921 /* Handle possible auto-increment. For PRE_INC / PRE_DEC /
2922 PRE_MODIFY, we will have handled the first word already;
2923 For POST_INC / POST_DEC / POST_MODIFY, the access to the
2924 first word will be done later. In either case, the access
2925 to the first word will do the modify, and we only have
2926 to add an offset of four here. */
2927 if (GET_CODE (XEXP (x
, 0)) == PRE_INC
2928 || GET_CODE (XEXP (x
, 0)) == PRE_DEC
2929 || GET_CODE (XEXP (x
, 0)) == PRE_MODIFY
2930 || GET_CODE (XEXP (x
, 0)) == POST_INC
2931 || GET_CODE (XEXP (x
, 0)) == POST_DEC
2932 || GET_CODE (XEXP (x
, 0)) == POST_MODIFY
)
2933 output_address (plus_constant (Pmode
, XEXP (XEXP (x
, 0), 0), 4));
2934 else if (output_scaled
)
2936 rtx addr
= XEXP (x
, 0);
2937 int size
= GET_MODE_SIZE (GET_MODE (x
));
2939 output_address (plus_constant (Pmode
, XEXP (addr
, 0),
2940 ((INTVAL (XEXP (addr
, 1)) + 4)
2941 >> (size
== 2 ? 1 : 2))));
2945 output_address (plus_constant (Pmode
, XEXP (x
, 0), 4));
2949 output_operand_lossage ("invalid operand to %%R code");
2952 /* FIXME: remove %S option. */
2954 case 'B' /* Branch or other LIMM ref - must not use sda references. */ :
2957 output_addr_const (file
, x
);
2963 if (GET_CODE (x
) == REG
)
2965 /* L = least significant word, H = most significant word. */
2966 if ((WORDS_BIG_ENDIAN
!= 0) ^ (code
== 'L'))
2967 fputs (reg_names
[REGNO (x
)], file
);
2969 fputs (reg_names
[REGNO (x
)+1], file
);
2971 else if (GET_CODE (x
) == CONST_INT
2972 || GET_CODE (x
) == CONST_DOUBLE
)
2976 split_double (x
, &first
, &second
);
2978 if((WORDS_BIG_ENDIAN
) == 0)
2979 fprintf (file
, "0x%08lx",
2980 code
== 'L' ? INTVAL (first
) : INTVAL (second
));
2982 fprintf (file
, "0x%08lx",
2983 code
== 'L' ? INTVAL (second
) : INTVAL (first
));
2988 output_operand_lossage ("invalid operand to %%H/%%L code");
2994 gcc_assert (GET_CODE (x
) == CONST_DOUBLE
2995 && GET_MODE_CLASS (GET_MODE (x
)) == MODE_FLOAT
);
2997 real_to_decimal (str
, CONST_DOUBLE_REAL_VALUE (x
), sizeof (str
), 0, 1);
2998 fprintf (file
, "%s", str
);
3002 /* Output a load/store with update indicator if appropriate. */
3003 if (GET_CODE (x
) == MEM
)
3005 rtx addr
= XEXP (x
, 0);
3006 switch (GET_CODE (addr
))
3008 case PRE_INC
: case PRE_DEC
: case PRE_MODIFY
:
3009 fputs (".a", file
); break;
3010 case POST_INC
: case POST_DEC
: case POST_MODIFY
:
3011 fputs (".ab", file
); break;
3013 /* Are we using a scaled index? */
3014 if (GET_CODE (XEXP (addr
, 0)) == MULT
)
3015 fputs (".as", file
);
3016 /* Can we use a scaled offset? */
3017 else if (CONST_INT_P (XEXP (addr
, 1))
3018 && GET_MODE_SIZE (GET_MODE (x
)) > 1
3019 && (!(INTVAL (XEXP (addr
, 1))
3020 & (GET_MODE_SIZE (GET_MODE (x
)) - 1) & 3))
3021 /* Does it make a difference? */
3022 && !SMALL_INT_RANGE(INTVAL (XEXP (addr
, 1)),
3023 GET_MODE_SIZE (GET_MODE (x
)) - 2, 0))
3025 fputs (".as", file
);
3032 gcc_assert (CONSTANT_P (addr
)); break;
3036 output_operand_lossage ("invalid operand to %%U code");
3039 /* Output cache bypass indicator for a load/store insn. Volatile memory
3040 refs are defined to use the cache bypass mechanism. */
3041 if (GET_CODE (x
) == MEM
)
3043 if (MEM_VOLATILE_P (x
) && !TARGET_VOLATILE_CACHE_SET
)
3044 fputs (".di", file
);
3047 output_operand_lossage ("invalid operand to %%V code");
3052 /* Do nothing special. */
3055 fputs (reg_names
[REGNO (x
)]+1, file
);
3058 /* This punctuation character is needed because label references are
3059 printed in the output template using %l. This is a front end
3060 character, and when we want to emit a '@' before it, we have to use
3066 /* Output an operator. */
3067 switch (GET_CODE (x
))
3069 case PLUS
: fputs ("add", file
); return;
3070 case SS_PLUS
: fputs ("adds", file
); return;
3071 case AND
: fputs ("and", file
); return;
3072 case IOR
: fputs ("or", file
); return;
3073 case XOR
: fputs ("xor", file
); return;
3074 case MINUS
: fputs ("sub", file
); return;
3075 case SS_MINUS
: fputs ("subs", file
); return;
3076 case ASHIFT
: fputs ("asl", file
); return;
3077 case ASHIFTRT
: fputs ("asr", file
); return;
3078 case LSHIFTRT
: fputs ("lsr", file
); return;
3079 case ROTATERT
: fputs ("ror", file
); return;
3080 case MULT
: fputs ("mpy", file
); return;
3081 case ABS
: fputs ("abs", file
); return; /* Unconditional. */
3082 case NEG
: fputs ("neg", file
); return;
3083 case SS_NEG
: fputs ("negs", file
); return;
3084 case NOT
: fputs ("not", file
); return; /* Unconditional. */
3086 fputs ("ext", file
); /* bmsk allows predication. */
3088 case SIGN_EXTEND
: /* Unconditional. */
3089 fputs ("sex", file
);
3091 switch (GET_MODE (XEXP (x
, 0)))
3093 case QImode
: fputs ("b", file
); return;
3094 case HImode
: fputs ("w", file
); return;
3099 if (GET_MODE (x
) != HImode
)
3101 fputs ("sat16", file
);
3104 output_operand_lossage ("invalid operand to %%O code"); return;
3106 if (GET_CODE (x
) == SYMBOL_REF
)
3108 assemble_name (file
, XSTR (x
, 0));
3113 if (TARGET_ANNOTATE_ALIGN
&& cfun
->machine
->size_reason
)
3114 fprintf (file
, "; unalign: %d", cfun
->machine
->unalign
);
3118 output_operand_lossage ("invalid operand output code");
3121 switch (GET_CODE (x
))
3124 fputs (reg_names
[REGNO (x
)], file
);
3128 rtx addr
= XEXP (x
, 0);
3129 int size
= GET_MODE_SIZE (GET_MODE (x
));
3133 switch (GET_CODE (addr
))
3135 case PRE_INC
: case POST_INC
:
3136 output_address (plus_constant (Pmode
, XEXP (addr
, 0), size
)); break;
3137 case PRE_DEC
: case POST_DEC
:
3138 output_address (plus_constant (Pmode
, XEXP (addr
, 0), -size
));
3140 case PRE_MODIFY
: case POST_MODIFY
:
3141 output_address (XEXP (addr
, 1)); break;
3145 output_address (plus_constant (Pmode
, XEXP (addr
, 0),
3146 (INTVAL (XEXP (addr
, 1))
3147 >> (size
== 2 ? 1 : 2))));
3151 output_address (addr
);
3154 if (flag_pic
&& CONSTANT_ADDRESS_P (addr
))
3155 arc_output_pic_addr_const (file
, addr
, code
);
3157 output_address (addr
);
3164 /* We handle SFmode constants here as output_addr_const doesn't. */
3165 if (GET_MODE (x
) == SFmode
)
3170 REAL_VALUE_FROM_CONST_DOUBLE (d
, x
);
3171 REAL_VALUE_TO_TARGET_SINGLE (d
, l
);
3172 fprintf (file
, "0x%08lx", l
);
3175 /* Fall through. Let output_addr_const deal with it. */
3178 arc_output_pic_addr_const (file
, x
, code
);
3181 /* FIXME: Dirty way to handle @var@sda+const. Shd be handled
3182 with asm_output_symbol_ref */
3183 if (GET_CODE (x
) == CONST
&& GET_CODE (XEXP (x
, 0)) == PLUS
)
3186 output_addr_const (file
, XEXP (x
, 0));
3187 if (GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
&& SYMBOL_REF_SMALL_P (XEXP (x
, 0)))
3188 fprintf (file
, "@sda");
3190 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
3191 || INTVAL (XEXP (x
, 1)) >= 0)
3192 fprintf (file
, "+");
3193 output_addr_const (file
, XEXP (x
, 1));
3196 output_addr_const (file
, x
);
3198 if (GET_CODE (x
) == SYMBOL_REF
&& SYMBOL_REF_SMALL_P (x
))
3199 fprintf (file
, "@sda");
3204 /* Print a memory address as an operand to reference that memory location. */
3207 arc_print_operand_address (FILE *file
, rtx addr
)
3209 register rtx base
, index
= 0;
3211 switch (GET_CODE (addr
))
3214 fputs (reg_names
[REGNO (addr
)], file
);
3217 output_addr_const (file
, addr
);
3218 if (SYMBOL_REF_SMALL_P (addr
))
3219 fprintf (file
, "@sda");
3222 if (GET_CODE (XEXP (addr
, 0)) == MULT
)
3223 index
= XEXP (XEXP (addr
, 0), 0), base
= XEXP (addr
, 1);
3224 else if (CONST_INT_P (XEXP (addr
, 0)))
3225 index
= XEXP (addr
, 0), base
= XEXP (addr
, 1);
3227 base
= XEXP (addr
, 0), index
= XEXP (addr
, 1);
3229 gcc_assert (OBJECT_P (base
));
3230 arc_print_operand_address (file
, base
);
3231 if (CONSTANT_P (base
) && CONST_INT_P (index
))
3235 gcc_assert (OBJECT_P (index
));
3236 arc_print_operand_address (file
, index
);
3240 rtx c
= XEXP (addr
, 0);
3242 gcc_assert (GET_CODE (XEXP (c
, 0)) == SYMBOL_REF
);
3243 gcc_assert (GET_CODE (XEXP (c
, 1)) == CONST_INT
);
3245 output_address(XEXP(addr
,0));
3251 /* We shouldn't get here as we've lost the mode of the memory object
3252 (which says how much to inc/dec by. */
3257 arc_output_pic_addr_const (file
, addr
, 0);
3259 output_addr_const (file
, addr
);
3264 /* Called via walk_stores. DATA points to a hash table we can use to
3265 establish a unique SYMBOL_REF for each counter, which corresponds to
3266 a caller-callee pair.
3267 X is a store which we want to examine for an UNSPEC_PROF, which
3268 would be an address loaded into a register, or directly used in a MEM.
3269 If we found an UNSPEC_PROF, if we encounter a new counter the first time,
3270 write out a description and a data allocation for a 32 bit counter.
3271 Also, fill in the appropriate symbol_ref into each UNSPEC_PROF instance. */
3274 write_profile_sections (rtx dest ATTRIBUTE_UNUSED
, rtx x
, void *data
)
3277 htab_t htab
= (htab_t
) data
;
3280 if (GET_CODE (x
) != SET
)
3282 srcp
= &SET_SRC (x
);
3284 srcp
= &XEXP (*srcp
, 0);
3285 else if (MEM_P (SET_DEST (x
)))
3286 srcp
= &XEXP (SET_DEST (x
), 0);
3288 if (GET_CODE (src
) != CONST
)
3290 src
= XEXP (src
, 0);
3291 if (GET_CODE (src
) != UNSPEC
|| XINT (src
, 1) != UNSPEC_PROF
)
3294 gcc_assert (XVECLEN (src
, 0) == 3);
3295 if (!htab_elements (htab
))
3297 output_asm_insn (".section .__arc_profile_desc, \"a\"\n"
3299 &XVECEXP (src
, 0, 0));
3301 slot
= (rtx
*) htab_find_slot (htab
, src
, INSERT
);
3302 if (*slot
== HTAB_EMPTY_ENTRY
)
3304 static int count_nr
;
3309 sprintf (buf
, "__prof_count%d", count_nr
++);
3310 count
= gen_rtx_SYMBOL_REF (Pmode
, xstrdup (buf
));
3311 XVECEXP (src
, 0, 2) = count
;
3312 output_asm_insn (".section\t.__arc_profile_desc, \"a\"\n"
3314 "\t.section\t.__arc_profile_counters, \"aw\"\n"
3315 "\t.type\t%o2, @object\n"
3318 &XVECEXP (src
, 0, 0));
3322 *srcp
= XVECEXP (*slot
, 0, 2);
3325 /* Hash function for UNSPEC_PROF htab. Use both the caller's name and
3326 the callee's name (if known). */
3329 unspec_prof_hash (const void *x
)
3331 const_rtx u
= (const_rtx
) x
;
3332 const_rtx s1
= XVECEXP (u
, 0, 1);
3334 return (htab_hash_string (XSTR (XVECEXP (u
, 0, 0), 0))
3335 ^ (s1
->code
== SYMBOL_REF
? htab_hash_string (XSTR (s1
, 0)) : 0));
3338 /* Equality function for UNSPEC_PROF htab. Two pieces of UNSPEC_PROF rtl
3339 shall refer to the same counter if both caller name and callee rtl
3343 unspec_prof_htab_eq (const void *x
, const void *y
)
3345 const_rtx u0
= (const_rtx
) x
;
3346 const_rtx u1
= (const_rtx
) y
;
3347 const_rtx s01
= XVECEXP (u0
, 0, 1);
3348 const_rtx s11
= XVECEXP (u1
, 0, 1);
3350 return (!strcmp (XSTR (XVECEXP (u0
, 0, 0), 0),
3351 XSTR (XVECEXP (u1
, 0, 0), 0))
3352 && rtx_equal_p (s01
, s11
));
3355 /* Conditional execution support.
3357 This is based on the ARM port but for now is much simpler.
3359 A finite state machine takes care of noticing whether or not instructions
3360 can be conditionally executed, and thus decrease execution time and code
3361 size by deleting branch instructions. The fsm is controlled by
3362 arc_ccfsm_advance (called by arc_final_prescan_insn), and controls the
3363 actions of PRINT_OPERAND. The patterns in the .md file for the branch
3364 insns also have a hand in this. */
3365 /* The way we leave dealing with non-anulled or annull-false delay slot
3366 insns to the consumer is awkward. */
3368 /* The state of the fsm controlling condition codes are:
3369 0: normal, do nothing special
3370 1: don't output this insn
3371 2: don't output this insn
3372 3: make insns conditional
3373 4: make insns conditional
3374 5: make insn conditional (only for outputting anulled delay slot insns)
3376 special value for cfun->machine->uid_ccfsm_state:
3377 6: return with but one insn before it since function start / call
3379 State transitions (state->state by whom, under what condition):
3380 0 -> 1 arc_ccfsm_advance, if insn is a conditional branch skipping over
3382 0 -> 2 arc_ccfsm_advance, if insn is a conditional branch followed
3383 by zero or more non-jump insns and an unconditional branch with
3384 the same target label as the condbranch.
3385 1 -> 3 branch patterns, after having not output the conditional branch
3386 2 -> 4 branch patterns, after having not output the conditional branch
3387 0 -> 5 branch patterns, for anulled delay slot insn.
3388 3 -> 0 ASM_OUTPUT_INTERNAL_LABEL, if the `target' label is reached
3389 (the target label has CODE_LABEL_NUMBER equal to
3390 arc_ccfsm_target_label).
3391 4 -> 0 arc_ccfsm_advance, if `target' unconditional branch is reached
3392 3 -> 1 arc_ccfsm_advance, finding an 'else' jump skipping over some insns.
3393 5 -> 0 when outputting the delay slot insn
3395 If the jump clobbers the conditions then we use states 2 and 4.
3397 A similar thing can be done with conditional return insns.
3399 We also handle separating branches from sets of the condition code.
3400 This is done here because knowledge of the ccfsm state is required,
3401 we may not be outputting the branch. */
3403 /* arc_final_prescan_insn calls arc_ccfsm_advance to adjust arc_ccfsm_current,
3404 before letting final output INSN. */
3407 arc_ccfsm_advance (rtx insn
, struct arc_ccfsm
*state
)
3409 /* BODY will hold the body of INSN. */
3412 /* This will be 1 if trying to repeat the trick (ie: do the `else' part of
3413 an if/then/else), and things need to be reversed. */
3416 /* If we start with a return insn, we only succeed if we find another one. */
3417 int seeking_return
= 0;
3419 /* START_INSN will hold the insn from where we start looking. This is the
3420 first insn after the following code_label if REVERSE is true. */
3421 rtx start_insn
= insn
;
3423 /* Type of the jump_insn. Brcc insns don't affect ccfsm changes,
3424 since they don't rely on a cmp preceding the. */
3425 enum attr_type jump_insn_type
;
3427 /* Allow -mdebug-ccfsm to turn this off so we can see how well it does.
3428 We can't do this in macro FINAL_PRESCAN_INSN because its called from
3429 final_scan_insn which has `optimize' as a local. */
3430 if (optimize
< 2 || TARGET_NO_COND_EXEC
)
3433 /* Ignore notes and labels. */
3436 body
= PATTERN (insn
);
3437 /* If in state 4, check if the target branch is reached, in order to
3438 change back to state 0. */
3439 if (state
->state
== 4)
3441 if (insn
== state
->target_insn
)
3443 state
->target_insn
= NULL
;
3449 /* If in state 3, it is possible to repeat the trick, if this insn is an
3450 unconditional branch to a label, and immediately following this branch
3451 is the previous target label which is only used once, and the label this
3452 branch jumps to is not too far off. Or in other words "we've done the
3453 `then' part, see if we can do the `else' part." */
3454 if (state
->state
== 3)
3456 if (simplejump_p (insn
))
3458 start_insn
= next_nonnote_insn (start_insn
);
3459 if (GET_CODE (start_insn
) == BARRIER
)
3461 /* ??? Isn't this always a barrier? */
3462 start_insn
= next_nonnote_insn (start_insn
);
3464 if (GET_CODE (start_insn
) == CODE_LABEL
3465 && CODE_LABEL_NUMBER (start_insn
) == state
->target_label
3466 && LABEL_NUSES (start_insn
) == 1)
3471 else if (GET_CODE (body
) == SIMPLE_RETURN
)
3473 start_insn
= next_nonnote_insn (start_insn
);
3474 if (GET_CODE (start_insn
) == BARRIER
)
3475 start_insn
= next_nonnote_insn (start_insn
);
3476 if (GET_CODE (start_insn
) == CODE_LABEL
3477 && CODE_LABEL_NUMBER (start_insn
) == state
->target_label
3478 && LABEL_NUSES (start_insn
) == 1)
3490 if (GET_CODE (insn
) != JUMP_INSN
3491 || GET_CODE (PATTERN (insn
)) == ADDR_VEC
3492 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
3495 /* We can't predicate BRCC or loop ends.
3496 Also, when generating PIC code, and considering a medium range call,
3497 we can't predicate the call. */
3498 jump_insn_type
= get_attr_type (insn
);
3499 if (jump_insn_type
== TYPE_BRCC
3500 || jump_insn_type
== TYPE_BRCC_NO_DELAY_SLOT
3501 || jump_insn_type
== TYPE_LOOP_END
3502 || (jump_insn_type
== TYPE_CALL
&& !get_attr_predicable (insn
)))
3505 /* This jump might be paralleled with a clobber of the condition codes,
3506 the jump should always come first. */
3507 if (GET_CODE (body
) == PARALLEL
&& XVECLEN (body
, 0) > 0)
3508 body
= XVECEXP (body
, 0, 0);
3511 || (GET_CODE (body
) == SET
&& GET_CODE (SET_DEST (body
)) == PC
3512 && GET_CODE (SET_SRC (body
)) == IF_THEN_ELSE
))
3514 int insns_skipped
= 0, fail
= FALSE
, succeed
= FALSE
;
3515 /* Flag which part of the IF_THEN_ELSE is the LABEL_REF. */
3516 int then_not_else
= TRUE
;
3517 /* Nonzero if next insn must be the target label. */
3518 int next_must_be_target_label_p
;
3519 rtx this_insn
= start_insn
, label
= 0;
3521 /* Register the insn jumped to. */
3524 if (!seeking_return
)
3525 label
= XEXP (SET_SRC (body
), 0);
3527 else if (GET_CODE (XEXP (SET_SRC (body
), 1)) == LABEL_REF
)
3528 label
= XEXP (XEXP (SET_SRC (body
), 1), 0);
3529 else if (GET_CODE (XEXP (SET_SRC (body
), 2)) == LABEL_REF
)
3531 label
= XEXP (XEXP (SET_SRC (body
), 2), 0);
3532 then_not_else
= FALSE
;
3534 else if (GET_CODE (XEXP (SET_SRC (body
), 1)) == SIMPLE_RETURN
)
3536 else if (GET_CODE (XEXP (SET_SRC (body
), 2)) == SIMPLE_RETURN
)
3539 then_not_else
= FALSE
;
3544 /* If this is a non-annulled branch with a delay slot, there is
3545 no need to conditionalize the delay slot. */
3546 if (NEXT_INSN (PREV_INSN (insn
)) != insn
3547 && state
->state
== 0 && !INSN_ANNULLED_BRANCH_P (insn
))
3549 this_insn
= NEXT_INSN (this_insn
);
3550 gcc_assert (NEXT_INSN (NEXT_INSN (PREV_INSN (start_insn
)))
3551 == NEXT_INSN (this_insn
));
3553 /* See how many insns this branch skips, and what kind of insns. If all
3554 insns are okay, and the label or unconditional branch to the same
3555 label is not too far away, succeed. */
3556 for (insns_skipped
= 0, next_must_be_target_label_p
= FALSE
;
3557 !fail
&& !succeed
&& insns_skipped
< MAX_INSNS_SKIPPED
;
3562 this_insn
= next_nonnote_insn (this_insn
);
3566 if (next_must_be_target_label_p
)
3568 if (GET_CODE (this_insn
) == BARRIER
)
3570 if (GET_CODE (this_insn
) == CODE_LABEL
3571 && this_insn
== label
)
3581 scanbody
= PATTERN (this_insn
);
3583 switch (GET_CODE (this_insn
))
3586 /* Succeed if it is the target label, otherwise fail since
3587 control falls in from somewhere else. */
3588 if (this_insn
== label
)
3598 /* Succeed if the following insn is the target label.
3600 If return insns are used then the last insn in a function
3601 will be a barrier. */
3602 next_must_be_target_label_p
= TRUE
;
3606 /* Can handle a call insn if there are no insns after it.
3607 IE: The next "insn" is the target label. We don't have to
3608 worry about delay slots as such insns are SEQUENCE's inside
3609 INSN's. ??? It is possible to handle such insns though. */
3610 if (get_attr_cond (this_insn
) == COND_CANUSE
)
3611 next_must_be_target_label_p
= TRUE
;
3617 /* If this is an unconditional branch to the same label, succeed.
3618 If it is to another label, do nothing. If it is conditional,
3620 /* ??? Probably, the test for the SET and the PC are
3623 if (GET_CODE (scanbody
) == SET
3624 && GET_CODE (SET_DEST (scanbody
)) == PC
)
3626 if (GET_CODE (SET_SRC (scanbody
)) == LABEL_REF
3627 && XEXP (SET_SRC (scanbody
), 0) == label
&& !reverse
)
3632 else if (GET_CODE (SET_SRC (scanbody
)) == IF_THEN_ELSE
)
3634 else if (get_attr_cond (this_insn
) != COND_CANUSE
)
3637 else if (GET_CODE (scanbody
) == SIMPLE_RETURN
3643 else if (GET_CODE (scanbody
) == PARALLEL
)
3645 if (get_attr_cond (this_insn
) != COND_CANUSE
)
3651 /* We can only do this with insns that can use the condition
3652 codes (and don't set them). */
3653 if (GET_CODE (scanbody
) == SET
3654 || GET_CODE (scanbody
) == PARALLEL
)
3656 if (get_attr_cond (this_insn
) != COND_CANUSE
)
3659 /* We can't handle other insns like sequences. */
3671 if ((!seeking_return
) && (state
->state
== 1 || reverse
))
3672 state
->target_label
= CODE_LABEL_NUMBER (label
);
3673 else if (seeking_return
|| state
->state
== 2)
3675 while (this_insn
&& GET_CODE (PATTERN (this_insn
)) == USE
)
3677 this_insn
= next_nonnote_insn (this_insn
);
3679 gcc_assert (!this_insn
||
3680 (GET_CODE (this_insn
) != BARRIER
3681 && GET_CODE (this_insn
) != CODE_LABEL
));
3685 /* Oh dear! we ran off the end, give up. */
3686 extract_insn_cached (insn
);
3688 state
->target_insn
= NULL
;
3691 state
->target_insn
= this_insn
;
3696 /* If REVERSE is true, ARM_CURRENT_CC needs to be inverted from
3700 state
->cond
= XEXP (SET_SRC (body
), 0);
3701 state
->cc
= get_arc_condition_code (XEXP (SET_SRC (body
), 0));
3704 if (reverse
|| then_not_else
)
3705 state
->cc
= ARC_INVERSE_CONDITION_CODE (state
->cc
);
3708 /* Restore recog_operand. Getting the attributes of other insns can
3709 destroy this array, but final.c assumes that it remains intact
3710 across this call; since the insn has been recognized already we
3711 call insn_extract direct. */
3712 extract_insn_cached (insn
);
3716 /* Record that we are currently outputting label NUM with prefix PREFIX.
3717 It it's the label we're looking for, reset the ccfsm machinery.
3719 Called from ASM_OUTPUT_INTERNAL_LABEL. */
3722 arc_ccfsm_at_label (const char *prefix
, int num
, struct arc_ccfsm
*state
)
3724 if (state
->state
== 3 && state
->target_label
== num
3725 && !strcmp (prefix
, "L"))
3728 state
->target_insn
= NULL_RTX
;
3732 /* We are considering a conditional branch with the condition COND.
3733 Check if we want to conditionalize a delay slot insn, and if so modify
3734 the ccfsm state accordingly.
3735 REVERSE says branch will branch when the condition is false. */
3737 arc_ccfsm_record_condition (rtx cond
, bool reverse
, rtx jump
,
3738 struct arc_ccfsm
*state
)
3740 rtx seq_insn
= NEXT_INSN (PREV_INSN (jump
));
3742 state
= &arc_ccfsm_current
;
3744 gcc_assert (state
->state
== 0);
3745 if (seq_insn
!= jump
)
3747 rtx insn
= XVECEXP (PATTERN (seq_insn
), 0, 1);
3749 if (!INSN_DELETED_P (insn
)
3750 && INSN_ANNULLED_BRANCH_P (jump
)
3751 && (TARGET_AT_DBR_CONDEXEC
|| INSN_FROM_TARGET_P (insn
)))
3754 state
->cc
= get_arc_condition_code (cond
);
3756 arc_ccfsm_current
.cc
3757 = ARC_INVERSE_CONDITION_CODE (state
->cc
);
3758 rtx pat
= PATTERN (insn
);
3759 if (GET_CODE (pat
) == COND_EXEC
)
3760 gcc_assert ((INSN_FROM_TARGET_P (insn
)
3761 ? ARC_INVERSE_CONDITION_CODE (state
->cc
) : state
->cc
)
3762 == get_arc_condition_code (XEXP (pat
, 0)));
3769 /* Update *STATE as we would when we emit INSN. */
3772 arc_ccfsm_post_advance (rtx insn
, struct arc_ccfsm
*state
)
3774 enum attr_type type
;
3777 arc_ccfsm_at_label ("L", CODE_LABEL_NUMBER (insn
), state
);
3778 else if (JUMP_P (insn
)
3779 && GET_CODE (PATTERN (insn
)) != ADDR_VEC
3780 && GET_CODE (PATTERN (insn
)) != ADDR_DIFF_VEC
3781 && ((type
= get_attr_type (insn
)) == TYPE_BRANCH
3782 || (type
== TYPE_UNCOND_BRANCH
3783 /* ??? Maybe should also handle TYPE_RETURN here,
3784 but we don't have a testcase for that. */
3785 && ARC_CCFSM_BRANCH_DELETED_P (state
))))
3787 if (ARC_CCFSM_BRANCH_DELETED_P (state
))
3788 ARC_CCFSM_RECORD_BRANCH_DELETED (state
);
3791 rtx src
= SET_SRC (PATTERN (insn
));
3792 arc_ccfsm_record_condition (XEXP (src
, 0), XEXP (src
, 1) == pc_rtx
,
3796 else if (arc_ccfsm_current
.state
== 5)
3797 arc_ccfsm_current
.state
= 0;
3800 /* Return true if the current insn, which is a conditional branch, is to be
3804 arc_ccfsm_branch_deleted_p (void)
3806 return ARC_CCFSM_BRANCH_DELETED_P (&arc_ccfsm_current
);
3809 /* Record a branch isn't output because subsequent insns can be
3813 arc_ccfsm_record_branch_deleted (void)
3815 ARC_CCFSM_RECORD_BRANCH_DELETED (&arc_ccfsm_current
);
3818 /* During insn output, indicate if the current insn is predicated. */
3821 arc_ccfsm_cond_exec_p (void)
3823 return (cfun
->machine
->prescan_initialized
3824 && ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current
));
3827 /* Like next_active_insn, but return NULL if we find an ADDR_(DIFF_)VEC,
3828 and look inside SEQUENCEs. */
3831 arc_next_active_insn (rtx insn
, struct arc_ccfsm
*statep
)
3838 arc_ccfsm_post_advance (insn
, statep
);
3839 insn
= NEXT_INSN (insn
);
3840 if (!insn
|| BARRIER_P (insn
))
3843 arc_ccfsm_advance (insn
, statep
);
3845 while (NOTE_P (insn
)
3846 || (cfun
->machine
->arc_reorg_started
3847 && LABEL_P (insn
) && !label_to_alignment (insn
))
3848 || (NONJUMP_INSN_P (insn
)
3849 && (GET_CODE (PATTERN (insn
)) == USE
3850 || GET_CODE (PATTERN (insn
)) == CLOBBER
)));
3851 if (!LABEL_P (insn
))
3853 gcc_assert (INSN_P (insn
));
3854 pat
= PATTERN (insn
);
3855 if (GET_CODE (pat
) == ADDR_VEC
|| GET_CODE (pat
) == ADDR_DIFF_VEC
)
3857 if (GET_CODE (pat
) == SEQUENCE
)
3858 return XVECEXP (pat
, 0, 0);
3863 /* When deciding if an insn should be output short, we want to know something
3864 about the following insns:
3865 - if another insn follows which we know we can output as a short insn
3866 before an alignment-sensitive point, we can output this insn short:
3867 the decision about the eventual alignment can be postponed.
3868 - if a to-be-aligned label comes next, we should output this insn such
3869 as to get / preserve 4-byte alignment.
3870 - if a likely branch without delay slot insn, or a call with an immediately
3871 following short insn comes next, we should out output this insn such as to
3872 get / preserve 2 mod 4 unalignment.
3873 - do the same for a not completely unlikely branch with a short insn
3874 following before any other branch / label.
3875 - in order to decide if we are actually looking at a branch, we need to
3876 call arc_ccfsm_advance.
3877 - in order to decide if we are looking at a short insn, we should know
3878 if it is conditionalized. To a first order of approximation this is
3879 the case if the state from arc_ccfsm_advance from before this insn
3880 indicates the insn is conditionalized. However, a further refinement
3881 could be to not conditionalize an insn if the destination register(s)
3882 is/are dead in the non-executed case. */
3883 /* Return non-zero if INSN should be output as a short insn. UNALIGN is
3884 zero if the current insn is aligned to a 4-byte-boundary, two otherwise.
3885 If CHECK_ATTR is greater than 0, check the iscompact attribute first. */
3888 arc_verify_short (rtx insn
, int, int check_attr
)
3890 enum attr_iscompact iscompact
;
3891 struct machine_function
*machine
;
3895 iscompact
= get_attr_iscompact (insn
);
3896 if (iscompact
== ISCOMPACT_FALSE
)
3899 machine
= cfun
->machine
;
3901 if (machine
->force_short_suffix
>= 0)
3902 return machine
->force_short_suffix
;
3904 return (get_attr_length (insn
) & 2) != 0;
3907 /* When outputting an instruction (alternative) that can potentially be short,
3908 output the short suffix if the insn is in fact short, and update
3909 cfun->machine->unalign accordingly. */
3912 output_short_suffix (FILE *file
)
3914 rtx insn
= current_output_insn
;
3916 if (arc_verify_short (insn
, cfun
->machine
->unalign
, 1))
3918 fprintf (file
, "_s");
3919 cfun
->machine
->unalign
^= 2;
3921 /* Restore recog_operand. */
3922 extract_insn_cached (insn
);
3925 /* Implement FINAL_PRESCAN_INSN. */
3928 arc_final_prescan_insn (rtx insn
, rtx
*opvec ATTRIBUTE_UNUSED
,
3929 int noperands ATTRIBUTE_UNUSED
)
3931 if (TARGET_DUMPISIZE
)
3932 fprintf (asm_out_file
, "\n; at %04x\n", INSN_ADDRESSES (INSN_UID (insn
)));
3934 /* Output a nop if necessary to prevent a hazard.
3935 Don't do this for delay slots: inserting a nop would
3936 alter semantics, and the only time we would find a hazard is for a
3937 call function result - and in that case, the hazard is spurious to
3939 if (PREV_INSN (insn
)
3940 && PREV_INSN (NEXT_INSN (insn
)) == insn
3941 && arc_hazard (prev_real_insn (insn
), insn
))
3943 current_output_insn
=
3944 emit_insn_before (gen_nop (), NEXT_INSN (PREV_INSN (insn
)));
3945 final_scan_insn (current_output_insn
, asm_out_file
, optimize
, 1, NULL
);
3946 current_output_insn
= insn
;
3948 /* Restore extraction data which might have been clobbered by arc_hazard. */
3949 extract_constrain_insn_cached (insn
);
3951 if (!cfun
->machine
->prescan_initialized
)
3953 /* Clear lingering state from branch shortening. */
3954 memset (&arc_ccfsm_current
, 0, sizeof arc_ccfsm_current
);
3955 cfun
->machine
->prescan_initialized
= 1;
3957 arc_ccfsm_advance (insn
, &arc_ccfsm_current
);
3959 cfun
->machine
->size_reason
= 0;
3962 /* Given FROM and TO register numbers, say whether this elimination is allowed.
3963 Frame pointer elimination is automatically handled.
3965 All eliminations are permissible. If we need a frame
3966 pointer, we must eliminate ARG_POINTER_REGNUM into
3967 FRAME_POINTER_REGNUM and not into STACK_POINTER_REGNUM. */
3970 arc_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to
)
3972 return to
== FRAME_POINTER_REGNUM
|| !arc_frame_pointer_required ();
3975 /* Define the offset between two registers, one to be eliminated, and
3976 the other its replacement, at the start of a routine. */
3979 arc_initial_elimination_offset (int from
, int to
)
3981 if (! cfun
->machine
->frame_info
.initialized
)
3982 arc_compute_frame_size (get_frame_size ());
3984 if (from
== ARG_POINTER_REGNUM
&& to
== FRAME_POINTER_REGNUM
)
3986 return (cfun
->machine
->frame_info
.extra_size
3987 + cfun
->machine
->frame_info
.reg_size
);
3990 if (from
== ARG_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
3992 return (cfun
->machine
->frame_info
.total_size
3993 - cfun
->machine
->frame_info
.pretend_size
);
3996 if ((from
== FRAME_POINTER_REGNUM
) && (to
== STACK_POINTER_REGNUM
))
3998 return (cfun
->machine
->frame_info
.total_size
3999 - (cfun
->machine
->frame_info
.pretend_size
4000 + cfun
->machine
->frame_info
.extra_size
4001 + cfun
->machine
->frame_info
.reg_size
));
4008 arc_frame_pointer_required (void)
4010 return cfun
->calls_alloca
;
4014 /* Return the destination address of a branch. */
4017 branch_dest (rtx branch
)
4019 rtx pat
= PATTERN (branch
);
4020 rtx dest
= (GET_CODE (pat
) == PARALLEL
4021 ? SET_SRC (XVECEXP (pat
, 0, 0)) : SET_SRC (pat
));
4024 if (GET_CODE (dest
) == IF_THEN_ELSE
)
4025 dest
= XEXP (dest
, XEXP (dest
, 1) == pc_rtx
? 2 : 1);
4027 dest
= XEXP (dest
, 0);
4028 dest_uid
= INSN_UID (dest
);
4030 return INSN_ADDRESSES (dest_uid
);
4034 /* Implement TARGET_ENCODE_SECTION_INFO hook. */
4037 arc_encode_section_info (tree decl
, rtx rtl
, int first
)
4039 /* For sdata, SYMBOL_FLAG_LOCAL and SYMBOL_FLAG_FUNCTION.
4040 This clears machine specific flags, so has to come first. */
4041 default_encode_section_info (decl
, rtl
, first
);
4043 /* Check if it is a function, and whether it has the
4044 [long/medium/short]_call attribute specified. */
4045 if (TREE_CODE (decl
) == FUNCTION_DECL
)
4047 rtx symbol
= XEXP (rtl
, 0);
4048 int flags
= SYMBOL_REF_FLAGS (symbol
);
4050 tree attr
= (TREE_TYPE (decl
) != error_mark_node
4051 ? TYPE_ATTRIBUTES (TREE_TYPE (decl
)) : NULL_TREE
);
4052 tree long_call_attr
= lookup_attribute ("long_call", attr
);
4053 tree medium_call_attr
= lookup_attribute ("medium_call", attr
);
4054 tree short_call_attr
= lookup_attribute ("short_call", attr
);
4056 if (long_call_attr
!= NULL_TREE
)
4057 flags
|= SYMBOL_FLAG_LONG_CALL
;
4058 else if (medium_call_attr
!= NULL_TREE
)
4059 flags
|= SYMBOL_FLAG_MEDIUM_CALL
;
4060 else if (short_call_attr
!= NULL_TREE
)
4061 flags
|= SYMBOL_FLAG_SHORT_CALL
;
4063 SYMBOL_REF_FLAGS (symbol
) = flags
;
4067 /* This is how to output a definition of an internal numbered label where
4068 PREFIX is the class of label and NUM is the number within the class. */
4070 static void arc_internal_label (FILE *stream
, const char *prefix
, unsigned long labelno
)
4073 arc_ccfsm_at_label (prefix
, labelno
, &arc_ccfsm_current
);
4074 default_internal_label (stream
, prefix
, labelno
);
4077 /* Set the cpu type and print out other fancy things,
4078 at the top of the file. */
4080 static void arc_file_start (void)
4082 default_file_start ();
4083 fprintf (asm_out_file
, "\t.cpu %s\n", arc_cpu_string
);
4086 /* Cost functions. */
4088 /* Compute a (partial) cost for rtx X. Return true if the complete
4089 cost has been computed, and false if subexpressions should be
4090 scanned. In either case, *TOTAL contains the cost result. */
4093 arc_rtx_costs (rtx x
, int code
, int outer_code
, int opno ATTRIBUTE_UNUSED
,
4094 int *total
, bool speed
)
4098 /* Small integers are as cheap as registers. */
4101 bool nolimm
= false; /* Can we do without long immediate? */
4102 bool fast
= false; /* Is the result available immediately? */
4103 bool condexec
= false; /* Does this allow conditiobnal execution? */
4104 bool compact
= false; /* Is a 16 bit opcode available? */
4105 /* CONDEXEC also implies that we can have an unconditional
4106 3-address operation. */
4108 nolimm
= compact
= condexec
= false;
4109 if (UNSIGNED_INT6 (INTVAL (x
)))
4110 nolimm
= condexec
= compact
= true;
4113 if (SMALL_INT (INTVAL (x
)))
4114 nolimm
= fast
= true;
4117 case AND
: /* bclr, bmsk, ext[bw] */
4118 if (satisfies_constraint_Ccp (x
) /* bclr */
4119 || satisfies_constraint_C1p (x
) /* bmsk */)
4120 nolimm
= fast
= condexec
= compact
= true;
4122 case IOR
: /* bset */
4123 if (satisfies_constraint_C0p (x
)) /* bset */
4124 nolimm
= fast
= condexec
= compact
= true;
4127 if (satisfies_constraint_C0p (x
)) /* bxor */
4128 nolimm
= fast
= condexec
= true;
4131 if (satisfies_constraint_Crr (x
)) /* ror b,u6 */
4137 /* FIXME: Add target options to attach a small cost if
4138 condexec / compact is not true. */
4147 /* 4 byte values can be fetched as immediate constants -
4148 let's give that the cost of an extra insn. */
4152 *total
= COSTS_N_INSNS (1);
4161 *total
= COSTS_N_INSNS (1);
4164 /* FIXME: correct the order of high,low */
4165 split_double (x
, &high
, &low
);
4166 *total
= COSTS_N_INSNS (!SMALL_INT (INTVAL (high
))
4167 + !SMALL_INT (INTVAL (low
)));
4171 /* Encourage synth_mult to find a synthetic multiply when reasonable.
4172 If we need more than 12 insns to do a multiply, then go out-of-line,
4173 since the call overhead will be < 10% of the cost of the multiply. */
4177 if (TARGET_BARREL_SHIFTER
)
4179 /* If we want to shift a constant, we need a LIMM. */
4180 /* ??? when the optimizers want to know if a constant should be
4181 hoisted, they ask for the cost of the constant. OUTER_CODE is
4182 insufficient context for shifts since we don't know which operand
4183 we are looking at. */
4184 if (CONSTANT_P (XEXP (x
, 0)))
4186 *total
+= (COSTS_N_INSNS (2)
4187 + rtx_cost (XEXP (x
, 1), (enum rtx_code
) code
, 0, speed
));
4190 *total
= COSTS_N_INSNS (1);
4192 else if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
4193 *total
= COSTS_N_INSNS (16);
4196 *total
= COSTS_N_INSNS (INTVAL (XEXP ((x
), 1)));
4197 /* ??? want_to_gcse_p can throw negative shift counts at us,
4198 and then panics when it gets a negative cost as result.
4199 Seen for gcc.c-torture/compile/20020710-1.c -Os . */
4208 *total
= COSTS_N_INSNS(30);
4210 *total
= COSTS_N_INSNS(1);
4214 if ((TARGET_DPFP
&& GET_MODE (x
) == DFmode
))
4215 *total
= COSTS_N_INSNS (1);
4217 *total
= arc_multcost
;
4218 /* We do not want synth_mult sequences when optimizing
4220 else if (TARGET_MUL64_SET
|| (TARGET_ARC700
&& !TARGET_NOMPY_SET
))
4221 *total
= COSTS_N_INSNS (1);
4223 *total
= COSTS_N_INSNS (2);
4226 if (GET_CODE (XEXP (x
, 0)) == MULT
4227 && _2_4_8_operand (XEXP (XEXP (x
, 0), 1), VOIDmode
))
4229 *total
+= (rtx_cost (XEXP (x
, 1), PLUS
, 0, speed
)
4230 + rtx_cost (XEXP (XEXP (x
, 0), 0), PLUS
, 1, speed
));
4235 if (GET_CODE (XEXP (x
, 1)) == MULT
4236 && _2_4_8_operand (XEXP (XEXP (x
, 1), 1), VOIDmode
))
4238 *total
+= (rtx_cost (XEXP (x
, 0), PLUS
, 0, speed
)
4239 + rtx_cost (XEXP (XEXP (x
, 1), 0), PLUS
, 1, speed
));
4245 rtx op0
= XEXP (x
, 0);
4246 rtx op1
= XEXP (x
, 1);
4248 if (GET_CODE (op0
) == ZERO_EXTRACT
&& op1
== const0_rtx
4249 && XEXP (op0
, 1) == const1_rtx
)
4251 /* btst / bbit0 / bbit1:
4252 Small integers and registers are free; everything else can
4253 be put in a register. */
4254 *total
= (rtx_cost (XEXP (op0
, 0), SET
, 1, speed
)
4255 + rtx_cost (XEXP (op0
, 2), SET
, 1, speed
));
4258 if (GET_CODE (op0
) == AND
&& op1
== const0_rtx
4259 && satisfies_constraint_C1p (XEXP (op0
, 1)))
4262 *total
= rtx_cost (XEXP (op0
, 0), SET
, 1, speed
);
4266 if (GET_CODE (op1
) == NEG
)
4268 /* op0 might be constant, the inside of op1 is rather
4269 unlikely to be so. So swapping the operands might lower
4271 *total
= (rtx_cost (op0
, PLUS
, 1, speed
)
4272 + rtx_cost (XEXP (op1
, 0), PLUS
, 0, speed
));
4277 if (outer_code
== IF_THEN_ELSE
4278 && GET_CODE (XEXP (x
, 0)) == ZERO_EXTRACT
4279 && XEXP (x
, 1) == const0_rtx
4280 && XEXP (XEXP (x
, 0), 1) == const1_rtx
)
4282 /* btst / bbit0 / bbit1:
4283 Small integers and registers are free; everything else can
4284 be put in a register. */
4285 rtx op0
= XEXP (x
, 0);
4287 *total
= (rtx_cost (XEXP (op0
, 0), SET
, 1, speed
)
4288 + rtx_cost (XEXP (op0
, 2), SET
, 1, speed
));
4292 /* scc_insn expands into two insns. */
4293 case GTU
: case GEU
: case LEU
:
4294 if (GET_MODE (x
) == SImode
)
4295 *total
+= COSTS_N_INSNS (1);
4297 case LTU
: /* might use adc. */
4298 if (GET_MODE (x
) == SImode
)
4299 *total
+= COSTS_N_INSNS (1) - 1;
4306 /* Return true if ADDR is an address that needs to be expressed as an
4307 explicit sum of pcl + offset. */
4310 arc_legitimate_pc_offset_p (rtx addr
)
4312 if (GET_CODE (addr
) != CONST
)
4314 addr
= XEXP (addr
, 0);
4315 if (GET_CODE (addr
) == PLUS
)
4317 if (GET_CODE (XEXP (addr
, 1)) != CONST_INT
)
4319 addr
= XEXP (addr
, 0);
4321 return (GET_CODE (addr
) == UNSPEC
4322 && XVECLEN (addr
, 0) == 1
4323 && XINT (addr
, 1) == ARC_UNSPEC_GOT
4324 && GET_CODE (XVECEXP (addr
, 0, 0)) == SYMBOL_REF
);
4327 /* Return true if ADDR is a valid pic address.
4328 A valid pic address on arc should look like
4329 const (unspec (SYMBOL_REF/LABEL) (ARC_UNSPEC_GOTOFF/ARC_UNSPEC_GOT)) */
4332 arc_legitimate_pic_addr_p (rtx addr
)
4334 if (GET_CODE (addr
) == LABEL_REF
)
4336 if (GET_CODE (addr
) != CONST
)
4339 addr
= XEXP (addr
, 0);
4342 if (GET_CODE (addr
) == PLUS
)
4344 if (GET_CODE (XEXP (addr
, 1)) != CONST_INT
)
4346 addr
= XEXP (addr
, 0);
4349 if (GET_CODE (addr
) != UNSPEC
4350 || XVECLEN (addr
, 0) != 1)
4353 /* Must be @GOT or @GOTOFF. */
4354 if (XINT (addr
, 1) != ARC_UNSPEC_GOT
4355 && XINT (addr
, 1) != ARC_UNSPEC_GOTOFF
)
4358 if (GET_CODE (XVECEXP (addr
, 0, 0)) != SYMBOL_REF
4359 && GET_CODE (XVECEXP (addr
, 0, 0)) != LABEL_REF
)
4367 /* Return true if OP contains a symbol reference. */
4370 symbolic_reference_mentioned_p (rtx op
)
4372 register const char *fmt
;
4375 if (GET_CODE (op
) == SYMBOL_REF
|| GET_CODE (op
) == LABEL_REF
)
4378 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
4379 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
4385 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
4386 if (symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
)))
4390 else if (fmt
[i
] == 'e' && symbolic_reference_mentioned_p (XEXP (op
, i
)))
4397 /* Return true if OP contains a SYMBOL_REF that is not wrapped in an unspec.
4398 If SKIP_LOCAL is true, skip symbols that bind locally.
4399 This is used further down in this file, and, without SKIP_LOCAL,
4400 in the addsi3 / subsi3 expanders when generating PIC code. */
4403 arc_raw_symbolic_reference_mentioned_p (rtx op
, bool skip_local
)
4405 register const char *fmt
;
4408 if (GET_CODE(op
) == UNSPEC
)
4411 if (GET_CODE (op
) == SYMBOL_REF
)
4413 tree decl
= SYMBOL_REF_DECL (op
);
4414 return !skip_local
|| !decl
|| !default_binds_local_p (decl
);
4417 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
4418 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
4424 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
4425 if (arc_raw_symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
),
4430 else if (fmt
[i
] == 'e'
4431 && arc_raw_symbolic_reference_mentioned_p (XEXP (op
, i
),
4439 /* Legitimize a pic address reference in ORIG.
4440 The return value is the legitimated address.
4441 If OLDX is non-zero, it is the target to assign the address to first. */
4444 arc_legitimize_pic_address (rtx orig
, rtx oldx
)
4453 if (GET_CODE (addr
) == LABEL_REF
)
4455 else if (GET_CODE (addr
) == SYMBOL_REF
4456 && (CONSTANT_POOL_ADDRESS_P (addr
)
4457 || SYMBOL_REF_LOCAL_P (addr
)))
4459 /* This symbol may be referenced via a displacement from the PIC
4460 base address (@GOTOFF). */
4462 /* FIXME: if we had a way to emit pc-relative adds that don't
4463 create a GOT entry, we could do without the use of the gp register. */
4464 crtl
->uses_pic_offset_table
= 1;
4465 pat
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, addr
), ARC_UNSPEC_GOTOFF
);
4466 pat
= gen_rtx_CONST (Pmode
, pat
);
4467 pat
= gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, pat
);
4470 oldx
= gen_reg_rtx (Pmode
);
4474 emit_move_insn (oldx
, pat
);
4479 else if (GET_CODE (addr
) == SYMBOL_REF
)
4481 /* This symbol must be referenced via a load from the
4482 Global Offset Table (@GOTPC). */
4484 pat
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, addr
), ARC_UNSPEC_GOT
);
4485 pat
= gen_rtx_CONST (Pmode
, pat
);
4486 pat
= gen_const_mem (Pmode
, pat
);
4489 oldx
= gen_reg_rtx (Pmode
);
4491 emit_move_insn (oldx
, pat
);
4496 if (GET_CODE (addr
) == CONST
)
4498 addr
= XEXP (addr
, 0);
4499 if (GET_CODE (addr
) == UNSPEC
)
4501 /* Check that the unspec is one of the ones we generate? */
4504 gcc_assert (GET_CODE (addr
) == PLUS
);
4507 if (GET_CODE (addr
) == PLUS
)
4509 rtx op0
= XEXP (addr
, 0), op1
= XEXP (addr
, 1);
4511 /* Check first to see if this is a constant offset from a @GOTOFF
4512 symbol reference. */
4513 if ((GET_CODE (op0
) == LABEL_REF
4514 || (GET_CODE (op0
) == SYMBOL_REF
4515 && (CONSTANT_POOL_ADDRESS_P (op0
)
4516 || SYMBOL_REF_LOCAL_P (op0
))))
4517 && GET_CODE (op1
) == CONST_INT
)
4519 /* FIXME: like above, could do without gp reference. */
4520 crtl
->uses_pic_offset_table
= 1;
4522 = gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, op0
), ARC_UNSPEC_GOTOFF
);
4523 pat
= gen_rtx_PLUS (Pmode
, pat
, op1
);
4524 pat
= gen_rtx_CONST (Pmode
, pat
);
4525 pat
= gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, pat
);
4529 emit_move_insn (oldx
, pat
);
4535 base
= arc_legitimize_pic_address (XEXP (addr
, 0), oldx
);
4536 pat
= arc_legitimize_pic_address (XEXP (addr
, 1),
4537 base
== oldx
? NULL_RTX
: oldx
);
4539 if (GET_CODE (pat
) == CONST_INT
)
4540 pat
= plus_constant (Pmode
, base
, INTVAL (pat
));
4543 if (GET_CODE (pat
) == PLUS
&& CONSTANT_P (XEXP (pat
, 1)))
4545 base
= gen_rtx_PLUS (Pmode
, base
, XEXP (pat
, 0));
4546 pat
= XEXP (pat
, 1);
4548 pat
= gen_rtx_PLUS (Pmode
, base
, pat
);
4557 /* Output address constant X to FILE, taking PIC into account. */
4560 arc_output_pic_addr_const (FILE * file
, rtx x
, int code
)
4565 switch (GET_CODE (x
))
4575 output_addr_const (file
, x
);
4577 /* Local functions do not get references through the PLT. */
4578 if (code
== 'P' && ! SYMBOL_REF_LOCAL_P (x
))
4579 fputs ("@plt", file
);
4583 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (XEXP (x
, 0)));
4584 assemble_name (file
, buf
);
4588 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (x
));
4589 assemble_name (file
, buf
);
4593 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
));
4597 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4601 if (GET_MODE (x
) == VOIDmode
)
4603 /* We can use %d if the number is one word and positive. */
4604 if (CONST_DOUBLE_HIGH (x
))
4605 fprintf (file
, HOST_WIDE_INT_PRINT_DOUBLE_HEX
,
4606 CONST_DOUBLE_HIGH (x
), CONST_DOUBLE_LOW (x
));
4607 else if (CONST_DOUBLE_LOW (x
) < 0)
4608 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, CONST_DOUBLE_LOW (x
));
4610 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, CONST_DOUBLE_LOW (x
));
4613 /* We can't handle floating point constants;
4614 PRINT_OPERAND must handle them. */
4615 output_operand_lossage ("floating constant misused");
4619 /* FIXME: Not needed here. */
4620 /* Some assemblers need integer constants to appear last (eg masm). */
4621 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
4623 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4624 fprintf (file
, "+");
4625 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4627 else if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
4629 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4630 if (INTVAL (XEXP (x
, 1)) >= 0)
4631 fprintf (file
, "+");
4632 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4639 /* Avoid outputting things like x-x or x+5-x,
4640 since some assemblers can't handle that. */
4641 x
= simplify_subtraction (x
);
4642 if (GET_CODE (x
) != MINUS
)
4645 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4646 fprintf (file
, "-");
4647 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
4648 && INTVAL (XEXP (x
, 1)) < 0)
4650 fprintf (file
, "(");
4651 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4652 fprintf (file
, ")");
4655 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4660 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4665 gcc_assert (XVECLEN (x
, 0) == 1);
4666 if (XINT (x
, 1) == ARC_UNSPEC_GOT
)
4667 fputs ("pcl,", file
);
4668 arc_output_pic_addr_const (file
, XVECEXP (x
, 0, 0), code
);
4669 switch (XINT (x
, 1))
4671 case ARC_UNSPEC_GOT
:
4672 fputs ("@gotpc", file
);
4674 case ARC_UNSPEC_GOTOFF
:
4675 fputs ("@gotoff", file
);
4677 case ARC_UNSPEC_PLT
:
4678 fputs ("@plt", file
);
4681 output_operand_lossage ("invalid UNSPEC as operand: %d", XINT (x
,1));
4687 output_operand_lossage ("invalid expression as operand");
4691 #define SYMBOLIC_CONST(X) \
4692 (GET_CODE (X) == SYMBOL_REF \
4693 || GET_CODE (X) == LABEL_REF \
4694 || (GET_CODE (X) == CONST && symbolic_reference_mentioned_p (X)))
4696 /* Emit insns to move operands[1] into operands[0]. */
4699 emit_pic_move (rtx
*operands
, enum machine_mode
)
4701 rtx temp
= reload_in_progress
? operands
[0] : gen_reg_rtx (Pmode
);
4703 if (GET_CODE (operands
[0]) == MEM
&& SYMBOLIC_CONST (operands
[1]))
4704 operands
[1] = force_reg (Pmode
, operands
[1]);
4706 operands
[1] = arc_legitimize_pic_address (operands
[1], temp
);
4710 /* The function returning the number of words, at the beginning of an
4711 argument, must be put in registers. The returned value must be
4712 zero for arguments that are passed entirely in registers or that
4713 are entirely pushed on the stack.
4715 On some machines, certain arguments must be passed partially in
4716 registers and partially in memory. On these machines, typically
4717 the first N words of arguments are passed in registers, and the
4718 rest on the stack. If a multi-word argument (a `double' or a
4719 structure) crosses that boundary, its first few words must be
4720 passed in registers and the rest must be pushed. This function
4721 tells the compiler when this occurs, and how many of the words
4722 should go in registers.
4724 `FUNCTION_ARG' for these arguments should return the first register
4725 to be used by the caller for this argument; likewise
4726 `FUNCTION_INCOMING_ARG', for the called function.
4728 The function is used to implement macro FUNCTION_ARG_PARTIAL_NREGS. */
4730 /* If REGNO is the least arg reg available then what is the total number of arg
4732 #define GPR_REST_ARG_REGS(REGNO) \
4733 ((REGNO) <= MAX_ARC_PARM_REGS ? MAX_ARC_PARM_REGS - (REGNO) : 0 )
4735 /* Since arc parm regs are contiguous. */
4736 #define ARC_NEXT_ARG_REG(REGNO) ( (REGNO) + 1 )
4738 /* Implement TARGET_ARG_PARTIAL_BYTES. */
4741 arc_arg_partial_bytes (cumulative_args_t cum_v
, enum machine_mode mode
,
4742 tree type
, bool named ATTRIBUTE_UNUSED
)
4744 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
4745 int bytes
= (mode
== BLKmode
4746 ? int_size_in_bytes (type
) : (int) GET_MODE_SIZE (mode
));
4747 int words
= (bytes
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
4751 arg_num
= ROUND_ADVANCE_CUM (arg_num
, mode
, type
);
4752 ret
= GPR_REST_ARG_REGS (arg_num
);
4754 /* ICEd at function.c:2361, and ret is copied to data->partial */
4755 ret
= (ret
>= words
? 0 : ret
* UNITS_PER_WORD
);
4762 /* This function is used to control a function argument is passed in a
4763 register, and which register.
4765 The arguments are CUM, of type CUMULATIVE_ARGS, which summarizes
4766 (in a way defined by INIT_CUMULATIVE_ARGS and FUNCTION_ARG_ADVANCE)
4767 all of the previous arguments so far passed in registers; MODE, the
4768 machine mode of the argument; TYPE, the data type of the argument
4769 as a tree node or 0 if that is not known (which happens for C
4770 support library functions); and NAMED, which is 1 for an ordinary
4771 argument and 0 for nameless arguments that correspond to `...' in
4772 the called function's prototype.
4774 The returned value should either be a `reg' RTX for the hard
4775 register in which to pass the argument, or zero to pass the
4776 argument on the stack.
4778 For machines like the Vax and 68000, where normally all arguments
4779 are pushed, zero suffices as a definition.
4781 The usual way to make the ANSI library `stdarg.h' work on a machine
4782 where some arguments are usually passed in registers, is to cause
4783 nameless arguments to be passed on the stack instead. This is done
4784 by making the function return 0 whenever NAMED is 0.
4786 You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the
4787 definition of this function to determine if this argument is of a
4788 type that must be passed in the stack. If `REG_PARM_STACK_SPACE'
4789 is not defined and the function returns non-zero for such an
4790 argument, the compiler will abort. If `REG_PARM_STACK_SPACE' is
4791 defined, the argument will be computed in the stack and then loaded
4794 The function is used to implement macro FUNCTION_ARG. */
4795 /* On the ARC the first MAX_ARC_PARM_REGS args are normally in registers
4796 and the rest are pushed. */
4799 arc_function_arg (cumulative_args_t cum_v
, enum machine_mode mode
,
4800 const_tree type ATTRIBUTE_UNUSED
, bool named ATTRIBUTE_UNUSED
)
4802 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
4805 const char *debstr ATTRIBUTE_UNUSED
;
4807 arg_num
= ROUND_ADVANCE_CUM (arg_num
, mode
, type
);
4808 /* Return a marker for use in the call instruction. */
4809 if (mode
== VOIDmode
)
4814 else if (GPR_REST_ARG_REGS (arg_num
) > 0)
4816 ret
= gen_rtx_REG (mode
, arg_num
);
4817 debstr
= reg_names
[arg_num
];
4827 /* The function to update the summarizer variable *CUM to advance past
4828 an argument in the argument list. The values MODE, TYPE and NAMED
4829 describe that argument. Once this is done, the variable *CUM is
4830 suitable for analyzing the *following* argument with
4831 `FUNCTION_ARG', etc.
4833 This function need not do anything if the argument in question was
4834 passed on the stack. The compiler knows how to track the amount of
4835 stack space used for arguments without any special help.
4837 The function is used to implement macro FUNCTION_ARG_ADVANCE. */
4838 /* For the ARC: the cum set here is passed on to function_arg where we
4839 look at its value and say which reg to use. Strategy: advance the
4840 regnumber here till we run out of arg regs, then set *cum to last
4841 reg. In function_arg, since *cum > last arg reg we would return 0
4842 and thus the arg will end up on the stack. For straddling args of
4843 course function_arg_partial_nregs will come into play. */
4846 arc_function_arg_advance (cumulative_args_t cum_v
, enum machine_mode mode
,
4847 const_tree type
, bool named ATTRIBUTE_UNUSED
)
4849 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
4850 int bytes
= (mode
== BLKmode
4851 ? int_size_in_bytes (type
) : (int) GET_MODE_SIZE (mode
));
4852 int words
= (bytes
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
4856 *cum
= ROUND_ADVANCE_CUM (*cum
, mode
, type
);
4857 for (i
= 0; i
< words
; i
++)
4858 *cum
= ARC_NEXT_ARG_REG (*cum
);
4862 /* Define how to find the value returned by a function.
4863 VALTYPE is the data type of the value (as a tree).
4864 If the precise function being called is known, FN_DECL_OR_TYPE is its
4865 FUNCTION_DECL; otherwise, FN_DECL_OR_TYPE is its type. */
4868 arc_function_value (const_tree valtype
,
4869 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
4870 bool outgoing ATTRIBUTE_UNUSED
)
4872 enum machine_mode mode
= TYPE_MODE (valtype
);
4873 int unsignedp ATTRIBUTE_UNUSED
;
4875 unsignedp
= TYPE_UNSIGNED (valtype
);
4876 if (INTEGRAL_TYPE_P (valtype
) || TREE_CODE (valtype
) == OFFSET_TYPE
)
4877 PROMOTE_MODE (mode
, unsignedp
, valtype
);
4878 return gen_rtx_REG (mode
, 0);
4881 /* Returns the return address that is used by builtin_return_address. */
4884 arc_return_addr_rtx (int count
, ATTRIBUTE_UNUSED rtx frame
)
4889 return get_hard_reg_initial_val (Pmode
, RETURN_ADDR_REGNUM
);
4892 /* Nonzero if the constant value X is a legitimate general operand
4893 when generating PIC code. It is given that flag_pic is on and
4894 that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
4897 arc_legitimate_pic_operand_p (rtx x
)
4899 return !arc_raw_symbolic_reference_mentioned_p (x
, true);
4902 /* Determine if a given RTX is a valid constant. We already know this
4903 satisfies CONSTANT_P. */
4906 arc_legitimate_constant_p (enum machine_mode
, rtx x
)
4911 switch (GET_CODE (x
))
4916 if (GET_CODE (x
) == PLUS
)
4918 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
4923 /* Only some unspecs are valid as "constants". */
4924 if (GET_CODE (x
) == UNSPEC
)
4925 switch (XINT (x
, 1))
4927 case ARC_UNSPEC_PLT
:
4928 case ARC_UNSPEC_GOTOFF
:
4929 case ARC_UNSPEC_GOT
:
4937 /* We must have drilled down to a symbol. */
4938 if (arc_raw_symbolic_reference_mentioned_p (x
, false))
4952 /* Otherwise we handle everything else in the move patterns. */
4957 arc_legitimate_address_p (enum machine_mode mode
, rtx x
, bool strict
)
4959 if (RTX_OK_FOR_BASE_P (x
, strict
))
4961 if (LEGITIMATE_OFFSET_ADDRESS_P (mode
, x
, TARGET_INDEXED_LOADS
, strict
))
4963 if (LEGITIMATE_SCALED_ADDRESS_P (mode
, x
, strict
))
4965 if (LEGITIMATE_SMALL_DATA_ADDRESS_P (x
))
4967 if (GET_CODE (x
) == CONST_INT
&& LARGE_INT (INTVAL (x
)))
4969 if ((GET_MODE_SIZE (mode
) != 16)
4970 && (GET_CODE (x
) == SYMBOL_REF
4971 || GET_CODE (x
) == LABEL_REF
4972 || GET_CODE (x
) == CONST
))
4974 if (!flag_pic
|| arc_legitimate_pic_addr_p (x
))
4977 if ((GET_CODE (x
) == PRE_DEC
|| GET_CODE (x
) == PRE_INC
4978 || GET_CODE (x
) == POST_DEC
|| GET_CODE (x
) == POST_INC
)
4979 && RTX_OK_FOR_BASE_P (XEXP (x
, 0), strict
))
4981 /* We're restricted here by the `st' insn. */
4982 if ((GET_CODE (x
) == PRE_MODIFY
|| GET_CODE (x
) == POST_MODIFY
)
4983 && GET_CODE (XEXP ((x
), 1)) == PLUS
4984 && rtx_equal_p (XEXP ((x
), 0), XEXP (XEXP (x
, 1), 0))
4985 && LEGITIMATE_OFFSET_ADDRESS_P (QImode
, XEXP (x
, 1),
4986 TARGET_AUTO_MODIFY_REG
, strict
))
4991 /* Return true iff ADDR (a legitimate address expression)
4992 has an effect that depends on the machine mode it is used for. */
4995 arc_mode_dependent_address_p (const_rtx addr
, addr_space_t
)
4997 /* SYMBOL_REF is not mode dependent: it is either a small data reference,
4998 which is valid for loads and stores, or a limm offset, which is valid for
5000 /* Scaled indices are scaled by the access mode; likewise for scaled
5001 offsets, which are needed for maximum offset stores. */
5002 if (GET_CODE (addr
) == PLUS
5003 && (GET_CODE (XEXP ((addr
), 0)) == MULT
5004 || (CONST_INT_P (XEXP ((addr
), 1))
5005 && !SMALL_INT (INTVAL (XEXP ((addr
), 1))))))
5010 /* Determine if it's legal to put X into the constant pool. */
5013 arc_cannot_force_const_mem (enum machine_mode mode
, rtx x
)
5015 return !arc_legitimate_constant_p (mode
, x
);
5019 /* Generic function to define a builtin. */
5020 #define def_mbuiltin(MASK, NAME, TYPE, CODE) \
5024 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL, NULL_TREE); \
5030 arc_init_builtins (void)
5032 tree endlink
= void_list_node
;
5034 tree void_ftype_void
5035 = build_function_type (void_type_node
,
5039 = build_function_type (integer_type_node
,
5040 tree_cons (NULL_TREE
, integer_type_node
, endlink
));
5042 tree pcvoid_type_node
5043 = build_pointer_type (build_qualified_type (void_type_node
, TYPE_QUAL_CONST
));
5044 tree int_ftype_pcvoid_int
5045 = build_function_type (integer_type_node
,
5046 tree_cons (NULL_TREE
, pcvoid_type_node
,
5047 tree_cons (NULL_TREE
, integer_type_node
,
5050 tree int_ftype_short_int
5051 = build_function_type (integer_type_node
,
5052 tree_cons (NULL_TREE
, short_integer_type_node
, endlink
));
5054 tree void_ftype_int_int
5055 = build_function_type (void_type_node
,
5056 tree_cons (NULL_TREE
, integer_type_node
,
5057 tree_cons (NULL_TREE
, integer_type_node
, endlink
)));
5058 tree void_ftype_usint_usint
5059 = build_function_type (void_type_node
,
5060 tree_cons (NULL_TREE
, long_unsigned_type_node
,
5061 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
)));
5063 tree int_ftype_int_int
5064 = build_function_type (integer_type_node
,
5065 tree_cons (NULL_TREE
, integer_type_node
,
5066 tree_cons (NULL_TREE
, integer_type_node
, endlink
)));
5068 tree usint_ftype_usint
5069 = build_function_type (long_unsigned_type_node
,
5070 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
));
5072 tree void_ftype_usint
5073 = build_function_type (void_type_node
,
5074 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
));
5076 /* Add the builtins. */
5077 def_mbuiltin (1,"__builtin_arc_nop", void_ftype_void
, ARC_BUILTIN_NOP
);
5078 def_mbuiltin (TARGET_NORM
, "__builtin_arc_norm", int_ftype_int
, ARC_BUILTIN_NORM
);
5079 def_mbuiltin (TARGET_NORM
, "__builtin_arc_normw", int_ftype_short_int
, ARC_BUILTIN_NORMW
);
5080 def_mbuiltin (TARGET_SWAP
, "__builtin_arc_swap", int_ftype_int
, ARC_BUILTIN_SWAP
);
5081 def_mbuiltin (TARGET_MUL64_SET
,"__builtin_arc_mul64", void_ftype_int_int
, ARC_BUILTIN_MUL64
);
5082 def_mbuiltin (TARGET_MUL64_SET
,"__builtin_arc_mulu64", void_ftype_usint_usint
, ARC_BUILTIN_MULU64
);
5083 def_mbuiltin (1,"__builtin_arc_rtie", void_ftype_void
, ARC_BUILTIN_RTIE
);
5084 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_sync", void_ftype_void
, ARC_BUILTIN_SYNC
);
5085 def_mbuiltin ((TARGET_EA_SET
),"__builtin_arc_divaw", int_ftype_int_int
, ARC_BUILTIN_DIVAW
);
5086 def_mbuiltin (1,"__builtin_arc_brk", void_ftype_void
, ARC_BUILTIN_BRK
);
5087 def_mbuiltin (1,"__builtin_arc_flag", void_ftype_usint
, ARC_BUILTIN_FLAG
);
5088 def_mbuiltin (1,"__builtin_arc_sleep", void_ftype_usint
, ARC_BUILTIN_SLEEP
);
5089 def_mbuiltin (1,"__builtin_arc_swi", void_ftype_void
, ARC_BUILTIN_SWI
);
5090 def_mbuiltin (1,"__builtin_arc_core_read", usint_ftype_usint
, ARC_BUILTIN_CORE_READ
);
5091 def_mbuiltin (1,"__builtin_arc_core_write", void_ftype_usint_usint
, ARC_BUILTIN_CORE_WRITE
);
5092 def_mbuiltin (1,"__builtin_arc_lr", usint_ftype_usint
, ARC_BUILTIN_LR
);
5093 def_mbuiltin (1,"__builtin_arc_sr", void_ftype_usint_usint
, ARC_BUILTIN_SR
);
5094 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_trap_s", void_ftype_usint
, ARC_BUILTIN_TRAP_S
);
5095 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_unimp_s", void_ftype_void
, ARC_BUILTIN_UNIMP_S
);
5096 def_mbuiltin (1,"__builtin_arc_aligned", int_ftype_pcvoid_int
, ARC_BUILTIN_ALIGNED
);
5098 if (TARGET_SIMD_SET
)
5099 arc_init_simd_builtins ();
5102 static rtx
arc_expand_simd_builtin (tree
, rtx
, rtx
, enum machine_mode
, int);
5104 /* Expand an expression EXP that calls a built-in function,
5105 with result going to TARGET if that's convenient
5106 (and in mode MODE if that's convenient).
5107 SUBTARGET may be used as the target for computing one of EXP's operands.
5108 IGNORE is nonzero if the value is to be ignored. */
5111 arc_expand_builtin (tree exp
,
5114 enum machine_mode mode
,
5117 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
5122 int fcode
= DECL_FUNCTION_CODE (fndecl
);
5124 enum machine_mode mode0
;
5125 enum machine_mode mode1
;
5127 if (fcode
> ARC_SIMD_BUILTIN_BEGIN
&& fcode
< ARC_SIMD_BUILTIN_END
)
5128 return arc_expand_simd_builtin (exp
, target
, subtarget
, mode
, ignore
);
5132 case ARC_BUILTIN_NOP
:
5133 emit_insn (gen_nop ());
5136 case ARC_BUILTIN_NORM
:
5137 icode
= CODE_FOR_clrsbsi2
;
5138 arg0
= CALL_EXPR_ARG (exp
, 0);
5139 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5140 mode0
= insn_data
[icode
].operand
[1].mode
;
5141 target
= gen_reg_rtx (SImode
);
5143 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5144 op0
= copy_to_mode_reg (mode0
, op0
);
5146 emit_insn (gen_clrsbsi2 (target
, op0
));
5149 case ARC_BUILTIN_NORMW
:
5151 /* FIXME : This should all be HImode, not SImode. */
5152 icode
= CODE_FOR_normw
;
5153 arg0
= CALL_EXPR_ARG (exp
, 0);
5154 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5155 mode0
= insn_data
[icode
].operand
[1].mode
;
5156 target
= gen_reg_rtx (SImode
);
5158 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5159 op0
= copy_to_mode_reg (mode0
, convert_to_mode (mode0
, op0
,0));
5161 emit_insn (gen_normw (target
, op0
));
5164 case ARC_BUILTIN_MUL64
:
5165 icode
= CODE_FOR_mul64
;
5166 arg0
= CALL_EXPR_ARG (exp
, 0);
5167 arg1
= CALL_EXPR_ARG (exp
, 1);
5168 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5169 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5171 mode0
= insn_data
[icode
].operand
[0].mode
;
5172 mode1
= insn_data
[icode
].operand
[1].mode
;
5174 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5175 op0
= copy_to_mode_reg (mode0
, op0
);
5177 if (! (*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
5178 op1
= copy_to_mode_reg (mode1
, op1
);
5180 emit_insn (gen_mul64 (op0
,op1
));
5183 case ARC_BUILTIN_MULU64
:
5184 icode
= CODE_FOR_mulu64
;
5185 arg0
= CALL_EXPR_ARG (exp
, 0);
5186 arg1
= CALL_EXPR_ARG (exp
, 1);
5187 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5188 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5190 mode0
= insn_data
[icode
].operand
[0].mode
;
5191 mode1
= insn_data
[icode
].operand
[1].mode
;
5193 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5194 op0
= copy_to_mode_reg (mode0
, op0
);
5196 if (! (*insn_data
[icode
].operand
[0].predicate
) (op1
, mode1
))
5197 op1
= copy_to_mode_reg (mode1
, op1
);
5199 emit_insn (gen_mulu64 (op0
,op1
));
5202 case ARC_BUILTIN_RTIE
:
5203 icode
= CODE_FOR_rtie
;
5204 emit_insn (gen_rtie (const1_rtx
));
5207 case ARC_BUILTIN_SYNC
:
5208 icode
= CODE_FOR_sync
;
5209 emit_insn (gen_sync (const1_rtx
));
5212 case ARC_BUILTIN_SWAP
:
5213 icode
= CODE_FOR_swap
;
5214 arg0
= CALL_EXPR_ARG (exp
, 0);
5215 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5216 mode0
= insn_data
[icode
].operand
[1].mode
;
5217 target
= gen_reg_rtx (SImode
);
5219 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5220 op0
= copy_to_mode_reg (mode0
, op0
);
5222 emit_insn (gen_swap (target
, op0
));
5225 case ARC_BUILTIN_DIVAW
:
5226 icode
= CODE_FOR_divaw
;
5227 arg0
= CALL_EXPR_ARG (exp
, 0);
5228 arg1
= CALL_EXPR_ARG (exp
, 1);
5230 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5231 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5232 target
= gen_reg_rtx (SImode
);
5234 mode0
= insn_data
[icode
].operand
[0].mode
;
5235 mode1
= insn_data
[icode
].operand
[1].mode
;
5237 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5238 op0
= copy_to_mode_reg (mode0
, op0
);
5240 if (! (*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
5241 op1
= copy_to_mode_reg (mode1
, op1
);
5243 emit_insn (gen_divaw (target
, op0
, op1
));
5246 case ARC_BUILTIN_BRK
:
5247 icode
= CODE_FOR_brk
;
5248 emit_insn (gen_brk (const1_rtx
));
5251 case ARC_BUILTIN_SLEEP
:
5252 icode
= CODE_FOR_sleep
;
5253 arg0
= CALL_EXPR_ARG (exp
, 0);
5257 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5258 mode0
= insn_data
[icode
].operand
[1].mode
;
5260 emit_insn (gen_sleep (op0
));
5263 case ARC_BUILTIN_SWI
:
5264 icode
= CODE_FOR_swi
;
5265 emit_insn (gen_swi (const1_rtx
));
5268 case ARC_BUILTIN_FLAG
:
5269 icode
= CODE_FOR_flag
;
5270 arg0
= CALL_EXPR_ARG (exp
, 0);
5271 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5272 mode0
= insn_data
[icode
].operand
[0].mode
;
5274 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5275 op0
= copy_to_mode_reg (mode0
, op0
);
5277 emit_insn (gen_flag (op0
));
5280 case ARC_BUILTIN_CORE_READ
:
5281 icode
= CODE_FOR_core_read
;
5282 arg0
= CALL_EXPR_ARG (exp
, 0);
5283 target
= gen_reg_rtx (SImode
);
5287 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5288 mode0
= insn_data
[icode
].operand
[1].mode
;
5290 emit_insn (gen_core_read (target
, op0
));
5293 case ARC_BUILTIN_CORE_WRITE
:
5294 icode
= CODE_FOR_core_write
;
5295 arg0
= CALL_EXPR_ARG (exp
, 0);
5296 arg1
= CALL_EXPR_ARG (exp
, 1);
5300 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5301 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5303 mode0
= insn_data
[icode
].operand
[0].mode
;
5304 mode1
= insn_data
[icode
].operand
[1].mode
;
5306 emit_insn (gen_core_write (op0
, op1
));
5309 case ARC_BUILTIN_LR
:
5310 icode
= CODE_FOR_lr
;
5311 arg0
= CALL_EXPR_ARG (exp
, 0);
5312 target
= gen_reg_rtx (SImode
);
5316 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5317 mode0
= insn_data
[icode
].operand
[1].mode
;
5319 emit_insn (gen_lr (target
, op0
));
5322 case ARC_BUILTIN_SR
:
5323 icode
= CODE_FOR_sr
;
5324 arg0
= CALL_EXPR_ARG (exp
, 0);
5325 arg1
= CALL_EXPR_ARG (exp
, 1);
5329 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5330 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5332 mode0
= insn_data
[icode
].operand
[0].mode
;
5333 mode1
= insn_data
[icode
].operand
[1].mode
;
5335 emit_insn (gen_sr (op0
, op1
));
5338 case ARC_BUILTIN_TRAP_S
:
5339 icode
= CODE_FOR_trap_s
;
5340 arg0
= CALL_EXPR_ARG (exp
, 0);
5344 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5345 mode0
= insn_data
[icode
].operand
[1].mode
;
5347 /* We don't give an error for non-cost values here because
5348 we still want to allow things to be fixed up by later inlining /
5349 constant folding / dead code elimination. */
5350 if (CONST_INT_P (op0
) && !satisfies_constraint_L (op0
))
5352 /* Keep this message in sync with the one in arc.md:trap_s,
5353 because *.md files don't get scanned by exgettext. */
5354 error ("operand to trap_s should be an unsigned 6-bit value");
5356 emit_insn (gen_trap_s (op0
));
5359 case ARC_BUILTIN_UNIMP_S
:
5360 icode
= CODE_FOR_unimp_s
;
5361 emit_insn (gen_unimp_s (const1_rtx
));
5364 case ARC_BUILTIN_ALIGNED
:
5365 /* __builtin_arc_aligned (void* val, int alignval) */
5366 arg0
= CALL_EXPR_ARG (exp
, 0);
5367 arg1
= CALL_EXPR_ARG (exp
, 1);
5369 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5370 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5371 target
= gen_reg_rtx (SImode
);
5373 if (!CONST_INT_P (op1
))
5375 /* If we can't fold the alignment to a constant integer
5376 whilst optimizing, this is probably a user error. */
5378 warning (0, "__builtin_arc_aligned with non-constant alignment");
5382 HOST_WIDE_INT alignTest
= INTVAL (op1
);
5383 /* Check alignTest is positive, and a power of two. */
5384 if (alignTest
<= 0 || alignTest
!= (alignTest
& -alignTest
))
5386 error ("invalid alignment value for __builtin_arc_aligned");
5390 if (CONST_INT_P (op0
))
5392 HOST_WIDE_INT pnt
= INTVAL (op0
);
5394 if ((pnt
& (alignTest
- 1)) == 0)
5399 unsigned align
= get_pointer_alignment (arg0
);
5400 unsigned numBits
= alignTest
* BITS_PER_UNIT
;
5402 if (align
&& align
>= numBits
)
5404 /* Another attempt to ascertain alignment. Check the type
5405 we are pointing to. */
5406 if (POINTER_TYPE_P (TREE_TYPE (arg0
))
5407 && TYPE_ALIGN (TREE_TYPE (TREE_TYPE (arg0
))) >= numBits
)
5412 /* Default to false. */
5419 /* @@@ Should really do something sensible here. */
5423 /* Returns true if the operands[opno] is a valid compile-time constant to be
5424 used as register number in the code for builtins. Else it flags an error
5425 and returns false. */
5428 check_if_valid_regno_const (rtx
*operands
, int opno
)
5431 switch (GET_CODE (operands
[opno
]))
5438 error ("register number must be a compile-time constant. Try giving higher optimization levels");
5444 /* Check that after all the constant folding, whether the operand to
5445 __builtin_arc_sleep is an unsigned int of 6 bits. If not, flag an error. */
5448 check_if_valid_sleep_operand (rtx
*operands
, int opno
)
5450 switch (GET_CODE (operands
[opno
]))
5454 if( UNSIGNED_INT6 (INTVAL (operands
[opno
])))
5457 fatal_error("operand for sleep instruction must be an unsigned 6 bit compile-time constant");
5463 /* Return true if it is ok to make a tail-call to DECL. */
5466 arc_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED
,
5467 tree exp ATTRIBUTE_UNUSED
)
5469 /* Never tailcall from an ISR routine - it needs a special exit sequence. */
5470 if (ARC_INTERRUPT_P (arc_compute_function_type (cfun
)))
5473 /* Everything else is ok. */
5477 /* Output code to add DELTA to the first argument, and then jump
5478 to FUNCTION. Used for C++ multiple inheritance. */
5481 arc_output_mi_thunk (FILE *file
, tree thunk ATTRIBUTE_UNUSED
,
5482 HOST_WIDE_INT delta
,
5483 HOST_WIDE_INT vcall_offset
,
5486 int mi_delta
= delta
;
5487 const char *const mi_op
= mi_delta
< 0 ? "sub" : "add";
5490 = aggregate_value_p (TREE_TYPE (TREE_TYPE (function
)), function
) ? 1 : 0;
5494 mi_delta
= - mi_delta
;
5496 /* Add DELTA. When possible use a plain add, otherwise load it into
5497 a register first. */
5499 while (mi_delta
!= 0)
5501 if ((mi_delta
& (3 << shift
)) == 0)
5505 asm_fprintf (file
, "\t%s\t%s, %s, %d\n",
5506 mi_op
, reg_names
[this_regno
], reg_names
[this_regno
],
5507 mi_delta
& (0xff << shift
));
5508 mi_delta
&= ~(0xff << shift
);
5513 /* If needed, add *(*THIS + VCALL_OFFSET) to THIS. */
5514 if (vcall_offset
!= 0)
5516 /* ld r12,[this] --> temp = *this
5517 add r12,r12,vcall_offset --> temp = *(*this + vcall_offset)
5519 add this,this,r12 --> this+ = *(*this + vcall_offset) */
5520 asm_fprintf (file
, "\tld\t%s, [%s]\n",
5521 ARC_TEMP_SCRATCH_REG
, reg_names
[this_regno
]);
5522 asm_fprintf (file
, "\tadd\t%s, %s, %ld\n",
5523 ARC_TEMP_SCRATCH_REG
, ARC_TEMP_SCRATCH_REG
, vcall_offset
);
5524 asm_fprintf (file
, "\tld\t%s, [%s]\n",
5525 ARC_TEMP_SCRATCH_REG
, ARC_TEMP_SCRATCH_REG
);
5526 asm_fprintf (file
, "\tadd\t%s, %s, %s\n", reg_names
[this_regno
],
5527 reg_names
[this_regno
], ARC_TEMP_SCRATCH_REG
);
5530 fnaddr
= XEXP (DECL_RTL (function
), 0);
5532 if (arc_is_longcall_p (fnaddr
))
5533 fputs ("\tj\t", file
);
5535 fputs ("\tb\t", file
);
5536 assemble_name (file
, XSTR (fnaddr
, 0));
5540 /* Return true if a 32 bit "long_call" should be generated for
5541 this calling SYM_REF. We generate a long_call if the function:
5543 a. has an __attribute__((long call))
5544 or b. the -mlong-calls command line switch has been specified
5546 However we do not generate a long call if the function has an
5547 __attribute__ ((short_call)) or __attribute__ ((medium_call))
5549 This function will be called by C fragments contained in the machine
5550 description file. */
5553 arc_is_longcall_p (rtx sym_ref
)
5555 if (GET_CODE (sym_ref
) != SYMBOL_REF
)
5558 return (SYMBOL_REF_LONG_CALL_P (sym_ref
)
5559 || (TARGET_LONG_CALLS_SET
5560 && !SYMBOL_REF_SHORT_CALL_P (sym_ref
)
5561 && !SYMBOL_REF_MEDIUM_CALL_P (sym_ref
)));
5565 /* Likewise for short calls. */
5568 arc_is_shortcall_p (rtx sym_ref
)
5570 if (GET_CODE (sym_ref
) != SYMBOL_REF
)
5573 return (SYMBOL_REF_SHORT_CALL_P (sym_ref
)
5574 || (!TARGET_LONG_CALLS_SET
&& !TARGET_MEDIUM_CALLS
5575 && !SYMBOL_REF_LONG_CALL_P (sym_ref
)
5576 && !SYMBOL_REF_MEDIUM_CALL_P (sym_ref
)));
5580 /* Emit profiling code for calling CALLEE. Return true if a special
5581 call pattern needs to be generated. */
5584 arc_profile_call (rtx callee
)
5586 rtx from
= XEXP (DECL_RTL (current_function_decl
), 0);
5588 if (TARGET_UCB_MCOUNT
)
5589 /* Profiling is done by instrumenting the callee. */
5592 if (CONSTANT_P (callee
))
5595 = gen_rtx_CONST (Pmode
,
5596 gen_rtx_UNSPEC (Pmode
,
5597 gen_rtvec (3, from
, callee
,
5598 CONST0_RTX (Pmode
)),
5600 rtx counter
= gen_rtx_MEM (SImode
, count_ptr
);
5601 /* ??? The increment would better be done atomically, but as there is
5602 no proper hardware support, that would be too expensive. */
5603 emit_move_insn (counter
,
5604 force_reg (SImode
, plus_constant (SImode
, counter
, 1)));
5610 = gen_rtx_CONST (Pmode
,
5611 gen_rtx_UNSPEC (Pmode
,
5612 gen_rtvec (3, from
, CONST0_RTX (Pmode
),
5613 CONST0_RTX (Pmode
)),
5615 emit_move_insn (gen_rtx_REG (Pmode
, 8), count_list_ptr
);
5616 emit_move_insn (gen_rtx_REG (Pmode
, 9), callee
);
5621 /* Worker function for TARGET_RETURN_IN_MEMORY. */
5624 arc_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
5626 if (AGGREGATE_TYPE_P (type
) || TREE_ADDRESSABLE (type
))
5630 HOST_WIDE_INT size
= int_size_in_bytes (type
);
5631 return (size
== -1 || size
> 8);
5636 /* This was in rtlanal.c, and can go in there when we decide we want
5637 to submit the change for inclusion in the GCC tree. */
5638 /* Like note_stores, but allow the callback to have side effects on the rtl
5639 (like the note_stores of yore):
5640 Call FUN on each register or MEM that is stored into or clobbered by X.
5641 (X would be the pattern of an insn). DATA is an arbitrary pointer,
5642 ignored by note_stores, but passed to FUN.
5643 FUN may alter parts of the RTL.
5645 FUN receives three arguments:
5646 1. the REG, MEM, CC0 or PC being stored in or clobbered,
5647 2. the SET or CLOBBER rtx that does the store,
5648 3. the pointer DATA provided to note_stores.
5650 If the item being stored in or clobbered is a SUBREG of a hard register,
5651 the SUBREG will be passed. */
5653 /* For now. */ static
5655 walk_stores (rtx x
, void (*fun
) (rtx
, rtx
, void *), void *data
)
5659 if (GET_CODE (x
) == COND_EXEC
)
5660 x
= COND_EXEC_CODE (x
);
5662 if (GET_CODE (x
) == SET
|| GET_CODE (x
) == CLOBBER
)
5664 rtx dest
= SET_DEST (x
);
5666 while ((GET_CODE (dest
) == SUBREG
5667 && (!REG_P (SUBREG_REG (dest
))
5668 || REGNO (SUBREG_REG (dest
)) >= FIRST_PSEUDO_REGISTER
))
5669 || GET_CODE (dest
) == ZERO_EXTRACT
5670 || GET_CODE (dest
) == STRICT_LOW_PART
)
5671 dest
= XEXP (dest
, 0);
5673 /* If we have a PARALLEL, SET_DEST is a list of EXPR_LIST expressions,
5674 each of whose first operand is a register. */
5675 if (GET_CODE (dest
) == PARALLEL
)
5677 for (i
= XVECLEN (dest
, 0) - 1; i
>= 0; i
--)
5678 if (XEXP (XVECEXP (dest
, 0, i
), 0) != 0)
5679 (*fun
) (XEXP (XVECEXP (dest
, 0, i
), 0), x
, data
);
5682 (*fun
) (dest
, x
, data
);
5685 else if (GET_CODE (x
) == PARALLEL
)
5686 for (i
= XVECLEN (x
, 0) - 1; i
>= 0; i
--)
5687 walk_stores (XVECEXP (x
, 0, i
), fun
, data
);
5691 arc_pass_by_reference (cumulative_args_t ca_v ATTRIBUTE_UNUSED
,
5692 enum machine_mode mode ATTRIBUTE_UNUSED
,
5694 bool named ATTRIBUTE_UNUSED
)
5697 && (TREE_CODE (TYPE_SIZE (type
)) != INTEGER_CST
5698 || TREE_ADDRESSABLE (type
)));
5701 /* Implement TARGET_CAN_USE_DOLOOP_P. */
5704 arc_can_use_doloop_p (const widest_int
&iterations
, const widest_int
&,
5705 unsigned int loop_depth
, bool entered_at_top
)
5709 /* Setting up the loop with two sr instructions costs 6 cycles. */
5712 && wi::gtu_p (iterations
, 0)
5713 && wi::leu_p (iterations
, flag_pic
? 6 : 3))
5718 /* NULL if INSN insn is valid within a low-overhead loop.
5719 Otherwise return why doloop cannot be applied. */
5722 arc_invalid_within_doloop (const_rtx insn
)
5725 return "Function call in the loop.";
5729 static int arc_reorg_in_progress
= 0;
5731 /* ARC's machince specific reorg function. */
5741 cfun
->machine
->arc_reorg_started
= 1;
5742 arc_reorg_in_progress
= 1;
5744 /* Emit special sections for profiling. */
5747 section
*save_text_section
;
5749 int size
= get_max_uid () >> 4;
5750 htab_t htab
= htab_create (size
, unspec_prof_hash
, unspec_prof_htab_eq
,
5753 save_text_section
= in_section
;
5754 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
5755 if (NONJUMP_INSN_P (insn
))
5756 walk_stores (PATTERN (insn
), write_profile_sections
, htab
);
5757 if (htab_elements (htab
))
5759 switch_to_section (save_text_section
);
5763 /* Link up loop ends with their loop start. */
5765 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
5766 if (GET_CODE (insn
) == JUMP_INSN
5767 && recog_memoized (insn
) == CODE_FOR_doloop_end_i
)
5770 = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn
), 0, 0)), 1), 0);
5771 rtx num
= GEN_INT (CODE_LABEL_NUMBER (top_label
));
5772 rtx lp
, prev
= prev_nonnote_insn (top_label
);
5773 rtx lp_simple
= NULL_RTX
;
5774 rtx next
= NULL_RTX
;
5775 rtx op0
= XEXP (XVECEXP (PATTERN (insn
), 0, 1), 0);
5776 HOST_WIDE_INT loop_end_id
5777 = -INTVAL (XEXP (XVECEXP (PATTERN (insn
), 0, 4), 0));
5781 (lp
&& NONJUMP_INSN_P (lp
)
5782 && recog_memoized (lp
) != CODE_FOR_doloop_begin_i
);
5783 lp
= prev_nonnote_insn (lp
))
5785 if (!lp
|| !NONJUMP_INSN_P (lp
)
5786 || dead_or_set_regno_p (lp
, LP_COUNT
))
5788 for (prev
= next
= insn
, lp
= NULL_RTX
; prev
|| next
;)
5792 if (NONJUMP_INSN_P (prev
)
5793 && recog_memoized (prev
) == CODE_FOR_doloop_begin_i
5794 && (INTVAL (XEXP (XVECEXP (PATTERN (prev
), 0, 5), 0))
5800 else if (LABEL_P (prev
))
5802 prev
= prev_nonnote_insn (prev
);
5806 if (NONJUMP_INSN_P (next
)
5807 && recog_memoized (next
) == CODE_FOR_doloop_begin_i
5808 && (INTVAL (XEXP (XVECEXP (PATTERN (next
), 0, 5), 0))
5814 next
= next_nonnote_insn (next
);
5821 if (lp
&& !dead_or_set_regno_p (lp
, LP_COUNT
))
5823 rtx begin_cnt
= XEXP (XVECEXP (PATTERN (lp
), 0 ,3), 0);
5824 if (INTVAL (XEXP (XVECEXP (PATTERN (lp
), 0, 4), 0)))
5825 /* The loop end insn has been duplicated. That can happen
5826 when there is a conditional block at the very end of
5829 /* If Register allocation failed to allocate to the right
5830 register, There is no point into teaching reload to
5831 fix this up with reloads, as that would cost more
5832 than using an ordinary core register with the
5833 doloop_fallback pattern. */
5834 if ((true_regnum (op0
) != LP_COUNT
|| !REG_P (begin_cnt
))
5835 /* Likewise, if the loop setup is evidently inside the loop,
5837 || (!lp_simple
&& lp
!= next
&& !seen_label
))
5842 /* It is common that the optimizers copy the loop count from
5843 another register, and doloop_begin_i is stuck with the
5844 source of the move. Making doloop_begin_i only accept "l"
5845 is nonsentical, as this then makes reload evict the pseudo
5846 used for the loop end. The underlying cause is that the
5847 optimizers don't understand that the register allocation for
5848 doloop_begin_i should be treated as part of the loop.
5849 Try to work around this problem by verifying the previous
5851 if (true_regnum (begin_cnt
) != LP_COUNT
)
5855 for (mov
= prev_nonnote_insn (lp
); mov
;
5856 mov
= prev_nonnote_insn (mov
))
5858 if (!NONJUMP_INSN_P (mov
))
5860 else if ((set
= single_set (mov
))
5861 && rtx_equal_p (SET_SRC (set
), begin_cnt
)
5862 && rtx_equal_p (SET_DEST (set
), op0
))
5867 XEXP (XVECEXP (PATTERN (lp
), 0 ,3), 0) = op0
;
5868 note
= find_regno_note (lp
, REG_DEAD
, REGNO (begin_cnt
));
5870 remove_note (lp
, note
);
5878 XEXP (XVECEXP (PATTERN (insn
), 0, 4), 0) = num
;
5879 XEXP (XVECEXP (PATTERN (lp
), 0, 4), 0) = num
;
5881 XEXP (XVECEXP (PATTERN (lp
), 0, 6), 0) = const2_rtx
;
5882 else if (!lp_simple
)
5883 XEXP (XVECEXP (PATTERN (lp
), 0, 6), 0) = const1_rtx
;
5884 else if (prev
!= lp
)
5887 add_insn_after (lp
, prev
, NULL
);
5891 XEXP (XVECEXP (PATTERN (lp
), 0, 7), 0)
5892 = gen_rtx_LABEL_REF (Pmode
, top_label
);
5893 add_reg_note (lp
, REG_LABEL_OPERAND
, top_label
);
5894 LABEL_NUSES (top_label
)++;
5896 /* We can avoid tedious loop start / end setting for empty loops
5897 be merely setting the loop count to its final value. */
5898 if (next_active_insn (top_label
) == insn
)
5901 = gen_rtx_SET (VOIDmode
,
5902 XEXP (XVECEXP (PATTERN (lp
), 0, 3), 0),
5905 lc_set
= emit_insn_before (lc_set
, insn
);
5910 /* If the loop is non-empty with zero length, we can't make it
5911 a zero-overhead loop. That can happen for empty asms. */
5916 for (scan
= top_label
;
5917 (scan
&& scan
!= insn
5918 && (!NONJUMP_INSN_P (scan
) || !get_attr_length (scan
)));
5919 scan
= NEXT_INSN (scan
));
5929 /* Sometimes the loop optimizer makes a complete hash of the
5930 loop. If it were only that the loop is not entered at the
5931 top, we could fix this up by setting LP_START with SR .
5932 However, if we can't find the loop begin were it should be,
5933 chances are that it does not even dominate the loop, but is
5934 inside the loop instead. Using SR there would kill
5936 We use the doloop_fallback pattern here, which executes
5937 in two cycles on the ARC700 when predicted correctly. */
5941 rtx op3
= XEXP (XVECEXP (PATTERN (insn
), 0, 5), 0);
5943 emit_insn_before (gen_move_insn (op3
, op0
), insn
);
5945 = gen_doloop_fallback_m (op3
, JUMP_LABEL (insn
), op0
);
5948 XVEC (PATTERN (insn
), 0)
5949 = gen_rtvec (2, XVECEXP (PATTERN (insn
), 0, 0),
5950 XVECEXP (PATTERN (insn
), 0, 1));
5951 INSN_CODE (insn
) = -1;
5956 /* FIXME: should anticipate ccfsm action, generate special patterns for
5957 to-be-deleted branches that have no delay slot and have at least the
5958 length of the size increase forced on other insns that are conditionalized.
5959 This can also have an insn_list inside that enumerates insns which are
5960 not actually conditionalized because the destinations are dead in the
5962 Could also tag branches that we want to be unaligned if they get no delay
5963 slot, or even ones that we don't want to do delay slot sheduling for
5964 because we can unalign them.
5966 However, there are cases when conditional execution is only possible after
5967 delay slot scheduling:
5969 - If a delay slot is filled with a nocond/set insn from above, the previous
5970 basic block can become elegible for conditional execution.
5971 - If a delay slot is filled with a nocond insn from the fall-through path,
5972 the branch with that delay slot can become eligble for conditional
5973 execution (however, with the same sort of data flow analysis that dbr
5974 does, we could have figured out before that we don't need to
5975 conditionalize this insn.)
5976 - If a delay slot insn is filled with an insn from the target, the
5977 target label gets its uses decremented (even deleted if falling to zero),
5978 thus possibly creating more condexec opportunities there.
5979 Therefore, we should still be prepared to apply condexec optimization on
5980 non-prepared branches if the size increase of conditionalized insns is no
5981 more than the size saved from eliminating the branch. An invocation option
5982 could also be used to reserve a bit of extra size for condbranches so that
5983 this'll work more often (could also test in arc_reorg if the block is
5984 'close enough' to be eligible for condexec to make this likely, and
5985 estimate required size increase). */
5986 /* Generate BRcc insns, by combining cmp and Bcc insns wherever possible. */
5987 if (TARGET_NO_BRCC_SET
)
5992 init_insn_lengths();
5995 if (optimize
> 1 && !TARGET_NO_COND_EXEC
)
5998 unsigned int flags
= pass_data_arc_ifcvt
.todo_flags_finish
;
5999 df_finish_pass ((flags
& TODO_df_verify
) != 0);
6002 /* Call shorten_branches to calculate the insn lengths. */
6003 shorten_branches (get_insns());
6004 cfun
->machine
->ccfsm_current_insn
= NULL_RTX
;
6006 if (!INSN_ADDRESSES_SET_P())
6007 fatal_error ("Insn addresses not set after shorten_branches");
6009 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
6012 enum attr_type insn_type
;
6014 /* If a non-jump insn (or a casesi jump table), continue. */
6015 if (GET_CODE (insn
) != JUMP_INSN
||
6016 GET_CODE (PATTERN (insn
)) == ADDR_VEC
6017 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
6020 /* If we already have a brcc, note if it is suitable for brcc_s.
6021 Be a bit generous with the brcc_s range so that we can take
6022 advantage of any code shortening from delay slot scheduling. */
6023 if (recog_memoized (insn
) == CODE_FOR_cbranchsi4_scratch
)
6025 rtx pat
= PATTERN (insn
);
6026 rtx op
= XEXP (SET_SRC (XVECEXP (pat
, 0, 0)), 0);
6027 rtx
*ccp
= &XEXP (XVECEXP (pat
, 0, 1), 0);
6029 offset
= branch_dest (insn
) - INSN_ADDRESSES (INSN_UID (insn
));
6030 if ((offset
>= -140 && offset
< 140)
6031 && rtx_equal_p (XEXP (op
, 1), const0_rtx
)
6032 && compact_register_operand (XEXP (op
, 0), VOIDmode
)
6033 && equality_comparison_operator (op
, VOIDmode
))
6034 PUT_MODE (*ccp
, CC_Zmode
);
6035 else if (GET_MODE (*ccp
) == CC_Zmode
)
6036 PUT_MODE (*ccp
, CC_ZNmode
);
6039 if ((insn_type
= get_attr_type (insn
)) == TYPE_BRCC
6040 || insn_type
== TYPE_BRCC_NO_DELAY_SLOT
)
6043 /* OK. so we have a jump insn. */
6044 /* We need to check that it is a bcc. */
6045 /* Bcc => set (pc) (if_then_else ) */
6046 pattern
= PATTERN (insn
);
6047 if (GET_CODE (pattern
) != SET
6048 || GET_CODE (SET_SRC (pattern
)) != IF_THEN_ELSE
6049 || ANY_RETURN_P (XEXP (SET_SRC (pattern
), 1)))
6052 /* Now check if the jump is beyond the s9 range. */
6053 if (CROSSING_JUMP_P (insn
))
6055 offset
= branch_dest (insn
) - INSN_ADDRESSES (INSN_UID (insn
));
6057 if(offset
> 253 || offset
< -254)
6060 pc_target
= SET_SRC (pattern
);
6062 /* Now go back and search for the set cc insn. */
6064 label
= XEXP (pc_target
, 1);
6067 rtx pat
, scan
, link_insn
= NULL
;
6069 for (scan
= PREV_INSN (insn
);
6070 scan
&& GET_CODE (scan
) != CODE_LABEL
;
6071 scan
= PREV_INSN (scan
))
6073 if (! INSN_P (scan
))
6075 pat
= PATTERN (scan
);
6076 if (GET_CODE (pat
) == SET
6077 && cc_register (SET_DEST (pat
), VOIDmode
))
6086 /* Check if this is a data dependency. */
6088 rtx op
, cc_clob_rtx
, op0
, op1
, brcc_insn
, note
;
6091 /* Ok this is the set cc. copy args here. */
6092 op
= XEXP (pc_target
, 0);
6094 op0
= cmp0
= XEXP (SET_SRC (pat
), 0);
6095 op1
= cmp1
= XEXP (SET_SRC (pat
), 1);
6096 if (GET_CODE (op0
) == ZERO_EXTRACT
6097 && XEXP (op0
, 1) == const1_rtx
6098 && (GET_CODE (op
) == EQ
6099 || GET_CODE (op
) == NE
))
6101 /* btst / b{eq,ne} -> bbit{0,1} */
6102 op0
= XEXP (cmp0
, 0);
6103 op1
= XEXP (cmp0
, 2);
6105 else if (!register_operand (op0
, VOIDmode
)
6106 || !general_operand (op1
, VOIDmode
))
6108 /* Be careful not to break what cmpsfpx_raw is
6109 trying to create for checking equality of
6110 single-precision floats. */
6111 else if (TARGET_SPFP
6112 && GET_MODE (op0
) == SFmode
6113 && GET_MODE (op1
) == SFmode
)
6116 /* None of the two cmp operands should be set between the
6117 cmp and the branch. */
6118 if (reg_set_between_p (op0
, link_insn
, insn
))
6121 if (reg_set_between_p (op1
, link_insn
, insn
))
6124 /* Since the MODE check does not work, check that this is
6125 CC reg's last set location before insn, and also no
6126 instruction between the cmp and branch uses the
6128 if ((reg_set_between_p (SET_DEST (pat
), link_insn
, insn
))
6129 || (reg_used_between_p (SET_DEST (pat
), link_insn
, insn
)))
6132 /* CC reg should be dead after insn. */
6133 if (!find_regno_note (insn
, REG_DEAD
, CC_REG
))
6136 op
= gen_rtx_fmt_ee (GET_CODE (op
),
6137 GET_MODE (op
), cmp0
, cmp1
);
6138 /* If we create a LIMM where there was none before,
6139 we only benefit if we can avoid a scheduling bubble
6140 for the ARC600. Otherwise, we'd only forgo chances
6141 at short insn generation, and risk out-of-range
6143 if (!brcc_nolimm_operator (op
, VOIDmode
)
6144 && !long_immediate_operand (op1
, VOIDmode
)
6146 || next_active_insn (link_insn
) != insn
))
6149 /* Emit bbit / brcc (or brcc_s if possible).
6150 CC_Zmode indicates that brcc_s is possible. */
6153 cc_clob_rtx
= gen_rtx_REG (CC_ZNmode
, CC_REG
);
6154 else if ((offset
>= -140 && offset
< 140)
6155 && rtx_equal_p (op1
, const0_rtx
)
6156 && compact_register_operand (op0
, VOIDmode
)
6157 && (GET_CODE (op
) == EQ
6158 || GET_CODE (op
) == NE
))
6159 cc_clob_rtx
= gen_rtx_REG (CC_Zmode
, CC_REG
);
6161 cc_clob_rtx
= gen_rtx_REG (CCmode
, CC_REG
);
6164 = gen_rtx_IF_THEN_ELSE (VOIDmode
, op
, label
, pc_rtx
);
6165 brcc_insn
= gen_rtx_SET (VOIDmode
, pc_rtx
, brcc_insn
);
6166 cc_clob_rtx
= gen_rtx_CLOBBER (VOIDmode
, cc_clob_rtx
);
6169 (VOIDmode
, gen_rtvec (2, brcc_insn
, cc_clob_rtx
));
6170 brcc_insn
= emit_jump_insn_before (brcc_insn
, insn
);
6172 JUMP_LABEL (brcc_insn
) = JUMP_LABEL (insn
);
6173 note
= find_reg_note (insn
, REG_BR_PROB
, 0);
6176 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6177 REG_NOTES (brcc_insn
) = note
;
6179 note
= find_reg_note (link_insn
, REG_DEAD
, op0
);
6182 remove_note (link_insn
, note
);
6183 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6184 REG_NOTES (brcc_insn
) = note
;
6186 note
= find_reg_note (link_insn
, REG_DEAD
, op1
);
6189 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6190 REG_NOTES (brcc_insn
) = note
;
6195 /* Delete the bcc insn. */
6196 set_insn_deleted (insn
);
6198 /* Delete the cmp insn. */
6199 set_insn_deleted (link_insn
);
6204 /* Clear out insn_addresses. */
6205 INSN_ADDRESSES_FREE ();
6209 if (INSN_ADDRESSES_SET_P())
6210 fatal_error ("insn addresses not freed");
6212 arc_reorg_in_progress
= 0;
6215 /* Check if the operands are valid for BRcc.d generation
6216 Valid Brcc.d patterns are
6220 For cc={GT, LE, GTU, LEU}, u6=63 can not be allowed,
6221 since they are encoded by the assembler as {GE, LT, HS, LS} 64, which
6222 does not have a delay slot
6224 Assumed precondition: Second operand is either a register or a u6 value. */
6227 valid_brcc_with_delay_p (rtx
*operands
)
6229 if (optimize_size
&& GET_MODE (operands
[4]) == CC_Zmode
)
6231 return brcc_nolimm_operator (operands
[0], VOIDmode
);
6234 /* ??? Hack. This should no really be here. See PR32143. */
6236 arc_decl_anon_ns_mem_p (const_tree decl
)
6240 if (decl
== NULL_TREE
|| decl
== error_mark_node
)
6242 if (TREE_CODE (decl
) == NAMESPACE_DECL
6243 && DECL_NAME (decl
) == NULL_TREE
)
6245 /* Classes and namespaces inside anonymous namespaces have
6246 TREE_PUBLIC == 0, so we can shortcut the search. */
6247 else if (TYPE_P (decl
))
6248 return (TREE_PUBLIC (TYPE_NAME (decl
)) == 0);
6249 else if (TREE_CODE (decl
) == NAMESPACE_DECL
)
6250 return (TREE_PUBLIC (decl
) == 0);
6252 decl
= DECL_CONTEXT (decl
);
6256 /* Implement TARGET_IN_SMALL_DATA_P. Return true if it would be safe to
6257 access DECL using %gp_rel(...)($gp). */
6260 arc_in_small_data_p (const_tree decl
)
6264 if (TREE_CODE (decl
) == STRING_CST
|| TREE_CODE (decl
) == FUNCTION_DECL
)
6268 /* We don't yet generate small-data references for -mabicalls. See related
6269 -G handling in override_options. */
6270 if (TARGET_NO_SDATA_SET
)
6273 if (TREE_CODE (decl
) == VAR_DECL
&& DECL_SECTION_NAME (decl
) != 0)
6277 /* Reject anything that isn't in a known small-data section. */
6278 name
= DECL_SECTION_NAME (decl
);
6279 if (strcmp (name
, ".sdata") != 0 && strcmp (name
, ".sbss") != 0)
6282 /* If a symbol is defined externally, the assembler will use the
6283 usual -G rules when deciding how to implement macros. */
6284 if (!DECL_EXTERNAL (decl
))
6287 /* Only global variables go into sdata section for now. */
6290 /* Don't put constants into the small data section: we want them
6291 to be in ROM rather than RAM. */
6292 if (TREE_CODE (decl
) != VAR_DECL
)
6295 if (TREE_READONLY (decl
)
6296 && !TREE_SIDE_EFFECTS (decl
)
6297 && (!DECL_INITIAL (decl
) || TREE_CONSTANT (DECL_INITIAL (decl
))))
6300 /* TREE_PUBLIC might change after the first call, because of the patch
6302 if (default_binds_local_p_1 (decl
, 1)
6303 || arc_decl_anon_ns_mem_p (decl
))
6306 /* To ensure -mvolatile-cache works
6307 ld.di does not have a gp-relative variant. */
6308 if (TREE_THIS_VOLATILE (decl
))
6312 /* Disable sdata references to weak variables. */
6313 if (DECL_WEAK (decl
))
6316 size
= int_size_in_bytes (TREE_TYPE (decl
));
6318 /* if (AGGREGATE_TYPE_P (TREE_TYPE (decl))) */
6321 /* Allow only <=4B long data types into sdata. */
6322 return (size
> 0 && size
<= 4);
6325 /* Return true if X is a small data address that can be rewritten
6329 arc_rewrite_small_data_p (rtx x
)
6331 if (GET_CODE (x
) == CONST
)
6334 if (GET_CODE (x
) == PLUS
)
6336 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
6340 return (GET_CODE (x
) == SYMBOL_REF
6341 && SYMBOL_REF_SMALL_P(x
));
6344 /* A for_each_rtx callback, used by arc_rewrite_small_data. */
6347 arc_rewrite_small_data_1 (rtx
*loc
, void *data
)
6349 if (arc_rewrite_small_data_p (*loc
))
6353 gcc_assert (SDATA_BASE_REGNUM
== PIC_OFFSET_TABLE_REGNUM
);
6354 *loc
= gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, *loc
);
6358 if (GET_CODE (top
) == MEM
&& &XEXP (top
, 0) == loc
)
6360 else if (GET_CODE (top
) == MEM
6361 && GET_CODE (XEXP (top
, 0)) == PLUS
6362 && GET_CODE (XEXP (XEXP (top
, 0), 0)) == MULT
)
6363 *loc
= force_reg (Pmode
, *loc
);
6369 if (GET_CODE (*loc
) == PLUS
6370 && rtx_equal_p (XEXP (*loc
, 0), pic_offset_table_rtx
))
6376 /* If possible, rewrite OP so that it refers to small data using
6377 explicit relocations. */
6380 arc_rewrite_small_data (rtx op
)
6382 op
= copy_insn (op
);
6383 for_each_rtx (&op
, arc_rewrite_small_data_1
, &op
);
6387 /* A for_each_rtx callback for small_data_pattern. */
6390 small_data_pattern_1 (rtx
*loc
, void *data ATTRIBUTE_UNUSED
)
6392 if (GET_CODE (*loc
) == PLUS
6393 && rtx_equal_p (XEXP (*loc
, 0), pic_offset_table_rtx
))
6396 return arc_rewrite_small_data_p (*loc
);
6399 /* Return true if OP refers to small data symbols directly, not through
6403 small_data_pattern (rtx op
, enum machine_mode
)
6405 return (GET_CODE (op
) != SEQUENCE
6406 && for_each_rtx (&op
, small_data_pattern_1
, 0));
6409 /* Return true if OP is an acceptable memory operand for ARCompact
6410 16-bit gp-relative load instructions.
6411 op shd look like : [r26, symref@sda]
6412 i.e. (mem (plus (reg 26) (symref with smalldata flag set))
6414 /* volatile cache option still to be handled. */
6417 compact_sda_memory_operand (rtx op
, enum machine_mode mode
)
6422 /* Eliminate non-memory operations. */
6423 if (GET_CODE (op
) != MEM
)
6426 if (mode
== VOIDmode
)
6427 mode
= GET_MODE (op
);
6429 size
= GET_MODE_SIZE (mode
);
6431 /* dword operations really put out 2 instructions, so eliminate them. */
6432 if (size
> UNITS_PER_WORD
)
6435 /* Decode the address now. */
6436 addr
= XEXP (op
, 0);
6438 return LEGITIMATE_SMALL_DATA_ADDRESS_P (addr
);
6441 /* Implement ASM_OUTPUT_ALIGNED_DECL_LOCAL. */
6444 arc_asm_output_aligned_decl_local (FILE * stream
, tree decl
, const char * name
,
6445 unsigned HOST_WIDE_INT size
,
6446 unsigned HOST_WIDE_INT align
,
6447 unsigned HOST_WIDE_INT globalize_p
)
6449 int in_small_data
= arc_in_small_data_p (decl
);
6452 switch_to_section (get_named_section (NULL
, ".sbss", 0));
6453 /* named_section (0,".sbss",0); */
6455 switch_to_section (bss_section
);
6458 (*targetm
.asm_out
.globalize_label
) (stream
, name
);
6460 ASM_OUTPUT_ALIGN (stream
, floor_log2 ((align
) / BITS_PER_UNIT
));
6461 ASM_OUTPUT_TYPE_DIRECTIVE (stream
, name
, "object");
6462 ASM_OUTPUT_SIZE_DIRECTIVE (stream
, name
, size
);
6463 ASM_OUTPUT_LABEL (stream
, name
);
6466 ASM_OUTPUT_SKIP (stream
, size
);
6502 /* SIMD builtins support. */
6503 enum simd_insn_args_type
{
6526 struct builtin_description
6528 enum simd_insn_args_type args_type
;
6529 const enum insn_code icode
;
6530 const char * const name
;
6531 const enum arc_builtins code
;
6534 static const struct builtin_description arc_simd_builtin_desc_list
[] =
6536 /* VVV builtins go first. */
6537 #define SIMD_BUILTIN(type, code, string, builtin) \
6538 { type,CODE_FOR_##code, "__builtin_arc_" string, \
6539 ARC_SIMD_BUILTIN_##builtin },
6541 SIMD_BUILTIN (Va_Vb_Vc
, vaddaw_insn
, "vaddaw", VADDAW
)
6542 SIMD_BUILTIN (Va_Vb_Vc
, vaddw_insn
, "vaddw", VADDW
)
6543 SIMD_BUILTIN (Va_Vb_Vc
, vavb_insn
, "vavb", VAVB
)
6544 SIMD_BUILTIN (Va_Vb_Vc
, vavrb_insn
, "vavrb", VAVRB
)
6545 SIMD_BUILTIN (Va_Vb_Vc
, vdifaw_insn
, "vdifaw", VDIFAW
)
6546 SIMD_BUILTIN (Va_Vb_Vc
, vdifw_insn
, "vdifw", VDIFW
)
6547 SIMD_BUILTIN (Va_Vb_Vc
, vmaxaw_insn
, "vmaxaw", VMAXAW
)
6548 SIMD_BUILTIN (Va_Vb_Vc
, vmaxw_insn
, "vmaxw", VMAXW
)
6549 SIMD_BUILTIN (Va_Vb_Vc
, vminaw_insn
, "vminaw", VMINAW
)
6550 SIMD_BUILTIN (Va_Vb_Vc
, vminw_insn
, "vminw", VMINW
)
6551 SIMD_BUILTIN (Va_Vb_Vc
, vmulaw_insn
, "vmulaw", VMULAW
)
6552 SIMD_BUILTIN (Va_Vb_Vc
, vmulfaw_insn
, "vmulfaw", VMULFAW
)
6553 SIMD_BUILTIN (Va_Vb_Vc
, vmulfw_insn
, "vmulfw", VMULFW
)
6554 SIMD_BUILTIN (Va_Vb_Vc
, vmulw_insn
, "vmulw", VMULW
)
6555 SIMD_BUILTIN (Va_Vb_Vc
, vsubaw_insn
, "vsubaw", VSUBAW
)
6556 SIMD_BUILTIN (Va_Vb_Vc
, vsubw_insn
, "vsubw", VSUBW
)
6557 SIMD_BUILTIN (Va_Vb_Vc
, vsummw_insn
, "vsummw", VSUMMW
)
6558 SIMD_BUILTIN (Va_Vb_Vc
, vand_insn
, "vand", VAND
)
6559 SIMD_BUILTIN (Va_Vb_Vc
, vandaw_insn
, "vandaw", VANDAW
)
6560 SIMD_BUILTIN (Va_Vb_Vc
, vbic_insn
, "vbic", VBIC
)
6561 SIMD_BUILTIN (Va_Vb_Vc
, vbicaw_insn
, "vbicaw", VBICAW
)
6562 SIMD_BUILTIN (Va_Vb_Vc
, vor_insn
, "vor", VOR
)
6563 SIMD_BUILTIN (Va_Vb_Vc
, vxor_insn
, "vxor", VXOR
)
6564 SIMD_BUILTIN (Va_Vb_Vc
, vxoraw_insn
, "vxoraw", VXORAW
)
6565 SIMD_BUILTIN (Va_Vb_Vc
, veqw_insn
, "veqw", VEQW
)
6566 SIMD_BUILTIN (Va_Vb_Vc
, vlew_insn
, "vlew", VLEW
)
6567 SIMD_BUILTIN (Va_Vb_Vc
, vltw_insn
, "vltw", VLTW
)
6568 SIMD_BUILTIN (Va_Vb_Vc
, vnew_insn
, "vnew", VNEW
)
6569 SIMD_BUILTIN (Va_Vb_Vc
, vmr1aw_insn
, "vmr1aw", VMR1AW
)
6570 SIMD_BUILTIN (Va_Vb_Vc
, vmr1w_insn
, "vmr1w", VMR1W
)
6571 SIMD_BUILTIN (Va_Vb_Vc
, vmr2aw_insn
, "vmr2aw", VMR2AW
)
6572 SIMD_BUILTIN (Va_Vb_Vc
, vmr2w_insn
, "vmr2w", VMR2W
)
6573 SIMD_BUILTIN (Va_Vb_Vc
, vmr3aw_insn
, "vmr3aw", VMR3AW
)
6574 SIMD_BUILTIN (Va_Vb_Vc
, vmr3w_insn
, "vmr3w", VMR3W
)
6575 SIMD_BUILTIN (Va_Vb_Vc
, vmr4aw_insn
, "vmr4aw", VMR4AW
)
6576 SIMD_BUILTIN (Va_Vb_Vc
, vmr4w_insn
, "vmr4w", VMR4W
)
6577 SIMD_BUILTIN (Va_Vb_Vc
, vmr5aw_insn
, "vmr5aw", VMR5AW
)
6578 SIMD_BUILTIN (Va_Vb_Vc
, vmr5w_insn
, "vmr5w", VMR5W
)
6579 SIMD_BUILTIN (Va_Vb_Vc
, vmr6aw_insn
, "vmr6aw", VMR6AW
)
6580 SIMD_BUILTIN (Va_Vb_Vc
, vmr6w_insn
, "vmr6w", VMR6W
)
6581 SIMD_BUILTIN (Va_Vb_Vc
, vmr7aw_insn
, "vmr7aw", VMR7AW
)
6582 SIMD_BUILTIN (Va_Vb_Vc
, vmr7w_insn
, "vmr7w", VMR7W
)
6583 SIMD_BUILTIN (Va_Vb_Vc
, vmrb_insn
, "vmrb", VMRB
)
6584 SIMD_BUILTIN (Va_Vb_Vc
, vh264f_insn
, "vh264f", VH264F
)
6585 SIMD_BUILTIN (Va_Vb_Vc
, vh264ft_insn
, "vh264ft", VH264FT
)
6586 SIMD_BUILTIN (Va_Vb_Vc
, vh264fw_insn
, "vh264fw", VH264FW
)
6587 SIMD_BUILTIN (Va_Vb_Vc
, vvc1f_insn
, "vvc1f", VVC1F
)
6588 SIMD_BUILTIN (Va_Vb_Vc
, vvc1ft_insn
, "vvc1ft", VVC1FT
)
6590 SIMD_BUILTIN (Va_Vb_rlimm
, vbaddw_insn
, "vbaddw", VBADDW
)
6591 SIMD_BUILTIN (Va_Vb_rlimm
, vbmaxw_insn
, "vbmaxw", VBMAXW
)
6592 SIMD_BUILTIN (Va_Vb_rlimm
, vbminw_insn
, "vbminw", VBMINW
)
6593 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulaw_insn
, "vbmulaw", VBMULAW
)
6594 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulfw_insn
, "vbmulfw", VBMULFW
)
6595 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulw_insn
, "vbmulw", VBMULW
)
6596 SIMD_BUILTIN (Va_Vb_rlimm
, vbrsubw_insn
, "vbrsubw", VBRSUBW
)
6597 SIMD_BUILTIN (Va_Vb_rlimm
, vbsubw_insn
, "vbsubw", VBSUBW
)
6599 /* Va, Vb, Ic instructions. */
6600 SIMD_BUILTIN (Va_Vb_Ic
, vasrw_insn
, "vasrw", VASRW
)
6601 SIMD_BUILTIN (Va_Vb_Ic
, vsr8_insn
, "vsr8", VSR8
)
6602 SIMD_BUILTIN (Va_Vb_Ic
, vsr8aw_insn
, "vsr8aw", VSR8AW
)
6604 /* Va, Vb, u6 instructions. */
6605 SIMD_BUILTIN (Va_Vb_u6
, vasrrwi_insn
, "vasrrwi", VASRRWi
)
6606 SIMD_BUILTIN (Va_Vb_u6
, vasrsrwi_insn
, "vasrsrwi", VASRSRWi
)
6607 SIMD_BUILTIN (Va_Vb_u6
, vasrwi_insn
, "vasrwi", VASRWi
)
6608 SIMD_BUILTIN (Va_Vb_u6
, vasrpwbi_insn
, "vasrpwbi", VASRPWBi
)
6609 SIMD_BUILTIN (Va_Vb_u6
, vasrrpwbi_insn
,"vasrrpwbi", VASRRPWBi
)
6610 SIMD_BUILTIN (Va_Vb_u6
, vsr8awi_insn
, "vsr8awi", VSR8AWi
)
6611 SIMD_BUILTIN (Va_Vb_u6
, vsr8i_insn
, "vsr8i", VSR8i
)
6613 /* Va, Vb, u8 (simm) instructions. */
6614 SIMD_BUILTIN (Va_Vb_u8
, vmvaw_insn
, "vmvaw", VMVAW
)
6615 SIMD_BUILTIN (Va_Vb_u8
, vmvw_insn
, "vmvw", VMVW
)
6616 SIMD_BUILTIN (Va_Vb_u8
, vmvzw_insn
, "vmvzw", VMVZW
)
6617 SIMD_BUILTIN (Va_Vb_u8
, vd6tapf_insn
, "vd6tapf", VD6TAPF
)
6619 /* Va, rlimm, u8 (simm) instructions. */
6620 SIMD_BUILTIN (Va_rlimm_u8
, vmovaw_insn
, "vmovaw", VMOVAW
)
6621 SIMD_BUILTIN (Va_rlimm_u8
, vmovw_insn
, "vmovw", VMOVW
)
6622 SIMD_BUILTIN (Va_rlimm_u8
, vmovzw_insn
, "vmovzw", VMOVZW
)
6624 /* Va, Vb instructions. */
6625 SIMD_BUILTIN (Va_Vb
, vabsaw_insn
, "vabsaw", VABSAW
)
6626 SIMD_BUILTIN (Va_Vb
, vabsw_insn
, "vabsw", VABSW
)
6627 SIMD_BUILTIN (Va_Vb
, vaddsuw_insn
, "vaddsuw", VADDSUW
)
6628 SIMD_BUILTIN (Va_Vb
, vsignw_insn
, "vsignw", VSIGNW
)
6629 SIMD_BUILTIN (Va_Vb
, vexch1_insn
, "vexch1", VEXCH1
)
6630 SIMD_BUILTIN (Va_Vb
, vexch2_insn
, "vexch2", VEXCH2
)
6631 SIMD_BUILTIN (Va_Vb
, vexch4_insn
, "vexch4", VEXCH4
)
6632 SIMD_BUILTIN (Va_Vb
, vupbaw_insn
, "vupbaw", VUPBAW
)
6633 SIMD_BUILTIN (Va_Vb
, vupbw_insn
, "vupbw", VUPBW
)
6634 SIMD_BUILTIN (Va_Vb
, vupsbaw_insn
, "vupsbaw", VUPSBAW
)
6635 SIMD_BUILTIN (Va_Vb
, vupsbw_insn
, "vupsbw", VUPSBW
)
6637 /* DIb, rlimm, rlimm instructions. */
6638 SIMD_BUILTIN (Da_rlimm_rlimm
, vdirun_insn
, "vdirun", VDIRUN
)
6639 SIMD_BUILTIN (Da_rlimm_rlimm
, vdorun_insn
, "vdorun", VDORUN
)
6641 /* DIb, limm, rlimm instructions. */
6642 SIMD_BUILTIN (Da_u3_rlimm
, vdiwr_insn
, "vdiwr", VDIWR
)
6643 SIMD_BUILTIN (Da_u3_rlimm
, vdowr_insn
, "vdowr", VDOWR
)
6645 /* rlimm instructions. */
6646 SIMD_BUILTIN (void_rlimm
, vrec_insn
, "vrec", VREC
)
6647 SIMD_BUILTIN (void_rlimm
, vrun_insn
, "vrun", VRUN
)
6648 SIMD_BUILTIN (void_rlimm
, vrecrun_insn
, "vrecrun", VRECRUN
)
6649 SIMD_BUILTIN (void_rlimm
, vendrec_insn
, "vendrec", VENDREC
)
6651 /* Va, [Ib,u8] instructions. */
6652 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32wh_insn
, "vld32wh", VLD32WH
)
6653 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32wl_insn
, "vld32wl", VLD32WL
)
6654 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld64_insn
, "vld64", VLD64
)
6655 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32_insn
, "vld32", VLD32
)
6657 SIMD_BUILTIN (Va_Ib_u8
, vld64w_insn
, "vld64w", VLD64W
)
6658 SIMD_BUILTIN (Va_Ib_u8
, vld128_insn
, "vld128", VLD128
)
6659 SIMD_BUILTIN (void_Va_Ib_u8
, vst128_insn
, "vst128", VST128
)
6660 SIMD_BUILTIN (void_Va_Ib_u8
, vst64_insn
, "vst64", VST64
)
6662 /* Va, [Ib, u8] instructions. */
6663 SIMD_BUILTIN (void_Va_u3_Ib_u8
, vst16_n_insn
, "vst16_n", VST16_N
)
6664 SIMD_BUILTIN (void_Va_u3_Ib_u8
, vst32_n_insn
, "vst32_n", VST32_N
)
6666 SIMD_BUILTIN (void_u6
, vinti_insn
, "vinti", VINTI
)
6670 arc_init_simd_builtins (void)
6673 tree endlink
= void_list_node
;
6674 tree V8HI_type_node
= build_vector_type_for_mode (intHI_type_node
, V8HImode
);
6676 tree v8hi_ftype_v8hi_v8hi
6677 = build_function_type (V8HI_type_node
,
6678 tree_cons (NULL_TREE
, V8HI_type_node
,
6679 tree_cons (NULL_TREE
, V8HI_type_node
,
6681 tree v8hi_ftype_v8hi_int
6682 = build_function_type (V8HI_type_node
,
6683 tree_cons (NULL_TREE
, V8HI_type_node
,
6684 tree_cons (NULL_TREE
, integer_type_node
,
6687 tree v8hi_ftype_v8hi_int_int
6688 = build_function_type (V8HI_type_node
,
6689 tree_cons (NULL_TREE
, V8HI_type_node
,
6690 tree_cons (NULL_TREE
, integer_type_node
,
6691 tree_cons (NULL_TREE
,
6695 tree void_ftype_v8hi_int_int
6696 = build_function_type (void_type_node
,
6697 tree_cons (NULL_TREE
, V8HI_type_node
,
6698 tree_cons (NULL_TREE
, integer_type_node
,
6699 tree_cons (NULL_TREE
,
6703 tree void_ftype_v8hi_int_int_int
6704 = (build_function_type
6706 tree_cons (NULL_TREE
, V8HI_type_node
,
6707 tree_cons (NULL_TREE
, integer_type_node
,
6708 tree_cons (NULL_TREE
, integer_type_node
,
6709 tree_cons (NULL_TREE
,
6713 tree v8hi_ftype_int_int
6714 = build_function_type (V8HI_type_node
,
6715 tree_cons (NULL_TREE
, integer_type_node
,
6716 tree_cons (NULL_TREE
, integer_type_node
,
6719 tree void_ftype_int_int
6720 = build_function_type (void_type_node
,
6721 tree_cons (NULL_TREE
, integer_type_node
,
6722 tree_cons (NULL_TREE
, integer_type_node
,
6726 = build_function_type (void_type_node
,
6727 tree_cons (NULL_TREE
, integer_type_node
, endlink
));
6729 tree v8hi_ftype_v8hi
6730 = build_function_type (V8HI_type_node
, tree_cons (NULL_TREE
, V8HI_type_node
,
6733 /* These asserts have been introduced to ensure that the order of builtins
6734 does not get messed up, else the initialization goes wrong. */
6735 gcc_assert (arc_simd_builtin_desc_list
[0].args_type
== Va_Vb_Vc
);
6736 for (i
=0; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Vc
; i
++)
6737 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6738 v8hi_ftype_v8hi_v8hi
, arc_simd_builtin_desc_list
[i
].code
);
6740 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_rlimm
);
6741 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_rlimm
; i
++)
6742 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6743 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6745 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic
);
6746 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic
; i
++)
6747 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6748 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6750 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u6
);
6751 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u6
; i
++)
6752 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6753 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6755 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u8
);
6756 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u8
; i
++)
6757 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6758 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6760 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_rlimm_u8
);
6761 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_rlimm_u8
; i
++)
6762 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6763 v8hi_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6765 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb
);
6766 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb
; i
++)
6767 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6768 v8hi_ftype_v8hi
, arc_simd_builtin_desc_list
[i
].code
);
6770 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Da_rlimm_rlimm
);
6771 for (; arc_simd_builtin_desc_list
[i
].args_type
== Da_rlimm_rlimm
; i
++)
6772 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6773 void_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6775 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Da_u3_rlimm
);
6776 for (; arc_simd_builtin_desc_list
[i
].args_type
== Da_u3_rlimm
; i
++)
6777 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6778 void_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6780 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_rlimm
);
6781 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_rlimm
; i
++)
6782 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6783 void_ftype_int
, arc_simd_builtin_desc_list
[i
].code
);
6785 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic_u8
);
6786 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic_u8
; i
++)
6787 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6788 v8hi_ftype_v8hi_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6790 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Ib_u8
);
6791 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Ib_u8
; i
++)
6792 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6793 v8hi_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6795 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_Va_Ib_u8
);
6796 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_Va_Ib_u8
; i
++)
6797 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6798 void_ftype_v8hi_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6800 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_Va_u3_Ib_u8
);
6801 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_Va_u3_Ib_u8
; i
++)
6802 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6803 void_ftype_v8hi_int_int_int
,
6804 arc_simd_builtin_desc_list
[i
].code
);
6806 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_u6
);
6807 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_u6
; i
++)
6808 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6809 void_ftype_int
, arc_simd_builtin_desc_list
[i
].code
);
6811 gcc_assert(i
== ARRAY_SIZE (arc_simd_builtin_desc_list
));
6814 /* Helper function of arc_expand_builtin; has the same parameters,
6815 except that EXP is now known to be a call to a simd builtin. */
6818 arc_expand_simd_builtin (tree exp
,
6820 rtx subtarget ATTRIBUTE_UNUSED
,
6821 enum machine_mode mode ATTRIBUTE_UNUSED
,
6822 int ignore ATTRIBUTE_UNUSED
)
6824 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
6836 int fcode
= DECL_FUNCTION_CODE (fndecl
);
6838 enum machine_mode mode0
;
6839 enum machine_mode mode1
;
6840 enum machine_mode mode2
;
6841 enum machine_mode mode3
;
6842 enum machine_mode mode4
;
6843 const struct builtin_description
* d
;
6845 for (i
= 0, d
= arc_simd_builtin_desc_list
;
6846 i
< ARRAY_SIZE (arc_simd_builtin_desc_list
); i
++, d
++)
6847 if (d
->code
== (const enum arc_builtins
) fcode
)
6850 /* We must get an entry here. */
6851 gcc_assert (i
< ARRAY_SIZE (arc_simd_builtin_desc_list
));
6853 switch (d
->args_type
)
6857 arg0
= CALL_EXPR_ARG (exp
, 0);
6858 arg1
= CALL_EXPR_ARG (exp
, 1);
6859 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6860 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6862 target
= gen_reg_rtx (V8HImode
);
6863 mode0
= insn_data
[icode
].operand
[1].mode
;
6864 mode1
= insn_data
[icode
].operand
[2].mode
;
6866 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6867 op0
= copy_to_mode_reg (mode0
, op0
);
6869 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6870 op1
= copy_to_mode_reg (mode1
, op1
);
6872 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
6882 arg0
= CALL_EXPR_ARG (exp
, 0);
6883 arg1
= CALL_EXPR_ARG (exp
, 1);
6884 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6885 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6887 target
= gen_reg_rtx (V8HImode
);
6888 mode0
= insn_data
[icode
].operand
[1].mode
;
6889 mode1
= insn_data
[icode
].operand
[2].mode
;
6891 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6892 op0
= copy_to_mode_reg (mode0
, op0
);
6894 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
)
6895 || (d
->args_type
== Va_Vb_u6
&& !UNSIGNED_INT6 (INTVAL (op1
)))
6896 || (d
->args_type
== Va_Vb_u8
&& !UNSIGNED_INT8 (INTVAL (op1
))))
6897 error ("operand 2 of %s instruction should be an unsigned %d-bit value",
6899 (d
->args_type
== Va_Vb_u6
)? 6: 8);
6901 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
6910 arg0
= CALL_EXPR_ARG (exp
, 0);
6911 arg1
= CALL_EXPR_ARG (exp
, 1);
6912 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6913 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6915 target
= gen_reg_rtx (V8HImode
);
6916 mode0
= insn_data
[icode
].operand
[1].mode
;
6917 mode1
= insn_data
[icode
].operand
[2].mode
;
6919 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6920 op0
= copy_to_mode_reg (mode0
, op0
);
6922 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6923 || !(UNSIGNED_INT8 (INTVAL (op1
))))
6924 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
6927 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
6936 arg0
= CALL_EXPR_ARG (exp
, 0);
6937 arg1
= CALL_EXPR_ARG (exp
, 1);
6938 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6939 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6940 op2
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
);
6942 target
= gen_reg_rtx (V8HImode
);
6943 mode0
= insn_data
[icode
].operand
[1].mode
;
6944 mode1
= insn_data
[icode
].operand
[2].mode
;
6946 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6947 op0
= copy_to_mode_reg (mode0
, op0
);
6949 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6950 || !(UNSIGNED_INT3 (INTVAL (op1
))))
6951 error ("operand 2 of %s instruction should be an unsigned 3-bit value (I0-I7)",
6954 pat
= GEN_FCN (icode
) (target
, op0
, op1
, op2
);
6963 arg0
= CALL_EXPR_ARG (exp
, 0);
6964 arg1
= CALL_EXPR_ARG (exp
, 1);
6965 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6966 op1
= expand_expr (arg1
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6968 target
= gen_reg_rtx (V8HImode
);
6969 mode0
= insn_data
[icode
].operand
[1].mode
;
6970 mode1
= insn_data
[icode
].operand
[2].mode
;
6972 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6973 op0
= copy_to_mode_reg (mode0
, op0
);
6975 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6976 op1
= copy_to_mode_reg (mode1
, op1
);
6978 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
6987 arg0
= CALL_EXPR_ARG (exp
, 0);
6988 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6990 target
= gen_reg_rtx (V8HImode
);
6991 mode0
= insn_data
[icode
].operand
[1].mode
;
6993 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6994 op0
= copy_to_mode_reg (mode0
, op0
);
6996 pat
= GEN_FCN (icode
) (target
, op0
);
7003 case Da_rlimm_rlimm
:
7005 arg0
= CALL_EXPR_ARG (exp
, 0);
7006 arg1
= CALL_EXPR_ARG (exp
, 1);
7007 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7008 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7011 if (icode
== CODE_FOR_vdirun_insn
)
7012 target
= gen_rtx_REG (SImode
, 131);
7013 else if (icode
== CODE_FOR_vdorun_insn
)
7014 target
= gen_rtx_REG (SImode
, 139);
7018 mode0
= insn_data
[icode
].operand
[1].mode
;
7019 mode1
= insn_data
[icode
].operand
[2].mode
;
7021 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
7022 op0
= copy_to_mode_reg (mode0
, op0
);
7024 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7025 op1
= copy_to_mode_reg (mode1
, op1
);
7028 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
7037 arg0
= CALL_EXPR_ARG (exp
, 0);
7038 arg1
= CALL_EXPR_ARG (exp
, 1);
7039 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7040 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7043 if (! (GET_CODE (op0
) == CONST_INT
)
7044 || !(UNSIGNED_INT3 (INTVAL (op0
))))
7045 error ("operand 1 of %s instruction should be an unsigned 3-bit value (DR0-DR7)",
7048 mode1
= insn_data
[icode
].operand
[1].mode
;
7050 if (icode
== CODE_FOR_vdiwr_insn
)
7051 target
= gen_rtx_REG (SImode
,
7052 ARC_FIRST_SIMD_DMA_CONFIG_IN_REG
+ INTVAL (op0
));
7053 else if (icode
== CODE_FOR_vdowr_insn
)
7054 target
= gen_rtx_REG (SImode
,
7055 ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG
+ INTVAL (op0
));
7059 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7060 op1
= copy_to_mode_reg (mode1
, op1
);
7062 pat
= GEN_FCN (icode
) (target
, op1
);
7071 arg0
= CALL_EXPR_ARG (exp
, 0);
7075 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7076 mode0
= insn_data
[icode
].operand
[0].mode
;
7078 /* op0 should be u6. */
7079 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
)
7080 || !(UNSIGNED_INT6 (INTVAL (op0
))))
7081 error ("operand of %s instruction should be an unsigned 6-bit value",
7084 pat
= GEN_FCN (icode
) (op0
);
7093 arg0
= CALL_EXPR_ARG (exp
, 0);
7097 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7098 mode0
= insn_data
[icode
].operand
[0].mode
;
7100 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
7101 op0
= copy_to_mode_reg (mode0
, op0
);
7103 pat
= GEN_FCN (icode
) (op0
);
7114 arg0
= CALL_EXPR_ARG (exp
, 0); /* source vreg */
7115 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7116 arg2
= CALL_EXPR_ARG (exp
, 2); /* u8 */
7118 src_vreg
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
7119 op0
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* [I]0-7 */
7120 op1
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7121 op2
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7123 /* target <- src vreg */
7124 emit_insn (gen_move_insn (target
, src_vreg
));
7126 /* target <- vec_concat: target, mem(Ib, u8) */
7127 mode0
= insn_data
[icode
].operand
[3].mode
;
7128 mode1
= insn_data
[icode
].operand
[1].mode
;
7130 if ( (!(*insn_data
[icode
].operand
[3].predicate
) (op0
, mode0
))
7131 || !(UNSIGNED_INT3 (INTVAL (op0
))))
7132 error ("operand 1 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7135 if ( (!(*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
7136 || !(UNSIGNED_INT8 (INTVAL (op1
))))
7137 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
7140 pat
= GEN_FCN (icode
) (target
, op1
, op2
, op0
);
7150 arg0
= CALL_EXPR_ARG (exp
, 0); /* src vreg */
7151 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7152 arg2
= CALL_EXPR_ARG (exp
, 2); /* u8 */
7154 op0
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7155 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* I[0-7] */
7156 op2
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7157 op3
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
); /* Vdest */
7159 mode0
= insn_data
[icode
].operand
[0].mode
;
7160 mode1
= insn_data
[icode
].operand
[1].mode
;
7161 mode2
= insn_data
[icode
].operand
[2].mode
;
7162 mode3
= insn_data
[icode
].operand
[3].mode
;
7164 if ( (!(*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
7165 || !(UNSIGNED_INT3 (INTVAL (op1
))))
7166 error ("operand 2 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7169 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op2
, mode2
))
7170 || !(UNSIGNED_INT8 (INTVAL (op2
))))
7171 error ("operand 3 of %s instruction should be an unsigned 8-bit value",
7174 if (!(*insn_data
[icode
].operand
[3].predicate
) (op3
, mode3
))
7175 op3
= copy_to_mode_reg (mode3
, op3
);
7177 pat
= GEN_FCN (icode
) (op0
, op1
, op2
, op3
);
7186 arg0
= CALL_EXPR_ARG (exp
, 0); /* dest vreg */
7187 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7189 op0
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7190 op1
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* I[0-7] */
7191 op2
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7193 /* target <- src vreg */
7194 target
= gen_reg_rtx (V8HImode
);
7196 /* target <- vec_concat: target, mem(Ib, u8) */
7197 mode0
= insn_data
[icode
].operand
[1].mode
;
7198 mode1
= insn_data
[icode
].operand
[2].mode
;
7199 mode2
= insn_data
[icode
].operand
[3].mode
;
7201 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7202 || !(UNSIGNED_INT3 (INTVAL (op1
))))
7203 error ("operand 1 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7206 if ( (!(*insn_data
[icode
].operand
[3].predicate
) (op2
, mode2
))
7207 || !(UNSIGNED_INT8 (INTVAL (op2
))))
7208 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
7211 pat
= GEN_FCN (icode
) (target
, op0
, op1
, op2
);
7218 case void_Va_u3_Ib_u8
:
7220 arg0
= CALL_EXPR_ARG (exp
, 0); /* source vreg */
7221 arg1
= CALL_EXPR_ARG (exp
, 1); /* u3 */
7222 arg2
= CALL_EXPR_ARG (exp
, 2); /* [I]0-7 */
7223 arg3
= CALL_EXPR_ARG (exp
, 3); /* u8 */
7225 op0
= expand_expr (arg3
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7226 op1
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR */
7227 op2
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* [I]0-7 */
7228 op3
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);/* vreg to be stored */
7229 op4
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* vreg 0-7 subreg no. */
7231 mode0
= insn_data
[icode
].operand
[0].mode
;
7232 mode2
= insn_data
[icode
].operand
[2].mode
;
7233 mode3
= insn_data
[icode
].operand
[3].mode
;
7234 mode4
= insn_data
[icode
].operand
[4].mode
;
7236 /* Do some correctness checks for the operands. */
7237 if ( (!(*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
7238 || !(UNSIGNED_INT8 (INTVAL (op0
))))
7239 error ("operand 4 of %s instruction should be an unsigned 8-bit value (0-255)",
7242 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op2
, mode2
))
7243 || !(UNSIGNED_INT3 (INTVAL (op2
))))
7244 error ("operand 3 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7247 if (!(*insn_data
[icode
].operand
[3].predicate
) (op3
, mode3
))
7248 op3
= copy_to_mode_reg (mode3
, op3
);
7250 if ( (!(*insn_data
[icode
].operand
[4].predicate
) (op4
, mode4
))
7251 || !(UNSIGNED_INT3 (INTVAL (op4
))))
7252 error ("operand 2 of %s instruction should be an unsigned 3-bit value (subreg 0-7)",
7254 else if (icode
== CODE_FOR_vst32_n_insn
7255 && ((INTVAL(op4
) % 2 ) != 0))
7256 error ("operand 2 of %s instruction should be an even 3-bit value (subreg 0,2,4,6)",
7259 pat
= GEN_FCN (icode
) (op0
, op1
, op2
, op3
, op4
);
7273 arc_preserve_reload_p (rtx in
)
7275 return (GET_CODE (in
) == PLUS
7276 && RTX_OK_FOR_BASE_P (XEXP (in
, 0), true)
7277 && CONST_INT_P (XEXP (in
, 1))
7278 && !((INTVAL (XEXP (in
, 1)) & 511)));
7282 arc_register_move_cost (enum machine_mode
,
7283 enum reg_class from_class
, enum reg_class to_class
)
7285 /* The ARC600 has no bypass for extension registers, hence a nop might be
7286 needed to be inserted after a write so that reads are safe. */
7289 if (to_class
== MPY_WRITABLE_CORE_REGS
)
7291 /* Instructions modifying LP_COUNT need 4 additional cycles before
7292 the register will actually contain the value. */
7293 else if (to_class
== LPCOUNT_REG
)
7295 else if (to_class
== WRITABLE_CORE_REGS
)
7299 /* The ARC700 stalls for 3 cycles when *reading* from lp_count. */
7301 && (from_class
== LPCOUNT_REG
|| from_class
== ALL_CORE_REGS
7302 || from_class
== WRITABLE_CORE_REGS
))
7305 /* Force an attempt to 'mov Dy,Dx' to spill. */
7306 if (TARGET_ARC700
&& TARGET_DPFP
7307 && from_class
== DOUBLE_REGS
&& to_class
== DOUBLE_REGS
)
7313 /* Emit code for an addsi3 instruction with OPERANDS.
7314 COND_P indicates if this will use conditional execution.
7315 Return the length of the instruction.
7316 If OUTPUT_P is false, don't actually output the instruction, just return
7319 arc_output_addsi (rtx
*operands
, bool cond_p
, bool output_p
)
7323 int match
= operands_match_p (operands
[0], operands
[1]);
7324 int match2
= operands_match_p (operands
[0], operands
[2]);
7325 int intval
= (REG_P (operands
[2]) ? 1
7326 : CONST_INT_P (operands
[2]) ? INTVAL (operands
[2]) : 0xbadc057);
7327 int neg_intval
= -intval
;
7328 int short_0
= satisfies_constraint_Rcq (operands
[0]);
7329 int short_p
= (!cond_p
&& short_0
&& satisfies_constraint_Rcq (operands
[1]));
7332 #define ADDSI_OUTPUT1(FORMAT) do {\
7334 output_asm_insn (FORMAT, operands);\
7337 #define ADDSI_OUTPUT(LIST) do {\
7340 ADDSI_OUTPUT1 (format);\
7344 /* First try to emit a 16 bit insn. */
7347 /* If we are actually about to output this insn, don't try a 16 bit
7348 variant if we already decided that we don't want that
7349 (I.e. we upsized this insn to align some following insn.)
7350 E.g. add_s r0,sp,70 is 16 bit, but add r0,sp,70 requires a LIMM -
7351 but add1 r0,sp,35 doesn't. */
7352 && (!output_p
|| (get_attr_length (current_output_insn
) & 2)))
7355 && (REG_P (operands
[2])
7356 ? (match
|| satisfies_constraint_Rcq (operands
[2]))
7357 : (unsigned) intval
<= (match
? 127 : 7)))
7358 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7359 if (short_0
&& REG_P (operands
[1]) && match2
)
7360 ADDSI_OUTPUT1 ("add%? %0,%2,%1");
7361 if ((short_0
|| REGNO (operands
[0]) == STACK_POINTER_REGNUM
)
7362 && REGNO (operands
[1]) == STACK_POINTER_REGNUM
&& !(intval
& ~124))
7363 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7365 if ((short_p
&& (unsigned) neg_intval
<= (match
? 31 : 7))
7366 || (REGNO (operands
[0]) == STACK_POINTER_REGNUM
7367 && match
&& !(neg_intval
& ~124)))
7368 ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
7371 /* Now try to emit a 32 bit insn without long immediate. */
7373 if (!match
&& match2
&& REG_P (operands
[1]))
7374 ADDSI_OUTPUT1 ("add%? %0,%2,%1");
7375 if (match
|| !cond_p
)
7377 int limit
= (match
&& !cond_p
) ? 0x7ff : 0x3f;
7378 int range_factor
= neg_intval
& intval
;
7381 if (intval
== -1 << 31)
7382 ADDSI_OUTPUT1 ("bxor%? %0,%1,31");
7384 /* If we can use a straight add / sub instead of a {add,sub}[123] of
7385 same size, do, so - the insn latency is lower. */
7386 /* -0x800 is a 12-bit constant for add /add3 / sub / sub3, but
7388 if ((intval
>= 0 && intval
<= limit
)
7389 || (intval
== -0x800 && limit
== 0x7ff))
7390 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7391 else if ((intval
< 0 && neg_intval
<= limit
)
7392 || (intval
== 0x800 && limit
== 0x7ff))
7393 ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
7394 shift
= range_factor
>= 8 ? 3 : (range_factor
>> 1);
7395 gcc_assert (shift
== 0 || shift
== 1 || shift
== 2 || shift
== 3);
7396 gcc_assert ((((1 << shift
) - 1) & intval
) == 0);
7397 if (((intval
< 0 && intval
!= -0x4000)
7398 /* sub[123] is slower than add_s / sub, only use it if it
7399 avoids a long immediate. */
7400 && neg_intval
<= limit
<< shift
)
7401 || (intval
== 0x4000 && limit
== 0x7ff))
7402 ADDSI_OUTPUT ((format
, "sub%d%%? %%0,%%1,%d",
7403 shift
, neg_intval
>> shift
));
7404 else if ((intval
>= 0 && intval
<= limit
<< shift
)
7405 || (intval
== -0x4000 && limit
== 0x7ff))
7406 ADDSI_OUTPUT ((format
, "add%d%%? %%0,%%1,%d", shift
, intval
>> shift
));
7408 /* Try to emit a 16 bit opcode with long immediate. */
7410 if (short_p
&& match
)
7411 ADDSI_OUTPUT1 ("add%? %0,%1,%S2");
7413 /* We have to use a 32 bit opcode, and with a long immediate. */
7415 ADDSI_OUTPUT1 (intval
< 0 ? "sub%? %0,%1,%n2" : "add%? %0,%1,%S2");
7418 /* Emit code for an commutative_cond_exec instruction with OPERANDS.
7419 Return the length of the instruction.
7420 If OUTPUT_P is false, don't actually output the instruction, just return
7423 arc_output_commutative_cond_exec (rtx
*operands
, bool output_p
)
7425 enum rtx_code commutative_op
= GET_CODE (operands
[3]);
7426 const char *pat
= NULL
;
7428 /* Canonical rtl should not have a constant in the first operand position. */
7429 gcc_assert (!CONSTANT_P (operands
[1]));
7431 switch (commutative_op
)
7434 if (satisfies_constraint_C1p (operands
[2]))
7435 pat
= "bmsk%? %0,%1,%Z2";
7436 else if (satisfies_constraint_Ccp (operands
[2]))
7437 pat
= "bclr%? %0,%1,%M2";
7438 else if (satisfies_constraint_CnL (operands
[2]))
7439 pat
= "bic%? %0,%1,%n2-1";
7442 if (satisfies_constraint_C0p (operands
[2]))
7443 pat
= "bset%? %0,%1,%z2";
7446 if (satisfies_constraint_C0p (operands
[2]))
7447 pat
= "bxor%? %0,%1,%z2";
7450 return arc_output_addsi (operands
, true, output_p
);
7454 output_asm_insn (pat
? pat
: "%O3.%d5 %0,%1,%2", operands
);
7455 if (pat
|| REG_P (operands
[2]) || satisfies_constraint_L (operands
[2]))
7460 /* Helper function of arc_expand_movmem. ADDR points to a chunk of memory.
7461 Emit code and return an potentially modified address such that offsets
7462 up to SIZE are can be added to yield a legitimate address.
7463 if REUSE is set, ADDR is a register that may be modified. */
7466 force_offsettable (rtx addr
, HOST_WIDE_INT size
, bool reuse
)
7469 rtx offs
= const0_rtx
;
7471 if (GET_CODE (base
) == PLUS
)
7473 offs
= XEXP (base
, 1);
7474 base
= XEXP (base
, 0);
7477 || (REGNO (base
) != STACK_POINTER_REGNUM
7478 && REGNO_PTR_FRAME_P (REGNO (addr
)))
7479 || !CONST_INT_P (offs
) || !SMALL_INT (INTVAL (offs
))
7480 || !SMALL_INT (INTVAL (offs
) + size
))
7483 emit_insn (gen_add2_insn (addr
, offs
));
7485 addr
= copy_to_mode_reg (Pmode
, addr
);
7490 /* Like move_by_pieces, but take account of load latency,
7491 and actual offset ranges.
7492 Return true on success. */
7495 arc_expand_movmem (rtx
*operands
)
7497 rtx dst
= operands
[0];
7498 rtx src
= operands
[1];
7499 rtx dst_addr
, src_addr
;
7501 int align
= INTVAL (operands
[3]);
7508 if (!CONST_INT_P (operands
[2]))
7510 size
= INTVAL (operands
[2]);
7511 /* move_by_pieces_ninsns is static, so we can't use it. */
7513 n_pieces
= (size
+ 2) / 4U + (size
& 1);
7514 else if (align
== 2)
7515 n_pieces
= (size
+ 1) / 2U;
7518 if (n_pieces
>= (unsigned int) (optimize_size
? 3 : 15))
7522 dst_addr
= force_offsettable (XEXP (operands
[0], 0), size
, 0);
7523 src_addr
= force_offsettable (XEXP (operands
[1], 0), size
, 0);
7524 store
[0] = store
[1] = NULL_RTX
;
7525 tmpx
[0] = tmpx
[1] = NULL_RTX
;
7526 for (i
= 0; size
> 0; i
^= 1, size
-= piece
)
7529 enum machine_mode mode
;
7532 piece
= size
& -size
;
7533 mode
= smallest_mode_for_size (piece
* BITS_PER_UNIT
, MODE_INT
);
7534 /* If we don't re-use temporaries, the scheduler gets carried away,
7535 and the register pressure gets unnecessarily high. */
7536 if (0 && tmpx
[i
] && GET_MODE (tmpx
[i
]) == mode
)
7539 tmpx
[i
] = tmp
= gen_reg_rtx (mode
);
7540 dst_addr
= force_offsettable (dst_addr
, piece
, 1);
7541 src_addr
= force_offsettable (src_addr
, piece
, 1);
7543 emit_insn (store
[i
]);
7544 emit_move_insn (tmp
, change_address (src
, mode
, src_addr
));
7545 store
[i
] = gen_move_insn (change_address (dst
, mode
, dst_addr
), tmp
);
7546 dst_addr
= plus_constant (Pmode
, dst_addr
, piece
);
7547 src_addr
= plus_constant (Pmode
, src_addr
, piece
);
7550 emit_insn (store
[i
]);
7552 emit_insn (store
[i
^1]);
7556 /* Prepare operands for move in MODE. Return true iff the move has
7560 prepare_move_operands (rtx
*operands
, enum machine_mode mode
)
7562 /* We used to do this only for MODE_INT Modes, but addresses to floating
7563 point variables may well be in the small data section. */
7566 if (!TARGET_NO_SDATA_SET
&& small_data_pattern (operands
[0], Pmode
))
7567 operands
[0] = arc_rewrite_small_data (operands
[0]);
7568 else if (mode
== SImode
&& flag_pic
&& SYMBOLIC_CONST (operands
[1]))
7570 emit_pic_move (operands
, SImode
);
7572 /* Disable any REG_EQUALs associated with the symref
7573 otherwise the optimization pass undoes the work done
7574 here and references the variable directly. */
7576 else if (GET_CODE (operands
[0]) != MEM
7577 && !TARGET_NO_SDATA_SET
7578 && small_data_pattern (operands
[1], Pmode
))
7580 /* This is to take care of address calculations involving sdata
7582 operands
[1] = arc_rewrite_small_data (operands
[1]);
7584 emit_insn (gen_rtx_SET (mode
, operands
[0],operands
[1]));
7585 /* ??? This note is useless, since it only restates the set itself.
7586 We should rather use the original SYMBOL_REF. However, there is
7587 the problem that we are lying to the compiler about these
7588 SYMBOL_REFs to start with. symbol@sda should be encoded specially
7589 so that we can tell it apart from an actual symbol. */
7590 set_unique_reg_note (get_last_insn (), REG_EQUAL
, operands
[1]);
7592 /* Take care of the REG_EQUAL note that will be attached to mark the
7593 output reg equal to the initial symbol_ref after this code is
7595 emit_move_insn (operands
[0], operands
[0]);
7600 if (MEM_P (operands
[0])
7601 && !(reload_in_progress
|| reload_completed
))
7603 operands
[1] = force_reg (mode
, operands
[1]);
7604 if (!move_dest_operand (operands
[0], mode
))
7606 rtx addr
= copy_to_mode_reg (Pmode
, XEXP (operands
[0], 0));
7607 /* This is like change_address_1 (operands[0], mode, 0, 1) ,
7608 except that we can't use that function because it is static. */
7609 rtx pat
= change_address (operands
[0], mode
, addr
);
7610 MEM_COPY_ATTRIBUTES (pat
, operands
[0]);
7613 if (!cse_not_expected
)
7615 rtx pat
= XEXP (operands
[0], 0);
7617 pat
= arc_legitimize_address_0 (pat
, pat
, mode
);
7620 pat
= change_address (operands
[0], mode
, pat
);
7621 MEM_COPY_ATTRIBUTES (pat
, operands
[0]);
7627 if (MEM_P (operands
[1]) && !cse_not_expected
)
7629 rtx pat
= XEXP (operands
[1], 0);
7631 pat
= arc_legitimize_address_0 (pat
, pat
, mode
);
7634 pat
= change_address (operands
[1], mode
, pat
);
7635 MEM_COPY_ATTRIBUTES (pat
, operands
[1]);
7643 /* Prepare OPERANDS for an extension using CODE to OMODE.
7644 Return true iff the move has been emitted. */
7647 prepare_extend_operands (rtx
*operands
, enum rtx_code code
,
7648 enum machine_mode omode
)
7650 if (!TARGET_NO_SDATA_SET
&& small_data_pattern (operands
[1], Pmode
))
7652 /* This is to take care of address calculations involving sdata
7655 = gen_rtx_fmt_e (code
, omode
, arc_rewrite_small_data (operands
[1]));
7656 emit_insn (gen_rtx_SET (omode
, operands
[0], operands
[1]));
7657 set_unique_reg_note (get_last_insn (), REG_EQUAL
, operands
[1]);
7659 /* Take care of the REG_EQUAL note that will be attached to mark the
7660 output reg equal to the initial extension after this code is
7662 emit_move_insn (operands
[0], operands
[0]);
7668 /* Output a library call to a function called FNAME that has been arranged
7669 to be local to any dso. */
7672 arc_output_libcall (const char *fname
)
7674 unsigned len
= strlen (fname
);
7675 static char buf
[64];
7677 gcc_assert (len
< sizeof buf
- 35);
7678 if (TARGET_LONG_CALLS_SET
7679 || (TARGET_MEDIUM_CALLS
&& arc_ccfsm_cond_exec_p ()))
7682 sprintf (buf
, "add r12,pcl,@%s-(.&-4)\n\tjl%%!%%* [r12]", fname
);
7684 sprintf (buf
, "jl%%! @%s", fname
);
7687 sprintf (buf
, "bl%%!%%* @%s", fname
);
7691 /* Return the SImode highpart of the DImode value IN. */
7694 disi_highpart (rtx in
)
7696 return simplify_gen_subreg (SImode
, in
, DImode
, TARGET_BIG_ENDIAN
? 0 : 4);
7699 /* Called by arc600_corereg_hazard via for_each_rtx.
7700 If a hazard is found, return a conservative estimate of the required
7701 length adjustment to accomodate a nop. */
7704 arc600_corereg_hazard_1 (rtx
*xp
, void *data
)
7708 rtx pat
= (rtx
) data
;
7710 switch (GET_CODE (x
))
7712 case SET
: case POST_INC
: case POST_DEC
: case PRE_INC
: case PRE_DEC
:
7715 /* This is also fine for PRE/POST_MODIFY, because they contain a SET. */
7719 /* Check if this sets a an extension register. N.B. we use 61 for the
7720 condition codes, which is definitely not an extension register. */
7721 if (REG_P (dest
) && REGNO (dest
) >= 32 && REGNO (dest
) < 61
7722 /* Check if the same register is used by the PAT. */
7723 && (refers_to_regno_p
7725 REGNO (dest
) + (GET_MODE_SIZE (GET_MODE (dest
)) + 3) / 4U, pat
, 0)))
7731 /* Return length adjustment for INSN.
7733 A write to a core reg greater or equal to 32 must not be immediately
7734 followed by a use. Anticipate the length requirement to insert a nop
7735 between PRED and SUCC to prevent a hazard. */
7738 arc600_corereg_hazard (rtx pred
, rtx succ
)
7742 /* If SUCC is a doloop_end_i with a preceding label, we must output a nop
7743 in front of SUCC anyway, so there will be separation between PRED and
7745 if (recog_memoized (succ
) == CODE_FOR_doloop_end_i
7746 && LABEL_P (prev_nonnote_insn (succ
)))
7748 if (recog_memoized (succ
) == CODE_FOR_doloop_begin_i
)
7750 if (GET_CODE (PATTERN (pred
)) == SEQUENCE
)
7751 pred
= XVECEXP (PATTERN (pred
), 0, 1);
7752 if (GET_CODE (PATTERN (succ
)) == SEQUENCE
)
7753 succ
= XVECEXP (PATTERN (succ
), 0, 0);
7754 if (recog_memoized (pred
) == CODE_FOR_mulsi_600
7755 || recog_memoized (pred
) == CODE_FOR_umul_600
7756 || recog_memoized (pred
) == CODE_FOR_mac_600
7757 || recog_memoized (pred
) == CODE_FOR_mul64_600
7758 || recog_memoized (pred
) == CODE_FOR_mac64_600
7759 || recog_memoized (pred
) == CODE_FOR_umul64_600
7760 || recog_memoized (pred
) == CODE_FOR_umac64_600
)
7762 return for_each_rtx (&PATTERN (pred
), arc600_corereg_hazard_1
,
7767 A write to a core reg greater or equal to 32 must not be immediately
7768 followed by a use. Anticipate the length requirement to insert a nop
7769 between PRED and SUCC to prevent a hazard. */
7772 arc_hazard (rtx pred
, rtx succ
)
7776 if (!pred
|| !INSN_P (pred
) || !succ
|| !INSN_P (succ
))
7778 /* We might have a CALL to a non-returning function before a loop end.
7779 ??? Although the manual says that's OK (the target is outside the loop,
7780 and the loop counter unused there), the assembler barfs on this, so we
7781 must instert a nop before such a call too. */
7782 if (recog_memoized (succ
) == CODE_FOR_doloop_end_i
7783 && (JUMP_P (pred
) || CALL_P (pred
)
7784 || GET_CODE (PATTERN (pred
)) == SEQUENCE
))
7786 return arc600_corereg_hazard (pred
, succ
);
7789 /* Return length adjustment for INSN. */
7792 arc_adjust_insn_length (rtx insn
, int len
, bool)
7796 /* We already handle sequences by ignoring the delay sequence flag. */
7797 if (GET_CODE (PATTERN (insn
)) == SEQUENCE
)
7800 /* It is impossible to jump to the very end of a Zero-Overhead Loop, as
7801 the ZOL mechanism only triggers when advancing to the end address,
7802 so if there's a label at the end of a ZOL, we need to insert a nop.
7803 The ARC600 ZOL also has extra restrictions on jumps at the end of a
7805 if (recog_memoized (insn
) == CODE_FOR_doloop_end_i
)
7807 rtx prev
= prev_nonnote_insn (insn
);
7809 return ((LABEL_P (prev
)
7812 || CALL_P (prev
) /* Could be a noreturn call. */
7813 || (NONJUMP_INSN_P (prev
)
7814 && GET_CODE (PATTERN (prev
)) == SEQUENCE
))))
7818 /* Check for return with but one preceding insn since function
7820 if (TARGET_PAD_RETURN
7822 && GET_CODE (PATTERN (insn
)) != ADDR_VEC
7823 && GET_CODE (PATTERN (insn
)) != ADDR_DIFF_VEC
7824 && get_attr_type (insn
) == TYPE_RETURN
)
7826 rtx prev
= prev_active_insn (insn
);
7828 if (!prev
|| !(prev
= prev_active_insn (prev
))
7829 || ((NONJUMP_INSN_P (prev
)
7830 && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
7831 ? CALL_ATTR (XVECEXP (PATTERN (prev
), 0, 0), NON_SIBCALL
)
7832 : CALL_ATTR (prev
, NON_SIBCALL
)))
7837 rtx succ
= next_real_insn (insn
);
7839 /* One the ARC600, a write to an extension register must be separated
7841 if (succ
&& INSN_P (succ
))
7842 len
+= arc600_corereg_hazard (insn
, succ
);
7845 /* Restore extracted operands - otherwise splitters like the addsi3_mixed one
7847 extract_constrain_insn_cached (insn
);
7852 /* Values for length_sensitive. */
7856 ARC_LS_25
, // 25 bit offset, B
7857 ARC_LS_21
, // 21 bit offset, Bcc
7858 ARC_LS_U13
,// 13 bit unsigned offset, LP
7859 ARC_LS_10
, // 10 bit offset, B_s, Beq_s, Bne_s
7860 ARC_LS_9
, // 9 bit offset, BRcc
7861 ARC_LS_8
, // 8 bit offset, BRcc_s
7862 ARC_LS_U7
, // 7 bit unsigned offset, LPcc
7863 ARC_LS_7
// 7 bit offset, Bcc_s
7866 /* While the infrastructure patch is waiting for review, duplicate the
7867 struct definitions, to allow this file to compile. */
7872 /* Cost as a branch / call target or call return address. */
7874 int fallthrough_cost
;
7877 /* 0 for not length sensitive, 1 for largest offset range,
7878 * 2 for next smaller etc. */
7879 unsigned length_sensitive
: 8;
7881 } insn_length_variant_t
;
7883 typedef struct insn_length_parameters_s
7888 int (*get_variants
) (rtx
, int, bool, bool, insn_length_variant_t
*);
7889 } insn_length_parameters_t
;
7892 arc_insn_length_parameters (insn_length_parameters_t
*ilp
) ATTRIBUTE_UNUSED
;
7896 arc_get_insn_variants (rtx insn
, int len
, bool, bool target_p
,
7897 insn_length_variant_t
*ilv
)
7899 if (!NONDEBUG_INSN_P (insn
))
7901 enum attr_type type
;
7902 /* shorten_branches doesn't take optimize_size into account yet for the
7903 get_variants mechanism, so turn this off for now. */
7906 if (GET_CODE (PATTERN (insn
)) == SEQUENCE
)
7908 /* The interaction of a short delay slot insn with a short branch is
7909 too weird for shorten_branches to piece together, so describe the
7912 if (TARGET_UPSIZE_DBR
7913 && get_attr_length (XVECEXP ((pat
= PATTERN (insn
)), 0, 1)) <= 2
7914 && (((type
= get_attr_type (inner
= XVECEXP (pat
, 0, 0)))
7915 == TYPE_UNCOND_BRANCH
)
7916 || type
== TYPE_BRANCH
)
7917 && get_attr_delay_slot_filled (inner
) == DELAY_SLOT_FILLED_YES
)
7920 = arc_get_insn_variants (inner
, get_attr_length (inner
), true,
7922 /* The short variant gets split into a higher-cost aligned
7923 and a lower cost unaligned variant. */
7924 gcc_assert (n_variants
);
7925 gcc_assert (ilv
[1].length_sensitive
== ARC_LS_7
7926 || ilv
[1].length_sensitive
== ARC_LS_10
);
7927 gcc_assert (ilv
[1].align_set
== 3);
7929 ilv
[0].align_set
= 1;
7930 ilv
[0].branch_cost
+= 1;
7931 ilv
[1].align_set
= 2;
7933 for (int i
= 0; i
< n_variants
; i
++)
7935 /* In case an instruction with aligned size is wanted, and
7936 the short variants are unavailable / too expensive, add
7937 versions of long branch + long delay slot. */
7938 for (int i
= 2, end
= n_variants
; i
< end
; i
++, n_variants
++)
7940 ilv
[n_variants
] = ilv
[i
];
7941 ilv
[n_variants
].length
+= 2;
7947 insn_length_variant_t
*first_ilv
= ilv
;
7948 type
= get_attr_type (insn
);
7950 = (get_attr_delay_slot_filled (insn
) == DELAY_SLOT_FILLED_YES
);
7951 int branch_align_cost
= delay_filled
? 0 : 1;
7952 int branch_unalign_cost
= delay_filled
? 0 : TARGET_UNALIGN_BRANCH
? 0 : 1;
7953 /* If the previous instruction is an sfunc call, this insn is always
7954 a target, even though the middle-end is unaware of this. */
7955 bool force_target
= false;
7956 rtx prev
= prev_active_insn (insn
);
7957 if (prev
&& arc_next_active_insn (prev
, 0) == insn
7958 && ((NONJUMP_INSN_P (prev
) && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
7959 ? CALL_ATTR (XVECEXP (PATTERN (prev
), 0, 0), NON_SIBCALL
)
7960 : (CALL_ATTR (prev
, NON_SIBCALL
)
7961 && NEXT_INSN (PREV_INSN (prev
)) == prev
)))
7962 force_target
= true;
7967 /* Short BRCC only comes in no-delay-slot version, and without limm */
7972 ilv
->branch_cost
= 1;
7973 ilv
->enabled
= (len
== 2);
7974 ilv
->length_sensitive
= ARC_LS_8
;
7978 case TYPE_BRCC_NO_DELAY_SLOT
:
7979 /* doloop_fallback* patterns are TYPE_BRCC_NO_DELAY_SLOT for
7980 (delay slot) scheduling purposes, but they are longer. */
7981 if (GET_CODE (PATTERN (insn
)) == PARALLEL
7982 && GET_CODE (XVECEXP (PATTERN (insn
), 0, 1)) == SET
)
7984 /* Standard BRCC: 4 bytes, or 8 bytes with limm. */
7985 ilv
->length
= ((type
== TYPE_BRCC
) ? 4 : 8);
7987 ilv
->branch_cost
= branch_align_cost
;
7988 ilv
->enabled
= (len
<= ilv
->length
);
7989 ilv
->length_sensitive
= ARC_LS_9
;
7990 if ((target_p
|| force_target
)
7991 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
7997 ilv
->target_cost
= 1;
7998 ilv
->branch_cost
= branch_unalign_cost
;
8003 op
= XEXP (SET_SRC (XVECEXP (PATTERN (insn
), 0, 0)), 0);
8006 if (GET_CODE (op0
) == ZERO_EXTRACT
8007 && satisfies_constraint_L (XEXP (op0
, 2)))
8008 op0
= XEXP (op0
, 0);
8009 if (satisfies_constraint_Rcq (op0
))
8011 ilv
->length
= ((type
== TYPE_BRCC
) ? 6 : 10);
8013 ilv
->branch_cost
= 1 + branch_align_cost
;
8014 ilv
->fallthrough_cost
= 1;
8015 ilv
->enabled
= true;
8016 ilv
->length_sensitive
= ARC_LS_21
;
8017 if (!delay_filled
&& TARGET_UNALIGN_BRANCH
)
8023 ilv
->branch_cost
= 1 + branch_unalign_cost
;
8027 ilv
->length
= ((type
== TYPE_BRCC
) ? 8 : 12);
8029 ilv
->branch_cost
= 1 + branch_align_cost
;
8030 ilv
->fallthrough_cost
= 1;
8031 ilv
->enabled
= true;
8032 ilv
->length_sensitive
= ARC_LS_21
;
8033 if ((target_p
|| force_target
)
8034 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8040 ilv
->target_cost
= 1;
8041 ilv
->branch_cost
= 1 + branch_unalign_cost
;
8049 case TYPE_CALL_NO_DELAY_SLOT
:
8054 ilv
->length_sensitive
8055 = GET_CODE (PATTERN (insn
)) == COND_EXEC
? ARC_LS_21
: ARC_LS_25
;
8058 ilv
->fallthrough_cost
= branch_align_cost
;
8059 ilv
->enabled
= true;
8060 if ((target_p
|| force_target
)
8061 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8067 ilv
->target_cost
= 1;
8068 ilv
->fallthrough_cost
= branch_unalign_cost
;
8072 case TYPE_UNCOND_BRANCH
:
8073 /* Strictly speaking, this should be ARC_LS_10 for equality comparisons,
8074 but that makes no difference at the moment. */
8075 ilv
->length_sensitive
= ARC_LS_7
;
8076 ilv
[1].length_sensitive
= ARC_LS_25
;
8079 ilv
->length_sensitive
= ARC_LS_10
;
8080 ilv
[1].length_sensitive
= ARC_LS_21
;
8084 ilv
->branch_cost
= branch_align_cost
;
8085 ilv
->enabled
= (len
== ilv
->length
);
8089 ilv
->branch_cost
= branch_align_cost
;
8090 ilv
->enabled
= true;
8091 if ((target_p
|| force_target
)
8092 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8098 ilv
->target_cost
= 1;
8099 ilv
->branch_cost
= branch_unalign_cost
;
8106 /* For every short insn, there is generally also a long insn.
8107 trap_s is an exception. */
8108 if ((len
& 2) == 0 || recog_memoized (insn
) == CODE_FOR_trap_s
)
8115 ilv
->length
= len
+ 2;
8117 if (target_p
|| force_target
)
8123 ilv
->target_cost
= 1;
8127 /* If the previous instruction is an sfunc call, this insn is always
8128 a target, even though the middle-end is unaware of this.
8129 Therefore, if we have a call predecessor, transfer the target cost
8130 to the fallthrough and branch costs. */
8133 for (insn_length_variant_t
*p
= first_ilv
; p
< ilv
; p
++)
8135 p
->fallthrough_cost
+= p
->target_cost
;
8136 p
->branch_cost
+= p
->target_cost
;
8141 return ilv
- first_ilv
;
8145 arc_insn_length_parameters (insn_length_parameters_t
*ilp
)
8147 ilp
->align_unit_log
= 1;
8148 ilp
->align_base_log
= 1;
8149 ilp
->max_variants
= 7;
8150 ilp
->get_variants
= arc_get_insn_variants
;
8153 /* Return a copy of COND from *STATEP, inverted if that is indicated by the
8154 CC field of *STATEP. */
8157 arc_get_ccfsm_cond (struct arc_ccfsm
*statep
, bool reverse
)
8159 rtx cond
= statep
->cond
;
8160 int raw_cc
= get_arc_condition_code (cond
);
8162 raw_cc
= ARC_INVERSE_CONDITION_CODE (raw_cc
);
8164 if (statep
->cc
== raw_cc
)
8165 return copy_rtx (cond
);
8167 gcc_assert (ARC_INVERSE_CONDITION_CODE (raw_cc
) == statep
->cc
);
8169 enum machine_mode ccm
= GET_MODE (XEXP (cond
, 0));
8170 enum rtx_code code
= reverse_condition (GET_CODE (cond
));
8171 if (code
== UNKNOWN
|| ccm
== CC_FP_GTmode
|| ccm
== CC_FP_GEmode
)
8172 code
= reverse_condition_maybe_unordered (GET_CODE (cond
));
8174 return gen_rtx_fmt_ee (code
, GET_MODE (cond
),
8175 copy_rtx (XEXP (cond
, 0)), copy_rtx (XEXP (cond
, 1)));
8178 /* Return version of PAT conditionalized with COND, which is part of INSN.
8179 ANNULLED indicates if INSN is an annulled delay-slot insn.
8180 Register further changes if necessary. */
8182 conditionalize_nonjump (rtx pat
, rtx cond
, rtx insn
, bool annulled
)
8184 /* For commutative operators, we generally prefer to have
8185 the first source match the destination. */
8186 if (GET_CODE (pat
) == SET
)
8188 rtx src
= SET_SRC (pat
);
8190 if (COMMUTATIVE_P (src
))
8192 rtx src0
= XEXP (src
, 0);
8193 rtx src1
= XEXP (src
, 1);
8194 rtx dst
= SET_DEST (pat
);
8196 if (rtx_equal_p (src1
, dst
) && !rtx_equal_p (src0
, dst
)
8197 /* Leave add_n alone - the canonical form is to
8198 have the complex summand first. */
8200 pat
= gen_rtx_SET (VOIDmode
, dst
,
8201 gen_rtx_fmt_ee (GET_CODE (src
), GET_MODE (src
),
8206 /* dwarf2out.c:dwarf2out_frame_debug_expr doesn't know
8207 what to do with COND_EXEC. */
8208 if (RTX_FRAME_RELATED_P (insn
))
8210 /* If this is the delay slot insn of an anulled branch,
8211 dwarf2out.c:scan_trace understands the anulling semantics
8212 without the COND_EXEC. */
8213 gcc_assert (annulled
);
8214 rtx note
= alloc_reg_note (REG_FRAME_RELATED_EXPR
, pat
,
8216 validate_change (insn
, ®_NOTES (insn
), note
, 1);
8218 pat
= gen_rtx_COND_EXEC (VOIDmode
, cond
, pat
);
8222 /* Use the ccfsm machinery to do if conversion. */
8227 struct arc_ccfsm
*statep
= &cfun
->machine
->ccfsm_current
;
8228 basic_block merge_bb
= 0;
8230 memset (statep
, 0, sizeof *statep
);
8231 for (rtx insn
= get_insns (); insn
; insn
= next_insn (insn
))
8233 arc_ccfsm_advance (insn
, statep
);
8235 switch (statep
->state
)
8243 /* Deleted branch. */
8244 gcc_assert (!merge_bb
);
8245 merge_bb
= BLOCK_FOR_INSN (insn
);
8247 = BLOCK_FOR_INSN (NEXT_INSN (NEXT_INSN (PREV_INSN (insn
))));
8248 arc_ccfsm_post_advance (insn
, statep
);
8249 gcc_assert (!IN_RANGE (statep
->state
, 1, 2));
8250 rtx seq
= NEXT_INSN (PREV_INSN (insn
));
8253 rtx slot
= XVECEXP (PATTERN (seq
), 0, 1);
8254 rtx pat
= PATTERN (slot
);
8255 if (INSN_ANNULLED_BRANCH_P (insn
))
8258 = arc_get_ccfsm_cond (statep
, INSN_FROM_TARGET_P (slot
));
8259 pat
= gen_rtx_COND_EXEC (VOIDmode
, cond
, pat
);
8261 if (!validate_change (seq
, &PATTERN (seq
), pat
, 0))
8263 PUT_CODE (slot
, NOTE
);
8264 NOTE_KIND (slot
) = NOTE_INSN_DELETED
;
8265 if (merge_bb
&& succ_bb
)
8266 merge_blocks (merge_bb
, succ_bb
);
8268 else if (merge_bb
&& succ_bb
)
8270 set_insn_deleted (insn
);
8271 merge_blocks (merge_bb
, succ_bb
);
8275 PUT_CODE (insn
, NOTE
);
8276 NOTE_KIND (insn
) = NOTE_INSN_DELETED
;
8282 && statep
->target_label
== CODE_LABEL_NUMBER (insn
))
8284 arc_ccfsm_post_advance (insn
, statep
);
8285 basic_block succ_bb
= BLOCK_FOR_INSN (insn
);
8286 if (merge_bb
&& succ_bb
)
8287 merge_blocks (merge_bb
, succ_bb
);
8288 else if (--LABEL_NUSES (insn
) == 0)
8290 const char *name
= LABEL_NAME (insn
);
8291 PUT_CODE (insn
, NOTE
);
8292 NOTE_KIND (insn
) = NOTE_INSN_DELETED_LABEL
;
8293 NOTE_DELETED_LABEL_NAME (insn
) = name
;
8300 if (!NONDEBUG_INSN_P (insn
))
8303 /* Conditionalized insn. */
8305 rtx prev
, pprev
, *patp
, pat
, cond
;
8306 bool annulled
; annulled
= false;
8308 /* If this is a delay slot insn in a non-annulled branch,
8309 don't conditionalize it. N.B., this should be fine for
8310 conditional return too. However, don't do this for
8311 unconditional branches, as these would be encountered when
8312 processing an 'else' part. */
8313 prev
= PREV_INSN (insn
);
8314 pprev
= PREV_INSN (prev
);
8315 if (pprev
&& NEXT_INSN (NEXT_INSN (pprev
)) == NEXT_INSN (insn
)
8316 && JUMP_P (prev
) && get_attr_cond (prev
) == COND_USE
)
8318 if (!INSN_ANNULLED_BRANCH_P (prev
))
8323 patp
= &PATTERN (insn
);
8325 cond
= arc_get_ccfsm_cond (statep
, INSN_FROM_TARGET_P (insn
));
8326 if (NONJUMP_INSN_P (insn
) || CALL_P (insn
))
8328 /* ??? don't conditionalize if all side effects are dead
8329 in the not-execute case. */
8331 pat
= conditionalize_nonjump (pat
, cond
, insn
, annulled
);
8333 else if (simplejump_p (insn
))
8335 patp
= &SET_SRC (pat
);
8336 pat
= gen_rtx_IF_THEN_ELSE (VOIDmode
, cond
, *patp
, pc_rtx
);
8338 else if (JUMP_P (insn
) && ANY_RETURN_P (PATTERN (insn
)))
8340 pat
= gen_rtx_IF_THEN_ELSE (VOIDmode
, cond
, pat
, pc_rtx
);
8341 pat
= gen_rtx_SET (VOIDmode
, pc_rtx
, pat
);
8345 validate_change (insn
, patp
, pat
, 1);
8346 if (!apply_change_group ())
8350 rtx next
= next_nonnote_insn (insn
);
8351 if (GET_CODE (next
) == BARRIER
)
8353 if (statep
->state
== 3)
8360 arc_ccfsm_post_advance (insn
, statep
);
8365 /* Find annulled delay insns and convert them to use the appropriate predicate.
8366 This allows branch shortening to size up these insns properly. */
8369 arc_predicate_delay_insns (void)
8371 for (rtx insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
8373 rtx pat
, jump
, dlay
, src
, cond
, *patp
;
8376 if (!NONJUMP_INSN_P (insn
)
8377 || GET_CODE (pat
= PATTERN (insn
)) != SEQUENCE
)
8379 jump
= XVECEXP (pat
, 0, 0);
8380 dlay
= XVECEXP (pat
, 0, 1);
8381 if (!JUMP_P (jump
) || !INSN_ANNULLED_BRANCH_P (jump
))
8383 /* If the branch insn does the annulling, leave the delay insn alone. */
8384 if (!TARGET_AT_DBR_CONDEXEC
&& !INSN_FROM_TARGET_P (dlay
))
8386 /* ??? Could also leave DLAY un-conditionalized if its target is dead
8387 on the other path. */
8388 gcc_assert (GET_CODE (PATTERN (jump
)) == SET
);
8389 gcc_assert (SET_DEST (PATTERN (jump
)) == pc_rtx
);
8390 src
= SET_SRC (PATTERN (jump
));
8391 gcc_assert (GET_CODE (src
) == IF_THEN_ELSE
);
8392 cond
= XEXP (src
, 0);
8393 if (XEXP (src
, 2) == pc_rtx
)
8395 else if (XEXP (src
, 1) == pc_rtx
)
8399 if (!INSN_FROM_TARGET_P (dlay
) != reverse
)
8401 enum machine_mode ccm
= GET_MODE (XEXP (cond
, 0));
8402 enum rtx_code code
= reverse_condition (GET_CODE (cond
));
8403 if (code
== UNKNOWN
|| ccm
== CC_FP_GTmode
|| ccm
== CC_FP_GEmode
)
8404 code
= reverse_condition_maybe_unordered (GET_CODE (cond
));
8406 cond
= gen_rtx_fmt_ee (code
, GET_MODE (cond
),
8407 copy_rtx (XEXP (cond
, 0)),
8408 copy_rtx (XEXP (cond
, 1)));
8411 cond
= copy_rtx (cond
);
8412 patp
= &PATTERN (dlay
);
8414 pat
= conditionalize_nonjump (pat
, cond
, dlay
, true);
8415 validate_change (dlay
, patp
, pat
, 1);
8416 if (!apply_change_group ())
8422 /* For ARC600: If a write to a core reg >=32 appears in a delay slot
8423 (other than of a forward brcc), it creates a hazard when there is a read
8424 of the same register at the branch target. We can't know what is at the
8425 branch target of calls, and for branches, we don't really know before the
8426 end of delay slot scheduling, either. Not only can individual instruction
8427 be hoisted out into a delay slot, a basic block can also be emptied this
8428 way, and branch and/or fall through targets be redirected. Hence we don't
8429 want such writes in a delay slot. */
8430 /* Called by arc_write_ext_corereg via for_each_rtx. */
8433 write_ext_corereg_1 (rtx
*xp
, void *data ATTRIBUTE_UNUSED
)
8438 switch (GET_CODE (x
))
8440 case SET
: case POST_INC
: case POST_DEC
: case PRE_INC
: case PRE_DEC
:
8443 /* This is also fine for PRE/POST_MODIFY, because they contain a SET. */
8447 if (REG_P (dest
) && REGNO (dest
) >= 32 && REGNO (dest
) < 61)
8452 /* Return nonzreo iff INSN writes to an extension core register. */
8455 arc_write_ext_corereg (rtx insn
)
8457 return for_each_rtx (&PATTERN (insn
), write_ext_corereg_1
, 0);
8460 /* This is like the hook, but returns NULL when it can't / won't generate
8461 a legitimate address. */
8464 arc_legitimize_address_0 (rtx x
, rtx oldx ATTRIBUTE_UNUSED
,
8465 enum machine_mode mode
)
8469 if (flag_pic
&& SYMBOLIC_CONST (x
))
8470 (x
) = arc_legitimize_pic_address (x
, 0);
8472 if (GET_CODE (addr
) == CONST
)
8473 addr
= XEXP (addr
, 0);
8474 if (GET_CODE (addr
) == PLUS
8475 && CONST_INT_P (XEXP (addr
, 1))
8476 && ((GET_CODE (XEXP (addr
, 0)) == SYMBOL_REF
8477 && !SYMBOL_REF_FUNCTION_P (XEXP (addr
, 0)))
8478 || (REG_P (XEXP (addr
, 0))
8479 && (INTVAL (XEXP (addr
, 1)) & 252))))
8481 HOST_WIDE_INT offs
, upper
;
8482 int size
= GET_MODE_SIZE (mode
);
8484 offs
= INTVAL (XEXP (addr
, 1));
8485 upper
= (offs
+ 256 * size
) & ~511 * size
;
8486 inner
= plus_constant (Pmode
, XEXP (addr
, 0), upper
);
8487 #if 0 /* ??? this produces worse code for EEMBC idctrn01 */
8488 if (GET_CODE (x
) == CONST
)
8489 inner
= gen_rtx_CONST (Pmode
, inner
);
8491 addr
= plus_constant (Pmode
, force_reg (Pmode
, inner
), offs
- upper
);
8494 else if (GET_CODE (addr
) == SYMBOL_REF
&& !SYMBOL_REF_FUNCTION_P (addr
))
8495 x
= force_reg (Pmode
, x
);
8496 if (memory_address_p ((enum machine_mode
) mode
, x
))
8502 arc_legitimize_address (rtx orig_x
, rtx oldx
, enum machine_mode mode
)
8504 rtx new_x
= arc_legitimize_address_0 (orig_x
, oldx
, mode
);
8512 arc_delegitimize_address_0 (rtx x
)
8516 if (GET_CODE (x
) == CONST
&& GET_CODE (u
= XEXP (x
, 0)) == UNSPEC
)
8518 if (XINT (u
, 1) == ARC_UNSPEC_GOT
)
8519 return XVECEXP (u
, 0, 0);
8521 else if (GET_CODE (x
) == PLUS
8522 && ((REG_P (gp
= XEXP (x
, 0))
8523 && REGNO (gp
) == PIC_OFFSET_TABLE_REGNUM
)
8524 || (GET_CODE (gp
) == CONST
8525 && GET_CODE (u
= XEXP (gp
, 0)) == UNSPEC
8526 && XINT (u
, 1) == ARC_UNSPEC_GOT
8527 && GET_CODE (XVECEXP (u
, 0, 0)) == SYMBOL_REF
8528 && !strcmp (XSTR (XVECEXP (u
, 0, 0), 0), "_DYNAMIC")))
8529 && GET_CODE (XEXP (x
, 1)) == CONST
8530 && GET_CODE (u
= XEXP (XEXP (x
, 1), 0)) == UNSPEC
8531 && XINT (u
, 1) == ARC_UNSPEC_GOTOFF
)
8532 return XVECEXP (u
, 0, 0);
8533 else if (GET_CODE (x
) == PLUS
&& GET_CODE (XEXP (x
, 0)) == PLUS
8534 && ((REG_P (gp
= XEXP (XEXP (x
, 0), 1))
8535 && REGNO (gp
) == PIC_OFFSET_TABLE_REGNUM
)
8536 || (GET_CODE (gp
) == CONST
8537 && GET_CODE (u
= XEXP (gp
, 0)) == UNSPEC
8538 && XINT (u
, 1) == ARC_UNSPEC_GOT
8539 && GET_CODE (XVECEXP (u
, 0, 0)) == SYMBOL_REF
8540 && !strcmp (XSTR (XVECEXP (u
, 0, 0), 0), "_DYNAMIC")))
8541 && GET_CODE (XEXP (x
, 1)) == CONST
8542 && GET_CODE (u
= XEXP (XEXP (x
, 1), 0)) == UNSPEC
8543 && XINT (u
, 1) == ARC_UNSPEC_GOTOFF
)
8544 return gen_rtx_PLUS (GET_MODE (x
), XEXP (XEXP (x
, 0), 0),
8546 else if (GET_CODE (x
) == PLUS
8547 && (u
= arc_delegitimize_address_0 (XEXP (x
, 1))))
8548 return gen_rtx_PLUS (GET_MODE (x
), XEXP (x
, 0), u
);
8553 arc_delegitimize_address (rtx x
)
8555 rtx orig_x
= x
= delegitimize_mem_from_attrs (x
);
8556 if (GET_CODE (x
) == MEM
)
8558 x
= arc_delegitimize_address_0 (x
);
8562 x
= replace_equiv_address_nv (orig_x
, x
);
8568 /* Return a REG rtx for acc1. N.B. the gcc-internal representation may
8569 differ from the hardware register number in order to allow the generic
8570 code to correctly split the concatenation of acc1 and acc2. */
8575 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 56: 57);
8578 /* Return a REG rtx for acc2. N.B. the gcc-internal representation may
8579 differ from the hardware register number in order to allow the generic
8580 code to correctly split the concatenation of acc1 and acc2. */
8585 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 57: 56);
8588 /* Return a REG rtx for mlo. N.B. the gcc-internal representation may
8589 differ from the hardware register number in order to allow the generic
8590 code to correctly split the concatenation of mhi and mlo. */
8595 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 59: 58);
8598 /* Return a REG rtx for mhi. N.B. the gcc-internal representation may
8599 differ from the hardware register number in order to allow the generic
8600 code to correctly split the concatenation of mhi and mlo. */
8605 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 58: 59);
8608 /* FIXME: a parameter should be added, and code added to final.c,
8609 to reproduce this functionality in shorten_branches. */
8611 /* Return nonzero iff BRANCH should be unaligned if possible by upsizing
8612 a previous instruction. */
8614 arc_unalign_branch_p (rtx branch
)
8618 if (!TARGET_UNALIGN_BRANCH
)
8620 /* Do not do this if we have a filled delay slot. */
8621 if (get_attr_delay_slot_filled (branch
) == DELAY_SLOT_FILLED_YES
8622 && !INSN_DELETED_P (NEXT_INSN (branch
)))
8624 note
= find_reg_note (branch
, REG_BR_PROB
, 0);
8626 || (arc_unalign_prob_threshold
&& !br_prob_note_reliable_p (note
))
8627 || INTVAL (XEXP (note
, 0)) < arc_unalign_prob_threshold
);
8631 /* When estimating sizes during arc_reorg, when optimizing for speed, there
8632 are three reasons why we need to consider branches to be length 6:
8633 - annull-false delay slot insns are implemented using conditional execution,
8634 thus preventing short insn formation where used.
8635 - for ARC600: annul-true delay slot insns are implemented where possible
8636 using conditional execution, preventing short insn formation where used.
8637 - for ARC700: likely or somewhat likely taken branches are made long and
8638 unaligned if possible to avoid branch penalty. */
8641 arc_branch_size_unknown_p (void)
8643 return !optimize_size
&& arc_reorg_in_progress
;
8646 /* We are about to output a return insn. Add padding if necessary to avoid
8647 a mispredict. A return could happen immediately after the function
8648 start, but after a call we know that there will be at least a blink
8652 arc_pad_return (void)
8654 rtx insn
= current_output_insn
;
8655 rtx prev
= prev_active_insn (insn
);
8660 fputs ("\tnop_s\n", asm_out_file
);
8661 cfun
->machine
->unalign
^= 2;
8664 /* If PREV is a sequence, we know it must be a branch / jump or a tailcall,
8665 because after a call, we'd have to restore blink first. */
8666 else if (GET_CODE (PATTERN (prev
)) == SEQUENCE
)
8670 want_long
= (get_attr_length (prev
) == 2);
8671 prev
= prev_active_insn (prev
);
8674 || ((NONJUMP_INSN_P (prev
) && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
8675 ? CALL_ATTR (XVECEXP (PATTERN (prev
), 0, 0), NON_SIBCALL
)
8676 : CALL_ATTR (prev
, NON_SIBCALL
)))
8679 cfun
->machine
->size_reason
8680 = "call/return and return/return must be 6 bytes apart to avoid mispredict";
8681 else if (TARGET_UNALIGN_BRANCH
&& cfun
->machine
->unalign
)
8683 cfun
->machine
->size_reason
8684 = "Long unaligned jump avoids non-delay slot penalty";
8687 /* Disgorge delay insn, if there is any, and it may be moved. */
8689 /* ??? Annulled would be OK if we can and do conditionalize
8690 the delay slot insn accordingly. */
8691 && !INSN_ANNULLED_BRANCH_P (insn
)
8692 && (get_attr_cond (insn
) != COND_USE
8693 || !reg_set_p (gen_rtx_REG (CCmode
, CC_REG
),
8694 XVECEXP (final_sequence
, 0, 1))))
8696 prev
= XVECEXP (final_sequence
, 0, 1);
8697 gcc_assert (!prev_real_insn (insn
)
8698 || !arc_hazard (prev_real_insn (insn
), prev
));
8699 cfun
->machine
->force_short_suffix
= !want_long
;
8700 rtx save_pred
= current_insn_predicate
;
8701 final_scan_insn (prev
, asm_out_file
, optimize
, 1, NULL
);
8702 cfun
->machine
->force_short_suffix
= -1;
8703 INSN_DELETED_P (prev
) = 1;
8704 current_output_insn
= insn
;
8705 current_insn_predicate
= save_pred
;
8708 fputs ("\tnop\n", asm_out_file
);
8711 fputs ("\tnop_s\n", asm_out_file
);
8712 cfun
->machine
->unalign
^= 2;
8718 /* The usual; we set up our machine_function data. */
8720 static struct machine_function
*
8721 arc_init_machine_status (void)
8723 struct machine_function
*machine
;
8724 machine
= ggc_cleared_alloc
<machine_function
> ();
8725 machine
->fn_type
= ARC_FUNCTION_UNKNOWN
;
8726 machine
->force_short_suffix
= -1;
8731 /* Implements INIT_EXPANDERS. We just set up to call the above
8735 arc_init_expanders (void)
8737 init_machine_status
= arc_init_machine_status
;
8740 /* Check if OP is a proper parallel of a millicode call pattern. OFFSET
8741 indicates a number of elements to ignore - that allows to have a
8742 sibcall pattern that starts with (return). LOAD_P is zero for store
8743 multiple (for prologues), and one for load multiples (for epilogues),
8744 and two for load multiples where no final clobber of blink is required.
8745 We also skip the first load / store element since this is supposed to
8746 be checked in the instruction pattern. */
8749 arc_check_millicode (rtx op
, int offset
, int load_p
)
8751 int len
= XVECLEN (op
, 0) - offset
;
8756 if (len
< 2 || len
> 13)
8762 rtx elt
= XVECEXP (op
, 0, --len
);
8764 if (GET_CODE (elt
) != CLOBBER
8765 || !REG_P (XEXP (elt
, 0))
8766 || REGNO (XEXP (elt
, 0)) != RETURN_ADDR_REGNUM
8767 || len
< 3 || len
> 13)
8770 for (i
= 1; i
< len
; i
++)
8772 rtx elt
= XVECEXP (op
, 0, i
+ offset
);
8775 if (GET_CODE (elt
) != SET
)
8777 mem
= XEXP (elt
, load_p
);
8778 reg
= XEXP (elt
, 1-load_p
);
8779 if (!REG_P (reg
) || REGNO (reg
) != 13U+i
|| !MEM_P (mem
))
8781 addr
= XEXP (mem
, 0);
8782 if (GET_CODE (addr
) != PLUS
8783 || !rtx_equal_p (stack_pointer_rtx
, XEXP (addr
, 0))
8784 || !CONST_INT_P (XEXP (addr
, 1)) || INTVAL (XEXP (addr
, 1)) != i
*4)
8790 /* Accessor functions for cfun->machine->unalign. */
8793 arc_get_unalign (void)
8795 return cfun
->machine
->unalign
;
8799 arc_clear_unalign (void)
8802 cfun
->machine
->unalign
= 0;
8806 arc_toggle_unalign (void)
8808 cfun
->machine
->unalign
^= 2;
8811 /* Operands 0..2 are the operands of a addsi which uses a 12 bit
8812 constant in operand 2, but which would require a LIMM because of
8814 operands 3 and 4 are new SET_SRCs for operands 0. */
8817 split_addsi (rtx
*operands
)
8819 int val
= INTVAL (operands
[2]);
8821 /* Try for two short insns first. Lengths being equal, we prefer
8822 expansions with shorter register lifetimes. */
8823 if (val
> 127 && val
<= 255
8824 && satisfies_constraint_Rcq (operands
[0]))
8826 operands
[3] = operands
[2];
8827 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[1]);
8831 operands
[3] = operands
[1];
8832 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[2]);
8836 /* Operands 0..2 are the operands of a subsi which uses a 12 bit
8837 constant in operand 1, but which would require a LIMM because of
8839 operands 3 and 4 are new SET_SRCs for operands 0. */
8842 split_subsi (rtx
*operands
)
8844 int val
= INTVAL (operands
[1]);
8846 /* Try for two short insns first. Lengths being equal, we prefer
8847 expansions with shorter register lifetimes. */
8848 if (satisfies_constraint_Rcq (operands
[0])
8849 && satisfies_constraint_Rcq (operands
[2]))
8851 if (val
>= -31 && val
<= 127)
8853 operands
[3] = gen_rtx_NEG (SImode
, operands
[2]);
8854 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[1]);
8857 else if (val
>= 0 && val
< 255)
8859 operands
[3] = operands
[1];
8860 operands
[4] = gen_rtx_MINUS (SImode
, operands
[0], operands
[2]);
8864 /* If the destination is not an ARCompact16 register, we might
8865 still have a chance to make a short insn if the source is;
8866 we need to start with a reg-reg move for this. */
8867 operands
[3] = operands
[2];
8868 operands
[4] = gen_rtx_MINUS (SImode
, operands
[1], operands
[0]);
8871 /* Handle DOUBLE_REGS uses.
8872 Operand 0: destination register
8873 Operand 1: source register */
8876 arc_process_double_reg_moves (rtx
*operands
)
8878 rtx dest
= operands
[0];
8879 rtx src
= operands
[1];
8882 enum usesDxState
{ none
, srcDx
, destDx
, maxDx
};
8883 enum usesDxState state
= none
;
8885 if (refers_to_regno_p (40, 44, src
, 0))
8887 if (refers_to_regno_p (40, 44, dest
, 0))
8889 /* Via arc_register_move_cost, we should never see D,D moves. */
8890 gcc_assert (state
== none
);
8901 /* Without the LR insn, we need to split this into a
8902 sequence of insns which will use the DEXCLx and DADDHxy
8903 insns to be able to read the Dx register in question. */
8904 if (TARGET_DPFP_DISABLE_LRSR
)
8906 /* gen *movdf_insn_nolrsr */
8907 rtx set
= gen_rtx_SET (VOIDmode
, dest
, src
);
8908 rtx use1
= gen_rtx_USE (VOIDmode
, const1_rtx
);
8909 emit_insn (gen_rtx_PARALLEL (VOIDmode
, gen_rtvec (2, set
, use1
)));
8913 /* When we have 'mov D, r' or 'mov D, D' then get the target
8914 register pair for use with LR insn. */
8915 rtx destHigh
= simplify_gen_subreg(SImode
, dest
, DFmode
, 4);
8916 rtx destLow
= simplify_gen_subreg(SImode
, dest
, DFmode
, 0);
8918 /* Produce the two LR insns to get the high and low parts. */
8919 emit_insn (gen_rtx_SET (VOIDmode
,
8921 gen_rtx_UNSPEC_VOLATILE (Pmode
, gen_rtvec (1, src
),
8923 emit_insn (gen_rtx_SET (VOIDmode
,
8925 gen_rtx_UNSPEC_VOLATILE (Pmode
, gen_rtvec (1, src
),
8929 else if (state
== destDx
)
8931 /* When we have 'mov r, D' or 'mov D, D' and we have access to the
8932 LR insn get the target register pair. */
8933 rtx srcHigh
= simplify_gen_subreg(SImode
, src
, DFmode
, 4);
8934 rtx srcLow
= simplify_gen_subreg(SImode
, src
, DFmode
, 0);
8936 emit_insn (gen_rtx_UNSPEC_VOLATILE (Pmode
,
8937 gen_rtvec (3, dest
, srcHigh
, srcLow
),
8938 VUNSPEC_DEXCL_NORES
));
8949 /* operands 0..1 are the operands of a 64 bit move instruction.
8950 split it into two moves with operands 2/3 and 4/5. */
8953 arc_split_move (rtx
*operands
)
8955 enum machine_mode mode
= GET_MODE (operands
[0]);
8963 val
= arc_process_double_reg_moves (operands
);
8968 for (i
= 0; i
< 2; i
++)
8970 if (MEM_P (operands
[i
]) && auto_inc_p (XEXP (operands
[i
], 0)))
8972 rtx addr
= XEXP (operands
[i
], 0);
8976 gcc_assert (!reg_overlap_mentioned_p (operands
[0], addr
));
8977 switch (GET_CODE (addr
))
8979 case PRE_DEC
: o
= GEN_INT (-8); goto pre_modify
;
8980 case PRE_INC
: o
= GEN_INT (8); goto pre_modify
;
8981 case PRE_MODIFY
: o
= XEXP (XEXP (addr
, 1), 1);
8985 case POST_DEC
: o
= GEN_INT (-8); goto post_modify
;
8986 case POST_INC
: o
= GEN_INT (8); goto post_modify
;
8987 case POST_MODIFY
: o
= XEXP (XEXP (addr
, 1), 1);
8996 xop
[0+i
] = adjust_automodify_address_nv
8997 (operands
[i
], SImode
,
8998 gen_rtx_fmt_ee (code
, Pmode
, r
,
8999 gen_rtx_PLUS (Pmode
, r
, o
)),
9001 xop
[2+i
] = adjust_automodify_address_nv
9002 (operands
[i
], SImode
, plus_constant (Pmode
, r
, 4), 4);
9006 xop
[0+i
] = operand_subword (operands
[i
], 0, 0, mode
);
9007 xop
[2+i
] = operand_subword (operands
[i
], 1, 0, mode
);
9010 if (reg_overlap_mentioned_p (xop
[0], xop
[3]))
9013 gcc_assert (!reg_overlap_mentioned_p (xop
[2], xop
[1]));
9015 operands
[2+swap
] = xop
[0];
9016 operands
[3+swap
] = xop
[1];
9017 operands
[4-swap
] = xop
[2];
9018 operands
[5-swap
] = xop
[3];
9021 emit_insn (gen_rtx_SET (VOIDmode
, operands
[2], operands
[3]));
9022 emit_insn (gen_rtx_SET (VOIDmode
, operands
[4], operands
[5]));
9029 /* Select between the instruction output templates s_tmpl (for short INSNs)
9030 and l_tmpl (for long INSNs). */
9033 arc_short_long (rtx insn
, const char *s_tmpl
, const char *l_tmpl
)
9035 int is_short
= arc_verify_short (insn
, cfun
->machine
->unalign
, -1);
9037 extract_constrain_insn_cached (insn
);
9038 return is_short
? s_tmpl
: l_tmpl
;
9041 /* Searches X for any reference to REGNO, returning the rtx of the
9042 reference found if any. Otherwise, returns NULL_RTX. */
9045 arc_regno_use_in (unsigned int regno
, rtx x
)
9051 if (REG_P (x
) && refers_to_regno_p (regno
, regno
+1, x
, (rtx
*) 0))
9054 fmt
= GET_RTX_FORMAT (GET_CODE (x
));
9055 for (i
= GET_RTX_LENGTH (GET_CODE (x
)) - 1; i
>= 0; i
--)
9059 if ((tem
= regno_use_in (regno
, XEXP (x
, i
))))
9062 else if (fmt
[i
] == 'E')
9063 for (j
= XVECLEN (x
, i
) - 1; j
>= 0; j
--)
9064 if ((tem
= regno_use_in (regno
, XVECEXP (x
, i
, j
))))
9071 /* Return the integer value of the "type" attribute for INSN, or -1 if
9072 INSN can't have attributes. */
9075 arc_attr_type (rtx insn
)
9077 if (NONJUMP_INSN_P (insn
)
9078 ? (GET_CODE (PATTERN (insn
)) == USE
9079 || GET_CODE (PATTERN (insn
)) == CLOBBER
)
9081 ? (GET_CODE (PATTERN (insn
)) == ADDR_VEC
9082 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
9085 return get_attr_type (insn
);
9088 /* Return true if insn sets the condition codes. */
9091 arc_sets_cc_p (rtx insn
)
9093 if (NONJUMP_INSN_P (insn
) && GET_CODE (PATTERN (insn
)) == SEQUENCE
)
9094 insn
= XVECEXP (PATTERN (insn
), 0, XVECLEN (PATTERN (insn
), 0) - 1);
9095 return arc_attr_type (insn
) == TYPE_COMPARE
;
9098 /* Return true if INSN is an instruction with a delay slot we may want
9102 arc_need_delay (rtx insn
)
9106 if (!flag_delayed_branch
)
9108 /* The return at the end of a function needs a delay slot. */
9109 if (NONJUMP_INSN_P (insn
) && GET_CODE (PATTERN (insn
)) == USE
9110 && (!(next
= next_active_insn (insn
))
9111 || ((!NONJUMP_INSN_P (next
) || GET_CODE (PATTERN (next
)) != SEQUENCE
)
9112 && arc_attr_type (next
) == TYPE_RETURN
))
9113 && (!TARGET_PAD_RETURN
9114 || (prev_active_insn (insn
)
9115 && prev_active_insn (prev_active_insn (insn
))
9116 && prev_active_insn (prev_active_insn (prev_active_insn (insn
))))))
9118 if (NONJUMP_INSN_P (insn
)
9119 ? (GET_CODE (PATTERN (insn
)) == USE
9120 || GET_CODE (PATTERN (insn
)) == CLOBBER
9121 || GET_CODE (PATTERN (insn
)) == SEQUENCE
)
9123 ? (GET_CODE (PATTERN (insn
)) == ADDR_VEC
9124 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
9127 return num_delay_slots (insn
) != 0;
9130 /* Return true if the scheduling pass(es) has/have already run,
9131 i.e. where possible, we should try to mitigate high latencies
9132 by different instruction selection. */
9135 arc_scheduling_not_expected (void)
9137 return cfun
->machine
->arc_reorg_started
;
9140 /* Oddly enough, sometimes we get a zero overhead loop that branch
9141 shortening doesn't think is a loop - observed with compile/pr24883.c
9142 -O3 -fomit-frame-pointer -funroll-loops. Make sure to include the
9143 alignment visible for branch shortening (we actually align the loop
9144 insn before it, but that is equivalent since the loop insn is 4 byte
9148 arc_label_align (rtx label
)
9150 int loop_align
= LOOP_ALIGN (LABEL
);
9152 if (loop_align
> align_labels_log
)
9154 rtx prev
= prev_nonnote_insn (label
);
9156 if (prev
&& NONJUMP_INSN_P (prev
)
9157 && GET_CODE (PATTERN (prev
)) == PARALLEL
9158 && recog_memoized (prev
) == CODE_FOR_doloop_begin_i
)
9161 /* Code has a minimum p2 alignment of 1, which we must restore after an
9163 if (align_labels_log
< 1)
9165 rtx next
= next_nonnote_nondebug_insn (label
);
9166 if (INSN_P (next
) && recog_memoized (next
) >= 0)
9169 return align_labels_log
;
9172 /* Return true if LABEL is in executable code. */
9175 arc_text_label (rtx label
)
9179 /* ??? We use deleted labels like they were still there, see
9180 gcc.c-torture/compile/20000326-2.c . */
9181 gcc_assert (GET_CODE (label
) == CODE_LABEL
9182 || (GET_CODE (label
) == NOTE
9183 && NOTE_KIND (label
) == NOTE_INSN_DELETED_LABEL
));
9184 next
= next_nonnote_insn (label
);
9186 return (!JUMP_TABLE_DATA_P (next
)
9187 || GET_CODE (PATTERN (next
)) != ADDR_VEC
);
9188 else if (!PREV_INSN (label
))
9189 /* ??? sometimes text labels get inserted very late, see
9190 gcc.dg/torture/stackalign/comp-goto-1.c */
9195 /* Return the size of the pretend args for DECL. */
9198 arc_decl_pretend_args (tree decl
)
9200 /* struct function is in DECL_STRUCT_FUNCTION (decl), but no
9201 pretend_args there... See PR38391. */
9202 gcc_assert (decl
== current_function_decl
);
9203 return crtl
->args
.pretend_args_size
;
9206 /* Without this, gcc.dg/tree-prof/bb-reorg.c fails to assemble
9207 when compiling with -O2 -freorder-blocks-and-partition -fprofile-use
9208 -D_PROFILE_USE; delay branch scheduling then follows a crossing jump
9209 to redirect two breqs. */
9212 arc_can_follow_jump (const_rtx follower
, const_rtx followee
)
9214 /* ??? get_attr_type is declared to take an rtx. */
9215 union { const_rtx c
; rtx r
; } u
;
9218 if (CROSSING_JUMP_P (followee
))
9219 switch (get_attr_type (u
.r
))
9222 case TYPE_BRCC_NO_DELAY_SLOT
:
9230 /* Implement EPILOGUE__USES.
9231 Return true if REGNO should be added to the deemed uses of the epilogue.
9233 We use the return address
9234 arc_return_address_regs[arc_compute_function_type (cfun)] .
9235 But also, we have to make sure all the register restore instructions
9236 are known to be live in interrupt functions. */
9239 arc_epilogue_uses (int regno
)
9241 if (reload_completed
)
9243 if (ARC_INTERRUPT_P (cfun
->machine
->fn_type
))
9245 if (!fixed_regs
[regno
])
9247 return regno
== arc_return_address_regs
[cfun
->machine
->fn_type
];
9250 return regno
== RETURN_ADDR_REGNUM
;
9253 return regno
== arc_return_address_regs
[arc_compute_function_type (cfun
)];
9256 #ifndef TARGET_NO_LRA
9257 #define TARGET_NO_LRA !TARGET_LRA
9263 return !TARGET_NO_LRA
;
9266 /* ??? Should we define TARGET_REGISTER_PRIORITY? We might perfer to use
9267 Rcq registers, because some insn are shorter with them. OTOH we already
9268 have separate alternatives for this purpose, and other insns don't
9269 mind, so maybe we should rather prefer the other registers?
9270 We need more data, and we can only get that if we allow people to
9273 arc_register_priority (int r
)
9275 switch (arc_lra_priority_tag
)
9277 case ARC_LRA_PRIORITY_NONE
:
9279 case ARC_LRA_PRIORITY_NONCOMPACT
:
9280 return ((((r
& 7) ^ 4) - 4) & 15) != r
;
9281 case ARC_LRA_PRIORITY_COMPACT
:
9282 return ((((r
& 7) ^ 4) - 4) & 15) == r
;
9289 arc_spill_class (reg_class_t
/* orig_class */, enum machine_mode
)
9291 return GENERAL_REGS
;
9295 arc_legitimize_reload_address (rtx
*p
, enum machine_mode mode
, int opnum
,
9299 enum reload_type type
= (enum reload_type
) itype
;
9301 if (GET_CODE (x
) == PLUS
9302 && CONST_INT_P (XEXP (x
, 1))
9303 && (RTX_OK_FOR_BASE_P (XEXP (x
, 0), true)
9304 || (REG_P (XEXP (x
, 0))
9305 && reg_equiv_constant (REGNO (XEXP (x
, 0))))))
9307 int scale
= GET_MODE_SIZE (mode
);
9309 rtx index_rtx
= XEXP (x
, 1);
9310 HOST_WIDE_INT offset
= INTVAL (index_rtx
), offset_base
;
9315 if ((scale
-1) & offset
)
9318 offset_base
= (offset
+ (256 << shift
)) & (-512 << shift
);
9319 /* Sometimes the normal form does not suit DImode. We
9320 could avoid that by using smaller ranges, but that
9321 would give less optimized code when SImode is
9323 if (GET_MODE_SIZE (mode
) + offset
- offset_base
<= (256 << shift
))
9328 regno
= REGNO (reg
);
9329 sum2
= sum
= plus_constant (Pmode
, reg
, offset_base
);
9331 if (reg_equiv_constant (regno
))
9333 sum2
= plus_constant (Pmode
, reg_equiv_constant (regno
),
9335 if (GET_CODE (sum2
) == PLUS
)
9336 sum2
= gen_rtx_CONST (Pmode
, sum2
);
9338 *p
= gen_rtx_PLUS (Pmode
, sum
, GEN_INT (offset
- offset_base
));
9339 push_reload (sum2
, NULL_RTX
, &XEXP (*p
, 0), NULL
,
9340 BASE_REG_CLASS
, Pmode
, VOIDmode
, 0, 0, opnum
,
9345 /* We must re-recognize what we created before. */
9346 else if (GET_CODE (x
) == PLUS
9347 && GET_CODE (XEXP (x
, 0)) == PLUS
9348 && CONST_INT_P (XEXP (XEXP (x
, 0), 1))
9349 && REG_P (XEXP (XEXP (x
, 0), 0))
9350 && CONST_INT_P (XEXP (x
, 1)))
9352 /* Because this address is so complex, we know it must have
9353 been created by LEGITIMIZE_RELOAD_ADDRESS before; thus,
9354 it is already unshared, and needs no further unsharing. */
9355 push_reload (XEXP (x
, 0), NULL_RTX
, &XEXP (x
, 0), NULL
,
9356 BASE_REG_CLASS
, Pmode
, VOIDmode
, 0, 0, opnum
, type
);
9362 struct gcc_target targetm
= TARGET_INITIALIZER
;