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 true, /* has_execute */
613 TV_IFCVT2
, /* tv_id */
614 0, /* properties_required */
615 0, /* properties_provided */
616 0, /* properties_destroyed */
617 0, /* todo_flags_start */
618 TODO_df_finish
/* todo_flags_finish */
621 class pass_arc_ifcvt
: public rtl_opt_pass
624 pass_arc_ifcvt(gcc::context
*ctxt
)
625 : rtl_opt_pass(pass_data_arc_ifcvt
, ctxt
)
628 /* opt_pass methods: */
629 opt_pass
* clone () { return new pass_arc_ifcvt (m_ctxt
); }
630 virtual unsigned int execute (function
*) { return arc_ifcvt (); }
636 make_pass_arc_ifcvt (gcc::context
*ctxt
)
638 return new pass_arc_ifcvt (ctxt
);
641 static unsigned arc_predicate_delay_insns (void);
645 const pass_data pass_data_arc_predicate_delay_insns
=
648 "arc_predicate_delay_insns", /* name */
649 OPTGROUP_NONE
, /* optinfo_flags */
650 true, /* has_execute */
651 TV_IFCVT2
, /* tv_id */
652 0, /* properties_required */
653 0, /* properties_provided */
654 0, /* properties_destroyed */
655 0, /* todo_flags_start */
656 TODO_df_finish
/* todo_flags_finish */
659 class pass_arc_predicate_delay_insns
: public rtl_opt_pass
662 pass_arc_predicate_delay_insns(gcc::context
*ctxt
)
663 : rtl_opt_pass(pass_data_arc_predicate_delay_insns
, ctxt
)
666 /* opt_pass methods: */
667 virtual unsigned int execute (function
*)
669 return arc_predicate_delay_insns ();
676 make_pass_arc_predicate_delay_insns (gcc::context
*ctxt
)
678 return new pass_arc_predicate_delay_insns (ctxt
);
681 /* Called by OVERRIDE_OPTIONS to initialize various things. */
686 enum attr_tune tune_dflt
= TUNE_NONE
;
690 arc_cpu_string
= "A5";
692 else if (TARGET_ARC600
)
694 arc_cpu_string
= "ARC600";
695 tune_dflt
= TUNE_ARC600
;
697 else if (TARGET_ARC601
)
699 arc_cpu_string
= "ARC601";
700 tune_dflt
= TUNE_ARC600
;
702 else if (TARGET_ARC700
)
704 arc_cpu_string
= "ARC700";
705 tune_dflt
= TUNE_ARC700_4_2_STD
;
709 if (arc_tune
== TUNE_NONE
)
710 arc_tune
= tune_dflt
;
711 /* Note: arc_multcost is only used in rtx_cost if speed is true. */
712 if (arc_multcost
< 0)
715 case TUNE_ARC700_4_2_STD
:
717 max throughput (1 multiply + 4 other insns) / 5 cycles. */
718 arc_multcost
= COSTS_N_INSNS (4);
719 if (TARGET_NOMPY_SET
)
720 arc_multcost
= COSTS_N_INSNS (30);
722 case TUNE_ARC700_4_2_XMAC
:
724 max throughput (1 multiply + 2 other insns) / 3 cycles. */
725 arc_multcost
= COSTS_N_INSNS (3);
726 if (TARGET_NOMPY_SET
)
727 arc_multcost
= COSTS_N_INSNS (30);
730 if (TARGET_MUL64_SET
)
732 arc_multcost
= COSTS_N_INSNS (4);
737 arc_multcost
= COSTS_N_INSNS (30);
741 /* Support mul64 generation only for A5 and ARC600. */
742 if (TARGET_MUL64_SET
&& TARGET_ARC700
)
743 error ("-mmul64 not supported for ARC700");
745 /* MPY instructions valid only for ARC700. */
746 if (TARGET_NOMPY_SET
&& !TARGET_ARC700
)
747 error ("-mno-mpy supported only for ARC700");
749 /* mul/mac instructions only for ARC600. */
750 if (TARGET_MULMAC_32BY16_SET
&& !(TARGET_ARC600
|| TARGET_ARC601
))
751 error ("-mmul32x16 supported only for ARC600 or ARC601");
753 if (!TARGET_DPFP
&& TARGET_DPFP_DISABLE_LRSR
)
754 error ("-mno-dpfp-lrsr supported only with -mdpfp");
756 /* FPX-1. No fast and compact together. */
757 if ((TARGET_DPFP_FAST_SET
&& TARGET_DPFP_COMPACT_SET
)
758 || (TARGET_SPFP_FAST_SET
&& TARGET_SPFP_COMPACT_SET
))
759 error ("FPX fast and compact options cannot be specified together");
761 /* FPX-2. No fast-spfp for arc600 or arc601. */
762 if (TARGET_SPFP_FAST_SET
&& (TARGET_ARC600
|| TARGET_ARC601
))
763 error ("-mspfp_fast not available on ARC600 or ARC601");
765 /* FPX-3. No FPX extensions on pre-ARC600 cores. */
766 if ((TARGET_DPFP
|| TARGET_SPFP
)
767 && !(TARGET_ARC600
|| TARGET_ARC601
|| TARGET_ARC700
))
768 error ("FPX extensions not available on pre-ARC600 cores");
770 /* Warn for unimplemented PIC in pre-ARC700 cores, and disable flag_pic. */
771 if (flag_pic
&& !TARGET_ARC700
)
773 warning (DK_WARNING
, "PIC is not supported for %s. Generating non-PIC code only..", arc_cpu_string
);
777 arc_init_reg_tables ();
779 /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P. */
780 memset (arc_punct_chars
, 0, sizeof (arc_punct_chars
));
781 arc_punct_chars
['#'] = 1;
782 arc_punct_chars
['*'] = 1;
783 arc_punct_chars
['?'] = 1;
784 arc_punct_chars
['!'] = 1;
785 arc_punct_chars
['^'] = 1;
786 arc_punct_chars
['&'] = 1;
788 if (optimize
> 1 && !TARGET_NO_COND_EXEC
)
790 /* There are two target-independent ifcvt passes, and arc_reorg may do
791 one or more arc_ifcvt calls. */
792 opt_pass
*pass_arc_ifcvt_4
= make_pass_arc_ifcvt (g
);
793 struct register_pass_info arc_ifcvt4_info
794 = { pass_arc_ifcvt_4
, "dbr", 1, PASS_POS_INSERT_AFTER
};
795 struct register_pass_info arc_ifcvt5_info
796 = { pass_arc_ifcvt_4
->clone (), "shorten", 1, PASS_POS_INSERT_BEFORE
};
798 register_pass (&arc_ifcvt4_info
);
799 register_pass (&arc_ifcvt5_info
);
802 if (flag_delayed_branch
)
804 opt_pass
*pass_arc_predicate_delay_insns
805 = make_pass_arc_predicate_delay_insns (g
);
806 struct register_pass_info arc_predicate_delay_info
807 = { pass_arc_predicate_delay_insns
, "dbr", 1, PASS_POS_INSERT_AFTER
};
809 register_pass (&arc_predicate_delay_info
);
813 /* Check ARC options, generate derived target attributes. */
816 arc_override_options (void)
818 if (arc_cpu
== PROCESSOR_NONE
)
819 arc_cpu
= PROCESSOR_ARC700
;
821 if (arc_size_opt_level
== 3)
825 target_flags
|= MASK_NO_SDATA_SET
;
827 if (flag_no_common
== 255)
828 flag_no_common
= !TARGET_NO_SDATA_SET
;
830 /* TARGET_COMPACT_CASESI needs the "q" register class. */ \
831 if (TARGET_MIXED_CODE
)
834 TARGET_COMPACT_CASESI
= 0;
835 if (TARGET_COMPACT_CASESI
)
836 TARGET_CASE_VECTOR_PC_RELATIVE
= 1;
838 /* These need to be done at start up. It's convenient to do them here. */
842 /* The condition codes of the ARC, and the inverse function. */
843 /* For short branches, the "c" / "nc" names are not defined in the ARC
844 Programmers manual, so we have to use "lo" / "hs"" instead. */
845 static const char *arc_condition_codes
[] =
847 "al", 0, "eq", "ne", "p", "n", "lo", "hs", "v", "nv",
848 "gt", "le", "ge", "lt", "hi", "ls", "pnz", 0
851 enum arc_cc_code_index
853 ARC_CC_AL
, ARC_CC_EQ
= ARC_CC_AL
+2, ARC_CC_NE
, ARC_CC_P
, ARC_CC_N
,
854 ARC_CC_C
, ARC_CC_NC
, ARC_CC_V
, ARC_CC_NV
,
855 ARC_CC_GT
, ARC_CC_LE
, ARC_CC_GE
, ARC_CC_LT
, ARC_CC_HI
, ARC_CC_LS
, ARC_CC_PNZ
,
856 ARC_CC_LO
= ARC_CC_C
, ARC_CC_HS
= ARC_CC_NC
859 #define ARC_INVERSE_CONDITION_CODE(X) ((X) ^ 1)
861 /* Returns the index of the ARC condition code string in
862 `arc_condition_codes'. COMPARISON should be an rtx like
863 `(eq (...) (...))'. */
866 get_arc_condition_code (rtx comparison
)
868 switch (GET_MODE (XEXP (comparison
, 0)))
871 case SImode
: /* For BRcc. */
872 switch (GET_CODE (comparison
))
874 case EQ
: return ARC_CC_EQ
;
875 case NE
: return ARC_CC_NE
;
876 case GT
: return ARC_CC_GT
;
877 case LE
: return ARC_CC_LE
;
878 case GE
: return ARC_CC_GE
;
879 case LT
: return ARC_CC_LT
;
880 case GTU
: return ARC_CC_HI
;
881 case LEU
: return ARC_CC_LS
;
882 case LTU
: return ARC_CC_LO
;
883 case GEU
: return ARC_CC_HS
;
884 default : gcc_unreachable ();
887 switch (GET_CODE (comparison
))
889 case EQ
: return ARC_CC_EQ
;
890 case NE
: return ARC_CC_NE
;
891 case GE
: return ARC_CC_P
;
892 case LT
: return ARC_CC_N
;
893 case GT
: return ARC_CC_PNZ
;
894 default : gcc_unreachable ();
897 switch (GET_CODE (comparison
))
899 case EQ
: return ARC_CC_EQ
;
900 case NE
: return ARC_CC_NE
;
901 default : gcc_unreachable ();
904 switch (GET_CODE (comparison
))
906 case LTU
: return ARC_CC_C
;
907 case GEU
: return ARC_CC_NC
;
908 default : gcc_unreachable ();
911 if (TARGET_ARGONAUT_SET
&& TARGET_SPFP
)
912 switch (GET_CODE (comparison
))
914 case GT
: return ARC_CC_N
;
915 case UNLE
: return ARC_CC_P
;
916 default : gcc_unreachable ();
919 switch (GET_CODE (comparison
))
921 case GT
: return ARC_CC_HI
;
922 case UNLE
: return ARC_CC_LS
;
923 default : gcc_unreachable ();
926 /* Same for FPX and non-FPX. */
927 switch (GET_CODE (comparison
))
929 case GE
: return ARC_CC_HS
;
930 case UNLT
: return ARC_CC_LO
;
931 default : gcc_unreachable ();
934 switch (GET_CODE (comparison
))
936 case UNEQ
: return ARC_CC_EQ
;
937 case LTGT
: return ARC_CC_NE
;
938 default : gcc_unreachable ();
941 switch (GET_CODE (comparison
))
943 case UNORDERED
: return ARC_CC_C
;
944 case ORDERED
: return ARC_CC_NC
;
945 default : gcc_unreachable ();
948 switch (GET_CODE (comparison
))
950 case EQ
: return ARC_CC_EQ
;
951 case NE
: return ARC_CC_NE
;
952 case UNORDERED
: return ARC_CC_C
;
953 case ORDERED
: return ARC_CC_NC
;
954 case LTGT
: return ARC_CC_HI
;
955 case UNEQ
: return ARC_CC_LS
;
956 default : gcc_unreachable ();
958 default : gcc_unreachable ();
964 /* Return true if COMPARISON has a short form that can accomodate OFFSET. */
967 arc_short_comparison_p (rtx comparison
, int offset
)
969 gcc_assert (ARC_CC_NC
== ARC_CC_HS
);
970 gcc_assert (ARC_CC_C
== ARC_CC_LO
);
971 switch (get_arc_condition_code (comparison
))
973 case ARC_CC_EQ
: case ARC_CC_NE
:
974 return offset
>= -512 && offset
<= 506;
975 case ARC_CC_GT
: case ARC_CC_LE
: case ARC_CC_GE
: case ARC_CC_LT
:
976 case ARC_CC_HI
: case ARC_CC_LS
: case ARC_CC_LO
: case ARC_CC_HS
:
977 return offset
>= -64 && offset
<= 58;
983 /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
984 return the mode to be used for the comparison. */
987 arc_select_cc_mode (enum rtx_code op
, rtx x
, rtx y
)
989 enum machine_mode mode
= GET_MODE (x
);
992 /* For an operation that sets the condition codes as a side-effect, the
993 C and V flags is not set as for cmp, so we can only use comparisons where
994 this doesn't matter. (For LT and GE we can use "mi" and "pl"
996 /* ??? We could use "pnz" for greater than zero, however, we could then
997 get into trouble because the comparison could not be reversed. */
998 if (GET_MODE_CLASS (mode
) == MODE_INT
1000 && (op
== EQ
|| op
== NE
1001 || ((op
== LT
|| op
== GE
) && GET_MODE_SIZE (GET_MODE (x
)) <= 4)))
1004 /* add.f for if (a+b) */
1006 && GET_CODE (y
) == NEG
1007 && (op
== EQ
|| op
== NE
))
1010 /* Check if this is a test suitable for bxor.f . */
1011 if (mode
== SImode
&& (op
== EQ
|| op
== NE
) && CONST_INT_P (y
)
1012 && ((INTVAL (y
) - 1) & INTVAL (y
)) == 0
1016 /* Check if this is a test suitable for add / bmsk.f . */
1017 if (mode
== SImode
&& (op
== EQ
|| op
== NE
) && CONST_INT_P (y
)
1018 && GET_CODE (x
) == AND
&& CONST_INT_P ((x1
= XEXP (x
, 1)))
1019 && ((INTVAL (x1
) + 1) & INTVAL (x1
)) == 0
1020 && (~INTVAL (x1
) | INTVAL (y
)) < 0
1021 && (~INTVAL (x1
) | INTVAL (y
)) > -0x800)
1024 if (GET_MODE (x
) == SImode
&& (op
== LTU
|| op
== GEU
)
1025 && GET_CODE (x
) == PLUS
1026 && (rtx_equal_p (XEXP (x
, 0), y
) || rtx_equal_p (XEXP (x
, 1), y
)))
1029 if (TARGET_ARGONAUT_SET
1030 && ((mode
== SFmode
&& TARGET_SPFP
) || (mode
== DFmode
&& TARGET_DPFP
)))
1033 case EQ
: case NE
: case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1035 case LT
: case UNGE
: case GT
: case UNLE
:
1036 return CC_FP_GTmode
;
1037 case LE
: case UNGT
: case GE
: case UNLT
:
1038 return CC_FP_GEmode
;
1039 default: gcc_unreachable ();
1041 else if (GET_MODE_CLASS (mode
) == MODE_FLOAT
&& TARGET_OPTFPE
)
1044 case EQ
: case NE
: return CC_Zmode
;
1046 case GT
: case UNLE
: return CC_FP_GTmode
;
1048 case GE
: case UNLT
: return CC_FP_GEmode
;
1049 case UNEQ
: case LTGT
: return CC_FP_UNEQmode
;
1050 case ORDERED
: case UNORDERED
: return CC_FP_ORDmode
;
1051 default: gcc_unreachable ();
1057 /* Vectors to keep interesting information about registers where it can easily
1058 be got. We use to use the actual mode value as the bit number, but there
1059 is (or may be) more than 32 modes now. Instead we use two tables: one
1060 indexed by hard register number, and one indexed by mode. */
1062 /* The purpose of arc_mode_class is to shrink the range of modes so that
1063 they all fit (as bit numbers) in a 32-bit word (again). Each real mode is
1064 mapped into one arc_mode_class mode. */
1066 enum arc_mode_class
{
1068 S_MODE
, D_MODE
, T_MODE
, O_MODE
,
1069 SF_MODE
, DF_MODE
, TF_MODE
, OF_MODE
,
1073 /* Modes for condition codes. */
1074 #define C_MODES (1 << (int) C_MODE)
1076 /* Modes for single-word and smaller quantities. */
1077 #define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
1079 /* Modes for double-word and smaller quantities. */
1080 #define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))
1082 /* Mode for 8-byte DF values only. */
1083 #define DF_MODES (1 << DF_MODE)
1085 /* Modes for quad-word and smaller quantities. */
1086 #define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE))
1088 /* Modes for 128-bit vectors. */
1089 #define V_MODES (1 << (int) V_MODE)
1091 /* Value is 1 if register/mode pair is acceptable on arc. */
1093 unsigned int arc_hard_regno_mode_ok
[] = {
1094 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
,
1095 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
,
1096 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, D_MODES
,
1097 D_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1099 /* ??? Leave these as S_MODES for now. */
1100 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1101 DF_MODES
, 0, DF_MODES
, 0, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1102 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1103 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, C_MODES
, S_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
,
1107 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
,
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
,
1112 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1113 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1115 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1116 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
1119 unsigned int arc_mode_class
[NUM_MACHINE_MODES
];
1121 enum reg_class arc_regno_reg_class
[FIRST_PSEUDO_REGISTER
];
1124 arc_preferred_reload_class (rtx
, enum reg_class cl
)
1126 if ((cl
) == CHEAP_CORE_REGS
|| (cl
) == WRITABLE_CORE_REGS
)
1127 return GENERAL_REGS
;
1131 /* Initialize the arc_mode_class array. */
1134 arc_init_reg_tables (void)
1138 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
1140 enum machine_mode m
= (enum machine_mode
) i
;
1142 switch (GET_MODE_CLASS (m
))
1145 case MODE_PARTIAL_INT
:
1146 case MODE_COMPLEX_INT
:
1147 if (GET_MODE_SIZE (m
) <= 4)
1148 arc_mode_class
[i
] = 1 << (int) S_MODE
;
1149 else if (GET_MODE_SIZE (m
) == 8)
1150 arc_mode_class
[i
] = 1 << (int) D_MODE
;
1151 else if (GET_MODE_SIZE (m
) == 16)
1152 arc_mode_class
[i
] = 1 << (int) T_MODE
;
1153 else if (GET_MODE_SIZE (m
) == 32)
1154 arc_mode_class
[i
] = 1 << (int) O_MODE
;
1156 arc_mode_class
[i
] = 0;
1159 case MODE_COMPLEX_FLOAT
:
1160 if (GET_MODE_SIZE (m
) <= 4)
1161 arc_mode_class
[i
] = 1 << (int) SF_MODE
;
1162 else if (GET_MODE_SIZE (m
) == 8)
1163 arc_mode_class
[i
] = 1 << (int) DF_MODE
;
1164 else if (GET_MODE_SIZE (m
) == 16)
1165 arc_mode_class
[i
] = 1 << (int) TF_MODE
;
1166 else if (GET_MODE_SIZE (m
) == 32)
1167 arc_mode_class
[i
] = 1 << (int) OF_MODE
;
1169 arc_mode_class
[i
] = 0;
1171 case MODE_VECTOR_INT
:
1172 arc_mode_class
[i
] = (1<< (int) V_MODE
);
1176 /* mode_class hasn't been initialized yet for EXTRA_CC_MODES, so
1177 we must explicitly check for them here. */
1178 if (i
== (int) CCmode
|| i
== (int) CC_ZNmode
|| i
== (int) CC_Zmode
1179 || i
== (int) CC_Cmode
1180 || i
== CC_FP_GTmode
|| i
== CC_FP_GEmode
|| i
== CC_FP_ORDmode
)
1181 arc_mode_class
[i
] = 1 << (int) C_MODE
;
1183 arc_mode_class
[i
] = 0;
1189 /* Core registers 56..59 are used for multiply extension options.
1190 The dsp option uses r56 and r57, these are then named acc1 and acc2.
1191 acc1 is the highpart, and acc2 the lowpart, so which register gets which
1192 number depends on endianness.
1193 The mul64 multiplier options use r57 for mlo, r58 for mmid and r59 for mhi.
1194 Because mlo / mhi form a 64 bit value, we use different gcc internal
1195 register numbers to make them form a register pair as the gcc internals
1196 know it. mmid gets number 57, if still available, and mlo / mhi get
1197 number 58 and 59, depending on endianness. We use DBX_REGISTER_NUMBER
1198 to map this back. */
1199 char rname56
[5] = "r56";
1200 char rname57
[5] = "r57";
1201 char rname58
[5] = "r58";
1202 char rname59
[5] = "r59";
1205 arc_conditional_register_usage (void)
1209 int fix_start
= 60, fix_end
= 55;
1211 if (TARGET_MUL64_SET
)
1216 /* We don't provide a name for mmed. In rtl / assembly resource lists,
1217 you are supposed to refer to it as mlo & mhi, e.g
1218 (zero_extract:SI (reg:DI 58) (const_int 32) (16)) .
1219 In an actual asm instruction, you are of course use mmed.
1220 The point of avoiding having a separate register for mmed is that
1221 this way, we don't have to carry clobbers of that reg around in every
1222 isntruction that modifies mlo and/or mhi. */
1223 strcpy (rname57
, "");
1224 strcpy (rname58
, TARGET_BIG_ENDIAN
? "mhi" : "mlo");
1225 strcpy (rname59
, TARGET_BIG_ENDIAN
? "mlo" : "mhi");
1227 if (TARGET_MULMAC_32BY16_SET
)
1230 fix_end
= fix_end
> 57 ? fix_end
: 57;
1231 strcpy (rname56
, TARGET_BIG_ENDIAN
? "acc1" : "acc2");
1232 strcpy (rname57
, TARGET_BIG_ENDIAN
? "acc2" : "acc1");
1234 for (regno
= fix_start
; regno
<= fix_end
; regno
++)
1236 if (!fixed_regs
[regno
])
1237 warning (0, "multiply option implies r%d is fixed", regno
);
1238 fixed_regs
[regno
] = call_used_regs
[regno
] = 1;
1242 reg_alloc_order
[2] = 12;
1243 reg_alloc_order
[3] = 13;
1244 reg_alloc_order
[4] = 14;
1245 reg_alloc_order
[5] = 15;
1246 reg_alloc_order
[6] = 1;
1247 reg_alloc_order
[7] = 0;
1248 reg_alloc_order
[8] = 4;
1249 reg_alloc_order
[9] = 5;
1250 reg_alloc_order
[10] = 6;
1251 reg_alloc_order
[11] = 7;
1252 reg_alloc_order
[12] = 8;
1253 reg_alloc_order
[13] = 9;
1254 reg_alloc_order
[14] = 10;
1255 reg_alloc_order
[15] = 11;
1257 if (TARGET_SIMD_SET
)
1260 for (i
= ARC_FIRST_SIMD_VR_REG
; i
<= ARC_LAST_SIMD_VR_REG
; i
++)
1261 reg_alloc_order
[i
] = i
;
1262 for (i
= ARC_FIRST_SIMD_DMA_CONFIG_REG
;
1263 i
<= ARC_LAST_SIMD_DMA_CONFIG_REG
; i
++)
1264 reg_alloc_order
[i
] = i
;
1266 /* For Arctangent-A5 / ARC600, lp_count may not be read in an instruction
1267 following immediately after another one setting it to a new value.
1268 There was some discussion on how to enforce scheduling constraints for
1269 processors with missing interlocks on the gcc mailing list:
1270 http://gcc.gnu.org/ml/gcc/2008-05/msg00021.html .
1271 However, we can't actually use this approach, because for ARC the
1272 delay slot scheduling pass is active, which runs after
1273 machine_dependent_reorg. */
1275 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], LP_COUNT
);
1276 else if (!TARGET_ARC700
)
1277 fixed_regs
[LP_COUNT
] = 1;
1278 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
1279 if (!call_used_regs
[regno
])
1280 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], regno
);
1281 for (regno
= 32; regno
< 60; regno
++)
1282 if (!fixed_regs
[regno
])
1283 SET_HARD_REG_BIT (reg_class_contents
[WRITABLE_CORE_REGS
], regno
);
1286 for (regno
= 32; regno
<= 60; regno
++)
1287 CLEAR_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], regno
);
1289 /* If they have used -ffixed-lp_count, make sure it takes
1291 if (fixed_regs
[LP_COUNT
])
1293 CLEAR_HARD_REG_BIT (reg_class_contents
[LPCOUNT_REG
], LP_COUNT
);
1294 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], LP_COUNT
);
1295 CLEAR_HARD_REG_BIT (reg_class_contents
[WRITABLE_CORE_REGS
], LP_COUNT
);
1297 /* Instead of taking out SF_MODE like below, forbid it outright. */
1298 arc_hard_regno_mode_ok
[60] = 0;
1301 arc_hard_regno_mode_ok
[60] = 1 << (int) S_MODE
;
1304 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1308 if (TARGET_Q_CLASS
&& ((i
<= 3) || ((i
>= 12) && (i
<= 15))))
1309 arc_regno_reg_class
[i
] = ARCOMPACT16_REGS
;
1311 arc_regno_reg_class
[i
] = GENERAL_REGS
;
1314 arc_regno_reg_class
[i
]
1316 ? (TEST_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], i
)
1317 ? CHEAP_CORE_REGS
: ALL_CORE_REGS
)
1319 && TEST_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], i
))
1320 ? CHEAP_CORE_REGS
: WRITABLE_CORE_REGS
));
1322 arc_regno_reg_class
[i
] = NO_REGS
;
1325 /* ARCOMPACT16_REGS is empty, if TARGET_Q_CLASS has not been activated. */
1326 if (!TARGET_Q_CLASS
)
1328 CLEAR_HARD_REG_SET(reg_class_contents
[ARCOMPACT16_REGS
]);
1329 CLEAR_HARD_REG_SET(reg_class_contents
[AC16_BASE_REGS
]);
1332 gcc_assert (FIRST_PSEUDO_REGISTER
>= 144);
1334 /* Handle Special Registers. */
1335 arc_regno_reg_class
[29] = LINK_REGS
; /* ilink1 register. */
1336 arc_regno_reg_class
[30] = LINK_REGS
; /* ilink2 register. */
1337 arc_regno_reg_class
[31] = LINK_REGS
; /* blink register. */
1338 arc_regno_reg_class
[60] = LPCOUNT_REG
;
1339 arc_regno_reg_class
[61] = NO_REGS
; /* CC_REG: must be NO_REGS. */
1340 arc_regno_reg_class
[62] = GENERAL_REGS
;
1344 for (i
= 40; i
< 44; ++i
)
1346 arc_regno_reg_class
[i
] = DOUBLE_REGS
;
1348 /* Unless they want us to do 'mov d1, 0x00000000' make sure
1349 no attempt is made to use such a register as a destination
1350 operand in *movdf_insn. */
1351 if (!TARGET_ARGONAUT_SET
)
1353 /* Make sure no 'c', 'w', 'W', or 'Rac' constraint is
1354 interpreted to mean they can use D1 or D2 in their insn. */
1355 CLEAR_HARD_REG_BIT(reg_class_contents
[CHEAP_CORE_REGS
], i
);
1356 CLEAR_HARD_REG_BIT(reg_class_contents
[ALL_CORE_REGS
], i
);
1357 CLEAR_HARD_REG_BIT(reg_class_contents
[WRITABLE_CORE_REGS
], i
);
1358 CLEAR_HARD_REG_BIT(reg_class_contents
[MPY_WRITABLE_CORE_REGS
], i
);
1364 /* Disable all DOUBLE_REGISTER settings,
1365 if not generating DPFP code. */
1366 arc_regno_reg_class
[40] = ALL_REGS
;
1367 arc_regno_reg_class
[41] = ALL_REGS
;
1368 arc_regno_reg_class
[42] = ALL_REGS
;
1369 arc_regno_reg_class
[43] = ALL_REGS
;
1371 arc_hard_regno_mode_ok
[40] = 0;
1372 arc_hard_regno_mode_ok
[42] = 0;
1374 CLEAR_HARD_REG_SET(reg_class_contents
[DOUBLE_REGS
]);
1377 if (TARGET_SIMD_SET
)
1379 gcc_assert (ARC_FIRST_SIMD_VR_REG
== 64);
1380 gcc_assert (ARC_LAST_SIMD_VR_REG
== 127);
1382 for (i
= ARC_FIRST_SIMD_VR_REG
; i
<= ARC_LAST_SIMD_VR_REG
; i
++)
1383 arc_regno_reg_class
[i
] = SIMD_VR_REGS
;
1385 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_REG
== 128);
1386 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_IN_REG
== 128);
1387 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG
== 136);
1388 gcc_assert (ARC_LAST_SIMD_DMA_CONFIG_REG
== 143);
1390 for (i
= ARC_FIRST_SIMD_DMA_CONFIG_REG
;
1391 i
<= ARC_LAST_SIMD_DMA_CONFIG_REG
; i
++)
1392 arc_regno_reg_class
[i
] = SIMD_DMA_CONFIG_REGS
;
1396 arc_regno_reg_class
[PROGRAM_COUNTER_REGNO
] = GENERAL_REGS
;
1399 /* Handle an "interrupt" attribute; arguments as in
1400 struct attribute_spec.handler. */
1403 arc_handle_interrupt_attribute (tree
*, tree name
, tree args
, int,
1408 tree value
= TREE_VALUE (args
);
1410 if (TREE_CODE (value
) != STRING_CST
)
1412 warning (OPT_Wattributes
,
1413 "argument of %qE attribute is not a string constant",
1415 *no_add_attrs
= true;
1417 else if (strcmp (TREE_STRING_POINTER (value
), "ilink1")
1418 && strcmp (TREE_STRING_POINTER (value
), "ilink2"))
1420 warning (OPT_Wattributes
,
1421 "argument of %qE attribute is not \"ilink1\" or \"ilink2\"",
1423 *no_add_attrs
= true;
1428 /* Return zero if TYPE1 and TYPE are incompatible, one if they are compatible,
1429 and two if they are nearly compatible (which causes a warning to be
1433 arc_comp_type_attributes (const_tree type1
,
1436 int l1
, l2
, m1
, m2
, s1
, s2
;
1438 /* Check for mismatch of non-default calling convention. */
1439 if (TREE_CODE (type1
) != FUNCTION_TYPE
)
1442 /* Check for mismatched call attributes. */
1443 l1
= lookup_attribute ("long_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
1444 l2
= lookup_attribute ("long_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
1445 m1
= lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
1446 m2
= lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
1447 s1
= lookup_attribute ("short_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
1448 s2
= lookup_attribute ("short_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
1450 /* Only bother to check if an attribute is defined. */
1451 if (l1
| l2
| m1
| m2
| s1
| s2
)
1453 /* If one type has an attribute, the other must have the same attribute. */
1454 if ((l1
!= l2
) || (m1
!= m2
) || (s1
!= s2
))
1457 /* Disallow mixed attributes. */
1458 if (l1
+ m1
+ s1
> 1)
1466 /* Set the default attributes for TYPE. */
1469 arc_set_default_type_attributes (tree type ATTRIBUTE_UNUSED
)
1474 /* Misc. utilities. */
1476 /* X and Y are two things to compare using CODE. Emit the compare insn and
1477 return the rtx for the cc reg in the proper mode. */
1480 gen_compare_reg (rtx comparison
, enum machine_mode omode
)
1482 enum rtx_code code
= GET_CODE (comparison
);
1483 rtx x
= XEXP (comparison
, 0);
1484 rtx y
= XEXP (comparison
, 1);
1486 enum machine_mode mode
, cmode
;
1489 cmode
= GET_MODE (x
);
1490 if (cmode
== VOIDmode
)
1491 cmode
= GET_MODE (y
);
1492 gcc_assert (cmode
== SImode
|| cmode
== SFmode
|| cmode
== DFmode
);
1493 if (cmode
== SImode
)
1495 if (!register_operand (x
, SImode
))
1497 if (register_operand (y
, SImode
))
1502 code
= swap_condition (code
);
1505 x
= copy_to_mode_reg (SImode
, x
);
1507 if (GET_CODE (y
) == SYMBOL_REF
&& flag_pic
)
1508 y
= copy_to_mode_reg (SImode
, y
);
1512 x
= force_reg (cmode
, x
);
1513 y
= force_reg (cmode
, y
);
1515 mode
= SELECT_CC_MODE (code
, x
, y
);
1517 cc_reg
= gen_rtx_REG (mode
, CC_REG
);
1519 /* ??? FIXME (x-y)==0, as done by both cmpsfpx_raw and
1520 cmpdfpx_raw, is not a correct comparison for floats:
1521 http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
1523 if (TARGET_ARGONAUT_SET
1524 && ((cmode
== SFmode
&& TARGET_SPFP
) || (cmode
== DFmode
&& TARGET_DPFP
)))
1528 case NE
: case EQ
: case LT
: case UNGE
: case LE
: case UNGT
:
1529 case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1531 case GT
: case UNLE
: case GE
: case UNLT
:
1532 code
= swap_condition (code
);
1540 if (cmode
== SFmode
)
1542 emit_insn (gen_cmpsfpx_raw (x
, y
));
1546 /* Accepts Dx regs directly by insns. */
1547 emit_insn (gen_cmpdfpx_raw (x
, y
));
1550 if (mode
!= CC_FPXmode
)
1551 emit_insn (gen_rtx_SET (VOIDmode
, cc_reg
,
1552 gen_rtx_COMPARE (mode
,
1553 gen_rtx_REG (CC_FPXmode
, 61),
1556 else if (GET_MODE_CLASS (cmode
) == MODE_FLOAT
&& TARGET_OPTFPE
)
1558 rtx op0
= gen_rtx_REG (cmode
, 0);
1559 rtx op1
= gen_rtx_REG (cmode
, GET_MODE_SIZE (cmode
) / UNITS_PER_WORD
);
1563 case NE
: case EQ
: case GT
: case UNLE
: case GE
: case UNLT
:
1564 case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1566 case LT
: case UNGE
: case LE
: case UNGT
:
1567 code
= swap_condition (code
);
1575 if (currently_expanding_to_rtl
)
1577 emit_move_insn (op0
, x
);
1578 emit_move_insn (op1
, y
);
1582 gcc_assert (rtx_equal_p (op0
, x
));
1583 gcc_assert (rtx_equal_p (op1
, y
));
1585 emit_insn (gen_cmp_float (cc_reg
, gen_rtx_COMPARE (mode
, op0
, op1
)));
1588 emit_insn (gen_rtx_SET (omode
, cc_reg
,
1589 gen_rtx_COMPARE (mode
, x
, y
)));
1590 return gen_rtx_fmt_ee (code
, omode
, cc_reg
, const0_rtx
);
1593 /* Return true if VALUE, a const_double, will fit in a limm (4 byte number).
1594 We assume the value can be either signed or unsigned. */
1597 arc_double_limm_p (rtx value
)
1599 HOST_WIDE_INT low
, high
;
1601 gcc_assert (GET_CODE (value
) == CONST_DOUBLE
);
1606 low
= CONST_DOUBLE_LOW (value
);
1607 high
= CONST_DOUBLE_HIGH (value
);
1609 if (low
& 0x80000000)
1611 return (((unsigned HOST_WIDE_INT
) low
<= 0xffffffff && high
== 0)
1612 || (((low
& - (unsigned HOST_WIDE_INT
) 0x80000000)
1613 == - (unsigned HOST_WIDE_INT
) 0x80000000)
1618 return (unsigned HOST_WIDE_INT
) low
<= 0x7fffffff && high
== 0;
1622 /* Do any needed setup for a variadic function. For the ARC, we must
1623 create a register parameter block, and then copy any anonymous arguments
1624 in registers to memory.
1626 CUM has not been updated for the last named argument which has type TYPE
1627 and mode MODE, and we rely on this fact. */
1630 arc_setup_incoming_varargs (cumulative_args_t args_so_far
,
1631 enum machine_mode mode
, tree type
,
1632 int *pretend_size
, int no_rtl
)
1635 CUMULATIVE_ARGS next_cum
;
1637 /* We must treat `__builtin_va_alist' as an anonymous arg. */
1639 next_cum
= *get_cumulative_args (args_so_far
);
1640 arc_function_arg_advance (pack_cumulative_args (&next_cum
), mode
, type
, 1);
1641 first_anon_arg
= next_cum
;
1643 if (first_anon_arg
< MAX_ARC_PARM_REGS
)
1645 /* First anonymous (unnamed) argument is in a reg. */
1647 /* Note that first_reg_offset < MAX_ARC_PARM_REGS. */
1648 int first_reg_offset
= first_anon_arg
;
1653 = gen_rtx_MEM (BLKmode
, plus_constant (Pmode
, arg_pointer_rtx
,
1654 FIRST_PARM_OFFSET (0)));
1655 move_block_from_reg (first_reg_offset
, regblock
,
1656 MAX_ARC_PARM_REGS
- first_reg_offset
);
1660 = ((MAX_ARC_PARM_REGS
- first_reg_offset
) * UNITS_PER_WORD
);
1664 /* Cost functions. */
1666 /* Provide the costs of an addressing mode that contains ADDR.
1667 If ADDR is not a valid address, its cost is irrelevant. */
1670 arc_address_cost (rtx addr
, enum machine_mode
, addr_space_t
, bool speed
)
1672 switch (GET_CODE (addr
))
1675 return speed
|| satisfies_constraint_Rcq (addr
) ? 0 : 1;
1676 case PRE_INC
: case PRE_DEC
: case POST_INC
: case POST_DEC
:
1677 case PRE_MODIFY
: case POST_MODIFY
:
1683 /* Most likely needs a LIMM. */
1684 return COSTS_N_INSNS (1);
1688 register rtx plus0
= XEXP (addr
, 0);
1689 register rtx plus1
= XEXP (addr
, 1);
1691 if (GET_CODE (plus0
) != REG
1692 && (GET_CODE (plus0
) != MULT
1693 || !CONST_INT_P (XEXP (plus0
, 1))
1694 || (INTVAL (XEXP (plus0
, 1)) != 2
1695 && INTVAL (XEXP (plus0
, 1)) != 4)))
1698 switch (GET_CODE (plus1
))
1701 return (!RTX_OK_FOR_OFFSET_P (SImode
, plus1
)
1705 : (satisfies_constraint_Rcq (plus0
)
1706 && satisfies_constraint_O (plus1
))
1710 return (speed
< 1 ? 0
1711 : (satisfies_constraint_Rcq (plus0
)
1712 && satisfies_constraint_Rcq (plus1
))
1717 return COSTS_N_INSNS (1);
1730 /* Emit instruction X with the frame related bit set. */
1736 RTX_FRAME_RELATED_P (x
) = 1;
1740 /* Emit a frame insn to move SRC to DST. */
1743 frame_move (rtx dst
, rtx src
)
1745 return frame_insn (gen_rtx_SET (VOIDmode
, dst
, src
));
1748 /* Like frame_move, but add a REG_INC note for REG if ADDR contains an
1749 auto increment address, or is zero. */
1752 frame_move_inc (rtx dst
, rtx src
, rtx reg
, rtx addr
)
1754 rtx insn
= frame_move (dst
, src
);
1757 || GET_CODE (addr
) == PRE_DEC
|| GET_CODE (addr
) == POST_INC
1758 || GET_CODE (addr
) == PRE_MODIFY
|| GET_CODE (addr
) == POST_MODIFY
)
1759 add_reg_note (insn
, REG_INC
, reg
);
1763 /* Emit a frame insn which adjusts a frame address register REG by OFFSET. */
1766 frame_add (rtx reg
, HOST_WIDE_INT offset
)
1768 gcc_assert ((offset
& 0x3) == 0);
1771 return frame_move (reg
, plus_constant (Pmode
, reg
, offset
));
1774 /* Emit a frame insn which adjusts stack pointer by OFFSET. */
1777 frame_stack_add (HOST_WIDE_INT offset
)
1779 return frame_add (stack_pointer_rtx
, offset
);
1782 /* Traditionally, we push saved registers first in the prologue,
1783 then we allocate the rest of the frame - and reverse in the epilogue.
1784 This has still its merits for ease of debugging, or saving code size
1785 or even execution time if the stack frame is so large that some accesses
1786 can't be encoded anymore with offsets in the instruction code when using
1788 Also, it would be a good starting point if we got instructions to help
1789 with register save/restore.
1791 However, often stack frames are small, and the pushing / popping has
1793 - the stack modification prevents a lot of scheduling.
1794 - frame allocation / deallocation needs extra instructions.
1795 - unless we know that we compile ARC700 user code, we need to put
1796 a memory barrier after frame allocation / before deallocation to
1797 prevent interrupts clobbering our data in the frame.
1798 In particular, we don't have any such guarantees for library functions,
1799 which tend to, on the other hand, to have small frames.
1801 Thus, for small frames, we'd like to use a different scheme:
1802 - The frame is allocated in full with the first prologue instruction,
1803 and deallocated in full with the last epilogue instruction.
1804 Thus, the instructions in-betwen can be freely scheduled.
1805 - If the function has no outgoing arguments on the stack, we can allocate
1806 one register save slot at the top of the stack. This register can then
1807 be saved simultanously with frame allocation, and restored with
1809 This register can be picked depending on scheduling considerations,
1810 although same though should go into having some set of registers
1811 to be potentially lingering after a call, and others to be available
1812 immediately - i.e. in the absence of interprocedual optimization, we
1813 can use an ABI-like convention for register allocation to reduce
1814 stalls after function return. */
1815 /* Function prologue/epilogue handlers. */
1817 /* ARCompact stack frames look like:
1819 Before call After call
1820 high +-----------------------+ +-----------------------+
1821 mem | reg parm save area | | reg parm save area |
1822 | only created for | | only created for |
1823 | variable arg fns | | variable arg fns |
1824 AP +-----------------------+ +-----------------------+
1825 | return addr register | | return addr register |
1826 | (if required) | | (if required) |
1827 +-----------------------+ +-----------------------+
1829 | reg save area | | reg save area |
1831 +-----------------------+ +-----------------------+
1832 | frame pointer | | frame pointer |
1833 | (if required) | | (if required) |
1834 FP +-----------------------+ +-----------------------+
1836 | local/temp variables | | local/temp variables |
1838 +-----------------------+ +-----------------------+
1840 | arguments on stack | | arguments on stack |
1842 SP +-----------------------+ +-----------------------+
1843 | reg parm save area |
1844 | only created for |
1845 | variable arg fns |
1846 AP +-----------------------+
1847 | return addr register |
1849 +-----------------------+
1853 +-----------------------+
1856 FP +-----------------------+
1858 | local/temp variables |
1860 +-----------------------+
1862 | arguments on stack |
1864 mem SP +-----------------------+
1867 1) The "reg parm save area" does not exist for non variable argument fns.
1868 The "reg parm save area" can be eliminated completely if we created our
1869 own va-arc.h, but that has tradeoffs as well (so it's not done). */
1871 /* Structure to be filled in by arc_compute_frame_size with register
1872 save masks, and offsets for the current function. */
1873 struct GTY (()) arc_frame_info
1875 unsigned int total_size
; /* # bytes that the entire frame takes up. */
1876 unsigned int extra_size
; /* # bytes of extra stuff. */
1877 unsigned int pretend_size
; /* # bytes we push and pretend caller did. */
1878 unsigned int args_size
; /* # bytes that outgoing arguments take up. */
1879 unsigned int reg_size
; /* # bytes needed to store regs. */
1880 unsigned int var_size
; /* # bytes that variables take up. */
1881 unsigned int reg_offset
; /* Offset from new sp to store regs. */
1882 unsigned int gmask
; /* Mask of saved gp registers. */
1883 int initialized
; /* Nonzero if frame size already calculated. */
1884 short millicode_start_reg
;
1885 short millicode_end_reg
;
1886 bool save_return_addr
;
1889 /* Defining data structures for per-function information. */
1891 typedef struct GTY (()) machine_function
1893 enum arc_function_type fn_type
;
1894 struct arc_frame_info frame_info
;
1895 /* To keep track of unalignment caused by short insns. */
1897 int force_short_suffix
; /* Used when disgorging return delay slot insns. */
1898 const char *size_reason
;
1899 struct arc_ccfsm ccfsm_current
;
1900 /* Map from uid to ccfsm state during branch shortening. */
1901 rtx ccfsm_current_insn
;
1902 char arc_reorg_started
;
1903 char prescan_initialized
;
1906 /* Type of function DECL.
1908 The result is cached. To reset the cache at the end of a function,
1909 call with DECL = NULL_TREE. */
1911 enum arc_function_type
1912 arc_compute_function_type (struct function
*fun
)
1914 tree decl
= fun
->decl
;
1916 enum arc_function_type fn_type
= fun
->machine
->fn_type
;
1918 if (fn_type
!= ARC_FUNCTION_UNKNOWN
)
1921 /* Assume we have a normal function (not an interrupt handler). */
1922 fn_type
= ARC_FUNCTION_NORMAL
;
1924 /* Now see if this is an interrupt handler. */
1925 for (a
= DECL_ATTRIBUTES (decl
);
1929 tree name
= TREE_PURPOSE (a
), args
= TREE_VALUE (a
);
1931 if (name
== get_identifier ("interrupt")
1932 && list_length (args
) == 1
1933 && TREE_CODE (TREE_VALUE (args
)) == STRING_CST
)
1935 tree value
= TREE_VALUE (args
);
1937 if (!strcmp (TREE_STRING_POINTER (value
), "ilink1"))
1938 fn_type
= ARC_FUNCTION_ILINK1
;
1939 else if (!strcmp (TREE_STRING_POINTER (value
), "ilink2"))
1940 fn_type
= ARC_FUNCTION_ILINK2
;
1947 return fun
->machine
->fn_type
= fn_type
;
1950 #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
1951 #define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM))
1953 /* Tell prologue and epilogue if register REGNO should be saved / restored.
1954 The return address and frame pointer are treated separately.
1955 Don't consider them here.
1956 Addition for pic: The gp register needs to be saved if the current
1957 function changes it to access gotoff variables.
1958 FIXME: This will not be needed if we used some arbitrary register
1961 #define MUST_SAVE_REGISTER(regno, interrupt_p) \
1962 (((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \
1963 && (df_regs_ever_live_p (regno) && (!call_used_regs[regno] || interrupt_p))) \
1964 || (flag_pic && crtl->uses_pic_offset_table \
1965 && regno == PIC_OFFSET_TABLE_REGNUM) )
1967 #define MUST_SAVE_RETURN_ADDR \
1968 (cfun->machine->frame_info.save_return_addr)
1970 /* Return non-zero if there are registers to be saved or loaded using
1971 millicode thunks. We can only use consecutive sequences starting
1972 with r13, and not going beyond r25.
1973 GMASK is a bitmask of registers to save. This function sets
1974 FRAME->millicod_start_reg .. FRAME->millicode_end_reg to the range
1975 of registers to be saved / restored with a millicode call. */
1978 arc_compute_millicode_save_restore_regs (unsigned int gmask
,
1979 struct arc_frame_info
*frame
)
1983 int start_reg
= 13, end_reg
= 25;
1985 for (regno
= start_reg
; regno
<= end_reg
&& (gmask
& (1L << regno
));)
1987 end_reg
= regno
- 1;
1988 /* There is no point in using millicode thunks if we don't save/restore
1989 at least three registers. For non-leaf functions we also have the
1991 if (regno
- start_reg
>= 3 - (crtl
->is_leaf
== 0))
1993 frame
->millicode_start_reg
= 13;
1994 frame
->millicode_end_reg
= regno
- 1;
2000 /* Return the bytes needed to compute the frame pointer from the current
2003 SIZE is the size needed for local variables. */
2006 arc_compute_frame_size (int size
) /* size = # of var. bytes allocated. */
2009 unsigned int total_size
, var_size
, args_size
, pretend_size
, extra_size
;
2010 unsigned int reg_size
, reg_offset
;
2012 enum arc_function_type fn_type
;
2014 struct arc_frame_info
*frame_info
= &cfun
->machine
->frame_info
;
2016 size
= ARC_STACK_ALIGN (size
);
2018 /* 1) Size of locals and temporaries */
2021 /* 2) Size of outgoing arguments */
2022 args_size
= crtl
->outgoing_args_size
;
2024 /* 3) Calculate space needed for saved registers.
2025 ??? We ignore the extension registers for now. */
2027 /* See if this is an interrupt handler. Call used registers must be saved
2032 fn_type
= arc_compute_function_type (cfun
);
2033 interrupt_p
= ARC_INTERRUPT_P (fn_type
);
2035 for (regno
= 0; regno
<= 31; regno
++)
2037 if (MUST_SAVE_REGISTER (regno
, interrupt_p
))
2039 reg_size
+= UNITS_PER_WORD
;
2040 gmask
|= 1 << regno
;
2044 /* 4) Space for back trace data structure.
2045 <return addr reg size> (if required) + <fp size> (if required). */
2046 frame_info
->save_return_addr
2047 = (!crtl
->is_leaf
|| df_regs_ever_live_p (RETURN_ADDR_REGNUM
));
2048 /* Saving blink reg in case of leaf function for millicode thunk calls. */
2049 if (optimize_size
&& !TARGET_NO_MILLICODE_THUNK_SET
)
2051 if (arc_compute_millicode_save_restore_regs (gmask
, frame_info
))
2052 frame_info
->save_return_addr
= true;
2056 if (MUST_SAVE_RETURN_ADDR
)
2058 if (frame_pointer_needed
)
2061 /* 5) Space for variable arguments passed in registers */
2062 pretend_size
= crtl
->args
.pretend_args_size
;
2064 /* Ensure everything before the locals is aligned appropriately. */
2066 unsigned int extra_plus_reg_size
;
2067 unsigned int extra_plus_reg_size_aligned
;
2069 extra_plus_reg_size
= extra_size
+ reg_size
;
2070 extra_plus_reg_size_aligned
= ARC_STACK_ALIGN(extra_plus_reg_size
);
2071 reg_size
= extra_plus_reg_size_aligned
- extra_size
;
2074 /* Compute total frame size. */
2075 total_size
= var_size
+ args_size
+ extra_size
+ pretend_size
+ reg_size
;
2077 total_size
= ARC_STACK_ALIGN (total_size
);
2079 /* Compute offset of register save area from stack pointer:
2080 A5 Frame: pretend_size <blink> reg_size <fp> var_size args_size <--sp
2082 reg_offset
= (total_size
- (pretend_size
+ reg_size
+ extra_size
)
2083 + (frame_pointer_needed
? 4 : 0));
2085 /* Save computed information. */
2086 frame_info
->total_size
= total_size
;
2087 frame_info
->extra_size
= extra_size
;
2088 frame_info
->pretend_size
= pretend_size
;
2089 frame_info
->var_size
= var_size
;
2090 frame_info
->args_size
= args_size
;
2091 frame_info
->reg_size
= reg_size
;
2092 frame_info
->reg_offset
= reg_offset
;
2093 frame_info
->gmask
= gmask
;
2094 frame_info
->initialized
= reload_completed
;
2096 /* Ok, we're done. */
2100 /* Common code to save/restore registers. */
2101 /* BASE_REG is the base register to use for addressing and to adjust.
2102 GMASK is a bitmask of general purpose registers to save/restore.
2103 epilogue_p 0: prologue 1:epilogue 2:epilogue, sibling thunk
2104 If *FIRST_OFFSET is non-zero, add it first to BASE_REG - preferably
2105 using a pre-modify for the first memory access. *FIRST_OFFSET is then
2109 arc_save_restore (rtx base_reg
,
2110 unsigned int gmask
, int epilogue_p
, int *first_offset
)
2112 unsigned int offset
= 0;
2114 struct arc_frame_info
*frame
= &cfun
->machine
->frame_info
;
2115 rtx sibthunk_insn
= NULL_RTX
;
2119 /* Millicode thunks implementation:
2120 Generates calls to millicodes for registers starting from r13 to r25
2121 Present Limitations:
2122 - Only one range supported. The remaining regs will have the ordinary
2123 st and ld instructions for store and loads. Hence a gmask asking
2124 to store r13-14, r16-r25 will only generate calls to store and
2125 load r13 to r14 while store and load insns will be generated for
2126 r16 to r25 in the prologue and epilogue respectively.
2128 - Presently library only supports register ranges starting from r13.
2130 if (epilogue_p
== 2 || frame
->millicode_end_reg
> 14)
2132 int start_call
= frame
->millicode_start_reg
;
2133 int end_call
= frame
->millicode_end_reg
;
2134 int n_regs
= end_call
- start_call
+ 1;
2135 int i
= 0, r
, off
= 0;
2137 rtx ret_addr
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
2141 /* "reg_size" won't be more than 127 . */
2142 gcc_assert (epilogue_p
|| abs (*first_offset
) <= 127);
2143 frame_add (base_reg
, *first_offset
);
2146 insn
= gen_rtx_PARALLEL
2147 (VOIDmode
, rtvec_alloc ((epilogue_p
== 2) + n_regs
+ 1));
2148 if (epilogue_p
== 2)
2151 XVECEXP (insn
, 0, n_regs
) = gen_rtx_CLOBBER (VOIDmode
, ret_addr
);
2152 for (r
= start_call
; r
<= end_call
; r
++, off
+= UNITS_PER_WORD
, i
++)
2154 rtx reg
= gen_rtx_REG (SImode
, r
);
2156 = gen_frame_mem (SImode
, plus_constant (Pmode
, base_reg
, off
));
2159 XVECEXP (insn
, 0, i
) = gen_rtx_SET (VOIDmode
, reg
, mem
);
2161 XVECEXP (insn
, 0, i
) = gen_rtx_SET (VOIDmode
, mem
, reg
);
2162 gmask
= gmask
& ~(1L << r
);
2164 if (epilogue_p
== 2)
2165 sibthunk_insn
= insn
;
2171 for (regno
= 0; regno
<= 31; regno
++)
2173 if ((gmask
& (1L << regno
)) != 0)
2175 rtx reg
= gen_rtx_REG (SImode
, regno
);
2180 gcc_assert (!offset
);
2181 addr
= plus_constant (Pmode
, base_reg
, *first_offset
);
2182 addr
= gen_rtx_PRE_MODIFY (Pmode
, base_reg
, addr
);
2187 gcc_assert (SMALL_INT (offset
));
2188 addr
= plus_constant (Pmode
, base_reg
, offset
);
2190 mem
= gen_frame_mem (SImode
, addr
);
2192 frame_move_inc (reg
, mem
, base_reg
, addr
);
2194 frame_move_inc (mem
, reg
, base_reg
, addr
);
2195 offset
+= UNITS_PER_WORD
;
2201 rtx r12
= gen_rtx_REG (Pmode
, 12);
2203 frame_insn (gen_rtx_SET (VOIDmode
, r12
, GEN_INT (offset
)));
2204 XVECEXP (sibthunk_insn
, 0, 0) = ret_rtx
;
2205 XVECEXP (sibthunk_insn
, 0, 1)
2206 = gen_rtx_SET (VOIDmode
, stack_pointer_rtx
,
2207 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
, r12
));
2208 sibthunk_insn
= emit_jump_insn (sibthunk_insn
);
2209 RTX_FRAME_RELATED_P (sibthunk_insn
) = 1;
2211 } /* arc_save_restore */
2214 int arc_return_address_regs
[4]
2215 = {0, RETURN_ADDR_REGNUM
, ILINK1_REGNUM
, ILINK2_REGNUM
};
2217 /* Set up the stack and frame pointer (if desired) for the function. */
2220 arc_expand_prologue (void)
2222 int size
= get_frame_size ();
2223 unsigned int gmask
= cfun
->machine
->frame_info
.gmask
;
2224 /* unsigned int frame_pointer_offset;*/
2225 unsigned int frame_size_to_allocate
;
2226 /* (FIXME: The first store will use a PRE_MODIFY; this will usually be r13.
2227 Change the stack layout so that we rather store a high register with the
2228 PRE_MODIFY, thus enabling more short insn generation.) */
2229 int first_offset
= 0;
2231 size
= ARC_STACK_ALIGN (size
);
2233 /* Compute/get total frame size. */
2234 size
= (!cfun
->machine
->frame_info
.initialized
2235 ? arc_compute_frame_size (size
)
2236 : cfun
->machine
->frame_info
.total_size
);
2238 if (flag_stack_usage_info
)
2239 current_function_static_stack_size
= size
;
2241 /* Keep track of frame size to be allocated. */
2242 frame_size_to_allocate
= size
;
2244 /* These cases shouldn't happen. Catch them now. */
2245 gcc_assert (!(size
== 0 && gmask
));
2247 /* Allocate space for register arguments if this is a variadic function. */
2248 if (cfun
->machine
->frame_info
.pretend_size
!= 0)
2250 /* Ensure pretend_size is maximum of 8 * word_size. */
2251 gcc_assert (cfun
->machine
->frame_info
.pretend_size
<= 32);
2253 frame_stack_add (-(HOST_WIDE_INT
)cfun
->machine
->frame_info
.pretend_size
);
2254 frame_size_to_allocate
-= cfun
->machine
->frame_info
.pretend_size
;
2257 /* The home-grown ABI says link register is saved first. */
2258 if (MUST_SAVE_RETURN_ADDR
)
2260 rtx ra
= gen_rtx_REG (SImode
, RETURN_ADDR_REGNUM
);
2261 rtx mem
= gen_frame_mem (Pmode
, gen_rtx_PRE_DEC (Pmode
, stack_pointer_rtx
));
2263 frame_move_inc (mem
, ra
, stack_pointer_rtx
, 0);
2264 frame_size_to_allocate
-= UNITS_PER_WORD
;
2266 } /* MUST_SAVE_RETURN_ADDR */
2268 /* Save any needed call-saved regs (and call-used if this is an
2269 interrupt handler) for ARCompact ISA. */
2270 if (cfun
->machine
->frame_info
.reg_size
)
2272 first_offset
= -cfun
->machine
->frame_info
.reg_size
;
2273 /* N.B. FRAME_POINTER_MASK and RETURN_ADDR_MASK are cleared in gmask. */
2274 arc_save_restore (stack_pointer_rtx
, gmask
, 0, &first_offset
);
2275 frame_size_to_allocate
-= cfun
->machine
->frame_info
.reg_size
;
2279 /* Save frame pointer if needed. */
2280 if (frame_pointer_needed
)
2282 rtx addr
= gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
2283 GEN_INT (-UNITS_PER_WORD
+ first_offset
));
2284 rtx mem
= gen_frame_mem (Pmode
, gen_rtx_PRE_MODIFY (Pmode
,
2287 frame_move_inc (mem
, frame_pointer_rtx
, stack_pointer_rtx
, 0);
2288 frame_size_to_allocate
-= UNITS_PER_WORD
;
2290 frame_move (frame_pointer_rtx
, stack_pointer_rtx
);
2293 /* ??? We don't handle the case where the saved regs are more than 252
2294 bytes away from sp. This can be handled by decrementing sp once, saving
2295 the regs, and then decrementing it again. The epilogue doesn't have this
2296 problem as the `ld' insn takes reg+limm values (though it would be more
2297 efficient to avoid reg+limm). */
2299 frame_size_to_allocate
-= first_offset
;
2300 /* Allocate the stack frame. */
2301 if (frame_size_to_allocate
> 0)
2302 frame_stack_add ((HOST_WIDE_INT
) 0 - frame_size_to_allocate
);
2304 /* Setup the gp register, if needed. */
2305 if (crtl
->uses_pic_offset_table
)
2306 arc_finalize_pic ();
2309 /* Do any necessary cleanup after a function to restore stack, frame,
2313 arc_expand_epilogue (int sibcall_p
)
2315 int size
= get_frame_size ();
2316 enum arc_function_type fn_type
= arc_compute_function_type (cfun
);
2318 size
= ARC_STACK_ALIGN (size
);
2319 size
= (!cfun
->machine
->frame_info
.initialized
2320 ? arc_compute_frame_size (size
)
2321 : cfun
->machine
->frame_info
.total_size
);
2323 unsigned int pretend_size
= cfun
->machine
->frame_info
.pretend_size
;
2324 unsigned int frame_size
;
2325 unsigned int size_to_deallocate
;
2327 int can_trust_sp_p
= !cfun
->calls_alloca
;
2328 int first_offset
= 0;
2329 int millicode_p
= cfun
->machine
->frame_info
.millicode_end_reg
> 0;
2331 size_to_deallocate
= size
;
2333 frame_size
= size
- (pretend_size
+
2334 cfun
->machine
->frame_info
.reg_size
+
2335 cfun
->machine
->frame_info
.extra_size
);
2337 /* ??? There are lots of optimizations that can be done here.
2338 EG: Use fp to restore regs if it's closer.
2339 Maybe in time we'll do them all. For now, always restore regs from
2340 sp, but don't restore sp if we don't have to. */
2342 if (!can_trust_sp_p
)
2343 gcc_assert (frame_pointer_needed
);
2345 /* Restore stack pointer to the beginning of saved register area for
2349 if (frame_pointer_needed
)
2350 frame_move (stack_pointer_rtx
, frame_pointer_rtx
);
2352 first_offset
= frame_size
;
2353 size_to_deallocate
-= frame_size
;
2355 else if (!can_trust_sp_p
)
2356 frame_stack_add (-frame_size
);
2359 /* Restore any saved registers. */
2360 if (frame_pointer_needed
)
2362 rtx addr
= gen_rtx_POST_INC (Pmode
, stack_pointer_rtx
);
2364 frame_move_inc (frame_pointer_rtx
, gen_frame_mem (Pmode
, addr
),
2365 stack_pointer_rtx
, 0);
2366 size_to_deallocate
-= UNITS_PER_WORD
;
2369 /* Load blink after the calls to thunk calls in case of optimize size. */
2372 int sibthunk_p
= (!sibcall_p
2373 && fn_type
== ARC_FUNCTION_NORMAL
2374 && !cfun
->machine
->frame_info
.pretend_size
);
2376 gcc_assert (!(cfun
->machine
->frame_info
.gmask
2377 & (FRAME_POINTER_MASK
| RETURN_ADDR_MASK
)));
2378 arc_save_restore (stack_pointer_rtx
,
2379 cfun
->machine
->frame_info
.gmask
,
2380 1 + sibthunk_p
, &first_offset
);
2384 /* If we are to restore registers, and first_offset would require
2385 a limm to be encoded in a PRE_MODIFY, yet we can add it with a
2386 fast add to the stack pointer, do this now. */
2387 if ((!SMALL_INT (first_offset
)
2388 && cfun
->machine
->frame_info
.gmask
2389 && ((TARGET_ARC700
&& !optimize_size
)
2390 ? first_offset
<= 0x800
2391 : satisfies_constraint_C2a (GEN_INT (first_offset
))))
2392 /* Also do this if we have both gprs and return
2393 address to restore, and they both would need a LIMM. */
2394 || (MUST_SAVE_RETURN_ADDR
2395 && !SMALL_INT ((cfun
->machine
->frame_info
.reg_size
+ first_offset
) >> 2)
2396 && cfun
->machine
->frame_info
.gmask
))
2398 frame_stack_add (first_offset
);
2401 if (MUST_SAVE_RETURN_ADDR
)
2403 rtx ra
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
2404 int ra_offs
= cfun
->machine
->frame_info
.reg_size
+ first_offset
;
2405 rtx addr
= plus_constant (Pmode
, stack_pointer_rtx
, ra_offs
);
2407 /* If the load of blink would need a LIMM, but we can add
2408 the offset quickly to sp, do the latter. */
2409 if (!SMALL_INT (ra_offs
>> 2)
2410 && !cfun
->machine
->frame_info
.gmask
2411 && ((TARGET_ARC700
&& !optimize_size
)
2413 : satisfies_constraint_C2a (GEN_INT (ra_offs
))))
2415 size_to_deallocate
-= ra_offs
- first_offset
;
2417 frame_stack_add (ra_offs
);
2419 addr
= stack_pointer_rtx
;
2421 /* See if we can combine the load of the return address with the
2422 final stack adjustment.
2423 We need a separate load if there are still registers to
2424 restore. We also want a separate load if the combined insn
2425 would need a limm, but a separate load doesn't. */
2427 && !cfun
->machine
->frame_info
.gmask
2428 && (SMALL_INT (ra_offs
) || !SMALL_INT (ra_offs
>> 2)))
2430 addr
= gen_rtx_PRE_MODIFY (Pmode
, stack_pointer_rtx
, addr
);
2432 size_to_deallocate
-= cfun
->machine
->frame_info
.reg_size
;
2434 else if (!ra_offs
&& size_to_deallocate
== UNITS_PER_WORD
)
2436 addr
= gen_rtx_POST_INC (Pmode
, addr
);
2437 size_to_deallocate
= 0;
2439 frame_move_inc (ra
, gen_frame_mem (Pmode
, addr
), stack_pointer_rtx
, addr
);
2444 if (cfun
->machine
->frame_info
.reg_size
)
2445 arc_save_restore (stack_pointer_rtx
,
2446 /* The zeroing of these two bits is unnecessary, but leave this in for clarity. */
2447 cfun
->machine
->frame_info
.gmask
2448 & ~(FRAME_POINTER_MASK
| RETURN_ADDR_MASK
), 1, &first_offset
);
2452 /* The rest of this function does the following:
2453 ARCompact : handle epilogue_delay, restore sp (phase-2), return
2456 /* Keep track of how much of the stack pointer we've restored.
2457 It makes the following a lot more readable. */
2458 size_to_deallocate
+= first_offset
;
2459 restored
= size
- size_to_deallocate
;
2461 if (size
> restored
)
2462 frame_stack_add (size
- restored
);
2463 /* Emit the return instruction. */
2464 if (sibcall_p
== FALSE
)
2465 emit_jump_insn (gen_simple_return ());
2467 if (!TARGET_EPILOGUE_CFI
)
2471 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
2472 RTX_FRAME_RELATED_P (insn
) = 0;
2476 /* Return the offset relative to the stack pointer where the return address
2477 is stored, or -1 if it is not stored. */
2480 arc_return_slot_offset ()
2482 struct arc_frame_info
*afi
= &cfun
->machine
->frame_info
;
2484 return (afi
->save_return_addr
2485 ? afi
->total_size
- afi
->pretend_size
- afi
->extra_size
: -1);
2490 /* Emit special PIC prologues and epilogues. */
2491 /* If the function has any GOTOFF relocations, then the GOTBASE
2492 register has to be setup in the prologue
2493 The instruction needed at the function start for setting up the
2496 ----------------------------------------------------------
2497 The rtl to be emitted for this should be:
2500 (const (unspec (symref _DYNAMIC) 3)))
2501 ---------------------------------------------------------- */
2504 arc_finalize_pic (void)
2507 rtx baseptr_rtx
= gen_rtx_REG (Pmode
, PIC_OFFSET_TABLE_REGNUM
);
2509 if (crtl
->uses_pic_offset_table
== 0)
2512 gcc_assert (flag_pic
!= 0);
2514 pat
= gen_rtx_SYMBOL_REF (Pmode
, "_DYNAMIC");
2515 pat
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, pat
), ARC_UNSPEC_GOT
);
2516 pat
= gen_rtx_CONST (Pmode
, pat
);
2518 pat
= gen_rtx_SET (VOIDmode
, baseptr_rtx
, pat
);
2523 /* !TARGET_BARREL_SHIFTER support. */
2524 /* Emit a shift insn to set OP0 to OP1 shifted by OP2; CODE specifies what
2528 emit_shift (enum rtx_code code
, rtx op0
, rtx op1
, rtx op2
)
2530 rtx shift
= gen_rtx_fmt_ee (code
, SImode
, op1
, op2
);
2532 = ((shift4_operator (shift
, SImode
) ? gen_shift_si3
: gen_shift_si3_loop
)
2533 (op0
, op1
, op2
, shift
));
2537 /* Output the assembler code for doing a shift.
2538 We go to a bit of trouble to generate efficient code as the ARC601 only has
2539 single bit shifts. This is taken from the h8300 port. We only have one
2540 mode of shifting and can't access individual bytes like the h8300 can, so
2541 this is greatly simplified (at the expense of not generating hyper-
2544 This function is not used if the variable shift insns are present. */
2546 /* FIXME: This probably can be done using a define_split in arc.md.
2547 Alternately, generate rtx rather than output instructions. */
2550 output_shift (rtx
*operands
)
2552 /* static int loopend_lab;*/
2553 rtx shift
= operands
[3];
2554 enum machine_mode mode
= GET_MODE (shift
);
2555 enum rtx_code code
= GET_CODE (shift
);
2556 const char *shift_one
;
2558 gcc_assert (mode
== SImode
);
2562 case ASHIFT
: shift_one
= "add %0,%1,%1"; break;
2563 case ASHIFTRT
: shift_one
= "asr %0,%1"; break;
2564 case LSHIFTRT
: shift_one
= "lsr %0,%1"; break;
2565 default: gcc_unreachable ();
2568 if (GET_CODE (operands
[2]) != CONST_INT
)
2570 output_asm_insn ("and.f lp_count,%2, 0x1f", operands
);
2577 n
= INTVAL (operands
[2]);
2579 /* Only consider the lower 5 bits of the shift count. */
2582 /* First see if we can do them inline. */
2583 /* ??? We could get better scheduling & shorter code (using short insns)
2584 by using splitters. Alas, that'd be even more verbose. */
2585 if (code
== ASHIFT
&& n
<= 9 && n
> 2
2586 && dest_reg_operand (operands
[4], SImode
))
2588 output_asm_insn ("mov %4,0\n\tadd3 %0,%4,%1", operands
);
2589 for (n
-=3 ; n
>= 3; n
-= 3)
2590 output_asm_insn ("add3 %0,%4,%0", operands
);
2592 output_asm_insn ("add2 %0,%4,%0", operands
);
2594 output_asm_insn ("add %0,%0,%0", operands
);
2600 output_asm_insn (shift_one
, operands
);
2601 operands
[1] = operands
[0];
2604 /* See if we can use a rotate/and. */
2605 else if (n
== BITS_PER_WORD
- 1)
2610 output_asm_insn ("and %0,%1,1\n\tror %0,%0", operands
);
2613 /* The ARC doesn't have a rol insn. Use something else. */
2614 output_asm_insn ("add.f 0,%1,%1\n\tsbc %0,%0,%0", operands
);
2617 /* The ARC doesn't have a rol insn. Use something else. */
2618 output_asm_insn ("add.f 0,%1,%1\n\trlc %0,0", operands
);
2624 else if (n
== BITS_PER_WORD
- 2 && dest_reg_operand (operands
[4], SImode
))
2629 output_asm_insn ("and %0,%1,3\n\tror %0,%0\n\tror %0,%0", operands
);
2632 #if 1 /* Need some scheduling comparisons. */
2633 output_asm_insn ("add.f %4,%1,%1\n\tsbc %0,%0,%0\n\t"
2634 "add.f 0,%4,%4\n\trlc %0,%0", operands
);
2636 output_asm_insn ("add.f %4,%1,%1\n\tbxor %0,%4,31\n\t"
2637 "sbc.f %0,%0,%4\n\trlc %0,%0", operands
);
2642 output_asm_insn ("add.f %4,%1,%1\n\trlc %0,0\n\t"
2643 "add.f 0,%4,%4\n\trlc %0,%0", operands
);
2645 output_asm_insn ("add.f %0,%1,%1\n\trlc.f %0,0\n\t"
2646 "and %0,%0,1\n\trlc %0,%0", operands
);
2653 else if (n
== BITS_PER_WORD
- 3 && code
== ASHIFT
)
2654 output_asm_insn ("and %0,%1,7\n\tror %0,%0\n\tror %0,%0\n\tror %0,%0",
2659 operands
[2] = GEN_INT (n
);
2660 output_asm_insn ("mov.f lp_count, %2", operands
);
2664 output_asm_insn ("lpnz\t2f", operands
);
2665 output_asm_insn (shift_one
, operands
);
2666 output_asm_insn ("nop", operands
);
2667 fprintf (asm_out_file
, "2:\t%s end single insn loop\n",
2676 /* Nested function support. */
2678 /* Directly store VALUE into memory object BLOCK at OFFSET. */
2681 emit_store_direct (rtx block
, int offset
, int value
)
2683 emit_insn (gen_store_direct (adjust_address (block
, SImode
, offset
),
2685 gen_int_mode (value
, SImode
))));
2688 /* Emit RTL insns to initialize the variable parts of a trampoline.
2689 FNADDR is an RTX for the address of the function's pure code.
2690 CXT is an RTX for the static chain value for the function. */
2691 /* With potentially multiple shared objects loaded, and multiple stacks
2692 present for multiple thereds where trampolines might reside, a simple
2693 range check will likely not suffice for the profiler to tell if a callee
2694 is a trampoline. We a speedier check by making the trampoline start at
2695 an address that is not 4-byte aligned.
2696 A trampoline looks like this:
2700 ld_s r12,[pcl,12] 0xd403
2701 ld r11,[pcl,12] 0x170c 700b
2705 The fastest trampoline to execute for trampolines within +-8KB of CTX
2708 j [limm] 0x20200f80 limm
2709 and that would also be faster to write to the stack by computing the offset
2710 from CTX to TRAMP at compile time. However, it would really be better to
2711 get rid of the high cost of cache invalidation when generating trampolines,
2712 which requires that the code part of trampolines stays constant, and
2714 - making sure that no executable code but trampolines is on the stack,
2715 no icache entries linger for the area of the stack from when before the
2716 stack was allocated, and allocating trampolines in trampoline-only
2719 - allocate trampolines fram a special pool of pre-allocated trampolines. */
2722 arc_initialize_trampoline (rtx tramp
, tree fndecl
, rtx cxt
)
2724 rtx fnaddr
= XEXP (DECL_RTL (fndecl
), 0);
2726 emit_store_direct (tramp
, 0, TARGET_BIG_ENDIAN
? 0x78e0d403 : 0xd40378e0);
2727 emit_store_direct (tramp
, 4, TARGET_BIG_ENDIAN
? 0x170c700b : 0x700b170c);
2728 emit_store_direct (tramp
, 8, TARGET_BIG_ENDIAN
? 0x7c0078e0 : 0x78e07c00);
2729 emit_move_insn (adjust_address (tramp
, SImode
, 12), fnaddr
);
2730 emit_move_insn (adjust_address (tramp
, SImode
, 16), cxt
);
2731 emit_insn (gen_flush_icache (adjust_address (tramp
, SImode
, 0)));
2734 /* Allow the profiler to easily distinguish trampolines from normal
2738 arc_trampoline_adjust_address (rtx addr
)
2740 return plus_constant (Pmode
, addr
, 2);
2743 /* This is set briefly to 1 when we output a ".as" address modifer, and then
2744 reset when we output the scaled address. */
2745 static int output_scaled
= 0;
2747 /* Print operand X (an rtx) in assembler syntax to file FILE.
2748 CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
2749 For `%' followed by punctuation, CODE is the punctuation and X is null. */
2750 /* In final.c:output_asm_insn:
2753 'c' : constant address if CONSTANT_ADDRESS_P
2759 '#': condbranch delay slot suffix
2760 '*': jump delay slot suffix
2761 '?' : nonjump-insn suffix for conditional execution or short instruction
2762 '!' : jump / call suffix for conditional execution or short instruction
2763 '`': fold constant inside unary o-perator, re-recognize, and emit.
2768 'B': Branch comparison operand - suppress sda reference
2769 'H': Most significant word
2770 'L': Least significant word
2771 'A': ASCII decimal representation of floating point value
2772 'U': Load/store update or scaling indicator
2773 'V': cache bypass indicator for volatile
2778 'o': original symbol - no @ prepending. */
2781 arc_print_operand (FILE *file
, rtx x
, int code
)
2786 if (GET_CODE (x
) == CONST_INT
)
2787 fprintf (file
, "%d",exact_log2(INTVAL (x
) + 1) - 1 );
2789 output_operand_lossage ("invalid operand to %%Z code");
2794 if (GET_CODE (x
) == CONST_INT
)
2795 fprintf (file
, "%d",exact_log2(INTVAL (x
)) );
2797 output_operand_lossage ("invalid operand to %%z code");
2802 if (GET_CODE (x
) == CONST_INT
)
2803 fprintf (file
, "%d",exact_log2(~INTVAL (x
)) );
2805 output_operand_lossage ("invalid operand to %%M code");
2810 /* Conditional branches depending on condition codes.
2811 Note that this is only for branches that were known to depend on
2812 condition codes before delay slot scheduling;
2813 out-of-range brcc / bbit expansions should use '*'.
2814 This distinction is important because of the different
2815 allowable delay slot insns and the output of the delay suffix
2816 for TARGET_AT_DBR_COND_EXEC. */
2818 /* Unconditional branches / branches not depending on condition codes.
2819 This could also be a CALL_INSN.
2820 Output the appropriate delay slot suffix. */
2821 if (final_sequence
&& XVECLEN (final_sequence
, 0) != 1)
2823 rtx jump
= XVECEXP (final_sequence
, 0, 0);
2824 rtx delay
= XVECEXP (final_sequence
, 0, 1);
2826 /* For TARGET_PAD_RETURN we might have grabbed the delay insn. */
2827 if (INSN_DELETED_P (delay
))
2829 if (JUMP_P (jump
) && INSN_ANNULLED_BRANCH_P (jump
))
2830 fputs (INSN_FROM_TARGET_P (delay
) ? ".d"
2831 : TARGET_AT_DBR_CONDEXEC
&& code
== '#' ? ".d"
2832 : get_attr_type (jump
) == TYPE_RETURN
&& code
== '#' ? ""
2839 case '?' : /* with leading "." */
2840 case '!' : /* without leading "." */
2841 /* This insn can be conditionally executed. See if the ccfsm machinery
2842 says it should be conditionalized.
2843 If it shouldn't, we'll check the compact attribute if this insn
2844 has a short variant, which may be used depending on code size and
2845 alignment considerations. */
2846 if (current_insn_predicate
)
2847 arc_ccfsm_current
.cc
2848 = get_arc_condition_code (current_insn_predicate
);
2849 if (ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current
))
2851 /* Is this insn in a delay slot sequence? */
2852 if (!final_sequence
|| XVECLEN (final_sequence
, 0) < 2
2853 || current_insn_predicate
2854 || CALL_P (XVECEXP (final_sequence
, 0, 0))
2855 || simplejump_p (XVECEXP (final_sequence
, 0, 0)))
2857 /* This insn isn't in a delay slot sequence, or conditionalized
2858 independently of its position in a delay slot. */
2859 fprintf (file
, "%s%s",
2860 code
== '?' ? "." : "",
2861 arc_condition_codes
[arc_ccfsm_current
.cc
]);
2862 /* If this is a jump, there are still short variants. However,
2863 only beq_s / bne_s have the same offset range as b_s,
2864 and the only short conditional returns are jeq_s and jne_s. */
2866 && (arc_ccfsm_current
.cc
== ARC_CC_EQ
2867 || arc_ccfsm_current
.cc
== ARC_CC_NE
2868 || 0 /* FIXME: check if branch in 7 bit range. */))
2869 output_short_suffix (file
);
2871 else if (code
== '!') /* Jump with delay slot. */
2872 fputs (arc_condition_codes
[arc_ccfsm_current
.cc
], file
);
2873 else /* An Instruction in a delay slot of a jump or call. */
2875 rtx jump
= XVECEXP (final_sequence
, 0, 0);
2876 rtx insn
= XVECEXP (final_sequence
, 0, 1);
2878 /* If the insn is annulled and is from the target path, we need
2879 to inverse the condition test. */
2880 if (JUMP_P (jump
) && INSN_ANNULLED_BRANCH_P (jump
))
2882 if (INSN_FROM_TARGET_P (insn
))
2883 fprintf (file
, "%s%s",
2884 code
== '?' ? "." : "",
2885 arc_condition_codes
[ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current
.cc
)]);
2887 fprintf (file
, "%s%s",
2888 code
== '?' ? "." : "",
2889 arc_condition_codes
[arc_ccfsm_current
.cc
]);
2890 if (arc_ccfsm_current
.state
== 5)
2891 arc_ccfsm_current
.state
= 0;
2894 /* This insn is executed for either path, so don't
2895 conditionalize it at all. */
2896 output_short_suffix (file
);
2901 output_short_suffix (file
);
2904 /* FIXME: fold constant inside unary operator, re-recognize, and emit. */
2907 fputs (arc_condition_codes
[get_arc_condition_code (x
)], file
);
2910 fputs (arc_condition_codes
[ARC_INVERSE_CONDITION_CODE
2911 (get_arc_condition_code (x
))],
2915 /* Write second word of DImode or DFmode reference,
2916 register or memory. */
2917 if (GET_CODE (x
) == REG
)
2918 fputs (reg_names
[REGNO (x
)+1], file
);
2919 else if (GET_CODE (x
) == MEM
)
2923 /* Handle possible auto-increment. For PRE_INC / PRE_DEC /
2924 PRE_MODIFY, we will have handled the first word already;
2925 For POST_INC / POST_DEC / POST_MODIFY, the access to the
2926 first word will be done later. In either case, the access
2927 to the first word will do the modify, and we only have
2928 to add an offset of four here. */
2929 if (GET_CODE (XEXP (x
, 0)) == PRE_INC
2930 || GET_CODE (XEXP (x
, 0)) == PRE_DEC
2931 || GET_CODE (XEXP (x
, 0)) == PRE_MODIFY
2932 || GET_CODE (XEXP (x
, 0)) == POST_INC
2933 || GET_CODE (XEXP (x
, 0)) == POST_DEC
2934 || GET_CODE (XEXP (x
, 0)) == POST_MODIFY
)
2935 output_address (plus_constant (Pmode
, XEXP (XEXP (x
, 0), 0), 4));
2936 else if (output_scaled
)
2938 rtx addr
= XEXP (x
, 0);
2939 int size
= GET_MODE_SIZE (GET_MODE (x
));
2941 output_address (plus_constant (Pmode
, XEXP (addr
, 0),
2942 ((INTVAL (XEXP (addr
, 1)) + 4)
2943 >> (size
== 2 ? 1 : 2))));
2947 output_address (plus_constant (Pmode
, XEXP (x
, 0), 4));
2951 output_operand_lossage ("invalid operand to %%R code");
2954 /* FIXME: remove %S option. */
2956 case 'B' /* Branch or other LIMM ref - must not use sda references. */ :
2959 output_addr_const (file
, x
);
2965 if (GET_CODE (x
) == REG
)
2967 /* L = least significant word, H = most significant word. */
2968 if ((WORDS_BIG_ENDIAN
!= 0) ^ (code
== 'L'))
2969 fputs (reg_names
[REGNO (x
)], file
);
2971 fputs (reg_names
[REGNO (x
)+1], file
);
2973 else if (GET_CODE (x
) == CONST_INT
2974 || GET_CODE (x
) == CONST_DOUBLE
)
2978 split_double (x
, &first
, &second
);
2980 if((WORDS_BIG_ENDIAN
) == 0)
2981 fprintf (file
, "0x%08lx",
2982 code
== 'L' ? INTVAL (first
) : INTVAL (second
));
2984 fprintf (file
, "0x%08lx",
2985 code
== 'L' ? INTVAL (second
) : INTVAL (first
));
2990 output_operand_lossage ("invalid operand to %%H/%%L code");
2996 gcc_assert (GET_CODE (x
) == CONST_DOUBLE
2997 && GET_MODE_CLASS (GET_MODE (x
)) == MODE_FLOAT
);
2999 real_to_decimal (str
, CONST_DOUBLE_REAL_VALUE (x
), sizeof (str
), 0, 1);
3000 fprintf (file
, "%s", str
);
3004 /* Output a load/store with update indicator if appropriate. */
3005 if (GET_CODE (x
) == MEM
)
3007 rtx addr
= XEXP (x
, 0);
3008 switch (GET_CODE (addr
))
3010 case PRE_INC
: case PRE_DEC
: case PRE_MODIFY
:
3011 fputs (".a", file
); break;
3012 case POST_INC
: case POST_DEC
: case POST_MODIFY
:
3013 fputs (".ab", file
); break;
3015 /* Are we using a scaled index? */
3016 if (GET_CODE (XEXP (addr
, 0)) == MULT
)
3017 fputs (".as", file
);
3018 /* Can we use a scaled offset? */
3019 else if (CONST_INT_P (XEXP (addr
, 1))
3020 && GET_MODE_SIZE (GET_MODE (x
)) > 1
3021 && (!(INTVAL (XEXP (addr
, 1))
3022 & (GET_MODE_SIZE (GET_MODE (x
)) - 1) & 3))
3023 /* Does it make a difference? */
3024 && !SMALL_INT_RANGE(INTVAL (XEXP (addr
, 1)),
3025 GET_MODE_SIZE (GET_MODE (x
)) - 2, 0))
3027 fputs (".as", file
);
3034 gcc_assert (CONSTANT_P (addr
)); break;
3038 output_operand_lossage ("invalid operand to %%U code");
3041 /* Output cache bypass indicator for a load/store insn. Volatile memory
3042 refs are defined to use the cache bypass mechanism. */
3043 if (GET_CODE (x
) == MEM
)
3045 if (MEM_VOLATILE_P (x
) && !TARGET_VOLATILE_CACHE_SET
)
3046 fputs (".di", file
);
3049 output_operand_lossage ("invalid operand to %%V code");
3054 /* Do nothing special. */
3057 fputs (reg_names
[REGNO (x
)]+1, file
);
3060 /* This punctuation character is needed because label references are
3061 printed in the output template using %l. This is a front end
3062 character, and when we want to emit a '@' before it, we have to use
3068 /* Output an operator. */
3069 switch (GET_CODE (x
))
3071 case PLUS
: fputs ("add", file
); return;
3072 case SS_PLUS
: fputs ("adds", file
); return;
3073 case AND
: fputs ("and", file
); return;
3074 case IOR
: fputs ("or", file
); return;
3075 case XOR
: fputs ("xor", file
); return;
3076 case MINUS
: fputs ("sub", file
); return;
3077 case SS_MINUS
: fputs ("subs", file
); return;
3078 case ASHIFT
: fputs ("asl", file
); return;
3079 case ASHIFTRT
: fputs ("asr", file
); return;
3080 case LSHIFTRT
: fputs ("lsr", file
); return;
3081 case ROTATERT
: fputs ("ror", file
); return;
3082 case MULT
: fputs ("mpy", file
); return;
3083 case ABS
: fputs ("abs", file
); return; /* Unconditional. */
3084 case NEG
: fputs ("neg", file
); return;
3085 case SS_NEG
: fputs ("negs", file
); return;
3086 case NOT
: fputs ("not", file
); return; /* Unconditional. */
3088 fputs ("ext", file
); /* bmsk allows predication. */
3090 case SIGN_EXTEND
: /* Unconditional. */
3091 fputs ("sex", file
);
3093 switch (GET_MODE (XEXP (x
, 0)))
3095 case QImode
: fputs ("b", file
); return;
3096 case HImode
: fputs ("w", file
); return;
3101 if (GET_MODE (x
) != HImode
)
3103 fputs ("sat16", file
);
3106 output_operand_lossage ("invalid operand to %%O code"); return;
3108 if (GET_CODE (x
) == SYMBOL_REF
)
3110 assemble_name (file
, XSTR (x
, 0));
3115 if (TARGET_ANNOTATE_ALIGN
&& cfun
->machine
->size_reason
)
3116 fprintf (file
, "; unalign: %d", cfun
->machine
->unalign
);
3120 output_operand_lossage ("invalid operand output code");
3123 switch (GET_CODE (x
))
3126 fputs (reg_names
[REGNO (x
)], file
);
3130 rtx addr
= XEXP (x
, 0);
3131 int size
= GET_MODE_SIZE (GET_MODE (x
));
3135 switch (GET_CODE (addr
))
3137 case PRE_INC
: case POST_INC
:
3138 output_address (plus_constant (Pmode
, XEXP (addr
, 0), size
)); break;
3139 case PRE_DEC
: case POST_DEC
:
3140 output_address (plus_constant (Pmode
, XEXP (addr
, 0), -size
));
3142 case PRE_MODIFY
: case POST_MODIFY
:
3143 output_address (XEXP (addr
, 1)); break;
3147 output_address (plus_constant (Pmode
, XEXP (addr
, 0),
3148 (INTVAL (XEXP (addr
, 1))
3149 >> (size
== 2 ? 1 : 2))));
3153 output_address (addr
);
3156 if (flag_pic
&& CONSTANT_ADDRESS_P (addr
))
3157 arc_output_pic_addr_const (file
, addr
, code
);
3159 output_address (addr
);
3166 /* We handle SFmode constants here as output_addr_const doesn't. */
3167 if (GET_MODE (x
) == SFmode
)
3172 REAL_VALUE_FROM_CONST_DOUBLE (d
, x
);
3173 REAL_VALUE_TO_TARGET_SINGLE (d
, l
);
3174 fprintf (file
, "0x%08lx", l
);
3177 /* Fall through. Let output_addr_const deal with it. */
3180 arc_output_pic_addr_const (file
, x
, code
);
3183 /* FIXME: Dirty way to handle @var@sda+const. Shd be handled
3184 with asm_output_symbol_ref */
3185 if (GET_CODE (x
) == CONST
&& GET_CODE (XEXP (x
, 0)) == PLUS
)
3188 output_addr_const (file
, XEXP (x
, 0));
3189 if (GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
&& SYMBOL_REF_SMALL_P (XEXP (x
, 0)))
3190 fprintf (file
, "@sda");
3192 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
3193 || INTVAL (XEXP (x
, 1)) >= 0)
3194 fprintf (file
, "+");
3195 output_addr_const (file
, XEXP (x
, 1));
3198 output_addr_const (file
, x
);
3200 if (GET_CODE (x
) == SYMBOL_REF
&& SYMBOL_REF_SMALL_P (x
))
3201 fprintf (file
, "@sda");
3206 /* Print a memory address as an operand to reference that memory location. */
3209 arc_print_operand_address (FILE *file
, rtx addr
)
3211 register rtx base
, index
= 0;
3213 switch (GET_CODE (addr
))
3216 fputs (reg_names
[REGNO (addr
)], file
);
3219 output_addr_const (file
, addr
);
3220 if (SYMBOL_REF_SMALL_P (addr
))
3221 fprintf (file
, "@sda");
3224 if (GET_CODE (XEXP (addr
, 0)) == MULT
)
3225 index
= XEXP (XEXP (addr
, 0), 0), base
= XEXP (addr
, 1);
3226 else if (CONST_INT_P (XEXP (addr
, 0)))
3227 index
= XEXP (addr
, 0), base
= XEXP (addr
, 1);
3229 base
= XEXP (addr
, 0), index
= XEXP (addr
, 1);
3231 gcc_assert (OBJECT_P (base
));
3232 arc_print_operand_address (file
, base
);
3233 if (CONSTANT_P (base
) && CONST_INT_P (index
))
3237 gcc_assert (OBJECT_P (index
));
3238 arc_print_operand_address (file
, index
);
3242 rtx c
= XEXP (addr
, 0);
3244 gcc_assert (GET_CODE (XEXP (c
, 0)) == SYMBOL_REF
);
3245 gcc_assert (GET_CODE (XEXP (c
, 1)) == CONST_INT
);
3247 output_address(XEXP(addr
,0));
3253 /* We shouldn't get here as we've lost the mode of the memory object
3254 (which says how much to inc/dec by. */
3259 arc_output_pic_addr_const (file
, addr
, 0);
3261 output_addr_const (file
, addr
);
3266 /* Called via walk_stores. DATA points to a hash table we can use to
3267 establish a unique SYMBOL_REF for each counter, which corresponds to
3268 a caller-callee pair.
3269 X is a store which we want to examine for an UNSPEC_PROF, which
3270 would be an address loaded into a register, or directly used in a MEM.
3271 If we found an UNSPEC_PROF, if we encounter a new counter the first time,
3272 write out a description and a data allocation for a 32 bit counter.
3273 Also, fill in the appropriate symbol_ref into each UNSPEC_PROF instance. */
3276 write_profile_sections (rtx dest ATTRIBUTE_UNUSED
, rtx x
, void *data
)
3279 htab_t htab
= (htab_t
) data
;
3282 if (GET_CODE (x
) != SET
)
3284 srcp
= &SET_SRC (x
);
3286 srcp
= &XEXP (*srcp
, 0);
3287 else if (MEM_P (SET_DEST (x
)))
3288 srcp
= &XEXP (SET_DEST (x
), 0);
3290 if (GET_CODE (src
) != CONST
)
3292 src
= XEXP (src
, 0);
3293 if (GET_CODE (src
) != UNSPEC
|| XINT (src
, 1) != UNSPEC_PROF
)
3296 gcc_assert (XVECLEN (src
, 0) == 3);
3297 if (!htab_elements (htab
))
3299 output_asm_insn (".section .__arc_profile_desc, \"a\"\n"
3301 &XVECEXP (src
, 0, 0));
3303 slot
= (rtx
*) htab_find_slot (htab
, src
, INSERT
);
3304 if (*slot
== HTAB_EMPTY_ENTRY
)
3306 static int count_nr
;
3311 sprintf (buf
, "__prof_count%d", count_nr
++);
3312 count
= gen_rtx_SYMBOL_REF (Pmode
, xstrdup (buf
));
3313 XVECEXP (src
, 0, 2) = count
;
3314 output_asm_insn (".section\t.__arc_profile_desc, \"a\"\n"
3316 "\t.section\t.__arc_profile_counters, \"aw\"\n"
3317 "\t.type\t%o2, @object\n"
3320 &XVECEXP (src
, 0, 0));
3324 *srcp
= XVECEXP (*slot
, 0, 2);
3327 /* Hash function for UNSPEC_PROF htab. Use both the caller's name and
3328 the callee's name (if known). */
3331 unspec_prof_hash (const void *x
)
3333 const_rtx u
= (const_rtx
) x
;
3334 const_rtx s1
= XVECEXP (u
, 0, 1);
3336 return (htab_hash_string (XSTR (XVECEXP (u
, 0, 0), 0))
3337 ^ (s1
->code
== SYMBOL_REF
? htab_hash_string (XSTR (s1
, 0)) : 0));
3340 /* Equality function for UNSPEC_PROF htab. Two pieces of UNSPEC_PROF rtl
3341 shall refer to the same counter if both caller name and callee rtl
3345 unspec_prof_htab_eq (const void *x
, const void *y
)
3347 const_rtx u0
= (const_rtx
) x
;
3348 const_rtx u1
= (const_rtx
) y
;
3349 const_rtx s01
= XVECEXP (u0
, 0, 1);
3350 const_rtx s11
= XVECEXP (u1
, 0, 1);
3352 return (!strcmp (XSTR (XVECEXP (u0
, 0, 0), 0),
3353 XSTR (XVECEXP (u1
, 0, 0), 0))
3354 && rtx_equal_p (s01
, s11
));
3357 /* Conditional execution support.
3359 This is based on the ARM port but for now is much simpler.
3361 A finite state machine takes care of noticing whether or not instructions
3362 can be conditionally executed, and thus decrease execution time and code
3363 size by deleting branch instructions. The fsm is controlled by
3364 arc_ccfsm_advance (called by arc_final_prescan_insn), and controls the
3365 actions of PRINT_OPERAND. The patterns in the .md file for the branch
3366 insns also have a hand in this. */
3367 /* The way we leave dealing with non-anulled or annull-false delay slot
3368 insns to the consumer is awkward. */
3370 /* The state of the fsm controlling condition codes are:
3371 0: normal, do nothing special
3372 1: don't output this insn
3373 2: don't output this insn
3374 3: make insns conditional
3375 4: make insns conditional
3376 5: make insn conditional (only for outputting anulled delay slot insns)
3378 special value for cfun->machine->uid_ccfsm_state:
3379 6: return with but one insn before it since function start / call
3381 State transitions (state->state by whom, under what condition):
3382 0 -> 1 arc_ccfsm_advance, if insn is a conditional branch skipping over
3384 0 -> 2 arc_ccfsm_advance, if insn is a conditional branch followed
3385 by zero or more non-jump insns and an unconditional branch with
3386 the same target label as the condbranch.
3387 1 -> 3 branch patterns, after having not output the conditional branch
3388 2 -> 4 branch patterns, after having not output the conditional branch
3389 0 -> 5 branch patterns, for anulled delay slot insn.
3390 3 -> 0 ASM_OUTPUT_INTERNAL_LABEL, if the `target' label is reached
3391 (the target label has CODE_LABEL_NUMBER equal to
3392 arc_ccfsm_target_label).
3393 4 -> 0 arc_ccfsm_advance, if `target' unconditional branch is reached
3394 3 -> 1 arc_ccfsm_advance, finding an 'else' jump skipping over some insns.
3395 5 -> 0 when outputting the delay slot insn
3397 If the jump clobbers the conditions then we use states 2 and 4.
3399 A similar thing can be done with conditional return insns.
3401 We also handle separating branches from sets of the condition code.
3402 This is done here because knowledge of the ccfsm state is required,
3403 we may not be outputting the branch. */
3405 /* arc_final_prescan_insn calls arc_ccfsm_advance to adjust arc_ccfsm_current,
3406 before letting final output INSN. */
3409 arc_ccfsm_advance (rtx insn
, struct arc_ccfsm
*state
)
3411 /* BODY will hold the body of INSN. */
3414 /* This will be 1 if trying to repeat the trick (ie: do the `else' part of
3415 an if/then/else), and things need to be reversed. */
3418 /* If we start with a return insn, we only succeed if we find another one. */
3419 int seeking_return
= 0;
3421 /* START_INSN will hold the insn from where we start looking. This is the
3422 first insn after the following code_label if REVERSE is true. */
3423 rtx start_insn
= insn
;
3425 /* Type of the jump_insn. Brcc insns don't affect ccfsm changes,
3426 since they don't rely on a cmp preceding the. */
3427 enum attr_type jump_insn_type
;
3429 /* Allow -mdebug-ccfsm to turn this off so we can see how well it does.
3430 We can't do this in macro FINAL_PRESCAN_INSN because its called from
3431 final_scan_insn which has `optimize' as a local. */
3432 if (optimize
< 2 || TARGET_NO_COND_EXEC
)
3435 /* Ignore notes and labels. */
3438 body
= PATTERN (insn
);
3439 /* If in state 4, check if the target branch is reached, in order to
3440 change back to state 0. */
3441 if (state
->state
== 4)
3443 if (insn
== state
->target_insn
)
3445 state
->target_insn
= NULL
;
3451 /* If in state 3, it is possible to repeat the trick, if this insn is an
3452 unconditional branch to a label, and immediately following this branch
3453 is the previous target label which is only used once, and the label this
3454 branch jumps to is not too far off. Or in other words "we've done the
3455 `then' part, see if we can do the `else' part." */
3456 if (state
->state
== 3)
3458 if (simplejump_p (insn
))
3460 start_insn
= next_nonnote_insn (start_insn
);
3461 if (GET_CODE (start_insn
) == BARRIER
)
3463 /* ??? Isn't this always a barrier? */
3464 start_insn
= next_nonnote_insn (start_insn
);
3466 if (GET_CODE (start_insn
) == CODE_LABEL
3467 && CODE_LABEL_NUMBER (start_insn
) == state
->target_label
3468 && LABEL_NUSES (start_insn
) == 1)
3473 else if (GET_CODE (body
) == SIMPLE_RETURN
)
3475 start_insn
= next_nonnote_insn (start_insn
);
3476 if (GET_CODE (start_insn
) == BARRIER
)
3477 start_insn
= next_nonnote_insn (start_insn
);
3478 if (GET_CODE (start_insn
) == CODE_LABEL
3479 && CODE_LABEL_NUMBER (start_insn
) == state
->target_label
3480 && LABEL_NUSES (start_insn
) == 1)
3492 if (GET_CODE (insn
) != JUMP_INSN
3493 || GET_CODE (PATTERN (insn
)) == ADDR_VEC
3494 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
3497 /* We can't predicate BRCC or loop ends.
3498 Also, when generating PIC code, and considering a medium range call,
3499 we can't predicate the call. */
3500 jump_insn_type
= get_attr_type (insn
);
3501 if (jump_insn_type
== TYPE_BRCC
3502 || jump_insn_type
== TYPE_BRCC_NO_DELAY_SLOT
3503 || jump_insn_type
== TYPE_LOOP_END
3504 || (jump_insn_type
== TYPE_CALL
&& !get_attr_predicable (insn
)))
3507 /* This jump might be paralleled with a clobber of the condition codes,
3508 the jump should always come first. */
3509 if (GET_CODE (body
) == PARALLEL
&& XVECLEN (body
, 0) > 0)
3510 body
= XVECEXP (body
, 0, 0);
3513 || (GET_CODE (body
) == SET
&& GET_CODE (SET_DEST (body
)) == PC
3514 && GET_CODE (SET_SRC (body
)) == IF_THEN_ELSE
))
3516 int insns_skipped
= 0, fail
= FALSE
, succeed
= FALSE
;
3517 /* Flag which part of the IF_THEN_ELSE is the LABEL_REF. */
3518 int then_not_else
= TRUE
;
3519 /* Nonzero if next insn must be the target label. */
3520 int next_must_be_target_label_p
;
3521 rtx this_insn
= start_insn
, label
= 0;
3523 /* Register the insn jumped to. */
3526 if (!seeking_return
)
3527 label
= XEXP (SET_SRC (body
), 0);
3529 else if (GET_CODE (XEXP (SET_SRC (body
), 1)) == LABEL_REF
)
3530 label
= XEXP (XEXP (SET_SRC (body
), 1), 0);
3531 else if (GET_CODE (XEXP (SET_SRC (body
), 2)) == LABEL_REF
)
3533 label
= XEXP (XEXP (SET_SRC (body
), 2), 0);
3534 then_not_else
= FALSE
;
3536 else if (GET_CODE (XEXP (SET_SRC (body
), 1)) == SIMPLE_RETURN
)
3538 else if (GET_CODE (XEXP (SET_SRC (body
), 2)) == SIMPLE_RETURN
)
3541 then_not_else
= FALSE
;
3546 /* If this is a non-annulled branch with a delay slot, there is
3547 no need to conditionalize the delay slot. */
3548 if (NEXT_INSN (PREV_INSN (insn
)) != insn
3549 && state
->state
== 0 && !INSN_ANNULLED_BRANCH_P (insn
))
3551 this_insn
= NEXT_INSN (this_insn
);
3552 gcc_assert (NEXT_INSN (NEXT_INSN (PREV_INSN (start_insn
)))
3553 == NEXT_INSN (this_insn
));
3555 /* See how many insns this branch skips, and what kind of insns. If all
3556 insns are okay, and the label or unconditional branch to the same
3557 label is not too far away, succeed. */
3558 for (insns_skipped
= 0, next_must_be_target_label_p
= FALSE
;
3559 !fail
&& !succeed
&& insns_skipped
< MAX_INSNS_SKIPPED
;
3564 this_insn
= next_nonnote_insn (this_insn
);
3568 if (next_must_be_target_label_p
)
3570 if (GET_CODE (this_insn
) == BARRIER
)
3572 if (GET_CODE (this_insn
) == CODE_LABEL
3573 && this_insn
== label
)
3583 scanbody
= PATTERN (this_insn
);
3585 switch (GET_CODE (this_insn
))
3588 /* Succeed if it is the target label, otherwise fail since
3589 control falls in from somewhere else. */
3590 if (this_insn
== label
)
3600 /* Succeed if the following insn is the target label.
3602 If return insns are used then the last insn in a function
3603 will be a barrier. */
3604 next_must_be_target_label_p
= TRUE
;
3608 /* Can handle a call insn if there are no insns after it.
3609 IE: The next "insn" is the target label. We don't have to
3610 worry about delay slots as such insns are SEQUENCE's inside
3611 INSN's. ??? It is possible to handle such insns though. */
3612 if (get_attr_cond (this_insn
) == COND_CANUSE
)
3613 next_must_be_target_label_p
= TRUE
;
3619 /* If this is an unconditional branch to the same label, succeed.
3620 If it is to another label, do nothing. If it is conditional,
3622 /* ??? Probably, the test for the SET and the PC are
3625 if (GET_CODE (scanbody
) == SET
3626 && GET_CODE (SET_DEST (scanbody
)) == PC
)
3628 if (GET_CODE (SET_SRC (scanbody
)) == LABEL_REF
3629 && XEXP (SET_SRC (scanbody
), 0) == label
&& !reverse
)
3634 else if (GET_CODE (SET_SRC (scanbody
)) == IF_THEN_ELSE
)
3636 else if (get_attr_cond (this_insn
) != COND_CANUSE
)
3639 else if (GET_CODE (scanbody
) == SIMPLE_RETURN
3645 else if (GET_CODE (scanbody
) == PARALLEL
)
3647 if (get_attr_cond (this_insn
) != COND_CANUSE
)
3653 /* We can only do this with insns that can use the condition
3654 codes (and don't set them). */
3655 if (GET_CODE (scanbody
) == SET
3656 || GET_CODE (scanbody
) == PARALLEL
)
3658 if (get_attr_cond (this_insn
) != COND_CANUSE
)
3661 /* We can't handle other insns like sequences. */
3673 if ((!seeking_return
) && (state
->state
== 1 || reverse
))
3674 state
->target_label
= CODE_LABEL_NUMBER (label
);
3675 else if (seeking_return
|| state
->state
== 2)
3677 while (this_insn
&& GET_CODE (PATTERN (this_insn
)) == USE
)
3679 this_insn
= next_nonnote_insn (this_insn
);
3681 gcc_assert (!this_insn
||
3682 (GET_CODE (this_insn
) != BARRIER
3683 && GET_CODE (this_insn
) != CODE_LABEL
));
3687 /* Oh dear! we ran off the end, give up. */
3688 extract_insn_cached (insn
);
3690 state
->target_insn
= NULL
;
3693 state
->target_insn
= this_insn
;
3698 /* If REVERSE is true, ARM_CURRENT_CC needs to be inverted from
3702 state
->cond
= XEXP (SET_SRC (body
), 0);
3703 state
->cc
= get_arc_condition_code (XEXP (SET_SRC (body
), 0));
3706 if (reverse
|| then_not_else
)
3707 state
->cc
= ARC_INVERSE_CONDITION_CODE (state
->cc
);
3710 /* Restore recog_operand. Getting the attributes of other insns can
3711 destroy this array, but final.c assumes that it remains intact
3712 across this call; since the insn has been recognized already we
3713 call insn_extract direct. */
3714 extract_insn_cached (insn
);
3718 /* Record that we are currently outputting label NUM with prefix PREFIX.
3719 It it's the label we're looking for, reset the ccfsm machinery.
3721 Called from ASM_OUTPUT_INTERNAL_LABEL. */
3724 arc_ccfsm_at_label (const char *prefix
, int num
, struct arc_ccfsm
*state
)
3726 if (state
->state
== 3 && state
->target_label
== num
3727 && !strcmp (prefix
, "L"))
3730 state
->target_insn
= NULL_RTX
;
3734 /* We are considering a conditional branch with the condition COND.
3735 Check if we want to conditionalize a delay slot insn, and if so modify
3736 the ccfsm state accordingly.
3737 REVERSE says branch will branch when the condition is false. */
3739 arc_ccfsm_record_condition (rtx cond
, bool reverse
, rtx jump
,
3740 struct arc_ccfsm
*state
)
3742 rtx seq_insn
= NEXT_INSN (PREV_INSN (jump
));
3744 state
= &arc_ccfsm_current
;
3746 gcc_assert (state
->state
== 0);
3747 if (seq_insn
!= jump
)
3749 rtx insn
= XVECEXP (PATTERN (seq_insn
), 0, 1);
3751 if (!INSN_DELETED_P (insn
)
3752 && INSN_ANNULLED_BRANCH_P (jump
)
3753 && (TARGET_AT_DBR_CONDEXEC
|| INSN_FROM_TARGET_P (insn
)))
3756 state
->cc
= get_arc_condition_code (cond
);
3758 arc_ccfsm_current
.cc
3759 = ARC_INVERSE_CONDITION_CODE (state
->cc
);
3760 rtx pat
= PATTERN (insn
);
3761 if (GET_CODE (pat
) == COND_EXEC
)
3762 gcc_assert ((INSN_FROM_TARGET_P (insn
)
3763 ? ARC_INVERSE_CONDITION_CODE (state
->cc
) : state
->cc
)
3764 == get_arc_condition_code (XEXP (pat
, 0)));
3771 /* Update *STATE as we would when we emit INSN. */
3774 arc_ccfsm_post_advance (rtx insn
, struct arc_ccfsm
*state
)
3776 enum attr_type type
;
3779 arc_ccfsm_at_label ("L", CODE_LABEL_NUMBER (insn
), state
);
3780 else if (JUMP_P (insn
)
3781 && GET_CODE (PATTERN (insn
)) != ADDR_VEC
3782 && GET_CODE (PATTERN (insn
)) != ADDR_DIFF_VEC
3783 && ((type
= get_attr_type (insn
)) == TYPE_BRANCH
3784 || (type
== TYPE_UNCOND_BRANCH
3785 /* ??? Maybe should also handle TYPE_RETURN here,
3786 but we don't have a testcase for that. */
3787 && ARC_CCFSM_BRANCH_DELETED_P (state
))))
3789 if (ARC_CCFSM_BRANCH_DELETED_P (state
))
3790 ARC_CCFSM_RECORD_BRANCH_DELETED (state
);
3793 rtx src
= SET_SRC (PATTERN (insn
));
3794 arc_ccfsm_record_condition (XEXP (src
, 0), XEXP (src
, 1) == pc_rtx
,
3798 else if (arc_ccfsm_current
.state
== 5)
3799 arc_ccfsm_current
.state
= 0;
3802 /* Return true if the current insn, which is a conditional branch, is to be
3806 arc_ccfsm_branch_deleted_p (void)
3808 return ARC_CCFSM_BRANCH_DELETED_P (&arc_ccfsm_current
);
3811 /* Record a branch isn't output because subsequent insns can be
3815 arc_ccfsm_record_branch_deleted (void)
3817 ARC_CCFSM_RECORD_BRANCH_DELETED (&arc_ccfsm_current
);
3820 /* During insn output, indicate if the current insn is predicated. */
3823 arc_ccfsm_cond_exec_p (void)
3825 return (cfun
->machine
->prescan_initialized
3826 && ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current
));
3829 /* Like next_active_insn, but return NULL if we find an ADDR_(DIFF_)VEC,
3830 and look inside SEQUENCEs. */
3833 arc_next_active_insn (rtx insn
, struct arc_ccfsm
*statep
)
3840 arc_ccfsm_post_advance (insn
, statep
);
3841 insn
= NEXT_INSN (insn
);
3842 if (!insn
|| BARRIER_P (insn
))
3845 arc_ccfsm_advance (insn
, statep
);
3847 while (NOTE_P (insn
)
3848 || (cfun
->machine
->arc_reorg_started
3849 && LABEL_P (insn
) && !label_to_alignment (insn
))
3850 || (NONJUMP_INSN_P (insn
)
3851 && (GET_CODE (PATTERN (insn
)) == USE
3852 || GET_CODE (PATTERN (insn
)) == CLOBBER
)));
3853 if (!LABEL_P (insn
))
3855 gcc_assert (INSN_P (insn
));
3856 pat
= PATTERN (insn
);
3857 if (GET_CODE (pat
) == ADDR_VEC
|| GET_CODE (pat
) == ADDR_DIFF_VEC
)
3859 if (GET_CODE (pat
) == SEQUENCE
)
3860 return XVECEXP (pat
, 0, 0);
3865 /* When deciding if an insn should be output short, we want to know something
3866 about the following insns:
3867 - if another insn follows which we know we can output as a short insn
3868 before an alignment-sensitive point, we can output this insn short:
3869 the decision about the eventual alignment can be postponed.
3870 - if a to-be-aligned label comes next, we should output this insn such
3871 as to get / preserve 4-byte alignment.
3872 - if a likely branch without delay slot insn, or a call with an immediately
3873 following short insn comes next, we should out output this insn such as to
3874 get / preserve 2 mod 4 unalignment.
3875 - do the same for a not completely unlikely branch with a short insn
3876 following before any other branch / label.
3877 - in order to decide if we are actually looking at a branch, we need to
3878 call arc_ccfsm_advance.
3879 - in order to decide if we are looking at a short insn, we should know
3880 if it is conditionalized. To a first order of approximation this is
3881 the case if the state from arc_ccfsm_advance from before this insn
3882 indicates the insn is conditionalized. However, a further refinement
3883 could be to not conditionalize an insn if the destination register(s)
3884 is/are dead in the non-executed case. */
3885 /* Return non-zero if INSN should be output as a short insn. UNALIGN is
3886 zero if the current insn is aligned to a 4-byte-boundary, two otherwise.
3887 If CHECK_ATTR is greater than 0, check the iscompact attribute first. */
3890 arc_verify_short (rtx insn
, int, int check_attr
)
3892 enum attr_iscompact iscompact
;
3893 struct machine_function
*machine
;
3897 iscompact
= get_attr_iscompact (insn
);
3898 if (iscompact
== ISCOMPACT_FALSE
)
3901 machine
= cfun
->machine
;
3903 if (machine
->force_short_suffix
>= 0)
3904 return machine
->force_short_suffix
;
3906 return (get_attr_length (insn
) & 2) != 0;
3909 /* When outputting an instruction (alternative) that can potentially be short,
3910 output the short suffix if the insn is in fact short, and update
3911 cfun->machine->unalign accordingly. */
3914 output_short_suffix (FILE *file
)
3916 rtx insn
= current_output_insn
;
3918 if (arc_verify_short (insn
, cfun
->machine
->unalign
, 1))
3920 fprintf (file
, "_s");
3921 cfun
->machine
->unalign
^= 2;
3923 /* Restore recog_operand. */
3924 extract_insn_cached (insn
);
3927 /* Implement FINAL_PRESCAN_INSN. */
3930 arc_final_prescan_insn (rtx insn
, rtx
*opvec ATTRIBUTE_UNUSED
,
3931 int noperands ATTRIBUTE_UNUSED
)
3933 if (TARGET_DUMPISIZE
)
3934 fprintf (asm_out_file
, "\n; at %04x\n", INSN_ADDRESSES (INSN_UID (insn
)));
3936 /* Output a nop if necessary to prevent a hazard.
3937 Don't do this for delay slots: inserting a nop would
3938 alter semantics, and the only time we would find a hazard is for a
3939 call function result - and in that case, the hazard is spurious to
3941 if (PREV_INSN (insn
)
3942 && PREV_INSN (NEXT_INSN (insn
)) == insn
3943 && arc_hazard (prev_real_insn (insn
), insn
))
3945 current_output_insn
=
3946 emit_insn_before (gen_nop (), NEXT_INSN (PREV_INSN (insn
)));
3947 final_scan_insn (current_output_insn
, asm_out_file
, optimize
, 1, NULL
);
3948 current_output_insn
= insn
;
3950 /* Restore extraction data which might have been clobbered by arc_hazard. */
3951 extract_constrain_insn_cached (insn
);
3953 if (!cfun
->machine
->prescan_initialized
)
3955 /* Clear lingering state from branch shortening. */
3956 memset (&arc_ccfsm_current
, 0, sizeof arc_ccfsm_current
);
3957 cfun
->machine
->prescan_initialized
= 1;
3959 arc_ccfsm_advance (insn
, &arc_ccfsm_current
);
3961 cfun
->machine
->size_reason
= 0;
3964 /* Given FROM and TO register numbers, say whether this elimination is allowed.
3965 Frame pointer elimination is automatically handled.
3967 All eliminations are permissible. If we need a frame
3968 pointer, we must eliminate ARG_POINTER_REGNUM into
3969 FRAME_POINTER_REGNUM and not into STACK_POINTER_REGNUM. */
3972 arc_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to
)
3974 return to
== FRAME_POINTER_REGNUM
|| !arc_frame_pointer_required ();
3977 /* Define the offset between two registers, one to be eliminated, and
3978 the other its replacement, at the start of a routine. */
3981 arc_initial_elimination_offset (int from
, int to
)
3983 if (! cfun
->machine
->frame_info
.initialized
)
3984 arc_compute_frame_size (get_frame_size ());
3986 if (from
== ARG_POINTER_REGNUM
&& to
== FRAME_POINTER_REGNUM
)
3988 return (cfun
->machine
->frame_info
.extra_size
3989 + cfun
->machine
->frame_info
.reg_size
);
3992 if (from
== ARG_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
3994 return (cfun
->machine
->frame_info
.total_size
3995 - cfun
->machine
->frame_info
.pretend_size
);
3998 if ((from
== FRAME_POINTER_REGNUM
) && (to
== STACK_POINTER_REGNUM
))
4000 return (cfun
->machine
->frame_info
.total_size
4001 - (cfun
->machine
->frame_info
.pretend_size
4002 + cfun
->machine
->frame_info
.extra_size
4003 + cfun
->machine
->frame_info
.reg_size
));
4010 arc_frame_pointer_required (void)
4012 return cfun
->calls_alloca
;
4016 /* Return the destination address of a branch. */
4019 branch_dest (rtx branch
)
4021 rtx pat
= PATTERN (branch
);
4022 rtx dest
= (GET_CODE (pat
) == PARALLEL
4023 ? SET_SRC (XVECEXP (pat
, 0, 0)) : SET_SRC (pat
));
4026 if (GET_CODE (dest
) == IF_THEN_ELSE
)
4027 dest
= XEXP (dest
, XEXP (dest
, 1) == pc_rtx
? 2 : 1);
4029 dest
= XEXP (dest
, 0);
4030 dest_uid
= INSN_UID (dest
);
4032 return INSN_ADDRESSES (dest_uid
);
4036 /* Implement TARGET_ENCODE_SECTION_INFO hook. */
4039 arc_encode_section_info (tree decl
, rtx rtl
, int first
)
4041 /* For sdata, SYMBOL_FLAG_LOCAL and SYMBOL_FLAG_FUNCTION.
4042 This clears machine specific flags, so has to come first. */
4043 default_encode_section_info (decl
, rtl
, first
);
4045 /* Check if it is a function, and whether it has the
4046 [long/medium/short]_call attribute specified. */
4047 if (TREE_CODE (decl
) == FUNCTION_DECL
)
4049 rtx symbol
= XEXP (rtl
, 0);
4050 int flags
= SYMBOL_REF_FLAGS (symbol
);
4052 tree attr
= (TREE_TYPE (decl
) != error_mark_node
4053 ? TYPE_ATTRIBUTES (TREE_TYPE (decl
)) : NULL_TREE
);
4054 tree long_call_attr
= lookup_attribute ("long_call", attr
);
4055 tree medium_call_attr
= lookup_attribute ("medium_call", attr
);
4056 tree short_call_attr
= lookup_attribute ("short_call", attr
);
4058 if (long_call_attr
!= NULL_TREE
)
4059 flags
|= SYMBOL_FLAG_LONG_CALL
;
4060 else if (medium_call_attr
!= NULL_TREE
)
4061 flags
|= SYMBOL_FLAG_MEDIUM_CALL
;
4062 else if (short_call_attr
!= NULL_TREE
)
4063 flags
|= SYMBOL_FLAG_SHORT_CALL
;
4065 SYMBOL_REF_FLAGS (symbol
) = flags
;
4069 /* This is how to output a definition of an internal numbered label where
4070 PREFIX is the class of label and NUM is the number within the class. */
4072 static void arc_internal_label (FILE *stream
, const char *prefix
, unsigned long labelno
)
4075 arc_ccfsm_at_label (prefix
, labelno
, &arc_ccfsm_current
);
4076 default_internal_label (stream
, prefix
, labelno
);
4079 /* Set the cpu type and print out other fancy things,
4080 at the top of the file. */
4082 static void arc_file_start (void)
4084 default_file_start ();
4085 fprintf (asm_out_file
, "\t.cpu %s\n", arc_cpu_string
);
4088 /* Cost functions. */
4090 /* Compute a (partial) cost for rtx X. Return true if the complete
4091 cost has been computed, and false if subexpressions should be
4092 scanned. In either case, *TOTAL contains the cost result. */
4095 arc_rtx_costs (rtx x
, int code
, int outer_code
, int opno ATTRIBUTE_UNUSED
,
4096 int *total
, bool speed
)
4100 /* Small integers are as cheap as registers. */
4103 bool nolimm
= false; /* Can we do without long immediate? */
4104 bool fast
= false; /* Is the result available immediately? */
4105 bool condexec
= false; /* Does this allow conditiobnal execution? */
4106 bool compact
= false; /* Is a 16 bit opcode available? */
4107 /* CONDEXEC also implies that we can have an unconditional
4108 3-address operation. */
4110 nolimm
= compact
= condexec
= false;
4111 if (UNSIGNED_INT6 (INTVAL (x
)))
4112 nolimm
= condexec
= compact
= true;
4115 if (SMALL_INT (INTVAL (x
)))
4116 nolimm
= fast
= true;
4119 case AND
: /* bclr, bmsk, ext[bw] */
4120 if (satisfies_constraint_Ccp (x
) /* bclr */
4121 || satisfies_constraint_C1p (x
) /* bmsk */)
4122 nolimm
= fast
= condexec
= compact
= true;
4124 case IOR
: /* bset */
4125 if (satisfies_constraint_C0p (x
)) /* bset */
4126 nolimm
= fast
= condexec
= compact
= true;
4129 if (satisfies_constraint_C0p (x
)) /* bxor */
4130 nolimm
= fast
= condexec
= true;
4133 if (satisfies_constraint_Crr (x
)) /* ror b,u6 */
4139 /* FIXME: Add target options to attach a small cost if
4140 condexec / compact is not true. */
4149 /* 4 byte values can be fetched as immediate constants -
4150 let's give that the cost of an extra insn. */
4154 *total
= COSTS_N_INSNS (1);
4163 *total
= COSTS_N_INSNS (1);
4166 /* FIXME: correct the order of high,low */
4167 split_double (x
, &high
, &low
);
4168 *total
= COSTS_N_INSNS (!SMALL_INT (INTVAL (high
))
4169 + !SMALL_INT (INTVAL (low
)));
4173 /* Encourage synth_mult to find a synthetic multiply when reasonable.
4174 If we need more than 12 insns to do a multiply, then go out-of-line,
4175 since the call overhead will be < 10% of the cost of the multiply. */
4179 if (TARGET_BARREL_SHIFTER
)
4181 /* If we want to shift a constant, we need a LIMM. */
4182 /* ??? when the optimizers want to know if a constant should be
4183 hoisted, they ask for the cost of the constant. OUTER_CODE is
4184 insufficient context for shifts since we don't know which operand
4185 we are looking at. */
4186 if (CONSTANT_P (XEXP (x
, 0)))
4188 *total
+= (COSTS_N_INSNS (2)
4189 + rtx_cost (XEXP (x
, 1), (enum rtx_code
) code
, 0, speed
));
4192 *total
= COSTS_N_INSNS (1);
4194 else if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
4195 *total
= COSTS_N_INSNS (16);
4198 *total
= COSTS_N_INSNS (INTVAL (XEXP ((x
), 1)));
4199 /* ??? want_to_gcse_p can throw negative shift counts at us,
4200 and then panics when it gets a negative cost as result.
4201 Seen for gcc.c-torture/compile/20020710-1.c -Os . */
4210 *total
= COSTS_N_INSNS(30);
4212 *total
= COSTS_N_INSNS(1);
4216 if ((TARGET_DPFP
&& GET_MODE (x
) == DFmode
))
4217 *total
= COSTS_N_INSNS (1);
4219 *total
= arc_multcost
;
4220 /* We do not want synth_mult sequences when optimizing
4222 else if (TARGET_MUL64_SET
|| (TARGET_ARC700
&& !TARGET_NOMPY_SET
))
4223 *total
= COSTS_N_INSNS (1);
4225 *total
= COSTS_N_INSNS (2);
4228 if (GET_CODE (XEXP (x
, 0)) == MULT
4229 && _2_4_8_operand (XEXP (XEXP (x
, 0), 1), VOIDmode
))
4231 *total
+= (rtx_cost (XEXP (x
, 1), PLUS
, 0, speed
)
4232 + rtx_cost (XEXP (XEXP (x
, 0), 0), PLUS
, 1, speed
));
4237 if (GET_CODE (XEXP (x
, 1)) == MULT
4238 && _2_4_8_operand (XEXP (XEXP (x
, 1), 1), VOIDmode
))
4240 *total
+= (rtx_cost (XEXP (x
, 0), PLUS
, 0, speed
)
4241 + rtx_cost (XEXP (XEXP (x
, 1), 0), PLUS
, 1, speed
));
4247 rtx op0
= XEXP (x
, 0);
4248 rtx op1
= XEXP (x
, 1);
4250 if (GET_CODE (op0
) == ZERO_EXTRACT
&& op1
== const0_rtx
4251 && XEXP (op0
, 1) == const1_rtx
)
4253 /* btst / bbit0 / bbit1:
4254 Small integers and registers are free; everything else can
4255 be put in a register. */
4256 *total
= (rtx_cost (XEXP (op0
, 0), SET
, 1, speed
)
4257 + rtx_cost (XEXP (op0
, 2), SET
, 1, speed
));
4260 if (GET_CODE (op0
) == AND
&& op1
== const0_rtx
4261 && satisfies_constraint_C1p (XEXP (op0
, 1)))
4264 *total
= rtx_cost (XEXP (op0
, 0), SET
, 1, speed
);
4268 if (GET_CODE (op1
) == NEG
)
4270 /* op0 might be constant, the inside of op1 is rather
4271 unlikely to be so. So swapping the operands might lower
4273 *total
= (rtx_cost (op0
, PLUS
, 1, speed
)
4274 + rtx_cost (XEXP (op1
, 0), PLUS
, 0, speed
));
4279 if (outer_code
== IF_THEN_ELSE
4280 && GET_CODE (XEXP (x
, 0)) == ZERO_EXTRACT
4281 && XEXP (x
, 1) == const0_rtx
4282 && XEXP (XEXP (x
, 0), 1) == const1_rtx
)
4284 /* btst / bbit0 / bbit1:
4285 Small integers and registers are free; everything else can
4286 be put in a register. */
4287 rtx op0
= XEXP (x
, 0);
4289 *total
= (rtx_cost (XEXP (op0
, 0), SET
, 1, speed
)
4290 + rtx_cost (XEXP (op0
, 2), SET
, 1, speed
));
4294 /* scc_insn expands into two insns. */
4295 case GTU
: case GEU
: case LEU
:
4296 if (GET_MODE (x
) == SImode
)
4297 *total
+= COSTS_N_INSNS (1);
4299 case LTU
: /* might use adc. */
4300 if (GET_MODE (x
) == SImode
)
4301 *total
+= COSTS_N_INSNS (1) - 1;
4308 /* Return true if ADDR is an address that needs to be expressed as an
4309 explicit sum of pcl + offset. */
4312 arc_legitimate_pc_offset_p (rtx addr
)
4314 if (GET_CODE (addr
) != CONST
)
4316 addr
= XEXP (addr
, 0);
4317 if (GET_CODE (addr
) == PLUS
)
4319 if (GET_CODE (XEXP (addr
, 1)) != CONST_INT
)
4321 addr
= XEXP (addr
, 0);
4323 return (GET_CODE (addr
) == UNSPEC
4324 && XVECLEN (addr
, 0) == 1
4325 && XINT (addr
, 1) == ARC_UNSPEC_GOT
4326 && GET_CODE (XVECEXP (addr
, 0, 0)) == SYMBOL_REF
);
4329 /* Return true if ADDR is a valid pic address.
4330 A valid pic address on arc should look like
4331 const (unspec (SYMBOL_REF/LABEL) (ARC_UNSPEC_GOTOFF/ARC_UNSPEC_GOT)) */
4334 arc_legitimate_pic_addr_p (rtx addr
)
4336 if (GET_CODE (addr
) == LABEL_REF
)
4338 if (GET_CODE (addr
) != CONST
)
4341 addr
= XEXP (addr
, 0);
4344 if (GET_CODE (addr
) == PLUS
)
4346 if (GET_CODE (XEXP (addr
, 1)) != CONST_INT
)
4348 addr
= XEXP (addr
, 0);
4351 if (GET_CODE (addr
) != UNSPEC
4352 || XVECLEN (addr
, 0) != 1)
4355 /* Must be @GOT or @GOTOFF. */
4356 if (XINT (addr
, 1) != ARC_UNSPEC_GOT
4357 && XINT (addr
, 1) != ARC_UNSPEC_GOTOFF
)
4360 if (GET_CODE (XVECEXP (addr
, 0, 0)) != SYMBOL_REF
4361 && GET_CODE (XVECEXP (addr
, 0, 0)) != LABEL_REF
)
4369 /* Return true if OP contains a symbol reference. */
4372 symbolic_reference_mentioned_p (rtx op
)
4374 register const char *fmt
;
4377 if (GET_CODE (op
) == SYMBOL_REF
|| GET_CODE (op
) == LABEL_REF
)
4380 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
4381 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
4387 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
4388 if (symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
)))
4392 else if (fmt
[i
] == 'e' && symbolic_reference_mentioned_p (XEXP (op
, i
)))
4399 /* Return true if OP contains a SYMBOL_REF that is not wrapped in an unspec.
4400 If SKIP_LOCAL is true, skip symbols that bind locally.
4401 This is used further down in this file, and, without SKIP_LOCAL,
4402 in the addsi3 / subsi3 expanders when generating PIC code. */
4405 arc_raw_symbolic_reference_mentioned_p (rtx op
, bool skip_local
)
4407 register const char *fmt
;
4410 if (GET_CODE(op
) == UNSPEC
)
4413 if (GET_CODE (op
) == SYMBOL_REF
)
4415 tree decl
= SYMBOL_REF_DECL (op
);
4416 return !skip_local
|| !decl
|| !default_binds_local_p (decl
);
4419 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
4420 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
4426 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
4427 if (arc_raw_symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
),
4432 else if (fmt
[i
] == 'e'
4433 && arc_raw_symbolic_reference_mentioned_p (XEXP (op
, i
),
4441 /* Legitimize a pic address reference in ORIG.
4442 The return value is the legitimated address.
4443 If OLDX is non-zero, it is the target to assign the address to first. */
4446 arc_legitimize_pic_address (rtx orig
, rtx oldx
)
4455 if (GET_CODE (addr
) == LABEL_REF
)
4457 else if (GET_CODE (addr
) == SYMBOL_REF
4458 && (CONSTANT_POOL_ADDRESS_P (addr
)
4459 || SYMBOL_REF_LOCAL_P (addr
)))
4461 /* This symbol may be referenced via a displacement from the PIC
4462 base address (@GOTOFF). */
4464 /* FIXME: if we had a way to emit pc-relative adds that don't
4465 create a GOT entry, we could do without the use of the gp register. */
4466 crtl
->uses_pic_offset_table
= 1;
4467 pat
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, addr
), ARC_UNSPEC_GOTOFF
);
4468 pat
= gen_rtx_CONST (Pmode
, pat
);
4469 pat
= gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, pat
);
4472 oldx
= gen_reg_rtx (Pmode
);
4476 emit_move_insn (oldx
, pat
);
4481 else if (GET_CODE (addr
) == SYMBOL_REF
)
4483 /* This symbol must be referenced via a load from the
4484 Global Offset Table (@GOTPC). */
4486 pat
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, addr
), ARC_UNSPEC_GOT
);
4487 pat
= gen_rtx_CONST (Pmode
, pat
);
4488 pat
= gen_const_mem (Pmode
, pat
);
4491 oldx
= gen_reg_rtx (Pmode
);
4493 emit_move_insn (oldx
, pat
);
4498 if (GET_CODE (addr
) == CONST
)
4500 addr
= XEXP (addr
, 0);
4501 if (GET_CODE (addr
) == UNSPEC
)
4503 /* Check that the unspec is one of the ones we generate? */
4506 gcc_assert (GET_CODE (addr
) == PLUS
);
4509 if (GET_CODE (addr
) == PLUS
)
4511 rtx op0
= XEXP (addr
, 0), op1
= XEXP (addr
, 1);
4513 /* Check first to see if this is a constant offset from a @GOTOFF
4514 symbol reference. */
4515 if ((GET_CODE (op0
) == LABEL_REF
4516 || (GET_CODE (op0
) == SYMBOL_REF
4517 && (CONSTANT_POOL_ADDRESS_P (op0
)
4518 || SYMBOL_REF_LOCAL_P (op0
))))
4519 && GET_CODE (op1
) == CONST_INT
)
4521 /* FIXME: like above, could do without gp reference. */
4522 crtl
->uses_pic_offset_table
= 1;
4524 = gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, op0
), ARC_UNSPEC_GOTOFF
);
4525 pat
= gen_rtx_PLUS (Pmode
, pat
, op1
);
4526 pat
= gen_rtx_CONST (Pmode
, pat
);
4527 pat
= gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, pat
);
4531 emit_move_insn (oldx
, pat
);
4537 base
= arc_legitimize_pic_address (XEXP (addr
, 0), oldx
);
4538 pat
= arc_legitimize_pic_address (XEXP (addr
, 1),
4539 base
== oldx
? NULL_RTX
: oldx
);
4541 if (GET_CODE (pat
) == CONST_INT
)
4542 pat
= plus_constant (Pmode
, base
, INTVAL (pat
));
4545 if (GET_CODE (pat
) == PLUS
&& CONSTANT_P (XEXP (pat
, 1)))
4547 base
= gen_rtx_PLUS (Pmode
, base
, XEXP (pat
, 0));
4548 pat
= XEXP (pat
, 1);
4550 pat
= gen_rtx_PLUS (Pmode
, base
, pat
);
4559 /* Output address constant X to FILE, taking PIC into account. */
4562 arc_output_pic_addr_const (FILE * file
, rtx x
, int code
)
4567 switch (GET_CODE (x
))
4577 output_addr_const (file
, x
);
4579 /* Local functions do not get references through the PLT. */
4580 if (code
== 'P' && ! SYMBOL_REF_LOCAL_P (x
))
4581 fputs ("@plt", file
);
4585 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (XEXP (x
, 0)));
4586 assemble_name (file
, buf
);
4590 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (x
));
4591 assemble_name (file
, buf
);
4595 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
));
4599 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4603 if (GET_MODE (x
) == VOIDmode
)
4605 /* We can use %d if the number is one word and positive. */
4606 if (CONST_DOUBLE_HIGH (x
))
4607 fprintf (file
, HOST_WIDE_INT_PRINT_DOUBLE_HEX
,
4608 CONST_DOUBLE_HIGH (x
), CONST_DOUBLE_LOW (x
));
4609 else if (CONST_DOUBLE_LOW (x
) < 0)
4610 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, CONST_DOUBLE_LOW (x
));
4612 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, CONST_DOUBLE_LOW (x
));
4615 /* We can't handle floating point constants;
4616 PRINT_OPERAND must handle them. */
4617 output_operand_lossage ("floating constant misused");
4621 /* FIXME: Not needed here. */
4622 /* Some assemblers need integer constants to appear last (eg masm). */
4623 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
4625 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4626 fprintf (file
, "+");
4627 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4629 else if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
4631 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4632 if (INTVAL (XEXP (x
, 1)) >= 0)
4633 fprintf (file
, "+");
4634 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4641 /* Avoid outputting things like x-x or x+5-x,
4642 since some assemblers can't handle that. */
4643 x
= simplify_subtraction (x
);
4644 if (GET_CODE (x
) != MINUS
)
4647 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4648 fprintf (file
, "-");
4649 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
4650 && INTVAL (XEXP (x
, 1)) < 0)
4652 fprintf (file
, "(");
4653 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4654 fprintf (file
, ")");
4657 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4662 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4667 gcc_assert (XVECLEN (x
, 0) == 1);
4668 if (XINT (x
, 1) == ARC_UNSPEC_GOT
)
4669 fputs ("pcl,", file
);
4670 arc_output_pic_addr_const (file
, XVECEXP (x
, 0, 0), code
);
4671 switch (XINT (x
, 1))
4673 case ARC_UNSPEC_GOT
:
4674 fputs ("@gotpc", file
);
4676 case ARC_UNSPEC_GOTOFF
:
4677 fputs ("@gotoff", file
);
4679 case ARC_UNSPEC_PLT
:
4680 fputs ("@plt", file
);
4683 output_operand_lossage ("invalid UNSPEC as operand: %d", XINT (x
,1));
4689 output_operand_lossage ("invalid expression as operand");
4693 #define SYMBOLIC_CONST(X) \
4694 (GET_CODE (X) == SYMBOL_REF \
4695 || GET_CODE (X) == LABEL_REF \
4696 || (GET_CODE (X) == CONST && symbolic_reference_mentioned_p (X)))
4698 /* Emit insns to move operands[1] into operands[0]. */
4701 emit_pic_move (rtx
*operands
, enum machine_mode
)
4703 rtx temp
= reload_in_progress
? operands
[0] : gen_reg_rtx (Pmode
);
4705 if (GET_CODE (operands
[0]) == MEM
&& SYMBOLIC_CONST (operands
[1]))
4706 operands
[1] = force_reg (Pmode
, operands
[1]);
4708 operands
[1] = arc_legitimize_pic_address (operands
[1], temp
);
4712 /* The function returning the number of words, at the beginning of an
4713 argument, must be put in registers. The returned value must be
4714 zero for arguments that are passed entirely in registers or that
4715 are entirely pushed on the stack.
4717 On some machines, certain arguments must be passed partially in
4718 registers and partially in memory. On these machines, typically
4719 the first N words of arguments are passed in registers, and the
4720 rest on the stack. If a multi-word argument (a `double' or a
4721 structure) crosses that boundary, its first few words must be
4722 passed in registers and the rest must be pushed. This function
4723 tells the compiler when this occurs, and how many of the words
4724 should go in registers.
4726 `FUNCTION_ARG' for these arguments should return the first register
4727 to be used by the caller for this argument; likewise
4728 `FUNCTION_INCOMING_ARG', for the called function.
4730 The function is used to implement macro FUNCTION_ARG_PARTIAL_NREGS. */
4732 /* If REGNO is the least arg reg available then what is the total number of arg
4734 #define GPR_REST_ARG_REGS(REGNO) \
4735 ((REGNO) <= MAX_ARC_PARM_REGS ? MAX_ARC_PARM_REGS - (REGNO) : 0 )
4737 /* Since arc parm regs are contiguous. */
4738 #define ARC_NEXT_ARG_REG(REGNO) ( (REGNO) + 1 )
4740 /* Implement TARGET_ARG_PARTIAL_BYTES. */
4743 arc_arg_partial_bytes (cumulative_args_t cum_v
, enum machine_mode mode
,
4744 tree type
, bool named ATTRIBUTE_UNUSED
)
4746 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
4747 int bytes
= (mode
== BLKmode
4748 ? int_size_in_bytes (type
) : (int) GET_MODE_SIZE (mode
));
4749 int words
= (bytes
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
4753 arg_num
= ROUND_ADVANCE_CUM (arg_num
, mode
, type
);
4754 ret
= GPR_REST_ARG_REGS (arg_num
);
4756 /* ICEd at function.c:2361, and ret is copied to data->partial */
4757 ret
= (ret
>= words
? 0 : ret
* UNITS_PER_WORD
);
4764 /* This function is used to control a function argument is passed in a
4765 register, and which register.
4767 The arguments are CUM, of type CUMULATIVE_ARGS, which summarizes
4768 (in a way defined by INIT_CUMULATIVE_ARGS and FUNCTION_ARG_ADVANCE)
4769 all of the previous arguments so far passed in registers; MODE, the
4770 machine mode of the argument; TYPE, the data type of the argument
4771 as a tree node or 0 if that is not known (which happens for C
4772 support library functions); and NAMED, which is 1 for an ordinary
4773 argument and 0 for nameless arguments that correspond to `...' in
4774 the called function's prototype.
4776 The returned value should either be a `reg' RTX for the hard
4777 register in which to pass the argument, or zero to pass the
4778 argument on the stack.
4780 For machines like the Vax and 68000, where normally all arguments
4781 are pushed, zero suffices as a definition.
4783 The usual way to make the ANSI library `stdarg.h' work on a machine
4784 where some arguments are usually passed in registers, is to cause
4785 nameless arguments to be passed on the stack instead. This is done
4786 by making the function return 0 whenever NAMED is 0.
4788 You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the
4789 definition of this function to determine if this argument is of a
4790 type that must be passed in the stack. If `REG_PARM_STACK_SPACE'
4791 is not defined and the function returns non-zero for such an
4792 argument, the compiler will abort. If `REG_PARM_STACK_SPACE' is
4793 defined, the argument will be computed in the stack and then loaded
4796 The function is used to implement macro FUNCTION_ARG. */
4797 /* On the ARC the first MAX_ARC_PARM_REGS args are normally in registers
4798 and the rest are pushed. */
4801 arc_function_arg (cumulative_args_t cum_v
, enum machine_mode mode
,
4802 const_tree type ATTRIBUTE_UNUSED
, bool named ATTRIBUTE_UNUSED
)
4804 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
4807 const char *debstr ATTRIBUTE_UNUSED
;
4809 arg_num
= ROUND_ADVANCE_CUM (arg_num
, mode
, type
);
4810 /* Return a marker for use in the call instruction. */
4811 if (mode
== VOIDmode
)
4816 else if (GPR_REST_ARG_REGS (arg_num
) > 0)
4818 ret
= gen_rtx_REG (mode
, arg_num
);
4819 debstr
= reg_names
[arg_num
];
4829 /* The function to update the summarizer variable *CUM to advance past
4830 an argument in the argument list. The values MODE, TYPE and NAMED
4831 describe that argument. Once this is done, the variable *CUM is
4832 suitable for analyzing the *following* argument with
4833 `FUNCTION_ARG', etc.
4835 This function need not do anything if the argument in question was
4836 passed on the stack. The compiler knows how to track the amount of
4837 stack space used for arguments without any special help.
4839 The function is used to implement macro FUNCTION_ARG_ADVANCE. */
4840 /* For the ARC: the cum set here is passed on to function_arg where we
4841 look at its value and say which reg to use. Strategy: advance the
4842 regnumber here till we run out of arg regs, then set *cum to last
4843 reg. In function_arg, since *cum > last arg reg we would return 0
4844 and thus the arg will end up on the stack. For straddling args of
4845 course function_arg_partial_nregs will come into play. */
4848 arc_function_arg_advance (cumulative_args_t cum_v
, enum machine_mode mode
,
4849 const_tree type
, bool named ATTRIBUTE_UNUSED
)
4851 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
4852 int bytes
= (mode
== BLKmode
4853 ? int_size_in_bytes (type
) : (int) GET_MODE_SIZE (mode
));
4854 int words
= (bytes
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
4858 *cum
= ROUND_ADVANCE_CUM (*cum
, mode
, type
);
4859 for (i
= 0; i
< words
; i
++)
4860 *cum
= ARC_NEXT_ARG_REG (*cum
);
4864 /* Define how to find the value returned by a function.
4865 VALTYPE is the data type of the value (as a tree).
4866 If the precise function being called is known, FN_DECL_OR_TYPE is its
4867 FUNCTION_DECL; otherwise, FN_DECL_OR_TYPE is its type. */
4870 arc_function_value (const_tree valtype
,
4871 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
4872 bool outgoing ATTRIBUTE_UNUSED
)
4874 enum machine_mode mode
= TYPE_MODE (valtype
);
4875 int unsignedp ATTRIBUTE_UNUSED
;
4877 unsignedp
= TYPE_UNSIGNED (valtype
);
4878 if (INTEGRAL_TYPE_P (valtype
) || TREE_CODE (valtype
) == OFFSET_TYPE
)
4879 PROMOTE_MODE (mode
, unsignedp
, valtype
);
4880 return gen_rtx_REG (mode
, 0);
4883 /* Returns the return address that is used by builtin_return_address. */
4886 arc_return_addr_rtx (int count
, ATTRIBUTE_UNUSED rtx frame
)
4891 return get_hard_reg_initial_val (Pmode
, RETURN_ADDR_REGNUM
);
4894 /* Nonzero if the constant value X is a legitimate general operand
4895 when generating PIC code. It is given that flag_pic is on and
4896 that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
4899 arc_legitimate_pic_operand_p (rtx x
)
4901 return !arc_raw_symbolic_reference_mentioned_p (x
, true);
4904 /* Determine if a given RTX is a valid constant. We already know this
4905 satisfies CONSTANT_P. */
4908 arc_legitimate_constant_p (enum machine_mode
, rtx x
)
4913 switch (GET_CODE (x
))
4918 if (GET_CODE (x
) == PLUS
)
4920 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
4925 /* Only some unspecs are valid as "constants". */
4926 if (GET_CODE (x
) == UNSPEC
)
4927 switch (XINT (x
, 1))
4929 case ARC_UNSPEC_PLT
:
4930 case ARC_UNSPEC_GOTOFF
:
4931 case ARC_UNSPEC_GOT
:
4939 /* We must have drilled down to a symbol. */
4940 if (arc_raw_symbolic_reference_mentioned_p (x
, false))
4954 /* Otherwise we handle everything else in the move patterns. */
4959 arc_legitimate_address_p (enum machine_mode mode
, rtx x
, bool strict
)
4961 if (RTX_OK_FOR_BASE_P (x
, strict
))
4963 if (LEGITIMATE_OFFSET_ADDRESS_P (mode
, x
, TARGET_INDEXED_LOADS
, strict
))
4965 if (LEGITIMATE_SCALED_ADDRESS_P (mode
, x
, strict
))
4967 if (LEGITIMATE_SMALL_DATA_ADDRESS_P (x
))
4969 if (GET_CODE (x
) == CONST_INT
&& LARGE_INT (INTVAL (x
)))
4971 if ((GET_MODE_SIZE (mode
) != 16)
4972 && (GET_CODE (x
) == SYMBOL_REF
4973 || GET_CODE (x
) == LABEL_REF
4974 || GET_CODE (x
) == CONST
))
4976 if (!flag_pic
|| arc_legitimate_pic_addr_p (x
))
4979 if ((GET_CODE (x
) == PRE_DEC
|| GET_CODE (x
) == PRE_INC
4980 || GET_CODE (x
) == POST_DEC
|| GET_CODE (x
) == POST_INC
)
4981 && RTX_OK_FOR_BASE_P (XEXP (x
, 0), strict
))
4983 /* We're restricted here by the `st' insn. */
4984 if ((GET_CODE (x
) == PRE_MODIFY
|| GET_CODE (x
) == POST_MODIFY
)
4985 && GET_CODE (XEXP ((x
), 1)) == PLUS
4986 && rtx_equal_p (XEXP ((x
), 0), XEXP (XEXP (x
, 1), 0))
4987 && LEGITIMATE_OFFSET_ADDRESS_P (QImode
, XEXP (x
, 1),
4988 TARGET_AUTO_MODIFY_REG
, strict
))
4993 /* Return true iff ADDR (a legitimate address expression)
4994 has an effect that depends on the machine mode it is used for. */
4997 arc_mode_dependent_address_p (const_rtx addr
, addr_space_t
)
4999 /* SYMBOL_REF is not mode dependent: it is either a small data reference,
5000 which is valid for loads and stores, or a limm offset, which is valid for
5002 /* Scaled indices are scaled by the access mode; likewise for scaled
5003 offsets, which are needed for maximum offset stores. */
5004 if (GET_CODE (addr
) == PLUS
5005 && (GET_CODE (XEXP ((addr
), 0)) == MULT
5006 || (CONST_INT_P (XEXP ((addr
), 1))
5007 && !SMALL_INT (INTVAL (XEXP ((addr
), 1))))))
5012 /* Determine if it's legal to put X into the constant pool. */
5015 arc_cannot_force_const_mem (enum machine_mode mode
, rtx x
)
5017 return !arc_legitimate_constant_p (mode
, x
);
5021 /* Generic function to define a builtin. */
5022 #define def_mbuiltin(MASK, NAME, TYPE, CODE) \
5026 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL, NULL_TREE); \
5032 arc_init_builtins (void)
5034 tree endlink
= void_list_node
;
5036 tree void_ftype_void
5037 = build_function_type (void_type_node
,
5041 = build_function_type (integer_type_node
,
5042 tree_cons (NULL_TREE
, integer_type_node
, endlink
));
5044 tree pcvoid_type_node
5045 = build_pointer_type (build_qualified_type (void_type_node
, TYPE_QUAL_CONST
));
5046 tree int_ftype_pcvoid_int
5047 = build_function_type (integer_type_node
,
5048 tree_cons (NULL_TREE
, pcvoid_type_node
,
5049 tree_cons (NULL_TREE
, integer_type_node
,
5052 tree int_ftype_short_int
5053 = build_function_type (integer_type_node
,
5054 tree_cons (NULL_TREE
, short_integer_type_node
, endlink
));
5056 tree void_ftype_int_int
5057 = build_function_type (void_type_node
,
5058 tree_cons (NULL_TREE
, integer_type_node
,
5059 tree_cons (NULL_TREE
, integer_type_node
, endlink
)));
5060 tree void_ftype_usint_usint
5061 = build_function_type (void_type_node
,
5062 tree_cons (NULL_TREE
, long_unsigned_type_node
,
5063 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
)));
5065 tree int_ftype_int_int
5066 = build_function_type (integer_type_node
,
5067 tree_cons (NULL_TREE
, integer_type_node
,
5068 tree_cons (NULL_TREE
, integer_type_node
, endlink
)));
5070 tree usint_ftype_usint
5071 = build_function_type (long_unsigned_type_node
,
5072 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
));
5074 tree void_ftype_usint
5075 = build_function_type (void_type_node
,
5076 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
));
5078 /* Add the builtins. */
5079 def_mbuiltin (1,"__builtin_arc_nop", void_ftype_void
, ARC_BUILTIN_NOP
);
5080 def_mbuiltin (TARGET_NORM
, "__builtin_arc_norm", int_ftype_int
, ARC_BUILTIN_NORM
);
5081 def_mbuiltin (TARGET_NORM
, "__builtin_arc_normw", int_ftype_short_int
, ARC_BUILTIN_NORMW
);
5082 def_mbuiltin (TARGET_SWAP
, "__builtin_arc_swap", int_ftype_int
, ARC_BUILTIN_SWAP
);
5083 def_mbuiltin (TARGET_MUL64_SET
,"__builtin_arc_mul64", void_ftype_int_int
, ARC_BUILTIN_MUL64
);
5084 def_mbuiltin (TARGET_MUL64_SET
,"__builtin_arc_mulu64", void_ftype_usint_usint
, ARC_BUILTIN_MULU64
);
5085 def_mbuiltin (1,"__builtin_arc_rtie", void_ftype_void
, ARC_BUILTIN_RTIE
);
5086 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_sync", void_ftype_void
, ARC_BUILTIN_SYNC
);
5087 def_mbuiltin ((TARGET_EA_SET
),"__builtin_arc_divaw", int_ftype_int_int
, ARC_BUILTIN_DIVAW
);
5088 def_mbuiltin (1,"__builtin_arc_brk", void_ftype_void
, ARC_BUILTIN_BRK
);
5089 def_mbuiltin (1,"__builtin_arc_flag", void_ftype_usint
, ARC_BUILTIN_FLAG
);
5090 def_mbuiltin (1,"__builtin_arc_sleep", void_ftype_usint
, ARC_BUILTIN_SLEEP
);
5091 def_mbuiltin (1,"__builtin_arc_swi", void_ftype_void
, ARC_BUILTIN_SWI
);
5092 def_mbuiltin (1,"__builtin_arc_core_read", usint_ftype_usint
, ARC_BUILTIN_CORE_READ
);
5093 def_mbuiltin (1,"__builtin_arc_core_write", void_ftype_usint_usint
, ARC_BUILTIN_CORE_WRITE
);
5094 def_mbuiltin (1,"__builtin_arc_lr", usint_ftype_usint
, ARC_BUILTIN_LR
);
5095 def_mbuiltin (1,"__builtin_arc_sr", void_ftype_usint_usint
, ARC_BUILTIN_SR
);
5096 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_trap_s", void_ftype_usint
, ARC_BUILTIN_TRAP_S
);
5097 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_unimp_s", void_ftype_void
, ARC_BUILTIN_UNIMP_S
);
5098 def_mbuiltin (1,"__builtin_arc_aligned", int_ftype_pcvoid_int
, ARC_BUILTIN_ALIGNED
);
5100 if (TARGET_SIMD_SET
)
5101 arc_init_simd_builtins ();
5104 static rtx
arc_expand_simd_builtin (tree
, rtx
, rtx
, enum machine_mode
, int);
5106 /* Expand an expression EXP that calls a built-in function,
5107 with result going to TARGET if that's convenient
5108 (and in mode MODE if that's convenient).
5109 SUBTARGET may be used as the target for computing one of EXP's operands.
5110 IGNORE is nonzero if the value is to be ignored. */
5113 arc_expand_builtin (tree exp
,
5116 enum machine_mode mode
,
5119 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
5124 int fcode
= DECL_FUNCTION_CODE (fndecl
);
5126 enum machine_mode mode0
;
5127 enum machine_mode mode1
;
5129 if (fcode
> ARC_SIMD_BUILTIN_BEGIN
&& fcode
< ARC_SIMD_BUILTIN_END
)
5130 return arc_expand_simd_builtin (exp
, target
, subtarget
, mode
, ignore
);
5134 case ARC_BUILTIN_NOP
:
5135 emit_insn (gen_nop ());
5138 case ARC_BUILTIN_NORM
:
5139 icode
= CODE_FOR_clrsbsi2
;
5140 arg0
= CALL_EXPR_ARG (exp
, 0);
5141 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5142 mode0
= insn_data
[icode
].operand
[1].mode
;
5143 target
= gen_reg_rtx (SImode
);
5145 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5146 op0
= copy_to_mode_reg (mode0
, op0
);
5148 emit_insn (gen_clrsbsi2 (target
, op0
));
5151 case ARC_BUILTIN_NORMW
:
5153 /* FIXME : This should all be HImode, not SImode. */
5154 icode
= CODE_FOR_normw
;
5155 arg0
= CALL_EXPR_ARG (exp
, 0);
5156 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5157 mode0
= insn_data
[icode
].operand
[1].mode
;
5158 target
= gen_reg_rtx (SImode
);
5160 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5161 op0
= copy_to_mode_reg (mode0
, convert_to_mode (mode0
, op0
,0));
5163 emit_insn (gen_normw (target
, op0
));
5166 case ARC_BUILTIN_MUL64
:
5167 icode
= CODE_FOR_mul64
;
5168 arg0
= CALL_EXPR_ARG (exp
, 0);
5169 arg1
= CALL_EXPR_ARG (exp
, 1);
5170 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5171 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5173 mode0
= insn_data
[icode
].operand
[0].mode
;
5174 mode1
= insn_data
[icode
].operand
[1].mode
;
5176 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5177 op0
= copy_to_mode_reg (mode0
, op0
);
5179 if (! (*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
5180 op1
= copy_to_mode_reg (mode1
, op1
);
5182 emit_insn (gen_mul64 (op0
,op1
));
5185 case ARC_BUILTIN_MULU64
:
5186 icode
= CODE_FOR_mulu64
;
5187 arg0
= CALL_EXPR_ARG (exp
, 0);
5188 arg1
= CALL_EXPR_ARG (exp
, 1);
5189 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5190 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5192 mode0
= insn_data
[icode
].operand
[0].mode
;
5193 mode1
= insn_data
[icode
].operand
[1].mode
;
5195 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5196 op0
= copy_to_mode_reg (mode0
, op0
);
5198 if (! (*insn_data
[icode
].operand
[0].predicate
) (op1
, mode1
))
5199 op1
= copy_to_mode_reg (mode1
, op1
);
5201 emit_insn (gen_mulu64 (op0
,op1
));
5204 case ARC_BUILTIN_RTIE
:
5205 icode
= CODE_FOR_rtie
;
5206 emit_insn (gen_rtie (const1_rtx
));
5209 case ARC_BUILTIN_SYNC
:
5210 icode
= CODE_FOR_sync
;
5211 emit_insn (gen_sync (const1_rtx
));
5214 case ARC_BUILTIN_SWAP
:
5215 icode
= CODE_FOR_swap
;
5216 arg0
= CALL_EXPR_ARG (exp
, 0);
5217 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5218 mode0
= insn_data
[icode
].operand
[1].mode
;
5219 target
= gen_reg_rtx (SImode
);
5221 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5222 op0
= copy_to_mode_reg (mode0
, op0
);
5224 emit_insn (gen_swap (target
, op0
));
5227 case ARC_BUILTIN_DIVAW
:
5228 icode
= CODE_FOR_divaw
;
5229 arg0
= CALL_EXPR_ARG (exp
, 0);
5230 arg1
= CALL_EXPR_ARG (exp
, 1);
5232 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5233 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5234 target
= gen_reg_rtx (SImode
);
5236 mode0
= insn_data
[icode
].operand
[0].mode
;
5237 mode1
= insn_data
[icode
].operand
[1].mode
;
5239 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5240 op0
= copy_to_mode_reg (mode0
, op0
);
5242 if (! (*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
5243 op1
= copy_to_mode_reg (mode1
, op1
);
5245 emit_insn (gen_divaw (target
, op0
, op1
));
5248 case ARC_BUILTIN_BRK
:
5249 icode
= CODE_FOR_brk
;
5250 emit_insn (gen_brk (const1_rtx
));
5253 case ARC_BUILTIN_SLEEP
:
5254 icode
= CODE_FOR_sleep
;
5255 arg0
= CALL_EXPR_ARG (exp
, 0);
5259 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5260 mode0
= insn_data
[icode
].operand
[1].mode
;
5262 emit_insn (gen_sleep (op0
));
5265 case ARC_BUILTIN_SWI
:
5266 icode
= CODE_FOR_swi
;
5267 emit_insn (gen_swi (const1_rtx
));
5270 case ARC_BUILTIN_FLAG
:
5271 icode
= CODE_FOR_flag
;
5272 arg0
= CALL_EXPR_ARG (exp
, 0);
5273 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5274 mode0
= insn_data
[icode
].operand
[0].mode
;
5276 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5277 op0
= copy_to_mode_reg (mode0
, op0
);
5279 emit_insn (gen_flag (op0
));
5282 case ARC_BUILTIN_CORE_READ
:
5283 icode
= CODE_FOR_core_read
;
5284 arg0
= CALL_EXPR_ARG (exp
, 0);
5285 target
= gen_reg_rtx (SImode
);
5289 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5290 mode0
= insn_data
[icode
].operand
[1].mode
;
5292 emit_insn (gen_core_read (target
, op0
));
5295 case ARC_BUILTIN_CORE_WRITE
:
5296 icode
= CODE_FOR_core_write
;
5297 arg0
= CALL_EXPR_ARG (exp
, 0);
5298 arg1
= CALL_EXPR_ARG (exp
, 1);
5302 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5303 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5305 mode0
= insn_data
[icode
].operand
[0].mode
;
5306 mode1
= insn_data
[icode
].operand
[1].mode
;
5308 emit_insn (gen_core_write (op0
, op1
));
5311 case ARC_BUILTIN_LR
:
5312 icode
= CODE_FOR_lr
;
5313 arg0
= CALL_EXPR_ARG (exp
, 0);
5314 target
= gen_reg_rtx (SImode
);
5318 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5319 mode0
= insn_data
[icode
].operand
[1].mode
;
5321 emit_insn (gen_lr (target
, op0
));
5324 case ARC_BUILTIN_SR
:
5325 icode
= CODE_FOR_sr
;
5326 arg0
= CALL_EXPR_ARG (exp
, 0);
5327 arg1
= CALL_EXPR_ARG (exp
, 1);
5331 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5332 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5334 mode0
= insn_data
[icode
].operand
[0].mode
;
5335 mode1
= insn_data
[icode
].operand
[1].mode
;
5337 emit_insn (gen_sr (op0
, op1
));
5340 case ARC_BUILTIN_TRAP_S
:
5341 icode
= CODE_FOR_trap_s
;
5342 arg0
= CALL_EXPR_ARG (exp
, 0);
5346 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5347 mode0
= insn_data
[icode
].operand
[1].mode
;
5349 /* We don't give an error for non-cost values here because
5350 we still want to allow things to be fixed up by later inlining /
5351 constant folding / dead code elimination. */
5352 if (CONST_INT_P (op0
) && !satisfies_constraint_L (op0
))
5354 /* Keep this message in sync with the one in arc.md:trap_s,
5355 because *.md files don't get scanned by exgettext. */
5356 error ("operand to trap_s should be an unsigned 6-bit value");
5358 emit_insn (gen_trap_s (op0
));
5361 case ARC_BUILTIN_UNIMP_S
:
5362 icode
= CODE_FOR_unimp_s
;
5363 emit_insn (gen_unimp_s (const1_rtx
));
5366 case ARC_BUILTIN_ALIGNED
:
5367 /* __builtin_arc_aligned (void* val, int alignval) */
5368 arg0
= CALL_EXPR_ARG (exp
, 0);
5369 arg1
= CALL_EXPR_ARG (exp
, 1);
5371 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5372 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5373 target
= gen_reg_rtx (SImode
);
5375 if (!CONST_INT_P (op1
))
5377 /* If we can't fold the alignment to a constant integer
5378 whilst optimizing, this is probably a user error. */
5380 warning (0, "__builtin_arc_aligned with non-constant alignment");
5384 HOST_WIDE_INT alignTest
= INTVAL (op1
);
5385 /* Check alignTest is positive, and a power of two. */
5386 if (alignTest
<= 0 || alignTest
!= (alignTest
& -alignTest
))
5388 error ("invalid alignment value for __builtin_arc_aligned");
5392 if (CONST_INT_P (op0
))
5394 HOST_WIDE_INT pnt
= INTVAL (op0
);
5396 if ((pnt
& (alignTest
- 1)) == 0)
5401 unsigned align
= get_pointer_alignment (arg0
);
5402 unsigned numBits
= alignTest
* BITS_PER_UNIT
;
5404 if (align
&& align
>= numBits
)
5406 /* Another attempt to ascertain alignment. Check the type
5407 we are pointing to. */
5408 if (POINTER_TYPE_P (TREE_TYPE (arg0
))
5409 && TYPE_ALIGN (TREE_TYPE (TREE_TYPE (arg0
))) >= numBits
)
5414 /* Default to false. */
5421 /* @@@ Should really do something sensible here. */
5425 /* Returns true if the operands[opno] is a valid compile-time constant to be
5426 used as register number in the code for builtins. Else it flags an error
5427 and returns false. */
5430 check_if_valid_regno_const (rtx
*operands
, int opno
)
5433 switch (GET_CODE (operands
[opno
]))
5440 error ("register number must be a compile-time constant. Try giving higher optimization levels");
5446 /* Check that after all the constant folding, whether the operand to
5447 __builtin_arc_sleep is an unsigned int of 6 bits. If not, flag an error. */
5450 check_if_valid_sleep_operand (rtx
*operands
, int opno
)
5452 switch (GET_CODE (operands
[opno
]))
5456 if( UNSIGNED_INT6 (INTVAL (operands
[opno
])))
5459 fatal_error("operand for sleep instruction must be an unsigned 6 bit compile-time constant");
5465 /* Return true if it is ok to make a tail-call to DECL. */
5468 arc_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED
,
5469 tree exp ATTRIBUTE_UNUSED
)
5471 /* Never tailcall from an ISR routine - it needs a special exit sequence. */
5472 if (ARC_INTERRUPT_P (arc_compute_function_type (cfun
)))
5475 /* Everything else is ok. */
5479 /* Output code to add DELTA to the first argument, and then jump
5480 to FUNCTION. Used for C++ multiple inheritance. */
5483 arc_output_mi_thunk (FILE *file
, tree thunk ATTRIBUTE_UNUSED
,
5484 HOST_WIDE_INT delta
,
5485 HOST_WIDE_INT vcall_offset
,
5488 int mi_delta
= delta
;
5489 const char *const mi_op
= mi_delta
< 0 ? "sub" : "add";
5492 = aggregate_value_p (TREE_TYPE (TREE_TYPE (function
)), function
) ? 1 : 0;
5496 mi_delta
= - mi_delta
;
5498 /* Add DELTA. When possible use a plain add, otherwise load it into
5499 a register first. */
5501 while (mi_delta
!= 0)
5503 if ((mi_delta
& (3 << shift
)) == 0)
5507 asm_fprintf (file
, "\t%s\t%s, %s, %d\n",
5508 mi_op
, reg_names
[this_regno
], reg_names
[this_regno
],
5509 mi_delta
& (0xff << shift
));
5510 mi_delta
&= ~(0xff << shift
);
5515 /* If needed, add *(*THIS + VCALL_OFFSET) to THIS. */
5516 if (vcall_offset
!= 0)
5518 /* ld r12,[this] --> temp = *this
5519 add r12,r12,vcall_offset --> temp = *(*this + vcall_offset)
5521 add this,this,r12 --> this+ = *(*this + vcall_offset) */
5522 asm_fprintf (file
, "\tld\t%s, [%s]\n",
5523 ARC_TEMP_SCRATCH_REG
, reg_names
[this_regno
]);
5524 asm_fprintf (file
, "\tadd\t%s, %s, %ld\n",
5525 ARC_TEMP_SCRATCH_REG
, ARC_TEMP_SCRATCH_REG
, vcall_offset
);
5526 asm_fprintf (file
, "\tld\t%s, [%s]\n",
5527 ARC_TEMP_SCRATCH_REG
, ARC_TEMP_SCRATCH_REG
);
5528 asm_fprintf (file
, "\tadd\t%s, %s, %s\n", reg_names
[this_regno
],
5529 reg_names
[this_regno
], ARC_TEMP_SCRATCH_REG
);
5532 fnaddr
= XEXP (DECL_RTL (function
), 0);
5534 if (arc_is_longcall_p (fnaddr
))
5535 fputs ("\tj\t", file
);
5537 fputs ("\tb\t", file
);
5538 assemble_name (file
, XSTR (fnaddr
, 0));
5542 /* Return true if a 32 bit "long_call" should be generated for
5543 this calling SYM_REF. We generate a long_call if the function:
5545 a. has an __attribute__((long call))
5546 or b. the -mlong-calls command line switch has been specified
5548 However we do not generate a long call if the function has an
5549 __attribute__ ((short_call)) or __attribute__ ((medium_call))
5551 This function will be called by C fragments contained in the machine
5552 description file. */
5555 arc_is_longcall_p (rtx sym_ref
)
5557 if (GET_CODE (sym_ref
) != SYMBOL_REF
)
5560 return (SYMBOL_REF_LONG_CALL_P (sym_ref
)
5561 || (TARGET_LONG_CALLS_SET
5562 && !SYMBOL_REF_SHORT_CALL_P (sym_ref
)
5563 && !SYMBOL_REF_MEDIUM_CALL_P (sym_ref
)));
5567 /* Likewise for short calls. */
5570 arc_is_shortcall_p (rtx sym_ref
)
5572 if (GET_CODE (sym_ref
) != SYMBOL_REF
)
5575 return (SYMBOL_REF_SHORT_CALL_P (sym_ref
)
5576 || (!TARGET_LONG_CALLS_SET
&& !TARGET_MEDIUM_CALLS
5577 && !SYMBOL_REF_LONG_CALL_P (sym_ref
)
5578 && !SYMBOL_REF_MEDIUM_CALL_P (sym_ref
)));
5582 /* Emit profiling code for calling CALLEE. Return true if a special
5583 call pattern needs to be generated. */
5586 arc_profile_call (rtx callee
)
5588 rtx from
= XEXP (DECL_RTL (current_function_decl
), 0);
5590 if (TARGET_UCB_MCOUNT
)
5591 /* Profiling is done by instrumenting the callee. */
5594 if (CONSTANT_P (callee
))
5597 = gen_rtx_CONST (Pmode
,
5598 gen_rtx_UNSPEC (Pmode
,
5599 gen_rtvec (3, from
, callee
,
5600 CONST0_RTX (Pmode
)),
5602 rtx counter
= gen_rtx_MEM (SImode
, count_ptr
);
5603 /* ??? The increment would better be done atomically, but as there is
5604 no proper hardware support, that would be too expensive. */
5605 emit_move_insn (counter
,
5606 force_reg (SImode
, plus_constant (SImode
, counter
, 1)));
5612 = gen_rtx_CONST (Pmode
,
5613 gen_rtx_UNSPEC (Pmode
,
5614 gen_rtvec (3, from
, CONST0_RTX (Pmode
),
5615 CONST0_RTX (Pmode
)),
5617 emit_move_insn (gen_rtx_REG (Pmode
, 8), count_list_ptr
);
5618 emit_move_insn (gen_rtx_REG (Pmode
, 9), callee
);
5623 /* Worker function for TARGET_RETURN_IN_MEMORY. */
5626 arc_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
5628 if (AGGREGATE_TYPE_P (type
) || TREE_ADDRESSABLE (type
))
5632 HOST_WIDE_INT size
= int_size_in_bytes (type
);
5633 return (size
== -1 || size
> 8);
5638 /* This was in rtlanal.c, and can go in there when we decide we want
5639 to submit the change for inclusion in the GCC tree. */
5640 /* Like note_stores, but allow the callback to have side effects on the rtl
5641 (like the note_stores of yore):
5642 Call FUN on each register or MEM that is stored into or clobbered by X.
5643 (X would be the pattern of an insn). DATA is an arbitrary pointer,
5644 ignored by note_stores, but passed to FUN.
5645 FUN may alter parts of the RTL.
5647 FUN receives three arguments:
5648 1. the REG, MEM, CC0 or PC being stored in or clobbered,
5649 2. the SET or CLOBBER rtx that does the store,
5650 3. the pointer DATA provided to note_stores.
5652 If the item being stored in or clobbered is a SUBREG of a hard register,
5653 the SUBREG will be passed. */
5655 /* For now. */ static
5657 walk_stores (rtx x
, void (*fun
) (rtx
, rtx
, void *), void *data
)
5661 if (GET_CODE (x
) == COND_EXEC
)
5662 x
= COND_EXEC_CODE (x
);
5664 if (GET_CODE (x
) == SET
|| GET_CODE (x
) == CLOBBER
)
5666 rtx dest
= SET_DEST (x
);
5668 while ((GET_CODE (dest
) == SUBREG
5669 && (!REG_P (SUBREG_REG (dest
))
5670 || REGNO (SUBREG_REG (dest
)) >= FIRST_PSEUDO_REGISTER
))
5671 || GET_CODE (dest
) == ZERO_EXTRACT
5672 || GET_CODE (dest
) == STRICT_LOW_PART
)
5673 dest
= XEXP (dest
, 0);
5675 /* If we have a PARALLEL, SET_DEST is a list of EXPR_LIST expressions,
5676 each of whose first operand is a register. */
5677 if (GET_CODE (dest
) == PARALLEL
)
5679 for (i
= XVECLEN (dest
, 0) - 1; i
>= 0; i
--)
5680 if (XEXP (XVECEXP (dest
, 0, i
), 0) != 0)
5681 (*fun
) (XEXP (XVECEXP (dest
, 0, i
), 0), x
, data
);
5684 (*fun
) (dest
, x
, data
);
5687 else if (GET_CODE (x
) == PARALLEL
)
5688 for (i
= XVECLEN (x
, 0) - 1; i
>= 0; i
--)
5689 walk_stores (XVECEXP (x
, 0, i
), fun
, data
);
5693 arc_pass_by_reference (cumulative_args_t ca_v ATTRIBUTE_UNUSED
,
5694 enum machine_mode mode ATTRIBUTE_UNUSED
,
5696 bool named ATTRIBUTE_UNUSED
)
5699 && (TREE_CODE (TYPE_SIZE (type
)) != INTEGER_CST
5700 || TREE_ADDRESSABLE (type
)));
5703 /* Implement TARGET_CAN_USE_DOLOOP_P. */
5706 arc_can_use_doloop_p (const widest_int
&iterations
, const widest_int
&,
5707 unsigned int loop_depth
, bool entered_at_top
)
5711 /* Setting up the loop with two sr instructions costs 6 cycles. */
5714 && wi::gtu_p (iterations
, 0)
5715 && wi::leu_p (iterations
, flag_pic
? 6 : 3))
5720 /* NULL if INSN insn is valid within a low-overhead loop.
5721 Otherwise return why doloop cannot be applied. */
5724 arc_invalid_within_doloop (const_rtx insn
)
5727 return "Function call in the loop.";
5731 static int arc_reorg_in_progress
= 0;
5733 /* ARC's machince specific reorg function. */
5743 cfun
->machine
->arc_reorg_started
= 1;
5744 arc_reorg_in_progress
= 1;
5746 /* Emit special sections for profiling. */
5749 section
*save_text_section
;
5751 int size
= get_max_uid () >> 4;
5752 htab_t htab
= htab_create (size
, unspec_prof_hash
, unspec_prof_htab_eq
,
5755 save_text_section
= in_section
;
5756 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
5757 if (NONJUMP_INSN_P (insn
))
5758 walk_stores (PATTERN (insn
), write_profile_sections
, htab
);
5759 if (htab_elements (htab
))
5761 switch_to_section (save_text_section
);
5765 /* Link up loop ends with their loop start. */
5767 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
5768 if (GET_CODE (insn
) == JUMP_INSN
5769 && recog_memoized (insn
) == CODE_FOR_doloop_end_i
)
5772 = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn
), 0, 0)), 1), 0);
5773 rtx num
= GEN_INT (CODE_LABEL_NUMBER (top_label
));
5774 rtx lp
, prev
= prev_nonnote_insn (top_label
);
5775 rtx lp_simple
= NULL_RTX
;
5776 rtx next
= NULL_RTX
;
5777 rtx op0
= XEXP (XVECEXP (PATTERN (insn
), 0, 1), 0);
5778 HOST_WIDE_INT loop_end_id
5779 = -INTVAL (XEXP (XVECEXP (PATTERN (insn
), 0, 4), 0));
5783 (lp
&& NONJUMP_INSN_P (lp
)
5784 && recog_memoized (lp
) != CODE_FOR_doloop_begin_i
);
5785 lp
= prev_nonnote_insn (lp
))
5787 if (!lp
|| !NONJUMP_INSN_P (lp
)
5788 || dead_or_set_regno_p (lp
, LP_COUNT
))
5790 for (prev
= next
= insn
, lp
= NULL_RTX
; prev
|| next
;)
5794 if (NONJUMP_INSN_P (prev
)
5795 && recog_memoized (prev
) == CODE_FOR_doloop_begin_i
5796 && (INTVAL (XEXP (XVECEXP (PATTERN (prev
), 0, 5), 0))
5802 else if (LABEL_P (prev
))
5804 prev
= prev_nonnote_insn (prev
);
5808 if (NONJUMP_INSN_P (next
)
5809 && recog_memoized (next
) == CODE_FOR_doloop_begin_i
5810 && (INTVAL (XEXP (XVECEXP (PATTERN (next
), 0, 5), 0))
5816 next
= next_nonnote_insn (next
);
5823 if (lp
&& !dead_or_set_regno_p (lp
, LP_COUNT
))
5825 rtx begin_cnt
= XEXP (XVECEXP (PATTERN (lp
), 0 ,3), 0);
5826 if (INTVAL (XEXP (XVECEXP (PATTERN (lp
), 0, 4), 0)))
5827 /* The loop end insn has been duplicated. That can happen
5828 when there is a conditional block at the very end of
5831 /* If Register allocation failed to allocate to the right
5832 register, There is no point into teaching reload to
5833 fix this up with reloads, as that would cost more
5834 than using an ordinary core register with the
5835 doloop_fallback pattern. */
5836 if ((true_regnum (op0
) != LP_COUNT
|| !REG_P (begin_cnt
))
5837 /* Likewise, if the loop setup is evidently inside the loop,
5839 || (!lp_simple
&& lp
!= next
&& !seen_label
))
5844 /* It is common that the optimizers copy the loop count from
5845 another register, and doloop_begin_i is stuck with the
5846 source of the move. Making doloop_begin_i only accept "l"
5847 is nonsentical, as this then makes reload evict the pseudo
5848 used for the loop end. The underlying cause is that the
5849 optimizers don't understand that the register allocation for
5850 doloop_begin_i should be treated as part of the loop.
5851 Try to work around this problem by verifying the previous
5853 if (true_regnum (begin_cnt
) != LP_COUNT
)
5857 for (mov
= prev_nonnote_insn (lp
); mov
;
5858 mov
= prev_nonnote_insn (mov
))
5860 if (!NONJUMP_INSN_P (mov
))
5862 else if ((set
= single_set (mov
))
5863 && rtx_equal_p (SET_SRC (set
), begin_cnt
)
5864 && rtx_equal_p (SET_DEST (set
), op0
))
5869 XEXP (XVECEXP (PATTERN (lp
), 0 ,3), 0) = op0
;
5870 note
= find_regno_note (lp
, REG_DEAD
, REGNO (begin_cnt
));
5872 remove_note (lp
, note
);
5880 XEXP (XVECEXP (PATTERN (insn
), 0, 4), 0) = num
;
5881 XEXP (XVECEXP (PATTERN (lp
), 0, 4), 0) = num
;
5883 XEXP (XVECEXP (PATTERN (lp
), 0, 6), 0) = const2_rtx
;
5884 else if (!lp_simple
)
5885 XEXP (XVECEXP (PATTERN (lp
), 0, 6), 0) = const1_rtx
;
5886 else if (prev
!= lp
)
5889 add_insn_after (lp
, prev
, NULL
);
5893 XEXP (XVECEXP (PATTERN (lp
), 0, 7), 0)
5894 = gen_rtx_LABEL_REF (Pmode
, top_label
);
5895 add_reg_note (lp
, REG_LABEL_OPERAND
, top_label
);
5896 LABEL_NUSES (top_label
)++;
5898 /* We can avoid tedious loop start / end setting for empty loops
5899 be merely setting the loop count to its final value. */
5900 if (next_active_insn (top_label
) == insn
)
5903 = gen_rtx_SET (VOIDmode
,
5904 XEXP (XVECEXP (PATTERN (lp
), 0, 3), 0),
5907 lc_set
= emit_insn_before (lc_set
, insn
);
5912 /* If the loop is non-empty with zero length, we can't make it
5913 a zero-overhead loop. That can happen for empty asms. */
5918 for (scan
= top_label
;
5919 (scan
&& scan
!= insn
5920 && (!NONJUMP_INSN_P (scan
) || !get_attr_length (scan
)));
5921 scan
= NEXT_INSN (scan
));
5931 /* Sometimes the loop optimizer makes a complete hash of the
5932 loop. If it were only that the loop is not entered at the
5933 top, we could fix this up by setting LP_START with SR .
5934 However, if we can't find the loop begin were it should be,
5935 chances are that it does not even dominate the loop, but is
5936 inside the loop instead. Using SR there would kill
5938 We use the doloop_fallback pattern here, which executes
5939 in two cycles on the ARC700 when predicted correctly. */
5943 rtx op3
= XEXP (XVECEXP (PATTERN (insn
), 0, 5), 0);
5945 emit_insn_before (gen_move_insn (op3
, op0
), insn
);
5947 = gen_doloop_fallback_m (op3
, JUMP_LABEL (insn
), op0
);
5950 XVEC (PATTERN (insn
), 0)
5951 = gen_rtvec (2, XVECEXP (PATTERN (insn
), 0, 0),
5952 XVECEXP (PATTERN (insn
), 0, 1));
5953 INSN_CODE (insn
) = -1;
5958 /* FIXME: should anticipate ccfsm action, generate special patterns for
5959 to-be-deleted branches that have no delay slot and have at least the
5960 length of the size increase forced on other insns that are conditionalized.
5961 This can also have an insn_list inside that enumerates insns which are
5962 not actually conditionalized because the destinations are dead in the
5964 Could also tag branches that we want to be unaligned if they get no delay
5965 slot, or even ones that we don't want to do delay slot sheduling for
5966 because we can unalign them.
5968 However, there are cases when conditional execution is only possible after
5969 delay slot scheduling:
5971 - If a delay slot is filled with a nocond/set insn from above, the previous
5972 basic block can become elegible for conditional execution.
5973 - If a delay slot is filled with a nocond insn from the fall-through path,
5974 the branch with that delay slot can become eligble for conditional
5975 execution (however, with the same sort of data flow analysis that dbr
5976 does, we could have figured out before that we don't need to
5977 conditionalize this insn.)
5978 - If a delay slot insn is filled with an insn from the target, the
5979 target label gets its uses decremented (even deleted if falling to zero),
5980 thus possibly creating more condexec opportunities there.
5981 Therefore, we should still be prepared to apply condexec optimization on
5982 non-prepared branches if the size increase of conditionalized insns is no
5983 more than the size saved from eliminating the branch. An invocation option
5984 could also be used to reserve a bit of extra size for condbranches so that
5985 this'll work more often (could also test in arc_reorg if the block is
5986 'close enough' to be eligible for condexec to make this likely, and
5987 estimate required size increase). */
5988 /* Generate BRcc insns, by combining cmp and Bcc insns wherever possible. */
5989 if (TARGET_NO_BRCC_SET
)
5994 init_insn_lengths();
5997 if (optimize
> 1 && !TARGET_NO_COND_EXEC
)
6000 unsigned int flags
= pass_data_arc_ifcvt
.todo_flags_finish
;
6001 df_finish_pass ((flags
& TODO_df_verify
) != 0);
6004 /* Call shorten_branches to calculate the insn lengths. */
6005 shorten_branches (get_insns());
6006 cfun
->machine
->ccfsm_current_insn
= NULL_RTX
;
6008 if (!INSN_ADDRESSES_SET_P())
6009 fatal_error ("Insn addresses not set after shorten_branches");
6011 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
6014 enum attr_type insn_type
;
6016 /* If a non-jump insn (or a casesi jump table), continue. */
6017 if (GET_CODE (insn
) != JUMP_INSN
||
6018 GET_CODE (PATTERN (insn
)) == ADDR_VEC
6019 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
6022 /* If we already have a brcc, note if it is suitable for brcc_s.
6023 Be a bit generous with the brcc_s range so that we can take
6024 advantage of any code shortening from delay slot scheduling. */
6025 if (recog_memoized (insn
) == CODE_FOR_cbranchsi4_scratch
)
6027 rtx pat
= PATTERN (insn
);
6028 rtx op
= XEXP (SET_SRC (XVECEXP (pat
, 0, 0)), 0);
6029 rtx
*ccp
= &XEXP (XVECEXP (pat
, 0, 1), 0);
6031 offset
= branch_dest (insn
) - INSN_ADDRESSES (INSN_UID (insn
));
6032 if ((offset
>= -140 && offset
< 140)
6033 && rtx_equal_p (XEXP (op
, 1), const0_rtx
)
6034 && compact_register_operand (XEXP (op
, 0), VOIDmode
)
6035 && equality_comparison_operator (op
, VOIDmode
))
6036 PUT_MODE (*ccp
, CC_Zmode
);
6037 else if (GET_MODE (*ccp
) == CC_Zmode
)
6038 PUT_MODE (*ccp
, CC_ZNmode
);
6041 if ((insn_type
= get_attr_type (insn
)) == TYPE_BRCC
6042 || insn_type
== TYPE_BRCC_NO_DELAY_SLOT
)
6045 /* OK. so we have a jump insn. */
6046 /* We need to check that it is a bcc. */
6047 /* Bcc => set (pc) (if_then_else ) */
6048 pattern
= PATTERN (insn
);
6049 if (GET_CODE (pattern
) != SET
6050 || GET_CODE (SET_SRC (pattern
)) != IF_THEN_ELSE
6051 || ANY_RETURN_P (XEXP (SET_SRC (pattern
), 1)))
6054 /* Now check if the jump is beyond the s9 range. */
6055 if (CROSSING_JUMP_P (insn
))
6057 offset
= branch_dest (insn
) - INSN_ADDRESSES (INSN_UID (insn
));
6059 if(offset
> 253 || offset
< -254)
6062 pc_target
= SET_SRC (pattern
);
6064 /* Now go back and search for the set cc insn. */
6066 label
= XEXP (pc_target
, 1);
6069 rtx pat
, scan
, link_insn
= NULL
;
6071 for (scan
= PREV_INSN (insn
);
6072 scan
&& GET_CODE (scan
) != CODE_LABEL
;
6073 scan
= PREV_INSN (scan
))
6075 if (! INSN_P (scan
))
6077 pat
= PATTERN (scan
);
6078 if (GET_CODE (pat
) == SET
6079 && cc_register (SET_DEST (pat
), VOIDmode
))
6088 /* Check if this is a data dependency. */
6090 rtx op
, cc_clob_rtx
, op0
, op1
, brcc_insn
, note
;
6093 /* Ok this is the set cc. copy args here. */
6094 op
= XEXP (pc_target
, 0);
6096 op0
= cmp0
= XEXP (SET_SRC (pat
), 0);
6097 op1
= cmp1
= XEXP (SET_SRC (pat
), 1);
6098 if (GET_CODE (op0
) == ZERO_EXTRACT
6099 && XEXP (op0
, 1) == const1_rtx
6100 && (GET_CODE (op
) == EQ
6101 || GET_CODE (op
) == NE
))
6103 /* btst / b{eq,ne} -> bbit{0,1} */
6104 op0
= XEXP (cmp0
, 0);
6105 op1
= XEXP (cmp0
, 2);
6107 else if (!register_operand (op0
, VOIDmode
)
6108 || !general_operand (op1
, VOIDmode
))
6110 /* Be careful not to break what cmpsfpx_raw is
6111 trying to create for checking equality of
6112 single-precision floats. */
6113 else if (TARGET_SPFP
6114 && GET_MODE (op0
) == SFmode
6115 && GET_MODE (op1
) == SFmode
)
6118 /* None of the two cmp operands should be set between the
6119 cmp and the branch. */
6120 if (reg_set_between_p (op0
, link_insn
, insn
))
6123 if (reg_set_between_p (op1
, link_insn
, insn
))
6126 /* Since the MODE check does not work, check that this is
6127 CC reg's last set location before insn, and also no
6128 instruction between the cmp and branch uses the
6130 if ((reg_set_between_p (SET_DEST (pat
), link_insn
, insn
))
6131 || (reg_used_between_p (SET_DEST (pat
), link_insn
, insn
)))
6134 /* CC reg should be dead after insn. */
6135 if (!find_regno_note (insn
, REG_DEAD
, CC_REG
))
6138 op
= gen_rtx_fmt_ee (GET_CODE (op
),
6139 GET_MODE (op
), cmp0
, cmp1
);
6140 /* If we create a LIMM where there was none before,
6141 we only benefit if we can avoid a scheduling bubble
6142 for the ARC600. Otherwise, we'd only forgo chances
6143 at short insn generation, and risk out-of-range
6145 if (!brcc_nolimm_operator (op
, VOIDmode
)
6146 && !long_immediate_operand (op1
, VOIDmode
)
6148 || next_active_insn (link_insn
) != insn
))
6151 /* Emit bbit / brcc (or brcc_s if possible).
6152 CC_Zmode indicates that brcc_s is possible. */
6155 cc_clob_rtx
= gen_rtx_REG (CC_ZNmode
, CC_REG
);
6156 else if ((offset
>= -140 && offset
< 140)
6157 && rtx_equal_p (op1
, const0_rtx
)
6158 && compact_register_operand (op0
, VOIDmode
)
6159 && (GET_CODE (op
) == EQ
6160 || GET_CODE (op
) == NE
))
6161 cc_clob_rtx
= gen_rtx_REG (CC_Zmode
, CC_REG
);
6163 cc_clob_rtx
= gen_rtx_REG (CCmode
, CC_REG
);
6166 = gen_rtx_IF_THEN_ELSE (VOIDmode
, op
, label
, pc_rtx
);
6167 brcc_insn
= gen_rtx_SET (VOIDmode
, pc_rtx
, brcc_insn
);
6168 cc_clob_rtx
= gen_rtx_CLOBBER (VOIDmode
, cc_clob_rtx
);
6171 (VOIDmode
, gen_rtvec (2, brcc_insn
, cc_clob_rtx
));
6172 brcc_insn
= emit_jump_insn_before (brcc_insn
, insn
);
6174 JUMP_LABEL (brcc_insn
) = JUMP_LABEL (insn
);
6175 note
= find_reg_note (insn
, REG_BR_PROB
, 0);
6178 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6179 REG_NOTES (brcc_insn
) = note
;
6181 note
= find_reg_note (link_insn
, REG_DEAD
, op0
);
6184 remove_note (link_insn
, note
);
6185 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6186 REG_NOTES (brcc_insn
) = note
;
6188 note
= find_reg_note (link_insn
, REG_DEAD
, op1
);
6191 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6192 REG_NOTES (brcc_insn
) = note
;
6197 /* Delete the bcc insn. */
6198 set_insn_deleted (insn
);
6200 /* Delete the cmp insn. */
6201 set_insn_deleted (link_insn
);
6206 /* Clear out insn_addresses. */
6207 INSN_ADDRESSES_FREE ();
6211 if (INSN_ADDRESSES_SET_P())
6212 fatal_error ("insn addresses not freed");
6214 arc_reorg_in_progress
= 0;
6217 /* Check if the operands are valid for BRcc.d generation
6218 Valid Brcc.d patterns are
6222 For cc={GT, LE, GTU, LEU}, u6=63 can not be allowed,
6223 since they are encoded by the assembler as {GE, LT, HS, LS} 64, which
6224 does not have a delay slot
6226 Assumed precondition: Second operand is either a register or a u6 value. */
6229 valid_brcc_with_delay_p (rtx
*operands
)
6231 if (optimize_size
&& GET_MODE (operands
[4]) == CC_Zmode
)
6233 return brcc_nolimm_operator (operands
[0], VOIDmode
);
6236 /* ??? Hack. This should no really be here. See PR32143. */
6238 arc_decl_anon_ns_mem_p (const_tree decl
)
6242 if (decl
== NULL_TREE
|| decl
== error_mark_node
)
6244 if (TREE_CODE (decl
) == NAMESPACE_DECL
6245 && DECL_NAME (decl
) == NULL_TREE
)
6247 /* Classes and namespaces inside anonymous namespaces have
6248 TREE_PUBLIC == 0, so we can shortcut the search. */
6249 else if (TYPE_P (decl
))
6250 return (TREE_PUBLIC (TYPE_NAME (decl
)) == 0);
6251 else if (TREE_CODE (decl
) == NAMESPACE_DECL
)
6252 return (TREE_PUBLIC (decl
) == 0);
6254 decl
= DECL_CONTEXT (decl
);
6258 /* Implement TARGET_IN_SMALL_DATA_P. Return true if it would be safe to
6259 access DECL using %gp_rel(...)($gp). */
6262 arc_in_small_data_p (const_tree decl
)
6266 if (TREE_CODE (decl
) == STRING_CST
|| TREE_CODE (decl
) == FUNCTION_DECL
)
6270 /* We don't yet generate small-data references for -mabicalls. See related
6271 -G handling in override_options. */
6272 if (TARGET_NO_SDATA_SET
)
6275 if (TREE_CODE (decl
) == VAR_DECL
&& DECL_SECTION_NAME (decl
) != 0)
6279 /* Reject anything that isn't in a known small-data section. */
6280 name
= DECL_SECTION_NAME (decl
);
6281 if (strcmp (name
, ".sdata") != 0 && strcmp (name
, ".sbss") != 0)
6284 /* If a symbol is defined externally, the assembler will use the
6285 usual -G rules when deciding how to implement macros. */
6286 if (!DECL_EXTERNAL (decl
))
6289 /* Only global variables go into sdata section for now. */
6292 /* Don't put constants into the small data section: we want them
6293 to be in ROM rather than RAM. */
6294 if (TREE_CODE (decl
) != VAR_DECL
)
6297 if (TREE_READONLY (decl
)
6298 && !TREE_SIDE_EFFECTS (decl
)
6299 && (!DECL_INITIAL (decl
) || TREE_CONSTANT (DECL_INITIAL (decl
))))
6302 /* TREE_PUBLIC might change after the first call, because of the patch
6304 if (default_binds_local_p_1 (decl
, 1)
6305 || arc_decl_anon_ns_mem_p (decl
))
6308 /* To ensure -mvolatile-cache works
6309 ld.di does not have a gp-relative variant. */
6310 if (TREE_THIS_VOLATILE (decl
))
6314 /* Disable sdata references to weak variables. */
6315 if (DECL_WEAK (decl
))
6318 size
= int_size_in_bytes (TREE_TYPE (decl
));
6320 /* if (AGGREGATE_TYPE_P (TREE_TYPE (decl))) */
6323 /* Allow only <=4B long data types into sdata. */
6324 return (size
> 0 && size
<= 4);
6327 /* Return true if X is a small data address that can be rewritten
6331 arc_rewrite_small_data_p (rtx x
)
6333 if (GET_CODE (x
) == CONST
)
6336 if (GET_CODE (x
) == PLUS
)
6338 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
6342 return (GET_CODE (x
) == SYMBOL_REF
6343 && SYMBOL_REF_SMALL_P(x
));
6346 /* A for_each_rtx callback, used by arc_rewrite_small_data. */
6349 arc_rewrite_small_data_1 (rtx
*loc
, void *data
)
6351 if (arc_rewrite_small_data_p (*loc
))
6355 gcc_assert (SDATA_BASE_REGNUM
== PIC_OFFSET_TABLE_REGNUM
);
6356 *loc
= gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, *loc
);
6360 if (GET_CODE (top
) == MEM
&& &XEXP (top
, 0) == loc
)
6362 else if (GET_CODE (top
) == MEM
6363 && GET_CODE (XEXP (top
, 0)) == PLUS
6364 && GET_CODE (XEXP (XEXP (top
, 0), 0)) == MULT
)
6365 *loc
= force_reg (Pmode
, *loc
);
6371 if (GET_CODE (*loc
) == PLUS
6372 && rtx_equal_p (XEXP (*loc
, 0), pic_offset_table_rtx
))
6378 /* If possible, rewrite OP so that it refers to small data using
6379 explicit relocations. */
6382 arc_rewrite_small_data (rtx op
)
6384 op
= copy_insn (op
);
6385 for_each_rtx (&op
, arc_rewrite_small_data_1
, &op
);
6389 /* A for_each_rtx callback for small_data_pattern. */
6392 small_data_pattern_1 (rtx
*loc
, void *data ATTRIBUTE_UNUSED
)
6394 if (GET_CODE (*loc
) == PLUS
6395 && rtx_equal_p (XEXP (*loc
, 0), pic_offset_table_rtx
))
6398 return arc_rewrite_small_data_p (*loc
);
6401 /* Return true if OP refers to small data symbols directly, not through
6405 small_data_pattern (rtx op
, enum machine_mode
)
6407 return (GET_CODE (op
) != SEQUENCE
6408 && for_each_rtx (&op
, small_data_pattern_1
, 0));
6411 /* Return true if OP is an acceptable memory operand for ARCompact
6412 16-bit gp-relative load instructions.
6413 op shd look like : [r26, symref@sda]
6414 i.e. (mem (plus (reg 26) (symref with smalldata flag set))
6416 /* volatile cache option still to be handled. */
6419 compact_sda_memory_operand (rtx op
, enum machine_mode mode
)
6424 /* Eliminate non-memory operations. */
6425 if (GET_CODE (op
) != MEM
)
6428 if (mode
== VOIDmode
)
6429 mode
= GET_MODE (op
);
6431 size
= GET_MODE_SIZE (mode
);
6433 /* dword operations really put out 2 instructions, so eliminate them. */
6434 if (size
> UNITS_PER_WORD
)
6437 /* Decode the address now. */
6438 addr
= XEXP (op
, 0);
6440 return LEGITIMATE_SMALL_DATA_ADDRESS_P (addr
);
6443 /* Implement ASM_OUTPUT_ALIGNED_DECL_LOCAL. */
6446 arc_asm_output_aligned_decl_local (FILE * stream
, tree decl
, const char * name
,
6447 unsigned HOST_WIDE_INT size
,
6448 unsigned HOST_WIDE_INT align
,
6449 unsigned HOST_WIDE_INT globalize_p
)
6451 int in_small_data
= arc_in_small_data_p (decl
);
6454 switch_to_section (get_named_section (NULL
, ".sbss", 0));
6455 /* named_section (0,".sbss",0); */
6457 switch_to_section (bss_section
);
6460 (*targetm
.asm_out
.globalize_label
) (stream
, name
);
6462 ASM_OUTPUT_ALIGN (stream
, floor_log2 ((align
) / BITS_PER_UNIT
));
6463 ASM_OUTPUT_TYPE_DIRECTIVE (stream
, name
, "object");
6464 ASM_OUTPUT_SIZE_DIRECTIVE (stream
, name
, size
);
6465 ASM_OUTPUT_LABEL (stream
, name
);
6468 ASM_OUTPUT_SKIP (stream
, size
);
6504 /* SIMD builtins support. */
6505 enum simd_insn_args_type
{
6528 struct builtin_description
6530 enum simd_insn_args_type args_type
;
6531 const enum insn_code icode
;
6532 const char * const name
;
6533 const enum arc_builtins code
;
6536 static const struct builtin_description arc_simd_builtin_desc_list
[] =
6538 /* VVV builtins go first. */
6539 #define SIMD_BUILTIN(type, code, string, builtin) \
6540 { type,CODE_FOR_##code, "__builtin_arc_" string, \
6541 ARC_SIMD_BUILTIN_##builtin },
6543 SIMD_BUILTIN (Va_Vb_Vc
, vaddaw_insn
, "vaddaw", VADDAW
)
6544 SIMD_BUILTIN (Va_Vb_Vc
, vaddw_insn
, "vaddw", VADDW
)
6545 SIMD_BUILTIN (Va_Vb_Vc
, vavb_insn
, "vavb", VAVB
)
6546 SIMD_BUILTIN (Va_Vb_Vc
, vavrb_insn
, "vavrb", VAVRB
)
6547 SIMD_BUILTIN (Va_Vb_Vc
, vdifaw_insn
, "vdifaw", VDIFAW
)
6548 SIMD_BUILTIN (Va_Vb_Vc
, vdifw_insn
, "vdifw", VDIFW
)
6549 SIMD_BUILTIN (Va_Vb_Vc
, vmaxaw_insn
, "vmaxaw", VMAXAW
)
6550 SIMD_BUILTIN (Va_Vb_Vc
, vmaxw_insn
, "vmaxw", VMAXW
)
6551 SIMD_BUILTIN (Va_Vb_Vc
, vminaw_insn
, "vminaw", VMINAW
)
6552 SIMD_BUILTIN (Va_Vb_Vc
, vminw_insn
, "vminw", VMINW
)
6553 SIMD_BUILTIN (Va_Vb_Vc
, vmulaw_insn
, "vmulaw", VMULAW
)
6554 SIMD_BUILTIN (Va_Vb_Vc
, vmulfaw_insn
, "vmulfaw", VMULFAW
)
6555 SIMD_BUILTIN (Va_Vb_Vc
, vmulfw_insn
, "vmulfw", VMULFW
)
6556 SIMD_BUILTIN (Va_Vb_Vc
, vmulw_insn
, "vmulw", VMULW
)
6557 SIMD_BUILTIN (Va_Vb_Vc
, vsubaw_insn
, "vsubaw", VSUBAW
)
6558 SIMD_BUILTIN (Va_Vb_Vc
, vsubw_insn
, "vsubw", VSUBW
)
6559 SIMD_BUILTIN (Va_Vb_Vc
, vsummw_insn
, "vsummw", VSUMMW
)
6560 SIMD_BUILTIN (Va_Vb_Vc
, vand_insn
, "vand", VAND
)
6561 SIMD_BUILTIN (Va_Vb_Vc
, vandaw_insn
, "vandaw", VANDAW
)
6562 SIMD_BUILTIN (Va_Vb_Vc
, vbic_insn
, "vbic", VBIC
)
6563 SIMD_BUILTIN (Va_Vb_Vc
, vbicaw_insn
, "vbicaw", VBICAW
)
6564 SIMD_BUILTIN (Va_Vb_Vc
, vor_insn
, "vor", VOR
)
6565 SIMD_BUILTIN (Va_Vb_Vc
, vxor_insn
, "vxor", VXOR
)
6566 SIMD_BUILTIN (Va_Vb_Vc
, vxoraw_insn
, "vxoraw", VXORAW
)
6567 SIMD_BUILTIN (Va_Vb_Vc
, veqw_insn
, "veqw", VEQW
)
6568 SIMD_BUILTIN (Va_Vb_Vc
, vlew_insn
, "vlew", VLEW
)
6569 SIMD_BUILTIN (Va_Vb_Vc
, vltw_insn
, "vltw", VLTW
)
6570 SIMD_BUILTIN (Va_Vb_Vc
, vnew_insn
, "vnew", VNEW
)
6571 SIMD_BUILTIN (Va_Vb_Vc
, vmr1aw_insn
, "vmr1aw", VMR1AW
)
6572 SIMD_BUILTIN (Va_Vb_Vc
, vmr1w_insn
, "vmr1w", VMR1W
)
6573 SIMD_BUILTIN (Va_Vb_Vc
, vmr2aw_insn
, "vmr2aw", VMR2AW
)
6574 SIMD_BUILTIN (Va_Vb_Vc
, vmr2w_insn
, "vmr2w", VMR2W
)
6575 SIMD_BUILTIN (Va_Vb_Vc
, vmr3aw_insn
, "vmr3aw", VMR3AW
)
6576 SIMD_BUILTIN (Va_Vb_Vc
, vmr3w_insn
, "vmr3w", VMR3W
)
6577 SIMD_BUILTIN (Va_Vb_Vc
, vmr4aw_insn
, "vmr4aw", VMR4AW
)
6578 SIMD_BUILTIN (Va_Vb_Vc
, vmr4w_insn
, "vmr4w", VMR4W
)
6579 SIMD_BUILTIN (Va_Vb_Vc
, vmr5aw_insn
, "vmr5aw", VMR5AW
)
6580 SIMD_BUILTIN (Va_Vb_Vc
, vmr5w_insn
, "vmr5w", VMR5W
)
6581 SIMD_BUILTIN (Va_Vb_Vc
, vmr6aw_insn
, "vmr6aw", VMR6AW
)
6582 SIMD_BUILTIN (Va_Vb_Vc
, vmr6w_insn
, "vmr6w", VMR6W
)
6583 SIMD_BUILTIN (Va_Vb_Vc
, vmr7aw_insn
, "vmr7aw", VMR7AW
)
6584 SIMD_BUILTIN (Va_Vb_Vc
, vmr7w_insn
, "vmr7w", VMR7W
)
6585 SIMD_BUILTIN (Va_Vb_Vc
, vmrb_insn
, "vmrb", VMRB
)
6586 SIMD_BUILTIN (Va_Vb_Vc
, vh264f_insn
, "vh264f", VH264F
)
6587 SIMD_BUILTIN (Va_Vb_Vc
, vh264ft_insn
, "vh264ft", VH264FT
)
6588 SIMD_BUILTIN (Va_Vb_Vc
, vh264fw_insn
, "vh264fw", VH264FW
)
6589 SIMD_BUILTIN (Va_Vb_Vc
, vvc1f_insn
, "vvc1f", VVC1F
)
6590 SIMD_BUILTIN (Va_Vb_Vc
, vvc1ft_insn
, "vvc1ft", VVC1FT
)
6592 SIMD_BUILTIN (Va_Vb_rlimm
, vbaddw_insn
, "vbaddw", VBADDW
)
6593 SIMD_BUILTIN (Va_Vb_rlimm
, vbmaxw_insn
, "vbmaxw", VBMAXW
)
6594 SIMD_BUILTIN (Va_Vb_rlimm
, vbminw_insn
, "vbminw", VBMINW
)
6595 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulaw_insn
, "vbmulaw", VBMULAW
)
6596 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulfw_insn
, "vbmulfw", VBMULFW
)
6597 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulw_insn
, "vbmulw", VBMULW
)
6598 SIMD_BUILTIN (Va_Vb_rlimm
, vbrsubw_insn
, "vbrsubw", VBRSUBW
)
6599 SIMD_BUILTIN (Va_Vb_rlimm
, vbsubw_insn
, "vbsubw", VBSUBW
)
6601 /* Va, Vb, Ic instructions. */
6602 SIMD_BUILTIN (Va_Vb_Ic
, vasrw_insn
, "vasrw", VASRW
)
6603 SIMD_BUILTIN (Va_Vb_Ic
, vsr8_insn
, "vsr8", VSR8
)
6604 SIMD_BUILTIN (Va_Vb_Ic
, vsr8aw_insn
, "vsr8aw", VSR8AW
)
6606 /* Va, Vb, u6 instructions. */
6607 SIMD_BUILTIN (Va_Vb_u6
, vasrrwi_insn
, "vasrrwi", VASRRWi
)
6608 SIMD_BUILTIN (Va_Vb_u6
, vasrsrwi_insn
, "vasrsrwi", VASRSRWi
)
6609 SIMD_BUILTIN (Va_Vb_u6
, vasrwi_insn
, "vasrwi", VASRWi
)
6610 SIMD_BUILTIN (Va_Vb_u6
, vasrpwbi_insn
, "vasrpwbi", VASRPWBi
)
6611 SIMD_BUILTIN (Va_Vb_u6
, vasrrpwbi_insn
,"vasrrpwbi", VASRRPWBi
)
6612 SIMD_BUILTIN (Va_Vb_u6
, vsr8awi_insn
, "vsr8awi", VSR8AWi
)
6613 SIMD_BUILTIN (Va_Vb_u6
, vsr8i_insn
, "vsr8i", VSR8i
)
6615 /* Va, Vb, u8 (simm) instructions. */
6616 SIMD_BUILTIN (Va_Vb_u8
, vmvaw_insn
, "vmvaw", VMVAW
)
6617 SIMD_BUILTIN (Va_Vb_u8
, vmvw_insn
, "vmvw", VMVW
)
6618 SIMD_BUILTIN (Va_Vb_u8
, vmvzw_insn
, "vmvzw", VMVZW
)
6619 SIMD_BUILTIN (Va_Vb_u8
, vd6tapf_insn
, "vd6tapf", VD6TAPF
)
6621 /* Va, rlimm, u8 (simm) instructions. */
6622 SIMD_BUILTIN (Va_rlimm_u8
, vmovaw_insn
, "vmovaw", VMOVAW
)
6623 SIMD_BUILTIN (Va_rlimm_u8
, vmovw_insn
, "vmovw", VMOVW
)
6624 SIMD_BUILTIN (Va_rlimm_u8
, vmovzw_insn
, "vmovzw", VMOVZW
)
6626 /* Va, Vb instructions. */
6627 SIMD_BUILTIN (Va_Vb
, vabsaw_insn
, "vabsaw", VABSAW
)
6628 SIMD_BUILTIN (Va_Vb
, vabsw_insn
, "vabsw", VABSW
)
6629 SIMD_BUILTIN (Va_Vb
, vaddsuw_insn
, "vaddsuw", VADDSUW
)
6630 SIMD_BUILTIN (Va_Vb
, vsignw_insn
, "vsignw", VSIGNW
)
6631 SIMD_BUILTIN (Va_Vb
, vexch1_insn
, "vexch1", VEXCH1
)
6632 SIMD_BUILTIN (Va_Vb
, vexch2_insn
, "vexch2", VEXCH2
)
6633 SIMD_BUILTIN (Va_Vb
, vexch4_insn
, "vexch4", VEXCH4
)
6634 SIMD_BUILTIN (Va_Vb
, vupbaw_insn
, "vupbaw", VUPBAW
)
6635 SIMD_BUILTIN (Va_Vb
, vupbw_insn
, "vupbw", VUPBW
)
6636 SIMD_BUILTIN (Va_Vb
, vupsbaw_insn
, "vupsbaw", VUPSBAW
)
6637 SIMD_BUILTIN (Va_Vb
, vupsbw_insn
, "vupsbw", VUPSBW
)
6639 /* DIb, rlimm, rlimm instructions. */
6640 SIMD_BUILTIN (Da_rlimm_rlimm
, vdirun_insn
, "vdirun", VDIRUN
)
6641 SIMD_BUILTIN (Da_rlimm_rlimm
, vdorun_insn
, "vdorun", VDORUN
)
6643 /* DIb, limm, rlimm instructions. */
6644 SIMD_BUILTIN (Da_u3_rlimm
, vdiwr_insn
, "vdiwr", VDIWR
)
6645 SIMD_BUILTIN (Da_u3_rlimm
, vdowr_insn
, "vdowr", VDOWR
)
6647 /* rlimm instructions. */
6648 SIMD_BUILTIN (void_rlimm
, vrec_insn
, "vrec", VREC
)
6649 SIMD_BUILTIN (void_rlimm
, vrun_insn
, "vrun", VRUN
)
6650 SIMD_BUILTIN (void_rlimm
, vrecrun_insn
, "vrecrun", VRECRUN
)
6651 SIMD_BUILTIN (void_rlimm
, vendrec_insn
, "vendrec", VENDREC
)
6653 /* Va, [Ib,u8] instructions. */
6654 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32wh_insn
, "vld32wh", VLD32WH
)
6655 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32wl_insn
, "vld32wl", VLD32WL
)
6656 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld64_insn
, "vld64", VLD64
)
6657 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32_insn
, "vld32", VLD32
)
6659 SIMD_BUILTIN (Va_Ib_u8
, vld64w_insn
, "vld64w", VLD64W
)
6660 SIMD_BUILTIN (Va_Ib_u8
, vld128_insn
, "vld128", VLD128
)
6661 SIMD_BUILTIN (void_Va_Ib_u8
, vst128_insn
, "vst128", VST128
)
6662 SIMD_BUILTIN (void_Va_Ib_u8
, vst64_insn
, "vst64", VST64
)
6664 /* Va, [Ib, u8] instructions. */
6665 SIMD_BUILTIN (void_Va_u3_Ib_u8
, vst16_n_insn
, "vst16_n", VST16_N
)
6666 SIMD_BUILTIN (void_Va_u3_Ib_u8
, vst32_n_insn
, "vst32_n", VST32_N
)
6668 SIMD_BUILTIN (void_u6
, vinti_insn
, "vinti", VINTI
)
6672 arc_init_simd_builtins (void)
6675 tree endlink
= void_list_node
;
6676 tree V8HI_type_node
= build_vector_type_for_mode (intHI_type_node
, V8HImode
);
6678 tree v8hi_ftype_v8hi_v8hi
6679 = build_function_type (V8HI_type_node
,
6680 tree_cons (NULL_TREE
, V8HI_type_node
,
6681 tree_cons (NULL_TREE
, V8HI_type_node
,
6683 tree v8hi_ftype_v8hi_int
6684 = build_function_type (V8HI_type_node
,
6685 tree_cons (NULL_TREE
, V8HI_type_node
,
6686 tree_cons (NULL_TREE
, integer_type_node
,
6689 tree v8hi_ftype_v8hi_int_int
6690 = build_function_type (V8HI_type_node
,
6691 tree_cons (NULL_TREE
, V8HI_type_node
,
6692 tree_cons (NULL_TREE
, integer_type_node
,
6693 tree_cons (NULL_TREE
,
6697 tree void_ftype_v8hi_int_int
6698 = build_function_type (void_type_node
,
6699 tree_cons (NULL_TREE
, V8HI_type_node
,
6700 tree_cons (NULL_TREE
, integer_type_node
,
6701 tree_cons (NULL_TREE
,
6705 tree void_ftype_v8hi_int_int_int
6706 = (build_function_type
6708 tree_cons (NULL_TREE
, V8HI_type_node
,
6709 tree_cons (NULL_TREE
, integer_type_node
,
6710 tree_cons (NULL_TREE
, integer_type_node
,
6711 tree_cons (NULL_TREE
,
6715 tree v8hi_ftype_int_int
6716 = build_function_type (V8HI_type_node
,
6717 tree_cons (NULL_TREE
, integer_type_node
,
6718 tree_cons (NULL_TREE
, integer_type_node
,
6721 tree void_ftype_int_int
6722 = build_function_type (void_type_node
,
6723 tree_cons (NULL_TREE
, integer_type_node
,
6724 tree_cons (NULL_TREE
, integer_type_node
,
6728 = build_function_type (void_type_node
,
6729 tree_cons (NULL_TREE
, integer_type_node
, endlink
));
6731 tree v8hi_ftype_v8hi
6732 = build_function_type (V8HI_type_node
, tree_cons (NULL_TREE
, V8HI_type_node
,
6735 /* These asserts have been introduced to ensure that the order of builtins
6736 does not get messed up, else the initialization goes wrong. */
6737 gcc_assert (arc_simd_builtin_desc_list
[0].args_type
== Va_Vb_Vc
);
6738 for (i
=0; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Vc
; i
++)
6739 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6740 v8hi_ftype_v8hi_v8hi
, arc_simd_builtin_desc_list
[i
].code
);
6742 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_rlimm
);
6743 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_rlimm
; i
++)
6744 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6745 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6747 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic
);
6748 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic
; i
++)
6749 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6750 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6752 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u6
);
6753 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u6
; i
++)
6754 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6755 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6757 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u8
);
6758 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u8
; i
++)
6759 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6760 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6762 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_rlimm_u8
);
6763 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_rlimm_u8
; i
++)
6764 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6765 v8hi_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6767 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb
);
6768 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb
; i
++)
6769 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6770 v8hi_ftype_v8hi
, arc_simd_builtin_desc_list
[i
].code
);
6772 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Da_rlimm_rlimm
);
6773 for (; arc_simd_builtin_desc_list
[i
].args_type
== Da_rlimm_rlimm
; i
++)
6774 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6775 void_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6777 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Da_u3_rlimm
);
6778 for (; arc_simd_builtin_desc_list
[i
].args_type
== Da_u3_rlimm
; i
++)
6779 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6780 void_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6782 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_rlimm
);
6783 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_rlimm
; i
++)
6784 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6785 void_ftype_int
, arc_simd_builtin_desc_list
[i
].code
);
6787 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic_u8
);
6788 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic_u8
; i
++)
6789 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6790 v8hi_ftype_v8hi_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6792 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Ib_u8
);
6793 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Ib_u8
; i
++)
6794 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6795 v8hi_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6797 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_Va_Ib_u8
);
6798 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_Va_Ib_u8
; i
++)
6799 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6800 void_ftype_v8hi_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6802 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_Va_u3_Ib_u8
);
6803 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_Va_u3_Ib_u8
; i
++)
6804 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6805 void_ftype_v8hi_int_int_int
,
6806 arc_simd_builtin_desc_list
[i
].code
);
6808 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_u6
);
6809 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_u6
; i
++)
6810 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6811 void_ftype_int
, arc_simd_builtin_desc_list
[i
].code
);
6813 gcc_assert(i
== ARRAY_SIZE (arc_simd_builtin_desc_list
));
6816 /* Helper function of arc_expand_builtin; has the same parameters,
6817 except that EXP is now known to be a call to a simd builtin. */
6820 arc_expand_simd_builtin (tree exp
,
6822 rtx subtarget ATTRIBUTE_UNUSED
,
6823 enum machine_mode mode ATTRIBUTE_UNUSED
,
6824 int ignore ATTRIBUTE_UNUSED
)
6826 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
6838 int fcode
= DECL_FUNCTION_CODE (fndecl
);
6840 enum machine_mode mode0
;
6841 enum machine_mode mode1
;
6842 enum machine_mode mode2
;
6843 enum machine_mode mode3
;
6844 enum machine_mode mode4
;
6845 const struct builtin_description
* d
;
6847 for (i
= 0, d
= arc_simd_builtin_desc_list
;
6848 i
< ARRAY_SIZE (arc_simd_builtin_desc_list
); i
++, d
++)
6849 if (d
->code
== (const enum arc_builtins
) fcode
)
6852 /* We must get an entry here. */
6853 gcc_assert (i
< ARRAY_SIZE (arc_simd_builtin_desc_list
));
6855 switch (d
->args_type
)
6859 arg0
= CALL_EXPR_ARG (exp
, 0);
6860 arg1
= CALL_EXPR_ARG (exp
, 1);
6861 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6862 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6864 target
= gen_reg_rtx (V8HImode
);
6865 mode0
= insn_data
[icode
].operand
[1].mode
;
6866 mode1
= insn_data
[icode
].operand
[2].mode
;
6868 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6869 op0
= copy_to_mode_reg (mode0
, op0
);
6871 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6872 op1
= copy_to_mode_reg (mode1
, op1
);
6874 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
6884 arg0
= CALL_EXPR_ARG (exp
, 0);
6885 arg1
= CALL_EXPR_ARG (exp
, 1);
6886 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6887 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6889 target
= gen_reg_rtx (V8HImode
);
6890 mode0
= insn_data
[icode
].operand
[1].mode
;
6891 mode1
= insn_data
[icode
].operand
[2].mode
;
6893 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6894 op0
= copy_to_mode_reg (mode0
, op0
);
6896 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
)
6897 || (d
->args_type
== Va_Vb_u6
&& !UNSIGNED_INT6 (INTVAL (op1
)))
6898 || (d
->args_type
== Va_Vb_u8
&& !UNSIGNED_INT8 (INTVAL (op1
))))
6899 error ("operand 2 of %s instruction should be an unsigned %d-bit value",
6901 (d
->args_type
== Va_Vb_u6
)? 6: 8);
6903 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
6912 arg0
= CALL_EXPR_ARG (exp
, 0);
6913 arg1
= CALL_EXPR_ARG (exp
, 1);
6914 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6915 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6917 target
= gen_reg_rtx (V8HImode
);
6918 mode0
= insn_data
[icode
].operand
[1].mode
;
6919 mode1
= insn_data
[icode
].operand
[2].mode
;
6921 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6922 op0
= copy_to_mode_reg (mode0
, op0
);
6924 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6925 || !(UNSIGNED_INT8 (INTVAL (op1
))))
6926 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
6929 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
6938 arg0
= CALL_EXPR_ARG (exp
, 0);
6939 arg1
= CALL_EXPR_ARG (exp
, 1);
6940 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6941 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6942 op2
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
);
6944 target
= gen_reg_rtx (V8HImode
);
6945 mode0
= insn_data
[icode
].operand
[1].mode
;
6946 mode1
= insn_data
[icode
].operand
[2].mode
;
6948 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6949 op0
= copy_to_mode_reg (mode0
, op0
);
6951 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6952 || !(UNSIGNED_INT3 (INTVAL (op1
))))
6953 error ("operand 2 of %s instruction should be an unsigned 3-bit value (I0-I7)",
6956 pat
= GEN_FCN (icode
) (target
, op0
, op1
, op2
);
6965 arg0
= CALL_EXPR_ARG (exp
, 0);
6966 arg1
= CALL_EXPR_ARG (exp
, 1);
6967 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6968 op1
= expand_expr (arg1
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6970 target
= gen_reg_rtx (V8HImode
);
6971 mode0
= insn_data
[icode
].operand
[1].mode
;
6972 mode1
= insn_data
[icode
].operand
[2].mode
;
6974 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6975 op0
= copy_to_mode_reg (mode0
, op0
);
6977 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6978 op1
= copy_to_mode_reg (mode1
, op1
);
6980 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
6989 arg0
= CALL_EXPR_ARG (exp
, 0);
6990 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6992 target
= gen_reg_rtx (V8HImode
);
6993 mode0
= insn_data
[icode
].operand
[1].mode
;
6995 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6996 op0
= copy_to_mode_reg (mode0
, op0
);
6998 pat
= GEN_FCN (icode
) (target
, op0
);
7005 case Da_rlimm_rlimm
:
7007 arg0
= CALL_EXPR_ARG (exp
, 0);
7008 arg1
= CALL_EXPR_ARG (exp
, 1);
7009 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7010 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7013 if (icode
== CODE_FOR_vdirun_insn
)
7014 target
= gen_rtx_REG (SImode
, 131);
7015 else if (icode
== CODE_FOR_vdorun_insn
)
7016 target
= gen_rtx_REG (SImode
, 139);
7020 mode0
= insn_data
[icode
].operand
[1].mode
;
7021 mode1
= insn_data
[icode
].operand
[2].mode
;
7023 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
7024 op0
= copy_to_mode_reg (mode0
, op0
);
7026 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7027 op1
= copy_to_mode_reg (mode1
, op1
);
7030 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
7039 arg0
= CALL_EXPR_ARG (exp
, 0);
7040 arg1
= CALL_EXPR_ARG (exp
, 1);
7041 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7042 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7045 if (! (GET_CODE (op0
) == CONST_INT
)
7046 || !(UNSIGNED_INT3 (INTVAL (op0
))))
7047 error ("operand 1 of %s instruction should be an unsigned 3-bit value (DR0-DR7)",
7050 mode1
= insn_data
[icode
].operand
[1].mode
;
7052 if (icode
== CODE_FOR_vdiwr_insn
)
7053 target
= gen_rtx_REG (SImode
,
7054 ARC_FIRST_SIMD_DMA_CONFIG_IN_REG
+ INTVAL (op0
));
7055 else if (icode
== CODE_FOR_vdowr_insn
)
7056 target
= gen_rtx_REG (SImode
,
7057 ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG
+ INTVAL (op0
));
7061 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7062 op1
= copy_to_mode_reg (mode1
, op1
);
7064 pat
= GEN_FCN (icode
) (target
, op1
);
7073 arg0
= CALL_EXPR_ARG (exp
, 0);
7077 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7078 mode0
= insn_data
[icode
].operand
[0].mode
;
7080 /* op0 should be u6. */
7081 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
)
7082 || !(UNSIGNED_INT6 (INTVAL (op0
))))
7083 error ("operand of %s instruction should be an unsigned 6-bit value",
7086 pat
= GEN_FCN (icode
) (op0
);
7095 arg0
= CALL_EXPR_ARG (exp
, 0);
7099 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7100 mode0
= insn_data
[icode
].operand
[0].mode
;
7102 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
7103 op0
= copy_to_mode_reg (mode0
, op0
);
7105 pat
= GEN_FCN (icode
) (op0
);
7116 arg0
= CALL_EXPR_ARG (exp
, 0); /* source vreg */
7117 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7118 arg2
= CALL_EXPR_ARG (exp
, 2); /* u8 */
7120 src_vreg
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
7121 op0
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* [I]0-7 */
7122 op1
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7123 op2
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7125 /* target <- src vreg */
7126 emit_insn (gen_move_insn (target
, src_vreg
));
7128 /* target <- vec_concat: target, mem(Ib, u8) */
7129 mode0
= insn_data
[icode
].operand
[3].mode
;
7130 mode1
= insn_data
[icode
].operand
[1].mode
;
7132 if ( (!(*insn_data
[icode
].operand
[3].predicate
) (op0
, mode0
))
7133 || !(UNSIGNED_INT3 (INTVAL (op0
))))
7134 error ("operand 1 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7137 if ( (!(*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
7138 || !(UNSIGNED_INT8 (INTVAL (op1
))))
7139 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
7142 pat
= GEN_FCN (icode
) (target
, op1
, op2
, op0
);
7152 arg0
= CALL_EXPR_ARG (exp
, 0); /* src vreg */
7153 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7154 arg2
= CALL_EXPR_ARG (exp
, 2); /* u8 */
7156 op0
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7157 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* I[0-7] */
7158 op2
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7159 op3
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
); /* Vdest */
7161 mode0
= insn_data
[icode
].operand
[0].mode
;
7162 mode1
= insn_data
[icode
].operand
[1].mode
;
7163 mode2
= insn_data
[icode
].operand
[2].mode
;
7164 mode3
= insn_data
[icode
].operand
[3].mode
;
7166 if ( (!(*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
7167 || !(UNSIGNED_INT3 (INTVAL (op1
))))
7168 error ("operand 2 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7171 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op2
, mode2
))
7172 || !(UNSIGNED_INT8 (INTVAL (op2
))))
7173 error ("operand 3 of %s instruction should be an unsigned 8-bit value",
7176 if (!(*insn_data
[icode
].operand
[3].predicate
) (op3
, mode3
))
7177 op3
= copy_to_mode_reg (mode3
, op3
);
7179 pat
= GEN_FCN (icode
) (op0
, op1
, op2
, op3
);
7188 arg0
= CALL_EXPR_ARG (exp
, 0); /* dest vreg */
7189 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7191 op0
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7192 op1
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* I[0-7] */
7193 op2
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7195 /* target <- src vreg */
7196 target
= gen_reg_rtx (V8HImode
);
7198 /* target <- vec_concat: target, mem(Ib, u8) */
7199 mode0
= insn_data
[icode
].operand
[1].mode
;
7200 mode1
= insn_data
[icode
].operand
[2].mode
;
7201 mode2
= insn_data
[icode
].operand
[3].mode
;
7203 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7204 || !(UNSIGNED_INT3 (INTVAL (op1
))))
7205 error ("operand 1 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7208 if ( (!(*insn_data
[icode
].operand
[3].predicate
) (op2
, mode2
))
7209 || !(UNSIGNED_INT8 (INTVAL (op2
))))
7210 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
7213 pat
= GEN_FCN (icode
) (target
, op0
, op1
, op2
);
7220 case void_Va_u3_Ib_u8
:
7222 arg0
= CALL_EXPR_ARG (exp
, 0); /* source vreg */
7223 arg1
= CALL_EXPR_ARG (exp
, 1); /* u3 */
7224 arg2
= CALL_EXPR_ARG (exp
, 2); /* [I]0-7 */
7225 arg3
= CALL_EXPR_ARG (exp
, 3); /* u8 */
7227 op0
= expand_expr (arg3
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7228 op1
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR */
7229 op2
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* [I]0-7 */
7230 op3
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);/* vreg to be stored */
7231 op4
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* vreg 0-7 subreg no. */
7233 mode0
= insn_data
[icode
].operand
[0].mode
;
7234 mode2
= insn_data
[icode
].operand
[2].mode
;
7235 mode3
= insn_data
[icode
].operand
[3].mode
;
7236 mode4
= insn_data
[icode
].operand
[4].mode
;
7238 /* Do some correctness checks for the operands. */
7239 if ( (!(*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
7240 || !(UNSIGNED_INT8 (INTVAL (op0
))))
7241 error ("operand 4 of %s instruction should be an unsigned 8-bit value (0-255)",
7244 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op2
, mode2
))
7245 || !(UNSIGNED_INT3 (INTVAL (op2
))))
7246 error ("operand 3 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7249 if (!(*insn_data
[icode
].operand
[3].predicate
) (op3
, mode3
))
7250 op3
= copy_to_mode_reg (mode3
, op3
);
7252 if ( (!(*insn_data
[icode
].operand
[4].predicate
) (op4
, mode4
))
7253 || !(UNSIGNED_INT3 (INTVAL (op4
))))
7254 error ("operand 2 of %s instruction should be an unsigned 3-bit value (subreg 0-7)",
7256 else if (icode
== CODE_FOR_vst32_n_insn
7257 && ((INTVAL(op4
) % 2 ) != 0))
7258 error ("operand 2 of %s instruction should be an even 3-bit value (subreg 0,2,4,6)",
7261 pat
= GEN_FCN (icode
) (op0
, op1
, op2
, op3
, op4
);
7275 arc_preserve_reload_p (rtx in
)
7277 return (GET_CODE (in
) == PLUS
7278 && RTX_OK_FOR_BASE_P (XEXP (in
, 0), true)
7279 && CONST_INT_P (XEXP (in
, 1))
7280 && !((INTVAL (XEXP (in
, 1)) & 511)));
7284 arc_register_move_cost (enum machine_mode
,
7285 enum reg_class from_class
, enum reg_class to_class
)
7287 /* The ARC600 has no bypass for extension registers, hence a nop might be
7288 needed to be inserted after a write so that reads are safe. */
7291 if (to_class
== MPY_WRITABLE_CORE_REGS
)
7293 /* Instructions modifying LP_COUNT need 4 additional cycles before
7294 the register will actually contain the value. */
7295 else if (to_class
== LPCOUNT_REG
)
7297 else if (to_class
== WRITABLE_CORE_REGS
)
7301 /* The ARC700 stalls for 3 cycles when *reading* from lp_count. */
7303 && (from_class
== LPCOUNT_REG
|| from_class
== ALL_CORE_REGS
7304 || from_class
== WRITABLE_CORE_REGS
))
7307 /* Force an attempt to 'mov Dy,Dx' to spill. */
7308 if (TARGET_ARC700
&& TARGET_DPFP
7309 && from_class
== DOUBLE_REGS
&& to_class
== DOUBLE_REGS
)
7315 /* Emit code for an addsi3 instruction with OPERANDS.
7316 COND_P indicates if this will use conditional execution.
7317 Return the length of the instruction.
7318 If OUTPUT_P is false, don't actually output the instruction, just return
7321 arc_output_addsi (rtx
*operands
, bool cond_p
, bool output_p
)
7325 int match
= operands_match_p (operands
[0], operands
[1]);
7326 int match2
= operands_match_p (operands
[0], operands
[2]);
7327 int intval
= (REG_P (operands
[2]) ? 1
7328 : CONST_INT_P (operands
[2]) ? INTVAL (operands
[2]) : 0xbadc057);
7329 int neg_intval
= -intval
;
7330 int short_0
= satisfies_constraint_Rcq (operands
[0]);
7331 int short_p
= (!cond_p
&& short_0
&& satisfies_constraint_Rcq (operands
[1]));
7334 #define ADDSI_OUTPUT1(FORMAT) do {\
7336 output_asm_insn (FORMAT, operands);\
7339 #define ADDSI_OUTPUT(LIST) do {\
7342 ADDSI_OUTPUT1 (format);\
7346 /* First try to emit a 16 bit insn. */
7349 /* If we are actually about to output this insn, don't try a 16 bit
7350 variant if we already decided that we don't want that
7351 (I.e. we upsized this insn to align some following insn.)
7352 E.g. add_s r0,sp,70 is 16 bit, but add r0,sp,70 requires a LIMM -
7353 but add1 r0,sp,35 doesn't. */
7354 && (!output_p
|| (get_attr_length (current_output_insn
) & 2)))
7357 && (REG_P (operands
[2])
7358 ? (match
|| satisfies_constraint_Rcq (operands
[2]))
7359 : (unsigned) intval
<= (match
? 127 : 7)))
7360 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7361 if (short_0
&& REG_P (operands
[1]) && match2
)
7362 ADDSI_OUTPUT1 ("add%? %0,%2,%1");
7363 if ((short_0
|| REGNO (operands
[0]) == STACK_POINTER_REGNUM
)
7364 && REGNO (operands
[1]) == STACK_POINTER_REGNUM
&& !(intval
& ~124))
7365 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7367 if ((short_p
&& (unsigned) neg_intval
<= (match
? 31 : 7))
7368 || (REGNO (operands
[0]) == STACK_POINTER_REGNUM
7369 && match
&& !(neg_intval
& ~124)))
7370 ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
7373 /* Now try to emit a 32 bit insn without long immediate. */
7375 if (!match
&& match2
&& REG_P (operands
[1]))
7376 ADDSI_OUTPUT1 ("add%? %0,%2,%1");
7377 if (match
|| !cond_p
)
7379 int limit
= (match
&& !cond_p
) ? 0x7ff : 0x3f;
7380 int range_factor
= neg_intval
& intval
;
7383 if (intval
== -1 << 31)
7384 ADDSI_OUTPUT1 ("bxor%? %0,%1,31");
7386 /* If we can use a straight add / sub instead of a {add,sub}[123] of
7387 same size, do, so - the insn latency is lower. */
7388 /* -0x800 is a 12-bit constant for add /add3 / sub / sub3, but
7390 if ((intval
>= 0 && intval
<= limit
)
7391 || (intval
== -0x800 && limit
== 0x7ff))
7392 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7393 else if ((intval
< 0 && neg_intval
<= limit
)
7394 || (intval
== 0x800 && limit
== 0x7ff))
7395 ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
7396 shift
= range_factor
>= 8 ? 3 : (range_factor
>> 1);
7397 gcc_assert (shift
== 0 || shift
== 1 || shift
== 2 || shift
== 3);
7398 gcc_assert ((((1 << shift
) - 1) & intval
) == 0);
7399 if (((intval
< 0 && intval
!= -0x4000)
7400 /* sub[123] is slower than add_s / sub, only use it if it
7401 avoids a long immediate. */
7402 && neg_intval
<= limit
<< shift
)
7403 || (intval
== 0x4000 && limit
== 0x7ff))
7404 ADDSI_OUTPUT ((format
, "sub%d%%? %%0,%%1,%d",
7405 shift
, neg_intval
>> shift
));
7406 else if ((intval
>= 0 && intval
<= limit
<< shift
)
7407 || (intval
== -0x4000 && limit
== 0x7ff))
7408 ADDSI_OUTPUT ((format
, "add%d%%? %%0,%%1,%d", shift
, intval
>> shift
));
7410 /* Try to emit a 16 bit opcode with long immediate. */
7412 if (short_p
&& match
)
7413 ADDSI_OUTPUT1 ("add%? %0,%1,%S2");
7415 /* We have to use a 32 bit opcode, and with a long immediate. */
7417 ADDSI_OUTPUT1 (intval
< 0 ? "sub%? %0,%1,%n2" : "add%? %0,%1,%S2");
7420 /* Emit code for an commutative_cond_exec instruction with OPERANDS.
7421 Return the length of the instruction.
7422 If OUTPUT_P is false, don't actually output the instruction, just return
7425 arc_output_commutative_cond_exec (rtx
*operands
, bool output_p
)
7427 enum rtx_code commutative_op
= GET_CODE (operands
[3]);
7428 const char *pat
= NULL
;
7430 /* Canonical rtl should not have a constant in the first operand position. */
7431 gcc_assert (!CONSTANT_P (operands
[1]));
7433 switch (commutative_op
)
7436 if (satisfies_constraint_C1p (operands
[2]))
7437 pat
= "bmsk%? %0,%1,%Z2";
7438 else if (satisfies_constraint_Ccp (operands
[2]))
7439 pat
= "bclr%? %0,%1,%M2";
7440 else if (satisfies_constraint_CnL (operands
[2]))
7441 pat
= "bic%? %0,%1,%n2-1";
7444 if (satisfies_constraint_C0p (operands
[2]))
7445 pat
= "bset%? %0,%1,%z2";
7448 if (satisfies_constraint_C0p (operands
[2]))
7449 pat
= "bxor%? %0,%1,%z2";
7452 return arc_output_addsi (operands
, true, output_p
);
7456 output_asm_insn (pat
? pat
: "%O3.%d5 %0,%1,%2", operands
);
7457 if (pat
|| REG_P (operands
[2]) || satisfies_constraint_L (operands
[2]))
7462 /* Helper function of arc_expand_movmem. ADDR points to a chunk of memory.
7463 Emit code and return an potentially modified address such that offsets
7464 up to SIZE are can be added to yield a legitimate address.
7465 if REUSE is set, ADDR is a register that may be modified. */
7468 force_offsettable (rtx addr
, HOST_WIDE_INT size
, bool reuse
)
7471 rtx offs
= const0_rtx
;
7473 if (GET_CODE (base
) == PLUS
)
7475 offs
= XEXP (base
, 1);
7476 base
= XEXP (base
, 0);
7479 || (REGNO (base
) != STACK_POINTER_REGNUM
7480 && REGNO_PTR_FRAME_P (REGNO (addr
)))
7481 || !CONST_INT_P (offs
) || !SMALL_INT (INTVAL (offs
))
7482 || !SMALL_INT (INTVAL (offs
) + size
))
7485 emit_insn (gen_add2_insn (addr
, offs
));
7487 addr
= copy_to_mode_reg (Pmode
, addr
);
7492 /* Like move_by_pieces, but take account of load latency,
7493 and actual offset ranges.
7494 Return true on success. */
7497 arc_expand_movmem (rtx
*operands
)
7499 rtx dst
= operands
[0];
7500 rtx src
= operands
[1];
7501 rtx dst_addr
, src_addr
;
7503 int align
= INTVAL (operands
[3]);
7510 if (!CONST_INT_P (operands
[2]))
7512 size
= INTVAL (operands
[2]);
7513 /* move_by_pieces_ninsns is static, so we can't use it. */
7515 n_pieces
= (size
+ 2) / 4U + (size
& 1);
7516 else if (align
== 2)
7517 n_pieces
= (size
+ 1) / 2U;
7520 if (n_pieces
>= (unsigned int) (optimize_size
? 3 : 15))
7524 dst_addr
= force_offsettable (XEXP (operands
[0], 0), size
, 0);
7525 src_addr
= force_offsettable (XEXP (operands
[1], 0), size
, 0);
7526 store
[0] = store
[1] = NULL_RTX
;
7527 tmpx
[0] = tmpx
[1] = NULL_RTX
;
7528 for (i
= 0; size
> 0; i
^= 1, size
-= piece
)
7531 enum machine_mode mode
;
7534 piece
= size
& -size
;
7535 mode
= smallest_mode_for_size (piece
* BITS_PER_UNIT
, MODE_INT
);
7536 /* If we don't re-use temporaries, the scheduler gets carried away,
7537 and the register pressure gets unnecessarily high. */
7538 if (0 && tmpx
[i
] && GET_MODE (tmpx
[i
]) == mode
)
7541 tmpx
[i
] = tmp
= gen_reg_rtx (mode
);
7542 dst_addr
= force_offsettable (dst_addr
, piece
, 1);
7543 src_addr
= force_offsettable (src_addr
, piece
, 1);
7545 emit_insn (store
[i
]);
7546 emit_move_insn (tmp
, change_address (src
, mode
, src_addr
));
7547 store
[i
] = gen_move_insn (change_address (dst
, mode
, dst_addr
), tmp
);
7548 dst_addr
= plus_constant (Pmode
, dst_addr
, piece
);
7549 src_addr
= plus_constant (Pmode
, src_addr
, piece
);
7552 emit_insn (store
[i
]);
7554 emit_insn (store
[i
^1]);
7558 /* Prepare operands for move in MODE. Return true iff the move has
7562 prepare_move_operands (rtx
*operands
, enum machine_mode mode
)
7564 /* We used to do this only for MODE_INT Modes, but addresses to floating
7565 point variables may well be in the small data section. */
7568 if (!TARGET_NO_SDATA_SET
&& small_data_pattern (operands
[0], Pmode
))
7569 operands
[0] = arc_rewrite_small_data (operands
[0]);
7570 else if (mode
== SImode
&& flag_pic
&& SYMBOLIC_CONST (operands
[1]))
7572 emit_pic_move (operands
, SImode
);
7574 /* Disable any REG_EQUALs associated with the symref
7575 otherwise the optimization pass undoes the work done
7576 here and references the variable directly. */
7578 else if (GET_CODE (operands
[0]) != MEM
7579 && !TARGET_NO_SDATA_SET
7580 && small_data_pattern (operands
[1], Pmode
))
7582 /* This is to take care of address calculations involving sdata
7584 operands
[1] = arc_rewrite_small_data (operands
[1]);
7586 emit_insn (gen_rtx_SET (mode
, operands
[0],operands
[1]));
7587 /* ??? This note is useless, since it only restates the set itself.
7588 We should rather use the original SYMBOL_REF. However, there is
7589 the problem that we are lying to the compiler about these
7590 SYMBOL_REFs to start with. symbol@sda should be encoded specially
7591 so that we can tell it apart from an actual symbol. */
7592 set_unique_reg_note (get_last_insn (), REG_EQUAL
, operands
[1]);
7594 /* Take care of the REG_EQUAL note that will be attached to mark the
7595 output reg equal to the initial symbol_ref after this code is
7597 emit_move_insn (operands
[0], operands
[0]);
7602 if (MEM_P (operands
[0])
7603 && !(reload_in_progress
|| reload_completed
))
7605 operands
[1] = force_reg (mode
, operands
[1]);
7606 if (!move_dest_operand (operands
[0], mode
))
7608 rtx addr
= copy_to_mode_reg (Pmode
, XEXP (operands
[0], 0));
7609 /* This is like change_address_1 (operands[0], mode, 0, 1) ,
7610 except that we can't use that function because it is static. */
7611 rtx pat
= change_address (operands
[0], mode
, addr
);
7612 MEM_COPY_ATTRIBUTES (pat
, operands
[0]);
7615 if (!cse_not_expected
)
7617 rtx pat
= XEXP (operands
[0], 0);
7619 pat
= arc_legitimize_address_0 (pat
, pat
, mode
);
7622 pat
= change_address (operands
[0], mode
, pat
);
7623 MEM_COPY_ATTRIBUTES (pat
, operands
[0]);
7629 if (MEM_P (operands
[1]) && !cse_not_expected
)
7631 rtx pat
= XEXP (operands
[1], 0);
7633 pat
= arc_legitimize_address_0 (pat
, pat
, mode
);
7636 pat
= change_address (operands
[1], mode
, pat
);
7637 MEM_COPY_ATTRIBUTES (pat
, operands
[1]);
7645 /* Prepare OPERANDS for an extension using CODE to OMODE.
7646 Return true iff the move has been emitted. */
7649 prepare_extend_operands (rtx
*operands
, enum rtx_code code
,
7650 enum machine_mode omode
)
7652 if (!TARGET_NO_SDATA_SET
&& small_data_pattern (operands
[1], Pmode
))
7654 /* This is to take care of address calculations involving sdata
7657 = gen_rtx_fmt_e (code
, omode
, arc_rewrite_small_data (operands
[1]));
7658 emit_insn (gen_rtx_SET (omode
, operands
[0], operands
[1]));
7659 set_unique_reg_note (get_last_insn (), REG_EQUAL
, operands
[1]);
7661 /* Take care of the REG_EQUAL note that will be attached to mark the
7662 output reg equal to the initial extension after this code is
7664 emit_move_insn (operands
[0], operands
[0]);
7670 /* Output a library call to a function called FNAME that has been arranged
7671 to be local to any dso. */
7674 arc_output_libcall (const char *fname
)
7676 unsigned len
= strlen (fname
);
7677 static char buf
[64];
7679 gcc_assert (len
< sizeof buf
- 35);
7680 if (TARGET_LONG_CALLS_SET
7681 || (TARGET_MEDIUM_CALLS
&& arc_ccfsm_cond_exec_p ()))
7684 sprintf (buf
, "add r12,pcl,@%s-(.&-4)\n\tjl%%!%%* [r12]", fname
);
7686 sprintf (buf
, "jl%%! @%s", fname
);
7689 sprintf (buf
, "bl%%!%%* @%s", fname
);
7693 /* Return the SImode highpart of the DImode value IN. */
7696 disi_highpart (rtx in
)
7698 return simplify_gen_subreg (SImode
, in
, DImode
, TARGET_BIG_ENDIAN
? 0 : 4);
7701 /* Called by arc600_corereg_hazard via for_each_rtx.
7702 If a hazard is found, return a conservative estimate of the required
7703 length adjustment to accomodate a nop. */
7706 arc600_corereg_hazard_1 (rtx
*xp
, void *data
)
7710 rtx pat
= (rtx
) data
;
7712 switch (GET_CODE (x
))
7714 case SET
: case POST_INC
: case POST_DEC
: case PRE_INC
: case PRE_DEC
:
7717 /* This is also fine for PRE/POST_MODIFY, because they contain a SET. */
7721 /* Check if this sets a an extension register. N.B. we use 61 for the
7722 condition codes, which is definitely not an extension register. */
7723 if (REG_P (dest
) && REGNO (dest
) >= 32 && REGNO (dest
) < 61
7724 /* Check if the same register is used by the PAT. */
7725 && (refers_to_regno_p
7727 REGNO (dest
) + (GET_MODE_SIZE (GET_MODE (dest
)) + 3) / 4U, pat
, 0)))
7733 /* Return length adjustment for INSN.
7735 A write to a core reg greater or equal to 32 must not be immediately
7736 followed by a use. Anticipate the length requirement to insert a nop
7737 between PRED and SUCC to prevent a hazard. */
7740 arc600_corereg_hazard (rtx pred
, rtx succ
)
7744 /* If SUCC is a doloop_end_i with a preceding label, we must output a nop
7745 in front of SUCC anyway, so there will be separation between PRED and
7747 if (recog_memoized (succ
) == CODE_FOR_doloop_end_i
7748 && LABEL_P (prev_nonnote_insn (succ
)))
7750 if (recog_memoized (succ
) == CODE_FOR_doloop_begin_i
)
7752 if (GET_CODE (PATTERN (pred
)) == SEQUENCE
)
7753 pred
= XVECEXP (PATTERN (pred
), 0, 1);
7754 if (GET_CODE (PATTERN (succ
)) == SEQUENCE
)
7755 succ
= XVECEXP (PATTERN (succ
), 0, 0);
7756 if (recog_memoized (pred
) == CODE_FOR_mulsi_600
7757 || recog_memoized (pred
) == CODE_FOR_umul_600
7758 || recog_memoized (pred
) == CODE_FOR_mac_600
7759 || recog_memoized (pred
) == CODE_FOR_mul64_600
7760 || recog_memoized (pred
) == CODE_FOR_mac64_600
7761 || recog_memoized (pred
) == CODE_FOR_umul64_600
7762 || recog_memoized (pred
) == CODE_FOR_umac64_600
)
7764 return for_each_rtx (&PATTERN (pred
), arc600_corereg_hazard_1
,
7769 A write to a core reg greater or equal to 32 must not be immediately
7770 followed by a use. Anticipate the length requirement to insert a nop
7771 between PRED and SUCC to prevent a hazard. */
7774 arc_hazard (rtx pred
, rtx succ
)
7778 if (!pred
|| !INSN_P (pred
) || !succ
|| !INSN_P (succ
))
7780 /* We might have a CALL to a non-returning function before a loop end.
7781 ??? Although the manual says that's OK (the target is outside the loop,
7782 and the loop counter unused there), the assembler barfs on this, so we
7783 must instert a nop before such a call too. */
7784 if (recog_memoized (succ
) == CODE_FOR_doloop_end_i
7785 && (JUMP_P (pred
) || CALL_P (pred
)
7786 || GET_CODE (PATTERN (pred
)) == SEQUENCE
))
7788 return arc600_corereg_hazard (pred
, succ
);
7791 /* Return length adjustment for INSN. */
7794 arc_adjust_insn_length (rtx insn
, int len
, bool)
7798 /* We already handle sequences by ignoring the delay sequence flag. */
7799 if (GET_CODE (PATTERN (insn
)) == SEQUENCE
)
7802 /* It is impossible to jump to the very end of a Zero-Overhead Loop, as
7803 the ZOL mechanism only triggers when advancing to the end address,
7804 so if there's a label at the end of a ZOL, we need to insert a nop.
7805 The ARC600 ZOL also has extra restrictions on jumps at the end of a
7807 if (recog_memoized (insn
) == CODE_FOR_doloop_end_i
)
7809 rtx prev
= prev_nonnote_insn (insn
);
7811 return ((LABEL_P (prev
)
7814 || CALL_P (prev
) /* Could be a noreturn call. */
7815 || (NONJUMP_INSN_P (prev
)
7816 && GET_CODE (PATTERN (prev
)) == SEQUENCE
))))
7820 /* Check for return with but one preceding insn since function
7822 if (TARGET_PAD_RETURN
7824 && GET_CODE (PATTERN (insn
)) != ADDR_VEC
7825 && GET_CODE (PATTERN (insn
)) != ADDR_DIFF_VEC
7826 && get_attr_type (insn
) == TYPE_RETURN
)
7828 rtx prev
= prev_active_insn (insn
);
7830 if (!prev
|| !(prev
= prev_active_insn (prev
))
7831 || ((NONJUMP_INSN_P (prev
)
7832 && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
7833 ? CALL_ATTR (XVECEXP (PATTERN (prev
), 0, 0), NON_SIBCALL
)
7834 : CALL_ATTR (prev
, NON_SIBCALL
)))
7839 rtx succ
= next_real_insn (insn
);
7841 /* One the ARC600, a write to an extension register must be separated
7843 if (succ
&& INSN_P (succ
))
7844 len
+= arc600_corereg_hazard (insn
, succ
);
7847 /* Restore extracted operands - otherwise splitters like the addsi3_mixed one
7849 extract_constrain_insn_cached (insn
);
7854 /* Values for length_sensitive. */
7858 ARC_LS_25
, // 25 bit offset, B
7859 ARC_LS_21
, // 21 bit offset, Bcc
7860 ARC_LS_U13
,// 13 bit unsigned offset, LP
7861 ARC_LS_10
, // 10 bit offset, B_s, Beq_s, Bne_s
7862 ARC_LS_9
, // 9 bit offset, BRcc
7863 ARC_LS_8
, // 8 bit offset, BRcc_s
7864 ARC_LS_U7
, // 7 bit unsigned offset, LPcc
7865 ARC_LS_7
// 7 bit offset, Bcc_s
7868 /* While the infrastructure patch is waiting for review, duplicate the
7869 struct definitions, to allow this file to compile. */
7874 /* Cost as a branch / call target or call return address. */
7876 int fallthrough_cost
;
7879 /* 0 for not length sensitive, 1 for largest offset range,
7880 * 2 for next smaller etc. */
7881 unsigned length_sensitive
: 8;
7883 } insn_length_variant_t
;
7885 typedef struct insn_length_parameters_s
7890 int (*get_variants
) (rtx
, int, bool, bool, insn_length_variant_t
*);
7891 } insn_length_parameters_t
;
7894 arc_insn_length_parameters (insn_length_parameters_t
*ilp
) ATTRIBUTE_UNUSED
;
7898 arc_get_insn_variants (rtx insn
, int len
, bool, bool target_p
,
7899 insn_length_variant_t
*ilv
)
7901 if (!NONDEBUG_INSN_P (insn
))
7903 enum attr_type type
;
7904 /* shorten_branches doesn't take optimize_size into account yet for the
7905 get_variants mechanism, so turn this off for now. */
7908 if (GET_CODE (PATTERN (insn
)) == SEQUENCE
)
7910 /* The interaction of a short delay slot insn with a short branch is
7911 too weird for shorten_branches to piece together, so describe the
7914 if (TARGET_UPSIZE_DBR
7915 && get_attr_length (XVECEXP ((pat
= PATTERN (insn
)), 0, 1)) <= 2
7916 && (((type
= get_attr_type (inner
= XVECEXP (pat
, 0, 0)))
7917 == TYPE_UNCOND_BRANCH
)
7918 || type
== TYPE_BRANCH
)
7919 && get_attr_delay_slot_filled (inner
) == DELAY_SLOT_FILLED_YES
)
7922 = arc_get_insn_variants (inner
, get_attr_length (inner
), true,
7924 /* The short variant gets split into a higher-cost aligned
7925 and a lower cost unaligned variant. */
7926 gcc_assert (n_variants
);
7927 gcc_assert (ilv
[1].length_sensitive
== ARC_LS_7
7928 || ilv
[1].length_sensitive
== ARC_LS_10
);
7929 gcc_assert (ilv
[1].align_set
== 3);
7931 ilv
[0].align_set
= 1;
7932 ilv
[0].branch_cost
+= 1;
7933 ilv
[1].align_set
= 2;
7935 for (int i
= 0; i
< n_variants
; i
++)
7937 /* In case an instruction with aligned size is wanted, and
7938 the short variants are unavailable / too expensive, add
7939 versions of long branch + long delay slot. */
7940 for (int i
= 2, end
= n_variants
; i
< end
; i
++, n_variants
++)
7942 ilv
[n_variants
] = ilv
[i
];
7943 ilv
[n_variants
].length
+= 2;
7949 insn_length_variant_t
*first_ilv
= ilv
;
7950 type
= get_attr_type (insn
);
7952 = (get_attr_delay_slot_filled (insn
) == DELAY_SLOT_FILLED_YES
);
7953 int branch_align_cost
= delay_filled
? 0 : 1;
7954 int branch_unalign_cost
= delay_filled
? 0 : TARGET_UNALIGN_BRANCH
? 0 : 1;
7955 /* If the previous instruction is an sfunc call, this insn is always
7956 a target, even though the middle-end is unaware of this. */
7957 bool force_target
= false;
7958 rtx prev
= prev_active_insn (insn
);
7959 if (prev
&& arc_next_active_insn (prev
, 0) == insn
7960 && ((NONJUMP_INSN_P (prev
) && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
7961 ? CALL_ATTR (XVECEXP (PATTERN (prev
), 0, 0), NON_SIBCALL
)
7962 : (CALL_ATTR (prev
, NON_SIBCALL
)
7963 && NEXT_INSN (PREV_INSN (prev
)) == prev
)))
7964 force_target
= true;
7969 /* Short BRCC only comes in no-delay-slot version, and without limm */
7974 ilv
->branch_cost
= 1;
7975 ilv
->enabled
= (len
== 2);
7976 ilv
->length_sensitive
= ARC_LS_8
;
7980 case TYPE_BRCC_NO_DELAY_SLOT
:
7981 /* doloop_fallback* patterns are TYPE_BRCC_NO_DELAY_SLOT for
7982 (delay slot) scheduling purposes, but they are longer. */
7983 if (GET_CODE (PATTERN (insn
)) == PARALLEL
7984 && GET_CODE (XVECEXP (PATTERN (insn
), 0, 1)) == SET
)
7986 /* Standard BRCC: 4 bytes, or 8 bytes with limm. */
7987 ilv
->length
= ((type
== TYPE_BRCC
) ? 4 : 8);
7989 ilv
->branch_cost
= branch_align_cost
;
7990 ilv
->enabled
= (len
<= ilv
->length
);
7991 ilv
->length_sensitive
= ARC_LS_9
;
7992 if ((target_p
|| force_target
)
7993 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
7999 ilv
->target_cost
= 1;
8000 ilv
->branch_cost
= branch_unalign_cost
;
8005 op
= XEXP (SET_SRC (XVECEXP (PATTERN (insn
), 0, 0)), 0);
8008 if (GET_CODE (op0
) == ZERO_EXTRACT
8009 && satisfies_constraint_L (XEXP (op0
, 2)))
8010 op0
= XEXP (op0
, 0);
8011 if (satisfies_constraint_Rcq (op0
))
8013 ilv
->length
= ((type
== TYPE_BRCC
) ? 6 : 10);
8015 ilv
->branch_cost
= 1 + branch_align_cost
;
8016 ilv
->fallthrough_cost
= 1;
8017 ilv
->enabled
= true;
8018 ilv
->length_sensitive
= ARC_LS_21
;
8019 if (!delay_filled
&& TARGET_UNALIGN_BRANCH
)
8025 ilv
->branch_cost
= 1 + branch_unalign_cost
;
8029 ilv
->length
= ((type
== TYPE_BRCC
) ? 8 : 12);
8031 ilv
->branch_cost
= 1 + branch_align_cost
;
8032 ilv
->fallthrough_cost
= 1;
8033 ilv
->enabled
= true;
8034 ilv
->length_sensitive
= ARC_LS_21
;
8035 if ((target_p
|| force_target
)
8036 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8042 ilv
->target_cost
= 1;
8043 ilv
->branch_cost
= 1 + branch_unalign_cost
;
8051 case TYPE_CALL_NO_DELAY_SLOT
:
8056 ilv
->length_sensitive
8057 = GET_CODE (PATTERN (insn
)) == COND_EXEC
? ARC_LS_21
: ARC_LS_25
;
8060 ilv
->fallthrough_cost
= branch_align_cost
;
8061 ilv
->enabled
= true;
8062 if ((target_p
|| force_target
)
8063 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8069 ilv
->target_cost
= 1;
8070 ilv
->fallthrough_cost
= branch_unalign_cost
;
8074 case TYPE_UNCOND_BRANCH
:
8075 /* Strictly speaking, this should be ARC_LS_10 for equality comparisons,
8076 but that makes no difference at the moment. */
8077 ilv
->length_sensitive
= ARC_LS_7
;
8078 ilv
[1].length_sensitive
= ARC_LS_25
;
8081 ilv
->length_sensitive
= ARC_LS_10
;
8082 ilv
[1].length_sensitive
= ARC_LS_21
;
8086 ilv
->branch_cost
= branch_align_cost
;
8087 ilv
->enabled
= (len
== ilv
->length
);
8091 ilv
->branch_cost
= branch_align_cost
;
8092 ilv
->enabled
= true;
8093 if ((target_p
|| force_target
)
8094 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8100 ilv
->target_cost
= 1;
8101 ilv
->branch_cost
= branch_unalign_cost
;
8108 /* For every short insn, there is generally also a long insn.
8109 trap_s is an exception. */
8110 if ((len
& 2) == 0 || recog_memoized (insn
) == CODE_FOR_trap_s
)
8117 ilv
->length
= len
+ 2;
8119 if (target_p
|| force_target
)
8125 ilv
->target_cost
= 1;
8129 /* If the previous instruction is an sfunc call, this insn is always
8130 a target, even though the middle-end is unaware of this.
8131 Therefore, if we have a call predecessor, transfer the target cost
8132 to the fallthrough and branch costs. */
8135 for (insn_length_variant_t
*p
= first_ilv
; p
< ilv
; p
++)
8137 p
->fallthrough_cost
+= p
->target_cost
;
8138 p
->branch_cost
+= p
->target_cost
;
8143 return ilv
- first_ilv
;
8147 arc_insn_length_parameters (insn_length_parameters_t
*ilp
)
8149 ilp
->align_unit_log
= 1;
8150 ilp
->align_base_log
= 1;
8151 ilp
->max_variants
= 7;
8152 ilp
->get_variants
= arc_get_insn_variants
;
8155 /* Return a copy of COND from *STATEP, inverted if that is indicated by the
8156 CC field of *STATEP. */
8159 arc_get_ccfsm_cond (struct arc_ccfsm
*statep
, bool reverse
)
8161 rtx cond
= statep
->cond
;
8162 int raw_cc
= get_arc_condition_code (cond
);
8164 raw_cc
= ARC_INVERSE_CONDITION_CODE (raw_cc
);
8166 if (statep
->cc
== raw_cc
)
8167 return copy_rtx (cond
);
8169 gcc_assert (ARC_INVERSE_CONDITION_CODE (raw_cc
) == statep
->cc
);
8171 enum machine_mode ccm
= GET_MODE (XEXP (cond
, 0));
8172 enum rtx_code code
= reverse_condition (GET_CODE (cond
));
8173 if (code
== UNKNOWN
|| ccm
== CC_FP_GTmode
|| ccm
== CC_FP_GEmode
)
8174 code
= reverse_condition_maybe_unordered (GET_CODE (cond
));
8176 return gen_rtx_fmt_ee (code
, GET_MODE (cond
),
8177 copy_rtx (XEXP (cond
, 0)), copy_rtx (XEXP (cond
, 1)));
8180 /* Return version of PAT conditionalized with COND, which is part of INSN.
8181 ANNULLED indicates if INSN is an annulled delay-slot insn.
8182 Register further changes if necessary. */
8184 conditionalize_nonjump (rtx pat
, rtx cond
, rtx insn
, bool annulled
)
8186 /* For commutative operators, we generally prefer to have
8187 the first source match the destination. */
8188 if (GET_CODE (pat
) == SET
)
8190 rtx src
= SET_SRC (pat
);
8192 if (COMMUTATIVE_P (src
))
8194 rtx src0
= XEXP (src
, 0);
8195 rtx src1
= XEXP (src
, 1);
8196 rtx dst
= SET_DEST (pat
);
8198 if (rtx_equal_p (src1
, dst
) && !rtx_equal_p (src0
, dst
)
8199 /* Leave add_n alone - the canonical form is to
8200 have the complex summand first. */
8202 pat
= gen_rtx_SET (VOIDmode
, dst
,
8203 gen_rtx_fmt_ee (GET_CODE (src
), GET_MODE (src
),
8208 /* dwarf2out.c:dwarf2out_frame_debug_expr doesn't know
8209 what to do with COND_EXEC. */
8210 if (RTX_FRAME_RELATED_P (insn
))
8212 /* If this is the delay slot insn of an anulled branch,
8213 dwarf2out.c:scan_trace understands the anulling semantics
8214 without the COND_EXEC. */
8215 gcc_assert (annulled
);
8216 rtx note
= alloc_reg_note (REG_FRAME_RELATED_EXPR
, pat
,
8218 validate_change (insn
, ®_NOTES (insn
), note
, 1);
8220 pat
= gen_rtx_COND_EXEC (VOIDmode
, cond
, pat
);
8224 /* Use the ccfsm machinery to do if conversion. */
8229 struct arc_ccfsm
*statep
= &cfun
->machine
->ccfsm_current
;
8230 basic_block merge_bb
= 0;
8232 memset (statep
, 0, sizeof *statep
);
8233 for (rtx insn
= get_insns (); insn
; insn
= next_insn (insn
))
8235 arc_ccfsm_advance (insn
, statep
);
8237 switch (statep
->state
)
8245 /* Deleted branch. */
8246 gcc_assert (!merge_bb
);
8247 merge_bb
= BLOCK_FOR_INSN (insn
);
8249 = BLOCK_FOR_INSN (NEXT_INSN (NEXT_INSN (PREV_INSN (insn
))));
8250 arc_ccfsm_post_advance (insn
, statep
);
8251 gcc_assert (!IN_RANGE (statep
->state
, 1, 2));
8252 rtx seq
= NEXT_INSN (PREV_INSN (insn
));
8255 rtx slot
= XVECEXP (PATTERN (seq
), 0, 1);
8256 rtx pat
= PATTERN (slot
);
8257 if (INSN_ANNULLED_BRANCH_P (insn
))
8260 = arc_get_ccfsm_cond (statep
, INSN_FROM_TARGET_P (slot
));
8261 pat
= gen_rtx_COND_EXEC (VOIDmode
, cond
, pat
);
8263 if (!validate_change (seq
, &PATTERN (seq
), pat
, 0))
8265 PUT_CODE (slot
, NOTE
);
8266 NOTE_KIND (slot
) = NOTE_INSN_DELETED
;
8267 if (merge_bb
&& succ_bb
)
8268 merge_blocks (merge_bb
, succ_bb
);
8270 else if (merge_bb
&& succ_bb
)
8272 set_insn_deleted (insn
);
8273 merge_blocks (merge_bb
, succ_bb
);
8277 PUT_CODE (insn
, NOTE
);
8278 NOTE_KIND (insn
) = NOTE_INSN_DELETED
;
8284 && statep
->target_label
== CODE_LABEL_NUMBER (insn
))
8286 arc_ccfsm_post_advance (insn
, statep
);
8287 basic_block succ_bb
= BLOCK_FOR_INSN (insn
);
8288 if (merge_bb
&& succ_bb
)
8289 merge_blocks (merge_bb
, succ_bb
);
8290 else if (--LABEL_NUSES (insn
) == 0)
8292 const char *name
= LABEL_NAME (insn
);
8293 PUT_CODE (insn
, NOTE
);
8294 NOTE_KIND (insn
) = NOTE_INSN_DELETED_LABEL
;
8295 NOTE_DELETED_LABEL_NAME (insn
) = name
;
8302 if (!NONDEBUG_INSN_P (insn
))
8305 /* Conditionalized insn. */
8307 rtx prev
, pprev
, *patp
, pat
, cond
;
8308 bool annulled
; annulled
= false;
8310 /* If this is a delay slot insn in a non-annulled branch,
8311 don't conditionalize it. N.B., this should be fine for
8312 conditional return too. However, don't do this for
8313 unconditional branches, as these would be encountered when
8314 processing an 'else' part. */
8315 prev
= PREV_INSN (insn
);
8316 pprev
= PREV_INSN (prev
);
8317 if (pprev
&& NEXT_INSN (NEXT_INSN (pprev
)) == NEXT_INSN (insn
)
8318 && JUMP_P (prev
) && get_attr_cond (prev
) == COND_USE
)
8320 if (!INSN_ANNULLED_BRANCH_P (prev
))
8325 patp
= &PATTERN (insn
);
8327 cond
= arc_get_ccfsm_cond (statep
, INSN_FROM_TARGET_P (insn
));
8328 if (NONJUMP_INSN_P (insn
) || CALL_P (insn
))
8330 /* ??? don't conditionalize if all side effects are dead
8331 in the not-execute case. */
8333 pat
= conditionalize_nonjump (pat
, cond
, insn
, annulled
);
8335 else if (simplejump_p (insn
))
8337 patp
= &SET_SRC (pat
);
8338 pat
= gen_rtx_IF_THEN_ELSE (VOIDmode
, cond
, *patp
, pc_rtx
);
8340 else if (JUMP_P (insn
) && ANY_RETURN_P (PATTERN (insn
)))
8342 pat
= gen_rtx_IF_THEN_ELSE (VOIDmode
, cond
, pat
, pc_rtx
);
8343 pat
= gen_rtx_SET (VOIDmode
, pc_rtx
, pat
);
8347 validate_change (insn
, patp
, pat
, 1);
8348 if (!apply_change_group ())
8352 rtx next
= next_nonnote_insn (insn
);
8353 if (GET_CODE (next
) == BARRIER
)
8355 if (statep
->state
== 3)
8362 arc_ccfsm_post_advance (insn
, statep
);
8367 /* Find annulled delay insns and convert them to use the appropriate predicate.
8368 This allows branch shortening to size up these insns properly. */
8371 arc_predicate_delay_insns (void)
8373 for (rtx insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
8375 rtx pat
, jump
, dlay
, src
, cond
, *patp
;
8378 if (!NONJUMP_INSN_P (insn
)
8379 || GET_CODE (pat
= PATTERN (insn
)) != SEQUENCE
)
8381 jump
= XVECEXP (pat
, 0, 0);
8382 dlay
= XVECEXP (pat
, 0, 1);
8383 if (!JUMP_P (jump
) || !INSN_ANNULLED_BRANCH_P (jump
))
8385 /* If the branch insn does the annulling, leave the delay insn alone. */
8386 if (!TARGET_AT_DBR_CONDEXEC
&& !INSN_FROM_TARGET_P (dlay
))
8388 /* ??? Could also leave DLAY un-conditionalized if its target is dead
8389 on the other path. */
8390 gcc_assert (GET_CODE (PATTERN (jump
)) == SET
);
8391 gcc_assert (SET_DEST (PATTERN (jump
)) == pc_rtx
);
8392 src
= SET_SRC (PATTERN (jump
));
8393 gcc_assert (GET_CODE (src
) == IF_THEN_ELSE
);
8394 cond
= XEXP (src
, 0);
8395 if (XEXP (src
, 2) == pc_rtx
)
8397 else if (XEXP (src
, 1) == pc_rtx
)
8401 if (!INSN_FROM_TARGET_P (dlay
) != reverse
)
8403 enum machine_mode ccm
= GET_MODE (XEXP (cond
, 0));
8404 enum rtx_code code
= reverse_condition (GET_CODE (cond
));
8405 if (code
== UNKNOWN
|| ccm
== CC_FP_GTmode
|| ccm
== CC_FP_GEmode
)
8406 code
= reverse_condition_maybe_unordered (GET_CODE (cond
));
8408 cond
= gen_rtx_fmt_ee (code
, GET_MODE (cond
),
8409 copy_rtx (XEXP (cond
, 0)),
8410 copy_rtx (XEXP (cond
, 1)));
8413 cond
= copy_rtx (cond
);
8414 patp
= &PATTERN (dlay
);
8416 pat
= conditionalize_nonjump (pat
, cond
, dlay
, true);
8417 validate_change (dlay
, patp
, pat
, 1);
8418 if (!apply_change_group ())
8424 /* For ARC600: If a write to a core reg >=32 appears in a delay slot
8425 (other than of a forward brcc), it creates a hazard when there is a read
8426 of the same register at the branch target. We can't know what is at the
8427 branch target of calls, and for branches, we don't really know before the
8428 end of delay slot scheduling, either. Not only can individual instruction
8429 be hoisted out into a delay slot, a basic block can also be emptied this
8430 way, and branch and/or fall through targets be redirected. Hence we don't
8431 want such writes in a delay slot. */
8432 /* Called by arc_write_ext_corereg via for_each_rtx. */
8435 write_ext_corereg_1 (rtx
*xp
, void *data ATTRIBUTE_UNUSED
)
8440 switch (GET_CODE (x
))
8442 case SET
: case POST_INC
: case POST_DEC
: case PRE_INC
: case PRE_DEC
:
8445 /* This is also fine for PRE/POST_MODIFY, because they contain a SET. */
8449 if (REG_P (dest
) && REGNO (dest
) >= 32 && REGNO (dest
) < 61)
8454 /* Return nonzreo iff INSN writes to an extension core register. */
8457 arc_write_ext_corereg (rtx insn
)
8459 return for_each_rtx (&PATTERN (insn
), write_ext_corereg_1
, 0);
8462 /* This is like the hook, but returns NULL when it can't / won't generate
8463 a legitimate address. */
8466 arc_legitimize_address_0 (rtx x
, rtx oldx ATTRIBUTE_UNUSED
,
8467 enum machine_mode mode
)
8471 if (flag_pic
&& SYMBOLIC_CONST (x
))
8472 (x
) = arc_legitimize_pic_address (x
, 0);
8474 if (GET_CODE (addr
) == CONST
)
8475 addr
= XEXP (addr
, 0);
8476 if (GET_CODE (addr
) == PLUS
8477 && CONST_INT_P (XEXP (addr
, 1))
8478 && ((GET_CODE (XEXP (addr
, 0)) == SYMBOL_REF
8479 && !SYMBOL_REF_FUNCTION_P (XEXP (addr
, 0)))
8480 || (REG_P (XEXP (addr
, 0))
8481 && (INTVAL (XEXP (addr
, 1)) & 252))))
8483 HOST_WIDE_INT offs
, upper
;
8484 int size
= GET_MODE_SIZE (mode
);
8486 offs
= INTVAL (XEXP (addr
, 1));
8487 upper
= (offs
+ 256 * size
) & ~511 * size
;
8488 inner
= plus_constant (Pmode
, XEXP (addr
, 0), upper
);
8489 #if 0 /* ??? this produces worse code for EEMBC idctrn01 */
8490 if (GET_CODE (x
) == CONST
)
8491 inner
= gen_rtx_CONST (Pmode
, inner
);
8493 addr
= plus_constant (Pmode
, force_reg (Pmode
, inner
), offs
- upper
);
8496 else if (GET_CODE (addr
) == SYMBOL_REF
&& !SYMBOL_REF_FUNCTION_P (addr
))
8497 x
= force_reg (Pmode
, x
);
8498 if (memory_address_p ((enum machine_mode
) mode
, x
))
8504 arc_legitimize_address (rtx orig_x
, rtx oldx
, enum machine_mode mode
)
8506 rtx new_x
= arc_legitimize_address_0 (orig_x
, oldx
, mode
);
8514 arc_delegitimize_address_0 (rtx x
)
8518 if (GET_CODE (x
) == CONST
&& GET_CODE (u
= XEXP (x
, 0)) == UNSPEC
)
8520 if (XINT (u
, 1) == ARC_UNSPEC_GOT
)
8521 return XVECEXP (u
, 0, 0);
8523 else if (GET_CODE (x
) == PLUS
8524 && ((REG_P (gp
= XEXP (x
, 0))
8525 && REGNO (gp
) == PIC_OFFSET_TABLE_REGNUM
)
8526 || (GET_CODE (gp
) == CONST
8527 && GET_CODE (u
= XEXP (gp
, 0)) == UNSPEC
8528 && XINT (u
, 1) == ARC_UNSPEC_GOT
8529 && GET_CODE (XVECEXP (u
, 0, 0)) == SYMBOL_REF
8530 && !strcmp (XSTR (XVECEXP (u
, 0, 0), 0), "_DYNAMIC")))
8531 && GET_CODE (XEXP (x
, 1)) == CONST
8532 && GET_CODE (u
= XEXP (XEXP (x
, 1), 0)) == UNSPEC
8533 && XINT (u
, 1) == ARC_UNSPEC_GOTOFF
)
8534 return XVECEXP (u
, 0, 0);
8535 else if (GET_CODE (x
) == PLUS
&& GET_CODE (XEXP (x
, 0)) == PLUS
8536 && ((REG_P (gp
= XEXP (XEXP (x
, 0), 1))
8537 && REGNO (gp
) == PIC_OFFSET_TABLE_REGNUM
)
8538 || (GET_CODE (gp
) == CONST
8539 && GET_CODE (u
= XEXP (gp
, 0)) == UNSPEC
8540 && XINT (u
, 1) == ARC_UNSPEC_GOT
8541 && GET_CODE (XVECEXP (u
, 0, 0)) == SYMBOL_REF
8542 && !strcmp (XSTR (XVECEXP (u
, 0, 0), 0), "_DYNAMIC")))
8543 && GET_CODE (XEXP (x
, 1)) == CONST
8544 && GET_CODE (u
= XEXP (XEXP (x
, 1), 0)) == UNSPEC
8545 && XINT (u
, 1) == ARC_UNSPEC_GOTOFF
)
8546 return gen_rtx_PLUS (GET_MODE (x
), XEXP (XEXP (x
, 0), 0),
8548 else if (GET_CODE (x
) == PLUS
8549 && (u
= arc_delegitimize_address_0 (XEXP (x
, 1))))
8550 return gen_rtx_PLUS (GET_MODE (x
), XEXP (x
, 0), u
);
8555 arc_delegitimize_address (rtx x
)
8557 rtx orig_x
= x
= delegitimize_mem_from_attrs (x
);
8558 if (GET_CODE (x
) == MEM
)
8560 x
= arc_delegitimize_address_0 (x
);
8564 x
= replace_equiv_address_nv (orig_x
, x
);
8570 /* Return a REG rtx for acc1. N.B. the gcc-internal representation may
8571 differ from the hardware register number in order to allow the generic
8572 code to correctly split the concatenation of acc1 and acc2. */
8577 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 56: 57);
8580 /* Return a REG rtx for acc2. N.B. the gcc-internal representation may
8581 differ from the hardware register number in order to allow the generic
8582 code to correctly split the concatenation of acc1 and acc2. */
8587 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 57: 56);
8590 /* Return a REG rtx for mlo. N.B. the gcc-internal representation may
8591 differ from the hardware register number in order to allow the generic
8592 code to correctly split the concatenation of mhi and mlo. */
8597 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 59: 58);
8600 /* Return a REG rtx for mhi. N.B. the gcc-internal representation may
8601 differ from the hardware register number in order to allow the generic
8602 code to correctly split the concatenation of mhi and mlo. */
8607 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 58: 59);
8610 /* FIXME: a parameter should be added, and code added to final.c,
8611 to reproduce this functionality in shorten_branches. */
8613 /* Return nonzero iff BRANCH should be unaligned if possible by upsizing
8614 a previous instruction. */
8616 arc_unalign_branch_p (rtx branch
)
8620 if (!TARGET_UNALIGN_BRANCH
)
8622 /* Do not do this if we have a filled delay slot. */
8623 if (get_attr_delay_slot_filled (branch
) == DELAY_SLOT_FILLED_YES
8624 && !INSN_DELETED_P (NEXT_INSN (branch
)))
8626 note
= find_reg_note (branch
, REG_BR_PROB
, 0);
8628 || (arc_unalign_prob_threshold
&& !br_prob_note_reliable_p (note
))
8629 || INTVAL (XEXP (note
, 0)) < arc_unalign_prob_threshold
);
8633 /* When estimating sizes during arc_reorg, when optimizing for speed, there
8634 are three reasons why we need to consider branches to be length 6:
8635 - annull-false delay slot insns are implemented using conditional execution,
8636 thus preventing short insn formation where used.
8637 - for ARC600: annul-true delay slot insns are implemented where possible
8638 using conditional execution, preventing short insn formation where used.
8639 - for ARC700: likely or somewhat likely taken branches are made long and
8640 unaligned if possible to avoid branch penalty. */
8643 arc_branch_size_unknown_p (void)
8645 return !optimize_size
&& arc_reorg_in_progress
;
8648 /* We are about to output a return insn. Add padding if necessary to avoid
8649 a mispredict. A return could happen immediately after the function
8650 start, but after a call we know that there will be at least a blink
8654 arc_pad_return (void)
8656 rtx insn
= current_output_insn
;
8657 rtx prev
= prev_active_insn (insn
);
8662 fputs ("\tnop_s\n", asm_out_file
);
8663 cfun
->machine
->unalign
^= 2;
8666 /* If PREV is a sequence, we know it must be a branch / jump or a tailcall,
8667 because after a call, we'd have to restore blink first. */
8668 else if (GET_CODE (PATTERN (prev
)) == SEQUENCE
)
8672 want_long
= (get_attr_length (prev
) == 2);
8673 prev
= prev_active_insn (prev
);
8676 || ((NONJUMP_INSN_P (prev
) && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
8677 ? CALL_ATTR (XVECEXP (PATTERN (prev
), 0, 0), NON_SIBCALL
)
8678 : CALL_ATTR (prev
, NON_SIBCALL
)))
8681 cfun
->machine
->size_reason
8682 = "call/return and return/return must be 6 bytes apart to avoid mispredict";
8683 else if (TARGET_UNALIGN_BRANCH
&& cfun
->machine
->unalign
)
8685 cfun
->machine
->size_reason
8686 = "Long unaligned jump avoids non-delay slot penalty";
8689 /* Disgorge delay insn, if there is any, and it may be moved. */
8691 /* ??? Annulled would be OK if we can and do conditionalize
8692 the delay slot insn accordingly. */
8693 && !INSN_ANNULLED_BRANCH_P (insn
)
8694 && (get_attr_cond (insn
) != COND_USE
8695 || !reg_set_p (gen_rtx_REG (CCmode
, CC_REG
),
8696 XVECEXP (final_sequence
, 0, 1))))
8698 prev
= XVECEXP (final_sequence
, 0, 1);
8699 gcc_assert (!prev_real_insn (insn
)
8700 || !arc_hazard (prev_real_insn (insn
), prev
));
8701 cfun
->machine
->force_short_suffix
= !want_long
;
8702 rtx save_pred
= current_insn_predicate
;
8703 final_scan_insn (prev
, asm_out_file
, optimize
, 1, NULL
);
8704 cfun
->machine
->force_short_suffix
= -1;
8705 INSN_DELETED_P (prev
) = 1;
8706 current_output_insn
= insn
;
8707 current_insn_predicate
= save_pred
;
8710 fputs ("\tnop\n", asm_out_file
);
8713 fputs ("\tnop_s\n", asm_out_file
);
8714 cfun
->machine
->unalign
^= 2;
8720 /* The usual; we set up our machine_function data. */
8722 static struct machine_function
*
8723 arc_init_machine_status (void)
8725 struct machine_function
*machine
;
8726 machine
= ggc_cleared_alloc
<machine_function
> ();
8727 machine
->fn_type
= ARC_FUNCTION_UNKNOWN
;
8728 machine
->force_short_suffix
= -1;
8733 /* Implements INIT_EXPANDERS. We just set up to call the above
8737 arc_init_expanders (void)
8739 init_machine_status
= arc_init_machine_status
;
8742 /* Check if OP is a proper parallel of a millicode call pattern. OFFSET
8743 indicates a number of elements to ignore - that allows to have a
8744 sibcall pattern that starts with (return). LOAD_P is zero for store
8745 multiple (for prologues), and one for load multiples (for epilogues),
8746 and two for load multiples where no final clobber of blink is required.
8747 We also skip the first load / store element since this is supposed to
8748 be checked in the instruction pattern. */
8751 arc_check_millicode (rtx op
, int offset
, int load_p
)
8753 int len
= XVECLEN (op
, 0) - offset
;
8758 if (len
< 2 || len
> 13)
8764 rtx elt
= XVECEXP (op
, 0, --len
);
8766 if (GET_CODE (elt
) != CLOBBER
8767 || !REG_P (XEXP (elt
, 0))
8768 || REGNO (XEXP (elt
, 0)) != RETURN_ADDR_REGNUM
8769 || len
< 3 || len
> 13)
8772 for (i
= 1; i
< len
; i
++)
8774 rtx elt
= XVECEXP (op
, 0, i
+ offset
);
8777 if (GET_CODE (elt
) != SET
)
8779 mem
= XEXP (elt
, load_p
);
8780 reg
= XEXP (elt
, 1-load_p
);
8781 if (!REG_P (reg
) || REGNO (reg
) != 13U+i
|| !MEM_P (mem
))
8783 addr
= XEXP (mem
, 0);
8784 if (GET_CODE (addr
) != PLUS
8785 || !rtx_equal_p (stack_pointer_rtx
, XEXP (addr
, 0))
8786 || !CONST_INT_P (XEXP (addr
, 1)) || INTVAL (XEXP (addr
, 1)) != i
*4)
8792 /* Accessor functions for cfun->machine->unalign. */
8795 arc_get_unalign (void)
8797 return cfun
->machine
->unalign
;
8801 arc_clear_unalign (void)
8804 cfun
->machine
->unalign
= 0;
8808 arc_toggle_unalign (void)
8810 cfun
->machine
->unalign
^= 2;
8813 /* Operands 0..2 are the operands of a addsi which uses a 12 bit
8814 constant in operand 2, but which would require a LIMM because of
8816 operands 3 and 4 are new SET_SRCs for operands 0. */
8819 split_addsi (rtx
*operands
)
8821 int val
= INTVAL (operands
[2]);
8823 /* Try for two short insns first. Lengths being equal, we prefer
8824 expansions with shorter register lifetimes. */
8825 if (val
> 127 && val
<= 255
8826 && satisfies_constraint_Rcq (operands
[0]))
8828 operands
[3] = operands
[2];
8829 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[1]);
8833 operands
[3] = operands
[1];
8834 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[2]);
8838 /* Operands 0..2 are the operands of a subsi which uses a 12 bit
8839 constant in operand 1, but which would require a LIMM because of
8841 operands 3 and 4 are new SET_SRCs for operands 0. */
8844 split_subsi (rtx
*operands
)
8846 int val
= INTVAL (operands
[1]);
8848 /* Try for two short insns first. Lengths being equal, we prefer
8849 expansions with shorter register lifetimes. */
8850 if (satisfies_constraint_Rcq (operands
[0])
8851 && satisfies_constraint_Rcq (operands
[2]))
8853 if (val
>= -31 && val
<= 127)
8855 operands
[3] = gen_rtx_NEG (SImode
, operands
[2]);
8856 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[1]);
8859 else if (val
>= 0 && val
< 255)
8861 operands
[3] = operands
[1];
8862 operands
[4] = gen_rtx_MINUS (SImode
, operands
[0], operands
[2]);
8866 /* If the destination is not an ARCompact16 register, we might
8867 still have a chance to make a short insn if the source is;
8868 we need to start with a reg-reg move for this. */
8869 operands
[3] = operands
[2];
8870 operands
[4] = gen_rtx_MINUS (SImode
, operands
[1], operands
[0]);
8873 /* Handle DOUBLE_REGS uses.
8874 Operand 0: destination register
8875 Operand 1: source register */
8878 arc_process_double_reg_moves (rtx
*operands
)
8880 rtx dest
= operands
[0];
8881 rtx src
= operands
[1];
8884 enum usesDxState
{ none
, srcDx
, destDx
, maxDx
};
8885 enum usesDxState state
= none
;
8887 if (refers_to_regno_p (40, 44, src
, 0))
8889 if (refers_to_regno_p (40, 44, dest
, 0))
8891 /* Via arc_register_move_cost, we should never see D,D moves. */
8892 gcc_assert (state
== none
);
8903 /* Without the LR insn, we need to split this into a
8904 sequence of insns which will use the DEXCLx and DADDHxy
8905 insns to be able to read the Dx register in question. */
8906 if (TARGET_DPFP_DISABLE_LRSR
)
8908 /* gen *movdf_insn_nolrsr */
8909 rtx set
= gen_rtx_SET (VOIDmode
, dest
, src
);
8910 rtx use1
= gen_rtx_USE (VOIDmode
, const1_rtx
);
8911 emit_insn (gen_rtx_PARALLEL (VOIDmode
, gen_rtvec (2, set
, use1
)));
8915 /* When we have 'mov D, r' or 'mov D, D' then get the target
8916 register pair for use with LR insn. */
8917 rtx destHigh
= simplify_gen_subreg(SImode
, dest
, DFmode
, 4);
8918 rtx destLow
= simplify_gen_subreg(SImode
, dest
, DFmode
, 0);
8920 /* Produce the two LR insns to get the high and low parts. */
8921 emit_insn (gen_rtx_SET (VOIDmode
,
8923 gen_rtx_UNSPEC_VOLATILE (Pmode
, gen_rtvec (1, src
),
8925 emit_insn (gen_rtx_SET (VOIDmode
,
8927 gen_rtx_UNSPEC_VOLATILE (Pmode
, gen_rtvec (1, src
),
8931 else if (state
== destDx
)
8933 /* When we have 'mov r, D' or 'mov D, D' and we have access to the
8934 LR insn get the target register pair. */
8935 rtx srcHigh
= simplify_gen_subreg(SImode
, src
, DFmode
, 4);
8936 rtx srcLow
= simplify_gen_subreg(SImode
, src
, DFmode
, 0);
8938 emit_insn (gen_rtx_UNSPEC_VOLATILE (Pmode
,
8939 gen_rtvec (3, dest
, srcHigh
, srcLow
),
8940 VUNSPEC_DEXCL_NORES
));
8951 /* operands 0..1 are the operands of a 64 bit move instruction.
8952 split it into two moves with operands 2/3 and 4/5. */
8955 arc_split_move (rtx
*operands
)
8957 enum machine_mode mode
= GET_MODE (operands
[0]);
8965 val
= arc_process_double_reg_moves (operands
);
8970 for (i
= 0; i
< 2; i
++)
8972 if (MEM_P (operands
[i
]) && auto_inc_p (XEXP (operands
[i
], 0)))
8974 rtx addr
= XEXP (operands
[i
], 0);
8978 gcc_assert (!reg_overlap_mentioned_p (operands
[0], addr
));
8979 switch (GET_CODE (addr
))
8981 case PRE_DEC
: o
= GEN_INT (-8); goto pre_modify
;
8982 case PRE_INC
: o
= GEN_INT (8); goto pre_modify
;
8983 case PRE_MODIFY
: o
= XEXP (XEXP (addr
, 1), 1);
8987 case POST_DEC
: o
= GEN_INT (-8); goto post_modify
;
8988 case POST_INC
: o
= GEN_INT (8); goto post_modify
;
8989 case POST_MODIFY
: o
= XEXP (XEXP (addr
, 1), 1);
8998 xop
[0+i
] = adjust_automodify_address_nv
8999 (operands
[i
], SImode
,
9000 gen_rtx_fmt_ee (code
, Pmode
, r
,
9001 gen_rtx_PLUS (Pmode
, r
, o
)),
9003 xop
[2+i
] = adjust_automodify_address_nv
9004 (operands
[i
], SImode
, plus_constant (Pmode
, r
, 4), 4);
9008 xop
[0+i
] = operand_subword (operands
[i
], 0, 0, mode
);
9009 xop
[2+i
] = operand_subword (operands
[i
], 1, 0, mode
);
9012 if (reg_overlap_mentioned_p (xop
[0], xop
[3]))
9015 gcc_assert (!reg_overlap_mentioned_p (xop
[2], xop
[1]));
9017 operands
[2+swap
] = xop
[0];
9018 operands
[3+swap
] = xop
[1];
9019 operands
[4-swap
] = xop
[2];
9020 operands
[5-swap
] = xop
[3];
9023 emit_insn (gen_rtx_SET (VOIDmode
, operands
[2], operands
[3]));
9024 emit_insn (gen_rtx_SET (VOIDmode
, operands
[4], operands
[5]));
9031 /* Select between the instruction output templates s_tmpl (for short INSNs)
9032 and l_tmpl (for long INSNs). */
9035 arc_short_long (rtx insn
, const char *s_tmpl
, const char *l_tmpl
)
9037 int is_short
= arc_verify_short (insn
, cfun
->machine
->unalign
, -1);
9039 extract_constrain_insn_cached (insn
);
9040 return is_short
? s_tmpl
: l_tmpl
;
9043 /* Searches X for any reference to REGNO, returning the rtx of the
9044 reference found if any. Otherwise, returns NULL_RTX. */
9047 arc_regno_use_in (unsigned int regno
, rtx x
)
9053 if (REG_P (x
) && refers_to_regno_p (regno
, regno
+1, x
, (rtx
*) 0))
9056 fmt
= GET_RTX_FORMAT (GET_CODE (x
));
9057 for (i
= GET_RTX_LENGTH (GET_CODE (x
)) - 1; i
>= 0; i
--)
9061 if ((tem
= regno_use_in (regno
, XEXP (x
, i
))))
9064 else if (fmt
[i
] == 'E')
9065 for (j
= XVECLEN (x
, i
) - 1; j
>= 0; j
--)
9066 if ((tem
= regno_use_in (regno
, XVECEXP (x
, i
, j
))))
9073 /* Return the integer value of the "type" attribute for INSN, or -1 if
9074 INSN can't have attributes. */
9077 arc_attr_type (rtx insn
)
9079 if (NONJUMP_INSN_P (insn
)
9080 ? (GET_CODE (PATTERN (insn
)) == USE
9081 || GET_CODE (PATTERN (insn
)) == CLOBBER
)
9083 ? (GET_CODE (PATTERN (insn
)) == ADDR_VEC
9084 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
9087 return get_attr_type (insn
);
9090 /* Return true if insn sets the condition codes. */
9093 arc_sets_cc_p (rtx insn
)
9095 if (NONJUMP_INSN_P (insn
) && GET_CODE (PATTERN (insn
)) == SEQUENCE
)
9096 insn
= XVECEXP (PATTERN (insn
), 0, XVECLEN (PATTERN (insn
), 0) - 1);
9097 return arc_attr_type (insn
) == TYPE_COMPARE
;
9100 /* Return true if INSN is an instruction with a delay slot we may want
9104 arc_need_delay (rtx insn
)
9108 if (!flag_delayed_branch
)
9110 /* The return at the end of a function needs a delay slot. */
9111 if (NONJUMP_INSN_P (insn
) && GET_CODE (PATTERN (insn
)) == USE
9112 && (!(next
= next_active_insn (insn
))
9113 || ((!NONJUMP_INSN_P (next
) || GET_CODE (PATTERN (next
)) != SEQUENCE
)
9114 && arc_attr_type (next
) == TYPE_RETURN
))
9115 && (!TARGET_PAD_RETURN
9116 || (prev_active_insn (insn
)
9117 && prev_active_insn (prev_active_insn (insn
))
9118 && prev_active_insn (prev_active_insn (prev_active_insn (insn
))))))
9120 if (NONJUMP_INSN_P (insn
)
9121 ? (GET_CODE (PATTERN (insn
)) == USE
9122 || GET_CODE (PATTERN (insn
)) == CLOBBER
9123 || GET_CODE (PATTERN (insn
)) == SEQUENCE
)
9125 ? (GET_CODE (PATTERN (insn
)) == ADDR_VEC
9126 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
9129 return num_delay_slots (insn
) != 0;
9132 /* Return true if the scheduling pass(es) has/have already run,
9133 i.e. where possible, we should try to mitigate high latencies
9134 by different instruction selection. */
9137 arc_scheduling_not_expected (void)
9139 return cfun
->machine
->arc_reorg_started
;
9142 /* Oddly enough, sometimes we get a zero overhead loop that branch
9143 shortening doesn't think is a loop - observed with compile/pr24883.c
9144 -O3 -fomit-frame-pointer -funroll-loops. Make sure to include the
9145 alignment visible for branch shortening (we actually align the loop
9146 insn before it, but that is equivalent since the loop insn is 4 byte
9150 arc_label_align (rtx label
)
9152 int loop_align
= LOOP_ALIGN (LABEL
);
9154 if (loop_align
> align_labels_log
)
9156 rtx prev
= prev_nonnote_insn (label
);
9158 if (prev
&& NONJUMP_INSN_P (prev
)
9159 && GET_CODE (PATTERN (prev
)) == PARALLEL
9160 && recog_memoized (prev
) == CODE_FOR_doloop_begin_i
)
9163 /* Code has a minimum p2 alignment of 1, which we must restore after an
9165 if (align_labels_log
< 1)
9167 rtx next
= next_nonnote_nondebug_insn (label
);
9168 if (INSN_P (next
) && recog_memoized (next
) >= 0)
9171 return align_labels_log
;
9174 /* Return true if LABEL is in executable code. */
9177 arc_text_label (rtx label
)
9181 /* ??? We use deleted labels like they were still there, see
9182 gcc.c-torture/compile/20000326-2.c . */
9183 gcc_assert (GET_CODE (label
) == CODE_LABEL
9184 || (GET_CODE (label
) == NOTE
9185 && NOTE_KIND (label
) == NOTE_INSN_DELETED_LABEL
));
9186 next
= next_nonnote_insn (label
);
9188 return (!JUMP_TABLE_DATA_P (next
)
9189 || GET_CODE (PATTERN (next
)) != ADDR_VEC
);
9190 else if (!PREV_INSN (label
))
9191 /* ??? sometimes text labels get inserted very late, see
9192 gcc.dg/torture/stackalign/comp-goto-1.c */
9197 /* Return the size of the pretend args for DECL. */
9200 arc_decl_pretend_args (tree decl
)
9202 /* struct function is in DECL_STRUCT_FUNCTION (decl), but no
9203 pretend_args there... See PR38391. */
9204 gcc_assert (decl
== current_function_decl
);
9205 return crtl
->args
.pretend_args_size
;
9208 /* Without this, gcc.dg/tree-prof/bb-reorg.c fails to assemble
9209 when compiling with -O2 -freorder-blocks-and-partition -fprofile-use
9210 -D_PROFILE_USE; delay branch scheduling then follows a crossing jump
9211 to redirect two breqs. */
9214 arc_can_follow_jump (const_rtx follower
, const_rtx followee
)
9216 /* ??? get_attr_type is declared to take an rtx. */
9217 union { const_rtx c
; rtx r
; } u
;
9220 if (CROSSING_JUMP_P (followee
))
9221 switch (get_attr_type (u
.r
))
9224 case TYPE_BRCC_NO_DELAY_SLOT
:
9232 /* Implement EPILOGUE__USES.
9233 Return true if REGNO should be added to the deemed uses of the epilogue.
9235 We use the return address
9236 arc_return_address_regs[arc_compute_function_type (cfun)] .
9237 But also, we have to make sure all the register restore instructions
9238 are known to be live in interrupt functions. */
9241 arc_epilogue_uses (int regno
)
9243 if (reload_completed
)
9245 if (ARC_INTERRUPT_P (cfun
->machine
->fn_type
))
9247 if (!fixed_regs
[regno
])
9249 return regno
== arc_return_address_regs
[cfun
->machine
->fn_type
];
9252 return regno
== RETURN_ADDR_REGNUM
;
9255 return regno
== arc_return_address_regs
[arc_compute_function_type (cfun
)];
9258 #ifndef TARGET_NO_LRA
9259 #define TARGET_NO_LRA !TARGET_LRA
9265 return !TARGET_NO_LRA
;
9268 /* ??? Should we define TARGET_REGISTER_PRIORITY? We might perfer to use
9269 Rcq registers, because some insn are shorter with them. OTOH we already
9270 have separate alternatives for this purpose, and other insns don't
9271 mind, so maybe we should rather prefer the other registers?
9272 We need more data, and we can only get that if we allow people to
9275 arc_register_priority (int r
)
9277 switch (arc_lra_priority_tag
)
9279 case ARC_LRA_PRIORITY_NONE
:
9281 case ARC_LRA_PRIORITY_NONCOMPACT
:
9282 return ((((r
& 7) ^ 4) - 4) & 15) != r
;
9283 case ARC_LRA_PRIORITY_COMPACT
:
9284 return ((((r
& 7) ^ 4) - 4) & 15) == r
;
9291 arc_spill_class (reg_class_t
/* orig_class */, enum machine_mode
)
9293 return GENERAL_REGS
;
9297 arc_legitimize_reload_address (rtx
*p
, enum machine_mode mode
, int opnum
,
9301 enum reload_type type
= (enum reload_type
) itype
;
9303 if (GET_CODE (x
) == PLUS
9304 && CONST_INT_P (XEXP (x
, 1))
9305 && (RTX_OK_FOR_BASE_P (XEXP (x
, 0), true)
9306 || (REG_P (XEXP (x
, 0))
9307 && reg_equiv_constant (REGNO (XEXP (x
, 0))))))
9309 int scale
= GET_MODE_SIZE (mode
);
9311 rtx index_rtx
= XEXP (x
, 1);
9312 HOST_WIDE_INT offset
= INTVAL (index_rtx
), offset_base
;
9317 if ((scale
-1) & offset
)
9320 offset_base
= (offset
+ (256 << shift
)) & (-512 << shift
);
9321 /* Sometimes the normal form does not suit DImode. We
9322 could avoid that by using smaller ranges, but that
9323 would give less optimized code when SImode is
9325 if (GET_MODE_SIZE (mode
) + offset
- offset_base
<= (256 << shift
))
9330 regno
= REGNO (reg
);
9331 sum2
= sum
= plus_constant (Pmode
, reg
, offset_base
);
9333 if (reg_equiv_constant (regno
))
9335 sum2
= plus_constant (Pmode
, reg_equiv_constant (regno
),
9337 if (GET_CODE (sum2
) == PLUS
)
9338 sum2
= gen_rtx_CONST (Pmode
, sum2
);
9340 *p
= gen_rtx_PLUS (Pmode
, sum
, GEN_INT (offset
- offset_base
));
9341 push_reload (sum2
, NULL_RTX
, &XEXP (*p
, 0), NULL
,
9342 BASE_REG_CLASS
, Pmode
, VOIDmode
, 0, 0, opnum
,
9347 /* We must re-recognize what we created before. */
9348 else if (GET_CODE (x
) == PLUS
9349 && GET_CODE (XEXP (x
, 0)) == PLUS
9350 && CONST_INT_P (XEXP (XEXP (x
, 0), 1))
9351 && REG_P (XEXP (XEXP (x
, 0), 0))
9352 && CONST_INT_P (XEXP (x
, 1)))
9354 /* Because this address is so complex, we know it must have
9355 been created by LEGITIMIZE_RELOAD_ADDRESS before; thus,
9356 it is already unshared, and needs no further unsharing. */
9357 push_reload (XEXP (x
, 0), NULL_RTX
, &XEXP (x
, 0), NULL
,
9358 BASE_REG_CLASS
, Pmode
, VOIDmode
, 0, 0, opnum
, type
);
9364 struct gcc_target targetm
= TARGET_INITIALIZER
;