1 /* Subroutines used for code generation on the Synopsys DesignWare ARC cpu.
2 Copyright (C) 1994-2014 Free Software Foundation, Inc.
4 Sources derived from work done by Sankhya Technologies (www.sankhya.com) on
5 behalf of Synopsys Inc.
7 Position Independent Code support added,Code cleaned up,
8 Comments and Support For ARC700 instructions added by
9 Saurabh Verma (saurabh.verma@codito.com)
10 Ramana Radhakrishnan(ramana.radhakrishnan@codito.com)
12 Fixing ABI inconsistencies, optimizations for ARC600 / ARC700 pipelines,
13 profiling support added by Joern Rennecke <joern.rennecke@embecosm.com>
15 This file is part of GCC.
17 GCC is free software; you can redistribute it and/or modify
18 it under the terms of the GNU General Public License as published by
19 the Free Software Foundation; either version 3, or (at your option)
22 GCC is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 GNU General Public License for more details.
27 You should have received a copy of the GNU General Public License
28 along with GCC; see the file COPYING3. If not see
29 <http://www.gnu.org/licenses/>. */
33 #include "coretypes.h"
37 #include "stor-layout.h"
38 #include "stringpool.h"
42 #include "hard-reg-set.h"
44 #include "insn-config.h"
45 #include "conditions.h"
46 #include "insn-flags.h"
53 #include "insn-attr.h"
58 #include "diagnostic.h"
59 #include "insn-codes.h"
60 #include "langhooks.h"
62 #include "tm-constrs.h"
63 #include "reload.h" /* For operands_match_p */
65 #include "tree-pass.h"
67 #include "pass_manager.h"
69 /* Which cpu we're compiling for (A5, ARC600, ARC601, ARC700). */
70 static const char *arc_cpu_string
= "";
72 /* ??? Loads can handle any constant, stores can only handle small ones. */
73 /* OTOH, LIMMs cost extra, so their usefulness is limited. */
74 #define RTX_OK_FOR_OFFSET_P(MODE, X) \
75 (GET_CODE (X) == CONST_INT \
76 && SMALL_INT_RANGE (INTVAL (X), (GET_MODE_SIZE (MODE) - 1) & -4, \
77 (INTVAL (X) & (GET_MODE_SIZE (MODE) - 1) & 3 \
79 : -(-GET_MODE_SIZE (MODE) | -4) >> 1)))
81 #define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X, INDEX, STRICT) \
82 (GET_CODE (X) == PLUS \
83 && RTX_OK_FOR_BASE_P (XEXP (X, 0), (STRICT)) \
84 && ((INDEX && RTX_OK_FOR_INDEX_P (XEXP (X, 1), (STRICT)) \
85 && GET_MODE_SIZE ((MODE)) <= 4) \
86 || RTX_OK_FOR_OFFSET_P (MODE, XEXP (X, 1))))
88 #define LEGITIMATE_SCALED_ADDRESS_P(MODE, X, STRICT) \
89 (GET_CODE (X) == PLUS \
90 && GET_CODE (XEXP (X, 0)) == MULT \
91 && RTX_OK_FOR_INDEX_P (XEXP (XEXP (X, 0), 0), (STRICT)) \
92 && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \
93 && ((GET_MODE_SIZE (MODE) == 2 && INTVAL (XEXP (XEXP (X, 0), 1)) == 2) \
94 || (GET_MODE_SIZE (MODE) == 4 && INTVAL (XEXP (XEXP (X, 0), 1)) == 4)) \
95 && (RTX_OK_FOR_BASE_P (XEXP (X, 1), (STRICT)) \
96 || (flag_pic ? CONST_INT_P (XEXP (X, 1)) : CONSTANT_P (XEXP (X, 1)))))
98 #define LEGITIMATE_SMALL_DATA_ADDRESS_P(X) \
99 (GET_CODE (X) == PLUS \
100 && (REG_P (XEXP ((X), 0)) && REGNO (XEXP ((X), 0)) == SDATA_BASE_REGNUM) \
101 && ((GET_CODE (XEXP((X),1)) == SYMBOL_REF \
102 && SYMBOL_REF_SMALL_P (XEXP ((X), 1))) \
103 || (GET_CODE (XEXP ((X), 1)) == CONST \
104 && GET_CODE (XEXP (XEXP ((X), 1), 0)) == PLUS \
105 && GET_CODE (XEXP (XEXP (XEXP ((X), 1), 0), 0)) == SYMBOL_REF \
106 && SYMBOL_REF_SMALL_P (XEXP (XEXP (XEXP ((X), 1), 0), 0)) \
107 && GET_CODE (XEXP(XEXP (XEXP ((X), 1), 0), 1)) == CONST_INT)))
109 /* Array of valid operand punctuation characters. */
110 char arc_punct_chars
[256];
112 /* State used by arc_ccfsm_advance to implement conditional execution. */
113 struct GTY (()) arc_ccfsm
122 #define arc_ccfsm_current cfun->machine->ccfsm_current
124 #define ARC_CCFSM_BRANCH_DELETED_P(STATE) \
125 ((STATE)->state == 1 || (STATE)->state == 2)
127 /* Indicate we're conditionalizing insns now. */
128 #define ARC_CCFSM_RECORD_BRANCH_DELETED(STATE) \
129 ((STATE)->state += 2)
131 #define ARC_CCFSM_COND_EXEC_P(STATE) \
132 ((STATE)->state == 3 || (STATE)->state == 4 || (STATE)->state == 5 \
133 || current_insn_predicate)
135 /* Check if INSN has a 16 bit opcode considering struct arc_ccfsm *STATE. */
136 #define CCFSM_ISCOMPACT(INSN,STATE) \
137 (ARC_CCFSM_COND_EXEC_P (STATE) \
138 ? (get_attr_iscompact (INSN) == ISCOMPACT_TRUE \
139 || get_attr_iscompact (INSN) == ISCOMPACT_TRUE_LIMM) \
140 : get_attr_iscompact (INSN) != ISCOMPACT_FALSE)
142 /* Likewise, but also consider that INSN might be in a delay slot of JUMP. */
143 #define CCFSM_DBR_ISCOMPACT(INSN,JUMP,STATE) \
144 ((ARC_CCFSM_COND_EXEC_P (STATE) \
146 && INSN_ANNULLED_BRANCH_P (JUMP) \
147 && (TARGET_AT_DBR_CONDEXEC || INSN_FROM_TARGET_P (INSN)))) \
148 ? (get_attr_iscompact (INSN) == ISCOMPACT_TRUE \
149 || get_attr_iscompact (INSN) == ISCOMPACT_TRUE_LIMM) \
150 : get_attr_iscompact (INSN) != ISCOMPACT_FALSE)
152 /* The maximum number of insns skipped which will be conditionalised if
154 /* When optimizing for speed:
155 Let p be the probability that the potentially skipped insns need to
156 be executed, pn the cost of a correctly predicted non-taken branch,
157 mt the cost of a mis/non-predicted taken branch,
158 mn mispredicted non-taken, pt correctly predicted taken ;
159 costs expressed in numbers of instructions like the ones considered
161 Unfortunately we don't have a measure of predictability - this
162 is linked to probability only in that in the no-eviction-scenario
163 there is a lower bound 1 - 2 * min (p, 1-p), and a somewhat larger
164 value that can be assumed *if* the distribution is perfectly random.
165 A predictability of 1 is perfectly plausible not matter what p is,
166 because the decision could be dependent on an invocation parameter
168 For large p, we want MAX_INSNS_SKIPPED == pn/(1-p) + mt - pn
169 For small p, we want MAX_INSNS_SKIPPED == pt
171 When optimizing for size:
172 We want to skip insn unless we could use 16 opcodes for the
173 non-conditionalized insn to balance the branch length or more.
174 Performance can be tie-breaker. */
175 /* If the potentially-skipped insns are likely to be executed, we'll
176 generally save one non-taken branch
178 this to be no less than the 1/p */
179 #define MAX_INSNS_SKIPPED 3
181 /* The values of unspec's first field. */
191 ARC_BUILTIN_NORM
= 3,
192 ARC_BUILTIN_NORMW
= 4,
193 ARC_BUILTIN_SWAP
= 5,
195 ARC_BUILTIN_DIVAW
= 7,
197 ARC_BUILTIN_MUL64
= 9,
198 ARC_BUILTIN_MULU64
= 10,
199 ARC_BUILTIN_RTIE
= 11,
200 ARC_BUILTIN_SYNC
= 12,
201 ARC_BUILTIN_CORE_READ
= 13,
202 ARC_BUILTIN_CORE_WRITE
= 14,
203 ARC_BUILTIN_FLAG
= 15,
206 ARC_BUILTIN_SLEEP
= 18,
207 ARC_BUILTIN_SWI
= 19,
208 ARC_BUILTIN_TRAP_S
= 20,
209 ARC_BUILTIN_UNIMP_S
= 21,
210 ARC_BUILTIN_ALIGNED
= 22,
212 /* Sentinel to mark start of simd builtins. */
213 ARC_SIMD_BUILTIN_BEGIN
= 1000,
215 ARC_SIMD_BUILTIN_VADDAW
= 1001,
216 ARC_SIMD_BUILTIN_VADDW
= 1002,
217 ARC_SIMD_BUILTIN_VAVB
= 1003,
218 ARC_SIMD_BUILTIN_VAVRB
= 1004,
219 ARC_SIMD_BUILTIN_VDIFAW
= 1005,
220 ARC_SIMD_BUILTIN_VDIFW
= 1006,
221 ARC_SIMD_BUILTIN_VMAXAW
= 1007,
222 ARC_SIMD_BUILTIN_VMAXW
= 1008,
223 ARC_SIMD_BUILTIN_VMINAW
= 1009,
224 ARC_SIMD_BUILTIN_VMINW
= 1010,
225 ARC_SIMD_BUILTIN_VMULAW
= 1011,
226 ARC_SIMD_BUILTIN_VMULFAW
= 1012,
227 ARC_SIMD_BUILTIN_VMULFW
= 1013,
228 ARC_SIMD_BUILTIN_VMULW
= 1014,
229 ARC_SIMD_BUILTIN_VSUBAW
= 1015,
230 ARC_SIMD_BUILTIN_VSUBW
= 1016,
231 ARC_SIMD_BUILTIN_VSUMMW
= 1017,
232 ARC_SIMD_BUILTIN_VAND
= 1018,
233 ARC_SIMD_BUILTIN_VANDAW
= 1019,
234 ARC_SIMD_BUILTIN_VBIC
= 1020,
235 ARC_SIMD_BUILTIN_VBICAW
= 1021,
236 ARC_SIMD_BUILTIN_VOR
= 1022,
237 ARC_SIMD_BUILTIN_VXOR
= 1023,
238 ARC_SIMD_BUILTIN_VXORAW
= 1024,
239 ARC_SIMD_BUILTIN_VEQW
= 1025,
240 ARC_SIMD_BUILTIN_VLEW
= 1026,
241 ARC_SIMD_BUILTIN_VLTW
= 1027,
242 ARC_SIMD_BUILTIN_VNEW
= 1028,
243 ARC_SIMD_BUILTIN_VMR1AW
= 1029,
244 ARC_SIMD_BUILTIN_VMR1W
= 1030,
245 ARC_SIMD_BUILTIN_VMR2AW
= 1031,
246 ARC_SIMD_BUILTIN_VMR2W
= 1032,
247 ARC_SIMD_BUILTIN_VMR3AW
= 1033,
248 ARC_SIMD_BUILTIN_VMR3W
= 1034,
249 ARC_SIMD_BUILTIN_VMR4AW
= 1035,
250 ARC_SIMD_BUILTIN_VMR4W
= 1036,
251 ARC_SIMD_BUILTIN_VMR5AW
= 1037,
252 ARC_SIMD_BUILTIN_VMR5W
= 1038,
253 ARC_SIMD_BUILTIN_VMR6AW
= 1039,
254 ARC_SIMD_BUILTIN_VMR6W
= 1040,
255 ARC_SIMD_BUILTIN_VMR7AW
= 1041,
256 ARC_SIMD_BUILTIN_VMR7W
= 1042,
257 ARC_SIMD_BUILTIN_VMRB
= 1043,
258 ARC_SIMD_BUILTIN_VH264F
= 1044,
259 ARC_SIMD_BUILTIN_VH264FT
= 1045,
260 ARC_SIMD_BUILTIN_VH264FW
= 1046,
261 ARC_SIMD_BUILTIN_VVC1F
= 1047,
262 ARC_SIMD_BUILTIN_VVC1FT
= 1048,
264 /* Va, Vb, rlimm instructions. */
265 ARC_SIMD_BUILTIN_VBADDW
= 1050,
266 ARC_SIMD_BUILTIN_VBMAXW
= 1051,
267 ARC_SIMD_BUILTIN_VBMINW
= 1052,
268 ARC_SIMD_BUILTIN_VBMULAW
= 1053,
269 ARC_SIMD_BUILTIN_VBMULFW
= 1054,
270 ARC_SIMD_BUILTIN_VBMULW
= 1055,
271 ARC_SIMD_BUILTIN_VBRSUBW
= 1056,
272 ARC_SIMD_BUILTIN_VBSUBW
= 1057,
274 /* Va, Vb, Ic instructions. */
275 ARC_SIMD_BUILTIN_VASRW
= 1060,
276 ARC_SIMD_BUILTIN_VSR8
= 1061,
277 ARC_SIMD_BUILTIN_VSR8AW
= 1062,
279 /* Va, Vb, u6 instructions. */
280 ARC_SIMD_BUILTIN_VASRRWi
= 1065,
281 ARC_SIMD_BUILTIN_VASRSRWi
= 1066,
282 ARC_SIMD_BUILTIN_VASRWi
= 1067,
283 ARC_SIMD_BUILTIN_VASRPWBi
= 1068,
284 ARC_SIMD_BUILTIN_VASRRPWBi
= 1069,
285 ARC_SIMD_BUILTIN_VSR8AWi
= 1070,
286 ARC_SIMD_BUILTIN_VSR8i
= 1071,
288 /* Va, Vb, u8 (simm) instructions. */
289 ARC_SIMD_BUILTIN_VMVAW
= 1075,
290 ARC_SIMD_BUILTIN_VMVW
= 1076,
291 ARC_SIMD_BUILTIN_VMVZW
= 1077,
292 ARC_SIMD_BUILTIN_VD6TAPF
= 1078,
294 /* Va, rlimm, u8 (simm) instructions. */
295 ARC_SIMD_BUILTIN_VMOVAW
= 1080,
296 ARC_SIMD_BUILTIN_VMOVW
= 1081,
297 ARC_SIMD_BUILTIN_VMOVZW
= 1082,
299 /* Va, Vb instructions. */
300 ARC_SIMD_BUILTIN_VABSAW
= 1085,
301 ARC_SIMD_BUILTIN_VABSW
= 1086,
302 ARC_SIMD_BUILTIN_VADDSUW
= 1087,
303 ARC_SIMD_BUILTIN_VSIGNW
= 1088,
304 ARC_SIMD_BUILTIN_VEXCH1
= 1089,
305 ARC_SIMD_BUILTIN_VEXCH2
= 1090,
306 ARC_SIMD_BUILTIN_VEXCH4
= 1091,
307 ARC_SIMD_BUILTIN_VUPBAW
= 1092,
308 ARC_SIMD_BUILTIN_VUPBW
= 1093,
309 ARC_SIMD_BUILTIN_VUPSBAW
= 1094,
310 ARC_SIMD_BUILTIN_VUPSBW
= 1095,
312 ARC_SIMD_BUILTIN_VDIRUN
= 1100,
313 ARC_SIMD_BUILTIN_VDORUN
= 1101,
314 ARC_SIMD_BUILTIN_VDIWR
= 1102,
315 ARC_SIMD_BUILTIN_VDOWR
= 1103,
317 ARC_SIMD_BUILTIN_VREC
= 1105,
318 ARC_SIMD_BUILTIN_VRUN
= 1106,
319 ARC_SIMD_BUILTIN_VRECRUN
= 1107,
320 ARC_SIMD_BUILTIN_VENDREC
= 1108,
322 ARC_SIMD_BUILTIN_VLD32WH
= 1110,
323 ARC_SIMD_BUILTIN_VLD32WL
= 1111,
324 ARC_SIMD_BUILTIN_VLD64
= 1112,
325 ARC_SIMD_BUILTIN_VLD32
= 1113,
326 ARC_SIMD_BUILTIN_VLD64W
= 1114,
327 ARC_SIMD_BUILTIN_VLD128
= 1115,
328 ARC_SIMD_BUILTIN_VST128
= 1116,
329 ARC_SIMD_BUILTIN_VST64
= 1117,
331 ARC_SIMD_BUILTIN_VST16_N
= 1120,
332 ARC_SIMD_BUILTIN_VST32_N
= 1121,
334 ARC_SIMD_BUILTIN_VINTI
= 1201,
339 /* A nop is needed between a 4 byte insn that sets the condition codes and
340 a branch that uses them (the same isn't true for an 8 byte insn that sets
341 the condition codes). Set by arc_ccfsm_advance. Used by
342 arc_print_operand. */
344 static int get_arc_condition_code (rtx
);
346 static tree
arc_handle_interrupt_attribute (tree
*, tree
, tree
, int, bool *);
348 /* Initialized arc_attribute_table to NULL since arc doesnot have any
349 machine specific supported attributes. */
350 const struct attribute_spec arc_attribute_table
[] =
352 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
353 affects_type_identity } */
354 { "interrupt", 1, 1, true, false, false, arc_handle_interrupt_attribute
, true },
355 /* Function calls made to this symbol must be done indirectly, because
356 it may lie outside of the 21/25 bit addressing range of a normal function
358 { "long_call", 0, 0, false, true, true, NULL
, false },
359 /* Whereas these functions are always known to reside within the 25 bit
360 addressing range of unconditionalized bl. */
361 { "medium_call", 0, 0, false, true, true, NULL
, false },
362 /* And these functions are always known to reside within the 21 bit
363 addressing range of blcc. */
364 { "short_call", 0, 0, false, true, true, NULL
, false },
365 { NULL
, 0, 0, false, false, false, NULL
, false }
367 static int arc_comp_type_attributes (const_tree
, const_tree
);
368 static void arc_file_start (void);
369 static void arc_internal_label (FILE *, const char *, unsigned long);
370 static void arc_output_mi_thunk (FILE *, tree
, HOST_WIDE_INT
, HOST_WIDE_INT
,
372 static int arc_address_cost (rtx
, enum machine_mode
, addr_space_t
, bool);
373 static void arc_encode_section_info (tree decl
, rtx rtl
, int first
);
375 static void arc_init_builtins (void);
376 static rtx
arc_expand_builtin (tree
, rtx
, rtx
, enum machine_mode
, int);
378 static int branch_dest (rtx
);
380 static void arc_output_pic_addr_const (FILE *, rtx
, int);
381 void emit_pic_move (rtx
*, enum machine_mode
);
382 bool arc_legitimate_pic_operand_p (rtx
);
383 static bool arc_function_ok_for_sibcall (tree
, tree
);
384 static rtx
arc_function_value (const_tree
, const_tree
, bool);
385 const char * output_shift (rtx
*);
386 static void arc_reorg (void);
387 static bool arc_in_small_data_p (const_tree
);
389 static void arc_init_reg_tables (void);
390 static bool arc_return_in_memory (const_tree
, const_tree
);
391 static void arc_init_simd_builtins (void);
392 static bool arc_vector_mode_supported_p (enum machine_mode
);
394 static bool arc_can_use_doloop_p (double_int
, double_int
, unsigned int, bool);
395 static const char *arc_invalid_within_doloop (const_rtx
);
397 static void output_short_suffix (FILE *file
);
399 static bool arc_frame_pointer_required (void);
401 /* Implements target hook vector_mode_supported_p. */
404 arc_vector_mode_supported_p (enum machine_mode mode
)
406 if (!TARGET_SIMD_SET
)
409 if ((mode
== V4SImode
)
410 || (mode
== V8HImode
))
417 /* TARGET_PRESERVE_RELOAD_P is still awaiting patch re-evaluation / review. */
418 static bool arc_preserve_reload_p (rtx in
) ATTRIBUTE_UNUSED
;
419 static rtx
arc_delegitimize_address (rtx
);
420 static bool arc_can_follow_jump (const_rtx follower
, const_rtx followee
);
422 static rtx
frame_insn (rtx
);
423 static void arc_function_arg_advance (cumulative_args_t
, enum machine_mode
,
425 static rtx
arc_legitimize_address_0 (rtx
, rtx
, enum machine_mode mode
);
427 static void arc_finalize_pic (void);
429 /* initialize the GCC target structure. */
430 #undef TARGET_COMP_TYPE_ATTRIBUTES
431 #define TARGET_COMP_TYPE_ATTRIBUTES arc_comp_type_attributes
432 #undef TARGET_ASM_FILE_START
433 #define TARGET_ASM_FILE_START arc_file_start
434 #undef TARGET_ATTRIBUTE_TABLE
435 #define TARGET_ATTRIBUTE_TABLE arc_attribute_table
436 #undef TARGET_ASM_INTERNAL_LABEL
437 #define TARGET_ASM_INTERNAL_LABEL arc_internal_label
438 #undef TARGET_RTX_COSTS
439 #define TARGET_RTX_COSTS arc_rtx_costs
440 #undef TARGET_ADDRESS_COST
441 #define TARGET_ADDRESS_COST arc_address_cost
443 #undef TARGET_ENCODE_SECTION_INFO
444 #define TARGET_ENCODE_SECTION_INFO arc_encode_section_info
446 #undef TARGET_CANNOT_FORCE_CONST_MEM
447 #define TARGET_CANNOT_FORCE_CONST_MEM arc_cannot_force_const_mem
449 #undef TARGET_INIT_BUILTINS
450 #define TARGET_INIT_BUILTINS arc_init_builtins
452 #undef TARGET_EXPAND_BUILTIN
453 #define TARGET_EXPAND_BUILTIN arc_expand_builtin
455 #undef TARGET_ASM_OUTPUT_MI_THUNK
456 #define TARGET_ASM_OUTPUT_MI_THUNK arc_output_mi_thunk
458 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
459 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
461 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
462 #define TARGET_FUNCTION_OK_FOR_SIBCALL arc_function_ok_for_sibcall
464 #undef TARGET_MACHINE_DEPENDENT_REORG
465 #define TARGET_MACHINE_DEPENDENT_REORG arc_reorg
467 #undef TARGET_IN_SMALL_DATA_P
468 #define TARGET_IN_SMALL_DATA_P arc_in_small_data_p
470 #undef TARGET_PROMOTE_FUNCTION_MODE
471 #define TARGET_PROMOTE_FUNCTION_MODE \
472 default_promote_function_mode_always_promote
474 #undef TARGET_PROMOTE_PROTOTYPES
475 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
477 #undef TARGET_RETURN_IN_MEMORY
478 #define TARGET_RETURN_IN_MEMORY arc_return_in_memory
479 #undef TARGET_PASS_BY_REFERENCE
480 #define TARGET_PASS_BY_REFERENCE arc_pass_by_reference
482 #undef TARGET_SETUP_INCOMING_VARARGS
483 #define TARGET_SETUP_INCOMING_VARARGS arc_setup_incoming_varargs
485 #undef TARGET_ARG_PARTIAL_BYTES
486 #define TARGET_ARG_PARTIAL_BYTES arc_arg_partial_bytes
488 #undef TARGET_MUST_PASS_IN_STACK
489 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
491 #undef TARGET_FUNCTION_VALUE
492 #define TARGET_FUNCTION_VALUE arc_function_value
494 #undef TARGET_SCHED_ADJUST_PRIORITY
495 #define TARGET_SCHED_ADJUST_PRIORITY arc_sched_adjust_priority
497 #undef TARGET_VECTOR_MODE_SUPPORTED_P
498 #define TARGET_VECTOR_MODE_SUPPORTED_P arc_vector_mode_supported_p
500 #undef TARGET_CAN_USE_DOLOOP_P
501 #define TARGET_CAN_USE_DOLOOP_P arc_can_use_doloop_p
503 #undef TARGET_INVALID_WITHIN_DOLOOP
504 #define TARGET_INVALID_WITHIN_DOLOOP arc_invalid_within_doloop
506 #undef TARGET_PRESERVE_RELOAD_P
507 #define TARGET_PRESERVE_RELOAD_P arc_preserve_reload_p
509 #undef TARGET_CAN_FOLLOW_JUMP
510 #define TARGET_CAN_FOLLOW_JUMP arc_can_follow_jump
512 #undef TARGET_DELEGITIMIZE_ADDRESS
513 #define TARGET_DELEGITIMIZE_ADDRESS arc_delegitimize_address
515 /* Usually, we will be able to scale anchor offsets.
516 When this fails, we want LEGITIMIZE_ADDRESS to kick in. */
517 #undef TARGET_MIN_ANCHOR_OFFSET
518 #define TARGET_MIN_ANCHOR_OFFSET (-1024)
519 #undef TARGET_MAX_ANCHOR_OFFSET
520 #define TARGET_MAX_ANCHOR_OFFSET (1020)
522 #undef TARGET_SECONDARY_RELOAD
523 #define TARGET_SECONDARY_RELOAD arc_secondary_reload
525 #define TARGET_OPTION_OVERRIDE arc_override_options
527 #define TARGET_CONDITIONAL_REGISTER_USAGE arc_conditional_register_usage
529 #define TARGET_TRAMPOLINE_INIT arc_initialize_trampoline
531 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS arc_trampoline_adjust_address
533 #define TARGET_CAN_ELIMINATE arc_can_eliminate
535 #define TARGET_FRAME_POINTER_REQUIRED arc_frame_pointer_required
537 #define TARGET_FUNCTION_ARG arc_function_arg
539 #define TARGET_FUNCTION_ARG_ADVANCE arc_function_arg_advance
541 #define TARGET_LEGITIMATE_CONSTANT_P arc_legitimate_constant_p
543 #define TARGET_LEGITIMATE_ADDRESS_P arc_legitimate_address_p
545 #define TARGET_MODE_DEPENDENT_ADDRESS_P arc_mode_dependent_address_p
547 #define TARGET_LEGITIMIZE_ADDRESS arc_legitimize_address
549 #define TARGET_ADJUST_INSN_LENGTH arc_adjust_insn_length
551 #define TARGET_INSN_LENGTH_PARAMETERS arc_insn_length_parameters
553 #define TARGET_LRA_P arc_lra_p
554 #define TARGET_REGISTER_PRIORITY arc_register_priority
555 /* Stores with scaled offsets have different displacement ranges. */
556 #define TARGET_DIFFERENT_ADDR_DISPLACEMENT_P hook_bool_void_true
557 #define TARGET_SPILL_CLASS arc_spill_class
559 #include "target-def.h"
561 #undef TARGET_ASM_ALIGNED_HI_OP
562 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
563 #undef TARGET_ASM_ALIGNED_SI_OP
564 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
566 /* Try to keep the (mov:DF _, reg) as early as possible so
567 that the d<add/sub/mul>h-lr insns appear together and can
568 use the peephole2 pattern. */
571 arc_sched_adjust_priority (rtx insn
, int priority
)
573 rtx set
= single_set (insn
);
575 && GET_MODE (SET_SRC(set
)) == DFmode
576 && GET_CODE (SET_SRC(set
)) == REG
)
578 /* Incrementing priority by 20 (empirically derived). */
579 return priority
+ 20;
586 arc_secondary_reload (bool in_p
, rtx x
, reg_class_t cl
, enum machine_mode
,
587 secondary_reload_info
*)
589 if (cl
== DOUBLE_REGS
)
592 /* The loop counter register can be stored, but not loaded directly. */
593 if ((cl
== LPCOUNT_REG
|| cl
== WRITABLE_CORE_REGS
)
594 && in_p
&& MEM_P (x
))
599 static unsigned arc_ifcvt (void);
603 const pass_data pass_data_arc_ifcvt
=
606 "arc_ifcvt", /* name */
607 OPTGROUP_NONE
, /* optinfo_flags */
608 false, /* has_gate */
609 true, /* has_execute */
610 TV_IFCVT2
, /* tv_id */
611 0, /* properties_required */
612 0, /* properties_provided */
613 0, /* properties_destroyed */
614 0, /* todo_flags_start */
615 TODO_df_finish
/* todo_flags_finish */
618 class pass_arc_ifcvt
: public rtl_opt_pass
621 pass_arc_ifcvt(gcc::context
*ctxt
)
622 : rtl_opt_pass(pass_data_arc_ifcvt
, ctxt
)
625 /* opt_pass methods: */
626 opt_pass
* clone () { return new pass_arc_ifcvt (m_ctxt
); }
627 unsigned int execute () { return arc_ifcvt (); }
633 make_pass_arc_ifcvt (gcc::context
*ctxt
)
635 return new pass_arc_ifcvt (ctxt
);
638 static unsigned arc_predicate_delay_insns (void);
642 const pass_data pass_data_arc_predicate_delay_insns
=
645 "arc_predicate_delay_insns", /* name */
646 OPTGROUP_NONE
, /* optinfo_flags */
647 false, /* has_gate */
648 true, /* has_execute */
649 TV_IFCVT2
, /* tv_id */
650 0, /* properties_required */
651 0, /* properties_provided */
652 0, /* properties_destroyed */
653 0, /* todo_flags_start */
654 TODO_df_finish
/* todo_flags_finish */
657 class pass_arc_predicate_delay_insns
: public rtl_opt_pass
660 pass_arc_predicate_delay_insns(gcc::context
*ctxt
)
661 : rtl_opt_pass(pass_data_arc_predicate_delay_insns
, ctxt
)
664 /* opt_pass methods: */
665 unsigned int execute () { return arc_predicate_delay_insns (); }
671 make_pass_arc_predicate_delay_insns (gcc::context
*ctxt
)
673 return new pass_arc_predicate_delay_insns (ctxt
);
676 /* Called by OVERRIDE_OPTIONS to initialize various things. */
681 enum attr_tune tune_dflt
= TUNE_NONE
;
685 arc_cpu_string
= "A5";
687 else if (TARGET_ARC600
)
689 arc_cpu_string
= "ARC600";
690 tune_dflt
= TUNE_ARC600
;
692 else if (TARGET_ARC601
)
694 arc_cpu_string
= "ARC601";
695 tune_dflt
= TUNE_ARC600
;
697 else if (TARGET_ARC700
)
699 arc_cpu_string
= "ARC700";
700 tune_dflt
= TUNE_ARC700_4_2_STD
;
704 if (arc_tune
== TUNE_NONE
)
705 arc_tune
= tune_dflt
;
706 /* Note: arc_multcost is only used in rtx_cost if speed is true. */
707 if (arc_multcost
< 0)
710 case TUNE_ARC700_4_2_STD
:
712 max throughput (1 multiply + 4 other insns) / 5 cycles. */
713 arc_multcost
= COSTS_N_INSNS (4);
714 if (TARGET_NOMPY_SET
)
715 arc_multcost
= COSTS_N_INSNS (30);
717 case TUNE_ARC700_4_2_XMAC
:
719 max throughput (1 multiply + 2 other insns) / 3 cycles. */
720 arc_multcost
= COSTS_N_INSNS (3);
721 if (TARGET_NOMPY_SET
)
722 arc_multcost
= COSTS_N_INSNS (30);
725 if (TARGET_MUL64_SET
)
727 arc_multcost
= COSTS_N_INSNS (4);
732 arc_multcost
= COSTS_N_INSNS (30);
736 /* Support mul64 generation only for A5 and ARC600. */
737 if (TARGET_MUL64_SET
&& TARGET_ARC700
)
738 error ("-mmul64 not supported for ARC700");
740 /* MPY instructions valid only for ARC700. */
741 if (TARGET_NOMPY_SET
&& !TARGET_ARC700
)
742 error ("-mno-mpy supported only for ARC700");
744 /* mul/mac instructions only for ARC600. */
745 if (TARGET_MULMAC_32BY16_SET
&& !(TARGET_ARC600
|| TARGET_ARC601
))
746 error ("-mmul32x16 supported only for ARC600 or ARC601");
748 if (!TARGET_DPFP
&& TARGET_DPFP_DISABLE_LRSR
)
749 error ("-mno-dpfp-lrsr suppforted only with -mdpfp");
751 /* FPX-1. No fast and compact together. */
752 if ((TARGET_DPFP_FAST_SET
&& TARGET_DPFP_COMPACT_SET
)
753 || (TARGET_SPFP_FAST_SET
&& TARGET_SPFP_COMPACT_SET
))
754 error ("FPX fast and compact options cannot be specified together");
756 /* FPX-2. No fast-spfp for arc600 or arc601. */
757 if (TARGET_SPFP_FAST_SET
&& (TARGET_ARC600
|| TARGET_ARC601
))
758 error ("-mspfp_fast not available on ARC600 or ARC601");
760 /* FPX-3. No FPX extensions on pre-ARC600 cores. */
761 if ((TARGET_DPFP
|| TARGET_SPFP
)
762 && !(TARGET_ARC600
|| TARGET_ARC601
|| TARGET_ARC700
))
763 error ("FPX extensions not available on pre-ARC600 cores");
765 /* Warn for unimplemented PIC in pre-ARC700 cores, and disable flag_pic. */
766 if (flag_pic
&& !TARGET_ARC700
)
768 warning (DK_WARNING
, "PIC is not supported for %s. Generating non-PIC code only..", arc_cpu_string
);
772 arc_init_reg_tables ();
774 /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P. */
775 memset (arc_punct_chars
, 0, sizeof (arc_punct_chars
));
776 arc_punct_chars
['#'] = 1;
777 arc_punct_chars
['*'] = 1;
778 arc_punct_chars
['?'] = 1;
779 arc_punct_chars
['!'] = 1;
780 arc_punct_chars
['^'] = 1;
781 arc_punct_chars
['&'] = 1;
783 if (optimize
> 1 && !TARGET_NO_COND_EXEC
)
785 /* There are two target-independent ifcvt passes, and arc_reorg may do
786 one or more arc_ifcvt calls. */
787 opt_pass
*pass_arc_ifcvt_4
= make_pass_arc_ifcvt (g
);
788 struct register_pass_info arc_ifcvt4_info
789 = { pass_arc_ifcvt_4
, "dbr", 1, PASS_POS_INSERT_AFTER
};
790 struct register_pass_info arc_ifcvt5_info
791 = { pass_arc_ifcvt_4
->clone (), "shorten", 1, PASS_POS_INSERT_BEFORE
};
793 register_pass (&arc_ifcvt4_info
);
794 register_pass (&arc_ifcvt5_info
);
797 if (flag_delayed_branch
)
799 opt_pass
*pass_arc_predicate_delay_insns
800 = make_pass_arc_predicate_delay_insns (g
);
801 struct register_pass_info arc_predicate_delay_info
802 = { pass_arc_predicate_delay_insns
, "dbr", 1, PASS_POS_INSERT_AFTER
};
804 register_pass (&arc_predicate_delay_info
);
808 /* Check ARC options, generate derived target attributes. */
811 arc_override_options (void)
813 if (arc_cpu
== PROCESSOR_NONE
)
814 arc_cpu
= PROCESSOR_ARC700
;
816 if (arc_size_opt_level
== 3)
820 target_flags
|= MASK_NO_SDATA_SET
;
822 if (flag_no_common
== 255)
823 flag_no_common
= !TARGET_NO_SDATA_SET
;
825 /* TARGET_COMPACT_CASESI needs the "q" register class. */ \
826 if (TARGET_MIXED_CODE
)
829 TARGET_COMPACT_CASESI
= 0;
830 if (TARGET_COMPACT_CASESI
)
831 TARGET_CASE_VECTOR_PC_RELATIVE
= 1;
833 /* These need to be done at start up. It's convenient to do them here. */
837 /* The condition codes of the ARC, and the inverse function. */
838 /* For short branches, the "c" / "nc" names are not defined in the ARC
839 Programmers manual, so we have to use "lo" / "hs"" instead. */
840 static const char *arc_condition_codes
[] =
842 "al", 0, "eq", "ne", "p", "n", "lo", "hs", "v", "nv",
843 "gt", "le", "ge", "lt", "hi", "ls", "pnz", 0
846 enum arc_cc_code_index
848 ARC_CC_AL
, ARC_CC_EQ
= ARC_CC_AL
+2, ARC_CC_NE
, ARC_CC_P
, ARC_CC_N
,
849 ARC_CC_C
, ARC_CC_NC
, ARC_CC_V
, ARC_CC_NV
,
850 ARC_CC_GT
, ARC_CC_LE
, ARC_CC_GE
, ARC_CC_LT
, ARC_CC_HI
, ARC_CC_LS
, ARC_CC_PNZ
,
851 ARC_CC_LO
= ARC_CC_C
, ARC_CC_HS
= ARC_CC_NC
854 #define ARC_INVERSE_CONDITION_CODE(X) ((X) ^ 1)
856 /* Returns the index of the ARC condition code string in
857 `arc_condition_codes'. COMPARISON should be an rtx like
858 `(eq (...) (...))'. */
861 get_arc_condition_code (rtx comparison
)
863 switch (GET_MODE (XEXP (comparison
, 0)))
866 case SImode
: /* For BRcc. */
867 switch (GET_CODE (comparison
))
869 case EQ
: return ARC_CC_EQ
;
870 case NE
: return ARC_CC_NE
;
871 case GT
: return ARC_CC_GT
;
872 case LE
: return ARC_CC_LE
;
873 case GE
: return ARC_CC_GE
;
874 case LT
: return ARC_CC_LT
;
875 case GTU
: return ARC_CC_HI
;
876 case LEU
: return ARC_CC_LS
;
877 case LTU
: return ARC_CC_LO
;
878 case GEU
: return ARC_CC_HS
;
879 default : gcc_unreachable ();
882 switch (GET_CODE (comparison
))
884 case EQ
: return ARC_CC_EQ
;
885 case NE
: return ARC_CC_NE
;
886 case GE
: return ARC_CC_P
;
887 case LT
: return ARC_CC_N
;
888 case GT
: return ARC_CC_PNZ
;
889 default : gcc_unreachable ();
892 switch (GET_CODE (comparison
))
894 case EQ
: return ARC_CC_EQ
;
895 case NE
: return ARC_CC_NE
;
896 default : gcc_unreachable ();
899 switch (GET_CODE (comparison
))
901 case LTU
: return ARC_CC_C
;
902 case GEU
: return ARC_CC_NC
;
903 default : gcc_unreachable ();
906 if (TARGET_ARGONAUT_SET
&& TARGET_SPFP
)
907 switch (GET_CODE (comparison
))
909 case GT
: return ARC_CC_N
;
910 case UNLE
: return ARC_CC_P
;
911 default : gcc_unreachable ();
914 switch (GET_CODE (comparison
))
916 case GT
: return ARC_CC_HI
;
917 case UNLE
: return ARC_CC_LS
;
918 default : gcc_unreachable ();
921 /* Same for FPX and non-FPX. */
922 switch (GET_CODE (comparison
))
924 case GE
: return ARC_CC_HS
;
925 case UNLT
: return ARC_CC_LO
;
926 default : gcc_unreachable ();
929 switch (GET_CODE (comparison
))
931 case UNEQ
: return ARC_CC_EQ
;
932 case LTGT
: return ARC_CC_NE
;
933 default : gcc_unreachable ();
936 switch (GET_CODE (comparison
))
938 case UNORDERED
: return ARC_CC_C
;
939 case ORDERED
: return ARC_CC_NC
;
940 default : gcc_unreachable ();
943 switch (GET_CODE (comparison
))
945 case EQ
: return ARC_CC_EQ
;
946 case NE
: return ARC_CC_NE
;
947 case UNORDERED
: return ARC_CC_C
;
948 case ORDERED
: return ARC_CC_NC
;
949 case LTGT
: return ARC_CC_HI
;
950 case UNEQ
: return ARC_CC_LS
;
951 default : gcc_unreachable ();
953 default : gcc_unreachable ();
959 /* Return true if COMPARISON has a short form that can accomodate OFFSET. */
962 arc_short_comparison_p (rtx comparison
, int offset
)
964 gcc_assert (ARC_CC_NC
== ARC_CC_HS
);
965 gcc_assert (ARC_CC_C
== ARC_CC_LO
);
966 switch (get_arc_condition_code (comparison
))
968 case ARC_CC_EQ
: case ARC_CC_NE
:
969 return offset
>= -512 && offset
<= 506;
970 case ARC_CC_GT
: case ARC_CC_LE
: case ARC_CC_GE
: case ARC_CC_LT
:
971 case ARC_CC_HI
: case ARC_CC_LS
: case ARC_CC_LO
: case ARC_CC_HS
:
972 return offset
>= -64 && offset
<= 58;
978 /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
979 return the mode to be used for the comparison. */
982 arc_select_cc_mode (enum rtx_code op
, rtx x
, rtx y
)
984 enum machine_mode mode
= GET_MODE (x
);
987 /* For an operation that sets the condition codes as a side-effect, the
988 C and V flags is not set as for cmp, so we can only use comparisons where
989 this doesn't matter. (For LT and GE we can use "mi" and "pl"
991 /* ??? We could use "pnz" for greater than zero, however, we could then
992 get into trouble because the comparison could not be reversed. */
993 if (GET_MODE_CLASS (mode
) == MODE_INT
995 && (op
== EQ
|| op
== NE
996 || ((op
== LT
|| op
== GE
) && GET_MODE_SIZE (GET_MODE (x
) <= 4))))
999 /* add.f for if (a+b) */
1001 && GET_CODE (y
) == NEG
1002 && (op
== EQ
|| op
== NE
))
1005 /* Check if this is a test suitable for bxor.f . */
1006 if (mode
== SImode
&& (op
== EQ
|| op
== NE
) && CONST_INT_P (y
)
1007 && ((INTVAL (y
) - 1) & INTVAL (y
)) == 0
1011 /* Check if this is a test suitable for add / bmsk.f . */
1012 if (mode
== SImode
&& (op
== EQ
|| op
== NE
) && CONST_INT_P (y
)
1013 && GET_CODE (x
) == AND
&& CONST_INT_P ((x1
= XEXP (x
, 1)))
1014 && ((INTVAL (x1
) + 1) & INTVAL (x1
)) == 0
1015 && (~INTVAL (x1
) | INTVAL (y
)) < 0
1016 && (~INTVAL (x1
) | INTVAL (y
)) > -0x800)
1019 if (GET_MODE (x
) == SImode
&& (op
== LTU
|| op
== GEU
)
1020 && GET_CODE (x
) == PLUS
1021 && (rtx_equal_p (XEXP (x
, 0), y
) || rtx_equal_p (XEXP (x
, 1), y
)))
1024 if (TARGET_ARGONAUT_SET
1025 && ((mode
== SFmode
&& TARGET_SPFP
) || (mode
== DFmode
&& TARGET_DPFP
)))
1028 case EQ
: case NE
: case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1030 case LT
: case UNGE
: case GT
: case UNLE
:
1031 return CC_FP_GTmode
;
1032 case LE
: case UNGT
: case GE
: case UNLT
:
1033 return CC_FP_GEmode
;
1034 default: gcc_unreachable ();
1036 else if (GET_MODE_CLASS (mode
) == MODE_FLOAT
&& TARGET_OPTFPE
)
1039 case EQ
: case NE
: return CC_Zmode
;
1041 case GT
: case UNLE
: return CC_FP_GTmode
;
1043 case GE
: case UNLT
: return CC_FP_GEmode
;
1044 case UNEQ
: case LTGT
: return CC_FP_UNEQmode
;
1045 case ORDERED
: case UNORDERED
: return CC_FP_ORDmode
;
1046 default: gcc_unreachable ();
1052 /* Vectors to keep interesting information about registers where it can easily
1053 be got. We use to use the actual mode value as the bit number, but there
1054 is (or may be) more than 32 modes now. Instead we use two tables: one
1055 indexed by hard register number, and one indexed by mode. */
1057 /* The purpose of arc_mode_class is to shrink the range of modes so that
1058 they all fit (as bit numbers) in a 32-bit word (again). Each real mode is
1059 mapped into one arc_mode_class mode. */
1061 enum arc_mode_class
{
1063 S_MODE
, D_MODE
, T_MODE
, O_MODE
,
1064 SF_MODE
, DF_MODE
, TF_MODE
, OF_MODE
,
1068 /* Modes for condition codes. */
1069 #define C_MODES (1 << (int) C_MODE)
1071 /* Modes for single-word and smaller quantities. */
1072 #define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
1074 /* Modes for double-word and smaller quantities. */
1075 #define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))
1077 /* Mode for 8-byte DF values only. */
1078 #define DF_MODES (1 << DF_MODE)
1080 /* Modes for quad-word and smaller quantities. */
1081 #define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE))
1083 /* Modes for 128-bit vectors. */
1084 #define V_MODES (1 << (int) V_MODE)
1086 /* Value is 1 if register/mode pair is acceptable on arc. */
1088 unsigned int arc_hard_regno_mode_ok
[] = {
1089 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
,
1090 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
,
1091 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, D_MODES
,
1092 D_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1094 /* ??? Leave these as S_MODES for now. */
1095 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1096 DF_MODES
, 0, DF_MODES
, 0, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1097 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1098 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, C_MODES
, S_MODES
,
1100 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1101 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1102 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1103 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1105 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1106 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1107 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1108 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1110 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1111 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
1114 unsigned int arc_mode_class
[NUM_MACHINE_MODES
];
1116 enum reg_class arc_regno_reg_class
[FIRST_PSEUDO_REGISTER
];
1119 arc_preferred_reload_class (rtx
, enum reg_class cl
)
1121 if ((cl
) == CHEAP_CORE_REGS
|| (cl
) == WRITABLE_CORE_REGS
)
1122 return GENERAL_REGS
;
1126 /* Initialize the arc_mode_class array. */
1129 arc_init_reg_tables (void)
1133 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
1135 switch (GET_MODE_CLASS (i
))
1138 case MODE_PARTIAL_INT
:
1139 case MODE_COMPLEX_INT
:
1140 if (GET_MODE_SIZE (i
) <= 4)
1141 arc_mode_class
[i
] = 1 << (int) S_MODE
;
1142 else if (GET_MODE_SIZE (i
) == 8)
1143 arc_mode_class
[i
] = 1 << (int) D_MODE
;
1144 else if (GET_MODE_SIZE (i
) == 16)
1145 arc_mode_class
[i
] = 1 << (int) T_MODE
;
1146 else if (GET_MODE_SIZE (i
) == 32)
1147 arc_mode_class
[i
] = 1 << (int) O_MODE
;
1149 arc_mode_class
[i
] = 0;
1152 case MODE_COMPLEX_FLOAT
:
1153 if (GET_MODE_SIZE (i
) <= 4)
1154 arc_mode_class
[i
] = 1 << (int) SF_MODE
;
1155 else if (GET_MODE_SIZE (i
) == 8)
1156 arc_mode_class
[i
] = 1 << (int) DF_MODE
;
1157 else if (GET_MODE_SIZE (i
) == 16)
1158 arc_mode_class
[i
] = 1 << (int) TF_MODE
;
1159 else if (GET_MODE_SIZE (i
) == 32)
1160 arc_mode_class
[i
] = 1 << (int) OF_MODE
;
1162 arc_mode_class
[i
] = 0;
1164 case MODE_VECTOR_INT
:
1165 arc_mode_class
[i
] = (1<< (int) V_MODE
);
1169 /* mode_class hasn't been initialized yet for EXTRA_CC_MODES, so
1170 we must explicitly check for them here. */
1171 if (i
== (int) CCmode
|| i
== (int) CC_ZNmode
|| i
== (int) CC_Zmode
1172 || i
== (int) CC_Cmode
1173 || i
== CC_FP_GTmode
|| i
== CC_FP_GEmode
|| i
== CC_FP_ORDmode
)
1174 arc_mode_class
[i
] = 1 << (int) C_MODE
;
1176 arc_mode_class
[i
] = 0;
1182 /* Core registers 56..59 are used for multiply extension options.
1183 The dsp option uses r56 and r57, these are then named acc1 and acc2.
1184 acc1 is the highpart, and acc2 the lowpart, so which register gets which
1185 number depends on endianness.
1186 The mul64 multiplier options use r57 for mlo, r58 for mmid and r59 for mhi.
1187 Because mlo / mhi form a 64 bit value, we use different gcc internal
1188 register numbers to make them form a register pair as the gcc internals
1189 know it. mmid gets number 57, if still available, and mlo / mhi get
1190 number 58 and 59, depending on endianness. We use DBX_REGISTER_NUMBER
1191 to map this back. */
1192 char rname56
[5] = "r56";
1193 char rname57
[5] = "r57";
1194 char rname58
[5] = "r58";
1195 char rname59
[5] = "r59";
1198 arc_conditional_register_usage (void)
1202 int fix_start
= 60, fix_end
= 55;
1204 if (TARGET_MUL64_SET
)
1209 /* We don't provide a name for mmed. In rtl / assembly resource lists,
1210 you are supposed to refer to it as mlo & mhi, e.g
1211 (zero_extract:SI (reg:DI 58) (const_int 32) (16)) .
1212 In an actual asm instruction, you are of course use mmed.
1213 The point of avoiding having a separate register for mmed is that
1214 this way, we don't have to carry clobbers of that reg around in every
1215 isntruction that modifies mlo and/or mhi. */
1216 strcpy (rname57
, "");
1217 strcpy (rname58
, TARGET_BIG_ENDIAN
? "mhi" : "mlo");
1218 strcpy (rname59
, TARGET_BIG_ENDIAN
? "mlo" : "mhi");
1220 if (TARGET_MULMAC_32BY16_SET
)
1223 fix_end
= fix_end
> 57 ? fix_end
: 57;
1224 strcpy (rname56
, TARGET_BIG_ENDIAN
? "acc1" : "acc2");
1225 strcpy (rname57
, TARGET_BIG_ENDIAN
? "acc2" : "acc1");
1227 for (regno
= fix_start
; regno
<= fix_end
; regno
++)
1229 if (!fixed_regs
[regno
])
1230 warning (0, "multiply option implies r%d is fixed", regno
);
1231 fixed_regs
[regno
] = call_used_regs
[regno
] = 1;
1235 reg_alloc_order
[2] = 12;
1236 reg_alloc_order
[3] = 13;
1237 reg_alloc_order
[4] = 14;
1238 reg_alloc_order
[5] = 15;
1239 reg_alloc_order
[6] = 1;
1240 reg_alloc_order
[7] = 0;
1241 reg_alloc_order
[8] = 4;
1242 reg_alloc_order
[9] = 5;
1243 reg_alloc_order
[10] = 6;
1244 reg_alloc_order
[11] = 7;
1245 reg_alloc_order
[12] = 8;
1246 reg_alloc_order
[13] = 9;
1247 reg_alloc_order
[14] = 10;
1248 reg_alloc_order
[15] = 11;
1250 if (TARGET_SIMD_SET
)
1253 for (i
= ARC_FIRST_SIMD_VR_REG
; i
<= ARC_LAST_SIMD_VR_REG
; i
++)
1254 reg_alloc_order
[i
] = i
;
1255 for (i
= ARC_FIRST_SIMD_DMA_CONFIG_REG
;
1256 i
<= ARC_LAST_SIMD_DMA_CONFIG_REG
; i
++)
1257 reg_alloc_order
[i
] = i
;
1259 /* For Arctangent-A5 / ARC600, lp_count may not be read in an instruction
1260 following immediately after another one setting it to a new value.
1261 There was some discussion on how to enforce scheduling constraints for
1262 processors with missing interlocks on the gcc mailing list:
1263 http://gcc.gnu.org/ml/gcc/2008-05/msg00021.html .
1264 However, we can't actually use this approach, because for ARC the
1265 delay slot scheduling pass is active, which runs after
1266 machine_dependent_reorg. */
1268 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], LP_COUNT
);
1269 else if (!TARGET_ARC700
)
1270 fixed_regs
[LP_COUNT
] = 1;
1271 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
1272 if (!call_used_regs
[regno
])
1273 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], regno
);
1274 for (regno
= 32; regno
< 60; regno
++)
1275 if (!fixed_regs
[regno
])
1276 SET_HARD_REG_BIT (reg_class_contents
[WRITABLE_CORE_REGS
], regno
);
1279 for (regno
= 32; regno
<= 60; regno
++)
1280 CLEAR_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], regno
);
1282 /* If they have used -ffixed-lp_count, make sure it takes
1284 if (fixed_regs
[LP_COUNT
])
1286 CLEAR_HARD_REG_BIT (reg_class_contents
[LPCOUNT_REG
], LP_COUNT
);
1287 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], LP_COUNT
);
1288 CLEAR_HARD_REG_BIT (reg_class_contents
[WRITABLE_CORE_REGS
], LP_COUNT
);
1290 /* Instead of taking out SF_MODE like below, forbid it outright. */
1291 arc_hard_regno_mode_ok
[60] = 0;
1294 arc_hard_regno_mode_ok
[60] = 1 << (int) S_MODE
;
1297 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1301 if (TARGET_Q_CLASS
&& ((i
<= 3) || ((i
>= 12) && (i
<= 15))))
1302 arc_regno_reg_class
[i
] = ARCOMPACT16_REGS
;
1304 arc_regno_reg_class
[i
] = GENERAL_REGS
;
1307 arc_regno_reg_class
[i
]
1309 ? (TEST_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], i
)
1310 ? CHEAP_CORE_REGS
: ALL_CORE_REGS
)
1312 && TEST_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], i
))
1313 ? CHEAP_CORE_REGS
: WRITABLE_CORE_REGS
));
1315 arc_regno_reg_class
[i
] = NO_REGS
;
1318 /* ARCOMPACT16_REGS is empty, if TARGET_Q_CLASS has not been activated. */
1319 if (!TARGET_Q_CLASS
)
1321 CLEAR_HARD_REG_SET(reg_class_contents
[ARCOMPACT16_REGS
]);
1322 CLEAR_HARD_REG_SET(reg_class_contents
[AC16_BASE_REGS
]);
1325 gcc_assert (FIRST_PSEUDO_REGISTER
>= 144);
1327 /* Handle Special Registers. */
1328 arc_regno_reg_class
[29] = LINK_REGS
; /* ilink1 register. */
1329 arc_regno_reg_class
[30] = LINK_REGS
; /* ilink2 register. */
1330 arc_regno_reg_class
[31] = LINK_REGS
; /* blink register. */
1331 arc_regno_reg_class
[60] = LPCOUNT_REG
;
1332 arc_regno_reg_class
[61] = NO_REGS
; /* CC_REG: must be NO_REGS. */
1333 arc_regno_reg_class
[62] = GENERAL_REGS
;
1337 for (i
= 40; i
< 44; ++i
)
1339 arc_regno_reg_class
[i
] = DOUBLE_REGS
;
1341 /* Unless they want us to do 'mov d1, 0x00000000' make sure
1342 no attempt is made to use such a register as a destination
1343 operand in *movdf_insn. */
1344 if (!TARGET_ARGONAUT_SET
)
1346 /* Make sure no 'c', 'w', 'W', or 'Rac' constraint is
1347 interpreted to mean they can use D1 or D2 in their insn. */
1348 CLEAR_HARD_REG_BIT(reg_class_contents
[CHEAP_CORE_REGS
], i
);
1349 CLEAR_HARD_REG_BIT(reg_class_contents
[ALL_CORE_REGS
], i
);
1350 CLEAR_HARD_REG_BIT(reg_class_contents
[WRITABLE_CORE_REGS
], i
);
1351 CLEAR_HARD_REG_BIT(reg_class_contents
[MPY_WRITABLE_CORE_REGS
], i
);
1357 /* Disable all DOUBLE_REGISTER settings,
1358 if not generating DPFP code. */
1359 arc_regno_reg_class
[40] = ALL_REGS
;
1360 arc_regno_reg_class
[41] = ALL_REGS
;
1361 arc_regno_reg_class
[42] = ALL_REGS
;
1362 arc_regno_reg_class
[43] = ALL_REGS
;
1364 arc_hard_regno_mode_ok
[40] = 0;
1365 arc_hard_regno_mode_ok
[42] = 0;
1367 CLEAR_HARD_REG_SET(reg_class_contents
[DOUBLE_REGS
]);
1370 if (TARGET_SIMD_SET
)
1372 gcc_assert (ARC_FIRST_SIMD_VR_REG
== 64);
1373 gcc_assert (ARC_LAST_SIMD_VR_REG
== 127);
1375 for (i
= ARC_FIRST_SIMD_VR_REG
; i
<= ARC_LAST_SIMD_VR_REG
; i
++)
1376 arc_regno_reg_class
[i
] = SIMD_VR_REGS
;
1378 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_REG
== 128);
1379 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_IN_REG
== 128);
1380 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG
== 136);
1381 gcc_assert (ARC_LAST_SIMD_DMA_CONFIG_REG
== 143);
1383 for (i
= ARC_FIRST_SIMD_DMA_CONFIG_REG
;
1384 i
<= ARC_LAST_SIMD_DMA_CONFIG_REG
; i
++)
1385 arc_regno_reg_class
[i
] = SIMD_DMA_CONFIG_REGS
;
1389 arc_regno_reg_class
[PROGRAM_COUNTER_REGNO
] = GENERAL_REGS
;
1392 /* Handle an "interrupt" attribute; arguments as in
1393 struct attribute_spec.handler. */
1396 arc_handle_interrupt_attribute (tree
*, tree name
, tree args
, int,
1401 tree value
= TREE_VALUE (args
);
1403 if (TREE_CODE (value
) != STRING_CST
)
1405 warning (OPT_Wattributes
,
1406 "argument of %qE attribute is not a string constant",
1408 *no_add_attrs
= true;
1410 else if (strcmp (TREE_STRING_POINTER (value
), "ilink1")
1411 && strcmp (TREE_STRING_POINTER (value
), "ilink2"))
1413 warning (OPT_Wattributes
,
1414 "argument of %qE attribute is not \"ilink1\" or \"ilink2\"",
1416 *no_add_attrs
= true;
1421 /* Return zero if TYPE1 and TYPE are incompatible, one if they are compatible,
1422 and two if they are nearly compatible (which causes a warning to be
1426 arc_comp_type_attributes (const_tree type1
,
1429 int l1
, l2
, m1
, m2
, s1
, s2
;
1431 /* Check for mismatch of non-default calling convention. */
1432 if (TREE_CODE (type1
) != FUNCTION_TYPE
)
1435 /* Check for mismatched call attributes. */
1436 l1
= lookup_attribute ("long_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
1437 l2
= lookup_attribute ("long_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
1438 m1
= lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
1439 m2
= lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
1440 s1
= lookup_attribute ("short_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
1441 s2
= lookup_attribute ("short_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
1443 /* Only bother to check if an attribute is defined. */
1444 if (l1
| l2
| m1
| m2
| s1
| s2
)
1446 /* If one type has an attribute, the other must have the same attribute. */
1447 if ((l1
!= l2
) || (m1
!= m2
) || (s1
!= s2
))
1450 /* Disallow mixed attributes. */
1451 if (l1
+ m1
+ s1
> 1)
1459 /* Set the default attributes for TYPE. */
1462 arc_set_default_type_attributes (tree type ATTRIBUTE_UNUSED
)
1467 /* Misc. utilities. */
1469 /* X and Y are two things to compare using CODE. Emit the compare insn and
1470 return the rtx for the cc reg in the proper mode. */
1473 gen_compare_reg (rtx comparison
, enum machine_mode omode
)
1475 enum rtx_code code
= GET_CODE (comparison
);
1476 rtx x
= XEXP (comparison
, 0);
1477 rtx y
= XEXP (comparison
, 1);
1479 enum machine_mode mode
, cmode
;
1482 cmode
= GET_MODE (x
);
1483 if (cmode
== VOIDmode
)
1484 cmode
= GET_MODE (y
);
1485 gcc_assert (cmode
== SImode
|| cmode
== SFmode
|| cmode
== DFmode
);
1486 if (cmode
== SImode
)
1488 if (!register_operand (x
, SImode
))
1490 if (register_operand (y
, SImode
))
1495 code
= swap_condition (code
);
1498 x
= copy_to_mode_reg (SImode
, x
);
1500 if (GET_CODE (y
) == SYMBOL_REF
&& flag_pic
)
1501 y
= copy_to_mode_reg (SImode
, y
);
1505 x
= force_reg (cmode
, x
);
1506 y
= force_reg (cmode
, y
);
1508 mode
= SELECT_CC_MODE (code
, x
, y
);
1510 cc_reg
= gen_rtx_REG (mode
, CC_REG
);
1512 /* ??? FIXME (x-y)==0, as done by both cmpsfpx_raw and
1513 cmpdfpx_raw, is not a correct comparison for floats:
1514 http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
1516 if (TARGET_ARGONAUT_SET
1517 && ((cmode
== SFmode
&& TARGET_SPFP
) || (cmode
== DFmode
&& TARGET_DPFP
)))
1521 case NE
: case EQ
: case LT
: case UNGE
: case LE
: case UNGT
:
1522 case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1524 case GT
: case UNLE
: case GE
: case UNLT
:
1525 code
= swap_condition (code
);
1533 if (cmode
== SFmode
)
1535 emit_insn (gen_cmpsfpx_raw (x
, y
));
1539 /* Accepts Dx regs directly by insns. */
1540 emit_insn (gen_cmpdfpx_raw (x
, y
));
1543 if (mode
!= CC_FPXmode
)
1544 emit_insn (gen_rtx_SET (VOIDmode
, cc_reg
,
1545 gen_rtx_COMPARE (mode
,
1546 gen_rtx_REG (CC_FPXmode
, 61),
1549 else if (GET_MODE_CLASS (cmode
) == MODE_FLOAT
&& TARGET_OPTFPE
)
1551 rtx op0
= gen_rtx_REG (cmode
, 0);
1552 rtx op1
= gen_rtx_REG (cmode
, GET_MODE_SIZE (cmode
) / UNITS_PER_WORD
);
1556 case NE
: case EQ
: case GT
: case UNLE
: case GE
: case UNLT
:
1557 case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1559 case LT
: case UNGE
: case LE
: case UNGT
:
1560 code
= swap_condition (code
);
1568 if (currently_expanding_to_rtl
)
1570 emit_move_insn (op0
, x
);
1571 emit_move_insn (op1
, y
);
1575 gcc_assert (rtx_equal_p (op0
, x
));
1576 gcc_assert (rtx_equal_p (op1
, y
));
1578 emit_insn (gen_cmp_float (cc_reg
, gen_rtx_COMPARE (mode
, op0
, op1
)));
1581 emit_insn (gen_rtx_SET (omode
, cc_reg
,
1582 gen_rtx_COMPARE (mode
, x
, y
)));
1583 return gen_rtx_fmt_ee (code
, omode
, cc_reg
, const0_rtx
);
1586 /* Return true if VALUE, a const_double, will fit in a limm (4 byte number).
1587 We assume the value can be either signed or unsigned. */
1590 arc_double_limm_p (rtx value
)
1592 HOST_WIDE_INT low
, high
;
1594 gcc_assert (GET_CODE (value
) == CONST_DOUBLE
);
1599 low
= CONST_DOUBLE_LOW (value
);
1600 high
= CONST_DOUBLE_HIGH (value
);
1602 if (low
& 0x80000000)
1604 return (((unsigned HOST_WIDE_INT
) low
<= 0xffffffff && high
== 0)
1605 || (((low
& - (unsigned HOST_WIDE_INT
) 0x80000000)
1606 == - (unsigned HOST_WIDE_INT
) 0x80000000)
1611 return (unsigned HOST_WIDE_INT
) low
<= 0x7fffffff && high
== 0;
1615 /* Do any needed setup for a variadic function. For the ARC, we must
1616 create a register parameter block, and then copy any anonymous arguments
1617 in registers to memory.
1619 CUM has not been updated for the last named argument which has type TYPE
1620 and mode MODE, and we rely on this fact. */
1623 arc_setup_incoming_varargs (cumulative_args_t args_so_far
,
1624 enum machine_mode mode
, tree type
,
1625 int *pretend_size
, int no_rtl
)
1628 CUMULATIVE_ARGS next_cum
;
1630 /* We must treat `__builtin_va_alist' as an anonymous arg. */
1632 next_cum
= *get_cumulative_args (args_so_far
);
1633 arc_function_arg_advance (pack_cumulative_args (&next_cum
), mode
, type
, 1);
1634 first_anon_arg
= next_cum
;
1636 if (first_anon_arg
< MAX_ARC_PARM_REGS
)
1638 /* First anonymous (unnamed) argument is in a reg. */
1640 /* Note that first_reg_offset < MAX_ARC_PARM_REGS. */
1641 int first_reg_offset
= first_anon_arg
;
1646 = gen_rtx_MEM (BLKmode
, plus_constant (Pmode
, arg_pointer_rtx
,
1647 FIRST_PARM_OFFSET (0)));
1648 move_block_from_reg (first_reg_offset
, regblock
,
1649 MAX_ARC_PARM_REGS
- first_reg_offset
);
1653 = ((MAX_ARC_PARM_REGS
- first_reg_offset
) * UNITS_PER_WORD
);
1657 /* Cost functions. */
1659 /* Provide the costs of an addressing mode that contains ADDR.
1660 If ADDR is not a valid address, its cost is irrelevant. */
1663 arc_address_cost (rtx addr
, enum machine_mode
, addr_space_t
, bool speed
)
1665 switch (GET_CODE (addr
))
1668 return speed
|| satisfies_constraint_Rcq (addr
) ? 0 : 1;
1669 case PRE_INC
: case PRE_DEC
: case POST_INC
: case POST_DEC
:
1670 case PRE_MODIFY
: case POST_MODIFY
:
1676 /* Most likely needs a LIMM. */
1677 return COSTS_N_INSNS (1);
1681 register rtx plus0
= XEXP (addr
, 0);
1682 register rtx plus1
= XEXP (addr
, 1);
1684 if (GET_CODE (plus0
) != REG
1685 && (GET_CODE (plus0
) != MULT
1686 || !CONST_INT_P (XEXP (plus0
, 1))
1687 || (INTVAL (XEXP (plus0
, 1)) != 2
1688 && INTVAL (XEXP (plus0
, 1)) != 4)))
1691 switch (GET_CODE (plus1
))
1694 return (!RTX_OK_FOR_OFFSET_P (SImode
, plus1
)
1698 : (satisfies_constraint_Rcq (plus0
)
1699 && satisfies_constraint_O (plus1
))
1703 return (speed
< 1 ? 0
1704 : (satisfies_constraint_Rcq (plus0
)
1705 && satisfies_constraint_Rcq (plus1
))
1710 return COSTS_N_INSNS (1);
1723 /* Emit instruction X with the frame related bit set. */
1729 RTX_FRAME_RELATED_P (x
) = 1;
1733 /* Emit a frame insn to move SRC to DST. */
1736 frame_move (rtx dst
, rtx src
)
1738 return frame_insn (gen_rtx_SET (VOIDmode
, dst
, src
));
1741 /* Like frame_move, but add a REG_INC note for REG if ADDR contains an
1742 auto increment address, or is zero. */
1745 frame_move_inc (rtx dst
, rtx src
, rtx reg
, rtx addr
)
1747 rtx insn
= frame_move (dst
, src
);
1750 || GET_CODE (addr
) == PRE_DEC
|| GET_CODE (addr
) == POST_INC
1751 || GET_CODE (addr
) == PRE_MODIFY
|| GET_CODE (addr
) == POST_MODIFY
)
1752 add_reg_note (insn
, REG_INC
, reg
);
1756 /* Emit a frame insn which adjusts a frame address register REG by OFFSET. */
1759 frame_add (rtx reg
, HOST_WIDE_INT offset
)
1761 gcc_assert ((offset
& 0x3) == 0);
1764 return frame_move (reg
, plus_constant (Pmode
, reg
, offset
));
1767 /* Emit a frame insn which adjusts stack pointer by OFFSET. */
1770 frame_stack_add (HOST_WIDE_INT offset
)
1772 return frame_add (stack_pointer_rtx
, offset
);
1775 /* Traditionally, we push saved registers first in the prologue,
1776 then we allocate the rest of the frame - and reverse in the epilogue.
1777 This has still its merits for ease of debugging, or saving code size
1778 or even execution time if the stack frame is so large that some accesses
1779 can't be encoded anymore with offsets in the instruction code when using
1781 Also, it would be a good starting point if we got instructions to help
1782 with register save/restore.
1784 However, often stack frames are small, and the pushing / popping has
1786 - the stack modification prevents a lot of scheduling.
1787 - frame allocation / deallocation needs extra instructions.
1788 - unless we know that we compile ARC700 user code, we need to put
1789 a memory barrier after frame allocation / before deallocation to
1790 prevent interrupts clobbering our data in the frame.
1791 In particular, we don't have any such guarantees for library functions,
1792 which tend to, on the other hand, to have small frames.
1794 Thus, for small frames, we'd like to use a different scheme:
1795 - The frame is allocated in full with the first prologue instruction,
1796 and deallocated in full with the last epilogue instruction.
1797 Thus, the instructions in-betwen can be freely scheduled.
1798 - If the function has no outgoing arguments on the stack, we can allocate
1799 one register save slot at the top of the stack. This register can then
1800 be saved simultanously with frame allocation, and restored with
1802 This register can be picked depending on scheduling considerations,
1803 although same though should go into having some set of registers
1804 to be potentially lingering after a call, and others to be available
1805 immediately - i.e. in the absence of interprocedual optimization, we
1806 can use an ABI-like convention for register allocation to reduce
1807 stalls after function return. */
1808 /* Function prologue/epilogue handlers. */
1810 /* ARCompact stack frames look like:
1812 Before call After call
1813 high +-----------------------+ +-----------------------+
1814 mem | reg parm save area | | reg parm save area |
1815 | only created for | | only created for |
1816 | variable arg fns | | variable arg fns |
1817 AP +-----------------------+ +-----------------------+
1818 | return addr register | | return addr register |
1819 | (if required) | | (if required) |
1820 +-----------------------+ +-----------------------+
1822 | reg save area | | reg save area |
1824 +-----------------------+ +-----------------------+
1825 | frame pointer | | frame pointer |
1826 | (if required) | | (if required) |
1827 FP +-----------------------+ +-----------------------+
1829 | local/temp variables | | local/temp variables |
1831 +-----------------------+ +-----------------------+
1833 | arguments on stack | | arguments on stack |
1835 SP +-----------------------+ +-----------------------+
1836 | reg parm save area |
1837 | only created for |
1838 | variable arg fns |
1839 AP +-----------------------+
1840 | return addr register |
1842 +-----------------------+
1846 +-----------------------+
1849 FP +-----------------------+
1851 | local/temp variables |
1853 +-----------------------+
1855 | arguments on stack |
1857 mem SP +-----------------------+
1860 1) The "reg parm save area" does not exist for non variable argument fns.
1861 The "reg parm save area" can be eliminated completely if we created our
1862 own va-arc.h, but that has tradeoffs as well (so it's not done). */
1864 /* Structure to be filled in by arc_compute_frame_size with register
1865 save masks, and offsets for the current function. */
1866 struct GTY (()) arc_frame_info
1868 unsigned int total_size
; /* # bytes that the entire frame takes up. */
1869 unsigned int extra_size
; /* # bytes of extra stuff. */
1870 unsigned int pretend_size
; /* # bytes we push and pretend caller did. */
1871 unsigned int args_size
; /* # bytes that outgoing arguments take up. */
1872 unsigned int reg_size
; /* # bytes needed to store regs. */
1873 unsigned int var_size
; /* # bytes that variables take up. */
1874 unsigned int reg_offset
; /* Offset from new sp to store regs. */
1875 unsigned int gmask
; /* Mask of saved gp registers. */
1876 int initialized
; /* Nonzero if frame size already calculated. */
1877 short millicode_start_reg
;
1878 short millicode_end_reg
;
1879 bool save_return_addr
;
1882 /* Defining data structures for per-function information. */
1884 typedef struct GTY (()) machine_function
1886 enum arc_function_type fn_type
;
1887 struct arc_frame_info frame_info
;
1888 /* To keep track of unalignment caused by short insns. */
1890 int force_short_suffix
; /* Used when disgorging return delay slot insns. */
1891 const char *size_reason
;
1892 struct arc_ccfsm ccfsm_current
;
1893 /* Map from uid to ccfsm state during branch shortening. */
1894 rtx ccfsm_current_insn
;
1895 char arc_reorg_started
;
1896 char prescan_initialized
;
1899 /* Type of function DECL.
1901 The result is cached. To reset the cache at the end of a function,
1902 call with DECL = NULL_TREE. */
1904 enum arc_function_type
1905 arc_compute_function_type (struct function
*fun
)
1907 tree decl
= fun
->decl
;
1909 enum arc_function_type fn_type
= fun
->machine
->fn_type
;
1911 if (fn_type
!= ARC_FUNCTION_UNKNOWN
)
1914 /* Assume we have a normal function (not an interrupt handler). */
1915 fn_type
= ARC_FUNCTION_NORMAL
;
1917 /* Now see if this is an interrupt handler. */
1918 for (a
= DECL_ATTRIBUTES (decl
);
1922 tree name
= TREE_PURPOSE (a
), args
= TREE_VALUE (a
);
1924 if (name
== get_identifier ("interrupt")
1925 && list_length (args
) == 1
1926 && TREE_CODE (TREE_VALUE (args
)) == STRING_CST
)
1928 tree value
= TREE_VALUE (args
);
1930 if (!strcmp (TREE_STRING_POINTER (value
), "ilink1"))
1931 fn_type
= ARC_FUNCTION_ILINK1
;
1932 else if (!strcmp (TREE_STRING_POINTER (value
), "ilink2"))
1933 fn_type
= ARC_FUNCTION_ILINK2
;
1940 return fun
->machine
->fn_type
= fn_type
;
1943 #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
1944 #define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM))
1946 /* Tell prologue and epilogue if register REGNO should be saved / restored.
1947 The return address and frame pointer are treated separately.
1948 Don't consider them here.
1949 Addition for pic: The gp register needs to be saved if the current
1950 function changes it to access gotoff variables.
1951 FIXME: This will not be needed if we used some arbitrary register
1954 #define MUST_SAVE_REGISTER(regno, interrupt_p) \
1955 (((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \
1956 && (df_regs_ever_live_p (regno) && (!call_used_regs[regno] || interrupt_p))) \
1957 || (flag_pic && crtl->uses_pic_offset_table \
1958 && regno == PIC_OFFSET_TABLE_REGNUM) )
1960 #define MUST_SAVE_RETURN_ADDR \
1961 (cfun->machine->frame_info.save_return_addr)
1963 /* Return non-zero if there are registers to be saved or loaded using
1964 millicode thunks. We can only use consecutive sequences starting
1965 with r13, and not going beyond r25.
1966 GMASK is a bitmask of registers to save. This function sets
1967 FRAME->millicod_start_reg .. FRAME->millicode_end_reg to the range
1968 of registers to be saved / restored with a millicode call. */
1971 arc_compute_millicode_save_restore_regs (unsigned int gmask
,
1972 struct arc_frame_info
*frame
)
1976 int start_reg
= 13, end_reg
= 25;
1978 for (regno
= start_reg
; regno
<= end_reg
&& (gmask
& (1L << regno
));)
1980 end_reg
= regno
- 1;
1981 /* There is no point in using millicode thunks if we don't save/restore
1982 at least three registers. For non-leaf functions we also have the
1984 if (regno
- start_reg
>= 3 - (crtl
->is_leaf
== 0))
1986 frame
->millicode_start_reg
= 13;
1987 frame
->millicode_end_reg
= regno
- 1;
1993 /* Return the bytes needed to compute the frame pointer from the current
1996 SIZE is the size needed for local variables. */
1999 arc_compute_frame_size (int size
) /* size = # of var. bytes allocated. */
2002 unsigned int total_size
, var_size
, args_size
, pretend_size
, extra_size
;
2003 unsigned int reg_size
, reg_offset
;
2005 enum arc_function_type fn_type
;
2007 struct arc_frame_info
*frame_info
= &cfun
->machine
->frame_info
;
2009 size
= ARC_STACK_ALIGN (size
);
2011 /* 1) Size of locals and temporaries */
2014 /* 2) Size of outgoing arguments */
2015 args_size
= crtl
->outgoing_args_size
;
2017 /* 3) Calculate space needed for saved registers.
2018 ??? We ignore the extension registers for now. */
2020 /* See if this is an interrupt handler. Call used registers must be saved
2025 fn_type
= arc_compute_function_type (cfun
);
2026 interrupt_p
= ARC_INTERRUPT_P (fn_type
);
2028 for (regno
= 0; regno
<= 31; regno
++)
2030 if (MUST_SAVE_REGISTER (regno
, interrupt_p
))
2032 reg_size
+= UNITS_PER_WORD
;
2033 gmask
|= 1 << regno
;
2037 /* 4) Space for back trace data structure.
2038 <return addr reg size> (if required) + <fp size> (if required). */
2039 frame_info
->save_return_addr
2040 = (!crtl
->is_leaf
|| df_regs_ever_live_p (RETURN_ADDR_REGNUM
));
2041 /* Saving blink reg in case of leaf function for millicode thunk calls. */
2042 if (optimize_size
&& !TARGET_NO_MILLICODE_THUNK_SET
)
2044 if (arc_compute_millicode_save_restore_regs (gmask
, frame_info
))
2045 frame_info
->save_return_addr
= true;
2049 if (MUST_SAVE_RETURN_ADDR
)
2051 if (frame_pointer_needed
)
2054 /* 5) Space for variable arguments passed in registers */
2055 pretend_size
= crtl
->args
.pretend_args_size
;
2057 /* Ensure everything before the locals is aligned appropriately. */
2059 unsigned int extra_plus_reg_size
;
2060 unsigned int extra_plus_reg_size_aligned
;
2062 extra_plus_reg_size
= extra_size
+ reg_size
;
2063 extra_plus_reg_size_aligned
= ARC_STACK_ALIGN(extra_plus_reg_size
);
2064 reg_size
= extra_plus_reg_size_aligned
- extra_size
;
2067 /* Compute total frame size. */
2068 total_size
= var_size
+ args_size
+ extra_size
+ pretend_size
+ reg_size
;
2070 total_size
= ARC_STACK_ALIGN (total_size
);
2072 /* Compute offset of register save area from stack pointer:
2073 A5 Frame: pretend_size <blink> reg_size <fp> var_size args_size <--sp
2075 reg_offset
= (total_size
- (pretend_size
+ reg_size
+ extra_size
)
2076 + (frame_pointer_needed
? 4 : 0));
2078 /* Save computed information. */
2079 frame_info
->total_size
= total_size
;
2080 frame_info
->extra_size
= extra_size
;
2081 frame_info
->pretend_size
= pretend_size
;
2082 frame_info
->var_size
= var_size
;
2083 frame_info
->args_size
= args_size
;
2084 frame_info
->reg_size
= reg_size
;
2085 frame_info
->reg_offset
= reg_offset
;
2086 frame_info
->gmask
= gmask
;
2087 frame_info
->initialized
= reload_completed
;
2089 /* Ok, we're done. */
2093 /* Common code to save/restore registers. */
2094 /* BASE_REG is the base register to use for addressing and to adjust.
2095 GMASK is a bitmask of general purpose registers to save/restore.
2096 epilogue_p 0: prologue 1:epilogue 2:epilogue, sibling thunk
2097 If *FIRST_OFFSET is non-zero, add it first to BASE_REG - preferably
2098 using a pre-modify for the first memory access. *FIRST_OFFSET is then
2102 arc_save_restore (rtx base_reg
,
2103 unsigned int gmask
, int epilogue_p
, int *first_offset
)
2105 unsigned int offset
= 0;
2107 struct arc_frame_info
*frame
= &cfun
->machine
->frame_info
;
2108 rtx sibthunk_insn
= NULL_RTX
;
2112 /* Millicode thunks implementation:
2113 Generates calls to millicodes for registers starting from r13 to r25
2114 Present Limitations:
2115 - Only one range supported. The remaining regs will have the ordinary
2116 st and ld instructions for store and loads. Hence a gmask asking
2117 to store r13-14, r16-r25 will only generate calls to store and
2118 load r13 to r14 while store and load insns will be generated for
2119 r16 to r25 in the prologue and epilogue respectively.
2121 - Presently library only supports register ranges starting from r13.
2123 if (epilogue_p
== 2 || frame
->millicode_end_reg
> 14)
2125 int start_call
= frame
->millicode_start_reg
;
2126 int end_call
= frame
->millicode_end_reg
;
2127 int n_regs
= end_call
- start_call
+ 1;
2128 int i
= 0, r
, off
= 0;
2130 rtx ret_addr
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
2134 /* "reg_size" won't be more than 127 . */
2135 gcc_assert (epilogue_p
|| abs (*first_offset
) <= 127);
2136 frame_add (base_reg
, *first_offset
);
2139 insn
= gen_rtx_PARALLEL
2140 (VOIDmode
, rtvec_alloc ((epilogue_p
== 2) + n_regs
+ 1));
2141 if (epilogue_p
== 2)
2144 XVECEXP (insn
, 0, n_regs
) = gen_rtx_CLOBBER (VOIDmode
, ret_addr
);
2145 for (r
= start_call
; r
<= end_call
; r
++, off
+= UNITS_PER_WORD
, i
++)
2147 rtx reg
= gen_rtx_REG (SImode
, r
);
2149 = gen_frame_mem (SImode
, plus_constant (Pmode
, base_reg
, off
));
2152 XVECEXP (insn
, 0, i
) = gen_rtx_SET (VOIDmode
, reg
, mem
);
2154 XVECEXP (insn
, 0, i
) = gen_rtx_SET (VOIDmode
, mem
, reg
);
2155 gmask
= gmask
& ~(1L << r
);
2157 if (epilogue_p
== 2)
2158 sibthunk_insn
= insn
;
2164 for (regno
= 0; regno
<= 31; regno
++)
2166 if ((gmask
& (1L << regno
)) != 0)
2168 rtx reg
= gen_rtx_REG (SImode
, regno
);
2173 gcc_assert (!offset
);
2174 addr
= plus_constant (Pmode
, base_reg
, *first_offset
);
2175 addr
= gen_rtx_PRE_MODIFY (Pmode
, base_reg
, addr
);
2180 gcc_assert (SMALL_INT (offset
));
2181 addr
= plus_constant (Pmode
, base_reg
, offset
);
2183 mem
= gen_frame_mem (SImode
, addr
);
2185 frame_move_inc (reg
, mem
, base_reg
, addr
);
2187 frame_move_inc (mem
, reg
, base_reg
, addr
);
2188 offset
+= UNITS_PER_WORD
;
2194 rtx r12
= gen_rtx_REG (Pmode
, 12);
2196 frame_insn (gen_rtx_SET (VOIDmode
, r12
, GEN_INT (offset
)));
2197 XVECEXP (sibthunk_insn
, 0, 0) = ret_rtx
;
2198 XVECEXP (sibthunk_insn
, 0, 1)
2199 = gen_rtx_SET (VOIDmode
, stack_pointer_rtx
,
2200 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
, r12
));
2201 sibthunk_insn
= emit_jump_insn (sibthunk_insn
);
2202 RTX_FRAME_RELATED_P (sibthunk_insn
) = 1;
2204 } /* arc_save_restore */
2207 int arc_return_address_regs
[4]
2208 = {0, RETURN_ADDR_REGNUM
, ILINK1_REGNUM
, ILINK2_REGNUM
};
2210 /* Set up the stack and frame pointer (if desired) for the function. */
2213 arc_expand_prologue (void)
2215 int size
= get_frame_size ();
2216 unsigned int gmask
= cfun
->machine
->frame_info
.gmask
;
2217 /* unsigned int frame_pointer_offset;*/
2218 unsigned int frame_size_to_allocate
;
2219 /* (FIXME: The first store will use a PRE_MODIFY; this will usually be r13.
2220 Change the stack layout so that we rather store a high register with the
2221 PRE_MODIFY, thus enabling more short insn generation.) */
2222 int first_offset
= 0;
2224 size
= ARC_STACK_ALIGN (size
);
2226 /* Compute/get total frame size. */
2227 size
= (!cfun
->machine
->frame_info
.initialized
2228 ? arc_compute_frame_size (size
)
2229 : cfun
->machine
->frame_info
.total_size
);
2231 if (flag_stack_usage_info
)
2232 current_function_static_stack_size
= size
;
2234 /* Keep track of frame size to be allocated. */
2235 frame_size_to_allocate
= size
;
2237 /* These cases shouldn't happen. Catch them now. */
2238 gcc_assert (!(size
== 0 && gmask
));
2240 /* Allocate space for register arguments if this is a variadic function. */
2241 if (cfun
->machine
->frame_info
.pretend_size
!= 0)
2243 /* Ensure pretend_size is maximum of 8 * word_size. */
2244 gcc_assert (cfun
->machine
->frame_info
.pretend_size
<= 32);
2246 frame_stack_add (-(HOST_WIDE_INT
)cfun
->machine
->frame_info
.pretend_size
);
2247 frame_size_to_allocate
-= cfun
->machine
->frame_info
.pretend_size
;
2250 /* The home-grown ABI says link register is saved first. */
2251 if (MUST_SAVE_RETURN_ADDR
)
2253 rtx ra
= gen_rtx_REG (SImode
, RETURN_ADDR_REGNUM
);
2254 rtx mem
= gen_frame_mem (Pmode
, gen_rtx_PRE_DEC (Pmode
, stack_pointer_rtx
));
2256 frame_move_inc (mem
, ra
, stack_pointer_rtx
, 0);
2257 frame_size_to_allocate
-= UNITS_PER_WORD
;
2259 } /* MUST_SAVE_RETURN_ADDR */
2261 /* Save any needed call-saved regs (and call-used if this is an
2262 interrupt handler) for ARCompact ISA. */
2263 if (cfun
->machine
->frame_info
.reg_size
)
2265 first_offset
= -cfun
->machine
->frame_info
.reg_size
;
2266 /* N.B. FRAME_POINTER_MASK and RETURN_ADDR_MASK are cleared in gmask. */
2267 arc_save_restore (stack_pointer_rtx
, gmask
, 0, &first_offset
);
2268 frame_size_to_allocate
-= cfun
->machine
->frame_info
.reg_size
;
2272 /* Save frame pointer if needed. */
2273 if (frame_pointer_needed
)
2275 rtx addr
= gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
2276 GEN_INT (-UNITS_PER_WORD
+ first_offset
));
2277 rtx mem
= gen_frame_mem (Pmode
, gen_rtx_PRE_MODIFY (Pmode
,
2280 frame_move_inc (mem
, frame_pointer_rtx
, stack_pointer_rtx
, 0);
2281 frame_size_to_allocate
-= UNITS_PER_WORD
;
2283 frame_move (frame_pointer_rtx
, stack_pointer_rtx
);
2286 /* ??? We don't handle the case where the saved regs are more than 252
2287 bytes away from sp. This can be handled by decrementing sp once, saving
2288 the regs, and then decrementing it again. The epilogue doesn't have this
2289 problem as the `ld' insn takes reg+limm values (though it would be more
2290 efficient to avoid reg+limm). */
2292 frame_size_to_allocate
-= first_offset
;
2293 /* Allocate the stack frame. */
2294 if (frame_size_to_allocate
> 0)
2295 frame_stack_add ((HOST_WIDE_INT
) 0 - frame_size_to_allocate
);
2297 /* Setup the gp register, if needed. */
2298 if (crtl
->uses_pic_offset_table
)
2299 arc_finalize_pic ();
2302 /* Do any necessary cleanup after a function to restore stack, frame,
2306 arc_expand_epilogue (int sibcall_p
)
2308 int size
= get_frame_size ();
2309 enum arc_function_type fn_type
= arc_compute_function_type (cfun
);
2311 size
= ARC_STACK_ALIGN (size
);
2312 size
= (!cfun
->machine
->frame_info
.initialized
2313 ? arc_compute_frame_size (size
)
2314 : cfun
->machine
->frame_info
.total_size
);
2316 unsigned int pretend_size
= cfun
->machine
->frame_info
.pretend_size
;
2317 unsigned int frame_size
;
2318 unsigned int size_to_deallocate
;
2320 int can_trust_sp_p
= !cfun
->calls_alloca
;
2321 int first_offset
= 0;
2322 int millicode_p
= cfun
->machine
->frame_info
.millicode_end_reg
> 0;
2324 size_to_deallocate
= size
;
2326 frame_size
= size
- (pretend_size
+
2327 cfun
->machine
->frame_info
.reg_size
+
2328 cfun
->machine
->frame_info
.extra_size
);
2330 /* ??? There are lots of optimizations that can be done here.
2331 EG: Use fp to restore regs if it's closer.
2332 Maybe in time we'll do them all. For now, always restore regs from
2333 sp, but don't restore sp if we don't have to. */
2335 if (!can_trust_sp_p
)
2336 gcc_assert (frame_pointer_needed
);
2338 /* Restore stack pointer to the beginning of saved register area for
2342 if (frame_pointer_needed
)
2343 frame_move (stack_pointer_rtx
, frame_pointer_rtx
);
2345 first_offset
= frame_size
;
2346 size_to_deallocate
-= frame_size
;
2348 else if (!can_trust_sp_p
)
2349 frame_stack_add (-frame_size
);
2352 /* Restore any saved registers. */
2353 if (frame_pointer_needed
)
2355 rtx addr
= gen_rtx_POST_INC (Pmode
, stack_pointer_rtx
);
2357 frame_move_inc (frame_pointer_rtx
, gen_frame_mem (Pmode
, addr
),
2358 stack_pointer_rtx
, 0);
2359 size_to_deallocate
-= UNITS_PER_WORD
;
2362 /* Load blink after the calls to thunk calls in case of optimize size. */
2365 int sibthunk_p
= (!sibcall_p
2366 && fn_type
== ARC_FUNCTION_NORMAL
2367 && !cfun
->machine
->frame_info
.pretend_size
);
2369 gcc_assert (!(cfun
->machine
->frame_info
.gmask
2370 & (FRAME_POINTER_MASK
| RETURN_ADDR_MASK
)));
2371 arc_save_restore (stack_pointer_rtx
,
2372 cfun
->machine
->frame_info
.gmask
,
2373 1 + sibthunk_p
, &first_offset
);
2377 /* If we are to restore registers, and first_offset would require
2378 a limm to be encoded in a PRE_MODIFY, yet we can add it with a
2379 fast add to the stack pointer, do this now. */
2380 if ((!SMALL_INT (first_offset
)
2381 && cfun
->machine
->frame_info
.gmask
2382 && ((TARGET_ARC700
&& !optimize_size
)
2383 ? first_offset
<= 0x800
2384 : satisfies_constraint_C2a (GEN_INT (first_offset
))))
2385 /* Also do this if we have both gprs and return
2386 address to restore, and they both would need a LIMM. */
2387 || (MUST_SAVE_RETURN_ADDR
2388 && !SMALL_INT ((cfun
->machine
->frame_info
.reg_size
+ first_offset
) >> 2)
2389 && cfun
->machine
->frame_info
.gmask
))
2391 frame_stack_add (first_offset
);
2394 if (MUST_SAVE_RETURN_ADDR
)
2396 rtx ra
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
2397 int ra_offs
= cfun
->machine
->frame_info
.reg_size
+ first_offset
;
2398 rtx addr
= plus_constant (Pmode
, stack_pointer_rtx
, ra_offs
);
2400 /* If the load of blink would need a LIMM, but we can add
2401 the offset quickly to sp, do the latter. */
2402 if (!SMALL_INT (ra_offs
>> 2)
2403 && !cfun
->machine
->frame_info
.gmask
2404 && ((TARGET_ARC700
&& !optimize_size
)
2406 : satisfies_constraint_C2a (GEN_INT (ra_offs
))))
2408 size_to_deallocate
-= ra_offs
- first_offset
;
2410 frame_stack_add (ra_offs
);
2412 addr
= stack_pointer_rtx
;
2414 /* See if we can combine the load of the return address with the
2415 final stack adjustment.
2416 We need a separate load if there are still registers to
2417 restore. We also want a separate load if the combined insn
2418 would need a limm, but a separate load doesn't. */
2420 && !cfun
->machine
->frame_info
.gmask
2421 && (SMALL_INT (ra_offs
) || !SMALL_INT (ra_offs
>> 2)))
2423 addr
= gen_rtx_PRE_MODIFY (Pmode
, stack_pointer_rtx
, addr
);
2425 size_to_deallocate
-= cfun
->machine
->frame_info
.reg_size
;
2427 else if (!ra_offs
&& size_to_deallocate
== UNITS_PER_WORD
)
2429 addr
= gen_rtx_POST_INC (Pmode
, addr
);
2430 size_to_deallocate
= 0;
2432 frame_move_inc (ra
, gen_frame_mem (Pmode
, addr
), stack_pointer_rtx
, addr
);
2437 if (cfun
->machine
->frame_info
.reg_size
)
2438 arc_save_restore (stack_pointer_rtx
,
2439 /* The zeroing of these two bits is unnecessary, but leave this in for clarity. */
2440 cfun
->machine
->frame_info
.gmask
2441 & ~(FRAME_POINTER_MASK
| RETURN_ADDR_MASK
), 1, &first_offset
);
2445 /* The rest of this function does the following:
2446 ARCompact : handle epilogue_delay, restore sp (phase-2), return
2449 /* Keep track of how much of the stack pointer we've restored.
2450 It makes the following a lot more readable. */
2451 size_to_deallocate
+= first_offset
;
2452 restored
= size
- size_to_deallocate
;
2454 if (size
> restored
)
2455 frame_stack_add (size
- restored
);
2456 /* Emit the return instruction. */
2457 if (sibcall_p
== FALSE
)
2458 emit_jump_insn (gen_simple_return ());
2460 if (!TARGET_EPILOGUE_CFI
)
2464 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
2465 RTX_FRAME_RELATED_P (insn
) = 0;
2469 /* Return the offset relative to the stack pointer where the return address
2470 is stored, or -1 if it is not stored. */
2473 arc_return_slot_offset ()
2475 struct arc_frame_info
*afi
= &cfun
->machine
->frame_info
;
2477 return (afi
->save_return_addr
2478 ? afi
->total_size
- afi
->pretend_size
- afi
->extra_size
: -1);
2483 /* Emit special PIC prologues and epilogues. */
2484 /* If the function has any GOTOFF relocations, then the GOTBASE
2485 register has to be setup in the prologue
2486 The instruction needed at the function start for setting up the
2489 ----------------------------------------------------------
2490 The rtl to be emitted for this should be:
2493 (const (unspec (symref _DYNAMIC) 3)))
2494 ---------------------------------------------------------- */
2497 arc_finalize_pic (void)
2500 rtx baseptr_rtx
= gen_rtx_REG (Pmode
, PIC_OFFSET_TABLE_REGNUM
);
2502 if (crtl
->uses_pic_offset_table
== 0)
2505 gcc_assert (flag_pic
!= 0);
2507 pat
= gen_rtx_SYMBOL_REF (Pmode
, "_DYNAMIC");
2508 pat
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, pat
), ARC_UNSPEC_GOT
);
2509 pat
= gen_rtx_CONST (Pmode
, pat
);
2511 pat
= gen_rtx_SET (VOIDmode
, baseptr_rtx
, pat
);
2516 /* !TARGET_BARREL_SHIFTER support. */
2517 /* Emit a shift insn to set OP0 to OP1 shifted by OP2; CODE specifies what
2521 emit_shift (enum rtx_code code
, rtx op0
, rtx op1
, rtx op2
)
2523 rtx shift
= gen_rtx_fmt_ee (code
, SImode
, op1
, op2
);
2525 = ((shift4_operator (shift
, SImode
) ? gen_shift_si3
: gen_shift_si3_loop
)
2526 (op0
, op1
, op2
, shift
));
2530 /* Output the assembler code for doing a shift.
2531 We go to a bit of trouble to generate efficient code as the ARC601 only has
2532 single bit shifts. This is taken from the h8300 port. We only have one
2533 mode of shifting and can't access individual bytes like the h8300 can, so
2534 this is greatly simplified (at the expense of not generating hyper-
2537 This function is not used if the variable shift insns are present. */
2539 /* FIXME: This probably can be done using a define_split in arc.md.
2540 Alternately, generate rtx rather than output instructions. */
2543 output_shift (rtx
*operands
)
2545 /* static int loopend_lab;*/
2546 rtx shift
= operands
[3];
2547 enum machine_mode mode
= GET_MODE (shift
);
2548 enum rtx_code code
= GET_CODE (shift
);
2549 const char *shift_one
;
2551 gcc_assert (mode
== SImode
);
2555 case ASHIFT
: shift_one
= "add %0,%1,%1"; break;
2556 case ASHIFTRT
: shift_one
= "asr %0,%1"; break;
2557 case LSHIFTRT
: shift_one
= "lsr %0,%1"; break;
2558 default: gcc_unreachable ();
2561 if (GET_CODE (operands
[2]) != CONST_INT
)
2563 output_asm_insn ("and.f lp_count,%2, 0x1f", operands
);
2570 n
= INTVAL (operands
[2]);
2572 /* Only consider the lower 5 bits of the shift count. */
2575 /* First see if we can do them inline. */
2576 /* ??? We could get better scheduling & shorter code (using short insns)
2577 by using splitters. Alas, that'd be even more verbose. */
2578 if (code
== ASHIFT
&& n
<= 9 && n
> 2
2579 && dest_reg_operand (operands
[4], SImode
))
2581 output_asm_insn ("mov %4,0\n\tadd3 %0,%4,%1", operands
);
2582 for (n
-=3 ; n
>= 3; n
-= 3)
2583 output_asm_insn ("add3 %0,%4,%0", operands
);
2585 output_asm_insn ("add2 %0,%4,%0", operands
);
2587 output_asm_insn ("add %0,%0,%0", operands
);
2593 output_asm_insn (shift_one
, operands
);
2594 operands
[1] = operands
[0];
2597 /* See if we can use a rotate/and. */
2598 else if (n
== BITS_PER_WORD
- 1)
2603 output_asm_insn ("and %0,%1,1\n\tror %0,%0", operands
);
2606 /* The ARC doesn't have a rol insn. Use something else. */
2607 output_asm_insn ("add.f 0,%1,%1\n\tsbc %0,%0,%0", operands
);
2610 /* The ARC doesn't have a rol insn. Use something else. */
2611 output_asm_insn ("add.f 0,%1,%1\n\trlc %0,0", operands
);
2617 else if (n
== BITS_PER_WORD
- 2 && dest_reg_operand (operands
[4], SImode
))
2622 output_asm_insn ("and %0,%1,3\n\tror %0,%0\n\tror %0,%0", operands
);
2625 #if 1 /* Need some scheduling comparisons. */
2626 output_asm_insn ("add.f %4,%1,%1\n\tsbc %0,%0,%0\n\t"
2627 "add.f 0,%4,%4\n\trlc %0,%0", operands
);
2629 output_asm_insn ("add.f %4,%1,%1\n\tbxor %0,%4,31\n\t"
2630 "sbc.f %0,%0,%4\n\trlc %0,%0", operands
);
2635 output_asm_insn ("add.f %4,%1,%1\n\trlc %0,0\n\t"
2636 "add.f 0,%4,%4\n\trlc %0,%0", operands
);
2638 output_asm_insn ("add.f %0,%1,%1\n\trlc.f %0,0\n\t"
2639 "and %0,%0,1\n\trlc %0,%0", operands
);
2646 else if (n
== BITS_PER_WORD
- 3 && code
== ASHIFT
)
2647 output_asm_insn ("and %0,%1,7\n\tror %0,%0\n\tror %0,%0\n\tror %0,%0",
2652 operands
[2] = GEN_INT (n
);
2653 output_asm_insn ("mov.f lp_count, %2", operands
);
2657 output_asm_insn ("lpnz\t2f", operands
);
2658 output_asm_insn (shift_one
, operands
);
2659 output_asm_insn ("nop", operands
);
2660 fprintf (asm_out_file
, "2:\t%s end single insn loop\n",
2669 /* Nested function support. */
2671 /* Directly store VALUE into memory object BLOCK at OFFSET. */
2674 emit_store_direct (rtx block
, int offset
, int value
)
2676 emit_insn (gen_store_direct (adjust_address (block
, SImode
, offset
),
2678 gen_int_mode (value
, SImode
))));
2681 /* Emit RTL insns to initialize the variable parts of a trampoline.
2682 FNADDR is an RTX for the address of the function's pure code.
2683 CXT is an RTX for the static chain value for the function. */
2684 /* With potentially multiple shared objects loaded, and multiple stacks
2685 present for multiple thereds where trampolines might reside, a simple
2686 range check will likely not suffice for the profiler to tell if a callee
2687 is a trampoline. We a speedier check by making the trampoline start at
2688 an address that is not 4-byte aligned.
2689 A trampoline looks like this:
2693 ld_s r12,[pcl,12] 0xd403
2694 ld r11,[pcl,12] 0x170c 700b
2698 The fastest trampoline to execute for trampolines within +-8KB of CTX
2701 j [limm] 0x20200f80 limm
2702 and that would also be faster to write to the stack by computing the offset
2703 from CTX to TRAMP at compile time. However, it would really be better to
2704 get rid of the high cost of cache invalidation when generating trampolines,
2705 which requires that the code part of trampolines stays constant, and
2707 - making sure that no executable code but trampolines is on the stack,
2708 no icache entries linger for the area of the stack from when before the
2709 stack was allocated, and allocating trampolines in trampoline-only
2712 - allocate trampolines fram a special pool of pre-allocated trampolines. */
2715 arc_initialize_trampoline (rtx tramp
, tree fndecl
, rtx cxt
)
2717 rtx fnaddr
= XEXP (DECL_RTL (fndecl
), 0);
2719 emit_store_direct (tramp
, 0, TARGET_BIG_ENDIAN
? 0x78e0d403 : 0xd40378e0);
2720 emit_store_direct (tramp
, 4, TARGET_BIG_ENDIAN
? 0x170c700b : 0x700b170c);
2721 emit_store_direct (tramp
, 8, TARGET_BIG_ENDIAN
? 0x7c0078e0 : 0x78e07c00);
2722 emit_move_insn (adjust_address (tramp
, SImode
, 12), fnaddr
);
2723 emit_move_insn (adjust_address (tramp
, SImode
, 16), cxt
);
2724 emit_insn (gen_flush_icache (adjust_address (tramp
, SImode
, 0)));
2727 /* Allow the profiler to easily distinguish trampolines from normal
2731 arc_trampoline_adjust_address (rtx addr
)
2733 return plus_constant (Pmode
, addr
, 2);
2736 /* This is set briefly to 1 when we output a ".as" address modifer, and then
2737 reset when we output the scaled address. */
2738 static int output_scaled
= 0;
2740 /* Print operand X (an rtx) in assembler syntax to file FILE.
2741 CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
2742 For `%' followed by punctuation, CODE is the punctuation and X is null. */
2743 /* In final.c:output_asm_insn:
2746 'c' : constant address if CONSTANT_ADDRESS_P
2752 '#': condbranch delay slot suffix
2753 '*': jump delay slot suffix
2754 '?' : nonjump-insn suffix for conditional execution or short instruction
2755 '!' : jump / call suffix for conditional execution or short instruction
2756 '`': fold constant inside unary o-perator, re-recognize, and emit.
2761 'B': Branch comparison operand - suppress sda reference
2762 'H': Most significant word
2763 'L': Least significant word
2764 'A': ASCII decimal representation of floating point value
2765 'U': Load/store update or scaling indicator
2766 'V': cache bypass indicator for volatile
2771 'o': original symbol - no @ prepending. */
2774 arc_print_operand (FILE *file
, rtx x
, int code
)
2779 if (GET_CODE (x
) == CONST_INT
)
2780 fprintf (file
, "%d",exact_log2(INTVAL (x
) + 1) - 1 );
2782 output_operand_lossage ("invalid operand to %%Z code");
2787 if (GET_CODE (x
) == CONST_INT
)
2788 fprintf (file
, "%d",exact_log2(INTVAL (x
)) );
2790 output_operand_lossage ("invalid operand to %%z code");
2795 if (GET_CODE (x
) == CONST_INT
)
2796 fprintf (file
, "%d",exact_log2(~INTVAL (x
)) );
2798 output_operand_lossage ("invalid operand to %%M code");
2803 /* Conditional branches depending on condition codes.
2804 Note that this is only for branches that were known to depend on
2805 condition codes before delay slot scheduling;
2806 out-of-range brcc / bbit expansions should use '*'.
2807 This distinction is important because of the different
2808 allowable delay slot insns and the output of the delay suffix
2809 for TARGET_AT_DBR_COND_EXEC. */
2811 /* Unconditional branches / branches not depending on condition codes.
2812 This could also be a CALL_INSN.
2813 Output the appropriate delay slot suffix. */
2814 if (final_sequence
&& XVECLEN (final_sequence
, 0) != 1)
2816 rtx jump
= XVECEXP (final_sequence
, 0, 0);
2817 rtx delay
= XVECEXP (final_sequence
, 0, 1);
2819 /* For TARGET_PAD_RETURN we might have grabbed the delay insn. */
2820 if (INSN_DELETED_P (delay
))
2822 if (JUMP_P (jump
) && INSN_ANNULLED_BRANCH_P (jump
))
2823 fputs (INSN_FROM_TARGET_P (delay
) ? ".d"
2824 : TARGET_AT_DBR_CONDEXEC
&& code
== '#' ? ".d"
2825 : get_attr_type (jump
) == TYPE_RETURN
&& code
== '#' ? ""
2832 case '?' : /* with leading "." */
2833 case '!' : /* without leading "." */
2834 /* This insn can be conditionally executed. See if the ccfsm machinery
2835 says it should be conditionalized.
2836 If it shouldn't, we'll check the compact attribute if this insn
2837 has a short variant, which may be used depending on code size and
2838 alignment considerations. */
2839 if (current_insn_predicate
)
2840 arc_ccfsm_current
.cc
2841 = get_arc_condition_code (current_insn_predicate
);
2842 if (ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current
))
2844 /* Is this insn in a delay slot sequence? */
2845 if (!final_sequence
|| XVECLEN (final_sequence
, 0) < 2
2846 || current_insn_predicate
2847 || CALL_P (XVECEXP (final_sequence
, 0, 0))
2848 || simplejump_p (XVECEXP (final_sequence
, 0, 0)))
2850 /* This insn isn't in a delay slot sequence, or conditionalized
2851 independently of its position in a delay slot. */
2852 fprintf (file
, "%s%s",
2853 code
== '?' ? "." : "",
2854 arc_condition_codes
[arc_ccfsm_current
.cc
]);
2855 /* If this is a jump, there are still short variants. However,
2856 only beq_s / bne_s have the same offset range as b_s,
2857 and the only short conditional returns are jeq_s and jne_s. */
2859 && (arc_ccfsm_current
.cc
== ARC_CC_EQ
2860 || arc_ccfsm_current
.cc
== ARC_CC_NE
2861 || 0 /* FIXME: check if branch in 7 bit range. */))
2862 output_short_suffix (file
);
2864 else if (code
== '!') /* Jump with delay slot. */
2865 fputs (arc_condition_codes
[arc_ccfsm_current
.cc
], file
);
2866 else /* An Instruction in a delay slot of a jump or call. */
2868 rtx jump
= XVECEXP (final_sequence
, 0, 0);
2869 rtx insn
= XVECEXP (final_sequence
, 0, 1);
2871 /* If the insn is annulled and is from the target path, we need
2872 to inverse the condition test. */
2873 if (JUMP_P (jump
) && INSN_ANNULLED_BRANCH_P (jump
))
2875 if (INSN_FROM_TARGET_P (insn
))
2876 fprintf (file
, "%s%s",
2877 code
== '?' ? "." : "",
2878 arc_condition_codes
[ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current
.cc
)]);
2880 fprintf (file
, "%s%s",
2881 code
== '?' ? "." : "",
2882 arc_condition_codes
[arc_ccfsm_current
.cc
]);
2883 if (arc_ccfsm_current
.state
== 5)
2884 arc_ccfsm_current
.state
= 0;
2887 /* This insn is executed for either path, so don't
2888 conditionalize it at all. */
2889 output_short_suffix (file
);
2894 output_short_suffix (file
);
2897 /* FIXME: fold constant inside unary operator, re-recognize, and emit. */
2900 fputs (arc_condition_codes
[get_arc_condition_code (x
)], file
);
2903 fputs (arc_condition_codes
[ARC_INVERSE_CONDITION_CODE
2904 (get_arc_condition_code (x
))],
2908 /* Write second word of DImode or DFmode reference,
2909 register or memory. */
2910 if (GET_CODE (x
) == REG
)
2911 fputs (reg_names
[REGNO (x
)+1], file
);
2912 else if (GET_CODE (x
) == MEM
)
2916 /* Handle possible auto-increment. For PRE_INC / PRE_DEC /
2917 PRE_MODIFY, we will have handled the first word already;
2918 For POST_INC / POST_DEC / POST_MODIFY, the access to the
2919 first word will be done later. In either case, the access
2920 to the first word will do the modify, and we only have
2921 to add an offset of four here. */
2922 if (GET_CODE (XEXP (x
, 0)) == PRE_INC
2923 || GET_CODE (XEXP (x
, 0)) == PRE_DEC
2924 || GET_CODE (XEXP (x
, 0)) == PRE_MODIFY
2925 || GET_CODE (XEXP (x
, 0)) == POST_INC
2926 || GET_CODE (XEXP (x
, 0)) == POST_DEC
2927 || GET_CODE (XEXP (x
, 0)) == POST_MODIFY
)
2928 output_address (plus_constant (Pmode
, XEXP (XEXP (x
, 0), 0), 4));
2929 else if (output_scaled
)
2931 rtx addr
= XEXP (x
, 0);
2932 int size
= GET_MODE_SIZE (GET_MODE (x
));
2934 output_address (plus_constant (Pmode
, XEXP (addr
, 0),
2935 ((INTVAL (XEXP (addr
, 1)) + 4)
2936 >> (size
== 2 ? 1 : 2))));
2940 output_address (plus_constant (Pmode
, XEXP (x
, 0), 4));
2944 output_operand_lossage ("invalid operand to %%R code");
2947 /* FIXME: remove %S option. */
2949 case 'B' /* Branch or other LIMM ref - must not use sda references. */ :
2952 output_addr_const (file
, x
);
2958 if (GET_CODE (x
) == REG
)
2960 /* L = least significant word, H = most significant word. */
2961 if ((WORDS_BIG_ENDIAN
!= 0) ^ (code
== 'L'))
2962 fputs (reg_names
[REGNO (x
)], file
);
2964 fputs (reg_names
[REGNO (x
)+1], file
);
2966 else if (GET_CODE (x
) == CONST_INT
2967 || GET_CODE (x
) == CONST_DOUBLE
)
2971 split_double (x
, &first
, &second
);
2973 if((WORDS_BIG_ENDIAN
) == 0)
2974 fprintf (file
, "0x%08lx",
2975 code
== 'L' ? INTVAL (first
) : INTVAL (second
));
2977 fprintf (file
, "0x%08lx",
2978 code
== 'L' ? INTVAL (second
) : INTVAL (first
));
2983 output_operand_lossage ("invalid operand to %%H/%%L code");
2989 gcc_assert (GET_CODE (x
) == CONST_DOUBLE
2990 && GET_MODE_CLASS (GET_MODE (x
)) == MODE_FLOAT
);
2992 real_to_decimal (str
, CONST_DOUBLE_REAL_VALUE (x
), sizeof (str
), 0, 1);
2993 fprintf (file
, "%s", str
);
2997 /* Output a load/store with update indicator if appropriate. */
2998 if (GET_CODE (x
) == MEM
)
3000 rtx addr
= XEXP (x
, 0);
3001 switch (GET_CODE (addr
))
3003 case PRE_INC
: case PRE_DEC
: case PRE_MODIFY
:
3004 fputs (".a", file
); break;
3005 case POST_INC
: case POST_DEC
: case POST_MODIFY
:
3006 fputs (".ab", file
); break;
3008 /* Are we using a scaled index? */
3009 if (GET_CODE (XEXP (addr
, 0)) == MULT
)
3010 fputs (".as", file
);
3011 /* Can we use a scaled offset? */
3012 else if (CONST_INT_P (XEXP (addr
, 1))
3013 && GET_MODE_SIZE (GET_MODE (x
)) > 1
3014 && (!(INTVAL (XEXP (addr
, 1))
3015 & (GET_MODE_SIZE (GET_MODE (x
)) - 1) & 3))
3016 /* Does it make a difference? */
3017 && !SMALL_INT_RANGE(INTVAL (XEXP (addr
, 1)),
3018 GET_MODE_SIZE (GET_MODE (x
)) - 2, 0))
3020 fputs (".as", file
);
3027 gcc_assert (CONSTANT_P (addr
)); break;
3031 output_operand_lossage ("invalid operand to %%U code");
3034 /* Output cache bypass indicator for a load/store insn. Volatile memory
3035 refs are defined to use the cache bypass mechanism. */
3036 if (GET_CODE (x
) == MEM
)
3038 if (MEM_VOLATILE_P (x
) && !TARGET_VOLATILE_CACHE_SET
)
3039 fputs (".di", file
);
3042 output_operand_lossage ("invalid operand to %%V code");
3047 /* Do nothing special. */
3050 fputs (reg_names
[REGNO (x
)]+1, file
);
3053 /* This punctuation character is needed because label references are
3054 printed in the output template using %l. This is a front end
3055 character, and when we want to emit a '@' before it, we have to use
3061 /* Output an operator. */
3062 switch (GET_CODE (x
))
3064 case PLUS
: fputs ("add", file
); return;
3065 case SS_PLUS
: fputs ("adds", file
); return;
3066 case AND
: fputs ("and", file
); return;
3067 case IOR
: fputs ("or", file
); return;
3068 case XOR
: fputs ("xor", file
); return;
3069 case MINUS
: fputs ("sub", file
); return;
3070 case SS_MINUS
: fputs ("subs", file
); return;
3071 case ASHIFT
: fputs ("asl", file
); return;
3072 case ASHIFTRT
: fputs ("asr", file
); return;
3073 case LSHIFTRT
: fputs ("lsr", file
); return;
3074 case ROTATERT
: fputs ("ror", file
); return;
3075 case MULT
: fputs ("mpy", file
); return;
3076 case ABS
: fputs ("abs", file
); return; /* Unconditional. */
3077 case NEG
: fputs ("neg", file
); return;
3078 case SS_NEG
: fputs ("negs", file
); return;
3079 case NOT
: fputs ("not", file
); return; /* Unconditional. */
3081 fputs ("ext", file
); /* bmsk allows predication. */
3083 case SIGN_EXTEND
: /* Unconditional. */
3084 fputs ("sex", file
);
3086 switch (GET_MODE (XEXP (x
, 0)))
3088 case QImode
: fputs ("b", file
); return;
3089 case HImode
: fputs ("w", file
); return;
3094 if (GET_MODE (x
) != HImode
)
3096 fputs ("sat16", file
);
3099 output_operand_lossage ("invalid operand to %%O code"); return;
3101 if (GET_CODE (x
) == SYMBOL_REF
)
3103 assemble_name (file
, XSTR (x
, 0));
3108 if (TARGET_ANNOTATE_ALIGN
&& cfun
->machine
->size_reason
)
3109 fprintf (file
, "; unalign: %d", cfun
->machine
->unalign
);
3113 output_operand_lossage ("invalid operand output code");
3116 switch (GET_CODE (x
))
3119 fputs (reg_names
[REGNO (x
)], file
);
3123 rtx addr
= XEXP (x
, 0);
3124 int size
= GET_MODE_SIZE (GET_MODE (x
));
3128 switch (GET_CODE (addr
))
3130 case PRE_INC
: case POST_INC
:
3131 output_address (plus_constant (Pmode
, XEXP (addr
, 0), size
)); break;
3132 case PRE_DEC
: case POST_DEC
:
3133 output_address (plus_constant (Pmode
, XEXP (addr
, 0), -size
));
3135 case PRE_MODIFY
: case POST_MODIFY
:
3136 output_address (XEXP (addr
, 1)); break;
3140 output_address (plus_constant (Pmode
, XEXP (addr
, 0),
3141 (INTVAL (XEXP (addr
, 1))
3142 >> (size
== 2 ? 1 : 2))));
3146 output_address (addr
);
3149 if (flag_pic
&& CONSTANT_ADDRESS_P (addr
))
3150 arc_output_pic_addr_const (file
, addr
, code
);
3152 output_address (addr
);
3159 /* We handle SFmode constants here as output_addr_const doesn't. */
3160 if (GET_MODE (x
) == SFmode
)
3165 REAL_VALUE_FROM_CONST_DOUBLE (d
, x
);
3166 REAL_VALUE_TO_TARGET_SINGLE (d
, l
);
3167 fprintf (file
, "0x%08lx", l
);
3170 /* Fall through. Let output_addr_const deal with it. */
3173 arc_output_pic_addr_const (file
, x
, code
);
3176 /* FIXME: Dirty way to handle @var@sda+const. Shd be handled
3177 with asm_output_symbol_ref */
3178 if (GET_CODE (x
) == CONST
&& GET_CODE (XEXP (x
, 0)) == PLUS
)
3181 output_addr_const (file
, XEXP (x
, 0));
3182 if (GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
&& SYMBOL_REF_SMALL_P (XEXP (x
, 0)))
3183 fprintf (file
, "@sda");
3185 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
3186 || INTVAL (XEXP (x
, 1)) >= 0)
3187 fprintf (file
, "+");
3188 output_addr_const (file
, XEXP (x
, 1));
3191 output_addr_const (file
, x
);
3193 if (GET_CODE (x
) == SYMBOL_REF
&& SYMBOL_REF_SMALL_P (x
))
3194 fprintf (file
, "@sda");
3199 /* Print a memory address as an operand to reference that memory location. */
3202 arc_print_operand_address (FILE *file
, rtx addr
)
3204 register rtx base
, index
= 0;
3206 switch (GET_CODE (addr
))
3209 fputs (reg_names
[REGNO (addr
)], file
);
3212 output_addr_const (file
, addr
);
3213 if (SYMBOL_REF_SMALL_P (addr
))
3214 fprintf (file
, "@sda");
3217 if (GET_CODE (XEXP (addr
, 0)) == MULT
)
3218 index
= XEXP (XEXP (addr
, 0), 0), base
= XEXP (addr
, 1);
3219 else if (CONST_INT_P (XEXP (addr
, 0)))
3220 index
= XEXP (addr
, 0), base
= XEXP (addr
, 1);
3222 base
= XEXP (addr
, 0), index
= XEXP (addr
, 1);
3224 gcc_assert (OBJECT_P (base
));
3225 arc_print_operand_address (file
, base
);
3226 if (CONSTANT_P (base
) && CONST_INT_P (index
))
3230 gcc_assert (OBJECT_P (index
));
3231 arc_print_operand_address (file
, index
);
3235 rtx c
= XEXP (addr
, 0);
3237 gcc_assert (GET_CODE (XEXP (c
, 0)) == SYMBOL_REF
);
3238 gcc_assert (GET_CODE (XEXP (c
, 1)) == CONST_INT
);
3240 output_address(XEXP(addr
,0));
3246 /* We shouldn't get here as we've lost the mode of the memory object
3247 (which says how much to inc/dec by. */
3252 arc_output_pic_addr_const (file
, addr
, 0);
3254 output_addr_const (file
, addr
);
3259 /* Called via walk_stores. DATA points to a hash table we can use to
3260 establish a unique SYMBOL_REF for each counter, which corresponds to
3261 a caller-callee pair.
3262 X is a store which we want to examine for an UNSPEC_PROF, which
3263 would be an address loaded into a register, or directly used in a MEM.
3264 If we found an UNSPEC_PROF, if we encounter a new counter the first time,
3265 write out a description and a data allocation for a 32 bit counter.
3266 Also, fill in the appropriate symbol_ref into each UNSPEC_PROF instance. */
3269 write_profile_sections (rtx dest ATTRIBUTE_UNUSED
, rtx x
, void *data
)
3272 htab_t htab
= (htab_t
) data
;
3275 if (GET_CODE (x
) != SET
)
3277 srcp
= &SET_SRC (x
);
3279 srcp
= &XEXP (*srcp
, 0);
3280 else if (MEM_P (SET_DEST (x
)))
3281 srcp
= &XEXP (SET_DEST (x
), 0);
3283 if (GET_CODE (src
) != CONST
)
3285 src
= XEXP (src
, 0);
3286 if (GET_CODE (src
) != UNSPEC
|| XINT (src
, 1) != UNSPEC_PROF
)
3289 gcc_assert (XVECLEN (src
, 0) == 3);
3290 if (!htab_elements (htab
))
3292 output_asm_insn (".section .__arc_profile_desc, \"a\"\n"
3294 &XVECEXP (src
, 0, 0));
3296 slot
= (rtx
*) htab_find_slot (htab
, src
, INSERT
);
3297 if (*slot
== HTAB_EMPTY_ENTRY
)
3299 static int count_nr
;
3304 sprintf (buf
, "__prof_count%d", count_nr
++);
3305 count
= gen_rtx_SYMBOL_REF (Pmode
, xstrdup (buf
));
3306 XVECEXP (src
, 0, 2) = count
;
3307 output_asm_insn (".section\t.__arc_profile_desc, \"a\"\n"
3309 "\t.section\t.__arc_profile_counters, \"aw\"\n"
3310 "\t.type\t%o2, @object\n"
3313 &XVECEXP (src
, 0, 0));
3317 *srcp
= XVECEXP (*slot
, 0, 2);
3320 /* Hash function for UNSPEC_PROF htab. Use both the caller's name and
3321 the callee's name (if known). */
3324 unspec_prof_hash (const void *x
)
3326 const_rtx u
= (const_rtx
) x
;
3327 const_rtx s1
= XVECEXP (u
, 0, 1);
3329 return (htab_hash_string (XSTR (XVECEXP (u
, 0, 0), 0))
3330 ^ (s1
->code
== SYMBOL_REF
? htab_hash_string (XSTR (s1
, 0)) : 0));
3333 /* Equality function for UNSPEC_PROF htab. Two pieces of UNSPEC_PROF rtl
3334 shall refer to the same counter if both caller name and callee rtl
3338 unspec_prof_htab_eq (const void *x
, const void *y
)
3340 const_rtx u0
= (const_rtx
) x
;
3341 const_rtx u1
= (const_rtx
) y
;
3342 const_rtx s01
= XVECEXP (u0
, 0, 1);
3343 const_rtx s11
= XVECEXP (u1
, 0, 1);
3345 return (!strcmp (XSTR (XVECEXP (u0
, 0, 0), 0),
3346 XSTR (XVECEXP (u1
, 0, 0), 0))
3347 && rtx_equal_p (s01
, s11
));
3350 /* Conditional execution support.
3352 This is based on the ARM port but for now is much simpler.
3354 A finite state machine takes care of noticing whether or not instructions
3355 can be conditionally executed, and thus decrease execution time and code
3356 size by deleting branch instructions. The fsm is controlled by
3357 arc_ccfsm_advance (called by arc_final_prescan_insn), and controls the
3358 actions of PRINT_OPERAND. The patterns in the .md file for the branch
3359 insns also have a hand in this. */
3360 /* The way we leave dealing with non-anulled or annull-false delay slot
3361 insns to the consumer is awkward. */
3363 /* The state of the fsm controlling condition codes are:
3364 0: normal, do nothing special
3365 1: don't output this insn
3366 2: don't output this insn
3367 3: make insns conditional
3368 4: make insns conditional
3369 5: make insn conditional (only for outputting anulled delay slot insns)
3371 special value for cfun->machine->uid_ccfsm_state:
3372 6: return with but one insn before it since function start / call
3374 State transitions (state->state by whom, under what condition):
3375 0 -> 1 arc_ccfsm_advance, if insn is a conditional branch skipping over
3377 0 -> 2 arc_ccfsm_advance, if insn is a conditional branch followed
3378 by zero or more non-jump insns and an unconditional branch with
3379 the same target label as the condbranch.
3380 1 -> 3 branch patterns, after having not output the conditional branch
3381 2 -> 4 branch patterns, after having not output the conditional branch
3382 0 -> 5 branch patterns, for anulled delay slot insn.
3383 3 -> 0 ASM_OUTPUT_INTERNAL_LABEL, if the `target' label is reached
3384 (the target label has CODE_LABEL_NUMBER equal to
3385 arc_ccfsm_target_label).
3386 4 -> 0 arc_ccfsm_advance, if `target' unconditional branch is reached
3387 3 -> 1 arc_ccfsm_advance, finding an 'else' jump skipping over some insns.
3388 5 -> 0 when outputting the delay slot insn
3390 If the jump clobbers the conditions then we use states 2 and 4.
3392 A similar thing can be done with conditional return insns.
3394 We also handle separating branches from sets of the condition code.
3395 This is done here because knowledge of the ccfsm state is required,
3396 we may not be outputting the branch. */
3398 /* arc_final_prescan_insn calls arc_ccfsm_advance to adjust arc_ccfsm_current,
3399 before letting final output INSN. */
3402 arc_ccfsm_advance (rtx insn
, struct arc_ccfsm
*state
)
3404 /* BODY will hold the body of INSN. */
3407 /* This will be 1 if trying to repeat the trick (ie: do the `else' part of
3408 an if/then/else), and things need to be reversed. */
3411 /* If we start with a return insn, we only succeed if we find another one. */
3412 int seeking_return
= 0;
3414 /* START_INSN will hold the insn from where we start looking. This is the
3415 first insn after the following code_label if REVERSE is true. */
3416 rtx start_insn
= insn
;
3418 /* Type of the jump_insn. Brcc insns don't affect ccfsm changes,
3419 since they don't rely on a cmp preceding the. */
3420 enum attr_type jump_insn_type
;
3422 /* Allow -mdebug-ccfsm to turn this off so we can see how well it does.
3423 We can't do this in macro FINAL_PRESCAN_INSN because its called from
3424 final_scan_insn which has `optimize' as a local. */
3425 if (optimize
< 2 || TARGET_NO_COND_EXEC
)
3428 /* Ignore notes and labels. */
3431 body
= PATTERN (insn
);
3432 /* If in state 4, check if the target branch is reached, in order to
3433 change back to state 0. */
3434 if (state
->state
== 4)
3436 if (insn
== state
->target_insn
)
3438 state
->target_insn
= NULL
;
3444 /* If in state 3, it is possible to repeat the trick, if this insn is an
3445 unconditional branch to a label, and immediately following this branch
3446 is the previous target label which is only used once, and the label this
3447 branch jumps to is not too far off. Or in other words "we've done the
3448 `then' part, see if we can do the `else' part." */
3449 if (state
->state
== 3)
3451 if (simplejump_p (insn
))
3453 start_insn
= next_nonnote_insn (start_insn
);
3454 if (GET_CODE (start_insn
) == BARRIER
)
3456 /* ??? Isn't this always a barrier? */
3457 start_insn
= next_nonnote_insn (start_insn
);
3459 if (GET_CODE (start_insn
) == CODE_LABEL
3460 && CODE_LABEL_NUMBER (start_insn
) == state
->target_label
3461 && LABEL_NUSES (start_insn
) == 1)
3466 else if (GET_CODE (body
) == SIMPLE_RETURN
)
3468 start_insn
= next_nonnote_insn (start_insn
);
3469 if (GET_CODE (start_insn
) == BARRIER
)
3470 start_insn
= next_nonnote_insn (start_insn
);
3471 if (GET_CODE (start_insn
) == CODE_LABEL
3472 && CODE_LABEL_NUMBER (start_insn
) == state
->target_label
3473 && LABEL_NUSES (start_insn
) == 1)
3485 if (GET_CODE (insn
) != JUMP_INSN
3486 || GET_CODE (PATTERN (insn
)) == ADDR_VEC
3487 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
3490 /* We can't predicate BRCC or loop ends.
3491 Also, when generating PIC code, and considering a medium range call,
3492 we can't predicate the call. */
3493 jump_insn_type
= get_attr_type (insn
);
3494 if (jump_insn_type
== TYPE_BRCC
3495 || jump_insn_type
== TYPE_BRCC_NO_DELAY_SLOT
3496 || jump_insn_type
== TYPE_LOOP_END
3497 || (jump_insn_type
== TYPE_CALL
&& !get_attr_predicable (insn
)))
3500 /* This jump might be paralleled with a clobber of the condition codes,
3501 the jump should always come first. */
3502 if (GET_CODE (body
) == PARALLEL
&& XVECLEN (body
, 0) > 0)
3503 body
= XVECEXP (body
, 0, 0);
3506 || (GET_CODE (body
) == SET
&& GET_CODE (SET_DEST (body
)) == PC
3507 && GET_CODE (SET_SRC (body
)) == IF_THEN_ELSE
))
3509 int insns_skipped
= 0, fail
= FALSE
, succeed
= FALSE
;
3510 /* Flag which part of the IF_THEN_ELSE is the LABEL_REF. */
3511 int then_not_else
= TRUE
;
3512 /* Nonzero if next insn must be the target label. */
3513 int next_must_be_target_label_p
;
3514 rtx this_insn
= start_insn
, label
= 0;
3516 /* Register the insn jumped to. */
3519 if (!seeking_return
)
3520 label
= XEXP (SET_SRC (body
), 0);
3522 else if (GET_CODE (XEXP (SET_SRC (body
), 1)) == LABEL_REF
)
3523 label
= XEXP (XEXP (SET_SRC (body
), 1), 0);
3524 else if (GET_CODE (XEXP (SET_SRC (body
), 2)) == LABEL_REF
)
3526 label
= XEXP (XEXP (SET_SRC (body
), 2), 0);
3527 then_not_else
= FALSE
;
3529 else if (GET_CODE (XEXP (SET_SRC (body
), 1)) == SIMPLE_RETURN
)
3531 else if (GET_CODE (XEXP (SET_SRC (body
), 2)) == SIMPLE_RETURN
)
3534 then_not_else
= FALSE
;
3539 /* If this is a non-annulled branch with a delay slot, there is
3540 no need to conditionalize the delay slot. */
3541 if (NEXT_INSN (PREV_INSN (insn
)) != insn
3542 && state
->state
== 0 && !INSN_ANNULLED_BRANCH_P (insn
))
3544 this_insn
= NEXT_INSN (this_insn
);
3545 gcc_assert (NEXT_INSN (NEXT_INSN (PREV_INSN (start_insn
)))
3546 == NEXT_INSN (this_insn
));
3548 /* See how many insns this branch skips, and what kind of insns. If all
3549 insns are okay, and the label or unconditional branch to the same
3550 label is not too far away, succeed. */
3551 for (insns_skipped
= 0, next_must_be_target_label_p
= FALSE
;
3552 !fail
&& !succeed
&& insns_skipped
< MAX_INSNS_SKIPPED
;
3557 this_insn
= next_nonnote_insn (this_insn
);
3561 if (next_must_be_target_label_p
)
3563 if (GET_CODE (this_insn
) == BARRIER
)
3565 if (GET_CODE (this_insn
) == CODE_LABEL
3566 && this_insn
== label
)
3576 scanbody
= PATTERN (this_insn
);
3578 switch (GET_CODE (this_insn
))
3581 /* Succeed if it is the target label, otherwise fail since
3582 control falls in from somewhere else. */
3583 if (this_insn
== label
)
3593 /* Succeed if the following insn is the target label.
3595 If return insns are used then the last insn in a function
3596 will be a barrier. */
3597 next_must_be_target_label_p
= TRUE
;
3601 /* Can handle a call insn if there are no insns after it.
3602 IE: The next "insn" is the target label. We don't have to
3603 worry about delay slots as such insns are SEQUENCE's inside
3604 INSN's. ??? It is possible to handle such insns though. */
3605 if (get_attr_cond (this_insn
) == COND_CANUSE
)
3606 next_must_be_target_label_p
= TRUE
;
3612 /* If this is an unconditional branch to the same label, succeed.
3613 If it is to another label, do nothing. If it is conditional,
3615 /* ??? Probably, the test for the SET and the PC are
3618 if (GET_CODE (scanbody
) == SET
3619 && GET_CODE (SET_DEST (scanbody
)) == PC
)
3621 if (GET_CODE (SET_SRC (scanbody
)) == LABEL_REF
3622 && XEXP (SET_SRC (scanbody
), 0) == label
&& !reverse
)
3627 else if (GET_CODE (SET_SRC (scanbody
)) == IF_THEN_ELSE
)
3629 else if (get_attr_cond (this_insn
) != COND_CANUSE
)
3632 else if (GET_CODE (scanbody
) == SIMPLE_RETURN
3638 else if (GET_CODE (scanbody
) == PARALLEL
)
3640 if (get_attr_cond (this_insn
) != COND_CANUSE
)
3646 /* We can only do this with insns that can use the condition
3647 codes (and don't set them). */
3648 if (GET_CODE (scanbody
) == SET
3649 || GET_CODE (scanbody
) == PARALLEL
)
3651 if (get_attr_cond (this_insn
) != COND_CANUSE
)
3654 /* We can't handle other insns like sequences. */
3666 if ((!seeking_return
) && (state
->state
== 1 || reverse
))
3667 state
->target_label
= CODE_LABEL_NUMBER (label
);
3668 else if (seeking_return
|| state
->state
== 2)
3670 while (this_insn
&& GET_CODE (PATTERN (this_insn
)) == USE
)
3672 this_insn
= next_nonnote_insn (this_insn
);
3674 gcc_assert (!this_insn
||
3675 (GET_CODE (this_insn
) != BARRIER
3676 && GET_CODE (this_insn
) != CODE_LABEL
));
3680 /* Oh dear! we ran off the end, give up. */
3681 extract_insn_cached (insn
);
3683 state
->target_insn
= NULL
;
3686 state
->target_insn
= this_insn
;
3691 /* If REVERSE is true, ARM_CURRENT_CC needs to be inverted from
3695 state
->cond
= XEXP (SET_SRC (body
), 0);
3696 state
->cc
= get_arc_condition_code (XEXP (SET_SRC (body
), 0));
3699 if (reverse
|| then_not_else
)
3700 state
->cc
= ARC_INVERSE_CONDITION_CODE (state
->cc
);
3703 /* Restore recog_operand. Getting the attributes of other insns can
3704 destroy this array, but final.c assumes that it remains intact
3705 across this call; since the insn has been recognized already we
3706 call insn_extract direct. */
3707 extract_insn_cached (insn
);
3711 /* Record that we are currently outputting label NUM with prefix PREFIX.
3712 It it's the label we're looking for, reset the ccfsm machinery.
3714 Called from ASM_OUTPUT_INTERNAL_LABEL. */
3717 arc_ccfsm_at_label (const char *prefix
, int num
, struct arc_ccfsm
*state
)
3719 if (state
->state
== 3 && state
->target_label
== num
3720 && !strcmp (prefix
, "L"))
3723 state
->target_insn
= NULL_RTX
;
3727 /* We are considering a conditional branch with the condition COND.
3728 Check if we want to conditionalize a delay slot insn, and if so modify
3729 the ccfsm state accordingly.
3730 REVERSE says branch will branch when the condition is false. */
3732 arc_ccfsm_record_condition (rtx cond
, bool reverse
, rtx jump
,
3733 struct arc_ccfsm
*state
)
3735 rtx seq_insn
= NEXT_INSN (PREV_INSN (jump
));
3737 state
= &arc_ccfsm_current
;
3739 gcc_assert (state
->state
== 0);
3740 if (seq_insn
!= jump
)
3742 rtx insn
= XVECEXP (PATTERN (seq_insn
), 0, 1);
3744 if (!INSN_DELETED_P (insn
)
3745 && INSN_ANNULLED_BRANCH_P (jump
)
3746 && (TARGET_AT_DBR_CONDEXEC
|| INSN_FROM_TARGET_P (insn
)))
3749 state
->cc
= get_arc_condition_code (cond
);
3751 arc_ccfsm_current
.cc
3752 = ARC_INVERSE_CONDITION_CODE (state
->cc
);
3753 rtx pat
= PATTERN (insn
);
3754 if (GET_CODE (pat
) == COND_EXEC
)
3755 gcc_assert ((INSN_FROM_TARGET_P (insn
)
3756 ? ARC_INVERSE_CONDITION_CODE (state
->cc
) : state
->cc
)
3757 == get_arc_condition_code (XEXP (pat
, 0)));
3764 /* Update *STATE as we would when we emit INSN. */
3767 arc_ccfsm_post_advance (rtx insn
, struct arc_ccfsm
*state
)
3769 enum attr_type type
;
3772 arc_ccfsm_at_label ("L", CODE_LABEL_NUMBER (insn
), state
);
3773 else if (JUMP_P (insn
)
3774 && GET_CODE (PATTERN (insn
)) != ADDR_VEC
3775 && GET_CODE (PATTERN (insn
)) != ADDR_DIFF_VEC
3776 && ((type
= get_attr_type (insn
)) == TYPE_BRANCH
3777 || (type
== TYPE_UNCOND_BRANCH
3778 /* ??? Maybe should also handle TYPE_RETURN here,
3779 but we don't have a testcase for that. */
3780 && ARC_CCFSM_BRANCH_DELETED_P (state
))))
3782 if (ARC_CCFSM_BRANCH_DELETED_P (state
))
3783 ARC_CCFSM_RECORD_BRANCH_DELETED (state
);
3786 rtx src
= SET_SRC (PATTERN (insn
));
3787 arc_ccfsm_record_condition (XEXP (src
, 0), XEXP (src
, 1) == pc_rtx
,
3791 else if (arc_ccfsm_current
.state
== 5)
3792 arc_ccfsm_current
.state
= 0;
3795 /* Return true if the current insn, which is a conditional branch, is to be
3799 arc_ccfsm_branch_deleted_p (void)
3801 return ARC_CCFSM_BRANCH_DELETED_P (&arc_ccfsm_current
);
3804 /* Record a branch isn't output because subsequent insns can be
3808 arc_ccfsm_record_branch_deleted (void)
3810 ARC_CCFSM_RECORD_BRANCH_DELETED (&arc_ccfsm_current
);
3813 /* During insn output, indicate if the current insn is predicated. */
3816 arc_ccfsm_cond_exec_p (void)
3818 return (cfun
->machine
->prescan_initialized
3819 && ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current
));
3822 /* Like next_active_insn, but return NULL if we find an ADDR_(DIFF_)VEC,
3823 and look inside SEQUENCEs. */
3826 arc_next_active_insn (rtx insn
, struct arc_ccfsm
*statep
)
3833 arc_ccfsm_post_advance (insn
, statep
);
3834 insn
= NEXT_INSN (insn
);
3835 if (!insn
|| BARRIER_P (insn
))
3838 arc_ccfsm_advance (insn
, statep
);
3840 while (NOTE_P (insn
)
3841 || (cfun
->machine
->arc_reorg_started
3842 && LABEL_P (insn
) && !label_to_alignment (insn
))
3843 || (NONJUMP_INSN_P (insn
)
3844 && (GET_CODE (PATTERN (insn
)) == USE
3845 || GET_CODE (PATTERN (insn
)) == CLOBBER
)));
3846 if (!LABEL_P (insn
))
3848 gcc_assert (INSN_P (insn
));
3849 pat
= PATTERN (insn
);
3850 if (GET_CODE (pat
) == ADDR_VEC
|| GET_CODE (pat
) == ADDR_DIFF_VEC
)
3852 if (GET_CODE (pat
) == SEQUENCE
)
3853 return XVECEXP (pat
, 0, 0);
3858 /* When deciding if an insn should be output short, we want to know something
3859 about the following insns:
3860 - if another insn follows which we know we can output as a short insn
3861 before an alignment-sensitive point, we can output this insn short:
3862 the decision about the eventual alignment can be postponed.
3863 - if a to-be-aligned label comes next, we should output this insn such
3864 as to get / preserve 4-byte alignment.
3865 - if a likely branch without delay slot insn, or a call with an immediately
3866 following short insn comes next, we should out output this insn such as to
3867 get / preserve 2 mod 4 unalignment.
3868 - do the same for a not completely unlikely branch with a short insn
3869 following before any other branch / label.
3870 - in order to decide if we are actually looking at a branch, we need to
3871 call arc_ccfsm_advance.
3872 - in order to decide if we are looking at a short insn, we should know
3873 if it is conditionalized. To a first order of approximation this is
3874 the case if the state from arc_ccfsm_advance from before this insn
3875 indicates the insn is conditionalized. However, a further refinement
3876 could be to not conditionalize an insn if the destination register(s)
3877 is/are dead in the non-executed case. */
3878 /* Return non-zero if INSN should be output as a short insn. UNALIGN is
3879 zero if the current insn is aligned to a 4-byte-boundary, two otherwise.
3880 If CHECK_ATTR is greater than 0, check the iscompact attribute first. */
3883 arc_verify_short (rtx insn
, int, int check_attr
)
3885 enum attr_iscompact iscompact
;
3886 struct machine_function
*machine
;
3890 iscompact
= get_attr_iscompact (insn
);
3891 if (iscompact
== ISCOMPACT_FALSE
)
3894 machine
= cfun
->machine
;
3896 if (machine
->force_short_suffix
>= 0)
3897 return machine
->force_short_suffix
;
3899 return (get_attr_length (insn
) & 2) != 0;
3902 /* When outputting an instruction (alternative) that can potentially be short,
3903 output the short suffix if the insn is in fact short, and update
3904 cfun->machine->unalign accordingly. */
3907 output_short_suffix (FILE *file
)
3909 rtx insn
= current_output_insn
;
3911 if (arc_verify_short (insn
, cfun
->machine
->unalign
, 1))
3913 fprintf (file
, "_s");
3914 cfun
->machine
->unalign
^= 2;
3916 /* Restore recog_operand. */
3917 extract_insn_cached (insn
);
3920 /* Implement FINAL_PRESCAN_INSN. */
3923 arc_final_prescan_insn (rtx insn
, rtx
*opvec ATTRIBUTE_UNUSED
,
3924 int noperands ATTRIBUTE_UNUSED
)
3926 if (TARGET_DUMPISIZE
)
3927 fprintf (asm_out_file
, "\n; at %04x\n", INSN_ADDRESSES (INSN_UID (insn
)));
3929 /* Output a nop if necessary to prevent a hazard.
3930 Don't do this for delay slots: inserting a nop would
3931 alter semantics, and the only time we would find a hazard is for a
3932 call function result - and in that case, the hazard is spurious to
3934 if (PREV_INSN (insn
)
3935 && PREV_INSN (NEXT_INSN (insn
)) == insn
3936 && arc_hazard (prev_real_insn (insn
), insn
))
3938 current_output_insn
=
3939 emit_insn_before (gen_nop (), NEXT_INSN (PREV_INSN (insn
)));
3940 final_scan_insn (current_output_insn
, asm_out_file
, optimize
, 1, NULL
);
3941 current_output_insn
= insn
;
3943 /* Restore extraction data which might have been clobbered by arc_hazard. */
3944 extract_constrain_insn_cached (insn
);
3946 if (!cfun
->machine
->prescan_initialized
)
3948 /* Clear lingering state from branch shortening. */
3949 memset (&arc_ccfsm_current
, 0, sizeof arc_ccfsm_current
);
3950 cfun
->machine
->prescan_initialized
= 1;
3952 arc_ccfsm_advance (insn
, &arc_ccfsm_current
);
3954 cfun
->machine
->size_reason
= 0;
3957 /* Given FROM and TO register numbers, say whether this elimination is allowed.
3958 Frame pointer elimination is automatically handled.
3960 All eliminations are permissible. If we need a frame
3961 pointer, we must eliminate ARG_POINTER_REGNUM into
3962 FRAME_POINTER_REGNUM and not into STACK_POINTER_REGNUM. */
3965 arc_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to
)
3967 return to
== FRAME_POINTER_REGNUM
|| !arc_frame_pointer_required ();
3970 /* Define the offset between two registers, one to be eliminated, and
3971 the other its replacement, at the start of a routine. */
3974 arc_initial_elimination_offset (int from
, int to
)
3976 if (! cfun
->machine
->frame_info
.initialized
)
3977 arc_compute_frame_size (get_frame_size ());
3979 if (from
== ARG_POINTER_REGNUM
&& to
== FRAME_POINTER_REGNUM
)
3981 return (cfun
->machine
->frame_info
.extra_size
3982 + cfun
->machine
->frame_info
.reg_size
);
3985 if (from
== ARG_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
3987 return (cfun
->machine
->frame_info
.total_size
3988 - cfun
->machine
->frame_info
.pretend_size
);
3991 if ((from
== FRAME_POINTER_REGNUM
) && (to
== STACK_POINTER_REGNUM
))
3993 return (cfun
->machine
->frame_info
.total_size
3994 - (cfun
->machine
->frame_info
.pretend_size
3995 + cfun
->machine
->frame_info
.extra_size
3996 + cfun
->machine
->frame_info
.reg_size
));
4003 arc_frame_pointer_required (void)
4005 return cfun
->calls_alloca
;
4009 /* Return the destination address of a branch. */
4012 branch_dest (rtx branch
)
4014 rtx pat
= PATTERN (branch
);
4015 rtx dest
= (GET_CODE (pat
) == PARALLEL
4016 ? SET_SRC (XVECEXP (pat
, 0, 0)) : SET_SRC (pat
));
4019 if (GET_CODE (dest
) == IF_THEN_ELSE
)
4020 dest
= XEXP (dest
, XEXP (dest
, 1) == pc_rtx
? 2 : 1);
4022 dest
= XEXP (dest
, 0);
4023 dest_uid
= INSN_UID (dest
);
4025 return INSN_ADDRESSES (dest_uid
);
4029 /* Implement TARGET_ENCODE_SECTION_INFO hook. */
4032 arc_encode_section_info (tree decl
, rtx rtl
, int first
)
4034 /* For sdata, SYMBOL_FLAG_LOCAL and SYMBOL_FLAG_FUNCTION.
4035 This clears machine specific flags, so has to come first. */
4036 default_encode_section_info (decl
, rtl
, first
);
4038 /* Check if it is a function, and whether it has the
4039 [long/medium/short]_call attribute specified. */
4040 if (TREE_CODE (decl
) == FUNCTION_DECL
)
4042 rtx symbol
= XEXP (rtl
, 0);
4043 int flags
= SYMBOL_REF_FLAGS (symbol
);
4045 tree attr
= (TREE_TYPE (decl
) != error_mark_node
4046 ? TYPE_ATTRIBUTES (TREE_TYPE (decl
)) : NULL_TREE
);
4047 tree long_call_attr
= lookup_attribute ("long_call", attr
);
4048 tree medium_call_attr
= lookup_attribute ("medium_call", attr
);
4049 tree short_call_attr
= lookup_attribute ("short_call", attr
);
4051 if (long_call_attr
!= NULL_TREE
)
4052 flags
|= SYMBOL_FLAG_LONG_CALL
;
4053 else if (medium_call_attr
!= NULL_TREE
)
4054 flags
|= SYMBOL_FLAG_MEDIUM_CALL
;
4055 else if (short_call_attr
!= NULL_TREE
)
4056 flags
|= SYMBOL_FLAG_SHORT_CALL
;
4058 SYMBOL_REF_FLAGS (symbol
) = flags
;
4062 /* This is how to output a definition of an internal numbered label where
4063 PREFIX is the class of label and NUM is the number within the class. */
4065 static void arc_internal_label (FILE *stream
, const char *prefix
, unsigned long labelno
)
4068 arc_ccfsm_at_label (prefix
, labelno
, &arc_ccfsm_current
);
4069 default_internal_label (stream
, prefix
, labelno
);
4072 /* Set the cpu type and print out other fancy things,
4073 at the top of the file. */
4075 static void arc_file_start (void)
4077 default_file_start ();
4078 fprintf (asm_out_file
, "\t.cpu %s\n", arc_cpu_string
);
4081 /* Cost functions. */
4083 /* Compute a (partial) cost for rtx X. Return true if the complete
4084 cost has been computed, and false if subexpressions should be
4085 scanned. In either case, *TOTAL contains the cost result. */
4088 arc_rtx_costs (rtx x
, int code
, int outer_code
, int opno ATTRIBUTE_UNUSED
,
4089 int *total
, bool speed
)
4093 /* Small integers are as cheap as registers. */
4096 bool nolimm
= false; /* Can we do without long immediate? */
4097 bool fast
= false; /* Is the result available immediately? */
4098 bool condexec
= false; /* Does this allow conditiobnal execution? */
4099 bool compact
= false; /* Is a 16 bit opcode available? */
4100 /* CONDEXEC also implies that we can have an unconditional
4101 3-address operation. */
4103 nolimm
= compact
= condexec
= false;
4104 if (UNSIGNED_INT6 (INTVAL (x
)))
4105 nolimm
= condexec
= compact
= true;
4108 if (SMALL_INT (INTVAL (x
)))
4109 nolimm
= fast
= true;
4112 case AND
: /* bclr, bmsk, ext[bw] */
4113 if (satisfies_constraint_Ccp (x
) /* bclr */
4114 || satisfies_constraint_C1p (x
) /* bmsk */)
4115 nolimm
= fast
= condexec
= compact
= true;
4117 case IOR
: /* bset */
4118 if (satisfies_constraint_C0p (x
)) /* bset */
4119 nolimm
= fast
= condexec
= compact
= true;
4122 if (satisfies_constraint_C0p (x
)) /* bxor */
4123 nolimm
= fast
= condexec
= true;
4126 if (satisfies_constraint_Crr (x
)) /* ror b,u6 */
4132 /* FIXME: Add target options to attach a small cost if
4133 condexec / compact is not true. */
4142 /* 4 byte values can be fetched as immediate constants -
4143 let's give that the cost of an extra insn. */
4147 *total
= COSTS_N_INSNS (1);
4156 *total
= COSTS_N_INSNS (1);
4159 /* FIXME: correct the order of high,low */
4160 split_double (x
, &high
, &low
);
4161 *total
= COSTS_N_INSNS (!SMALL_INT (INTVAL (high
))
4162 + !SMALL_INT (INTVAL (low
)));
4166 /* Encourage synth_mult to find a synthetic multiply when reasonable.
4167 If we need more than 12 insns to do a multiply, then go out-of-line,
4168 since the call overhead will be < 10% of the cost of the multiply. */
4172 if (TARGET_BARREL_SHIFTER
)
4174 /* If we want to shift a constant, we need a LIMM. */
4175 /* ??? when the optimizers want to know if a constant should be
4176 hoisted, they ask for the cost of the constant. OUTER_CODE is
4177 insufficient context for shifts since we don't know which operand
4178 we are looking at. */
4179 if (CONSTANT_P (XEXP (x
, 0)))
4181 *total
+= (COSTS_N_INSNS (2)
4182 + rtx_cost (XEXP (x
, 1), (enum rtx_code
) code
, 0, speed
));
4185 *total
= COSTS_N_INSNS (1);
4187 else if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
4188 *total
= COSTS_N_INSNS (16);
4191 *total
= COSTS_N_INSNS (INTVAL (XEXP ((x
), 1)));
4192 /* ??? want_to_gcse_p can throw negative shift counts at us,
4193 and then panics when it gets a negative cost as result.
4194 Seen for gcc.c-torture/compile/20020710-1.c -Os . */
4203 *total
= COSTS_N_INSNS(30);
4205 *total
= COSTS_N_INSNS(1);
4209 if ((TARGET_DPFP
&& GET_MODE (x
) == DFmode
))
4210 *total
= COSTS_N_INSNS (1);
4212 *total
= arc_multcost
;
4213 /* We do not want synth_mult sequences when optimizing
4215 else if (TARGET_MUL64_SET
|| (TARGET_ARC700
&& !TARGET_NOMPY_SET
))
4216 *total
= COSTS_N_INSNS (1);
4218 *total
= COSTS_N_INSNS (2);
4221 if (GET_CODE (XEXP (x
, 0)) == MULT
4222 && _2_4_8_operand (XEXP (XEXP (x
, 0), 1), VOIDmode
))
4224 *total
+= (rtx_cost (XEXP (x
, 1), PLUS
, 0, speed
)
4225 + rtx_cost (XEXP (XEXP (x
, 0), 0), PLUS
, 1, speed
));
4230 if (GET_CODE (XEXP (x
, 1)) == MULT
4231 && _2_4_8_operand (XEXP (XEXP (x
, 1), 1), VOIDmode
))
4233 *total
+= (rtx_cost (XEXP (x
, 0), PLUS
, 0, speed
)
4234 + rtx_cost (XEXP (XEXP (x
, 1), 0), PLUS
, 1, speed
));
4240 rtx op0
= XEXP (x
, 0);
4241 rtx op1
= XEXP (x
, 1);
4243 if (GET_CODE (op0
) == ZERO_EXTRACT
&& op1
== const0_rtx
4244 && XEXP (op0
, 1) == const1_rtx
)
4246 /* btst / bbit0 / bbit1:
4247 Small integers and registers are free; everything else can
4248 be put in a register. */
4249 *total
= (rtx_cost (XEXP (op0
, 0), SET
, 1, speed
)
4250 + rtx_cost (XEXP (op0
, 2), SET
, 1, speed
));
4253 if (GET_CODE (op0
) == AND
&& op1
== const0_rtx
4254 && satisfies_constraint_C1p (XEXP (op0
, 1)))
4257 *total
= rtx_cost (XEXP (op0
, 0), SET
, 1, speed
);
4261 if (GET_CODE (op1
) == NEG
)
4263 /* op0 might be constant, the inside of op1 is rather
4264 unlikely to be so. So swapping the operands might lower
4266 *total
= (rtx_cost (op0
, PLUS
, 1, speed
)
4267 + rtx_cost (XEXP (op1
, 0), PLUS
, 0, speed
));
4272 if (outer_code
== IF_THEN_ELSE
4273 && GET_CODE (XEXP (x
, 0)) == ZERO_EXTRACT
4274 && XEXP (x
, 1) == const0_rtx
4275 && XEXP (XEXP (x
, 0), 1) == const1_rtx
)
4277 /* btst / bbit0 / bbit1:
4278 Small integers and registers are free; everything else can
4279 be put in a register. */
4280 rtx op0
= XEXP (x
, 0);
4282 *total
= (rtx_cost (XEXP (op0
, 0), SET
, 1, speed
)
4283 + rtx_cost (XEXP (op0
, 2), SET
, 1, speed
));
4287 /* scc_insn expands into two insns. */
4288 case GTU
: case GEU
: case LEU
:
4289 if (GET_MODE (x
) == SImode
)
4290 *total
+= COSTS_N_INSNS (1);
4292 case LTU
: /* might use adc. */
4293 if (GET_MODE (x
) == SImode
)
4294 *total
+= COSTS_N_INSNS (1) - 1;
4301 /* Return true if ADDR is an address that needs to be expressed as an
4302 explicit sum of pcl + offset. */
4305 arc_legitimate_pc_offset_p (rtx addr
)
4307 if (GET_CODE (addr
) != CONST
)
4309 addr
= XEXP (addr
, 0);
4310 if (GET_CODE (addr
) == PLUS
)
4312 if (GET_CODE (XEXP (addr
, 1)) != CONST_INT
)
4314 addr
= XEXP (addr
, 0);
4316 return (GET_CODE (addr
) == UNSPEC
4317 && XVECLEN (addr
, 0) == 1
4318 && XINT (addr
, 1) == ARC_UNSPEC_GOT
4319 && GET_CODE (XVECEXP (addr
, 0, 0)) == SYMBOL_REF
);
4322 /* Return true if ADDR is a valid pic address.
4323 A valid pic address on arc should look like
4324 const (unspec (SYMBOL_REF/LABEL) (ARC_UNSPEC_GOTOFF/ARC_UNSPEC_GOT)) */
4327 arc_legitimate_pic_addr_p (rtx addr
)
4329 if (GET_CODE (addr
) == LABEL_REF
)
4331 if (GET_CODE (addr
) != CONST
)
4334 addr
= XEXP (addr
, 0);
4337 if (GET_CODE (addr
) == PLUS
)
4339 if (GET_CODE (XEXP (addr
, 1)) != CONST_INT
)
4341 addr
= XEXP (addr
, 0);
4344 if (GET_CODE (addr
) != UNSPEC
4345 || XVECLEN (addr
, 0) != 1)
4348 /* Must be @GOT or @GOTOFF. */
4349 if (XINT (addr
, 1) != ARC_UNSPEC_GOT
4350 && XINT (addr
, 1) != ARC_UNSPEC_GOTOFF
)
4353 if (GET_CODE (XVECEXP (addr
, 0, 0)) != SYMBOL_REF
4354 && GET_CODE (XVECEXP (addr
, 0, 0)) != LABEL_REF
)
4362 /* Return true if OP contains a symbol reference. */
4365 symbolic_reference_mentioned_p (rtx op
)
4367 register const char *fmt
;
4370 if (GET_CODE (op
) == SYMBOL_REF
|| GET_CODE (op
) == LABEL_REF
)
4373 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
4374 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
4380 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
4381 if (symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
)))
4385 else if (fmt
[i
] == 'e' && symbolic_reference_mentioned_p (XEXP (op
, i
)))
4392 /* Return true if OP contains a SYMBOL_REF that is not wrapped in an unspec.
4393 If SKIP_LOCAL is true, skip symbols that bind locally.
4394 This is used further down in this file, and, without SKIP_LOCAL,
4395 in the addsi3 / subsi3 expanders when generating PIC code. */
4398 arc_raw_symbolic_reference_mentioned_p (rtx op
, bool skip_local
)
4400 register const char *fmt
;
4403 if (GET_CODE(op
) == UNSPEC
)
4406 if (GET_CODE (op
) == SYMBOL_REF
)
4408 tree decl
= SYMBOL_REF_DECL (op
);
4409 return !skip_local
|| !decl
|| !default_binds_local_p (decl
);
4412 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
4413 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
4419 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
4420 if (arc_raw_symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
),
4425 else if (fmt
[i
] == 'e'
4426 && arc_raw_symbolic_reference_mentioned_p (XEXP (op
, i
),
4434 /* Legitimize a pic address reference in ORIG.
4435 The return value is the legitimated address.
4436 If OLDX is non-zero, it is the target to assign the address to first. */
4439 arc_legitimize_pic_address (rtx orig
, rtx oldx
)
4448 if (GET_CODE (addr
) == LABEL_REF
)
4450 else if (GET_CODE (addr
) == SYMBOL_REF
4451 && (CONSTANT_POOL_ADDRESS_P (addr
)
4452 || SYMBOL_REF_LOCAL_P (addr
)))
4454 /* This symbol may be referenced via a displacement from the PIC
4455 base address (@GOTOFF). */
4457 /* FIXME: if we had a way to emit pc-relative adds that don't
4458 create a GOT entry, we could do without the use of the gp register. */
4459 crtl
->uses_pic_offset_table
= 1;
4460 pat
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, addr
), ARC_UNSPEC_GOTOFF
);
4461 pat
= gen_rtx_CONST (Pmode
, pat
);
4462 pat
= gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, pat
);
4465 oldx
= gen_reg_rtx (Pmode
);
4469 emit_move_insn (oldx
, pat
);
4474 else if (GET_CODE (addr
) == SYMBOL_REF
)
4476 /* This symbol must be referenced via a load from the
4477 Global Offset Table (@GOTPC). */
4479 pat
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, addr
), ARC_UNSPEC_GOT
);
4480 pat
= gen_rtx_CONST (Pmode
, pat
);
4481 pat
= gen_const_mem (Pmode
, pat
);
4484 oldx
= gen_reg_rtx (Pmode
);
4486 emit_move_insn (oldx
, pat
);
4491 if (GET_CODE (addr
) == CONST
)
4493 addr
= XEXP (addr
, 0);
4494 if (GET_CODE (addr
) == UNSPEC
)
4496 /* Check that the unspec is one of the ones we generate? */
4499 gcc_assert (GET_CODE (addr
) == PLUS
);
4502 if (GET_CODE (addr
) == PLUS
)
4504 rtx op0
= XEXP (addr
, 0), op1
= XEXP (addr
, 1);
4506 /* Check first to see if this is a constant offset from a @GOTOFF
4507 symbol reference. */
4508 if ((GET_CODE (op0
) == LABEL_REF
4509 || (GET_CODE (op0
) == SYMBOL_REF
4510 && (CONSTANT_POOL_ADDRESS_P (op0
)
4511 || SYMBOL_REF_LOCAL_P (op0
))))
4512 && GET_CODE (op1
) == CONST_INT
)
4514 /* FIXME: like above, could do without gp reference. */
4515 crtl
->uses_pic_offset_table
= 1;
4517 = gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, op0
), ARC_UNSPEC_GOTOFF
);
4518 pat
= gen_rtx_PLUS (Pmode
, pat
, op1
);
4519 pat
= gen_rtx_CONST (Pmode
, pat
);
4520 pat
= gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, pat
);
4524 emit_move_insn (oldx
, pat
);
4530 base
= arc_legitimize_pic_address (XEXP (addr
, 0), oldx
);
4531 pat
= arc_legitimize_pic_address (XEXP (addr
, 1),
4532 base
== oldx
? NULL_RTX
: oldx
);
4534 if (GET_CODE (pat
) == CONST_INT
)
4535 pat
= plus_constant (Pmode
, base
, INTVAL (pat
));
4538 if (GET_CODE (pat
) == PLUS
&& CONSTANT_P (XEXP (pat
, 1)))
4540 base
= gen_rtx_PLUS (Pmode
, base
, XEXP (pat
, 0));
4541 pat
= XEXP (pat
, 1);
4543 pat
= gen_rtx_PLUS (Pmode
, base
, pat
);
4552 /* Output address constant X to FILE, taking PIC into account. */
4555 arc_output_pic_addr_const (FILE * file
, rtx x
, int code
)
4560 switch (GET_CODE (x
))
4570 output_addr_const (file
, x
);
4572 /* Local functions do not get references through the PLT. */
4573 if (code
== 'P' && ! SYMBOL_REF_LOCAL_P (x
))
4574 fputs ("@plt", file
);
4578 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (XEXP (x
, 0)));
4579 assemble_name (file
, buf
);
4583 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (x
));
4584 assemble_name (file
, buf
);
4588 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
));
4592 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4596 if (GET_MODE (x
) == VOIDmode
)
4598 /* We can use %d if the number is one word and positive. */
4599 if (CONST_DOUBLE_HIGH (x
))
4600 fprintf (file
, HOST_WIDE_INT_PRINT_DOUBLE_HEX
,
4601 CONST_DOUBLE_HIGH (x
), CONST_DOUBLE_LOW (x
));
4602 else if (CONST_DOUBLE_LOW (x
) < 0)
4603 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, CONST_DOUBLE_LOW (x
));
4605 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, CONST_DOUBLE_LOW (x
));
4608 /* We can't handle floating point constants;
4609 PRINT_OPERAND must handle them. */
4610 output_operand_lossage ("floating constant misused");
4614 /* FIXME: Not needed here. */
4615 /* Some assemblers need integer constants to appear last (eg masm). */
4616 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
4618 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4619 fprintf (file
, "+");
4620 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4622 else if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
4624 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4625 if (INTVAL (XEXP (x
, 1)) >= 0)
4626 fprintf (file
, "+");
4627 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4634 /* Avoid outputting things like x-x or x+5-x,
4635 since some assemblers can't handle that. */
4636 x
= simplify_subtraction (x
);
4637 if (GET_CODE (x
) != MINUS
)
4640 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4641 fprintf (file
, "-");
4642 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
4643 && INTVAL (XEXP (x
, 1)) < 0)
4645 fprintf (file
, "(");
4646 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4647 fprintf (file
, ")");
4650 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4655 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4660 gcc_assert (XVECLEN (x
, 0) == 1);
4661 if (XINT (x
, 1) == ARC_UNSPEC_GOT
)
4662 fputs ("pcl,", file
);
4663 arc_output_pic_addr_const (file
, XVECEXP (x
, 0, 0), code
);
4664 switch (XINT (x
, 1))
4666 case ARC_UNSPEC_GOT
:
4667 fputs ("@gotpc", file
);
4669 case ARC_UNSPEC_GOTOFF
:
4670 fputs ("@gotoff", file
);
4672 case ARC_UNSPEC_PLT
:
4673 fputs ("@plt", file
);
4676 output_operand_lossage ("invalid UNSPEC as operand: %d", XINT (x
,1));
4682 output_operand_lossage ("invalid expression as operand");
4686 #define SYMBOLIC_CONST(X) \
4687 (GET_CODE (X) == SYMBOL_REF \
4688 || GET_CODE (X) == LABEL_REF \
4689 || (GET_CODE (X) == CONST && symbolic_reference_mentioned_p (X)))
4691 /* Emit insns to move operands[1] into operands[0]. */
4694 emit_pic_move (rtx
*operands
, enum machine_mode
)
4696 rtx temp
= reload_in_progress
? operands
[0] : gen_reg_rtx (Pmode
);
4698 if (GET_CODE (operands
[0]) == MEM
&& SYMBOLIC_CONST (operands
[1]))
4699 operands
[1] = force_reg (Pmode
, operands
[1]);
4701 operands
[1] = arc_legitimize_pic_address (operands
[1], temp
);
4705 /* The function returning the number of words, at the beginning of an
4706 argument, must be put in registers. The returned value must be
4707 zero for arguments that are passed entirely in registers or that
4708 are entirely pushed on the stack.
4710 On some machines, certain arguments must be passed partially in
4711 registers and partially in memory. On these machines, typically
4712 the first N words of arguments are passed in registers, and the
4713 rest on the stack. If a multi-word argument (a `double' or a
4714 structure) crosses that boundary, its first few words must be
4715 passed in registers and the rest must be pushed. This function
4716 tells the compiler when this occurs, and how many of the words
4717 should go in registers.
4719 `FUNCTION_ARG' for these arguments should return the first register
4720 to be used by the caller for this argument; likewise
4721 `FUNCTION_INCOMING_ARG', for the called function.
4723 The function is used to implement macro FUNCTION_ARG_PARTIAL_NREGS. */
4725 /* If REGNO is the least arg reg available then what is the total number of arg
4727 #define GPR_REST_ARG_REGS(REGNO) \
4728 ((REGNO) <= MAX_ARC_PARM_REGS ? MAX_ARC_PARM_REGS - (REGNO) : 0 )
4730 /* Since arc parm regs are contiguous. */
4731 #define ARC_NEXT_ARG_REG(REGNO) ( (REGNO) + 1 )
4733 /* Implement TARGET_ARG_PARTIAL_BYTES. */
4736 arc_arg_partial_bytes (cumulative_args_t cum_v
, enum machine_mode mode
,
4737 tree type
, bool named ATTRIBUTE_UNUSED
)
4739 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
4740 int bytes
= (mode
== BLKmode
4741 ? int_size_in_bytes (type
) : (int) GET_MODE_SIZE (mode
));
4742 int words
= (bytes
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
4746 arg_num
= ROUND_ADVANCE_CUM (arg_num
, mode
, type
);
4747 ret
= GPR_REST_ARG_REGS (arg_num
);
4749 /* ICEd at function.c:2361, and ret is copied to data->partial */
4750 ret
= (ret
>= words
? 0 : ret
* UNITS_PER_WORD
);
4757 /* This function is used to control a function argument is passed in a
4758 register, and which register.
4760 The arguments are CUM, of type CUMULATIVE_ARGS, which summarizes
4761 (in a way defined by INIT_CUMULATIVE_ARGS and FUNCTION_ARG_ADVANCE)
4762 all of the previous arguments so far passed in registers; MODE, the
4763 machine mode of the argument; TYPE, the data type of the argument
4764 as a tree node or 0 if that is not known (which happens for C
4765 support library functions); and NAMED, which is 1 for an ordinary
4766 argument and 0 for nameless arguments that correspond to `...' in
4767 the called function's prototype.
4769 The returned value should either be a `reg' RTX for the hard
4770 register in which to pass the argument, or zero to pass the
4771 argument on the stack.
4773 For machines like the Vax and 68000, where normally all arguments
4774 are pushed, zero suffices as a definition.
4776 The usual way to make the ANSI library `stdarg.h' work on a machine
4777 where some arguments are usually passed in registers, is to cause
4778 nameless arguments to be passed on the stack instead. This is done
4779 by making the function return 0 whenever NAMED is 0.
4781 You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the
4782 definition of this function to determine if this argument is of a
4783 type that must be passed in the stack. If `REG_PARM_STACK_SPACE'
4784 is not defined and the function returns non-zero for such an
4785 argument, the compiler will abort. If `REG_PARM_STACK_SPACE' is
4786 defined, the argument will be computed in the stack and then loaded
4789 The function is used to implement macro FUNCTION_ARG. */
4790 /* On the ARC the first MAX_ARC_PARM_REGS args are normally in registers
4791 and the rest are pushed. */
4794 arc_function_arg (cumulative_args_t cum_v
, enum machine_mode mode
,
4795 const_tree type ATTRIBUTE_UNUSED
, bool named ATTRIBUTE_UNUSED
)
4797 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
4800 const char *debstr ATTRIBUTE_UNUSED
;
4802 arg_num
= ROUND_ADVANCE_CUM (arg_num
, mode
, type
);
4803 /* Return a marker for use in the call instruction. */
4804 if (mode
== VOIDmode
)
4809 else if (GPR_REST_ARG_REGS (arg_num
) > 0)
4811 ret
= gen_rtx_REG (mode
, arg_num
);
4812 debstr
= reg_names
[arg_num
];
4822 /* The function to update the summarizer variable *CUM to advance past
4823 an argument in the argument list. The values MODE, TYPE and NAMED
4824 describe that argument. Once this is done, the variable *CUM is
4825 suitable for analyzing the *following* argument with
4826 `FUNCTION_ARG', etc.
4828 This function need not do anything if the argument in question was
4829 passed on the stack. The compiler knows how to track the amount of
4830 stack space used for arguments without any special help.
4832 The function is used to implement macro FUNCTION_ARG_ADVANCE. */
4833 /* For the ARC: the cum set here is passed on to function_arg where we
4834 look at its value and say which reg to use. Strategy: advance the
4835 regnumber here till we run out of arg regs, then set *cum to last
4836 reg. In function_arg, since *cum > last arg reg we would return 0
4837 and thus the arg will end up on the stack. For straddling args of
4838 course function_arg_partial_nregs will come into play. */
4841 arc_function_arg_advance (cumulative_args_t cum_v
, enum machine_mode mode
,
4842 const_tree type
, bool named ATTRIBUTE_UNUSED
)
4844 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
4845 int bytes
= (mode
== BLKmode
4846 ? int_size_in_bytes (type
) : (int) GET_MODE_SIZE (mode
));
4847 int words
= (bytes
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
4851 *cum
= ROUND_ADVANCE_CUM (*cum
, mode
, type
);
4852 for (i
= 0; i
< words
; i
++)
4853 *cum
= ARC_NEXT_ARG_REG (*cum
);
4857 /* Define how to find the value returned by a function.
4858 VALTYPE is the data type of the value (as a tree).
4859 If the precise function being called is known, FN_DECL_OR_TYPE is its
4860 FUNCTION_DECL; otherwise, FN_DECL_OR_TYPE is its type. */
4863 arc_function_value (const_tree valtype
,
4864 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
4865 bool outgoing ATTRIBUTE_UNUSED
)
4867 enum machine_mode mode
= TYPE_MODE (valtype
);
4868 int unsignedp ATTRIBUTE_UNUSED
;
4870 unsignedp
= TYPE_UNSIGNED (valtype
);
4871 if (INTEGRAL_TYPE_P (valtype
) || TREE_CODE (valtype
) == OFFSET_TYPE
)
4872 PROMOTE_MODE (mode
, unsignedp
, valtype
);
4873 return gen_rtx_REG (mode
, 0);
4876 /* Returns the return address that is used by builtin_return_address. */
4879 arc_return_addr_rtx (int count
, ATTRIBUTE_UNUSED rtx frame
)
4884 return get_hard_reg_initial_val (Pmode
, RETURN_ADDR_REGNUM
);
4887 /* Nonzero if the constant value X is a legitimate general operand
4888 when generating PIC code. It is given that flag_pic is on and
4889 that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
4892 arc_legitimate_pic_operand_p (rtx x
)
4894 return !arc_raw_symbolic_reference_mentioned_p (x
, true);
4897 /* Determine if a given RTX is a valid constant. We already know this
4898 satisfies CONSTANT_P. */
4901 arc_legitimate_constant_p (enum machine_mode
, rtx x
)
4906 switch (GET_CODE (x
))
4911 if (GET_CODE (x
) == PLUS
)
4913 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
4918 /* Only some unspecs are valid as "constants". */
4919 if (GET_CODE (x
) == UNSPEC
)
4920 switch (XINT (x
, 1))
4922 case ARC_UNSPEC_PLT
:
4923 case ARC_UNSPEC_GOTOFF
:
4924 case ARC_UNSPEC_GOT
:
4932 /* We must have drilled down to a symbol. */
4933 if (arc_raw_symbolic_reference_mentioned_p (x
, false))
4947 /* Otherwise we handle everything else in the move patterns. */
4952 arc_legitimate_address_p (enum machine_mode mode
, rtx x
, bool strict
)
4954 if (RTX_OK_FOR_BASE_P (x
, strict
))
4956 if (LEGITIMATE_OFFSET_ADDRESS_P (mode
, x
, TARGET_INDEXED_LOADS
, strict
))
4958 if (LEGITIMATE_SCALED_ADDRESS_P (mode
, x
, strict
))
4960 if (LEGITIMATE_SMALL_DATA_ADDRESS_P (x
))
4962 if (GET_CODE (x
) == CONST_INT
&& LARGE_INT (INTVAL (x
)))
4964 if ((GET_MODE_SIZE (mode
) != 16)
4965 && (GET_CODE (x
) == SYMBOL_REF
4966 || GET_CODE (x
) == LABEL_REF
4967 || GET_CODE (x
) == CONST
))
4969 if (!flag_pic
|| arc_legitimate_pic_addr_p (x
))
4972 if ((GET_CODE (x
) == PRE_DEC
|| GET_CODE (x
) == PRE_INC
4973 || GET_CODE (x
) == POST_DEC
|| GET_CODE (x
) == POST_INC
)
4974 && RTX_OK_FOR_BASE_P (XEXP (x
, 0), strict
))
4976 /* We're restricted here by the `st' insn. */
4977 if ((GET_CODE (x
) == PRE_MODIFY
|| GET_CODE (x
) == POST_MODIFY
)
4978 && GET_CODE (XEXP ((x
), 1)) == PLUS
4979 && rtx_equal_p (XEXP ((x
), 0), XEXP (XEXP (x
, 1), 0))
4980 && LEGITIMATE_OFFSET_ADDRESS_P (QImode
, XEXP (x
, 1),
4981 TARGET_AUTO_MODIFY_REG
, strict
))
4986 /* Return true iff ADDR (a legitimate address expression)
4987 has an effect that depends on the machine mode it is used for. */
4990 arc_mode_dependent_address_p (const_rtx addr
, addr_space_t
)
4992 /* SYMBOL_REF is not mode dependent: it is either a small data reference,
4993 which is valid for loads and stores, or a limm offset, which is valid for
4995 /* Scaled indices are scaled by the access mode; likewise for scaled
4996 offsets, which are needed for maximum offset stores. */
4997 if (GET_CODE (addr
) == PLUS
4998 && (GET_CODE (XEXP ((addr
), 0)) == MULT
4999 || (CONST_INT_P (XEXP ((addr
), 1))
5000 && !SMALL_INT (INTVAL (XEXP ((addr
), 1))))))
5005 /* Determine if it's legal to put X into the constant pool. */
5008 arc_cannot_force_const_mem (enum machine_mode mode
, rtx x
)
5010 return !arc_legitimate_constant_p (mode
, x
);
5014 /* Generic function to define a builtin. */
5015 #define def_mbuiltin(MASK, NAME, TYPE, CODE) \
5019 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL, NULL_TREE); \
5025 arc_init_builtins (void)
5027 tree endlink
= void_list_node
;
5029 tree void_ftype_void
5030 = build_function_type (void_type_node
,
5034 = build_function_type (integer_type_node
,
5035 tree_cons (NULL_TREE
, integer_type_node
, endlink
));
5037 tree pcvoid_type_node
5038 = build_pointer_type (build_qualified_type (void_type_node
, TYPE_QUAL_CONST
));
5039 tree int_ftype_pcvoid_int
5040 = build_function_type (integer_type_node
,
5041 tree_cons (NULL_TREE
, pcvoid_type_node
,
5042 tree_cons (NULL_TREE
, integer_type_node
,
5045 tree int_ftype_short_int
5046 = build_function_type (integer_type_node
,
5047 tree_cons (NULL_TREE
, short_integer_type_node
, endlink
));
5049 tree void_ftype_int_int
5050 = build_function_type (void_type_node
,
5051 tree_cons (NULL_TREE
, integer_type_node
,
5052 tree_cons (NULL_TREE
, integer_type_node
, endlink
)));
5053 tree void_ftype_usint_usint
5054 = build_function_type (void_type_node
,
5055 tree_cons (NULL_TREE
, long_unsigned_type_node
,
5056 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
)));
5058 tree int_ftype_int_int
5059 = build_function_type (integer_type_node
,
5060 tree_cons (NULL_TREE
, integer_type_node
,
5061 tree_cons (NULL_TREE
, integer_type_node
, endlink
)));
5063 tree usint_ftype_usint
5064 = build_function_type (long_unsigned_type_node
,
5065 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
));
5067 tree void_ftype_usint
5068 = build_function_type (void_type_node
,
5069 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
));
5071 /* Add the builtins. */
5072 def_mbuiltin (1,"__builtin_arc_nop", void_ftype_void
, ARC_BUILTIN_NOP
);
5073 def_mbuiltin (TARGET_NORM
, "__builtin_arc_norm", int_ftype_int
, ARC_BUILTIN_NORM
);
5074 def_mbuiltin (TARGET_NORM
, "__builtin_arc_normw", int_ftype_short_int
, ARC_BUILTIN_NORMW
);
5075 def_mbuiltin (TARGET_SWAP
, "__builtin_arc_swap", int_ftype_int
, ARC_BUILTIN_SWAP
);
5076 def_mbuiltin (TARGET_MUL64_SET
,"__builtin_arc_mul64", void_ftype_int_int
, ARC_BUILTIN_MUL64
);
5077 def_mbuiltin (TARGET_MUL64_SET
,"__builtin_arc_mulu64", void_ftype_usint_usint
, ARC_BUILTIN_MULU64
);
5078 def_mbuiltin (1,"__builtin_arc_rtie", void_ftype_void
, ARC_BUILTIN_RTIE
);
5079 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_sync", void_ftype_void
, ARC_BUILTIN_SYNC
);
5080 def_mbuiltin ((TARGET_EA_SET
),"__builtin_arc_divaw", int_ftype_int_int
, ARC_BUILTIN_DIVAW
);
5081 def_mbuiltin (1,"__builtin_arc_brk", void_ftype_void
, ARC_BUILTIN_BRK
);
5082 def_mbuiltin (1,"__builtin_arc_flag", void_ftype_usint
, ARC_BUILTIN_FLAG
);
5083 def_mbuiltin (1,"__builtin_arc_sleep", void_ftype_usint
, ARC_BUILTIN_SLEEP
);
5084 def_mbuiltin (1,"__builtin_arc_swi", void_ftype_void
, ARC_BUILTIN_SWI
);
5085 def_mbuiltin (1,"__builtin_arc_core_read", usint_ftype_usint
, ARC_BUILTIN_CORE_READ
);
5086 def_mbuiltin (1,"__builtin_arc_core_write", void_ftype_usint_usint
, ARC_BUILTIN_CORE_WRITE
);
5087 def_mbuiltin (1,"__builtin_arc_lr", usint_ftype_usint
, ARC_BUILTIN_LR
);
5088 def_mbuiltin (1,"__builtin_arc_sr", void_ftype_usint_usint
, ARC_BUILTIN_SR
);
5089 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_trap_s", void_ftype_usint
, ARC_BUILTIN_TRAP_S
);
5090 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_unimp_s", void_ftype_void
, ARC_BUILTIN_UNIMP_S
);
5091 def_mbuiltin (1,"__builtin_arc_aligned", int_ftype_pcvoid_int
, ARC_BUILTIN_ALIGNED
);
5093 if (TARGET_SIMD_SET
)
5094 arc_init_simd_builtins ();
5097 static rtx
arc_expand_simd_builtin (tree
, rtx
, rtx
, enum machine_mode
, int);
5099 /* Expand an expression EXP that calls a built-in function,
5100 with result going to TARGET if that's convenient
5101 (and in mode MODE if that's convenient).
5102 SUBTARGET may be used as the target for computing one of EXP's operands.
5103 IGNORE is nonzero if the value is to be ignored. */
5106 arc_expand_builtin (tree exp
,
5109 enum machine_mode mode
,
5112 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
5117 int fcode
= DECL_FUNCTION_CODE (fndecl
);
5119 enum machine_mode mode0
;
5120 enum machine_mode mode1
;
5122 if (fcode
> ARC_SIMD_BUILTIN_BEGIN
&& fcode
< ARC_SIMD_BUILTIN_END
)
5123 return arc_expand_simd_builtin (exp
, target
, subtarget
, mode
, ignore
);
5127 case ARC_BUILTIN_NOP
:
5128 emit_insn (gen_nop ());
5131 case ARC_BUILTIN_NORM
:
5132 icode
= CODE_FOR_clrsbsi2
;
5133 arg0
= CALL_EXPR_ARG (exp
, 0);
5134 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5135 mode0
= insn_data
[icode
].operand
[1].mode
;
5136 target
= gen_reg_rtx (SImode
);
5138 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5139 op0
= copy_to_mode_reg (mode0
, op0
);
5141 emit_insn (gen_clrsbsi2 (target
, op0
));
5144 case ARC_BUILTIN_NORMW
:
5146 /* FIXME : This should all be HImode, not SImode. */
5147 icode
= CODE_FOR_normw
;
5148 arg0
= CALL_EXPR_ARG (exp
, 0);
5149 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5150 mode0
= insn_data
[icode
].operand
[1].mode
;
5151 target
= gen_reg_rtx (SImode
);
5153 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5154 op0
= copy_to_mode_reg (mode0
, convert_to_mode (mode0
, op0
,0));
5156 emit_insn (gen_normw (target
, op0
));
5159 case ARC_BUILTIN_MUL64
:
5160 icode
= CODE_FOR_mul64
;
5161 arg0
= CALL_EXPR_ARG (exp
, 0);
5162 arg1
= CALL_EXPR_ARG (exp
, 1);
5163 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5164 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5166 mode0
= insn_data
[icode
].operand
[0].mode
;
5167 mode1
= insn_data
[icode
].operand
[1].mode
;
5169 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5170 op0
= copy_to_mode_reg (mode0
, op0
);
5172 if (! (*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
5173 op1
= copy_to_mode_reg (mode1
, op1
);
5175 emit_insn (gen_mul64 (op0
,op1
));
5178 case ARC_BUILTIN_MULU64
:
5179 icode
= CODE_FOR_mulu64
;
5180 arg0
= CALL_EXPR_ARG (exp
, 0);
5181 arg1
= CALL_EXPR_ARG (exp
, 1);
5182 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5183 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5185 mode0
= insn_data
[icode
].operand
[0].mode
;
5186 mode1
= insn_data
[icode
].operand
[1].mode
;
5188 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5189 op0
= copy_to_mode_reg (mode0
, op0
);
5191 if (! (*insn_data
[icode
].operand
[0].predicate
) (op1
, mode1
))
5192 op1
= copy_to_mode_reg (mode1
, op1
);
5194 emit_insn (gen_mulu64 (op0
,op1
));
5197 case ARC_BUILTIN_RTIE
:
5198 icode
= CODE_FOR_rtie
;
5199 emit_insn (gen_rtie (const1_rtx
));
5202 case ARC_BUILTIN_SYNC
:
5203 icode
= CODE_FOR_sync
;
5204 emit_insn (gen_sync (const1_rtx
));
5207 case ARC_BUILTIN_SWAP
:
5208 icode
= CODE_FOR_swap
;
5209 arg0
= CALL_EXPR_ARG (exp
, 0);
5210 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5211 mode0
= insn_data
[icode
].operand
[1].mode
;
5212 target
= gen_reg_rtx (SImode
);
5214 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5215 op0
= copy_to_mode_reg (mode0
, op0
);
5217 emit_insn (gen_swap (target
, op0
));
5220 case ARC_BUILTIN_DIVAW
:
5221 icode
= CODE_FOR_divaw
;
5222 arg0
= CALL_EXPR_ARG (exp
, 0);
5223 arg1
= CALL_EXPR_ARG (exp
, 1);
5225 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5226 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5227 target
= gen_reg_rtx (SImode
);
5229 mode0
= insn_data
[icode
].operand
[0].mode
;
5230 mode1
= insn_data
[icode
].operand
[1].mode
;
5232 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5233 op0
= copy_to_mode_reg (mode0
, op0
);
5235 if (! (*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
5236 op1
= copy_to_mode_reg (mode1
, op1
);
5238 emit_insn (gen_divaw (target
, op0
, op1
));
5241 case ARC_BUILTIN_BRK
:
5242 icode
= CODE_FOR_brk
;
5243 emit_insn (gen_brk (const1_rtx
));
5246 case ARC_BUILTIN_SLEEP
:
5247 icode
= CODE_FOR_sleep
;
5248 arg0
= CALL_EXPR_ARG (exp
, 0);
5252 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5253 mode0
= insn_data
[icode
].operand
[1].mode
;
5255 emit_insn (gen_sleep (op0
));
5258 case ARC_BUILTIN_SWI
:
5259 icode
= CODE_FOR_swi
;
5260 emit_insn (gen_swi (const1_rtx
));
5263 case ARC_BUILTIN_FLAG
:
5264 icode
= CODE_FOR_flag
;
5265 arg0
= CALL_EXPR_ARG (exp
, 0);
5266 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5267 mode0
= insn_data
[icode
].operand
[0].mode
;
5269 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5270 op0
= copy_to_mode_reg (mode0
, op0
);
5272 emit_insn (gen_flag (op0
));
5275 case ARC_BUILTIN_CORE_READ
:
5276 icode
= CODE_FOR_core_read
;
5277 arg0
= CALL_EXPR_ARG (exp
, 0);
5278 target
= gen_reg_rtx (SImode
);
5282 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5283 mode0
= insn_data
[icode
].operand
[1].mode
;
5285 emit_insn (gen_core_read (target
, op0
));
5288 case ARC_BUILTIN_CORE_WRITE
:
5289 icode
= CODE_FOR_core_write
;
5290 arg0
= CALL_EXPR_ARG (exp
, 0);
5291 arg1
= CALL_EXPR_ARG (exp
, 1);
5295 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5296 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5298 mode0
= insn_data
[icode
].operand
[0].mode
;
5299 mode1
= insn_data
[icode
].operand
[1].mode
;
5301 emit_insn (gen_core_write (op0
, op1
));
5304 case ARC_BUILTIN_LR
:
5305 icode
= CODE_FOR_lr
;
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_lr (target
, op0
));
5317 case ARC_BUILTIN_SR
:
5318 icode
= CODE_FOR_sr
;
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_sr (op0
, op1
));
5333 case ARC_BUILTIN_TRAP_S
:
5334 icode
= CODE_FOR_trap_s
;
5335 arg0
= CALL_EXPR_ARG (exp
, 0);
5339 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5340 mode0
= insn_data
[icode
].operand
[1].mode
;
5342 /* We don't give an error for non-cost values here because
5343 we still want to allow things to be fixed up by later inlining /
5344 constant folding / dead code elimination. */
5345 if (CONST_INT_P (op0
) && !satisfies_constraint_L (op0
))
5347 /* Keep this message in sync with the one in arc.md:trap_s,
5348 because *.md files don't get scanned by exgettext. */
5349 error ("operand to trap_s should be an unsigned 6-bit value");
5351 emit_insn (gen_trap_s (op0
));
5354 case ARC_BUILTIN_UNIMP_S
:
5355 icode
= CODE_FOR_unimp_s
;
5356 emit_insn (gen_unimp_s (const1_rtx
));
5359 case ARC_BUILTIN_ALIGNED
:
5360 /* __builtin_arc_aligned (void* val, int alignval) */
5361 arg0
= CALL_EXPR_ARG (exp
, 0);
5362 arg1
= CALL_EXPR_ARG (exp
, 1);
5364 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5365 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5366 target
= gen_reg_rtx (SImode
);
5368 if (!CONST_INT_P (op1
))
5370 /* If we can't fold the alignment to a constant integer
5371 whilst optimizing, this is probably a user error. */
5373 warning (0, "__builtin_arc_aligned with non-constant alignment");
5377 HOST_WIDE_INT alignTest
= INTVAL (op1
);
5378 /* Check alignTest is positive, and a power of two. */
5379 if (alignTest
<= 0 || alignTest
!= (alignTest
& -alignTest
))
5381 error ("invalid alignment value for __builtin_arc_aligned");
5385 if (CONST_INT_P (op0
))
5387 HOST_WIDE_INT pnt
= INTVAL (op0
);
5389 if ((pnt
& (alignTest
- 1)) == 0)
5394 unsigned align
= get_pointer_alignment (arg0
);
5395 unsigned numBits
= alignTest
* BITS_PER_UNIT
;
5397 if (align
&& align
>= numBits
)
5399 /* Another attempt to ascertain alignment. Check the type
5400 we are pointing to. */
5401 if (POINTER_TYPE_P (TREE_TYPE (arg0
))
5402 && TYPE_ALIGN (TREE_TYPE (TREE_TYPE (arg0
))) >= numBits
)
5407 /* Default to false. */
5414 /* @@@ Should really do something sensible here. */
5418 /* Returns true if the operands[opno] is a valid compile-time constant to be
5419 used as register number in the code for builtins. Else it flags an error
5420 and returns false. */
5423 check_if_valid_regno_const (rtx
*operands
, int opno
)
5426 switch (GET_CODE (operands
[opno
]))
5433 error ("register number must be a compile-time constant. Try giving higher optimization levels");
5439 /* Check that after all the constant folding, whether the operand to
5440 __builtin_arc_sleep is an unsigned int of 6 bits. If not, flag an error. */
5443 check_if_valid_sleep_operand (rtx
*operands
, int opno
)
5445 switch (GET_CODE (operands
[opno
]))
5449 if( UNSIGNED_INT6 (INTVAL (operands
[opno
])))
5452 fatal_error("operand for sleep instruction must be an unsigned 6 bit compile-time constant");
5458 /* Return true if it is ok to make a tail-call to DECL. */
5461 arc_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED
,
5462 tree exp ATTRIBUTE_UNUSED
)
5464 /* Never tailcall from an ISR routine - it needs a special exit sequence. */
5465 if (ARC_INTERRUPT_P (arc_compute_function_type (cfun
)))
5468 /* Everything else is ok. */
5472 /* Output code to add DELTA to the first argument, and then jump
5473 to FUNCTION. Used for C++ multiple inheritance. */
5476 arc_output_mi_thunk (FILE *file
, tree thunk ATTRIBUTE_UNUSED
,
5477 HOST_WIDE_INT delta
,
5478 HOST_WIDE_INT vcall_offset
,
5481 int mi_delta
= delta
;
5482 const char *const mi_op
= mi_delta
< 0 ? "sub" : "add";
5485 = aggregate_value_p (TREE_TYPE (TREE_TYPE (function
)), function
) ? 1 : 0;
5489 mi_delta
= - mi_delta
;
5491 /* Add DELTA. When possible use a plain add, otherwise load it into
5492 a register first. */
5494 while (mi_delta
!= 0)
5496 if ((mi_delta
& (3 << shift
)) == 0)
5500 asm_fprintf (file
, "\t%s\t%s, %s, %d\n",
5501 mi_op
, reg_names
[this_regno
], reg_names
[this_regno
],
5502 mi_delta
& (0xff << shift
));
5503 mi_delta
&= ~(0xff << shift
);
5508 /* If needed, add *(*THIS + VCALL_OFFSET) to THIS. */
5509 if (vcall_offset
!= 0)
5511 /* ld r12,[this] --> temp = *this
5512 add r12,r12,vcall_offset --> temp = *(*this + vcall_offset)
5514 add this,this,r12 --> this+ = *(*this + vcall_offset) */
5515 asm_fprintf (file
, "\tld\t%s, [%s]\n",
5516 ARC_TEMP_SCRATCH_REG
, reg_names
[this_regno
]);
5517 asm_fprintf (file
, "\tadd\t%s, %s, %ld\n",
5518 ARC_TEMP_SCRATCH_REG
, ARC_TEMP_SCRATCH_REG
, vcall_offset
);
5519 asm_fprintf (file
, "\tld\t%s, [%s]\n",
5520 ARC_TEMP_SCRATCH_REG
, ARC_TEMP_SCRATCH_REG
);
5521 asm_fprintf (file
, "\tadd\t%s, %s, %s\n", reg_names
[this_regno
],
5522 reg_names
[this_regno
], ARC_TEMP_SCRATCH_REG
);
5525 fnaddr
= XEXP (DECL_RTL (function
), 0);
5527 if (arc_is_longcall_p (fnaddr
))
5528 fputs ("\tj\t", file
);
5530 fputs ("\tb\t", file
);
5531 assemble_name (file
, XSTR (fnaddr
, 0));
5535 /* Return true if a 32 bit "long_call" should be generated for
5536 this calling SYM_REF. We generate a long_call if the function:
5538 a. has an __attribute__((long call))
5539 or b. the -mlong-calls command line switch has been specified
5541 However we do not generate a long call if the function has an
5542 __attribute__ ((short_call)) or __attribute__ ((medium_call))
5544 This function will be called by C fragments contained in the machine
5545 description file. */
5548 arc_is_longcall_p (rtx sym_ref
)
5550 if (GET_CODE (sym_ref
) != SYMBOL_REF
)
5553 return (SYMBOL_REF_LONG_CALL_P (sym_ref
)
5554 || (TARGET_LONG_CALLS_SET
5555 && !SYMBOL_REF_SHORT_CALL_P (sym_ref
)
5556 && !SYMBOL_REF_MEDIUM_CALL_P (sym_ref
)));
5560 /* Likewise for short calls. */
5563 arc_is_shortcall_p (rtx sym_ref
)
5565 if (GET_CODE (sym_ref
) != SYMBOL_REF
)
5568 return (SYMBOL_REF_SHORT_CALL_P (sym_ref
)
5569 || (!TARGET_LONG_CALLS_SET
&& !TARGET_MEDIUM_CALLS
5570 && !SYMBOL_REF_LONG_CALL_P (sym_ref
)
5571 && !SYMBOL_REF_MEDIUM_CALL_P (sym_ref
)));
5575 /* Emit profiling code for calling CALLEE. Return true if a special
5576 call pattern needs to be generated. */
5579 arc_profile_call (rtx callee
)
5581 rtx from
= XEXP (DECL_RTL (current_function_decl
), 0);
5583 if (TARGET_UCB_MCOUNT
)
5584 /* Profiling is done by instrumenting the callee. */
5587 if (CONSTANT_P (callee
))
5590 = gen_rtx_CONST (Pmode
,
5591 gen_rtx_UNSPEC (Pmode
,
5592 gen_rtvec (3, from
, callee
,
5593 CONST0_RTX (Pmode
)),
5595 rtx counter
= gen_rtx_MEM (SImode
, count_ptr
);
5596 /* ??? The increment would better be done atomically, but as there is
5597 no proper hardware support, that would be too expensive. */
5598 emit_move_insn (counter
,
5599 force_reg (SImode
, plus_constant (SImode
, counter
, 1)));
5605 = gen_rtx_CONST (Pmode
,
5606 gen_rtx_UNSPEC (Pmode
,
5607 gen_rtvec (3, from
, CONST0_RTX (Pmode
),
5608 CONST0_RTX (Pmode
)),
5610 emit_move_insn (gen_rtx_REG (Pmode
, 8), count_list_ptr
);
5611 emit_move_insn (gen_rtx_REG (Pmode
, 9), callee
);
5616 /* Worker function for TARGET_RETURN_IN_MEMORY. */
5619 arc_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
5621 if (AGGREGATE_TYPE_P (type
) || TREE_ADDRESSABLE (type
))
5625 HOST_WIDE_INT size
= int_size_in_bytes (type
);
5626 return (size
== -1 || size
> 8);
5631 /* This was in rtlanal.c, and can go in there when we decide we want
5632 to submit the change for inclusion in the GCC tree. */
5633 /* Like note_stores, but allow the callback to have side effects on the rtl
5634 (like the note_stores of yore):
5635 Call FUN on each register or MEM that is stored into or clobbered by X.
5636 (X would be the pattern of an insn). DATA is an arbitrary pointer,
5637 ignored by note_stores, but passed to FUN.
5638 FUN may alter parts of the RTL.
5640 FUN receives three arguments:
5641 1. the REG, MEM, CC0 or PC being stored in or clobbered,
5642 2. the SET or CLOBBER rtx that does the store,
5643 3. the pointer DATA provided to note_stores.
5645 If the item being stored in or clobbered is a SUBREG of a hard register,
5646 the SUBREG will be passed. */
5648 /* For now. */ static
5650 walk_stores (rtx x
, void (*fun
) (rtx
, rtx
, void *), void *data
)
5654 if (GET_CODE (x
) == COND_EXEC
)
5655 x
= COND_EXEC_CODE (x
);
5657 if (GET_CODE (x
) == SET
|| GET_CODE (x
) == CLOBBER
)
5659 rtx dest
= SET_DEST (x
);
5661 while ((GET_CODE (dest
) == SUBREG
5662 && (!REG_P (SUBREG_REG (dest
))
5663 || REGNO (SUBREG_REG (dest
)) >= FIRST_PSEUDO_REGISTER
))
5664 || GET_CODE (dest
) == ZERO_EXTRACT
5665 || GET_CODE (dest
) == STRICT_LOW_PART
)
5666 dest
= XEXP (dest
, 0);
5668 /* If we have a PARALLEL, SET_DEST is a list of EXPR_LIST expressions,
5669 each of whose first operand is a register. */
5670 if (GET_CODE (dest
) == PARALLEL
)
5672 for (i
= XVECLEN (dest
, 0) - 1; i
>= 0; i
--)
5673 if (XEXP (XVECEXP (dest
, 0, i
), 0) != 0)
5674 (*fun
) (XEXP (XVECEXP (dest
, 0, i
), 0), x
, data
);
5677 (*fun
) (dest
, x
, data
);
5680 else if (GET_CODE (x
) == PARALLEL
)
5681 for (i
= XVECLEN (x
, 0) - 1; i
>= 0; i
--)
5682 walk_stores (XVECEXP (x
, 0, i
), fun
, data
);
5686 arc_pass_by_reference (cumulative_args_t ca_v ATTRIBUTE_UNUSED
,
5687 enum machine_mode mode ATTRIBUTE_UNUSED
,
5689 bool named ATTRIBUTE_UNUSED
)
5692 && (TREE_CODE (TYPE_SIZE (type
)) != INTEGER_CST
5693 || TREE_ADDRESSABLE (type
)));
5696 /* Implement TARGET_CAN_USE_DOLOOP_P. */
5699 arc_can_use_doloop_p (double_int iterations
, double_int
,
5700 unsigned int loop_depth
, bool entered_at_top
)
5704 /* Setting up the loop with two sr instructions costs 6 cycles. */
5707 && iterations
.high
== 0
5708 && iterations
.low
> 0
5709 && iterations
.low
<= (flag_pic
? 6 : 3))
5714 /* NULL if INSN insn is valid within a low-overhead loop.
5715 Otherwise return why doloop cannot be applied. */
5718 arc_invalid_within_doloop (const_rtx insn
)
5721 return "Function call in the loop.";
5725 static int arc_reorg_in_progress
= 0;
5727 /* ARC's machince specific reorg function. */
5737 cfun
->machine
->arc_reorg_started
= 1;
5738 arc_reorg_in_progress
= 1;
5740 /* Emit special sections for profiling. */
5743 section
*save_text_section
;
5745 int size
= get_max_uid () >> 4;
5746 htab_t htab
= htab_create (size
, unspec_prof_hash
, unspec_prof_htab_eq
,
5749 save_text_section
= in_section
;
5750 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
5751 if (NONJUMP_INSN_P (insn
))
5752 walk_stores (PATTERN (insn
), write_profile_sections
, htab
);
5753 if (htab_elements (htab
))
5755 switch_to_section (save_text_section
);
5759 /* Link up loop ends with their loop start. */
5761 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
5762 if (GET_CODE (insn
) == JUMP_INSN
5763 && recog_memoized (insn
) == CODE_FOR_doloop_end_i
)
5766 = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn
), 0, 0)), 1), 0);
5767 rtx num
= GEN_INT (CODE_LABEL_NUMBER (top_label
));
5768 rtx lp
, prev
= prev_nonnote_insn (top_label
);
5769 rtx lp_simple
= NULL_RTX
;
5770 rtx next
= NULL_RTX
;
5771 rtx op0
= XEXP (XVECEXP (PATTERN (insn
), 0, 1), 0);
5772 HOST_WIDE_INT loop_end_id
5773 = -INTVAL (XEXP (XVECEXP (PATTERN (insn
), 0, 4), 0));
5777 (lp
&& NONJUMP_INSN_P (lp
)
5778 && recog_memoized (lp
) != CODE_FOR_doloop_begin_i
);
5779 lp
= prev_nonnote_insn (lp
))
5781 if (!lp
|| !NONJUMP_INSN_P (lp
)
5782 || dead_or_set_regno_p (lp
, LP_COUNT
))
5784 for (prev
= next
= insn
, lp
= NULL_RTX
; prev
|| next
;)
5788 if (NONJUMP_INSN_P (prev
)
5789 && recog_memoized (prev
) == CODE_FOR_doloop_begin_i
5790 && (INTVAL (XEXP (XVECEXP (PATTERN (prev
), 0, 5), 0))
5796 else if (LABEL_P (prev
))
5798 prev
= prev_nonnote_insn (prev
);
5802 if (NONJUMP_INSN_P (next
)
5803 && recog_memoized (next
) == CODE_FOR_doloop_begin_i
5804 && (INTVAL (XEXP (XVECEXP (PATTERN (next
), 0, 5), 0))
5810 next
= next_nonnote_insn (next
);
5817 if (lp
&& !dead_or_set_regno_p (lp
, LP_COUNT
))
5819 rtx begin_cnt
= XEXP (XVECEXP (PATTERN (lp
), 0 ,3), 0);
5820 if (INTVAL (XEXP (XVECEXP (PATTERN (lp
), 0, 4), 0)))
5821 /* The loop end insn has been duplicated. That can happen
5822 when there is a conditional block at the very end of
5825 /* If Register allocation failed to allocate to the right
5826 register, There is no point into teaching reload to
5827 fix this up with reloads, as that would cost more
5828 than using an ordinary core register with the
5829 doloop_fallback pattern. */
5830 if ((true_regnum (op0
) != LP_COUNT
|| !REG_P (begin_cnt
))
5831 /* Likewise, if the loop setup is evidently inside the loop,
5833 || (!lp_simple
&& lp
!= next
&& !seen_label
))
5838 /* It is common that the optimizers copy the loop count from
5839 another register, and doloop_begin_i is stuck with the
5840 source of the move. Making doloop_begin_i only accept "l"
5841 is nonsentical, as this then makes reload evict the pseudo
5842 used for the loop end. The underlying cause is that the
5843 optimizers don't understand that the register allocation for
5844 doloop_begin_i should be treated as part of the loop.
5845 Try to work around this problem by verifying the previous
5847 if (true_regnum (begin_cnt
) != LP_COUNT
)
5851 for (mov
= prev_nonnote_insn (lp
); mov
;
5852 mov
= prev_nonnote_insn (mov
))
5854 if (!NONJUMP_INSN_P (mov
))
5856 else if ((set
= single_set (mov
))
5857 && rtx_equal_p (SET_SRC (set
), begin_cnt
)
5858 && rtx_equal_p (SET_DEST (set
), op0
))
5863 XEXP (XVECEXP (PATTERN (lp
), 0 ,3), 0) = op0
;
5864 note
= find_regno_note (lp
, REG_DEAD
, REGNO (begin_cnt
));
5866 remove_note (lp
, note
);
5874 XEXP (XVECEXP (PATTERN (insn
), 0, 4), 0) = num
;
5875 XEXP (XVECEXP (PATTERN (lp
), 0, 4), 0) = num
;
5877 XEXP (XVECEXP (PATTERN (lp
), 0, 6), 0) = const2_rtx
;
5878 else if (!lp_simple
)
5879 XEXP (XVECEXP (PATTERN (lp
), 0, 6), 0) = const1_rtx
;
5880 else if (prev
!= lp
)
5883 add_insn_after (lp
, prev
, NULL
);
5887 XEXP (XVECEXP (PATTERN (lp
), 0, 7), 0)
5888 = gen_rtx_LABEL_REF (Pmode
, top_label
);
5889 add_reg_note (lp
, REG_LABEL_OPERAND
, top_label
);
5890 LABEL_NUSES (top_label
)++;
5892 /* We can avoid tedious loop start / end setting for empty loops
5893 be merely setting the loop count to its final value. */
5894 if (next_active_insn (top_label
) == insn
)
5897 = gen_rtx_SET (VOIDmode
,
5898 XEXP (XVECEXP (PATTERN (lp
), 0, 3), 0),
5901 lc_set
= emit_insn_before (lc_set
, insn
);
5906 /* If the loop is non-empty with zero length, we can't make it
5907 a zero-overhead loop. That can happen for empty asms. */
5912 for (scan
= top_label
;
5913 (scan
&& scan
!= insn
5914 && (!NONJUMP_INSN_P (scan
) || !get_attr_length (scan
)));
5915 scan
= NEXT_INSN (scan
));
5925 /* Sometimes the loop optimizer makes a complete hash of the
5926 loop. If it were only that the loop is not entered at the
5927 top, we could fix this up by setting LP_START with SR .
5928 However, if we can't find the loop begin were it should be,
5929 chances are that it does not even dominate the loop, but is
5930 inside the loop instead. Using SR there would kill
5932 We use the doloop_fallback pattern here, which executes
5933 in two cycles on the ARC700 when predicted correctly. */
5937 rtx op3
= XEXP (XVECEXP (PATTERN (insn
), 0, 5), 0);
5939 emit_insn_before (gen_move_insn (op3
, op0
), insn
);
5941 = gen_doloop_fallback_m (op3
, JUMP_LABEL (insn
), op0
);
5944 XVEC (PATTERN (insn
), 0)
5945 = gen_rtvec (2, XVECEXP (PATTERN (insn
), 0, 0),
5946 XVECEXP (PATTERN (insn
), 0, 1));
5947 INSN_CODE (insn
) = -1;
5952 /* FIXME: should anticipate ccfsm action, generate special patterns for
5953 to-be-deleted branches that have no delay slot and have at least the
5954 length of the size increase forced on other insns that are conditionalized.
5955 This can also have an insn_list inside that enumerates insns which are
5956 not actually conditionalized because the destinations are dead in the
5958 Could also tag branches that we want to be unaligned if they get no delay
5959 slot, or even ones that we don't want to do delay slot sheduling for
5960 because we can unalign them.
5962 However, there are cases when conditional execution is only possible after
5963 delay slot scheduling:
5965 - If a delay slot is filled with a nocond/set insn from above, the previous
5966 basic block can become elegible for conditional execution.
5967 - If a delay slot is filled with a nocond insn from the fall-through path,
5968 the branch with that delay slot can become eligble for conditional
5969 execution (however, with the same sort of data flow analysis that dbr
5970 does, we could have figured out before that we don't need to
5971 conditionalize this insn.)
5972 - If a delay slot insn is filled with an insn from the target, the
5973 target label gets its uses decremented (even deleted if falling to zero),
5974 thus possibly creating more condexec opportunities there.
5975 Therefore, we should still be prepared to apply condexec optimization on
5976 non-prepared branches if the size increase of conditionalized insns is no
5977 more than the size saved from eliminating the branch. An invocation option
5978 could also be used to reserve a bit of extra size for condbranches so that
5979 this'll work more often (could also test in arc_reorg if the block is
5980 'close enough' to be eligible for condexec to make this likely, and
5981 estimate required size increase). */
5982 /* Generate BRcc insns, by combining cmp and Bcc insns wherever possible. */
5983 if (TARGET_NO_BRCC_SET
)
5988 init_insn_lengths();
5991 if (optimize
> 1 && !TARGET_NO_COND_EXEC
)
5994 unsigned int flags
= pass_data_arc_ifcvt
.todo_flags_finish
;
5995 df_finish_pass ((flags
& TODO_df_verify
) != 0);
5998 /* Call shorten_branches to calculate the insn lengths. */
5999 shorten_branches (get_insns());
6000 cfun
->machine
->ccfsm_current_insn
= NULL_RTX
;
6002 if (!INSN_ADDRESSES_SET_P())
6003 fatal_error ("Insn addresses not set after shorten_branches");
6005 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
6008 enum attr_type insn_type
;
6010 /* If a non-jump insn (or a casesi jump table), continue. */
6011 if (GET_CODE (insn
) != JUMP_INSN
||
6012 GET_CODE (PATTERN (insn
)) == ADDR_VEC
6013 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
6016 /* If we already have a brcc, note if it is suitable for brcc_s.
6017 Be a bit generous with the brcc_s range so that we can take
6018 advantage of any code shortening from delay slot scheduling. */
6019 if (recog_memoized (insn
) == CODE_FOR_cbranchsi4_scratch
)
6021 rtx pat
= PATTERN (insn
);
6022 rtx op
= XEXP (SET_SRC (XVECEXP (pat
, 0, 0)), 0);
6023 rtx
*ccp
= &XEXP (XVECEXP (pat
, 0, 1), 0);
6025 offset
= branch_dest (insn
) - INSN_ADDRESSES (INSN_UID (insn
));
6026 if ((offset
>= -140 && offset
< 140)
6027 && rtx_equal_p (XEXP (op
, 1), const0_rtx
)
6028 && compact_register_operand (XEXP (op
, 0), VOIDmode
)
6029 && equality_comparison_operator (op
, VOIDmode
))
6030 PUT_MODE (*ccp
, CC_Zmode
);
6031 else if (GET_MODE (*ccp
) == CC_Zmode
)
6032 PUT_MODE (*ccp
, CC_ZNmode
);
6035 if ((insn_type
= get_attr_type (insn
)) == TYPE_BRCC
6036 || insn_type
== TYPE_BRCC_NO_DELAY_SLOT
)
6039 /* OK. so we have a jump insn. */
6040 /* We need to check that it is a bcc. */
6041 /* Bcc => set (pc) (if_then_else ) */
6042 pattern
= PATTERN (insn
);
6043 if (GET_CODE (pattern
) != SET
6044 || GET_CODE (SET_SRC (pattern
)) != IF_THEN_ELSE
6045 || ANY_RETURN_P (XEXP (SET_SRC (pattern
), 1)))
6048 /* Now check if the jump is beyond the s9 range. */
6049 if (find_reg_note (insn
, REG_CROSSING_JUMP
, NULL_RTX
))
6051 offset
= branch_dest (insn
) - INSN_ADDRESSES (INSN_UID (insn
));
6053 if(offset
> 253 || offset
< -254)
6056 pc_target
= SET_SRC (pattern
);
6058 /* Now go back and search for the set cc insn. */
6060 label
= XEXP (pc_target
, 1);
6063 rtx pat
, scan
, link_insn
= NULL
;
6065 for (scan
= PREV_INSN (insn
);
6066 scan
&& GET_CODE (scan
) != CODE_LABEL
;
6067 scan
= PREV_INSN (scan
))
6069 if (! INSN_P (scan
))
6071 pat
= PATTERN (scan
);
6072 if (GET_CODE (pat
) == SET
6073 && cc_register (SET_DEST (pat
), VOIDmode
))
6082 /* Check if this is a data dependency. */
6084 rtx op
, cc_clob_rtx
, op0
, op1
, brcc_insn
, note
;
6087 /* Ok this is the set cc. copy args here. */
6088 op
= XEXP (pc_target
, 0);
6090 op0
= cmp0
= XEXP (SET_SRC (pat
), 0);
6091 op1
= cmp1
= XEXP (SET_SRC (pat
), 1);
6092 if (GET_CODE (op0
) == ZERO_EXTRACT
6093 && XEXP (op0
, 1) == const1_rtx
6094 && (GET_CODE (op
) == EQ
6095 || GET_CODE (op
) == NE
))
6097 /* btst / b{eq,ne} -> bbit{0,1} */
6098 op0
= XEXP (cmp0
, 0);
6099 op1
= XEXP (cmp0
, 2);
6101 else if (!register_operand (op0
, VOIDmode
)
6102 || !general_operand (op1
, VOIDmode
))
6104 /* Be careful not to break what cmpsfpx_raw is
6105 trying to create for checking equality of
6106 single-precision floats. */
6107 else if (TARGET_SPFP
6108 && GET_MODE (op0
) == SFmode
6109 && GET_MODE (op1
) == SFmode
)
6112 /* None of the two cmp operands should be set between the
6113 cmp and the branch. */
6114 if (reg_set_between_p (op0
, link_insn
, insn
))
6117 if (reg_set_between_p (op1
, link_insn
, insn
))
6120 /* Since the MODE check does not work, check that this is
6121 CC reg's last set location before insn, and also no
6122 instruction between the cmp and branch uses the
6124 if ((reg_set_between_p (SET_DEST (pat
), link_insn
, insn
))
6125 || (reg_used_between_p (SET_DEST (pat
), link_insn
, insn
)))
6128 /* CC reg should be dead after insn. */
6129 if (!find_regno_note (insn
, REG_DEAD
, CC_REG
))
6132 op
= gen_rtx_fmt_ee (GET_CODE (op
),
6133 GET_MODE (op
), cmp0
, cmp1
);
6134 /* If we create a LIMM where there was none before,
6135 we only benefit if we can avoid a scheduling bubble
6136 for the ARC600. Otherwise, we'd only forgo chances
6137 at short insn generation, and risk out-of-range
6139 if (!brcc_nolimm_operator (op
, VOIDmode
)
6140 && !long_immediate_operand (op1
, VOIDmode
)
6142 || next_active_insn (link_insn
) != insn
))
6145 /* Emit bbit / brcc (or brcc_s if possible).
6146 CC_Zmode indicates that brcc_s is possible. */
6149 cc_clob_rtx
= gen_rtx_REG (CC_ZNmode
, CC_REG
);
6150 else if ((offset
>= -140 && offset
< 140)
6151 && rtx_equal_p (op1
, const0_rtx
)
6152 && compact_register_operand (op0
, VOIDmode
)
6153 && (GET_CODE (op
) == EQ
6154 || GET_CODE (op
) == NE
))
6155 cc_clob_rtx
= gen_rtx_REG (CC_Zmode
, CC_REG
);
6157 cc_clob_rtx
= gen_rtx_REG (CCmode
, CC_REG
);
6160 = gen_rtx_IF_THEN_ELSE (VOIDmode
, op
, label
, pc_rtx
);
6161 brcc_insn
= gen_rtx_SET (VOIDmode
, pc_rtx
, brcc_insn
);
6162 cc_clob_rtx
= gen_rtx_CLOBBER (VOIDmode
, cc_clob_rtx
);
6165 (VOIDmode
, gen_rtvec (2, brcc_insn
, cc_clob_rtx
));
6166 brcc_insn
= emit_jump_insn_before (brcc_insn
, insn
);
6168 JUMP_LABEL (brcc_insn
) = JUMP_LABEL (insn
);
6169 note
= find_reg_note (insn
, REG_BR_PROB
, 0);
6172 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6173 REG_NOTES (brcc_insn
) = note
;
6175 note
= find_reg_note (link_insn
, REG_DEAD
, op0
);
6178 remove_note (link_insn
, note
);
6179 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6180 REG_NOTES (brcc_insn
) = note
;
6182 note
= find_reg_note (link_insn
, REG_DEAD
, op1
);
6185 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6186 REG_NOTES (brcc_insn
) = note
;
6191 /* Delete the bcc insn. */
6192 set_insn_deleted (insn
);
6194 /* Delete the cmp insn. */
6195 set_insn_deleted (link_insn
);
6200 /* Clear out insn_addresses. */
6201 INSN_ADDRESSES_FREE ();
6205 if (INSN_ADDRESSES_SET_P())
6206 fatal_error ("insn addresses not freed");
6208 arc_reorg_in_progress
= 0;
6211 /* Check if the operands are valid for BRcc.d generation
6212 Valid Brcc.d patterns are
6216 For cc={GT, LE, GTU, LEU}, u6=63 can not be allowed,
6217 since they are encoded by the assembler as {GE, LT, HS, LS} 64, which
6218 does not have a delay slot
6220 Assumed precondition: Second operand is either a register or a u6 value. */
6223 valid_brcc_with_delay_p (rtx
*operands
)
6225 if (optimize_size
&& GET_MODE (operands
[4]) == CC_Zmode
)
6227 return brcc_nolimm_operator (operands
[0], VOIDmode
);
6230 /* ??? Hack. This should no really be here. See PR32143. */
6232 arc_decl_anon_ns_mem_p (const_tree decl
)
6236 if (decl
== NULL_TREE
|| decl
== error_mark_node
)
6238 if (TREE_CODE (decl
) == NAMESPACE_DECL
6239 && DECL_NAME (decl
) == NULL_TREE
)
6241 /* Classes and namespaces inside anonymous namespaces have
6242 TREE_PUBLIC == 0, so we can shortcut the search. */
6243 else if (TYPE_P (decl
))
6244 return (TREE_PUBLIC (TYPE_NAME (decl
)) == 0);
6245 else if (TREE_CODE (decl
) == NAMESPACE_DECL
)
6246 return (TREE_PUBLIC (decl
) == 0);
6248 decl
= DECL_CONTEXT (decl
);
6252 /* Implement TARGET_IN_SMALL_DATA_P. Return true if it would be safe to
6253 access DECL using %gp_rel(...)($gp). */
6256 arc_in_small_data_p (const_tree decl
)
6260 if (TREE_CODE (decl
) == STRING_CST
|| TREE_CODE (decl
) == FUNCTION_DECL
)
6264 /* We don't yet generate small-data references for -mabicalls. See related
6265 -G handling in override_options. */
6266 if (TARGET_NO_SDATA_SET
)
6269 if (TREE_CODE (decl
) == VAR_DECL
&& DECL_SECTION_NAME (decl
) != 0)
6273 /* Reject anything that isn't in a known small-data section. */
6274 name
= TREE_STRING_POINTER (DECL_SECTION_NAME (decl
));
6275 if (strcmp (name
, ".sdata") != 0 && strcmp (name
, ".sbss") != 0)
6278 /* If a symbol is defined externally, the assembler will use the
6279 usual -G rules when deciding how to implement macros. */
6280 if (!DECL_EXTERNAL (decl
))
6283 /* Only global variables go into sdata section for now. */
6286 /* Don't put constants into the small data section: we want them
6287 to be in ROM rather than RAM. */
6288 if (TREE_CODE (decl
) != VAR_DECL
)
6291 if (TREE_READONLY (decl
)
6292 && !TREE_SIDE_EFFECTS (decl
)
6293 && (!DECL_INITIAL (decl
) || TREE_CONSTANT (DECL_INITIAL (decl
))))
6296 /* TREE_PUBLIC might change after the first call, because of the patch
6298 if (default_binds_local_p_1 (decl
, 1)
6299 || arc_decl_anon_ns_mem_p (decl
))
6302 /* To ensure -mvolatile-cache works
6303 ld.di does not have a gp-relative variant. */
6304 if (TREE_THIS_VOLATILE (decl
))
6308 /* Disable sdata references to weak variables. */
6309 if (DECL_WEAK (decl
))
6312 size
= int_size_in_bytes (TREE_TYPE (decl
));
6314 /* if (AGGREGATE_TYPE_P (TREE_TYPE (decl))) */
6317 /* Allow only <=4B long data types into sdata. */
6318 return (size
> 0 && size
<= 4);
6321 /* Return true if X is a small data address that can be rewritten
6325 arc_rewrite_small_data_p (rtx x
)
6327 if (GET_CODE (x
) == CONST
)
6330 if (GET_CODE (x
) == PLUS
)
6332 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
6336 return (GET_CODE (x
) == SYMBOL_REF
6337 && SYMBOL_REF_SMALL_P(x
));
6340 /* A for_each_rtx callback, used by arc_rewrite_small_data. */
6343 arc_rewrite_small_data_1 (rtx
*loc
, void *data
)
6345 if (arc_rewrite_small_data_p (*loc
))
6349 gcc_assert (SDATA_BASE_REGNUM
== PIC_OFFSET_TABLE_REGNUM
);
6350 *loc
= gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, *loc
);
6354 if (GET_CODE (top
) == MEM
&& &XEXP (top
, 0) == loc
)
6356 else if (GET_CODE (top
) == MEM
6357 && GET_CODE (XEXP (top
, 0)) == PLUS
6358 && GET_CODE (XEXP (XEXP (top
, 0), 0)) == MULT
)
6359 *loc
= force_reg (Pmode
, *loc
);
6365 if (GET_CODE (*loc
) == PLUS
6366 && rtx_equal_p (XEXP (*loc
, 0), pic_offset_table_rtx
))
6372 /* If possible, rewrite OP so that it refers to small data using
6373 explicit relocations. */
6376 arc_rewrite_small_data (rtx op
)
6378 op
= copy_insn (op
);
6379 for_each_rtx (&op
, arc_rewrite_small_data_1
, &op
);
6383 /* A for_each_rtx callback for small_data_pattern. */
6386 small_data_pattern_1 (rtx
*loc
, void *data ATTRIBUTE_UNUSED
)
6388 if (GET_CODE (*loc
) == PLUS
6389 && rtx_equal_p (XEXP (*loc
, 0), pic_offset_table_rtx
))
6392 return arc_rewrite_small_data_p (*loc
);
6395 /* Return true if OP refers to small data symbols directly, not through
6399 small_data_pattern (rtx op
, enum machine_mode
)
6401 return (GET_CODE (op
) != SEQUENCE
6402 && for_each_rtx (&op
, small_data_pattern_1
, 0));
6405 /* Return true if OP is an acceptable memory operand for ARCompact
6406 16-bit gp-relative load instructions.
6407 op shd look like : [r26, symref@sda]
6408 i.e. (mem (plus (reg 26) (symref with smalldata flag set))
6410 /* volatile cache option still to be handled. */
6413 compact_sda_memory_operand (rtx op
, enum machine_mode mode
)
6418 /* Eliminate non-memory operations. */
6419 if (GET_CODE (op
) != MEM
)
6422 if (mode
== VOIDmode
)
6423 mode
= GET_MODE (op
);
6425 size
= GET_MODE_SIZE (mode
);
6427 /* dword operations really put out 2 instructions, so eliminate them. */
6428 if (size
> UNITS_PER_WORD
)
6431 /* Decode the address now. */
6432 addr
= XEXP (op
, 0);
6434 return LEGITIMATE_SMALL_DATA_ADDRESS_P (addr
);
6437 /* Implement ASM_OUTPUT_ALIGNED_DECL_LOCAL. */
6440 arc_asm_output_aligned_decl_local (FILE * stream
, tree decl
, const char * name
,
6441 unsigned HOST_WIDE_INT size
,
6442 unsigned HOST_WIDE_INT align
,
6443 unsigned HOST_WIDE_INT globalize_p
)
6445 int in_small_data
= arc_in_small_data_p (decl
);
6448 switch_to_section (get_named_section (NULL
, ".sbss", 0));
6449 /* named_section (0,".sbss",0); */
6451 switch_to_section (bss_section
);
6454 (*targetm
.asm_out
.globalize_label
) (stream
, name
);
6456 ASM_OUTPUT_ALIGN (stream
, floor_log2 ((align
) / BITS_PER_UNIT
));
6457 ASM_OUTPUT_TYPE_DIRECTIVE (stream
, name
, "object");
6458 ASM_OUTPUT_SIZE_DIRECTIVE (stream
, name
, size
);
6459 ASM_OUTPUT_LABEL (stream
, name
);
6462 ASM_OUTPUT_SKIP (stream
, size
);
6498 /* SIMD builtins support. */
6499 enum simd_insn_args_type
{
6522 struct builtin_description
6524 enum simd_insn_args_type args_type
;
6525 const enum insn_code icode
;
6526 const char * const name
;
6527 const enum arc_builtins code
;
6530 static const struct builtin_description arc_simd_builtin_desc_list
[] =
6532 /* VVV builtins go first. */
6533 #define SIMD_BUILTIN(type, code, string, builtin) \
6534 { type,CODE_FOR_##code, "__builtin_arc_" string, \
6535 ARC_SIMD_BUILTIN_##builtin },
6537 SIMD_BUILTIN (Va_Vb_Vc
, vaddaw_insn
, "vaddaw", VADDAW
)
6538 SIMD_BUILTIN (Va_Vb_Vc
, vaddw_insn
, "vaddw", VADDW
)
6539 SIMD_BUILTIN (Va_Vb_Vc
, vavb_insn
, "vavb", VAVB
)
6540 SIMD_BUILTIN (Va_Vb_Vc
, vavrb_insn
, "vavrb", VAVRB
)
6541 SIMD_BUILTIN (Va_Vb_Vc
, vdifaw_insn
, "vdifaw", VDIFAW
)
6542 SIMD_BUILTIN (Va_Vb_Vc
, vdifw_insn
, "vdifw", VDIFW
)
6543 SIMD_BUILTIN (Va_Vb_Vc
, vmaxaw_insn
, "vmaxaw", VMAXAW
)
6544 SIMD_BUILTIN (Va_Vb_Vc
, vmaxw_insn
, "vmaxw", VMAXW
)
6545 SIMD_BUILTIN (Va_Vb_Vc
, vminaw_insn
, "vminaw", VMINAW
)
6546 SIMD_BUILTIN (Va_Vb_Vc
, vminw_insn
, "vminw", VMINW
)
6547 SIMD_BUILTIN (Va_Vb_Vc
, vmulaw_insn
, "vmulaw", VMULAW
)
6548 SIMD_BUILTIN (Va_Vb_Vc
, vmulfaw_insn
, "vmulfaw", VMULFAW
)
6549 SIMD_BUILTIN (Va_Vb_Vc
, vmulfw_insn
, "vmulfw", VMULFW
)
6550 SIMD_BUILTIN (Va_Vb_Vc
, vmulw_insn
, "vmulw", VMULW
)
6551 SIMD_BUILTIN (Va_Vb_Vc
, vsubaw_insn
, "vsubaw", VSUBAW
)
6552 SIMD_BUILTIN (Va_Vb_Vc
, vsubw_insn
, "vsubw", VSUBW
)
6553 SIMD_BUILTIN (Va_Vb_Vc
, vsummw_insn
, "vsummw", VSUMMW
)
6554 SIMD_BUILTIN (Va_Vb_Vc
, vand_insn
, "vand", VAND
)
6555 SIMD_BUILTIN (Va_Vb_Vc
, vandaw_insn
, "vandaw", VANDAW
)
6556 SIMD_BUILTIN (Va_Vb_Vc
, vbic_insn
, "vbic", VBIC
)
6557 SIMD_BUILTIN (Va_Vb_Vc
, vbicaw_insn
, "vbicaw", VBICAW
)
6558 SIMD_BUILTIN (Va_Vb_Vc
, vor_insn
, "vor", VOR
)
6559 SIMD_BUILTIN (Va_Vb_Vc
, vxor_insn
, "vxor", VXOR
)
6560 SIMD_BUILTIN (Va_Vb_Vc
, vxoraw_insn
, "vxoraw", VXORAW
)
6561 SIMD_BUILTIN (Va_Vb_Vc
, veqw_insn
, "veqw", VEQW
)
6562 SIMD_BUILTIN (Va_Vb_Vc
, vlew_insn
, "vlew", VLEW
)
6563 SIMD_BUILTIN (Va_Vb_Vc
, vltw_insn
, "vltw", VLTW
)
6564 SIMD_BUILTIN (Va_Vb_Vc
, vnew_insn
, "vnew", VNEW
)
6565 SIMD_BUILTIN (Va_Vb_Vc
, vmr1aw_insn
, "vmr1aw", VMR1AW
)
6566 SIMD_BUILTIN (Va_Vb_Vc
, vmr1w_insn
, "vmr1w", VMR1W
)
6567 SIMD_BUILTIN (Va_Vb_Vc
, vmr2aw_insn
, "vmr2aw", VMR2AW
)
6568 SIMD_BUILTIN (Va_Vb_Vc
, vmr2w_insn
, "vmr2w", VMR2W
)
6569 SIMD_BUILTIN (Va_Vb_Vc
, vmr3aw_insn
, "vmr3aw", VMR3AW
)
6570 SIMD_BUILTIN (Va_Vb_Vc
, vmr3w_insn
, "vmr3w", VMR3W
)
6571 SIMD_BUILTIN (Va_Vb_Vc
, vmr4aw_insn
, "vmr4aw", VMR4AW
)
6572 SIMD_BUILTIN (Va_Vb_Vc
, vmr4w_insn
, "vmr4w", VMR4W
)
6573 SIMD_BUILTIN (Va_Vb_Vc
, vmr5aw_insn
, "vmr5aw", VMR5AW
)
6574 SIMD_BUILTIN (Va_Vb_Vc
, vmr5w_insn
, "vmr5w", VMR5W
)
6575 SIMD_BUILTIN (Va_Vb_Vc
, vmr6aw_insn
, "vmr6aw", VMR6AW
)
6576 SIMD_BUILTIN (Va_Vb_Vc
, vmr6w_insn
, "vmr6w", VMR6W
)
6577 SIMD_BUILTIN (Va_Vb_Vc
, vmr7aw_insn
, "vmr7aw", VMR7AW
)
6578 SIMD_BUILTIN (Va_Vb_Vc
, vmr7w_insn
, "vmr7w", VMR7W
)
6579 SIMD_BUILTIN (Va_Vb_Vc
, vmrb_insn
, "vmrb", VMRB
)
6580 SIMD_BUILTIN (Va_Vb_Vc
, vh264f_insn
, "vh264f", VH264F
)
6581 SIMD_BUILTIN (Va_Vb_Vc
, vh264ft_insn
, "vh264ft", VH264FT
)
6582 SIMD_BUILTIN (Va_Vb_Vc
, vh264fw_insn
, "vh264fw", VH264FW
)
6583 SIMD_BUILTIN (Va_Vb_Vc
, vvc1f_insn
, "vvc1f", VVC1F
)
6584 SIMD_BUILTIN (Va_Vb_Vc
, vvc1ft_insn
, "vvc1ft", VVC1FT
)
6586 SIMD_BUILTIN (Va_Vb_rlimm
, vbaddw_insn
, "vbaddw", VBADDW
)
6587 SIMD_BUILTIN (Va_Vb_rlimm
, vbmaxw_insn
, "vbmaxw", VBMAXW
)
6588 SIMD_BUILTIN (Va_Vb_rlimm
, vbminw_insn
, "vbminw", VBMINW
)
6589 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulaw_insn
, "vbmulaw", VBMULAW
)
6590 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulfw_insn
, "vbmulfw", VBMULFW
)
6591 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulw_insn
, "vbmulw", VBMULW
)
6592 SIMD_BUILTIN (Va_Vb_rlimm
, vbrsubw_insn
, "vbrsubw", VBRSUBW
)
6593 SIMD_BUILTIN (Va_Vb_rlimm
, vbsubw_insn
, "vbsubw", VBSUBW
)
6595 /* Va, Vb, Ic instructions. */
6596 SIMD_BUILTIN (Va_Vb_Ic
, vasrw_insn
, "vasrw", VASRW
)
6597 SIMD_BUILTIN (Va_Vb_Ic
, vsr8_insn
, "vsr8", VSR8
)
6598 SIMD_BUILTIN (Va_Vb_Ic
, vsr8aw_insn
, "vsr8aw", VSR8AW
)
6600 /* Va, Vb, u6 instructions. */
6601 SIMD_BUILTIN (Va_Vb_u6
, vasrrwi_insn
, "vasrrwi", VASRRWi
)
6602 SIMD_BUILTIN (Va_Vb_u6
, vasrsrwi_insn
, "vasrsrwi", VASRSRWi
)
6603 SIMD_BUILTIN (Va_Vb_u6
, vasrwi_insn
, "vasrwi", VASRWi
)
6604 SIMD_BUILTIN (Va_Vb_u6
, vasrpwbi_insn
, "vasrpwbi", VASRPWBi
)
6605 SIMD_BUILTIN (Va_Vb_u6
, vasrrpwbi_insn
,"vasrrpwbi", VASRRPWBi
)
6606 SIMD_BUILTIN (Va_Vb_u6
, vsr8awi_insn
, "vsr8awi", VSR8AWi
)
6607 SIMD_BUILTIN (Va_Vb_u6
, vsr8i_insn
, "vsr8i", VSR8i
)
6609 /* Va, Vb, u8 (simm) instructions. */
6610 SIMD_BUILTIN (Va_Vb_u8
, vmvaw_insn
, "vmvaw", VMVAW
)
6611 SIMD_BUILTIN (Va_Vb_u8
, vmvw_insn
, "vmvw", VMVW
)
6612 SIMD_BUILTIN (Va_Vb_u8
, vmvzw_insn
, "vmvzw", VMVZW
)
6613 SIMD_BUILTIN (Va_Vb_u8
, vd6tapf_insn
, "vd6tapf", VD6TAPF
)
6615 /* Va, rlimm, u8 (simm) instructions. */
6616 SIMD_BUILTIN (Va_rlimm_u8
, vmovaw_insn
, "vmovaw", VMOVAW
)
6617 SIMD_BUILTIN (Va_rlimm_u8
, vmovw_insn
, "vmovw", VMOVW
)
6618 SIMD_BUILTIN (Va_rlimm_u8
, vmovzw_insn
, "vmovzw", VMOVZW
)
6620 /* Va, Vb instructions. */
6621 SIMD_BUILTIN (Va_Vb
, vabsaw_insn
, "vabsaw", VABSAW
)
6622 SIMD_BUILTIN (Va_Vb
, vabsw_insn
, "vabsw", VABSW
)
6623 SIMD_BUILTIN (Va_Vb
, vaddsuw_insn
, "vaddsuw", VADDSUW
)
6624 SIMD_BUILTIN (Va_Vb
, vsignw_insn
, "vsignw", VSIGNW
)
6625 SIMD_BUILTIN (Va_Vb
, vexch1_insn
, "vexch1", VEXCH1
)
6626 SIMD_BUILTIN (Va_Vb
, vexch2_insn
, "vexch2", VEXCH2
)
6627 SIMD_BUILTIN (Va_Vb
, vexch4_insn
, "vexch4", VEXCH4
)
6628 SIMD_BUILTIN (Va_Vb
, vupbaw_insn
, "vupbaw", VUPBAW
)
6629 SIMD_BUILTIN (Va_Vb
, vupbw_insn
, "vupbw", VUPBW
)
6630 SIMD_BUILTIN (Va_Vb
, vupsbaw_insn
, "vupsbaw", VUPSBAW
)
6631 SIMD_BUILTIN (Va_Vb
, vupsbw_insn
, "vupsbw", VUPSBW
)
6633 /* DIb, rlimm, rlimm instructions. */
6634 SIMD_BUILTIN (Da_rlimm_rlimm
, vdirun_insn
, "vdirun", VDIRUN
)
6635 SIMD_BUILTIN (Da_rlimm_rlimm
, vdorun_insn
, "vdorun", VDORUN
)
6637 /* DIb, limm, rlimm instructions. */
6638 SIMD_BUILTIN (Da_u3_rlimm
, vdiwr_insn
, "vdiwr", VDIWR
)
6639 SIMD_BUILTIN (Da_u3_rlimm
, vdowr_insn
, "vdowr", VDOWR
)
6641 /* rlimm instructions. */
6642 SIMD_BUILTIN (void_rlimm
, vrec_insn
, "vrec", VREC
)
6643 SIMD_BUILTIN (void_rlimm
, vrun_insn
, "vrun", VRUN
)
6644 SIMD_BUILTIN (void_rlimm
, vrecrun_insn
, "vrecrun", VRECRUN
)
6645 SIMD_BUILTIN (void_rlimm
, vendrec_insn
, "vendrec", VENDREC
)
6647 /* Va, [Ib,u8] instructions. */
6648 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32wh_insn
, "vld32wh", VLD32WH
)
6649 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32wl_insn
, "vld32wl", VLD32WL
)
6650 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld64_insn
, "vld64", VLD64
)
6651 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32_insn
, "vld32", VLD32
)
6653 SIMD_BUILTIN (Va_Ib_u8
, vld64w_insn
, "vld64w", VLD64W
)
6654 SIMD_BUILTIN (Va_Ib_u8
, vld128_insn
, "vld128", VLD128
)
6655 SIMD_BUILTIN (void_Va_Ib_u8
, vst128_insn
, "vst128", VST128
)
6656 SIMD_BUILTIN (void_Va_Ib_u8
, vst64_insn
, "vst64", VST64
)
6658 /* Va, [Ib, u8] instructions. */
6659 SIMD_BUILTIN (void_Va_u3_Ib_u8
, vst16_n_insn
, "vst16_n", VST16_N
)
6660 SIMD_BUILTIN (void_Va_u3_Ib_u8
, vst32_n_insn
, "vst32_n", VST32_N
)
6662 SIMD_BUILTIN (void_u6
, vinti_insn
, "vinti", VINTI
)
6666 arc_init_simd_builtins (void)
6669 tree endlink
= void_list_node
;
6670 tree V8HI_type_node
= build_vector_type_for_mode (intHI_type_node
, V8HImode
);
6672 tree v8hi_ftype_v8hi_v8hi
6673 = build_function_type (V8HI_type_node
,
6674 tree_cons (NULL_TREE
, V8HI_type_node
,
6675 tree_cons (NULL_TREE
, V8HI_type_node
,
6677 tree v8hi_ftype_v8hi_int
6678 = build_function_type (V8HI_type_node
,
6679 tree_cons (NULL_TREE
, V8HI_type_node
,
6680 tree_cons (NULL_TREE
, integer_type_node
,
6683 tree v8hi_ftype_v8hi_int_int
6684 = build_function_type (V8HI_type_node
,
6685 tree_cons (NULL_TREE
, V8HI_type_node
,
6686 tree_cons (NULL_TREE
, integer_type_node
,
6687 tree_cons (NULL_TREE
,
6691 tree void_ftype_v8hi_int_int
6692 = build_function_type (void_type_node
,
6693 tree_cons (NULL_TREE
, V8HI_type_node
,
6694 tree_cons (NULL_TREE
, integer_type_node
,
6695 tree_cons (NULL_TREE
,
6699 tree void_ftype_v8hi_int_int_int
6700 = (build_function_type
6702 tree_cons (NULL_TREE
, V8HI_type_node
,
6703 tree_cons (NULL_TREE
, integer_type_node
,
6704 tree_cons (NULL_TREE
, integer_type_node
,
6705 tree_cons (NULL_TREE
,
6709 tree v8hi_ftype_int_int
6710 = build_function_type (V8HI_type_node
,
6711 tree_cons (NULL_TREE
, integer_type_node
,
6712 tree_cons (NULL_TREE
, integer_type_node
,
6715 tree void_ftype_int_int
6716 = build_function_type (void_type_node
,
6717 tree_cons (NULL_TREE
, integer_type_node
,
6718 tree_cons (NULL_TREE
, integer_type_node
,
6722 = build_function_type (void_type_node
,
6723 tree_cons (NULL_TREE
, integer_type_node
, endlink
));
6725 tree v8hi_ftype_v8hi
6726 = build_function_type (V8HI_type_node
, tree_cons (NULL_TREE
, V8HI_type_node
,
6729 /* These asserts have been introduced to ensure that the order of builtins
6730 does not get messed up, else the initialization goes wrong. */
6731 gcc_assert (arc_simd_builtin_desc_list
[0].args_type
== Va_Vb_Vc
);
6732 for (i
=0; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Vc
; i
++)
6733 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6734 v8hi_ftype_v8hi_v8hi
, arc_simd_builtin_desc_list
[i
].code
);
6736 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_rlimm
);
6737 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_rlimm
; i
++)
6738 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6739 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6741 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic
);
6742 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic
; i
++)
6743 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6744 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6746 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u6
);
6747 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u6
; i
++)
6748 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6749 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6751 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u8
);
6752 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u8
; i
++)
6753 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6754 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6756 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_rlimm_u8
);
6757 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_rlimm_u8
; i
++)
6758 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6759 v8hi_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6761 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb
);
6762 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb
; i
++)
6763 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6764 v8hi_ftype_v8hi
, arc_simd_builtin_desc_list
[i
].code
);
6766 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Da_rlimm_rlimm
);
6767 for (; arc_simd_builtin_desc_list
[i
].args_type
== Da_rlimm_rlimm
; i
++)
6768 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6769 void_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6771 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Da_u3_rlimm
);
6772 for (; arc_simd_builtin_desc_list
[i
].args_type
== Da_u3_rlimm
; i
++)
6773 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6774 void_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6776 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_rlimm
);
6777 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_rlimm
; i
++)
6778 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6779 void_ftype_int
, arc_simd_builtin_desc_list
[i
].code
);
6781 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic_u8
);
6782 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic_u8
; i
++)
6783 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6784 v8hi_ftype_v8hi_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6786 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Ib_u8
);
6787 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Ib_u8
; i
++)
6788 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6789 v8hi_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6791 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_Va_Ib_u8
);
6792 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_Va_Ib_u8
; i
++)
6793 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6794 void_ftype_v8hi_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6796 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_Va_u3_Ib_u8
);
6797 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_Va_u3_Ib_u8
; i
++)
6798 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6799 void_ftype_v8hi_int_int_int
,
6800 arc_simd_builtin_desc_list
[i
].code
);
6802 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_u6
);
6803 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_u6
; i
++)
6804 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6805 void_ftype_int
, arc_simd_builtin_desc_list
[i
].code
);
6807 gcc_assert(i
== ARRAY_SIZE (arc_simd_builtin_desc_list
));
6810 /* Helper function of arc_expand_builtin; has the same parameters,
6811 except that EXP is now known to be a call to a simd builtin. */
6814 arc_expand_simd_builtin (tree exp
,
6816 rtx subtarget ATTRIBUTE_UNUSED
,
6817 enum machine_mode mode ATTRIBUTE_UNUSED
,
6818 int ignore ATTRIBUTE_UNUSED
)
6820 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
6832 int fcode
= DECL_FUNCTION_CODE (fndecl
);
6834 enum machine_mode mode0
;
6835 enum machine_mode mode1
;
6836 enum machine_mode mode2
;
6837 enum machine_mode mode3
;
6838 enum machine_mode mode4
;
6839 const struct builtin_description
* d
;
6841 for (i
= 0, d
= arc_simd_builtin_desc_list
;
6842 i
< ARRAY_SIZE (arc_simd_builtin_desc_list
); i
++, d
++)
6843 if (d
->code
== (const enum arc_builtins
) fcode
)
6846 /* We must get an entry here. */
6847 gcc_assert (i
< ARRAY_SIZE (arc_simd_builtin_desc_list
));
6849 switch (d
->args_type
)
6853 arg0
= CALL_EXPR_ARG (exp
, 0);
6854 arg1
= CALL_EXPR_ARG (exp
, 1);
6855 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6856 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6858 target
= gen_reg_rtx (V8HImode
);
6859 mode0
= insn_data
[icode
].operand
[1].mode
;
6860 mode1
= insn_data
[icode
].operand
[2].mode
;
6862 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6863 op0
= copy_to_mode_reg (mode0
, op0
);
6865 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6866 op1
= copy_to_mode_reg (mode1
, op1
);
6868 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
6878 arg0
= CALL_EXPR_ARG (exp
, 0);
6879 arg1
= CALL_EXPR_ARG (exp
, 1);
6880 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6881 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6883 target
= gen_reg_rtx (V8HImode
);
6884 mode0
= insn_data
[icode
].operand
[1].mode
;
6885 mode1
= insn_data
[icode
].operand
[2].mode
;
6887 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6888 op0
= copy_to_mode_reg (mode0
, op0
);
6890 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
)
6891 || (d
->args_type
== Va_Vb_u6
&& !UNSIGNED_INT6 (INTVAL (op1
)))
6892 || (d
->args_type
== Va_Vb_u8
&& !UNSIGNED_INT8 (INTVAL (op1
))))
6893 error ("operand 2 of %s instruction should be an unsigned %d-bit value",
6895 (d
->args_type
== Va_Vb_u6
)? 6: 8);
6897 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
6906 arg0
= CALL_EXPR_ARG (exp
, 0);
6907 arg1
= CALL_EXPR_ARG (exp
, 1);
6908 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6909 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6911 target
= gen_reg_rtx (V8HImode
);
6912 mode0
= insn_data
[icode
].operand
[1].mode
;
6913 mode1
= insn_data
[icode
].operand
[2].mode
;
6915 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6916 op0
= copy_to_mode_reg (mode0
, op0
);
6918 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6919 || !(UNSIGNED_INT8 (INTVAL (op1
))))
6920 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
6923 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
6932 arg0
= CALL_EXPR_ARG (exp
, 0);
6933 arg1
= CALL_EXPR_ARG (exp
, 1);
6934 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6935 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6936 op2
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
);
6938 target
= gen_reg_rtx (V8HImode
);
6939 mode0
= insn_data
[icode
].operand
[1].mode
;
6940 mode1
= insn_data
[icode
].operand
[2].mode
;
6942 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6943 op0
= copy_to_mode_reg (mode0
, op0
);
6945 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6946 || !(UNSIGNED_INT3 (INTVAL (op1
))))
6947 error ("operand 2 of %s instruction should be an unsigned 3-bit value (I0-I7)",
6950 pat
= GEN_FCN (icode
) (target
, op0
, op1
, op2
);
6959 arg0
= CALL_EXPR_ARG (exp
, 0);
6960 arg1
= CALL_EXPR_ARG (exp
, 1);
6961 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6962 op1
= expand_expr (arg1
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6964 target
= gen_reg_rtx (V8HImode
);
6965 mode0
= insn_data
[icode
].operand
[1].mode
;
6966 mode1
= insn_data
[icode
].operand
[2].mode
;
6968 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6969 op0
= copy_to_mode_reg (mode0
, op0
);
6971 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6972 op1
= copy_to_mode_reg (mode1
, op1
);
6974 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
6983 arg0
= CALL_EXPR_ARG (exp
, 0);
6984 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6986 target
= gen_reg_rtx (V8HImode
);
6987 mode0
= insn_data
[icode
].operand
[1].mode
;
6989 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6990 op0
= copy_to_mode_reg (mode0
, op0
);
6992 pat
= GEN_FCN (icode
) (target
, op0
);
6999 case Da_rlimm_rlimm
:
7001 arg0
= CALL_EXPR_ARG (exp
, 0);
7002 arg1
= CALL_EXPR_ARG (exp
, 1);
7003 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7004 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7007 if (icode
== CODE_FOR_vdirun_insn
)
7008 target
= gen_rtx_REG (SImode
, 131);
7009 else if (icode
== CODE_FOR_vdorun_insn
)
7010 target
= gen_rtx_REG (SImode
, 139);
7014 mode0
= insn_data
[icode
].operand
[1].mode
;
7015 mode1
= insn_data
[icode
].operand
[2].mode
;
7017 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
7018 op0
= copy_to_mode_reg (mode0
, op0
);
7020 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7021 op1
= copy_to_mode_reg (mode1
, op1
);
7024 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
7033 arg0
= CALL_EXPR_ARG (exp
, 0);
7034 arg1
= CALL_EXPR_ARG (exp
, 1);
7035 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7036 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7039 if (! (GET_CODE (op0
) == CONST_INT
)
7040 || !(UNSIGNED_INT3 (INTVAL (op0
))))
7041 error ("operand 1 of %s instruction should be an unsigned 3-bit value (DR0-DR7)",
7044 mode1
= insn_data
[icode
].operand
[1].mode
;
7046 if (icode
== CODE_FOR_vdiwr_insn
)
7047 target
= gen_rtx_REG (SImode
,
7048 ARC_FIRST_SIMD_DMA_CONFIG_IN_REG
+ INTVAL (op0
));
7049 else if (icode
== CODE_FOR_vdowr_insn
)
7050 target
= gen_rtx_REG (SImode
,
7051 ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG
+ INTVAL (op0
));
7055 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7056 op1
= copy_to_mode_reg (mode1
, op1
);
7058 pat
= GEN_FCN (icode
) (target
, op1
);
7067 arg0
= CALL_EXPR_ARG (exp
, 0);
7071 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7072 mode0
= insn_data
[icode
].operand
[0].mode
;
7074 /* op0 should be u6. */
7075 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
)
7076 || !(UNSIGNED_INT6 (INTVAL (op0
))))
7077 error ("operand of %s instruction should be an unsigned 6-bit value",
7080 pat
= GEN_FCN (icode
) (op0
);
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 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
7097 op0
= copy_to_mode_reg (mode0
, op0
);
7099 pat
= GEN_FCN (icode
) (op0
);
7110 arg0
= CALL_EXPR_ARG (exp
, 0); /* source vreg */
7111 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7112 arg2
= CALL_EXPR_ARG (exp
, 2); /* u8 */
7114 src_vreg
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
7115 op0
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* [I]0-7 */
7116 op1
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7117 op2
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7119 /* target <- src vreg */
7120 emit_insn (gen_move_insn (target
, src_vreg
));
7122 /* target <- vec_concat: target, mem(Ib, u8) */
7123 mode0
= insn_data
[icode
].operand
[3].mode
;
7124 mode1
= insn_data
[icode
].operand
[1].mode
;
7126 if ( (!(*insn_data
[icode
].operand
[3].predicate
) (op0
, mode0
))
7127 || !(UNSIGNED_INT3 (INTVAL (op0
))))
7128 error ("operand 1 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7131 if ( (!(*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
7132 || !(UNSIGNED_INT8 (INTVAL (op1
))))
7133 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
7136 pat
= GEN_FCN (icode
) (target
, op1
, op2
, op0
);
7146 arg0
= CALL_EXPR_ARG (exp
, 0); /* src vreg */
7147 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7148 arg2
= CALL_EXPR_ARG (exp
, 2); /* u8 */
7150 op0
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7151 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* I[0-7] */
7152 op2
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7153 op3
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
); /* Vdest */
7155 mode0
= insn_data
[icode
].operand
[0].mode
;
7156 mode1
= insn_data
[icode
].operand
[1].mode
;
7157 mode2
= insn_data
[icode
].operand
[2].mode
;
7158 mode3
= insn_data
[icode
].operand
[3].mode
;
7160 if ( (!(*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
7161 || !(UNSIGNED_INT3 (INTVAL (op1
))))
7162 error ("operand 2 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7165 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op2
, mode2
))
7166 || !(UNSIGNED_INT8 (INTVAL (op2
))))
7167 error ("operand 3 of %s instruction should be an unsigned 8-bit value",
7170 if (!(*insn_data
[icode
].operand
[3].predicate
) (op3
, mode3
))
7171 op3
= copy_to_mode_reg (mode3
, op3
);
7173 pat
= GEN_FCN (icode
) (op0
, op1
, op2
, op3
);
7182 arg0
= CALL_EXPR_ARG (exp
, 0); /* dest vreg */
7183 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7185 op0
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7186 op1
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* I[0-7] */
7187 op2
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7189 /* target <- src vreg */
7190 target
= gen_reg_rtx (V8HImode
);
7192 /* target <- vec_concat: target, mem(Ib, u8) */
7193 mode0
= insn_data
[icode
].operand
[1].mode
;
7194 mode1
= insn_data
[icode
].operand
[2].mode
;
7195 mode2
= insn_data
[icode
].operand
[3].mode
;
7197 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7198 || !(UNSIGNED_INT3 (INTVAL (op1
))))
7199 error ("operand 1 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7202 if ( (!(*insn_data
[icode
].operand
[3].predicate
) (op2
, mode2
))
7203 || !(UNSIGNED_INT8 (INTVAL (op2
))))
7204 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
7207 pat
= GEN_FCN (icode
) (target
, op0
, op1
, op2
);
7214 case void_Va_u3_Ib_u8
:
7216 arg0
= CALL_EXPR_ARG (exp
, 0); /* source vreg */
7217 arg1
= CALL_EXPR_ARG (exp
, 1); /* u3 */
7218 arg2
= CALL_EXPR_ARG (exp
, 2); /* [I]0-7 */
7219 arg3
= CALL_EXPR_ARG (exp
, 3); /* u8 */
7221 op0
= expand_expr (arg3
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7222 op1
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR */
7223 op2
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* [I]0-7 */
7224 op3
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);/* vreg to be stored */
7225 op4
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* vreg 0-7 subreg no. */
7227 mode0
= insn_data
[icode
].operand
[0].mode
;
7228 mode2
= insn_data
[icode
].operand
[2].mode
;
7229 mode3
= insn_data
[icode
].operand
[3].mode
;
7230 mode4
= insn_data
[icode
].operand
[4].mode
;
7232 /* Do some correctness checks for the operands. */
7233 if ( (!(*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
7234 || !(UNSIGNED_INT8 (INTVAL (op0
))))
7235 error ("operand 4 of %s instruction should be an unsigned 8-bit value (0-255)",
7238 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op2
, mode2
))
7239 || !(UNSIGNED_INT3 (INTVAL (op2
))))
7240 error ("operand 3 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7243 if (!(*insn_data
[icode
].operand
[3].predicate
) (op3
, mode3
))
7244 op3
= copy_to_mode_reg (mode3
, op3
);
7246 if ( (!(*insn_data
[icode
].operand
[4].predicate
) (op4
, mode4
))
7247 || !(UNSIGNED_INT3 (INTVAL (op4
))))
7248 error ("operand 2 of %s instruction should be an unsigned 3-bit value (subreg 0-7)",
7250 else if (icode
== CODE_FOR_vst32_n_insn
7251 && ((INTVAL(op4
) % 2 ) != 0))
7252 error ("operand 2 of %s instruction should be an even 3-bit value (subreg 0,2,4,6)",
7255 pat
= GEN_FCN (icode
) (op0
, op1
, op2
, op3
, op4
);
7269 arc_preserve_reload_p (rtx in
)
7271 return (GET_CODE (in
) == PLUS
7272 && RTX_OK_FOR_BASE_P (XEXP (in
, 0), true)
7273 && CONST_INT_P (XEXP (in
, 1))
7274 && !((INTVAL (XEXP (in
, 1)) & 511)));
7278 arc_register_move_cost (enum machine_mode
,
7279 enum reg_class from_class
, enum reg_class to_class
)
7281 /* The ARC600 has no bypass for extension registers, hence a nop might be
7282 needed to be inserted after a write so that reads are safe. */
7285 if (to_class
== MPY_WRITABLE_CORE_REGS
)
7287 /* Instructions modifying LP_COUNT need 4 additional cycles before
7288 the register will actually contain the value. */
7289 else if (to_class
== LPCOUNT_REG
)
7291 else if (to_class
== WRITABLE_CORE_REGS
)
7295 /* The ARC700 stalls for 3 cycles when *reading* from lp_count. */
7297 && (from_class
== LPCOUNT_REG
|| from_class
== ALL_CORE_REGS
7298 || from_class
== WRITABLE_CORE_REGS
))
7301 /* Force an attempt to 'mov Dy,Dx' to spill. */
7302 if (TARGET_ARC700
&& TARGET_DPFP
7303 && from_class
== DOUBLE_REGS
&& to_class
== DOUBLE_REGS
)
7309 /* Emit code for an addsi3 instruction with OPERANDS.
7310 COND_P indicates if this will use conditional execution.
7311 Return the length of the instruction.
7312 If OUTPUT_P is false, don't actually output the instruction, just return
7315 arc_output_addsi (rtx
*operands
, bool cond_p
, bool output_p
)
7319 int match
= operands_match_p (operands
[0], operands
[1]);
7320 int match2
= operands_match_p (operands
[0], operands
[2]);
7321 int intval
= (REG_P (operands
[2]) ? 1
7322 : CONST_INT_P (operands
[2]) ? INTVAL (operands
[2]) : 0xbadc057);
7323 int neg_intval
= -intval
;
7324 int short_0
= satisfies_constraint_Rcq (operands
[0]);
7325 int short_p
= (!cond_p
&& short_0
&& satisfies_constraint_Rcq (operands
[1]));
7328 #define ADDSI_OUTPUT1(FORMAT) do {\
7330 output_asm_insn (FORMAT, operands);\
7333 #define ADDSI_OUTPUT(LIST) do {\
7336 ADDSI_OUTPUT1 (format);\
7340 /* First try to emit a 16 bit insn. */
7343 /* If we are actually about to output this insn, don't try a 16 bit
7344 variant if we already decided that we don't want that
7345 (I.e. we upsized this insn to align some following insn.)
7346 E.g. add_s r0,sp,70 is 16 bit, but add r0,sp,70 requires a LIMM -
7347 but add1 r0,sp,35 doesn't. */
7348 && (!output_p
|| (get_attr_length (current_output_insn
) & 2)))
7351 && (REG_P (operands
[2])
7352 ? (match
|| satisfies_constraint_Rcq (operands
[2]))
7353 : (unsigned) intval
<= (match
? 127 : 7)))
7354 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7355 if (short_0
&& REG_P (operands
[1]) && match2
)
7356 ADDSI_OUTPUT1 ("add%? %0,%2,%1");
7357 if ((short_0
|| REGNO (operands
[0]) == STACK_POINTER_REGNUM
)
7358 && REGNO (operands
[1]) == STACK_POINTER_REGNUM
&& !(intval
& ~124))
7359 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7361 if ((short_p
&& (unsigned) neg_intval
<= (match
? 31 : 7))
7362 || (REGNO (operands
[0]) == STACK_POINTER_REGNUM
7363 && match
&& !(neg_intval
& ~124)))
7364 ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
7367 /* Now try to emit a 32 bit insn without long immediate. */
7369 if (!match
&& match2
&& REG_P (operands
[1]))
7370 ADDSI_OUTPUT1 ("add%? %0,%2,%1");
7371 if (match
|| !cond_p
)
7373 int limit
= (match
&& !cond_p
) ? 0x7ff : 0x3f;
7374 int range_factor
= neg_intval
& intval
;
7377 if (intval
== -1 << 31)
7378 ADDSI_OUTPUT1 ("bxor%? %0,%1,31");
7380 /* If we can use a straight add / sub instead of a {add,sub}[123] of
7381 same size, do, so - the insn latency is lower. */
7382 /* -0x800 is a 12-bit constant for add /add3 / sub / sub3, but
7384 if ((intval
>= 0 && intval
<= limit
)
7385 || (intval
== -0x800 && limit
== 0x7ff))
7386 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7387 else if ((intval
< 0 && neg_intval
<= limit
)
7388 || (intval
== 0x800 && limit
== 0x7ff))
7389 ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
7390 shift
= range_factor
>= 8 ? 3 : (range_factor
>> 1);
7391 gcc_assert (shift
== 0 || shift
== 1 || shift
== 2 || shift
== 3);
7392 gcc_assert ((((1 << shift
) - 1) & intval
) == 0);
7393 if (((intval
< 0 && intval
!= -0x4000)
7394 /* sub[123] is slower than add_s / sub, only use it if it
7395 avoids a long immediate. */
7396 && neg_intval
<= limit
<< shift
)
7397 || (intval
== 0x4000 && limit
== 0x7ff))
7398 ADDSI_OUTPUT ((format
, "sub%d%%? %%0,%%1,%d",
7399 shift
, neg_intval
>> shift
));
7400 else if ((intval
>= 0 && intval
<= limit
<< shift
)
7401 || (intval
== -0x4000 && limit
== 0x7ff))
7402 ADDSI_OUTPUT ((format
, "add%d%%? %%0,%%1,%d", shift
, intval
>> shift
));
7404 /* Try to emit a 16 bit opcode with long immediate. */
7406 if (short_p
&& match
)
7407 ADDSI_OUTPUT1 ("add%? %0,%1,%S2");
7409 /* We have to use a 32 bit opcode, and with a long immediate. */
7411 ADDSI_OUTPUT1 (intval
< 0 ? "sub%? %0,%1,%n2" : "add%? %0,%1,%S2");
7414 /* Emit code for an commutative_cond_exec instruction with OPERANDS.
7415 Return the length of the instruction.
7416 If OUTPUT_P is false, don't actually output the instruction, just return
7419 arc_output_commutative_cond_exec (rtx
*operands
, bool output_p
)
7421 enum rtx_code commutative_op
= GET_CODE (operands
[3]);
7422 const char *pat
= NULL
;
7424 /* Canonical rtl should not have a constant in the first operand position. */
7425 gcc_assert (!CONSTANT_P (operands
[1]));
7427 switch (commutative_op
)
7430 if (satisfies_constraint_C1p (operands
[2]))
7431 pat
= "bmsk%? %0,%1,%Z2";
7432 else if (satisfies_constraint_Ccp (operands
[2]))
7433 pat
= "bclr%? %0,%1,%M2";
7434 else if (satisfies_constraint_CnL (operands
[2]))
7435 pat
= "bic%? %0,%1,%n2-1";
7438 if (satisfies_constraint_C0p (operands
[2]))
7439 pat
= "bset%? %0,%1,%z2";
7442 if (satisfies_constraint_C0p (operands
[2]))
7443 pat
= "bxor%? %0,%1,%z2";
7446 return arc_output_addsi (operands
, true, output_p
);
7450 output_asm_insn (pat
? pat
: "%O3.%d5 %0,%1,%2", operands
);
7451 if (pat
|| REG_P (operands
[2]) || satisfies_constraint_L (operands
[2]))
7456 /* Helper function of arc_expand_movmem. ADDR points to a chunk of memory.
7457 Emit code and return an potentially modified address such that offsets
7458 up to SIZE are can be added to yield a legitimate address.
7459 if REUSE is set, ADDR is a register that may be modified. */
7462 force_offsettable (rtx addr
, HOST_WIDE_INT size
, bool reuse
)
7465 rtx offs
= const0_rtx
;
7467 if (GET_CODE (base
) == PLUS
)
7469 offs
= XEXP (base
, 1);
7470 base
= XEXP (base
, 0);
7473 || (REGNO (base
) != STACK_POINTER_REGNUM
7474 && REGNO_PTR_FRAME_P (REGNO (addr
)))
7475 || !CONST_INT_P (offs
) || !SMALL_INT (INTVAL (offs
))
7476 || !SMALL_INT (INTVAL (offs
) + size
))
7479 emit_insn (gen_add2_insn (addr
, offs
));
7481 addr
= copy_to_mode_reg (Pmode
, addr
);
7486 /* Like move_by_pieces, but take account of load latency,
7487 and actual offset ranges.
7488 Return true on success. */
7491 arc_expand_movmem (rtx
*operands
)
7493 rtx dst
= operands
[0];
7494 rtx src
= operands
[1];
7495 rtx dst_addr
, src_addr
;
7497 int align
= INTVAL (operands
[3]);
7504 if (!CONST_INT_P (operands
[2]))
7506 size
= INTVAL (operands
[2]);
7507 /* move_by_pieces_ninsns is static, so we can't use it. */
7509 n_pieces
= (size
+ 2) / 4U + (size
& 1);
7510 else if (align
== 2)
7511 n_pieces
= (size
+ 1) / 2U;
7514 if (n_pieces
>= (unsigned int) (optimize_size
? 3 : 15))
7518 dst_addr
= force_offsettable (XEXP (operands
[0], 0), size
, 0);
7519 src_addr
= force_offsettable (XEXP (operands
[1], 0), size
, 0);
7520 store
[0] = store
[1] = NULL_RTX
;
7521 tmpx
[0] = tmpx
[1] = NULL_RTX
;
7522 for (i
= 0; size
> 0; i
^= 1, size
-= piece
)
7525 enum machine_mode mode
;
7528 piece
= size
& -size
;
7529 mode
= smallest_mode_for_size (piece
* BITS_PER_UNIT
, MODE_INT
);
7530 /* If we don't re-use temporaries, the scheduler gets carried away,
7531 and the register pressure gets unnecessarily high. */
7532 if (0 && tmpx
[i
] && GET_MODE (tmpx
[i
]) == mode
)
7535 tmpx
[i
] = tmp
= gen_reg_rtx (mode
);
7536 dst_addr
= force_offsettable (dst_addr
, piece
, 1);
7537 src_addr
= force_offsettable (src_addr
, piece
, 1);
7539 emit_insn (store
[i
]);
7540 emit_move_insn (tmp
, change_address (src
, mode
, src_addr
));
7541 store
[i
] = gen_move_insn (change_address (dst
, mode
, dst_addr
), tmp
);
7542 dst_addr
= plus_constant (Pmode
, dst_addr
, piece
);
7543 src_addr
= plus_constant (Pmode
, src_addr
, piece
);
7546 emit_insn (store
[i
]);
7548 emit_insn (store
[i
^1]);
7552 /* Prepare operands for move in MODE. Return true iff the move has
7556 prepare_move_operands (rtx
*operands
, enum machine_mode mode
)
7558 /* We used to do this only for MODE_INT Modes, but addresses to floating
7559 point variables may well be in the small data section. */
7562 if (!TARGET_NO_SDATA_SET
&& small_data_pattern (operands
[0], Pmode
))
7563 operands
[0] = arc_rewrite_small_data (operands
[0]);
7564 else if (mode
== SImode
&& flag_pic
&& SYMBOLIC_CONST (operands
[1]))
7566 emit_pic_move (operands
, SImode
);
7568 /* Disable any REG_EQUALs associated with the symref
7569 otherwise the optimization pass undoes the work done
7570 here and references the variable directly. */
7572 else if (GET_CODE (operands
[0]) != MEM
7573 && !TARGET_NO_SDATA_SET
7574 && small_data_pattern (operands
[1], Pmode
))
7576 /* This is to take care of address calculations involving sdata
7578 operands
[1] = arc_rewrite_small_data (operands
[1]);
7580 emit_insn (gen_rtx_SET (mode
, operands
[0],operands
[1]));
7581 /* ??? This note is useless, since it only restates the set itself.
7582 We should rather use the original SYMBOL_REF. However, there is
7583 the problem that we are lying to the compiler about these
7584 SYMBOL_REFs to start with. symbol@sda should be encoded specially
7585 so that we can tell it apart from an actual symbol. */
7586 set_unique_reg_note (get_last_insn (), REG_EQUAL
, operands
[1]);
7588 /* Take care of the REG_EQUAL note that will be attached to mark the
7589 output reg equal to the initial symbol_ref after this code is
7591 emit_move_insn (operands
[0], operands
[0]);
7596 if (MEM_P (operands
[0])
7597 && !(reload_in_progress
|| reload_completed
))
7599 operands
[1] = force_reg (mode
, operands
[1]);
7600 if (!move_dest_operand (operands
[0], mode
))
7602 rtx addr
= copy_to_mode_reg (Pmode
, XEXP (operands
[0], 0));
7603 /* This is like change_address_1 (operands[0], mode, 0, 1) ,
7604 except that we can't use that function because it is static. */
7605 rtx pat
= change_address (operands
[0], mode
, addr
);
7606 MEM_COPY_ATTRIBUTES (pat
, operands
[0]);
7609 if (!cse_not_expected
)
7611 rtx pat
= XEXP (operands
[0], 0);
7613 pat
= arc_legitimize_address_0 (pat
, pat
, mode
);
7616 pat
= change_address (operands
[0], mode
, pat
);
7617 MEM_COPY_ATTRIBUTES (pat
, operands
[0]);
7623 if (MEM_P (operands
[1]) && !cse_not_expected
)
7625 rtx pat
= XEXP (operands
[1], 0);
7627 pat
= arc_legitimize_address_0 (pat
, pat
, mode
);
7630 pat
= change_address (operands
[1], mode
, pat
);
7631 MEM_COPY_ATTRIBUTES (pat
, operands
[1]);
7639 /* Prepare OPERANDS for an extension using CODE to OMODE.
7640 Return true iff the move has been emitted. */
7643 prepare_extend_operands (rtx
*operands
, enum rtx_code code
,
7644 enum machine_mode omode
)
7646 if (!TARGET_NO_SDATA_SET
&& small_data_pattern (operands
[1], Pmode
))
7648 /* This is to take care of address calculations involving sdata
7651 = gen_rtx_fmt_e (code
, omode
, arc_rewrite_small_data (operands
[1]));
7652 emit_insn (gen_rtx_SET (omode
, operands
[0], operands
[1]));
7653 set_unique_reg_note (get_last_insn (), REG_EQUAL
, operands
[1]);
7655 /* Take care of the REG_EQUAL note that will be attached to mark the
7656 output reg equal to the initial extension after this code is
7658 emit_move_insn (operands
[0], operands
[0]);
7664 /* Output a library call to a function called FNAME that has been arranged
7665 to be local to any dso. */
7668 arc_output_libcall (const char *fname
)
7670 unsigned len
= strlen (fname
);
7671 static char buf
[64];
7673 gcc_assert (len
< sizeof buf
- 35);
7674 if (TARGET_LONG_CALLS_SET
7675 || (TARGET_MEDIUM_CALLS
&& arc_ccfsm_cond_exec_p ()))
7678 sprintf (buf
, "add r12,pcl,@%s-(.&-4)\n\tjl%%!%%* [r12]", fname
);
7680 sprintf (buf
, "jl%%! @%s", fname
);
7683 sprintf (buf
, "bl%%!%%* @%s", fname
);
7687 /* Return the SImode highpart of the DImode value IN. */
7690 disi_highpart (rtx in
)
7692 return simplify_gen_subreg (SImode
, in
, DImode
, TARGET_BIG_ENDIAN
? 0 : 4);
7695 /* Called by arc600_corereg_hazard via for_each_rtx.
7696 If a hazard is found, return a conservative estimate of the required
7697 length adjustment to accomodate a nop. */
7700 arc600_corereg_hazard_1 (rtx
*xp
, void *data
)
7704 rtx pat
= (rtx
) data
;
7706 switch (GET_CODE (x
))
7708 case SET
: case POST_INC
: case POST_DEC
: case PRE_INC
: case PRE_DEC
:
7711 /* This is also fine for PRE/POST_MODIFY, because they contain a SET. */
7715 /* Check if this sets a an extension register. N.B. we use 61 for the
7716 condition codes, which is definitely not an extension register. */
7717 if (REG_P (dest
) && REGNO (dest
) >= 32 && REGNO (dest
) < 61
7718 /* Check if the same register is used by the PAT. */
7719 && (refers_to_regno_p
7721 REGNO (dest
) + (GET_MODE_SIZE (GET_MODE (dest
)) + 3) / 4U, pat
, 0)))
7727 /* Return length adjustment for INSN.
7729 A write to a core reg greater or equal to 32 must not be immediately
7730 followed by a use. Anticipate the length requirement to insert a nop
7731 between PRED and SUCC to prevent a hazard. */
7734 arc600_corereg_hazard (rtx pred
, rtx succ
)
7738 /* If SUCC is a doloop_end_i with a preceding label, we must output a nop
7739 in front of SUCC anyway, so there will be separation between PRED and
7741 if (recog_memoized (succ
) == CODE_FOR_doloop_end_i
7742 && LABEL_P (prev_nonnote_insn (succ
)))
7744 if (recog_memoized (succ
) == CODE_FOR_doloop_begin_i
)
7746 if (GET_CODE (PATTERN (pred
)) == SEQUENCE
)
7747 pred
= XVECEXP (PATTERN (pred
), 0, 1);
7748 if (GET_CODE (PATTERN (succ
)) == SEQUENCE
)
7749 succ
= XVECEXP (PATTERN (succ
), 0, 0);
7750 if (recog_memoized (pred
) == CODE_FOR_mulsi_600
7751 || recog_memoized (pred
) == CODE_FOR_umul_600
7752 || recog_memoized (pred
) == CODE_FOR_mac_600
7753 || recog_memoized (pred
) == CODE_FOR_mul64_600
7754 || recog_memoized (pred
) == CODE_FOR_mac64_600
7755 || recog_memoized (pred
) == CODE_FOR_umul64_600
7756 || recog_memoized (pred
) == CODE_FOR_umac64_600
)
7758 return for_each_rtx (&PATTERN (pred
), arc600_corereg_hazard_1
,
7763 A write to a core reg greater or equal to 32 must not be immediately
7764 followed by a use. Anticipate the length requirement to insert a nop
7765 between PRED and SUCC to prevent a hazard. */
7768 arc_hazard (rtx pred
, rtx succ
)
7772 if (!pred
|| !INSN_P (pred
) || !succ
|| !INSN_P (succ
))
7774 /* We might have a CALL to a non-returning function before a loop end.
7775 ??? Although the manual says that's OK (the target is outside the loop,
7776 and the loop counter unused there), the assembler barfs on this, so we
7777 must instert a nop before such a call too. */
7778 if (recog_memoized (succ
) == CODE_FOR_doloop_end_i
7779 && (JUMP_P (pred
) || CALL_P (pred
)
7780 || GET_CODE (PATTERN (pred
)) == SEQUENCE
))
7782 return arc600_corereg_hazard (pred
, succ
);
7785 /* Return length adjustment for INSN. */
7788 arc_adjust_insn_length (rtx insn
, int len
, bool)
7792 /* We already handle sequences by ignoring the delay sequence flag. */
7793 if (GET_CODE (PATTERN (insn
)) == SEQUENCE
)
7796 /* It is impossible to jump to the very end of a Zero-Overhead Loop, as
7797 the ZOL mechanism only triggers when advancing to the end address,
7798 so if there's a label at the end of a ZOL, we need to insert a nop.
7799 The ARC600 ZOL also has extra restrictions on jumps at the end of a
7801 if (recog_memoized (insn
) == CODE_FOR_doloop_end_i
)
7803 rtx prev
= prev_nonnote_insn (insn
);
7805 return ((LABEL_P (prev
)
7808 || CALL_P (prev
) /* Could be a noreturn call. */
7809 || (NONJUMP_INSN_P (prev
)
7810 && GET_CODE (PATTERN (prev
)) == SEQUENCE
))))
7814 /* Check for return with but one preceding insn since function
7816 if (TARGET_PAD_RETURN
7818 && GET_CODE (PATTERN (insn
)) != ADDR_VEC
7819 && GET_CODE (PATTERN (insn
)) != ADDR_DIFF_VEC
7820 && get_attr_type (insn
) == TYPE_RETURN
)
7822 rtx prev
= prev_active_insn (insn
);
7824 if (!prev
|| !(prev
= prev_active_insn (prev
))
7825 || ((NONJUMP_INSN_P (prev
)
7826 && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
7827 ? CALL_ATTR (XVECEXP (PATTERN (prev
), 0, 0), NON_SIBCALL
)
7828 : CALL_ATTR (prev
, NON_SIBCALL
)))
7833 rtx succ
= next_real_insn (insn
);
7835 /* One the ARC600, a write to an extension register must be separated
7837 if (succ
&& INSN_P (succ
))
7838 len
+= arc600_corereg_hazard (insn
, succ
);
7841 /* Restore extracted operands - otherwise splitters like the addsi3_mixed one
7843 extract_constrain_insn_cached (insn
);
7848 /* Values for length_sensitive. */
7852 ARC_LS_25
, // 25 bit offset, B
7853 ARC_LS_21
, // 21 bit offset, Bcc
7854 ARC_LS_U13
,// 13 bit unsigned offset, LP
7855 ARC_LS_10
, // 10 bit offset, B_s, Beq_s, Bne_s
7856 ARC_LS_9
, // 9 bit offset, BRcc
7857 ARC_LS_8
, // 8 bit offset, BRcc_s
7858 ARC_LS_U7
, // 7 bit unsigned offset, LPcc
7859 ARC_LS_7
// 7 bit offset, Bcc_s
7862 /* While the infrastructure patch is waiting for review, duplicate the
7863 struct definitions, to allow this file to compile. */
7868 /* Cost as a branch / call target or call return address. */
7870 int fallthrough_cost
;
7873 /* 0 for not length sensitive, 1 for largest offset range,
7874 * 2 for next smaller etc. */
7875 unsigned length_sensitive
: 8;
7877 } insn_length_variant_t
;
7879 typedef struct insn_length_parameters_s
7884 int (*get_variants
) (rtx
, int, bool, bool, insn_length_variant_t
*);
7885 } insn_length_parameters_t
;
7888 arc_insn_length_parameters (insn_length_parameters_t
*ilp
) ATTRIBUTE_UNUSED
;
7892 arc_get_insn_variants (rtx insn
, int len
, bool, bool target_p
,
7893 insn_length_variant_t
*ilv
)
7895 if (!NONDEBUG_INSN_P (insn
))
7897 enum attr_type type
;
7898 /* shorten_branches doesn't take optimize_size into account yet for the
7899 get_variants mechanism, so turn this off for now. */
7902 if (GET_CODE (PATTERN (insn
)) == SEQUENCE
)
7904 /* The interaction of a short delay slot insn with a short branch is
7905 too weird for shorten_branches to piece together, so describe the
7908 if (TARGET_UPSIZE_DBR
7909 && get_attr_length (XVECEXP ((pat
= PATTERN (insn
)), 0, 1)) <= 2
7910 && (((type
= get_attr_type (inner
= XVECEXP (pat
, 0, 0)))
7911 == TYPE_UNCOND_BRANCH
)
7912 || type
== TYPE_BRANCH
)
7913 && get_attr_delay_slot_filled (inner
) == DELAY_SLOT_FILLED_YES
)
7916 = arc_get_insn_variants (inner
, get_attr_length (inner
), true,
7918 /* The short variant gets split into a higher-cost aligned
7919 and a lower cost unaligned variant. */
7920 gcc_assert (n_variants
);
7921 gcc_assert (ilv
[1].length_sensitive
== ARC_LS_7
7922 || ilv
[1].length_sensitive
== ARC_LS_10
);
7923 gcc_assert (ilv
[1].align_set
== 3);
7925 ilv
[0].align_set
= 1;
7926 ilv
[0].branch_cost
+= 1;
7927 ilv
[1].align_set
= 2;
7929 for (int i
= 0; i
< n_variants
; i
++)
7931 /* In case an instruction with aligned size is wanted, and
7932 the short variants are unavailable / too expensive, add
7933 versions of long branch + long delay slot. */
7934 for (int i
= 2, end
= n_variants
; i
< end
; i
++, n_variants
++)
7936 ilv
[n_variants
] = ilv
[i
];
7937 ilv
[n_variants
].length
+= 2;
7943 insn_length_variant_t
*first_ilv
= ilv
;
7944 type
= get_attr_type (insn
);
7946 = (get_attr_delay_slot_filled (insn
) == DELAY_SLOT_FILLED_YES
);
7947 int branch_align_cost
= delay_filled
? 0 : 1;
7948 int branch_unalign_cost
= delay_filled
? 0 : TARGET_UNALIGN_BRANCH
? 0 : 1;
7949 /* If the previous instruction is an sfunc call, this insn is always
7950 a target, even though the middle-end is unaware of this. */
7951 bool force_target
= false;
7952 rtx prev
= prev_active_insn (insn
);
7953 if (prev
&& arc_next_active_insn (prev
, 0) == insn
7954 && ((NONJUMP_INSN_P (prev
) && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
7955 ? CALL_ATTR (XVECEXP (PATTERN (prev
), 0, 0), NON_SIBCALL
)
7956 : (CALL_ATTR (prev
, NON_SIBCALL
)
7957 && NEXT_INSN (PREV_INSN (prev
)) == prev
)))
7958 force_target
= true;
7963 /* Short BRCC only comes in no-delay-slot version, and without limm */
7968 ilv
->branch_cost
= 1;
7969 ilv
->enabled
= (len
== 2);
7970 ilv
->length_sensitive
= ARC_LS_8
;
7974 case TYPE_BRCC_NO_DELAY_SLOT
:
7975 /* doloop_fallback* patterns are TYPE_BRCC_NO_DELAY_SLOT for
7976 (delay slot) scheduling purposes, but they are longer. */
7977 if (GET_CODE (PATTERN (insn
)) == PARALLEL
7978 && GET_CODE (XVECEXP (PATTERN (insn
), 0, 1)) == SET
)
7980 /* Standard BRCC: 4 bytes, or 8 bytes with limm. */
7981 ilv
->length
= ((type
== TYPE_BRCC
) ? 4 : 8);
7983 ilv
->branch_cost
= branch_align_cost
;
7984 ilv
->enabled
= (len
<= ilv
->length
);
7985 ilv
->length_sensitive
= ARC_LS_9
;
7986 if ((target_p
|| force_target
)
7987 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
7993 ilv
->target_cost
= 1;
7994 ilv
->branch_cost
= branch_unalign_cost
;
7999 op
= XEXP (SET_SRC (XVECEXP (PATTERN (insn
), 0, 0)), 0);
8002 if (GET_CODE (op0
) == ZERO_EXTRACT
8003 && satisfies_constraint_L (XEXP (op0
, 2)))
8004 op0
= XEXP (op0
, 0);
8005 if (satisfies_constraint_Rcq (op0
))
8007 ilv
->length
= ((type
== TYPE_BRCC
) ? 6 : 10);
8009 ilv
->branch_cost
= 1 + branch_align_cost
;
8010 ilv
->fallthrough_cost
= 1;
8011 ilv
->enabled
= true;
8012 ilv
->length_sensitive
= ARC_LS_21
;
8013 if (!delay_filled
&& TARGET_UNALIGN_BRANCH
)
8019 ilv
->branch_cost
= 1 + branch_unalign_cost
;
8023 ilv
->length
= ((type
== TYPE_BRCC
) ? 8 : 12);
8025 ilv
->branch_cost
= 1 + branch_align_cost
;
8026 ilv
->fallthrough_cost
= 1;
8027 ilv
->enabled
= true;
8028 ilv
->length_sensitive
= ARC_LS_21
;
8029 if ((target_p
|| force_target
)
8030 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8036 ilv
->target_cost
= 1;
8037 ilv
->branch_cost
= 1 + branch_unalign_cost
;
8045 case TYPE_CALL_NO_DELAY_SLOT
:
8050 ilv
->length_sensitive
8051 = GET_CODE (PATTERN (insn
)) == COND_EXEC
? ARC_LS_21
: ARC_LS_25
;
8054 ilv
->fallthrough_cost
= branch_align_cost
;
8055 ilv
->enabled
= true;
8056 if ((target_p
|| force_target
)
8057 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8063 ilv
->target_cost
= 1;
8064 ilv
->fallthrough_cost
= branch_unalign_cost
;
8068 case TYPE_UNCOND_BRANCH
:
8069 /* Strictly speaking, this should be ARC_LS_10 for equality comparisons,
8070 but that makes no difference at the moment. */
8071 ilv
->length_sensitive
= ARC_LS_7
;
8072 ilv
[1].length_sensitive
= ARC_LS_25
;
8075 ilv
->length_sensitive
= ARC_LS_10
;
8076 ilv
[1].length_sensitive
= ARC_LS_21
;
8080 ilv
->branch_cost
= branch_align_cost
;
8081 ilv
->enabled
= (len
== ilv
->length
);
8085 ilv
->branch_cost
= branch_align_cost
;
8086 ilv
->enabled
= true;
8087 if ((target_p
|| force_target
)
8088 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8094 ilv
->target_cost
= 1;
8095 ilv
->branch_cost
= branch_unalign_cost
;
8102 /* For every short insn, there is generally also a long insn.
8103 trap_s is an exception. */
8104 if ((len
& 2) == 0 || recog_memoized (insn
) == CODE_FOR_trap_s
)
8111 ilv
->length
= len
+ 2;
8113 if (target_p
|| force_target
)
8119 ilv
->target_cost
= 1;
8123 /* If the previous instruction is an sfunc call, this insn is always
8124 a target, even though the middle-end is unaware of this.
8125 Therefore, if we have a call predecessor, transfer the target cost
8126 to the fallthrough and branch costs. */
8129 for (insn_length_variant_t
*p
= first_ilv
; p
< ilv
; p
++)
8131 p
->fallthrough_cost
+= p
->target_cost
;
8132 p
->branch_cost
+= p
->target_cost
;
8137 return ilv
- first_ilv
;
8141 arc_insn_length_parameters (insn_length_parameters_t
*ilp
)
8143 ilp
->align_unit_log
= 1;
8144 ilp
->align_base_log
= 1;
8145 ilp
->max_variants
= 7;
8146 ilp
->get_variants
= arc_get_insn_variants
;
8149 /* Return a copy of COND from *STATEP, inverted if that is indicated by the
8150 CC field of *STATEP. */
8153 arc_get_ccfsm_cond (struct arc_ccfsm
*statep
, bool reverse
)
8155 rtx cond
= statep
->cond
;
8156 int raw_cc
= get_arc_condition_code (cond
);
8158 raw_cc
= ARC_INVERSE_CONDITION_CODE (raw_cc
);
8160 if (statep
->cc
== raw_cc
)
8161 return copy_rtx (cond
);
8163 gcc_assert (ARC_INVERSE_CONDITION_CODE (raw_cc
) == statep
->cc
);
8165 enum machine_mode ccm
= GET_MODE (XEXP (cond
, 0));
8166 enum rtx_code code
= reverse_condition (GET_CODE (cond
));
8167 if (code
== UNKNOWN
|| ccm
== CC_FP_GTmode
|| ccm
== CC_FP_GEmode
)
8168 code
= reverse_condition_maybe_unordered (GET_CODE (cond
));
8170 return gen_rtx_fmt_ee (code
, GET_MODE (cond
),
8171 copy_rtx (XEXP (cond
, 0)), copy_rtx (XEXP (cond
, 1)));
8174 /* Return version of PAT conditionalized with COND, which is part of INSN.
8175 ANNULLED indicates if INSN is an annulled delay-slot insn.
8176 Register further changes if necessary. */
8178 conditionalize_nonjump (rtx pat
, rtx cond
, rtx insn
, bool annulled
)
8180 /* For commutative operators, we generally prefer to have
8181 the first source match the destination. */
8182 if (GET_CODE (pat
) == SET
)
8184 rtx src
= SET_SRC (pat
);
8186 if (COMMUTATIVE_P (src
))
8188 rtx src0
= XEXP (src
, 0);
8189 rtx src1
= XEXP (src
, 1);
8190 rtx dst
= SET_DEST (pat
);
8192 if (rtx_equal_p (src1
, dst
) && !rtx_equal_p (src0
, dst
)
8193 /* Leave add_n alone - the canonical form is to
8194 have the complex summand first. */
8196 pat
= gen_rtx_SET (VOIDmode
, dst
,
8197 gen_rtx_fmt_ee (GET_CODE (src
), GET_MODE (src
),
8202 /* dwarf2out.c:dwarf2out_frame_debug_expr doesn't know
8203 what to do with COND_EXEC. */
8204 if (RTX_FRAME_RELATED_P (insn
))
8206 /* If this is the delay slot insn of an anulled branch,
8207 dwarf2out.c:scan_trace understands the anulling semantics
8208 without the COND_EXEC. */
8209 gcc_assert (annulled
);
8210 rtx note
= alloc_reg_note (REG_FRAME_RELATED_EXPR
, pat
,
8212 validate_change (insn
, ®_NOTES (insn
), note
, 1);
8214 pat
= gen_rtx_COND_EXEC (VOIDmode
, cond
, pat
);
8218 /* Use the ccfsm machinery to do if conversion. */
8223 struct arc_ccfsm
*statep
= &cfun
->machine
->ccfsm_current
;
8224 basic_block merge_bb
= 0;
8226 memset (statep
, 0, sizeof *statep
);
8227 for (rtx insn
= get_insns (); insn
; insn
= next_insn (insn
))
8229 arc_ccfsm_advance (insn
, statep
);
8231 switch (statep
->state
)
8239 /* Deleted branch. */
8240 gcc_assert (!merge_bb
);
8241 merge_bb
= BLOCK_FOR_INSN (insn
);
8243 = BLOCK_FOR_INSN (NEXT_INSN (NEXT_INSN (PREV_INSN (insn
))));
8244 arc_ccfsm_post_advance (insn
, statep
);
8245 gcc_assert (!IN_RANGE (statep
->state
, 1, 2));
8246 rtx seq
= NEXT_INSN (PREV_INSN (insn
));
8249 rtx slot
= XVECEXP (PATTERN (seq
), 0, 1);
8250 rtx pat
= PATTERN (slot
);
8251 if (INSN_ANNULLED_BRANCH_P (insn
))
8254 = arc_get_ccfsm_cond (statep
, INSN_FROM_TARGET_P (slot
));
8255 pat
= gen_rtx_COND_EXEC (VOIDmode
, cond
, pat
);
8257 if (!validate_change (seq
, &PATTERN (seq
), pat
, 0))
8259 PUT_CODE (slot
, NOTE
);
8260 NOTE_KIND (slot
) = NOTE_INSN_DELETED
;
8261 if (merge_bb
&& succ_bb
)
8262 merge_blocks (merge_bb
, succ_bb
);
8264 else if (merge_bb
&& succ_bb
)
8266 set_insn_deleted (insn
);
8267 merge_blocks (merge_bb
, succ_bb
);
8271 PUT_CODE (insn
, NOTE
);
8272 NOTE_KIND (insn
) = NOTE_INSN_DELETED
;
8278 && statep
->target_label
== CODE_LABEL_NUMBER (insn
))
8280 arc_ccfsm_post_advance (insn
, statep
);
8281 basic_block succ_bb
= BLOCK_FOR_INSN (insn
);
8282 if (merge_bb
&& succ_bb
)
8283 merge_blocks (merge_bb
, succ_bb
);
8284 else if (--LABEL_NUSES (insn
) == 0)
8286 const char *name
= LABEL_NAME (insn
);
8287 PUT_CODE (insn
, NOTE
);
8288 NOTE_KIND (insn
) = NOTE_INSN_DELETED_LABEL
;
8289 NOTE_DELETED_LABEL_NAME (insn
) = name
;
8296 if (!NONDEBUG_INSN_P (insn
))
8299 /* Conditionalized insn. */
8301 rtx prev
, pprev
, *patp
, pat
, cond
;
8302 bool annulled
; annulled
= false;
8304 /* If this is a delay slot insn in a non-annulled branch,
8305 don't conditionalize it. N.B., this should be fine for
8306 conditional return too. However, don't do this for
8307 unconditional branches, as these would be encountered when
8308 processing an 'else' part. */
8309 prev
= PREV_INSN (insn
);
8310 pprev
= PREV_INSN (prev
);
8311 if (pprev
&& NEXT_INSN (NEXT_INSN (pprev
)) == NEXT_INSN (insn
)
8312 && JUMP_P (prev
) && get_attr_cond (prev
) == COND_USE
)
8314 if (!INSN_ANNULLED_BRANCH_P (prev
))
8319 patp
= &PATTERN (insn
);
8321 cond
= arc_get_ccfsm_cond (statep
, INSN_FROM_TARGET_P (insn
));
8322 if (NONJUMP_INSN_P (insn
) || CALL_P (insn
))
8324 /* ??? don't conditionalize if all side effects are dead
8325 in the not-execute case. */
8327 pat
= conditionalize_nonjump (pat
, cond
, insn
, annulled
);
8329 else if (simplejump_p (insn
))
8331 patp
= &SET_SRC (pat
);
8332 pat
= gen_rtx_IF_THEN_ELSE (VOIDmode
, cond
, *patp
, pc_rtx
);
8334 else if (JUMP_P (insn
) && ANY_RETURN_P (PATTERN (insn
)))
8336 pat
= gen_rtx_IF_THEN_ELSE (VOIDmode
, cond
, pat
, pc_rtx
);
8337 pat
= gen_rtx_SET (VOIDmode
, pc_rtx
, pat
);
8341 validate_change (insn
, patp
, pat
, 1);
8342 if (!apply_change_group ())
8346 rtx next
= next_nonnote_insn (insn
);
8347 if (GET_CODE (next
) == BARRIER
)
8349 if (statep
->state
== 3)
8356 arc_ccfsm_post_advance (insn
, statep
);
8361 /* Find annulled delay insns and convert them to use the appropriate predicate.
8362 This allows branch shortening to size up these insns properly. */
8365 arc_predicate_delay_insns (void)
8367 for (rtx insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
8369 rtx pat
, jump
, dlay
, src
, cond
, *patp
;
8372 if (!NONJUMP_INSN_P (insn
)
8373 || GET_CODE (pat
= PATTERN (insn
)) != SEQUENCE
)
8375 jump
= XVECEXP (pat
, 0, 0);
8376 dlay
= XVECEXP (pat
, 0, 1);
8377 if (!JUMP_P (jump
) || !INSN_ANNULLED_BRANCH_P (jump
))
8379 /* If the branch insn does the annulling, leave the delay insn alone. */
8380 if (!TARGET_AT_DBR_CONDEXEC
&& !INSN_FROM_TARGET_P (dlay
))
8382 /* ??? Could also leave DLAY un-conditionalized if its target is dead
8383 on the other path. */
8384 gcc_assert (GET_CODE (PATTERN (jump
)) == SET
);
8385 gcc_assert (SET_DEST (PATTERN (jump
)) == pc_rtx
);
8386 src
= SET_SRC (PATTERN (jump
));
8387 gcc_assert (GET_CODE (src
) == IF_THEN_ELSE
);
8388 cond
= XEXP (src
, 0);
8389 if (XEXP (src
, 2) == pc_rtx
)
8391 else if (XEXP (src
, 1) == pc_rtx
)
8395 if (!INSN_FROM_TARGET_P (dlay
) != reverse
)
8397 enum machine_mode ccm
= GET_MODE (XEXP (cond
, 0));
8398 enum rtx_code code
= reverse_condition (GET_CODE (cond
));
8399 if (code
== UNKNOWN
|| ccm
== CC_FP_GTmode
|| ccm
== CC_FP_GEmode
)
8400 code
= reverse_condition_maybe_unordered (GET_CODE (cond
));
8402 cond
= gen_rtx_fmt_ee (code
, GET_MODE (cond
),
8403 copy_rtx (XEXP (cond
, 0)),
8404 copy_rtx (XEXP (cond
, 1)));
8407 cond
= copy_rtx (cond
);
8408 patp
= &PATTERN (dlay
);
8410 pat
= conditionalize_nonjump (pat
, cond
, dlay
, true);
8411 validate_change (dlay
, patp
, pat
, 1);
8412 if (!apply_change_group ())
8418 /* For ARC600: If a write to a core reg >=32 appears in a delay slot
8419 (other than of a forward brcc), it creates a hazard when there is a read
8420 of the same register at the branch target. We can't know what is at the
8421 branch target of calls, and for branches, we don't really know before the
8422 end of delay slot scheduling, either. Not only can individual instruction
8423 be hoisted out into a delay slot, a basic block can also be emptied this
8424 way, and branch and/or fall through targets be redirected. Hence we don't
8425 want such writes in a delay slot. */
8426 /* Called by arc_write_ext_corereg via for_each_rtx. */
8429 write_ext_corereg_1 (rtx
*xp
, void *data ATTRIBUTE_UNUSED
)
8434 switch (GET_CODE (x
))
8436 case SET
: case POST_INC
: case POST_DEC
: case PRE_INC
: case PRE_DEC
:
8439 /* This is also fine for PRE/POST_MODIFY, because they contain a SET. */
8443 if (REG_P (dest
) && REGNO (dest
) >= 32 && REGNO (dest
) < 61)
8448 /* Return nonzreo iff INSN writes to an extension core register. */
8451 arc_write_ext_corereg (rtx insn
)
8453 return for_each_rtx (&PATTERN (insn
), write_ext_corereg_1
, 0);
8456 /* This is like the hook, but returns NULL when it can't / won't generate
8457 a legitimate address. */
8460 arc_legitimize_address_0 (rtx x
, rtx oldx ATTRIBUTE_UNUSED
,
8461 enum machine_mode mode
)
8465 if (flag_pic
&& SYMBOLIC_CONST (x
))
8466 (x
) = arc_legitimize_pic_address (x
, 0);
8468 if (GET_CODE (addr
) == CONST
)
8469 addr
= XEXP (addr
, 0);
8470 if (GET_CODE (addr
) == PLUS
8471 && CONST_INT_P (XEXP (addr
, 1))
8472 && ((GET_CODE (XEXP (addr
, 0)) == SYMBOL_REF
8473 && !SYMBOL_REF_FUNCTION_P (XEXP (addr
, 0)))
8474 || (REG_P (XEXP (addr
, 0))
8475 && (INTVAL (XEXP (addr
, 1)) & 252))))
8477 HOST_WIDE_INT offs
, upper
;
8478 int size
= GET_MODE_SIZE (mode
);
8480 offs
= INTVAL (XEXP (addr
, 1));
8481 upper
= (offs
+ 256 * size
) & ~511 * size
;
8482 inner
= plus_constant (Pmode
, XEXP (addr
, 0), upper
);
8483 #if 0 /* ??? this produces worse code for EEMBC idctrn01 */
8484 if (GET_CODE (x
) == CONST
)
8485 inner
= gen_rtx_CONST (Pmode
, inner
);
8487 addr
= plus_constant (Pmode
, force_reg (Pmode
, inner
), offs
- upper
);
8490 else if (GET_CODE (addr
) == SYMBOL_REF
&& !SYMBOL_REF_FUNCTION_P (addr
))
8491 x
= force_reg (Pmode
, x
);
8492 if (memory_address_p ((enum machine_mode
) mode
, x
))
8498 arc_legitimize_address (rtx orig_x
, rtx oldx
, enum machine_mode mode
)
8500 rtx new_x
= arc_legitimize_address_0 (orig_x
, oldx
, mode
);
8508 arc_delegitimize_address_0 (rtx x
)
8512 if (GET_CODE (x
) == CONST
&& GET_CODE (u
= XEXP (x
, 0)) == UNSPEC
)
8514 if (XINT (u
, 1) == ARC_UNSPEC_GOT
)
8515 return XVECEXP (u
, 0, 0);
8517 else if (GET_CODE (x
) == PLUS
8518 && ((REG_P (gp
= XEXP (x
, 0))
8519 && REGNO (gp
) == PIC_OFFSET_TABLE_REGNUM
)
8520 || (GET_CODE (gp
) == CONST
8521 && GET_CODE (u
= XEXP (gp
, 0)) == UNSPEC
8522 && XINT (u
, 1) == ARC_UNSPEC_GOT
8523 && GET_CODE (XVECEXP (u
, 0, 0)) == SYMBOL_REF
8524 && !strcmp (XSTR (XVECEXP (u
, 0, 0), 0), "_DYNAMIC")))
8525 && GET_CODE (XEXP (x
, 1)) == CONST
8526 && GET_CODE (u
= XEXP (XEXP (x
, 1), 0)) == UNSPEC
8527 && XINT (u
, 1) == ARC_UNSPEC_GOTOFF
)
8528 return XVECEXP (u
, 0, 0);
8529 else if (GET_CODE (x
) == PLUS
&& GET_CODE (XEXP (x
, 0)) == PLUS
8530 && ((REG_P (gp
= XEXP (XEXP (x
, 0), 1))
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 gen_rtx_PLUS (GET_MODE (x
), XEXP (XEXP (x
, 0), 0),
8542 else if (GET_CODE (x
) == PLUS
8543 && (u
= arc_delegitimize_address_0 (XEXP (x
, 1))))
8544 return gen_rtx_PLUS (GET_MODE (x
), XEXP (x
, 0), u
);
8549 arc_delegitimize_address (rtx x
)
8551 rtx orig_x
= x
= delegitimize_mem_from_attrs (x
);
8552 if (GET_CODE (x
) == MEM
)
8554 x
= arc_delegitimize_address_0 (x
);
8558 x
= replace_equiv_address_nv (orig_x
, x
);
8564 /* Return a REG rtx for acc1. N.B. the gcc-internal representation may
8565 differ from the hardware register number in order to allow the generic
8566 code to correctly split the concatenation of acc1 and acc2. */
8571 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 56: 57);
8574 /* Return a REG rtx for acc2. N.B. the gcc-internal representation may
8575 differ from the hardware register number in order to allow the generic
8576 code to correctly split the concatenation of acc1 and acc2. */
8581 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 57: 56);
8584 /* Return a REG rtx for mlo. N.B. the gcc-internal representation may
8585 differ from the hardware register number in order to allow the generic
8586 code to correctly split the concatenation of mhi and mlo. */
8591 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 59: 58);
8594 /* Return a REG rtx for mhi. N.B. the gcc-internal representation may
8595 differ from the hardware register number in order to allow the generic
8596 code to correctly split the concatenation of mhi and mlo. */
8601 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 58: 59);
8604 /* FIXME: a parameter should be added, and code added to final.c,
8605 to reproduce this functionality in shorten_branches. */
8607 /* Return nonzero iff BRANCH should be unaligned if possible by upsizing
8608 a previous instruction. */
8610 arc_unalign_branch_p (rtx branch
)
8614 if (!TARGET_UNALIGN_BRANCH
)
8616 /* Do not do this if we have a filled delay slot. */
8617 if (get_attr_delay_slot_filled (branch
) == DELAY_SLOT_FILLED_YES
8618 && !INSN_DELETED_P (NEXT_INSN (branch
)))
8620 note
= find_reg_note (branch
, REG_BR_PROB
, 0);
8622 || (arc_unalign_prob_threshold
&& !br_prob_note_reliable_p (note
))
8623 || INTVAL (XEXP (note
, 0)) < arc_unalign_prob_threshold
);
8627 /* When estimating sizes during arc_reorg, when optimizing for speed, there
8628 are three reasons why we need to consider branches to be length 6:
8629 - annull-false delay slot insns are implemented using conditional execution,
8630 thus preventing short insn formation where used.
8631 - for ARC600: annul-true delay slot insns are implemented where possible
8632 using conditional execution, preventing short insn formation where used.
8633 - for ARC700: likely or somewhat likely taken branches are made long and
8634 unaligned if possible to avoid branch penalty. */
8637 arc_branch_size_unknown_p (void)
8639 return !optimize_size
&& arc_reorg_in_progress
;
8642 /* We are about to output a return insn. Add padding if necessary to avoid
8643 a mispredict. A return could happen immediately after the function
8644 start, but after a call we know that there will be at least a blink
8648 arc_pad_return (void)
8650 rtx insn
= current_output_insn
;
8651 rtx prev
= prev_active_insn (insn
);
8656 fputs ("\tnop_s\n", asm_out_file
);
8657 cfun
->machine
->unalign
^= 2;
8660 /* If PREV is a sequence, we know it must be a branch / jump or a tailcall,
8661 because after a call, we'd have to restore blink first. */
8662 else if (GET_CODE (PATTERN (prev
)) == SEQUENCE
)
8666 want_long
= (get_attr_length (prev
) == 2);
8667 prev
= prev_active_insn (prev
);
8670 || ((NONJUMP_INSN_P (prev
) && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
8671 ? CALL_ATTR (XVECEXP (PATTERN (prev
), 0, 0), NON_SIBCALL
)
8672 : CALL_ATTR (prev
, NON_SIBCALL
)))
8675 cfun
->machine
->size_reason
8676 = "call/return and return/return must be 6 bytes apart to avoid mispredict";
8677 else if (TARGET_UNALIGN_BRANCH
&& cfun
->machine
->unalign
)
8679 cfun
->machine
->size_reason
8680 = "Long unaligned jump avoids non-delay slot penalty";
8683 /* Disgorge delay insn, if there is any, and it may be moved. */
8685 /* ??? Annulled would be OK if we can and do conditionalize
8686 the delay slot insn accordingly. */
8687 && !INSN_ANNULLED_BRANCH_P (insn
)
8688 && (get_attr_cond (insn
) != COND_USE
8689 || !reg_set_p (gen_rtx_REG (CCmode
, CC_REG
),
8690 XVECEXP (final_sequence
, 0, 1))))
8692 prev
= XVECEXP (final_sequence
, 0, 1);
8693 gcc_assert (!prev_real_insn (insn
)
8694 || !arc_hazard (prev_real_insn (insn
), prev
));
8695 cfun
->machine
->force_short_suffix
= !want_long
;
8696 rtx save_pred
= current_insn_predicate
;
8697 final_scan_insn (prev
, asm_out_file
, optimize
, 1, NULL
);
8698 cfun
->machine
->force_short_suffix
= -1;
8699 INSN_DELETED_P (prev
) = 1;
8700 current_output_insn
= insn
;
8701 current_insn_predicate
= save_pred
;
8704 fputs ("\tnop\n", asm_out_file
);
8707 fputs ("\tnop_s\n", asm_out_file
);
8708 cfun
->machine
->unalign
^= 2;
8714 /* The usual; we set up our machine_function data. */
8716 static struct machine_function
*
8717 arc_init_machine_status (void)
8719 struct machine_function
*machine
;
8720 machine
= ggc_alloc_cleared_machine_function ();
8721 machine
->fn_type
= ARC_FUNCTION_UNKNOWN
;
8722 machine
->force_short_suffix
= -1;
8727 /* Implements INIT_EXPANDERS. We just set up to call the above
8731 arc_init_expanders (void)
8733 init_machine_status
= arc_init_machine_status
;
8736 /* Check if OP is a proper parallel of a millicode call pattern. OFFSET
8737 indicates a number of elements to ignore - that allows to have a
8738 sibcall pattern that starts with (return). LOAD_P is zero for store
8739 multiple (for prologues), and one for load multiples (for epilogues),
8740 and two for load multiples where no final clobber of blink is required.
8741 We also skip the first load / store element since this is supposed to
8742 be checked in the instruction pattern. */
8745 arc_check_millicode (rtx op
, int offset
, int load_p
)
8747 int len
= XVECLEN (op
, 0) - offset
;
8752 if (len
< 2 || len
> 13)
8758 rtx elt
= XVECEXP (op
, 0, --len
);
8760 if (GET_CODE (elt
) != CLOBBER
8761 || !REG_P (XEXP (elt
, 0))
8762 || REGNO (XEXP (elt
, 0)) != RETURN_ADDR_REGNUM
8763 || len
< 3 || len
> 13)
8766 for (i
= 1; i
< len
; i
++)
8768 rtx elt
= XVECEXP (op
, 0, i
+ offset
);
8771 if (GET_CODE (elt
) != SET
)
8773 mem
= XEXP (elt
, load_p
);
8774 reg
= XEXP (elt
, 1-load_p
);
8775 if (!REG_P (reg
) || REGNO (reg
) != 13U+i
|| !MEM_P (mem
))
8777 addr
= XEXP (mem
, 0);
8778 if (GET_CODE (addr
) != PLUS
8779 || !rtx_equal_p (stack_pointer_rtx
, XEXP (addr
, 0))
8780 || !CONST_INT_P (XEXP (addr
, 1)) || INTVAL (XEXP (addr
, 1)) != i
*4)
8786 /* Accessor functions for cfun->machine->unalign. */
8789 arc_get_unalign (void)
8791 return cfun
->machine
->unalign
;
8795 arc_clear_unalign (void)
8798 cfun
->machine
->unalign
= 0;
8802 arc_toggle_unalign (void)
8804 cfun
->machine
->unalign
^= 2;
8807 /* Operands 0..2 are the operands of a addsi which uses a 12 bit
8808 constant in operand 2, but which would require a LIMM because of
8810 operands 3 and 4 are new SET_SRCs for operands 0. */
8813 split_addsi (rtx
*operands
)
8815 int val
= INTVAL (operands
[2]);
8817 /* Try for two short insns first. Lengths being equal, we prefer
8818 expansions with shorter register lifetimes. */
8819 if (val
> 127 && val
<= 255
8820 && satisfies_constraint_Rcq (operands
[0]))
8822 operands
[3] = operands
[2];
8823 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[1]);
8827 operands
[3] = operands
[1];
8828 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[2]);
8832 /* Operands 0..2 are the operands of a subsi which uses a 12 bit
8833 constant in operand 1, but which would require a LIMM because of
8835 operands 3 and 4 are new SET_SRCs for operands 0. */
8838 split_subsi (rtx
*operands
)
8840 int val
= INTVAL (operands
[1]);
8842 /* Try for two short insns first. Lengths being equal, we prefer
8843 expansions with shorter register lifetimes. */
8844 if (satisfies_constraint_Rcq (operands
[0])
8845 && satisfies_constraint_Rcq (operands
[2]))
8847 if (val
>= -31 && val
<= 127)
8849 operands
[3] = gen_rtx_NEG (SImode
, operands
[2]);
8850 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[1]);
8853 else if (val
>= 0 && val
< 255)
8855 operands
[3] = operands
[1];
8856 operands
[4] = gen_rtx_MINUS (SImode
, operands
[0], operands
[2]);
8860 /* If the destination is not an ARCompact16 register, we might
8861 still have a chance to make a short insn if the source is;
8862 we need to start with a reg-reg move for this. */
8863 operands
[3] = operands
[2];
8864 operands
[4] = gen_rtx_MINUS (SImode
, operands
[1], operands
[0]);
8867 /* Handle DOUBLE_REGS uses.
8868 Operand 0: destination register
8869 Operand 1: source register */
8872 arc_process_double_reg_moves (rtx
*operands
)
8874 rtx dest
= operands
[0];
8875 rtx src
= operands
[1];
8878 enum usesDxState
{ none
, srcDx
, destDx
, maxDx
};
8879 enum usesDxState state
= none
;
8881 if (refers_to_regno_p (40, 44, src
, 0))
8883 if (refers_to_regno_p (40, 44, dest
, 0))
8885 /* Via arc_register_move_cost, we should never see D,D moves. */
8886 gcc_assert (state
== none
);
8897 /* Without the LR insn, we need to split this into a
8898 sequence of insns which will use the DEXCLx and DADDHxy
8899 insns to be able to read the Dx register in question. */
8900 if (TARGET_DPFP_DISABLE_LRSR
)
8902 /* gen *movdf_insn_nolrsr */
8903 rtx set
= gen_rtx_SET (VOIDmode
, dest
, src
);
8904 rtx use1
= gen_rtx_USE (VOIDmode
, const1_rtx
);
8905 emit_insn (gen_rtx_PARALLEL (VOIDmode
, gen_rtvec (2, set
, use1
)));
8909 /* When we have 'mov D, r' or 'mov D, D' then get the target
8910 register pair for use with LR insn. */
8911 rtx destHigh
= simplify_gen_subreg(SImode
, dest
, DFmode
, 4);
8912 rtx destLow
= simplify_gen_subreg(SImode
, dest
, DFmode
, 0);
8914 /* Produce the two LR insns to get the high and low parts. */
8915 emit_insn (gen_rtx_SET (VOIDmode
,
8917 gen_rtx_UNSPEC_VOLATILE (Pmode
, gen_rtvec (1, src
),
8919 emit_insn (gen_rtx_SET (VOIDmode
,
8921 gen_rtx_UNSPEC_VOLATILE (Pmode
, gen_rtvec (1, src
),
8925 else if (state
== destDx
)
8927 /* When we have 'mov r, D' or 'mov D, D' and we have access to the
8928 LR insn get the target register pair. */
8929 rtx srcHigh
= simplify_gen_subreg(SImode
, src
, DFmode
, 4);
8930 rtx srcLow
= simplify_gen_subreg(SImode
, src
, DFmode
, 0);
8932 emit_insn (gen_rtx_UNSPEC_VOLATILE (Pmode
,
8933 gen_rtvec (3, dest
, srcHigh
, srcLow
),
8934 VUNSPEC_DEXCL_NORES
));
8945 /* operands 0..1 are the operands of a 64 bit move instruction.
8946 split it into two moves with operands 2/3 and 4/5. */
8949 arc_split_move (rtx
*operands
)
8951 enum machine_mode mode
= GET_MODE (operands
[0]);
8959 val
= arc_process_double_reg_moves (operands
);
8964 for (i
= 0; i
< 2; i
++)
8966 if (MEM_P (operands
[i
]) && auto_inc_p (XEXP (operands
[i
], 0)))
8968 rtx addr
= XEXP (operands
[i
], 0);
8972 gcc_assert (!reg_overlap_mentioned_p (operands
[0], addr
));
8973 switch (GET_CODE (addr
))
8975 case PRE_DEC
: o
= GEN_INT (-8); goto pre_modify
;
8976 case PRE_INC
: o
= GEN_INT (8); goto pre_modify
;
8977 case PRE_MODIFY
: o
= XEXP (XEXP (addr
, 1), 1);
8981 case POST_DEC
: o
= GEN_INT (-8); goto post_modify
;
8982 case POST_INC
: o
= GEN_INT (8); goto post_modify
;
8983 case POST_MODIFY
: o
= XEXP (XEXP (addr
, 1), 1);
8992 xop
[0+i
] = adjust_automodify_address_nv
8993 (operands
[i
], SImode
,
8994 gen_rtx_fmt_ee (code
, Pmode
, r
,
8995 gen_rtx_PLUS (Pmode
, r
, o
)),
8997 xop
[2+i
] = adjust_automodify_address_nv
8998 (operands
[i
], SImode
, plus_constant (Pmode
, r
, 4), 4);
9002 xop
[0+i
] = operand_subword (operands
[i
], 0, 0, mode
);
9003 xop
[2+i
] = operand_subword (operands
[i
], 1, 0, mode
);
9006 if (reg_overlap_mentioned_p (xop
[0], xop
[3]))
9009 gcc_assert (!reg_overlap_mentioned_p (xop
[2], xop
[1]));
9011 operands
[2+swap
] = xop
[0];
9012 operands
[3+swap
] = xop
[1];
9013 operands
[4-swap
] = xop
[2];
9014 operands
[5-swap
] = xop
[3];
9017 emit_insn (gen_rtx_SET (VOIDmode
, operands
[2], operands
[3]));
9018 emit_insn (gen_rtx_SET (VOIDmode
, operands
[4], operands
[5]));
9025 /* Select between the instruction output templates s_tmpl (for short INSNs)
9026 and l_tmpl (for long INSNs). */
9029 arc_short_long (rtx insn
, const char *s_tmpl
, const char *l_tmpl
)
9031 int is_short
= arc_verify_short (insn
, cfun
->machine
->unalign
, -1);
9033 extract_constrain_insn_cached (insn
);
9034 return is_short
? s_tmpl
: l_tmpl
;
9037 /* Searches X for any reference to REGNO, returning the rtx of the
9038 reference found if any. Otherwise, returns NULL_RTX. */
9041 arc_regno_use_in (unsigned int regno
, rtx x
)
9047 if (REG_P (x
) && refers_to_regno_p (regno
, regno
+1, x
, (rtx
*) 0))
9050 fmt
= GET_RTX_FORMAT (GET_CODE (x
));
9051 for (i
= GET_RTX_LENGTH (GET_CODE (x
)) - 1; i
>= 0; i
--)
9055 if ((tem
= regno_use_in (regno
, XEXP (x
, i
))))
9058 else if (fmt
[i
] == 'E')
9059 for (j
= XVECLEN (x
, i
) - 1; j
>= 0; j
--)
9060 if ((tem
= regno_use_in (regno
, XVECEXP (x
, i
, j
))))
9067 /* Return the integer value of the "type" attribute for INSN, or -1 if
9068 INSN can't have attributes. */
9071 arc_attr_type (rtx insn
)
9073 if (NONJUMP_INSN_P (insn
)
9074 ? (GET_CODE (PATTERN (insn
)) == USE
9075 || GET_CODE (PATTERN (insn
)) == CLOBBER
)
9077 ? (GET_CODE (PATTERN (insn
)) == ADDR_VEC
9078 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
9081 return get_attr_type (insn
);
9084 /* Return true if insn sets the condition codes. */
9087 arc_sets_cc_p (rtx insn
)
9089 if (NONJUMP_INSN_P (insn
) && GET_CODE (PATTERN (insn
)) == SEQUENCE
)
9090 insn
= XVECEXP (PATTERN (insn
), 0, XVECLEN (PATTERN (insn
), 0) - 1);
9091 return arc_attr_type (insn
) == TYPE_COMPARE
;
9094 /* Return true if INSN is an instruction with a delay slot we may want
9098 arc_need_delay (rtx insn
)
9102 if (!flag_delayed_branch
)
9104 /* The return at the end of a function needs a delay slot. */
9105 if (NONJUMP_INSN_P (insn
) && GET_CODE (PATTERN (insn
)) == USE
9106 && (!(next
= next_active_insn (insn
))
9107 || ((!NONJUMP_INSN_P (next
) || GET_CODE (PATTERN (next
)) != SEQUENCE
)
9108 && arc_attr_type (next
) == TYPE_RETURN
))
9109 && (!TARGET_PAD_RETURN
9110 || (prev_active_insn (insn
)
9111 && prev_active_insn (prev_active_insn (insn
))
9112 && prev_active_insn (prev_active_insn (prev_active_insn (insn
))))))
9114 if (NONJUMP_INSN_P (insn
)
9115 ? (GET_CODE (PATTERN (insn
)) == USE
9116 || GET_CODE (PATTERN (insn
)) == CLOBBER
9117 || GET_CODE (PATTERN (insn
)) == SEQUENCE
)
9119 ? (GET_CODE (PATTERN (insn
)) == ADDR_VEC
9120 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
9123 return num_delay_slots (insn
) != 0;
9126 /* Return true if the scheduling pass(es) has/have already run,
9127 i.e. where possible, we should try to mitigate high latencies
9128 by different instruction selection. */
9131 arc_scheduling_not_expected (void)
9133 return cfun
->machine
->arc_reorg_started
;
9136 /* Oddly enough, sometimes we get a zero overhead loop that branch
9137 shortening doesn't think is a loop - observed with compile/pr24883.c
9138 -O3 -fomit-frame-pointer -funroll-loops. Make sure to include the
9139 alignment visible for branch shortening (we actually align the loop
9140 insn before it, but that is equivalent since the loop insn is 4 byte
9144 arc_label_align (rtx label
)
9146 int loop_align
= LOOP_ALIGN (LABEL
);
9148 if (loop_align
> align_labels_log
)
9150 rtx prev
= prev_nonnote_insn (label
);
9152 if (prev
&& NONJUMP_INSN_P (prev
)
9153 && GET_CODE (PATTERN (prev
)) == PARALLEL
9154 && recog_memoized (prev
) == CODE_FOR_doloop_begin_i
)
9157 /* Code has a minimum p2 alignment of 1, which we must restore after an
9159 if (align_labels_log
< 1)
9161 rtx next
= next_nonnote_nondebug_insn (label
);
9162 if (INSN_P (next
) && recog_memoized (next
) >= 0)
9165 return align_labels_log
;
9168 /* Return true if LABEL is in executable code. */
9171 arc_text_label (rtx label
)
9175 /* ??? We use deleted labels like they were still there, see
9176 gcc.c-torture/compile/20000326-2.c . */
9177 gcc_assert (GET_CODE (label
) == CODE_LABEL
9178 || (GET_CODE (label
) == NOTE
9179 && NOTE_KIND (label
) == NOTE_INSN_DELETED_LABEL
));
9180 next
= next_nonnote_insn (label
);
9182 return (!JUMP_TABLE_DATA_P (next
)
9183 || GET_CODE (PATTERN (next
)) != ADDR_VEC
);
9184 else if (!PREV_INSN (label
))
9185 /* ??? sometimes text labels get inserted very late, see
9186 gcc.dg/torture/stackalign/comp-goto-1.c */
9191 /* Return the size of the pretend args for DECL. */
9194 arc_decl_pretend_args (tree decl
)
9196 /* struct function is in DECL_STRUCT_FUNCTION (decl), but no
9197 pretend_args there... See PR38391. */
9198 gcc_assert (decl
== current_function_decl
);
9199 return crtl
->args
.pretend_args_size
;
9202 /* Without this, gcc.dg/tree-prof/bb-reorg.c fails to assemble
9203 when compiling with -O2 -freorder-blocks-and-partition -fprofile-use
9204 -D_PROFILE_USE; delay branch scheduling then follows a REG_CROSSING_JUMP
9205 to redirect two breqs. */
9208 arc_can_follow_jump (const_rtx follower
, const_rtx followee
)
9210 /* ??? get_attr_type is declared to take an rtx. */
9211 union { const_rtx c
; rtx r
; } u
;
9214 if (find_reg_note (followee
, REG_CROSSING_JUMP
, NULL_RTX
))
9215 switch (get_attr_type (u
.r
))
9218 case TYPE_BRCC_NO_DELAY_SLOT
:
9226 /* Implement EPILOGUE__USES.
9227 Return true if REGNO should be added to the deemed uses of the epilogue.
9229 We use the return address
9230 arc_return_address_regs[arc_compute_function_type (cfun)] .
9231 But also, we have to make sure all the register restore instructions
9232 are known to be live in interrupt functions. */
9235 arc_epilogue_uses (int regno
)
9237 if (reload_completed
)
9239 if (ARC_INTERRUPT_P (cfun
->machine
->fn_type
))
9241 if (!fixed_regs
[regno
])
9243 return regno
== arc_return_address_regs
[cfun
->machine
->fn_type
];
9246 return regno
== RETURN_ADDR_REGNUM
;
9249 return regno
== arc_return_address_regs
[arc_compute_function_type (cfun
)];
9252 #ifndef TARGET_NO_LRA
9253 #define TARGET_NO_LRA !TARGET_LRA
9259 return !TARGET_NO_LRA
;
9262 /* ??? Should we define TARGET_REGISTER_PRIORITY? We might perfer to use
9263 Rcq registers, because some insn are shorter with them. OTOH we already
9264 have separate alternatives for this purpose, and other insns don't
9265 mind, so maybe we should rather prefer the other registers?
9266 We need more data, and we can only get that if we allow people to
9269 arc_register_priority (int r
)
9271 switch (arc_lra_priority_tag
)
9273 case ARC_LRA_PRIORITY_NONE
:
9275 case ARC_LRA_PRIORITY_NONCOMPACT
:
9276 return ((((r
& 7) ^ 4) - 4) & 15) != r
;
9277 case ARC_LRA_PRIORITY_COMPACT
:
9278 return ((((r
& 7) ^ 4) - 4) & 15) == r
;
9285 arc_spill_class (reg_class_t
/* orig_class */, enum machine_mode
)
9287 return GENERAL_REGS
;
9291 arc_legitimize_reload_address (rtx
*p
, enum machine_mode mode
, int opnum
,
9295 enum reload_type type
= (enum reload_type
) itype
;
9297 if (GET_CODE (x
) == PLUS
9298 && CONST_INT_P (XEXP (x
, 1))
9299 && (RTX_OK_FOR_BASE_P (XEXP (x
, 0), true)
9300 || (REG_P (XEXP (x
, 0))
9301 && reg_equiv_constant (REGNO (XEXP (x
, 0))))))
9303 int scale
= GET_MODE_SIZE (mode
);
9305 rtx index_rtx
= XEXP (x
, 1);
9306 HOST_WIDE_INT offset
= INTVAL (index_rtx
), offset_base
;
9311 if ((scale
-1) & offset
)
9314 offset_base
= (offset
+ (256 << shift
)) & (-512 << shift
);
9315 /* Sometimes the normal form does not suit DImode. We
9316 could avoid that by using smaller ranges, but that
9317 would give less optimized code when SImode is
9319 if (GET_MODE_SIZE (mode
) + offset
- offset_base
<= (256 << shift
))
9324 regno
= REGNO (reg
);
9325 sum2
= sum
= plus_constant (Pmode
, reg
, offset_base
);
9327 if (reg_equiv_constant (regno
))
9329 sum2
= plus_constant (Pmode
, reg_equiv_constant (regno
),
9331 if (GET_CODE (sum2
) == PLUS
)
9332 sum2
= gen_rtx_CONST (Pmode
, sum2
);
9334 *p
= gen_rtx_PLUS (Pmode
, sum
, GEN_INT (offset
- offset_base
));
9335 push_reload (sum2
, NULL_RTX
, &XEXP (*p
, 0), NULL
,
9336 BASE_REG_CLASS
, Pmode
, VOIDmode
, 0, 0, opnum
,
9341 /* We must re-recognize what we created before. */
9342 else if (GET_CODE (x
) == PLUS
9343 && GET_CODE (XEXP (x
, 0)) == PLUS
9344 && CONST_INT_P (XEXP (XEXP (x
, 0), 1))
9345 && REG_P (XEXP (XEXP (x
, 0), 0))
9346 && CONST_INT_P (XEXP (x
, 1)))
9348 /* Because this address is so complex, we know it must have
9349 been created by LEGITIMIZE_RELOAD_ADDRESS before; thus,
9350 it is already unshared, and needs no further unsharing. */
9351 push_reload (XEXP (x
, 0), NULL_RTX
, &XEXP (x
, 0), NULL
,
9352 BASE_REG_CLASS
, Pmode
, VOIDmode
, 0, 0, opnum
, type
);
9358 struct gcc_target targetm
= TARGET_INITIALIZER
;