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"
58 #include "insn-attr.h"
63 #include "diagnostic.h"
64 #include "insn-codes.h"
65 #include "langhooks.h"
67 #include "tm-constrs.h"
68 #include "reload.h" /* For operands_match_p */
69 #include "dominance.h"
75 #include "cfgcleanup.h"
77 #include "basic-block.h"
79 #include "tree-pass.h"
81 #include "pass_manager.h"
85 /* Which cpu we're compiling for (A5, ARC600, ARC601, ARC700). */
86 static const char *arc_cpu_string
= "";
88 /* ??? Loads can handle any constant, stores can only handle small ones. */
89 /* OTOH, LIMMs cost extra, so their usefulness is limited. */
90 #define RTX_OK_FOR_OFFSET_P(MODE, X) \
91 (GET_CODE (X) == CONST_INT \
92 && SMALL_INT_RANGE (INTVAL (X), (GET_MODE_SIZE (MODE) - 1) & -4, \
93 (INTVAL (X) & (GET_MODE_SIZE (MODE) - 1) & 3 \
95 : -(-GET_MODE_SIZE (MODE) | -4) >> 1)))
97 #define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X, INDEX, STRICT) \
98 (GET_CODE (X) == PLUS \
99 && RTX_OK_FOR_BASE_P (XEXP (X, 0), (STRICT)) \
100 && ((INDEX && RTX_OK_FOR_INDEX_P (XEXP (X, 1), (STRICT)) \
101 && GET_MODE_SIZE ((MODE)) <= 4) \
102 || RTX_OK_FOR_OFFSET_P (MODE, XEXP (X, 1))))
104 #define LEGITIMATE_SCALED_ADDRESS_P(MODE, X, STRICT) \
105 (GET_CODE (X) == PLUS \
106 && GET_CODE (XEXP (X, 0)) == MULT \
107 && RTX_OK_FOR_INDEX_P (XEXP (XEXP (X, 0), 0), (STRICT)) \
108 && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \
109 && ((GET_MODE_SIZE (MODE) == 2 && INTVAL (XEXP (XEXP (X, 0), 1)) == 2) \
110 || (GET_MODE_SIZE (MODE) == 4 && INTVAL (XEXP (XEXP (X, 0), 1)) == 4)) \
111 && (RTX_OK_FOR_BASE_P (XEXP (X, 1), (STRICT)) \
112 || (flag_pic ? CONST_INT_P (XEXP (X, 1)) : CONSTANT_P (XEXP (X, 1)))))
114 #define LEGITIMATE_SMALL_DATA_ADDRESS_P(X) \
115 (GET_CODE (X) == PLUS \
116 && (REG_P (XEXP ((X), 0)) && REGNO (XEXP ((X), 0)) == SDATA_BASE_REGNUM) \
117 && ((GET_CODE (XEXP((X),1)) == SYMBOL_REF \
118 && SYMBOL_REF_SMALL_P (XEXP ((X), 1))) \
119 || (GET_CODE (XEXP ((X), 1)) == CONST \
120 && GET_CODE (XEXP (XEXP ((X), 1), 0)) == PLUS \
121 && GET_CODE (XEXP (XEXP (XEXP ((X), 1), 0), 0)) == SYMBOL_REF \
122 && SYMBOL_REF_SMALL_P (XEXP (XEXP (XEXP ((X), 1), 0), 0)) \
123 && GET_CODE (XEXP(XEXP (XEXP ((X), 1), 0), 1)) == CONST_INT)))
125 /* Array of valid operand punctuation characters. */
126 char arc_punct_chars
[256];
128 /* State used by arc_ccfsm_advance to implement conditional execution. */
129 struct GTY (()) arc_ccfsm
134 rtx_insn
*target_insn
;
138 #define arc_ccfsm_current cfun->machine->ccfsm_current
140 #define ARC_CCFSM_BRANCH_DELETED_P(STATE) \
141 ((STATE)->state == 1 || (STATE)->state == 2)
143 /* Indicate we're conditionalizing insns now. */
144 #define ARC_CCFSM_RECORD_BRANCH_DELETED(STATE) \
145 ((STATE)->state += 2)
147 #define ARC_CCFSM_COND_EXEC_P(STATE) \
148 ((STATE)->state == 3 || (STATE)->state == 4 || (STATE)->state == 5 \
149 || current_insn_predicate)
151 /* Check if INSN has a 16 bit opcode considering struct arc_ccfsm *STATE. */
152 #define CCFSM_ISCOMPACT(INSN,STATE) \
153 (ARC_CCFSM_COND_EXEC_P (STATE) \
154 ? (get_attr_iscompact (INSN) == ISCOMPACT_TRUE \
155 || get_attr_iscompact (INSN) == ISCOMPACT_TRUE_LIMM) \
156 : get_attr_iscompact (INSN) != ISCOMPACT_FALSE)
158 /* Likewise, but also consider that INSN might be in a delay slot of JUMP. */
159 #define CCFSM_DBR_ISCOMPACT(INSN,JUMP,STATE) \
160 ((ARC_CCFSM_COND_EXEC_P (STATE) \
162 && INSN_ANNULLED_BRANCH_P (JUMP) \
163 && (TARGET_AT_DBR_CONDEXEC || INSN_FROM_TARGET_P (INSN)))) \
164 ? (get_attr_iscompact (INSN) == ISCOMPACT_TRUE \
165 || get_attr_iscompact (INSN) == ISCOMPACT_TRUE_LIMM) \
166 : get_attr_iscompact (INSN) != ISCOMPACT_FALSE)
168 /* The maximum number of insns skipped which will be conditionalised if
170 /* When optimizing for speed:
171 Let p be the probability that the potentially skipped insns need to
172 be executed, pn the cost of a correctly predicted non-taken branch,
173 mt the cost of a mis/non-predicted taken branch,
174 mn mispredicted non-taken, pt correctly predicted taken ;
175 costs expressed in numbers of instructions like the ones considered
177 Unfortunately we don't have a measure of predictability - this
178 is linked to probability only in that in the no-eviction-scenario
179 there is a lower bound 1 - 2 * min (p, 1-p), and a somewhat larger
180 value that can be assumed *if* the distribution is perfectly random.
181 A predictability of 1 is perfectly plausible not matter what p is,
182 because the decision could be dependent on an invocation parameter
184 For large p, we want MAX_INSNS_SKIPPED == pn/(1-p) + mt - pn
185 For small p, we want MAX_INSNS_SKIPPED == pt
187 When optimizing for size:
188 We want to skip insn unless we could use 16 opcodes for the
189 non-conditionalized insn to balance the branch length or more.
190 Performance can be tie-breaker. */
191 /* If the potentially-skipped insns are likely to be executed, we'll
192 generally save one non-taken branch
194 this to be no less than the 1/p */
195 #define MAX_INSNS_SKIPPED 3
197 /* The values of unspec's first field. */
207 ARC_BUILTIN_NORM
= 3,
208 ARC_BUILTIN_NORMW
= 4,
209 ARC_BUILTIN_SWAP
= 5,
211 ARC_BUILTIN_DIVAW
= 7,
213 ARC_BUILTIN_MUL64
= 9,
214 ARC_BUILTIN_MULU64
= 10,
215 ARC_BUILTIN_RTIE
= 11,
216 ARC_BUILTIN_SYNC
= 12,
217 ARC_BUILTIN_CORE_READ
= 13,
218 ARC_BUILTIN_CORE_WRITE
= 14,
219 ARC_BUILTIN_FLAG
= 15,
222 ARC_BUILTIN_SLEEP
= 18,
223 ARC_BUILTIN_SWI
= 19,
224 ARC_BUILTIN_TRAP_S
= 20,
225 ARC_BUILTIN_UNIMP_S
= 21,
226 ARC_BUILTIN_ALIGNED
= 22,
228 /* Sentinel to mark start of simd builtins. */
229 ARC_SIMD_BUILTIN_BEGIN
= 1000,
231 ARC_SIMD_BUILTIN_VADDAW
= 1001,
232 ARC_SIMD_BUILTIN_VADDW
= 1002,
233 ARC_SIMD_BUILTIN_VAVB
= 1003,
234 ARC_SIMD_BUILTIN_VAVRB
= 1004,
235 ARC_SIMD_BUILTIN_VDIFAW
= 1005,
236 ARC_SIMD_BUILTIN_VDIFW
= 1006,
237 ARC_SIMD_BUILTIN_VMAXAW
= 1007,
238 ARC_SIMD_BUILTIN_VMAXW
= 1008,
239 ARC_SIMD_BUILTIN_VMINAW
= 1009,
240 ARC_SIMD_BUILTIN_VMINW
= 1010,
241 ARC_SIMD_BUILTIN_VMULAW
= 1011,
242 ARC_SIMD_BUILTIN_VMULFAW
= 1012,
243 ARC_SIMD_BUILTIN_VMULFW
= 1013,
244 ARC_SIMD_BUILTIN_VMULW
= 1014,
245 ARC_SIMD_BUILTIN_VSUBAW
= 1015,
246 ARC_SIMD_BUILTIN_VSUBW
= 1016,
247 ARC_SIMD_BUILTIN_VSUMMW
= 1017,
248 ARC_SIMD_BUILTIN_VAND
= 1018,
249 ARC_SIMD_BUILTIN_VANDAW
= 1019,
250 ARC_SIMD_BUILTIN_VBIC
= 1020,
251 ARC_SIMD_BUILTIN_VBICAW
= 1021,
252 ARC_SIMD_BUILTIN_VOR
= 1022,
253 ARC_SIMD_BUILTIN_VXOR
= 1023,
254 ARC_SIMD_BUILTIN_VXORAW
= 1024,
255 ARC_SIMD_BUILTIN_VEQW
= 1025,
256 ARC_SIMD_BUILTIN_VLEW
= 1026,
257 ARC_SIMD_BUILTIN_VLTW
= 1027,
258 ARC_SIMD_BUILTIN_VNEW
= 1028,
259 ARC_SIMD_BUILTIN_VMR1AW
= 1029,
260 ARC_SIMD_BUILTIN_VMR1W
= 1030,
261 ARC_SIMD_BUILTIN_VMR2AW
= 1031,
262 ARC_SIMD_BUILTIN_VMR2W
= 1032,
263 ARC_SIMD_BUILTIN_VMR3AW
= 1033,
264 ARC_SIMD_BUILTIN_VMR3W
= 1034,
265 ARC_SIMD_BUILTIN_VMR4AW
= 1035,
266 ARC_SIMD_BUILTIN_VMR4W
= 1036,
267 ARC_SIMD_BUILTIN_VMR5AW
= 1037,
268 ARC_SIMD_BUILTIN_VMR5W
= 1038,
269 ARC_SIMD_BUILTIN_VMR6AW
= 1039,
270 ARC_SIMD_BUILTIN_VMR6W
= 1040,
271 ARC_SIMD_BUILTIN_VMR7AW
= 1041,
272 ARC_SIMD_BUILTIN_VMR7W
= 1042,
273 ARC_SIMD_BUILTIN_VMRB
= 1043,
274 ARC_SIMD_BUILTIN_VH264F
= 1044,
275 ARC_SIMD_BUILTIN_VH264FT
= 1045,
276 ARC_SIMD_BUILTIN_VH264FW
= 1046,
277 ARC_SIMD_BUILTIN_VVC1F
= 1047,
278 ARC_SIMD_BUILTIN_VVC1FT
= 1048,
280 /* Va, Vb, rlimm instructions. */
281 ARC_SIMD_BUILTIN_VBADDW
= 1050,
282 ARC_SIMD_BUILTIN_VBMAXW
= 1051,
283 ARC_SIMD_BUILTIN_VBMINW
= 1052,
284 ARC_SIMD_BUILTIN_VBMULAW
= 1053,
285 ARC_SIMD_BUILTIN_VBMULFW
= 1054,
286 ARC_SIMD_BUILTIN_VBMULW
= 1055,
287 ARC_SIMD_BUILTIN_VBRSUBW
= 1056,
288 ARC_SIMD_BUILTIN_VBSUBW
= 1057,
290 /* Va, Vb, Ic instructions. */
291 ARC_SIMD_BUILTIN_VASRW
= 1060,
292 ARC_SIMD_BUILTIN_VSR8
= 1061,
293 ARC_SIMD_BUILTIN_VSR8AW
= 1062,
295 /* Va, Vb, u6 instructions. */
296 ARC_SIMD_BUILTIN_VASRRWi
= 1065,
297 ARC_SIMD_BUILTIN_VASRSRWi
= 1066,
298 ARC_SIMD_BUILTIN_VASRWi
= 1067,
299 ARC_SIMD_BUILTIN_VASRPWBi
= 1068,
300 ARC_SIMD_BUILTIN_VASRRPWBi
= 1069,
301 ARC_SIMD_BUILTIN_VSR8AWi
= 1070,
302 ARC_SIMD_BUILTIN_VSR8i
= 1071,
304 /* Va, Vb, u8 (simm) instructions. */
305 ARC_SIMD_BUILTIN_VMVAW
= 1075,
306 ARC_SIMD_BUILTIN_VMVW
= 1076,
307 ARC_SIMD_BUILTIN_VMVZW
= 1077,
308 ARC_SIMD_BUILTIN_VD6TAPF
= 1078,
310 /* Va, rlimm, u8 (simm) instructions. */
311 ARC_SIMD_BUILTIN_VMOVAW
= 1080,
312 ARC_SIMD_BUILTIN_VMOVW
= 1081,
313 ARC_SIMD_BUILTIN_VMOVZW
= 1082,
315 /* Va, Vb instructions. */
316 ARC_SIMD_BUILTIN_VABSAW
= 1085,
317 ARC_SIMD_BUILTIN_VABSW
= 1086,
318 ARC_SIMD_BUILTIN_VADDSUW
= 1087,
319 ARC_SIMD_BUILTIN_VSIGNW
= 1088,
320 ARC_SIMD_BUILTIN_VEXCH1
= 1089,
321 ARC_SIMD_BUILTIN_VEXCH2
= 1090,
322 ARC_SIMD_BUILTIN_VEXCH4
= 1091,
323 ARC_SIMD_BUILTIN_VUPBAW
= 1092,
324 ARC_SIMD_BUILTIN_VUPBW
= 1093,
325 ARC_SIMD_BUILTIN_VUPSBAW
= 1094,
326 ARC_SIMD_BUILTIN_VUPSBW
= 1095,
328 ARC_SIMD_BUILTIN_VDIRUN
= 1100,
329 ARC_SIMD_BUILTIN_VDORUN
= 1101,
330 ARC_SIMD_BUILTIN_VDIWR
= 1102,
331 ARC_SIMD_BUILTIN_VDOWR
= 1103,
333 ARC_SIMD_BUILTIN_VREC
= 1105,
334 ARC_SIMD_BUILTIN_VRUN
= 1106,
335 ARC_SIMD_BUILTIN_VRECRUN
= 1107,
336 ARC_SIMD_BUILTIN_VENDREC
= 1108,
338 ARC_SIMD_BUILTIN_VLD32WH
= 1110,
339 ARC_SIMD_BUILTIN_VLD32WL
= 1111,
340 ARC_SIMD_BUILTIN_VLD64
= 1112,
341 ARC_SIMD_BUILTIN_VLD32
= 1113,
342 ARC_SIMD_BUILTIN_VLD64W
= 1114,
343 ARC_SIMD_BUILTIN_VLD128
= 1115,
344 ARC_SIMD_BUILTIN_VST128
= 1116,
345 ARC_SIMD_BUILTIN_VST64
= 1117,
347 ARC_SIMD_BUILTIN_VST16_N
= 1120,
348 ARC_SIMD_BUILTIN_VST32_N
= 1121,
350 ARC_SIMD_BUILTIN_VINTI
= 1201,
355 /* A nop is needed between a 4 byte insn that sets the condition codes and
356 a branch that uses them (the same isn't true for an 8 byte insn that sets
357 the condition codes). Set by arc_ccfsm_advance. Used by
358 arc_print_operand. */
360 static int get_arc_condition_code (rtx
);
362 static tree
arc_handle_interrupt_attribute (tree
*, tree
, tree
, int, bool *);
364 /* Initialized arc_attribute_table to NULL since arc doesnot have any
365 machine specific supported attributes. */
366 const struct attribute_spec arc_attribute_table
[] =
368 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
369 affects_type_identity } */
370 { "interrupt", 1, 1, true, false, false, arc_handle_interrupt_attribute
, true },
371 /* Function calls made to this symbol must be done indirectly, because
372 it may lie outside of the 21/25 bit addressing range of a normal function
374 { "long_call", 0, 0, false, true, true, NULL
, false },
375 /* Whereas these functions are always known to reside within the 25 bit
376 addressing range of unconditionalized bl. */
377 { "medium_call", 0, 0, false, true, true, NULL
, false },
378 /* And these functions are always known to reside within the 21 bit
379 addressing range of blcc. */
380 { "short_call", 0, 0, false, true, true, NULL
, false },
381 { NULL
, 0, 0, false, false, false, NULL
, false }
383 static int arc_comp_type_attributes (const_tree
, const_tree
);
384 static void arc_file_start (void);
385 static void arc_internal_label (FILE *, const char *, unsigned long);
386 static void arc_output_mi_thunk (FILE *, tree
, HOST_WIDE_INT
, HOST_WIDE_INT
,
388 static int arc_address_cost (rtx
, machine_mode
, addr_space_t
, bool);
389 static void arc_encode_section_info (tree decl
, rtx rtl
, int first
);
391 static void arc_init_builtins (void);
392 static rtx
arc_expand_builtin (tree
, rtx
, rtx
, machine_mode
, int);
394 static int branch_dest (rtx
);
396 static void arc_output_pic_addr_const (FILE *, rtx
, int);
397 void emit_pic_move (rtx
*, machine_mode
);
398 bool arc_legitimate_pic_operand_p (rtx
);
399 static bool arc_function_ok_for_sibcall (tree
, tree
);
400 static rtx
arc_function_value (const_tree
, const_tree
, bool);
401 const char * output_shift (rtx
*);
402 static void arc_reorg (void);
403 static bool arc_in_small_data_p (const_tree
);
405 static void arc_init_reg_tables (void);
406 static bool arc_return_in_memory (const_tree
, const_tree
);
407 static void arc_init_simd_builtins (void);
408 static bool arc_vector_mode_supported_p (machine_mode
);
410 static bool arc_can_use_doloop_p (const widest_int
&, const widest_int
&,
412 static const char *arc_invalid_within_doloop (const rtx_insn
*);
414 static void output_short_suffix (FILE *file
);
416 static bool arc_frame_pointer_required (void);
418 /* Implements target hook vector_mode_supported_p. */
421 arc_vector_mode_supported_p (machine_mode mode
)
423 if (!TARGET_SIMD_SET
)
426 if ((mode
== V4SImode
)
427 || (mode
== V8HImode
))
434 /* TARGET_PRESERVE_RELOAD_P is still awaiting patch re-evaluation / review. */
435 static bool arc_preserve_reload_p (rtx in
) ATTRIBUTE_UNUSED
;
436 static rtx
arc_delegitimize_address (rtx
);
437 static bool arc_can_follow_jump (const rtx_insn
*follower
,
438 const rtx_insn
*followee
);
440 static rtx
frame_insn (rtx
);
441 static void arc_function_arg_advance (cumulative_args_t
, machine_mode
,
443 static rtx
arc_legitimize_address_0 (rtx
, rtx
, machine_mode mode
);
445 static void arc_finalize_pic (void);
447 /* initialize the GCC target structure. */
448 #undef TARGET_COMP_TYPE_ATTRIBUTES
449 #define TARGET_COMP_TYPE_ATTRIBUTES arc_comp_type_attributes
450 #undef TARGET_ASM_FILE_START
451 #define TARGET_ASM_FILE_START arc_file_start
452 #undef TARGET_ATTRIBUTE_TABLE
453 #define TARGET_ATTRIBUTE_TABLE arc_attribute_table
454 #undef TARGET_ASM_INTERNAL_LABEL
455 #define TARGET_ASM_INTERNAL_LABEL arc_internal_label
456 #undef TARGET_RTX_COSTS
457 #define TARGET_RTX_COSTS arc_rtx_costs
458 #undef TARGET_ADDRESS_COST
459 #define TARGET_ADDRESS_COST arc_address_cost
461 #undef TARGET_ENCODE_SECTION_INFO
462 #define TARGET_ENCODE_SECTION_INFO arc_encode_section_info
464 #undef TARGET_CANNOT_FORCE_CONST_MEM
465 #define TARGET_CANNOT_FORCE_CONST_MEM arc_cannot_force_const_mem
467 #undef TARGET_INIT_BUILTINS
468 #define TARGET_INIT_BUILTINS arc_init_builtins
470 #undef TARGET_EXPAND_BUILTIN
471 #define TARGET_EXPAND_BUILTIN arc_expand_builtin
473 #undef TARGET_ASM_OUTPUT_MI_THUNK
474 #define TARGET_ASM_OUTPUT_MI_THUNK arc_output_mi_thunk
476 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
477 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
479 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
480 #define TARGET_FUNCTION_OK_FOR_SIBCALL arc_function_ok_for_sibcall
482 #undef TARGET_MACHINE_DEPENDENT_REORG
483 #define TARGET_MACHINE_DEPENDENT_REORG arc_reorg
485 #undef TARGET_IN_SMALL_DATA_P
486 #define TARGET_IN_SMALL_DATA_P arc_in_small_data_p
488 #undef TARGET_PROMOTE_FUNCTION_MODE
489 #define TARGET_PROMOTE_FUNCTION_MODE \
490 default_promote_function_mode_always_promote
492 #undef TARGET_PROMOTE_PROTOTYPES
493 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
495 #undef TARGET_RETURN_IN_MEMORY
496 #define TARGET_RETURN_IN_MEMORY arc_return_in_memory
497 #undef TARGET_PASS_BY_REFERENCE
498 #define TARGET_PASS_BY_REFERENCE arc_pass_by_reference
500 #undef TARGET_SETUP_INCOMING_VARARGS
501 #define TARGET_SETUP_INCOMING_VARARGS arc_setup_incoming_varargs
503 #undef TARGET_ARG_PARTIAL_BYTES
504 #define TARGET_ARG_PARTIAL_BYTES arc_arg_partial_bytes
506 #undef TARGET_MUST_PASS_IN_STACK
507 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
509 #undef TARGET_FUNCTION_VALUE
510 #define TARGET_FUNCTION_VALUE arc_function_value
512 #undef TARGET_SCHED_ADJUST_PRIORITY
513 #define TARGET_SCHED_ADJUST_PRIORITY arc_sched_adjust_priority
515 #undef TARGET_VECTOR_MODE_SUPPORTED_P
516 #define TARGET_VECTOR_MODE_SUPPORTED_P arc_vector_mode_supported_p
518 #undef TARGET_CAN_USE_DOLOOP_P
519 #define TARGET_CAN_USE_DOLOOP_P arc_can_use_doloop_p
521 #undef TARGET_INVALID_WITHIN_DOLOOP
522 #define TARGET_INVALID_WITHIN_DOLOOP arc_invalid_within_doloop
524 #undef TARGET_PRESERVE_RELOAD_P
525 #define TARGET_PRESERVE_RELOAD_P arc_preserve_reload_p
527 #undef TARGET_CAN_FOLLOW_JUMP
528 #define TARGET_CAN_FOLLOW_JUMP arc_can_follow_jump
530 #undef TARGET_DELEGITIMIZE_ADDRESS
531 #define TARGET_DELEGITIMIZE_ADDRESS arc_delegitimize_address
533 /* Usually, we will be able to scale anchor offsets.
534 When this fails, we want LEGITIMIZE_ADDRESS to kick in. */
535 #undef TARGET_MIN_ANCHOR_OFFSET
536 #define TARGET_MIN_ANCHOR_OFFSET (-1024)
537 #undef TARGET_MAX_ANCHOR_OFFSET
538 #define TARGET_MAX_ANCHOR_OFFSET (1020)
540 #undef TARGET_SECONDARY_RELOAD
541 #define TARGET_SECONDARY_RELOAD arc_secondary_reload
543 #define TARGET_OPTION_OVERRIDE arc_override_options
545 #define TARGET_CONDITIONAL_REGISTER_USAGE arc_conditional_register_usage
547 #define TARGET_TRAMPOLINE_INIT arc_initialize_trampoline
549 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS arc_trampoline_adjust_address
551 #define TARGET_CAN_ELIMINATE arc_can_eliminate
553 #define TARGET_FRAME_POINTER_REQUIRED arc_frame_pointer_required
555 #define TARGET_FUNCTION_ARG arc_function_arg
557 #define TARGET_FUNCTION_ARG_ADVANCE arc_function_arg_advance
559 #define TARGET_LEGITIMATE_CONSTANT_P arc_legitimate_constant_p
561 #define TARGET_LEGITIMATE_ADDRESS_P arc_legitimate_address_p
563 #define TARGET_MODE_DEPENDENT_ADDRESS_P arc_mode_dependent_address_p
565 #define TARGET_LEGITIMIZE_ADDRESS arc_legitimize_address
567 #define TARGET_ADJUST_INSN_LENGTH arc_adjust_insn_length
569 #define TARGET_INSN_LENGTH_PARAMETERS arc_insn_length_parameters
572 #define TARGET_LRA_P arc_lra_p
573 #define TARGET_REGISTER_PRIORITY arc_register_priority
574 /* Stores with scaled offsets have different displacement ranges. */
575 #define TARGET_DIFFERENT_ADDR_DISPLACEMENT_P hook_bool_void_true
576 #define TARGET_SPILL_CLASS arc_spill_class
578 #include "target-def.h"
580 #undef TARGET_ASM_ALIGNED_HI_OP
581 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
582 #undef TARGET_ASM_ALIGNED_SI_OP
583 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
585 /* Try to keep the (mov:DF _, reg) as early as possible so
586 that the d<add/sub/mul>h-lr insns appear together and can
587 use the peephole2 pattern. */
590 arc_sched_adjust_priority (rtx_insn
*insn
, int priority
)
592 rtx set
= single_set (insn
);
594 && GET_MODE (SET_SRC(set
)) == DFmode
595 && GET_CODE (SET_SRC(set
)) == REG
)
597 /* Incrementing priority by 20 (empirically derived). */
598 return priority
+ 20;
605 arc_secondary_reload (bool in_p
, rtx x
, reg_class_t cl
, machine_mode
,
606 secondary_reload_info
*)
608 if (cl
== DOUBLE_REGS
)
611 /* The loop counter register can be stored, but not loaded directly. */
612 if ((cl
== LPCOUNT_REG
|| cl
== WRITABLE_CORE_REGS
)
613 && in_p
&& MEM_P (x
))
618 static unsigned arc_ifcvt (void);
622 const pass_data pass_data_arc_ifcvt
=
625 "arc_ifcvt", /* name */
626 OPTGROUP_NONE
, /* optinfo_flags */
627 TV_IFCVT2
, /* tv_id */
628 0, /* properties_required */
629 0, /* properties_provided */
630 0, /* properties_destroyed */
631 0, /* todo_flags_start */
632 TODO_df_finish
/* todo_flags_finish */
635 class pass_arc_ifcvt
: public rtl_opt_pass
638 pass_arc_ifcvt(gcc::context
*ctxt
)
639 : rtl_opt_pass(pass_data_arc_ifcvt
, ctxt
)
642 /* opt_pass methods: */
643 opt_pass
* clone () { return new pass_arc_ifcvt (m_ctxt
); }
644 virtual unsigned int execute (function
*) { return arc_ifcvt (); }
650 make_pass_arc_ifcvt (gcc::context
*ctxt
)
652 return new pass_arc_ifcvt (ctxt
);
655 static unsigned arc_predicate_delay_insns (void);
659 const pass_data pass_data_arc_predicate_delay_insns
=
662 "arc_predicate_delay_insns", /* name */
663 OPTGROUP_NONE
, /* optinfo_flags */
664 TV_IFCVT2
, /* tv_id */
665 0, /* properties_required */
666 0, /* properties_provided */
667 0, /* properties_destroyed */
668 0, /* todo_flags_start */
669 TODO_df_finish
/* todo_flags_finish */
672 class pass_arc_predicate_delay_insns
: public rtl_opt_pass
675 pass_arc_predicate_delay_insns(gcc::context
*ctxt
)
676 : rtl_opt_pass(pass_data_arc_predicate_delay_insns
, ctxt
)
679 /* opt_pass methods: */
680 virtual unsigned int execute (function
*)
682 return arc_predicate_delay_insns ();
689 make_pass_arc_predicate_delay_insns (gcc::context
*ctxt
)
691 return new pass_arc_predicate_delay_insns (ctxt
);
694 /* Called by OVERRIDE_OPTIONS to initialize various things. */
699 enum attr_tune tune_dflt
= TUNE_NONE
;
703 arc_cpu_string
= "A5";
705 else if (TARGET_ARC600
)
707 arc_cpu_string
= "ARC600";
708 tune_dflt
= TUNE_ARC600
;
710 else if (TARGET_ARC601
)
712 arc_cpu_string
= "ARC601";
713 tune_dflt
= TUNE_ARC600
;
715 else if (TARGET_ARC700
)
717 arc_cpu_string
= "ARC700";
718 tune_dflt
= TUNE_ARC700_4_2_STD
;
722 if (arc_tune
== TUNE_NONE
)
723 arc_tune
= tune_dflt
;
724 /* Note: arc_multcost is only used in rtx_cost if speed is true. */
725 if (arc_multcost
< 0)
728 case TUNE_ARC700_4_2_STD
:
730 max throughput (1 multiply + 4 other insns) / 5 cycles. */
731 arc_multcost
= COSTS_N_INSNS (4);
732 if (TARGET_NOMPY_SET
)
733 arc_multcost
= COSTS_N_INSNS (30);
735 case TUNE_ARC700_4_2_XMAC
:
737 max throughput (1 multiply + 2 other insns) / 3 cycles. */
738 arc_multcost
= COSTS_N_INSNS (3);
739 if (TARGET_NOMPY_SET
)
740 arc_multcost
= COSTS_N_INSNS (30);
743 if (TARGET_MUL64_SET
)
745 arc_multcost
= COSTS_N_INSNS (4);
750 arc_multcost
= COSTS_N_INSNS (30);
754 /* Support mul64 generation only for A5 and ARC600. */
755 if (TARGET_MUL64_SET
&& TARGET_ARC700
)
756 error ("-mmul64 not supported for ARC700");
758 /* MPY instructions valid only for ARC700. */
759 if (TARGET_NOMPY_SET
&& !TARGET_ARC700
)
760 error ("-mno-mpy supported only for ARC700");
762 /* mul/mac instructions only for ARC600. */
763 if (TARGET_MULMAC_32BY16_SET
&& !(TARGET_ARC600
|| TARGET_ARC601
))
764 error ("-mmul32x16 supported only for ARC600 or ARC601");
766 if (!TARGET_DPFP
&& TARGET_DPFP_DISABLE_LRSR
)
767 error ("-mno-dpfp-lrsr supported only with -mdpfp");
769 /* FPX-1. No fast and compact together. */
770 if ((TARGET_DPFP_FAST_SET
&& TARGET_DPFP_COMPACT_SET
)
771 || (TARGET_SPFP_FAST_SET
&& TARGET_SPFP_COMPACT_SET
))
772 error ("FPX fast and compact options cannot be specified together");
774 /* FPX-2. No fast-spfp for arc600 or arc601. */
775 if (TARGET_SPFP_FAST_SET
&& (TARGET_ARC600
|| TARGET_ARC601
))
776 error ("-mspfp_fast not available on ARC600 or ARC601");
778 /* FPX-3. No FPX extensions on pre-ARC600 cores. */
779 if ((TARGET_DPFP
|| TARGET_SPFP
)
780 && !(TARGET_ARC600
|| TARGET_ARC601
|| TARGET_ARC700
))
781 error ("FPX extensions not available on pre-ARC600 cores");
783 /* Warn for unimplemented PIC in pre-ARC700 cores, and disable flag_pic. */
784 if (flag_pic
&& !TARGET_ARC700
)
786 warning (DK_WARNING
, "PIC is not supported for %s. Generating non-PIC code only..", arc_cpu_string
);
790 arc_init_reg_tables ();
792 /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P. */
793 memset (arc_punct_chars
, 0, sizeof (arc_punct_chars
));
794 arc_punct_chars
['#'] = 1;
795 arc_punct_chars
['*'] = 1;
796 arc_punct_chars
['?'] = 1;
797 arc_punct_chars
['!'] = 1;
798 arc_punct_chars
['^'] = 1;
799 arc_punct_chars
['&'] = 1;
801 if (optimize
> 1 && !TARGET_NO_COND_EXEC
)
803 /* There are two target-independent ifcvt passes, and arc_reorg may do
804 one or more arc_ifcvt calls. */
805 opt_pass
*pass_arc_ifcvt_4
= make_pass_arc_ifcvt (g
);
806 struct register_pass_info arc_ifcvt4_info
807 = { pass_arc_ifcvt_4
, "dbr", 1, PASS_POS_INSERT_AFTER
};
808 struct register_pass_info arc_ifcvt5_info
809 = { pass_arc_ifcvt_4
->clone (), "shorten", 1, PASS_POS_INSERT_BEFORE
};
811 register_pass (&arc_ifcvt4_info
);
812 register_pass (&arc_ifcvt5_info
);
815 if (flag_delayed_branch
)
817 opt_pass
*pass_arc_predicate_delay_insns
818 = make_pass_arc_predicate_delay_insns (g
);
819 struct register_pass_info arc_predicate_delay_info
820 = { pass_arc_predicate_delay_insns
, "dbr", 1, PASS_POS_INSERT_AFTER
};
822 register_pass (&arc_predicate_delay_info
);
826 /* Check ARC options, generate derived target attributes. */
829 arc_override_options (void)
831 if (arc_cpu
== PROCESSOR_NONE
)
832 arc_cpu
= PROCESSOR_ARC700
;
834 if (arc_size_opt_level
== 3)
838 target_flags
|= MASK_NO_SDATA_SET
;
840 if (flag_no_common
== 255)
841 flag_no_common
= !TARGET_NO_SDATA_SET
;
843 /* TARGET_COMPACT_CASESI needs the "q" register class. */ \
844 if (TARGET_MIXED_CODE
)
847 TARGET_COMPACT_CASESI
= 0;
848 if (TARGET_COMPACT_CASESI
)
849 TARGET_CASE_VECTOR_PC_RELATIVE
= 1;
851 /* These need to be done at start up. It's convenient to do them here. */
855 /* The condition codes of the ARC, and the inverse function. */
856 /* For short branches, the "c" / "nc" names are not defined in the ARC
857 Programmers manual, so we have to use "lo" / "hs"" instead. */
858 static const char *arc_condition_codes
[] =
860 "al", 0, "eq", "ne", "p", "n", "lo", "hs", "v", "nv",
861 "gt", "le", "ge", "lt", "hi", "ls", "pnz", 0
864 enum arc_cc_code_index
866 ARC_CC_AL
, ARC_CC_EQ
= ARC_CC_AL
+2, ARC_CC_NE
, ARC_CC_P
, ARC_CC_N
,
867 ARC_CC_C
, ARC_CC_NC
, ARC_CC_V
, ARC_CC_NV
,
868 ARC_CC_GT
, ARC_CC_LE
, ARC_CC_GE
, ARC_CC_LT
, ARC_CC_HI
, ARC_CC_LS
, ARC_CC_PNZ
,
869 ARC_CC_LO
= ARC_CC_C
, ARC_CC_HS
= ARC_CC_NC
872 #define ARC_INVERSE_CONDITION_CODE(X) ((X) ^ 1)
874 /* Returns the index of the ARC condition code string in
875 `arc_condition_codes'. COMPARISON should be an rtx like
876 `(eq (...) (...))'. */
879 get_arc_condition_code (rtx comparison
)
881 switch (GET_MODE (XEXP (comparison
, 0)))
884 case SImode
: /* For BRcc. */
885 switch (GET_CODE (comparison
))
887 case EQ
: return ARC_CC_EQ
;
888 case NE
: return ARC_CC_NE
;
889 case GT
: return ARC_CC_GT
;
890 case LE
: return ARC_CC_LE
;
891 case GE
: return ARC_CC_GE
;
892 case LT
: return ARC_CC_LT
;
893 case GTU
: return ARC_CC_HI
;
894 case LEU
: return ARC_CC_LS
;
895 case LTU
: return ARC_CC_LO
;
896 case GEU
: return ARC_CC_HS
;
897 default : gcc_unreachable ();
900 switch (GET_CODE (comparison
))
902 case EQ
: return ARC_CC_EQ
;
903 case NE
: return ARC_CC_NE
;
904 case GE
: return ARC_CC_P
;
905 case LT
: return ARC_CC_N
;
906 case GT
: return ARC_CC_PNZ
;
907 default : gcc_unreachable ();
910 switch (GET_CODE (comparison
))
912 case EQ
: return ARC_CC_EQ
;
913 case NE
: return ARC_CC_NE
;
914 default : gcc_unreachable ();
917 switch (GET_CODE (comparison
))
919 case LTU
: return ARC_CC_C
;
920 case GEU
: return ARC_CC_NC
;
921 default : gcc_unreachable ();
924 if (TARGET_ARGONAUT_SET
&& TARGET_SPFP
)
925 switch (GET_CODE (comparison
))
927 case GT
: return ARC_CC_N
;
928 case UNLE
: return ARC_CC_P
;
929 default : gcc_unreachable ();
932 switch (GET_CODE (comparison
))
934 case GT
: return ARC_CC_HI
;
935 case UNLE
: return ARC_CC_LS
;
936 default : gcc_unreachable ();
939 /* Same for FPX and non-FPX. */
940 switch (GET_CODE (comparison
))
942 case GE
: return ARC_CC_HS
;
943 case UNLT
: return ARC_CC_LO
;
944 default : gcc_unreachable ();
947 switch (GET_CODE (comparison
))
949 case UNEQ
: return ARC_CC_EQ
;
950 case LTGT
: return ARC_CC_NE
;
951 default : gcc_unreachable ();
954 switch (GET_CODE (comparison
))
956 case UNORDERED
: return ARC_CC_C
;
957 case ORDERED
: return ARC_CC_NC
;
958 default : gcc_unreachable ();
961 switch (GET_CODE (comparison
))
963 case EQ
: return ARC_CC_EQ
;
964 case NE
: return ARC_CC_NE
;
965 case UNORDERED
: return ARC_CC_C
;
966 case ORDERED
: return ARC_CC_NC
;
967 case LTGT
: return ARC_CC_HI
;
968 case UNEQ
: return ARC_CC_LS
;
969 default : gcc_unreachable ();
971 default : gcc_unreachable ();
977 /* Return true if COMPARISON has a short form that can accomodate OFFSET. */
980 arc_short_comparison_p (rtx comparison
, int offset
)
982 gcc_assert (ARC_CC_NC
== ARC_CC_HS
);
983 gcc_assert (ARC_CC_C
== ARC_CC_LO
);
984 switch (get_arc_condition_code (comparison
))
986 case ARC_CC_EQ
: case ARC_CC_NE
:
987 return offset
>= -512 && offset
<= 506;
988 case ARC_CC_GT
: case ARC_CC_LE
: case ARC_CC_GE
: case ARC_CC_LT
:
989 case ARC_CC_HI
: case ARC_CC_LS
: case ARC_CC_LO
: case ARC_CC_HS
:
990 return offset
>= -64 && offset
<= 58;
996 /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
997 return the mode to be used for the comparison. */
1000 arc_select_cc_mode (enum rtx_code op
, rtx x
, rtx y
)
1002 machine_mode mode
= GET_MODE (x
);
1005 /* For an operation that sets the condition codes as a side-effect, the
1006 C and V flags is not set as for cmp, so we can only use comparisons where
1007 this doesn't matter. (For LT and GE we can use "mi" and "pl"
1009 /* ??? We could use "pnz" for greater than zero, however, we could then
1010 get into trouble because the comparison could not be reversed. */
1011 if (GET_MODE_CLASS (mode
) == MODE_INT
1013 && (op
== EQ
|| op
== NE
1014 || ((op
== LT
|| op
== GE
) && GET_MODE_SIZE (GET_MODE (x
)) <= 4)))
1017 /* add.f for if (a+b) */
1019 && GET_CODE (y
) == NEG
1020 && (op
== EQ
|| op
== NE
))
1023 /* Check if this is a test suitable for bxor.f . */
1024 if (mode
== SImode
&& (op
== EQ
|| op
== NE
) && CONST_INT_P (y
)
1025 && ((INTVAL (y
) - 1) & INTVAL (y
)) == 0
1029 /* Check if this is a test suitable for add / bmsk.f . */
1030 if (mode
== SImode
&& (op
== EQ
|| op
== NE
) && CONST_INT_P (y
)
1031 && GET_CODE (x
) == AND
&& CONST_INT_P ((x1
= XEXP (x
, 1)))
1032 && ((INTVAL (x1
) + 1) & INTVAL (x1
)) == 0
1033 && (~INTVAL (x1
) | INTVAL (y
)) < 0
1034 && (~INTVAL (x1
) | INTVAL (y
)) > -0x800)
1037 if (GET_MODE (x
) == SImode
&& (op
== LTU
|| op
== GEU
)
1038 && GET_CODE (x
) == PLUS
1039 && (rtx_equal_p (XEXP (x
, 0), y
) || rtx_equal_p (XEXP (x
, 1), y
)))
1042 if (TARGET_ARGONAUT_SET
1043 && ((mode
== SFmode
&& TARGET_SPFP
) || (mode
== DFmode
&& TARGET_DPFP
)))
1046 case EQ
: case NE
: case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1048 case LT
: case UNGE
: case GT
: case UNLE
:
1049 return CC_FP_GTmode
;
1050 case LE
: case UNGT
: case GE
: case UNLT
:
1051 return CC_FP_GEmode
;
1052 default: gcc_unreachable ();
1054 else if (GET_MODE_CLASS (mode
) == MODE_FLOAT
&& TARGET_OPTFPE
)
1057 case EQ
: case NE
: return CC_Zmode
;
1059 case GT
: case UNLE
: return CC_FP_GTmode
;
1061 case GE
: case UNLT
: return CC_FP_GEmode
;
1062 case UNEQ
: case LTGT
: return CC_FP_UNEQmode
;
1063 case ORDERED
: case UNORDERED
: return CC_FP_ORDmode
;
1064 default: gcc_unreachable ();
1070 /* Vectors to keep interesting information about registers where it can easily
1071 be got. We use to use the actual mode value as the bit number, but there
1072 is (or may be) more than 32 modes now. Instead we use two tables: one
1073 indexed by hard register number, and one indexed by mode. */
1075 /* The purpose of arc_mode_class is to shrink the range of modes so that
1076 they all fit (as bit numbers) in a 32-bit word (again). Each real mode is
1077 mapped into one arc_mode_class mode. */
1079 enum arc_mode_class
{
1081 S_MODE
, D_MODE
, T_MODE
, O_MODE
,
1082 SF_MODE
, DF_MODE
, TF_MODE
, OF_MODE
,
1086 /* Modes for condition codes. */
1087 #define C_MODES (1 << (int) C_MODE)
1089 /* Modes for single-word and smaller quantities. */
1090 #define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
1092 /* Modes for double-word and smaller quantities. */
1093 #define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))
1095 /* Mode for 8-byte DF values only. */
1096 #define DF_MODES (1 << DF_MODE)
1098 /* Modes for quad-word and smaller quantities. */
1099 #define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE))
1101 /* Modes for 128-bit vectors. */
1102 #define V_MODES (1 << (int) V_MODE)
1104 /* Value is 1 if register/mode pair is acceptable on arc. */
1106 unsigned int arc_hard_regno_mode_ok
[] = {
1107 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
,
1108 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
,
1109 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, D_MODES
,
1110 D_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1112 /* ??? Leave these as S_MODES for now. */
1113 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1114 DF_MODES
, 0, DF_MODES
, 0, S_MODES
, S_MODES
, S_MODES
, S_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
, C_MODES
, S_MODES
,
1118 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1119 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1120 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1121 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1123 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1124 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1125 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1126 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1128 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1129 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
1132 unsigned int arc_mode_class
[NUM_MACHINE_MODES
];
1134 enum reg_class arc_regno_reg_class
[FIRST_PSEUDO_REGISTER
];
1137 arc_preferred_reload_class (rtx
, enum reg_class cl
)
1139 if ((cl
) == CHEAP_CORE_REGS
|| (cl
) == WRITABLE_CORE_REGS
)
1140 return GENERAL_REGS
;
1144 /* Initialize the arc_mode_class array. */
1147 arc_init_reg_tables (void)
1151 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
1153 machine_mode m
= (machine_mode
) i
;
1155 switch (GET_MODE_CLASS (m
))
1158 case MODE_PARTIAL_INT
:
1159 case MODE_COMPLEX_INT
:
1160 if (GET_MODE_SIZE (m
) <= 4)
1161 arc_mode_class
[i
] = 1 << (int) S_MODE
;
1162 else if (GET_MODE_SIZE (m
) == 8)
1163 arc_mode_class
[i
] = 1 << (int) D_MODE
;
1164 else if (GET_MODE_SIZE (m
) == 16)
1165 arc_mode_class
[i
] = 1 << (int) T_MODE
;
1166 else if (GET_MODE_SIZE (m
) == 32)
1167 arc_mode_class
[i
] = 1 << (int) O_MODE
;
1169 arc_mode_class
[i
] = 0;
1172 case MODE_COMPLEX_FLOAT
:
1173 if (GET_MODE_SIZE (m
) <= 4)
1174 arc_mode_class
[i
] = 1 << (int) SF_MODE
;
1175 else if (GET_MODE_SIZE (m
) == 8)
1176 arc_mode_class
[i
] = 1 << (int) DF_MODE
;
1177 else if (GET_MODE_SIZE (m
) == 16)
1178 arc_mode_class
[i
] = 1 << (int) TF_MODE
;
1179 else if (GET_MODE_SIZE (m
) == 32)
1180 arc_mode_class
[i
] = 1 << (int) OF_MODE
;
1182 arc_mode_class
[i
] = 0;
1184 case MODE_VECTOR_INT
:
1185 arc_mode_class
[i
] = (1<< (int) V_MODE
);
1189 /* mode_class hasn't been initialized yet for EXTRA_CC_MODES, so
1190 we must explicitly check for them here. */
1191 if (i
== (int) CCmode
|| i
== (int) CC_ZNmode
|| i
== (int) CC_Zmode
1192 || i
== (int) CC_Cmode
1193 || i
== CC_FP_GTmode
|| i
== CC_FP_GEmode
|| i
== CC_FP_ORDmode
)
1194 arc_mode_class
[i
] = 1 << (int) C_MODE
;
1196 arc_mode_class
[i
] = 0;
1202 /* Core registers 56..59 are used for multiply extension options.
1203 The dsp option uses r56 and r57, these are then named acc1 and acc2.
1204 acc1 is the highpart, and acc2 the lowpart, so which register gets which
1205 number depends on endianness.
1206 The mul64 multiplier options use r57 for mlo, r58 for mmid and r59 for mhi.
1207 Because mlo / mhi form a 64 bit value, we use different gcc internal
1208 register numbers to make them form a register pair as the gcc internals
1209 know it. mmid gets number 57, if still available, and mlo / mhi get
1210 number 58 and 59, depending on endianness. We use DBX_REGISTER_NUMBER
1211 to map this back. */
1212 char rname56
[5] = "r56";
1213 char rname57
[5] = "r57";
1214 char rname58
[5] = "r58";
1215 char rname59
[5] = "r59";
1218 arc_conditional_register_usage (void)
1222 int fix_start
= 60, fix_end
= 55;
1224 if (TARGET_MUL64_SET
)
1229 /* We don't provide a name for mmed. In rtl / assembly resource lists,
1230 you are supposed to refer to it as mlo & mhi, e.g
1231 (zero_extract:SI (reg:DI 58) (const_int 32) (16)) .
1232 In an actual asm instruction, you are of course use mmed.
1233 The point of avoiding having a separate register for mmed is that
1234 this way, we don't have to carry clobbers of that reg around in every
1235 isntruction that modifies mlo and/or mhi. */
1236 strcpy (rname57
, "");
1237 strcpy (rname58
, TARGET_BIG_ENDIAN
? "mhi" : "mlo");
1238 strcpy (rname59
, TARGET_BIG_ENDIAN
? "mlo" : "mhi");
1240 if (TARGET_MULMAC_32BY16_SET
)
1243 fix_end
= fix_end
> 57 ? fix_end
: 57;
1244 strcpy (rname56
, TARGET_BIG_ENDIAN
? "acc1" : "acc2");
1245 strcpy (rname57
, TARGET_BIG_ENDIAN
? "acc2" : "acc1");
1247 for (regno
= fix_start
; regno
<= fix_end
; regno
++)
1249 if (!fixed_regs
[regno
])
1250 warning (0, "multiply option implies r%d is fixed", regno
);
1251 fixed_regs
[regno
] = call_used_regs
[regno
] = 1;
1255 reg_alloc_order
[2] = 12;
1256 reg_alloc_order
[3] = 13;
1257 reg_alloc_order
[4] = 14;
1258 reg_alloc_order
[5] = 15;
1259 reg_alloc_order
[6] = 1;
1260 reg_alloc_order
[7] = 0;
1261 reg_alloc_order
[8] = 4;
1262 reg_alloc_order
[9] = 5;
1263 reg_alloc_order
[10] = 6;
1264 reg_alloc_order
[11] = 7;
1265 reg_alloc_order
[12] = 8;
1266 reg_alloc_order
[13] = 9;
1267 reg_alloc_order
[14] = 10;
1268 reg_alloc_order
[15] = 11;
1270 if (TARGET_SIMD_SET
)
1273 for (i
= ARC_FIRST_SIMD_VR_REG
; i
<= ARC_LAST_SIMD_VR_REG
; i
++)
1274 reg_alloc_order
[i
] = i
;
1275 for (i
= ARC_FIRST_SIMD_DMA_CONFIG_REG
;
1276 i
<= ARC_LAST_SIMD_DMA_CONFIG_REG
; i
++)
1277 reg_alloc_order
[i
] = i
;
1279 /* For Arctangent-A5 / ARC600, lp_count may not be read in an instruction
1280 following immediately after another one setting it to a new value.
1281 There was some discussion on how to enforce scheduling constraints for
1282 processors with missing interlocks on the gcc mailing list:
1283 http://gcc.gnu.org/ml/gcc/2008-05/msg00021.html .
1284 However, we can't actually use this approach, because for ARC the
1285 delay slot scheduling pass is active, which runs after
1286 machine_dependent_reorg. */
1288 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], LP_COUNT
);
1289 else if (!TARGET_ARC700
)
1290 fixed_regs
[LP_COUNT
] = 1;
1291 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
1292 if (!call_used_regs
[regno
])
1293 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], regno
);
1294 for (regno
= 32; regno
< 60; regno
++)
1295 if (!fixed_regs
[regno
])
1296 SET_HARD_REG_BIT (reg_class_contents
[WRITABLE_CORE_REGS
], regno
);
1299 for (regno
= 32; regno
<= 60; regno
++)
1300 CLEAR_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], regno
);
1302 /* If they have used -ffixed-lp_count, make sure it takes
1304 if (fixed_regs
[LP_COUNT
])
1306 CLEAR_HARD_REG_BIT (reg_class_contents
[LPCOUNT_REG
], LP_COUNT
);
1307 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], LP_COUNT
);
1308 CLEAR_HARD_REG_BIT (reg_class_contents
[WRITABLE_CORE_REGS
], LP_COUNT
);
1310 /* Instead of taking out SF_MODE like below, forbid it outright. */
1311 arc_hard_regno_mode_ok
[60] = 0;
1314 arc_hard_regno_mode_ok
[60] = 1 << (int) S_MODE
;
1317 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1321 if (TARGET_Q_CLASS
&& ((i
<= 3) || ((i
>= 12) && (i
<= 15))))
1322 arc_regno_reg_class
[i
] = ARCOMPACT16_REGS
;
1324 arc_regno_reg_class
[i
] = GENERAL_REGS
;
1327 arc_regno_reg_class
[i
]
1329 ? (TEST_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], i
)
1330 ? CHEAP_CORE_REGS
: ALL_CORE_REGS
)
1332 && TEST_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], i
))
1333 ? CHEAP_CORE_REGS
: WRITABLE_CORE_REGS
));
1335 arc_regno_reg_class
[i
] = NO_REGS
;
1338 /* ARCOMPACT16_REGS is empty, if TARGET_Q_CLASS has not been activated. */
1339 if (!TARGET_Q_CLASS
)
1341 CLEAR_HARD_REG_SET(reg_class_contents
[ARCOMPACT16_REGS
]);
1342 CLEAR_HARD_REG_SET(reg_class_contents
[AC16_BASE_REGS
]);
1345 gcc_assert (FIRST_PSEUDO_REGISTER
>= 144);
1347 /* Handle Special Registers. */
1348 arc_regno_reg_class
[29] = LINK_REGS
; /* ilink1 register. */
1349 arc_regno_reg_class
[30] = LINK_REGS
; /* ilink2 register. */
1350 arc_regno_reg_class
[31] = LINK_REGS
; /* blink register. */
1351 arc_regno_reg_class
[60] = LPCOUNT_REG
;
1352 arc_regno_reg_class
[61] = NO_REGS
; /* CC_REG: must be NO_REGS. */
1353 arc_regno_reg_class
[62] = GENERAL_REGS
;
1357 for (i
= 40; i
< 44; ++i
)
1359 arc_regno_reg_class
[i
] = DOUBLE_REGS
;
1361 /* Unless they want us to do 'mov d1, 0x00000000' make sure
1362 no attempt is made to use such a register as a destination
1363 operand in *movdf_insn. */
1364 if (!TARGET_ARGONAUT_SET
)
1366 /* Make sure no 'c', 'w', 'W', or 'Rac' constraint is
1367 interpreted to mean they can use D1 or D2 in their insn. */
1368 CLEAR_HARD_REG_BIT(reg_class_contents
[CHEAP_CORE_REGS
], i
);
1369 CLEAR_HARD_REG_BIT(reg_class_contents
[ALL_CORE_REGS
], i
);
1370 CLEAR_HARD_REG_BIT(reg_class_contents
[WRITABLE_CORE_REGS
], i
);
1371 CLEAR_HARD_REG_BIT(reg_class_contents
[MPY_WRITABLE_CORE_REGS
], i
);
1377 /* Disable all DOUBLE_REGISTER settings,
1378 if not generating DPFP code. */
1379 arc_regno_reg_class
[40] = ALL_REGS
;
1380 arc_regno_reg_class
[41] = ALL_REGS
;
1381 arc_regno_reg_class
[42] = ALL_REGS
;
1382 arc_regno_reg_class
[43] = ALL_REGS
;
1384 arc_hard_regno_mode_ok
[40] = 0;
1385 arc_hard_regno_mode_ok
[42] = 0;
1387 CLEAR_HARD_REG_SET(reg_class_contents
[DOUBLE_REGS
]);
1390 if (TARGET_SIMD_SET
)
1392 gcc_assert (ARC_FIRST_SIMD_VR_REG
== 64);
1393 gcc_assert (ARC_LAST_SIMD_VR_REG
== 127);
1395 for (i
= ARC_FIRST_SIMD_VR_REG
; i
<= ARC_LAST_SIMD_VR_REG
; i
++)
1396 arc_regno_reg_class
[i
] = SIMD_VR_REGS
;
1398 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_REG
== 128);
1399 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_IN_REG
== 128);
1400 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG
== 136);
1401 gcc_assert (ARC_LAST_SIMD_DMA_CONFIG_REG
== 143);
1403 for (i
= ARC_FIRST_SIMD_DMA_CONFIG_REG
;
1404 i
<= ARC_LAST_SIMD_DMA_CONFIG_REG
; i
++)
1405 arc_regno_reg_class
[i
] = SIMD_DMA_CONFIG_REGS
;
1409 arc_regno_reg_class
[PROGRAM_COUNTER_REGNO
] = GENERAL_REGS
;
1412 /* Handle an "interrupt" attribute; arguments as in
1413 struct attribute_spec.handler. */
1416 arc_handle_interrupt_attribute (tree
*, tree name
, tree args
, int,
1421 tree value
= TREE_VALUE (args
);
1423 if (TREE_CODE (value
) != STRING_CST
)
1425 warning (OPT_Wattributes
,
1426 "argument of %qE attribute is not a string constant",
1428 *no_add_attrs
= true;
1430 else if (strcmp (TREE_STRING_POINTER (value
), "ilink1")
1431 && strcmp (TREE_STRING_POINTER (value
), "ilink2"))
1433 warning (OPT_Wattributes
,
1434 "argument of %qE attribute is not \"ilink1\" or \"ilink2\"",
1436 *no_add_attrs
= true;
1441 /* Return zero if TYPE1 and TYPE are incompatible, one if they are compatible,
1442 and two if they are nearly compatible (which causes a warning to be
1446 arc_comp_type_attributes (const_tree type1
,
1449 int l1
, l2
, m1
, m2
, s1
, s2
;
1451 /* Check for mismatch of non-default calling convention. */
1452 if (TREE_CODE (type1
) != FUNCTION_TYPE
)
1455 /* Check for mismatched call attributes. */
1456 l1
= lookup_attribute ("long_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
1457 l2
= lookup_attribute ("long_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
1458 m1
= lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
1459 m2
= lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
1460 s1
= lookup_attribute ("short_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
1461 s2
= lookup_attribute ("short_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
1463 /* Only bother to check if an attribute is defined. */
1464 if (l1
| l2
| m1
| m2
| s1
| s2
)
1466 /* If one type has an attribute, the other must have the same attribute. */
1467 if ((l1
!= l2
) || (m1
!= m2
) || (s1
!= s2
))
1470 /* Disallow mixed attributes. */
1471 if (l1
+ m1
+ s1
> 1)
1479 /* Set the default attributes for TYPE. */
1482 arc_set_default_type_attributes (tree type ATTRIBUTE_UNUSED
)
1487 /* Misc. utilities. */
1489 /* X and Y are two things to compare using CODE. Emit the compare insn and
1490 return the rtx for the cc reg in the proper mode. */
1493 gen_compare_reg (rtx comparison
, machine_mode omode
)
1495 enum rtx_code code
= GET_CODE (comparison
);
1496 rtx x
= XEXP (comparison
, 0);
1497 rtx y
= XEXP (comparison
, 1);
1499 machine_mode mode
, cmode
;
1502 cmode
= GET_MODE (x
);
1503 if (cmode
== VOIDmode
)
1504 cmode
= GET_MODE (y
);
1505 gcc_assert (cmode
== SImode
|| cmode
== SFmode
|| cmode
== DFmode
);
1506 if (cmode
== SImode
)
1508 if (!register_operand (x
, SImode
))
1510 if (register_operand (y
, SImode
))
1515 code
= swap_condition (code
);
1518 x
= copy_to_mode_reg (SImode
, x
);
1520 if (GET_CODE (y
) == SYMBOL_REF
&& flag_pic
)
1521 y
= copy_to_mode_reg (SImode
, y
);
1525 x
= force_reg (cmode
, x
);
1526 y
= force_reg (cmode
, y
);
1528 mode
= SELECT_CC_MODE (code
, x
, y
);
1530 cc_reg
= gen_rtx_REG (mode
, CC_REG
);
1532 /* ??? FIXME (x-y)==0, as done by both cmpsfpx_raw and
1533 cmpdfpx_raw, is not a correct comparison for floats:
1534 http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
1536 if (TARGET_ARGONAUT_SET
1537 && ((cmode
== SFmode
&& TARGET_SPFP
) || (cmode
== DFmode
&& TARGET_DPFP
)))
1541 case NE
: case EQ
: case LT
: case UNGE
: case LE
: case UNGT
:
1542 case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1544 case GT
: case UNLE
: case GE
: case UNLT
:
1545 code
= swap_condition (code
);
1553 if (cmode
== SFmode
)
1555 emit_insn (gen_cmpsfpx_raw (x
, y
));
1559 /* Accepts Dx regs directly by insns. */
1560 emit_insn (gen_cmpdfpx_raw (x
, y
));
1563 if (mode
!= CC_FPXmode
)
1564 emit_insn (gen_rtx_SET (VOIDmode
, cc_reg
,
1565 gen_rtx_COMPARE (mode
,
1566 gen_rtx_REG (CC_FPXmode
, 61),
1569 else if (GET_MODE_CLASS (cmode
) == MODE_FLOAT
&& TARGET_OPTFPE
)
1571 rtx op0
= gen_rtx_REG (cmode
, 0);
1572 rtx op1
= gen_rtx_REG (cmode
, GET_MODE_SIZE (cmode
) / UNITS_PER_WORD
);
1576 case NE
: case EQ
: case GT
: case UNLE
: case GE
: case UNLT
:
1577 case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1579 case LT
: case UNGE
: case LE
: case UNGT
:
1580 code
= swap_condition (code
);
1588 if (currently_expanding_to_rtl
)
1590 emit_move_insn (op0
, x
);
1591 emit_move_insn (op1
, y
);
1595 gcc_assert (rtx_equal_p (op0
, x
));
1596 gcc_assert (rtx_equal_p (op1
, y
));
1598 emit_insn (gen_cmp_float (cc_reg
, gen_rtx_COMPARE (mode
, op0
, op1
)));
1601 emit_insn (gen_rtx_SET (omode
, cc_reg
,
1602 gen_rtx_COMPARE (mode
, x
, y
)));
1603 return gen_rtx_fmt_ee (code
, omode
, cc_reg
, const0_rtx
);
1606 /* Return true if VALUE, a const_double, will fit in a limm (4 byte number).
1607 We assume the value can be either signed or unsigned. */
1610 arc_double_limm_p (rtx value
)
1612 HOST_WIDE_INT low
, high
;
1614 gcc_assert (GET_CODE (value
) == CONST_DOUBLE
);
1619 low
= CONST_DOUBLE_LOW (value
);
1620 high
= CONST_DOUBLE_HIGH (value
);
1622 if (low
& 0x80000000)
1624 return (((unsigned HOST_WIDE_INT
) low
<= 0xffffffff && high
== 0)
1625 || (((low
& - (unsigned HOST_WIDE_INT
) 0x80000000)
1626 == - (unsigned HOST_WIDE_INT
) 0x80000000)
1631 return (unsigned HOST_WIDE_INT
) low
<= 0x7fffffff && high
== 0;
1635 /* Do any needed setup for a variadic function. For the ARC, we must
1636 create a register parameter block, and then copy any anonymous arguments
1637 in registers to memory.
1639 CUM has not been updated for the last named argument which has type TYPE
1640 and mode MODE, and we rely on this fact. */
1643 arc_setup_incoming_varargs (cumulative_args_t args_so_far
,
1644 machine_mode mode
, tree type
,
1645 int *pretend_size
, int no_rtl
)
1648 CUMULATIVE_ARGS next_cum
;
1650 /* We must treat `__builtin_va_alist' as an anonymous arg. */
1652 next_cum
= *get_cumulative_args (args_so_far
);
1653 arc_function_arg_advance (pack_cumulative_args (&next_cum
), mode
, type
, 1);
1654 first_anon_arg
= next_cum
;
1656 if (first_anon_arg
< MAX_ARC_PARM_REGS
)
1658 /* First anonymous (unnamed) argument is in a reg. */
1660 /* Note that first_reg_offset < MAX_ARC_PARM_REGS. */
1661 int first_reg_offset
= first_anon_arg
;
1666 = gen_rtx_MEM (BLKmode
, plus_constant (Pmode
, arg_pointer_rtx
,
1667 FIRST_PARM_OFFSET (0)));
1668 move_block_from_reg (first_reg_offset
, regblock
,
1669 MAX_ARC_PARM_REGS
- first_reg_offset
);
1673 = ((MAX_ARC_PARM_REGS
- first_reg_offset
) * UNITS_PER_WORD
);
1677 /* Cost functions. */
1679 /* Provide the costs of an addressing mode that contains ADDR.
1680 If ADDR is not a valid address, its cost is irrelevant. */
1683 arc_address_cost (rtx addr
, machine_mode
, addr_space_t
, bool speed
)
1685 switch (GET_CODE (addr
))
1688 return speed
|| satisfies_constraint_Rcq (addr
) ? 0 : 1;
1689 case PRE_INC
: case PRE_DEC
: case POST_INC
: case POST_DEC
:
1690 case PRE_MODIFY
: case POST_MODIFY
:
1696 /* Most likely needs a LIMM. */
1697 return COSTS_N_INSNS (1);
1701 register rtx plus0
= XEXP (addr
, 0);
1702 register rtx plus1
= XEXP (addr
, 1);
1704 if (GET_CODE (plus0
) != REG
1705 && (GET_CODE (plus0
) != MULT
1706 || !CONST_INT_P (XEXP (plus0
, 1))
1707 || (INTVAL (XEXP (plus0
, 1)) != 2
1708 && INTVAL (XEXP (plus0
, 1)) != 4)))
1711 switch (GET_CODE (plus1
))
1714 return (!RTX_OK_FOR_OFFSET_P (SImode
, plus1
)
1718 : (satisfies_constraint_Rcq (plus0
)
1719 && satisfies_constraint_O (plus1
))
1723 return (speed
< 1 ? 0
1724 : (satisfies_constraint_Rcq (plus0
)
1725 && satisfies_constraint_Rcq (plus1
))
1730 return COSTS_N_INSNS (1);
1743 /* Emit instruction X with the frame related bit set. */
1749 RTX_FRAME_RELATED_P (x
) = 1;
1753 /* Emit a frame insn to move SRC to DST. */
1756 frame_move (rtx dst
, rtx src
)
1758 return frame_insn (gen_rtx_SET (VOIDmode
, dst
, src
));
1761 /* Like frame_move, but add a REG_INC note for REG if ADDR contains an
1762 auto increment address, or is zero. */
1765 frame_move_inc (rtx dst
, rtx src
, rtx reg
, rtx addr
)
1767 rtx insn
= frame_move (dst
, src
);
1770 || GET_CODE (addr
) == PRE_DEC
|| GET_CODE (addr
) == POST_INC
1771 || GET_CODE (addr
) == PRE_MODIFY
|| GET_CODE (addr
) == POST_MODIFY
)
1772 add_reg_note (insn
, REG_INC
, reg
);
1776 /* Emit a frame insn which adjusts a frame address register REG by OFFSET. */
1779 frame_add (rtx reg
, HOST_WIDE_INT offset
)
1781 gcc_assert ((offset
& 0x3) == 0);
1784 return frame_move (reg
, plus_constant (Pmode
, reg
, offset
));
1787 /* Emit a frame insn which adjusts stack pointer by OFFSET. */
1790 frame_stack_add (HOST_WIDE_INT offset
)
1792 return frame_add (stack_pointer_rtx
, offset
);
1795 /* Traditionally, we push saved registers first in the prologue,
1796 then we allocate the rest of the frame - and reverse in the epilogue.
1797 This has still its merits for ease of debugging, or saving code size
1798 or even execution time if the stack frame is so large that some accesses
1799 can't be encoded anymore with offsets in the instruction code when using
1801 Also, it would be a good starting point if we got instructions to help
1802 with register save/restore.
1804 However, often stack frames are small, and the pushing / popping has
1806 - the stack modification prevents a lot of scheduling.
1807 - frame allocation / deallocation needs extra instructions.
1808 - unless we know that we compile ARC700 user code, we need to put
1809 a memory barrier after frame allocation / before deallocation to
1810 prevent interrupts clobbering our data in the frame.
1811 In particular, we don't have any such guarantees for library functions,
1812 which tend to, on the other hand, to have small frames.
1814 Thus, for small frames, we'd like to use a different scheme:
1815 - The frame is allocated in full with the first prologue instruction,
1816 and deallocated in full with the last epilogue instruction.
1817 Thus, the instructions in-betwen can be freely scheduled.
1818 - If the function has no outgoing arguments on the stack, we can allocate
1819 one register save slot at the top of the stack. This register can then
1820 be saved simultanously with frame allocation, and restored with
1822 This register can be picked depending on scheduling considerations,
1823 although same though should go into having some set of registers
1824 to be potentially lingering after a call, and others to be available
1825 immediately - i.e. in the absence of interprocedual optimization, we
1826 can use an ABI-like convention for register allocation to reduce
1827 stalls after function return. */
1828 /* Function prologue/epilogue handlers. */
1830 /* ARCompact stack frames look like:
1832 Before call After call
1833 high +-----------------------+ +-----------------------+
1834 mem | reg parm save area | | reg parm save area |
1835 | only created for | | only created for |
1836 | variable arg fns | | variable arg fns |
1837 AP +-----------------------+ +-----------------------+
1838 | return addr register | | return addr register |
1839 | (if required) | | (if required) |
1840 +-----------------------+ +-----------------------+
1842 | reg save area | | reg save area |
1844 +-----------------------+ +-----------------------+
1845 | frame pointer | | frame pointer |
1846 | (if required) | | (if required) |
1847 FP +-----------------------+ +-----------------------+
1849 | local/temp variables | | local/temp variables |
1851 +-----------------------+ +-----------------------+
1853 | arguments on stack | | arguments on stack |
1855 SP +-----------------------+ +-----------------------+
1856 | reg parm save area |
1857 | only created for |
1858 | variable arg fns |
1859 AP +-----------------------+
1860 | return addr register |
1862 +-----------------------+
1866 +-----------------------+
1869 FP +-----------------------+
1871 | local/temp variables |
1873 +-----------------------+
1875 | arguments on stack |
1877 mem SP +-----------------------+
1880 1) The "reg parm save area" does not exist for non variable argument fns.
1881 The "reg parm save area" can be eliminated completely if we created our
1882 own va-arc.h, but that has tradeoffs as well (so it's not done). */
1884 /* Structure to be filled in by arc_compute_frame_size with register
1885 save masks, and offsets for the current function. */
1886 struct GTY (()) arc_frame_info
1888 unsigned int total_size
; /* # bytes that the entire frame takes up. */
1889 unsigned int extra_size
; /* # bytes of extra stuff. */
1890 unsigned int pretend_size
; /* # bytes we push and pretend caller did. */
1891 unsigned int args_size
; /* # bytes that outgoing arguments take up. */
1892 unsigned int reg_size
; /* # bytes needed to store regs. */
1893 unsigned int var_size
; /* # bytes that variables take up. */
1894 unsigned int reg_offset
; /* Offset from new sp to store regs. */
1895 unsigned int gmask
; /* Mask of saved gp registers. */
1896 int initialized
; /* Nonzero if frame size already calculated. */
1897 short millicode_start_reg
;
1898 short millicode_end_reg
;
1899 bool save_return_addr
;
1902 /* Defining data structures for per-function information. */
1904 typedef struct GTY (()) machine_function
1906 enum arc_function_type fn_type
;
1907 struct arc_frame_info frame_info
;
1908 /* To keep track of unalignment caused by short insns. */
1910 int force_short_suffix
; /* Used when disgorging return delay slot insns. */
1911 const char *size_reason
;
1912 struct arc_ccfsm ccfsm_current
;
1913 /* Map from uid to ccfsm state during branch shortening. */
1914 rtx ccfsm_current_insn
;
1915 char arc_reorg_started
;
1916 char prescan_initialized
;
1919 /* Type of function DECL.
1921 The result is cached. To reset the cache at the end of a function,
1922 call with DECL = NULL_TREE. */
1924 enum arc_function_type
1925 arc_compute_function_type (struct function
*fun
)
1927 tree decl
= fun
->decl
;
1929 enum arc_function_type fn_type
= fun
->machine
->fn_type
;
1931 if (fn_type
!= ARC_FUNCTION_UNKNOWN
)
1934 /* Assume we have a normal function (not an interrupt handler). */
1935 fn_type
= ARC_FUNCTION_NORMAL
;
1937 /* Now see if this is an interrupt handler. */
1938 for (a
= DECL_ATTRIBUTES (decl
);
1942 tree name
= TREE_PURPOSE (a
), args
= TREE_VALUE (a
);
1944 if (name
== get_identifier ("interrupt")
1945 && list_length (args
) == 1
1946 && TREE_CODE (TREE_VALUE (args
)) == STRING_CST
)
1948 tree value
= TREE_VALUE (args
);
1950 if (!strcmp (TREE_STRING_POINTER (value
), "ilink1"))
1951 fn_type
= ARC_FUNCTION_ILINK1
;
1952 else if (!strcmp (TREE_STRING_POINTER (value
), "ilink2"))
1953 fn_type
= ARC_FUNCTION_ILINK2
;
1960 return fun
->machine
->fn_type
= fn_type
;
1963 #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
1964 #define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM))
1966 /* Tell prologue and epilogue if register REGNO should be saved / restored.
1967 The return address and frame pointer are treated separately.
1968 Don't consider them here.
1969 Addition for pic: The gp register needs to be saved if the current
1970 function changes it to access gotoff variables.
1971 FIXME: This will not be needed if we used some arbitrary register
1974 #define MUST_SAVE_REGISTER(regno, interrupt_p) \
1975 (((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \
1976 && (df_regs_ever_live_p (regno) && (!call_used_regs[regno] || interrupt_p))) \
1977 || (flag_pic && crtl->uses_pic_offset_table \
1978 && regno == PIC_OFFSET_TABLE_REGNUM) )
1980 #define MUST_SAVE_RETURN_ADDR \
1981 (cfun->machine->frame_info.save_return_addr)
1983 /* Return non-zero if there are registers to be saved or loaded using
1984 millicode thunks. We can only use consecutive sequences starting
1985 with r13, and not going beyond r25.
1986 GMASK is a bitmask of registers to save. This function sets
1987 FRAME->millicod_start_reg .. FRAME->millicode_end_reg to the range
1988 of registers to be saved / restored with a millicode call. */
1991 arc_compute_millicode_save_restore_regs (unsigned int gmask
,
1992 struct arc_frame_info
*frame
)
1996 int start_reg
= 13, end_reg
= 25;
1998 for (regno
= start_reg
; regno
<= end_reg
&& (gmask
& (1L << regno
));)
2000 end_reg
= regno
- 1;
2001 /* There is no point in using millicode thunks if we don't save/restore
2002 at least three registers. For non-leaf functions we also have the
2004 if (regno
- start_reg
>= 3 - (crtl
->is_leaf
== 0))
2006 frame
->millicode_start_reg
= 13;
2007 frame
->millicode_end_reg
= regno
- 1;
2013 /* Return the bytes needed to compute the frame pointer from the current
2016 SIZE is the size needed for local variables. */
2019 arc_compute_frame_size (int size
) /* size = # of var. bytes allocated. */
2022 unsigned int total_size
, var_size
, args_size
, pretend_size
, extra_size
;
2023 unsigned int reg_size
, reg_offset
;
2025 enum arc_function_type fn_type
;
2027 struct arc_frame_info
*frame_info
= &cfun
->machine
->frame_info
;
2029 size
= ARC_STACK_ALIGN (size
);
2031 /* 1) Size of locals and temporaries */
2034 /* 2) Size of outgoing arguments */
2035 args_size
= crtl
->outgoing_args_size
;
2037 /* 3) Calculate space needed for saved registers.
2038 ??? We ignore the extension registers for now. */
2040 /* See if this is an interrupt handler. Call used registers must be saved
2045 fn_type
= arc_compute_function_type (cfun
);
2046 interrupt_p
= ARC_INTERRUPT_P (fn_type
);
2048 for (regno
= 0; regno
<= 31; regno
++)
2050 if (MUST_SAVE_REGISTER (regno
, interrupt_p
))
2052 reg_size
+= UNITS_PER_WORD
;
2053 gmask
|= 1 << regno
;
2057 /* 4) Space for back trace data structure.
2058 <return addr reg size> (if required) + <fp size> (if required). */
2059 frame_info
->save_return_addr
2060 = (!crtl
->is_leaf
|| df_regs_ever_live_p (RETURN_ADDR_REGNUM
));
2061 /* Saving blink reg in case of leaf function for millicode thunk calls. */
2062 if (optimize_size
&& !TARGET_NO_MILLICODE_THUNK_SET
)
2064 if (arc_compute_millicode_save_restore_regs (gmask
, frame_info
))
2065 frame_info
->save_return_addr
= true;
2069 if (MUST_SAVE_RETURN_ADDR
)
2071 if (frame_pointer_needed
)
2074 /* 5) Space for variable arguments passed in registers */
2075 pretend_size
= crtl
->args
.pretend_args_size
;
2077 /* Ensure everything before the locals is aligned appropriately. */
2079 unsigned int extra_plus_reg_size
;
2080 unsigned int extra_plus_reg_size_aligned
;
2082 extra_plus_reg_size
= extra_size
+ reg_size
;
2083 extra_plus_reg_size_aligned
= ARC_STACK_ALIGN(extra_plus_reg_size
);
2084 reg_size
= extra_plus_reg_size_aligned
- extra_size
;
2087 /* Compute total frame size. */
2088 total_size
= var_size
+ args_size
+ extra_size
+ pretend_size
+ reg_size
;
2090 total_size
= ARC_STACK_ALIGN (total_size
);
2092 /* Compute offset of register save area from stack pointer:
2093 A5 Frame: pretend_size <blink> reg_size <fp> var_size args_size <--sp
2095 reg_offset
= (total_size
- (pretend_size
+ reg_size
+ extra_size
)
2096 + (frame_pointer_needed
? 4 : 0));
2098 /* Save computed information. */
2099 frame_info
->total_size
= total_size
;
2100 frame_info
->extra_size
= extra_size
;
2101 frame_info
->pretend_size
= pretend_size
;
2102 frame_info
->var_size
= var_size
;
2103 frame_info
->args_size
= args_size
;
2104 frame_info
->reg_size
= reg_size
;
2105 frame_info
->reg_offset
= reg_offset
;
2106 frame_info
->gmask
= gmask
;
2107 frame_info
->initialized
= reload_completed
;
2109 /* Ok, we're done. */
2113 /* Common code to save/restore registers. */
2114 /* BASE_REG is the base register to use for addressing and to adjust.
2115 GMASK is a bitmask of general purpose registers to save/restore.
2116 epilogue_p 0: prologue 1:epilogue 2:epilogue, sibling thunk
2117 If *FIRST_OFFSET is non-zero, add it first to BASE_REG - preferably
2118 using a pre-modify for the first memory access. *FIRST_OFFSET is then
2122 arc_save_restore (rtx base_reg
,
2123 unsigned int gmask
, int epilogue_p
, int *first_offset
)
2125 unsigned int offset
= 0;
2127 struct arc_frame_info
*frame
= &cfun
->machine
->frame_info
;
2128 rtx sibthunk_insn
= NULL_RTX
;
2132 /* Millicode thunks implementation:
2133 Generates calls to millicodes for registers starting from r13 to r25
2134 Present Limitations:
2135 - Only one range supported. The remaining regs will have the ordinary
2136 st and ld instructions for store and loads. Hence a gmask asking
2137 to store r13-14, r16-r25 will only generate calls to store and
2138 load r13 to r14 while store and load insns will be generated for
2139 r16 to r25 in the prologue and epilogue respectively.
2141 - Presently library only supports register ranges starting from r13.
2143 if (epilogue_p
== 2 || frame
->millicode_end_reg
> 14)
2145 int start_call
= frame
->millicode_start_reg
;
2146 int end_call
= frame
->millicode_end_reg
;
2147 int n_regs
= end_call
- start_call
+ 1;
2148 int i
= 0, r
, off
= 0;
2150 rtx ret_addr
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
2154 /* "reg_size" won't be more than 127 . */
2155 gcc_assert (epilogue_p
|| abs (*first_offset
) <= 127);
2156 frame_add (base_reg
, *first_offset
);
2159 insn
= gen_rtx_PARALLEL
2160 (VOIDmode
, rtvec_alloc ((epilogue_p
== 2) + n_regs
+ 1));
2161 if (epilogue_p
== 2)
2164 XVECEXP (insn
, 0, n_regs
) = gen_rtx_CLOBBER (VOIDmode
, ret_addr
);
2165 for (r
= start_call
; r
<= end_call
; r
++, off
+= UNITS_PER_WORD
, i
++)
2167 rtx reg
= gen_rtx_REG (SImode
, r
);
2169 = gen_frame_mem (SImode
, plus_constant (Pmode
, base_reg
, off
));
2172 XVECEXP (insn
, 0, i
) = gen_rtx_SET (VOIDmode
, reg
, mem
);
2174 XVECEXP (insn
, 0, i
) = gen_rtx_SET (VOIDmode
, mem
, reg
);
2175 gmask
= gmask
& ~(1L << r
);
2177 if (epilogue_p
== 2)
2178 sibthunk_insn
= insn
;
2184 for (regno
= 0; regno
<= 31; regno
++)
2186 if ((gmask
& (1L << regno
)) != 0)
2188 rtx reg
= gen_rtx_REG (SImode
, regno
);
2193 gcc_assert (!offset
);
2194 addr
= plus_constant (Pmode
, base_reg
, *first_offset
);
2195 addr
= gen_rtx_PRE_MODIFY (Pmode
, base_reg
, addr
);
2200 gcc_assert (SMALL_INT (offset
));
2201 addr
= plus_constant (Pmode
, base_reg
, offset
);
2203 mem
= gen_frame_mem (SImode
, addr
);
2205 frame_move_inc (reg
, mem
, base_reg
, addr
);
2207 frame_move_inc (mem
, reg
, base_reg
, addr
);
2208 offset
+= UNITS_PER_WORD
;
2214 rtx r12
= gen_rtx_REG (Pmode
, 12);
2216 frame_insn (gen_rtx_SET (VOIDmode
, r12
, GEN_INT (offset
)));
2217 XVECEXP (sibthunk_insn
, 0, 0) = ret_rtx
;
2218 XVECEXP (sibthunk_insn
, 0, 1)
2219 = gen_rtx_SET (VOIDmode
, stack_pointer_rtx
,
2220 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
, r12
));
2221 sibthunk_insn
= emit_jump_insn (sibthunk_insn
);
2222 RTX_FRAME_RELATED_P (sibthunk_insn
) = 1;
2224 } /* arc_save_restore */
2227 int arc_return_address_regs
[4]
2228 = {0, RETURN_ADDR_REGNUM
, ILINK1_REGNUM
, ILINK2_REGNUM
};
2230 /* Set up the stack and frame pointer (if desired) for the function. */
2233 arc_expand_prologue (void)
2235 int size
= get_frame_size ();
2236 unsigned int gmask
= cfun
->machine
->frame_info
.gmask
;
2237 /* unsigned int frame_pointer_offset;*/
2238 unsigned int frame_size_to_allocate
;
2239 /* (FIXME: The first store will use a PRE_MODIFY; this will usually be r13.
2240 Change the stack layout so that we rather store a high register with the
2241 PRE_MODIFY, thus enabling more short insn generation.) */
2242 int first_offset
= 0;
2244 size
= ARC_STACK_ALIGN (size
);
2246 /* Compute/get total frame size. */
2247 size
= (!cfun
->machine
->frame_info
.initialized
2248 ? arc_compute_frame_size (size
)
2249 : cfun
->machine
->frame_info
.total_size
);
2251 if (flag_stack_usage_info
)
2252 current_function_static_stack_size
= size
;
2254 /* Keep track of frame size to be allocated. */
2255 frame_size_to_allocate
= size
;
2257 /* These cases shouldn't happen. Catch them now. */
2258 gcc_assert (!(size
== 0 && gmask
));
2260 /* Allocate space for register arguments if this is a variadic function. */
2261 if (cfun
->machine
->frame_info
.pretend_size
!= 0)
2263 /* Ensure pretend_size is maximum of 8 * word_size. */
2264 gcc_assert (cfun
->machine
->frame_info
.pretend_size
<= 32);
2266 frame_stack_add (-(HOST_WIDE_INT
)cfun
->machine
->frame_info
.pretend_size
);
2267 frame_size_to_allocate
-= cfun
->machine
->frame_info
.pretend_size
;
2270 /* The home-grown ABI says link register is saved first. */
2271 if (MUST_SAVE_RETURN_ADDR
)
2273 rtx ra
= gen_rtx_REG (SImode
, RETURN_ADDR_REGNUM
);
2274 rtx mem
= gen_frame_mem (Pmode
, gen_rtx_PRE_DEC (Pmode
, stack_pointer_rtx
));
2276 frame_move_inc (mem
, ra
, stack_pointer_rtx
, 0);
2277 frame_size_to_allocate
-= UNITS_PER_WORD
;
2279 } /* MUST_SAVE_RETURN_ADDR */
2281 /* Save any needed call-saved regs (and call-used if this is an
2282 interrupt handler) for ARCompact ISA. */
2283 if (cfun
->machine
->frame_info
.reg_size
)
2285 first_offset
= -cfun
->machine
->frame_info
.reg_size
;
2286 /* N.B. FRAME_POINTER_MASK and RETURN_ADDR_MASK are cleared in gmask. */
2287 arc_save_restore (stack_pointer_rtx
, gmask
, 0, &first_offset
);
2288 frame_size_to_allocate
-= cfun
->machine
->frame_info
.reg_size
;
2292 /* Save frame pointer if needed. */
2293 if (frame_pointer_needed
)
2295 rtx addr
= gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
2296 GEN_INT (-UNITS_PER_WORD
+ first_offset
));
2297 rtx mem
= gen_frame_mem (Pmode
, gen_rtx_PRE_MODIFY (Pmode
,
2300 frame_move_inc (mem
, frame_pointer_rtx
, stack_pointer_rtx
, 0);
2301 frame_size_to_allocate
-= UNITS_PER_WORD
;
2303 frame_move (frame_pointer_rtx
, stack_pointer_rtx
);
2306 /* ??? We don't handle the case where the saved regs are more than 252
2307 bytes away from sp. This can be handled by decrementing sp once, saving
2308 the regs, and then decrementing it again. The epilogue doesn't have this
2309 problem as the `ld' insn takes reg+limm values (though it would be more
2310 efficient to avoid reg+limm). */
2312 frame_size_to_allocate
-= first_offset
;
2313 /* Allocate the stack frame. */
2314 if (frame_size_to_allocate
> 0)
2315 frame_stack_add ((HOST_WIDE_INT
) 0 - frame_size_to_allocate
);
2317 /* Setup the gp register, if needed. */
2318 if (crtl
->uses_pic_offset_table
)
2319 arc_finalize_pic ();
2322 /* Do any necessary cleanup after a function to restore stack, frame,
2326 arc_expand_epilogue (int sibcall_p
)
2328 int size
= get_frame_size ();
2329 enum arc_function_type fn_type
= arc_compute_function_type (cfun
);
2331 size
= ARC_STACK_ALIGN (size
);
2332 size
= (!cfun
->machine
->frame_info
.initialized
2333 ? arc_compute_frame_size (size
)
2334 : cfun
->machine
->frame_info
.total_size
);
2336 unsigned int pretend_size
= cfun
->machine
->frame_info
.pretend_size
;
2337 unsigned int frame_size
;
2338 unsigned int size_to_deallocate
;
2340 int can_trust_sp_p
= !cfun
->calls_alloca
;
2341 int first_offset
= 0;
2342 int millicode_p
= cfun
->machine
->frame_info
.millicode_end_reg
> 0;
2344 size_to_deallocate
= size
;
2346 frame_size
= size
- (pretend_size
+
2347 cfun
->machine
->frame_info
.reg_size
+
2348 cfun
->machine
->frame_info
.extra_size
);
2350 /* ??? There are lots of optimizations that can be done here.
2351 EG: Use fp to restore regs if it's closer.
2352 Maybe in time we'll do them all. For now, always restore regs from
2353 sp, but don't restore sp if we don't have to. */
2355 if (!can_trust_sp_p
)
2356 gcc_assert (frame_pointer_needed
);
2358 /* Restore stack pointer to the beginning of saved register area for
2362 if (frame_pointer_needed
)
2363 frame_move (stack_pointer_rtx
, frame_pointer_rtx
);
2365 first_offset
= frame_size
;
2366 size_to_deallocate
-= frame_size
;
2368 else if (!can_trust_sp_p
)
2369 frame_stack_add (-frame_size
);
2372 /* Restore any saved registers. */
2373 if (frame_pointer_needed
)
2375 rtx addr
= gen_rtx_POST_INC (Pmode
, stack_pointer_rtx
);
2377 frame_move_inc (frame_pointer_rtx
, gen_frame_mem (Pmode
, addr
),
2378 stack_pointer_rtx
, 0);
2379 size_to_deallocate
-= UNITS_PER_WORD
;
2382 /* Load blink after the calls to thunk calls in case of optimize size. */
2385 int sibthunk_p
= (!sibcall_p
2386 && fn_type
== ARC_FUNCTION_NORMAL
2387 && !cfun
->machine
->frame_info
.pretend_size
);
2389 gcc_assert (!(cfun
->machine
->frame_info
.gmask
2390 & (FRAME_POINTER_MASK
| RETURN_ADDR_MASK
)));
2391 arc_save_restore (stack_pointer_rtx
,
2392 cfun
->machine
->frame_info
.gmask
,
2393 1 + sibthunk_p
, &first_offset
);
2397 /* If we are to restore registers, and first_offset would require
2398 a limm to be encoded in a PRE_MODIFY, yet we can add it with a
2399 fast add to the stack pointer, do this now. */
2400 if ((!SMALL_INT (first_offset
)
2401 && cfun
->machine
->frame_info
.gmask
2402 && ((TARGET_ARC700
&& !optimize_size
)
2403 ? first_offset
<= 0x800
2404 : satisfies_constraint_C2a (GEN_INT (first_offset
))))
2405 /* Also do this if we have both gprs and return
2406 address to restore, and they both would need a LIMM. */
2407 || (MUST_SAVE_RETURN_ADDR
2408 && !SMALL_INT ((cfun
->machine
->frame_info
.reg_size
+ first_offset
) >> 2)
2409 && cfun
->machine
->frame_info
.gmask
))
2411 frame_stack_add (first_offset
);
2414 if (MUST_SAVE_RETURN_ADDR
)
2416 rtx ra
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
2417 int ra_offs
= cfun
->machine
->frame_info
.reg_size
+ first_offset
;
2418 rtx addr
= plus_constant (Pmode
, stack_pointer_rtx
, ra_offs
);
2420 /* If the load of blink would need a LIMM, but we can add
2421 the offset quickly to sp, do the latter. */
2422 if (!SMALL_INT (ra_offs
>> 2)
2423 && !cfun
->machine
->frame_info
.gmask
2424 && ((TARGET_ARC700
&& !optimize_size
)
2426 : satisfies_constraint_C2a (GEN_INT (ra_offs
))))
2428 size_to_deallocate
-= ra_offs
- first_offset
;
2430 frame_stack_add (ra_offs
);
2432 addr
= stack_pointer_rtx
;
2434 /* See if we can combine the load of the return address with the
2435 final stack adjustment.
2436 We need a separate load if there are still registers to
2437 restore. We also want a separate load if the combined insn
2438 would need a limm, but a separate load doesn't. */
2440 && !cfun
->machine
->frame_info
.gmask
2441 && (SMALL_INT (ra_offs
) || !SMALL_INT (ra_offs
>> 2)))
2443 addr
= gen_rtx_PRE_MODIFY (Pmode
, stack_pointer_rtx
, addr
);
2445 size_to_deallocate
-= cfun
->machine
->frame_info
.reg_size
;
2447 else if (!ra_offs
&& size_to_deallocate
== UNITS_PER_WORD
)
2449 addr
= gen_rtx_POST_INC (Pmode
, addr
);
2450 size_to_deallocate
= 0;
2452 frame_move_inc (ra
, gen_frame_mem (Pmode
, addr
), stack_pointer_rtx
, addr
);
2457 if (cfun
->machine
->frame_info
.reg_size
)
2458 arc_save_restore (stack_pointer_rtx
,
2459 /* The zeroing of these two bits is unnecessary, but leave this in for clarity. */
2460 cfun
->machine
->frame_info
.gmask
2461 & ~(FRAME_POINTER_MASK
| RETURN_ADDR_MASK
), 1, &first_offset
);
2465 /* The rest of this function does the following:
2466 ARCompact : handle epilogue_delay, restore sp (phase-2), return
2469 /* Keep track of how much of the stack pointer we've restored.
2470 It makes the following a lot more readable. */
2471 size_to_deallocate
+= first_offset
;
2472 restored
= size
- size_to_deallocate
;
2474 if (size
> restored
)
2475 frame_stack_add (size
- restored
);
2476 /* Emit the return instruction. */
2477 if (sibcall_p
== FALSE
)
2478 emit_jump_insn (gen_simple_return ());
2480 if (!TARGET_EPILOGUE_CFI
)
2484 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
2485 RTX_FRAME_RELATED_P (insn
) = 0;
2489 /* Return the offset relative to the stack pointer where the return address
2490 is stored, or -1 if it is not stored. */
2493 arc_return_slot_offset ()
2495 struct arc_frame_info
*afi
= &cfun
->machine
->frame_info
;
2497 return (afi
->save_return_addr
2498 ? afi
->total_size
- afi
->pretend_size
- afi
->extra_size
: -1);
2503 /* Emit special PIC prologues and epilogues. */
2504 /* If the function has any GOTOFF relocations, then the GOTBASE
2505 register has to be setup in the prologue
2506 The instruction needed at the function start for setting up the
2509 ----------------------------------------------------------
2510 The rtl to be emitted for this should be:
2513 (const (unspec (symref _DYNAMIC) 3)))
2514 ---------------------------------------------------------- */
2517 arc_finalize_pic (void)
2520 rtx baseptr_rtx
= gen_rtx_REG (Pmode
, PIC_OFFSET_TABLE_REGNUM
);
2522 if (crtl
->uses_pic_offset_table
== 0)
2525 gcc_assert (flag_pic
!= 0);
2527 pat
= gen_rtx_SYMBOL_REF (Pmode
, "_DYNAMIC");
2528 pat
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, pat
), ARC_UNSPEC_GOT
);
2529 pat
= gen_rtx_CONST (Pmode
, pat
);
2531 pat
= gen_rtx_SET (VOIDmode
, baseptr_rtx
, pat
);
2536 /* !TARGET_BARREL_SHIFTER support. */
2537 /* Emit a shift insn to set OP0 to OP1 shifted by OP2; CODE specifies what
2541 emit_shift (enum rtx_code code
, rtx op0
, rtx op1
, rtx op2
)
2543 rtx shift
= gen_rtx_fmt_ee (code
, SImode
, op1
, op2
);
2545 = ((shift4_operator (shift
, SImode
) ? gen_shift_si3
: gen_shift_si3_loop
)
2546 (op0
, op1
, op2
, shift
));
2550 /* Output the assembler code for doing a shift.
2551 We go to a bit of trouble to generate efficient code as the ARC601 only has
2552 single bit shifts. This is taken from the h8300 port. We only have one
2553 mode of shifting and can't access individual bytes like the h8300 can, so
2554 this is greatly simplified (at the expense of not generating hyper-
2557 This function is not used if the variable shift insns are present. */
2559 /* FIXME: This probably can be done using a define_split in arc.md.
2560 Alternately, generate rtx rather than output instructions. */
2563 output_shift (rtx
*operands
)
2565 /* static int loopend_lab;*/
2566 rtx shift
= operands
[3];
2567 machine_mode mode
= GET_MODE (shift
);
2568 enum rtx_code code
= GET_CODE (shift
);
2569 const char *shift_one
;
2571 gcc_assert (mode
== SImode
);
2575 case ASHIFT
: shift_one
= "add %0,%1,%1"; break;
2576 case ASHIFTRT
: shift_one
= "asr %0,%1"; break;
2577 case LSHIFTRT
: shift_one
= "lsr %0,%1"; break;
2578 default: gcc_unreachable ();
2581 if (GET_CODE (operands
[2]) != CONST_INT
)
2583 output_asm_insn ("and.f lp_count,%2, 0x1f", operands
);
2590 n
= INTVAL (operands
[2]);
2592 /* Only consider the lower 5 bits of the shift count. */
2595 /* First see if we can do them inline. */
2596 /* ??? We could get better scheduling & shorter code (using short insns)
2597 by using splitters. Alas, that'd be even more verbose. */
2598 if (code
== ASHIFT
&& n
<= 9 && n
> 2
2599 && dest_reg_operand (operands
[4], SImode
))
2601 output_asm_insn ("mov %4,0\n\tadd3 %0,%4,%1", operands
);
2602 for (n
-=3 ; n
>= 3; n
-= 3)
2603 output_asm_insn ("add3 %0,%4,%0", operands
);
2605 output_asm_insn ("add2 %0,%4,%0", operands
);
2607 output_asm_insn ("add %0,%0,%0", operands
);
2613 output_asm_insn (shift_one
, operands
);
2614 operands
[1] = operands
[0];
2617 /* See if we can use a rotate/and. */
2618 else if (n
== BITS_PER_WORD
- 1)
2623 output_asm_insn ("and %0,%1,1\n\tror %0,%0", operands
);
2626 /* The ARC doesn't have a rol insn. Use something else. */
2627 output_asm_insn ("add.f 0,%1,%1\n\tsbc %0,%0,%0", operands
);
2630 /* The ARC doesn't have a rol insn. Use something else. */
2631 output_asm_insn ("add.f 0,%1,%1\n\trlc %0,0", operands
);
2637 else if (n
== BITS_PER_WORD
- 2 && dest_reg_operand (operands
[4], SImode
))
2642 output_asm_insn ("and %0,%1,3\n\tror %0,%0\n\tror %0,%0", operands
);
2645 #if 1 /* Need some scheduling comparisons. */
2646 output_asm_insn ("add.f %4,%1,%1\n\tsbc %0,%0,%0\n\t"
2647 "add.f 0,%4,%4\n\trlc %0,%0", operands
);
2649 output_asm_insn ("add.f %4,%1,%1\n\tbxor %0,%4,31\n\t"
2650 "sbc.f %0,%0,%4\n\trlc %0,%0", operands
);
2655 output_asm_insn ("add.f %4,%1,%1\n\trlc %0,0\n\t"
2656 "add.f 0,%4,%4\n\trlc %0,%0", operands
);
2658 output_asm_insn ("add.f %0,%1,%1\n\trlc.f %0,0\n\t"
2659 "and %0,%0,1\n\trlc %0,%0", operands
);
2666 else if (n
== BITS_PER_WORD
- 3 && code
== ASHIFT
)
2667 output_asm_insn ("and %0,%1,7\n\tror %0,%0\n\tror %0,%0\n\tror %0,%0",
2672 operands
[2] = GEN_INT (n
);
2673 output_asm_insn ("mov.f lp_count, %2", operands
);
2677 output_asm_insn ("lpnz\t2f", operands
);
2678 output_asm_insn (shift_one
, operands
);
2679 output_asm_insn ("nop", operands
);
2680 fprintf (asm_out_file
, "2:\t%s end single insn loop\n",
2689 /* Nested function support. */
2691 /* Directly store VALUE into memory object BLOCK at OFFSET. */
2694 emit_store_direct (rtx block
, int offset
, int value
)
2696 emit_insn (gen_store_direct (adjust_address (block
, SImode
, offset
),
2698 gen_int_mode (value
, SImode
))));
2701 /* Emit RTL insns to initialize the variable parts of a trampoline.
2702 FNADDR is an RTX for the address of the function's pure code.
2703 CXT is an RTX for the static chain value for the function. */
2704 /* With potentially multiple shared objects loaded, and multiple stacks
2705 present for multiple thereds where trampolines might reside, a simple
2706 range check will likely not suffice for the profiler to tell if a callee
2707 is a trampoline. We a speedier check by making the trampoline start at
2708 an address that is not 4-byte aligned.
2709 A trampoline looks like this:
2713 ld_s r12,[pcl,12] 0xd403
2714 ld r11,[pcl,12] 0x170c 700b
2718 The fastest trampoline to execute for trampolines within +-8KB of CTX
2721 j [limm] 0x20200f80 limm
2722 and that would also be faster to write to the stack by computing the offset
2723 from CTX to TRAMP at compile time. However, it would really be better to
2724 get rid of the high cost of cache invalidation when generating trampolines,
2725 which requires that the code part of trampolines stays constant, and
2727 - making sure that no executable code but trampolines is on the stack,
2728 no icache entries linger for the area of the stack from when before the
2729 stack was allocated, and allocating trampolines in trampoline-only
2732 - allocate trampolines fram a special pool of pre-allocated trampolines. */
2735 arc_initialize_trampoline (rtx tramp
, tree fndecl
, rtx cxt
)
2737 rtx fnaddr
= XEXP (DECL_RTL (fndecl
), 0);
2739 emit_store_direct (tramp
, 0, TARGET_BIG_ENDIAN
? 0x78e0d403 : 0xd40378e0);
2740 emit_store_direct (tramp
, 4, TARGET_BIG_ENDIAN
? 0x170c700b : 0x700b170c);
2741 emit_store_direct (tramp
, 8, TARGET_BIG_ENDIAN
? 0x7c0078e0 : 0x78e07c00);
2742 emit_move_insn (adjust_address (tramp
, SImode
, 12), fnaddr
);
2743 emit_move_insn (adjust_address (tramp
, SImode
, 16), cxt
);
2744 emit_insn (gen_flush_icache (adjust_address (tramp
, SImode
, 0)));
2747 /* Allow the profiler to easily distinguish trampolines from normal
2751 arc_trampoline_adjust_address (rtx addr
)
2753 return plus_constant (Pmode
, addr
, 2);
2756 /* This is set briefly to 1 when we output a ".as" address modifer, and then
2757 reset when we output the scaled address. */
2758 static int output_scaled
= 0;
2760 /* Print operand X (an rtx) in assembler syntax to file FILE.
2761 CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
2762 For `%' followed by punctuation, CODE is the punctuation and X is null. */
2763 /* In final.c:output_asm_insn:
2766 'c' : constant address if CONSTANT_ADDRESS_P
2772 '#': condbranch delay slot suffix
2773 '*': jump delay slot suffix
2774 '?' : nonjump-insn suffix for conditional execution or short instruction
2775 '!' : jump / call suffix for conditional execution or short instruction
2776 '`': fold constant inside unary o-perator, re-recognize, and emit.
2781 'B': Branch comparison operand - suppress sda reference
2782 'H': Most significant word
2783 'L': Least significant word
2784 'A': ASCII decimal representation of floating point value
2785 'U': Load/store update or scaling indicator
2786 'V': cache bypass indicator for volatile
2791 'o': original symbol - no @ prepending. */
2794 arc_print_operand (FILE *file
, rtx x
, int code
)
2799 if (GET_CODE (x
) == CONST_INT
)
2800 fprintf (file
, "%d",exact_log2(INTVAL (x
) + 1) - 1 );
2802 output_operand_lossage ("invalid operand to %%Z code");
2807 if (GET_CODE (x
) == CONST_INT
)
2808 fprintf (file
, "%d",exact_log2(INTVAL (x
)) );
2810 output_operand_lossage ("invalid operand to %%z code");
2815 if (GET_CODE (x
) == CONST_INT
)
2816 fprintf (file
, "%d",exact_log2(~INTVAL (x
)) );
2818 output_operand_lossage ("invalid operand to %%M code");
2823 /* Conditional branches depending on condition codes.
2824 Note that this is only for branches that were known to depend on
2825 condition codes before delay slot scheduling;
2826 out-of-range brcc / bbit expansions should use '*'.
2827 This distinction is important because of the different
2828 allowable delay slot insns and the output of the delay suffix
2829 for TARGET_AT_DBR_COND_EXEC. */
2831 /* Unconditional branches / branches not depending on condition codes.
2832 This could also be a CALL_INSN.
2833 Output the appropriate delay slot suffix. */
2834 if (final_sequence
&& final_sequence
->len () != 1)
2836 rtx_insn
*jump
= final_sequence
->insn (0);
2837 rtx_insn
*delay
= final_sequence
->insn (1);
2839 /* For TARGET_PAD_RETURN we might have grabbed the delay insn. */
2840 if (delay
->deleted ())
2842 if (JUMP_P (jump
) && INSN_ANNULLED_BRANCH_P (jump
))
2843 fputs (INSN_FROM_TARGET_P (delay
) ? ".d"
2844 : TARGET_AT_DBR_CONDEXEC
&& code
== '#' ? ".d"
2845 : get_attr_type (jump
) == TYPE_RETURN
&& code
== '#' ? ""
2852 case '?' : /* with leading "." */
2853 case '!' : /* without leading "." */
2854 /* This insn can be conditionally executed. See if the ccfsm machinery
2855 says it should be conditionalized.
2856 If it shouldn't, we'll check the compact attribute if this insn
2857 has a short variant, which may be used depending on code size and
2858 alignment considerations. */
2859 if (current_insn_predicate
)
2860 arc_ccfsm_current
.cc
2861 = get_arc_condition_code (current_insn_predicate
);
2862 if (ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current
))
2864 /* Is this insn in a delay slot sequence? */
2865 if (!final_sequence
|| XVECLEN (final_sequence
, 0) < 2
2866 || current_insn_predicate
2867 || CALL_P (final_sequence
->insn (0))
2868 || simplejump_p (final_sequence
->insn (0)))
2870 /* This insn isn't in a delay slot sequence, or conditionalized
2871 independently of its position in a delay slot. */
2872 fprintf (file
, "%s%s",
2873 code
== '?' ? "." : "",
2874 arc_condition_codes
[arc_ccfsm_current
.cc
]);
2875 /* If this is a jump, there are still short variants. However,
2876 only beq_s / bne_s have the same offset range as b_s,
2877 and the only short conditional returns are jeq_s and jne_s. */
2879 && (arc_ccfsm_current
.cc
== ARC_CC_EQ
2880 || arc_ccfsm_current
.cc
== ARC_CC_NE
2881 || 0 /* FIXME: check if branch in 7 bit range. */))
2882 output_short_suffix (file
);
2884 else if (code
== '!') /* Jump with delay slot. */
2885 fputs (arc_condition_codes
[arc_ccfsm_current
.cc
], file
);
2886 else /* An Instruction in a delay slot of a jump or call. */
2888 rtx jump
= XVECEXP (final_sequence
, 0, 0);
2889 rtx insn
= XVECEXP (final_sequence
, 0, 1);
2891 /* If the insn is annulled and is from the target path, we need
2892 to inverse the condition test. */
2893 if (JUMP_P (jump
) && INSN_ANNULLED_BRANCH_P (jump
))
2895 if (INSN_FROM_TARGET_P (insn
))
2896 fprintf (file
, "%s%s",
2897 code
== '?' ? "." : "",
2898 arc_condition_codes
[ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current
.cc
)]);
2900 fprintf (file
, "%s%s",
2901 code
== '?' ? "." : "",
2902 arc_condition_codes
[arc_ccfsm_current
.cc
]);
2903 if (arc_ccfsm_current
.state
== 5)
2904 arc_ccfsm_current
.state
= 0;
2907 /* This insn is executed for either path, so don't
2908 conditionalize it at all. */
2909 output_short_suffix (file
);
2914 output_short_suffix (file
);
2917 /* FIXME: fold constant inside unary operator, re-recognize, and emit. */
2920 fputs (arc_condition_codes
[get_arc_condition_code (x
)], file
);
2923 fputs (arc_condition_codes
[ARC_INVERSE_CONDITION_CODE
2924 (get_arc_condition_code (x
))],
2928 /* Write second word of DImode or DFmode reference,
2929 register or memory. */
2930 if (GET_CODE (x
) == REG
)
2931 fputs (reg_names
[REGNO (x
)+1], file
);
2932 else if (GET_CODE (x
) == MEM
)
2936 /* Handle possible auto-increment. For PRE_INC / PRE_DEC /
2937 PRE_MODIFY, we will have handled the first word already;
2938 For POST_INC / POST_DEC / POST_MODIFY, the access to the
2939 first word will be done later. In either case, the access
2940 to the first word will do the modify, and we only have
2941 to add an offset of four here. */
2942 if (GET_CODE (XEXP (x
, 0)) == PRE_INC
2943 || GET_CODE (XEXP (x
, 0)) == PRE_DEC
2944 || GET_CODE (XEXP (x
, 0)) == PRE_MODIFY
2945 || GET_CODE (XEXP (x
, 0)) == POST_INC
2946 || GET_CODE (XEXP (x
, 0)) == POST_DEC
2947 || GET_CODE (XEXP (x
, 0)) == POST_MODIFY
)
2948 output_address (plus_constant (Pmode
, XEXP (XEXP (x
, 0), 0), 4));
2949 else if (output_scaled
)
2951 rtx addr
= XEXP (x
, 0);
2952 int size
= GET_MODE_SIZE (GET_MODE (x
));
2954 output_address (plus_constant (Pmode
, XEXP (addr
, 0),
2955 ((INTVAL (XEXP (addr
, 1)) + 4)
2956 >> (size
== 2 ? 1 : 2))));
2960 output_address (plus_constant (Pmode
, XEXP (x
, 0), 4));
2964 output_operand_lossage ("invalid operand to %%R code");
2967 /* FIXME: remove %S option. */
2969 case 'B' /* Branch or other LIMM ref - must not use sda references. */ :
2972 output_addr_const (file
, x
);
2978 if (GET_CODE (x
) == REG
)
2980 /* L = least significant word, H = most significant word. */
2981 if ((WORDS_BIG_ENDIAN
!= 0) ^ (code
== 'L'))
2982 fputs (reg_names
[REGNO (x
)], file
);
2984 fputs (reg_names
[REGNO (x
)+1], file
);
2986 else if (GET_CODE (x
) == CONST_INT
2987 || GET_CODE (x
) == CONST_DOUBLE
)
2991 split_double (x
, &first
, &second
);
2993 if((WORDS_BIG_ENDIAN
) == 0)
2994 fprintf (file
, "0x%08" PRIx64
,
2995 code
== 'L' ? INTVAL (first
) : INTVAL (second
));
2997 fprintf (file
, "0x%08" PRIx64
,
2998 code
== 'L' ? INTVAL (second
) : INTVAL (first
));
3003 output_operand_lossage ("invalid operand to %%H/%%L code");
3009 gcc_assert (GET_CODE (x
) == CONST_DOUBLE
3010 && GET_MODE_CLASS (GET_MODE (x
)) == MODE_FLOAT
);
3012 real_to_decimal (str
, CONST_DOUBLE_REAL_VALUE (x
), sizeof (str
), 0, 1);
3013 fprintf (file
, "%s", str
);
3017 /* Output a load/store with update indicator if appropriate. */
3018 if (GET_CODE (x
) == MEM
)
3020 rtx addr
= XEXP (x
, 0);
3021 switch (GET_CODE (addr
))
3023 case PRE_INC
: case PRE_DEC
: case PRE_MODIFY
:
3024 fputs (".a", file
); break;
3025 case POST_INC
: case POST_DEC
: case POST_MODIFY
:
3026 fputs (".ab", file
); break;
3028 /* Are we using a scaled index? */
3029 if (GET_CODE (XEXP (addr
, 0)) == MULT
)
3030 fputs (".as", file
);
3031 /* Can we use a scaled offset? */
3032 else if (CONST_INT_P (XEXP (addr
, 1))
3033 && GET_MODE_SIZE (GET_MODE (x
)) > 1
3034 && (!(INTVAL (XEXP (addr
, 1))
3035 & (GET_MODE_SIZE (GET_MODE (x
)) - 1) & 3))
3036 /* Does it make a difference? */
3037 && !SMALL_INT_RANGE(INTVAL (XEXP (addr
, 1)),
3038 GET_MODE_SIZE (GET_MODE (x
)) - 2, 0))
3040 fputs (".as", file
);
3047 gcc_assert (CONSTANT_P (addr
)); break;
3051 output_operand_lossage ("invalid operand to %%U code");
3054 /* Output cache bypass indicator for a load/store insn. Volatile memory
3055 refs are defined to use the cache bypass mechanism. */
3056 if (GET_CODE (x
) == MEM
)
3058 if (MEM_VOLATILE_P (x
) && !TARGET_VOLATILE_CACHE_SET
)
3059 fputs (".di", file
);
3062 output_operand_lossage ("invalid operand to %%V code");
3067 /* Do nothing special. */
3070 fputs (reg_names
[REGNO (x
)]+1, file
);
3073 /* This punctuation character is needed because label references are
3074 printed in the output template using %l. This is a front end
3075 character, and when we want to emit a '@' before it, we have to use
3081 /* Output an operator. */
3082 switch (GET_CODE (x
))
3084 case PLUS
: fputs ("add", file
); return;
3085 case SS_PLUS
: fputs ("adds", file
); return;
3086 case AND
: fputs ("and", file
); return;
3087 case IOR
: fputs ("or", file
); return;
3088 case XOR
: fputs ("xor", file
); return;
3089 case MINUS
: fputs ("sub", file
); return;
3090 case SS_MINUS
: fputs ("subs", file
); return;
3091 case ASHIFT
: fputs ("asl", file
); return;
3092 case ASHIFTRT
: fputs ("asr", file
); return;
3093 case LSHIFTRT
: fputs ("lsr", file
); return;
3094 case ROTATERT
: fputs ("ror", file
); return;
3095 case MULT
: fputs ("mpy", file
); return;
3096 case ABS
: fputs ("abs", file
); return; /* Unconditional. */
3097 case NEG
: fputs ("neg", file
); return;
3098 case SS_NEG
: fputs ("negs", file
); return;
3099 case NOT
: fputs ("not", file
); return; /* Unconditional. */
3101 fputs ("ext", file
); /* bmsk allows predication. */
3103 case SIGN_EXTEND
: /* Unconditional. */
3104 fputs ("sex", file
);
3106 switch (GET_MODE (XEXP (x
, 0)))
3108 case QImode
: fputs ("b", file
); return;
3109 case HImode
: fputs ("w", file
); return;
3114 if (GET_MODE (x
) != HImode
)
3116 fputs ("sat16", file
);
3119 output_operand_lossage ("invalid operand to %%O code"); return;
3121 if (GET_CODE (x
) == SYMBOL_REF
)
3123 assemble_name (file
, XSTR (x
, 0));
3128 if (TARGET_ANNOTATE_ALIGN
&& cfun
->machine
->size_reason
)
3129 fprintf (file
, "; unalign: %d", cfun
->machine
->unalign
);
3133 output_operand_lossage ("invalid operand output code");
3136 switch (GET_CODE (x
))
3139 fputs (reg_names
[REGNO (x
)], file
);
3143 rtx addr
= XEXP (x
, 0);
3144 int size
= GET_MODE_SIZE (GET_MODE (x
));
3148 switch (GET_CODE (addr
))
3150 case PRE_INC
: case POST_INC
:
3151 output_address (plus_constant (Pmode
, XEXP (addr
, 0), size
)); break;
3152 case PRE_DEC
: case POST_DEC
:
3153 output_address (plus_constant (Pmode
, XEXP (addr
, 0), -size
));
3155 case PRE_MODIFY
: case POST_MODIFY
:
3156 output_address (XEXP (addr
, 1)); break;
3160 output_address (plus_constant (Pmode
, XEXP (addr
, 0),
3161 (INTVAL (XEXP (addr
, 1))
3162 >> (size
== 2 ? 1 : 2))));
3166 output_address (addr
);
3169 if (flag_pic
&& CONSTANT_ADDRESS_P (addr
))
3170 arc_output_pic_addr_const (file
, addr
, code
);
3172 output_address (addr
);
3179 /* We handle SFmode constants here as output_addr_const doesn't. */
3180 if (GET_MODE (x
) == SFmode
)
3185 REAL_VALUE_FROM_CONST_DOUBLE (d
, x
);
3186 REAL_VALUE_TO_TARGET_SINGLE (d
, l
);
3187 fprintf (file
, "0x%08lx", l
);
3190 /* Fall through. Let output_addr_const deal with it. */
3193 arc_output_pic_addr_const (file
, x
, code
);
3196 /* FIXME: Dirty way to handle @var@sda+const. Shd be handled
3197 with asm_output_symbol_ref */
3198 if (GET_CODE (x
) == CONST
&& GET_CODE (XEXP (x
, 0)) == PLUS
)
3201 output_addr_const (file
, XEXP (x
, 0));
3202 if (GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
&& SYMBOL_REF_SMALL_P (XEXP (x
, 0)))
3203 fprintf (file
, "@sda");
3205 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
3206 || INTVAL (XEXP (x
, 1)) >= 0)
3207 fprintf (file
, "+");
3208 output_addr_const (file
, XEXP (x
, 1));
3211 output_addr_const (file
, x
);
3213 if (GET_CODE (x
) == SYMBOL_REF
&& SYMBOL_REF_SMALL_P (x
))
3214 fprintf (file
, "@sda");
3219 /* Print a memory address as an operand to reference that memory location. */
3222 arc_print_operand_address (FILE *file
, rtx addr
)
3224 register rtx base
, index
= 0;
3226 switch (GET_CODE (addr
))
3229 fputs (reg_names
[REGNO (addr
)], file
);
3232 output_addr_const (file
, addr
);
3233 if (SYMBOL_REF_SMALL_P (addr
))
3234 fprintf (file
, "@sda");
3237 if (GET_CODE (XEXP (addr
, 0)) == MULT
)
3238 index
= XEXP (XEXP (addr
, 0), 0), base
= XEXP (addr
, 1);
3239 else if (CONST_INT_P (XEXP (addr
, 0)))
3240 index
= XEXP (addr
, 0), base
= XEXP (addr
, 1);
3242 base
= XEXP (addr
, 0), index
= XEXP (addr
, 1);
3244 gcc_assert (OBJECT_P (base
));
3245 arc_print_operand_address (file
, base
);
3246 if (CONSTANT_P (base
) && CONST_INT_P (index
))
3250 gcc_assert (OBJECT_P (index
));
3251 arc_print_operand_address (file
, index
);
3255 rtx c
= XEXP (addr
, 0);
3257 gcc_assert (GET_CODE (XEXP (c
, 0)) == SYMBOL_REF
);
3258 gcc_assert (GET_CODE (XEXP (c
, 1)) == CONST_INT
);
3260 output_address(XEXP(addr
,0));
3266 /* We shouldn't get here as we've lost the mode of the memory object
3267 (which says how much to inc/dec by. */
3272 arc_output_pic_addr_const (file
, addr
, 0);
3274 output_addr_const (file
, addr
);
3279 /* Called via walk_stores. DATA points to a hash table we can use to
3280 establish a unique SYMBOL_REF for each counter, which corresponds to
3281 a caller-callee pair.
3282 X is a store which we want to examine for an UNSPEC_PROF, which
3283 would be an address loaded into a register, or directly used in a MEM.
3284 If we found an UNSPEC_PROF, if we encounter a new counter the first time,
3285 write out a description and a data allocation for a 32 bit counter.
3286 Also, fill in the appropriate symbol_ref into each UNSPEC_PROF instance. */
3289 write_profile_sections (rtx dest ATTRIBUTE_UNUSED
, rtx x
, void *data
)
3292 htab_t htab
= (htab_t
) data
;
3295 if (GET_CODE (x
) != SET
)
3297 srcp
= &SET_SRC (x
);
3299 srcp
= &XEXP (*srcp
, 0);
3300 else if (MEM_P (SET_DEST (x
)))
3301 srcp
= &XEXP (SET_DEST (x
), 0);
3303 if (GET_CODE (src
) != CONST
)
3305 src
= XEXP (src
, 0);
3306 if (GET_CODE (src
) != UNSPEC
|| XINT (src
, 1) != UNSPEC_PROF
)
3309 gcc_assert (XVECLEN (src
, 0) == 3);
3310 if (!htab_elements (htab
))
3312 output_asm_insn (".section .__arc_profile_desc, \"a\"\n"
3314 &XVECEXP (src
, 0, 0));
3316 slot
= (rtx
*) htab_find_slot (htab
, src
, INSERT
);
3317 if (*slot
== HTAB_EMPTY_ENTRY
)
3319 static int count_nr
;
3324 sprintf (buf
, "__prof_count%d", count_nr
++);
3325 count
= gen_rtx_SYMBOL_REF (Pmode
, xstrdup (buf
));
3326 XVECEXP (src
, 0, 2) = count
;
3327 output_asm_insn (".section\t.__arc_profile_desc, \"a\"\n"
3329 "\t.section\t.__arc_profile_counters, \"aw\"\n"
3330 "\t.type\t%o2, @object\n"
3333 &XVECEXP (src
, 0, 0));
3337 *srcp
= XVECEXP (*slot
, 0, 2);
3340 /* Hash function for UNSPEC_PROF htab. Use both the caller's name and
3341 the callee's name (if known). */
3344 unspec_prof_hash (const void *x
)
3346 const_rtx u
= (const_rtx
) x
;
3347 const_rtx s1
= XVECEXP (u
, 0, 1);
3349 return (htab_hash_string (XSTR (XVECEXP (u
, 0, 0), 0))
3350 ^ (s1
->code
== SYMBOL_REF
? htab_hash_string (XSTR (s1
, 0)) : 0));
3353 /* Equality function for UNSPEC_PROF htab. Two pieces of UNSPEC_PROF rtl
3354 shall refer to the same counter if both caller name and callee rtl
3358 unspec_prof_htab_eq (const void *x
, const void *y
)
3360 const_rtx u0
= (const_rtx
) x
;
3361 const_rtx u1
= (const_rtx
) y
;
3362 const_rtx s01
= XVECEXP (u0
, 0, 1);
3363 const_rtx s11
= XVECEXP (u1
, 0, 1);
3365 return (!strcmp (XSTR (XVECEXP (u0
, 0, 0), 0),
3366 XSTR (XVECEXP (u1
, 0, 0), 0))
3367 && rtx_equal_p (s01
, s11
));
3370 /* Conditional execution support.
3372 This is based on the ARM port but for now is much simpler.
3374 A finite state machine takes care of noticing whether or not instructions
3375 can be conditionally executed, and thus decrease execution time and code
3376 size by deleting branch instructions. The fsm is controlled by
3377 arc_ccfsm_advance (called by arc_final_prescan_insn), and controls the
3378 actions of PRINT_OPERAND. The patterns in the .md file for the branch
3379 insns also have a hand in this. */
3380 /* The way we leave dealing with non-anulled or annull-false delay slot
3381 insns to the consumer is awkward. */
3383 /* The state of the fsm controlling condition codes are:
3384 0: normal, do nothing special
3385 1: don't output this insn
3386 2: don't output this insn
3387 3: make insns conditional
3388 4: make insns conditional
3389 5: make insn conditional (only for outputting anulled delay slot insns)
3391 special value for cfun->machine->uid_ccfsm_state:
3392 6: return with but one insn before it since function start / call
3394 State transitions (state->state by whom, under what condition):
3395 0 -> 1 arc_ccfsm_advance, if insn is a conditional branch skipping over
3397 0 -> 2 arc_ccfsm_advance, if insn is a conditional branch followed
3398 by zero or more non-jump insns and an unconditional branch with
3399 the same target label as the condbranch.
3400 1 -> 3 branch patterns, after having not output the conditional branch
3401 2 -> 4 branch patterns, after having not output the conditional branch
3402 0 -> 5 branch patterns, for anulled delay slot insn.
3403 3 -> 0 ASM_OUTPUT_INTERNAL_LABEL, if the `target' label is reached
3404 (the target label has CODE_LABEL_NUMBER equal to
3405 arc_ccfsm_target_label).
3406 4 -> 0 arc_ccfsm_advance, if `target' unconditional branch is reached
3407 3 -> 1 arc_ccfsm_advance, finding an 'else' jump skipping over some insns.
3408 5 -> 0 when outputting the delay slot insn
3410 If the jump clobbers the conditions then we use states 2 and 4.
3412 A similar thing can be done with conditional return insns.
3414 We also handle separating branches from sets of the condition code.
3415 This is done here because knowledge of the ccfsm state is required,
3416 we may not be outputting the branch. */
3418 /* arc_final_prescan_insn calls arc_ccfsm_advance to adjust arc_ccfsm_current,
3419 before letting final output INSN. */
3422 arc_ccfsm_advance (rtx_insn
*insn
, struct arc_ccfsm
*state
)
3424 /* BODY will hold the body of INSN. */
3427 /* This will be 1 if trying to repeat the trick (ie: do the `else' part of
3428 an if/then/else), and things need to be reversed. */
3431 /* If we start with a return insn, we only succeed if we find another one. */
3432 int seeking_return
= 0;
3434 /* START_INSN will hold the insn from where we start looking. This is the
3435 first insn after the following code_label if REVERSE is true. */
3436 rtx_insn
*start_insn
= insn
;
3438 /* Type of the jump_insn. Brcc insns don't affect ccfsm changes,
3439 since they don't rely on a cmp preceding the. */
3440 enum attr_type jump_insn_type
;
3442 /* Allow -mdebug-ccfsm to turn this off so we can see how well it does.
3443 We can't do this in macro FINAL_PRESCAN_INSN because its called from
3444 final_scan_insn which has `optimize' as a local. */
3445 if (optimize
< 2 || TARGET_NO_COND_EXEC
)
3448 /* Ignore notes and labels. */
3451 body
= PATTERN (insn
);
3452 /* If in state 4, check if the target branch is reached, in order to
3453 change back to state 0. */
3454 if (state
->state
== 4)
3456 if (insn
== state
->target_insn
)
3458 state
->target_insn
= NULL
;
3464 /* If in state 3, it is possible to repeat the trick, if this insn is an
3465 unconditional branch to a label, and immediately following this branch
3466 is the previous target label which is only used once, and the label this
3467 branch jumps to is not too far off. Or in other words "we've done the
3468 `then' part, see if we can do the `else' part." */
3469 if (state
->state
== 3)
3471 if (simplejump_p (insn
))
3473 start_insn
= next_nonnote_insn (start_insn
);
3474 if (GET_CODE (start_insn
) == BARRIER
)
3476 /* ??? Isn't this always a barrier? */
3477 start_insn
= next_nonnote_insn (start_insn
);
3479 if (GET_CODE (start_insn
) == CODE_LABEL
3480 && CODE_LABEL_NUMBER (start_insn
) == state
->target_label
3481 && LABEL_NUSES (start_insn
) == 1)
3486 else if (GET_CODE (body
) == SIMPLE_RETURN
)
3488 start_insn
= next_nonnote_insn (start_insn
);
3489 if (GET_CODE (start_insn
) == BARRIER
)
3490 start_insn
= next_nonnote_insn (start_insn
);
3491 if (GET_CODE (start_insn
) == CODE_LABEL
3492 && CODE_LABEL_NUMBER (start_insn
) == state
->target_label
3493 && LABEL_NUSES (start_insn
) == 1)
3505 if (GET_CODE (insn
) != JUMP_INSN
3506 || GET_CODE (PATTERN (insn
)) == ADDR_VEC
3507 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
3510 /* We can't predicate BRCC or loop ends.
3511 Also, when generating PIC code, and considering a medium range call,
3512 we can't predicate the call. */
3513 jump_insn_type
= get_attr_type (insn
);
3514 if (jump_insn_type
== TYPE_BRCC
3515 || jump_insn_type
== TYPE_BRCC_NO_DELAY_SLOT
3516 || jump_insn_type
== TYPE_LOOP_END
3517 || (jump_insn_type
== TYPE_CALL
&& !get_attr_predicable (insn
)))
3520 /* This jump might be paralleled with a clobber of the condition codes,
3521 the jump should always come first. */
3522 if (GET_CODE (body
) == PARALLEL
&& XVECLEN (body
, 0) > 0)
3523 body
= XVECEXP (body
, 0, 0);
3526 || (GET_CODE (body
) == SET
&& GET_CODE (SET_DEST (body
)) == PC
3527 && GET_CODE (SET_SRC (body
)) == IF_THEN_ELSE
))
3529 int insns_skipped
= 0, fail
= FALSE
, succeed
= FALSE
;
3530 /* Flag which part of the IF_THEN_ELSE is the LABEL_REF. */
3531 int then_not_else
= TRUE
;
3532 /* Nonzero if next insn must be the target label. */
3533 int next_must_be_target_label_p
;
3534 rtx_insn
*this_insn
= start_insn
;
3537 /* Register the insn jumped to. */
3540 if (!seeking_return
)
3541 label
= XEXP (SET_SRC (body
), 0);
3543 else if (GET_CODE (XEXP (SET_SRC (body
), 1)) == LABEL_REF
)
3544 label
= XEXP (XEXP (SET_SRC (body
), 1), 0);
3545 else if (GET_CODE (XEXP (SET_SRC (body
), 2)) == LABEL_REF
)
3547 label
= XEXP (XEXP (SET_SRC (body
), 2), 0);
3548 then_not_else
= FALSE
;
3550 else if (GET_CODE (XEXP (SET_SRC (body
), 1)) == SIMPLE_RETURN
)
3552 else if (GET_CODE (XEXP (SET_SRC (body
), 2)) == SIMPLE_RETURN
)
3555 then_not_else
= FALSE
;
3560 /* If this is a non-annulled branch with a delay slot, there is
3561 no need to conditionalize the delay slot. */
3562 if (NEXT_INSN (PREV_INSN (insn
)) != insn
3563 && state
->state
== 0 && !INSN_ANNULLED_BRANCH_P (insn
))
3565 this_insn
= NEXT_INSN (this_insn
);
3566 gcc_assert (NEXT_INSN (NEXT_INSN (PREV_INSN (start_insn
)))
3567 == NEXT_INSN (this_insn
));
3569 /* See how many insns this branch skips, and what kind of insns. If all
3570 insns are okay, and the label or unconditional branch to the same
3571 label is not too far away, succeed. */
3572 for (insns_skipped
= 0, next_must_be_target_label_p
= FALSE
;
3573 !fail
&& !succeed
&& insns_skipped
< MAX_INSNS_SKIPPED
;
3578 this_insn
= next_nonnote_insn (this_insn
);
3582 if (next_must_be_target_label_p
)
3584 if (GET_CODE (this_insn
) == BARRIER
)
3586 if (GET_CODE (this_insn
) == CODE_LABEL
3587 && this_insn
== label
)
3597 scanbody
= PATTERN (this_insn
);
3599 switch (GET_CODE (this_insn
))
3602 /* Succeed if it is the target label, otherwise fail since
3603 control falls in from somewhere else. */
3604 if (this_insn
== label
)
3614 /* Succeed if the following insn is the target label.
3616 If return insns are used then the last insn in a function
3617 will be a barrier. */
3618 next_must_be_target_label_p
= TRUE
;
3622 /* Can handle a call insn if there are no insns after it.
3623 IE: The next "insn" is the target label. We don't have to
3624 worry about delay slots as such insns are SEQUENCE's inside
3625 INSN's. ??? It is possible to handle such insns though. */
3626 if (get_attr_cond (this_insn
) == COND_CANUSE
)
3627 next_must_be_target_label_p
= TRUE
;
3633 /* If this is an unconditional branch to the same label, succeed.
3634 If it is to another label, do nothing. If it is conditional,
3636 /* ??? Probably, the test for the SET and the PC are
3639 if (GET_CODE (scanbody
) == SET
3640 && GET_CODE (SET_DEST (scanbody
)) == PC
)
3642 if (GET_CODE (SET_SRC (scanbody
)) == LABEL_REF
3643 && XEXP (SET_SRC (scanbody
), 0) == label
&& !reverse
)
3648 else if (GET_CODE (SET_SRC (scanbody
)) == IF_THEN_ELSE
)
3650 else if (get_attr_cond (this_insn
) != COND_CANUSE
)
3653 else if (GET_CODE (scanbody
) == SIMPLE_RETURN
3659 else if (GET_CODE (scanbody
) == PARALLEL
)
3661 if (get_attr_cond (this_insn
) != COND_CANUSE
)
3667 /* We can only do this with insns that can use the condition
3668 codes (and don't set them). */
3669 if (GET_CODE (scanbody
) == SET
3670 || GET_CODE (scanbody
) == PARALLEL
)
3672 if (get_attr_cond (this_insn
) != COND_CANUSE
)
3675 /* We can't handle other insns like sequences. */
3687 if ((!seeking_return
) && (state
->state
== 1 || reverse
))
3688 state
->target_label
= CODE_LABEL_NUMBER (label
);
3689 else if (seeking_return
|| state
->state
== 2)
3691 while (this_insn
&& GET_CODE (PATTERN (this_insn
)) == USE
)
3693 this_insn
= next_nonnote_insn (this_insn
);
3695 gcc_assert (!this_insn
||
3696 (GET_CODE (this_insn
) != BARRIER
3697 && GET_CODE (this_insn
) != CODE_LABEL
));
3701 /* Oh dear! we ran off the end, give up. */
3702 extract_insn_cached (insn
);
3704 state
->target_insn
= NULL
;
3707 state
->target_insn
= this_insn
;
3712 /* If REVERSE is true, ARM_CURRENT_CC needs to be inverted from
3716 state
->cond
= XEXP (SET_SRC (body
), 0);
3717 state
->cc
= get_arc_condition_code (XEXP (SET_SRC (body
), 0));
3720 if (reverse
|| then_not_else
)
3721 state
->cc
= ARC_INVERSE_CONDITION_CODE (state
->cc
);
3724 /* Restore recog_operand. Getting the attributes of other insns can
3725 destroy this array, but final.c assumes that it remains intact
3726 across this call; since the insn has been recognized already we
3727 call insn_extract direct. */
3728 extract_insn_cached (insn
);
3732 /* Record that we are currently outputting label NUM with prefix PREFIX.
3733 It it's the label we're looking for, reset the ccfsm machinery.
3735 Called from ASM_OUTPUT_INTERNAL_LABEL. */
3738 arc_ccfsm_at_label (const char *prefix
, int num
, struct arc_ccfsm
*state
)
3740 if (state
->state
== 3 && state
->target_label
== num
3741 && !strcmp (prefix
, "L"))
3744 state
->target_insn
= NULL
;
3748 /* We are considering a conditional branch with the condition COND.
3749 Check if we want to conditionalize a delay slot insn, and if so modify
3750 the ccfsm state accordingly.
3751 REVERSE says branch will branch when the condition is false. */
3753 arc_ccfsm_record_condition (rtx cond
, bool reverse
, rtx_insn
*jump
,
3754 struct arc_ccfsm
*state
)
3756 rtx_insn
*seq_insn
= NEXT_INSN (PREV_INSN (jump
));
3758 state
= &arc_ccfsm_current
;
3760 gcc_assert (state
->state
== 0);
3761 if (seq_insn
!= jump
)
3763 rtx insn
= XVECEXP (PATTERN (seq_insn
), 0, 1);
3765 if (!as_a
<rtx_insn
*> (insn
)->deleted ()
3766 && INSN_ANNULLED_BRANCH_P (jump
)
3767 && (TARGET_AT_DBR_CONDEXEC
|| INSN_FROM_TARGET_P (insn
)))
3770 state
->cc
= get_arc_condition_code (cond
);
3772 arc_ccfsm_current
.cc
3773 = ARC_INVERSE_CONDITION_CODE (state
->cc
);
3774 rtx pat
= PATTERN (insn
);
3775 if (GET_CODE (pat
) == COND_EXEC
)
3776 gcc_assert ((INSN_FROM_TARGET_P (insn
)
3777 ? ARC_INVERSE_CONDITION_CODE (state
->cc
) : state
->cc
)
3778 == get_arc_condition_code (XEXP (pat
, 0)));
3785 /* Update *STATE as we would when we emit INSN. */
3788 arc_ccfsm_post_advance (rtx_insn
*insn
, struct arc_ccfsm
*state
)
3790 enum attr_type type
;
3793 arc_ccfsm_at_label ("L", CODE_LABEL_NUMBER (insn
), state
);
3794 else if (JUMP_P (insn
)
3795 && GET_CODE (PATTERN (insn
)) != ADDR_VEC
3796 && GET_CODE (PATTERN (insn
)) != ADDR_DIFF_VEC
3797 && ((type
= get_attr_type (insn
)) == TYPE_BRANCH
3798 || (type
== TYPE_UNCOND_BRANCH
3799 /* ??? Maybe should also handle TYPE_RETURN here,
3800 but we don't have a testcase for that. */
3801 && ARC_CCFSM_BRANCH_DELETED_P (state
))))
3803 if (ARC_CCFSM_BRANCH_DELETED_P (state
))
3804 ARC_CCFSM_RECORD_BRANCH_DELETED (state
);
3807 rtx src
= SET_SRC (PATTERN (insn
));
3808 arc_ccfsm_record_condition (XEXP (src
, 0), XEXP (src
, 1) == pc_rtx
,
3812 else if (arc_ccfsm_current
.state
== 5)
3813 arc_ccfsm_current
.state
= 0;
3816 /* Return true if the current insn, which is a conditional branch, is to be
3820 arc_ccfsm_branch_deleted_p (void)
3822 return ARC_CCFSM_BRANCH_DELETED_P (&arc_ccfsm_current
);
3825 /* Record a branch isn't output because subsequent insns can be
3829 arc_ccfsm_record_branch_deleted (void)
3831 ARC_CCFSM_RECORD_BRANCH_DELETED (&arc_ccfsm_current
);
3834 /* During insn output, indicate if the current insn is predicated. */
3837 arc_ccfsm_cond_exec_p (void)
3839 return (cfun
->machine
->prescan_initialized
3840 && ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current
));
3843 /* Like next_active_insn, but return NULL if we find an ADDR_(DIFF_)VEC,
3844 and look inside SEQUENCEs. */
3847 arc_next_active_insn (rtx_insn
*insn
, struct arc_ccfsm
*statep
)
3854 arc_ccfsm_post_advance (insn
, statep
);
3855 insn
= NEXT_INSN (insn
);
3856 if (!insn
|| BARRIER_P (insn
))
3859 arc_ccfsm_advance (insn
, statep
);
3861 while (NOTE_P (insn
)
3862 || (cfun
->machine
->arc_reorg_started
3863 && LABEL_P (insn
) && !label_to_alignment (insn
))
3864 || (NONJUMP_INSN_P (insn
)
3865 && (GET_CODE (PATTERN (insn
)) == USE
3866 || GET_CODE (PATTERN (insn
)) == CLOBBER
)));
3867 if (!LABEL_P (insn
))
3869 gcc_assert (INSN_P (insn
));
3870 pat
= PATTERN (insn
);
3871 if (GET_CODE (pat
) == ADDR_VEC
|| GET_CODE (pat
) == ADDR_DIFF_VEC
)
3873 if (GET_CODE (pat
) == SEQUENCE
)
3874 return as_a
<rtx_insn
*> (XVECEXP (pat
, 0, 0));
3879 /* When deciding if an insn should be output short, we want to know something
3880 about the following insns:
3881 - if another insn follows which we know we can output as a short insn
3882 before an alignment-sensitive point, we can output this insn short:
3883 the decision about the eventual alignment can be postponed.
3884 - if a to-be-aligned label comes next, we should output this insn such
3885 as to get / preserve 4-byte alignment.
3886 - if a likely branch without delay slot insn, or a call with an immediately
3887 following short insn comes next, we should out output this insn such as to
3888 get / preserve 2 mod 4 unalignment.
3889 - do the same for a not completely unlikely branch with a short insn
3890 following before any other branch / label.
3891 - in order to decide if we are actually looking at a branch, we need to
3892 call arc_ccfsm_advance.
3893 - in order to decide if we are looking at a short insn, we should know
3894 if it is conditionalized. To a first order of approximation this is
3895 the case if the state from arc_ccfsm_advance from before this insn
3896 indicates the insn is conditionalized. However, a further refinement
3897 could be to not conditionalize an insn if the destination register(s)
3898 is/are dead in the non-executed case. */
3899 /* Return non-zero if INSN should be output as a short insn. UNALIGN is
3900 zero if the current insn is aligned to a 4-byte-boundary, two otherwise.
3901 If CHECK_ATTR is greater than 0, check the iscompact attribute first. */
3904 arc_verify_short (rtx_insn
*insn
, int, int check_attr
)
3906 enum attr_iscompact iscompact
;
3907 struct machine_function
*machine
;
3911 iscompact
= get_attr_iscompact (insn
);
3912 if (iscompact
== ISCOMPACT_FALSE
)
3915 machine
= cfun
->machine
;
3917 if (machine
->force_short_suffix
>= 0)
3918 return machine
->force_short_suffix
;
3920 return (get_attr_length (insn
) & 2) != 0;
3923 /* When outputting an instruction (alternative) that can potentially be short,
3924 output the short suffix if the insn is in fact short, and update
3925 cfun->machine->unalign accordingly. */
3928 output_short_suffix (FILE *file
)
3930 rtx_insn
*insn
= current_output_insn
;
3932 if (arc_verify_short (insn
, cfun
->machine
->unalign
, 1))
3934 fprintf (file
, "_s");
3935 cfun
->machine
->unalign
^= 2;
3937 /* Restore recog_operand. */
3938 extract_insn_cached (insn
);
3941 /* Implement FINAL_PRESCAN_INSN. */
3944 arc_final_prescan_insn (rtx_insn
*insn
, rtx
*opvec ATTRIBUTE_UNUSED
,
3945 int noperands ATTRIBUTE_UNUSED
)
3947 if (TARGET_DUMPISIZE
)
3948 fprintf (asm_out_file
, "\n; at %04x\n", INSN_ADDRESSES (INSN_UID (insn
)));
3950 /* Output a nop if necessary to prevent a hazard.
3951 Don't do this for delay slots: inserting a nop would
3952 alter semantics, and the only time we would find a hazard is for a
3953 call function result - and in that case, the hazard is spurious to
3955 if (PREV_INSN (insn
)
3956 && PREV_INSN (NEXT_INSN (insn
)) == insn
3957 && arc_hazard (prev_real_insn (insn
), insn
))
3959 current_output_insn
=
3960 emit_insn_before (gen_nop (), NEXT_INSN (PREV_INSN (insn
)));
3961 final_scan_insn (current_output_insn
, asm_out_file
, optimize
, 1, NULL
);
3962 current_output_insn
= insn
;
3964 /* Restore extraction data which might have been clobbered by arc_hazard. */
3965 extract_constrain_insn_cached (insn
);
3967 if (!cfun
->machine
->prescan_initialized
)
3969 /* Clear lingering state from branch shortening. */
3970 memset (&arc_ccfsm_current
, 0, sizeof arc_ccfsm_current
);
3971 cfun
->machine
->prescan_initialized
= 1;
3973 arc_ccfsm_advance (insn
, &arc_ccfsm_current
);
3975 cfun
->machine
->size_reason
= 0;
3978 /* Given FROM and TO register numbers, say whether this elimination is allowed.
3979 Frame pointer elimination is automatically handled.
3981 All eliminations are permissible. If we need a frame
3982 pointer, we must eliminate ARG_POINTER_REGNUM into
3983 FRAME_POINTER_REGNUM and not into STACK_POINTER_REGNUM. */
3986 arc_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to
)
3988 return to
== FRAME_POINTER_REGNUM
|| !arc_frame_pointer_required ();
3991 /* Define the offset between two registers, one to be eliminated, and
3992 the other its replacement, at the start of a routine. */
3995 arc_initial_elimination_offset (int from
, int to
)
3997 if (! cfun
->machine
->frame_info
.initialized
)
3998 arc_compute_frame_size (get_frame_size ());
4000 if (from
== ARG_POINTER_REGNUM
&& to
== FRAME_POINTER_REGNUM
)
4002 return (cfun
->machine
->frame_info
.extra_size
4003 + cfun
->machine
->frame_info
.reg_size
);
4006 if (from
== ARG_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
4008 return (cfun
->machine
->frame_info
.total_size
4009 - cfun
->machine
->frame_info
.pretend_size
);
4012 if ((from
== FRAME_POINTER_REGNUM
) && (to
== STACK_POINTER_REGNUM
))
4014 return (cfun
->machine
->frame_info
.total_size
4015 - (cfun
->machine
->frame_info
.pretend_size
4016 + cfun
->machine
->frame_info
.extra_size
4017 + cfun
->machine
->frame_info
.reg_size
));
4024 arc_frame_pointer_required (void)
4026 return cfun
->calls_alloca
;
4030 /* Return the destination address of a branch. */
4033 branch_dest (rtx branch
)
4035 rtx pat
= PATTERN (branch
);
4036 rtx dest
= (GET_CODE (pat
) == PARALLEL
4037 ? SET_SRC (XVECEXP (pat
, 0, 0)) : SET_SRC (pat
));
4040 if (GET_CODE (dest
) == IF_THEN_ELSE
)
4041 dest
= XEXP (dest
, XEXP (dest
, 1) == pc_rtx
? 2 : 1);
4043 dest
= XEXP (dest
, 0);
4044 dest_uid
= INSN_UID (dest
);
4046 return INSN_ADDRESSES (dest_uid
);
4050 /* Implement TARGET_ENCODE_SECTION_INFO hook. */
4053 arc_encode_section_info (tree decl
, rtx rtl
, int first
)
4055 /* For sdata, SYMBOL_FLAG_LOCAL and SYMBOL_FLAG_FUNCTION.
4056 This clears machine specific flags, so has to come first. */
4057 default_encode_section_info (decl
, rtl
, first
);
4059 /* Check if it is a function, and whether it has the
4060 [long/medium/short]_call attribute specified. */
4061 if (TREE_CODE (decl
) == FUNCTION_DECL
)
4063 rtx symbol
= XEXP (rtl
, 0);
4064 int flags
= SYMBOL_REF_FLAGS (symbol
);
4066 tree attr
= (TREE_TYPE (decl
) != error_mark_node
4067 ? TYPE_ATTRIBUTES (TREE_TYPE (decl
)) : NULL_TREE
);
4068 tree long_call_attr
= lookup_attribute ("long_call", attr
);
4069 tree medium_call_attr
= lookup_attribute ("medium_call", attr
);
4070 tree short_call_attr
= lookup_attribute ("short_call", attr
);
4072 if (long_call_attr
!= NULL_TREE
)
4073 flags
|= SYMBOL_FLAG_LONG_CALL
;
4074 else if (medium_call_attr
!= NULL_TREE
)
4075 flags
|= SYMBOL_FLAG_MEDIUM_CALL
;
4076 else if (short_call_attr
!= NULL_TREE
)
4077 flags
|= SYMBOL_FLAG_SHORT_CALL
;
4079 SYMBOL_REF_FLAGS (symbol
) = flags
;
4083 /* This is how to output a definition of an internal numbered label where
4084 PREFIX is the class of label and NUM is the number within the class. */
4086 static void arc_internal_label (FILE *stream
, const char *prefix
, unsigned long labelno
)
4089 arc_ccfsm_at_label (prefix
, labelno
, &arc_ccfsm_current
);
4090 default_internal_label (stream
, prefix
, labelno
);
4093 /* Set the cpu type and print out other fancy things,
4094 at the top of the file. */
4096 static void arc_file_start (void)
4098 default_file_start ();
4099 fprintf (asm_out_file
, "\t.cpu %s\n", arc_cpu_string
);
4102 /* Cost functions. */
4104 /* Compute a (partial) cost for rtx X. Return true if the complete
4105 cost has been computed, and false if subexpressions should be
4106 scanned. In either case, *TOTAL contains the cost result. */
4109 arc_rtx_costs (rtx x
, int code
, int outer_code
, int opno ATTRIBUTE_UNUSED
,
4110 int *total
, bool speed
)
4114 /* Small integers are as cheap as registers. */
4117 bool nolimm
= false; /* Can we do without long immediate? */
4118 bool fast
= false; /* Is the result available immediately? */
4119 bool condexec
= false; /* Does this allow conditiobnal execution? */
4120 bool compact
= false; /* Is a 16 bit opcode available? */
4121 /* CONDEXEC also implies that we can have an unconditional
4122 3-address operation. */
4124 nolimm
= compact
= condexec
= false;
4125 if (UNSIGNED_INT6 (INTVAL (x
)))
4126 nolimm
= condexec
= compact
= true;
4129 if (SMALL_INT (INTVAL (x
)))
4130 nolimm
= fast
= true;
4133 case AND
: /* bclr, bmsk, ext[bw] */
4134 if (satisfies_constraint_Ccp (x
) /* bclr */
4135 || satisfies_constraint_C1p (x
) /* bmsk */)
4136 nolimm
= fast
= condexec
= compact
= true;
4138 case IOR
: /* bset */
4139 if (satisfies_constraint_C0p (x
)) /* bset */
4140 nolimm
= fast
= condexec
= compact
= true;
4143 if (satisfies_constraint_C0p (x
)) /* bxor */
4144 nolimm
= fast
= condexec
= true;
4147 if (satisfies_constraint_Crr (x
)) /* ror b,u6 */
4153 /* FIXME: Add target options to attach a small cost if
4154 condexec / compact is not true. */
4163 /* 4 byte values can be fetched as immediate constants -
4164 let's give that the cost of an extra insn. */
4168 *total
= COSTS_N_INSNS (1);
4177 *total
= COSTS_N_INSNS (1);
4180 /* FIXME: correct the order of high,low */
4181 split_double (x
, &high
, &low
);
4182 *total
= COSTS_N_INSNS (!SMALL_INT (INTVAL (high
))
4183 + !SMALL_INT (INTVAL (low
)));
4187 /* Encourage synth_mult to find a synthetic multiply when reasonable.
4188 If we need more than 12 insns to do a multiply, then go out-of-line,
4189 since the call overhead will be < 10% of the cost of the multiply. */
4193 if (TARGET_BARREL_SHIFTER
)
4195 /* If we want to shift a constant, we need a LIMM. */
4196 /* ??? when the optimizers want to know if a constant should be
4197 hoisted, they ask for the cost of the constant. OUTER_CODE is
4198 insufficient context for shifts since we don't know which operand
4199 we are looking at. */
4200 if (CONSTANT_P (XEXP (x
, 0)))
4202 *total
+= (COSTS_N_INSNS (2)
4203 + rtx_cost (XEXP (x
, 1), (enum rtx_code
) code
, 0, speed
));
4206 *total
= COSTS_N_INSNS (1);
4208 else if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
4209 *total
= COSTS_N_INSNS (16);
4212 *total
= COSTS_N_INSNS (INTVAL (XEXP ((x
), 1)));
4213 /* ??? want_to_gcse_p can throw negative shift counts at us,
4214 and then panics when it gets a negative cost as result.
4215 Seen for gcc.c-torture/compile/20020710-1.c -Os . */
4224 *total
= COSTS_N_INSNS(30);
4226 *total
= COSTS_N_INSNS(1);
4230 if ((TARGET_DPFP
&& GET_MODE (x
) == DFmode
))
4231 *total
= COSTS_N_INSNS (1);
4233 *total
= arc_multcost
;
4234 /* We do not want synth_mult sequences when optimizing
4236 else if (TARGET_MUL64_SET
|| (TARGET_ARC700
&& !TARGET_NOMPY_SET
))
4237 *total
= COSTS_N_INSNS (1);
4239 *total
= COSTS_N_INSNS (2);
4242 if (GET_CODE (XEXP (x
, 0)) == MULT
4243 && _2_4_8_operand (XEXP (XEXP (x
, 0), 1), VOIDmode
))
4245 *total
+= (rtx_cost (XEXP (x
, 1), PLUS
, 0, speed
)
4246 + rtx_cost (XEXP (XEXP (x
, 0), 0), PLUS
, 1, speed
));
4251 if (GET_CODE (XEXP (x
, 1)) == MULT
4252 && _2_4_8_operand (XEXP (XEXP (x
, 1), 1), VOIDmode
))
4254 *total
+= (rtx_cost (XEXP (x
, 0), PLUS
, 0, speed
)
4255 + rtx_cost (XEXP (XEXP (x
, 1), 0), PLUS
, 1, speed
));
4261 rtx op0
= XEXP (x
, 0);
4262 rtx op1
= XEXP (x
, 1);
4264 if (GET_CODE (op0
) == ZERO_EXTRACT
&& op1
== const0_rtx
4265 && XEXP (op0
, 1) == const1_rtx
)
4267 /* btst / bbit0 / bbit1:
4268 Small integers and registers are free; everything else can
4269 be put in a register. */
4270 *total
= (rtx_cost (XEXP (op0
, 0), SET
, 1, speed
)
4271 + rtx_cost (XEXP (op0
, 2), SET
, 1, speed
));
4274 if (GET_CODE (op0
) == AND
&& op1
== const0_rtx
4275 && satisfies_constraint_C1p (XEXP (op0
, 1)))
4278 *total
= rtx_cost (XEXP (op0
, 0), SET
, 1, speed
);
4282 if (GET_CODE (op1
) == NEG
)
4284 /* op0 might be constant, the inside of op1 is rather
4285 unlikely to be so. So swapping the operands might lower
4287 *total
= (rtx_cost (op0
, PLUS
, 1, speed
)
4288 + rtx_cost (XEXP (op1
, 0), PLUS
, 0, speed
));
4293 if (outer_code
== IF_THEN_ELSE
4294 && GET_CODE (XEXP (x
, 0)) == ZERO_EXTRACT
4295 && XEXP (x
, 1) == const0_rtx
4296 && XEXP (XEXP (x
, 0), 1) == const1_rtx
)
4298 /* btst / bbit0 / bbit1:
4299 Small integers and registers are free; everything else can
4300 be put in a register. */
4301 rtx op0
= XEXP (x
, 0);
4303 *total
= (rtx_cost (XEXP (op0
, 0), SET
, 1, speed
)
4304 + rtx_cost (XEXP (op0
, 2), SET
, 1, speed
));
4308 /* scc_insn expands into two insns. */
4309 case GTU
: case GEU
: case LEU
:
4310 if (GET_MODE (x
) == SImode
)
4311 *total
+= COSTS_N_INSNS (1);
4313 case LTU
: /* might use adc. */
4314 if (GET_MODE (x
) == SImode
)
4315 *total
+= COSTS_N_INSNS (1) - 1;
4322 /* Return true if ADDR is an address that needs to be expressed as an
4323 explicit sum of pcl + offset. */
4326 arc_legitimate_pc_offset_p (rtx addr
)
4328 if (GET_CODE (addr
) != CONST
)
4330 addr
= XEXP (addr
, 0);
4331 if (GET_CODE (addr
) == PLUS
)
4333 if (GET_CODE (XEXP (addr
, 1)) != CONST_INT
)
4335 addr
= XEXP (addr
, 0);
4337 return (GET_CODE (addr
) == UNSPEC
4338 && XVECLEN (addr
, 0) == 1
4339 && XINT (addr
, 1) == ARC_UNSPEC_GOT
4340 && GET_CODE (XVECEXP (addr
, 0, 0)) == SYMBOL_REF
);
4343 /* Return true if ADDR is a valid pic address.
4344 A valid pic address on arc should look like
4345 const (unspec (SYMBOL_REF/LABEL) (ARC_UNSPEC_GOTOFF/ARC_UNSPEC_GOT)) */
4348 arc_legitimate_pic_addr_p (rtx addr
)
4350 if (GET_CODE (addr
) == LABEL_REF
)
4352 if (GET_CODE (addr
) != CONST
)
4355 addr
= XEXP (addr
, 0);
4358 if (GET_CODE (addr
) == PLUS
)
4360 if (GET_CODE (XEXP (addr
, 1)) != CONST_INT
)
4362 addr
= XEXP (addr
, 0);
4365 if (GET_CODE (addr
) != UNSPEC
4366 || XVECLEN (addr
, 0) != 1)
4369 /* Must be @GOT or @GOTOFF. */
4370 if (XINT (addr
, 1) != ARC_UNSPEC_GOT
4371 && XINT (addr
, 1) != ARC_UNSPEC_GOTOFF
)
4374 if (GET_CODE (XVECEXP (addr
, 0, 0)) != SYMBOL_REF
4375 && GET_CODE (XVECEXP (addr
, 0, 0)) != LABEL_REF
)
4383 /* Return true if OP contains a symbol reference. */
4386 symbolic_reference_mentioned_p (rtx op
)
4388 register const char *fmt
;
4391 if (GET_CODE (op
) == SYMBOL_REF
|| GET_CODE (op
) == LABEL_REF
)
4394 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
4395 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
4401 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
4402 if (symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
)))
4406 else if (fmt
[i
] == 'e' && symbolic_reference_mentioned_p (XEXP (op
, i
)))
4413 /* Return true if OP contains a SYMBOL_REF that is not wrapped in an unspec.
4414 If SKIP_LOCAL is true, skip symbols that bind locally.
4415 This is used further down in this file, and, without SKIP_LOCAL,
4416 in the addsi3 / subsi3 expanders when generating PIC code. */
4419 arc_raw_symbolic_reference_mentioned_p (rtx op
, bool skip_local
)
4421 register const char *fmt
;
4424 if (GET_CODE(op
) == UNSPEC
)
4427 if (GET_CODE (op
) == SYMBOL_REF
)
4429 tree decl
= SYMBOL_REF_DECL (op
);
4430 return !skip_local
|| !decl
|| !default_binds_local_p (decl
);
4433 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
4434 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
4440 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
4441 if (arc_raw_symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
),
4446 else if (fmt
[i
] == 'e'
4447 && arc_raw_symbolic_reference_mentioned_p (XEXP (op
, i
),
4455 /* Legitimize a pic address reference in ORIG.
4456 The return value is the legitimated address.
4457 If OLDX is non-zero, it is the target to assign the address to first. */
4460 arc_legitimize_pic_address (rtx orig
, rtx oldx
)
4469 if (GET_CODE (addr
) == LABEL_REF
)
4471 else if (GET_CODE (addr
) == SYMBOL_REF
4472 && (CONSTANT_POOL_ADDRESS_P (addr
)
4473 || SYMBOL_REF_LOCAL_P (addr
)))
4475 /* This symbol may be referenced via a displacement from the PIC
4476 base address (@GOTOFF). */
4478 /* FIXME: if we had a way to emit pc-relative adds that don't
4479 create a GOT entry, we could do without the use of the gp register. */
4480 crtl
->uses_pic_offset_table
= 1;
4481 pat
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, addr
), ARC_UNSPEC_GOTOFF
);
4482 pat
= gen_rtx_CONST (Pmode
, pat
);
4483 pat
= gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, pat
);
4486 oldx
= gen_reg_rtx (Pmode
);
4490 emit_move_insn (oldx
, pat
);
4495 else if (GET_CODE (addr
) == SYMBOL_REF
)
4497 /* This symbol must be referenced via a load from the
4498 Global Offset Table (@GOTPC). */
4500 pat
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, addr
), ARC_UNSPEC_GOT
);
4501 pat
= gen_rtx_CONST (Pmode
, pat
);
4502 pat
= gen_const_mem (Pmode
, pat
);
4505 oldx
= gen_reg_rtx (Pmode
);
4507 emit_move_insn (oldx
, pat
);
4512 if (GET_CODE (addr
) == CONST
)
4514 addr
= XEXP (addr
, 0);
4515 if (GET_CODE (addr
) == UNSPEC
)
4517 /* Check that the unspec is one of the ones we generate? */
4520 gcc_assert (GET_CODE (addr
) == PLUS
);
4523 if (GET_CODE (addr
) == PLUS
)
4525 rtx op0
= XEXP (addr
, 0), op1
= XEXP (addr
, 1);
4527 /* Check first to see if this is a constant offset from a @GOTOFF
4528 symbol reference. */
4529 if ((GET_CODE (op0
) == LABEL_REF
4530 || (GET_CODE (op0
) == SYMBOL_REF
4531 && (CONSTANT_POOL_ADDRESS_P (op0
)
4532 || SYMBOL_REF_LOCAL_P (op0
))))
4533 && GET_CODE (op1
) == CONST_INT
)
4535 /* FIXME: like above, could do without gp reference. */
4536 crtl
->uses_pic_offset_table
= 1;
4538 = gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, op0
), ARC_UNSPEC_GOTOFF
);
4539 pat
= gen_rtx_PLUS (Pmode
, pat
, op1
);
4540 pat
= gen_rtx_CONST (Pmode
, pat
);
4541 pat
= gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, pat
);
4545 emit_move_insn (oldx
, pat
);
4551 base
= arc_legitimize_pic_address (XEXP (addr
, 0), oldx
);
4552 pat
= arc_legitimize_pic_address (XEXP (addr
, 1),
4553 base
== oldx
? NULL_RTX
: oldx
);
4555 if (GET_CODE (pat
) == CONST_INT
)
4556 pat
= plus_constant (Pmode
, base
, INTVAL (pat
));
4559 if (GET_CODE (pat
) == PLUS
&& CONSTANT_P (XEXP (pat
, 1)))
4561 base
= gen_rtx_PLUS (Pmode
, base
, XEXP (pat
, 0));
4562 pat
= XEXP (pat
, 1);
4564 pat
= gen_rtx_PLUS (Pmode
, base
, pat
);
4573 /* Output address constant X to FILE, taking PIC into account. */
4576 arc_output_pic_addr_const (FILE * file
, rtx x
, int code
)
4581 switch (GET_CODE (x
))
4591 output_addr_const (file
, x
);
4593 /* Local functions do not get references through the PLT. */
4594 if (code
== 'P' && ! SYMBOL_REF_LOCAL_P (x
))
4595 fputs ("@plt", file
);
4599 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (XEXP (x
, 0)));
4600 assemble_name (file
, buf
);
4604 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (x
));
4605 assemble_name (file
, buf
);
4609 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
));
4613 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4617 if (GET_MODE (x
) == VOIDmode
)
4619 /* We can use %d if the number is one word and positive. */
4620 if (CONST_DOUBLE_HIGH (x
))
4621 fprintf (file
, HOST_WIDE_INT_PRINT_DOUBLE_HEX
,
4622 CONST_DOUBLE_HIGH (x
), CONST_DOUBLE_LOW (x
));
4623 else if (CONST_DOUBLE_LOW (x
) < 0)
4624 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, CONST_DOUBLE_LOW (x
));
4626 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, CONST_DOUBLE_LOW (x
));
4629 /* We can't handle floating point constants;
4630 PRINT_OPERAND must handle them. */
4631 output_operand_lossage ("floating constant misused");
4635 /* FIXME: Not needed here. */
4636 /* Some assemblers need integer constants to appear last (eg masm). */
4637 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
4639 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4640 fprintf (file
, "+");
4641 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4643 else if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
4645 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4646 if (INTVAL (XEXP (x
, 1)) >= 0)
4647 fprintf (file
, "+");
4648 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4655 /* Avoid outputting things like x-x or x+5-x,
4656 since some assemblers can't handle that. */
4657 x
= simplify_subtraction (x
);
4658 if (GET_CODE (x
) != MINUS
)
4661 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4662 fprintf (file
, "-");
4663 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
4664 && INTVAL (XEXP (x
, 1)) < 0)
4666 fprintf (file
, "(");
4667 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4668 fprintf (file
, ")");
4671 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4676 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4681 gcc_assert (XVECLEN (x
, 0) == 1);
4682 if (XINT (x
, 1) == ARC_UNSPEC_GOT
)
4683 fputs ("pcl,", file
);
4684 arc_output_pic_addr_const (file
, XVECEXP (x
, 0, 0), code
);
4685 switch (XINT (x
, 1))
4687 case ARC_UNSPEC_GOT
:
4688 fputs ("@gotpc", file
);
4690 case ARC_UNSPEC_GOTOFF
:
4691 fputs ("@gotoff", file
);
4693 case ARC_UNSPEC_PLT
:
4694 fputs ("@plt", file
);
4697 output_operand_lossage ("invalid UNSPEC as operand: %d", XINT (x
,1));
4703 output_operand_lossage ("invalid expression as operand");
4707 #define SYMBOLIC_CONST(X) \
4708 (GET_CODE (X) == SYMBOL_REF \
4709 || GET_CODE (X) == LABEL_REF \
4710 || (GET_CODE (X) == CONST && symbolic_reference_mentioned_p (X)))
4712 /* Emit insns to move operands[1] into operands[0]. */
4715 emit_pic_move (rtx
*operands
, machine_mode
)
4717 rtx temp
= reload_in_progress
? operands
[0] : gen_reg_rtx (Pmode
);
4719 if (GET_CODE (operands
[0]) == MEM
&& SYMBOLIC_CONST (operands
[1]))
4720 operands
[1] = force_reg (Pmode
, operands
[1]);
4722 operands
[1] = arc_legitimize_pic_address (operands
[1], temp
);
4726 /* The function returning the number of words, at the beginning of an
4727 argument, must be put in registers. The returned value must be
4728 zero for arguments that are passed entirely in registers or that
4729 are entirely pushed on the stack.
4731 On some machines, certain arguments must be passed partially in
4732 registers and partially in memory. On these machines, typically
4733 the first N words of arguments are passed in registers, and the
4734 rest on the stack. If a multi-word argument (a `double' or a
4735 structure) crosses that boundary, its first few words must be
4736 passed in registers and the rest must be pushed. This function
4737 tells the compiler when this occurs, and how many of the words
4738 should go in registers.
4740 `FUNCTION_ARG' for these arguments should return the first register
4741 to be used by the caller for this argument; likewise
4742 `FUNCTION_INCOMING_ARG', for the called function.
4744 The function is used to implement macro FUNCTION_ARG_PARTIAL_NREGS. */
4746 /* If REGNO is the least arg reg available then what is the total number of arg
4748 #define GPR_REST_ARG_REGS(REGNO) \
4749 ((REGNO) <= MAX_ARC_PARM_REGS ? MAX_ARC_PARM_REGS - (REGNO) : 0 )
4751 /* Since arc parm regs are contiguous. */
4752 #define ARC_NEXT_ARG_REG(REGNO) ( (REGNO) + 1 )
4754 /* Implement TARGET_ARG_PARTIAL_BYTES. */
4757 arc_arg_partial_bytes (cumulative_args_t cum_v
, machine_mode mode
,
4758 tree type
, bool named ATTRIBUTE_UNUSED
)
4760 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
4761 int bytes
= (mode
== BLKmode
4762 ? int_size_in_bytes (type
) : (int) GET_MODE_SIZE (mode
));
4763 int words
= (bytes
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
4767 arg_num
= ROUND_ADVANCE_CUM (arg_num
, mode
, type
);
4768 ret
= GPR_REST_ARG_REGS (arg_num
);
4770 /* ICEd at function.c:2361, and ret is copied to data->partial */
4771 ret
= (ret
>= words
? 0 : ret
* UNITS_PER_WORD
);
4778 /* This function is used to control a function argument is passed in a
4779 register, and which register.
4781 The arguments are CUM, of type CUMULATIVE_ARGS, which summarizes
4782 (in a way defined by INIT_CUMULATIVE_ARGS and FUNCTION_ARG_ADVANCE)
4783 all of the previous arguments so far passed in registers; MODE, the
4784 machine mode of the argument; TYPE, the data type of the argument
4785 as a tree node or 0 if that is not known (which happens for C
4786 support library functions); and NAMED, which is 1 for an ordinary
4787 argument and 0 for nameless arguments that correspond to `...' in
4788 the called function's prototype.
4790 The returned value should either be a `reg' RTX for the hard
4791 register in which to pass the argument, or zero to pass the
4792 argument on the stack.
4794 For machines like the Vax and 68000, where normally all arguments
4795 are pushed, zero suffices as a definition.
4797 The usual way to make the ANSI library `stdarg.h' work on a machine
4798 where some arguments are usually passed in registers, is to cause
4799 nameless arguments to be passed on the stack instead. This is done
4800 by making the function return 0 whenever NAMED is 0.
4802 You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the
4803 definition of this function to determine if this argument is of a
4804 type that must be passed in the stack. If `REG_PARM_STACK_SPACE'
4805 is not defined and the function returns non-zero for such an
4806 argument, the compiler will abort. If `REG_PARM_STACK_SPACE' is
4807 defined, the argument will be computed in the stack and then loaded
4810 The function is used to implement macro FUNCTION_ARG. */
4811 /* On the ARC the first MAX_ARC_PARM_REGS args are normally in registers
4812 and the rest are pushed. */
4815 arc_function_arg (cumulative_args_t cum_v
, machine_mode mode
,
4816 const_tree type ATTRIBUTE_UNUSED
, bool named ATTRIBUTE_UNUSED
)
4818 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
4821 const char *debstr ATTRIBUTE_UNUSED
;
4823 arg_num
= ROUND_ADVANCE_CUM (arg_num
, mode
, type
);
4824 /* Return a marker for use in the call instruction. */
4825 if (mode
== VOIDmode
)
4830 else if (GPR_REST_ARG_REGS (arg_num
) > 0)
4832 ret
= gen_rtx_REG (mode
, arg_num
);
4833 debstr
= reg_names
[arg_num
];
4843 /* The function to update the summarizer variable *CUM to advance past
4844 an argument in the argument list. The values MODE, TYPE and NAMED
4845 describe that argument. Once this is done, the variable *CUM is
4846 suitable for analyzing the *following* argument with
4847 `FUNCTION_ARG', etc.
4849 This function need not do anything if the argument in question was
4850 passed on the stack. The compiler knows how to track the amount of
4851 stack space used for arguments without any special help.
4853 The function is used to implement macro FUNCTION_ARG_ADVANCE. */
4854 /* For the ARC: the cum set here is passed on to function_arg where we
4855 look at its value and say which reg to use. Strategy: advance the
4856 regnumber here till we run out of arg regs, then set *cum to last
4857 reg. In function_arg, since *cum > last arg reg we would return 0
4858 and thus the arg will end up on the stack. For straddling args of
4859 course function_arg_partial_nregs will come into play. */
4862 arc_function_arg_advance (cumulative_args_t cum_v
, machine_mode mode
,
4863 const_tree type
, bool named ATTRIBUTE_UNUSED
)
4865 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
4866 int bytes
= (mode
== BLKmode
4867 ? int_size_in_bytes (type
) : (int) GET_MODE_SIZE (mode
));
4868 int words
= (bytes
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
4872 *cum
= ROUND_ADVANCE_CUM (*cum
, mode
, type
);
4873 for (i
= 0; i
< words
; i
++)
4874 *cum
= ARC_NEXT_ARG_REG (*cum
);
4878 /* Define how to find the value returned by a function.
4879 VALTYPE is the data type of the value (as a tree).
4880 If the precise function being called is known, FN_DECL_OR_TYPE is its
4881 FUNCTION_DECL; otherwise, FN_DECL_OR_TYPE is its type. */
4884 arc_function_value (const_tree valtype
,
4885 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
4886 bool outgoing ATTRIBUTE_UNUSED
)
4888 machine_mode mode
= TYPE_MODE (valtype
);
4889 int unsignedp ATTRIBUTE_UNUSED
;
4891 unsignedp
= TYPE_UNSIGNED (valtype
);
4892 if (INTEGRAL_TYPE_P (valtype
) || TREE_CODE (valtype
) == OFFSET_TYPE
)
4893 PROMOTE_MODE (mode
, unsignedp
, valtype
);
4894 return gen_rtx_REG (mode
, 0);
4897 /* Returns the return address that is used by builtin_return_address. */
4900 arc_return_addr_rtx (int count
, ATTRIBUTE_UNUSED rtx frame
)
4905 return get_hard_reg_initial_val (Pmode
, RETURN_ADDR_REGNUM
);
4908 /* Nonzero if the constant value X is a legitimate general operand
4909 when generating PIC code. It is given that flag_pic is on and
4910 that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
4913 arc_legitimate_pic_operand_p (rtx x
)
4915 return !arc_raw_symbolic_reference_mentioned_p (x
, true);
4918 /* Determine if a given RTX is a valid constant. We already know this
4919 satisfies CONSTANT_P. */
4922 arc_legitimate_constant_p (machine_mode
, rtx x
)
4927 switch (GET_CODE (x
))
4932 if (GET_CODE (x
) == PLUS
)
4934 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
4939 /* Only some unspecs are valid as "constants". */
4940 if (GET_CODE (x
) == UNSPEC
)
4941 switch (XINT (x
, 1))
4943 case ARC_UNSPEC_PLT
:
4944 case ARC_UNSPEC_GOTOFF
:
4945 case ARC_UNSPEC_GOT
:
4953 /* We must have drilled down to a symbol. */
4954 if (arc_raw_symbolic_reference_mentioned_p (x
, false))
4968 /* Otherwise we handle everything else in the move patterns. */
4973 arc_legitimate_address_p (machine_mode mode
, rtx x
, bool strict
)
4975 if (RTX_OK_FOR_BASE_P (x
, strict
))
4977 if (LEGITIMATE_OFFSET_ADDRESS_P (mode
, x
, TARGET_INDEXED_LOADS
, strict
))
4979 if (LEGITIMATE_SCALED_ADDRESS_P (mode
, x
, strict
))
4981 if (LEGITIMATE_SMALL_DATA_ADDRESS_P (x
))
4983 if (GET_CODE (x
) == CONST_INT
&& LARGE_INT (INTVAL (x
)))
4985 if ((GET_MODE_SIZE (mode
) != 16)
4986 && (GET_CODE (x
) == SYMBOL_REF
4987 || GET_CODE (x
) == LABEL_REF
4988 || GET_CODE (x
) == CONST
))
4990 if (!flag_pic
|| arc_legitimate_pic_addr_p (x
))
4993 if ((GET_CODE (x
) == PRE_DEC
|| GET_CODE (x
) == PRE_INC
4994 || GET_CODE (x
) == POST_DEC
|| GET_CODE (x
) == POST_INC
)
4995 && RTX_OK_FOR_BASE_P (XEXP (x
, 0), strict
))
4997 /* We're restricted here by the `st' insn. */
4998 if ((GET_CODE (x
) == PRE_MODIFY
|| GET_CODE (x
) == POST_MODIFY
)
4999 && GET_CODE (XEXP ((x
), 1)) == PLUS
5000 && rtx_equal_p (XEXP ((x
), 0), XEXP (XEXP (x
, 1), 0))
5001 && LEGITIMATE_OFFSET_ADDRESS_P (QImode
, XEXP (x
, 1),
5002 TARGET_AUTO_MODIFY_REG
, strict
))
5007 /* Return true iff ADDR (a legitimate address expression)
5008 has an effect that depends on the machine mode it is used for. */
5011 arc_mode_dependent_address_p (const_rtx addr
, addr_space_t
)
5013 /* SYMBOL_REF is not mode dependent: it is either a small data reference,
5014 which is valid for loads and stores, or a limm offset, which is valid for
5016 /* Scaled indices are scaled by the access mode; likewise for scaled
5017 offsets, which are needed for maximum offset stores. */
5018 if (GET_CODE (addr
) == PLUS
5019 && (GET_CODE (XEXP ((addr
), 0)) == MULT
5020 || (CONST_INT_P (XEXP ((addr
), 1))
5021 && !SMALL_INT (INTVAL (XEXP ((addr
), 1))))))
5026 /* Determine if it's legal to put X into the constant pool. */
5029 arc_cannot_force_const_mem (machine_mode mode
, rtx x
)
5031 return !arc_legitimate_constant_p (mode
, x
);
5035 /* Generic function to define a builtin. */
5036 #define def_mbuiltin(MASK, NAME, TYPE, CODE) \
5040 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL, NULL_TREE); \
5046 arc_init_builtins (void)
5048 tree endlink
= void_list_node
;
5050 tree void_ftype_void
5051 = build_function_type (void_type_node
,
5055 = build_function_type (integer_type_node
,
5056 tree_cons (NULL_TREE
, integer_type_node
, endlink
));
5058 tree pcvoid_type_node
5059 = build_pointer_type (build_qualified_type (void_type_node
, TYPE_QUAL_CONST
));
5060 tree int_ftype_pcvoid_int
5061 = build_function_type (integer_type_node
,
5062 tree_cons (NULL_TREE
, pcvoid_type_node
,
5063 tree_cons (NULL_TREE
, integer_type_node
,
5066 tree int_ftype_short_int
5067 = build_function_type (integer_type_node
,
5068 tree_cons (NULL_TREE
, short_integer_type_node
, endlink
));
5070 tree void_ftype_int_int
5071 = build_function_type (void_type_node
,
5072 tree_cons (NULL_TREE
, integer_type_node
,
5073 tree_cons (NULL_TREE
, integer_type_node
, endlink
)));
5074 tree void_ftype_usint_usint
5075 = build_function_type (void_type_node
,
5076 tree_cons (NULL_TREE
, long_unsigned_type_node
,
5077 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
)));
5079 tree int_ftype_int_int
5080 = build_function_type (integer_type_node
,
5081 tree_cons (NULL_TREE
, integer_type_node
,
5082 tree_cons (NULL_TREE
, integer_type_node
, endlink
)));
5084 tree usint_ftype_usint
5085 = build_function_type (long_unsigned_type_node
,
5086 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
));
5088 tree void_ftype_usint
5089 = build_function_type (void_type_node
,
5090 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
));
5092 /* Add the builtins. */
5093 def_mbuiltin (1,"__builtin_arc_nop", void_ftype_void
, ARC_BUILTIN_NOP
);
5094 def_mbuiltin (TARGET_NORM
, "__builtin_arc_norm", int_ftype_int
, ARC_BUILTIN_NORM
);
5095 def_mbuiltin (TARGET_NORM
, "__builtin_arc_normw", int_ftype_short_int
, ARC_BUILTIN_NORMW
);
5096 def_mbuiltin (TARGET_SWAP
, "__builtin_arc_swap", int_ftype_int
, ARC_BUILTIN_SWAP
);
5097 def_mbuiltin (TARGET_MUL64_SET
,"__builtin_arc_mul64", void_ftype_int_int
, ARC_BUILTIN_MUL64
);
5098 def_mbuiltin (TARGET_MUL64_SET
,"__builtin_arc_mulu64", void_ftype_usint_usint
, ARC_BUILTIN_MULU64
);
5099 def_mbuiltin (1,"__builtin_arc_rtie", void_ftype_void
, ARC_BUILTIN_RTIE
);
5100 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_sync", void_ftype_void
, ARC_BUILTIN_SYNC
);
5101 def_mbuiltin ((TARGET_EA_SET
),"__builtin_arc_divaw", int_ftype_int_int
, ARC_BUILTIN_DIVAW
);
5102 def_mbuiltin (1,"__builtin_arc_brk", void_ftype_void
, ARC_BUILTIN_BRK
);
5103 def_mbuiltin (1,"__builtin_arc_flag", void_ftype_usint
, ARC_BUILTIN_FLAG
);
5104 def_mbuiltin (1,"__builtin_arc_sleep", void_ftype_usint
, ARC_BUILTIN_SLEEP
);
5105 def_mbuiltin (1,"__builtin_arc_swi", void_ftype_void
, ARC_BUILTIN_SWI
);
5106 def_mbuiltin (1,"__builtin_arc_core_read", usint_ftype_usint
, ARC_BUILTIN_CORE_READ
);
5107 def_mbuiltin (1,"__builtin_arc_core_write", void_ftype_usint_usint
, ARC_BUILTIN_CORE_WRITE
);
5108 def_mbuiltin (1,"__builtin_arc_lr", usint_ftype_usint
, ARC_BUILTIN_LR
);
5109 def_mbuiltin (1,"__builtin_arc_sr", void_ftype_usint_usint
, ARC_BUILTIN_SR
);
5110 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_trap_s", void_ftype_usint
, ARC_BUILTIN_TRAP_S
);
5111 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_unimp_s", void_ftype_void
, ARC_BUILTIN_UNIMP_S
);
5112 def_mbuiltin (1,"__builtin_arc_aligned", int_ftype_pcvoid_int
, ARC_BUILTIN_ALIGNED
);
5114 if (TARGET_SIMD_SET
)
5115 arc_init_simd_builtins ();
5118 static rtx
arc_expand_simd_builtin (tree
, rtx
, rtx
, machine_mode
, int);
5120 /* Expand an expression EXP that calls a built-in function,
5121 with result going to TARGET if that's convenient
5122 (and in mode MODE if that's convenient).
5123 SUBTARGET may be used as the target for computing one of EXP's operands.
5124 IGNORE is nonzero if the value is to be ignored. */
5127 arc_expand_builtin (tree exp
,
5133 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
5138 int fcode
= DECL_FUNCTION_CODE (fndecl
);
5143 if (fcode
> ARC_SIMD_BUILTIN_BEGIN
&& fcode
< ARC_SIMD_BUILTIN_END
)
5144 return arc_expand_simd_builtin (exp
, target
, subtarget
, mode
, ignore
);
5148 case ARC_BUILTIN_NOP
:
5149 emit_insn (gen_nop ());
5152 case ARC_BUILTIN_NORM
:
5153 icode
= CODE_FOR_clrsbsi2
;
5154 arg0
= CALL_EXPR_ARG (exp
, 0);
5155 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5156 mode0
= insn_data
[icode
].operand
[1].mode
;
5157 target
= gen_reg_rtx (SImode
);
5159 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5160 op0
= copy_to_mode_reg (mode0
, op0
);
5162 emit_insn (gen_clrsbsi2 (target
, op0
));
5165 case ARC_BUILTIN_NORMW
:
5167 /* FIXME : This should all be HImode, not SImode. */
5168 icode
= CODE_FOR_normw
;
5169 arg0
= CALL_EXPR_ARG (exp
, 0);
5170 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5171 mode0
= insn_data
[icode
].operand
[1].mode
;
5172 target
= gen_reg_rtx (SImode
);
5174 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5175 op0
= copy_to_mode_reg (mode0
, convert_to_mode (mode0
, op0
,0));
5177 emit_insn (gen_normw (target
, op0
));
5180 case ARC_BUILTIN_MUL64
:
5181 icode
= CODE_FOR_mul64
;
5182 arg0
= CALL_EXPR_ARG (exp
, 0);
5183 arg1
= CALL_EXPR_ARG (exp
, 1);
5184 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5185 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5187 mode0
= insn_data
[icode
].operand
[0].mode
;
5188 mode1
= insn_data
[icode
].operand
[1].mode
;
5190 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5191 op0
= copy_to_mode_reg (mode0
, op0
);
5193 if (! (*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
5194 op1
= copy_to_mode_reg (mode1
, op1
);
5196 emit_insn (gen_mul64 (op0
,op1
));
5199 case ARC_BUILTIN_MULU64
:
5200 icode
= CODE_FOR_mulu64
;
5201 arg0
= CALL_EXPR_ARG (exp
, 0);
5202 arg1
= CALL_EXPR_ARG (exp
, 1);
5203 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5204 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5206 mode0
= insn_data
[icode
].operand
[0].mode
;
5207 mode1
= insn_data
[icode
].operand
[1].mode
;
5209 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5210 op0
= copy_to_mode_reg (mode0
, op0
);
5212 if (! (*insn_data
[icode
].operand
[0].predicate
) (op1
, mode1
))
5213 op1
= copy_to_mode_reg (mode1
, op1
);
5215 emit_insn (gen_mulu64 (op0
,op1
));
5218 case ARC_BUILTIN_RTIE
:
5219 icode
= CODE_FOR_rtie
;
5220 emit_insn (gen_rtie (const1_rtx
));
5223 case ARC_BUILTIN_SYNC
:
5224 icode
= CODE_FOR_sync
;
5225 emit_insn (gen_sync (const1_rtx
));
5228 case ARC_BUILTIN_SWAP
:
5229 icode
= CODE_FOR_swap
;
5230 arg0
= CALL_EXPR_ARG (exp
, 0);
5231 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5232 mode0
= insn_data
[icode
].operand
[1].mode
;
5233 target
= gen_reg_rtx (SImode
);
5235 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5236 op0
= copy_to_mode_reg (mode0
, op0
);
5238 emit_insn (gen_swap (target
, op0
));
5241 case ARC_BUILTIN_DIVAW
:
5242 icode
= CODE_FOR_divaw
;
5243 arg0
= CALL_EXPR_ARG (exp
, 0);
5244 arg1
= CALL_EXPR_ARG (exp
, 1);
5246 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5247 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5248 target
= gen_reg_rtx (SImode
);
5250 mode0
= insn_data
[icode
].operand
[0].mode
;
5251 mode1
= insn_data
[icode
].operand
[1].mode
;
5253 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5254 op0
= copy_to_mode_reg (mode0
, op0
);
5256 if (! (*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
5257 op1
= copy_to_mode_reg (mode1
, op1
);
5259 emit_insn (gen_divaw (target
, op0
, op1
));
5262 case ARC_BUILTIN_BRK
:
5263 icode
= CODE_FOR_brk
;
5264 emit_insn (gen_brk (const1_rtx
));
5267 case ARC_BUILTIN_SLEEP
:
5268 icode
= CODE_FOR_sleep
;
5269 arg0
= CALL_EXPR_ARG (exp
, 0);
5273 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5274 mode0
= insn_data
[icode
].operand
[1].mode
;
5276 emit_insn (gen_sleep (op0
));
5279 case ARC_BUILTIN_SWI
:
5280 icode
= CODE_FOR_swi
;
5281 emit_insn (gen_swi (const1_rtx
));
5284 case ARC_BUILTIN_FLAG
:
5285 icode
= CODE_FOR_flag
;
5286 arg0
= CALL_EXPR_ARG (exp
, 0);
5287 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5288 mode0
= insn_data
[icode
].operand
[0].mode
;
5290 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5291 op0
= copy_to_mode_reg (mode0
, op0
);
5293 emit_insn (gen_flag (op0
));
5296 case ARC_BUILTIN_CORE_READ
:
5297 icode
= CODE_FOR_core_read
;
5298 arg0
= CALL_EXPR_ARG (exp
, 0);
5299 target
= gen_reg_rtx (SImode
);
5303 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5304 mode0
= insn_data
[icode
].operand
[1].mode
;
5306 emit_insn (gen_core_read (target
, op0
));
5309 case ARC_BUILTIN_CORE_WRITE
:
5310 icode
= CODE_FOR_core_write
;
5311 arg0
= CALL_EXPR_ARG (exp
, 0);
5312 arg1
= CALL_EXPR_ARG (exp
, 1);
5316 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5317 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5319 mode0
= insn_data
[icode
].operand
[0].mode
;
5320 mode1
= insn_data
[icode
].operand
[1].mode
;
5322 emit_insn (gen_core_write (op0
, op1
));
5325 case ARC_BUILTIN_LR
:
5326 icode
= CODE_FOR_lr
;
5327 arg0
= CALL_EXPR_ARG (exp
, 0);
5328 target
= gen_reg_rtx (SImode
);
5332 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5333 mode0
= insn_data
[icode
].operand
[1].mode
;
5335 emit_insn (gen_lr (target
, op0
));
5338 case ARC_BUILTIN_SR
:
5339 icode
= CODE_FOR_sr
;
5340 arg0
= CALL_EXPR_ARG (exp
, 0);
5341 arg1
= CALL_EXPR_ARG (exp
, 1);
5345 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5346 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5348 mode0
= insn_data
[icode
].operand
[0].mode
;
5349 mode1
= insn_data
[icode
].operand
[1].mode
;
5351 emit_insn (gen_sr (op0
, op1
));
5354 case ARC_BUILTIN_TRAP_S
:
5355 icode
= CODE_FOR_trap_s
;
5356 arg0
= CALL_EXPR_ARG (exp
, 0);
5360 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5361 mode0
= insn_data
[icode
].operand
[1].mode
;
5363 /* We don't give an error for non-cost values here because
5364 we still want to allow things to be fixed up by later inlining /
5365 constant folding / dead code elimination. */
5366 if (CONST_INT_P (op0
) && !satisfies_constraint_L (op0
))
5368 /* Keep this message in sync with the one in arc.md:trap_s,
5369 because *.md files don't get scanned by exgettext. */
5370 error ("operand to trap_s should be an unsigned 6-bit value");
5372 emit_insn (gen_trap_s (op0
));
5375 case ARC_BUILTIN_UNIMP_S
:
5376 icode
= CODE_FOR_unimp_s
;
5377 emit_insn (gen_unimp_s (const1_rtx
));
5380 case ARC_BUILTIN_ALIGNED
:
5381 /* __builtin_arc_aligned (void* val, int alignval) */
5382 arg0
= CALL_EXPR_ARG (exp
, 0);
5383 arg1
= CALL_EXPR_ARG (exp
, 1);
5385 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5386 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5387 target
= gen_reg_rtx (SImode
);
5389 if (!CONST_INT_P (op1
))
5391 /* If we can't fold the alignment to a constant integer
5392 whilst optimizing, this is probably a user error. */
5394 warning (0, "__builtin_arc_aligned with non-constant alignment");
5398 HOST_WIDE_INT alignTest
= INTVAL (op1
);
5399 /* Check alignTest is positive, and a power of two. */
5400 if (alignTest
<= 0 || alignTest
!= (alignTest
& -alignTest
))
5402 error ("invalid alignment value for __builtin_arc_aligned");
5406 if (CONST_INT_P (op0
))
5408 HOST_WIDE_INT pnt
= INTVAL (op0
);
5410 if ((pnt
& (alignTest
- 1)) == 0)
5415 unsigned align
= get_pointer_alignment (arg0
);
5416 unsigned numBits
= alignTest
* BITS_PER_UNIT
;
5418 if (align
&& align
>= numBits
)
5420 /* Another attempt to ascertain alignment. Check the type
5421 we are pointing to. */
5422 if (POINTER_TYPE_P (TREE_TYPE (arg0
))
5423 && TYPE_ALIGN (TREE_TYPE (TREE_TYPE (arg0
))) >= numBits
)
5428 /* Default to false. */
5435 /* @@@ Should really do something sensible here. */
5439 /* Returns true if the operands[opno] is a valid compile-time constant to be
5440 used as register number in the code for builtins. Else it flags an error
5441 and returns false. */
5444 check_if_valid_regno_const (rtx
*operands
, int opno
)
5447 switch (GET_CODE (operands
[opno
]))
5454 error ("register number must be a compile-time constant. Try giving higher optimization levels");
5460 /* Check that after all the constant folding, whether the operand to
5461 __builtin_arc_sleep is an unsigned int of 6 bits. If not, flag an error. */
5464 check_if_valid_sleep_operand (rtx
*operands
, int opno
)
5466 switch (GET_CODE (operands
[opno
]))
5470 if( UNSIGNED_INT6 (INTVAL (operands
[opno
])))
5473 fatal_error("operand for sleep instruction must be an unsigned 6 bit compile-time constant");
5479 /* Return true if it is ok to make a tail-call to DECL. */
5482 arc_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED
,
5483 tree exp ATTRIBUTE_UNUSED
)
5485 /* Never tailcall from an ISR routine - it needs a special exit sequence. */
5486 if (ARC_INTERRUPT_P (arc_compute_function_type (cfun
)))
5489 /* Everything else is ok. */
5493 /* Output code to add DELTA to the first argument, and then jump
5494 to FUNCTION. Used for C++ multiple inheritance. */
5497 arc_output_mi_thunk (FILE *file
, tree thunk ATTRIBUTE_UNUSED
,
5498 HOST_WIDE_INT delta
,
5499 HOST_WIDE_INT vcall_offset
,
5502 int mi_delta
= delta
;
5503 const char *const mi_op
= mi_delta
< 0 ? "sub" : "add";
5506 = aggregate_value_p (TREE_TYPE (TREE_TYPE (function
)), function
) ? 1 : 0;
5510 mi_delta
= - mi_delta
;
5512 /* Add DELTA. When possible use a plain add, otherwise load it into
5513 a register first. */
5515 while (mi_delta
!= 0)
5517 if ((mi_delta
& (3 << shift
)) == 0)
5521 asm_fprintf (file
, "\t%s\t%s, %s, %d\n",
5522 mi_op
, reg_names
[this_regno
], reg_names
[this_regno
],
5523 mi_delta
& (0xff << shift
));
5524 mi_delta
&= ~(0xff << shift
);
5529 /* If needed, add *(*THIS + VCALL_OFFSET) to THIS. */
5530 if (vcall_offset
!= 0)
5532 /* ld r12,[this] --> temp = *this
5533 add r12,r12,vcall_offset --> temp = *(*this + vcall_offset)
5535 add this,this,r12 --> this+ = *(*this + vcall_offset) */
5536 asm_fprintf (file
, "\tld\t%s, [%s]\n",
5537 ARC_TEMP_SCRATCH_REG
, reg_names
[this_regno
]);
5538 asm_fprintf (file
, "\tadd\t%s, %s, " HOST_WIDE_INT_PRINT_DEC
"\n",
5539 ARC_TEMP_SCRATCH_REG
, ARC_TEMP_SCRATCH_REG
, vcall_offset
);
5540 asm_fprintf (file
, "\tld\t%s, [%s]\n",
5541 ARC_TEMP_SCRATCH_REG
, ARC_TEMP_SCRATCH_REG
);
5542 asm_fprintf (file
, "\tadd\t%s, %s, %s\n", reg_names
[this_regno
],
5543 reg_names
[this_regno
], ARC_TEMP_SCRATCH_REG
);
5546 fnaddr
= XEXP (DECL_RTL (function
), 0);
5548 if (arc_is_longcall_p (fnaddr
))
5549 fputs ("\tj\t", file
);
5551 fputs ("\tb\t", file
);
5552 assemble_name (file
, XSTR (fnaddr
, 0));
5556 /* Return true if a 32 bit "long_call" should be generated for
5557 this calling SYM_REF. We generate a long_call if the function:
5559 a. has an __attribute__((long call))
5560 or b. the -mlong-calls command line switch has been specified
5562 However we do not generate a long call if the function has an
5563 __attribute__ ((short_call)) or __attribute__ ((medium_call))
5565 This function will be called by C fragments contained in the machine
5566 description file. */
5569 arc_is_longcall_p (rtx sym_ref
)
5571 if (GET_CODE (sym_ref
) != SYMBOL_REF
)
5574 return (SYMBOL_REF_LONG_CALL_P (sym_ref
)
5575 || (TARGET_LONG_CALLS_SET
5576 && !SYMBOL_REF_SHORT_CALL_P (sym_ref
)
5577 && !SYMBOL_REF_MEDIUM_CALL_P (sym_ref
)));
5581 /* Likewise for short calls. */
5584 arc_is_shortcall_p (rtx sym_ref
)
5586 if (GET_CODE (sym_ref
) != SYMBOL_REF
)
5589 return (SYMBOL_REF_SHORT_CALL_P (sym_ref
)
5590 || (!TARGET_LONG_CALLS_SET
&& !TARGET_MEDIUM_CALLS
5591 && !SYMBOL_REF_LONG_CALL_P (sym_ref
)
5592 && !SYMBOL_REF_MEDIUM_CALL_P (sym_ref
)));
5596 /* Emit profiling code for calling CALLEE. Return true if a special
5597 call pattern needs to be generated. */
5600 arc_profile_call (rtx callee
)
5602 rtx from
= XEXP (DECL_RTL (current_function_decl
), 0);
5604 if (TARGET_UCB_MCOUNT
)
5605 /* Profiling is done by instrumenting the callee. */
5608 if (CONSTANT_P (callee
))
5611 = gen_rtx_CONST (Pmode
,
5612 gen_rtx_UNSPEC (Pmode
,
5613 gen_rtvec (3, from
, callee
,
5614 CONST0_RTX (Pmode
)),
5616 rtx counter
= gen_rtx_MEM (SImode
, count_ptr
);
5617 /* ??? The increment would better be done atomically, but as there is
5618 no proper hardware support, that would be too expensive. */
5619 emit_move_insn (counter
,
5620 force_reg (SImode
, plus_constant (SImode
, counter
, 1)));
5626 = gen_rtx_CONST (Pmode
,
5627 gen_rtx_UNSPEC (Pmode
,
5628 gen_rtvec (3, from
, CONST0_RTX (Pmode
),
5629 CONST0_RTX (Pmode
)),
5631 emit_move_insn (gen_rtx_REG (Pmode
, 8), count_list_ptr
);
5632 emit_move_insn (gen_rtx_REG (Pmode
, 9), callee
);
5637 /* Worker function for TARGET_RETURN_IN_MEMORY. */
5640 arc_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
5642 if (AGGREGATE_TYPE_P (type
) || TREE_ADDRESSABLE (type
))
5646 HOST_WIDE_INT size
= int_size_in_bytes (type
);
5647 return (size
== -1 || size
> 8);
5652 /* This was in rtlanal.c, and can go in there when we decide we want
5653 to submit the change for inclusion in the GCC tree. */
5654 /* Like note_stores, but allow the callback to have side effects on the rtl
5655 (like the note_stores of yore):
5656 Call FUN on each register or MEM that is stored into or clobbered by X.
5657 (X would be the pattern of an insn). DATA is an arbitrary pointer,
5658 ignored by note_stores, but passed to FUN.
5659 FUN may alter parts of the RTL.
5661 FUN receives three arguments:
5662 1. the REG, MEM, CC0 or PC being stored in or clobbered,
5663 2. the SET or CLOBBER rtx that does the store,
5664 3. the pointer DATA provided to note_stores.
5666 If the item being stored in or clobbered is a SUBREG of a hard register,
5667 the SUBREG will be passed. */
5669 /* For now. */ static
5671 walk_stores (rtx x
, void (*fun
) (rtx
, rtx
, void *), void *data
)
5675 if (GET_CODE (x
) == COND_EXEC
)
5676 x
= COND_EXEC_CODE (x
);
5678 if (GET_CODE (x
) == SET
|| GET_CODE (x
) == CLOBBER
)
5680 rtx dest
= SET_DEST (x
);
5682 while ((GET_CODE (dest
) == SUBREG
5683 && (!REG_P (SUBREG_REG (dest
))
5684 || REGNO (SUBREG_REG (dest
)) >= FIRST_PSEUDO_REGISTER
))
5685 || GET_CODE (dest
) == ZERO_EXTRACT
5686 || GET_CODE (dest
) == STRICT_LOW_PART
)
5687 dest
= XEXP (dest
, 0);
5689 /* If we have a PARALLEL, SET_DEST is a list of EXPR_LIST expressions,
5690 each of whose first operand is a register. */
5691 if (GET_CODE (dest
) == PARALLEL
)
5693 for (i
= XVECLEN (dest
, 0) - 1; i
>= 0; i
--)
5694 if (XEXP (XVECEXP (dest
, 0, i
), 0) != 0)
5695 (*fun
) (XEXP (XVECEXP (dest
, 0, i
), 0), x
, data
);
5698 (*fun
) (dest
, x
, data
);
5701 else if (GET_CODE (x
) == PARALLEL
)
5702 for (i
= XVECLEN (x
, 0) - 1; i
>= 0; i
--)
5703 walk_stores (XVECEXP (x
, 0, i
), fun
, data
);
5707 arc_pass_by_reference (cumulative_args_t ca_v ATTRIBUTE_UNUSED
,
5708 machine_mode mode ATTRIBUTE_UNUSED
,
5710 bool named ATTRIBUTE_UNUSED
)
5713 && (TREE_CODE (TYPE_SIZE (type
)) != INTEGER_CST
5714 || TREE_ADDRESSABLE (type
)));
5717 /* Implement TARGET_CAN_USE_DOLOOP_P. */
5720 arc_can_use_doloop_p (const widest_int
&iterations
, const widest_int
&,
5721 unsigned int loop_depth
, bool entered_at_top
)
5725 /* Setting up the loop with two sr instructions costs 6 cycles. */
5728 && wi::gtu_p (iterations
, 0)
5729 && wi::leu_p (iterations
, flag_pic
? 6 : 3))
5734 /* NULL if INSN insn is valid within a low-overhead loop.
5735 Otherwise return why doloop cannot be applied. */
5738 arc_invalid_within_doloop (const rtx_insn
*insn
)
5741 return "Function call in the loop.";
5745 static int arc_reorg_in_progress
= 0;
5747 /* ARC's machince specific reorg function. */
5758 cfun
->machine
->arc_reorg_started
= 1;
5759 arc_reorg_in_progress
= 1;
5761 /* Emit special sections for profiling. */
5764 section
*save_text_section
;
5766 int size
= get_max_uid () >> 4;
5767 htab_t htab
= htab_create (size
, unspec_prof_hash
, unspec_prof_htab_eq
,
5770 save_text_section
= in_section
;
5771 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
5772 if (NONJUMP_INSN_P (insn
))
5773 walk_stores (PATTERN (insn
), write_profile_sections
, htab
);
5774 if (htab_elements (htab
))
5776 switch_to_section (save_text_section
);
5780 /* Link up loop ends with their loop start. */
5782 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
5783 if (GET_CODE (insn
) == JUMP_INSN
5784 && recog_memoized (insn
) == CODE_FOR_doloop_end_i
)
5787 = as_a
<rtx_insn
*> (XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn
), 0, 0)), 1), 0));
5788 rtx num
= GEN_INT (CODE_LABEL_NUMBER (top_label
));
5789 rtx_insn
*lp
, *prev
= prev_nonnote_insn (top_label
);
5790 rtx_insn
*lp_simple
= NULL
;
5791 rtx_insn
*next
= NULL
;
5792 rtx op0
= XEXP (XVECEXP (PATTERN (insn
), 0, 1), 0);
5793 HOST_WIDE_INT loop_end_id
5794 = -INTVAL (XEXP (XVECEXP (PATTERN (insn
), 0, 4), 0));
5798 (lp
&& NONJUMP_INSN_P (lp
)
5799 && recog_memoized (lp
) != CODE_FOR_doloop_begin_i
);
5800 lp
= prev_nonnote_insn (lp
))
5802 if (!lp
|| !NONJUMP_INSN_P (lp
)
5803 || dead_or_set_regno_p (lp
, LP_COUNT
))
5805 for (prev
= next
= insn
, lp
= NULL
; prev
|| next
;)
5809 if (NONJUMP_INSN_P (prev
)
5810 && recog_memoized (prev
) == CODE_FOR_doloop_begin_i
5811 && (INTVAL (XEXP (XVECEXP (PATTERN (prev
), 0, 5), 0))
5817 else if (LABEL_P (prev
))
5819 prev
= prev_nonnote_insn (prev
);
5823 if (NONJUMP_INSN_P (next
)
5824 && recog_memoized (next
) == CODE_FOR_doloop_begin_i
5825 && (INTVAL (XEXP (XVECEXP (PATTERN (next
), 0, 5), 0))
5831 next
= next_nonnote_insn (next
);
5838 if (lp
&& !dead_or_set_regno_p (lp
, LP_COUNT
))
5840 rtx begin_cnt
= XEXP (XVECEXP (PATTERN (lp
), 0 ,3), 0);
5841 if (INTVAL (XEXP (XVECEXP (PATTERN (lp
), 0, 4), 0)))
5842 /* The loop end insn has been duplicated. That can happen
5843 when there is a conditional block at the very end of
5846 /* If Register allocation failed to allocate to the right
5847 register, There is no point into teaching reload to
5848 fix this up with reloads, as that would cost more
5849 than using an ordinary core register with the
5850 doloop_fallback pattern. */
5851 if ((true_regnum (op0
) != LP_COUNT
|| !REG_P (begin_cnt
))
5852 /* Likewise, if the loop setup is evidently inside the loop,
5854 || (!lp_simple
&& lp
!= next
&& !seen_label
))
5859 /* It is common that the optimizers copy the loop count from
5860 another register, and doloop_begin_i is stuck with the
5861 source of the move. Making doloop_begin_i only accept "l"
5862 is nonsentical, as this then makes reload evict the pseudo
5863 used for the loop end. The underlying cause is that the
5864 optimizers don't understand that the register allocation for
5865 doloop_begin_i should be treated as part of the loop.
5866 Try to work around this problem by verifying the previous
5868 if (true_regnum (begin_cnt
) != LP_COUNT
)
5873 for (mov
= prev_nonnote_insn (lp
); mov
;
5874 mov
= prev_nonnote_insn (mov
))
5876 if (!NONJUMP_INSN_P (mov
))
5878 else if ((set
= single_set (mov
))
5879 && rtx_equal_p (SET_SRC (set
), begin_cnt
)
5880 && rtx_equal_p (SET_DEST (set
), op0
))
5885 XEXP (XVECEXP (PATTERN (lp
), 0 ,3), 0) = op0
;
5886 note
= find_regno_note (lp
, REG_DEAD
, REGNO (begin_cnt
));
5888 remove_note (lp
, note
);
5896 XEXP (XVECEXP (PATTERN (insn
), 0, 4), 0) = num
;
5897 XEXP (XVECEXP (PATTERN (lp
), 0, 4), 0) = num
;
5899 XEXP (XVECEXP (PATTERN (lp
), 0, 6), 0) = const2_rtx
;
5900 else if (!lp_simple
)
5901 XEXP (XVECEXP (PATTERN (lp
), 0, 6), 0) = const1_rtx
;
5902 else if (prev
!= lp
)
5905 add_insn_after (lp
, prev
, NULL
);
5909 XEXP (XVECEXP (PATTERN (lp
), 0, 7), 0)
5910 = gen_rtx_LABEL_REF (Pmode
, top_label
);
5911 add_reg_note (lp
, REG_LABEL_OPERAND
, top_label
);
5912 LABEL_NUSES (top_label
)++;
5914 /* We can avoid tedious loop start / end setting for empty loops
5915 be merely setting the loop count to its final value. */
5916 if (next_active_insn (top_label
) == insn
)
5919 = gen_rtx_SET (VOIDmode
,
5920 XEXP (XVECEXP (PATTERN (lp
), 0, 3), 0),
5923 rtx_insn
*lc_set_insn
= emit_insn_before (lc_set
, insn
);
5928 /* If the loop is non-empty with zero length, we can't make it
5929 a zero-overhead loop. That can happen for empty asms. */
5934 for (scan
= top_label
;
5935 (scan
&& scan
!= insn
5936 && (!NONJUMP_INSN_P (scan
) || !get_attr_length (scan
)));
5937 scan
= NEXT_INSN (scan
));
5947 /* Sometimes the loop optimizer makes a complete hash of the
5948 loop. If it were only that the loop is not entered at the
5949 top, we could fix this up by setting LP_START with SR .
5950 However, if we can't find the loop begin were it should be,
5951 chances are that it does not even dominate the loop, but is
5952 inside the loop instead. Using SR there would kill
5954 We use the doloop_fallback pattern here, which executes
5955 in two cycles on the ARC700 when predicted correctly. */
5959 rtx op3
= XEXP (XVECEXP (PATTERN (insn
), 0, 5), 0);
5961 emit_insn_before (gen_move_insn (op3
, op0
), insn
);
5963 = gen_doloop_fallback_m (op3
, JUMP_LABEL (insn
), op0
);
5966 XVEC (PATTERN (insn
), 0)
5967 = gen_rtvec (2, XVECEXP (PATTERN (insn
), 0, 0),
5968 XVECEXP (PATTERN (insn
), 0, 1));
5969 INSN_CODE (insn
) = -1;
5974 /* FIXME: should anticipate ccfsm action, generate special patterns for
5975 to-be-deleted branches that have no delay slot and have at least the
5976 length of the size increase forced on other insns that are conditionalized.
5977 This can also have an insn_list inside that enumerates insns which are
5978 not actually conditionalized because the destinations are dead in the
5980 Could also tag branches that we want to be unaligned if they get no delay
5981 slot, or even ones that we don't want to do delay slot sheduling for
5982 because we can unalign them.
5984 However, there are cases when conditional execution is only possible after
5985 delay slot scheduling:
5987 - If a delay slot is filled with a nocond/set insn from above, the previous
5988 basic block can become elegible for conditional execution.
5989 - If a delay slot is filled with a nocond insn from the fall-through path,
5990 the branch with that delay slot can become eligble for conditional
5991 execution (however, with the same sort of data flow analysis that dbr
5992 does, we could have figured out before that we don't need to
5993 conditionalize this insn.)
5994 - If a delay slot insn is filled with an insn from the target, the
5995 target label gets its uses decremented (even deleted if falling to zero),
5996 thus possibly creating more condexec opportunities there.
5997 Therefore, we should still be prepared to apply condexec optimization on
5998 non-prepared branches if the size increase of conditionalized insns is no
5999 more than the size saved from eliminating the branch. An invocation option
6000 could also be used to reserve a bit of extra size for condbranches so that
6001 this'll work more often (could also test in arc_reorg if the block is
6002 'close enough' to be eligible for condexec to make this likely, and
6003 estimate required size increase). */
6004 /* Generate BRcc insns, by combining cmp and Bcc insns wherever possible. */
6005 if (TARGET_NO_BRCC_SET
)
6010 init_insn_lengths();
6013 if (optimize
> 1 && !TARGET_NO_COND_EXEC
)
6016 unsigned int flags
= pass_data_arc_ifcvt
.todo_flags_finish
;
6017 df_finish_pass ((flags
& TODO_df_verify
) != 0);
6020 /* Call shorten_branches to calculate the insn lengths. */
6021 shorten_branches (get_insns());
6022 cfun
->machine
->ccfsm_current_insn
= NULL_RTX
;
6024 if (!INSN_ADDRESSES_SET_P())
6025 fatal_error ("Insn addresses not set after shorten_branches");
6027 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
6030 enum attr_type insn_type
;
6032 /* If a non-jump insn (or a casesi jump table), continue. */
6033 if (GET_CODE (insn
) != JUMP_INSN
||
6034 GET_CODE (PATTERN (insn
)) == ADDR_VEC
6035 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
6038 /* If we already have a brcc, note if it is suitable for brcc_s.
6039 Be a bit generous with the brcc_s range so that we can take
6040 advantage of any code shortening from delay slot scheduling. */
6041 if (recog_memoized (insn
) == CODE_FOR_cbranchsi4_scratch
)
6043 rtx pat
= PATTERN (insn
);
6044 rtx op
= XEXP (SET_SRC (XVECEXP (pat
, 0, 0)), 0);
6045 rtx
*ccp
= &XEXP (XVECEXP (pat
, 0, 1), 0);
6047 offset
= branch_dest (insn
) - INSN_ADDRESSES (INSN_UID (insn
));
6048 if ((offset
>= -140 && offset
< 140)
6049 && rtx_equal_p (XEXP (op
, 1), const0_rtx
)
6050 && compact_register_operand (XEXP (op
, 0), VOIDmode
)
6051 && equality_comparison_operator (op
, VOIDmode
))
6052 PUT_MODE (*ccp
, CC_Zmode
);
6053 else if (GET_MODE (*ccp
) == CC_Zmode
)
6054 PUT_MODE (*ccp
, CC_ZNmode
);
6057 if ((insn_type
= get_attr_type (insn
)) == TYPE_BRCC
6058 || insn_type
== TYPE_BRCC_NO_DELAY_SLOT
)
6061 /* OK. so we have a jump insn. */
6062 /* We need to check that it is a bcc. */
6063 /* Bcc => set (pc) (if_then_else ) */
6064 pattern
= PATTERN (insn
);
6065 if (GET_CODE (pattern
) != SET
6066 || GET_CODE (SET_SRC (pattern
)) != IF_THEN_ELSE
6067 || ANY_RETURN_P (XEXP (SET_SRC (pattern
), 1)))
6070 /* Now check if the jump is beyond the s9 range. */
6071 if (CROSSING_JUMP_P (insn
))
6073 offset
= branch_dest (insn
) - INSN_ADDRESSES (INSN_UID (insn
));
6075 if(offset
> 253 || offset
< -254)
6078 pc_target
= SET_SRC (pattern
);
6080 /* Now go back and search for the set cc insn. */
6082 label
= XEXP (pc_target
, 1);
6086 rtx_insn
*scan
, *link_insn
= NULL
;
6088 for (scan
= PREV_INSN (insn
);
6089 scan
&& GET_CODE (scan
) != CODE_LABEL
;
6090 scan
= PREV_INSN (scan
))
6092 if (! INSN_P (scan
))
6094 pat
= PATTERN (scan
);
6095 if (GET_CODE (pat
) == SET
6096 && cc_register (SET_DEST (pat
), VOIDmode
))
6105 /* Check if this is a data dependency. */
6107 rtx op
, cc_clob_rtx
, op0
, op1
, brcc_insn
, note
;
6110 /* Ok this is the set cc. copy args here. */
6111 op
= XEXP (pc_target
, 0);
6113 op0
= cmp0
= XEXP (SET_SRC (pat
), 0);
6114 op1
= cmp1
= XEXP (SET_SRC (pat
), 1);
6115 if (GET_CODE (op0
) == ZERO_EXTRACT
6116 && XEXP (op0
, 1) == const1_rtx
6117 && (GET_CODE (op
) == EQ
6118 || GET_CODE (op
) == NE
))
6120 /* btst / b{eq,ne} -> bbit{0,1} */
6121 op0
= XEXP (cmp0
, 0);
6122 op1
= XEXP (cmp0
, 2);
6124 else if (!register_operand (op0
, VOIDmode
)
6125 || !general_operand (op1
, VOIDmode
))
6127 /* Be careful not to break what cmpsfpx_raw is
6128 trying to create for checking equality of
6129 single-precision floats. */
6130 else if (TARGET_SPFP
6131 && GET_MODE (op0
) == SFmode
6132 && GET_MODE (op1
) == SFmode
)
6135 /* None of the two cmp operands should be set between the
6136 cmp and the branch. */
6137 if (reg_set_between_p (op0
, link_insn
, insn
))
6140 if (reg_set_between_p (op1
, link_insn
, insn
))
6143 /* Since the MODE check does not work, check that this is
6144 CC reg's last set location before insn, and also no
6145 instruction between the cmp and branch uses the
6147 if ((reg_set_between_p (SET_DEST (pat
), link_insn
, insn
))
6148 || (reg_used_between_p (SET_DEST (pat
), link_insn
, insn
)))
6151 /* CC reg should be dead after insn. */
6152 if (!find_regno_note (insn
, REG_DEAD
, CC_REG
))
6155 op
= gen_rtx_fmt_ee (GET_CODE (op
),
6156 GET_MODE (op
), cmp0
, cmp1
);
6157 /* If we create a LIMM where there was none before,
6158 we only benefit if we can avoid a scheduling bubble
6159 for the ARC600. Otherwise, we'd only forgo chances
6160 at short insn generation, and risk out-of-range
6162 if (!brcc_nolimm_operator (op
, VOIDmode
)
6163 && !long_immediate_operand (op1
, VOIDmode
)
6165 || next_active_insn (link_insn
) != insn
))
6168 /* Emit bbit / brcc (or brcc_s if possible).
6169 CC_Zmode indicates that brcc_s is possible. */
6172 cc_clob_rtx
= gen_rtx_REG (CC_ZNmode
, CC_REG
);
6173 else if ((offset
>= -140 && offset
< 140)
6174 && rtx_equal_p (op1
, const0_rtx
)
6175 && compact_register_operand (op0
, VOIDmode
)
6176 && (GET_CODE (op
) == EQ
6177 || GET_CODE (op
) == NE
))
6178 cc_clob_rtx
= gen_rtx_REG (CC_Zmode
, CC_REG
);
6180 cc_clob_rtx
= gen_rtx_REG (CCmode
, CC_REG
);
6183 = gen_rtx_IF_THEN_ELSE (VOIDmode
, op
, label
, pc_rtx
);
6184 brcc_insn
= gen_rtx_SET (VOIDmode
, pc_rtx
, brcc_insn
);
6185 cc_clob_rtx
= gen_rtx_CLOBBER (VOIDmode
, cc_clob_rtx
);
6188 (VOIDmode
, gen_rtvec (2, brcc_insn
, cc_clob_rtx
));
6189 brcc_insn
= emit_jump_insn_before (brcc_insn
, insn
);
6191 JUMP_LABEL (brcc_insn
) = JUMP_LABEL (insn
);
6192 note
= find_reg_note (insn
, REG_BR_PROB
, 0);
6195 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6196 REG_NOTES (brcc_insn
) = note
;
6198 note
= find_reg_note (link_insn
, REG_DEAD
, op0
);
6201 remove_note (link_insn
, note
);
6202 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6203 REG_NOTES (brcc_insn
) = note
;
6205 note
= find_reg_note (link_insn
, REG_DEAD
, op1
);
6208 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6209 REG_NOTES (brcc_insn
) = note
;
6214 /* Delete the bcc insn. */
6215 set_insn_deleted (insn
);
6217 /* Delete the cmp insn. */
6218 set_insn_deleted (link_insn
);
6223 /* Clear out insn_addresses. */
6224 INSN_ADDRESSES_FREE ();
6228 if (INSN_ADDRESSES_SET_P())
6229 fatal_error ("insn addresses not freed");
6231 arc_reorg_in_progress
= 0;
6234 /* Check if the operands are valid for BRcc.d generation
6235 Valid Brcc.d patterns are
6239 For cc={GT, LE, GTU, LEU}, u6=63 can not be allowed,
6240 since they are encoded by the assembler as {GE, LT, HS, LS} 64, which
6241 does not have a delay slot
6243 Assumed precondition: Second operand is either a register or a u6 value. */
6246 valid_brcc_with_delay_p (rtx
*operands
)
6248 if (optimize_size
&& GET_MODE (operands
[4]) == CC_Zmode
)
6250 return brcc_nolimm_operator (operands
[0], VOIDmode
);
6253 /* ??? Hack. This should no really be here. See PR32143. */
6255 arc_decl_anon_ns_mem_p (const_tree decl
)
6259 if (decl
== NULL_TREE
|| decl
== error_mark_node
)
6261 if (TREE_CODE (decl
) == NAMESPACE_DECL
6262 && DECL_NAME (decl
) == NULL_TREE
)
6264 /* Classes and namespaces inside anonymous namespaces have
6265 TREE_PUBLIC == 0, so we can shortcut the search. */
6266 else if (TYPE_P (decl
))
6267 return (TREE_PUBLIC (TYPE_NAME (decl
)) == 0);
6268 else if (TREE_CODE (decl
) == NAMESPACE_DECL
)
6269 return (TREE_PUBLIC (decl
) == 0);
6271 decl
= DECL_CONTEXT (decl
);
6275 /* Implement TARGET_IN_SMALL_DATA_P. Return true if it would be safe to
6276 access DECL using %gp_rel(...)($gp). */
6279 arc_in_small_data_p (const_tree decl
)
6283 if (TREE_CODE (decl
) == STRING_CST
|| TREE_CODE (decl
) == FUNCTION_DECL
)
6287 /* We don't yet generate small-data references for -mabicalls. See related
6288 -G handling in override_options. */
6289 if (TARGET_NO_SDATA_SET
)
6292 if (TREE_CODE (decl
) == VAR_DECL
&& DECL_SECTION_NAME (decl
) != 0)
6296 /* Reject anything that isn't in a known small-data section. */
6297 name
= DECL_SECTION_NAME (decl
);
6298 if (strcmp (name
, ".sdata") != 0 && strcmp (name
, ".sbss") != 0)
6301 /* If a symbol is defined externally, the assembler will use the
6302 usual -G rules when deciding how to implement macros. */
6303 if (!DECL_EXTERNAL (decl
))
6306 /* Only global variables go into sdata section for now. */
6309 /* Don't put constants into the small data section: we want them
6310 to be in ROM rather than RAM. */
6311 if (TREE_CODE (decl
) != VAR_DECL
)
6314 if (TREE_READONLY (decl
)
6315 && !TREE_SIDE_EFFECTS (decl
)
6316 && (!DECL_INITIAL (decl
) || TREE_CONSTANT (DECL_INITIAL (decl
))))
6319 /* TREE_PUBLIC might change after the first call, because of the patch
6321 if (default_binds_local_p_1 (decl
, 1)
6322 || arc_decl_anon_ns_mem_p (decl
))
6325 /* To ensure -mvolatile-cache works
6326 ld.di does not have a gp-relative variant. */
6327 if (TREE_THIS_VOLATILE (decl
))
6331 /* Disable sdata references to weak variables. */
6332 if (DECL_WEAK (decl
))
6335 size
= int_size_in_bytes (TREE_TYPE (decl
));
6337 /* if (AGGREGATE_TYPE_P (TREE_TYPE (decl))) */
6340 /* Allow only <=4B long data types into sdata. */
6341 return (size
> 0 && size
<= 4);
6344 /* Return true if X is a small data address that can be rewritten
6348 arc_rewrite_small_data_p (rtx x
)
6350 if (GET_CODE (x
) == CONST
)
6353 if (GET_CODE (x
) == PLUS
)
6355 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
6359 return (GET_CODE (x
) == SYMBOL_REF
6360 && SYMBOL_REF_SMALL_P(x
));
6363 /* A for_each_rtx callback, used by arc_rewrite_small_data. */
6366 arc_rewrite_small_data_1 (rtx
*loc
, void *data
)
6368 if (arc_rewrite_small_data_p (*loc
))
6372 gcc_assert (SDATA_BASE_REGNUM
== PIC_OFFSET_TABLE_REGNUM
);
6373 *loc
= gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, *loc
);
6377 if (GET_CODE (top
) == MEM
&& &XEXP (top
, 0) == loc
)
6379 else if (GET_CODE (top
) == MEM
6380 && GET_CODE (XEXP (top
, 0)) == PLUS
6381 && GET_CODE (XEXP (XEXP (top
, 0), 0)) == MULT
)
6382 *loc
= force_reg (Pmode
, *loc
);
6388 if (GET_CODE (*loc
) == PLUS
6389 && rtx_equal_p (XEXP (*loc
, 0), pic_offset_table_rtx
))
6395 /* If possible, rewrite OP so that it refers to small data using
6396 explicit relocations. */
6399 arc_rewrite_small_data (rtx op
)
6401 op
= copy_insn (op
);
6402 for_each_rtx (&op
, arc_rewrite_small_data_1
, &op
);
6406 /* A for_each_rtx callback for small_data_pattern. */
6409 small_data_pattern_1 (rtx
*loc
, void *data ATTRIBUTE_UNUSED
)
6411 if (GET_CODE (*loc
) == PLUS
6412 && rtx_equal_p (XEXP (*loc
, 0), pic_offset_table_rtx
))
6415 return arc_rewrite_small_data_p (*loc
);
6418 /* Return true if OP refers to small data symbols directly, not through
6422 small_data_pattern (rtx op
, machine_mode
)
6424 return (GET_CODE (op
) != SEQUENCE
6425 && for_each_rtx (&op
, small_data_pattern_1
, 0));
6428 /* Return true if OP is an acceptable memory operand for ARCompact
6429 16-bit gp-relative load instructions.
6430 op shd look like : [r26, symref@sda]
6431 i.e. (mem (plus (reg 26) (symref with smalldata flag set))
6433 /* volatile cache option still to be handled. */
6436 compact_sda_memory_operand (rtx op
, machine_mode mode
)
6441 /* Eliminate non-memory operations. */
6442 if (GET_CODE (op
) != MEM
)
6445 if (mode
== VOIDmode
)
6446 mode
= GET_MODE (op
);
6448 size
= GET_MODE_SIZE (mode
);
6450 /* dword operations really put out 2 instructions, so eliminate them. */
6451 if (size
> UNITS_PER_WORD
)
6454 /* Decode the address now. */
6455 addr
= XEXP (op
, 0);
6457 return LEGITIMATE_SMALL_DATA_ADDRESS_P (addr
);
6460 /* Implement ASM_OUTPUT_ALIGNED_DECL_LOCAL. */
6463 arc_asm_output_aligned_decl_local (FILE * stream
, tree decl
, const char * name
,
6464 unsigned HOST_WIDE_INT size
,
6465 unsigned HOST_WIDE_INT align
,
6466 unsigned HOST_WIDE_INT globalize_p
)
6468 int in_small_data
= arc_in_small_data_p (decl
);
6471 switch_to_section (get_named_section (NULL
, ".sbss", 0));
6472 /* named_section (0,".sbss",0); */
6474 switch_to_section (bss_section
);
6477 (*targetm
.asm_out
.globalize_label
) (stream
, name
);
6479 ASM_OUTPUT_ALIGN (stream
, floor_log2 ((align
) / BITS_PER_UNIT
));
6480 ASM_OUTPUT_TYPE_DIRECTIVE (stream
, name
, "object");
6481 ASM_OUTPUT_SIZE_DIRECTIVE (stream
, name
, size
);
6482 ASM_OUTPUT_LABEL (stream
, name
);
6485 ASM_OUTPUT_SKIP (stream
, size
);
6521 /* SIMD builtins support. */
6522 enum simd_insn_args_type
{
6545 struct builtin_description
6547 enum simd_insn_args_type args_type
;
6548 const enum insn_code icode
;
6549 const char * const name
;
6550 const enum arc_builtins code
;
6553 static const struct builtin_description arc_simd_builtin_desc_list
[] =
6555 /* VVV builtins go first. */
6556 #define SIMD_BUILTIN(type, code, string, builtin) \
6557 { type,CODE_FOR_##code, "__builtin_arc_" string, \
6558 ARC_SIMD_BUILTIN_##builtin },
6560 SIMD_BUILTIN (Va_Vb_Vc
, vaddaw_insn
, "vaddaw", VADDAW
)
6561 SIMD_BUILTIN (Va_Vb_Vc
, vaddw_insn
, "vaddw", VADDW
)
6562 SIMD_BUILTIN (Va_Vb_Vc
, vavb_insn
, "vavb", VAVB
)
6563 SIMD_BUILTIN (Va_Vb_Vc
, vavrb_insn
, "vavrb", VAVRB
)
6564 SIMD_BUILTIN (Va_Vb_Vc
, vdifaw_insn
, "vdifaw", VDIFAW
)
6565 SIMD_BUILTIN (Va_Vb_Vc
, vdifw_insn
, "vdifw", VDIFW
)
6566 SIMD_BUILTIN (Va_Vb_Vc
, vmaxaw_insn
, "vmaxaw", VMAXAW
)
6567 SIMD_BUILTIN (Va_Vb_Vc
, vmaxw_insn
, "vmaxw", VMAXW
)
6568 SIMD_BUILTIN (Va_Vb_Vc
, vminaw_insn
, "vminaw", VMINAW
)
6569 SIMD_BUILTIN (Va_Vb_Vc
, vminw_insn
, "vminw", VMINW
)
6570 SIMD_BUILTIN (Va_Vb_Vc
, vmulaw_insn
, "vmulaw", VMULAW
)
6571 SIMD_BUILTIN (Va_Vb_Vc
, vmulfaw_insn
, "vmulfaw", VMULFAW
)
6572 SIMD_BUILTIN (Va_Vb_Vc
, vmulfw_insn
, "vmulfw", VMULFW
)
6573 SIMD_BUILTIN (Va_Vb_Vc
, vmulw_insn
, "vmulw", VMULW
)
6574 SIMD_BUILTIN (Va_Vb_Vc
, vsubaw_insn
, "vsubaw", VSUBAW
)
6575 SIMD_BUILTIN (Va_Vb_Vc
, vsubw_insn
, "vsubw", VSUBW
)
6576 SIMD_BUILTIN (Va_Vb_Vc
, vsummw_insn
, "vsummw", VSUMMW
)
6577 SIMD_BUILTIN (Va_Vb_Vc
, vand_insn
, "vand", VAND
)
6578 SIMD_BUILTIN (Va_Vb_Vc
, vandaw_insn
, "vandaw", VANDAW
)
6579 SIMD_BUILTIN (Va_Vb_Vc
, vbic_insn
, "vbic", VBIC
)
6580 SIMD_BUILTIN (Va_Vb_Vc
, vbicaw_insn
, "vbicaw", VBICAW
)
6581 SIMD_BUILTIN (Va_Vb_Vc
, vor_insn
, "vor", VOR
)
6582 SIMD_BUILTIN (Va_Vb_Vc
, vxor_insn
, "vxor", VXOR
)
6583 SIMD_BUILTIN (Va_Vb_Vc
, vxoraw_insn
, "vxoraw", VXORAW
)
6584 SIMD_BUILTIN (Va_Vb_Vc
, veqw_insn
, "veqw", VEQW
)
6585 SIMD_BUILTIN (Va_Vb_Vc
, vlew_insn
, "vlew", VLEW
)
6586 SIMD_BUILTIN (Va_Vb_Vc
, vltw_insn
, "vltw", VLTW
)
6587 SIMD_BUILTIN (Va_Vb_Vc
, vnew_insn
, "vnew", VNEW
)
6588 SIMD_BUILTIN (Va_Vb_Vc
, vmr1aw_insn
, "vmr1aw", VMR1AW
)
6589 SIMD_BUILTIN (Va_Vb_Vc
, vmr1w_insn
, "vmr1w", VMR1W
)
6590 SIMD_BUILTIN (Va_Vb_Vc
, vmr2aw_insn
, "vmr2aw", VMR2AW
)
6591 SIMD_BUILTIN (Va_Vb_Vc
, vmr2w_insn
, "vmr2w", VMR2W
)
6592 SIMD_BUILTIN (Va_Vb_Vc
, vmr3aw_insn
, "vmr3aw", VMR3AW
)
6593 SIMD_BUILTIN (Va_Vb_Vc
, vmr3w_insn
, "vmr3w", VMR3W
)
6594 SIMD_BUILTIN (Va_Vb_Vc
, vmr4aw_insn
, "vmr4aw", VMR4AW
)
6595 SIMD_BUILTIN (Va_Vb_Vc
, vmr4w_insn
, "vmr4w", VMR4W
)
6596 SIMD_BUILTIN (Va_Vb_Vc
, vmr5aw_insn
, "vmr5aw", VMR5AW
)
6597 SIMD_BUILTIN (Va_Vb_Vc
, vmr5w_insn
, "vmr5w", VMR5W
)
6598 SIMD_BUILTIN (Va_Vb_Vc
, vmr6aw_insn
, "vmr6aw", VMR6AW
)
6599 SIMD_BUILTIN (Va_Vb_Vc
, vmr6w_insn
, "vmr6w", VMR6W
)
6600 SIMD_BUILTIN (Va_Vb_Vc
, vmr7aw_insn
, "vmr7aw", VMR7AW
)
6601 SIMD_BUILTIN (Va_Vb_Vc
, vmr7w_insn
, "vmr7w", VMR7W
)
6602 SIMD_BUILTIN (Va_Vb_Vc
, vmrb_insn
, "vmrb", VMRB
)
6603 SIMD_BUILTIN (Va_Vb_Vc
, vh264f_insn
, "vh264f", VH264F
)
6604 SIMD_BUILTIN (Va_Vb_Vc
, vh264ft_insn
, "vh264ft", VH264FT
)
6605 SIMD_BUILTIN (Va_Vb_Vc
, vh264fw_insn
, "vh264fw", VH264FW
)
6606 SIMD_BUILTIN (Va_Vb_Vc
, vvc1f_insn
, "vvc1f", VVC1F
)
6607 SIMD_BUILTIN (Va_Vb_Vc
, vvc1ft_insn
, "vvc1ft", VVC1FT
)
6609 SIMD_BUILTIN (Va_Vb_rlimm
, vbaddw_insn
, "vbaddw", VBADDW
)
6610 SIMD_BUILTIN (Va_Vb_rlimm
, vbmaxw_insn
, "vbmaxw", VBMAXW
)
6611 SIMD_BUILTIN (Va_Vb_rlimm
, vbminw_insn
, "vbminw", VBMINW
)
6612 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulaw_insn
, "vbmulaw", VBMULAW
)
6613 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulfw_insn
, "vbmulfw", VBMULFW
)
6614 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulw_insn
, "vbmulw", VBMULW
)
6615 SIMD_BUILTIN (Va_Vb_rlimm
, vbrsubw_insn
, "vbrsubw", VBRSUBW
)
6616 SIMD_BUILTIN (Va_Vb_rlimm
, vbsubw_insn
, "vbsubw", VBSUBW
)
6618 /* Va, Vb, Ic instructions. */
6619 SIMD_BUILTIN (Va_Vb_Ic
, vasrw_insn
, "vasrw", VASRW
)
6620 SIMD_BUILTIN (Va_Vb_Ic
, vsr8_insn
, "vsr8", VSR8
)
6621 SIMD_BUILTIN (Va_Vb_Ic
, vsr8aw_insn
, "vsr8aw", VSR8AW
)
6623 /* Va, Vb, u6 instructions. */
6624 SIMD_BUILTIN (Va_Vb_u6
, vasrrwi_insn
, "vasrrwi", VASRRWi
)
6625 SIMD_BUILTIN (Va_Vb_u6
, vasrsrwi_insn
, "vasrsrwi", VASRSRWi
)
6626 SIMD_BUILTIN (Va_Vb_u6
, vasrwi_insn
, "vasrwi", VASRWi
)
6627 SIMD_BUILTIN (Va_Vb_u6
, vasrpwbi_insn
, "vasrpwbi", VASRPWBi
)
6628 SIMD_BUILTIN (Va_Vb_u6
, vasrrpwbi_insn
,"vasrrpwbi", VASRRPWBi
)
6629 SIMD_BUILTIN (Va_Vb_u6
, vsr8awi_insn
, "vsr8awi", VSR8AWi
)
6630 SIMD_BUILTIN (Va_Vb_u6
, vsr8i_insn
, "vsr8i", VSR8i
)
6632 /* Va, Vb, u8 (simm) instructions. */
6633 SIMD_BUILTIN (Va_Vb_u8
, vmvaw_insn
, "vmvaw", VMVAW
)
6634 SIMD_BUILTIN (Va_Vb_u8
, vmvw_insn
, "vmvw", VMVW
)
6635 SIMD_BUILTIN (Va_Vb_u8
, vmvzw_insn
, "vmvzw", VMVZW
)
6636 SIMD_BUILTIN (Va_Vb_u8
, vd6tapf_insn
, "vd6tapf", VD6TAPF
)
6638 /* Va, rlimm, u8 (simm) instructions. */
6639 SIMD_BUILTIN (Va_rlimm_u8
, vmovaw_insn
, "vmovaw", VMOVAW
)
6640 SIMD_BUILTIN (Va_rlimm_u8
, vmovw_insn
, "vmovw", VMOVW
)
6641 SIMD_BUILTIN (Va_rlimm_u8
, vmovzw_insn
, "vmovzw", VMOVZW
)
6643 /* Va, Vb instructions. */
6644 SIMD_BUILTIN (Va_Vb
, vabsaw_insn
, "vabsaw", VABSAW
)
6645 SIMD_BUILTIN (Va_Vb
, vabsw_insn
, "vabsw", VABSW
)
6646 SIMD_BUILTIN (Va_Vb
, vaddsuw_insn
, "vaddsuw", VADDSUW
)
6647 SIMD_BUILTIN (Va_Vb
, vsignw_insn
, "vsignw", VSIGNW
)
6648 SIMD_BUILTIN (Va_Vb
, vexch1_insn
, "vexch1", VEXCH1
)
6649 SIMD_BUILTIN (Va_Vb
, vexch2_insn
, "vexch2", VEXCH2
)
6650 SIMD_BUILTIN (Va_Vb
, vexch4_insn
, "vexch4", VEXCH4
)
6651 SIMD_BUILTIN (Va_Vb
, vupbaw_insn
, "vupbaw", VUPBAW
)
6652 SIMD_BUILTIN (Va_Vb
, vupbw_insn
, "vupbw", VUPBW
)
6653 SIMD_BUILTIN (Va_Vb
, vupsbaw_insn
, "vupsbaw", VUPSBAW
)
6654 SIMD_BUILTIN (Va_Vb
, vupsbw_insn
, "vupsbw", VUPSBW
)
6656 /* DIb, rlimm, rlimm instructions. */
6657 SIMD_BUILTIN (Da_rlimm_rlimm
, vdirun_insn
, "vdirun", VDIRUN
)
6658 SIMD_BUILTIN (Da_rlimm_rlimm
, vdorun_insn
, "vdorun", VDORUN
)
6660 /* DIb, limm, rlimm instructions. */
6661 SIMD_BUILTIN (Da_u3_rlimm
, vdiwr_insn
, "vdiwr", VDIWR
)
6662 SIMD_BUILTIN (Da_u3_rlimm
, vdowr_insn
, "vdowr", VDOWR
)
6664 /* rlimm instructions. */
6665 SIMD_BUILTIN (void_rlimm
, vrec_insn
, "vrec", VREC
)
6666 SIMD_BUILTIN (void_rlimm
, vrun_insn
, "vrun", VRUN
)
6667 SIMD_BUILTIN (void_rlimm
, vrecrun_insn
, "vrecrun", VRECRUN
)
6668 SIMD_BUILTIN (void_rlimm
, vendrec_insn
, "vendrec", VENDREC
)
6670 /* Va, [Ib,u8] instructions. */
6671 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32wh_insn
, "vld32wh", VLD32WH
)
6672 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32wl_insn
, "vld32wl", VLD32WL
)
6673 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld64_insn
, "vld64", VLD64
)
6674 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32_insn
, "vld32", VLD32
)
6676 SIMD_BUILTIN (Va_Ib_u8
, vld64w_insn
, "vld64w", VLD64W
)
6677 SIMD_BUILTIN (Va_Ib_u8
, vld128_insn
, "vld128", VLD128
)
6678 SIMD_BUILTIN (void_Va_Ib_u8
, vst128_insn
, "vst128", VST128
)
6679 SIMD_BUILTIN (void_Va_Ib_u8
, vst64_insn
, "vst64", VST64
)
6681 /* Va, [Ib, u8] instructions. */
6682 SIMD_BUILTIN (void_Va_u3_Ib_u8
, vst16_n_insn
, "vst16_n", VST16_N
)
6683 SIMD_BUILTIN (void_Va_u3_Ib_u8
, vst32_n_insn
, "vst32_n", VST32_N
)
6685 SIMD_BUILTIN (void_u6
, vinti_insn
, "vinti", VINTI
)
6689 arc_init_simd_builtins (void)
6692 tree endlink
= void_list_node
;
6693 tree V8HI_type_node
= build_vector_type_for_mode (intHI_type_node
, V8HImode
);
6695 tree v8hi_ftype_v8hi_v8hi
6696 = build_function_type (V8HI_type_node
,
6697 tree_cons (NULL_TREE
, V8HI_type_node
,
6698 tree_cons (NULL_TREE
, V8HI_type_node
,
6700 tree v8hi_ftype_v8hi_int
6701 = build_function_type (V8HI_type_node
,
6702 tree_cons (NULL_TREE
, V8HI_type_node
,
6703 tree_cons (NULL_TREE
, integer_type_node
,
6706 tree v8hi_ftype_v8hi_int_int
6707 = build_function_type (V8HI_type_node
,
6708 tree_cons (NULL_TREE
, V8HI_type_node
,
6709 tree_cons (NULL_TREE
, integer_type_node
,
6710 tree_cons (NULL_TREE
,
6714 tree void_ftype_v8hi_int_int
6715 = build_function_type (void_type_node
,
6716 tree_cons (NULL_TREE
, V8HI_type_node
,
6717 tree_cons (NULL_TREE
, integer_type_node
,
6718 tree_cons (NULL_TREE
,
6722 tree void_ftype_v8hi_int_int_int
6723 = (build_function_type
6725 tree_cons (NULL_TREE
, V8HI_type_node
,
6726 tree_cons (NULL_TREE
, integer_type_node
,
6727 tree_cons (NULL_TREE
, integer_type_node
,
6728 tree_cons (NULL_TREE
,
6732 tree v8hi_ftype_int_int
6733 = build_function_type (V8HI_type_node
,
6734 tree_cons (NULL_TREE
, integer_type_node
,
6735 tree_cons (NULL_TREE
, integer_type_node
,
6738 tree void_ftype_int_int
6739 = build_function_type (void_type_node
,
6740 tree_cons (NULL_TREE
, integer_type_node
,
6741 tree_cons (NULL_TREE
, integer_type_node
,
6745 = build_function_type (void_type_node
,
6746 tree_cons (NULL_TREE
, integer_type_node
, endlink
));
6748 tree v8hi_ftype_v8hi
6749 = build_function_type (V8HI_type_node
, tree_cons (NULL_TREE
, V8HI_type_node
,
6752 /* These asserts have been introduced to ensure that the order of builtins
6753 does not get messed up, else the initialization goes wrong. */
6754 gcc_assert (arc_simd_builtin_desc_list
[0].args_type
== Va_Vb_Vc
);
6755 for (i
=0; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Vc
; i
++)
6756 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6757 v8hi_ftype_v8hi_v8hi
, arc_simd_builtin_desc_list
[i
].code
);
6759 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_rlimm
);
6760 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_rlimm
; i
++)
6761 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6762 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6764 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic
);
6765 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic
; i
++)
6766 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6767 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6769 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u6
);
6770 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u6
; i
++)
6771 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6772 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6774 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u8
);
6775 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u8
; i
++)
6776 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6777 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6779 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_rlimm_u8
);
6780 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_rlimm_u8
; i
++)
6781 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6782 v8hi_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6784 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb
);
6785 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb
; i
++)
6786 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6787 v8hi_ftype_v8hi
, arc_simd_builtin_desc_list
[i
].code
);
6789 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Da_rlimm_rlimm
);
6790 for (; arc_simd_builtin_desc_list
[i
].args_type
== Da_rlimm_rlimm
; i
++)
6791 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6792 void_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6794 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Da_u3_rlimm
);
6795 for (; arc_simd_builtin_desc_list
[i
].args_type
== Da_u3_rlimm
; i
++)
6796 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6797 void_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6799 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_rlimm
);
6800 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_rlimm
; i
++)
6801 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6802 void_ftype_int
, arc_simd_builtin_desc_list
[i
].code
);
6804 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic_u8
);
6805 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic_u8
; i
++)
6806 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6807 v8hi_ftype_v8hi_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6809 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Ib_u8
);
6810 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Ib_u8
; i
++)
6811 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6812 v8hi_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6814 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_Va_Ib_u8
);
6815 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_Va_Ib_u8
; i
++)
6816 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6817 void_ftype_v8hi_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6819 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_Va_u3_Ib_u8
);
6820 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_Va_u3_Ib_u8
; i
++)
6821 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6822 void_ftype_v8hi_int_int_int
,
6823 arc_simd_builtin_desc_list
[i
].code
);
6825 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_u6
);
6826 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_u6
; i
++)
6827 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6828 void_ftype_int
, arc_simd_builtin_desc_list
[i
].code
);
6830 gcc_assert(i
== ARRAY_SIZE (arc_simd_builtin_desc_list
));
6833 /* Helper function of arc_expand_builtin; has the same parameters,
6834 except that EXP is now known to be a call to a simd builtin. */
6837 arc_expand_simd_builtin (tree exp
,
6839 rtx subtarget ATTRIBUTE_UNUSED
,
6840 machine_mode mode ATTRIBUTE_UNUSED
,
6841 int ignore ATTRIBUTE_UNUSED
)
6843 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
6855 int fcode
= DECL_FUNCTION_CODE (fndecl
);
6862 const struct builtin_description
* d
;
6864 for (i
= 0, d
= arc_simd_builtin_desc_list
;
6865 i
< ARRAY_SIZE (arc_simd_builtin_desc_list
); i
++, d
++)
6866 if (d
->code
== (const enum arc_builtins
) fcode
)
6869 /* We must get an entry here. */
6870 gcc_assert (i
< ARRAY_SIZE (arc_simd_builtin_desc_list
));
6872 switch (d
->args_type
)
6876 arg0
= CALL_EXPR_ARG (exp
, 0);
6877 arg1
= CALL_EXPR_ARG (exp
, 1);
6878 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6879 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6881 target
= gen_reg_rtx (V8HImode
);
6882 mode0
= insn_data
[icode
].operand
[1].mode
;
6883 mode1
= insn_data
[icode
].operand
[2].mode
;
6885 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6886 op0
= copy_to_mode_reg (mode0
, op0
);
6888 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6889 op1
= copy_to_mode_reg (mode1
, op1
);
6891 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
6901 arg0
= CALL_EXPR_ARG (exp
, 0);
6902 arg1
= CALL_EXPR_ARG (exp
, 1);
6903 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6904 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6906 target
= gen_reg_rtx (V8HImode
);
6907 mode0
= insn_data
[icode
].operand
[1].mode
;
6908 mode1
= insn_data
[icode
].operand
[2].mode
;
6910 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6911 op0
= copy_to_mode_reg (mode0
, op0
);
6913 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
)
6914 || (d
->args_type
== Va_Vb_u6
&& !UNSIGNED_INT6 (INTVAL (op1
)))
6915 || (d
->args_type
== Va_Vb_u8
&& !UNSIGNED_INT8 (INTVAL (op1
))))
6916 error ("operand 2 of %s instruction should be an unsigned %d-bit value",
6918 (d
->args_type
== Va_Vb_u6
)? 6: 8);
6920 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
6929 arg0
= CALL_EXPR_ARG (exp
, 0);
6930 arg1
= CALL_EXPR_ARG (exp
, 1);
6931 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6932 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6934 target
= gen_reg_rtx (V8HImode
);
6935 mode0
= insn_data
[icode
].operand
[1].mode
;
6936 mode1
= insn_data
[icode
].operand
[2].mode
;
6938 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6939 op0
= copy_to_mode_reg (mode0
, op0
);
6941 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6942 || !(UNSIGNED_INT8 (INTVAL (op1
))))
6943 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
6946 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
6955 arg0
= CALL_EXPR_ARG (exp
, 0);
6956 arg1
= CALL_EXPR_ARG (exp
, 1);
6957 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6958 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6959 op2
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
);
6961 target
= gen_reg_rtx (V8HImode
);
6962 mode0
= insn_data
[icode
].operand
[1].mode
;
6963 mode1
= insn_data
[icode
].operand
[2].mode
;
6965 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6966 op0
= copy_to_mode_reg (mode0
, op0
);
6968 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6969 || !(UNSIGNED_INT3 (INTVAL (op1
))))
6970 error ("operand 2 of %s instruction should be an unsigned 3-bit value (I0-I7)",
6973 pat
= GEN_FCN (icode
) (target
, op0
, op1
, op2
);
6982 arg0
= CALL_EXPR_ARG (exp
, 0);
6983 arg1
= CALL_EXPR_ARG (exp
, 1);
6984 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6985 op1
= expand_expr (arg1
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6987 target
= gen_reg_rtx (V8HImode
);
6988 mode0
= insn_data
[icode
].operand
[1].mode
;
6989 mode1
= insn_data
[icode
].operand
[2].mode
;
6991 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6992 op0
= copy_to_mode_reg (mode0
, op0
);
6994 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6995 op1
= copy_to_mode_reg (mode1
, op1
);
6997 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
7006 arg0
= CALL_EXPR_ARG (exp
, 0);
7007 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
7009 target
= gen_reg_rtx (V8HImode
);
7010 mode0
= insn_data
[icode
].operand
[1].mode
;
7012 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
7013 op0
= copy_to_mode_reg (mode0
, op0
);
7015 pat
= GEN_FCN (icode
) (target
, op0
);
7022 case Da_rlimm_rlimm
:
7024 arg0
= CALL_EXPR_ARG (exp
, 0);
7025 arg1
= CALL_EXPR_ARG (exp
, 1);
7026 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7027 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7030 if (icode
== CODE_FOR_vdirun_insn
)
7031 target
= gen_rtx_REG (SImode
, 131);
7032 else if (icode
== CODE_FOR_vdorun_insn
)
7033 target
= gen_rtx_REG (SImode
, 139);
7037 mode0
= insn_data
[icode
].operand
[1].mode
;
7038 mode1
= insn_data
[icode
].operand
[2].mode
;
7040 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
7041 op0
= copy_to_mode_reg (mode0
, op0
);
7043 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7044 op1
= copy_to_mode_reg (mode1
, op1
);
7047 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
7056 arg0
= CALL_EXPR_ARG (exp
, 0);
7057 arg1
= CALL_EXPR_ARG (exp
, 1);
7058 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7059 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7062 if (! (GET_CODE (op0
) == CONST_INT
)
7063 || !(UNSIGNED_INT3 (INTVAL (op0
))))
7064 error ("operand 1 of %s instruction should be an unsigned 3-bit value (DR0-DR7)",
7067 mode1
= insn_data
[icode
].operand
[1].mode
;
7069 if (icode
== CODE_FOR_vdiwr_insn
)
7070 target
= gen_rtx_REG (SImode
,
7071 ARC_FIRST_SIMD_DMA_CONFIG_IN_REG
+ INTVAL (op0
));
7072 else if (icode
== CODE_FOR_vdowr_insn
)
7073 target
= gen_rtx_REG (SImode
,
7074 ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG
+ INTVAL (op0
));
7078 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7079 op1
= copy_to_mode_reg (mode1
, op1
);
7081 pat
= GEN_FCN (icode
) (target
, op1
);
7090 arg0
= CALL_EXPR_ARG (exp
, 0);
7094 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7095 mode0
= insn_data
[icode
].operand
[0].mode
;
7097 /* op0 should be u6. */
7098 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
)
7099 || !(UNSIGNED_INT6 (INTVAL (op0
))))
7100 error ("operand of %s instruction should be an unsigned 6-bit value",
7103 pat
= GEN_FCN (icode
) (op0
);
7112 arg0
= CALL_EXPR_ARG (exp
, 0);
7116 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7117 mode0
= insn_data
[icode
].operand
[0].mode
;
7119 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
7120 op0
= copy_to_mode_reg (mode0
, op0
);
7122 pat
= GEN_FCN (icode
) (op0
);
7133 arg0
= CALL_EXPR_ARG (exp
, 0); /* source vreg */
7134 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7135 arg2
= CALL_EXPR_ARG (exp
, 2); /* u8 */
7137 src_vreg
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
7138 op0
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* [I]0-7 */
7139 op1
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7140 op2
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7142 /* target <- src vreg */
7143 emit_insn (gen_move_insn (target
, src_vreg
));
7145 /* target <- vec_concat: target, mem(Ib, u8) */
7146 mode0
= insn_data
[icode
].operand
[3].mode
;
7147 mode1
= insn_data
[icode
].operand
[1].mode
;
7149 if ( (!(*insn_data
[icode
].operand
[3].predicate
) (op0
, mode0
))
7150 || !(UNSIGNED_INT3 (INTVAL (op0
))))
7151 error ("operand 1 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7154 if ( (!(*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
7155 || !(UNSIGNED_INT8 (INTVAL (op1
))))
7156 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
7159 pat
= GEN_FCN (icode
) (target
, op1
, op2
, op0
);
7169 arg0
= CALL_EXPR_ARG (exp
, 0); /* src vreg */
7170 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7171 arg2
= CALL_EXPR_ARG (exp
, 2); /* u8 */
7173 op0
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7174 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* I[0-7] */
7175 op2
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7176 op3
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
); /* Vdest */
7178 mode0
= insn_data
[icode
].operand
[0].mode
;
7179 mode1
= insn_data
[icode
].operand
[1].mode
;
7180 mode2
= insn_data
[icode
].operand
[2].mode
;
7181 mode3
= insn_data
[icode
].operand
[3].mode
;
7183 if ( (!(*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
7184 || !(UNSIGNED_INT3 (INTVAL (op1
))))
7185 error ("operand 2 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7188 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op2
, mode2
))
7189 || !(UNSIGNED_INT8 (INTVAL (op2
))))
7190 error ("operand 3 of %s instruction should be an unsigned 8-bit value",
7193 if (!(*insn_data
[icode
].operand
[3].predicate
) (op3
, mode3
))
7194 op3
= copy_to_mode_reg (mode3
, op3
);
7196 pat
= GEN_FCN (icode
) (op0
, op1
, op2
, op3
);
7205 arg0
= CALL_EXPR_ARG (exp
, 0); /* dest vreg */
7206 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7208 op0
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7209 op1
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* I[0-7] */
7210 op2
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7212 /* target <- src vreg */
7213 target
= gen_reg_rtx (V8HImode
);
7215 /* target <- vec_concat: target, mem(Ib, u8) */
7216 mode0
= insn_data
[icode
].operand
[1].mode
;
7217 mode1
= insn_data
[icode
].operand
[2].mode
;
7218 mode2
= insn_data
[icode
].operand
[3].mode
;
7220 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7221 || !(UNSIGNED_INT3 (INTVAL (op1
))))
7222 error ("operand 1 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7225 if ( (!(*insn_data
[icode
].operand
[3].predicate
) (op2
, mode2
))
7226 || !(UNSIGNED_INT8 (INTVAL (op2
))))
7227 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
7230 pat
= GEN_FCN (icode
) (target
, op0
, op1
, op2
);
7237 case void_Va_u3_Ib_u8
:
7239 arg0
= CALL_EXPR_ARG (exp
, 0); /* source vreg */
7240 arg1
= CALL_EXPR_ARG (exp
, 1); /* u3 */
7241 arg2
= CALL_EXPR_ARG (exp
, 2); /* [I]0-7 */
7242 arg3
= CALL_EXPR_ARG (exp
, 3); /* u8 */
7244 op0
= expand_expr (arg3
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7245 op1
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR */
7246 op2
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* [I]0-7 */
7247 op3
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);/* vreg to be stored */
7248 op4
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* vreg 0-7 subreg no. */
7250 mode0
= insn_data
[icode
].operand
[0].mode
;
7251 mode2
= insn_data
[icode
].operand
[2].mode
;
7252 mode3
= insn_data
[icode
].operand
[3].mode
;
7253 mode4
= insn_data
[icode
].operand
[4].mode
;
7255 /* Do some correctness checks for the operands. */
7256 if ( (!(*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
7257 || !(UNSIGNED_INT8 (INTVAL (op0
))))
7258 error ("operand 4 of %s instruction should be an unsigned 8-bit value (0-255)",
7261 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op2
, mode2
))
7262 || !(UNSIGNED_INT3 (INTVAL (op2
))))
7263 error ("operand 3 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7266 if (!(*insn_data
[icode
].operand
[3].predicate
) (op3
, mode3
))
7267 op3
= copy_to_mode_reg (mode3
, op3
);
7269 if ( (!(*insn_data
[icode
].operand
[4].predicate
) (op4
, mode4
))
7270 || !(UNSIGNED_INT3 (INTVAL (op4
))))
7271 error ("operand 2 of %s instruction should be an unsigned 3-bit value (subreg 0-7)",
7273 else if (icode
== CODE_FOR_vst32_n_insn
7274 && ((INTVAL(op4
) % 2 ) != 0))
7275 error ("operand 2 of %s instruction should be an even 3-bit value (subreg 0,2,4,6)",
7278 pat
= GEN_FCN (icode
) (op0
, op1
, op2
, op3
, op4
);
7292 arc_preserve_reload_p (rtx in
)
7294 return (GET_CODE (in
) == PLUS
7295 && RTX_OK_FOR_BASE_P (XEXP (in
, 0), true)
7296 && CONST_INT_P (XEXP (in
, 1))
7297 && !((INTVAL (XEXP (in
, 1)) & 511)));
7301 arc_register_move_cost (machine_mode
,
7302 enum reg_class from_class
, enum reg_class to_class
)
7304 /* The ARC600 has no bypass for extension registers, hence a nop might be
7305 needed to be inserted after a write so that reads are safe. */
7308 if (to_class
== MPY_WRITABLE_CORE_REGS
)
7310 /* Instructions modifying LP_COUNT need 4 additional cycles before
7311 the register will actually contain the value. */
7312 else if (to_class
== LPCOUNT_REG
)
7314 else if (to_class
== WRITABLE_CORE_REGS
)
7318 /* The ARC700 stalls for 3 cycles when *reading* from lp_count. */
7320 && (from_class
== LPCOUNT_REG
|| from_class
== ALL_CORE_REGS
7321 || from_class
== WRITABLE_CORE_REGS
))
7324 /* Force an attempt to 'mov Dy,Dx' to spill. */
7325 if (TARGET_ARC700
&& TARGET_DPFP
7326 && from_class
== DOUBLE_REGS
&& to_class
== DOUBLE_REGS
)
7332 /* Emit code for an addsi3 instruction with OPERANDS.
7333 COND_P indicates if this will use conditional execution.
7334 Return the length of the instruction.
7335 If OUTPUT_P is false, don't actually output the instruction, just return
7338 arc_output_addsi (rtx
*operands
, bool cond_p
, bool output_p
)
7342 int match
= operands_match_p (operands
[0], operands
[1]);
7343 int match2
= operands_match_p (operands
[0], operands
[2]);
7344 int intval
= (REG_P (operands
[2]) ? 1
7345 : CONST_INT_P (operands
[2]) ? INTVAL (operands
[2]) : 0xbadc057);
7346 int neg_intval
= -intval
;
7347 int short_0
= satisfies_constraint_Rcq (operands
[0]);
7348 int short_p
= (!cond_p
&& short_0
&& satisfies_constraint_Rcq (operands
[1]));
7351 #define ADDSI_OUTPUT1(FORMAT) do {\
7353 output_asm_insn (FORMAT, operands);\
7356 #define ADDSI_OUTPUT(LIST) do {\
7359 ADDSI_OUTPUT1 (format);\
7363 /* First try to emit a 16 bit insn. */
7366 /* If we are actually about to output this insn, don't try a 16 bit
7367 variant if we already decided that we don't want that
7368 (I.e. we upsized this insn to align some following insn.)
7369 E.g. add_s r0,sp,70 is 16 bit, but add r0,sp,70 requires a LIMM -
7370 but add1 r0,sp,35 doesn't. */
7371 && (!output_p
|| (get_attr_length (current_output_insn
) & 2)))
7374 && (REG_P (operands
[2])
7375 ? (match
|| satisfies_constraint_Rcq (operands
[2]))
7376 : (unsigned) intval
<= (match
? 127 : 7)))
7377 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7378 if (short_0
&& REG_P (operands
[1]) && match2
)
7379 ADDSI_OUTPUT1 ("add%? %0,%2,%1");
7380 if ((short_0
|| REGNO (operands
[0]) == STACK_POINTER_REGNUM
)
7381 && REGNO (operands
[1]) == STACK_POINTER_REGNUM
&& !(intval
& ~124))
7382 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7384 if ((short_p
&& (unsigned) neg_intval
<= (match
? 31 : 7))
7385 || (REGNO (operands
[0]) == STACK_POINTER_REGNUM
7386 && match
&& !(neg_intval
& ~124)))
7387 ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
7390 /* Now try to emit a 32 bit insn without long immediate. */
7392 if (!match
&& match2
&& REG_P (operands
[1]))
7393 ADDSI_OUTPUT1 ("add%? %0,%2,%1");
7394 if (match
|| !cond_p
)
7396 int limit
= (match
&& !cond_p
) ? 0x7ff : 0x3f;
7397 int range_factor
= neg_intval
& intval
;
7400 if (intval
== -1 << 31)
7401 ADDSI_OUTPUT1 ("bxor%? %0,%1,31");
7403 /* If we can use a straight add / sub instead of a {add,sub}[123] of
7404 same size, do, so - the insn latency is lower. */
7405 /* -0x800 is a 12-bit constant for add /add3 / sub / sub3, but
7407 if ((intval
>= 0 && intval
<= limit
)
7408 || (intval
== -0x800 && limit
== 0x7ff))
7409 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7410 else if ((intval
< 0 && neg_intval
<= limit
)
7411 || (intval
== 0x800 && limit
== 0x7ff))
7412 ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
7413 shift
= range_factor
>= 8 ? 3 : (range_factor
>> 1);
7414 gcc_assert (shift
== 0 || shift
== 1 || shift
== 2 || shift
== 3);
7415 gcc_assert ((((1 << shift
) - 1) & intval
) == 0);
7416 if (((intval
< 0 && intval
!= -0x4000)
7417 /* sub[123] is slower than add_s / sub, only use it if it
7418 avoids a long immediate. */
7419 && neg_intval
<= limit
<< shift
)
7420 || (intval
== 0x4000 && limit
== 0x7ff))
7421 ADDSI_OUTPUT ((format
, "sub%d%%? %%0,%%1,%d",
7422 shift
, neg_intval
>> shift
));
7423 else if ((intval
>= 0 && intval
<= limit
<< shift
)
7424 || (intval
== -0x4000 && limit
== 0x7ff))
7425 ADDSI_OUTPUT ((format
, "add%d%%? %%0,%%1,%d", shift
, intval
>> shift
));
7427 /* Try to emit a 16 bit opcode with long immediate. */
7429 if (short_p
&& match
)
7430 ADDSI_OUTPUT1 ("add%? %0,%1,%S2");
7432 /* We have to use a 32 bit opcode, and with a long immediate. */
7434 ADDSI_OUTPUT1 (intval
< 0 ? "sub%? %0,%1,%n2" : "add%? %0,%1,%S2");
7437 /* Emit code for an commutative_cond_exec instruction with OPERANDS.
7438 Return the length of the instruction.
7439 If OUTPUT_P is false, don't actually output the instruction, just return
7442 arc_output_commutative_cond_exec (rtx
*operands
, bool output_p
)
7444 enum rtx_code commutative_op
= GET_CODE (operands
[3]);
7445 const char *pat
= NULL
;
7447 /* Canonical rtl should not have a constant in the first operand position. */
7448 gcc_assert (!CONSTANT_P (operands
[1]));
7450 switch (commutative_op
)
7453 if (satisfies_constraint_C1p (operands
[2]))
7454 pat
= "bmsk%? %0,%1,%Z2";
7455 else if (satisfies_constraint_Ccp (operands
[2]))
7456 pat
= "bclr%? %0,%1,%M2";
7457 else if (satisfies_constraint_CnL (operands
[2]))
7458 pat
= "bic%? %0,%1,%n2-1";
7461 if (satisfies_constraint_C0p (operands
[2]))
7462 pat
= "bset%? %0,%1,%z2";
7465 if (satisfies_constraint_C0p (operands
[2]))
7466 pat
= "bxor%? %0,%1,%z2";
7469 return arc_output_addsi (operands
, true, output_p
);
7473 output_asm_insn (pat
? pat
: "%O3.%d5 %0,%1,%2", operands
);
7474 if (pat
|| REG_P (operands
[2]) || satisfies_constraint_L (operands
[2]))
7479 /* Helper function of arc_expand_movmem. ADDR points to a chunk of memory.
7480 Emit code and return an potentially modified address such that offsets
7481 up to SIZE are can be added to yield a legitimate address.
7482 if REUSE is set, ADDR is a register that may be modified. */
7485 force_offsettable (rtx addr
, HOST_WIDE_INT size
, bool reuse
)
7488 rtx offs
= const0_rtx
;
7490 if (GET_CODE (base
) == PLUS
)
7492 offs
= XEXP (base
, 1);
7493 base
= XEXP (base
, 0);
7496 || (REGNO (base
) != STACK_POINTER_REGNUM
7497 && REGNO_PTR_FRAME_P (REGNO (addr
)))
7498 || !CONST_INT_P (offs
) || !SMALL_INT (INTVAL (offs
))
7499 || !SMALL_INT (INTVAL (offs
) + size
))
7502 emit_insn (gen_add2_insn (addr
, offs
));
7504 addr
= copy_to_mode_reg (Pmode
, addr
);
7509 /* Like move_by_pieces, but take account of load latency,
7510 and actual offset ranges.
7511 Return true on success. */
7514 arc_expand_movmem (rtx
*operands
)
7516 rtx dst
= operands
[0];
7517 rtx src
= operands
[1];
7518 rtx dst_addr
, src_addr
;
7520 int align
= INTVAL (operands
[3]);
7527 if (!CONST_INT_P (operands
[2]))
7529 size
= INTVAL (operands
[2]);
7530 /* move_by_pieces_ninsns is static, so we can't use it. */
7532 n_pieces
= (size
+ 2) / 4U + (size
& 1);
7533 else if (align
== 2)
7534 n_pieces
= (size
+ 1) / 2U;
7537 if (n_pieces
>= (unsigned int) (optimize_size
? 3 : 15))
7541 dst_addr
= force_offsettable (XEXP (operands
[0], 0), size
, 0);
7542 src_addr
= force_offsettable (XEXP (operands
[1], 0), size
, 0);
7543 store
[0] = store
[1] = NULL_RTX
;
7544 tmpx
[0] = tmpx
[1] = NULL_RTX
;
7545 for (i
= 0; size
> 0; i
^= 1, size
-= piece
)
7551 piece
= size
& -size
;
7552 mode
= smallest_mode_for_size (piece
* BITS_PER_UNIT
, MODE_INT
);
7553 /* If we don't re-use temporaries, the scheduler gets carried away,
7554 and the register pressure gets unnecessarily high. */
7555 if (0 && tmpx
[i
] && GET_MODE (tmpx
[i
]) == mode
)
7558 tmpx
[i
] = tmp
= gen_reg_rtx (mode
);
7559 dst_addr
= force_offsettable (dst_addr
, piece
, 1);
7560 src_addr
= force_offsettable (src_addr
, piece
, 1);
7562 emit_insn (store
[i
]);
7563 emit_move_insn (tmp
, change_address (src
, mode
, src_addr
));
7564 store
[i
] = gen_move_insn (change_address (dst
, mode
, dst_addr
), tmp
);
7565 dst_addr
= plus_constant (Pmode
, dst_addr
, piece
);
7566 src_addr
= plus_constant (Pmode
, src_addr
, piece
);
7569 emit_insn (store
[i
]);
7571 emit_insn (store
[i
^1]);
7575 /* Prepare operands for move in MODE. Return true iff the move has
7579 prepare_move_operands (rtx
*operands
, machine_mode mode
)
7581 /* We used to do this only for MODE_INT Modes, but addresses to floating
7582 point variables may well be in the small data section. */
7585 if (!TARGET_NO_SDATA_SET
&& small_data_pattern (operands
[0], Pmode
))
7586 operands
[0] = arc_rewrite_small_data (operands
[0]);
7587 else if (mode
== SImode
&& flag_pic
&& SYMBOLIC_CONST (operands
[1]))
7589 emit_pic_move (operands
, SImode
);
7591 /* Disable any REG_EQUALs associated with the symref
7592 otherwise the optimization pass undoes the work done
7593 here and references the variable directly. */
7595 else if (GET_CODE (operands
[0]) != MEM
7596 && !TARGET_NO_SDATA_SET
7597 && small_data_pattern (operands
[1], Pmode
))
7599 /* This is to take care of address calculations involving sdata
7601 operands
[1] = arc_rewrite_small_data (operands
[1]);
7603 emit_insn (gen_rtx_SET (mode
, operands
[0],operands
[1]));
7604 /* ??? This note is useless, since it only restates the set itself.
7605 We should rather use the original SYMBOL_REF. However, there is
7606 the problem that we are lying to the compiler about these
7607 SYMBOL_REFs to start with. symbol@sda should be encoded specially
7608 so that we can tell it apart from an actual symbol. */
7609 set_unique_reg_note (get_last_insn (), REG_EQUAL
, operands
[1]);
7611 /* Take care of the REG_EQUAL note that will be attached to mark the
7612 output reg equal to the initial symbol_ref after this code is
7614 emit_move_insn (operands
[0], operands
[0]);
7619 if (MEM_P (operands
[0])
7620 && !(reload_in_progress
|| reload_completed
))
7622 operands
[1] = force_reg (mode
, operands
[1]);
7623 if (!move_dest_operand (operands
[0], mode
))
7625 rtx addr
= copy_to_mode_reg (Pmode
, XEXP (operands
[0], 0));
7626 /* This is like change_address_1 (operands[0], mode, 0, 1) ,
7627 except that we can't use that function because it is static. */
7628 rtx pat
= change_address (operands
[0], mode
, addr
);
7629 MEM_COPY_ATTRIBUTES (pat
, operands
[0]);
7632 if (!cse_not_expected
)
7634 rtx pat
= XEXP (operands
[0], 0);
7636 pat
= arc_legitimize_address_0 (pat
, pat
, mode
);
7639 pat
= change_address (operands
[0], mode
, pat
);
7640 MEM_COPY_ATTRIBUTES (pat
, operands
[0]);
7646 if (MEM_P (operands
[1]) && !cse_not_expected
)
7648 rtx pat
= XEXP (operands
[1], 0);
7650 pat
= arc_legitimize_address_0 (pat
, pat
, mode
);
7653 pat
= change_address (operands
[1], mode
, pat
);
7654 MEM_COPY_ATTRIBUTES (pat
, operands
[1]);
7662 /* Prepare OPERANDS for an extension using CODE to OMODE.
7663 Return true iff the move has been emitted. */
7666 prepare_extend_operands (rtx
*operands
, enum rtx_code code
,
7669 if (!TARGET_NO_SDATA_SET
&& small_data_pattern (operands
[1], Pmode
))
7671 /* This is to take care of address calculations involving sdata
7674 = gen_rtx_fmt_e (code
, omode
, arc_rewrite_small_data (operands
[1]));
7675 emit_insn (gen_rtx_SET (omode
, operands
[0], operands
[1]));
7676 set_unique_reg_note (get_last_insn (), REG_EQUAL
, operands
[1]);
7678 /* Take care of the REG_EQUAL note that will be attached to mark the
7679 output reg equal to the initial extension after this code is
7681 emit_move_insn (operands
[0], operands
[0]);
7687 /* Output a library call to a function called FNAME that has been arranged
7688 to be local to any dso. */
7691 arc_output_libcall (const char *fname
)
7693 unsigned len
= strlen (fname
);
7694 static char buf
[64];
7696 gcc_assert (len
< sizeof buf
- 35);
7697 if (TARGET_LONG_CALLS_SET
7698 || (TARGET_MEDIUM_CALLS
&& arc_ccfsm_cond_exec_p ()))
7701 sprintf (buf
, "add r12,pcl,@%s-(.&-4)\n\tjl%%!%%* [r12]", fname
);
7703 sprintf (buf
, "jl%%! @%s", fname
);
7706 sprintf (buf
, "bl%%!%%* @%s", fname
);
7710 /* Return the SImode highpart of the DImode value IN. */
7713 disi_highpart (rtx in
)
7715 return simplify_gen_subreg (SImode
, in
, DImode
, TARGET_BIG_ENDIAN
? 0 : 4);
7718 /* Called by arc600_corereg_hazard via for_each_rtx.
7719 If a hazard is found, return a conservative estimate of the required
7720 length adjustment to accomodate a nop. */
7723 arc600_corereg_hazard_1 (rtx
*xp
, void *data
)
7727 rtx pat
= (rtx
) data
;
7729 switch (GET_CODE (x
))
7731 case SET
: case POST_INC
: case POST_DEC
: case PRE_INC
: case PRE_DEC
:
7734 /* This is also fine for PRE/POST_MODIFY, because they contain a SET. */
7738 /* Check if this sets a an extension register. N.B. we use 61 for the
7739 condition codes, which is definitely not an extension register. */
7740 if (REG_P (dest
) && REGNO (dest
) >= 32 && REGNO (dest
) < 61
7741 /* Check if the same register is used by the PAT. */
7742 && (refers_to_regno_p
7744 REGNO (dest
) + (GET_MODE_SIZE (GET_MODE (dest
)) + 3) / 4U, pat
, 0)))
7750 /* Return length adjustment for INSN.
7752 A write to a core reg greater or equal to 32 must not be immediately
7753 followed by a use. Anticipate the length requirement to insert a nop
7754 between PRED and SUCC to prevent a hazard. */
7757 arc600_corereg_hazard (rtx_insn
*pred
, rtx_insn
*succ
)
7761 /* If SUCC is a doloop_end_i with a preceding label, we must output a nop
7762 in front of SUCC anyway, so there will be separation between PRED and
7764 if (recog_memoized (succ
) == CODE_FOR_doloop_end_i
7765 && LABEL_P (prev_nonnote_insn (succ
)))
7767 if (recog_memoized (succ
) == CODE_FOR_doloop_begin_i
)
7769 if (GET_CODE (PATTERN (pred
)) == SEQUENCE
)
7770 pred
= as_a
<rtx_sequence
*> (PATTERN (pred
))->insn (1);
7771 if (GET_CODE (PATTERN (succ
)) == SEQUENCE
)
7772 succ
= as_a
<rtx_sequence
*> (PATTERN (succ
))->insn (0);
7773 if (recog_memoized (pred
) == CODE_FOR_mulsi_600
7774 || recog_memoized (pred
) == CODE_FOR_umul_600
7775 || recog_memoized (pred
) == CODE_FOR_mac_600
7776 || recog_memoized (pred
) == CODE_FOR_mul64_600
7777 || recog_memoized (pred
) == CODE_FOR_mac64_600
7778 || recog_memoized (pred
) == CODE_FOR_umul64_600
7779 || recog_memoized (pred
) == CODE_FOR_umac64_600
)
7781 return for_each_rtx (&PATTERN (pred
), arc600_corereg_hazard_1
,
7786 A write to a core reg greater or equal to 32 must not be immediately
7787 followed by a use. Anticipate the length requirement to insert a nop
7788 between PRED and SUCC to prevent a hazard. */
7791 arc_hazard (rtx_insn
*pred
, rtx_insn
*succ
)
7795 if (!pred
|| !INSN_P (pred
) || !succ
|| !INSN_P (succ
))
7797 /* We might have a CALL to a non-returning function before a loop end.
7798 ??? Although the manual says that's OK (the target is outside the loop,
7799 and the loop counter unused there), the assembler barfs on this, so we
7800 must instert a nop before such a call too. */
7801 if (recog_memoized (succ
) == CODE_FOR_doloop_end_i
7802 && (JUMP_P (pred
) || CALL_P (pred
)
7803 || GET_CODE (PATTERN (pred
)) == SEQUENCE
))
7805 return arc600_corereg_hazard (pred
, succ
);
7808 /* Return length adjustment for INSN. */
7811 arc_adjust_insn_length (rtx_insn
*insn
, int len
, bool)
7815 /* We already handle sequences by ignoring the delay sequence flag. */
7816 if (GET_CODE (PATTERN (insn
)) == SEQUENCE
)
7819 /* It is impossible to jump to the very end of a Zero-Overhead Loop, as
7820 the ZOL mechanism only triggers when advancing to the end address,
7821 so if there's a label at the end of a ZOL, we need to insert a nop.
7822 The ARC600 ZOL also has extra restrictions on jumps at the end of a
7824 if (recog_memoized (insn
) == CODE_FOR_doloop_end_i
)
7826 rtx_insn
*prev
= prev_nonnote_insn (insn
);
7828 return ((LABEL_P (prev
)
7831 || CALL_P (prev
) /* Could be a noreturn call. */
7832 || (NONJUMP_INSN_P (prev
)
7833 && GET_CODE (PATTERN (prev
)) == SEQUENCE
))))
7837 /* Check for return with but one preceding insn since function
7839 if (TARGET_PAD_RETURN
7841 && GET_CODE (PATTERN (insn
)) != ADDR_VEC
7842 && GET_CODE (PATTERN (insn
)) != ADDR_DIFF_VEC
7843 && get_attr_type (insn
) == TYPE_RETURN
)
7845 rtx_insn
*prev
= prev_active_insn (insn
);
7847 if (!prev
|| !(prev
= prev_active_insn (prev
))
7848 || ((NONJUMP_INSN_P (prev
)
7849 && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
7850 ? CALL_ATTR (as_a
<rtx_sequence
*> (PATTERN (prev
))->insn (0),
7852 : CALL_ATTR (prev
, NON_SIBCALL
)))
7857 rtx_insn
*succ
= next_real_insn (insn
);
7859 /* One the ARC600, a write to an extension register must be separated
7861 if (succ
&& INSN_P (succ
))
7862 len
+= arc600_corereg_hazard (insn
, succ
);
7865 /* Restore extracted operands - otherwise splitters like the addsi3_mixed one
7867 extract_constrain_insn_cached (insn
);
7872 /* Values for length_sensitive. */
7876 ARC_LS_25
, // 25 bit offset, B
7877 ARC_LS_21
, // 21 bit offset, Bcc
7878 ARC_LS_U13
,// 13 bit unsigned offset, LP
7879 ARC_LS_10
, // 10 bit offset, B_s, Beq_s, Bne_s
7880 ARC_LS_9
, // 9 bit offset, BRcc
7881 ARC_LS_8
, // 8 bit offset, BRcc_s
7882 ARC_LS_U7
, // 7 bit unsigned offset, LPcc
7883 ARC_LS_7
// 7 bit offset, Bcc_s
7886 /* While the infrastructure patch is waiting for review, duplicate the
7887 struct definitions, to allow this file to compile. */
7892 /* Cost as a branch / call target or call return address. */
7894 int fallthrough_cost
;
7897 /* 0 for not length sensitive, 1 for largest offset range,
7898 * 2 for next smaller etc. */
7899 unsigned length_sensitive
: 8;
7901 } insn_length_variant_t
;
7903 typedef struct insn_length_parameters_s
7908 int (*get_variants
) (rtx_insn
*, int, bool, bool, insn_length_variant_t
*);
7909 } insn_length_parameters_t
;
7912 arc_insn_length_parameters (insn_length_parameters_t
*ilp
) ATTRIBUTE_UNUSED
;
7916 arc_get_insn_variants (rtx_insn
*insn
, int len
, bool, bool target_p
,
7917 insn_length_variant_t
*ilv
)
7919 if (!NONDEBUG_INSN_P (insn
))
7921 enum attr_type type
;
7922 /* shorten_branches doesn't take optimize_size into account yet for the
7923 get_variants mechanism, so turn this off for now. */
7926 if (rtx_sequence
*pat
= dyn_cast
<rtx_sequence
*> (PATTERN (insn
)))
7928 /* The interaction of a short delay slot insn with a short branch is
7929 too weird for shorten_branches to piece together, so describe the
7932 if (TARGET_UPSIZE_DBR
7933 && get_attr_length (pat
->insn (1)) <= 2
7934 && (((type
= get_attr_type (inner
= pat
->insn (0)))
7935 == TYPE_UNCOND_BRANCH
)
7936 || type
== TYPE_BRANCH
)
7937 && get_attr_delay_slot_filled (inner
) == DELAY_SLOT_FILLED_YES
)
7940 = arc_get_insn_variants (inner
, get_attr_length (inner
), true,
7942 /* The short variant gets split into a higher-cost aligned
7943 and a lower cost unaligned variant. */
7944 gcc_assert (n_variants
);
7945 gcc_assert (ilv
[1].length_sensitive
== ARC_LS_7
7946 || ilv
[1].length_sensitive
== ARC_LS_10
);
7947 gcc_assert (ilv
[1].align_set
== 3);
7949 ilv
[0].align_set
= 1;
7950 ilv
[0].branch_cost
+= 1;
7951 ilv
[1].align_set
= 2;
7953 for (int i
= 0; i
< n_variants
; i
++)
7955 /* In case an instruction with aligned size is wanted, and
7956 the short variants are unavailable / too expensive, add
7957 versions of long branch + long delay slot. */
7958 for (int i
= 2, end
= n_variants
; i
< end
; i
++, n_variants
++)
7960 ilv
[n_variants
] = ilv
[i
];
7961 ilv
[n_variants
].length
+= 2;
7967 insn_length_variant_t
*first_ilv
= ilv
;
7968 type
= get_attr_type (insn
);
7970 = (get_attr_delay_slot_filled (insn
) == DELAY_SLOT_FILLED_YES
);
7971 int branch_align_cost
= delay_filled
? 0 : 1;
7972 int branch_unalign_cost
= delay_filled
? 0 : TARGET_UNALIGN_BRANCH
? 0 : 1;
7973 /* If the previous instruction is an sfunc call, this insn is always
7974 a target, even though the middle-end is unaware of this. */
7975 bool force_target
= false;
7976 rtx_insn
*prev
= prev_active_insn (insn
);
7977 if (prev
&& arc_next_active_insn (prev
, 0) == insn
7978 && ((NONJUMP_INSN_P (prev
) && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
7979 ? CALL_ATTR (as_a
<rtx_sequence
*> (PATTERN (prev
))->insn (0),
7981 : (CALL_ATTR (prev
, NON_SIBCALL
)
7982 && NEXT_INSN (PREV_INSN (prev
)) == prev
)))
7983 force_target
= true;
7988 /* Short BRCC only comes in no-delay-slot version, and without limm */
7993 ilv
->branch_cost
= 1;
7994 ilv
->enabled
= (len
== 2);
7995 ilv
->length_sensitive
= ARC_LS_8
;
7999 case TYPE_BRCC_NO_DELAY_SLOT
:
8000 /* doloop_fallback* patterns are TYPE_BRCC_NO_DELAY_SLOT for
8001 (delay slot) scheduling purposes, but they are longer. */
8002 if (GET_CODE (PATTERN (insn
)) == PARALLEL
8003 && GET_CODE (XVECEXP (PATTERN (insn
), 0, 1)) == SET
)
8005 /* Standard BRCC: 4 bytes, or 8 bytes with limm. */
8006 ilv
->length
= ((type
== TYPE_BRCC
) ? 4 : 8);
8008 ilv
->branch_cost
= branch_align_cost
;
8009 ilv
->enabled
= (len
<= ilv
->length
);
8010 ilv
->length_sensitive
= ARC_LS_9
;
8011 if ((target_p
|| force_target
)
8012 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8018 ilv
->target_cost
= 1;
8019 ilv
->branch_cost
= branch_unalign_cost
;
8024 op
= XEXP (SET_SRC (XVECEXP (PATTERN (insn
), 0, 0)), 0);
8027 if (GET_CODE (op0
) == ZERO_EXTRACT
8028 && satisfies_constraint_L (XEXP (op0
, 2)))
8029 op0
= XEXP (op0
, 0);
8030 if (satisfies_constraint_Rcq (op0
))
8032 ilv
->length
= ((type
== TYPE_BRCC
) ? 6 : 10);
8034 ilv
->branch_cost
= 1 + branch_align_cost
;
8035 ilv
->fallthrough_cost
= 1;
8036 ilv
->enabled
= true;
8037 ilv
->length_sensitive
= ARC_LS_21
;
8038 if (!delay_filled
&& TARGET_UNALIGN_BRANCH
)
8044 ilv
->branch_cost
= 1 + branch_unalign_cost
;
8048 ilv
->length
= ((type
== TYPE_BRCC
) ? 8 : 12);
8050 ilv
->branch_cost
= 1 + branch_align_cost
;
8051 ilv
->fallthrough_cost
= 1;
8052 ilv
->enabled
= true;
8053 ilv
->length_sensitive
= ARC_LS_21
;
8054 if ((target_p
|| force_target
)
8055 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8061 ilv
->target_cost
= 1;
8062 ilv
->branch_cost
= 1 + branch_unalign_cost
;
8070 case TYPE_CALL_NO_DELAY_SLOT
:
8075 ilv
->length_sensitive
8076 = GET_CODE (PATTERN (insn
)) == COND_EXEC
? ARC_LS_21
: ARC_LS_25
;
8079 ilv
->fallthrough_cost
= branch_align_cost
;
8080 ilv
->enabled
= true;
8081 if ((target_p
|| force_target
)
8082 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8088 ilv
->target_cost
= 1;
8089 ilv
->fallthrough_cost
= branch_unalign_cost
;
8093 case TYPE_UNCOND_BRANCH
:
8094 /* Strictly speaking, this should be ARC_LS_10 for equality comparisons,
8095 but that makes no difference at the moment. */
8096 ilv
->length_sensitive
= ARC_LS_7
;
8097 ilv
[1].length_sensitive
= ARC_LS_25
;
8100 ilv
->length_sensitive
= ARC_LS_10
;
8101 ilv
[1].length_sensitive
= ARC_LS_21
;
8105 ilv
->branch_cost
= branch_align_cost
;
8106 ilv
->enabled
= (len
== ilv
->length
);
8110 ilv
->branch_cost
= branch_align_cost
;
8111 ilv
->enabled
= true;
8112 if ((target_p
|| force_target
)
8113 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8119 ilv
->target_cost
= 1;
8120 ilv
->branch_cost
= branch_unalign_cost
;
8127 /* For every short insn, there is generally also a long insn.
8128 trap_s is an exception. */
8129 if ((len
& 2) == 0 || recog_memoized (insn
) == CODE_FOR_trap_s
)
8136 ilv
->length
= len
+ 2;
8138 if (target_p
|| force_target
)
8144 ilv
->target_cost
= 1;
8148 /* If the previous instruction is an sfunc call, this insn is always
8149 a target, even though the middle-end is unaware of this.
8150 Therefore, if we have a call predecessor, transfer the target cost
8151 to the fallthrough and branch costs. */
8154 for (insn_length_variant_t
*p
= first_ilv
; p
< ilv
; p
++)
8156 p
->fallthrough_cost
+= p
->target_cost
;
8157 p
->branch_cost
+= p
->target_cost
;
8162 return ilv
- first_ilv
;
8166 arc_insn_length_parameters (insn_length_parameters_t
*ilp
)
8168 ilp
->align_unit_log
= 1;
8169 ilp
->align_base_log
= 1;
8170 ilp
->max_variants
= 7;
8171 ilp
->get_variants
= arc_get_insn_variants
;
8174 /* Return a copy of COND from *STATEP, inverted if that is indicated by the
8175 CC field of *STATEP. */
8178 arc_get_ccfsm_cond (struct arc_ccfsm
*statep
, bool reverse
)
8180 rtx cond
= statep
->cond
;
8181 int raw_cc
= get_arc_condition_code (cond
);
8183 raw_cc
= ARC_INVERSE_CONDITION_CODE (raw_cc
);
8185 if (statep
->cc
== raw_cc
)
8186 return copy_rtx (cond
);
8188 gcc_assert (ARC_INVERSE_CONDITION_CODE (raw_cc
) == statep
->cc
);
8190 machine_mode ccm
= GET_MODE (XEXP (cond
, 0));
8191 enum rtx_code code
= reverse_condition (GET_CODE (cond
));
8192 if (code
== UNKNOWN
|| ccm
== CC_FP_GTmode
|| ccm
== CC_FP_GEmode
)
8193 code
= reverse_condition_maybe_unordered (GET_CODE (cond
));
8195 return gen_rtx_fmt_ee (code
, GET_MODE (cond
),
8196 copy_rtx (XEXP (cond
, 0)), copy_rtx (XEXP (cond
, 1)));
8199 /* Return version of PAT conditionalized with COND, which is part of INSN.
8200 ANNULLED indicates if INSN is an annulled delay-slot insn.
8201 Register further changes if necessary. */
8203 conditionalize_nonjump (rtx pat
, rtx cond
, rtx insn
, bool annulled
)
8205 /* For commutative operators, we generally prefer to have
8206 the first source match the destination. */
8207 if (GET_CODE (pat
) == SET
)
8209 rtx src
= SET_SRC (pat
);
8211 if (COMMUTATIVE_P (src
))
8213 rtx src0
= XEXP (src
, 0);
8214 rtx src1
= XEXP (src
, 1);
8215 rtx dst
= SET_DEST (pat
);
8217 if (rtx_equal_p (src1
, dst
) && !rtx_equal_p (src0
, dst
)
8218 /* Leave add_n alone - the canonical form is to
8219 have the complex summand first. */
8221 pat
= gen_rtx_SET (VOIDmode
, dst
,
8222 gen_rtx_fmt_ee (GET_CODE (src
), GET_MODE (src
),
8227 /* dwarf2out.c:dwarf2out_frame_debug_expr doesn't know
8228 what to do with COND_EXEC. */
8229 if (RTX_FRAME_RELATED_P (insn
))
8231 /* If this is the delay slot insn of an anulled branch,
8232 dwarf2out.c:scan_trace understands the anulling semantics
8233 without the COND_EXEC. */
8234 gcc_assert (annulled
);
8235 rtx note
= alloc_reg_note (REG_FRAME_RELATED_EXPR
, pat
,
8237 validate_change (insn
, ®_NOTES (insn
), note
, 1);
8239 pat
= gen_rtx_COND_EXEC (VOIDmode
, cond
, pat
);
8243 /* Use the ccfsm machinery to do if conversion. */
8248 struct arc_ccfsm
*statep
= &cfun
->machine
->ccfsm_current
;
8249 basic_block merge_bb
= 0;
8251 memset (statep
, 0, sizeof *statep
);
8252 for (rtx_insn
*insn
= get_insns (); insn
; insn
= next_insn (insn
))
8254 arc_ccfsm_advance (insn
, statep
);
8256 switch (statep
->state
)
8264 /* Deleted branch. */
8265 gcc_assert (!merge_bb
);
8266 merge_bb
= BLOCK_FOR_INSN (insn
);
8268 = BLOCK_FOR_INSN (NEXT_INSN (NEXT_INSN (PREV_INSN (insn
))));
8269 arc_ccfsm_post_advance (insn
, statep
);
8270 gcc_assert (!IN_RANGE (statep
->state
, 1, 2));
8271 rtx_insn
*seq
= NEXT_INSN (PREV_INSN (insn
));
8274 rtx slot
= XVECEXP (PATTERN (seq
), 0, 1);
8275 rtx pat
= PATTERN (slot
);
8276 if (INSN_ANNULLED_BRANCH_P (insn
))
8279 = arc_get_ccfsm_cond (statep
, INSN_FROM_TARGET_P (slot
));
8280 pat
= gen_rtx_COND_EXEC (VOIDmode
, cond
, pat
);
8282 if (!validate_change (seq
, &PATTERN (seq
), pat
, 0))
8284 PUT_CODE (slot
, NOTE
);
8285 NOTE_KIND (slot
) = NOTE_INSN_DELETED
;
8286 if (merge_bb
&& succ_bb
)
8287 merge_blocks (merge_bb
, succ_bb
);
8289 else if (merge_bb
&& succ_bb
)
8291 set_insn_deleted (insn
);
8292 merge_blocks (merge_bb
, succ_bb
);
8296 PUT_CODE (insn
, NOTE
);
8297 NOTE_KIND (insn
) = NOTE_INSN_DELETED
;
8303 && statep
->target_label
== CODE_LABEL_NUMBER (insn
))
8305 arc_ccfsm_post_advance (insn
, statep
);
8306 basic_block succ_bb
= BLOCK_FOR_INSN (insn
);
8307 if (merge_bb
&& succ_bb
)
8308 merge_blocks (merge_bb
, succ_bb
);
8309 else if (--LABEL_NUSES (insn
) == 0)
8311 const char *name
= LABEL_NAME (insn
);
8312 PUT_CODE (insn
, NOTE
);
8313 NOTE_KIND (insn
) = NOTE_INSN_DELETED_LABEL
;
8314 NOTE_DELETED_LABEL_NAME (insn
) = name
;
8321 if (!NONDEBUG_INSN_P (insn
))
8324 /* Conditionalized insn. */
8326 rtx_insn
*prev
, *pprev
;
8327 rtx
*patp
, pat
, cond
;
8328 bool annulled
; annulled
= false;
8330 /* If this is a delay slot insn in a non-annulled branch,
8331 don't conditionalize it. N.B., this should be fine for
8332 conditional return too. However, don't do this for
8333 unconditional branches, as these would be encountered when
8334 processing an 'else' part. */
8335 prev
= PREV_INSN (insn
);
8336 pprev
= PREV_INSN (prev
);
8337 if (pprev
&& NEXT_INSN (NEXT_INSN (pprev
)) == NEXT_INSN (insn
)
8338 && JUMP_P (prev
) && get_attr_cond (prev
) == COND_USE
)
8340 if (!INSN_ANNULLED_BRANCH_P (prev
))
8345 patp
= &PATTERN (insn
);
8347 cond
= arc_get_ccfsm_cond (statep
, INSN_FROM_TARGET_P (insn
));
8348 if (NONJUMP_INSN_P (insn
) || CALL_P (insn
))
8350 /* ??? don't conditionalize if all side effects are dead
8351 in the not-execute case. */
8353 pat
= conditionalize_nonjump (pat
, cond
, insn
, annulled
);
8355 else if (simplejump_p (insn
))
8357 patp
= &SET_SRC (pat
);
8358 pat
= gen_rtx_IF_THEN_ELSE (VOIDmode
, cond
, *patp
, pc_rtx
);
8360 else if (JUMP_P (insn
) && ANY_RETURN_P (PATTERN (insn
)))
8362 pat
= gen_rtx_IF_THEN_ELSE (VOIDmode
, cond
, pat
, pc_rtx
);
8363 pat
= gen_rtx_SET (VOIDmode
, pc_rtx
, pat
);
8367 validate_change (insn
, patp
, pat
, 1);
8368 if (!apply_change_group ())
8372 rtx_insn
*next
= next_nonnote_insn (insn
);
8373 if (GET_CODE (next
) == BARRIER
)
8375 if (statep
->state
== 3)
8382 arc_ccfsm_post_advance (insn
, statep
);
8387 /* Find annulled delay insns and convert them to use the appropriate predicate.
8388 This allows branch shortening to size up these insns properly. */
8391 arc_predicate_delay_insns (void)
8393 for (rtx_insn
*insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
8395 rtx pat
, jump
, dlay
, src
, cond
, *patp
;
8398 if (!NONJUMP_INSN_P (insn
)
8399 || GET_CODE (pat
= PATTERN (insn
)) != SEQUENCE
)
8401 jump
= XVECEXP (pat
, 0, 0);
8402 dlay
= XVECEXP (pat
, 0, 1);
8403 if (!JUMP_P (jump
) || !INSN_ANNULLED_BRANCH_P (jump
))
8405 /* If the branch insn does the annulling, leave the delay insn alone. */
8406 if (!TARGET_AT_DBR_CONDEXEC
&& !INSN_FROM_TARGET_P (dlay
))
8408 /* ??? Could also leave DLAY un-conditionalized if its target is dead
8409 on the other path. */
8410 gcc_assert (GET_CODE (PATTERN (jump
)) == SET
);
8411 gcc_assert (SET_DEST (PATTERN (jump
)) == pc_rtx
);
8412 src
= SET_SRC (PATTERN (jump
));
8413 gcc_assert (GET_CODE (src
) == IF_THEN_ELSE
);
8414 cond
= XEXP (src
, 0);
8415 if (XEXP (src
, 2) == pc_rtx
)
8417 else if (XEXP (src
, 1) == pc_rtx
)
8421 if (reverse
!= !INSN_FROM_TARGET_P (dlay
))
8423 machine_mode ccm
= GET_MODE (XEXP (cond
, 0));
8424 enum rtx_code code
= reverse_condition (GET_CODE (cond
));
8425 if (code
== UNKNOWN
|| ccm
== CC_FP_GTmode
|| ccm
== CC_FP_GEmode
)
8426 code
= reverse_condition_maybe_unordered (GET_CODE (cond
));
8428 cond
= gen_rtx_fmt_ee (code
, GET_MODE (cond
),
8429 copy_rtx (XEXP (cond
, 0)),
8430 copy_rtx (XEXP (cond
, 1)));
8433 cond
= copy_rtx (cond
);
8434 patp
= &PATTERN (dlay
);
8436 pat
= conditionalize_nonjump (pat
, cond
, dlay
, true);
8437 validate_change (dlay
, patp
, pat
, 1);
8438 if (!apply_change_group ())
8444 /* For ARC600: If a write to a core reg >=32 appears in a delay slot
8445 (other than of a forward brcc), it creates a hazard when there is a read
8446 of the same register at the branch target. We can't know what is at the
8447 branch target of calls, and for branches, we don't really know before the
8448 end of delay slot scheduling, either. Not only can individual instruction
8449 be hoisted out into a delay slot, a basic block can also be emptied this
8450 way, and branch and/or fall through targets be redirected. Hence we don't
8451 want such writes in a delay slot. */
8452 /* Called by arc_write_ext_corereg via for_each_rtx. */
8455 write_ext_corereg_1 (rtx
*xp
, void *data ATTRIBUTE_UNUSED
)
8460 switch (GET_CODE (x
))
8462 case SET
: case POST_INC
: case POST_DEC
: case PRE_INC
: case PRE_DEC
:
8465 /* This is also fine for PRE/POST_MODIFY, because they contain a SET. */
8469 if (REG_P (dest
) && REGNO (dest
) >= 32 && REGNO (dest
) < 61)
8474 /* Return nonzreo iff INSN writes to an extension core register. */
8477 arc_write_ext_corereg (rtx insn
)
8479 return for_each_rtx (&PATTERN (insn
), write_ext_corereg_1
, 0);
8482 /* This is like the hook, but returns NULL when it can't / won't generate
8483 a legitimate address. */
8486 arc_legitimize_address_0 (rtx x
, rtx oldx ATTRIBUTE_UNUSED
,
8491 if (flag_pic
&& SYMBOLIC_CONST (x
))
8492 (x
) = arc_legitimize_pic_address (x
, 0);
8494 if (GET_CODE (addr
) == CONST
)
8495 addr
= XEXP (addr
, 0);
8496 if (GET_CODE (addr
) == PLUS
8497 && CONST_INT_P (XEXP (addr
, 1))
8498 && ((GET_CODE (XEXP (addr
, 0)) == SYMBOL_REF
8499 && !SYMBOL_REF_FUNCTION_P (XEXP (addr
, 0)))
8500 || (REG_P (XEXP (addr
, 0))
8501 && (INTVAL (XEXP (addr
, 1)) & 252))))
8503 HOST_WIDE_INT offs
, upper
;
8504 int size
= GET_MODE_SIZE (mode
);
8506 offs
= INTVAL (XEXP (addr
, 1));
8507 upper
= (offs
+ 256 * size
) & ~511 * size
;
8508 inner
= plus_constant (Pmode
, XEXP (addr
, 0), upper
);
8509 #if 0 /* ??? this produces worse code for EEMBC idctrn01 */
8510 if (GET_CODE (x
) == CONST
)
8511 inner
= gen_rtx_CONST (Pmode
, inner
);
8513 addr
= plus_constant (Pmode
, force_reg (Pmode
, inner
), offs
- upper
);
8516 else if (GET_CODE (addr
) == SYMBOL_REF
&& !SYMBOL_REF_FUNCTION_P (addr
))
8517 x
= force_reg (Pmode
, x
);
8518 if (memory_address_p ((machine_mode
) mode
, x
))
8524 arc_legitimize_address (rtx orig_x
, rtx oldx
, machine_mode mode
)
8526 rtx new_x
= arc_legitimize_address_0 (orig_x
, oldx
, mode
);
8534 arc_delegitimize_address_0 (rtx x
)
8538 if (GET_CODE (x
) == CONST
&& GET_CODE (u
= XEXP (x
, 0)) == UNSPEC
)
8540 if (XINT (u
, 1) == ARC_UNSPEC_GOT
)
8541 return XVECEXP (u
, 0, 0);
8543 else if (GET_CODE (x
) == PLUS
8544 && ((REG_P (gp
= XEXP (x
, 0))
8545 && REGNO (gp
) == PIC_OFFSET_TABLE_REGNUM
)
8546 || (GET_CODE (gp
) == CONST
8547 && GET_CODE (u
= XEXP (gp
, 0)) == UNSPEC
8548 && XINT (u
, 1) == ARC_UNSPEC_GOT
8549 && GET_CODE (XVECEXP (u
, 0, 0)) == SYMBOL_REF
8550 && !strcmp (XSTR (XVECEXP (u
, 0, 0), 0), "_DYNAMIC")))
8551 && GET_CODE (XEXP (x
, 1)) == CONST
8552 && GET_CODE (u
= XEXP (XEXP (x
, 1), 0)) == UNSPEC
8553 && XINT (u
, 1) == ARC_UNSPEC_GOTOFF
)
8554 return XVECEXP (u
, 0, 0);
8555 else if (GET_CODE (x
) == PLUS
&& GET_CODE (XEXP (x
, 0)) == PLUS
8556 && ((REG_P (gp
= XEXP (XEXP (x
, 0), 1))
8557 && REGNO (gp
) == PIC_OFFSET_TABLE_REGNUM
)
8558 || (GET_CODE (gp
) == CONST
8559 && GET_CODE (u
= XEXP (gp
, 0)) == UNSPEC
8560 && XINT (u
, 1) == ARC_UNSPEC_GOT
8561 && GET_CODE (XVECEXP (u
, 0, 0)) == SYMBOL_REF
8562 && !strcmp (XSTR (XVECEXP (u
, 0, 0), 0), "_DYNAMIC")))
8563 && GET_CODE (XEXP (x
, 1)) == CONST
8564 && GET_CODE (u
= XEXP (XEXP (x
, 1), 0)) == UNSPEC
8565 && XINT (u
, 1) == ARC_UNSPEC_GOTOFF
)
8566 return gen_rtx_PLUS (GET_MODE (x
), XEXP (XEXP (x
, 0), 0),
8568 else if (GET_CODE (x
) == PLUS
8569 && (u
= arc_delegitimize_address_0 (XEXP (x
, 1))))
8570 return gen_rtx_PLUS (GET_MODE (x
), XEXP (x
, 0), u
);
8575 arc_delegitimize_address (rtx x
)
8577 rtx orig_x
= x
= delegitimize_mem_from_attrs (x
);
8578 if (GET_CODE (x
) == MEM
)
8580 x
= arc_delegitimize_address_0 (x
);
8584 x
= replace_equiv_address_nv (orig_x
, x
);
8590 /* Return a REG rtx for acc1. 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 acc1 and acc2. */
8597 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 56: 57);
8600 /* Return a REG rtx for acc2. 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 acc1 and acc2. */
8607 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 57: 56);
8610 /* Return a REG rtx for mlo. N.B. the gcc-internal representation may
8611 differ from the hardware register number in order to allow the generic
8612 code to correctly split the concatenation of mhi and mlo. */
8617 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 59: 58);
8620 /* Return a REG rtx for mhi. N.B. the gcc-internal representation may
8621 differ from the hardware register number in order to allow the generic
8622 code to correctly split the concatenation of mhi and mlo. */
8627 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 58: 59);
8630 /* FIXME: a parameter should be added, and code added to final.c,
8631 to reproduce this functionality in shorten_branches. */
8633 /* Return nonzero iff BRANCH should be unaligned if possible by upsizing
8634 a previous instruction. */
8636 arc_unalign_branch_p (rtx branch
)
8640 if (!TARGET_UNALIGN_BRANCH
)
8642 /* Do not do this if we have a filled delay slot. */
8643 if (get_attr_delay_slot_filled (branch
) == DELAY_SLOT_FILLED_YES
8644 && !NEXT_INSN (branch
)->deleted ())
8646 note
= find_reg_note (branch
, REG_BR_PROB
, 0);
8648 || (arc_unalign_prob_threshold
&& !br_prob_note_reliable_p (note
))
8649 || INTVAL (XEXP (note
, 0)) < arc_unalign_prob_threshold
);
8653 /* When estimating sizes during arc_reorg, when optimizing for speed, there
8654 are three reasons why we need to consider branches to be length 6:
8655 - annull-false delay slot insns are implemented using conditional execution,
8656 thus preventing short insn formation where used.
8657 - for ARC600: annul-true delay slot insns are implemented where possible
8658 using conditional execution, preventing short insn formation where used.
8659 - for ARC700: likely or somewhat likely taken branches are made long and
8660 unaligned if possible to avoid branch penalty. */
8663 arc_branch_size_unknown_p (void)
8665 return !optimize_size
&& arc_reorg_in_progress
;
8668 /* We are about to output a return insn. Add padding if necessary to avoid
8669 a mispredict. A return could happen immediately after the function
8670 start, but after a call we know that there will be at least a blink
8674 arc_pad_return (void)
8676 rtx_insn
*insn
= current_output_insn
;
8677 rtx_insn
*prev
= prev_active_insn (insn
);
8682 fputs ("\tnop_s\n", asm_out_file
);
8683 cfun
->machine
->unalign
^= 2;
8686 /* If PREV is a sequence, we know it must be a branch / jump or a tailcall,
8687 because after a call, we'd have to restore blink first. */
8688 else if (GET_CODE (PATTERN (prev
)) == SEQUENCE
)
8692 want_long
= (get_attr_length (prev
) == 2);
8693 prev
= prev_active_insn (prev
);
8696 || ((NONJUMP_INSN_P (prev
) && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
8697 ? CALL_ATTR (as_a
<rtx_sequence
*> (PATTERN (prev
))->insn (0),
8699 : CALL_ATTR (prev
, NON_SIBCALL
)))
8702 cfun
->machine
->size_reason
8703 = "call/return and return/return must be 6 bytes apart to avoid mispredict";
8704 else if (TARGET_UNALIGN_BRANCH
&& cfun
->machine
->unalign
)
8706 cfun
->machine
->size_reason
8707 = "Long unaligned jump avoids non-delay slot penalty";
8710 /* Disgorge delay insn, if there is any, and it may be moved. */
8712 /* ??? Annulled would be OK if we can and do conditionalize
8713 the delay slot insn accordingly. */
8714 && !INSN_ANNULLED_BRANCH_P (insn
)
8715 && (get_attr_cond (insn
) != COND_USE
8716 || !reg_set_p (gen_rtx_REG (CCmode
, CC_REG
),
8717 XVECEXP (final_sequence
, 0, 1))))
8719 prev
= as_a
<rtx_insn
*> (XVECEXP (final_sequence
, 0, 1));
8720 gcc_assert (!prev_real_insn (insn
)
8721 || !arc_hazard (prev_real_insn (insn
), prev
));
8722 cfun
->machine
->force_short_suffix
= !want_long
;
8723 rtx save_pred
= current_insn_predicate
;
8724 final_scan_insn (prev
, asm_out_file
, optimize
, 1, NULL
);
8725 cfun
->machine
->force_short_suffix
= -1;
8726 prev
->set_deleted ();
8727 current_output_insn
= insn
;
8728 current_insn_predicate
= save_pred
;
8731 fputs ("\tnop\n", asm_out_file
);
8734 fputs ("\tnop_s\n", asm_out_file
);
8735 cfun
->machine
->unalign
^= 2;
8741 /* The usual; we set up our machine_function data. */
8743 static struct machine_function
*
8744 arc_init_machine_status (void)
8746 struct machine_function
*machine
;
8747 machine
= ggc_cleared_alloc
<machine_function
> ();
8748 machine
->fn_type
= ARC_FUNCTION_UNKNOWN
;
8749 machine
->force_short_suffix
= -1;
8754 /* Implements INIT_EXPANDERS. We just set up to call the above
8758 arc_init_expanders (void)
8760 init_machine_status
= arc_init_machine_status
;
8763 /* Check if OP is a proper parallel of a millicode call pattern. OFFSET
8764 indicates a number of elements to ignore - that allows to have a
8765 sibcall pattern that starts with (return). LOAD_P is zero for store
8766 multiple (for prologues), and one for load multiples (for epilogues),
8767 and two for load multiples where no final clobber of blink is required.
8768 We also skip the first load / store element since this is supposed to
8769 be checked in the instruction pattern. */
8772 arc_check_millicode (rtx op
, int offset
, int load_p
)
8774 int len
= XVECLEN (op
, 0) - offset
;
8779 if (len
< 2 || len
> 13)
8785 rtx elt
= XVECEXP (op
, 0, --len
);
8787 if (GET_CODE (elt
) != CLOBBER
8788 || !REG_P (XEXP (elt
, 0))
8789 || REGNO (XEXP (elt
, 0)) != RETURN_ADDR_REGNUM
8790 || len
< 3 || len
> 13)
8793 for (i
= 1; i
< len
; i
++)
8795 rtx elt
= XVECEXP (op
, 0, i
+ offset
);
8798 if (GET_CODE (elt
) != SET
)
8800 mem
= XEXP (elt
, load_p
);
8801 reg
= XEXP (elt
, 1-load_p
);
8802 if (!REG_P (reg
) || REGNO (reg
) != 13U+i
|| !MEM_P (mem
))
8804 addr
= XEXP (mem
, 0);
8805 if (GET_CODE (addr
) != PLUS
8806 || !rtx_equal_p (stack_pointer_rtx
, XEXP (addr
, 0))
8807 || !CONST_INT_P (XEXP (addr
, 1)) || INTVAL (XEXP (addr
, 1)) != i
*4)
8813 /* Accessor functions for cfun->machine->unalign. */
8816 arc_get_unalign (void)
8818 return cfun
->machine
->unalign
;
8822 arc_clear_unalign (void)
8825 cfun
->machine
->unalign
= 0;
8829 arc_toggle_unalign (void)
8831 cfun
->machine
->unalign
^= 2;
8834 /* Operands 0..2 are the operands of a addsi which uses a 12 bit
8835 constant in operand 2, but which would require a LIMM because of
8837 operands 3 and 4 are new SET_SRCs for operands 0. */
8840 split_addsi (rtx
*operands
)
8842 int val
= INTVAL (operands
[2]);
8844 /* Try for two short insns first. Lengths being equal, we prefer
8845 expansions with shorter register lifetimes. */
8846 if (val
> 127 && val
<= 255
8847 && satisfies_constraint_Rcq (operands
[0]))
8849 operands
[3] = operands
[2];
8850 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[1]);
8854 operands
[3] = operands
[1];
8855 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[2]);
8859 /* Operands 0..2 are the operands of a subsi which uses a 12 bit
8860 constant in operand 1, but which would require a LIMM because of
8862 operands 3 and 4 are new SET_SRCs for operands 0. */
8865 split_subsi (rtx
*operands
)
8867 int val
= INTVAL (operands
[1]);
8869 /* Try for two short insns first. Lengths being equal, we prefer
8870 expansions with shorter register lifetimes. */
8871 if (satisfies_constraint_Rcq (operands
[0])
8872 && satisfies_constraint_Rcq (operands
[2]))
8874 if (val
>= -31 && val
<= 127)
8876 operands
[3] = gen_rtx_NEG (SImode
, operands
[2]);
8877 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[1]);
8880 else if (val
>= 0 && val
< 255)
8882 operands
[3] = operands
[1];
8883 operands
[4] = gen_rtx_MINUS (SImode
, operands
[0], operands
[2]);
8887 /* If the destination is not an ARCompact16 register, we might
8888 still have a chance to make a short insn if the source is;
8889 we need to start with a reg-reg move for this. */
8890 operands
[3] = operands
[2];
8891 operands
[4] = gen_rtx_MINUS (SImode
, operands
[1], operands
[0]);
8894 /* Handle DOUBLE_REGS uses.
8895 Operand 0: destination register
8896 Operand 1: source register */
8899 arc_process_double_reg_moves (rtx
*operands
)
8901 rtx dest
= operands
[0];
8902 rtx src
= operands
[1];
8905 enum usesDxState
{ none
, srcDx
, destDx
, maxDx
};
8906 enum usesDxState state
= none
;
8908 if (refers_to_regno_p (40, 44, src
, 0))
8910 if (refers_to_regno_p (40, 44, dest
, 0))
8912 /* Via arc_register_move_cost, we should never see D,D moves. */
8913 gcc_assert (state
== none
);
8924 /* Without the LR insn, we need to split this into a
8925 sequence of insns which will use the DEXCLx and DADDHxy
8926 insns to be able to read the Dx register in question. */
8927 if (TARGET_DPFP_DISABLE_LRSR
)
8929 /* gen *movdf_insn_nolrsr */
8930 rtx set
= gen_rtx_SET (VOIDmode
, dest
, src
);
8931 rtx use1
= gen_rtx_USE (VOIDmode
, const1_rtx
);
8932 emit_insn (gen_rtx_PARALLEL (VOIDmode
, gen_rtvec (2, set
, use1
)));
8936 /* When we have 'mov D, r' or 'mov D, D' then get the target
8937 register pair for use with LR insn. */
8938 rtx destHigh
= simplify_gen_subreg(SImode
, dest
, DFmode
, 4);
8939 rtx destLow
= simplify_gen_subreg(SImode
, dest
, DFmode
, 0);
8941 /* Produce the two LR insns to get the high and low parts. */
8942 emit_insn (gen_rtx_SET (VOIDmode
,
8944 gen_rtx_UNSPEC_VOLATILE (Pmode
, gen_rtvec (1, src
),
8946 emit_insn (gen_rtx_SET (VOIDmode
,
8948 gen_rtx_UNSPEC_VOLATILE (Pmode
, gen_rtvec (1, src
),
8952 else if (state
== destDx
)
8954 /* When we have 'mov r, D' or 'mov D, D' and we have access to the
8955 LR insn get the target register pair. */
8956 rtx srcHigh
= simplify_gen_subreg(SImode
, src
, DFmode
, 4);
8957 rtx srcLow
= simplify_gen_subreg(SImode
, src
, DFmode
, 0);
8959 emit_insn (gen_rtx_UNSPEC_VOLATILE (Pmode
,
8960 gen_rtvec (3, dest
, srcHigh
, srcLow
),
8961 VUNSPEC_DEXCL_NORES
));
8972 /* operands 0..1 are the operands of a 64 bit move instruction.
8973 split it into two moves with operands 2/3 and 4/5. */
8976 arc_split_move (rtx
*operands
)
8978 machine_mode mode
= GET_MODE (operands
[0]);
8986 val
= arc_process_double_reg_moves (operands
);
8991 for (i
= 0; i
< 2; i
++)
8993 if (MEM_P (operands
[i
]) && auto_inc_p (XEXP (operands
[i
], 0)))
8995 rtx addr
= XEXP (operands
[i
], 0);
8999 gcc_assert (!reg_overlap_mentioned_p (operands
[0], addr
));
9000 switch (GET_CODE (addr
))
9002 case PRE_DEC
: o
= GEN_INT (-8); goto pre_modify
;
9003 case PRE_INC
: o
= GEN_INT (8); goto pre_modify
;
9004 case PRE_MODIFY
: o
= XEXP (XEXP (addr
, 1), 1);
9008 case POST_DEC
: o
= GEN_INT (-8); goto post_modify
;
9009 case POST_INC
: o
= GEN_INT (8); goto post_modify
;
9010 case POST_MODIFY
: o
= XEXP (XEXP (addr
, 1), 1);
9019 xop
[0+i
] = adjust_automodify_address_nv
9020 (operands
[i
], SImode
,
9021 gen_rtx_fmt_ee (code
, Pmode
, r
,
9022 gen_rtx_PLUS (Pmode
, r
, o
)),
9024 xop
[2+i
] = adjust_automodify_address_nv
9025 (operands
[i
], SImode
, plus_constant (Pmode
, r
, 4), 4);
9029 xop
[0+i
] = operand_subword (operands
[i
], 0, 0, mode
);
9030 xop
[2+i
] = operand_subword (operands
[i
], 1, 0, mode
);
9033 if (reg_overlap_mentioned_p (xop
[0], xop
[3]))
9036 gcc_assert (!reg_overlap_mentioned_p (xop
[2], xop
[1]));
9038 operands
[2+swap
] = xop
[0];
9039 operands
[3+swap
] = xop
[1];
9040 operands
[4-swap
] = xop
[2];
9041 operands
[5-swap
] = xop
[3];
9044 emit_insn (gen_rtx_SET (VOIDmode
, operands
[2], operands
[3]));
9045 emit_insn (gen_rtx_SET (VOIDmode
, operands
[4], operands
[5]));
9052 /* Select between the instruction output templates s_tmpl (for short INSNs)
9053 and l_tmpl (for long INSNs). */
9056 arc_short_long (rtx_insn
*insn
, const char *s_tmpl
, const char *l_tmpl
)
9058 int is_short
= arc_verify_short (insn
, cfun
->machine
->unalign
, -1);
9060 extract_constrain_insn_cached (insn
);
9061 return is_short
? s_tmpl
: l_tmpl
;
9064 /* Searches X for any reference to REGNO, returning the rtx of the
9065 reference found if any. Otherwise, returns NULL_RTX. */
9068 arc_regno_use_in (unsigned int regno
, rtx x
)
9074 if (REG_P (x
) && refers_to_regno_p (regno
, regno
+1, x
, (rtx
*) 0))
9077 fmt
= GET_RTX_FORMAT (GET_CODE (x
));
9078 for (i
= GET_RTX_LENGTH (GET_CODE (x
)) - 1; i
>= 0; i
--)
9082 if ((tem
= regno_use_in (regno
, XEXP (x
, i
))))
9085 else if (fmt
[i
] == 'E')
9086 for (j
= XVECLEN (x
, i
) - 1; j
>= 0; j
--)
9087 if ((tem
= regno_use_in (regno
, XVECEXP (x
, i
, j
))))
9094 /* Return the integer value of the "type" attribute for INSN, or -1 if
9095 INSN can't have attributes. */
9098 arc_attr_type (rtx_insn
*insn
)
9100 if (NONJUMP_INSN_P (insn
)
9101 ? (GET_CODE (PATTERN (insn
)) == USE
9102 || GET_CODE (PATTERN (insn
)) == CLOBBER
)
9104 ? (GET_CODE (PATTERN (insn
)) == ADDR_VEC
9105 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
9108 return get_attr_type (insn
);
9111 /* Return true if insn sets the condition codes. */
9114 arc_sets_cc_p (rtx_insn
*insn
)
9116 if (NONJUMP_INSN_P (insn
))
9117 if (rtx_sequence
*seq
= dyn_cast
<rtx_sequence
*> (PATTERN (insn
)))
9118 insn
= seq
->insn (seq
->len () - 1);
9119 return arc_attr_type (insn
) == TYPE_COMPARE
;
9122 /* Return true if INSN is an instruction with a delay slot we may want
9126 arc_need_delay (rtx_insn
*insn
)
9130 if (!flag_delayed_branch
)
9132 /* The return at the end of a function needs a delay slot. */
9133 if (NONJUMP_INSN_P (insn
) && GET_CODE (PATTERN (insn
)) == USE
9134 && (!(next
= next_active_insn (insn
))
9135 || ((!NONJUMP_INSN_P (next
) || GET_CODE (PATTERN (next
)) != SEQUENCE
)
9136 && arc_attr_type (next
) == TYPE_RETURN
))
9137 && (!TARGET_PAD_RETURN
9138 || (prev_active_insn (insn
)
9139 && prev_active_insn (prev_active_insn (insn
))
9140 && prev_active_insn (prev_active_insn (prev_active_insn (insn
))))))
9142 if (NONJUMP_INSN_P (insn
)
9143 ? (GET_CODE (PATTERN (insn
)) == USE
9144 || GET_CODE (PATTERN (insn
)) == CLOBBER
9145 || GET_CODE (PATTERN (insn
)) == SEQUENCE
)
9147 ? (GET_CODE (PATTERN (insn
)) == ADDR_VEC
9148 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
9151 return num_delay_slots (insn
) != 0;
9154 /* Return true if the scheduling pass(es) has/have already run,
9155 i.e. where possible, we should try to mitigate high latencies
9156 by different instruction selection. */
9159 arc_scheduling_not_expected (void)
9161 return cfun
->machine
->arc_reorg_started
;
9164 /* Oddly enough, sometimes we get a zero overhead loop that branch
9165 shortening doesn't think is a loop - observed with compile/pr24883.c
9166 -O3 -fomit-frame-pointer -funroll-loops. Make sure to include the
9167 alignment visible for branch shortening (we actually align the loop
9168 insn before it, but that is equivalent since the loop insn is 4 byte
9172 arc_label_align (rtx label
)
9174 int loop_align
= LOOP_ALIGN (LABEL
);
9176 if (loop_align
> align_labels_log
)
9178 rtx_insn
*prev
= prev_nonnote_insn (label
);
9180 if (prev
&& NONJUMP_INSN_P (prev
)
9181 && GET_CODE (PATTERN (prev
)) == PARALLEL
9182 && recog_memoized (prev
) == CODE_FOR_doloop_begin_i
)
9185 /* Code has a minimum p2 alignment of 1, which we must restore after an
9187 if (align_labels_log
< 1)
9189 rtx_insn
*next
= next_nonnote_nondebug_insn (label
);
9190 if (INSN_P (next
) && recog_memoized (next
) >= 0)
9193 return align_labels_log
;
9196 /* Return true if LABEL is in executable code. */
9199 arc_text_label (rtx_insn
*label
)
9203 /* ??? We use deleted labels like they were still there, see
9204 gcc.c-torture/compile/20000326-2.c . */
9205 gcc_assert (GET_CODE (label
) == CODE_LABEL
9206 || (GET_CODE (label
) == NOTE
9207 && NOTE_KIND (label
) == NOTE_INSN_DELETED_LABEL
));
9208 next
= next_nonnote_insn (label
);
9210 return (!JUMP_TABLE_DATA_P (next
)
9211 || GET_CODE (PATTERN (next
)) != ADDR_VEC
);
9212 else if (!PREV_INSN (label
))
9213 /* ??? sometimes text labels get inserted very late, see
9214 gcc.dg/torture/stackalign/comp-goto-1.c */
9219 /* Return the size of the pretend args for DECL. */
9222 arc_decl_pretend_args (tree decl
)
9224 /* struct function is in DECL_STRUCT_FUNCTION (decl), but no
9225 pretend_args there... See PR38391. */
9226 gcc_assert (decl
== current_function_decl
);
9227 return crtl
->args
.pretend_args_size
;
9230 /* Without this, gcc.dg/tree-prof/bb-reorg.c fails to assemble
9231 when compiling with -O2 -freorder-blocks-and-partition -fprofile-use
9232 -D_PROFILE_USE; delay branch scheduling then follows a crossing jump
9233 to redirect two breqs. */
9236 arc_can_follow_jump (const rtx_insn
*follower
, const rtx_insn
*followee
)
9238 /* ??? get_attr_type is declared to take an rtx. */
9239 union { const rtx_insn
*c
; rtx_insn
*r
; } u
;
9242 if (CROSSING_JUMP_P (followee
))
9243 switch (get_attr_type (u
.r
))
9246 case TYPE_BRCC_NO_DELAY_SLOT
:
9254 /* Implement EPILOGUE__USES.
9255 Return true if REGNO should be added to the deemed uses of the epilogue.
9257 We use the return address
9258 arc_return_address_regs[arc_compute_function_type (cfun)] .
9259 But also, we have to make sure all the register restore instructions
9260 are known to be live in interrupt functions. */
9263 arc_epilogue_uses (int regno
)
9265 if (reload_completed
)
9267 if (ARC_INTERRUPT_P (cfun
->machine
->fn_type
))
9269 if (!fixed_regs
[regno
])
9271 return regno
== arc_return_address_regs
[cfun
->machine
->fn_type
];
9274 return regno
== RETURN_ADDR_REGNUM
;
9277 return regno
== arc_return_address_regs
[arc_compute_function_type (cfun
)];
9280 #ifndef TARGET_NO_LRA
9281 #define TARGET_NO_LRA !TARGET_LRA
9287 return !TARGET_NO_LRA
;
9290 /* ??? Should we define TARGET_REGISTER_PRIORITY? We might perfer to use
9291 Rcq registers, because some insn are shorter with them. OTOH we already
9292 have separate alternatives for this purpose, and other insns don't
9293 mind, so maybe we should rather prefer the other registers?
9294 We need more data, and we can only get that if we allow people to
9297 arc_register_priority (int r
)
9299 switch (arc_lra_priority_tag
)
9301 case ARC_LRA_PRIORITY_NONE
:
9303 case ARC_LRA_PRIORITY_NONCOMPACT
:
9304 return ((((r
& 7) ^ 4) - 4) & 15) != r
;
9305 case ARC_LRA_PRIORITY_COMPACT
:
9306 return ((((r
& 7) ^ 4) - 4) & 15) == r
;
9313 arc_spill_class (reg_class_t
/* orig_class */, machine_mode
)
9315 return GENERAL_REGS
;
9319 arc_legitimize_reload_address (rtx
*p
, machine_mode mode
, int opnum
,
9323 enum reload_type type
= (enum reload_type
) itype
;
9325 if (GET_CODE (x
) == PLUS
9326 && CONST_INT_P (XEXP (x
, 1))
9327 && (RTX_OK_FOR_BASE_P (XEXP (x
, 0), true)
9328 || (REG_P (XEXP (x
, 0))
9329 && reg_equiv_constant (REGNO (XEXP (x
, 0))))))
9331 int scale
= GET_MODE_SIZE (mode
);
9333 rtx index_rtx
= XEXP (x
, 1);
9334 HOST_WIDE_INT offset
= INTVAL (index_rtx
), offset_base
;
9339 if ((scale
-1) & offset
)
9342 offset_base
= (offset
+ (256 << shift
)) & (-512 << shift
);
9343 /* Sometimes the normal form does not suit DImode. We
9344 could avoid that by using smaller ranges, but that
9345 would give less optimized code when SImode is
9347 if (GET_MODE_SIZE (mode
) + offset
- offset_base
<= (256 << shift
))
9352 regno
= REGNO (reg
);
9353 sum2
= sum
= plus_constant (Pmode
, reg
, offset_base
);
9355 if (reg_equiv_constant (regno
))
9357 sum2
= plus_constant (Pmode
, reg_equiv_constant (regno
),
9359 if (GET_CODE (sum2
) == PLUS
)
9360 sum2
= gen_rtx_CONST (Pmode
, sum2
);
9362 *p
= gen_rtx_PLUS (Pmode
, sum
, GEN_INT (offset
- offset_base
));
9363 push_reload (sum2
, NULL_RTX
, &XEXP (*p
, 0), NULL
,
9364 BASE_REG_CLASS
, Pmode
, VOIDmode
, 0, 0, opnum
,
9369 /* We must re-recognize what we created before. */
9370 else if (GET_CODE (x
) == PLUS
9371 && GET_CODE (XEXP (x
, 0)) == PLUS
9372 && CONST_INT_P (XEXP (XEXP (x
, 0), 1))
9373 && REG_P (XEXP (XEXP (x
, 0), 0))
9374 && CONST_INT_P (XEXP (x
, 1)))
9376 /* Because this address is so complex, we know it must have
9377 been created by LEGITIMIZE_RELOAD_ADDRESS before; thus,
9378 it is already unshared, and needs no further unsharing. */
9379 push_reload (XEXP (x
, 0), NULL_RTX
, &XEXP (x
, 0), NULL
,
9380 BASE_REG_CLASS
, Pmode
, VOIDmode
, 0, 0, opnum
, type
);
9386 struct gcc_target targetm
= TARGET_INITIALIZER
;