1 /* Subroutines used for code generation on the Synopsys DesignWare ARC cpu.
2 Copyright (C) 1994-2015 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"
39 #include "fold-const.h"
41 #include "stor-layout.h"
42 #include "stringpool.h"
45 #include "insn-config.h"
46 #include "conditions.h"
47 #include "insn-flags.h"
52 #include "insn-attr.h"
62 #include "diagnostic.h"
63 #include "insn-codes.h"
64 #include "langhooks.h"
66 #include "tm-constrs.h"
67 #include "reload.h" /* For operands_match_p */
72 #include "cfgcleanup.h"
73 #include "tree-pass.h"
75 #include "pass_manager.h"
79 /* Which cpu we're compiling for (A5, ARC600, ARC601, ARC700). */
80 static const char *arc_cpu_string
= "";
82 /* ??? Loads can handle any constant, stores can only handle small ones. */
83 /* OTOH, LIMMs cost extra, so their usefulness is limited. */
84 #define RTX_OK_FOR_OFFSET_P(MODE, X) \
85 (GET_CODE (X) == CONST_INT \
86 && SMALL_INT_RANGE (INTVAL (X), (GET_MODE_SIZE (MODE) - 1) & -4, \
87 (INTVAL (X) & (GET_MODE_SIZE (MODE) - 1) & 3 \
89 : -(-GET_MODE_SIZE (MODE) | -4) >> 1)))
91 #define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X, INDEX, STRICT) \
92 (GET_CODE (X) == PLUS \
93 && RTX_OK_FOR_BASE_P (XEXP (X, 0), (STRICT)) \
94 && ((INDEX && RTX_OK_FOR_INDEX_P (XEXP (X, 1), (STRICT)) \
95 && GET_MODE_SIZE ((MODE)) <= 4) \
96 || RTX_OK_FOR_OFFSET_P (MODE, XEXP (X, 1))))
98 #define LEGITIMATE_SCALED_ADDRESS_P(MODE, X, STRICT) \
99 (GET_CODE (X) == PLUS \
100 && GET_CODE (XEXP (X, 0)) == MULT \
101 && RTX_OK_FOR_INDEX_P (XEXP (XEXP (X, 0), 0), (STRICT)) \
102 && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \
103 && ((GET_MODE_SIZE (MODE) == 2 && INTVAL (XEXP (XEXP (X, 0), 1)) == 2) \
104 || (GET_MODE_SIZE (MODE) == 4 && INTVAL (XEXP (XEXP (X, 0), 1)) == 4)) \
105 && (RTX_OK_FOR_BASE_P (XEXP (X, 1), (STRICT)) \
106 || (flag_pic ? CONST_INT_P (XEXP (X, 1)) : CONSTANT_P (XEXP (X, 1)))))
108 #define LEGITIMATE_SMALL_DATA_ADDRESS_P(X) \
109 (GET_CODE (X) == PLUS \
110 && (REG_P (XEXP ((X), 0)) && REGNO (XEXP ((X), 0)) == SDATA_BASE_REGNUM) \
111 && ((GET_CODE (XEXP((X),1)) == SYMBOL_REF \
112 && SYMBOL_REF_SMALL_P (XEXP ((X), 1))) \
113 || (GET_CODE (XEXP ((X), 1)) == CONST \
114 && GET_CODE (XEXP (XEXP ((X), 1), 0)) == PLUS \
115 && GET_CODE (XEXP (XEXP (XEXP ((X), 1), 0), 0)) == SYMBOL_REF \
116 && SYMBOL_REF_SMALL_P (XEXP (XEXP (XEXP ((X), 1), 0), 0)) \
117 && GET_CODE (XEXP(XEXP (XEXP ((X), 1), 0), 1)) == CONST_INT)))
119 /* Array of valid operand punctuation characters. */
120 char arc_punct_chars
[256];
122 /* State used by arc_ccfsm_advance to implement conditional execution. */
123 struct GTY (()) arc_ccfsm
128 rtx_insn
*target_insn
;
132 #define arc_ccfsm_current cfun->machine->ccfsm_current
134 #define ARC_CCFSM_BRANCH_DELETED_P(STATE) \
135 ((STATE)->state == 1 || (STATE)->state == 2)
137 /* Indicate we're conditionalizing insns now. */
138 #define ARC_CCFSM_RECORD_BRANCH_DELETED(STATE) \
139 ((STATE)->state += 2)
141 #define ARC_CCFSM_COND_EXEC_P(STATE) \
142 ((STATE)->state == 3 || (STATE)->state == 4 || (STATE)->state == 5 \
143 || current_insn_predicate)
145 /* Check if INSN has a 16 bit opcode considering struct arc_ccfsm *STATE. */
146 #define CCFSM_ISCOMPACT(INSN,STATE) \
147 (ARC_CCFSM_COND_EXEC_P (STATE) \
148 ? (get_attr_iscompact (INSN) == ISCOMPACT_TRUE \
149 || get_attr_iscompact (INSN) == ISCOMPACT_TRUE_LIMM) \
150 : get_attr_iscompact (INSN) != ISCOMPACT_FALSE)
152 /* Likewise, but also consider that INSN might be in a delay slot of JUMP. */
153 #define CCFSM_DBR_ISCOMPACT(INSN,JUMP,STATE) \
154 ((ARC_CCFSM_COND_EXEC_P (STATE) \
156 && INSN_ANNULLED_BRANCH_P (JUMP) \
157 && (TARGET_AT_DBR_CONDEXEC || INSN_FROM_TARGET_P (INSN)))) \
158 ? (get_attr_iscompact (INSN) == ISCOMPACT_TRUE \
159 || get_attr_iscompact (INSN) == ISCOMPACT_TRUE_LIMM) \
160 : get_attr_iscompact (INSN) != ISCOMPACT_FALSE)
162 /* The maximum number of insns skipped which will be conditionalised if
164 /* When optimizing for speed:
165 Let p be the probability that the potentially skipped insns need to
166 be executed, pn the cost of a correctly predicted non-taken branch,
167 mt the cost of a mis/non-predicted taken branch,
168 mn mispredicted non-taken, pt correctly predicted taken ;
169 costs expressed in numbers of instructions like the ones considered
171 Unfortunately we don't have a measure of predictability - this
172 is linked to probability only in that in the no-eviction-scenario
173 there is a lower bound 1 - 2 * min (p, 1-p), and a somewhat larger
174 value that can be assumed *if* the distribution is perfectly random.
175 A predictability of 1 is perfectly plausible not matter what p is,
176 because the decision could be dependent on an invocation parameter
178 For large p, we want MAX_INSNS_SKIPPED == pn/(1-p) + mt - pn
179 For small p, we want MAX_INSNS_SKIPPED == pt
181 When optimizing for size:
182 We want to skip insn unless we could use 16 opcodes for the
183 non-conditionalized insn to balance the branch length or more.
184 Performance can be tie-breaker. */
185 /* If the potentially-skipped insns are likely to be executed, we'll
186 generally save one non-taken branch
188 this to be no less than the 1/p */
189 #define MAX_INSNS_SKIPPED 3
191 /* The values of unspec's first field. */
201 ARC_BUILTIN_NORM
= 3,
202 ARC_BUILTIN_NORMW
= 4,
203 ARC_BUILTIN_SWAP
= 5,
205 ARC_BUILTIN_DIVAW
= 7,
207 ARC_BUILTIN_MUL64
= 9,
208 ARC_BUILTIN_MULU64
= 10,
209 ARC_BUILTIN_RTIE
= 11,
210 ARC_BUILTIN_SYNC
= 12,
211 ARC_BUILTIN_CORE_READ
= 13,
212 ARC_BUILTIN_CORE_WRITE
= 14,
213 ARC_BUILTIN_FLAG
= 15,
216 ARC_BUILTIN_SLEEP
= 18,
217 ARC_BUILTIN_SWI
= 19,
218 ARC_BUILTIN_TRAP_S
= 20,
219 ARC_BUILTIN_UNIMP_S
= 21,
220 ARC_BUILTIN_ALIGNED
= 22,
222 /* Sentinel to mark start of simd builtins. */
223 ARC_SIMD_BUILTIN_BEGIN
= 1000,
225 ARC_SIMD_BUILTIN_VADDAW
= 1001,
226 ARC_SIMD_BUILTIN_VADDW
= 1002,
227 ARC_SIMD_BUILTIN_VAVB
= 1003,
228 ARC_SIMD_BUILTIN_VAVRB
= 1004,
229 ARC_SIMD_BUILTIN_VDIFAW
= 1005,
230 ARC_SIMD_BUILTIN_VDIFW
= 1006,
231 ARC_SIMD_BUILTIN_VMAXAW
= 1007,
232 ARC_SIMD_BUILTIN_VMAXW
= 1008,
233 ARC_SIMD_BUILTIN_VMINAW
= 1009,
234 ARC_SIMD_BUILTIN_VMINW
= 1010,
235 ARC_SIMD_BUILTIN_VMULAW
= 1011,
236 ARC_SIMD_BUILTIN_VMULFAW
= 1012,
237 ARC_SIMD_BUILTIN_VMULFW
= 1013,
238 ARC_SIMD_BUILTIN_VMULW
= 1014,
239 ARC_SIMD_BUILTIN_VSUBAW
= 1015,
240 ARC_SIMD_BUILTIN_VSUBW
= 1016,
241 ARC_SIMD_BUILTIN_VSUMMW
= 1017,
242 ARC_SIMD_BUILTIN_VAND
= 1018,
243 ARC_SIMD_BUILTIN_VANDAW
= 1019,
244 ARC_SIMD_BUILTIN_VBIC
= 1020,
245 ARC_SIMD_BUILTIN_VBICAW
= 1021,
246 ARC_SIMD_BUILTIN_VOR
= 1022,
247 ARC_SIMD_BUILTIN_VXOR
= 1023,
248 ARC_SIMD_BUILTIN_VXORAW
= 1024,
249 ARC_SIMD_BUILTIN_VEQW
= 1025,
250 ARC_SIMD_BUILTIN_VLEW
= 1026,
251 ARC_SIMD_BUILTIN_VLTW
= 1027,
252 ARC_SIMD_BUILTIN_VNEW
= 1028,
253 ARC_SIMD_BUILTIN_VMR1AW
= 1029,
254 ARC_SIMD_BUILTIN_VMR1W
= 1030,
255 ARC_SIMD_BUILTIN_VMR2AW
= 1031,
256 ARC_SIMD_BUILTIN_VMR2W
= 1032,
257 ARC_SIMD_BUILTIN_VMR3AW
= 1033,
258 ARC_SIMD_BUILTIN_VMR3W
= 1034,
259 ARC_SIMD_BUILTIN_VMR4AW
= 1035,
260 ARC_SIMD_BUILTIN_VMR4W
= 1036,
261 ARC_SIMD_BUILTIN_VMR5AW
= 1037,
262 ARC_SIMD_BUILTIN_VMR5W
= 1038,
263 ARC_SIMD_BUILTIN_VMR6AW
= 1039,
264 ARC_SIMD_BUILTIN_VMR6W
= 1040,
265 ARC_SIMD_BUILTIN_VMR7AW
= 1041,
266 ARC_SIMD_BUILTIN_VMR7W
= 1042,
267 ARC_SIMD_BUILTIN_VMRB
= 1043,
268 ARC_SIMD_BUILTIN_VH264F
= 1044,
269 ARC_SIMD_BUILTIN_VH264FT
= 1045,
270 ARC_SIMD_BUILTIN_VH264FW
= 1046,
271 ARC_SIMD_BUILTIN_VVC1F
= 1047,
272 ARC_SIMD_BUILTIN_VVC1FT
= 1048,
274 /* Va, Vb, rlimm instructions. */
275 ARC_SIMD_BUILTIN_VBADDW
= 1050,
276 ARC_SIMD_BUILTIN_VBMAXW
= 1051,
277 ARC_SIMD_BUILTIN_VBMINW
= 1052,
278 ARC_SIMD_BUILTIN_VBMULAW
= 1053,
279 ARC_SIMD_BUILTIN_VBMULFW
= 1054,
280 ARC_SIMD_BUILTIN_VBMULW
= 1055,
281 ARC_SIMD_BUILTIN_VBRSUBW
= 1056,
282 ARC_SIMD_BUILTIN_VBSUBW
= 1057,
284 /* Va, Vb, Ic instructions. */
285 ARC_SIMD_BUILTIN_VASRW
= 1060,
286 ARC_SIMD_BUILTIN_VSR8
= 1061,
287 ARC_SIMD_BUILTIN_VSR8AW
= 1062,
289 /* Va, Vb, u6 instructions. */
290 ARC_SIMD_BUILTIN_VASRRWi
= 1065,
291 ARC_SIMD_BUILTIN_VASRSRWi
= 1066,
292 ARC_SIMD_BUILTIN_VASRWi
= 1067,
293 ARC_SIMD_BUILTIN_VASRPWBi
= 1068,
294 ARC_SIMD_BUILTIN_VASRRPWBi
= 1069,
295 ARC_SIMD_BUILTIN_VSR8AWi
= 1070,
296 ARC_SIMD_BUILTIN_VSR8i
= 1071,
298 /* Va, Vb, u8 (simm) instructions. */
299 ARC_SIMD_BUILTIN_VMVAW
= 1075,
300 ARC_SIMD_BUILTIN_VMVW
= 1076,
301 ARC_SIMD_BUILTIN_VMVZW
= 1077,
302 ARC_SIMD_BUILTIN_VD6TAPF
= 1078,
304 /* Va, rlimm, u8 (simm) instructions. */
305 ARC_SIMD_BUILTIN_VMOVAW
= 1080,
306 ARC_SIMD_BUILTIN_VMOVW
= 1081,
307 ARC_SIMD_BUILTIN_VMOVZW
= 1082,
309 /* Va, Vb instructions. */
310 ARC_SIMD_BUILTIN_VABSAW
= 1085,
311 ARC_SIMD_BUILTIN_VABSW
= 1086,
312 ARC_SIMD_BUILTIN_VADDSUW
= 1087,
313 ARC_SIMD_BUILTIN_VSIGNW
= 1088,
314 ARC_SIMD_BUILTIN_VEXCH1
= 1089,
315 ARC_SIMD_BUILTIN_VEXCH2
= 1090,
316 ARC_SIMD_BUILTIN_VEXCH4
= 1091,
317 ARC_SIMD_BUILTIN_VUPBAW
= 1092,
318 ARC_SIMD_BUILTIN_VUPBW
= 1093,
319 ARC_SIMD_BUILTIN_VUPSBAW
= 1094,
320 ARC_SIMD_BUILTIN_VUPSBW
= 1095,
322 ARC_SIMD_BUILTIN_VDIRUN
= 1100,
323 ARC_SIMD_BUILTIN_VDORUN
= 1101,
324 ARC_SIMD_BUILTIN_VDIWR
= 1102,
325 ARC_SIMD_BUILTIN_VDOWR
= 1103,
327 ARC_SIMD_BUILTIN_VREC
= 1105,
328 ARC_SIMD_BUILTIN_VRUN
= 1106,
329 ARC_SIMD_BUILTIN_VRECRUN
= 1107,
330 ARC_SIMD_BUILTIN_VENDREC
= 1108,
332 ARC_SIMD_BUILTIN_VLD32WH
= 1110,
333 ARC_SIMD_BUILTIN_VLD32WL
= 1111,
334 ARC_SIMD_BUILTIN_VLD64
= 1112,
335 ARC_SIMD_BUILTIN_VLD32
= 1113,
336 ARC_SIMD_BUILTIN_VLD64W
= 1114,
337 ARC_SIMD_BUILTIN_VLD128
= 1115,
338 ARC_SIMD_BUILTIN_VST128
= 1116,
339 ARC_SIMD_BUILTIN_VST64
= 1117,
341 ARC_SIMD_BUILTIN_VST16_N
= 1120,
342 ARC_SIMD_BUILTIN_VST32_N
= 1121,
344 ARC_SIMD_BUILTIN_VINTI
= 1201,
349 /* A nop is needed between a 4 byte insn that sets the condition codes and
350 a branch that uses them (the same isn't true for an 8 byte insn that sets
351 the condition codes). Set by arc_ccfsm_advance. Used by
352 arc_print_operand. */
354 static int get_arc_condition_code (rtx
);
356 static tree
arc_handle_interrupt_attribute (tree
*, tree
, tree
, int, bool *);
358 /* Initialized arc_attribute_table to NULL since arc doesnot have any
359 machine specific supported attributes. */
360 const struct attribute_spec arc_attribute_table
[] =
362 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
363 affects_type_identity } */
364 { "interrupt", 1, 1, true, false, false, arc_handle_interrupt_attribute
, true },
365 /* Function calls made to this symbol must be done indirectly, because
366 it may lie outside of the 21/25 bit addressing range of a normal function
368 { "long_call", 0, 0, false, true, true, NULL
, false },
369 /* Whereas these functions are always known to reside within the 25 bit
370 addressing range of unconditionalized bl. */
371 { "medium_call", 0, 0, false, true, true, NULL
, false },
372 /* And these functions are always known to reside within the 21 bit
373 addressing range of blcc. */
374 { "short_call", 0, 0, false, true, true, NULL
, false },
375 { NULL
, 0, 0, false, false, false, NULL
, false }
377 static int arc_comp_type_attributes (const_tree
, const_tree
);
378 static void arc_file_start (void);
379 static void arc_internal_label (FILE *, const char *, unsigned long);
380 static void arc_output_mi_thunk (FILE *, tree
, HOST_WIDE_INT
, HOST_WIDE_INT
,
382 static int arc_address_cost (rtx
, machine_mode
, addr_space_t
, bool);
383 static void arc_encode_section_info (tree decl
, rtx rtl
, int first
);
385 static void arc_init_builtins (void);
386 static rtx
arc_expand_builtin (tree
, rtx
, rtx
, machine_mode
, int);
388 static int branch_dest (rtx
);
390 static void arc_output_pic_addr_const (FILE *, rtx
, int);
391 void emit_pic_move (rtx
*, machine_mode
);
392 bool arc_legitimate_pic_operand_p (rtx
);
393 static bool arc_function_ok_for_sibcall (tree
, tree
);
394 static rtx
arc_function_value (const_tree
, const_tree
, bool);
395 const char * output_shift (rtx
*);
396 static void arc_reorg (void);
397 static bool arc_in_small_data_p (const_tree
);
399 static void arc_init_reg_tables (void);
400 static bool arc_return_in_memory (const_tree
, const_tree
);
401 static void arc_init_simd_builtins (void);
402 static bool arc_vector_mode_supported_p (machine_mode
);
404 static bool arc_can_use_doloop_p (const widest_int
&, const widest_int
&,
406 static const char *arc_invalid_within_doloop (const rtx_insn
*);
408 static void output_short_suffix (FILE *file
);
410 static bool arc_frame_pointer_required (void);
412 static bool arc_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT
,
414 enum by_pieces_operation op
,
417 /* Implements target hook vector_mode_supported_p. */
420 arc_vector_mode_supported_p (machine_mode mode
)
422 if (!TARGET_SIMD_SET
)
425 if ((mode
== V4SImode
)
426 || (mode
== V8HImode
))
433 /* TARGET_PRESERVE_RELOAD_P is still awaiting patch re-evaluation / review. */
434 static bool arc_preserve_reload_p (rtx in
) ATTRIBUTE_UNUSED
;
435 static rtx
arc_delegitimize_address (rtx
);
436 static bool arc_can_follow_jump (const rtx_insn
*follower
,
437 const rtx_insn
*followee
);
439 static rtx
frame_insn (rtx
);
440 static void arc_function_arg_advance (cumulative_args_t
, machine_mode
,
442 static rtx
arc_legitimize_address_0 (rtx
, rtx
, machine_mode mode
);
444 static void arc_finalize_pic (void);
446 /* initialize the GCC target structure. */
447 #undef TARGET_COMP_TYPE_ATTRIBUTES
448 #define TARGET_COMP_TYPE_ATTRIBUTES arc_comp_type_attributes
449 #undef TARGET_ASM_FILE_START
450 #define TARGET_ASM_FILE_START arc_file_start
451 #undef TARGET_ATTRIBUTE_TABLE
452 #define TARGET_ATTRIBUTE_TABLE arc_attribute_table
453 #undef TARGET_ASM_INTERNAL_LABEL
454 #define TARGET_ASM_INTERNAL_LABEL arc_internal_label
455 #undef TARGET_RTX_COSTS
456 #define TARGET_RTX_COSTS arc_rtx_costs
457 #undef TARGET_ADDRESS_COST
458 #define TARGET_ADDRESS_COST arc_address_cost
460 #undef TARGET_ENCODE_SECTION_INFO
461 #define TARGET_ENCODE_SECTION_INFO arc_encode_section_info
463 #undef TARGET_CANNOT_FORCE_CONST_MEM
464 #define TARGET_CANNOT_FORCE_CONST_MEM arc_cannot_force_const_mem
466 #undef TARGET_INIT_BUILTINS
467 #define TARGET_INIT_BUILTINS arc_init_builtins
469 #undef TARGET_EXPAND_BUILTIN
470 #define TARGET_EXPAND_BUILTIN arc_expand_builtin
472 #undef TARGET_ASM_OUTPUT_MI_THUNK
473 #define TARGET_ASM_OUTPUT_MI_THUNK arc_output_mi_thunk
475 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
476 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
478 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
479 #define TARGET_FUNCTION_OK_FOR_SIBCALL arc_function_ok_for_sibcall
481 #undef TARGET_MACHINE_DEPENDENT_REORG
482 #define TARGET_MACHINE_DEPENDENT_REORG arc_reorg
484 #undef TARGET_IN_SMALL_DATA_P
485 #define TARGET_IN_SMALL_DATA_P arc_in_small_data_p
487 #undef TARGET_PROMOTE_FUNCTION_MODE
488 #define TARGET_PROMOTE_FUNCTION_MODE \
489 default_promote_function_mode_always_promote
491 #undef TARGET_PROMOTE_PROTOTYPES
492 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
494 #undef TARGET_RETURN_IN_MEMORY
495 #define TARGET_RETURN_IN_MEMORY arc_return_in_memory
496 #undef TARGET_PASS_BY_REFERENCE
497 #define TARGET_PASS_BY_REFERENCE arc_pass_by_reference
499 #undef TARGET_SETUP_INCOMING_VARARGS
500 #define TARGET_SETUP_INCOMING_VARARGS arc_setup_incoming_varargs
502 #undef TARGET_ARG_PARTIAL_BYTES
503 #define TARGET_ARG_PARTIAL_BYTES arc_arg_partial_bytes
505 #undef TARGET_MUST_PASS_IN_STACK
506 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
508 #undef TARGET_FUNCTION_VALUE
509 #define TARGET_FUNCTION_VALUE arc_function_value
511 #undef TARGET_SCHED_ADJUST_PRIORITY
512 #define TARGET_SCHED_ADJUST_PRIORITY arc_sched_adjust_priority
514 #undef TARGET_VECTOR_MODE_SUPPORTED_P
515 #define TARGET_VECTOR_MODE_SUPPORTED_P arc_vector_mode_supported_p
517 #undef TARGET_CAN_USE_DOLOOP_P
518 #define TARGET_CAN_USE_DOLOOP_P arc_can_use_doloop_p
520 #undef TARGET_INVALID_WITHIN_DOLOOP
521 #define TARGET_INVALID_WITHIN_DOLOOP arc_invalid_within_doloop
523 #undef TARGET_PRESERVE_RELOAD_P
524 #define TARGET_PRESERVE_RELOAD_P arc_preserve_reload_p
526 #undef TARGET_CAN_FOLLOW_JUMP
527 #define TARGET_CAN_FOLLOW_JUMP arc_can_follow_jump
529 #undef TARGET_DELEGITIMIZE_ADDRESS
530 #define TARGET_DELEGITIMIZE_ADDRESS arc_delegitimize_address
532 #undef TARGET_USE_BY_PIECES_INFRASTRUCTURE_P
533 #define TARGET_USE_BY_PIECES_INFRASTRUCTURE_P \
534 arc_use_by_pieces_infrastructure_p
536 /* Usually, we will be able to scale anchor offsets.
537 When this fails, we want LEGITIMIZE_ADDRESS to kick in. */
538 #undef TARGET_MIN_ANCHOR_OFFSET
539 #define TARGET_MIN_ANCHOR_OFFSET (-1024)
540 #undef TARGET_MAX_ANCHOR_OFFSET
541 #define TARGET_MAX_ANCHOR_OFFSET (1020)
543 #undef TARGET_SECONDARY_RELOAD
544 #define TARGET_SECONDARY_RELOAD arc_secondary_reload
546 #define TARGET_OPTION_OVERRIDE arc_override_options
548 #define TARGET_CONDITIONAL_REGISTER_USAGE arc_conditional_register_usage
550 #define TARGET_TRAMPOLINE_INIT arc_initialize_trampoline
552 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS arc_trampoline_adjust_address
554 #define TARGET_CAN_ELIMINATE arc_can_eliminate
556 #define TARGET_FRAME_POINTER_REQUIRED arc_frame_pointer_required
558 #define TARGET_FUNCTION_ARG arc_function_arg
560 #define TARGET_FUNCTION_ARG_ADVANCE arc_function_arg_advance
562 #define TARGET_LEGITIMATE_CONSTANT_P arc_legitimate_constant_p
564 #define TARGET_LEGITIMATE_ADDRESS_P arc_legitimate_address_p
566 #define TARGET_MODE_DEPENDENT_ADDRESS_P arc_mode_dependent_address_p
568 #define TARGET_LEGITIMIZE_ADDRESS arc_legitimize_address
570 #define TARGET_ADJUST_INSN_LENGTH arc_adjust_insn_length
572 #define TARGET_INSN_LENGTH_PARAMETERS arc_insn_length_parameters
575 #define TARGET_LRA_P arc_lra_p
576 #define TARGET_REGISTER_PRIORITY arc_register_priority
577 /* Stores with scaled offsets have different displacement ranges. */
578 #define TARGET_DIFFERENT_ADDR_DISPLACEMENT_P hook_bool_void_true
579 #define TARGET_SPILL_CLASS arc_spill_class
581 #include "target-def.h"
583 #undef TARGET_ASM_ALIGNED_HI_OP
584 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
585 #undef TARGET_ASM_ALIGNED_SI_OP
586 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
588 /* Try to keep the (mov:DF _, reg) as early as possible so
589 that the d<add/sub/mul>h-lr insns appear together and can
590 use the peephole2 pattern. */
593 arc_sched_adjust_priority (rtx_insn
*insn
, int priority
)
595 rtx set
= single_set (insn
);
597 && GET_MODE (SET_SRC(set
)) == DFmode
598 && GET_CODE (SET_SRC(set
)) == REG
)
600 /* Incrementing priority by 20 (empirically derived). */
601 return priority
+ 20;
608 arc_secondary_reload (bool in_p
, rtx x
, reg_class_t cl
, machine_mode
,
609 secondary_reload_info
*)
611 if (cl
== DOUBLE_REGS
)
614 /* The loop counter register can be stored, but not loaded directly. */
615 if ((cl
== LPCOUNT_REG
|| cl
== WRITABLE_CORE_REGS
)
616 && in_p
&& MEM_P (x
))
621 static unsigned arc_ifcvt (void);
625 const pass_data pass_data_arc_ifcvt
=
628 "arc_ifcvt", /* name */
629 OPTGROUP_NONE
, /* optinfo_flags */
630 TV_IFCVT2
, /* tv_id */
631 0, /* properties_required */
632 0, /* properties_provided */
633 0, /* properties_destroyed */
634 0, /* todo_flags_start */
635 TODO_df_finish
/* todo_flags_finish */
638 class pass_arc_ifcvt
: public rtl_opt_pass
641 pass_arc_ifcvt(gcc::context
*ctxt
)
642 : rtl_opt_pass(pass_data_arc_ifcvt
, ctxt
)
645 /* opt_pass methods: */
646 opt_pass
* clone () { return new pass_arc_ifcvt (m_ctxt
); }
647 virtual unsigned int execute (function
*) { return arc_ifcvt (); }
653 make_pass_arc_ifcvt (gcc::context
*ctxt
)
655 return new pass_arc_ifcvt (ctxt
);
658 static unsigned arc_predicate_delay_insns (void);
662 const pass_data pass_data_arc_predicate_delay_insns
=
665 "arc_predicate_delay_insns", /* name */
666 OPTGROUP_NONE
, /* optinfo_flags */
667 TV_IFCVT2
, /* tv_id */
668 0, /* properties_required */
669 0, /* properties_provided */
670 0, /* properties_destroyed */
671 0, /* todo_flags_start */
672 TODO_df_finish
/* todo_flags_finish */
675 class pass_arc_predicate_delay_insns
: public rtl_opt_pass
678 pass_arc_predicate_delay_insns(gcc::context
*ctxt
)
679 : rtl_opt_pass(pass_data_arc_predicate_delay_insns
, ctxt
)
682 /* opt_pass methods: */
683 virtual unsigned int execute (function
*)
685 return arc_predicate_delay_insns ();
692 make_pass_arc_predicate_delay_insns (gcc::context
*ctxt
)
694 return new pass_arc_predicate_delay_insns (ctxt
);
697 /* Called by OVERRIDE_OPTIONS to initialize various things. */
702 enum attr_tune tune_dflt
= TUNE_NONE
;
706 arc_cpu_string
= "A5";
708 else if (TARGET_ARC600
)
710 arc_cpu_string
= "ARC600";
711 tune_dflt
= TUNE_ARC600
;
713 else if (TARGET_ARC601
)
715 arc_cpu_string
= "ARC601";
716 tune_dflt
= TUNE_ARC600
;
718 else if (TARGET_ARC700
)
720 arc_cpu_string
= "ARC700";
721 tune_dflt
= TUNE_ARC700_4_2_STD
;
725 if (arc_tune
== TUNE_NONE
)
726 arc_tune
= tune_dflt
;
727 /* Note: arc_multcost is only used in rtx_cost if speed is true. */
728 if (arc_multcost
< 0)
731 case TUNE_ARC700_4_2_STD
:
733 max throughput (1 multiply + 4 other insns) / 5 cycles. */
734 arc_multcost
= COSTS_N_INSNS (4);
735 if (TARGET_NOMPY_SET
)
736 arc_multcost
= COSTS_N_INSNS (30);
738 case TUNE_ARC700_4_2_XMAC
:
740 max throughput (1 multiply + 2 other insns) / 3 cycles. */
741 arc_multcost
= COSTS_N_INSNS (3);
742 if (TARGET_NOMPY_SET
)
743 arc_multcost
= COSTS_N_INSNS (30);
746 if (TARGET_MUL64_SET
)
748 arc_multcost
= COSTS_N_INSNS (4);
753 arc_multcost
= COSTS_N_INSNS (30);
757 /* Support mul64 generation only for A5 and ARC600. */
758 if (TARGET_MUL64_SET
&& TARGET_ARC700
)
759 error ("-mmul64 not supported for ARC700");
761 /* MPY instructions valid only for ARC700. */
762 if (TARGET_NOMPY_SET
&& !TARGET_ARC700
)
763 error ("-mno-mpy supported only for ARC700");
765 /* mul/mac instructions only for ARC600. */
766 if (TARGET_MULMAC_32BY16_SET
&& !(TARGET_ARC600
|| TARGET_ARC601
))
767 error ("-mmul32x16 supported only for ARC600 or ARC601");
769 if (!TARGET_DPFP
&& TARGET_DPFP_DISABLE_LRSR
)
770 error ("-mno-dpfp-lrsr supported only with -mdpfp");
772 /* FPX-1. No fast and compact together. */
773 if ((TARGET_DPFP_FAST_SET
&& TARGET_DPFP_COMPACT_SET
)
774 || (TARGET_SPFP_FAST_SET
&& TARGET_SPFP_COMPACT_SET
))
775 error ("FPX fast and compact options cannot be specified together");
777 /* FPX-2. No fast-spfp for arc600 or arc601. */
778 if (TARGET_SPFP_FAST_SET
&& (TARGET_ARC600
|| TARGET_ARC601
))
779 error ("-mspfp_fast not available on ARC600 or ARC601");
781 /* FPX-3. No FPX extensions on pre-ARC600 cores. */
782 if ((TARGET_DPFP
|| TARGET_SPFP
)
783 && !(TARGET_ARC600
|| TARGET_ARC601
|| TARGET_ARC700
))
784 error ("FPX extensions not available on pre-ARC600 cores");
786 /* Warn for unimplemented PIC in pre-ARC700 cores, and disable flag_pic. */
787 if (flag_pic
&& !TARGET_ARC700
)
789 warning (DK_WARNING
, "PIC is not supported for %s. Generating non-PIC code only..", arc_cpu_string
);
793 arc_init_reg_tables ();
795 /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P. */
796 memset (arc_punct_chars
, 0, sizeof (arc_punct_chars
));
797 arc_punct_chars
['#'] = 1;
798 arc_punct_chars
['*'] = 1;
799 arc_punct_chars
['?'] = 1;
800 arc_punct_chars
['!'] = 1;
801 arc_punct_chars
['^'] = 1;
802 arc_punct_chars
['&'] = 1;
804 if (optimize
> 1 && !TARGET_NO_COND_EXEC
)
806 /* There are two target-independent ifcvt passes, and arc_reorg may do
807 one or more arc_ifcvt calls. */
808 opt_pass
*pass_arc_ifcvt_4
= make_pass_arc_ifcvt (g
);
809 struct register_pass_info arc_ifcvt4_info
810 = { pass_arc_ifcvt_4
, "dbr", 1, PASS_POS_INSERT_AFTER
};
811 struct register_pass_info arc_ifcvt5_info
812 = { pass_arc_ifcvt_4
->clone (), "shorten", 1, PASS_POS_INSERT_BEFORE
};
814 register_pass (&arc_ifcvt4_info
);
815 register_pass (&arc_ifcvt5_info
);
818 if (flag_delayed_branch
)
820 opt_pass
*pass_arc_predicate_delay_insns
821 = make_pass_arc_predicate_delay_insns (g
);
822 struct register_pass_info arc_predicate_delay_info
823 = { pass_arc_predicate_delay_insns
, "dbr", 1, PASS_POS_INSERT_AFTER
};
825 register_pass (&arc_predicate_delay_info
);
829 /* Check ARC options, generate derived target attributes. */
832 arc_override_options (void)
834 if (arc_cpu
== PROCESSOR_NONE
)
835 arc_cpu
= PROCESSOR_ARC700
;
837 if (arc_size_opt_level
== 3)
841 target_flags
|= MASK_NO_SDATA_SET
;
843 if (flag_no_common
== 255)
844 flag_no_common
= !TARGET_NO_SDATA_SET
;
846 /* TARGET_COMPACT_CASESI needs the "q" register class. */ \
847 if (TARGET_MIXED_CODE
)
850 TARGET_COMPACT_CASESI
= 0;
851 if (TARGET_COMPACT_CASESI
)
852 TARGET_CASE_VECTOR_PC_RELATIVE
= 1;
854 /* These need to be done at start up. It's convenient to do them here. */
858 /* The condition codes of the ARC, and the inverse function. */
859 /* For short branches, the "c" / "nc" names are not defined in the ARC
860 Programmers manual, so we have to use "lo" / "hs"" instead. */
861 static const char *arc_condition_codes
[] =
863 "al", 0, "eq", "ne", "p", "n", "lo", "hs", "v", "nv",
864 "gt", "le", "ge", "lt", "hi", "ls", "pnz", 0
867 enum arc_cc_code_index
869 ARC_CC_AL
, ARC_CC_EQ
= ARC_CC_AL
+2, ARC_CC_NE
, ARC_CC_P
, ARC_CC_N
,
870 ARC_CC_C
, ARC_CC_NC
, ARC_CC_V
, ARC_CC_NV
,
871 ARC_CC_GT
, ARC_CC_LE
, ARC_CC_GE
, ARC_CC_LT
, ARC_CC_HI
, ARC_CC_LS
, ARC_CC_PNZ
,
872 ARC_CC_LO
= ARC_CC_C
, ARC_CC_HS
= ARC_CC_NC
875 #define ARC_INVERSE_CONDITION_CODE(X) ((X) ^ 1)
877 /* Returns the index of the ARC condition code string in
878 `arc_condition_codes'. COMPARISON should be an rtx like
879 `(eq (...) (...))'. */
882 get_arc_condition_code (rtx comparison
)
884 switch (GET_MODE (XEXP (comparison
, 0)))
887 case SImode
: /* For BRcc. */
888 switch (GET_CODE (comparison
))
890 case EQ
: return ARC_CC_EQ
;
891 case NE
: return ARC_CC_NE
;
892 case GT
: return ARC_CC_GT
;
893 case LE
: return ARC_CC_LE
;
894 case GE
: return ARC_CC_GE
;
895 case LT
: return ARC_CC_LT
;
896 case GTU
: return ARC_CC_HI
;
897 case LEU
: return ARC_CC_LS
;
898 case LTU
: return ARC_CC_LO
;
899 case GEU
: return ARC_CC_HS
;
900 default : gcc_unreachable ();
903 switch (GET_CODE (comparison
))
905 case EQ
: return ARC_CC_EQ
;
906 case NE
: return ARC_CC_NE
;
907 case GE
: return ARC_CC_P
;
908 case LT
: return ARC_CC_N
;
909 case GT
: return ARC_CC_PNZ
;
910 default : gcc_unreachable ();
913 switch (GET_CODE (comparison
))
915 case EQ
: return ARC_CC_EQ
;
916 case NE
: return ARC_CC_NE
;
917 default : gcc_unreachable ();
920 switch (GET_CODE (comparison
))
922 case LTU
: return ARC_CC_C
;
923 case GEU
: return ARC_CC_NC
;
924 default : gcc_unreachable ();
927 if (TARGET_ARGONAUT_SET
&& TARGET_SPFP
)
928 switch (GET_CODE (comparison
))
930 case GT
: return ARC_CC_N
;
931 case UNLE
: return ARC_CC_P
;
932 default : gcc_unreachable ();
935 switch (GET_CODE (comparison
))
937 case GT
: return ARC_CC_HI
;
938 case UNLE
: return ARC_CC_LS
;
939 default : gcc_unreachable ();
942 /* Same for FPX and non-FPX. */
943 switch (GET_CODE (comparison
))
945 case GE
: return ARC_CC_HS
;
946 case UNLT
: return ARC_CC_LO
;
947 default : gcc_unreachable ();
950 switch (GET_CODE (comparison
))
952 case UNEQ
: return ARC_CC_EQ
;
953 case LTGT
: return ARC_CC_NE
;
954 default : gcc_unreachable ();
957 switch (GET_CODE (comparison
))
959 case UNORDERED
: return ARC_CC_C
;
960 case ORDERED
: return ARC_CC_NC
;
961 default : gcc_unreachable ();
964 switch (GET_CODE (comparison
))
966 case EQ
: return ARC_CC_EQ
;
967 case NE
: return ARC_CC_NE
;
968 case UNORDERED
: return ARC_CC_C
;
969 case ORDERED
: return ARC_CC_NC
;
970 case LTGT
: return ARC_CC_HI
;
971 case UNEQ
: return ARC_CC_LS
;
972 default : gcc_unreachable ();
974 default : gcc_unreachable ();
980 /* Return true if COMPARISON has a short form that can accomodate OFFSET. */
983 arc_short_comparison_p (rtx comparison
, int offset
)
985 gcc_assert (ARC_CC_NC
== ARC_CC_HS
);
986 gcc_assert (ARC_CC_C
== ARC_CC_LO
);
987 switch (get_arc_condition_code (comparison
))
989 case ARC_CC_EQ
: case ARC_CC_NE
:
990 return offset
>= -512 && offset
<= 506;
991 case ARC_CC_GT
: case ARC_CC_LE
: case ARC_CC_GE
: case ARC_CC_LT
:
992 case ARC_CC_HI
: case ARC_CC_LS
: case ARC_CC_LO
: case ARC_CC_HS
:
993 return offset
>= -64 && offset
<= 58;
999 /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
1000 return the mode to be used for the comparison. */
1003 arc_select_cc_mode (enum rtx_code op
, rtx x
, rtx y
)
1005 machine_mode mode
= GET_MODE (x
);
1008 /* For an operation that sets the condition codes as a side-effect, the
1009 C and V flags is not set as for cmp, so we can only use comparisons where
1010 this doesn't matter. (For LT and GE we can use "mi" and "pl"
1012 /* ??? We could use "pnz" for greater than zero, however, we could then
1013 get into trouble because the comparison could not be reversed. */
1014 if (GET_MODE_CLASS (mode
) == MODE_INT
1016 && (op
== EQ
|| op
== NE
1017 || ((op
== LT
|| op
== GE
) && GET_MODE_SIZE (GET_MODE (x
)) <= 4)))
1020 /* add.f for if (a+b) */
1022 && GET_CODE (y
) == NEG
1023 && (op
== EQ
|| op
== NE
))
1026 /* Check if this is a test suitable for bxor.f . */
1027 if (mode
== SImode
&& (op
== EQ
|| op
== NE
) && CONST_INT_P (y
)
1028 && ((INTVAL (y
) - 1) & INTVAL (y
)) == 0
1032 /* Check if this is a test suitable for add / bmsk.f . */
1033 if (mode
== SImode
&& (op
== EQ
|| op
== NE
) && CONST_INT_P (y
)
1034 && GET_CODE (x
) == AND
&& CONST_INT_P ((x1
= XEXP (x
, 1)))
1035 && ((INTVAL (x1
) + 1) & INTVAL (x1
)) == 0
1036 && (~INTVAL (x1
) | INTVAL (y
)) < 0
1037 && (~INTVAL (x1
) | INTVAL (y
)) > -0x800)
1040 if (GET_MODE (x
) == SImode
&& (op
== LTU
|| op
== GEU
)
1041 && GET_CODE (x
) == PLUS
1042 && (rtx_equal_p (XEXP (x
, 0), y
) || rtx_equal_p (XEXP (x
, 1), y
)))
1045 if (TARGET_ARGONAUT_SET
1046 && ((mode
== SFmode
&& TARGET_SPFP
) || (mode
== DFmode
&& TARGET_DPFP
)))
1049 case EQ
: case NE
: case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1051 case LT
: case UNGE
: case GT
: case UNLE
:
1052 return CC_FP_GTmode
;
1053 case LE
: case UNGT
: case GE
: case UNLT
:
1054 return CC_FP_GEmode
;
1055 default: gcc_unreachable ();
1057 else if (GET_MODE_CLASS (mode
) == MODE_FLOAT
&& TARGET_OPTFPE
)
1060 case EQ
: case NE
: return CC_Zmode
;
1062 case GT
: case UNLE
: return CC_FP_GTmode
;
1064 case GE
: case UNLT
: return CC_FP_GEmode
;
1065 case UNEQ
: case LTGT
: return CC_FP_UNEQmode
;
1066 case ORDERED
: case UNORDERED
: return CC_FP_ORDmode
;
1067 default: gcc_unreachable ();
1073 /* Vectors to keep interesting information about registers where it can easily
1074 be got. We use to use the actual mode value as the bit number, but there
1075 is (or may be) more than 32 modes now. Instead we use two tables: one
1076 indexed by hard register number, and one indexed by mode. */
1078 /* The purpose of arc_mode_class is to shrink the range of modes so that
1079 they all fit (as bit numbers) in a 32-bit word (again). Each real mode is
1080 mapped into one arc_mode_class mode. */
1082 enum arc_mode_class
{
1084 S_MODE
, D_MODE
, T_MODE
, O_MODE
,
1085 SF_MODE
, DF_MODE
, TF_MODE
, OF_MODE
,
1089 /* Modes for condition codes. */
1090 #define C_MODES (1 << (int) C_MODE)
1092 /* Modes for single-word and smaller quantities. */
1093 #define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
1095 /* Modes for double-word and smaller quantities. */
1096 #define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))
1098 /* Mode for 8-byte DF values only. */
1099 #define DF_MODES (1 << DF_MODE)
1101 /* Modes for quad-word and smaller quantities. */
1102 #define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE))
1104 /* Modes for 128-bit vectors. */
1105 #define V_MODES (1 << (int) V_MODE)
1107 /* Value is 1 if register/mode pair is acceptable on arc. */
1109 unsigned int arc_hard_regno_mode_ok
[] = {
1110 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
,
1111 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
,
1112 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, D_MODES
,
1113 D_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1115 /* ??? Leave these as S_MODES for now. */
1116 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1117 DF_MODES
, 0, DF_MODES
, 0, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1118 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1119 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, C_MODES
, S_MODES
,
1121 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1122 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
,
1126 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1127 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1128 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1129 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1131 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1132 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
1135 unsigned int arc_mode_class
[NUM_MACHINE_MODES
];
1137 enum reg_class arc_regno_reg_class
[FIRST_PSEUDO_REGISTER
];
1140 arc_preferred_reload_class (rtx
, enum reg_class cl
)
1142 if ((cl
) == CHEAP_CORE_REGS
|| (cl
) == WRITABLE_CORE_REGS
)
1143 return GENERAL_REGS
;
1147 /* Initialize the arc_mode_class array. */
1150 arc_init_reg_tables (void)
1154 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
1156 machine_mode m
= (machine_mode
) i
;
1158 switch (GET_MODE_CLASS (m
))
1161 case MODE_PARTIAL_INT
:
1162 case MODE_COMPLEX_INT
:
1163 if (GET_MODE_SIZE (m
) <= 4)
1164 arc_mode_class
[i
] = 1 << (int) S_MODE
;
1165 else if (GET_MODE_SIZE (m
) == 8)
1166 arc_mode_class
[i
] = 1 << (int) D_MODE
;
1167 else if (GET_MODE_SIZE (m
) == 16)
1168 arc_mode_class
[i
] = 1 << (int) T_MODE
;
1169 else if (GET_MODE_SIZE (m
) == 32)
1170 arc_mode_class
[i
] = 1 << (int) O_MODE
;
1172 arc_mode_class
[i
] = 0;
1175 case MODE_COMPLEX_FLOAT
:
1176 if (GET_MODE_SIZE (m
) <= 4)
1177 arc_mode_class
[i
] = 1 << (int) SF_MODE
;
1178 else if (GET_MODE_SIZE (m
) == 8)
1179 arc_mode_class
[i
] = 1 << (int) DF_MODE
;
1180 else if (GET_MODE_SIZE (m
) == 16)
1181 arc_mode_class
[i
] = 1 << (int) TF_MODE
;
1182 else if (GET_MODE_SIZE (m
) == 32)
1183 arc_mode_class
[i
] = 1 << (int) OF_MODE
;
1185 arc_mode_class
[i
] = 0;
1187 case MODE_VECTOR_INT
:
1188 arc_mode_class
[i
] = (1<< (int) V_MODE
);
1192 /* mode_class hasn't been initialized yet for EXTRA_CC_MODES, so
1193 we must explicitly check for them here. */
1194 if (i
== (int) CCmode
|| i
== (int) CC_ZNmode
|| i
== (int) CC_Zmode
1195 || i
== (int) CC_Cmode
1196 || i
== CC_FP_GTmode
|| i
== CC_FP_GEmode
|| i
== CC_FP_ORDmode
)
1197 arc_mode_class
[i
] = 1 << (int) C_MODE
;
1199 arc_mode_class
[i
] = 0;
1205 /* Core registers 56..59 are used for multiply extension options.
1206 The dsp option uses r56 and r57, these are then named acc1 and acc2.
1207 acc1 is the highpart, and acc2 the lowpart, so which register gets which
1208 number depends on endianness.
1209 The mul64 multiplier options use r57 for mlo, r58 for mmid and r59 for mhi.
1210 Because mlo / mhi form a 64 bit value, we use different gcc internal
1211 register numbers to make them form a register pair as the gcc internals
1212 know it. mmid gets number 57, if still available, and mlo / mhi get
1213 number 58 and 59, depending on endianness. We use DBX_REGISTER_NUMBER
1214 to map this back. */
1215 char rname56
[5] = "r56";
1216 char rname57
[5] = "r57";
1217 char rname58
[5] = "r58";
1218 char rname59
[5] = "r59";
1221 arc_conditional_register_usage (void)
1225 int fix_start
= 60, fix_end
= 55;
1227 if (TARGET_MUL64_SET
)
1232 /* We don't provide a name for mmed. In rtl / assembly resource lists,
1233 you are supposed to refer to it as mlo & mhi, e.g
1234 (zero_extract:SI (reg:DI 58) (const_int 32) (16)) .
1235 In an actual asm instruction, you are of course use mmed.
1236 The point of avoiding having a separate register for mmed is that
1237 this way, we don't have to carry clobbers of that reg around in every
1238 isntruction that modifies mlo and/or mhi. */
1239 strcpy (rname57
, "");
1240 strcpy (rname58
, TARGET_BIG_ENDIAN
? "mhi" : "mlo");
1241 strcpy (rname59
, TARGET_BIG_ENDIAN
? "mlo" : "mhi");
1243 if (TARGET_MULMAC_32BY16_SET
)
1246 fix_end
= fix_end
> 57 ? fix_end
: 57;
1247 strcpy (rname56
, TARGET_BIG_ENDIAN
? "acc1" : "acc2");
1248 strcpy (rname57
, TARGET_BIG_ENDIAN
? "acc2" : "acc1");
1250 for (regno
= fix_start
; regno
<= fix_end
; regno
++)
1252 if (!fixed_regs
[regno
])
1253 warning (0, "multiply option implies r%d is fixed", regno
);
1254 fixed_regs
[regno
] = call_used_regs
[regno
] = 1;
1258 reg_alloc_order
[2] = 12;
1259 reg_alloc_order
[3] = 13;
1260 reg_alloc_order
[4] = 14;
1261 reg_alloc_order
[5] = 15;
1262 reg_alloc_order
[6] = 1;
1263 reg_alloc_order
[7] = 0;
1264 reg_alloc_order
[8] = 4;
1265 reg_alloc_order
[9] = 5;
1266 reg_alloc_order
[10] = 6;
1267 reg_alloc_order
[11] = 7;
1268 reg_alloc_order
[12] = 8;
1269 reg_alloc_order
[13] = 9;
1270 reg_alloc_order
[14] = 10;
1271 reg_alloc_order
[15] = 11;
1273 if (TARGET_SIMD_SET
)
1276 for (i
= ARC_FIRST_SIMD_VR_REG
; i
<= ARC_LAST_SIMD_VR_REG
; i
++)
1277 reg_alloc_order
[i
] = i
;
1278 for (i
= ARC_FIRST_SIMD_DMA_CONFIG_REG
;
1279 i
<= ARC_LAST_SIMD_DMA_CONFIG_REG
; i
++)
1280 reg_alloc_order
[i
] = i
;
1282 /* For Arctangent-A5 / ARC600, lp_count may not be read in an instruction
1283 following immediately after another one setting it to a new value.
1284 There was some discussion on how to enforce scheduling constraints for
1285 processors with missing interlocks on the gcc mailing list:
1286 http://gcc.gnu.org/ml/gcc/2008-05/msg00021.html .
1287 However, we can't actually use this approach, because for ARC the
1288 delay slot scheduling pass is active, which runs after
1289 machine_dependent_reorg. */
1291 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], LP_COUNT
);
1292 else if (!TARGET_ARC700
)
1293 fixed_regs
[LP_COUNT
] = 1;
1294 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
1295 if (!call_used_regs
[regno
])
1296 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], regno
);
1297 for (regno
= 32; regno
< 60; regno
++)
1298 if (!fixed_regs
[regno
])
1299 SET_HARD_REG_BIT (reg_class_contents
[WRITABLE_CORE_REGS
], regno
);
1302 for (regno
= 32; regno
<= 60; regno
++)
1303 CLEAR_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], regno
);
1305 /* If they have used -ffixed-lp_count, make sure it takes
1307 if (fixed_regs
[LP_COUNT
])
1309 CLEAR_HARD_REG_BIT (reg_class_contents
[LPCOUNT_REG
], LP_COUNT
);
1310 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], LP_COUNT
);
1311 CLEAR_HARD_REG_BIT (reg_class_contents
[WRITABLE_CORE_REGS
], LP_COUNT
);
1313 /* Instead of taking out SF_MODE like below, forbid it outright. */
1314 arc_hard_regno_mode_ok
[60] = 0;
1317 arc_hard_regno_mode_ok
[60] = 1 << (int) S_MODE
;
1320 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1324 if (TARGET_Q_CLASS
&& ((i
<= 3) || ((i
>= 12) && (i
<= 15))))
1325 arc_regno_reg_class
[i
] = ARCOMPACT16_REGS
;
1327 arc_regno_reg_class
[i
] = GENERAL_REGS
;
1330 arc_regno_reg_class
[i
]
1332 ? (TEST_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], i
)
1333 ? CHEAP_CORE_REGS
: ALL_CORE_REGS
)
1335 && TEST_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], i
))
1336 ? CHEAP_CORE_REGS
: WRITABLE_CORE_REGS
));
1338 arc_regno_reg_class
[i
] = NO_REGS
;
1341 /* ARCOMPACT16_REGS is empty, if TARGET_Q_CLASS has not been activated. */
1342 if (!TARGET_Q_CLASS
)
1344 CLEAR_HARD_REG_SET(reg_class_contents
[ARCOMPACT16_REGS
]);
1345 CLEAR_HARD_REG_SET(reg_class_contents
[AC16_BASE_REGS
]);
1348 gcc_assert (FIRST_PSEUDO_REGISTER
>= 144);
1350 /* Handle Special Registers. */
1351 arc_regno_reg_class
[29] = LINK_REGS
; /* ilink1 register. */
1352 arc_regno_reg_class
[30] = LINK_REGS
; /* ilink2 register. */
1353 arc_regno_reg_class
[31] = LINK_REGS
; /* blink register. */
1354 arc_regno_reg_class
[60] = LPCOUNT_REG
;
1355 arc_regno_reg_class
[61] = NO_REGS
; /* CC_REG: must be NO_REGS. */
1356 arc_regno_reg_class
[62] = GENERAL_REGS
;
1360 for (i
= 40; i
< 44; ++i
)
1362 arc_regno_reg_class
[i
] = DOUBLE_REGS
;
1364 /* Unless they want us to do 'mov d1, 0x00000000' make sure
1365 no attempt is made to use such a register as a destination
1366 operand in *movdf_insn. */
1367 if (!TARGET_ARGONAUT_SET
)
1369 /* Make sure no 'c', 'w', 'W', or 'Rac' constraint is
1370 interpreted to mean they can use D1 or D2 in their insn. */
1371 CLEAR_HARD_REG_BIT(reg_class_contents
[CHEAP_CORE_REGS
], i
);
1372 CLEAR_HARD_REG_BIT(reg_class_contents
[ALL_CORE_REGS
], i
);
1373 CLEAR_HARD_REG_BIT(reg_class_contents
[WRITABLE_CORE_REGS
], i
);
1374 CLEAR_HARD_REG_BIT(reg_class_contents
[MPY_WRITABLE_CORE_REGS
], i
);
1380 /* Disable all DOUBLE_REGISTER settings,
1381 if not generating DPFP code. */
1382 arc_regno_reg_class
[40] = ALL_REGS
;
1383 arc_regno_reg_class
[41] = ALL_REGS
;
1384 arc_regno_reg_class
[42] = ALL_REGS
;
1385 arc_regno_reg_class
[43] = ALL_REGS
;
1387 arc_hard_regno_mode_ok
[40] = 0;
1388 arc_hard_regno_mode_ok
[42] = 0;
1390 CLEAR_HARD_REG_SET(reg_class_contents
[DOUBLE_REGS
]);
1393 if (TARGET_SIMD_SET
)
1395 gcc_assert (ARC_FIRST_SIMD_VR_REG
== 64);
1396 gcc_assert (ARC_LAST_SIMD_VR_REG
== 127);
1398 for (i
= ARC_FIRST_SIMD_VR_REG
; i
<= ARC_LAST_SIMD_VR_REG
; i
++)
1399 arc_regno_reg_class
[i
] = SIMD_VR_REGS
;
1401 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_REG
== 128);
1402 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_IN_REG
== 128);
1403 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG
== 136);
1404 gcc_assert (ARC_LAST_SIMD_DMA_CONFIG_REG
== 143);
1406 for (i
= ARC_FIRST_SIMD_DMA_CONFIG_REG
;
1407 i
<= ARC_LAST_SIMD_DMA_CONFIG_REG
; i
++)
1408 arc_regno_reg_class
[i
] = SIMD_DMA_CONFIG_REGS
;
1412 arc_regno_reg_class
[PROGRAM_COUNTER_REGNO
] = GENERAL_REGS
;
1415 /* Handle an "interrupt" attribute; arguments as in
1416 struct attribute_spec.handler. */
1419 arc_handle_interrupt_attribute (tree
*, tree name
, tree args
, int,
1424 tree value
= TREE_VALUE (args
);
1426 if (TREE_CODE (value
) != STRING_CST
)
1428 warning (OPT_Wattributes
,
1429 "argument of %qE attribute is not a string constant",
1431 *no_add_attrs
= true;
1433 else if (strcmp (TREE_STRING_POINTER (value
), "ilink1")
1434 && strcmp (TREE_STRING_POINTER (value
), "ilink2"))
1436 warning (OPT_Wattributes
,
1437 "argument of %qE attribute is not \"ilink1\" or \"ilink2\"",
1439 *no_add_attrs
= true;
1444 /* Return zero if TYPE1 and TYPE are incompatible, one if they are compatible,
1445 and two if they are nearly compatible (which causes a warning to be
1449 arc_comp_type_attributes (const_tree type1
,
1452 int l1
, l2
, m1
, m2
, s1
, s2
;
1454 /* Check for mismatch of non-default calling convention. */
1455 if (TREE_CODE (type1
) != FUNCTION_TYPE
)
1458 /* Check for mismatched call attributes. */
1459 l1
= lookup_attribute ("long_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
1460 l2
= lookup_attribute ("long_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
1461 m1
= lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
1462 m2
= lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
1463 s1
= lookup_attribute ("short_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
1464 s2
= lookup_attribute ("short_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
1466 /* Only bother to check if an attribute is defined. */
1467 if (l1
| l2
| m1
| m2
| s1
| s2
)
1469 /* If one type has an attribute, the other must have the same attribute. */
1470 if ((l1
!= l2
) || (m1
!= m2
) || (s1
!= s2
))
1473 /* Disallow mixed attributes. */
1474 if (l1
+ m1
+ s1
> 1)
1482 /* Set the default attributes for TYPE. */
1485 arc_set_default_type_attributes (tree type ATTRIBUTE_UNUSED
)
1490 /* Misc. utilities. */
1492 /* X and Y are two things to compare using CODE. Emit the compare insn and
1493 return the rtx for the cc reg in the proper mode. */
1496 gen_compare_reg (rtx comparison
, machine_mode omode
)
1498 enum rtx_code code
= GET_CODE (comparison
);
1499 rtx x
= XEXP (comparison
, 0);
1500 rtx y
= XEXP (comparison
, 1);
1502 machine_mode mode
, cmode
;
1505 cmode
= GET_MODE (x
);
1506 if (cmode
== VOIDmode
)
1507 cmode
= GET_MODE (y
);
1508 gcc_assert (cmode
== SImode
|| cmode
== SFmode
|| cmode
== DFmode
);
1509 if (cmode
== SImode
)
1511 if (!register_operand (x
, SImode
))
1513 if (register_operand (y
, SImode
))
1518 code
= swap_condition (code
);
1521 x
= copy_to_mode_reg (SImode
, x
);
1523 if (GET_CODE (y
) == SYMBOL_REF
&& flag_pic
)
1524 y
= copy_to_mode_reg (SImode
, y
);
1528 x
= force_reg (cmode
, x
);
1529 y
= force_reg (cmode
, y
);
1531 mode
= SELECT_CC_MODE (code
, x
, y
);
1533 cc_reg
= gen_rtx_REG (mode
, CC_REG
);
1535 /* ??? FIXME (x-y)==0, as done by both cmpsfpx_raw and
1536 cmpdfpx_raw, is not a correct comparison for floats:
1537 http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
1539 if (TARGET_ARGONAUT_SET
1540 && ((cmode
== SFmode
&& TARGET_SPFP
) || (cmode
== DFmode
&& TARGET_DPFP
)))
1544 case NE
: case EQ
: case LT
: case UNGE
: case LE
: case UNGT
:
1545 case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1547 case GT
: case UNLE
: case GE
: case UNLT
:
1548 code
= swap_condition (code
);
1556 if (cmode
== SFmode
)
1558 emit_insn (gen_cmpsfpx_raw (x
, y
));
1562 /* Accepts Dx regs directly by insns. */
1563 emit_insn (gen_cmpdfpx_raw (x
, y
));
1566 if (mode
!= CC_FPXmode
)
1567 emit_insn (gen_rtx_SET (cc_reg
,
1568 gen_rtx_COMPARE (mode
,
1569 gen_rtx_REG (CC_FPXmode
, 61),
1572 else if (GET_MODE_CLASS (cmode
) == MODE_FLOAT
&& TARGET_OPTFPE
)
1574 rtx op0
= gen_rtx_REG (cmode
, 0);
1575 rtx op1
= gen_rtx_REG (cmode
, GET_MODE_SIZE (cmode
) / UNITS_PER_WORD
);
1579 case NE
: case EQ
: case GT
: case UNLE
: case GE
: case UNLT
:
1580 case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1582 case LT
: case UNGE
: case LE
: case UNGT
:
1583 code
= swap_condition (code
);
1591 if (currently_expanding_to_rtl
)
1593 emit_move_insn (op0
, x
);
1594 emit_move_insn (op1
, y
);
1598 gcc_assert (rtx_equal_p (op0
, x
));
1599 gcc_assert (rtx_equal_p (op1
, y
));
1601 emit_insn (gen_cmp_float (cc_reg
, gen_rtx_COMPARE (mode
, op0
, op1
)));
1604 emit_insn (gen_rtx_SET (cc_reg
, gen_rtx_COMPARE (mode
, x
, y
)));
1605 return gen_rtx_fmt_ee (code
, omode
, cc_reg
, const0_rtx
);
1608 /* Return true if VALUE, a const_double, will fit in a limm (4 byte number).
1609 We assume the value can be either signed or unsigned. */
1612 arc_double_limm_p (rtx value
)
1614 HOST_WIDE_INT low
, high
;
1616 gcc_assert (GET_CODE (value
) == CONST_DOUBLE
);
1621 low
= CONST_DOUBLE_LOW (value
);
1622 high
= CONST_DOUBLE_HIGH (value
);
1624 if (low
& 0x80000000)
1626 return (((unsigned HOST_WIDE_INT
) low
<= 0xffffffff && high
== 0)
1627 || (((low
& - (unsigned HOST_WIDE_INT
) 0x80000000)
1628 == - (unsigned HOST_WIDE_INT
) 0x80000000)
1633 return (unsigned HOST_WIDE_INT
) low
<= 0x7fffffff && high
== 0;
1637 /* Do any needed setup for a variadic function. For the ARC, we must
1638 create a register parameter block, and then copy any anonymous arguments
1639 in registers to memory.
1641 CUM has not been updated for the last named argument which has type TYPE
1642 and mode MODE, and we rely on this fact. */
1645 arc_setup_incoming_varargs (cumulative_args_t args_so_far
,
1646 machine_mode mode
, tree type
,
1647 int *pretend_size
, int no_rtl
)
1650 CUMULATIVE_ARGS next_cum
;
1652 /* We must treat `__builtin_va_alist' as an anonymous arg. */
1654 next_cum
= *get_cumulative_args (args_so_far
);
1655 arc_function_arg_advance (pack_cumulative_args (&next_cum
), mode
, type
, 1);
1656 first_anon_arg
= next_cum
;
1658 if (first_anon_arg
< MAX_ARC_PARM_REGS
)
1660 /* First anonymous (unnamed) argument is in a reg. */
1662 /* Note that first_reg_offset < MAX_ARC_PARM_REGS. */
1663 int first_reg_offset
= first_anon_arg
;
1668 = gen_rtx_MEM (BLKmode
, plus_constant (Pmode
, arg_pointer_rtx
,
1669 FIRST_PARM_OFFSET (0)));
1670 move_block_from_reg (first_reg_offset
, regblock
,
1671 MAX_ARC_PARM_REGS
- first_reg_offset
);
1675 = ((MAX_ARC_PARM_REGS
- first_reg_offset
) * UNITS_PER_WORD
);
1679 /* Cost functions. */
1681 /* Provide the costs of an addressing mode that contains ADDR.
1682 If ADDR is not a valid address, its cost is irrelevant. */
1685 arc_address_cost (rtx addr
, machine_mode
, addr_space_t
, bool speed
)
1687 switch (GET_CODE (addr
))
1690 return speed
|| satisfies_constraint_Rcq (addr
) ? 0 : 1;
1691 case PRE_INC
: case PRE_DEC
: case POST_INC
: case POST_DEC
:
1692 case PRE_MODIFY
: case POST_MODIFY
:
1698 /* Most likely needs a LIMM. */
1699 return COSTS_N_INSNS (1);
1703 register rtx plus0
= XEXP (addr
, 0);
1704 register rtx plus1
= XEXP (addr
, 1);
1706 if (GET_CODE (plus0
) != REG
1707 && (GET_CODE (plus0
) != MULT
1708 || !CONST_INT_P (XEXP (plus0
, 1))
1709 || (INTVAL (XEXP (plus0
, 1)) != 2
1710 && INTVAL (XEXP (plus0
, 1)) != 4)))
1713 switch (GET_CODE (plus1
))
1716 return (!RTX_OK_FOR_OFFSET_P (SImode
, plus1
)
1720 : (satisfies_constraint_Rcq (plus0
)
1721 && satisfies_constraint_O (plus1
))
1725 return (speed
< 1 ? 0
1726 : (satisfies_constraint_Rcq (plus0
)
1727 && satisfies_constraint_Rcq (plus1
))
1732 return COSTS_N_INSNS (1);
1745 /* Emit instruction X with the frame related bit set. */
1751 RTX_FRAME_RELATED_P (x
) = 1;
1755 /* Emit a frame insn to move SRC to DST. */
1758 frame_move (rtx dst
, rtx src
)
1760 return frame_insn (gen_rtx_SET (dst
, src
));
1763 /* Like frame_move, but add a REG_INC note for REG if ADDR contains an
1764 auto increment address, or is zero. */
1767 frame_move_inc (rtx dst
, rtx src
, rtx reg
, rtx addr
)
1769 rtx insn
= frame_move (dst
, src
);
1772 || GET_CODE (addr
) == PRE_DEC
|| GET_CODE (addr
) == POST_INC
1773 || GET_CODE (addr
) == PRE_MODIFY
|| GET_CODE (addr
) == POST_MODIFY
)
1774 add_reg_note (insn
, REG_INC
, reg
);
1778 /* Emit a frame insn which adjusts a frame address register REG by OFFSET. */
1781 frame_add (rtx reg
, HOST_WIDE_INT offset
)
1783 gcc_assert ((offset
& 0x3) == 0);
1786 return frame_move (reg
, plus_constant (Pmode
, reg
, offset
));
1789 /* Emit a frame insn which adjusts stack pointer by OFFSET. */
1792 frame_stack_add (HOST_WIDE_INT offset
)
1794 return frame_add (stack_pointer_rtx
, offset
);
1797 /* Traditionally, we push saved registers first in the prologue,
1798 then we allocate the rest of the frame - and reverse in the epilogue.
1799 This has still its merits for ease of debugging, or saving code size
1800 or even execution time if the stack frame is so large that some accesses
1801 can't be encoded anymore with offsets in the instruction code when using
1803 Also, it would be a good starting point if we got instructions to help
1804 with register save/restore.
1806 However, often stack frames are small, and the pushing / popping has
1808 - the stack modification prevents a lot of scheduling.
1809 - frame allocation / deallocation needs extra instructions.
1810 - unless we know that we compile ARC700 user code, we need to put
1811 a memory barrier after frame allocation / before deallocation to
1812 prevent interrupts clobbering our data in the frame.
1813 In particular, we don't have any such guarantees for library functions,
1814 which tend to, on the other hand, to have small frames.
1816 Thus, for small frames, we'd like to use a different scheme:
1817 - The frame is allocated in full with the first prologue instruction,
1818 and deallocated in full with the last epilogue instruction.
1819 Thus, the instructions in-betwen can be freely scheduled.
1820 - If the function has no outgoing arguments on the stack, we can allocate
1821 one register save slot at the top of the stack. This register can then
1822 be saved simultanously with frame allocation, and restored with
1824 This register can be picked depending on scheduling considerations,
1825 although same though should go into having some set of registers
1826 to be potentially lingering after a call, and others to be available
1827 immediately - i.e. in the absence of interprocedual optimization, we
1828 can use an ABI-like convention for register allocation to reduce
1829 stalls after function return. */
1830 /* Function prologue/epilogue handlers. */
1832 /* ARCompact stack frames look like:
1834 Before call After call
1835 high +-----------------------+ +-----------------------+
1836 mem | reg parm save area | | reg parm save area |
1837 | only created for | | only created for |
1838 | variable arg fns | | variable arg fns |
1839 AP +-----------------------+ +-----------------------+
1840 | return addr register | | return addr register |
1841 | (if required) | | (if required) |
1842 +-----------------------+ +-----------------------+
1844 | reg save area | | reg save area |
1846 +-----------------------+ +-----------------------+
1847 | frame pointer | | frame pointer |
1848 | (if required) | | (if required) |
1849 FP +-----------------------+ +-----------------------+
1851 | local/temp variables | | local/temp variables |
1853 +-----------------------+ +-----------------------+
1855 | arguments on stack | | arguments on stack |
1857 SP +-----------------------+ +-----------------------+
1858 | reg parm save area |
1859 | only created for |
1860 | variable arg fns |
1861 AP +-----------------------+
1862 | return addr register |
1864 +-----------------------+
1868 +-----------------------+
1871 FP +-----------------------+
1873 | local/temp variables |
1875 +-----------------------+
1877 | arguments on stack |
1879 mem SP +-----------------------+
1882 1) The "reg parm save area" does not exist for non variable argument fns.
1883 The "reg parm save area" can be eliminated completely if we created our
1884 own va-arc.h, but that has tradeoffs as well (so it's not done). */
1886 /* Structure to be filled in by arc_compute_frame_size with register
1887 save masks, and offsets for the current function. */
1888 struct GTY (()) arc_frame_info
1890 unsigned int total_size
; /* # bytes that the entire frame takes up. */
1891 unsigned int extra_size
; /* # bytes of extra stuff. */
1892 unsigned int pretend_size
; /* # bytes we push and pretend caller did. */
1893 unsigned int args_size
; /* # bytes that outgoing arguments take up. */
1894 unsigned int reg_size
; /* # bytes needed to store regs. */
1895 unsigned int var_size
; /* # bytes that variables take up. */
1896 unsigned int reg_offset
; /* Offset from new sp to store regs. */
1897 unsigned int gmask
; /* Mask of saved gp registers. */
1898 int initialized
; /* Nonzero if frame size already calculated. */
1899 short millicode_start_reg
;
1900 short millicode_end_reg
;
1901 bool save_return_addr
;
1904 /* Defining data structures for per-function information. */
1906 typedef struct GTY (()) machine_function
1908 enum arc_function_type fn_type
;
1909 struct arc_frame_info frame_info
;
1910 /* To keep track of unalignment caused by short insns. */
1912 int force_short_suffix
; /* Used when disgorging return delay slot insns. */
1913 const char *size_reason
;
1914 struct arc_ccfsm ccfsm_current
;
1915 /* Map from uid to ccfsm state during branch shortening. */
1916 rtx ccfsm_current_insn
;
1917 char arc_reorg_started
;
1918 char prescan_initialized
;
1921 /* Type of function DECL.
1923 The result is cached. To reset the cache at the end of a function,
1924 call with DECL = NULL_TREE. */
1926 enum arc_function_type
1927 arc_compute_function_type (struct function
*fun
)
1929 tree decl
= fun
->decl
;
1931 enum arc_function_type fn_type
= fun
->machine
->fn_type
;
1933 if (fn_type
!= ARC_FUNCTION_UNKNOWN
)
1936 /* Assume we have a normal function (not an interrupt handler). */
1937 fn_type
= ARC_FUNCTION_NORMAL
;
1939 /* Now see if this is an interrupt handler. */
1940 for (a
= DECL_ATTRIBUTES (decl
);
1944 tree name
= TREE_PURPOSE (a
), args
= TREE_VALUE (a
);
1946 if (name
== get_identifier ("interrupt")
1947 && list_length (args
) == 1
1948 && TREE_CODE (TREE_VALUE (args
)) == STRING_CST
)
1950 tree value
= TREE_VALUE (args
);
1952 if (!strcmp (TREE_STRING_POINTER (value
), "ilink1"))
1953 fn_type
= ARC_FUNCTION_ILINK1
;
1954 else if (!strcmp (TREE_STRING_POINTER (value
), "ilink2"))
1955 fn_type
= ARC_FUNCTION_ILINK2
;
1962 return fun
->machine
->fn_type
= fn_type
;
1965 #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
1966 #define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM))
1968 /* Tell prologue and epilogue if register REGNO should be saved / restored.
1969 The return address and frame pointer are treated separately.
1970 Don't consider them here.
1971 Addition for pic: The gp register needs to be saved if the current
1972 function changes it to access gotoff variables.
1973 FIXME: This will not be needed if we used some arbitrary register
1976 #define MUST_SAVE_REGISTER(regno, interrupt_p) \
1977 (((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \
1978 && (df_regs_ever_live_p (regno) && (!call_used_regs[regno] || interrupt_p))) \
1979 || (flag_pic && crtl->uses_pic_offset_table \
1980 && regno == PIC_OFFSET_TABLE_REGNUM) )
1982 #define MUST_SAVE_RETURN_ADDR \
1983 (cfun->machine->frame_info.save_return_addr)
1985 /* Return non-zero if there are registers to be saved or loaded using
1986 millicode thunks. We can only use consecutive sequences starting
1987 with r13, and not going beyond r25.
1988 GMASK is a bitmask of registers to save. This function sets
1989 FRAME->millicod_start_reg .. FRAME->millicode_end_reg to the range
1990 of registers to be saved / restored with a millicode call. */
1993 arc_compute_millicode_save_restore_regs (unsigned int gmask
,
1994 struct arc_frame_info
*frame
)
1998 int start_reg
= 13, end_reg
= 25;
2000 for (regno
= start_reg
; regno
<= end_reg
&& (gmask
& (1L << regno
));)
2002 end_reg
= regno
- 1;
2003 /* There is no point in using millicode thunks if we don't save/restore
2004 at least three registers. For non-leaf functions we also have the
2006 if (regno
- start_reg
>= 3 - (crtl
->is_leaf
== 0))
2008 frame
->millicode_start_reg
= 13;
2009 frame
->millicode_end_reg
= regno
- 1;
2015 /* Return the bytes needed to compute the frame pointer from the current
2018 SIZE is the size needed for local variables. */
2021 arc_compute_frame_size (int size
) /* size = # of var. bytes allocated. */
2024 unsigned int total_size
, var_size
, args_size
, pretend_size
, extra_size
;
2025 unsigned int reg_size
, reg_offset
;
2027 enum arc_function_type fn_type
;
2029 struct arc_frame_info
*frame_info
= &cfun
->machine
->frame_info
;
2031 size
= ARC_STACK_ALIGN (size
);
2033 /* 1) Size of locals and temporaries */
2036 /* 2) Size of outgoing arguments */
2037 args_size
= crtl
->outgoing_args_size
;
2039 /* 3) Calculate space needed for saved registers.
2040 ??? We ignore the extension registers for now. */
2042 /* See if this is an interrupt handler. Call used registers must be saved
2047 fn_type
= arc_compute_function_type (cfun
);
2048 interrupt_p
= ARC_INTERRUPT_P (fn_type
);
2050 for (regno
= 0; regno
<= 31; regno
++)
2052 if (MUST_SAVE_REGISTER (regno
, interrupt_p
))
2054 reg_size
+= UNITS_PER_WORD
;
2055 gmask
|= 1 << regno
;
2059 /* 4) Space for back trace data structure.
2060 <return addr reg size> (if required) + <fp size> (if required). */
2061 frame_info
->save_return_addr
2062 = (!crtl
->is_leaf
|| df_regs_ever_live_p (RETURN_ADDR_REGNUM
));
2063 /* Saving blink reg in case of leaf function for millicode thunk calls. */
2064 if (optimize_size
&& !TARGET_NO_MILLICODE_THUNK_SET
)
2066 if (arc_compute_millicode_save_restore_regs (gmask
, frame_info
))
2067 frame_info
->save_return_addr
= true;
2071 if (MUST_SAVE_RETURN_ADDR
)
2073 if (frame_pointer_needed
)
2076 /* 5) Space for variable arguments passed in registers */
2077 pretend_size
= crtl
->args
.pretend_args_size
;
2079 /* Ensure everything before the locals is aligned appropriately. */
2081 unsigned int extra_plus_reg_size
;
2082 unsigned int extra_plus_reg_size_aligned
;
2084 extra_plus_reg_size
= extra_size
+ reg_size
;
2085 extra_plus_reg_size_aligned
= ARC_STACK_ALIGN(extra_plus_reg_size
);
2086 reg_size
= extra_plus_reg_size_aligned
- extra_size
;
2089 /* Compute total frame size. */
2090 total_size
= var_size
+ args_size
+ extra_size
+ pretend_size
+ reg_size
;
2092 total_size
= ARC_STACK_ALIGN (total_size
);
2094 /* Compute offset of register save area from stack pointer:
2095 A5 Frame: pretend_size <blink> reg_size <fp> var_size args_size <--sp
2097 reg_offset
= (total_size
- (pretend_size
+ reg_size
+ extra_size
)
2098 + (frame_pointer_needed
? 4 : 0));
2100 /* Save computed information. */
2101 frame_info
->total_size
= total_size
;
2102 frame_info
->extra_size
= extra_size
;
2103 frame_info
->pretend_size
= pretend_size
;
2104 frame_info
->var_size
= var_size
;
2105 frame_info
->args_size
= args_size
;
2106 frame_info
->reg_size
= reg_size
;
2107 frame_info
->reg_offset
= reg_offset
;
2108 frame_info
->gmask
= gmask
;
2109 frame_info
->initialized
= reload_completed
;
2111 /* Ok, we're done. */
2115 /* Common code to save/restore registers. */
2116 /* BASE_REG is the base register to use for addressing and to adjust.
2117 GMASK is a bitmask of general purpose registers to save/restore.
2118 epilogue_p 0: prologue 1:epilogue 2:epilogue, sibling thunk
2119 If *FIRST_OFFSET is non-zero, add it first to BASE_REG - preferably
2120 using a pre-modify for the first memory access. *FIRST_OFFSET is then
2124 arc_save_restore (rtx base_reg
,
2125 unsigned int gmask
, int epilogue_p
, int *first_offset
)
2127 unsigned int offset
= 0;
2129 struct arc_frame_info
*frame
= &cfun
->machine
->frame_info
;
2130 rtx sibthunk_insn
= NULL_RTX
;
2134 /* Millicode thunks implementation:
2135 Generates calls to millicodes for registers starting from r13 to r25
2136 Present Limitations:
2137 - Only one range supported. The remaining regs will have the ordinary
2138 st and ld instructions for store and loads. Hence a gmask asking
2139 to store r13-14, r16-r25 will only generate calls to store and
2140 load r13 to r14 while store and load insns will be generated for
2141 r16 to r25 in the prologue and epilogue respectively.
2143 - Presently library only supports register ranges starting from r13.
2145 if (epilogue_p
== 2 || frame
->millicode_end_reg
> 14)
2147 int start_call
= frame
->millicode_start_reg
;
2148 int end_call
= frame
->millicode_end_reg
;
2149 int n_regs
= end_call
- start_call
+ 1;
2150 int i
= 0, r
, off
= 0;
2152 rtx ret_addr
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
2156 /* "reg_size" won't be more than 127 . */
2157 gcc_assert (epilogue_p
|| abs (*first_offset
) <= 127);
2158 frame_add (base_reg
, *first_offset
);
2161 insn
= gen_rtx_PARALLEL
2162 (VOIDmode
, rtvec_alloc ((epilogue_p
== 2) + n_regs
+ 1));
2163 if (epilogue_p
== 2)
2166 XVECEXP (insn
, 0, n_regs
) = gen_rtx_CLOBBER (VOIDmode
, ret_addr
);
2167 for (r
= start_call
; r
<= end_call
; r
++, off
+= UNITS_PER_WORD
, i
++)
2169 rtx reg
= gen_rtx_REG (SImode
, r
);
2171 = gen_frame_mem (SImode
, plus_constant (Pmode
, base_reg
, off
));
2174 XVECEXP (insn
, 0, i
) = gen_rtx_SET (reg
, mem
);
2176 XVECEXP (insn
, 0, i
) = gen_rtx_SET (mem
, reg
);
2177 gmask
= gmask
& ~(1L << r
);
2179 if (epilogue_p
== 2)
2180 sibthunk_insn
= insn
;
2186 for (regno
= 0; regno
<= 31; regno
++)
2188 if ((gmask
& (1L << regno
)) != 0)
2190 rtx reg
= gen_rtx_REG (SImode
, regno
);
2195 gcc_assert (!offset
);
2196 addr
= plus_constant (Pmode
, base_reg
, *first_offset
);
2197 addr
= gen_rtx_PRE_MODIFY (Pmode
, base_reg
, addr
);
2202 gcc_assert (SMALL_INT (offset
));
2203 addr
= plus_constant (Pmode
, base_reg
, offset
);
2205 mem
= gen_frame_mem (SImode
, addr
);
2207 frame_move_inc (reg
, mem
, base_reg
, addr
);
2209 frame_move_inc (mem
, reg
, base_reg
, addr
);
2210 offset
+= UNITS_PER_WORD
;
2216 rtx r12
= gen_rtx_REG (Pmode
, 12);
2218 frame_insn (gen_rtx_SET (r12
, GEN_INT (offset
)));
2219 XVECEXP (sibthunk_insn
, 0, 0) = ret_rtx
;
2220 XVECEXP (sibthunk_insn
, 0, 1)
2221 = gen_rtx_SET (stack_pointer_rtx
,
2222 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
, r12
));
2223 sibthunk_insn
= emit_jump_insn (sibthunk_insn
);
2224 RTX_FRAME_RELATED_P (sibthunk_insn
) = 1;
2226 } /* arc_save_restore */
2229 int arc_return_address_regs
[4]
2230 = {0, RETURN_ADDR_REGNUM
, ILINK1_REGNUM
, ILINK2_REGNUM
};
2232 /* Set up the stack and frame pointer (if desired) for the function. */
2235 arc_expand_prologue (void)
2237 int size
= get_frame_size ();
2238 unsigned int gmask
= cfun
->machine
->frame_info
.gmask
;
2239 /* unsigned int frame_pointer_offset;*/
2240 unsigned int frame_size_to_allocate
;
2241 /* (FIXME: The first store will use a PRE_MODIFY; this will usually be r13.
2242 Change the stack layout so that we rather store a high register with the
2243 PRE_MODIFY, thus enabling more short insn generation.) */
2244 int first_offset
= 0;
2246 size
= ARC_STACK_ALIGN (size
);
2248 /* Compute/get total frame size. */
2249 size
= (!cfun
->machine
->frame_info
.initialized
2250 ? arc_compute_frame_size (size
)
2251 : cfun
->machine
->frame_info
.total_size
);
2253 if (flag_stack_usage_info
)
2254 current_function_static_stack_size
= size
;
2256 /* Keep track of frame size to be allocated. */
2257 frame_size_to_allocate
= size
;
2259 /* These cases shouldn't happen. Catch them now. */
2260 gcc_assert (!(size
== 0 && gmask
));
2262 /* Allocate space for register arguments if this is a variadic function. */
2263 if (cfun
->machine
->frame_info
.pretend_size
!= 0)
2265 /* Ensure pretend_size is maximum of 8 * word_size. */
2266 gcc_assert (cfun
->machine
->frame_info
.pretend_size
<= 32);
2268 frame_stack_add (-(HOST_WIDE_INT
)cfun
->machine
->frame_info
.pretend_size
);
2269 frame_size_to_allocate
-= cfun
->machine
->frame_info
.pretend_size
;
2272 /* The home-grown ABI says link register is saved first. */
2273 if (MUST_SAVE_RETURN_ADDR
)
2275 rtx ra
= gen_rtx_REG (SImode
, RETURN_ADDR_REGNUM
);
2276 rtx mem
= gen_frame_mem (Pmode
, gen_rtx_PRE_DEC (Pmode
, stack_pointer_rtx
));
2278 frame_move_inc (mem
, ra
, stack_pointer_rtx
, 0);
2279 frame_size_to_allocate
-= UNITS_PER_WORD
;
2281 } /* MUST_SAVE_RETURN_ADDR */
2283 /* Save any needed call-saved regs (and call-used if this is an
2284 interrupt handler) for ARCompact ISA. */
2285 if (cfun
->machine
->frame_info
.reg_size
)
2287 first_offset
= -cfun
->machine
->frame_info
.reg_size
;
2288 /* N.B. FRAME_POINTER_MASK and RETURN_ADDR_MASK are cleared in gmask. */
2289 arc_save_restore (stack_pointer_rtx
, gmask
, 0, &first_offset
);
2290 frame_size_to_allocate
-= cfun
->machine
->frame_info
.reg_size
;
2294 /* Save frame pointer if needed. */
2295 if (frame_pointer_needed
)
2297 rtx addr
= gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
2298 GEN_INT (-UNITS_PER_WORD
+ first_offset
));
2299 rtx mem
= gen_frame_mem (Pmode
, gen_rtx_PRE_MODIFY (Pmode
,
2302 frame_move_inc (mem
, frame_pointer_rtx
, stack_pointer_rtx
, 0);
2303 frame_size_to_allocate
-= UNITS_PER_WORD
;
2305 frame_move (frame_pointer_rtx
, stack_pointer_rtx
);
2308 /* ??? We don't handle the case where the saved regs are more than 252
2309 bytes away from sp. This can be handled by decrementing sp once, saving
2310 the regs, and then decrementing it again. The epilogue doesn't have this
2311 problem as the `ld' insn takes reg+limm values (though it would be more
2312 efficient to avoid reg+limm). */
2314 frame_size_to_allocate
-= first_offset
;
2315 /* Allocate the stack frame. */
2316 if (frame_size_to_allocate
> 0)
2317 frame_stack_add ((HOST_WIDE_INT
) 0 - frame_size_to_allocate
);
2319 /* Setup the gp register, if needed. */
2320 if (crtl
->uses_pic_offset_table
)
2321 arc_finalize_pic ();
2324 /* Do any necessary cleanup after a function to restore stack, frame,
2328 arc_expand_epilogue (int sibcall_p
)
2330 int size
= get_frame_size ();
2331 enum arc_function_type fn_type
= arc_compute_function_type (cfun
);
2333 size
= ARC_STACK_ALIGN (size
);
2334 size
= (!cfun
->machine
->frame_info
.initialized
2335 ? arc_compute_frame_size (size
)
2336 : cfun
->machine
->frame_info
.total_size
);
2338 unsigned int pretend_size
= cfun
->machine
->frame_info
.pretend_size
;
2339 unsigned int frame_size
;
2340 unsigned int size_to_deallocate
;
2342 int can_trust_sp_p
= !cfun
->calls_alloca
;
2343 int first_offset
= 0;
2344 int millicode_p
= cfun
->machine
->frame_info
.millicode_end_reg
> 0;
2346 size_to_deallocate
= size
;
2348 frame_size
= size
- (pretend_size
+
2349 cfun
->machine
->frame_info
.reg_size
+
2350 cfun
->machine
->frame_info
.extra_size
);
2352 /* ??? There are lots of optimizations that can be done here.
2353 EG: Use fp to restore regs if it's closer.
2354 Maybe in time we'll do them all. For now, always restore regs from
2355 sp, but don't restore sp if we don't have to. */
2357 if (!can_trust_sp_p
)
2358 gcc_assert (frame_pointer_needed
);
2360 /* Restore stack pointer to the beginning of saved register area for
2364 if (frame_pointer_needed
)
2365 frame_move (stack_pointer_rtx
, frame_pointer_rtx
);
2367 first_offset
= frame_size
;
2368 size_to_deallocate
-= frame_size
;
2370 else if (!can_trust_sp_p
)
2371 frame_stack_add (-frame_size
);
2374 /* Restore any saved registers. */
2375 if (frame_pointer_needed
)
2377 rtx addr
= gen_rtx_POST_INC (Pmode
, stack_pointer_rtx
);
2379 frame_move_inc (frame_pointer_rtx
, gen_frame_mem (Pmode
, addr
),
2380 stack_pointer_rtx
, 0);
2381 size_to_deallocate
-= UNITS_PER_WORD
;
2384 /* Load blink after the calls to thunk calls in case of optimize size. */
2387 int sibthunk_p
= (!sibcall_p
2388 && fn_type
== ARC_FUNCTION_NORMAL
2389 && !cfun
->machine
->frame_info
.pretend_size
);
2391 gcc_assert (!(cfun
->machine
->frame_info
.gmask
2392 & (FRAME_POINTER_MASK
| RETURN_ADDR_MASK
)));
2393 arc_save_restore (stack_pointer_rtx
,
2394 cfun
->machine
->frame_info
.gmask
,
2395 1 + sibthunk_p
, &first_offset
);
2399 /* If we are to restore registers, and first_offset would require
2400 a limm to be encoded in a PRE_MODIFY, yet we can add it with a
2401 fast add to the stack pointer, do this now. */
2402 if ((!SMALL_INT (first_offset
)
2403 && cfun
->machine
->frame_info
.gmask
2404 && ((TARGET_ARC700
&& !optimize_size
)
2405 ? first_offset
<= 0x800
2406 : satisfies_constraint_C2a (GEN_INT (first_offset
))))
2407 /* Also do this if we have both gprs and return
2408 address to restore, and they both would need a LIMM. */
2409 || (MUST_SAVE_RETURN_ADDR
2410 && !SMALL_INT ((cfun
->machine
->frame_info
.reg_size
+ first_offset
) >> 2)
2411 && cfun
->machine
->frame_info
.gmask
))
2413 frame_stack_add (first_offset
);
2416 if (MUST_SAVE_RETURN_ADDR
)
2418 rtx ra
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
2419 int ra_offs
= cfun
->machine
->frame_info
.reg_size
+ first_offset
;
2420 rtx addr
= plus_constant (Pmode
, stack_pointer_rtx
, ra_offs
);
2422 /* If the load of blink would need a LIMM, but we can add
2423 the offset quickly to sp, do the latter. */
2424 if (!SMALL_INT (ra_offs
>> 2)
2425 && !cfun
->machine
->frame_info
.gmask
2426 && ((TARGET_ARC700
&& !optimize_size
)
2428 : satisfies_constraint_C2a (GEN_INT (ra_offs
))))
2430 size_to_deallocate
-= ra_offs
- first_offset
;
2432 frame_stack_add (ra_offs
);
2434 addr
= stack_pointer_rtx
;
2436 /* See if we can combine the load of the return address with the
2437 final stack adjustment.
2438 We need a separate load if there are still registers to
2439 restore. We also want a separate load if the combined insn
2440 would need a limm, but a separate load doesn't. */
2442 && !cfun
->machine
->frame_info
.gmask
2443 && (SMALL_INT (ra_offs
) || !SMALL_INT (ra_offs
>> 2)))
2445 addr
= gen_rtx_PRE_MODIFY (Pmode
, stack_pointer_rtx
, addr
);
2447 size_to_deallocate
-= cfun
->machine
->frame_info
.reg_size
;
2449 else if (!ra_offs
&& size_to_deallocate
== UNITS_PER_WORD
)
2451 addr
= gen_rtx_POST_INC (Pmode
, addr
);
2452 size_to_deallocate
= 0;
2454 frame_move_inc (ra
, gen_frame_mem (Pmode
, addr
), stack_pointer_rtx
, addr
);
2459 if (cfun
->machine
->frame_info
.reg_size
)
2460 arc_save_restore (stack_pointer_rtx
,
2461 /* The zeroing of these two bits is unnecessary, but leave this in for clarity. */
2462 cfun
->machine
->frame_info
.gmask
2463 & ~(FRAME_POINTER_MASK
| RETURN_ADDR_MASK
), 1, &first_offset
);
2467 /* The rest of this function does the following:
2468 ARCompact : handle epilogue_delay, restore sp (phase-2), return
2471 /* Keep track of how much of the stack pointer we've restored.
2472 It makes the following a lot more readable. */
2473 size_to_deallocate
+= first_offset
;
2474 restored
= size
- size_to_deallocate
;
2476 if (size
> restored
)
2477 frame_stack_add (size
- restored
);
2478 /* Emit the return instruction. */
2479 if (sibcall_p
== FALSE
)
2480 emit_jump_insn (gen_simple_return ());
2482 if (!TARGET_EPILOGUE_CFI
)
2486 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
2487 RTX_FRAME_RELATED_P (insn
) = 0;
2491 /* Return the offset relative to the stack pointer where the return address
2492 is stored, or -1 if it is not stored. */
2495 arc_return_slot_offset ()
2497 struct arc_frame_info
*afi
= &cfun
->machine
->frame_info
;
2499 return (afi
->save_return_addr
2500 ? afi
->total_size
- afi
->pretend_size
- afi
->extra_size
: -1);
2505 /* Emit special PIC prologues and epilogues. */
2506 /* If the function has any GOTOFF relocations, then the GOTBASE
2507 register has to be setup in the prologue
2508 The instruction needed at the function start for setting up the
2511 ----------------------------------------------------------
2512 The rtl to be emitted for this should be:
2515 (const (unspec (symref _DYNAMIC) 3)))
2516 ---------------------------------------------------------- */
2519 arc_finalize_pic (void)
2522 rtx baseptr_rtx
= gen_rtx_REG (Pmode
, PIC_OFFSET_TABLE_REGNUM
);
2524 if (crtl
->uses_pic_offset_table
== 0)
2527 gcc_assert (flag_pic
!= 0);
2529 pat
= gen_rtx_SYMBOL_REF (Pmode
, "_DYNAMIC");
2530 pat
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, pat
), ARC_UNSPEC_GOT
);
2531 pat
= gen_rtx_CONST (Pmode
, pat
);
2533 pat
= gen_rtx_SET (baseptr_rtx
, pat
);
2538 /* !TARGET_BARREL_SHIFTER support. */
2539 /* Emit a shift insn to set OP0 to OP1 shifted by OP2; CODE specifies what
2543 emit_shift (enum rtx_code code
, rtx op0
, rtx op1
, rtx op2
)
2545 rtx shift
= gen_rtx_fmt_ee (code
, SImode
, op1
, op2
);
2547 = ((shift4_operator (shift
, SImode
) ? gen_shift_si3
: gen_shift_si3_loop
)
2548 (op0
, op1
, op2
, shift
));
2552 /* Output the assembler code for doing a shift.
2553 We go to a bit of trouble to generate efficient code as the ARC601 only has
2554 single bit shifts. This is taken from the h8300 port. We only have one
2555 mode of shifting and can't access individual bytes like the h8300 can, so
2556 this is greatly simplified (at the expense of not generating hyper-
2559 This function is not used if the variable shift insns are present. */
2561 /* FIXME: This probably can be done using a define_split in arc.md.
2562 Alternately, generate rtx rather than output instructions. */
2565 output_shift (rtx
*operands
)
2567 /* static int loopend_lab;*/
2568 rtx shift
= operands
[3];
2569 machine_mode mode
= GET_MODE (shift
);
2570 enum rtx_code code
= GET_CODE (shift
);
2571 const char *shift_one
;
2573 gcc_assert (mode
== SImode
);
2577 case ASHIFT
: shift_one
= "add %0,%1,%1"; break;
2578 case ASHIFTRT
: shift_one
= "asr %0,%1"; break;
2579 case LSHIFTRT
: shift_one
= "lsr %0,%1"; break;
2580 default: gcc_unreachable ();
2583 if (GET_CODE (operands
[2]) != CONST_INT
)
2585 output_asm_insn ("and.f lp_count,%2, 0x1f", operands
);
2592 n
= INTVAL (operands
[2]);
2594 /* Only consider the lower 5 bits of the shift count. */
2597 /* First see if we can do them inline. */
2598 /* ??? We could get better scheduling & shorter code (using short insns)
2599 by using splitters. Alas, that'd be even more verbose. */
2600 if (code
== ASHIFT
&& n
<= 9 && n
> 2
2601 && dest_reg_operand (operands
[4], SImode
))
2603 output_asm_insn ("mov %4,0\n\tadd3 %0,%4,%1", operands
);
2604 for (n
-=3 ; n
>= 3; n
-= 3)
2605 output_asm_insn ("add3 %0,%4,%0", operands
);
2607 output_asm_insn ("add2 %0,%4,%0", operands
);
2609 output_asm_insn ("add %0,%0,%0", operands
);
2615 output_asm_insn (shift_one
, operands
);
2616 operands
[1] = operands
[0];
2619 /* See if we can use a rotate/and. */
2620 else if (n
== BITS_PER_WORD
- 1)
2625 output_asm_insn ("and %0,%1,1\n\tror %0,%0", operands
);
2628 /* The ARC doesn't have a rol insn. Use something else. */
2629 output_asm_insn ("add.f 0,%1,%1\n\tsbc %0,%0,%0", operands
);
2632 /* The ARC doesn't have a rol insn. Use something else. */
2633 output_asm_insn ("add.f 0,%1,%1\n\trlc %0,0", operands
);
2639 else if (n
== BITS_PER_WORD
- 2 && dest_reg_operand (operands
[4], SImode
))
2644 output_asm_insn ("and %0,%1,3\n\tror %0,%0\n\tror %0,%0", operands
);
2647 #if 1 /* Need some scheduling comparisons. */
2648 output_asm_insn ("add.f %4,%1,%1\n\tsbc %0,%0,%0\n\t"
2649 "add.f 0,%4,%4\n\trlc %0,%0", operands
);
2651 output_asm_insn ("add.f %4,%1,%1\n\tbxor %0,%4,31\n\t"
2652 "sbc.f %0,%0,%4\n\trlc %0,%0", operands
);
2657 output_asm_insn ("add.f %4,%1,%1\n\trlc %0,0\n\t"
2658 "add.f 0,%4,%4\n\trlc %0,%0", operands
);
2660 output_asm_insn ("add.f %0,%1,%1\n\trlc.f %0,0\n\t"
2661 "and %0,%0,1\n\trlc %0,%0", operands
);
2668 else if (n
== BITS_PER_WORD
- 3 && code
== ASHIFT
)
2669 output_asm_insn ("and %0,%1,7\n\tror %0,%0\n\tror %0,%0\n\tror %0,%0",
2674 operands
[2] = GEN_INT (n
);
2675 output_asm_insn ("mov.f lp_count, %2", operands
);
2679 output_asm_insn ("lpnz\t2f", operands
);
2680 output_asm_insn (shift_one
, operands
);
2681 output_asm_insn ("nop", operands
);
2682 fprintf (asm_out_file
, "2:\t%s end single insn loop\n",
2691 /* Nested function support. */
2693 /* Directly store VALUE into memory object BLOCK at OFFSET. */
2696 emit_store_direct (rtx block
, int offset
, int value
)
2698 emit_insn (gen_store_direct (adjust_address (block
, SImode
, offset
),
2700 gen_int_mode (value
, SImode
))));
2703 /* Emit RTL insns to initialize the variable parts of a trampoline.
2704 FNADDR is an RTX for the address of the function's pure code.
2705 CXT is an RTX for the static chain value for the function. */
2706 /* With potentially multiple shared objects loaded, and multiple stacks
2707 present for multiple thereds where trampolines might reside, a simple
2708 range check will likely not suffice for the profiler to tell if a callee
2709 is a trampoline. We a speedier check by making the trampoline start at
2710 an address that is not 4-byte aligned.
2711 A trampoline looks like this:
2715 ld_s r12,[pcl,12] 0xd403
2716 ld r11,[pcl,12] 0x170c 700b
2720 The fastest trampoline to execute for trampolines within +-8KB of CTX
2723 j [limm] 0x20200f80 limm
2724 and that would also be faster to write to the stack by computing the offset
2725 from CTX to TRAMP at compile time. However, it would really be better to
2726 get rid of the high cost of cache invalidation when generating trampolines,
2727 which requires that the code part of trampolines stays constant, and
2729 - making sure that no executable code but trampolines is on the stack,
2730 no icache entries linger for the area of the stack from when before the
2731 stack was allocated, and allocating trampolines in trampoline-only
2734 - allocate trampolines fram a special pool of pre-allocated trampolines. */
2737 arc_initialize_trampoline (rtx tramp
, tree fndecl
, rtx cxt
)
2739 rtx fnaddr
= XEXP (DECL_RTL (fndecl
), 0);
2741 emit_store_direct (tramp
, 0, TARGET_BIG_ENDIAN
? 0x78e0d403 : 0xd40378e0);
2742 emit_store_direct (tramp
, 4, TARGET_BIG_ENDIAN
? 0x170c700b : 0x700b170c);
2743 emit_store_direct (tramp
, 8, TARGET_BIG_ENDIAN
? 0x7c0078e0 : 0x78e07c00);
2744 emit_move_insn (adjust_address (tramp
, SImode
, 12), fnaddr
);
2745 emit_move_insn (adjust_address (tramp
, SImode
, 16), cxt
);
2746 emit_insn (gen_flush_icache (adjust_address (tramp
, SImode
, 0)));
2749 /* Allow the profiler to easily distinguish trampolines from normal
2753 arc_trampoline_adjust_address (rtx addr
)
2755 return plus_constant (Pmode
, addr
, 2);
2758 /* This is set briefly to 1 when we output a ".as" address modifer, and then
2759 reset when we output the scaled address. */
2760 static int output_scaled
= 0;
2762 /* Print operand X (an rtx) in assembler syntax to file FILE.
2763 CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
2764 For `%' followed by punctuation, CODE is the punctuation and X is null. */
2765 /* In final.c:output_asm_insn:
2768 'c' : constant address if CONSTANT_ADDRESS_P
2774 '#': condbranch delay slot suffix
2775 '*': jump delay slot suffix
2776 '?' : nonjump-insn suffix for conditional execution or short instruction
2777 '!' : jump / call suffix for conditional execution or short instruction
2778 '`': fold constant inside unary o-perator, re-recognize, and emit.
2783 'B': Branch comparison operand - suppress sda reference
2784 'H': Most significant word
2785 'L': Least significant word
2786 'A': ASCII decimal representation of floating point value
2787 'U': Load/store update or scaling indicator
2788 'V': cache bypass indicator for volatile
2793 'o': original symbol - no @ prepending. */
2796 arc_print_operand (FILE *file
, rtx x
, int code
)
2801 if (GET_CODE (x
) == CONST_INT
)
2802 fprintf (file
, "%d",exact_log2(INTVAL (x
) + 1) - 1 );
2804 output_operand_lossage ("invalid operand to %%Z code");
2809 if (GET_CODE (x
) == CONST_INT
)
2810 fprintf (file
, "%d",exact_log2(INTVAL (x
)) );
2812 output_operand_lossage ("invalid operand to %%z code");
2817 if (GET_CODE (x
) == CONST_INT
)
2818 fprintf (file
, "%d",exact_log2(~INTVAL (x
)) );
2820 output_operand_lossage ("invalid operand to %%M code");
2825 /* Conditional branches depending on condition codes.
2826 Note that this is only for branches that were known to depend on
2827 condition codes before delay slot scheduling;
2828 out-of-range brcc / bbit expansions should use '*'.
2829 This distinction is important because of the different
2830 allowable delay slot insns and the output of the delay suffix
2831 for TARGET_AT_DBR_COND_EXEC. */
2833 /* Unconditional branches / branches not depending on condition codes.
2834 This could also be a CALL_INSN.
2835 Output the appropriate delay slot suffix. */
2836 if (final_sequence
&& final_sequence
->len () != 1)
2838 rtx_insn
*jump
= final_sequence
->insn (0);
2839 rtx_insn
*delay
= final_sequence
->insn (1);
2841 /* For TARGET_PAD_RETURN we might have grabbed the delay insn. */
2842 if (delay
->deleted ())
2844 if (JUMP_P (jump
) && INSN_ANNULLED_BRANCH_P (jump
))
2845 fputs (INSN_FROM_TARGET_P (delay
) ? ".d"
2846 : TARGET_AT_DBR_CONDEXEC
&& code
== '#' ? ".d"
2847 : get_attr_type (jump
) == TYPE_RETURN
&& code
== '#' ? ""
2854 case '?' : /* with leading "." */
2855 case '!' : /* without leading "." */
2856 /* This insn can be conditionally executed. See if the ccfsm machinery
2857 says it should be conditionalized.
2858 If it shouldn't, we'll check the compact attribute if this insn
2859 has a short variant, which may be used depending on code size and
2860 alignment considerations. */
2861 if (current_insn_predicate
)
2862 arc_ccfsm_current
.cc
2863 = get_arc_condition_code (current_insn_predicate
);
2864 if (ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current
))
2866 /* Is this insn in a delay slot sequence? */
2867 if (!final_sequence
|| XVECLEN (final_sequence
, 0) < 2
2868 || current_insn_predicate
2869 || CALL_P (final_sequence
->insn (0))
2870 || simplejump_p (final_sequence
->insn (0)))
2872 /* This insn isn't in a delay slot sequence, or conditionalized
2873 independently of its position in a delay slot. */
2874 fprintf (file
, "%s%s",
2875 code
== '?' ? "." : "",
2876 arc_condition_codes
[arc_ccfsm_current
.cc
]);
2877 /* If this is a jump, there are still short variants. However,
2878 only beq_s / bne_s have the same offset range as b_s,
2879 and the only short conditional returns are jeq_s and jne_s. */
2881 && (arc_ccfsm_current
.cc
== ARC_CC_EQ
2882 || arc_ccfsm_current
.cc
== ARC_CC_NE
2883 || 0 /* FIXME: check if branch in 7 bit range. */))
2884 output_short_suffix (file
);
2886 else if (code
== '!') /* Jump with delay slot. */
2887 fputs (arc_condition_codes
[arc_ccfsm_current
.cc
], file
);
2888 else /* An Instruction in a delay slot of a jump or call. */
2890 rtx jump
= XVECEXP (final_sequence
, 0, 0);
2891 rtx insn
= XVECEXP (final_sequence
, 0, 1);
2893 /* If the insn is annulled and is from the target path, we need
2894 to inverse the condition test. */
2895 if (JUMP_P (jump
) && INSN_ANNULLED_BRANCH_P (jump
))
2897 if (INSN_FROM_TARGET_P (insn
))
2898 fprintf (file
, "%s%s",
2899 code
== '?' ? "." : "",
2900 arc_condition_codes
[ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current
.cc
)]);
2902 fprintf (file
, "%s%s",
2903 code
== '?' ? "." : "",
2904 arc_condition_codes
[arc_ccfsm_current
.cc
]);
2905 if (arc_ccfsm_current
.state
== 5)
2906 arc_ccfsm_current
.state
= 0;
2909 /* This insn is executed for either path, so don't
2910 conditionalize it at all. */
2911 output_short_suffix (file
);
2916 output_short_suffix (file
);
2919 /* FIXME: fold constant inside unary operator, re-recognize, and emit. */
2922 fputs (arc_condition_codes
[get_arc_condition_code (x
)], file
);
2925 fputs (arc_condition_codes
[ARC_INVERSE_CONDITION_CODE
2926 (get_arc_condition_code (x
))],
2930 /* Write second word of DImode or DFmode reference,
2931 register or memory. */
2932 if (GET_CODE (x
) == REG
)
2933 fputs (reg_names
[REGNO (x
)+1], file
);
2934 else if (GET_CODE (x
) == MEM
)
2938 /* Handle possible auto-increment. For PRE_INC / PRE_DEC /
2939 PRE_MODIFY, we will have handled the first word already;
2940 For POST_INC / POST_DEC / POST_MODIFY, the access to the
2941 first word will be done later. In either case, the access
2942 to the first word will do the modify, and we only have
2943 to add an offset of four here. */
2944 if (GET_CODE (XEXP (x
, 0)) == PRE_INC
2945 || GET_CODE (XEXP (x
, 0)) == PRE_DEC
2946 || GET_CODE (XEXP (x
, 0)) == PRE_MODIFY
2947 || GET_CODE (XEXP (x
, 0)) == POST_INC
2948 || GET_CODE (XEXP (x
, 0)) == POST_DEC
2949 || GET_CODE (XEXP (x
, 0)) == POST_MODIFY
)
2950 output_address (plus_constant (Pmode
, XEXP (XEXP (x
, 0), 0), 4));
2951 else if (output_scaled
)
2953 rtx addr
= XEXP (x
, 0);
2954 int size
= GET_MODE_SIZE (GET_MODE (x
));
2956 output_address (plus_constant (Pmode
, XEXP (addr
, 0),
2957 ((INTVAL (XEXP (addr
, 1)) + 4)
2958 >> (size
== 2 ? 1 : 2))));
2962 output_address (plus_constant (Pmode
, XEXP (x
, 0), 4));
2966 output_operand_lossage ("invalid operand to %%R code");
2969 /* FIXME: remove %S option. */
2971 case 'B' /* Branch or other LIMM ref - must not use sda references. */ :
2974 output_addr_const (file
, x
);
2980 if (GET_CODE (x
) == REG
)
2982 /* L = least significant word, H = most significant word. */
2983 if ((WORDS_BIG_ENDIAN
!= 0) ^ (code
== 'L'))
2984 fputs (reg_names
[REGNO (x
)], file
);
2986 fputs (reg_names
[REGNO (x
)+1], file
);
2988 else if (GET_CODE (x
) == CONST_INT
2989 || GET_CODE (x
) == CONST_DOUBLE
)
2993 split_double (x
, &first
, &second
);
2995 if((WORDS_BIG_ENDIAN
) == 0)
2996 fprintf (file
, "0x%08" PRIx64
,
2997 code
== 'L' ? INTVAL (first
) : INTVAL (second
));
2999 fprintf (file
, "0x%08" PRIx64
,
3000 code
== 'L' ? INTVAL (second
) : INTVAL (first
));
3005 output_operand_lossage ("invalid operand to %%H/%%L code");
3011 gcc_assert (GET_CODE (x
) == CONST_DOUBLE
3012 && GET_MODE_CLASS (GET_MODE (x
)) == MODE_FLOAT
);
3014 real_to_decimal (str
, CONST_DOUBLE_REAL_VALUE (x
), sizeof (str
), 0, 1);
3015 fprintf (file
, "%s", str
);
3019 /* Output a load/store with update indicator if appropriate. */
3020 if (GET_CODE (x
) == MEM
)
3022 rtx addr
= XEXP (x
, 0);
3023 switch (GET_CODE (addr
))
3025 case PRE_INC
: case PRE_DEC
: case PRE_MODIFY
:
3026 fputs (".a", file
); break;
3027 case POST_INC
: case POST_DEC
: case POST_MODIFY
:
3028 fputs (".ab", file
); break;
3030 /* Are we using a scaled index? */
3031 if (GET_CODE (XEXP (addr
, 0)) == MULT
)
3032 fputs (".as", file
);
3033 /* Can we use a scaled offset? */
3034 else if (CONST_INT_P (XEXP (addr
, 1))
3035 && GET_MODE_SIZE (GET_MODE (x
)) > 1
3036 && (!(INTVAL (XEXP (addr
, 1))
3037 & (GET_MODE_SIZE (GET_MODE (x
)) - 1) & 3))
3038 /* Does it make a difference? */
3039 && !SMALL_INT_RANGE(INTVAL (XEXP (addr
, 1)),
3040 GET_MODE_SIZE (GET_MODE (x
)) - 2, 0))
3042 fputs (".as", file
);
3049 gcc_assert (CONSTANT_P (addr
)); break;
3053 output_operand_lossage ("invalid operand to %%U code");
3056 /* Output cache bypass indicator for a load/store insn. Volatile memory
3057 refs are defined to use the cache bypass mechanism. */
3058 if (GET_CODE (x
) == MEM
)
3060 if (MEM_VOLATILE_P (x
) && !TARGET_VOLATILE_CACHE_SET
)
3061 fputs (".di", file
);
3064 output_operand_lossage ("invalid operand to %%V code");
3069 /* Do nothing special. */
3072 fputs (reg_names
[REGNO (x
)]+1, file
);
3075 /* This punctuation character is needed because label references are
3076 printed in the output template using %l. This is a front end
3077 character, and when we want to emit a '@' before it, we have to use
3083 /* Output an operator. */
3084 switch (GET_CODE (x
))
3086 case PLUS
: fputs ("add", file
); return;
3087 case SS_PLUS
: fputs ("adds", file
); return;
3088 case AND
: fputs ("and", file
); return;
3089 case IOR
: fputs ("or", file
); return;
3090 case XOR
: fputs ("xor", file
); return;
3091 case MINUS
: fputs ("sub", file
); return;
3092 case SS_MINUS
: fputs ("subs", file
); return;
3093 case ASHIFT
: fputs ("asl", file
); return;
3094 case ASHIFTRT
: fputs ("asr", file
); return;
3095 case LSHIFTRT
: fputs ("lsr", file
); return;
3096 case ROTATERT
: fputs ("ror", file
); return;
3097 case MULT
: fputs ("mpy", file
); return;
3098 case ABS
: fputs ("abs", file
); return; /* Unconditional. */
3099 case NEG
: fputs ("neg", file
); return;
3100 case SS_NEG
: fputs ("negs", file
); return;
3101 case NOT
: fputs ("not", file
); return; /* Unconditional. */
3103 fputs ("ext", file
); /* bmsk allows predication. */
3105 case SIGN_EXTEND
: /* Unconditional. */
3106 fputs ("sex", file
);
3108 switch (GET_MODE (XEXP (x
, 0)))
3110 case QImode
: fputs ("b", file
); return;
3111 case HImode
: fputs ("w", file
); return;
3116 if (GET_MODE (x
) != HImode
)
3118 fputs ("sat16", file
);
3121 output_operand_lossage ("invalid operand to %%O code"); return;
3123 if (GET_CODE (x
) == SYMBOL_REF
)
3125 assemble_name (file
, XSTR (x
, 0));
3130 if (TARGET_ANNOTATE_ALIGN
&& cfun
->machine
->size_reason
)
3131 fprintf (file
, "; unalign: %d", cfun
->machine
->unalign
);
3135 output_operand_lossage ("invalid operand output code");
3138 switch (GET_CODE (x
))
3141 fputs (reg_names
[REGNO (x
)], file
);
3145 rtx addr
= XEXP (x
, 0);
3146 int size
= GET_MODE_SIZE (GET_MODE (x
));
3150 switch (GET_CODE (addr
))
3152 case PRE_INC
: case POST_INC
:
3153 output_address (plus_constant (Pmode
, XEXP (addr
, 0), size
)); break;
3154 case PRE_DEC
: case POST_DEC
:
3155 output_address (plus_constant (Pmode
, XEXP (addr
, 0), -size
));
3157 case PRE_MODIFY
: case POST_MODIFY
:
3158 output_address (XEXP (addr
, 1)); break;
3162 output_address (plus_constant (Pmode
, XEXP (addr
, 0),
3163 (INTVAL (XEXP (addr
, 1))
3164 >> (size
== 2 ? 1 : 2))));
3168 output_address (addr
);
3171 if (flag_pic
&& CONSTANT_ADDRESS_P (addr
))
3172 arc_output_pic_addr_const (file
, addr
, code
);
3174 output_address (addr
);
3181 /* We handle SFmode constants here as output_addr_const doesn't. */
3182 if (GET_MODE (x
) == SFmode
)
3187 REAL_VALUE_FROM_CONST_DOUBLE (d
, x
);
3188 REAL_VALUE_TO_TARGET_SINGLE (d
, l
);
3189 fprintf (file
, "0x%08lx", l
);
3192 /* Fall through. Let output_addr_const deal with it. */
3195 arc_output_pic_addr_const (file
, x
, code
);
3198 /* FIXME: Dirty way to handle @var@sda+const. Shd be handled
3199 with asm_output_symbol_ref */
3200 if (GET_CODE (x
) == CONST
&& GET_CODE (XEXP (x
, 0)) == PLUS
)
3203 output_addr_const (file
, XEXP (x
, 0));
3204 if (GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
&& SYMBOL_REF_SMALL_P (XEXP (x
, 0)))
3205 fprintf (file
, "@sda");
3207 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
3208 || INTVAL (XEXP (x
, 1)) >= 0)
3209 fprintf (file
, "+");
3210 output_addr_const (file
, XEXP (x
, 1));
3213 output_addr_const (file
, x
);
3215 if (GET_CODE (x
) == SYMBOL_REF
&& SYMBOL_REF_SMALL_P (x
))
3216 fprintf (file
, "@sda");
3221 /* Print a memory address as an operand to reference that memory location. */
3224 arc_print_operand_address (FILE *file
, rtx addr
)
3226 register rtx base
, index
= 0;
3228 switch (GET_CODE (addr
))
3231 fputs (reg_names
[REGNO (addr
)], file
);
3234 output_addr_const (file
, addr
);
3235 if (SYMBOL_REF_SMALL_P (addr
))
3236 fprintf (file
, "@sda");
3239 if (GET_CODE (XEXP (addr
, 0)) == MULT
)
3240 index
= XEXP (XEXP (addr
, 0), 0), base
= XEXP (addr
, 1);
3241 else if (CONST_INT_P (XEXP (addr
, 0)))
3242 index
= XEXP (addr
, 0), base
= XEXP (addr
, 1);
3244 base
= XEXP (addr
, 0), index
= XEXP (addr
, 1);
3246 gcc_assert (OBJECT_P (base
));
3247 arc_print_operand_address (file
, base
);
3248 if (CONSTANT_P (base
) && CONST_INT_P (index
))
3252 gcc_assert (OBJECT_P (index
));
3253 arc_print_operand_address (file
, index
);
3257 rtx c
= XEXP (addr
, 0);
3259 gcc_assert (GET_CODE (XEXP (c
, 0)) == SYMBOL_REF
);
3260 gcc_assert (GET_CODE (XEXP (c
, 1)) == CONST_INT
);
3262 output_address(XEXP(addr
,0));
3268 /* We shouldn't get here as we've lost the mode of the memory object
3269 (which says how much to inc/dec by. */
3274 arc_output_pic_addr_const (file
, addr
, 0);
3276 output_addr_const (file
, addr
);
3281 /* Called via walk_stores. DATA points to a hash table we can use to
3282 establish a unique SYMBOL_REF for each counter, which corresponds to
3283 a caller-callee pair.
3284 X is a store which we want to examine for an UNSPEC_PROF, which
3285 would be an address loaded into a register, or directly used in a MEM.
3286 If we found an UNSPEC_PROF, if we encounter a new counter the first time,
3287 write out a description and a data allocation for a 32 bit counter.
3288 Also, fill in the appropriate symbol_ref into each UNSPEC_PROF instance. */
3291 write_profile_sections (rtx dest ATTRIBUTE_UNUSED
, rtx x
, void *data
)
3294 htab_t htab
= (htab_t
) data
;
3297 if (GET_CODE (x
) != SET
)
3299 srcp
= &SET_SRC (x
);
3301 srcp
= &XEXP (*srcp
, 0);
3302 else if (MEM_P (SET_DEST (x
)))
3303 srcp
= &XEXP (SET_DEST (x
), 0);
3305 if (GET_CODE (src
) != CONST
)
3307 src
= XEXP (src
, 0);
3308 if (GET_CODE (src
) != UNSPEC
|| XINT (src
, 1) != UNSPEC_PROF
)
3311 gcc_assert (XVECLEN (src
, 0) == 3);
3312 if (!htab_elements (htab
))
3314 output_asm_insn (".section .__arc_profile_desc, \"a\"\n"
3316 &XVECEXP (src
, 0, 0));
3318 slot
= (rtx
*) htab_find_slot (htab
, src
, INSERT
);
3319 if (*slot
== HTAB_EMPTY_ENTRY
)
3321 static int count_nr
;
3326 sprintf (buf
, "__prof_count%d", count_nr
++);
3327 count
= gen_rtx_SYMBOL_REF (Pmode
, xstrdup (buf
));
3328 XVECEXP (src
, 0, 2) = count
;
3329 output_asm_insn (".section\t.__arc_profile_desc, \"a\"\n"
3331 "\t.section\t.__arc_profile_counters, \"aw\"\n"
3332 "\t.type\t%o2, @object\n"
3335 &XVECEXP (src
, 0, 0));
3339 *srcp
= XVECEXP (*slot
, 0, 2);
3342 /* Hash function for UNSPEC_PROF htab. Use both the caller's name and
3343 the callee's name (if known). */
3346 unspec_prof_hash (const void *x
)
3348 const_rtx u
= (const_rtx
) x
;
3349 const_rtx s1
= XVECEXP (u
, 0, 1);
3351 return (htab_hash_string (XSTR (XVECEXP (u
, 0, 0), 0))
3352 ^ (s1
->code
== SYMBOL_REF
? htab_hash_string (XSTR (s1
, 0)) : 0));
3355 /* Equality function for UNSPEC_PROF htab. Two pieces of UNSPEC_PROF rtl
3356 shall refer to the same counter if both caller name and callee rtl
3360 unspec_prof_htab_eq (const void *x
, const void *y
)
3362 const_rtx u0
= (const_rtx
) x
;
3363 const_rtx u1
= (const_rtx
) y
;
3364 const_rtx s01
= XVECEXP (u0
, 0, 1);
3365 const_rtx s11
= XVECEXP (u1
, 0, 1);
3367 return (!strcmp (XSTR (XVECEXP (u0
, 0, 0), 0),
3368 XSTR (XVECEXP (u1
, 0, 0), 0))
3369 && rtx_equal_p (s01
, s11
));
3372 /* Conditional execution support.
3374 This is based on the ARM port but for now is much simpler.
3376 A finite state machine takes care of noticing whether or not instructions
3377 can be conditionally executed, and thus decrease execution time and code
3378 size by deleting branch instructions. The fsm is controlled by
3379 arc_ccfsm_advance (called by arc_final_prescan_insn), and controls the
3380 actions of PRINT_OPERAND. The patterns in the .md file for the branch
3381 insns also have a hand in this. */
3382 /* The way we leave dealing with non-anulled or annull-false delay slot
3383 insns to the consumer is awkward. */
3385 /* The state of the fsm controlling condition codes are:
3386 0: normal, do nothing special
3387 1: don't output this insn
3388 2: don't output this insn
3389 3: make insns conditional
3390 4: make insns conditional
3391 5: make insn conditional (only for outputting anulled delay slot insns)
3393 special value for cfun->machine->uid_ccfsm_state:
3394 6: return with but one insn before it since function start / call
3396 State transitions (state->state by whom, under what condition):
3397 0 -> 1 arc_ccfsm_advance, if insn is a conditional branch skipping over
3399 0 -> 2 arc_ccfsm_advance, if insn is a conditional branch followed
3400 by zero or more non-jump insns and an unconditional branch with
3401 the same target label as the condbranch.
3402 1 -> 3 branch patterns, after having not output the conditional branch
3403 2 -> 4 branch patterns, after having not output the conditional branch
3404 0 -> 5 branch patterns, for anulled delay slot insn.
3405 3 -> 0 ASM_OUTPUT_INTERNAL_LABEL, if the `target' label is reached
3406 (the target label has CODE_LABEL_NUMBER equal to
3407 arc_ccfsm_target_label).
3408 4 -> 0 arc_ccfsm_advance, if `target' unconditional branch is reached
3409 3 -> 1 arc_ccfsm_advance, finding an 'else' jump skipping over some insns.
3410 5 -> 0 when outputting the delay slot insn
3412 If the jump clobbers the conditions then we use states 2 and 4.
3414 A similar thing can be done with conditional return insns.
3416 We also handle separating branches from sets of the condition code.
3417 This is done here because knowledge of the ccfsm state is required,
3418 we may not be outputting the branch. */
3420 /* arc_final_prescan_insn calls arc_ccfsm_advance to adjust arc_ccfsm_current,
3421 before letting final output INSN. */
3424 arc_ccfsm_advance (rtx_insn
*insn
, struct arc_ccfsm
*state
)
3426 /* BODY will hold the body of INSN. */
3429 /* This will be 1 if trying to repeat the trick (ie: do the `else' part of
3430 an if/then/else), and things need to be reversed. */
3433 /* If we start with a return insn, we only succeed if we find another one. */
3434 int seeking_return
= 0;
3436 /* START_INSN will hold the insn from where we start looking. This is the
3437 first insn after the following code_label if REVERSE is true. */
3438 rtx_insn
*start_insn
= insn
;
3440 /* Type of the jump_insn. Brcc insns don't affect ccfsm changes,
3441 since they don't rely on a cmp preceding the. */
3442 enum attr_type jump_insn_type
;
3444 /* Allow -mdebug-ccfsm to turn this off so we can see how well it does.
3445 We can't do this in macro FINAL_PRESCAN_INSN because its called from
3446 final_scan_insn which has `optimize' as a local. */
3447 if (optimize
< 2 || TARGET_NO_COND_EXEC
)
3450 /* Ignore notes and labels. */
3453 body
= PATTERN (insn
);
3454 /* If in state 4, check if the target branch is reached, in order to
3455 change back to state 0. */
3456 if (state
->state
== 4)
3458 if (insn
== state
->target_insn
)
3460 state
->target_insn
= NULL
;
3466 /* If in state 3, it is possible to repeat the trick, if this insn is an
3467 unconditional branch to a label, and immediately following this branch
3468 is the previous target label which is only used once, and the label this
3469 branch jumps to is not too far off. Or in other words "we've done the
3470 `then' part, see if we can do the `else' part." */
3471 if (state
->state
== 3)
3473 if (simplejump_p (insn
))
3475 start_insn
= next_nonnote_insn (start_insn
);
3476 if (GET_CODE (start_insn
) == BARRIER
)
3478 /* ??? Isn't this always a barrier? */
3479 start_insn
= next_nonnote_insn (start_insn
);
3481 if (GET_CODE (start_insn
) == CODE_LABEL
3482 && CODE_LABEL_NUMBER (start_insn
) == state
->target_label
3483 && LABEL_NUSES (start_insn
) == 1)
3488 else if (GET_CODE (body
) == SIMPLE_RETURN
)
3490 start_insn
= next_nonnote_insn (start_insn
);
3491 if (GET_CODE (start_insn
) == BARRIER
)
3492 start_insn
= next_nonnote_insn (start_insn
);
3493 if (GET_CODE (start_insn
) == CODE_LABEL
3494 && CODE_LABEL_NUMBER (start_insn
) == state
->target_label
3495 && LABEL_NUSES (start_insn
) == 1)
3507 if (GET_CODE (insn
) != JUMP_INSN
3508 || GET_CODE (PATTERN (insn
)) == ADDR_VEC
3509 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
3512 /* We can't predicate BRCC or loop ends.
3513 Also, when generating PIC code, and considering a medium range call,
3514 we can't predicate the call. */
3515 jump_insn_type
= get_attr_type (insn
);
3516 if (jump_insn_type
== TYPE_BRCC
3517 || jump_insn_type
== TYPE_BRCC_NO_DELAY_SLOT
3518 || jump_insn_type
== TYPE_LOOP_END
3519 || (jump_insn_type
== TYPE_CALL
&& !get_attr_predicable (insn
)))
3522 /* This jump might be paralleled with a clobber of the condition codes,
3523 the jump should always come first. */
3524 if (GET_CODE (body
) == PARALLEL
&& XVECLEN (body
, 0) > 0)
3525 body
= XVECEXP (body
, 0, 0);
3528 || (GET_CODE (body
) == SET
&& GET_CODE (SET_DEST (body
)) == PC
3529 && GET_CODE (SET_SRC (body
)) == IF_THEN_ELSE
))
3531 int insns_skipped
= 0, fail
= FALSE
, succeed
= FALSE
;
3532 /* Flag which part of the IF_THEN_ELSE is the LABEL_REF. */
3533 int then_not_else
= TRUE
;
3534 /* Nonzero if next insn must be the target label. */
3535 int next_must_be_target_label_p
;
3536 rtx_insn
*this_insn
= start_insn
;
3539 /* Register the insn jumped to. */
3542 if (!seeking_return
)
3543 label
= XEXP (SET_SRC (body
), 0);
3545 else if (GET_CODE (XEXP (SET_SRC (body
), 1)) == LABEL_REF
)
3546 label
= XEXP (XEXP (SET_SRC (body
), 1), 0);
3547 else if (GET_CODE (XEXP (SET_SRC (body
), 2)) == LABEL_REF
)
3549 label
= XEXP (XEXP (SET_SRC (body
), 2), 0);
3550 then_not_else
= FALSE
;
3552 else if (GET_CODE (XEXP (SET_SRC (body
), 1)) == SIMPLE_RETURN
)
3554 else if (GET_CODE (XEXP (SET_SRC (body
), 2)) == SIMPLE_RETURN
)
3557 then_not_else
= FALSE
;
3562 /* If this is a non-annulled branch with a delay slot, there is
3563 no need to conditionalize the delay slot. */
3564 if (NEXT_INSN (PREV_INSN (insn
)) != insn
3565 && state
->state
== 0 && !INSN_ANNULLED_BRANCH_P (insn
))
3567 this_insn
= NEXT_INSN (this_insn
);
3568 gcc_assert (NEXT_INSN (NEXT_INSN (PREV_INSN (start_insn
)))
3569 == NEXT_INSN (this_insn
));
3571 /* See how many insns this branch skips, and what kind of insns. If all
3572 insns are okay, and the label or unconditional branch to the same
3573 label is not too far away, succeed. */
3574 for (insns_skipped
= 0, next_must_be_target_label_p
= FALSE
;
3575 !fail
&& !succeed
&& insns_skipped
< MAX_INSNS_SKIPPED
;
3580 this_insn
= next_nonnote_insn (this_insn
);
3584 if (next_must_be_target_label_p
)
3586 if (GET_CODE (this_insn
) == BARRIER
)
3588 if (GET_CODE (this_insn
) == CODE_LABEL
3589 && this_insn
== label
)
3599 scanbody
= PATTERN (this_insn
);
3601 switch (GET_CODE (this_insn
))
3604 /* Succeed if it is the target label, otherwise fail since
3605 control falls in from somewhere else. */
3606 if (this_insn
== label
)
3616 /* Succeed if the following insn is the target label.
3618 If return insns are used then the last insn in a function
3619 will be a barrier. */
3620 next_must_be_target_label_p
= TRUE
;
3624 /* Can handle a call insn if there are no insns after it.
3625 IE: The next "insn" is the target label. We don't have to
3626 worry about delay slots as such insns are SEQUENCE's inside
3627 INSN's. ??? It is possible to handle such insns though. */
3628 if (get_attr_cond (this_insn
) == COND_CANUSE
)
3629 next_must_be_target_label_p
= TRUE
;
3635 /* If this is an unconditional branch to the same label, succeed.
3636 If it is to another label, do nothing. If it is conditional,
3638 /* ??? Probably, the test for the SET and the PC are
3641 if (GET_CODE (scanbody
) == SET
3642 && GET_CODE (SET_DEST (scanbody
)) == PC
)
3644 if (GET_CODE (SET_SRC (scanbody
)) == LABEL_REF
3645 && XEXP (SET_SRC (scanbody
), 0) == label
&& !reverse
)
3650 else if (GET_CODE (SET_SRC (scanbody
)) == IF_THEN_ELSE
)
3652 else if (get_attr_cond (this_insn
) != COND_CANUSE
)
3655 else if (GET_CODE (scanbody
) == SIMPLE_RETURN
3661 else if (GET_CODE (scanbody
) == PARALLEL
)
3663 if (get_attr_cond (this_insn
) != COND_CANUSE
)
3669 /* We can only do this with insns that can use the condition
3670 codes (and don't set them). */
3671 if (GET_CODE (scanbody
) == SET
3672 || GET_CODE (scanbody
) == PARALLEL
)
3674 if (get_attr_cond (this_insn
) != COND_CANUSE
)
3677 /* We can't handle other insns like sequences. */
3689 if ((!seeking_return
) && (state
->state
== 1 || reverse
))
3690 state
->target_label
= CODE_LABEL_NUMBER (label
);
3691 else if (seeking_return
|| state
->state
== 2)
3693 while (this_insn
&& GET_CODE (PATTERN (this_insn
)) == USE
)
3695 this_insn
= next_nonnote_insn (this_insn
);
3697 gcc_assert (!this_insn
||
3698 (GET_CODE (this_insn
) != BARRIER
3699 && GET_CODE (this_insn
) != CODE_LABEL
));
3703 /* Oh dear! we ran off the end, give up. */
3704 extract_insn_cached (insn
);
3706 state
->target_insn
= NULL
;
3709 state
->target_insn
= this_insn
;
3714 /* If REVERSE is true, ARM_CURRENT_CC needs to be inverted from
3718 state
->cond
= XEXP (SET_SRC (body
), 0);
3719 state
->cc
= get_arc_condition_code (XEXP (SET_SRC (body
), 0));
3722 if (reverse
|| then_not_else
)
3723 state
->cc
= ARC_INVERSE_CONDITION_CODE (state
->cc
);
3726 /* Restore recog_operand. Getting the attributes of other insns can
3727 destroy this array, but final.c assumes that it remains intact
3728 across this call; since the insn has been recognized already we
3729 call insn_extract direct. */
3730 extract_insn_cached (insn
);
3734 /* Record that we are currently outputting label NUM with prefix PREFIX.
3735 It it's the label we're looking for, reset the ccfsm machinery.
3737 Called from ASM_OUTPUT_INTERNAL_LABEL. */
3740 arc_ccfsm_at_label (const char *prefix
, int num
, struct arc_ccfsm
*state
)
3742 if (state
->state
== 3 && state
->target_label
== num
3743 && !strcmp (prefix
, "L"))
3746 state
->target_insn
= NULL
;
3750 /* We are considering a conditional branch with the condition COND.
3751 Check if we want to conditionalize a delay slot insn, and if so modify
3752 the ccfsm state accordingly.
3753 REVERSE says branch will branch when the condition is false. */
3755 arc_ccfsm_record_condition (rtx cond
, bool reverse
, rtx_insn
*jump
,
3756 struct arc_ccfsm
*state
)
3758 rtx_insn
*seq_insn
= NEXT_INSN (PREV_INSN (jump
));
3760 state
= &arc_ccfsm_current
;
3762 gcc_assert (state
->state
== 0);
3763 if (seq_insn
!= jump
)
3765 rtx insn
= XVECEXP (PATTERN (seq_insn
), 0, 1);
3767 if (!as_a
<rtx_insn
*> (insn
)->deleted ()
3768 && INSN_ANNULLED_BRANCH_P (jump
)
3769 && (TARGET_AT_DBR_CONDEXEC
|| INSN_FROM_TARGET_P (insn
)))
3772 state
->cc
= get_arc_condition_code (cond
);
3774 arc_ccfsm_current
.cc
3775 = ARC_INVERSE_CONDITION_CODE (state
->cc
);
3776 rtx pat
= PATTERN (insn
);
3777 if (GET_CODE (pat
) == COND_EXEC
)
3778 gcc_assert ((INSN_FROM_TARGET_P (insn
)
3779 ? ARC_INVERSE_CONDITION_CODE (state
->cc
) : state
->cc
)
3780 == get_arc_condition_code (XEXP (pat
, 0)));
3787 /* Update *STATE as we would when we emit INSN. */
3790 arc_ccfsm_post_advance (rtx_insn
*insn
, struct arc_ccfsm
*state
)
3792 enum attr_type type
;
3795 arc_ccfsm_at_label ("L", CODE_LABEL_NUMBER (insn
), state
);
3796 else if (JUMP_P (insn
)
3797 && GET_CODE (PATTERN (insn
)) != ADDR_VEC
3798 && GET_CODE (PATTERN (insn
)) != ADDR_DIFF_VEC
3799 && ((type
= get_attr_type (insn
)) == TYPE_BRANCH
3800 || (type
== TYPE_UNCOND_BRANCH
3801 /* ??? Maybe should also handle TYPE_RETURN here,
3802 but we don't have a testcase for that. */
3803 && ARC_CCFSM_BRANCH_DELETED_P (state
))))
3805 if (ARC_CCFSM_BRANCH_DELETED_P (state
))
3806 ARC_CCFSM_RECORD_BRANCH_DELETED (state
);
3809 rtx src
= SET_SRC (PATTERN (insn
));
3810 arc_ccfsm_record_condition (XEXP (src
, 0), XEXP (src
, 1) == pc_rtx
,
3814 else if (arc_ccfsm_current
.state
== 5)
3815 arc_ccfsm_current
.state
= 0;
3818 /* Return true if the current insn, which is a conditional branch, is to be
3822 arc_ccfsm_branch_deleted_p (void)
3824 return ARC_CCFSM_BRANCH_DELETED_P (&arc_ccfsm_current
);
3827 /* Record a branch isn't output because subsequent insns can be
3831 arc_ccfsm_record_branch_deleted (void)
3833 ARC_CCFSM_RECORD_BRANCH_DELETED (&arc_ccfsm_current
);
3836 /* During insn output, indicate if the current insn is predicated. */
3839 arc_ccfsm_cond_exec_p (void)
3841 return (cfun
->machine
->prescan_initialized
3842 && ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current
));
3845 /* Like next_active_insn, but return NULL if we find an ADDR_(DIFF_)VEC,
3846 and look inside SEQUENCEs. */
3849 arc_next_active_insn (rtx_insn
*insn
, struct arc_ccfsm
*statep
)
3856 arc_ccfsm_post_advance (insn
, statep
);
3857 insn
= NEXT_INSN (insn
);
3858 if (!insn
|| BARRIER_P (insn
))
3861 arc_ccfsm_advance (insn
, statep
);
3863 while (NOTE_P (insn
)
3864 || (cfun
->machine
->arc_reorg_started
3865 && LABEL_P (insn
) && !label_to_alignment (insn
))
3866 || (NONJUMP_INSN_P (insn
)
3867 && (GET_CODE (PATTERN (insn
)) == USE
3868 || GET_CODE (PATTERN (insn
)) == CLOBBER
)));
3869 if (!LABEL_P (insn
))
3871 gcc_assert (INSN_P (insn
));
3872 pat
= PATTERN (insn
);
3873 if (GET_CODE (pat
) == ADDR_VEC
|| GET_CODE (pat
) == ADDR_DIFF_VEC
)
3875 if (GET_CODE (pat
) == SEQUENCE
)
3876 return as_a
<rtx_insn
*> (XVECEXP (pat
, 0, 0));
3881 /* When deciding if an insn should be output short, we want to know something
3882 about the following insns:
3883 - if another insn follows which we know we can output as a short insn
3884 before an alignment-sensitive point, we can output this insn short:
3885 the decision about the eventual alignment can be postponed.
3886 - if a to-be-aligned label comes next, we should output this insn such
3887 as to get / preserve 4-byte alignment.
3888 - if a likely branch without delay slot insn, or a call with an immediately
3889 following short insn comes next, we should out output this insn such as to
3890 get / preserve 2 mod 4 unalignment.
3891 - do the same for a not completely unlikely branch with a short insn
3892 following before any other branch / label.
3893 - in order to decide if we are actually looking at a branch, we need to
3894 call arc_ccfsm_advance.
3895 - in order to decide if we are looking at a short insn, we should know
3896 if it is conditionalized. To a first order of approximation this is
3897 the case if the state from arc_ccfsm_advance from before this insn
3898 indicates the insn is conditionalized. However, a further refinement
3899 could be to not conditionalize an insn if the destination register(s)
3900 is/are dead in the non-executed case. */
3901 /* Return non-zero if INSN should be output as a short insn. UNALIGN is
3902 zero if the current insn is aligned to a 4-byte-boundary, two otherwise.
3903 If CHECK_ATTR is greater than 0, check the iscompact attribute first. */
3906 arc_verify_short (rtx_insn
*insn
, int, int check_attr
)
3908 enum attr_iscompact iscompact
;
3909 struct machine_function
*machine
;
3913 iscompact
= get_attr_iscompact (insn
);
3914 if (iscompact
== ISCOMPACT_FALSE
)
3917 machine
= cfun
->machine
;
3919 if (machine
->force_short_suffix
>= 0)
3920 return machine
->force_short_suffix
;
3922 return (get_attr_length (insn
) & 2) != 0;
3925 /* When outputting an instruction (alternative) that can potentially be short,
3926 output the short suffix if the insn is in fact short, and update
3927 cfun->machine->unalign accordingly. */
3930 output_short_suffix (FILE *file
)
3932 rtx_insn
*insn
= current_output_insn
;
3934 if (arc_verify_short (insn
, cfun
->machine
->unalign
, 1))
3936 fprintf (file
, "_s");
3937 cfun
->machine
->unalign
^= 2;
3939 /* Restore recog_operand. */
3940 extract_insn_cached (insn
);
3943 /* Implement FINAL_PRESCAN_INSN. */
3946 arc_final_prescan_insn (rtx_insn
*insn
, rtx
*opvec ATTRIBUTE_UNUSED
,
3947 int noperands ATTRIBUTE_UNUSED
)
3949 if (TARGET_DUMPISIZE
)
3950 fprintf (asm_out_file
, "\n; at %04x\n", INSN_ADDRESSES (INSN_UID (insn
)));
3952 /* Output a nop if necessary to prevent a hazard.
3953 Don't do this for delay slots: inserting a nop would
3954 alter semantics, and the only time we would find a hazard is for a
3955 call function result - and in that case, the hazard is spurious to
3957 if (PREV_INSN (insn
)
3958 && PREV_INSN (NEXT_INSN (insn
)) == insn
3959 && arc_hazard (prev_real_insn (insn
), insn
))
3961 current_output_insn
=
3962 emit_insn_before (gen_nop (), NEXT_INSN (PREV_INSN (insn
)));
3963 final_scan_insn (current_output_insn
, asm_out_file
, optimize
, 1, NULL
);
3964 current_output_insn
= insn
;
3966 /* Restore extraction data which might have been clobbered by arc_hazard. */
3967 extract_constrain_insn_cached (insn
);
3969 if (!cfun
->machine
->prescan_initialized
)
3971 /* Clear lingering state from branch shortening. */
3972 memset (&arc_ccfsm_current
, 0, sizeof arc_ccfsm_current
);
3973 cfun
->machine
->prescan_initialized
= 1;
3975 arc_ccfsm_advance (insn
, &arc_ccfsm_current
);
3977 cfun
->machine
->size_reason
= 0;
3980 /* Given FROM and TO register numbers, say whether this elimination is allowed.
3981 Frame pointer elimination is automatically handled.
3983 All eliminations are permissible. If we need a frame
3984 pointer, we must eliminate ARG_POINTER_REGNUM into
3985 FRAME_POINTER_REGNUM and not into STACK_POINTER_REGNUM. */
3988 arc_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to
)
3990 return to
== FRAME_POINTER_REGNUM
|| !arc_frame_pointer_required ();
3993 /* Define the offset between two registers, one to be eliminated, and
3994 the other its replacement, at the start of a routine. */
3997 arc_initial_elimination_offset (int from
, int to
)
3999 if (! cfun
->machine
->frame_info
.initialized
)
4000 arc_compute_frame_size (get_frame_size ());
4002 if (from
== ARG_POINTER_REGNUM
&& to
== FRAME_POINTER_REGNUM
)
4004 return (cfun
->machine
->frame_info
.extra_size
4005 + cfun
->machine
->frame_info
.reg_size
);
4008 if (from
== ARG_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
4010 return (cfun
->machine
->frame_info
.total_size
4011 - cfun
->machine
->frame_info
.pretend_size
);
4014 if ((from
== FRAME_POINTER_REGNUM
) && (to
== STACK_POINTER_REGNUM
))
4016 return (cfun
->machine
->frame_info
.total_size
4017 - (cfun
->machine
->frame_info
.pretend_size
4018 + cfun
->machine
->frame_info
.extra_size
4019 + cfun
->machine
->frame_info
.reg_size
));
4026 arc_frame_pointer_required (void)
4028 return cfun
->calls_alloca
;
4032 /* Return the destination address of a branch. */
4035 branch_dest (rtx branch
)
4037 rtx pat
= PATTERN (branch
);
4038 rtx dest
= (GET_CODE (pat
) == PARALLEL
4039 ? SET_SRC (XVECEXP (pat
, 0, 0)) : SET_SRC (pat
));
4042 if (GET_CODE (dest
) == IF_THEN_ELSE
)
4043 dest
= XEXP (dest
, XEXP (dest
, 1) == pc_rtx
? 2 : 1);
4045 dest
= XEXP (dest
, 0);
4046 dest_uid
= INSN_UID (dest
);
4048 return INSN_ADDRESSES (dest_uid
);
4052 /* Implement TARGET_ENCODE_SECTION_INFO hook. */
4055 arc_encode_section_info (tree decl
, rtx rtl
, int first
)
4057 /* For sdata, SYMBOL_FLAG_LOCAL and SYMBOL_FLAG_FUNCTION.
4058 This clears machine specific flags, so has to come first. */
4059 default_encode_section_info (decl
, rtl
, first
);
4061 /* Check if it is a function, and whether it has the
4062 [long/medium/short]_call attribute specified. */
4063 if (TREE_CODE (decl
) == FUNCTION_DECL
)
4065 rtx symbol
= XEXP (rtl
, 0);
4066 int flags
= SYMBOL_REF_FLAGS (symbol
);
4068 tree attr
= (TREE_TYPE (decl
) != error_mark_node
4069 ? TYPE_ATTRIBUTES (TREE_TYPE (decl
)) : NULL_TREE
);
4070 tree long_call_attr
= lookup_attribute ("long_call", attr
);
4071 tree medium_call_attr
= lookup_attribute ("medium_call", attr
);
4072 tree short_call_attr
= lookup_attribute ("short_call", attr
);
4074 if (long_call_attr
!= NULL_TREE
)
4075 flags
|= SYMBOL_FLAG_LONG_CALL
;
4076 else if (medium_call_attr
!= NULL_TREE
)
4077 flags
|= SYMBOL_FLAG_MEDIUM_CALL
;
4078 else if (short_call_attr
!= NULL_TREE
)
4079 flags
|= SYMBOL_FLAG_SHORT_CALL
;
4081 SYMBOL_REF_FLAGS (symbol
) = flags
;
4085 /* This is how to output a definition of an internal numbered label where
4086 PREFIX is the class of label and NUM is the number within the class. */
4088 static void arc_internal_label (FILE *stream
, const char *prefix
, unsigned long labelno
)
4091 arc_ccfsm_at_label (prefix
, labelno
, &arc_ccfsm_current
);
4092 default_internal_label (stream
, prefix
, labelno
);
4095 /* Set the cpu type and print out other fancy things,
4096 at the top of the file. */
4098 static void arc_file_start (void)
4100 default_file_start ();
4101 fprintf (asm_out_file
, "\t.cpu %s\n", arc_cpu_string
);
4104 /* Cost functions. */
4106 /* Compute a (partial) cost for rtx X. Return true if the complete
4107 cost has been computed, and false if subexpressions should be
4108 scanned. In either case, *TOTAL contains the cost result. */
4111 arc_rtx_costs (rtx x
, machine_mode mode
, int outer_code
,
4112 int opno ATTRIBUTE_UNUSED
, int *total
, bool speed
)
4114 int code
= GET_CODE (x
);
4118 /* Small integers are as cheap as registers. */
4121 bool nolimm
= false; /* Can we do without long immediate? */
4122 bool fast
= false; /* Is the result available immediately? */
4123 bool condexec
= false; /* Does this allow conditiobnal execution? */
4124 bool compact
= false; /* Is a 16 bit opcode available? */
4125 /* CONDEXEC also implies that we can have an unconditional
4126 3-address operation. */
4128 nolimm
= compact
= condexec
= false;
4129 if (UNSIGNED_INT6 (INTVAL (x
)))
4130 nolimm
= condexec
= compact
= true;
4133 if (SMALL_INT (INTVAL (x
)))
4134 nolimm
= fast
= true;
4137 case AND
: /* bclr, bmsk, ext[bw] */
4138 if (satisfies_constraint_Ccp (x
) /* bclr */
4139 || satisfies_constraint_C1p (x
) /* bmsk */)
4140 nolimm
= fast
= condexec
= compact
= true;
4142 case IOR
: /* bset */
4143 if (satisfies_constraint_C0p (x
)) /* bset */
4144 nolimm
= fast
= condexec
= compact
= true;
4147 if (satisfies_constraint_C0p (x
)) /* bxor */
4148 nolimm
= fast
= condexec
= true;
4151 if (satisfies_constraint_Crr (x
)) /* ror b,u6 */
4157 /* FIXME: Add target options to attach a small cost if
4158 condexec / compact is not true. */
4167 /* 4 byte values can be fetched as immediate constants -
4168 let's give that the cost of an extra insn. */
4172 *total
= COSTS_N_INSNS (1);
4181 *total
= COSTS_N_INSNS (1);
4184 /* FIXME: correct the order of high,low */
4185 split_double (x
, &high
, &low
);
4186 *total
= COSTS_N_INSNS (!SMALL_INT (INTVAL (high
))
4187 + !SMALL_INT (INTVAL (low
)));
4191 /* Encourage synth_mult to find a synthetic multiply when reasonable.
4192 If we need more than 12 insns to do a multiply, then go out-of-line,
4193 since the call overhead will be < 10% of the cost of the multiply. */
4197 if (TARGET_BARREL_SHIFTER
)
4199 /* If we want to shift a constant, we need a LIMM. */
4200 /* ??? when the optimizers want to know if a constant should be
4201 hoisted, they ask for the cost of the constant. OUTER_CODE is
4202 insufficient context for shifts since we don't know which operand
4203 we are looking at. */
4204 if (CONSTANT_P (XEXP (x
, 0)))
4206 *total
+= (COSTS_N_INSNS (2)
4207 + rtx_cost (XEXP (x
, 1), mode
, (enum rtx_code
) code
,
4211 *total
= COSTS_N_INSNS (1);
4213 else if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
4214 *total
= COSTS_N_INSNS (16);
4217 *total
= COSTS_N_INSNS (INTVAL (XEXP ((x
), 1)));
4218 /* ??? want_to_gcse_p can throw negative shift counts at us,
4219 and then panics when it gets a negative cost as result.
4220 Seen for gcc.c-torture/compile/20020710-1.c -Os . */
4229 *total
= COSTS_N_INSNS(30);
4231 *total
= COSTS_N_INSNS(1);
4235 if ((TARGET_DPFP
&& GET_MODE (x
) == DFmode
))
4236 *total
= COSTS_N_INSNS (1);
4238 *total
= arc_multcost
;
4239 /* We do not want synth_mult sequences when optimizing
4241 else if (TARGET_MUL64_SET
|| (TARGET_ARC700
&& !TARGET_NOMPY_SET
))
4242 *total
= COSTS_N_INSNS (1);
4244 *total
= COSTS_N_INSNS (2);
4247 if (GET_CODE (XEXP (x
, 0)) == MULT
4248 && _2_4_8_operand (XEXP (XEXP (x
, 0), 1), VOIDmode
))
4250 *total
+= (rtx_cost (XEXP (x
, 1), mode
, PLUS
, 0, speed
)
4251 + rtx_cost (XEXP (XEXP (x
, 0), 0), mode
, PLUS
, 1, speed
));
4256 if (GET_CODE (XEXP (x
, 1)) == MULT
4257 && _2_4_8_operand (XEXP (XEXP (x
, 1), 1), VOIDmode
))
4259 *total
+= (rtx_cost (XEXP (x
, 0), mode
, PLUS
, 0, speed
)
4260 + rtx_cost (XEXP (XEXP (x
, 1), 0), mode
, PLUS
, 1, speed
));
4266 rtx op0
= XEXP (x
, 0);
4267 rtx op1
= XEXP (x
, 1);
4269 if (GET_CODE (op0
) == ZERO_EXTRACT
&& op1
== const0_rtx
4270 && XEXP (op0
, 1) == const1_rtx
)
4272 /* btst / bbit0 / bbit1:
4273 Small integers and registers are free; everything else can
4274 be put in a register. */
4275 mode
= GET_MODE (XEXP (op0
, 0));
4276 *total
= (rtx_cost (XEXP (op0
, 0), mode
, SET
, 1, speed
)
4277 + rtx_cost (XEXP (op0
, 2), mode
, SET
, 1, speed
));
4280 if (GET_CODE (op0
) == AND
&& op1
== const0_rtx
4281 && satisfies_constraint_C1p (XEXP (op0
, 1)))
4284 *total
= rtx_cost (XEXP (op0
, 0), VOIDmode
, SET
, 1, speed
);
4288 if (GET_CODE (op1
) == NEG
)
4290 /* op0 might be constant, the inside of op1 is rather
4291 unlikely to be so. So swapping the operands might lower
4293 mode
= GET_MODE (op0
);
4294 *total
= (rtx_cost (op0
, mode
, PLUS
, 1, speed
)
4295 + rtx_cost (XEXP (op1
, 0), mode
, PLUS
, 0, speed
));
4300 if (outer_code
== IF_THEN_ELSE
4301 && GET_CODE (XEXP (x
, 0)) == ZERO_EXTRACT
4302 && XEXP (x
, 1) == const0_rtx
4303 && XEXP (XEXP (x
, 0), 1) == const1_rtx
)
4305 /* btst / bbit0 / bbit1:
4306 Small integers and registers are free; everything else can
4307 be put in a register. */
4308 rtx op0
= XEXP (x
, 0);
4310 mode
= GET_MODE (XEXP (op0
, 0));
4311 *total
= (rtx_cost (XEXP (op0
, 0), mode
, SET
, 1, speed
)
4312 + rtx_cost (XEXP (op0
, 2), mode
, SET
, 1, speed
));
4316 /* scc_insn expands into two insns. */
4317 case GTU
: case GEU
: case LEU
:
4319 *total
+= COSTS_N_INSNS (1);
4321 case LTU
: /* might use adc. */
4323 *total
+= COSTS_N_INSNS (1) - 1;
4330 /* Return true if ADDR is an address that needs to be expressed as an
4331 explicit sum of pcl + offset. */
4334 arc_legitimate_pc_offset_p (rtx addr
)
4336 if (GET_CODE (addr
) != CONST
)
4338 addr
= XEXP (addr
, 0);
4339 if (GET_CODE (addr
) == PLUS
)
4341 if (GET_CODE (XEXP (addr
, 1)) != CONST_INT
)
4343 addr
= XEXP (addr
, 0);
4345 return (GET_CODE (addr
) == UNSPEC
4346 && XVECLEN (addr
, 0) == 1
4347 && XINT (addr
, 1) == ARC_UNSPEC_GOT
4348 && GET_CODE (XVECEXP (addr
, 0, 0)) == SYMBOL_REF
);
4351 /* Return true if ADDR is a valid pic address.
4352 A valid pic address on arc should look like
4353 const (unspec (SYMBOL_REF/LABEL) (ARC_UNSPEC_GOTOFF/ARC_UNSPEC_GOT)) */
4356 arc_legitimate_pic_addr_p (rtx addr
)
4358 if (GET_CODE (addr
) == LABEL_REF
)
4360 if (GET_CODE (addr
) != CONST
)
4363 addr
= XEXP (addr
, 0);
4366 if (GET_CODE (addr
) == PLUS
)
4368 if (GET_CODE (XEXP (addr
, 1)) != CONST_INT
)
4370 addr
= XEXP (addr
, 0);
4373 if (GET_CODE (addr
) != UNSPEC
4374 || XVECLEN (addr
, 0) != 1)
4377 /* Must be @GOT or @GOTOFF. */
4378 if (XINT (addr
, 1) != ARC_UNSPEC_GOT
4379 && XINT (addr
, 1) != ARC_UNSPEC_GOTOFF
)
4382 if (GET_CODE (XVECEXP (addr
, 0, 0)) != SYMBOL_REF
4383 && GET_CODE (XVECEXP (addr
, 0, 0)) != LABEL_REF
)
4391 /* Return true if OP contains a symbol reference. */
4394 symbolic_reference_mentioned_p (rtx op
)
4396 register const char *fmt
;
4399 if (GET_CODE (op
) == SYMBOL_REF
|| GET_CODE (op
) == LABEL_REF
)
4402 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
4403 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
4409 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
4410 if (symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
)))
4414 else if (fmt
[i
] == 'e' && symbolic_reference_mentioned_p (XEXP (op
, i
)))
4421 /* Return true if OP contains a SYMBOL_REF that is not wrapped in an unspec.
4422 If SKIP_LOCAL is true, skip symbols that bind locally.
4423 This is used further down in this file, and, without SKIP_LOCAL,
4424 in the addsi3 / subsi3 expanders when generating PIC code. */
4427 arc_raw_symbolic_reference_mentioned_p (rtx op
, bool skip_local
)
4429 register const char *fmt
;
4432 if (GET_CODE(op
) == UNSPEC
)
4435 if (GET_CODE (op
) == SYMBOL_REF
)
4437 tree decl
= SYMBOL_REF_DECL (op
);
4438 return !skip_local
|| !decl
|| !default_binds_local_p (decl
);
4441 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
4442 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
4448 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
4449 if (arc_raw_symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
),
4454 else if (fmt
[i
] == 'e'
4455 && arc_raw_symbolic_reference_mentioned_p (XEXP (op
, i
),
4463 /* Legitimize a pic address reference in ORIG.
4464 The return value is the legitimated address.
4465 If OLDX is non-zero, it is the target to assign the address to first. */
4468 arc_legitimize_pic_address (rtx orig
, rtx oldx
)
4477 if (GET_CODE (addr
) == LABEL_REF
)
4479 else if (GET_CODE (addr
) == SYMBOL_REF
4480 && (CONSTANT_POOL_ADDRESS_P (addr
)
4481 || SYMBOL_REF_LOCAL_P (addr
)))
4483 /* This symbol may be referenced via a displacement from the PIC
4484 base address (@GOTOFF). */
4486 /* FIXME: if we had a way to emit pc-relative adds that don't
4487 create a GOT entry, we could do without the use of the gp register. */
4488 crtl
->uses_pic_offset_table
= 1;
4489 pat
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, addr
), ARC_UNSPEC_GOTOFF
);
4490 pat
= gen_rtx_CONST (Pmode
, pat
);
4491 pat
= gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, pat
);
4494 oldx
= gen_reg_rtx (Pmode
);
4498 emit_move_insn (oldx
, pat
);
4503 else if (GET_CODE (addr
) == SYMBOL_REF
)
4505 /* This symbol must be referenced via a load from the
4506 Global Offset Table (@GOTPC). */
4508 pat
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, addr
), ARC_UNSPEC_GOT
);
4509 pat
= gen_rtx_CONST (Pmode
, pat
);
4510 pat
= gen_const_mem (Pmode
, pat
);
4513 oldx
= gen_reg_rtx (Pmode
);
4515 emit_move_insn (oldx
, pat
);
4520 if (GET_CODE (addr
) == CONST
)
4522 addr
= XEXP (addr
, 0);
4523 if (GET_CODE (addr
) == UNSPEC
)
4525 /* Check that the unspec is one of the ones we generate? */
4528 gcc_assert (GET_CODE (addr
) == PLUS
);
4531 if (GET_CODE (addr
) == PLUS
)
4533 rtx op0
= XEXP (addr
, 0), op1
= XEXP (addr
, 1);
4535 /* Check first to see if this is a constant offset from a @GOTOFF
4536 symbol reference. */
4537 if ((GET_CODE (op0
) == LABEL_REF
4538 || (GET_CODE (op0
) == SYMBOL_REF
4539 && (CONSTANT_POOL_ADDRESS_P (op0
)
4540 || SYMBOL_REF_LOCAL_P (op0
))))
4541 && GET_CODE (op1
) == CONST_INT
)
4543 /* FIXME: like above, could do without gp reference. */
4544 crtl
->uses_pic_offset_table
= 1;
4546 = gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, op0
), ARC_UNSPEC_GOTOFF
);
4547 pat
= gen_rtx_PLUS (Pmode
, pat
, op1
);
4548 pat
= gen_rtx_CONST (Pmode
, pat
);
4549 pat
= gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, pat
);
4553 emit_move_insn (oldx
, pat
);
4559 base
= arc_legitimize_pic_address (XEXP (addr
, 0), oldx
);
4560 pat
= arc_legitimize_pic_address (XEXP (addr
, 1),
4561 base
== oldx
? NULL_RTX
: oldx
);
4563 if (GET_CODE (pat
) == CONST_INT
)
4564 pat
= plus_constant (Pmode
, base
, INTVAL (pat
));
4567 if (GET_CODE (pat
) == PLUS
&& CONSTANT_P (XEXP (pat
, 1)))
4569 base
= gen_rtx_PLUS (Pmode
, base
, XEXP (pat
, 0));
4570 pat
= XEXP (pat
, 1);
4572 pat
= gen_rtx_PLUS (Pmode
, base
, pat
);
4581 /* Output address constant X to FILE, taking PIC into account. */
4584 arc_output_pic_addr_const (FILE * file
, rtx x
, int code
)
4589 switch (GET_CODE (x
))
4599 output_addr_const (file
, x
);
4601 /* Local functions do not get references through the PLT. */
4602 if (code
== 'P' && ! SYMBOL_REF_LOCAL_P (x
))
4603 fputs ("@plt", file
);
4607 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (XEXP (x
, 0)));
4608 assemble_name (file
, buf
);
4612 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (x
));
4613 assemble_name (file
, buf
);
4617 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
));
4621 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4625 if (GET_MODE (x
) == VOIDmode
)
4627 /* We can use %d if the number is one word and positive. */
4628 if (CONST_DOUBLE_HIGH (x
))
4629 fprintf (file
, HOST_WIDE_INT_PRINT_DOUBLE_HEX
,
4630 CONST_DOUBLE_HIGH (x
), CONST_DOUBLE_LOW (x
));
4631 else if (CONST_DOUBLE_LOW (x
) < 0)
4632 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, CONST_DOUBLE_LOW (x
));
4634 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, CONST_DOUBLE_LOW (x
));
4637 /* We can't handle floating point constants;
4638 PRINT_OPERAND must handle them. */
4639 output_operand_lossage ("floating constant misused");
4643 /* FIXME: Not needed here. */
4644 /* Some assemblers need integer constants to appear last (eg masm). */
4645 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
4647 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4648 fprintf (file
, "+");
4649 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4651 else if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
4653 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4654 if (INTVAL (XEXP (x
, 1)) >= 0)
4655 fprintf (file
, "+");
4656 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4663 /* Avoid outputting things like x-x or x+5-x,
4664 since some assemblers can't handle that. */
4665 x
= simplify_subtraction (x
);
4666 if (GET_CODE (x
) != MINUS
)
4669 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4670 fprintf (file
, "-");
4671 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
4672 && INTVAL (XEXP (x
, 1)) < 0)
4674 fprintf (file
, "(");
4675 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4676 fprintf (file
, ")");
4679 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4684 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4689 gcc_assert (XVECLEN (x
, 0) == 1);
4690 if (XINT (x
, 1) == ARC_UNSPEC_GOT
)
4691 fputs ("pcl,", file
);
4692 arc_output_pic_addr_const (file
, XVECEXP (x
, 0, 0), code
);
4693 switch (XINT (x
, 1))
4695 case ARC_UNSPEC_GOT
:
4696 fputs ("@gotpc", file
);
4698 case ARC_UNSPEC_GOTOFF
:
4699 fputs ("@gotoff", file
);
4701 case ARC_UNSPEC_PLT
:
4702 fputs ("@plt", file
);
4705 output_operand_lossage ("invalid UNSPEC as operand: %d", XINT (x
,1));
4711 output_operand_lossage ("invalid expression as operand");
4715 #define SYMBOLIC_CONST(X) \
4716 (GET_CODE (X) == SYMBOL_REF \
4717 || GET_CODE (X) == LABEL_REF \
4718 || (GET_CODE (X) == CONST && symbolic_reference_mentioned_p (X)))
4720 /* Emit insns to move operands[1] into operands[0]. */
4723 emit_pic_move (rtx
*operands
, machine_mode
)
4725 rtx temp
= reload_in_progress
? operands
[0] : gen_reg_rtx (Pmode
);
4727 if (GET_CODE (operands
[0]) == MEM
&& SYMBOLIC_CONST (operands
[1]))
4728 operands
[1] = force_reg (Pmode
, operands
[1]);
4730 operands
[1] = arc_legitimize_pic_address (operands
[1], temp
);
4734 /* The function returning the number of words, at the beginning of an
4735 argument, must be put in registers. The returned value must be
4736 zero for arguments that are passed entirely in registers or that
4737 are entirely pushed on the stack.
4739 On some machines, certain arguments must be passed partially in
4740 registers and partially in memory. On these machines, typically
4741 the first N words of arguments are passed in registers, and the
4742 rest on the stack. If a multi-word argument (a `double' or a
4743 structure) crosses that boundary, its first few words must be
4744 passed in registers and the rest must be pushed. This function
4745 tells the compiler when this occurs, and how many of the words
4746 should go in registers.
4748 `FUNCTION_ARG' for these arguments should return the first register
4749 to be used by the caller for this argument; likewise
4750 `FUNCTION_INCOMING_ARG', for the called function.
4752 The function is used to implement macro FUNCTION_ARG_PARTIAL_NREGS. */
4754 /* If REGNO is the least arg reg available then what is the total number of arg
4756 #define GPR_REST_ARG_REGS(REGNO) \
4757 ((REGNO) <= MAX_ARC_PARM_REGS ? MAX_ARC_PARM_REGS - (REGNO) : 0 )
4759 /* Since arc parm regs are contiguous. */
4760 #define ARC_NEXT_ARG_REG(REGNO) ( (REGNO) + 1 )
4762 /* Implement TARGET_ARG_PARTIAL_BYTES. */
4765 arc_arg_partial_bytes (cumulative_args_t cum_v
, machine_mode mode
,
4766 tree type
, bool named ATTRIBUTE_UNUSED
)
4768 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
4769 int bytes
= (mode
== BLKmode
4770 ? int_size_in_bytes (type
) : (int) GET_MODE_SIZE (mode
));
4771 int words
= (bytes
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
4775 arg_num
= ROUND_ADVANCE_CUM (arg_num
, mode
, type
);
4776 ret
= GPR_REST_ARG_REGS (arg_num
);
4778 /* ICEd at function.c:2361, and ret is copied to data->partial */
4779 ret
= (ret
>= words
? 0 : ret
* UNITS_PER_WORD
);
4786 /* This function is used to control a function argument is passed in a
4787 register, and which register.
4789 The arguments are CUM, of type CUMULATIVE_ARGS, which summarizes
4790 (in a way defined by INIT_CUMULATIVE_ARGS and FUNCTION_ARG_ADVANCE)
4791 all of the previous arguments so far passed in registers; MODE, the
4792 machine mode of the argument; TYPE, the data type of the argument
4793 as a tree node or 0 if that is not known (which happens for C
4794 support library functions); and NAMED, which is 1 for an ordinary
4795 argument and 0 for nameless arguments that correspond to `...' in
4796 the called function's prototype.
4798 The returned value should either be a `reg' RTX for the hard
4799 register in which to pass the argument, or zero to pass the
4800 argument on the stack.
4802 For machines like the Vax and 68000, where normally all arguments
4803 are pushed, zero suffices as a definition.
4805 The usual way to make the ANSI library `stdarg.h' work on a machine
4806 where some arguments are usually passed in registers, is to cause
4807 nameless arguments to be passed on the stack instead. This is done
4808 by making the function return 0 whenever NAMED is 0.
4810 You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the
4811 definition of this function to determine if this argument is of a
4812 type that must be passed in the stack. If `REG_PARM_STACK_SPACE'
4813 is not defined and the function returns non-zero for such an
4814 argument, the compiler will abort. If `REG_PARM_STACK_SPACE' is
4815 defined, the argument will be computed in the stack and then loaded
4818 The function is used to implement macro FUNCTION_ARG. */
4819 /* On the ARC the first MAX_ARC_PARM_REGS args are normally in registers
4820 and the rest are pushed. */
4823 arc_function_arg (cumulative_args_t cum_v
, machine_mode mode
,
4824 const_tree type ATTRIBUTE_UNUSED
, bool named ATTRIBUTE_UNUSED
)
4826 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
4829 const char *debstr ATTRIBUTE_UNUSED
;
4831 arg_num
= ROUND_ADVANCE_CUM (arg_num
, mode
, type
);
4832 /* Return a marker for use in the call instruction. */
4833 if (mode
== VOIDmode
)
4838 else if (GPR_REST_ARG_REGS (arg_num
) > 0)
4840 ret
= gen_rtx_REG (mode
, arg_num
);
4841 debstr
= reg_names
[arg_num
];
4851 /* The function to update the summarizer variable *CUM to advance past
4852 an argument in the argument list. The values MODE, TYPE and NAMED
4853 describe that argument. Once this is done, the variable *CUM is
4854 suitable for analyzing the *following* argument with
4855 `FUNCTION_ARG', etc.
4857 This function need not do anything if the argument in question was
4858 passed on the stack. The compiler knows how to track the amount of
4859 stack space used for arguments without any special help.
4861 The function is used to implement macro FUNCTION_ARG_ADVANCE. */
4862 /* For the ARC: the cum set here is passed on to function_arg where we
4863 look at its value and say which reg to use. Strategy: advance the
4864 regnumber here till we run out of arg regs, then set *cum to last
4865 reg. In function_arg, since *cum > last arg reg we would return 0
4866 and thus the arg will end up on the stack. For straddling args of
4867 course function_arg_partial_nregs will come into play. */
4870 arc_function_arg_advance (cumulative_args_t cum_v
, machine_mode mode
,
4871 const_tree type
, bool named ATTRIBUTE_UNUSED
)
4873 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
4874 int bytes
= (mode
== BLKmode
4875 ? int_size_in_bytes (type
) : (int) GET_MODE_SIZE (mode
));
4876 int words
= (bytes
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
4880 *cum
= ROUND_ADVANCE_CUM (*cum
, mode
, type
);
4881 for (i
= 0; i
< words
; i
++)
4882 *cum
= ARC_NEXT_ARG_REG (*cum
);
4886 /* Define how to find the value returned by a function.
4887 VALTYPE is the data type of the value (as a tree).
4888 If the precise function being called is known, FN_DECL_OR_TYPE is its
4889 FUNCTION_DECL; otherwise, FN_DECL_OR_TYPE is its type. */
4892 arc_function_value (const_tree valtype
,
4893 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
4894 bool outgoing ATTRIBUTE_UNUSED
)
4896 machine_mode mode
= TYPE_MODE (valtype
);
4897 int unsignedp ATTRIBUTE_UNUSED
;
4899 unsignedp
= TYPE_UNSIGNED (valtype
);
4900 if (INTEGRAL_TYPE_P (valtype
) || TREE_CODE (valtype
) == OFFSET_TYPE
)
4901 PROMOTE_MODE (mode
, unsignedp
, valtype
);
4902 return gen_rtx_REG (mode
, 0);
4905 /* Returns the return address that is used by builtin_return_address. */
4908 arc_return_addr_rtx (int count
, ATTRIBUTE_UNUSED rtx frame
)
4913 return get_hard_reg_initial_val (Pmode
, RETURN_ADDR_REGNUM
);
4916 /* Nonzero if the constant value X is a legitimate general operand
4917 when generating PIC code. It is given that flag_pic is on and
4918 that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
4921 arc_legitimate_pic_operand_p (rtx x
)
4923 return !arc_raw_symbolic_reference_mentioned_p (x
, true);
4926 /* Determine if a given RTX is a valid constant. We already know this
4927 satisfies CONSTANT_P. */
4930 arc_legitimate_constant_p (machine_mode
, rtx x
)
4935 switch (GET_CODE (x
))
4940 if (GET_CODE (x
) == PLUS
)
4942 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
4947 /* Only some unspecs are valid as "constants". */
4948 if (GET_CODE (x
) == UNSPEC
)
4949 switch (XINT (x
, 1))
4951 case ARC_UNSPEC_PLT
:
4952 case ARC_UNSPEC_GOTOFF
:
4953 case ARC_UNSPEC_GOT
:
4961 /* We must have drilled down to a symbol. */
4962 if (arc_raw_symbolic_reference_mentioned_p (x
, false))
4976 /* Otherwise we handle everything else in the move patterns. */
4981 arc_legitimate_address_p (machine_mode mode
, rtx x
, bool strict
)
4983 if (RTX_OK_FOR_BASE_P (x
, strict
))
4985 if (LEGITIMATE_OFFSET_ADDRESS_P (mode
, x
, TARGET_INDEXED_LOADS
, strict
))
4987 if (LEGITIMATE_SCALED_ADDRESS_P (mode
, x
, strict
))
4989 if (LEGITIMATE_SMALL_DATA_ADDRESS_P (x
))
4991 if (GET_CODE (x
) == CONST_INT
&& LARGE_INT (INTVAL (x
)))
4993 if ((GET_MODE_SIZE (mode
) != 16)
4994 && (GET_CODE (x
) == SYMBOL_REF
4995 || GET_CODE (x
) == LABEL_REF
4996 || GET_CODE (x
) == CONST
))
4998 if (!flag_pic
|| arc_legitimate_pic_addr_p (x
))
5001 if ((GET_CODE (x
) == PRE_DEC
|| GET_CODE (x
) == PRE_INC
5002 || GET_CODE (x
) == POST_DEC
|| GET_CODE (x
) == POST_INC
)
5003 && RTX_OK_FOR_BASE_P (XEXP (x
, 0), strict
))
5005 /* We're restricted here by the `st' insn. */
5006 if ((GET_CODE (x
) == PRE_MODIFY
|| GET_CODE (x
) == POST_MODIFY
)
5007 && GET_CODE (XEXP ((x
), 1)) == PLUS
5008 && rtx_equal_p (XEXP ((x
), 0), XEXP (XEXP (x
, 1), 0))
5009 && LEGITIMATE_OFFSET_ADDRESS_P (QImode
, XEXP (x
, 1),
5010 TARGET_AUTO_MODIFY_REG
, strict
))
5015 /* Return true iff ADDR (a legitimate address expression)
5016 has an effect that depends on the machine mode it is used for. */
5019 arc_mode_dependent_address_p (const_rtx addr
, addr_space_t
)
5021 /* SYMBOL_REF is not mode dependent: it is either a small data reference,
5022 which is valid for loads and stores, or a limm offset, which is valid for
5024 /* Scaled indices are scaled by the access mode; likewise for scaled
5025 offsets, which are needed for maximum offset stores. */
5026 if (GET_CODE (addr
) == PLUS
5027 && (GET_CODE (XEXP ((addr
), 0)) == MULT
5028 || (CONST_INT_P (XEXP ((addr
), 1))
5029 && !SMALL_INT (INTVAL (XEXP ((addr
), 1))))))
5034 /* Determine if it's legal to put X into the constant pool. */
5037 arc_cannot_force_const_mem (machine_mode mode
, rtx x
)
5039 return !arc_legitimate_constant_p (mode
, x
);
5043 /* Generic function to define a builtin. */
5044 #define def_mbuiltin(MASK, NAME, TYPE, CODE) \
5048 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL, NULL_TREE); \
5054 arc_init_builtins (void)
5056 tree endlink
= void_list_node
;
5058 tree void_ftype_void
5059 = build_function_type (void_type_node
,
5063 = build_function_type (integer_type_node
,
5064 tree_cons (NULL_TREE
, integer_type_node
, endlink
));
5066 tree pcvoid_type_node
5067 = build_pointer_type (build_qualified_type (void_type_node
, TYPE_QUAL_CONST
));
5068 tree int_ftype_pcvoid_int
5069 = build_function_type (integer_type_node
,
5070 tree_cons (NULL_TREE
, pcvoid_type_node
,
5071 tree_cons (NULL_TREE
, integer_type_node
,
5074 tree int_ftype_short_int
5075 = build_function_type (integer_type_node
,
5076 tree_cons (NULL_TREE
, short_integer_type_node
, endlink
));
5078 tree void_ftype_int_int
5079 = build_function_type (void_type_node
,
5080 tree_cons (NULL_TREE
, integer_type_node
,
5081 tree_cons (NULL_TREE
, integer_type_node
, endlink
)));
5082 tree void_ftype_usint_usint
5083 = build_function_type (void_type_node
,
5084 tree_cons (NULL_TREE
, long_unsigned_type_node
,
5085 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
)));
5087 tree int_ftype_int_int
5088 = build_function_type (integer_type_node
,
5089 tree_cons (NULL_TREE
, integer_type_node
,
5090 tree_cons (NULL_TREE
, integer_type_node
, endlink
)));
5092 tree usint_ftype_usint
5093 = build_function_type (long_unsigned_type_node
,
5094 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
));
5096 tree void_ftype_usint
5097 = build_function_type (void_type_node
,
5098 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
));
5100 /* Add the builtins. */
5101 def_mbuiltin (1,"__builtin_arc_nop", void_ftype_void
, ARC_BUILTIN_NOP
);
5102 def_mbuiltin (TARGET_NORM
, "__builtin_arc_norm", int_ftype_int
, ARC_BUILTIN_NORM
);
5103 def_mbuiltin (TARGET_NORM
, "__builtin_arc_normw", int_ftype_short_int
, ARC_BUILTIN_NORMW
);
5104 def_mbuiltin (TARGET_SWAP
, "__builtin_arc_swap", int_ftype_int
, ARC_BUILTIN_SWAP
);
5105 def_mbuiltin (TARGET_MUL64_SET
,"__builtin_arc_mul64", void_ftype_int_int
, ARC_BUILTIN_MUL64
);
5106 def_mbuiltin (TARGET_MUL64_SET
,"__builtin_arc_mulu64", void_ftype_usint_usint
, ARC_BUILTIN_MULU64
);
5107 def_mbuiltin (1,"__builtin_arc_rtie", void_ftype_void
, ARC_BUILTIN_RTIE
);
5108 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_sync", void_ftype_void
, ARC_BUILTIN_SYNC
);
5109 def_mbuiltin ((TARGET_EA_SET
),"__builtin_arc_divaw", int_ftype_int_int
, ARC_BUILTIN_DIVAW
);
5110 def_mbuiltin (1,"__builtin_arc_brk", void_ftype_void
, ARC_BUILTIN_BRK
);
5111 def_mbuiltin (1,"__builtin_arc_flag", void_ftype_usint
, ARC_BUILTIN_FLAG
);
5112 def_mbuiltin (1,"__builtin_arc_sleep", void_ftype_usint
, ARC_BUILTIN_SLEEP
);
5113 def_mbuiltin (1,"__builtin_arc_swi", void_ftype_void
, ARC_BUILTIN_SWI
);
5114 def_mbuiltin (1,"__builtin_arc_core_read", usint_ftype_usint
, ARC_BUILTIN_CORE_READ
);
5115 def_mbuiltin (1,"__builtin_arc_core_write", void_ftype_usint_usint
, ARC_BUILTIN_CORE_WRITE
);
5116 def_mbuiltin (1,"__builtin_arc_lr", usint_ftype_usint
, ARC_BUILTIN_LR
);
5117 def_mbuiltin (1,"__builtin_arc_sr", void_ftype_usint_usint
, ARC_BUILTIN_SR
);
5118 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_trap_s", void_ftype_usint
, ARC_BUILTIN_TRAP_S
);
5119 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_unimp_s", void_ftype_void
, ARC_BUILTIN_UNIMP_S
);
5120 def_mbuiltin (1,"__builtin_arc_aligned", int_ftype_pcvoid_int
, ARC_BUILTIN_ALIGNED
);
5122 if (TARGET_SIMD_SET
)
5123 arc_init_simd_builtins ();
5126 static rtx
arc_expand_simd_builtin (tree
, rtx
, rtx
, machine_mode
, int);
5128 /* Expand an expression EXP that calls a built-in function,
5129 with result going to TARGET if that's convenient
5130 (and in mode MODE if that's convenient).
5131 SUBTARGET may be used as the target for computing one of EXP's operands.
5132 IGNORE is nonzero if the value is to be ignored. */
5135 arc_expand_builtin (tree exp
,
5141 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
5146 int fcode
= DECL_FUNCTION_CODE (fndecl
);
5151 if (fcode
> ARC_SIMD_BUILTIN_BEGIN
&& fcode
< ARC_SIMD_BUILTIN_END
)
5152 return arc_expand_simd_builtin (exp
, target
, subtarget
, mode
, ignore
);
5156 case ARC_BUILTIN_NOP
:
5157 emit_insn (gen_nop ());
5160 case ARC_BUILTIN_NORM
:
5161 icode
= CODE_FOR_clrsbsi2
;
5162 arg0
= CALL_EXPR_ARG (exp
, 0);
5163 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5164 mode0
= insn_data
[icode
].operand
[1].mode
;
5165 target
= gen_reg_rtx (SImode
);
5167 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5168 op0
= copy_to_mode_reg (mode0
, op0
);
5170 emit_insn (gen_clrsbsi2 (target
, op0
));
5173 case ARC_BUILTIN_NORMW
:
5175 /* FIXME : This should all be HImode, not SImode. */
5176 icode
= CODE_FOR_normw
;
5177 arg0
= CALL_EXPR_ARG (exp
, 0);
5178 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5179 mode0
= insn_data
[icode
].operand
[1].mode
;
5180 target
= gen_reg_rtx (SImode
);
5182 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5183 op0
= copy_to_mode_reg (mode0
, convert_to_mode (mode0
, op0
,0));
5185 emit_insn (gen_normw (target
, op0
));
5188 case ARC_BUILTIN_MUL64
:
5189 icode
= CODE_FOR_mul64
;
5190 arg0
= CALL_EXPR_ARG (exp
, 0);
5191 arg1
= CALL_EXPR_ARG (exp
, 1);
5192 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5193 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5195 mode0
= insn_data
[icode
].operand
[0].mode
;
5196 mode1
= insn_data
[icode
].operand
[1].mode
;
5198 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5199 op0
= copy_to_mode_reg (mode0
, op0
);
5201 if (! (*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
5202 op1
= copy_to_mode_reg (mode1
, op1
);
5204 emit_insn (gen_mul64 (op0
,op1
));
5207 case ARC_BUILTIN_MULU64
:
5208 icode
= CODE_FOR_mulu64
;
5209 arg0
= CALL_EXPR_ARG (exp
, 0);
5210 arg1
= CALL_EXPR_ARG (exp
, 1);
5211 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5212 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5214 mode0
= insn_data
[icode
].operand
[0].mode
;
5215 mode1
= insn_data
[icode
].operand
[1].mode
;
5217 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5218 op0
= copy_to_mode_reg (mode0
, op0
);
5220 if (! (*insn_data
[icode
].operand
[0].predicate
) (op1
, mode1
))
5221 op1
= copy_to_mode_reg (mode1
, op1
);
5223 emit_insn (gen_mulu64 (op0
,op1
));
5226 case ARC_BUILTIN_RTIE
:
5227 icode
= CODE_FOR_rtie
;
5228 emit_insn (gen_rtie (const1_rtx
));
5231 case ARC_BUILTIN_SYNC
:
5232 icode
= CODE_FOR_sync
;
5233 emit_insn (gen_sync (const1_rtx
));
5236 case ARC_BUILTIN_SWAP
:
5237 icode
= CODE_FOR_swap
;
5238 arg0
= CALL_EXPR_ARG (exp
, 0);
5239 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5240 mode0
= insn_data
[icode
].operand
[1].mode
;
5241 target
= gen_reg_rtx (SImode
);
5243 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5244 op0
= copy_to_mode_reg (mode0
, op0
);
5246 emit_insn (gen_swap (target
, op0
));
5249 case ARC_BUILTIN_DIVAW
:
5250 icode
= CODE_FOR_divaw
;
5251 arg0
= CALL_EXPR_ARG (exp
, 0);
5252 arg1
= CALL_EXPR_ARG (exp
, 1);
5254 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5255 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5256 target
= gen_reg_rtx (SImode
);
5258 mode0
= insn_data
[icode
].operand
[0].mode
;
5259 mode1
= insn_data
[icode
].operand
[1].mode
;
5261 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5262 op0
= copy_to_mode_reg (mode0
, op0
);
5264 if (! (*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
5265 op1
= copy_to_mode_reg (mode1
, op1
);
5267 emit_insn (gen_divaw (target
, op0
, op1
));
5270 case ARC_BUILTIN_BRK
:
5271 icode
= CODE_FOR_brk
;
5272 emit_insn (gen_brk (const1_rtx
));
5275 case ARC_BUILTIN_SLEEP
:
5276 icode
= CODE_FOR_sleep
;
5277 arg0
= CALL_EXPR_ARG (exp
, 0);
5281 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5282 mode0
= insn_data
[icode
].operand
[1].mode
;
5284 emit_insn (gen_sleep (op0
));
5287 case ARC_BUILTIN_SWI
:
5288 icode
= CODE_FOR_swi
;
5289 emit_insn (gen_swi (const1_rtx
));
5292 case ARC_BUILTIN_FLAG
:
5293 icode
= CODE_FOR_flag
;
5294 arg0
= CALL_EXPR_ARG (exp
, 0);
5295 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5296 mode0
= insn_data
[icode
].operand
[0].mode
;
5298 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5299 op0
= copy_to_mode_reg (mode0
, op0
);
5301 emit_insn (gen_flag (op0
));
5304 case ARC_BUILTIN_CORE_READ
:
5305 icode
= CODE_FOR_core_read
;
5306 arg0
= CALL_EXPR_ARG (exp
, 0);
5307 target
= gen_reg_rtx (SImode
);
5311 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5312 mode0
= insn_data
[icode
].operand
[1].mode
;
5314 emit_insn (gen_core_read (target
, op0
));
5317 case ARC_BUILTIN_CORE_WRITE
:
5318 icode
= CODE_FOR_core_write
;
5319 arg0
= CALL_EXPR_ARG (exp
, 0);
5320 arg1
= CALL_EXPR_ARG (exp
, 1);
5324 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5325 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5327 mode0
= insn_data
[icode
].operand
[0].mode
;
5328 mode1
= insn_data
[icode
].operand
[1].mode
;
5330 emit_insn (gen_core_write (op0
, op1
));
5333 case ARC_BUILTIN_LR
:
5334 icode
= CODE_FOR_lr
;
5335 arg0
= CALL_EXPR_ARG (exp
, 0);
5336 target
= gen_reg_rtx (SImode
);
5340 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5341 mode0
= insn_data
[icode
].operand
[1].mode
;
5343 emit_insn (gen_lr (target
, op0
));
5346 case ARC_BUILTIN_SR
:
5347 icode
= CODE_FOR_sr
;
5348 arg0
= CALL_EXPR_ARG (exp
, 0);
5349 arg1
= CALL_EXPR_ARG (exp
, 1);
5353 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5354 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5356 mode0
= insn_data
[icode
].operand
[0].mode
;
5357 mode1
= insn_data
[icode
].operand
[1].mode
;
5359 emit_insn (gen_sr (op0
, op1
));
5362 case ARC_BUILTIN_TRAP_S
:
5363 icode
= CODE_FOR_trap_s
;
5364 arg0
= CALL_EXPR_ARG (exp
, 0);
5368 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5369 mode0
= insn_data
[icode
].operand
[1].mode
;
5371 /* We don't give an error for non-cost values here because
5372 we still want to allow things to be fixed up by later inlining /
5373 constant folding / dead code elimination. */
5374 if (CONST_INT_P (op0
) && !satisfies_constraint_L (op0
))
5376 /* Keep this message in sync with the one in arc.md:trap_s,
5377 because *.md files don't get scanned by exgettext. */
5378 error ("operand to trap_s should be an unsigned 6-bit value");
5380 emit_insn (gen_trap_s (op0
));
5383 case ARC_BUILTIN_UNIMP_S
:
5384 icode
= CODE_FOR_unimp_s
;
5385 emit_insn (gen_unimp_s (const1_rtx
));
5388 case ARC_BUILTIN_ALIGNED
:
5389 /* __builtin_arc_aligned (void* val, int alignval) */
5390 arg0
= CALL_EXPR_ARG (exp
, 0);
5391 arg1
= CALL_EXPR_ARG (exp
, 1);
5393 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5394 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5395 target
= gen_reg_rtx (SImode
);
5397 if (!CONST_INT_P (op1
))
5399 /* If we can't fold the alignment to a constant integer
5400 whilst optimizing, this is probably a user error. */
5402 warning (0, "__builtin_arc_aligned with non-constant alignment");
5406 HOST_WIDE_INT alignTest
= INTVAL (op1
);
5407 /* Check alignTest is positive, and a power of two. */
5408 if (alignTest
<= 0 || alignTest
!= (alignTest
& -alignTest
))
5410 error ("invalid alignment value for __builtin_arc_aligned");
5414 if (CONST_INT_P (op0
))
5416 HOST_WIDE_INT pnt
= INTVAL (op0
);
5418 if ((pnt
& (alignTest
- 1)) == 0)
5423 unsigned align
= get_pointer_alignment (arg0
);
5424 unsigned numBits
= alignTest
* BITS_PER_UNIT
;
5426 if (align
&& align
>= numBits
)
5428 /* Another attempt to ascertain alignment. Check the type
5429 we are pointing to. */
5430 if (POINTER_TYPE_P (TREE_TYPE (arg0
))
5431 && TYPE_ALIGN (TREE_TYPE (TREE_TYPE (arg0
))) >= numBits
)
5436 /* Default to false. */
5443 /* @@@ Should really do something sensible here. */
5447 /* Returns true if the operands[opno] is a valid compile-time constant to be
5448 used as register number in the code for builtins. Else it flags an error
5449 and returns false. */
5452 check_if_valid_regno_const (rtx
*operands
, int opno
)
5455 switch (GET_CODE (operands
[opno
]))
5462 error ("register number must be a compile-time constant. Try giving higher optimization levels");
5468 /* Check that after all the constant folding, whether the operand to
5469 __builtin_arc_sleep is an unsigned int of 6 bits. If not, flag an error. */
5472 check_if_valid_sleep_operand (rtx
*operands
, int opno
)
5474 switch (GET_CODE (operands
[opno
]))
5478 if( UNSIGNED_INT6 (INTVAL (operands
[opno
])))
5481 fatal_error (input_location
,
5482 "operand for sleep instruction must be an unsigned 6 bit compile-time constant");
5488 /* Return true if it is ok to make a tail-call to DECL. */
5491 arc_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED
,
5492 tree exp ATTRIBUTE_UNUSED
)
5494 /* Never tailcall from an ISR routine - it needs a special exit sequence. */
5495 if (ARC_INTERRUPT_P (arc_compute_function_type (cfun
)))
5498 /* Everything else is ok. */
5502 /* Output code to add DELTA to the first argument, and then jump
5503 to FUNCTION. Used for C++ multiple inheritance. */
5506 arc_output_mi_thunk (FILE *file
, tree thunk ATTRIBUTE_UNUSED
,
5507 HOST_WIDE_INT delta
,
5508 HOST_WIDE_INT vcall_offset
,
5511 int mi_delta
= delta
;
5512 const char *const mi_op
= mi_delta
< 0 ? "sub" : "add";
5515 = aggregate_value_p (TREE_TYPE (TREE_TYPE (function
)), function
) ? 1 : 0;
5519 mi_delta
= - mi_delta
;
5521 /* Add DELTA. When possible use a plain add, otherwise load it into
5522 a register first. */
5524 while (mi_delta
!= 0)
5526 if ((mi_delta
& (3 << shift
)) == 0)
5530 asm_fprintf (file
, "\t%s\t%s, %s, %d\n",
5531 mi_op
, reg_names
[this_regno
], reg_names
[this_regno
],
5532 mi_delta
& (0xff << shift
));
5533 mi_delta
&= ~(0xff << shift
);
5538 /* If needed, add *(*THIS + VCALL_OFFSET) to THIS. */
5539 if (vcall_offset
!= 0)
5541 /* ld r12,[this] --> temp = *this
5542 add r12,r12,vcall_offset --> temp = *(*this + vcall_offset)
5544 add this,this,r12 --> this+ = *(*this + vcall_offset) */
5545 asm_fprintf (file
, "\tld\t%s, [%s]\n",
5546 ARC_TEMP_SCRATCH_REG
, reg_names
[this_regno
]);
5547 asm_fprintf (file
, "\tadd\t%s, %s, " HOST_WIDE_INT_PRINT_DEC
"\n",
5548 ARC_TEMP_SCRATCH_REG
, ARC_TEMP_SCRATCH_REG
, vcall_offset
);
5549 asm_fprintf (file
, "\tld\t%s, [%s]\n",
5550 ARC_TEMP_SCRATCH_REG
, ARC_TEMP_SCRATCH_REG
);
5551 asm_fprintf (file
, "\tadd\t%s, %s, %s\n", reg_names
[this_regno
],
5552 reg_names
[this_regno
], ARC_TEMP_SCRATCH_REG
);
5555 fnaddr
= XEXP (DECL_RTL (function
), 0);
5557 if (arc_is_longcall_p (fnaddr
))
5558 fputs ("\tj\t", file
);
5560 fputs ("\tb\t", file
);
5561 assemble_name (file
, XSTR (fnaddr
, 0));
5565 /* Return true if a 32 bit "long_call" should be generated for
5566 this calling SYM_REF. We generate a long_call if the function:
5568 a. has an __attribute__((long call))
5569 or b. the -mlong-calls command line switch has been specified
5571 However we do not generate a long call if the function has an
5572 __attribute__ ((short_call)) or __attribute__ ((medium_call))
5574 This function will be called by C fragments contained in the machine
5575 description file. */
5578 arc_is_longcall_p (rtx sym_ref
)
5580 if (GET_CODE (sym_ref
) != SYMBOL_REF
)
5583 return (SYMBOL_REF_LONG_CALL_P (sym_ref
)
5584 || (TARGET_LONG_CALLS_SET
5585 && !SYMBOL_REF_SHORT_CALL_P (sym_ref
)
5586 && !SYMBOL_REF_MEDIUM_CALL_P (sym_ref
)));
5590 /* Likewise for short calls. */
5593 arc_is_shortcall_p (rtx sym_ref
)
5595 if (GET_CODE (sym_ref
) != SYMBOL_REF
)
5598 return (SYMBOL_REF_SHORT_CALL_P (sym_ref
)
5599 || (!TARGET_LONG_CALLS_SET
&& !TARGET_MEDIUM_CALLS
5600 && !SYMBOL_REF_LONG_CALL_P (sym_ref
)
5601 && !SYMBOL_REF_MEDIUM_CALL_P (sym_ref
)));
5605 /* Emit profiling code for calling CALLEE. Return true if a special
5606 call pattern needs to be generated. */
5609 arc_profile_call (rtx callee
)
5611 rtx from
= XEXP (DECL_RTL (current_function_decl
), 0);
5613 if (TARGET_UCB_MCOUNT
)
5614 /* Profiling is done by instrumenting the callee. */
5617 if (CONSTANT_P (callee
))
5620 = gen_rtx_CONST (Pmode
,
5621 gen_rtx_UNSPEC (Pmode
,
5622 gen_rtvec (3, from
, callee
,
5623 CONST0_RTX (Pmode
)),
5625 rtx counter
= gen_rtx_MEM (SImode
, count_ptr
);
5626 /* ??? The increment would better be done atomically, but as there is
5627 no proper hardware support, that would be too expensive. */
5628 emit_move_insn (counter
,
5629 force_reg (SImode
, plus_constant (SImode
, counter
, 1)));
5635 = gen_rtx_CONST (Pmode
,
5636 gen_rtx_UNSPEC (Pmode
,
5637 gen_rtvec (3, from
, CONST0_RTX (Pmode
),
5638 CONST0_RTX (Pmode
)),
5640 emit_move_insn (gen_rtx_REG (Pmode
, 8), count_list_ptr
);
5641 emit_move_insn (gen_rtx_REG (Pmode
, 9), callee
);
5646 /* Worker function for TARGET_RETURN_IN_MEMORY. */
5649 arc_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
5651 if (AGGREGATE_TYPE_P (type
) || TREE_ADDRESSABLE (type
))
5655 HOST_WIDE_INT size
= int_size_in_bytes (type
);
5656 return (size
== -1 || size
> 8);
5661 /* This was in rtlanal.c, and can go in there when we decide we want
5662 to submit the change for inclusion in the GCC tree. */
5663 /* Like note_stores, but allow the callback to have side effects on the rtl
5664 (like the note_stores of yore):
5665 Call FUN on each register or MEM that is stored into or clobbered by X.
5666 (X would be the pattern of an insn). DATA is an arbitrary pointer,
5667 ignored by note_stores, but passed to FUN.
5668 FUN may alter parts of the RTL.
5670 FUN receives three arguments:
5671 1. the REG, MEM, CC0 or PC being stored in or clobbered,
5672 2. the SET or CLOBBER rtx that does the store,
5673 3. the pointer DATA provided to note_stores.
5675 If the item being stored in or clobbered is a SUBREG of a hard register,
5676 the SUBREG will be passed. */
5678 /* For now. */ static
5680 walk_stores (rtx x
, void (*fun
) (rtx
, rtx
, void *), void *data
)
5684 if (GET_CODE (x
) == COND_EXEC
)
5685 x
= COND_EXEC_CODE (x
);
5687 if (GET_CODE (x
) == SET
|| GET_CODE (x
) == CLOBBER
)
5689 rtx dest
= SET_DEST (x
);
5691 while ((GET_CODE (dest
) == SUBREG
5692 && (!REG_P (SUBREG_REG (dest
))
5693 || REGNO (SUBREG_REG (dest
)) >= FIRST_PSEUDO_REGISTER
))
5694 || GET_CODE (dest
) == ZERO_EXTRACT
5695 || GET_CODE (dest
) == STRICT_LOW_PART
)
5696 dest
= XEXP (dest
, 0);
5698 /* If we have a PARALLEL, SET_DEST is a list of EXPR_LIST expressions,
5699 each of whose first operand is a register. */
5700 if (GET_CODE (dest
) == PARALLEL
)
5702 for (i
= XVECLEN (dest
, 0) - 1; i
>= 0; i
--)
5703 if (XEXP (XVECEXP (dest
, 0, i
), 0) != 0)
5704 (*fun
) (XEXP (XVECEXP (dest
, 0, i
), 0), x
, data
);
5707 (*fun
) (dest
, x
, data
);
5710 else if (GET_CODE (x
) == PARALLEL
)
5711 for (i
= XVECLEN (x
, 0) - 1; i
>= 0; i
--)
5712 walk_stores (XVECEXP (x
, 0, i
), fun
, data
);
5716 arc_pass_by_reference (cumulative_args_t ca_v ATTRIBUTE_UNUSED
,
5717 machine_mode mode ATTRIBUTE_UNUSED
,
5719 bool named ATTRIBUTE_UNUSED
)
5722 && (TREE_CODE (TYPE_SIZE (type
)) != INTEGER_CST
5723 || TREE_ADDRESSABLE (type
)));
5726 /* Implement TARGET_CAN_USE_DOLOOP_P. */
5729 arc_can_use_doloop_p (const widest_int
&iterations
, const widest_int
&,
5730 unsigned int loop_depth
, bool entered_at_top
)
5734 /* Setting up the loop with two sr instructions costs 6 cycles. */
5737 && wi::gtu_p (iterations
, 0)
5738 && wi::leu_p (iterations
, flag_pic
? 6 : 3))
5743 /* NULL if INSN insn is valid within a low-overhead loop.
5744 Otherwise return why doloop cannot be applied. */
5747 arc_invalid_within_doloop (const rtx_insn
*insn
)
5750 return "Function call in the loop.";
5754 static int arc_reorg_in_progress
= 0;
5756 /* ARC's machince specific reorg function. */
5767 cfun
->machine
->arc_reorg_started
= 1;
5768 arc_reorg_in_progress
= 1;
5770 /* Emit special sections for profiling. */
5773 section
*save_text_section
;
5775 int size
= get_max_uid () >> 4;
5776 htab_t htab
= htab_create (size
, unspec_prof_hash
, unspec_prof_htab_eq
,
5779 save_text_section
= in_section
;
5780 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
5781 if (NONJUMP_INSN_P (insn
))
5782 walk_stores (PATTERN (insn
), write_profile_sections
, htab
);
5783 if (htab_elements (htab
))
5785 switch_to_section (save_text_section
);
5789 /* Link up loop ends with their loop start. */
5791 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
5792 if (GET_CODE (insn
) == JUMP_INSN
5793 && recog_memoized (insn
) == CODE_FOR_doloop_end_i
)
5796 = as_a
<rtx_insn
*> (XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn
), 0, 0)), 1), 0));
5797 rtx num
= GEN_INT (CODE_LABEL_NUMBER (top_label
));
5798 rtx_insn
*lp
, *prev
= prev_nonnote_insn (top_label
);
5799 rtx_insn
*lp_simple
= NULL
;
5800 rtx_insn
*next
= NULL
;
5801 rtx op0
= XEXP (XVECEXP (PATTERN (insn
), 0, 1), 0);
5802 HOST_WIDE_INT loop_end_id
5803 = -INTVAL (XEXP (XVECEXP (PATTERN (insn
), 0, 4), 0));
5807 (lp
&& NONJUMP_INSN_P (lp
)
5808 && recog_memoized (lp
) != CODE_FOR_doloop_begin_i
);
5809 lp
= prev_nonnote_insn (lp
))
5811 if (!lp
|| !NONJUMP_INSN_P (lp
)
5812 || dead_or_set_regno_p (lp
, LP_COUNT
))
5814 for (prev
= next
= insn
, lp
= NULL
; prev
|| next
;)
5818 if (NONJUMP_INSN_P (prev
)
5819 && recog_memoized (prev
) == CODE_FOR_doloop_begin_i
5820 && (INTVAL (XEXP (XVECEXP (PATTERN (prev
), 0, 5), 0))
5826 else if (LABEL_P (prev
))
5828 prev
= prev_nonnote_insn (prev
);
5832 if (NONJUMP_INSN_P (next
)
5833 && recog_memoized (next
) == CODE_FOR_doloop_begin_i
5834 && (INTVAL (XEXP (XVECEXP (PATTERN (next
), 0, 5), 0))
5840 next
= next_nonnote_insn (next
);
5847 if (lp
&& !dead_or_set_regno_p (lp
, LP_COUNT
))
5849 rtx begin_cnt
= XEXP (XVECEXP (PATTERN (lp
), 0 ,3), 0);
5850 if (INTVAL (XEXP (XVECEXP (PATTERN (lp
), 0, 4), 0)))
5851 /* The loop end insn has been duplicated. That can happen
5852 when there is a conditional block at the very end of
5855 /* If Register allocation failed to allocate to the right
5856 register, There is no point into teaching reload to
5857 fix this up with reloads, as that would cost more
5858 than using an ordinary core register with the
5859 doloop_fallback pattern. */
5860 if ((true_regnum (op0
) != LP_COUNT
|| !REG_P (begin_cnt
))
5861 /* Likewise, if the loop setup is evidently inside the loop,
5863 || (!lp_simple
&& lp
!= next
&& !seen_label
))
5868 /* It is common that the optimizers copy the loop count from
5869 another register, and doloop_begin_i is stuck with the
5870 source of the move. Making doloop_begin_i only accept "l"
5871 is nonsentical, as this then makes reload evict the pseudo
5872 used for the loop end. The underlying cause is that the
5873 optimizers don't understand that the register allocation for
5874 doloop_begin_i should be treated as part of the loop.
5875 Try to work around this problem by verifying the previous
5877 if (true_regnum (begin_cnt
) != LP_COUNT
)
5882 for (mov
= prev_nonnote_insn (lp
); mov
;
5883 mov
= prev_nonnote_insn (mov
))
5885 if (!NONJUMP_INSN_P (mov
))
5887 else if ((set
= single_set (mov
))
5888 && rtx_equal_p (SET_SRC (set
), begin_cnt
)
5889 && rtx_equal_p (SET_DEST (set
), op0
))
5894 XEXP (XVECEXP (PATTERN (lp
), 0 ,3), 0) = op0
;
5895 note
= find_regno_note (lp
, REG_DEAD
, REGNO (begin_cnt
));
5897 remove_note (lp
, note
);
5905 XEXP (XVECEXP (PATTERN (insn
), 0, 4), 0) = num
;
5906 XEXP (XVECEXP (PATTERN (lp
), 0, 4), 0) = num
;
5908 XEXP (XVECEXP (PATTERN (lp
), 0, 6), 0) = const2_rtx
;
5909 else if (!lp_simple
)
5910 XEXP (XVECEXP (PATTERN (lp
), 0, 6), 0) = const1_rtx
;
5911 else if (prev
!= lp
)
5914 add_insn_after (lp
, prev
, NULL
);
5918 XEXP (XVECEXP (PATTERN (lp
), 0, 7), 0)
5919 = gen_rtx_LABEL_REF (Pmode
, top_label
);
5920 add_reg_note (lp
, REG_LABEL_OPERAND
, top_label
);
5921 LABEL_NUSES (top_label
)++;
5923 /* We can avoid tedious loop start / end setting for empty loops
5924 be merely setting the loop count to its final value. */
5925 if (next_active_insn (top_label
) == insn
)
5928 = gen_rtx_SET (XEXP (XVECEXP (PATTERN (lp
), 0, 3), 0),
5931 rtx_insn
*lc_set_insn
= emit_insn_before (lc_set
, insn
);
5936 /* If the loop is non-empty with zero length, we can't make it
5937 a zero-overhead loop. That can happen for empty asms. */
5942 for (scan
= top_label
;
5943 (scan
&& scan
!= insn
5944 && (!NONJUMP_INSN_P (scan
) || !get_attr_length (scan
)));
5945 scan
= NEXT_INSN (scan
));
5955 /* Sometimes the loop optimizer makes a complete hash of the
5956 loop. If it were only that the loop is not entered at the
5957 top, we could fix this up by setting LP_START with SR .
5958 However, if we can't find the loop begin were it should be,
5959 chances are that it does not even dominate the loop, but is
5960 inside the loop instead. Using SR there would kill
5962 We use the doloop_fallback pattern here, which executes
5963 in two cycles on the ARC700 when predicted correctly. */
5967 rtx op3
= XEXP (XVECEXP (PATTERN (insn
), 0, 5), 0);
5969 emit_insn_before (gen_move_insn (op3
, op0
), insn
);
5971 = gen_doloop_fallback_m (op3
, JUMP_LABEL (insn
), op0
);
5974 XVEC (PATTERN (insn
), 0)
5975 = gen_rtvec (2, XVECEXP (PATTERN (insn
), 0, 0),
5976 XVECEXP (PATTERN (insn
), 0, 1));
5977 INSN_CODE (insn
) = -1;
5982 /* FIXME: should anticipate ccfsm action, generate special patterns for
5983 to-be-deleted branches that have no delay slot and have at least the
5984 length of the size increase forced on other insns that are conditionalized.
5985 This can also have an insn_list inside that enumerates insns which are
5986 not actually conditionalized because the destinations are dead in the
5988 Could also tag branches that we want to be unaligned if they get no delay
5989 slot, or even ones that we don't want to do delay slot sheduling for
5990 because we can unalign them.
5992 However, there are cases when conditional execution is only possible after
5993 delay slot scheduling:
5995 - If a delay slot is filled with a nocond/set insn from above, the previous
5996 basic block can become elegible for conditional execution.
5997 - If a delay slot is filled with a nocond insn from the fall-through path,
5998 the branch with that delay slot can become eligble for conditional
5999 execution (however, with the same sort of data flow analysis that dbr
6000 does, we could have figured out before that we don't need to
6001 conditionalize this insn.)
6002 - If a delay slot insn is filled with an insn from the target, the
6003 target label gets its uses decremented (even deleted if falling to zero),
6004 thus possibly creating more condexec opportunities there.
6005 Therefore, we should still be prepared to apply condexec optimization on
6006 non-prepared branches if the size increase of conditionalized insns is no
6007 more than the size saved from eliminating the branch. An invocation option
6008 could also be used to reserve a bit of extra size for condbranches so that
6009 this'll work more often (could also test in arc_reorg if the block is
6010 'close enough' to be eligible for condexec to make this likely, and
6011 estimate required size increase). */
6012 /* Generate BRcc insns, by combining cmp and Bcc insns wherever possible. */
6013 if (TARGET_NO_BRCC_SET
)
6018 init_insn_lengths();
6021 if (optimize
> 1 && !TARGET_NO_COND_EXEC
)
6024 unsigned int flags
= pass_data_arc_ifcvt
.todo_flags_finish
;
6025 df_finish_pass ((flags
& TODO_df_verify
) != 0);
6028 /* Call shorten_branches to calculate the insn lengths. */
6029 shorten_branches (get_insns());
6030 cfun
->machine
->ccfsm_current_insn
= NULL_RTX
;
6032 if (!INSN_ADDRESSES_SET_P())
6033 fatal_error (input_location
, "Insn addresses not set after shorten_branches");
6035 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
6038 enum attr_type insn_type
;
6040 /* If a non-jump insn (or a casesi jump table), continue. */
6041 if (GET_CODE (insn
) != JUMP_INSN
||
6042 GET_CODE (PATTERN (insn
)) == ADDR_VEC
6043 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
6046 /* If we already have a brcc, note if it is suitable for brcc_s.
6047 Be a bit generous with the brcc_s range so that we can take
6048 advantage of any code shortening from delay slot scheduling. */
6049 if (recog_memoized (insn
) == CODE_FOR_cbranchsi4_scratch
)
6051 rtx pat
= PATTERN (insn
);
6052 rtx op
= XEXP (SET_SRC (XVECEXP (pat
, 0, 0)), 0);
6053 rtx
*ccp
= &XEXP (XVECEXP (pat
, 0, 1), 0);
6055 offset
= branch_dest (insn
) - INSN_ADDRESSES (INSN_UID (insn
));
6056 if ((offset
>= -140 && offset
< 140)
6057 && rtx_equal_p (XEXP (op
, 1), const0_rtx
)
6058 && compact_register_operand (XEXP (op
, 0), VOIDmode
)
6059 && equality_comparison_operator (op
, VOIDmode
))
6060 PUT_MODE (*ccp
, CC_Zmode
);
6061 else if (GET_MODE (*ccp
) == CC_Zmode
)
6062 PUT_MODE (*ccp
, CC_ZNmode
);
6065 if ((insn_type
= get_attr_type (insn
)) == TYPE_BRCC
6066 || insn_type
== TYPE_BRCC_NO_DELAY_SLOT
)
6069 /* OK. so we have a jump insn. */
6070 /* We need to check that it is a bcc. */
6071 /* Bcc => set (pc) (if_then_else ) */
6072 pattern
= PATTERN (insn
);
6073 if (GET_CODE (pattern
) != SET
6074 || GET_CODE (SET_SRC (pattern
)) != IF_THEN_ELSE
6075 || ANY_RETURN_P (XEXP (SET_SRC (pattern
), 1)))
6078 /* Now check if the jump is beyond the s9 range. */
6079 if (CROSSING_JUMP_P (insn
))
6081 offset
= branch_dest (insn
) - INSN_ADDRESSES (INSN_UID (insn
));
6083 if(offset
> 253 || offset
< -254)
6086 pc_target
= SET_SRC (pattern
);
6088 /* Now go back and search for the set cc insn. */
6090 label
= XEXP (pc_target
, 1);
6094 rtx_insn
*scan
, *link_insn
= NULL
;
6096 for (scan
= PREV_INSN (insn
);
6097 scan
&& GET_CODE (scan
) != CODE_LABEL
;
6098 scan
= PREV_INSN (scan
))
6100 if (! INSN_P (scan
))
6102 pat
= PATTERN (scan
);
6103 if (GET_CODE (pat
) == SET
6104 && cc_register (SET_DEST (pat
), VOIDmode
))
6113 /* Check if this is a data dependency. */
6115 rtx op
, cc_clob_rtx
, op0
, op1
, brcc_insn
, note
;
6118 /* Ok this is the set cc. copy args here. */
6119 op
= XEXP (pc_target
, 0);
6121 op0
= cmp0
= XEXP (SET_SRC (pat
), 0);
6122 op1
= cmp1
= XEXP (SET_SRC (pat
), 1);
6123 if (GET_CODE (op0
) == ZERO_EXTRACT
6124 && XEXP (op0
, 1) == const1_rtx
6125 && (GET_CODE (op
) == EQ
6126 || GET_CODE (op
) == NE
))
6128 /* btst / b{eq,ne} -> bbit{0,1} */
6129 op0
= XEXP (cmp0
, 0);
6130 op1
= XEXP (cmp0
, 2);
6132 else if (!register_operand (op0
, VOIDmode
)
6133 || !general_operand (op1
, VOIDmode
))
6135 /* Be careful not to break what cmpsfpx_raw is
6136 trying to create for checking equality of
6137 single-precision floats. */
6138 else if (TARGET_SPFP
6139 && GET_MODE (op0
) == SFmode
6140 && GET_MODE (op1
) == SFmode
)
6143 /* None of the two cmp operands should be set between the
6144 cmp and the branch. */
6145 if (reg_set_between_p (op0
, link_insn
, insn
))
6148 if (reg_set_between_p (op1
, link_insn
, insn
))
6151 /* Since the MODE check does not work, check that this is
6152 CC reg's last set location before insn, and also no
6153 instruction between the cmp and branch uses the
6155 if ((reg_set_between_p (SET_DEST (pat
), link_insn
, insn
))
6156 || (reg_used_between_p (SET_DEST (pat
), link_insn
, insn
)))
6159 /* CC reg should be dead after insn. */
6160 if (!find_regno_note (insn
, REG_DEAD
, CC_REG
))
6163 op
= gen_rtx_fmt_ee (GET_CODE (op
),
6164 GET_MODE (op
), cmp0
, cmp1
);
6165 /* If we create a LIMM where there was none before,
6166 we only benefit if we can avoid a scheduling bubble
6167 for the ARC600. Otherwise, we'd only forgo chances
6168 at short insn generation, and risk out-of-range
6170 if (!brcc_nolimm_operator (op
, VOIDmode
)
6171 && !long_immediate_operand (op1
, VOIDmode
)
6173 || next_active_insn (link_insn
) != insn
))
6176 /* Emit bbit / brcc (or brcc_s if possible).
6177 CC_Zmode indicates that brcc_s is possible. */
6180 cc_clob_rtx
= gen_rtx_REG (CC_ZNmode
, CC_REG
);
6181 else if ((offset
>= -140 && offset
< 140)
6182 && rtx_equal_p (op1
, const0_rtx
)
6183 && compact_register_operand (op0
, VOIDmode
)
6184 && (GET_CODE (op
) == EQ
6185 || GET_CODE (op
) == NE
))
6186 cc_clob_rtx
= gen_rtx_REG (CC_Zmode
, CC_REG
);
6188 cc_clob_rtx
= gen_rtx_REG (CCmode
, CC_REG
);
6191 = gen_rtx_IF_THEN_ELSE (VOIDmode
, op
, label
, pc_rtx
);
6192 brcc_insn
= gen_rtx_SET (pc_rtx
, brcc_insn
);
6193 cc_clob_rtx
= gen_rtx_CLOBBER (VOIDmode
, cc_clob_rtx
);
6196 (VOIDmode
, gen_rtvec (2, brcc_insn
, cc_clob_rtx
));
6197 brcc_insn
= emit_jump_insn_before (brcc_insn
, insn
);
6199 JUMP_LABEL (brcc_insn
) = JUMP_LABEL (insn
);
6200 note
= find_reg_note (insn
, REG_BR_PROB
, 0);
6203 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6204 REG_NOTES (brcc_insn
) = note
;
6206 note
= find_reg_note (link_insn
, REG_DEAD
, op0
);
6209 remove_note (link_insn
, note
);
6210 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6211 REG_NOTES (brcc_insn
) = note
;
6213 note
= find_reg_note (link_insn
, REG_DEAD
, op1
);
6216 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6217 REG_NOTES (brcc_insn
) = note
;
6222 /* Delete the bcc insn. */
6223 set_insn_deleted (insn
);
6225 /* Delete the cmp insn. */
6226 set_insn_deleted (link_insn
);
6231 /* Clear out insn_addresses. */
6232 INSN_ADDRESSES_FREE ();
6236 if (INSN_ADDRESSES_SET_P())
6237 fatal_error (input_location
, "insn addresses not freed");
6239 arc_reorg_in_progress
= 0;
6242 /* Check if the operands are valid for BRcc.d generation
6243 Valid Brcc.d patterns are
6247 For cc={GT, LE, GTU, LEU}, u6=63 can not be allowed,
6248 since they are encoded by the assembler as {GE, LT, HS, LS} 64, which
6249 does not have a delay slot
6251 Assumed precondition: Second operand is either a register or a u6 value. */
6254 valid_brcc_with_delay_p (rtx
*operands
)
6256 if (optimize_size
&& GET_MODE (operands
[4]) == CC_Zmode
)
6258 return brcc_nolimm_operator (operands
[0], VOIDmode
);
6261 /* ??? Hack. This should no really be here. See PR32143. */
6263 arc_decl_anon_ns_mem_p (const_tree decl
)
6267 if (decl
== NULL_TREE
|| decl
== error_mark_node
)
6269 if (TREE_CODE (decl
) == NAMESPACE_DECL
6270 && DECL_NAME (decl
) == NULL_TREE
)
6272 /* Classes and namespaces inside anonymous namespaces have
6273 TREE_PUBLIC == 0, so we can shortcut the search. */
6274 else if (TYPE_P (decl
))
6275 return (TREE_PUBLIC (TYPE_NAME (decl
)) == 0);
6276 else if (TREE_CODE (decl
) == NAMESPACE_DECL
)
6277 return (TREE_PUBLIC (decl
) == 0);
6279 decl
= DECL_CONTEXT (decl
);
6283 /* Implement TARGET_IN_SMALL_DATA_P. Return true if it would be safe to
6284 access DECL using %gp_rel(...)($gp). */
6287 arc_in_small_data_p (const_tree decl
)
6291 if (TREE_CODE (decl
) == STRING_CST
|| TREE_CODE (decl
) == FUNCTION_DECL
)
6295 /* We don't yet generate small-data references for -mabicalls. See related
6296 -G handling in override_options. */
6297 if (TARGET_NO_SDATA_SET
)
6300 if (TREE_CODE (decl
) == VAR_DECL
&& DECL_SECTION_NAME (decl
) != 0)
6304 /* Reject anything that isn't in a known small-data section. */
6305 name
= DECL_SECTION_NAME (decl
);
6306 if (strcmp (name
, ".sdata") != 0 && strcmp (name
, ".sbss") != 0)
6309 /* If a symbol is defined externally, the assembler will use the
6310 usual -G rules when deciding how to implement macros. */
6311 if (!DECL_EXTERNAL (decl
))
6314 /* Only global variables go into sdata section for now. */
6317 /* Don't put constants into the small data section: we want them
6318 to be in ROM rather than RAM. */
6319 if (TREE_CODE (decl
) != VAR_DECL
)
6322 if (TREE_READONLY (decl
)
6323 && !TREE_SIDE_EFFECTS (decl
)
6324 && (!DECL_INITIAL (decl
) || TREE_CONSTANT (DECL_INITIAL (decl
))))
6327 /* TREE_PUBLIC might change after the first call, because of the patch
6329 if (default_binds_local_p_1 (decl
, 1)
6330 || arc_decl_anon_ns_mem_p (decl
))
6333 /* To ensure -mvolatile-cache works
6334 ld.di does not have a gp-relative variant. */
6335 if (TREE_THIS_VOLATILE (decl
))
6339 /* Disable sdata references to weak variables. */
6340 if (DECL_WEAK (decl
))
6343 size
= int_size_in_bytes (TREE_TYPE (decl
));
6345 /* if (AGGREGATE_TYPE_P (TREE_TYPE (decl))) */
6348 /* Allow only <=4B long data types into sdata. */
6349 return (size
> 0 && size
<= 4);
6352 /* Return true if X is a small data address that can be rewritten
6356 arc_rewrite_small_data_p (const_rtx x
)
6358 if (GET_CODE (x
) == CONST
)
6361 if (GET_CODE (x
) == PLUS
)
6363 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
6367 return (GET_CODE (x
) == SYMBOL_REF
6368 && SYMBOL_REF_SMALL_P(x
));
6371 /* If possible, rewrite OP so that it refers to small data using
6372 explicit relocations. */
6375 arc_rewrite_small_data (rtx op
)
6377 op
= copy_insn (op
);
6378 subrtx_ptr_iterator::array_type array
;
6379 FOR_EACH_SUBRTX_PTR (iter
, array
, &op
, ALL
)
6382 if (arc_rewrite_small_data_p (*loc
))
6384 gcc_assert (SDATA_BASE_REGNUM
== PIC_OFFSET_TABLE_REGNUM
);
6385 *loc
= gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, *loc
);
6388 if (GET_CODE (op
) == MEM
&& &XEXP (op
, 0) == loc
)
6390 else if (GET_CODE (op
) == MEM
6391 && GET_CODE (XEXP (op
, 0)) == PLUS
6392 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == MULT
)
6393 *loc
= force_reg (Pmode
, *loc
);
6397 iter
.skip_subrtxes ();
6399 else if (GET_CODE (*loc
) == PLUS
6400 && rtx_equal_p (XEXP (*loc
, 0), pic_offset_table_rtx
))
6401 iter
.skip_subrtxes ();
6406 /* Return true if OP refers to small data symbols directly, not through
6410 small_data_pattern (rtx op
, machine_mode
)
6412 if (GET_CODE (op
) == SEQUENCE
)
6414 subrtx_iterator::array_type array
;
6415 FOR_EACH_SUBRTX (iter
, array
, op
, ALL
)
6417 const_rtx x
= *iter
;
6418 if (GET_CODE (x
) == PLUS
6419 && rtx_equal_p (XEXP (x
, 0), pic_offset_table_rtx
))
6420 iter
.skip_subrtxes ();
6421 else if (arc_rewrite_small_data_p (x
))
6427 /* Return true if OP is an acceptable memory operand for ARCompact
6428 16-bit gp-relative load instructions.
6429 op shd look like : [r26, symref@sda]
6430 i.e. (mem (plus (reg 26) (symref with smalldata flag set))
6432 /* volatile cache option still to be handled. */
6435 compact_sda_memory_operand (rtx op
, machine_mode mode
)
6440 /* Eliminate non-memory operations. */
6441 if (GET_CODE (op
) != MEM
)
6444 if (mode
== VOIDmode
)
6445 mode
= GET_MODE (op
);
6447 size
= GET_MODE_SIZE (mode
);
6449 /* dword operations really put out 2 instructions, so eliminate them. */
6450 if (size
> UNITS_PER_WORD
)
6453 /* Decode the address now. */
6454 addr
= XEXP (op
, 0);
6456 return LEGITIMATE_SMALL_DATA_ADDRESS_P (addr
);
6459 /* Implement ASM_OUTPUT_ALIGNED_DECL_LOCAL. */
6462 arc_asm_output_aligned_decl_local (FILE * stream
, tree decl
, const char * name
,
6463 unsigned HOST_WIDE_INT size
,
6464 unsigned HOST_WIDE_INT align
,
6465 unsigned HOST_WIDE_INT globalize_p
)
6467 int in_small_data
= arc_in_small_data_p (decl
);
6470 switch_to_section (get_named_section (NULL
, ".sbss", 0));
6471 /* named_section (0,".sbss",0); */
6473 switch_to_section (bss_section
);
6476 (*targetm
.asm_out
.globalize_label
) (stream
, name
);
6478 ASM_OUTPUT_ALIGN (stream
, floor_log2 ((align
) / BITS_PER_UNIT
));
6479 ASM_OUTPUT_TYPE_DIRECTIVE (stream
, name
, "object");
6480 ASM_OUTPUT_SIZE_DIRECTIVE (stream
, name
, size
);
6481 ASM_OUTPUT_LABEL (stream
, name
);
6484 ASM_OUTPUT_SKIP (stream
, size
);
6520 /* SIMD builtins support. */
6521 enum simd_insn_args_type
{
6544 struct builtin_description
6546 enum simd_insn_args_type args_type
;
6547 const enum insn_code icode
;
6548 const char * const name
;
6549 const enum arc_builtins code
;
6552 static const struct builtin_description arc_simd_builtin_desc_list
[] =
6554 /* VVV builtins go first. */
6555 #define SIMD_BUILTIN(type, code, string, builtin) \
6556 { type,CODE_FOR_##code, "__builtin_arc_" string, \
6557 ARC_SIMD_BUILTIN_##builtin },
6559 SIMD_BUILTIN (Va_Vb_Vc
, vaddaw_insn
, "vaddaw", VADDAW
)
6560 SIMD_BUILTIN (Va_Vb_Vc
, vaddw_insn
, "vaddw", VADDW
)
6561 SIMD_BUILTIN (Va_Vb_Vc
, vavb_insn
, "vavb", VAVB
)
6562 SIMD_BUILTIN (Va_Vb_Vc
, vavrb_insn
, "vavrb", VAVRB
)
6563 SIMD_BUILTIN (Va_Vb_Vc
, vdifaw_insn
, "vdifaw", VDIFAW
)
6564 SIMD_BUILTIN (Va_Vb_Vc
, vdifw_insn
, "vdifw", VDIFW
)
6565 SIMD_BUILTIN (Va_Vb_Vc
, vmaxaw_insn
, "vmaxaw", VMAXAW
)
6566 SIMD_BUILTIN (Va_Vb_Vc
, vmaxw_insn
, "vmaxw", VMAXW
)
6567 SIMD_BUILTIN (Va_Vb_Vc
, vminaw_insn
, "vminaw", VMINAW
)
6568 SIMD_BUILTIN (Va_Vb_Vc
, vminw_insn
, "vminw", VMINW
)
6569 SIMD_BUILTIN (Va_Vb_Vc
, vmulaw_insn
, "vmulaw", VMULAW
)
6570 SIMD_BUILTIN (Va_Vb_Vc
, vmulfaw_insn
, "vmulfaw", VMULFAW
)
6571 SIMD_BUILTIN (Va_Vb_Vc
, vmulfw_insn
, "vmulfw", VMULFW
)
6572 SIMD_BUILTIN (Va_Vb_Vc
, vmulw_insn
, "vmulw", VMULW
)
6573 SIMD_BUILTIN (Va_Vb_Vc
, vsubaw_insn
, "vsubaw", VSUBAW
)
6574 SIMD_BUILTIN (Va_Vb_Vc
, vsubw_insn
, "vsubw", VSUBW
)
6575 SIMD_BUILTIN (Va_Vb_Vc
, vsummw_insn
, "vsummw", VSUMMW
)
6576 SIMD_BUILTIN (Va_Vb_Vc
, vand_insn
, "vand", VAND
)
6577 SIMD_BUILTIN (Va_Vb_Vc
, vandaw_insn
, "vandaw", VANDAW
)
6578 SIMD_BUILTIN (Va_Vb_Vc
, vbic_insn
, "vbic", VBIC
)
6579 SIMD_BUILTIN (Va_Vb_Vc
, vbicaw_insn
, "vbicaw", VBICAW
)
6580 SIMD_BUILTIN (Va_Vb_Vc
, vor_insn
, "vor", VOR
)
6581 SIMD_BUILTIN (Va_Vb_Vc
, vxor_insn
, "vxor", VXOR
)
6582 SIMD_BUILTIN (Va_Vb_Vc
, vxoraw_insn
, "vxoraw", VXORAW
)
6583 SIMD_BUILTIN (Va_Vb_Vc
, veqw_insn
, "veqw", VEQW
)
6584 SIMD_BUILTIN (Va_Vb_Vc
, vlew_insn
, "vlew", VLEW
)
6585 SIMD_BUILTIN (Va_Vb_Vc
, vltw_insn
, "vltw", VLTW
)
6586 SIMD_BUILTIN (Va_Vb_Vc
, vnew_insn
, "vnew", VNEW
)
6587 SIMD_BUILTIN (Va_Vb_Vc
, vmr1aw_insn
, "vmr1aw", VMR1AW
)
6588 SIMD_BUILTIN (Va_Vb_Vc
, vmr1w_insn
, "vmr1w", VMR1W
)
6589 SIMD_BUILTIN (Va_Vb_Vc
, vmr2aw_insn
, "vmr2aw", VMR2AW
)
6590 SIMD_BUILTIN (Va_Vb_Vc
, vmr2w_insn
, "vmr2w", VMR2W
)
6591 SIMD_BUILTIN (Va_Vb_Vc
, vmr3aw_insn
, "vmr3aw", VMR3AW
)
6592 SIMD_BUILTIN (Va_Vb_Vc
, vmr3w_insn
, "vmr3w", VMR3W
)
6593 SIMD_BUILTIN (Va_Vb_Vc
, vmr4aw_insn
, "vmr4aw", VMR4AW
)
6594 SIMD_BUILTIN (Va_Vb_Vc
, vmr4w_insn
, "vmr4w", VMR4W
)
6595 SIMD_BUILTIN (Va_Vb_Vc
, vmr5aw_insn
, "vmr5aw", VMR5AW
)
6596 SIMD_BUILTIN (Va_Vb_Vc
, vmr5w_insn
, "vmr5w", VMR5W
)
6597 SIMD_BUILTIN (Va_Vb_Vc
, vmr6aw_insn
, "vmr6aw", VMR6AW
)
6598 SIMD_BUILTIN (Va_Vb_Vc
, vmr6w_insn
, "vmr6w", VMR6W
)
6599 SIMD_BUILTIN (Va_Vb_Vc
, vmr7aw_insn
, "vmr7aw", VMR7AW
)
6600 SIMD_BUILTIN (Va_Vb_Vc
, vmr7w_insn
, "vmr7w", VMR7W
)
6601 SIMD_BUILTIN (Va_Vb_Vc
, vmrb_insn
, "vmrb", VMRB
)
6602 SIMD_BUILTIN (Va_Vb_Vc
, vh264f_insn
, "vh264f", VH264F
)
6603 SIMD_BUILTIN (Va_Vb_Vc
, vh264ft_insn
, "vh264ft", VH264FT
)
6604 SIMD_BUILTIN (Va_Vb_Vc
, vh264fw_insn
, "vh264fw", VH264FW
)
6605 SIMD_BUILTIN (Va_Vb_Vc
, vvc1f_insn
, "vvc1f", VVC1F
)
6606 SIMD_BUILTIN (Va_Vb_Vc
, vvc1ft_insn
, "vvc1ft", VVC1FT
)
6608 SIMD_BUILTIN (Va_Vb_rlimm
, vbaddw_insn
, "vbaddw", VBADDW
)
6609 SIMD_BUILTIN (Va_Vb_rlimm
, vbmaxw_insn
, "vbmaxw", VBMAXW
)
6610 SIMD_BUILTIN (Va_Vb_rlimm
, vbminw_insn
, "vbminw", VBMINW
)
6611 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulaw_insn
, "vbmulaw", VBMULAW
)
6612 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulfw_insn
, "vbmulfw", VBMULFW
)
6613 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulw_insn
, "vbmulw", VBMULW
)
6614 SIMD_BUILTIN (Va_Vb_rlimm
, vbrsubw_insn
, "vbrsubw", VBRSUBW
)
6615 SIMD_BUILTIN (Va_Vb_rlimm
, vbsubw_insn
, "vbsubw", VBSUBW
)
6617 /* Va, Vb, Ic instructions. */
6618 SIMD_BUILTIN (Va_Vb_Ic
, vasrw_insn
, "vasrw", VASRW
)
6619 SIMD_BUILTIN (Va_Vb_Ic
, vsr8_insn
, "vsr8", VSR8
)
6620 SIMD_BUILTIN (Va_Vb_Ic
, vsr8aw_insn
, "vsr8aw", VSR8AW
)
6622 /* Va, Vb, u6 instructions. */
6623 SIMD_BUILTIN (Va_Vb_u6
, vasrrwi_insn
, "vasrrwi", VASRRWi
)
6624 SIMD_BUILTIN (Va_Vb_u6
, vasrsrwi_insn
, "vasrsrwi", VASRSRWi
)
6625 SIMD_BUILTIN (Va_Vb_u6
, vasrwi_insn
, "vasrwi", VASRWi
)
6626 SIMD_BUILTIN (Va_Vb_u6
, vasrpwbi_insn
, "vasrpwbi", VASRPWBi
)
6627 SIMD_BUILTIN (Va_Vb_u6
, vasrrpwbi_insn
,"vasrrpwbi", VASRRPWBi
)
6628 SIMD_BUILTIN (Va_Vb_u6
, vsr8awi_insn
, "vsr8awi", VSR8AWi
)
6629 SIMD_BUILTIN (Va_Vb_u6
, vsr8i_insn
, "vsr8i", VSR8i
)
6631 /* Va, Vb, u8 (simm) instructions. */
6632 SIMD_BUILTIN (Va_Vb_u8
, vmvaw_insn
, "vmvaw", VMVAW
)
6633 SIMD_BUILTIN (Va_Vb_u8
, vmvw_insn
, "vmvw", VMVW
)
6634 SIMD_BUILTIN (Va_Vb_u8
, vmvzw_insn
, "vmvzw", VMVZW
)
6635 SIMD_BUILTIN (Va_Vb_u8
, vd6tapf_insn
, "vd6tapf", VD6TAPF
)
6637 /* Va, rlimm, u8 (simm) instructions. */
6638 SIMD_BUILTIN (Va_rlimm_u8
, vmovaw_insn
, "vmovaw", VMOVAW
)
6639 SIMD_BUILTIN (Va_rlimm_u8
, vmovw_insn
, "vmovw", VMOVW
)
6640 SIMD_BUILTIN (Va_rlimm_u8
, vmovzw_insn
, "vmovzw", VMOVZW
)
6642 /* Va, Vb instructions. */
6643 SIMD_BUILTIN (Va_Vb
, vabsaw_insn
, "vabsaw", VABSAW
)
6644 SIMD_BUILTIN (Va_Vb
, vabsw_insn
, "vabsw", VABSW
)
6645 SIMD_BUILTIN (Va_Vb
, vaddsuw_insn
, "vaddsuw", VADDSUW
)
6646 SIMD_BUILTIN (Va_Vb
, vsignw_insn
, "vsignw", VSIGNW
)
6647 SIMD_BUILTIN (Va_Vb
, vexch1_insn
, "vexch1", VEXCH1
)
6648 SIMD_BUILTIN (Va_Vb
, vexch2_insn
, "vexch2", VEXCH2
)
6649 SIMD_BUILTIN (Va_Vb
, vexch4_insn
, "vexch4", VEXCH4
)
6650 SIMD_BUILTIN (Va_Vb
, vupbaw_insn
, "vupbaw", VUPBAW
)
6651 SIMD_BUILTIN (Va_Vb
, vupbw_insn
, "vupbw", VUPBW
)
6652 SIMD_BUILTIN (Va_Vb
, vupsbaw_insn
, "vupsbaw", VUPSBAW
)
6653 SIMD_BUILTIN (Va_Vb
, vupsbw_insn
, "vupsbw", VUPSBW
)
6655 /* DIb, rlimm, rlimm instructions. */
6656 SIMD_BUILTIN (Da_rlimm_rlimm
, vdirun_insn
, "vdirun", VDIRUN
)
6657 SIMD_BUILTIN (Da_rlimm_rlimm
, vdorun_insn
, "vdorun", VDORUN
)
6659 /* DIb, limm, rlimm instructions. */
6660 SIMD_BUILTIN (Da_u3_rlimm
, vdiwr_insn
, "vdiwr", VDIWR
)
6661 SIMD_BUILTIN (Da_u3_rlimm
, vdowr_insn
, "vdowr", VDOWR
)
6663 /* rlimm instructions. */
6664 SIMD_BUILTIN (void_rlimm
, vrec_insn
, "vrec", VREC
)
6665 SIMD_BUILTIN (void_rlimm
, vrun_insn
, "vrun", VRUN
)
6666 SIMD_BUILTIN (void_rlimm
, vrecrun_insn
, "vrecrun", VRECRUN
)
6667 SIMD_BUILTIN (void_rlimm
, vendrec_insn
, "vendrec", VENDREC
)
6669 /* Va, [Ib,u8] instructions. */
6670 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32wh_insn
, "vld32wh", VLD32WH
)
6671 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32wl_insn
, "vld32wl", VLD32WL
)
6672 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld64_insn
, "vld64", VLD64
)
6673 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32_insn
, "vld32", VLD32
)
6675 SIMD_BUILTIN (Va_Ib_u8
, vld64w_insn
, "vld64w", VLD64W
)
6676 SIMD_BUILTIN (Va_Ib_u8
, vld128_insn
, "vld128", VLD128
)
6677 SIMD_BUILTIN (void_Va_Ib_u8
, vst128_insn
, "vst128", VST128
)
6678 SIMD_BUILTIN (void_Va_Ib_u8
, vst64_insn
, "vst64", VST64
)
6680 /* Va, [Ib, u8] instructions. */
6681 SIMD_BUILTIN (void_Va_u3_Ib_u8
, vst16_n_insn
, "vst16_n", VST16_N
)
6682 SIMD_BUILTIN (void_Va_u3_Ib_u8
, vst32_n_insn
, "vst32_n", VST32_N
)
6684 SIMD_BUILTIN (void_u6
, vinti_insn
, "vinti", VINTI
)
6688 arc_init_simd_builtins (void)
6691 tree endlink
= void_list_node
;
6692 tree V8HI_type_node
= build_vector_type_for_mode (intHI_type_node
, V8HImode
);
6694 tree v8hi_ftype_v8hi_v8hi
6695 = build_function_type (V8HI_type_node
,
6696 tree_cons (NULL_TREE
, V8HI_type_node
,
6697 tree_cons (NULL_TREE
, V8HI_type_node
,
6699 tree v8hi_ftype_v8hi_int
6700 = build_function_type (V8HI_type_node
,
6701 tree_cons (NULL_TREE
, V8HI_type_node
,
6702 tree_cons (NULL_TREE
, integer_type_node
,
6705 tree v8hi_ftype_v8hi_int_int
6706 = build_function_type (V8HI_type_node
,
6707 tree_cons (NULL_TREE
, V8HI_type_node
,
6708 tree_cons (NULL_TREE
, integer_type_node
,
6709 tree_cons (NULL_TREE
,
6713 tree void_ftype_v8hi_int_int
6714 = build_function_type (void_type_node
,
6715 tree_cons (NULL_TREE
, V8HI_type_node
,
6716 tree_cons (NULL_TREE
, integer_type_node
,
6717 tree_cons (NULL_TREE
,
6721 tree void_ftype_v8hi_int_int_int
6722 = (build_function_type
6724 tree_cons (NULL_TREE
, V8HI_type_node
,
6725 tree_cons (NULL_TREE
, integer_type_node
,
6726 tree_cons (NULL_TREE
, integer_type_node
,
6727 tree_cons (NULL_TREE
,
6731 tree v8hi_ftype_int_int
6732 = build_function_type (V8HI_type_node
,
6733 tree_cons (NULL_TREE
, integer_type_node
,
6734 tree_cons (NULL_TREE
, integer_type_node
,
6737 tree void_ftype_int_int
6738 = build_function_type (void_type_node
,
6739 tree_cons (NULL_TREE
, integer_type_node
,
6740 tree_cons (NULL_TREE
, integer_type_node
,
6744 = build_function_type (void_type_node
,
6745 tree_cons (NULL_TREE
, integer_type_node
, endlink
));
6747 tree v8hi_ftype_v8hi
6748 = build_function_type (V8HI_type_node
, tree_cons (NULL_TREE
, V8HI_type_node
,
6751 /* These asserts have been introduced to ensure that the order of builtins
6752 does not get messed up, else the initialization goes wrong. */
6753 gcc_assert (arc_simd_builtin_desc_list
[0].args_type
== Va_Vb_Vc
);
6754 for (i
=0; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Vc
; i
++)
6755 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6756 v8hi_ftype_v8hi_v8hi
, arc_simd_builtin_desc_list
[i
].code
);
6758 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_rlimm
);
6759 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_rlimm
; i
++)
6760 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6761 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6763 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic
);
6764 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic
; i
++)
6765 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6766 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6768 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u6
);
6769 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u6
; i
++)
6770 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6771 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6773 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u8
);
6774 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u8
; i
++)
6775 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6776 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6778 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_rlimm_u8
);
6779 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_rlimm_u8
; i
++)
6780 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6781 v8hi_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6783 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb
);
6784 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb
; i
++)
6785 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6786 v8hi_ftype_v8hi
, arc_simd_builtin_desc_list
[i
].code
);
6788 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Da_rlimm_rlimm
);
6789 for (; arc_simd_builtin_desc_list
[i
].args_type
== Da_rlimm_rlimm
; i
++)
6790 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6791 void_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6793 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Da_u3_rlimm
);
6794 for (; arc_simd_builtin_desc_list
[i
].args_type
== Da_u3_rlimm
; i
++)
6795 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6796 void_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6798 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_rlimm
);
6799 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_rlimm
; i
++)
6800 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6801 void_ftype_int
, arc_simd_builtin_desc_list
[i
].code
);
6803 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic_u8
);
6804 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic_u8
; i
++)
6805 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6806 v8hi_ftype_v8hi_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6808 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Ib_u8
);
6809 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Ib_u8
; i
++)
6810 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6811 v8hi_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6813 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_Va_Ib_u8
);
6814 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_Va_Ib_u8
; i
++)
6815 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6816 void_ftype_v8hi_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6818 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_Va_u3_Ib_u8
);
6819 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_Va_u3_Ib_u8
; i
++)
6820 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6821 void_ftype_v8hi_int_int_int
,
6822 arc_simd_builtin_desc_list
[i
].code
);
6824 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_u6
);
6825 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_u6
; i
++)
6826 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6827 void_ftype_int
, arc_simd_builtin_desc_list
[i
].code
);
6829 gcc_assert(i
== ARRAY_SIZE (arc_simd_builtin_desc_list
));
6832 /* Helper function of arc_expand_builtin; has the same parameters,
6833 except that EXP is now known to be a call to a simd builtin. */
6836 arc_expand_simd_builtin (tree exp
,
6838 rtx subtarget ATTRIBUTE_UNUSED
,
6839 machine_mode mode ATTRIBUTE_UNUSED
,
6840 int ignore ATTRIBUTE_UNUSED
)
6842 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
6854 int fcode
= DECL_FUNCTION_CODE (fndecl
);
6861 const struct builtin_description
* d
;
6863 for (i
= 0, d
= arc_simd_builtin_desc_list
;
6864 i
< ARRAY_SIZE (arc_simd_builtin_desc_list
); i
++, d
++)
6865 if (d
->code
== (const enum arc_builtins
) fcode
)
6868 /* We must get an entry here. */
6869 gcc_assert (i
< ARRAY_SIZE (arc_simd_builtin_desc_list
));
6871 switch (d
->args_type
)
6875 arg0
= CALL_EXPR_ARG (exp
, 0);
6876 arg1
= CALL_EXPR_ARG (exp
, 1);
6877 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6878 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6880 target
= gen_reg_rtx (V8HImode
);
6881 mode0
= insn_data
[icode
].operand
[1].mode
;
6882 mode1
= insn_data
[icode
].operand
[2].mode
;
6884 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6885 op0
= copy_to_mode_reg (mode0
, op0
);
6887 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6888 op1
= copy_to_mode_reg (mode1
, op1
);
6890 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
6900 arg0
= CALL_EXPR_ARG (exp
, 0);
6901 arg1
= CALL_EXPR_ARG (exp
, 1);
6902 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6903 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6905 target
= gen_reg_rtx (V8HImode
);
6906 mode0
= insn_data
[icode
].operand
[1].mode
;
6907 mode1
= insn_data
[icode
].operand
[2].mode
;
6909 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6910 op0
= copy_to_mode_reg (mode0
, op0
);
6912 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
)
6913 || (d
->args_type
== Va_Vb_u6
&& !UNSIGNED_INT6 (INTVAL (op1
)))
6914 || (d
->args_type
== Va_Vb_u8
&& !UNSIGNED_INT8 (INTVAL (op1
))))
6915 error ("operand 2 of %s instruction should be an unsigned %d-bit value",
6917 (d
->args_type
== Va_Vb_u6
)? 6: 8);
6919 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
6928 arg0
= CALL_EXPR_ARG (exp
, 0);
6929 arg1
= CALL_EXPR_ARG (exp
, 1);
6930 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6931 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6933 target
= gen_reg_rtx (V8HImode
);
6934 mode0
= insn_data
[icode
].operand
[1].mode
;
6935 mode1
= insn_data
[icode
].operand
[2].mode
;
6937 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6938 op0
= copy_to_mode_reg (mode0
, op0
);
6940 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6941 || !(UNSIGNED_INT8 (INTVAL (op1
))))
6942 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
6945 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
6954 arg0
= CALL_EXPR_ARG (exp
, 0);
6955 arg1
= CALL_EXPR_ARG (exp
, 1);
6956 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6957 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6958 op2
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
);
6960 target
= gen_reg_rtx (V8HImode
);
6961 mode0
= insn_data
[icode
].operand
[1].mode
;
6962 mode1
= insn_data
[icode
].operand
[2].mode
;
6964 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6965 op0
= copy_to_mode_reg (mode0
, op0
);
6967 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6968 || !(UNSIGNED_INT3 (INTVAL (op1
))))
6969 error ("operand 2 of %s instruction should be an unsigned 3-bit value (I0-I7)",
6972 pat
= GEN_FCN (icode
) (target
, op0
, op1
, op2
);
6981 arg0
= CALL_EXPR_ARG (exp
, 0);
6982 arg1
= CALL_EXPR_ARG (exp
, 1);
6983 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6984 op1
= expand_expr (arg1
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6986 target
= gen_reg_rtx (V8HImode
);
6987 mode0
= insn_data
[icode
].operand
[1].mode
;
6988 mode1
= insn_data
[icode
].operand
[2].mode
;
6990 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6991 op0
= copy_to_mode_reg (mode0
, op0
);
6993 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6994 op1
= copy_to_mode_reg (mode1
, op1
);
6996 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
7005 arg0
= CALL_EXPR_ARG (exp
, 0);
7006 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
7008 target
= gen_reg_rtx (V8HImode
);
7009 mode0
= insn_data
[icode
].operand
[1].mode
;
7011 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
7012 op0
= copy_to_mode_reg (mode0
, op0
);
7014 pat
= GEN_FCN (icode
) (target
, op0
);
7021 case Da_rlimm_rlimm
:
7023 arg0
= CALL_EXPR_ARG (exp
, 0);
7024 arg1
= CALL_EXPR_ARG (exp
, 1);
7025 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7026 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7029 if (icode
== CODE_FOR_vdirun_insn
)
7030 target
= gen_rtx_REG (SImode
, 131);
7031 else if (icode
== CODE_FOR_vdorun_insn
)
7032 target
= gen_rtx_REG (SImode
, 139);
7036 mode0
= insn_data
[icode
].operand
[1].mode
;
7037 mode1
= insn_data
[icode
].operand
[2].mode
;
7039 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
7040 op0
= copy_to_mode_reg (mode0
, op0
);
7042 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7043 op1
= copy_to_mode_reg (mode1
, op1
);
7046 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
7055 arg0
= CALL_EXPR_ARG (exp
, 0);
7056 arg1
= CALL_EXPR_ARG (exp
, 1);
7057 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7058 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7061 if (! (GET_CODE (op0
) == CONST_INT
)
7062 || !(UNSIGNED_INT3 (INTVAL (op0
))))
7063 error ("operand 1 of %s instruction should be an unsigned 3-bit value (DR0-DR7)",
7066 mode1
= insn_data
[icode
].operand
[1].mode
;
7068 if (icode
== CODE_FOR_vdiwr_insn
)
7069 target
= gen_rtx_REG (SImode
,
7070 ARC_FIRST_SIMD_DMA_CONFIG_IN_REG
+ INTVAL (op0
));
7071 else if (icode
== CODE_FOR_vdowr_insn
)
7072 target
= gen_rtx_REG (SImode
,
7073 ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG
+ INTVAL (op0
));
7077 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7078 op1
= copy_to_mode_reg (mode1
, op1
);
7080 pat
= GEN_FCN (icode
) (target
, op1
);
7089 arg0
= CALL_EXPR_ARG (exp
, 0);
7093 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7094 mode0
= insn_data
[icode
].operand
[0].mode
;
7096 /* op0 should be u6. */
7097 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
)
7098 || !(UNSIGNED_INT6 (INTVAL (op0
))))
7099 error ("operand of %s instruction should be an unsigned 6-bit value",
7102 pat
= GEN_FCN (icode
) (op0
);
7111 arg0
= CALL_EXPR_ARG (exp
, 0);
7115 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7116 mode0
= insn_data
[icode
].operand
[0].mode
;
7118 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
7119 op0
= copy_to_mode_reg (mode0
, op0
);
7121 pat
= GEN_FCN (icode
) (op0
);
7132 arg0
= CALL_EXPR_ARG (exp
, 0); /* source vreg */
7133 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7134 arg2
= CALL_EXPR_ARG (exp
, 2); /* u8 */
7136 src_vreg
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
7137 op0
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* [I]0-7 */
7138 op1
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7139 op2
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7141 /* target <- src vreg */
7142 emit_insn (gen_move_insn (target
, src_vreg
));
7144 /* target <- vec_concat: target, mem(Ib, u8) */
7145 mode0
= insn_data
[icode
].operand
[3].mode
;
7146 mode1
= insn_data
[icode
].operand
[1].mode
;
7148 if ( (!(*insn_data
[icode
].operand
[3].predicate
) (op0
, mode0
))
7149 || !(UNSIGNED_INT3 (INTVAL (op0
))))
7150 error ("operand 1 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7153 if ( (!(*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
7154 || !(UNSIGNED_INT8 (INTVAL (op1
))))
7155 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
7158 pat
= GEN_FCN (icode
) (target
, op1
, op2
, op0
);
7168 arg0
= CALL_EXPR_ARG (exp
, 0); /* src vreg */
7169 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7170 arg2
= CALL_EXPR_ARG (exp
, 2); /* u8 */
7172 op0
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7173 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* I[0-7] */
7174 op2
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7175 op3
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
); /* Vdest */
7177 mode0
= insn_data
[icode
].operand
[0].mode
;
7178 mode1
= insn_data
[icode
].operand
[1].mode
;
7179 mode2
= insn_data
[icode
].operand
[2].mode
;
7180 mode3
= insn_data
[icode
].operand
[3].mode
;
7182 if ( (!(*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
7183 || !(UNSIGNED_INT3 (INTVAL (op1
))))
7184 error ("operand 2 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7187 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op2
, mode2
))
7188 || !(UNSIGNED_INT8 (INTVAL (op2
))))
7189 error ("operand 3 of %s instruction should be an unsigned 8-bit value",
7192 if (!(*insn_data
[icode
].operand
[3].predicate
) (op3
, mode3
))
7193 op3
= copy_to_mode_reg (mode3
, op3
);
7195 pat
= GEN_FCN (icode
) (op0
, op1
, op2
, op3
);
7204 arg0
= CALL_EXPR_ARG (exp
, 0); /* dest vreg */
7205 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7207 op0
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7208 op1
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* I[0-7] */
7209 op2
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7211 /* target <- src vreg */
7212 target
= gen_reg_rtx (V8HImode
);
7214 /* target <- vec_concat: target, mem(Ib, u8) */
7215 mode0
= insn_data
[icode
].operand
[1].mode
;
7216 mode1
= insn_data
[icode
].operand
[2].mode
;
7217 mode2
= insn_data
[icode
].operand
[3].mode
;
7219 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7220 || !(UNSIGNED_INT3 (INTVAL (op1
))))
7221 error ("operand 1 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7224 if ( (!(*insn_data
[icode
].operand
[3].predicate
) (op2
, mode2
))
7225 || !(UNSIGNED_INT8 (INTVAL (op2
))))
7226 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
7229 pat
= GEN_FCN (icode
) (target
, op0
, op1
, op2
);
7236 case void_Va_u3_Ib_u8
:
7238 arg0
= CALL_EXPR_ARG (exp
, 0); /* source vreg */
7239 arg1
= CALL_EXPR_ARG (exp
, 1); /* u3 */
7240 arg2
= CALL_EXPR_ARG (exp
, 2); /* [I]0-7 */
7241 arg3
= CALL_EXPR_ARG (exp
, 3); /* u8 */
7243 op0
= expand_expr (arg3
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7244 op1
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR */
7245 op2
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* [I]0-7 */
7246 op3
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);/* vreg to be stored */
7247 op4
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* vreg 0-7 subreg no. */
7249 mode0
= insn_data
[icode
].operand
[0].mode
;
7250 mode2
= insn_data
[icode
].operand
[2].mode
;
7251 mode3
= insn_data
[icode
].operand
[3].mode
;
7252 mode4
= insn_data
[icode
].operand
[4].mode
;
7254 /* Do some correctness checks for the operands. */
7255 if ( (!(*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
7256 || !(UNSIGNED_INT8 (INTVAL (op0
))))
7257 error ("operand 4 of %s instruction should be an unsigned 8-bit value (0-255)",
7260 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op2
, mode2
))
7261 || !(UNSIGNED_INT3 (INTVAL (op2
))))
7262 error ("operand 3 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7265 if (!(*insn_data
[icode
].operand
[3].predicate
) (op3
, mode3
))
7266 op3
= copy_to_mode_reg (mode3
, op3
);
7268 if ( (!(*insn_data
[icode
].operand
[4].predicate
) (op4
, mode4
))
7269 || !(UNSIGNED_INT3 (INTVAL (op4
))))
7270 error ("operand 2 of %s instruction should be an unsigned 3-bit value (subreg 0-7)",
7272 else if (icode
== CODE_FOR_vst32_n_insn
7273 && ((INTVAL(op4
) % 2 ) != 0))
7274 error ("operand 2 of %s instruction should be an even 3-bit value (subreg 0,2,4,6)",
7277 pat
= GEN_FCN (icode
) (op0
, op1
, op2
, op3
, op4
);
7291 arc_preserve_reload_p (rtx in
)
7293 return (GET_CODE (in
) == PLUS
7294 && RTX_OK_FOR_BASE_P (XEXP (in
, 0), true)
7295 && CONST_INT_P (XEXP (in
, 1))
7296 && !((INTVAL (XEXP (in
, 1)) & 511)));
7300 arc_register_move_cost (machine_mode
,
7301 enum reg_class from_class
, enum reg_class to_class
)
7303 /* The ARC600 has no bypass for extension registers, hence a nop might be
7304 needed to be inserted after a write so that reads are safe. */
7307 if (to_class
== MPY_WRITABLE_CORE_REGS
)
7309 /* Instructions modifying LP_COUNT need 4 additional cycles before
7310 the register will actually contain the value. */
7311 else if (to_class
== LPCOUNT_REG
)
7313 else if (to_class
== WRITABLE_CORE_REGS
)
7317 /* The ARC700 stalls for 3 cycles when *reading* from lp_count. */
7319 && (from_class
== LPCOUNT_REG
|| from_class
== ALL_CORE_REGS
7320 || from_class
== WRITABLE_CORE_REGS
))
7323 /* Force an attempt to 'mov Dy,Dx' to spill. */
7324 if (TARGET_ARC700
&& TARGET_DPFP
7325 && from_class
== DOUBLE_REGS
&& to_class
== DOUBLE_REGS
)
7331 /* Emit code for an addsi3 instruction with OPERANDS.
7332 COND_P indicates if this will use conditional execution.
7333 Return the length of the instruction.
7334 If OUTPUT_P is false, don't actually output the instruction, just return
7337 arc_output_addsi (rtx
*operands
, bool cond_p
, bool output_p
)
7341 int match
= operands_match_p (operands
[0], operands
[1]);
7342 int match2
= operands_match_p (operands
[0], operands
[2]);
7343 int intval
= (REG_P (operands
[2]) ? 1
7344 : CONST_INT_P (operands
[2]) ? INTVAL (operands
[2]) : 0xbadc057);
7345 int neg_intval
= -intval
;
7346 int short_0
= satisfies_constraint_Rcq (operands
[0]);
7347 int short_p
= (!cond_p
&& short_0
&& satisfies_constraint_Rcq (operands
[1]));
7350 #define ADDSI_OUTPUT1(FORMAT) do {\
7352 output_asm_insn (FORMAT, operands);\
7355 #define ADDSI_OUTPUT(LIST) do {\
7358 ADDSI_OUTPUT1 (format);\
7362 /* First try to emit a 16 bit insn. */
7365 /* If we are actually about to output this insn, don't try a 16 bit
7366 variant if we already decided that we don't want that
7367 (I.e. we upsized this insn to align some following insn.)
7368 E.g. add_s r0,sp,70 is 16 bit, but add r0,sp,70 requires a LIMM -
7369 but add1 r0,sp,35 doesn't. */
7370 && (!output_p
|| (get_attr_length (current_output_insn
) & 2)))
7373 && (REG_P (operands
[2])
7374 ? (match
|| satisfies_constraint_Rcq (operands
[2]))
7375 : (unsigned) intval
<= (match
? 127 : 7)))
7376 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7377 if (short_0
&& REG_P (operands
[1]) && match2
)
7378 ADDSI_OUTPUT1 ("add%? %0,%2,%1");
7379 if ((short_0
|| REGNO (operands
[0]) == STACK_POINTER_REGNUM
)
7380 && REGNO (operands
[1]) == STACK_POINTER_REGNUM
&& !(intval
& ~124))
7381 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7383 if ((short_p
&& (unsigned) neg_intval
<= (match
? 31 : 7))
7384 || (REGNO (operands
[0]) == STACK_POINTER_REGNUM
7385 && match
&& !(neg_intval
& ~124)))
7386 ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
7389 /* Now try to emit a 32 bit insn without long immediate. */
7391 if (!match
&& match2
&& REG_P (operands
[1]))
7392 ADDSI_OUTPUT1 ("add%? %0,%2,%1");
7393 if (match
|| !cond_p
)
7395 int limit
= (match
&& !cond_p
) ? 0x7ff : 0x3f;
7396 int range_factor
= neg_intval
& intval
;
7399 if (intval
== -1 << 31)
7400 ADDSI_OUTPUT1 ("bxor%? %0,%1,31");
7402 /* If we can use a straight add / sub instead of a {add,sub}[123] of
7403 same size, do, so - the insn latency is lower. */
7404 /* -0x800 is a 12-bit constant for add /add3 / sub / sub3, but
7406 if ((intval
>= 0 && intval
<= limit
)
7407 || (intval
== -0x800 && limit
== 0x7ff))
7408 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7409 else if ((intval
< 0 && neg_intval
<= limit
)
7410 || (intval
== 0x800 && limit
== 0x7ff))
7411 ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
7412 shift
= range_factor
>= 8 ? 3 : (range_factor
>> 1);
7413 gcc_assert (shift
== 0 || shift
== 1 || shift
== 2 || shift
== 3);
7414 gcc_assert ((((1 << shift
) - 1) & intval
) == 0);
7415 if (((intval
< 0 && intval
!= -0x4000)
7416 /* sub[123] is slower than add_s / sub, only use it if it
7417 avoids a long immediate. */
7418 && neg_intval
<= limit
<< shift
)
7419 || (intval
== 0x4000 && limit
== 0x7ff))
7420 ADDSI_OUTPUT ((format
, "sub%d%%? %%0,%%1,%d",
7421 shift
, neg_intval
>> shift
));
7422 else if ((intval
>= 0 && intval
<= limit
<< shift
)
7423 || (intval
== -0x4000 && limit
== 0x7ff))
7424 ADDSI_OUTPUT ((format
, "add%d%%? %%0,%%1,%d", shift
, intval
>> shift
));
7426 /* Try to emit a 16 bit opcode with long immediate. */
7428 if (short_p
&& match
)
7429 ADDSI_OUTPUT1 ("add%? %0,%1,%S2");
7431 /* We have to use a 32 bit opcode, and with a long immediate. */
7433 ADDSI_OUTPUT1 (intval
< 0 ? "sub%? %0,%1,%n2" : "add%? %0,%1,%S2");
7436 /* Emit code for an commutative_cond_exec instruction with OPERANDS.
7437 Return the length of the instruction.
7438 If OUTPUT_P is false, don't actually output the instruction, just return
7441 arc_output_commutative_cond_exec (rtx
*operands
, bool output_p
)
7443 enum rtx_code commutative_op
= GET_CODE (operands
[3]);
7444 const char *pat
= NULL
;
7446 /* Canonical rtl should not have a constant in the first operand position. */
7447 gcc_assert (!CONSTANT_P (operands
[1]));
7449 switch (commutative_op
)
7452 if (satisfies_constraint_C1p (operands
[2]))
7453 pat
= "bmsk%? %0,%1,%Z2";
7454 else if (satisfies_constraint_Ccp (operands
[2]))
7455 pat
= "bclr%? %0,%1,%M2";
7456 else if (satisfies_constraint_CnL (operands
[2]))
7457 pat
= "bic%? %0,%1,%n2-1";
7460 if (satisfies_constraint_C0p (operands
[2]))
7461 pat
= "bset%? %0,%1,%z2";
7464 if (satisfies_constraint_C0p (operands
[2]))
7465 pat
= "bxor%? %0,%1,%z2";
7468 return arc_output_addsi (operands
, true, output_p
);
7472 output_asm_insn (pat
? pat
: "%O3.%d5 %0,%1,%2", operands
);
7473 if (pat
|| REG_P (operands
[2]) || satisfies_constraint_L (operands
[2]))
7478 /* Helper function of arc_expand_movmem. ADDR points to a chunk of memory.
7479 Emit code and return an potentially modified address such that offsets
7480 up to SIZE are can be added to yield a legitimate address.
7481 if REUSE is set, ADDR is a register that may be modified. */
7484 force_offsettable (rtx addr
, HOST_WIDE_INT size
, bool reuse
)
7487 rtx offs
= const0_rtx
;
7489 if (GET_CODE (base
) == PLUS
)
7491 offs
= XEXP (base
, 1);
7492 base
= XEXP (base
, 0);
7495 || (REGNO (base
) != STACK_POINTER_REGNUM
7496 && REGNO_PTR_FRAME_P (REGNO (addr
)))
7497 || !CONST_INT_P (offs
) || !SMALL_INT (INTVAL (offs
))
7498 || !SMALL_INT (INTVAL (offs
) + size
))
7501 emit_insn (gen_add2_insn (addr
, offs
));
7503 addr
= copy_to_mode_reg (Pmode
, addr
);
7508 /* Like move_by_pieces, but take account of load latency,
7509 and actual offset ranges.
7510 Return true on success. */
7513 arc_expand_movmem (rtx
*operands
)
7515 rtx dst
= operands
[0];
7516 rtx src
= operands
[1];
7517 rtx dst_addr
, src_addr
;
7519 int align
= INTVAL (operands
[3]);
7526 if (!CONST_INT_P (operands
[2]))
7528 size
= INTVAL (operands
[2]);
7529 /* move_by_pieces_ninsns is static, so we can't use it. */
7531 n_pieces
= (size
+ 2) / 4U + (size
& 1);
7532 else if (align
== 2)
7533 n_pieces
= (size
+ 1) / 2U;
7536 if (n_pieces
>= (unsigned int) (optimize_size
? 3 : 15))
7540 dst_addr
= force_offsettable (XEXP (operands
[0], 0), size
, 0);
7541 src_addr
= force_offsettable (XEXP (operands
[1], 0), size
, 0);
7542 store
[0] = store
[1] = NULL_RTX
;
7543 tmpx
[0] = tmpx
[1] = NULL_RTX
;
7544 for (i
= 0; size
> 0; i
^= 1, size
-= piece
)
7550 piece
= size
& -size
;
7551 mode
= smallest_mode_for_size (piece
* BITS_PER_UNIT
, MODE_INT
);
7552 /* If we don't re-use temporaries, the scheduler gets carried away,
7553 and the register pressure gets unnecessarily high. */
7554 if (0 && tmpx
[i
] && GET_MODE (tmpx
[i
]) == mode
)
7557 tmpx
[i
] = tmp
= gen_reg_rtx (mode
);
7558 dst_addr
= force_offsettable (dst_addr
, piece
, 1);
7559 src_addr
= force_offsettable (src_addr
, piece
, 1);
7561 emit_insn (store
[i
]);
7562 emit_move_insn (tmp
, change_address (src
, mode
, src_addr
));
7563 store
[i
] = gen_move_insn (change_address (dst
, mode
, dst_addr
), tmp
);
7564 dst_addr
= plus_constant (Pmode
, dst_addr
, piece
);
7565 src_addr
= plus_constant (Pmode
, src_addr
, piece
);
7568 emit_insn (store
[i
]);
7570 emit_insn (store
[i
^1]);
7574 /* Prepare operands for move in MODE. Return true iff the move has
7578 prepare_move_operands (rtx
*operands
, machine_mode mode
)
7580 /* We used to do this only for MODE_INT Modes, but addresses to floating
7581 point variables may well be in the small data section. */
7584 if (!TARGET_NO_SDATA_SET
&& small_data_pattern (operands
[0], Pmode
))
7585 operands
[0] = arc_rewrite_small_data (operands
[0]);
7586 else if (mode
== SImode
&& flag_pic
&& SYMBOLIC_CONST (operands
[1]))
7588 emit_pic_move (operands
, SImode
);
7590 /* Disable any REG_EQUALs associated with the symref
7591 otherwise the optimization pass undoes the work done
7592 here and references the variable directly. */
7594 else if (GET_CODE (operands
[0]) != MEM
7595 && !TARGET_NO_SDATA_SET
7596 && small_data_pattern (operands
[1], Pmode
))
7598 /* This is to take care of address calculations involving sdata
7600 operands
[1] = arc_rewrite_small_data (operands
[1]);
7602 emit_insn (gen_rtx_SET (operands
[0],operands
[1]));
7603 /* ??? This note is useless, since it only restates the set itself.
7604 We should rather use the original SYMBOL_REF. However, there is
7605 the problem that we are lying to the compiler about these
7606 SYMBOL_REFs to start with. symbol@sda should be encoded specially
7607 so that we can tell it apart from an actual symbol. */
7608 set_unique_reg_note (get_last_insn (), REG_EQUAL
, operands
[1]);
7610 /* Take care of the REG_EQUAL note that will be attached to mark the
7611 output reg equal to the initial symbol_ref after this code is
7613 emit_move_insn (operands
[0], operands
[0]);
7618 if (MEM_P (operands
[0])
7619 && !(reload_in_progress
|| reload_completed
))
7621 operands
[1] = force_reg (mode
, operands
[1]);
7622 if (!move_dest_operand (operands
[0], mode
))
7624 rtx addr
= copy_to_mode_reg (Pmode
, XEXP (operands
[0], 0));
7625 /* This is like change_address_1 (operands[0], mode, 0, 1) ,
7626 except that we can't use that function because it is static. */
7627 rtx pat
= change_address (operands
[0], mode
, addr
);
7628 MEM_COPY_ATTRIBUTES (pat
, operands
[0]);
7631 if (!cse_not_expected
)
7633 rtx pat
= XEXP (operands
[0], 0);
7635 pat
= arc_legitimize_address_0 (pat
, pat
, mode
);
7638 pat
= change_address (operands
[0], mode
, pat
);
7639 MEM_COPY_ATTRIBUTES (pat
, operands
[0]);
7645 if (MEM_P (operands
[1]) && !cse_not_expected
)
7647 rtx pat
= XEXP (operands
[1], 0);
7649 pat
= arc_legitimize_address_0 (pat
, pat
, mode
);
7652 pat
= change_address (operands
[1], mode
, pat
);
7653 MEM_COPY_ATTRIBUTES (pat
, operands
[1]);
7661 /* Prepare OPERANDS for an extension using CODE to OMODE.
7662 Return true iff the move has been emitted. */
7665 prepare_extend_operands (rtx
*operands
, enum rtx_code code
,
7668 if (!TARGET_NO_SDATA_SET
&& small_data_pattern (operands
[1], Pmode
))
7670 /* This is to take care of address calculations involving sdata
7673 = gen_rtx_fmt_e (code
, omode
, arc_rewrite_small_data (operands
[1]));
7674 emit_insn (gen_rtx_SET (operands
[0], operands
[1]));
7675 set_unique_reg_note (get_last_insn (), REG_EQUAL
, operands
[1]);
7677 /* Take care of the REG_EQUAL note that will be attached to mark the
7678 output reg equal to the initial extension after this code is
7680 emit_move_insn (operands
[0], operands
[0]);
7686 /* Output a library call to a function called FNAME that has been arranged
7687 to be local to any dso. */
7690 arc_output_libcall (const char *fname
)
7692 unsigned len
= strlen (fname
);
7693 static char buf
[64];
7695 gcc_assert (len
< sizeof buf
- 35);
7696 if (TARGET_LONG_CALLS_SET
7697 || (TARGET_MEDIUM_CALLS
&& arc_ccfsm_cond_exec_p ()))
7700 sprintf (buf
, "add r12,pcl,@%s-(.&-4)\n\tjl%%!%%* [r12]", fname
);
7702 sprintf (buf
, "jl%%! @%s", fname
);
7705 sprintf (buf
, "bl%%!%%* @%s", fname
);
7709 /* Return the SImode highpart of the DImode value IN. */
7712 disi_highpart (rtx in
)
7714 return simplify_gen_subreg (SImode
, in
, DImode
, TARGET_BIG_ENDIAN
? 0 : 4);
7717 /* Return length adjustment for INSN.
7719 A write to a core reg greater or equal to 32 must not be immediately
7720 followed by a use. Anticipate the length requirement to insert a nop
7721 between PRED and SUCC to prevent a hazard. */
7724 arc600_corereg_hazard (rtx_insn
*pred
, rtx_insn
*succ
)
7728 /* If SUCC is a doloop_end_i with a preceding label, we must output a nop
7729 in front of SUCC anyway, so there will be separation between PRED and
7731 if (recog_memoized (succ
) == CODE_FOR_doloop_end_i
7732 && LABEL_P (prev_nonnote_insn (succ
)))
7734 if (recog_memoized (succ
) == CODE_FOR_doloop_begin_i
)
7736 if (GET_CODE (PATTERN (pred
)) == SEQUENCE
)
7737 pred
= as_a
<rtx_sequence
*> (PATTERN (pred
))->insn (1);
7738 if (GET_CODE (PATTERN (succ
)) == SEQUENCE
)
7739 succ
= as_a
<rtx_sequence
*> (PATTERN (succ
))->insn (0);
7740 if (recog_memoized (pred
) == CODE_FOR_mulsi_600
7741 || recog_memoized (pred
) == CODE_FOR_umul_600
7742 || recog_memoized (pred
) == CODE_FOR_mac_600
7743 || recog_memoized (pred
) == CODE_FOR_mul64_600
7744 || recog_memoized (pred
) == CODE_FOR_mac64_600
7745 || recog_memoized (pred
) == CODE_FOR_umul64_600
7746 || recog_memoized (pred
) == CODE_FOR_umac64_600
)
7748 subrtx_iterator::array_type array
;
7749 FOR_EACH_SUBRTX (iter
, array
, PATTERN (pred
), NONCONST
)
7751 const_rtx x
= *iter
;
7752 switch (GET_CODE (x
))
7754 case SET
: case POST_INC
: case POST_DEC
: case PRE_INC
: case PRE_DEC
:
7757 /* This is also fine for PRE/POST_MODIFY, because they
7761 rtx dest
= XEXP (x
, 0);
7762 /* Check if this sets a an extension register. N.B. we use 61 for the
7763 condition codes, which is definitely not an extension register. */
7764 if (REG_P (dest
) && REGNO (dest
) >= 32 && REGNO (dest
) < 61
7765 /* Check if the same register is used by the PAT. */
7766 && (refers_to_regno_p
7768 REGNO (dest
) + (GET_MODE_SIZE (GET_MODE (dest
)) + 3) / 4U,
7769 PATTERN (succ
), 0)))
7776 A write to a core reg greater or equal to 32 must not be immediately
7777 followed by a use. Anticipate the length requirement to insert a nop
7778 between PRED and SUCC to prevent a hazard. */
7781 arc_hazard (rtx_insn
*pred
, rtx_insn
*succ
)
7785 if (!pred
|| !INSN_P (pred
) || !succ
|| !INSN_P (succ
))
7787 /* We might have a CALL to a non-returning function before a loop end.
7788 ??? Although the manual says that's OK (the target is outside the loop,
7789 and the loop counter unused there), the assembler barfs on this, so we
7790 must instert a nop before such a call too. */
7791 if (recog_memoized (succ
) == CODE_FOR_doloop_end_i
7792 && (JUMP_P (pred
) || CALL_P (pred
)
7793 || GET_CODE (PATTERN (pred
)) == SEQUENCE
))
7795 return arc600_corereg_hazard (pred
, succ
);
7798 /* Return length adjustment for INSN. */
7801 arc_adjust_insn_length (rtx_insn
*insn
, int len
, bool)
7805 /* We already handle sequences by ignoring the delay sequence flag. */
7806 if (GET_CODE (PATTERN (insn
)) == SEQUENCE
)
7809 /* It is impossible to jump to the very end of a Zero-Overhead Loop, as
7810 the ZOL mechanism only triggers when advancing to the end address,
7811 so if there's a label at the end of a ZOL, we need to insert a nop.
7812 The ARC600 ZOL also has extra restrictions on jumps at the end of a
7814 if (recog_memoized (insn
) == CODE_FOR_doloop_end_i
)
7816 rtx_insn
*prev
= prev_nonnote_insn (insn
);
7818 return ((LABEL_P (prev
)
7821 || CALL_P (prev
) /* Could be a noreturn call. */
7822 || (NONJUMP_INSN_P (prev
)
7823 && GET_CODE (PATTERN (prev
)) == SEQUENCE
))))
7827 /* Check for return with but one preceding insn since function
7829 if (TARGET_PAD_RETURN
7831 && GET_CODE (PATTERN (insn
)) != ADDR_VEC
7832 && GET_CODE (PATTERN (insn
)) != ADDR_DIFF_VEC
7833 && get_attr_type (insn
) == TYPE_RETURN
)
7835 rtx_insn
*prev
= prev_active_insn (insn
);
7837 if (!prev
|| !(prev
= prev_active_insn (prev
))
7838 || ((NONJUMP_INSN_P (prev
)
7839 && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
7840 ? CALL_ATTR (as_a
<rtx_sequence
*> (PATTERN (prev
))->insn (0),
7842 : CALL_ATTR (prev
, NON_SIBCALL
)))
7847 rtx_insn
*succ
= next_real_insn (insn
);
7849 /* One the ARC600, a write to an extension register must be separated
7851 if (succ
&& INSN_P (succ
))
7852 len
+= arc600_corereg_hazard (insn
, succ
);
7855 /* Restore extracted operands - otherwise splitters like the addsi3_mixed one
7857 extract_constrain_insn_cached (insn
);
7862 /* Values for length_sensitive. */
7866 ARC_LS_25
, // 25 bit offset, B
7867 ARC_LS_21
, // 21 bit offset, Bcc
7868 ARC_LS_U13
,// 13 bit unsigned offset, LP
7869 ARC_LS_10
, // 10 bit offset, B_s, Beq_s, Bne_s
7870 ARC_LS_9
, // 9 bit offset, BRcc
7871 ARC_LS_8
, // 8 bit offset, BRcc_s
7872 ARC_LS_U7
, // 7 bit unsigned offset, LPcc
7873 ARC_LS_7
// 7 bit offset, Bcc_s
7876 /* While the infrastructure patch is waiting for review, duplicate the
7877 struct definitions, to allow this file to compile. */
7882 /* Cost as a branch / call target or call return address. */
7884 int fallthrough_cost
;
7887 /* 0 for not length sensitive, 1 for largest offset range,
7888 * 2 for next smaller etc. */
7889 unsigned length_sensitive
: 8;
7891 } insn_length_variant_t
;
7893 typedef struct insn_length_parameters_s
7898 int (*get_variants
) (rtx_insn
*, int, bool, bool, insn_length_variant_t
*);
7899 } insn_length_parameters_t
;
7902 arc_insn_length_parameters (insn_length_parameters_t
*ilp
) ATTRIBUTE_UNUSED
;
7906 arc_get_insn_variants (rtx_insn
*insn
, int len
, bool, bool target_p
,
7907 insn_length_variant_t
*ilv
)
7909 if (!NONDEBUG_INSN_P (insn
))
7911 enum attr_type type
;
7912 /* shorten_branches doesn't take optimize_size into account yet for the
7913 get_variants mechanism, so turn this off for now. */
7916 if (rtx_sequence
*pat
= dyn_cast
<rtx_sequence
*> (PATTERN (insn
)))
7918 /* The interaction of a short delay slot insn with a short branch is
7919 too weird for shorten_branches to piece together, so describe the
7922 if (TARGET_UPSIZE_DBR
7923 && get_attr_length (pat
->insn (1)) <= 2
7924 && (((type
= get_attr_type (inner
= pat
->insn (0)))
7925 == TYPE_UNCOND_BRANCH
)
7926 || type
== TYPE_BRANCH
)
7927 && get_attr_delay_slot_filled (inner
) == DELAY_SLOT_FILLED_YES
)
7930 = arc_get_insn_variants (inner
, get_attr_length (inner
), true,
7932 /* The short variant gets split into a higher-cost aligned
7933 and a lower cost unaligned variant. */
7934 gcc_assert (n_variants
);
7935 gcc_assert (ilv
[1].length_sensitive
== ARC_LS_7
7936 || ilv
[1].length_sensitive
== ARC_LS_10
);
7937 gcc_assert (ilv
[1].align_set
== 3);
7939 ilv
[0].align_set
= 1;
7940 ilv
[0].branch_cost
+= 1;
7941 ilv
[1].align_set
= 2;
7943 for (int i
= 0; i
< n_variants
; i
++)
7945 /* In case an instruction with aligned size is wanted, and
7946 the short variants are unavailable / too expensive, add
7947 versions of long branch + long delay slot. */
7948 for (int i
= 2, end
= n_variants
; i
< end
; i
++, n_variants
++)
7950 ilv
[n_variants
] = ilv
[i
];
7951 ilv
[n_variants
].length
+= 2;
7957 insn_length_variant_t
*first_ilv
= ilv
;
7958 type
= get_attr_type (insn
);
7960 = (get_attr_delay_slot_filled (insn
) == DELAY_SLOT_FILLED_YES
);
7961 int branch_align_cost
= delay_filled
? 0 : 1;
7962 int branch_unalign_cost
= delay_filled
? 0 : TARGET_UNALIGN_BRANCH
? 0 : 1;
7963 /* If the previous instruction is an sfunc call, this insn is always
7964 a target, even though the middle-end is unaware of this. */
7965 bool force_target
= false;
7966 rtx_insn
*prev
= prev_active_insn (insn
);
7967 if (prev
&& arc_next_active_insn (prev
, 0) == insn
7968 && ((NONJUMP_INSN_P (prev
) && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
7969 ? CALL_ATTR (as_a
<rtx_sequence
*> (PATTERN (prev
))->insn (0),
7971 : (CALL_ATTR (prev
, NON_SIBCALL
)
7972 && NEXT_INSN (PREV_INSN (prev
)) == prev
)))
7973 force_target
= true;
7978 /* Short BRCC only comes in no-delay-slot version, and without limm */
7983 ilv
->branch_cost
= 1;
7984 ilv
->enabled
= (len
== 2);
7985 ilv
->length_sensitive
= ARC_LS_8
;
7989 case TYPE_BRCC_NO_DELAY_SLOT
:
7990 /* doloop_fallback* patterns are TYPE_BRCC_NO_DELAY_SLOT for
7991 (delay slot) scheduling purposes, but they are longer. */
7992 if (GET_CODE (PATTERN (insn
)) == PARALLEL
7993 && GET_CODE (XVECEXP (PATTERN (insn
), 0, 1)) == SET
)
7995 /* Standard BRCC: 4 bytes, or 8 bytes with limm. */
7996 ilv
->length
= ((type
== TYPE_BRCC
) ? 4 : 8);
7998 ilv
->branch_cost
= branch_align_cost
;
7999 ilv
->enabled
= (len
<= ilv
->length
);
8000 ilv
->length_sensitive
= ARC_LS_9
;
8001 if ((target_p
|| force_target
)
8002 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8008 ilv
->target_cost
= 1;
8009 ilv
->branch_cost
= branch_unalign_cost
;
8014 op
= XEXP (SET_SRC (XVECEXP (PATTERN (insn
), 0, 0)), 0);
8017 if (GET_CODE (op0
) == ZERO_EXTRACT
8018 && satisfies_constraint_L (XEXP (op0
, 2)))
8019 op0
= XEXP (op0
, 0);
8020 if (satisfies_constraint_Rcq (op0
))
8022 ilv
->length
= ((type
== TYPE_BRCC
) ? 6 : 10);
8024 ilv
->branch_cost
= 1 + branch_align_cost
;
8025 ilv
->fallthrough_cost
= 1;
8026 ilv
->enabled
= true;
8027 ilv
->length_sensitive
= ARC_LS_21
;
8028 if (!delay_filled
&& TARGET_UNALIGN_BRANCH
)
8034 ilv
->branch_cost
= 1 + branch_unalign_cost
;
8038 ilv
->length
= ((type
== TYPE_BRCC
) ? 8 : 12);
8040 ilv
->branch_cost
= 1 + branch_align_cost
;
8041 ilv
->fallthrough_cost
= 1;
8042 ilv
->enabled
= true;
8043 ilv
->length_sensitive
= ARC_LS_21
;
8044 if ((target_p
|| force_target
)
8045 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8051 ilv
->target_cost
= 1;
8052 ilv
->branch_cost
= 1 + branch_unalign_cost
;
8060 case TYPE_CALL_NO_DELAY_SLOT
:
8065 ilv
->length_sensitive
8066 = GET_CODE (PATTERN (insn
)) == COND_EXEC
? ARC_LS_21
: ARC_LS_25
;
8069 ilv
->fallthrough_cost
= branch_align_cost
;
8070 ilv
->enabled
= true;
8071 if ((target_p
|| force_target
)
8072 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8078 ilv
->target_cost
= 1;
8079 ilv
->fallthrough_cost
= branch_unalign_cost
;
8083 case TYPE_UNCOND_BRANCH
:
8084 /* Strictly speaking, this should be ARC_LS_10 for equality comparisons,
8085 but that makes no difference at the moment. */
8086 ilv
->length_sensitive
= ARC_LS_7
;
8087 ilv
[1].length_sensitive
= ARC_LS_25
;
8090 ilv
->length_sensitive
= ARC_LS_10
;
8091 ilv
[1].length_sensitive
= ARC_LS_21
;
8095 ilv
->branch_cost
= branch_align_cost
;
8096 ilv
->enabled
= (len
== ilv
->length
);
8100 ilv
->branch_cost
= branch_align_cost
;
8101 ilv
->enabled
= true;
8102 if ((target_p
|| force_target
)
8103 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8109 ilv
->target_cost
= 1;
8110 ilv
->branch_cost
= branch_unalign_cost
;
8117 /* For every short insn, there is generally also a long insn.
8118 trap_s is an exception. */
8119 if ((len
& 2) == 0 || recog_memoized (insn
) == CODE_FOR_trap_s
)
8126 ilv
->length
= len
+ 2;
8128 if (target_p
|| force_target
)
8134 ilv
->target_cost
= 1;
8138 /* If the previous instruction is an sfunc call, this insn is always
8139 a target, even though the middle-end is unaware of this.
8140 Therefore, if we have a call predecessor, transfer the target cost
8141 to the fallthrough and branch costs. */
8144 for (insn_length_variant_t
*p
= first_ilv
; p
< ilv
; p
++)
8146 p
->fallthrough_cost
+= p
->target_cost
;
8147 p
->branch_cost
+= p
->target_cost
;
8152 return ilv
- first_ilv
;
8156 arc_insn_length_parameters (insn_length_parameters_t
*ilp
)
8158 ilp
->align_unit_log
= 1;
8159 ilp
->align_base_log
= 1;
8160 ilp
->max_variants
= 7;
8161 ilp
->get_variants
= arc_get_insn_variants
;
8164 /* Return a copy of COND from *STATEP, inverted if that is indicated by the
8165 CC field of *STATEP. */
8168 arc_get_ccfsm_cond (struct arc_ccfsm
*statep
, bool reverse
)
8170 rtx cond
= statep
->cond
;
8171 int raw_cc
= get_arc_condition_code (cond
);
8173 raw_cc
= ARC_INVERSE_CONDITION_CODE (raw_cc
);
8175 if (statep
->cc
== raw_cc
)
8176 return copy_rtx (cond
);
8178 gcc_assert (ARC_INVERSE_CONDITION_CODE (raw_cc
) == statep
->cc
);
8180 machine_mode ccm
= GET_MODE (XEXP (cond
, 0));
8181 enum rtx_code code
= reverse_condition (GET_CODE (cond
));
8182 if (code
== UNKNOWN
|| ccm
== CC_FP_GTmode
|| ccm
== CC_FP_GEmode
)
8183 code
= reverse_condition_maybe_unordered (GET_CODE (cond
));
8185 return gen_rtx_fmt_ee (code
, GET_MODE (cond
),
8186 copy_rtx (XEXP (cond
, 0)), copy_rtx (XEXP (cond
, 1)));
8189 /* Return version of PAT conditionalized with COND, which is part of INSN.
8190 ANNULLED indicates if INSN is an annulled delay-slot insn.
8191 Register further changes if necessary. */
8193 conditionalize_nonjump (rtx pat
, rtx cond
, rtx insn
, bool annulled
)
8195 /* For commutative operators, we generally prefer to have
8196 the first source match the destination. */
8197 if (GET_CODE (pat
) == SET
)
8199 rtx src
= SET_SRC (pat
);
8201 if (COMMUTATIVE_P (src
))
8203 rtx src0
= XEXP (src
, 0);
8204 rtx src1
= XEXP (src
, 1);
8205 rtx dst
= SET_DEST (pat
);
8207 if (rtx_equal_p (src1
, dst
) && !rtx_equal_p (src0
, dst
)
8208 /* Leave add_n alone - the canonical form is to
8209 have the complex summand first. */
8211 pat
= gen_rtx_SET (dst
,
8212 gen_rtx_fmt_ee (GET_CODE (src
), GET_MODE (src
),
8217 /* dwarf2out.c:dwarf2out_frame_debug_expr doesn't know
8218 what to do with COND_EXEC. */
8219 if (RTX_FRAME_RELATED_P (insn
))
8221 /* If this is the delay slot insn of an anulled branch,
8222 dwarf2out.c:scan_trace understands the anulling semantics
8223 without the COND_EXEC. */
8224 gcc_assert (annulled
);
8225 rtx note
= alloc_reg_note (REG_FRAME_RELATED_EXPR
, pat
,
8227 validate_change (insn
, ®_NOTES (insn
), note
, 1);
8229 pat
= gen_rtx_COND_EXEC (VOIDmode
, cond
, pat
);
8233 /* Use the ccfsm machinery to do if conversion. */
8238 struct arc_ccfsm
*statep
= &cfun
->machine
->ccfsm_current
;
8239 basic_block merge_bb
= 0;
8241 memset (statep
, 0, sizeof *statep
);
8242 for (rtx_insn
*insn
= get_insns (); insn
; insn
= next_insn (insn
))
8244 arc_ccfsm_advance (insn
, statep
);
8246 switch (statep
->state
)
8254 /* Deleted branch. */
8255 gcc_assert (!merge_bb
);
8256 merge_bb
= BLOCK_FOR_INSN (insn
);
8258 = BLOCK_FOR_INSN (NEXT_INSN (NEXT_INSN (PREV_INSN (insn
))));
8259 arc_ccfsm_post_advance (insn
, statep
);
8260 gcc_assert (!IN_RANGE (statep
->state
, 1, 2));
8261 rtx_insn
*seq
= NEXT_INSN (PREV_INSN (insn
));
8264 rtx slot
= XVECEXP (PATTERN (seq
), 0, 1);
8265 rtx pat
= PATTERN (slot
);
8266 if (INSN_ANNULLED_BRANCH_P (insn
))
8269 = arc_get_ccfsm_cond (statep
, INSN_FROM_TARGET_P (slot
));
8270 pat
= gen_rtx_COND_EXEC (VOIDmode
, cond
, pat
);
8272 if (!validate_change (seq
, &PATTERN (seq
), pat
, 0))
8274 PUT_CODE (slot
, NOTE
);
8275 NOTE_KIND (slot
) = NOTE_INSN_DELETED
;
8276 if (merge_bb
&& succ_bb
)
8277 merge_blocks (merge_bb
, succ_bb
);
8279 else if (merge_bb
&& succ_bb
)
8281 set_insn_deleted (insn
);
8282 merge_blocks (merge_bb
, succ_bb
);
8286 PUT_CODE (insn
, NOTE
);
8287 NOTE_KIND (insn
) = NOTE_INSN_DELETED
;
8293 && statep
->target_label
== CODE_LABEL_NUMBER (insn
))
8295 arc_ccfsm_post_advance (insn
, statep
);
8296 basic_block succ_bb
= BLOCK_FOR_INSN (insn
);
8297 if (merge_bb
&& succ_bb
)
8298 merge_blocks (merge_bb
, succ_bb
);
8299 else if (--LABEL_NUSES (insn
) == 0)
8301 const char *name
= LABEL_NAME (insn
);
8302 PUT_CODE (insn
, NOTE
);
8303 NOTE_KIND (insn
) = NOTE_INSN_DELETED_LABEL
;
8304 NOTE_DELETED_LABEL_NAME (insn
) = name
;
8311 if (!NONDEBUG_INSN_P (insn
))
8314 /* Conditionalized insn. */
8316 rtx_insn
*prev
, *pprev
;
8317 rtx
*patp
, pat
, cond
;
8318 bool annulled
; annulled
= false;
8320 /* If this is a delay slot insn in a non-annulled branch,
8321 don't conditionalize it. N.B., this should be fine for
8322 conditional return too. However, don't do this for
8323 unconditional branches, as these would be encountered when
8324 processing an 'else' part. */
8325 prev
= PREV_INSN (insn
);
8326 pprev
= PREV_INSN (prev
);
8327 if (pprev
&& NEXT_INSN (NEXT_INSN (pprev
)) == NEXT_INSN (insn
)
8328 && JUMP_P (prev
) && get_attr_cond (prev
) == COND_USE
)
8330 if (!INSN_ANNULLED_BRANCH_P (prev
))
8335 patp
= &PATTERN (insn
);
8337 cond
= arc_get_ccfsm_cond (statep
, INSN_FROM_TARGET_P (insn
));
8338 if (NONJUMP_INSN_P (insn
) || CALL_P (insn
))
8340 /* ??? don't conditionalize if all side effects are dead
8341 in the not-execute case. */
8343 pat
= conditionalize_nonjump (pat
, cond
, insn
, annulled
);
8345 else if (simplejump_p (insn
))
8347 patp
= &SET_SRC (pat
);
8348 pat
= gen_rtx_IF_THEN_ELSE (VOIDmode
, cond
, *patp
, pc_rtx
);
8350 else if (JUMP_P (insn
) && ANY_RETURN_P (PATTERN (insn
)))
8352 pat
= gen_rtx_IF_THEN_ELSE (VOIDmode
, cond
, pat
, pc_rtx
);
8353 pat
= gen_rtx_SET (pc_rtx
, pat
);
8357 validate_change (insn
, patp
, pat
, 1);
8358 if (!apply_change_group ())
8362 rtx_insn
*next
= next_nonnote_insn (insn
);
8363 if (GET_CODE (next
) == BARRIER
)
8365 if (statep
->state
== 3)
8372 arc_ccfsm_post_advance (insn
, statep
);
8377 /* Find annulled delay insns and convert them to use the appropriate predicate.
8378 This allows branch shortening to size up these insns properly. */
8381 arc_predicate_delay_insns (void)
8383 for (rtx_insn
*insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
8385 rtx pat
, jump
, dlay
, src
, cond
, *patp
;
8388 if (!NONJUMP_INSN_P (insn
)
8389 || GET_CODE (pat
= PATTERN (insn
)) != SEQUENCE
)
8391 jump
= XVECEXP (pat
, 0, 0);
8392 dlay
= XVECEXP (pat
, 0, 1);
8393 if (!JUMP_P (jump
) || !INSN_ANNULLED_BRANCH_P (jump
))
8395 /* If the branch insn does the annulling, leave the delay insn alone. */
8396 if (!TARGET_AT_DBR_CONDEXEC
&& !INSN_FROM_TARGET_P (dlay
))
8398 /* ??? Could also leave DLAY un-conditionalized if its target is dead
8399 on the other path. */
8400 gcc_assert (GET_CODE (PATTERN (jump
)) == SET
);
8401 gcc_assert (SET_DEST (PATTERN (jump
)) == pc_rtx
);
8402 src
= SET_SRC (PATTERN (jump
));
8403 gcc_assert (GET_CODE (src
) == IF_THEN_ELSE
);
8404 cond
= XEXP (src
, 0);
8405 if (XEXP (src
, 2) == pc_rtx
)
8407 else if (XEXP (src
, 1) == pc_rtx
)
8411 if (reverse
!= !INSN_FROM_TARGET_P (dlay
))
8413 machine_mode ccm
= GET_MODE (XEXP (cond
, 0));
8414 enum rtx_code code
= reverse_condition (GET_CODE (cond
));
8415 if (code
== UNKNOWN
|| ccm
== CC_FP_GTmode
|| ccm
== CC_FP_GEmode
)
8416 code
= reverse_condition_maybe_unordered (GET_CODE (cond
));
8418 cond
= gen_rtx_fmt_ee (code
, GET_MODE (cond
),
8419 copy_rtx (XEXP (cond
, 0)),
8420 copy_rtx (XEXP (cond
, 1)));
8423 cond
= copy_rtx (cond
);
8424 patp
= &PATTERN (dlay
);
8426 pat
= conditionalize_nonjump (pat
, cond
, dlay
, true);
8427 validate_change (dlay
, patp
, pat
, 1);
8428 if (!apply_change_group ())
8434 /* For ARC600: If a write to a core reg >=32 appears in a delay slot
8435 (other than of a forward brcc), it creates a hazard when there is a read
8436 of the same register at the branch target. We can't know what is at the
8437 branch target of calls, and for branches, we don't really know before the
8438 end of delay slot scheduling, either. Not only can individual instruction
8439 be hoisted out into a delay slot, a basic block can also be emptied this
8440 way, and branch and/or fall through targets be redirected. Hence we don't
8441 want such writes in a delay slot. */
8443 /* Return nonzreo iff INSN writes to an extension core register. */
8446 arc_write_ext_corereg (rtx insn
)
8448 subrtx_iterator::array_type array
;
8449 FOR_EACH_SUBRTX (iter
, array
, PATTERN (insn
), NONCONST
)
8451 const_rtx x
= *iter
;
8452 switch (GET_CODE (x
))
8454 case SET
: case POST_INC
: case POST_DEC
: case PRE_INC
: case PRE_DEC
:
8457 /* This is also fine for PRE/POST_MODIFY, because they
8461 const_rtx dest
= XEXP (x
, 0);
8462 if (REG_P (dest
) && REGNO (dest
) >= 32 && REGNO (dest
) < 61)
8468 /* This is like the hook, but returns NULL when it can't / won't generate
8469 a legitimate address. */
8472 arc_legitimize_address_0 (rtx x
, rtx oldx ATTRIBUTE_UNUSED
,
8477 if (flag_pic
&& SYMBOLIC_CONST (x
))
8478 (x
) = arc_legitimize_pic_address (x
, 0);
8480 if (GET_CODE (addr
) == CONST
)
8481 addr
= XEXP (addr
, 0);
8482 if (GET_CODE (addr
) == PLUS
8483 && CONST_INT_P (XEXP (addr
, 1))
8484 && ((GET_CODE (XEXP (addr
, 0)) == SYMBOL_REF
8485 && !SYMBOL_REF_FUNCTION_P (XEXP (addr
, 0)))
8486 || (REG_P (XEXP (addr
, 0))
8487 && (INTVAL (XEXP (addr
, 1)) & 252))))
8489 HOST_WIDE_INT offs
, upper
;
8490 int size
= GET_MODE_SIZE (mode
);
8492 offs
= INTVAL (XEXP (addr
, 1));
8493 upper
= (offs
+ 256 * size
) & ~511 * size
;
8494 inner
= plus_constant (Pmode
, XEXP (addr
, 0), upper
);
8495 #if 0 /* ??? this produces worse code for EEMBC idctrn01 */
8496 if (GET_CODE (x
) == CONST
)
8497 inner
= gen_rtx_CONST (Pmode
, inner
);
8499 addr
= plus_constant (Pmode
, force_reg (Pmode
, inner
), offs
- upper
);
8502 else if (GET_CODE (addr
) == SYMBOL_REF
&& !SYMBOL_REF_FUNCTION_P (addr
))
8503 x
= force_reg (Pmode
, x
);
8504 if (memory_address_p ((machine_mode
) mode
, x
))
8510 arc_legitimize_address (rtx orig_x
, rtx oldx
, machine_mode mode
)
8512 rtx new_x
= arc_legitimize_address_0 (orig_x
, oldx
, mode
);
8520 arc_delegitimize_address_0 (rtx x
)
8524 if (GET_CODE (x
) == CONST
&& GET_CODE (u
= XEXP (x
, 0)) == UNSPEC
)
8526 if (XINT (u
, 1) == ARC_UNSPEC_GOT
)
8527 return XVECEXP (u
, 0, 0);
8529 else if (GET_CODE (x
) == PLUS
8530 && ((REG_P (gp
= XEXP (x
, 0))
8531 && REGNO (gp
) == PIC_OFFSET_TABLE_REGNUM
)
8532 || (GET_CODE (gp
) == CONST
8533 && GET_CODE (u
= XEXP (gp
, 0)) == UNSPEC
8534 && XINT (u
, 1) == ARC_UNSPEC_GOT
8535 && GET_CODE (XVECEXP (u
, 0, 0)) == SYMBOL_REF
8536 && !strcmp (XSTR (XVECEXP (u
, 0, 0), 0), "_DYNAMIC")))
8537 && GET_CODE (XEXP (x
, 1)) == CONST
8538 && GET_CODE (u
= XEXP (XEXP (x
, 1), 0)) == UNSPEC
8539 && XINT (u
, 1) == ARC_UNSPEC_GOTOFF
)
8540 return XVECEXP (u
, 0, 0);
8541 else if (GET_CODE (x
) == PLUS
&& GET_CODE (XEXP (x
, 0)) == PLUS
8542 && ((REG_P (gp
= XEXP (XEXP (x
, 0), 1))
8543 && REGNO (gp
) == PIC_OFFSET_TABLE_REGNUM
)
8544 || (GET_CODE (gp
) == CONST
8545 && GET_CODE (u
= XEXP (gp
, 0)) == UNSPEC
8546 && XINT (u
, 1) == ARC_UNSPEC_GOT
8547 && GET_CODE (XVECEXP (u
, 0, 0)) == SYMBOL_REF
8548 && !strcmp (XSTR (XVECEXP (u
, 0, 0), 0), "_DYNAMIC")))
8549 && GET_CODE (XEXP (x
, 1)) == CONST
8550 && GET_CODE (u
= XEXP (XEXP (x
, 1), 0)) == UNSPEC
8551 && XINT (u
, 1) == ARC_UNSPEC_GOTOFF
)
8552 return gen_rtx_PLUS (GET_MODE (x
), XEXP (XEXP (x
, 0), 0),
8554 else if (GET_CODE (x
) == PLUS
8555 && (u
= arc_delegitimize_address_0 (XEXP (x
, 1))))
8556 return gen_rtx_PLUS (GET_MODE (x
), XEXP (x
, 0), u
);
8561 arc_delegitimize_address (rtx x
)
8563 rtx orig_x
= x
= delegitimize_mem_from_attrs (x
);
8564 if (GET_CODE (x
) == MEM
)
8566 x
= arc_delegitimize_address_0 (x
);
8570 x
= replace_equiv_address_nv (orig_x
, x
);
8576 /* Return a REG rtx for acc1. N.B. the gcc-internal representation may
8577 differ from the hardware register number in order to allow the generic
8578 code to correctly split the concatenation of acc1 and acc2. */
8583 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 56: 57);
8586 /* Return a REG rtx for acc2. N.B. the gcc-internal representation may
8587 differ from the hardware register number in order to allow the generic
8588 code to correctly split the concatenation of acc1 and acc2. */
8593 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 57: 56);
8596 /* Return a REG rtx for mlo. N.B. the gcc-internal representation may
8597 differ from the hardware register number in order to allow the generic
8598 code to correctly split the concatenation of mhi and mlo. */
8603 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 59: 58);
8606 /* Return a REG rtx for mhi. N.B. the gcc-internal representation may
8607 differ from the hardware register number in order to allow the generic
8608 code to correctly split the concatenation of mhi and mlo. */
8613 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 58: 59);
8616 /* FIXME: a parameter should be added, and code added to final.c,
8617 to reproduce this functionality in shorten_branches. */
8619 /* Return nonzero iff BRANCH should be unaligned if possible by upsizing
8620 a previous instruction. */
8622 arc_unalign_branch_p (rtx branch
)
8626 if (!TARGET_UNALIGN_BRANCH
)
8628 /* Do not do this if we have a filled delay slot. */
8629 if (get_attr_delay_slot_filled (branch
) == DELAY_SLOT_FILLED_YES
8630 && !NEXT_INSN (branch
)->deleted ())
8632 note
= find_reg_note (branch
, REG_BR_PROB
, 0);
8634 || (arc_unalign_prob_threshold
&& !br_prob_note_reliable_p (note
))
8635 || INTVAL (XEXP (note
, 0)) < arc_unalign_prob_threshold
);
8639 /* When estimating sizes during arc_reorg, when optimizing for speed, there
8640 are three reasons why we need to consider branches to be length 6:
8641 - annull-false delay slot insns are implemented using conditional execution,
8642 thus preventing short insn formation where used.
8643 - for ARC600: annul-true delay slot insns are implemented where possible
8644 using conditional execution, preventing short insn formation where used.
8645 - for ARC700: likely or somewhat likely taken branches are made long and
8646 unaligned if possible to avoid branch penalty. */
8649 arc_branch_size_unknown_p (void)
8651 return !optimize_size
&& arc_reorg_in_progress
;
8654 /* We are about to output a return insn. Add padding if necessary to avoid
8655 a mispredict. A return could happen immediately after the function
8656 start, but after a call we know that there will be at least a blink
8660 arc_pad_return (void)
8662 rtx_insn
*insn
= current_output_insn
;
8663 rtx_insn
*prev
= prev_active_insn (insn
);
8668 fputs ("\tnop_s\n", asm_out_file
);
8669 cfun
->machine
->unalign
^= 2;
8672 /* If PREV is a sequence, we know it must be a branch / jump or a tailcall,
8673 because after a call, we'd have to restore blink first. */
8674 else if (GET_CODE (PATTERN (prev
)) == SEQUENCE
)
8678 want_long
= (get_attr_length (prev
) == 2);
8679 prev
= prev_active_insn (prev
);
8682 || ((NONJUMP_INSN_P (prev
) && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
8683 ? CALL_ATTR (as_a
<rtx_sequence
*> (PATTERN (prev
))->insn (0),
8685 : CALL_ATTR (prev
, NON_SIBCALL
)))
8688 cfun
->machine
->size_reason
8689 = "call/return and return/return must be 6 bytes apart to avoid mispredict";
8690 else if (TARGET_UNALIGN_BRANCH
&& cfun
->machine
->unalign
)
8692 cfun
->machine
->size_reason
8693 = "Long unaligned jump avoids non-delay slot penalty";
8696 /* Disgorge delay insn, if there is any, and it may be moved. */
8698 /* ??? Annulled would be OK if we can and do conditionalize
8699 the delay slot insn accordingly. */
8700 && !INSN_ANNULLED_BRANCH_P (insn
)
8701 && (get_attr_cond (insn
) != COND_USE
8702 || !reg_set_p (gen_rtx_REG (CCmode
, CC_REG
),
8703 XVECEXP (final_sequence
, 0, 1))))
8705 prev
= as_a
<rtx_insn
*> (XVECEXP (final_sequence
, 0, 1));
8706 gcc_assert (!prev_real_insn (insn
)
8707 || !arc_hazard (prev_real_insn (insn
), prev
));
8708 cfun
->machine
->force_short_suffix
= !want_long
;
8709 rtx save_pred
= current_insn_predicate
;
8710 final_scan_insn (prev
, asm_out_file
, optimize
, 1, NULL
);
8711 cfun
->machine
->force_short_suffix
= -1;
8712 prev
->set_deleted ();
8713 current_output_insn
= insn
;
8714 current_insn_predicate
= save_pred
;
8717 fputs ("\tnop\n", asm_out_file
);
8720 fputs ("\tnop_s\n", asm_out_file
);
8721 cfun
->machine
->unalign
^= 2;
8727 /* The usual; we set up our machine_function data. */
8729 static struct machine_function
*
8730 arc_init_machine_status (void)
8732 struct machine_function
*machine
;
8733 machine
= ggc_cleared_alloc
<machine_function
> ();
8734 machine
->fn_type
= ARC_FUNCTION_UNKNOWN
;
8735 machine
->force_short_suffix
= -1;
8740 /* Implements INIT_EXPANDERS. We just set up to call the above
8744 arc_init_expanders (void)
8746 init_machine_status
= arc_init_machine_status
;
8749 /* Check if OP is a proper parallel of a millicode call pattern. OFFSET
8750 indicates a number of elements to ignore - that allows to have a
8751 sibcall pattern that starts with (return). LOAD_P is zero for store
8752 multiple (for prologues), and one for load multiples (for epilogues),
8753 and two for load multiples where no final clobber of blink is required.
8754 We also skip the first load / store element since this is supposed to
8755 be checked in the instruction pattern. */
8758 arc_check_millicode (rtx op
, int offset
, int load_p
)
8760 int len
= XVECLEN (op
, 0) - offset
;
8765 if (len
< 2 || len
> 13)
8771 rtx elt
= XVECEXP (op
, 0, --len
);
8773 if (GET_CODE (elt
) != CLOBBER
8774 || !REG_P (XEXP (elt
, 0))
8775 || REGNO (XEXP (elt
, 0)) != RETURN_ADDR_REGNUM
8776 || len
< 3 || len
> 13)
8779 for (i
= 1; i
< len
; i
++)
8781 rtx elt
= XVECEXP (op
, 0, i
+ offset
);
8784 if (GET_CODE (elt
) != SET
)
8786 mem
= XEXP (elt
, load_p
);
8787 reg
= XEXP (elt
, 1-load_p
);
8788 if (!REG_P (reg
) || REGNO (reg
) != 13U+i
|| !MEM_P (mem
))
8790 addr
= XEXP (mem
, 0);
8791 if (GET_CODE (addr
) != PLUS
8792 || !rtx_equal_p (stack_pointer_rtx
, XEXP (addr
, 0))
8793 || !CONST_INT_P (XEXP (addr
, 1)) || INTVAL (XEXP (addr
, 1)) != i
*4)
8799 /* Accessor functions for cfun->machine->unalign. */
8802 arc_get_unalign (void)
8804 return cfun
->machine
->unalign
;
8808 arc_clear_unalign (void)
8811 cfun
->machine
->unalign
= 0;
8815 arc_toggle_unalign (void)
8817 cfun
->machine
->unalign
^= 2;
8820 /* Operands 0..2 are the operands of a addsi which uses a 12 bit
8821 constant in operand 2, but which would require a LIMM because of
8823 operands 3 and 4 are new SET_SRCs for operands 0. */
8826 split_addsi (rtx
*operands
)
8828 int val
= INTVAL (operands
[2]);
8830 /* Try for two short insns first. Lengths being equal, we prefer
8831 expansions with shorter register lifetimes. */
8832 if (val
> 127 && val
<= 255
8833 && satisfies_constraint_Rcq (operands
[0]))
8835 operands
[3] = operands
[2];
8836 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[1]);
8840 operands
[3] = operands
[1];
8841 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[2]);
8845 /* Operands 0..2 are the operands of a subsi which uses a 12 bit
8846 constant in operand 1, but which would require a LIMM because of
8848 operands 3 and 4 are new SET_SRCs for operands 0. */
8851 split_subsi (rtx
*operands
)
8853 int val
= INTVAL (operands
[1]);
8855 /* Try for two short insns first. Lengths being equal, we prefer
8856 expansions with shorter register lifetimes. */
8857 if (satisfies_constraint_Rcq (operands
[0])
8858 && satisfies_constraint_Rcq (operands
[2]))
8860 if (val
>= -31 && val
<= 127)
8862 operands
[3] = gen_rtx_NEG (SImode
, operands
[2]);
8863 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[1]);
8866 else if (val
>= 0 && val
< 255)
8868 operands
[3] = operands
[1];
8869 operands
[4] = gen_rtx_MINUS (SImode
, operands
[0], operands
[2]);
8873 /* If the destination is not an ARCompact16 register, we might
8874 still have a chance to make a short insn if the source is;
8875 we need to start with a reg-reg move for this. */
8876 operands
[3] = operands
[2];
8877 operands
[4] = gen_rtx_MINUS (SImode
, operands
[1], operands
[0]);
8880 /* Handle DOUBLE_REGS uses.
8881 Operand 0: destination register
8882 Operand 1: source register */
8885 arc_process_double_reg_moves (rtx
*operands
)
8887 rtx dest
= operands
[0];
8888 rtx src
= operands
[1];
8891 enum usesDxState
{ none
, srcDx
, destDx
, maxDx
};
8892 enum usesDxState state
= none
;
8894 if (refers_to_regno_p (40, 44, src
, 0))
8896 if (refers_to_regno_p (40, 44, dest
, 0))
8898 /* Via arc_register_move_cost, we should never see D,D moves. */
8899 gcc_assert (state
== none
);
8910 /* Without the LR insn, we need to split this into a
8911 sequence of insns which will use the DEXCLx and DADDHxy
8912 insns to be able to read the Dx register in question. */
8913 if (TARGET_DPFP_DISABLE_LRSR
)
8915 /* gen *movdf_insn_nolrsr */
8916 rtx set
= gen_rtx_SET (dest
, src
);
8917 rtx use1
= gen_rtx_USE (VOIDmode
, const1_rtx
);
8918 emit_insn (gen_rtx_PARALLEL (VOIDmode
, gen_rtvec (2, set
, use1
)));
8922 /* When we have 'mov D, r' or 'mov D, D' then get the target
8923 register pair for use with LR insn. */
8924 rtx destHigh
= simplify_gen_subreg(SImode
, dest
, DFmode
, 4);
8925 rtx destLow
= simplify_gen_subreg(SImode
, dest
, DFmode
, 0);
8927 /* Produce the two LR insns to get the high and low parts. */
8928 emit_insn (gen_rtx_SET (destHigh
,
8929 gen_rtx_UNSPEC_VOLATILE (Pmode
, gen_rtvec (1, src
),
8931 emit_insn (gen_rtx_SET (destLow
,
8932 gen_rtx_UNSPEC_VOLATILE (Pmode
, gen_rtvec (1, src
),
8936 else if (state
== destDx
)
8938 /* When we have 'mov r, D' or 'mov D, D' and we have access to the
8939 LR insn get the target register pair. */
8940 rtx srcHigh
= simplify_gen_subreg(SImode
, src
, DFmode
, 4);
8941 rtx srcLow
= simplify_gen_subreg(SImode
, src
, DFmode
, 0);
8943 emit_insn (gen_rtx_UNSPEC_VOLATILE (Pmode
,
8944 gen_rtvec (3, dest
, srcHigh
, srcLow
),
8945 VUNSPEC_DEXCL_NORES
));
8956 /* operands 0..1 are the operands of a 64 bit move instruction.
8957 split it into two moves with operands 2/3 and 4/5. */
8960 arc_split_move (rtx
*operands
)
8962 machine_mode mode
= GET_MODE (operands
[0]);
8970 val
= arc_process_double_reg_moves (operands
);
8975 for (i
= 0; i
< 2; i
++)
8977 if (MEM_P (operands
[i
]) && auto_inc_p (XEXP (operands
[i
], 0)))
8979 rtx addr
= XEXP (operands
[i
], 0);
8983 gcc_assert (!reg_overlap_mentioned_p (operands
[0], addr
));
8984 switch (GET_CODE (addr
))
8986 case PRE_DEC
: o
= GEN_INT (-8); goto pre_modify
;
8987 case PRE_INC
: o
= GEN_INT (8); goto pre_modify
;
8988 case PRE_MODIFY
: o
= XEXP (XEXP (addr
, 1), 1);
8992 case POST_DEC
: o
= GEN_INT (-8); goto post_modify
;
8993 case POST_INC
: o
= GEN_INT (8); goto post_modify
;
8994 case POST_MODIFY
: o
= XEXP (XEXP (addr
, 1), 1);
9003 xop
[0+i
] = adjust_automodify_address_nv
9004 (operands
[i
], SImode
,
9005 gen_rtx_fmt_ee (code
, Pmode
, r
,
9006 gen_rtx_PLUS (Pmode
, r
, o
)),
9008 xop
[2+i
] = adjust_automodify_address_nv
9009 (operands
[i
], SImode
, plus_constant (Pmode
, r
, 4), 4);
9013 xop
[0+i
] = operand_subword (operands
[i
], 0, 0, mode
);
9014 xop
[2+i
] = operand_subword (operands
[i
], 1, 0, mode
);
9017 if (reg_overlap_mentioned_p (xop
[0], xop
[3]))
9020 gcc_assert (!reg_overlap_mentioned_p (xop
[2], xop
[1]));
9022 operands
[2+swap
] = xop
[0];
9023 operands
[3+swap
] = xop
[1];
9024 operands
[4-swap
] = xop
[2];
9025 operands
[5-swap
] = xop
[3];
9028 emit_insn (gen_rtx_SET (operands
[2], operands
[3]));
9029 emit_insn (gen_rtx_SET (operands
[4], operands
[5]));
9036 /* Select between the instruction output templates s_tmpl (for short INSNs)
9037 and l_tmpl (for long INSNs). */
9040 arc_short_long (rtx_insn
*insn
, const char *s_tmpl
, const char *l_tmpl
)
9042 int is_short
= arc_verify_short (insn
, cfun
->machine
->unalign
, -1);
9044 extract_constrain_insn_cached (insn
);
9045 return is_short
? s_tmpl
: l_tmpl
;
9048 /* Searches X for any reference to REGNO, returning the rtx of the
9049 reference found if any. Otherwise, returns NULL_RTX. */
9052 arc_regno_use_in (unsigned int regno
, rtx x
)
9058 if (REG_P (x
) && refers_to_regno_p (regno
, x
))
9061 fmt
= GET_RTX_FORMAT (GET_CODE (x
));
9062 for (i
= GET_RTX_LENGTH (GET_CODE (x
)) - 1; i
>= 0; i
--)
9066 if ((tem
= regno_use_in (regno
, XEXP (x
, i
))))
9069 else if (fmt
[i
] == 'E')
9070 for (j
= XVECLEN (x
, i
) - 1; j
>= 0; j
--)
9071 if ((tem
= regno_use_in (regno
, XVECEXP (x
, i
, j
))))
9078 /* Return the integer value of the "type" attribute for INSN, or -1 if
9079 INSN can't have attributes. */
9082 arc_attr_type (rtx_insn
*insn
)
9084 if (NONJUMP_INSN_P (insn
)
9085 ? (GET_CODE (PATTERN (insn
)) == USE
9086 || GET_CODE (PATTERN (insn
)) == CLOBBER
)
9088 ? (GET_CODE (PATTERN (insn
)) == ADDR_VEC
9089 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
9092 return get_attr_type (insn
);
9095 /* Return true if insn sets the condition codes. */
9098 arc_sets_cc_p (rtx_insn
*insn
)
9100 if (NONJUMP_INSN_P (insn
))
9101 if (rtx_sequence
*seq
= dyn_cast
<rtx_sequence
*> (PATTERN (insn
)))
9102 insn
= seq
->insn (seq
->len () - 1);
9103 return arc_attr_type (insn
) == TYPE_COMPARE
;
9106 /* Return true if INSN is an instruction with a delay slot we may want
9110 arc_need_delay (rtx_insn
*insn
)
9114 if (!flag_delayed_branch
)
9116 /* The return at the end of a function needs a delay slot. */
9117 if (NONJUMP_INSN_P (insn
) && GET_CODE (PATTERN (insn
)) == USE
9118 && (!(next
= next_active_insn (insn
))
9119 || ((!NONJUMP_INSN_P (next
) || GET_CODE (PATTERN (next
)) != SEQUENCE
)
9120 && arc_attr_type (next
) == TYPE_RETURN
))
9121 && (!TARGET_PAD_RETURN
9122 || (prev_active_insn (insn
)
9123 && prev_active_insn (prev_active_insn (insn
))
9124 && prev_active_insn (prev_active_insn (prev_active_insn (insn
))))))
9126 if (NONJUMP_INSN_P (insn
)
9127 ? (GET_CODE (PATTERN (insn
)) == USE
9128 || GET_CODE (PATTERN (insn
)) == CLOBBER
9129 || GET_CODE (PATTERN (insn
)) == SEQUENCE
)
9131 ? (GET_CODE (PATTERN (insn
)) == ADDR_VEC
9132 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
9135 return num_delay_slots (insn
) != 0;
9138 /* Return true if the scheduling pass(es) has/have already run,
9139 i.e. where possible, we should try to mitigate high latencies
9140 by different instruction selection. */
9143 arc_scheduling_not_expected (void)
9145 return cfun
->machine
->arc_reorg_started
;
9148 /* Oddly enough, sometimes we get a zero overhead loop that branch
9149 shortening doesn't think is a loop - observed with compile/pr24883.c
9150 -O3 -fomit-frame-pointer -funroll-loops. Make sure to include the
9151 alignment visible for branch shortening (we actually align the loop
9152 insn before it, but that is equivalent since the loop insn is 4 byte
9156 arc_label_align (rtx label
)
9158 int loop_align
= LOOP_ALIGN (LABEL
);
9160 if (loop_align
> align_labels_log
)
9162 rtx_insn
*prev
= prev_nonnote_insn (label
);
9164 if (prev
&& NONJUMP_INSN_P (prev
)
9165 && GET_CODE (PATTERN (prev
)) == PARALLEL
9166 && recog_memoized (prev
) == CODE_FOR_doloop_begin_i
)
9169 /* Code has a minimum p2 alignment of 1, which we must restore after an
9171 if (align_labels_log
< 1)
9173 rtx_insn
*next
= next_nonnote_nondebug_insn (label
);
9174 if (INSN_P (next
) && recog_memoized (next
) >= 0)
9177 return align_labels_log
;
9180 /* Return true if LABEL is in executable code. */
9183 arc_text_label (rtx_insn
*label
)
9187 /* ??? We use deleted labels like they were still there, see
9188 gcc.c-torture/compile/20000326-2.c . */
9189 gcc_assert (GET_CODE (label
) == CODE_LABEL
9190 || (GET_CODE (label
) == NOTE
9191 && NOTE_KIND (label
) == NOTE_INSN_DELETED_LABEL
));
9192 next
= next_nonnote_insn (label
);
9194 return (!JUMP_TABLE_DATA_P (next
)
9195 || GET_CODE (PATTERN (next
)) != ADDR_VEC
);
9196 else if (!PREV_INSN (label
))
9197 /* ??? sometimes text labels get inserted very late, see
9198 gcc.dg/torture/stackalign/comp-goto-1.c */
9203 /* Return the size of the pretend args for DECL. */
9206 arc_decl_pretend_args (tree decl
)
9208 /* struct function is in DECL_STRUCT_FUNCTION (decl), but no
9209 pretend_args there... See PR38391. */
9210 gcc_assert (decl
== current_function_decl
);
9211 return crtl
->args
.pretend_args_size
;
9214 /* Without this, gcc.dg/tree-prof/bb-reorg.c fails to assemble
9215 when compiling with -O2 -freorder-blocks-and-partition -fprofile-use
9216 -D_PROFILE_USE; delay branch scheduling then follows a crossing jump
9217 to redirect two breqs. */
9220 arc_can_follow_jump (const rtx_insn
*follower
, const rtx_insn
*followee
)
9222 /* ??? get_attr_type is declared to take an rtx. */
9223 union { const rtx_insn
*c
; rtx_insn
*r
; } u
;
9226 if (CROSSING_JUMP_P (followee
))
9227 switch (get_attr_type (u
.r
))
9230 case TYPE_BRCC_NO_DELAY_SLOT
:
9238 /* Implement EPILOGUE__USES.
9239 Return true if REGNO should be added to the deemed uses of the epilogue.
9241 We use the return address
9242 arc_return_address_regs[arc_compute_function_type (cfun)] .
9243 But also, we have to make sure all the register restore instructions
9244 are known to be live in interrupt functions. */
9247 arc_epilogue_uses (int regno
)
9249 if (reload_completed
)
9251 if (ARC_INTERRUPT_P (cfun
->machine
->fn_type
))
9253 if (!fixed_regs
[regno
])
9255 return regno
== arc_return_address_regs
[cfun
->machine
->fn_type
];
9258 return regno
== RETURN_ADDR_REGNUM
;
9261 return regno
== arc_return_address_regs
[arc_compute_function_type (cfun
)];
9264 #ifndef TARGET_NO_LRA
9265 #define TARGET_NO_LRA !TARGET_LRA
9271 return !TARGET_NO_LRA
;
9274 /* ??? Should we define TARGET_REGISTER_PRIORITY? We might perfer to use
9275 Rcq registers, because some insn are shorter with them. OTOH we already
9276 have separate alternatives for this purpose, and other insns don't
9277 mind, so maybe we should rather prefer the other registers?
9278 We need more data, and we can only get that if we allow people to
9281 arc_register_priority (int r
)
9283 switch (arc_lra_priority_tag
)
9285 case ARC_LRA_PRIORITY_NONE
:
9287 case ARC_LRA_PRIORITY_NONCOMPACT
:
9288 return ((((r
& 7) ^ 4) - 4) & 15) != r
;
9289 case ARC_LRA_PRIORITY_COMPACT
:
9290 return ((((r
& 7) ^ 4) - 4) & 15) == r
;
9297 arc_spill_class (reg_class_t
/* orig_class */, machine_mode
)
9299 return GENERAL_REGS
;
9303 arc_legitimize_reload_address (rtx
*p
, machine_mode mode
, int opnum
,
9307 enum reload_type type
= (enum reload_type
) itype
;
9309 if (GET_CODE (x
) == PLUS
9310 && CONST_INT_P (XEXP (x
, 1))
9311 && (RTX_OK_FOR_BASE_P (XEXP (x
, 0), true)
9312 || (REG_P (XEXP (x
, 0))
9313 && reg_equiv_constant (REGNO (XEXP (x
, 0))))))
9315 int scale
= GET_MODE_SIZE (mode
);
9317 rtx index_rtx
= XEXP (x
, 1);
9318 HOST_WIDE_INT offset
= INTVAL (index_rtx
), offset_base
;
9323 if ((scale
-1) & offset
)
9326 offset_base
= (offset
+ (256 << shift
)) & (-512 << shift
);
9327 /* Sometimes the normal form does not suit DImode. We
9328 could avoid that by using smaller ranges, but that
9329 would give less optimized code when SImode is
9331 if (GET_MODE_SIZE (mode
) + offset
- offset_base
<= (256 << shift
))
9336 regno
= REGNO (reg
);
9337 sum2
= sum
= plus_constant (Pmode
, reg
, offset_base
);
9339 if (reg_equiv_constant (regno
))
9341 sum2
= plus_constant (Pmode
, reg_equiv_constant (regno
),
9343 if (GET_CODE (sum2
) == PLUS
)
9344 sum2
= gen_rtx_CONST (Pmode
, sum2
);
9346 *p
= gen_rtx_PLUS (Pmode
, sum
, GEN_INT (offset
- offset_base
));
9347 push_reload (sum2
, NULL_RTX
, &XEXP (*p
, 0), NULL
,
9348 BASE_REG_CLASS
, Pmode
, VOIDmode
, 0, 0, opnum
,
9353 /* We must re-recognize what we created before. */
9354 else if (GET_CODE (x
) == PLUS
9355 && GET_CODE (XEXP (x
, 0)) == PLUS
9356 && CONST_INT_P (XEXP (XEXP (x
, 0), 1))
9357 && REG_P (XEXP (XEXP (x
, 0), 0))
9358 && CONST_INT_P (XEXP (x
, 1)))
9360 /* Because this address is so complex, we know it must have
9361 been created by LEGITIMIZE_RELOAD_ADDRESS before; thus,
9362 it is already unshared, and needs no further unsharing. */
9363 push_reload (XEXP (x
, 0), NULL_RTX
, &XEXP (x
, 0), NULL
,
9364 BASE_REG_CLASS
, Pmode
, VOIDmode
, 0, 0, opnum
, type
);
9370 /* Implement TARGET_USE_BY_PIECES_INFRASTRUCTURE_P. */
9373 arc_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size
,
9375 enum by_pieces_operation op
,
9378 /* Let the movmem expander handle small block moves. */
9379 if (op
== MOVE_BY_PIECES
)
9382 return default_use_by_pieces_infrastructure_p (size
, align
, op
, speed_p
);
9385 struct gcc_target targetm
= TARGET_INITIALIZER
;