1 /* Subroutines used for code generation on the Synopsys DesignWare ARC cpu.
2 Copyright (C) 1994-2014 Free Software Foundation, Inc.
4 Sources derived from work done by Sankhya Technologies (www.sankhya.com) on
5 behalf of Synopsys Inc.
7 Position Independent Code support added,Code cleaned up,
8 Comments and Support For ARC700 instructions added by
9 Saurabh Verma (saurabh.verma@codito.com)
10 Ramana Radhakrishnan(ramana.radhakrishnan@codito.com)
12 Fixing ABI inconsistencies, optimizations for ARC600 / ARC700 pipelines,
13 profiling support added by Joern Rennecke <joern.rennecke@embecosm.com>
15 This file is part of GCC.
17 GCC is free software; you can redistribute it and/or modify
18 it under the terms of the GNU General Public License as published by
19 the Free Software Foundation; either version 3, or (at your option)
22 GCC is distributed in the hope that it will be useful,
23 but WITHOUT ANY WARRANTY; without even the implied warranty of
24 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 GNU General Public License for more details.
27 You should have received a copy of the GNU General Public License
28 along with GCC; see the file COPYING3. If not see
29 <http://www.gnu.org/licenses/>. */
33 #include "coretypes.h"
37 #include "stor-layout.h"
38 #include "stringpool.h"
42 #include "hard-reg-set.h"
44 #include "insn-config.h"
45 #include "conditions.h"
46 #include "insn-flags.h"
58 #include "insn-attr.h"
63 #include "diagnostic.h"
64 #include "insn-codes.h"
65 #include "langhooks.h"
67 #include "tm-constrs.h"
68 #include "reload.h" /* For operands_match_p */
69 #include "dominance.h"
75 #include "cfgcleanup.h"
77 #include "basic-block.h"
79 #include "tree-pass.h"
81 #include "pass_manager.h"
86 /* Which cpu we're compiling for (A5, ARC600, ARC601, ARC700). */
87 static const char *arc_cpu_string
= "";
89 /* ??? Loads can handle any constant, stores can only handle small ones. */
90 /* OTOH, LIMMs cost extra, so their usefulness is limited. */
91 #define RTX_OK_FOR_OFFSET_P(MODE, X) \
92 (GET_CODE (X) == CONST_INT \
93 && SMALL_INT_RANGE (INTVAL (X), (GET_MODE_SIZE (MODE) - 1) & -4, \
94 (INTVAL (X) & (GET_MODE_SIZE (MODE) - 1) & 3 \
96 : -(-GET_MODE_SIZE (MODE) | -4) >> 1)))
98 #define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X, INDEX, STRICT) \
99 (GET_CODE (X) == PLUS \
100 && RTX_OK_FOR_BASE_P (XEXP (X, 0), (STRICT)) \
101 && ((INDEX && RTX_OK_FOR_INDEX_P (XEXP (X, 1), (STRICT)) \
102 && GET_MODE_SIZE ((MODE)) <= 4) \
103 || RTX_OK_FOR_OFFSET_P (MODE, XEXP (X, 1))))
105 #define LEGITIMATE_SCALED_ADDRESS_P(MODE, X, STRICT) \
106 (GET_CODE (X) == PLUS \
107 && GET_CODE (XEXP (X, 0)) == MULT \
108 && RTX_OK_FOR_INDEX_P (XEXP (XEXP (X, 0), 0), (STRICT)) \
109 && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \
110 && ((GET_MODE_SIZE (MODE) == 2 && INTVAL (XEXP (XEXP (X, 0), 1)) == 2) \
111 || (GET_MODE_SIZE (MODE) == 4 && INTVAL (XEXP (XEXP (X, 0), 1)) == 4)) \
112 && (RTX_OK_FOR_BASE_P (XEXP (X, 1), (STRICT)) \
113 || (flag_pic ? CONST_INT_P (XEXP (X, 1)) : CONSTANT_P (XEXP (X, 1)))))
115 #define LEGITIMATE_SMALL_DATA_ADDRESS_P(X) \
116 (GET_CODE (X) == PLUS \
117 && (REG_P (XEXP ((X), 0)) && REGNO (XEXP ((X), 0)) == SDATA_BASE_REGNUM) \
118 && ((GET_CODE (XEXP((X),1)) == SYMBOL_REF \
119 && SYMBOL_REF_SMALL_P (XEXP ((X), 1))) \
120 || (GET_CODE (XEXP ((X), 1)) == CONST \
121 && GET_CODE (XEXP (XEXP ((X), 1), 0)) == PLUS \
122 && GET_CODE (XEXP (XEXP (XEXP ((X), 1), 0), 0)) == SYMBOL_REF \
123 && SYMBOL_REF_SMALL_P (XEXP (XEXP (XEXP ((X), 1), 0), 0)) \
124 && GET_CODE (XEXP(XEXP (XEXP ((X), 1), 0), 1)) == CONST_INT)))
126 /* Array of valid operand punctuation characters. */
127 char arc_punct_chars
[256];
129 /* State used by arc_ccfsm_advance to implement conditional execution. */
130 struct GTY (()) arc_ccfsm
135 rtx_insn
*target_insn
;
139 #define arc_ccfsm_current cfun->machine->ccfsm_current
141 #define ARC_CCFSM_BRANCH_DELETED_P(STATE) \
142 ((STATE)->state == 1 || (STATE)->state == 2)
144 /* Indicate we're conditionalizing insns now. */
145 #define ARC_CCFSM_RECORD_BRANCH_DELETED(STATE) \
146 ((STATE)->state += 2)
148 #define ARC_CCFSM_COND_EXEC_P(STATE) \
149 ((STATE)->state == 3 || (STATE)->state == 4 || (STATE)->state == 5 \
150 || current_insn_predicate)
152 /* Check if INSN has a 16 bit opcode considering struct arc_ccfsm *STATE. */
153 #define CCFSM_ISCOMPACT(INSN,STATE) \
154 (ARC_CCFSM_COND_EXEC_P (STATE) \
155 ? (get_attr_iscompact (INSN) == ISCOMPACT_TRUE \
156 || get_attr_iscompact (INSN) == ISCOMPACT_TRUE_LIMM) \
157 : get_attr_iscompact (INSN) != ISCOMPACT_FALSE)
159 /* Likewise, but also consider that INSN might be in a delay slot of JUMP. */
160 #define CCFSM_DBR_ISCOMPACT(INSN,JUMP,STATE) \
161 ((ARC_CCFSM_COND_EXEC_P (STATE) \
163 && INSN_ANNULLED_BRANCH_P (JUMP) \
164 && (TARGET_AT_DBR_CONDEXEC || INSN_FROM_TARGET_P (INSN)))) \
165 ? (get_attr_iscompact (INSN) == ISCOMPACT_TRUE \
166 || get_attr_iscompact (INSN) == ISCOMPACT_TRUE_LIMM) \
167 : get_attr_iscompact (INSN) != ISCOMPACT_FALSE)
169 /* The maximum number of insns skipped which will be conditionalised if
171 /* When optimizing for speed:
172 Let p be the probability that the potentially skipped insns need to
173 be executed, pn the cost of a correctly predicted non-taken branch,
174 mt the cost of a mis/non-predicted taken branch,
175 mn mispredicted non-taken, pt correctly predicted taken ;
176 costs expressed in numbers of instructions like the ones considered
178 Unfortunately we don't have a measure of predictability - this
179 is linked to probability only in that in the no-eviction-scenario
180 there is a lower bound 1 - 2 * min (p, 1-p), and a somewhat larger
181 value that can be assumed *if* the distribution is perfectly random.
182 A predictability of 1 is perfectly plausible not matter what p is,
183 because the decision could be dependent on an invocation parameter
185 For large p, we want MAX_INSNS_SKIPPED == pn/(1-p) + mt - pn
186 For small p, we want MAX_INSNS_SKIPPED == pt
188 When optimizing for size:
189 We want to skip insn unless we could use 16 opcodes for the
190 non-conditionalized insn to balance the branch length or more.
191 Performance can be tie-breaker. */
192 /* If the potentially-skipped insns are likely to be executed, we'll
193 generally save one non-taken branch
195 this to be no less than the 1/p */
196 #define MAX_INSNS_SKIPPED 3
198 /* The values of unspec's first field. */
208 ARC_BUILTIN_NORM
= 3,
209 ARC_BUILTIN_NORMW
= 4,
210 ARC_BUILTIN_SWAP
= 5,
212 ARC_BUILTIN_DIVAW
= 7,
214 ARC_BUILTIN_MUL64
= 9,
215 ARC_BUILTIN_MULU64
= 10,
216 ARC_BUILTIN_RTIE
= 11,
217 ARC_BUILTIN_SYNC
= 12,
218 ARC_BUILTIN_CORE_READ
= 13,
219 ARC_BUILTIN_CORE_WRITE
= 14,
220 ARC_BUILTIN_FLAG
= 15,
223 ARC_BUILTIN_SLEEP
= 18,
224 ARC_BUILTIN_SWI
= 19,
225 ARC_BUILTIN_TRAP_S
= 20,
226 ARC_BUILTIN_UNIMP_S
= 21,
227 ARC_BUILTIN_ALIGNED
= 22,
229 /* Sentinel to mark start of simd builtins. */
230 ARC_SIMD_BUILTIN_BEGIN
= 1000,
232 ARC_SIMD_BUILTIN_VADDAW
= 1001,
233 ARC_SIMD_BUILTIN_VADDW
= 1002,
234 ARC_SIMD_BUILTIN_VAVB
= 1003,
235 ARC_SIMD_BUILTIN_VAVRB
= 1004,
236 ARC_SIMD_BUILTIN_VDIFAW
= 1005,
237 ARC_SIMD_BUILTIN_VDIFW
= 1006,
238 ARC_SIMD_BUILTIN_VMAXAW
= 1007,
239 ARC_SIMD_BUILTIN_VMAXW
= 1008,
240 ARC_SIMD_BUILTIN_VMINAW
= 1009,
241 ARC_SIMD_BUILTIN_VMINW
= 1010,
242 ARC_SIMD_BUILTIN_VMULAW
= 1011,
243 ARC_SIMD_BUILTIN_VMULFAW
= 1012,
244 ARC_SIMD_BUILTIN_VMULFW
= 1013,
245 ARC_SIMD_BUILTIN_VMULW
= 1014,
246 ARC_SIMD_BUILTIN_VSUBAW
= 1015,
247 ARC_SIMD_BUILTIN_VSUBW
= 1016,
248 ARC_SIMD_BUILTIN_VSUMMW
= 1017,
249 ARC_SIMD_BUILTIN_VAND
= 1018,
250 ARC_SIMD_BUILTIN_VANDAW
= 1019,
251 ARC_SIMD_BUILTIN_VBIC
= 1020,
252 ARC_SIMD_BUILTIN_VBICAW
= 1021,
253 ARC_SIMD_BUILTIN_VOR
= 1022,
254 ARC_SIMD_BUILTIN_VXOR
= 1023,
255 ARC_SIMD_BUILTIN_VXORAW
= 1024,
256 ARC_SIMD_BUILTIN_VEQW
= 1025,
257 ARC_SIMD_BUILTIN_VLEW
= 1026,
258 ARC_SIMD_BUILTIN_VLTW
= 1027,
259 ARC_SIMD_BUILTIN_VNEW
= 1028,
260 ARC_SIMD_BUILTIN_VMR1AW
= 1029,
261 ARC_SIMD_BUILTIN_VMR1W
= 1030,
262 ARC_SIMD_BUILTIN_VMR2AW
= 1031,
263 ARC_SIMD_BUILTIN_VMR2W
= 1032,
264 ARC_SIMD_BUILTIN_VMR3AW
= 1033,
265 ARC_SIMD_BUILTIN_VMR3W
= 1034,
266 ARC_SIMD_BUILTIN_VMR4AW
= 1035,
267 ARC_SIMD_BUILTIN_VMR4W
= 1036,
268 ARC_SIMD_BUILTIN_VMR5AW
= 1037,
269 ARC_SIMD_BUILTIN_VMR5W
= 1038,
270 ARC_SIMD_BUILTIN_VMR6AW
= 1039,
271 ARC_SIMD_BUILTIN_VMR6W
= 1040,
272 ARC_SIMD_BUILTIN_VMR7AW
= 1041,
273 ARC_SIMD_BUILTIN_VMR7W
= 1042,
274 ARC_SIMD_BUILTIN_VMRB
= 1043,
275 ARC_SIMD_BUILTIN_VH264F
= 1044,
276 ARC_SIMD_BUILTIN_VH264FT
= 1045,
277 ARC_SIMD_BUILTIN_VH264FW
= 1046,
278 ARC_SIMD_BUILTIN_VVC1F
= 1047,
279 ARC_SIMD_BUILTIN_VVC1FT
= 1048,
281 /* Va, Vb, rlimm instructions. */
282 ARC_SIMD_BUILTIN_VBADDW
= 1050,
283 ARC_SIMD_BUILTIN_VBMAXW
= 1051,
284 ARC_SIMD_BUILTIN_VBMINW
= 1052,
285 ARC_SIMD_BUILTIN_VBMULAW
= 1053,
286 ARC_SIMD_BUILTIN_VBMULFW
= 1054,
287 ARC_SIMD_BUILTIN_VBMULW
= 1055,
288 ARC_SIMD_BUILTIN_VBRSUBW
= 1056,
289 ARC_SIMD_BUILTIN_VBSUBW
= 1057,
291 /* Va, Vb, Ic instructions. */
292 ARC_SIMD_BUILTIN_VASRW
= 1060,
293 ARC_SIMD_BUILTIN_VSR8
= 1061,
294 ARC_SIMD_BUILTIN_VSR8AW
= 1062,
296 /* Va, Vb, u6 instructions. */
297 ARC_SIMD_BUILTIN_VASRRWi
= 1065,
298 ARC_SIMD_BUILTIN_VASRSRWi
= 1066,
299 ARC_SIMD_BUILTIN_VASRWi
= 1067,
300 ARC_SIMD_BUILTIN_VASRPWBi
= 1068,
301 ARC_SIMD_BUILTIN_VASRRPWBi
= 1069,
302 ARC_SIMD_BUILTIN_VSR8AWi
= 1070,
303 ARC_SIMD_BUILTIN_VSR8i
= 1071,
305 /* Va, Vb, u8 (simm) instructions. */
306 ARC_SIMD_BUILTIN_VMVAW
= 1075,
307 ARC_SIMD_BUILTIN_VMVW
= 1076,
308 ARC_SIMD_BUILTIN_VMVZW
= 1077,
309 ARC_SIMD_BUILTIN_VD6TAPF
= 1078,
311 /* Va, rlimm, u8 (simm) instructions. */
312 ARC_SIMD_BUILTIN_VMOVAW
= 1080,
313 ARC_SIMD_BUILTIN_VMOVW
= 1081,
314 ARC_SIMD_BUILTIN_VMOVZW
= 1082,
316 /* Va, Vb instructions. */
317 ARC_SIMD_BUILTIN_VABSAW
= 1085,
318 ARC_SIMD_BUILTIN_VABSW
= 1086,
319 ARC_SIMD_BUILTIN_VADDSUW
= 1087,
320 ARC_SIMD_BUILTIN_VSIGNW
= 1088,
321 ARC_SIMD_BUILTIN_VEXCH1
= 1089,
322 ARC_SIMD_BUILTIN_VEXCH2
= 1090,
323 ARC_SIMD_BUILTIN_VEXCH4
= 1091,
324 ARC_SIMD_BUILTIN_VUPBAW
= 1092,
325 ARC_SIMD_BUILTIN_VUPBW
= 1093,
326 ARC_SIMD_BUILTIN_VUPSBAW
= 1094,
327 ARC_SIMD_BUILTIN_VUPSBW
= 1095,
329 ARC_SIMD_BUILTIN_VDIRUN
= 1100,
330 ARC_SIMD_BUILTIN_VDORUN
= 1101,
331 ARC_SIMD_BUILTIN_VDIWR
= 1102,
332 ARC_SIMD_BUILTIN_VDOWR
= 1103,
334 ARC_SIMD_BUILTIN_VREC
= 1105,
335 ARC_SIMD_BUILTIN_VRUN
= 1106,
336 ARC_SIMD_BUILTIN_VRECRUN
= 1107,
337 ARC_SIMD_BUILTIN_VENDREC
= 1108,
339 ARC_SIMD_BUILTIN_VLD32WH
= 1110,
340 ARC_SIMD_BUILTIN_VLD32WL
= 1111,
341 ARC_SIMD_BUILTIN_VLD64
= 1112,
342 ARC_SIMD_BUILTIN_VLD32
= 1113,
343 ARC_SIMD_BUILTIN_VLD64W
= 1114,
344 ARC_SIMD_BUILTIN_VLD128
= 1115,
345 ARC_SIMD_BUILTIN_VST128
= 1116,
346 ARC_SIMD_BUILTIN_VST64
= 1117,
348 ARC_SIMD_BUILTIN_VST16_N
= 1120,
349 ARC_SIMD_BUILTIN_VST32_N
= 1121,
351 ARC_SIMD_BUILTIN_VINTI
= 1201,
356 /* A nop is needed between a 4 byte insn that sets the condition codes and
357 a branch that uses them (the same isn't true for an 8 byte insn that sets
358 the condition codes). Set by arc_ccfsm_advance. Used by
359 arc_print_operand. */
361 static int get_arc_condition_code (rtx
);
363 static tree
arc_handle_interrupt_attribute (tree
*, tree
, tree
, int, bool *);
365 /* Initialized arc_attribute_table to NULL since arc doesnot have any
366 machine specific supported attributes. */
367 const struct attribute_spec arc_attribute_table
[] =
369 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
370 affects_type_identity } */
371 { "interrupt", 1, 1, true, false, false, arc_handle_interrupt_attribute
, true },
372 /* Function calls made to this symbol must be done indirectly, because
373 it may lie outside of the 21/25 bit addressing range of a normal function
375 { "long_call", 0, 0, false, true, true, NULL
, false },
376 /* Whereas these functions are always known to reside within the 25 bit
377 addressing range of unconditionalized bl. */
378 { "medium_call", 0, 0, false, true, true, NULL
, false },
379 /* And these functions are always known to reside within the 21 bit
380 addressing range of blcc. */
381 { "short_call", 0, 0, false, true, true, NULL
, false },
382 { NULL
, 0, 0, false, false, false, NULL
, false }
384 static int arc_comp_type_attributes (const_tree
, const_tree
);
385 static void arc_file_start (void);
386 static void arc_internal_label (FILE *, const char *, unsigned long);
387 static void arc_output_mi_thunk (FILE *, tree
, HOST_WIDE_INT
, HOST_WIDE_INT
,
389 static int arc_address_cost (rtx
, machine_mode
, addr_space_t
, bool);
390 static void arc_encode_section_info (tree decl
, rtx rtl
, int first
);
392 static void arc_init_builtins (void);
393 static rtx
arc_expand_builtin (tree
, rtx
, rtx
, machine_mode
, int);
395 static int branch_dest (rtx
);
397 static void arc_output_pic_addr_const (FILE *, rtx
, int);
398 void emit_pic_move (rtx
*, machine_mode
);
399 bool arc_legitimate_pic_operand_p (rtx
);
400 static bool arc_function_ok_for_sibcall (tree
, tree
);
401 static rtx
arc_function_value (const_tree
, const_tree
, bool);
402 const char * output_shift (rtx
*);
403 static void arc_reorg (void);
404 static bool arc_in_small_data_p (const_tree
);
406 static void arc_init_reg_tables (void);
407 static bool arc_return_in_memory (const_tree
, const_tree
);
408 static void arc_init_simd_builtins (void);
409 static bool arc_vector_mode_supported_p (machine_mode
);
411 static bool arc_can_use_doloop_p (const widest_int
&, const widest_int
&,
413 static const char *arc_invalid_within_doloop (const rtx_insn
*);
415 static void output_short_suffix (FILE *file
);
417 static bool arc_frame_pointer_required (void);
419 static bool arc_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT
,
421 enum by_pieces_operation op
,
424 /* Implements target hook vector_mode_supported_p. */
427 arc_vector_mode_supported_p (machine_mode mode
)
429 if (!TARGET_SIMD_SET
)
432 if ((mode
== V4SImode
)
433 || (mode
== V8HImode
))
440 /* TARGET_PRESERVE_RELOAD_P is still awaiting patch re-evaluation / review. */
441 static bool arc_preserve_reload_p (rtx in
) ATTRIBUTE_UNUSED
;
442 static rtx
arc_delegitimize_address (rtx
);
443 static bool arc_can_follow_jump (const rtx_insn
*follower
,
444 const rtx_insn
*followee
);
446 static rtx
frame_insn (rtx
);
447 static void arc_function_arg_advance (cumulative_args_t
, machine_mode
,
449 static rtx
arc_legitimize_address_0 (rtx
, rtx
, machine_mode mode
);
451 static void arc_finalize_pic (void);
453 /* initialize the GCC target structure. */
454 #undef TARGET_COMP_TYPE_ATTRIBUTES
455 #define TARGET_COMP_TYPE_ATTRIBUTES arc_comp_type_attributes
456 #undef TARGET_ASM_FILE_START
457 #define TARGET_ASM_FILE_START arc_file_start
458 #undef TARGET_ATTRIBUTE_TABLE
459 #define TARGET_ATTRIBUTE_TABLE arc_attribute_table
460 #undef TARGET_ASM_INTERNAL_LABEL
461 #define TARGET_ASM_INTERNAL_LABEL arc_internal_label
462 #undef TARGET_RTX_COSTS
463 #define TARGET_RTX_COSTS arc_rtx_costs
464 #undef TARGET_ADDRESS_COST
465 #define TARGET_ADDRESS_COST arc_address_cost
467 #undef TARGET_ENCODE_SECTION_INFO
468 #define TARGET_ENCODE_SECTION_INFO arc_encode_section_info
470 #undef TARGET_CANNOT_FORCE_CONST_MEM
471 #define TARGET_CANNOT_FORCE_CONST_MEM arc_cannot_force_const_mem
473 #undef TARGET_INIT_BUILTINS
474 #define TARGET_INIT_BUILTINS arc_init_builtins
476 #undef TARGET_EXPAND_BUILTIN
477 #define TARGET_EXPAND_BUILTIN arc_expand_builtin
479 #undef TARGET_ASM_OUTPUT_MI_THUNK
480 #define TARGET_ASM_OUTPUT_MI_THUNK arc_output_mi_thunk
482 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
483 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
485 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
486 #define TARGET_FUNCTION_OK_FOR_SIBCALL arc_function_ok_for_sibcall
488 #undef TARGET_MACHINE_DEPENDENT_REORG
489 #define TARGET_MACHINE_DEPENDENT_REORG arc_reorg
491 #undef TARGET_IN_SMALL_DATA_P
492 #define TARGET_IN_SMALL_DATA_P arc_in_small_data_p
494 #undef TARGET_PROMOTE_FUNCTION_MODE
495 #define TARGET_PROMOTE_FUNCTION_MODE \
496 default_promote_function_mode_always_promote
498 #undef TARGET_PROMOTE_PROTOTYPES
499 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
501 #undef TARGET_RETURN_IN_MEMORY
502 #define TARGET_RETURN_IN_MEMORY arc_return_in_memory
503 #undef TARGET_PASS_BY_REFERENCE
504 #define TARGET_PASS_BY_REFERENCE arc_pass_by_reference
506 #undef TARGET_SETUP_INCOMING_VARARGS
507 #define TARGET_SETUP_INCOMING_VARARGS arc_setup_incoming_varargs
509 #undef TARGET_ARG_PARTIAL_BYTES
510 #define TARGET_ARG_PARTIAL_BYTES arc_arg_partial_bytes
512 #undef TARGET_MUST_PASS_IN_STACK
513 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
515 #undef TARGET_FUNCTION_VALUE
516 #define TARGET_FUNCTION_VALUE arc_function_value
518 #undef TARGET_SCHED_ADJUST_PRIORITY
519 #define TARGET_SCHED_ADJUST_PRIORITY arc_sched_adjust_priority
521 #undef TARGET_VECTOR_MODE_SUPPORTED_P
522 #define TARGET_VECTOR_MODE_SUPPORTED_P arc_vector_mode_supported_p
524 #undef TARGET_CAN_USE_DOLOOP_P
525 #define TARGET_CAN_USE_DOLOOP_P arc_can_use_doloop_p
527 #undef TARGET_INVALID_WITHIN_DOLOOP
528 #define TARGET_INVALID_WITHIN_DOLOOP arc_invalid_within_doloop
530 #undef TARGET_PRESERVE_RELOAD_P
531 #define TARGET_PRESERVE_RELOAD_P arc_preserve_reload_p
533 #undef TARGET_CAN_FOLLOW_JUMP
534 #define TARGET_CAN_FOLLOW_JUMP arc_can_follow_jump
536 #undef TARGET_DELEGITIMIZE_ADDRESS
537 #define TARGET_DELEGITIMIZE_ADDRESS arc_delegitimize_address
539 #undef TARGET_USE_BY_PIECES_INFRASTRUCTURE_P
540 #define TARGET_USE_BY_PIECES_INFRASTRUCTURE_P \
541 arc_use_by_pieces_infrastructure_p
543 /* Usually, we will be able to scale anchor offsets.
544 When this fails, we want LEGITIMIZE_ADDRESS to kick in. */
545 #undef TARGET_MIN_ANCHOR_OFFSET
546 #define TARGET_MIN_ANCHOR_OFFSET (-1024)
547 #undef TARGET_MAX_ANCHOR_OFFSET
548 #define TARGET_MAX_ANCHOR_OFFSET (1020)
550 #undef TARGET_SECONDARY_RELOAD
551 #define TARGET_SECONDARY_RELOAD arc_secondary_reload
553 #define TARGET_OPTION_OVERRIDE arc_override_options
555 #define TARGET_CONDITIONAL_REGISTER_USAGE arc_conditional_register_usage
557 #define TARGET_TRAMPOLINE_INIT arc_initialize_trampoline
559 #define TARGET_TRAMPOLINE_ADJUST_ADDRESS arc_trampoline_adjust_address
561 #define TARGET_CAN_ELIMINATE arc_can_eliminate
563 #define TARGET_FRAME_POINTER_REQUIRED arc_frame_pointer_required
565 #define TARGET_FUNCTION_ARG arc_function_arg
567 #define TARGET_FUNCTION_ARG_ADVANCE arc_function_arg_advance
569 #define TARGET_LEGITIMATE_CONSTANT_P arc_legitimate_constant_p
571 #define TARGET_LEGITIMATE_ADDRESS_P arc_legitimate_address_p
573 #define TARGET_MODE_DEPENDENT_ADDRESS_P arc_mode_dependent_address_p
575 #define TARGET_LEGITIMIZE_ADDRESS arc_legitimize_address
577 #define TARGET_ADJUST_INSN_LENGTH arc_adjust_insn_length
579 #define TARGET_INSN_LENGTH_PARAMETERS arc_insn_length_parameters
582 #define TARGET_LRA_P arc_lra_p
583 #define TARGET_REGISTER_PRIORITY arc_register_priority
584 /* Stores with scaled offsets have different displacement ranges. */
585 #define TARGET_DIFFERENT_ADDR_DISPLACEMENT_P hook_bool_void_true
586 #define TARGET_SPILL_CLASS arc_spill_class
588 #include "target-def.h"
590 #undef TARGET_ASM_ALIGNED_HI_OP
591 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
592 #undef TARGET_ASM_ALIGNED_SI_OP
593 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
595 /* Try to keep the (mov:DF _, reg) as early as possible so
596 that the d<add/sub/mul>h-lr insns appear together and can
597 use the peephole2 pattern. */
600 arc_sched_adjust_priority (rtx_insn
*insn
, int priority
)
602 rtx set
= single_set (insn
);
604 && GET_MODE (SET_SRC(set
)) == DFmode
605 && GET_CODE (SET_SRC(set
)) == REG
)
607 /* Incrementing priority by 20 (empirically derived). */
608 return priority
+ 20;
615 arc_secondary_reload (bool in_p
, rtx x
, reg_class_t cl
, machine_mode
,
616 secondary_reload_info
*)
618 if (cl
== DOUBLE_REGS
)
621 /* The loop counter register can be stored, but not loaded directly. */
622 if ((cl
== LPCOUNT_REG
|| cl
== WRITABLE_CORE_REGS
)
623 && in_p
&& MEM_P (x
))
628 static unsigned arc_ifcvt (void);
632 const pass_data pass_data_arc_ifcvt
=
635 "arc_ifcvt", /* name */
636 OPTGROUP_NONE
, /* optinfo_flags */
637 TV_IFCVT2
, /* tv_id */
638 0, /* properties_required */
639 0, /* properties_provided */
640 0, /* properties_destroyed */
641 0, /* todo_flags_start */
642 TODO_df_finish
/* todo_flags_finish */
645 class pass_arc_ifcvt
: public rtl_opt_pass
648 pass_arc_ifcvt(gcc::context
*ctxt
)
649 : rtl_opt_pass(pass_data_arc_ifcvt
, ctxt
)
652 /* opt_pass methods: */
653 opt_pass
* clone () { return new pass_arc_ifcvt (m_ctxt
); }
654 virtual unsigned int execute (function
*) { return arc_ifcvt (); }
660 make_pass_arc_ifcvt (gcc::context
*ctxt
)
662 return new pass_arc_ifcvt (ctxt
);
665 static unsigned arc_predicate_delay_insns (void);
669 const pass_data pass_data_arc_predicate_delay_insns
=
672 "arc_predicate_delay_insns", /* name */
673 OPTGROUP_NONE
, /* optinfo_flags */
674 TV_IFCVT2
, /* tv_id */
675 0, /* properties_required */
676 0, /* properties_provided */
677 0, /* properties_destroyed */
678 0, /* todo_flags_start */
679 TODO_df_finish
/* todo_flags_finish */
682 class pass_arc_predicate_delay_insns
: public rtl_opt_pass
685 pass_arc_predicate_delay_insns(gcc::context
*ctxt
)
686 : rtl_opt_pass(pass_data_arc_predicate_delay_insns
, ctxt
)
689 /* opt_pass methods: */
690 virtual unsigned int execute (function
*)
692 return arc_predicate_delay_insns ();
699 make_pass_arc_predicate_delay_insns (gcc::context
*ctxt
)
701 return new pass_arc_predicate_delay_insns (ctxt
);
704 /* Called by OVERRIDE_OPTIONS to initialize various things. */
709 enum attr_tune tune_dflt
= TUNE_NONE
;
713 arc_cpu_string
= "A5";
715 else if (TARGET_ARC600
)
717 arc_cpu_string
= "ARC600";
718 tune_dflt
= TUNE_ARC600
;
720 else if (TARGET_ARC601
)
722 arc_cpu_string
= "ARC601";
723 tune_dflt
= TUNE_ARC600
;
725 else if (TARGET_ARC700
)
727 arc_cpu_string
= "ARC700";
728 tune_dflt
= TUNE_ARC700_4_2_STD
;
732 if (arc_tune
== TUNE_NONE
)
733 arc_tune
= tune_dflt
;
734 /* Note: arc_multcost is only used in rtx_cost if speed is true. */
735 if (arc_multcost
< 0)
738 case TUNE_ARC700_4_2_STD
:
740 max throughput (1 multiply + 4 other insns) / 5 cycles. */
741 arc_multcost
= COSTS_N_INSNS (4);
742 if (TARGET_NOMPY_SET
)
743 arc_multcost
= COSTS_N_INSNS (30);
745 case TUNE_ARC700_4_2_XMAC
:
747 max throughput (1 multiply + 2 other insns) / 3 cycles. */
748 arc_multcost
= COSTS_N_INSNS (3);
749 if (TARGET_NOMPY_SET
)
750 arc_multcost
= COSTS_N_INSNS (30);
753 if (TARGET_MUL64_SET
)
755 arc_multcost
= COSTS_N_INSNS (4);
760 arc_multcost
= COSTS_N_INSNS (30);
764 /* Support mul64 generation only for A5 and ARC600. */
765 if (TARGET_MUL64_SET
&& TARGET_ARC700
)
766 error ("-mmul64 not supported for ARC700");
768 /* MPY instructions valid only for ARC700. */
769 if (TARGET_NOMPY_SET
&& !TARGET_ARC700
)
770 error ("-mno-mpy supported only for ARC700");
772 /* mul/mac instructions only for ARC600. */
773 if (TARGET_MULMAC_32BY16_SET
&& !(TARGET_ARC600
|| TARGET_ARC601
))
774 error ("-mmul32x16 supported only for ARC600 or ARC601");
776 if (!TARGET_DPFP
&& TARGET_DPFP_DISABLE_LRSR
)
777 error ("-mno-dpfp-lrsr supported only with -mdpfp");
779 /* FPX-1. No fast and compact together. */
780 if ((TARGET_DPFP_FAST_SET
&& TARGET_DPFP_COMPACT_SET
)
781 || (TARGET_SPFP_FAST_SET
&& TARGET_SPFP_COMPACT_SET
))
782 error ("FPX fast and compact options cannot be specified together");
784 /* FPX-2. No fast-spfp for arc600 or arc601. */
785 if (TARGET_SPFP_FAST_SET
&& (TARGET_ARC600
|| TARGET_ARC601
))
786 error ("-mspfp_fast not available on ARC600 or ARC601");
788 /* FPX-3. No FPX extensions on pre-ARC600 cores. */
789 if ((TARGET_DPFP
|| TARGET_SPFP
)
790 && !(TARGET_ARC600
|| TARGET_ARC601
|| TARGET_ARC700
))
791 error ("FPX extensions not available on pre-ARC600 cores");
793 /* Warn for unimplemented PIC in pre-ARC700 cores, and disable flag_pic. */
794 if (flag_pic
&& !TARGET_ARC700
)
796 warning (DK_WARNING
, "PIC is not supported for %s. Generating non-PIC code only..", arc_cpu_string
);
800 arc_init_reg_tables ();
802 /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P. */
803 memset (arc_punct_chars
, 0, sizeof (arc_punct_chars
));
804 arc_punct_chars
['#'] = 1;
805 arc_punct_chars
['*'] = 1;
806 arc_punct_chars
['?'] = 1;
807 arc_punct_chars
['!'] = 1;
808 arc_punct_chars
['^'] = 1;
809 arc_punct_chars
['&'] = 1;
811 if (optimize
> 1 && !TARGET_NO_COND_EXEC
)
813 /* There are two target-independent ifcvt passes, and arc_reorg may do
814 one or more arc_ifcvt calls. */
815 opt_pass
*pass_arc_ifcvt_4
= make_pass_arc_ifcvt (g
);
816 struct register_pass_info arc_ifcvt4_info
817 = { pass_arc_ifcvt_4
, "dbr", 1, PASS_POS_INSERT_AFTER
};
818 struct register_pass_info arc_ifcvt5_info
819 = { pass_arc_ifcvt_4
->clone (), "shorten", 1, PASS_POS_INSERT_BEFORE
};
821 register_pass (&arc_ifcvt4_info
);
822 register_pass (&arc_ifcvt5_info
);
825 if (flag_delayed_branch
)
827 opt_pass
*pass_arc_predicate_delay_insns
828 = make_pass_arc_predicate_delay_insns (g
);
829 struct register_pass_info arc_predicate_delay_info
830 = { pass_arc_predicate_delay_insns
, "dbr", 1, PASS_POS_INSERT_AFTER
};
832 register_pass (&arc_predicate_delay_info
);
836 /* Check ARC options, generate derived target attributes. */
839 arc_override_options (void)
841 if (arc_cpu
== PROCESSOR_NONE
)
842 arc_cpu
= PROCESSOR_ARC700
;
844 if (arc_size_opt_level
== 3)
848 target_flags
|= MASK_NO_SDATA_SET
;
850 if (flag_no_common
== 255)
851 flag_no_common
= !TARGET_NO_SDATA_SET
;
853 /* TARGET_COMPACT_CASESI needs the "q" register class. */ \
854 if (TARGET_MIXED_CODE
)
857 TARGET_COMPACT_CASESI
= 0;
858 if (TARGET_COMPACT_CASESI
)
859 TARGET_CASE_VECTOR_PC_RELATIVE
= 1;
861 /* These need to be done at start up. It's convenient to do them here. */
865 /* The condition codes of the ARC, and the inverse function. */
866 /* For short branches, the "c" / "nc" names are not defined in the ARC
867 Programmers manual, so we have to use "lo" / "hs"" instead. */
868 static const char *arc_condition_codes
[] =
870 "al", 0, "eq", "ne", "p", "n", "lo", "hs", "v", "nv",
871 "gt", "le", "ge", "lt", "hi", "ls", "pnz", 0
874 enum arc_cc_code_index
876 ARC_CC_AL
, ARC_CC_EQ
= ARC_CC_AL
+2, ARC_CC_NE
, ARC_CC_P
, ARC_CC_N
,
877 ARC_CC_C
, ARC_CC_NC
, ARC_CC_V
, ARC_CC_NV
,
878 ARC_CC_GT
, ARC_CC_LE
, ARC_CC_GE
, ARC_CC_LT
, ARC_CC_HI
, ARC_CC_LS
, ARC_CC_PNZ
,
879 ARC_CC_LO
= ARC_CC_C
, ARC_CC_HS
= ARC_CC_NC
882 #define ARC_INVERSE_CONDITION_CODE(X) ((X) ^ 1)
884 /* Returns the index of the ARC condition code string in
885 `arc_condition_codes'. COMPARISON should be an rtx like
886 `(eq (...) (...))'. */
889 get_arc_condition_code (rtx comparison
)
891 switch (GET_MODE (XEXP (comparison
, 0)))
894 case SImode
: /* For BRcc. */
895 switch (GET_CODE (comparison
))
897 case EQ
: return ARC_CC_EQ
;
898 case NE
: return ARC_CC_NE
;
899 case GT
: return ARC_CC_GT
;
900 case LE
: return ARC_CC_LE
;
901 case GE
: return ARC_CC_GE
;
902 case LT
: return ARC_CC_LT
;
903 case GTU
: return ARC_CC_HI
;
904 case LEU
: return ARC_CC_LS
;
905 case LTU
: return ARC_CC_LO
;
906 case GEU
: return ARC_CC_HS
;
907 default : gcc_unreachable ();
910 switch (GET_CODE (comparison
))
912 case EQ
: return ARC_CC_EQ
;
913 case NE
: return ARC_CC_NE
;
914 case GE
: return ARC_CC_P
;
915 case LT
: return ARC_CC_N
;
916 case GT
: return ARC_CC_PNZ
;
917 default : gcc_unreachable ();
920 switch (GET_CODE (comparison
))
922 case EQ
: return ARC_CC_EQ
;
923 case NE
: return ARC_CC_NE
;
924 default : gcc_unreachable ();
927 switch (GET_CODE (comparison
))
929 case LTU
: return ARC_CC_C
;
930 case GEU
: return ARC_CC_NC
;
931 default : gcc_unreachable ();
934 if (TARGET_ARGONAUT_SET
&& TARGET_SPFP
)
935 switch (GET_CODE (comparison
))
937 case GT
: return ARC_CC_N
;
938 case UNLE
: return ARC_CC_P
;
939 default : gcc_unreachable ();
942 switch (GET_CODE (comparison
))
944 case GT
: return ARC_CC_HI
;
945 case UNLE
: return ARC_CC_LS
;
946 default : gcc_unreachable ();
949 /* Same for FPX and non-FPX. */
950 switch (GET_CODE (comparison
))
952 case GE
: return ARC_CC_HS
;
953 case UNLT
: return ARC_CC_LO
;
954 default : gcc_unreachable ();
957 switch (GET_CODE (comparison
))
959 case UNEQ
: return ARC_CC_EQ
;
960 case LTGT
: return ARC_CC_NE
;
961 default : gcc_unreachable ();
964 switch (GET_CODE (comparison
))
966 case UNORDERED
: return ARC_CC_C
;
967 case ORDERED
: return ARC_CC_NC
;
968 default : gcc_unreachable ();
971 switch (GET_CODE (comparison
))
973 case EQ
: return ARC_CC_EQ
;
974 case NE
: return ARC_CC_NE
;
975 case UNORDERED
: return ARC_CC_C
;
976 case ORDERED
: return ARC_CC_NC
;
977 case LTGT
: return ARC_CC_HI
;
978 case UNEQ
: return ARC_CC_LS
;
979 default : gcc_unreachable ();
981 default : gcc_unreachable ();
987 /* Return true if COMPARISON has a short form that can accomodate OFFSET. */
990 arc_short_comparison_p (rtx comparison
, int offset
)
992 gcc_assert (ARC_CC_NC
== ARC_CC_HS
);
993 gcc_assert (ARC_CC_C
== ARC_CC_LO
);
994 switch (get_arc_condition_code (comparison
))
996 case ARC_CC_EQ
: case ARC_CC_NE
:
997 return offset
>= -512 && offset
<= 506;
998 case ARC_CC_GT
: case ARC_CC_LE
: case ARC_CC_GE
: case ARC_CC_LT
:
999 case ARC_CC_HI
: case ARC_CC_LS
: case ARC_CC_LO
: case ARC_CC_HS
:
1000 return offset
>= -64 && offset
<= 58;
1006 /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
1007 return the mode to be used for the comparison. */
1010 arc_select_cc_mode (enum rtx_code op
, rtx x
, rtx y
)
1012 machine_mode mode
= GET_MODE (x
);
1015 /* For an operation that sets the condition codes as a side-effect, the
1016 C and V flags is not set as for cmp, so we can only use comparisons where
1017 this doesn't matter. (For LT and GE we can use "mi" and "pl"
1019 /* ??? We could use "pnz" for greater than zero, however, we could then
1020 get into trouble because the comparison could not be reversed. */
1021 if (GET_MODE_CLASS (mode
) == MODE_INT
1023 && (op
== EQ
|| op
== NE
1024 || ((op
== LT
|| op
== GE
) && GET_MODE_SIZE (GET_MODE (x
)) <= 4)))
1027 /* add.f for if (a+b) */
1029 && GET_CODE (y
) == NEG
1030 && (op
== EQ
|| op
== NE
))
1033 /* Check if this is a test suitable for bxor.f . */
1034 if (mode
== SImode
&& (op
== EQ
|| op
== NE
) && CONST_INT_P (y
)
1035 && ((INTVAL (y
) - 1) & INTVAL (y
)) == 0
1039 /* Check if this is a test suitable for add / bmsk.f . */
1040 if (mode
== SImode
&& (op
== EQ
|| op
== NE
) && CONST_INT_P (y
)
1041 && GET_CODE (x
) == AND
&& CONST_INT_P ((x1
= XEXP (x
, 1)))
1042 && ((INTVAL (x1
) + 1) & INTVAL (x1
)) == 0
1043 && (~INTVAL (x1
) | INTVAL (y
)) < 0
1044 && (~INTVAL (x1
) | INTVAL (y
)) > -0x800)
1047 if (GET_MODE (x
) == SImode
&& (op
== LTU
|| op
== GEU
)
1048 && GET_CODE (x
) == PLUS
1049 && (rtx_equal_p (XEXP (x
, 0), y
) || rtx_equal_p (XEXP (x
, 1), y
)))
1052 if (TARGET_ARGONAUT_SET
1053 && ((mode
== SFmode
&& TARGET_SPFP
) || (mode
== DFmode
&& TARGET_DPFP
)))
1056 case EQ
: case NE
: case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1058 case LT
: case UNGE
: case GT
: case UNLE
:
1059 return CC_FP_GTmode
;
1060 case LE
: case UNGT
: case GE
: case UNLT
:
1061 return CC_FP_GEmode
;
1062 default: gcc_unreachable ();
1064 else if (GET_MODE_CLASS (mode
) == MODE_FLOAT
&& TARGET_OPTFPE
)
1067 case EQ
: case NE
: return CC_Zmode
;
1069 case GT
: case UNLE
: return CC_FP_GTmode
;
1071 case GE
: case UNLT
: return CC_FP_GEmode
;
1072 case UNEQ
: case LTGT
: return CC_FP_UNEQmode
;
1073 case ORDERED
: case UNORDERED
: return CC_FP_ORDmode
;
1074 default: gcc_unreachable ();
1080 /* Vectors to keep interesting information about registers where it can easily
1081 be got. We use to use the actual mode value as the bit number, but there
1082 is (or may be) more than 32 modes now. Instead we use two tables: one
1083 indexed by hard register number, and one indexed by mode. */
1085 /* The purpose of arc_mode_class is to shrink the range of modes so that
1086 they all fit (as bit numbers) in a 32-bit word (again). Each real mode is
1087 mapped into one arc_mode_class mode. */
1089 enum arc_mode_class
{
1091 S_MODE
, D_MODE
, T_MODE
, O_MODE
,
1092 SF_MODE
, DF_MODE
, TF_MODE
, OF_MODE
,
1096 /* Modes for condition codes. */
1097 #define C_MODES (1 << (int) C_MODE)
1099 /* Modes for single-word and smaller quantities. */
1100 #define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
1102 /* Modes for double-word and smaller quantities. */
1103 #define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))
1105 /* Mode for 8-byte DF values only. */
1106 #define DF_MODES (1 << DF_MODE)
1108 /* Modes for quad-word and smaller quantities. */
1109 #define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE))
1111 /* Modes for 128-bit vectors. */
1112 #define V_MODES (1 << (int) V_MODE)
1114 /* Value is 1 if register/mode pair is acceptable on arc. */
1116 unsigned int arc_hard_regno_mode_ok
[] = {
1117 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
,
1118 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
,
1119 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, D_MODES
,
1120 D_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1122 /* ??? Leave these as S_MODES for now. */
1123 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1124 DF_MODES
, 0, DF_MODES
, 0, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1125 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1126 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, C_MODES
, S_MODES
,
1128 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1129 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1130 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1131 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1133 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1134 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1135 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1136 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
1138 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
1139 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
1142 unsigned int arc_mode_class
[NUM_MACHINE_MODES
];
1144 enum reg_class arc_regno_reg_class
[FIRST_PSEUDO_REGISTER
];
1147 arc_preferred_reload_class (rtx
, enum reg_class cl
)
1149 if ((cl
) == CHEAP_CORE_REGS
|| (cl
) == WRITABLE_CORE_REGS
)
1150 return GENERAL_REGS
;
1154 /* Initialize the arc_mode_class array. */
1157 arc_init_reg_tables (void)
1161 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
1163 machine_mode m
= (machine_mode
) i
;
1165 switch (GET_MODE_CLASS (m
))
1168 case MODE_PARTIAL_INT
:
1169 case MODE_COMPLEX_INT
:
1170 if (GET_MODE_SIZE (m
) <= 4)
1171 arc_mode_class
[i
] = 1 << (int) S_MODE
;
1172 else if (GET_MODE_SIZE (m
) == 8)
1173 arc_mode_class
[i
] = 1 << (int) D_MODE
;
1174 else if (GET_MODE_SIZE (m
) == 16)
1175 arc_mode_class
[i
] = 1 << (int) T_MODE
;
1176 else if (GET_MODE_SIZE (m
) == 32)
1177 arc_mode_class
[i
] = 1 << (int) O_MODE
;
1179 arc_mode_class
[i
] = 0;
1182 case MODE_COMPLEX_FLOAT
:
1183 if (GET_MODE_SIZE (m
) <= 4)
1184 arc_mode_class
[i
] = 1 << (int) SF_MODE
;
1185 else if (GET_MODE_SIZE (m
) == 8)
1186 arc_mode_class
[i
] = 1 << (int) DF_MODE
;
1187 else if (GET_MODE_SIZE (m
) == 16)
1188 arc_mode_class
[i
] = 1 << (int) TF_MODE
;
1189 else if (GET_MODE_SIZE (m
) == 32)
1190 arc_mode_class
[i
] = 1 << (int) OF_MODE
;
1192 arc_mode_class
[i
] = 0;
1194 case MODE_VECTOR_INT
:
1195 arc_mode_class
[i
] = (1<< (int) V_MODE
);
1199 /* mode_class hasn't been initialized yet for EXTRA_CC_MODES, so
1200 we must explicitly check for them here. */
1201 if (i
== (int) CCmode
|| i
== (int) CC_ZNmode
|| i
== (int) CC_Zmode
1202 || i
== (int) CC_Cmode
1203 || i
== CC_FP_GTmode
|| i
== CC_FP_GEmode
|| i
== CC_FP_ORDmode
)
1204 arc_mode_class
[i
] = 1 << (int) C_MODE
;
1206 arc_mode_class
[i
] = 0;
1212 /* Core registers 56..59 are used for multiply extension options.
1213 The dsp option uses r56 and r57, these are then named acc1 and acc2.
1214 acc1 is the highpart, and acc2 the lowpart, so which register gets which
1215 number depends on endianness.
1216 The mul64 multiplier options use r57 for mlo, r58 for mmid and r59 for mhi.
1217 Because mlo / mhi form a 64 bit value, we use different gcc internal
1218 register numbers to make them form a register pair as the gcc internals
1219 know it. mmid gets number 57, if still available, and mlo / mhi get
1220 number 58 and 59, depending on endianness. We use DBX_REGISTER_NUMBER
1221 to map this back. */
1222 char rname56
[5] = "r56";
1223 char rname57
[5] = "r57";
1224 char rname58
[5] = "r58";
1225 char rname59
[5] = "r59";
1228 arc_conditional_register_usage (void)
1232 int fix_start
= 60, fix_end
= 55;
1234 if (TARGET_MUL64_SET
)
1239 /* We don't provide a name for mmed. In rtl / assembly resource lists,
1240 you are supposed to refer to it as mlo & mhi, e.g
1241 (zero_extract:SI (reg:DI 58) (const_int 32) (16)) .
1242 In an actual asm instruction, you are of course use mmed.
1243 The point of avoiding having a separate register for mmed is that
1244 this way, we don't have to carry clobbers of that reg around in every
1245 isntruction that modifies mlo and/or mhi. */
1246 strcpy (rname57
, "");
1247 strcpy (rname58
, TARGET_BIG_ENDIAN
? "mhi" : "mlo");
1248 strcpy (rname59
, TARGET_BIG_ENDIAN
? "mlo" : "mhi");
1250 if (TARGET_MULMAC_32BY16_SET
)
1253 fix_end
= fix_end
> 57 ? fix_end
: 57;
1254 strcpy (rname56
, TARGET_BIG_ENDIAN
? "acc1" : "acc2");
1255 strcpy (rname57
, TARGET_BIG_ENDIAN
? "acc2" : "acc1");
1257 for (regno
= fix_start
; regno
<= fix_end
; regno
++)
1259 if (!fixed_regs
[regno
])
1260 warning (0, "multiply option implies r%d is fixed", regno
);
1261 fixed_regs
[regno
] = call_used_regs
[regno
] = 1;
1265 reg_alloc_order
[2] = 12;
1266 reg_alloc_order
[3] = 13;
1267 reg_alloc_order
[4] = 14;
1268 reg_alloc_order
[5] = 15;
1269 reg_alloc_order
[6] = 1;
1270 reg_alloc_order
[7] = 0;
1271 reg_alloc_order
[8] = 4;
1272 reg_alloc_order
[9] = 5;
1273 reg_alloc_order
[10] = 6;
1274 reg_alloc_order
[11] = 7;
1275 reg_alloc_order
[12] = 8;
1276 reg_alloc_order
[13] = 9;
1277 reg_alloc_order
[14] = 10;
1278 reg_alloc_order
[15] = 11;
1280 if (TARGET_SIMD_SET
)
1283 for (i
= ARC_FIRST_SIMD_VR_REG
; i
<= ARC_LAST_SIMD_VR_REG
; i
++)
1284 reg_alloc_order
[i
] = i
;
1285 for (i
= ARC_FIRST_SIMD_DMA_CONFIG_REG
;
1286 i
<= ARC_LAST_SIMD_DMA_CONFIG_REG
; i
++)
1287 reg_alloc_order
[i
] = i
;
1289 /* For Arctangent-A5 / ARC600, lp_count may not be read in an instruction
1290 following immediately after another one setting it to a new value.
1291 There was some discussion on how to enforce scheduling constraints for
1292 processors with missing interlocks on the gcc mailing list:
1293 http://gcc.gnu.org/ml/gcc/2008-05/msg00021.html .
1294 However, we can't actually use this approach, because for ARC the
1295 delay slot scheduling pass is active, which runs after
1296 machine_dependent_reorg. */
1298 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], LP_COUNT
);
1299 else if (!TARGET_ARC700
)
1300 fixed_regs
[LP_COUNT
] = 1;
1301 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
1302 if (!call_used_regs
[regno
])
1303 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], regno
);
1304 for (regno
= 32; regno
< 60; regno
++)
1305 if (!fixed_regs
[regno
])
1306 SET_HARD_REG_BIT (reg_class_contents
[WRITABLE_CORE_REGS
], regno
);
1309 for (regno
= 32; regno
<= 60; regno
++)
1310 CLEAR_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], regno
);
1312 /* If they have used -ffixed-lp_count, make sure it takes
1314 if (fixed_regs
[LP_COUNT
])
1316 CLEAR_HARD_REG_BIT (reg_class_contents
[LPCOUNT_REG
], LP_COUNT
);
1317 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], LP_COUNT
);
1318 CLEAR_HARD_REG_BIT (reg_class_contents
[WRITABLE_CORE_REGS
], LP_COUNT
);
1320 /* Instead of taking out SF_MODE like below, forbid it outright. */
1321 arc_hard_regno_mode_ok
[60] = 0;
1324 arc_hard_regno_mode_ok
[60] = 1 << (int) S_MODE
;
1327 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1331 if (TARGET_Q_CLASS
&& ((i
<= 3) || ((i
>= 12) && (i
<= 15))))
1332 arc_regno_reg_class
[i
] = ARCOMPACT16_REGS
;
1334 arc_regno_reg_class
[i
] = GENERAL_REGS
;
1337 arc_regno_reg_class
[i
]
1339 ? (TEST_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], i
)
1340 ? CHEAP_CORE_REGS
: ALL_CORE_REGS
)
1342 && TEST_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], i
))
1343 ? CHEAP_CORE_REGS
: WRITABLE_CORE_REGS
));
1345 arc_regno_reg_class
[i
] = NO_REGS
;
1348 /* ARCOMPACT16_REGS is empty, if TARGET_Q_CLASS has not been activated. */
1349 if (!TARGET_Q_CLASS
)
1351 CLEAR_HARD_REG_SET(reg_class_contents
[ARCOMPACT16_REGS
]);
1352 CLEAR_HARD_REG_SET(reg_class_contents
[AC16_BASE_REGS
]);
1355 gcc_assert (FIRST_PSEUDO_REGISTER
>= 144);
1357 /* Handle Special Registers. */
1358 arc_regno_reg_class
[29] = LINK_REGS
; /* ilink1 register. */
1359 arc_regno_reg_class
[30] = LINK_REGS
; /* ilink2 register. */
1360 arc_regno_reg_class
[31] = LINK_REGS
; /* blink register. */
1361 arc_regno_reg_class
[60] = LPCOUNT_REG
;
1362 arc_regno_reg_class
[61] = NO_REGS
; /* CC_REG: must be NO_REGS. */
1363 arc_regno_reg_class
[62] = GENERAL_REGS
;
1367 for (i
= 40; i
< 44; ++i
)
1369 arc_regno_reg_class
[i
] = DOUBLE_REGS
;
1371 /* Unless they want us to do 'mov d1, 0x00000000' make sure
1372 no attempt is made to use such a register as a destination
1373 operand in *movdf_insn. */
1374 if (!TARGET_ARGONAUT_SET
)
1376 /* Make sure no 'c', 'w', 'W', or 'Rac' constraint is
1377 interpreted to mean they can use D1 or D2 in their insn. */
1378 CLEAR_HARD_REG_BIT(reg_class_contents
[CHEAP_CORE_REGS
], i
);
1379 CLEAR_HARD_REG_BIT(reg_class_contents
[ALL_CORE_REGS
], i
);
1380 CLEAR_HARD_REG_BIT(reg_class_contents
[WRITABLE_CORE_REGS
], i
);
1381 CLEAR_HARD_REG_BIT(reg_class_contents
[MPY_WRITABLE_CORE_REGS
], i
);
1387 /* Disable all DOUBLE_REGISTER settings,
1388 if not generating DPFP code. */
1389 arc_regno_reg_class
[40] = ALL_REGS
;
1390 arc_regno_reg_class
[41] = ALL_REGS
;
1391 arc_regno_reg_class
[42] = ALL_REGS
;
1392 arc_regno_reg_class
[43] = ALL_REGS
;
1394 arc_hard_regno_mode_ok
[40] = 0;
1395 arc_hard_regno_mode_ok
[42] = 0;
1397 CLEAR_HARD_REG_SET(reg_class_contents
[DOUBLE_REGS
]);
1400 if (TARGET_SIMD_SET
)
1402 gcc_assert (ARC_FIRST_SIMD_VR_REG
== 64);
1403 gcc_assert (ARC_LAST_SIMD_VR_REG
== 127);
1405 for (i
= ARC_FIRST_SIMD_VR_REG
; i
<= ARC_LAST_SIMD_VR_REG
; i
++)
1406 arc_regno_reg_class
[i
] = SIMD_VR_REGS
;
1408 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_REG
== 128);
1409 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_IN_REG
== 128);
1410 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG
== 136);
1411 gcc_assert (ARC_LAST_SIMD_DMA_CONFIG_REG
== 143);
1413 for (i
= ARC_FIRST_SIMD_DMA_CONFIG_REG
;
1414 i
<= ARC_LAST_SIMD_DMA_CONFIG_REG
; i
++)
1415 arc_regno_reg_class
[i
] = SIMD_DMA_CONFIG_REGS
;
1419 arc_regno_reg_class
[PROGRAM_COUNTER_REGNO
] = GENERAL_REGS
;
1422 /* Handle an "interrupt" attribute; arguments as in
1423 struct attribute_spec.handler. */
1426 arc_handle_interrupt_attribute (tree
*, tree name
, tree args
, int,
1431 tree value
= TREE_VALUE (args
);
1433 if (TREE_CODE (value
) != STRING_CST
)
1435 warning (OPT_Wattributes
,
1436 "argument of %qE attribute is not a string constant",
1438 *no_add_attrs
= true;
1440 else if (strcmp (TREE_STRING_POINTER (value
), "ilink1")
1441 && strcmp (TREE_STRING_POINTER (value
), "ilink2"))
1443 warning (OPT_Wattributes
,
1444 "argument of %qE attribute is not \"ilink1\" or \"ilink2\"",
1446 *no_add_attrs
= true;
1451 /* Return zero if TYPE1 and TYPE are incompatible, one if they are compatible,
1452 and two if they are nearly compatible (which causes a warning to be
1456 arc_comp_type_attributes (const_tree type1
,
1459 int l1
, l2
, m1
, m2
, s1
, s2
;
1461 /* Check for mismatch of non-default calling convention. */
1462 if (TREE_CODE (type1
) != FUNCTION_TYPE
)
1465 /* Check for mismatched call attributes. */
1466 l1
= lookup_attribute ("long_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
1467 l2
= lookup_attribute ("long_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
1468 m1
= lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
1469 m2
= lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
1470 s1
= lookup_attribute ("short_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
1471 s2
= lookup_attribute ("short_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
1473 /* Only bother to check if an attribute is defined. */
1474 if (l1
| l2
| m1
| m2
| s1
| s2
)
1476 /* If one type has an attribute, the other must have the same attribute. */
1477 if ((l1
!= l2
) || (m1
!= m2
) || (s1
!= s2
))
1480 /* Disallow mixed attributes. */
1481 if (l1
+ m1
+ s1
> 1)
1489 /* Set the default attributes for TYPE. */
1492 arc_set_default_type_attributes (tree type ATTRIBUTE_UNUSED
)
1497 /* Misc. utilities. */
1499 /* X and Y are two things to compare using CODE. Emit the compare insn and
1500 return the rtx for the cc reg in the proper mode. */
1503 gen_compare_reg (rtx comparison
, machine_mode omode
)
1505 enum rtx_code code
= GET_CODE (comparison
);
1506 rtx x
= XEXP (comparison
, 0);
1507 rtx y
= XEXP (comparison
, 1);
1509 machine_mode mode
, cmode
;
1512 cmode
= GET_MODE (x
);
1513 if (cmode
== VOIDmode
)
1514 cmode
= GET_MODE (y
);
1515 gcc_assert (cmode
== SImode
|| cmode
== SFmode
|| cmode
== DFmode
);
1516 if (cmode
== SImode
)
1518 if (!register_operand (x
, SImode
))
1520 if (register_operand (y
, SImode
))
1525 code
= swap_condition (code
);
1528 x
= copy_to_mode_reg (SImode
, x
);
1530 if (GET_CODE (y
) == SYMBOL_REF
&& flag_pic
)
1531 y
= copy_to_mode_reg (SImode
, y
);
1535 x
= force_reg (cmode
, x
);
1536 y
= force_reg (cmode
, y
);
1538 mode
= SELECT_CC_MODE (code
, x
, y
);
1540 cc_reg
= gen_rtx_REG (mode
, CC_REG
);
1542 /* ??? FIXME (x-y)==0, as done by both cmpsfpx_raw and
1543 cmpdfpx_raw, is not a correct comparison for floats:
1544 http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
1546 if (TARGET_ARGONAUT_SET
1547 && ((cmode
== SFmode
&& TARGET_SPFP
) || (cmode
== DFmode
&& TARGET_DPFP
)))
1551 case NE
: case EQ
: case LT
: case UNGE
: case LE
: case UNGT
:
1552 case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1554 case GT
: case UNLE
: case GE
: case UNLT
:
1555 code
= swap_condition (code
);
1563 if (cmode
== SFmode
)
1565 emit_insn (gen_cmpsfpx_raw (x
, y
));
1569 /* Accepts Dx regs directly by insns. */
1570 emit_insn (gen_cmpdfpx_raw (x
, y
));
1573 if (mode
!= CC_FPXmode
)
1574 emit_insn (gen_rtx_SET (VOIDmode
, cc_reg
,
1575 gen_rtx_COMPARE (mode
,
1576 gen_rtx_REG (CC_FPXmode
, 61),
1579 else if (GET_MODE_CLASS (cmode
) == MODE_FLOAT
&& TARGET_OPTFPE
)
1581 rtx op0
= gen_rtx_REG (cmode
, 0);
1582 rtx op1
= gen_rtx_REG (cmode
, GET_MODE_SIZE (cmode
) / UNITS_PER_WORD
);
1586 case NE
: case EQ
: case GT
: case UNLE
: case GE
: case UNLT
:
1587 case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1589 case LT
: case UNGE
: case LE
: case UNGT
:
1590 code
= swap_condition (code
);
1598 if (currently_expanding_to_rtl
)
1600 emit_move_insn (op0
, x
);
1601 emit_move_insn (op1
, y
);
1605 gcc_assert (rtx_equal_p (op0
, x
));
1606 gcc_assert (rtx_equal_p (op1
, y
));
1608 emit_insn (gen_cmp_float (cc_reg
, gen_rtx_COMPARE (mode
, op0
, op1
)));
1611 emit_insn (gen_rtx_SET (omode
, cc_reg
,
1612 gen_rtx_COMPARE (mode
, x
, y
)));
1613 return gen_rtx_fmt_ee (code
, omode
, cc_reg
, const0_rtx
);
1616 /* Return true if VALUE, a const_double, will fit in a limm (4 byte number).
1617 We assume the value can be either signed or unsigned. */
1620 arc_double_limm_p (rtx value
)
1622 HOST_WIDE_INT low
, high
;
1624 gcc_assert (GET_CODE (value
) == CONST_DOUBLE
);
1629 low
= CONST_DOUBLE_LOW (value
);
1630 high
= CONST_DOUBLE_HIGH (value
);
1632 if (low
& 0x80000000)
1634 return (((unsigned HOST_WIDE_INT
) low
<= 0xffffffff && high
== 0)
1635 || (((low
& - (unsigned HOST_WIDE_INT
) 0x80000000)
1636 == - (unsigned HOST_WIDE_INT
) 0x80000000)
1641 return (unsigned HOST_WIDE_INT
) low
<= 0x7fffffff && high
== 0;
1645 /* Do any needed setup for a variadic function. For the ARC, we must
1646 create a register parameter block, and then copy any anonymous arguments
1647 in registers to memory.
1649 CUM has not been updated for the last named argument which has type TYPE
1650 and mode MODE, and we rely on this fact. */
1653 arc_setup_incoming_varargs (cumulative_args_t args_so_far
,
1654 machine_mode mode
, tree type
,
1655 int *pretend_size
, int no_rtl
)
1658 CUMULATIVE_ARGS next_cum
;
1660 /* We must treat `__builtin_va_alist' as an anonymous arg. */
1662 next_cum
= *get_cumulative_args (args_so_far
);
1663 arc_function_arg_advance (pack_cumulative_args (&next_cum
), mode
, type
, 1);
1664 first_anon_arg
= next_cum
;
1666 if (first_anon_arg
< MAX_ARC_PARM_REGS
)
1668 /* First anonymous (unnamed) argument is in a reg. */
1670 /* Note that first_reg_offset < MAX_ARC_PARM_REGS. */
1671 int first_reg_offset
= first_anon_arg
;
1676 = gen_rtx_MEM (BLKmode
, plus_constant (Pmode
, arg_pointer_rtx
,
1677 FIRST_PARM_OFFSET (0)));
1678 move_block_from_reg (first_reg_offset
, regblock
,
1679 MAX_ARC_PARM_REGS
- first_reg_offset
);
1683 = ((MAX_ARC_PARM_REGS
- first_reg_offset
) * UNITS_PER_WORD
);
1687 /* Cost functions. */
1689 /* Provide the costs of an addressing mode that contains ADDR.
1690 If ADDR is not a valid address, its cost is irrelevant. */
1693 arc_address_cost (rtx addr
, machine_mode
, addr_space_t
, bool speed
)
1695 switch (GET_CODE (addr
))
1698 return speed
|| satisfies_constraint_Rcq (addr
) ? 0 : 1;
1699 case PRE_INC
: case PRE_DEC
: case POST_INC
: case POST_DEC
:
1700 case PRE_MODIFY
: case POST_MODIFY
:
1706 /* Most likely needs a LIMM. */
1707 return COSTS_N_INSNS (1);
1711 register rtx plus0
= XEXP (addr
, 0);
1712 register rtx plus1
= XEXP (addr
, 1);
1714 if (GET_CODE (plus0
) != REG
1715 && (GET_CODE (plus0
) != MULT
1716 || !CONST_INT_P (XEXP (plus0
, 1))
1717 || (INTVAL (XEXP (plus0
, 1)) != 2
1718 && INTVAL (XEXP (plus0
, 1)) != 4)))
1721 switch (GET_CODE (plus1
))
1724 return (!RTX_OK_FOR_OFFSET_P (SImode
, plus1
)
1728 : (satisfies_constraint_Rcq (plus0
)
1729 && satisfies_constraint_O (plus1
))
1733 return (speed
< 1 ? 0
1734 : (satisfies_constraint_Rcq (plus0
)
1735 && satisfies_constraint_Rcq (plus1
))
1740 return COSTS_N_INSNS (1);
1753 /* Emit instruction X with the frame related bit set. */
1759 RTX_FRAME_RELATED_P (x
) = 1;
1763 /* Emit a frame insn to move SRC to DST. */
1766 frame_move (rtx dst
, rtx src
)
1768 return frame_insn (gen_rtx_SET (VOIDmode
, dst
, src
));
1771 /* Like frame_move, but add a REG_INC note for REG if ADDR contains an
1772 auto increment address, or is zero. */
1775 frame_move_inc (rtx dst
, rtx src
, rtx reg
, rtx addr
)
1777 rtx insn
= frame_move (dst
, src
);
1780 || GET_CODE (addr
) == PRE_DEC
|| GET_CODE (addr
) == POST_INC
1781 || GET_CODE (addr
) == PRE_MODIFY
|| GET_CODE (addr
) == POST_MODIFY
)
1782 add_reg_note (insn
, REG_INC
, reg
);
1786 /* Emit a frame insn which adjusts a frame address register REG by OFFSET. */
1789 frame_add (rtx reg
, HOST_WIDE_INT offset
)
1791 gcc_assert ((offset
& 0x3) == 0);
1794 return frame_move (reg
, plus_constant (Pmode
, reg
, offset
));
1797 /* Emit a frame insn which adjusts stack pointer by OFFSET. */
1800 frame_stack_add (HOST_WIDE_INT offset
)
1802 return frame_add (stack_pointer_rtx
, offset
);
1805 /* Traditionally, we push saved registers first in the prologue,
1806 then we allocate the rest of the frame - and reverse in the epilogue.
1807 This has still its merits for ease of debugging, or saving code size
1808 or even execution time if the stack frame is so large that some accesses
1809 can't be encoded anymore with offsets in the instruction code when using
1811 Also, it would be a good starting point if we got instructions to help
1812 with register save/restore.
1814 However, often stack frames are small, and the pushing / popping has
1816 - the stack modification prevents a lot of scheduling.
1817 - frame allocation / deallocation needs extra instructions.
1818 - unless we know that we compile ARC700 user code, we need to put
1819 a memory barrier after frame allocation / before deallocation to
1820 prevent interrupts clobbering our data in the frame.
1821 In particular, we don't have any such guarantees for library functions,
1822 which tend to, on the other hand, to have small frames.
1824 Thus, for small frames, we'd like to use a different scheme:
1825 - The frame is allocated in full with the first prologue instruction,
1826 and deallocated in full with the last epilogue instruction.
1827 Thus, the instructions in-betwen can be freely scheduled.
1828 - If the function has no outgoing arguments on the stack, we can allocate
1829 one register save slot at the top of the stack. This register can then
1830 be saved simultanously with frame allocation, and restored with
1832 This register can be picked depending on scheduling considerations,
1833 although same though should go into having some set of registers
1834 to be potentially lingering after a call, and others to be available
1835 immediately - i.e. in the absence of interprocedual optimization, we
1836 can use an ABI-like convention for register allocation to reduce
1837 stalls after function return. */
1838 /* Function prologue/epilogue handlers. */
1840 /* ARCompact stack frames look like:
1842 Before call After call
1843 high +-----------------------+ +-----------------------+
1844 mem | reg parm save area | | reg parm save area |
1845 | only created for | | only created for |
1846 | variable arg fns | | variable arg fns |
1847 AP +-----------------------+ +-----------------------+
1848 | return addr register | | return addr register |
1849 | (if required) | | (if required) |
1850 +-----------------------+ +-----------------------+
1852 | reg save area | | reg save area |
1854 +-----------------------+ +-----------------------+
1855 | frame pointer | | frame pointer |
1856 | (if required) | | (if required) |
1857 FP +-----------------------+ +-----------------------+
1859 | local/temp variables | | local/temp variables |
1861 +-----------------------+ +-----------------------+
1863 | arguments on stack | | arguments on stack |
1865 SP +-----------------------+ +-----------------------+
1866 | reg parm save area |
1867 | only created for |
1868 | variable arg fns |
1869 AP +-----------------------+
1870 | return addr register |
1872 +-----------------------+
1876 +-----------------------+
1879 FP +-----------------------+
1881 | local/temp variables |
1883 +-----------------------+
1885 | arguments on stack |
1887 mem SP +-----------------------+
1890 1) The "reg parm save area" does not exist for non variable argument fns.
1891 The "reg parm save area" can be eliminated completely if we created our
1892 own va-arc.h, but that has tradeoffs as well (so it's not done). */
1894 /* Structure to be filled in by arc_compute_frame_size with register
1895 save masks, and offsets for the current function. */
1896 struct GTY (()) arc_frame_info
1898 unsigned int total_size
; /* # bytes that the entire frame takes up. */
1899 unsigned int extra_size
; /* # bytes of extra stuff. */
1900 unsigned int pretend_size
; /* # bytes we push and pretend caller did. */
1901 unsigned int args_size
; /* # bytes that outgoing arguments take up. */
1902 unsigned int reg_size
; /* # bytes needed to store regs. */
1903 unsigned int var_size
; /* # bytes that variables take up. */
1904 unsigned int reg_offset
; /* Offset from new sp to store regs. */
1905 unsigned int gmask
; /* Mask of saved gp registers. */
1906 int initialized
; /* Nonzero if frame size already calculated. */
1907 short millicode_start_reg
;
1908 short millicode_end_reg
;
1909 bool save_return_addr
;
1912 /* Defining data structures for per-function information. */
1914 typedef struct GTY (()) machine_function
1916 enum arc_function_type fn_type
;
1917 struct arc_frame_info frame_info
;
1918 /* To keep track of unalignment caused by short insns. */
1920 int force_short_suffix
; /* Used when disgorging return delay slot insns. */
1921 const char *size_reason
;
1922 struct arc_ccfsm ccfsm_current
;
1923 /* Map from uid to ccfsm state during branch shortening. */
1924 rtx ccfsm_current_insn
;
1925 char arc_reorg_started
;
1926 char prescan_initialized
;
1929 /* Type of function DECL.
1931 The result is cached. To reset the cache at the end of a function,
1932 call with DECL = NULL_TREE. */
1934 enum arc_function_type
1935 arc_compute_function_type (struct function
*fun
)
1937 tree decl
= fun
->decl
;
1939 enum arc_function_type fn_type
= fun
->machine
->fn_type
;
1941 if (fn_type
!= ARC_FUNCTION_UNKNOWN
)
1944 /* Assume we have a normal function (not an interrupt handler). */
1945 fn_type
= ARC_FUNCTION_NORMAL
;
1947 /* Now see if this is an interrupt handler. */
1948 for (a
= DECL_ATTRIBUTES (decl
);
1952 tree name
= TREE_PURPOSE (a
), args
= TREE_VALUE (a
);
1954 if (name
== get_identifier ("interrupt")
1955 && list_length (args
) == 1
1956 && TREE_CODE (TREE_VALUE (args
)) == STRING_CST
)
1958 tree value
= TREE_VALUE (args
);
1960 if (!strcmp (TREE_STRING_POINTER (value
), "ilink1"))
1961 fn_type
= ARC_FUNCTION_ILINK1
;
1962 else if (!strcmp (TREE_STRING_POINTER (value
), "ilink2"))
1963 fn_type
= ARC_FUNCTION_ILINK2
;
1970 return fun
->machine
->fn_type
= fn_type
;
1973 #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
1974 #define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM))
1976 /* Tell prologue and epilogue if register REGNO should be saved / restored.
1977 The return address and frame pointer are treated separately.
1978 Don't consider them here.
1979 Addition for pic: The gp register needs to be saved if the current
1980 function changes it to access gotoff variables.
1981 FIXME: This will not be needed if we used some arbitrary register
1984 #define MUST_SAVE_REGISTER(regno, interrupt_p) \
1985 (((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \
1986 && (df_regs_ever_live_p (regno) && (!call_used_regs[regno] || interrupt_p))) \
1987 || (flag_pic && crtl->uses_pic_offset_table \
1988 && regno == PIC_OFFSET_TABLE_REGNUM) )
1990 #define MUST_SAVE_RETURN_ADDR \
1991 (cfun->machine->frame_info.save_return_addr)
1993 /* Return non-zero if there are registers to be saved or loaded using
1994 millicode thunks. We can only use consecutive sequences starting
1995 with r13, and not going beyond r25.
1996 GMASK is a bitmask of registers to save. This function sets
1997 FRAME->millicod_start_reg .. FRAME->millicode_end_reg to the range
1998 of registers to be saved / restored with a millicode call. */
2001 arc_compute_millicode_save_restore_regs (unsigned int gmask
,
2002 struct arc_frame_info
*frame
)
2006 int start_reg
= 13, end_reg
= 25;
2008 for (regno
= start_reg
; regno
<= end_reg
&& (gmask
& (1L << regno
));)
2010 end_reg
= regno
- 1;
2011 /* There is no point in using millicode thunks if we don't save/restore
2012 at least three registers. For non-leaf functions we also have the
2014 if (regno
- start_reg
>= 3 - (crtl
->is_leaf
== 0))
2016 frame
->millicode_start_reg
= 13;
2017 frame
->millicode_end_reg
= regno
- 1;
2023 /* Return the bytes needed to compute the frame pointer from the current
2026 SIZE is the size needed for local variables. */
2029 arc_compute_frame_size (int size
) /* size = # of var. bytes allocated. */
2032 unsigned int total_size
, var_size
, args_size
, pretend_size
, extra_size
;
2033 unsigned int reg_size
, reg_offset
;
2035 enum arc_function_type fn_type
;
2037 struct arc_frame_info
*frame_info
= &cfun
->machine
->frame_info
;
2039 size
= ARC_STACK_ALIGN (size
);
2041 /* 1) Size of locals and temporaries */
2044 /* 2) Size of outgoing arguments */
2045 args_size
= crtl
->outgoing_args_size
;
2047 /* 3) Calculate space needed for saved registers.
2048 ??? We ignore the extension registers for now. */
2050 /* See if this is an interrupt handler. Call used registers must be saved
2055 fn_type
= arc_compute_function_type (cfun
);
2056 interrupt_p
= ARC_INTERRUPT_P (fn_type
);
2058 for (regno
= 0; regno
<= 31; regno
++)
2060 if (MUST_SAVE_REGISTER (regno
, interrupt_p
))
2062 reg_size
+= UNITS_PER_WORD
;
2063 gmask
|= 1 << regno
;
2067 /* 4) Space for back trace data structure.
2068 <return addr reg size> (if required) + <fp size> (if required). */
2069 frame_info
->save_return_addr
2070 = (!crtl
->is_leaf
|| df_regs_ever_live_p (RETURN_ADDR_REGNUM
));
2071 /* Saving blink reg in case of leaf function for millicode thunk calls. */
2072 if (optimize_size
&& !TARGET_NO_MILLICODE_THUNK_SET
)
2074 if (arc_compute_millicode_save_restore_regs (gmask
, frame_info
))
2075 frame_info
->save_return_addr
= true;
2079 if (MUST_SAVE_RETURN_ADDR
)
2081 if (frame_pointer_needed
)
2084 /* 5) Space for variable arguments passed in registers */
2085 pretend_size
= crtl
->args
.pretend_args_size
;
2087 /* Ensure everything before the locals is aligned appropriately. */
2089 unsigned int extra_plus_reg_size
;
2090 unsigned int extra_plus_reg_size_aligned
;
2092 extra_plus_reg_size
= extra_size
+ reg_size
;
2093 extra_plus_reg_size_aligned
= ARC_STACK_ALIGN(extra_plus_reg_size
);
2094 reg_size
= extra_plus_reg_size_aligned
- extra_size
;
2097 /* Compute total frame size. */
2098 total_size
= var_size
+ args_size
+ extra_size
+ pretend_size
+ reg_size
;
2100 total_size
= ARC_STACK_ALIGN (total_size
);
2102 /* Compute offset of register save area from stack pointer:
2103 A5 Frame: pretend_size <blink> reg_size <fp> var_size args_size <--sp
2105 reg_offset
= (total_size
- (pretend_size
+ reg_size
+ extra_size
)
2106 + (frame_pointer_needed
? 4 : 0));
2108 /* Save computed information. */
2109 frame_info
->total_size
= total_size
;
2110 frame_info
->extra_size
= extra_size
;
2111 frame_info
->pretend_size
= pretend_size
;
2112 frame_info
->var_size
= var_size
;
2113 frame_info
->args_size
= args_size
;
2114 frame_info
->reg_size
= reg_size
;
2115 frame_info
->reg_offset
= reg_offset
;
2116 frame_info
->gmask
= gmask
;
2117 frame_info
->initialized
= reload_completed
;
2119 /* Ok, we're done. */
2123 /* Common code to save/restore registers. */
2124 /* BASE_REG is the base register to use for addressing and to adjust.
2125 GMASK is a bitmask of general purpose registers to save/restore.
2126 epilogue_p 0: prologue 1:epilogue 2:epilogue, sibling thunk
2127 If *FIRST_OFFSET is non-zero, add it first to BASE_REG - preferably
2128 using a pre-modify for the first memory access. *FIRST_OFFSET is then
2132 arc_save_restore (rtx base_reg
,
2133 unsigned int gmask
, int epilogue_p
, int *first_offset
)
2135 unsigned int offset
= 0;
2137 struct arc_frame_info
*frame
= &cfun
->machine
->frame_info
;
2138 rtx sibthunk_insn
= NULL_RTX
;
2142 /* Millicode thunks implementation:
2143 Generates calls to millicodes for registers starting from r13 to r25
2144 Present Limitations:
2145 - Only one range supported. The remaining regs will have the ordinary
2146 st and ld instructions for store and loads. Hence a gmask asking
2147 to store r13-14, r16-r25 will only generate calls to store and
2148 load r13 to r14 while store and load insns will be generated for
2149 r16 to r25 in the prologue and epilogue respectively.
2151 - Presently library only supports register ranges starting from r13.
2153 if (epilogue_p
== 2 || frame
->millicode_end_reg
> 14)
2155 int start_call
= frame
->millicode_start_reg
;
2156 int end_call
= frame
->millicode_end_reg
;
2157 int n_regs
= end_call
- start_call
+ 1;
2158 int i
= 0, r
, off
= 0;
2160 rtx ret_addr
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
2164 /* "reg_size" won't be more than 127 . */
2165 gcc_assert (epilogue_p
|| abs (*first_offset
) <= 127);
2166 frame_add (base_reg
, *first_offset
);
2169 insn
= gen_rtx_PARALLEL
2170 (VOIDmode
, rtvec_alloc ((epilogue_p
== 2) + n_regs
+ 1));
2171 if (epilogue_p
== 2)
2174 XVECEXP (insn
, 0, n_regs
) = gen_rtx_CLOBBER (VOIDmode
, ret_addr
);
2175 for (r
= start_call
; r
<= end_call
; r
++, off
+= UNITS_PER_WORD
, i
++)
2177 rtx reg
= gen_rtx_REG (SImode
, r
);
2179 = gen_frame_mem (SImode
, plus_constant (Pmode
, base_reg
, off
));
2182 XVECEXP (insn
, 0, i
) = gen_rtx_SET (VOIDmode
, reg
, mem
);
2184 XVECEXP (insn
, 0, i
) = gen_rtx_SET (VOIDmode
, mem
, reg
);
2185 gmask
= gmask
& ~(1L << r
);
2187 if (epilogue_p
== 2)
2188 sibthunk_insn
= insn
;
2194 for (regno
= 0; regno
<= 31; regno
++)
2196 if ((gmask
& (1L << regno
)) != 0)
2198 rtx reg
= gen_rtx_REG (SImode
, regno
);
2203 gcc_assert (!offset
);
2204 addr
= plus_constant (Pmode
, base_reg
, *first_offset
);
2205 addr
= gen_rtx_PRE_MODIFY (Pmode
, base_reg
, addr
);
2210 gcc_assert (SMALL_INT (offset
));
2211 addr
= plus_constant (Pmode
, base_reg
, offset
);
2213 mem
= gen_frame_mem (SImode
, addr
);
2215 frame_move_inc (reg
, mem
, base_reg
, addr
);
2217 frame_move_inc (mem
, reg
, base_reg
, addr
);
2218 offset
+= UNITS_PER_WORD
;
2224 rtx r12
= gen_rtx_REG (Pmode
, 12);
2226 frame_insn (gen_rtx_SET (VOIDmode
, r12
, GEN_INT (offset
)));
2227 XVECEXP (sibthunk_insn
, 0, 0) = ret_rtx
;
2228 XVECEXP (sibthunk_insn
, 0, 1)
2229 = gen_rtx_SET (VOIDmode
, stack_pointer_rtx
,
2230 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
, r12
));
2231 sibthunk_insn
= emit_jump_insn (sibthunk_insn
);
2232 RTX_FRAME_RELATED_P (sibthunk_insn
) = 1;
2234 } /* arc_save_restore */
2237 int arc_return_address_regs
[4]
2238 = {0, RETURN_ADDR_REGNUM
, ILINK1_REGNUM
, ILINK2_REGNUM
};
2240 /* Set up the stack and frame pointer (if desired) for the function. */
2243 arc_expand_prologue (void)
2245 int size
= get_frame_size ();
2246 unsigned int gmask
= cfun
->machine
->frame_info
.gmask
;
2247 /* unsigned int frame_pointer_offset;*/
2248 unsigned int frame_size_to_allocate
;
2249 /* (FIXME: The first store will use a PRE_MODIFY; this will usually be r13.
2250 Change the stack layout so that we rather store a high register with the
2251 PRE_MODIFY, thus enabling more short insn generation.) */
2252 int first_offset
= 0;
2254 size
= ARC_STACK_ALIGN (size
);
2256 /* Compute/get total frame size. */
2257 size
= (!cfun
->machine
->frame_info
.initialized
2258 ? arc_compute_frame_size (size
)
2259 : cfun
->machine
->frame_info
.total_size
);
2261 if (flag_stack_usage_info
)
2262 current_function_static_stack_size
= size
;
2264 /* Keep track of frame size to be allocated. */
2265 frame_size_to_allocate
= size
;
2267 /* These cases shouldn't happen. Catch them now. */
2268 gcc_assert (!(size
== 0 && gmask
));
2270 /* Allocate space for register arguments if this is a variadic function. */
2271 if (cfun
->machine
->frame_info
.pretend_size
!= 0)
2273 /* Ensure pretend_size is maximum of 8 * word_size. */
2274 gcc_assert (cfun
->machine
->frame_info
.pretend_size
<= 32);
2276 frame_stack_add (-(HOST_WIDE_INT
)cfun
->machine
->frame_info
.pretend_size
);
2277 frame_size_to_allocate
-= cfun
->machine
->frame_info
.pretend_size
;
2280 /* The home-grown ABI says link register is saved first. */
2281 if (MUST_SAVE_RETURN_ADDR
)
2283 rtx ra
= gen_rtx_REG (SImode
, RETURN_ADDR_REGNUM
);
2284 rtx mem
= gen_frame_mem (Pmode
, gen_rtx_PRE_DEC (Pmode
, stack_pointer_rtx
));
2286 frame_move_inc (mem
, ra
, stack_pointer_rtx
, 0);
2287 frame_size_to_allocate
-= UNITS_PER_WORD
;
2289 } /* MUST_SAVE_RETURN_ADDR */
2291 /* Save any needed call-saved regs (and call-used if this is an
2292 interrupt handler) for ARCompact ISA. */
2293 if (cfun
->machine
->frame_info
.reg_size
)
2295 first_offset
= -cfun
->machine
->frame_info
.reg_size
;
2296 /* N.B. FRAME_POINTER_MASK and RETURN_ADDR_MASK are cleared in gmask. */
2297 arc_save_restore (stack_pointer_rtx
, gmask
, 0, &first_offset
);
2298 frame_size_to_allocate
-= cfun
->machine
->frame_info
.reg_size
;
2302 /* Save frame pointer if needed. */
2303 if (frame_pointer_needed
)
2305 rtx addr
= gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
2306 GEN_INT (-UNITS_PER_WORD
+ first_offset
));
2307 rtx mem
= gen_frame_mem (Pmode
, gen_rtx_PRE_MODIFY (Pmode
,
2310 frame_move_inc (mem
, frame_pointer_rtx
, stack_pointer_rtx
, 0);
2311 frame_size_to_allocate
-= UNITS_PER_WORD
;
2313 frame_move (frame_pointer_rtx
, stack_pointer_rtx
);
2316 /* ??? We don't handle the case where the saved regs are more than 252
2317 bytes away from sp. This can be handled by decrementing sp once, saving
2318 the regs, and then decrementing it again. The epilogue doesn't have this
2319 problem as the `ld' insn takes reg+limm values (though it would be more
2320 efficient to avoid reg+limm). */
2322 frame_size_to_allocate
-= first_offset
;
2323 /* Allocate the stack frame. */
2324 if (frame_size_to_allocate
> 0)
2325 frame_stack_add ((HOST_WIDE_INT
) 0 - frame_size_to_allocate
);
2327 /* Setup the gp register, if needed. */
2328 if (crtl
->uses_pic_offset_table
)
2329 arc_finalize_pic ();
2332 /* Do any necessary cleanup after a function to restore stack, frame,
2336 arc_expand_epilogue (int sibcall_p
)
2338 int size
= get_frame_size ();
2339 enum arc_function_type fn_type
= arc_compute_function_type (cfun
);
2341 size
= ARC_STACK_ALIGN (size
);
2342 size
= (!cfun
->machine
->frame_info
.initialized
2343 ? arc_compute_frame_size (size
)
2344 : cfun
->machine
->frame_info
.total_size
);
2346 unsigned int pretend_size
= cfun
->machine
->frame_info
.pretend_size
;
2347 unsigned int frame_size
;
2348 unsigned int size_to_deallocate
;
2350 int can_trust_sp_p
= !cfun
->calls_alloca
;
2351 int first_offset
= 0;
2352 int millicode_p
= cfun
->machine
->frame_info
.millicode_end_reg
> 0;
2354 size_to_deallocate
= size
;
2356 frame_size
= size
- (pretend_size
+
2357 cfun
->machine
->frame_info
.reg_size
+
2358 cfun
->machine
->frame_info
.extra_size
);
2360 /* ??? There are lots of optimizations that can be done here.
2361 EG: Use fp to restore regs if it's closer.
2362 Maybe in time we'll do them all. For now, always restore regs from
2363 sp, but don't restore sp if we don't have to. */
2365 if (!can_trust_sp_p
)
2366 gcc_assert (frame_pointer_needed
);
2368 /* Restore stack pointer to the beginning of saved register area for
2372 if (frame_pointer_needed
)
2373 frame_move (stack_pointer_rtx
, frame_pointer_rtx
);
2375 first_offset
= frame_size
;
2376 size_to_deallocate
-= frame_size
;
2378 else if (!can_trust_sp_p
)
2379 frame_stack_add (-frame_size
);
2382 /* Restore any saved registers. */
2383 if (frame_pointer_needed
)
2385 rtx addr
= gen_rtx_POST_INC (Pmode
, stack_pointer_rtx
);
2387 frame_move_inc (frame_pointer_rtx
, gen_frame_mem (Pmode
, addr
),
2388 stack_pointer_rtx
, 0);
2389 size_to_deallocate
-= UNITS_PER_WORD
;
2392 /* Load blink after the calls to thunk calls in case of optimize size. */
2395 int sibthunk_p
= (!sibcall_p
2396 && fn_type
== ARC_FUNCTION_NORMAL
2397 && !cfun
->machine
->frame_info
.pretend_size
);
2399 gcc_assert (!(cfun
->machine
->frame_info
.gmask
2400 & (FRAME_POINTER_MASK
| RETURN_ADDR_MASK
)));
2401 arc_save_restore (stack_pointer_rtx
,
2402 cfun
->machine
->frame_info
.gmask
,
2403 1 + sibthunk_p
, &first_offset
);
2407 /* If we are to restore registers, and first_offset would require
2408 a limm to be encoded in a PRE_MODIFY, yet we can add it with a
2409 fast add to the stack pointer, do this now. */
2410 if ((!SMALL_INT (first_offset
)
2411 && cfun
->machine
->frame_info
.gmask
2412 && ((TARGET_ARC700
&& !optimize_size
)
2413 ? first_offset
<= 0x800
2414 : satisfies_constraint_C2a (GEN_INT (first_offset
))))
2415 /* Also do this if we have both gprs and return
2416 address to restore, and they both would need a LIMM. */
2417 || (MUST_SAVE_RETURN_ADDR
2418 && !SMALL_INT ((cfun
->machine
->frame_info
.reg_size
+ first_offset
) >> 2)
2419 && cfun
->machine
->frame_info
.gmask
))
2421 frame_stack_add (first_offset
);
2424 if (MUST_SAVE_RETURN_ADDR
)
2426 rtx ra
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
2427 int ra_offs
= cfun
->machine
->frame_info
.reg_size
+ first_offset
;
2428 rtx addr
= plus_constant (Pmode
, stack_pointer_rtx
, ra_offs
);
2430 /* If the load of blink would need a LIMM, but we can add
2431 the offset quickly to sp, do the latter. */
2432 if (!SMALL_INT (ra_offs
>> 2)
2433 && !cfun
->machine
->frame_info
.gmask
2434 && ((TARGET_ARC700
&& !optimize_size
)
2436 : satisfies_constraint_C2a (GEN_INT (ra_offs
))))
2438 size_to_deallocate
-= ra_offs
- first_offset
;
2440 frame_stack_add (ra_offs
);
2442 addr
= stack_pointer_rtx
;
2444 /* See if we can combine the load of the return address with the
2445 final stack adjustment.
2446 We need a separate load if there are still registers to
2447 restore. We also want a separate load if the combined insn
2448 would need a limm, but a separate load doesn't. */
2450 && !cfun
->machine
->frame_info
.gmask
2451 && (SMALL_INT (ra_offs
) || !SMALL_INT (ra_offs
>> 2)))
2453 addr
= gen_rtx_PRE_MODIFY (Pmode
, stack_pointer_rtx
, addr
);
2455 size_to_deallocate
-= cfun
->machine
->frame_info
.reg_size
;
2457 else if (!ra_offs
&& size_to_deallocate
== UNITS_PER_WORD
)
2459 addr
= gen_rtx_POST_INC (Pmode
, addr
);
2460 size_to_deallocate
= 0;
2462 frame_move_inc (ra
, gen_frame_mem (Pmode
, addr
), stack_pointer_rtx
, addr
);
2467 if (cfun
->machine
->frame_info
.reg_size
)
2468 arc_save_restore (stack_pointer_rtx
,
2469 /* The zeroing of these two bits is unnecessary, but leave this in for clarity. */
2470 cfun
->machine
->frame_info
.gmask
2471 & ~(FRAME_POINTER_MASK
| RETURN_ADDR_MASK
), 1, &first_offset
);
2475 /* The rest of this function does the following:
2476 ARCompact : handle epilogue_delay, restore sp (phase-2), return
2479 /* Keep track of how much of the stack pointer we've restored.
2480 It makes the following a lot more readable. */
2481 size_to_deallocate
+= first_offset
;
2482 restored
= size
- size_to_deallocate
;
2484 if (size
> restored
)
2485 frame_stack_add (size
- restored
);
2486 /* Emit the return instruction. */
2487 if (sibcall_p
== FALSE
)
2488 emit_jump_insn (gen_simple_return ());
2490 if (!TARGET_EPILOGUE_CFI
)
2494 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
2495 RTX_FRAME_RELATED_P (insn
) = 0;
2499 /* Return the offset relative to the stack pointer where the return address
2500 is stored, or -1 if it is not stored. */
2503 arc_return_slot_offset ()
2505 struct arc_frame_info
*afi
= &cfun
->machine
->frame_info
;
2507 return (afi
->save_return_addr
2508 ? afi
->total_size
- afi
->pretend_size
- afi
->extra_size
: -1);
2513 /* Emit special PIC prologues and epilogues. */
2514 /* If the function has any GOTOFF relocations, then the GOTBASE
2515 register has to be setup in the prologue
2516 The instruction needed at the function start for setting up the
2519 ----------------------------------------------------------
2520 The rtl to be emitted for this should be:
2523 (const (unspec (symref _DYNAMIC) 3)))
2524 ---------------------------------------------------------- */
2527 arc_finalize_pic (void)
2530 rtx baseptr_rtx
= gen_rtx_REG (Pmode
, PIC_OFFSET_TABLE_REGNUM
);
2532 if (crtl
->uses_pic_offset_table
== 0)
2535 gcc_assert (flag_pic
!= 0);
2537 pat
= gen_rtx_SYMBOL_REF (Pmode
, "_DYNAMIC");
2538 pat
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, pat
), ARC_UNSPEC_GOT
);
2539 pat
= gen_rtx_CONST (Pmode
, pat
);
2541 pat
= gen_rtx_SET (VOIDmode
, baseptr_rtx
, pat
);
2546 /* !TARGET_BARREL_SHIFTER support. */
2547 /* Emit a shift insn to set OP0 to OP1 shifted by OP2; CODE specifies what
2551 emit_shift (enum rtx_code code
, rtx op0
, rtx op1
, rtx op2
)
2553 rtx shift
= gen_rtx_fmt_ee (code
, SImode
, op1
, op2
);
2555 = ((shift4_operator (shift
, SImode
) ? gen_shift_si3
: gen_shift_si3_loop
)
2556 (op0
, op1
, op2
, shift
));
2560 /* Output the assembler code for doing a shift.
2561 We go to a bit of trouble to generate efficient code as the ARC601 only has
2562 single bit shifts. This is taken from the h8300 port. We only have one
2563 mode of shifting and can't access individual bytes like the h8300 can, so
2564 this is greatly simplified (at the expense of not generating hyper-
2567 This function is not used if the variable shift insns are present. */
2569 /* FIXME: This probably can be done using a define_split in arc.md.
2570 Alternately, generate rtx rather than output instructions. */
2573 output_shift (rtx
*operands
)
2575 /* static int loopend_lab;*/
2576 rtx shift
= operands
[3];
2577 machine_mode mode
= GET_MODE (shift
);
2578 enum rtx_code code
= GET_CODE (shift
);
2579 const char *shift_one
;
2581 gcc_assert (mode
== SImode
);
2585 case ASHIFT
: shift_one
= "add %0,%1,%1"; break;
2586 case ASHIFTRT
: shift_one
= "asr %0,%1"; break;
2587 case LSHIFTRT
: shift_one
= "lsr %0,%1"; break;
2588 default: gcc_unreachable ();
2591 if (GET_CODE (operands
[2]) != CONST_INT
)
2593 output_asm_insn ("and.f lp_count,%2, 0x1f", operands
);
2600 n
= INTVAL (operands
[2]);
2602 /* Only consider the lower 5 bits of the shift count. */
2605 /* First see if we can do them inline. */
2606 /* ??? We could get better scheduling & shorter code (using short insns)
2607 by using splitters. Alas, that'd be even more verbose. */
2608 if (code
== ASHIFT
&& n
<= 9 && n
> 2
2609 && dest_reg_operand (operands
[4], SImode
))
2611 output_asm_insn ("mov %4,0\n\tadd3 %0,%4,%1", operands
);
2612 for (n
-=3 ; n
>= 3; n
-= 3)
2613 output_asm_insn ("add3 %0,%4,%0", operands
);
2615 output_asm_insn ("add2 %0,%4,%0", operands
);
2617 output_asm_insn ("add %0,%0,%0", operands
);
2623 output_asm_insn (shift_one
, operands
);
2624 operands
[1] = operands
[0];
2627 /* See if we can use a rotate/and. */
2628 else if (n
== BITS_PER_WORD
- 1)
2633 output_asm_insn ("and %0,%1,1\n\tror %0,%0", operands
);
2636 /* The ARC doesn't have a rol insn. Use something else. */
2637 output_asm_insn ("add.f 0,%1,%1\n\tsbc %0,%0,%0", operands
);
2640 /* The ARC doesn't have a rol insn. Use something else. */
2641 output_asm_insn ("add.f 0,%1,%1\n\trlc %0,0", operands
);
2647 else if (n
== BITS_PER_WORD
- 2 && dest_reg_operand (operands
[4], SImode
))
2652 output_asm_insn ("and %0,%1,3\n\tror %0,%0\n\tror %0,%0", operands
);
2655 #if 1 /* Need some scheduling comparisons. */
2656 output_asm_insn ("add.f %4,%1,%1\n\tsbc %0,%0,%0\n\t"
2657 "add.f 0,%4,%4\n\trlc %0,%0", operands
);
2659 output_asm_insn ("add.f %4,%1,%1\n\tbxor %0,%4,31\n\t"
2660 "sbc.f %0,%0,%4\n\trlc %0,%0", operands
);
2665 output_asm_insn ("add.f %4,%1,%1\n\trlc %0,0\n\t"
2666 "add.f 0,%4,%4\n\trlc %0,%0", operands
);
2668 output_asm_insn ("add.f %0,%1,%1\n\trlc.f %0,0\n\t"
2669 "and %0,%0,1\n\trlc %0,%0", operands
);
2676 else if (n
== BITS_PER_WORD
- 3 && code
== ASHIFT
)
2677 output_asm_insn ("and %0,%1,7\n\tror %0,%0\n\tror %0,%0\n\tror %0,%0",
2682 operands
[2] = GEN_INT (n
);
2683 output_asm_insn ("mov.f lp_count, %2", operands
);
2687 output_asm_insn ("lpnz\t2f", operands
);
2688 output_asm_insn (shift_one
, operands
);
2689 output_asm_insn ("nop", operands
);
2690 fprintf (asm_out_file
, "2:\t%s end single insn loop\n",
2699 /* Nested function support. */
2701 /* Directly store VALUE into memory object BLOCK at OFFSET. */
2704 emit_store_direct (rtx block
, int offset
, int value
)
2706 emit_insn (gen_store_direct (adjust_address (block
, SImode
, offset
),
2708 gen_int_mode (value
, SImode
))));
2711 /* Emit RTL insns to initialize the variable parts of a trampoline.
2712 FNADDR is an RTX for the address of the function's pure code.
2713 CXT is an RTX for the static chain value for the function. */
2714 /* With potentially multiple shared objects loaded, and multiple stacks
2715 present for multiple thereds where trampolines might reside, a simple
2716 range check will likely not suffice for the profiler to tell if a callee
2717 is a trampoline. We a speedier check by making the trampoline start at
2718 an address that is not 4-byte aligned.
2719 A trampoline looks like this:
2723 ld_s r12,[pcl,12] 0xd403
2724 ld r11,[pcl,12] 0x170c 700b
2728 The fastest trampoline to execute for trampolines within +-8KB of CTX
2731 j [limm] 0x20200f80 limm
2732 and that would also be faster to write to the stack by computing the offset
2733 from CTX to TRAMP at compile time. However, it would really be better to
2734 get rid of the high cost of cache invalidation when generating trampolines,
2735 which requires that the code part of trampolines stays constant, and
2737 - making sure that no executable code but trampolines is on the stack,
2738 no icache entries linger for the area of the stack from when before the
2739 stack was allocated, and allocating trampolines in trampoline-only
2742 - allocate trampolines fram a special pool of pre-allocated trampolines. */
2745 arc_initialize_trampoline (rtx tramp
, tree fndecl
, rtx cxt
)
2747 rtx fnaddr
= XEXP (DECL_RTL (fndecl
), 0);
2749 emit_store_direct (tramp
, 0, TARGET_BIG_ENDIAN
? 0x78e0d403 : 0xd40378e0);
2750 emit_store_direct (tramp
, 4, TARGET_BIG_ENDIAN
? 0x170c700b : 0x700b170c);
2751 emit_store_direct (tramp
, 8, TARGET_BIG_ENDIAN
? 0x7c0078e0 : 0x78e07c00);
2752 emit_move_insn (adjust_address (tramp
, SImode
, 12), fnaddr
);
2753 emit_move_insn (adjust_address (tramp
, SImode
, 16), cxt
);
2754 emit_insn (gen_flush_icache (adjust_address (tramp
, SImode
, 0)));
2757 /* Allow the profiler to easily distinguish trampolines from normal
2761 arc_trampoline_adjust_address (rtx addr
)
2763 return plus_constant (Pmode
, addr
, 2);
2766 /* This is set briefly to 1 when we output a ".as" address modifer, and then
2767 reset when we output the scaled address. */
2768 static int output_scaled
= 0;
2770 /* Print operand X (an rtx) in assembler syntax to file FILE.
2771 CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
2772 For `%' followed by punctuation, CODE is the punctuation and X is null. */
2773 /* In final.c:output_asm_insn:
2776 'c' : constant address if CONSTANT_ADDRESS_P
2782 '#': condbranch delay slot suffix
2783 '*': jump delay slot suffix
2784 '?' : nonjump-insn suffix for conditional execution or short instruction
2785 '!' : jump / call suffix for conditional execution or short instruction
2786 '`': fold constant inside unary o-perator, re-recognize, and emit.
2791 'B': Branch comparison operand - suppress sda reference
2792 'H': Most significant word
2793 'L': Least significant word
2794 'A': ASCII decimal representation of floating point value
2795 'U': Load/store update or scaling indicator
2796 'V': cache bypass indicator for volatile
2801 'o': original symbol - no @ prepending. */
2804 arc_print_operand (FILE *file
, rtx x
, int code
)
2809 if (GET_CODE (x
) == CONST_INT
)
2810 fprintf (file
, "%d",exact_log2(INTVAL (x
) + 1) - 1 );
2812 output_operand_lossage ("invalid operand to %%Z code");
2817 if (GET_CODE (x
) == CONST_INT
)
2818 fprintf (file
, "%d",exact_log2(INTVAL (x
)) );
2820 output_operand_lossage ("invalid operand to %%z code");
2825 if (GET_CODE (x
) == CONST_INT
)
2826 fprintf (file
, "%d",exact_log2(~INTVAL (x
)) );
2828 output_operand_lossage ("invalid operand to %%M code");
2833 /* Conditional branches depending on condition codes.
2834 Note that this is only for branches that were known to depend on
2835 condition codes before delay slot scheduling;
2836 out-of-range brcc / bbit expansions should use '*'.
2837 This distinction is important because of the different
2838 allowable delay slot insns and the output of the delay suffix
2839 for TARGET_AT_DBR_COND_EXEC. */
2841 /* Unconditional branches / branches not depending on condition codes.
2842 This could also be a CALL_INSN.
2843 Output the appropriate delay slot suffix. */
2844 if (final_sequence
&& final_sequence
->len () != 1)
2846 rtx_insn
*jump
= final_sequence
->insn (0);
2847 rtx_insn
*delay
= final_sequence
->insn (1);
2849 /* For TARGET_PAD_RETURN we might have grabbed the delay insn. */
2850 if (delay
->deleted ())
2852 if (JUMP_P (jump
) && INSN_ANNULLED_BRANCH_P (jump
))
2853 fputs (INSN_FROM_TARGET_P (delay
) ? ".d"
2854 : TARGET_AT_DBR_CONDEXEC
&& code
== '#' ? ".d"
2855 : get_attr_type (jump
) == TYPE_RETURN
&& code
== '#' ? ""
2862 case '?' : /* with leading "." */
2863 case '!' : /* without leading "." */
2864 /* This insn can be conditionally executed. See if the ccfsm machinery
2865 says it should be conditionalized.
2866 If it shouldn't, we'll check the compact attribute if this insn
2867 has a short variant, which may be used depending on code size and
2868 alignment considerations. */
2869 if (current_insn_predicate
)
2870 arc_ccfsm_current
.cc
2871 = get_arc_condition_code (current_insn_predicate
);
2872 if (ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current
))
2874 /* Is this insn in a delay slot sequence? */
2875 if (!final_sequence
|| XVECLEN (final_sequence
, 0) < 2
2876 || current_insn_predicate
2877 || CALL_P (final_sequence
->insn (0))
2878 || simplejump_p (final_sequence
->insn (0)))
2880 /* This insn isn't in a delay slot sequence, or conditionalized
2881 independently of its position in a delay slot. */
2882 fprintf (file
, "%s%s",
2883 code
== '?' ? "." : "",
2884 arc_condition_codes
[arc_ccfsm_current
.cc
]);
2885 /* If this is a jump, there are still short variants. However,
2886 only beq_s / bne_s have the same offset range as b_s,
2887 and the only short conditional returns are jeq_s and jne_s. */
2889 && (arc_ccfsm_current
.cc
== ARC_CC_EQ
2890 || arc_ccfsm_current
.cc
== ARC_CC_NE
2891 || 0 /* FIXME: check if branch in 7 bit range. */))
2892 output_short_suffix (file
);
2894 else if (code
== '!') /* Jump with delay slot. */
2895 fputs (arc_condition_codes
[arc_ccfsm_current
.cc
], file
);
2896 else /* An Instruction in a delay slot of a jump or call. */
2898 rtx jump
= XVECEXP (final_sequence
, 0, 0);
2899 rtx insn
= XVECEXP (final_sequence
, 0, 1);
2901 /* If the insn is annulled and is from the target path, we need
2902 to inverse the condition test. */
2903 if (JUMP_P (jump
) && INSN_ANNULLED_BRANCH_P (jump
))
2905 if (INSN_FROM_TARGET_P (insn
))
2906 fprintf (file
, "%s%s",
2907 code
== '?' ? "." : "",
2908 arc_condition_codes
[ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current
.cc
)]);
2910 fprintf (file
, "%s%s",
2911 code
== '?' ? "." : "",
2912 arc_condition_codes
[arc_ccfsm_current
.cc
]);
2913 if (arc_ccfsm_current
.state
== 5)
2914 arc_ccfsm_current
.state
= 0;
2917 /* This insn is executed for either path, so don't
2918 conditionalize it at all. */
2919 output_short_suffix (file
);
2924 output_short_suffix (file
);
2927 /* FIXME: fold constant inside unary operator, re-recognize, and emit. */
2930 fputs (arc_condition_codes
[get_arc_condition_code (x
)], file
);
2933 fputs (arc_condition_codes
[ARC_INVERSE_CONDITION_CODE
2934 (get_arc_condition_code (x
))],
2938 /* Write second word of DImode or DFmode reference,
2939 register or memory. */
2940 if (GET_CODE (x
) == REG
)
2941 fputs (reg_names
[REGNO (x
)+1], file
);
2942 else if (GET_CODE (x
) == MEM
)
2946 /* Handle possible auto-increment. For PRE_INC / PRE_DEC /
2947 PRE_MODIFY, we will have handled the first word already;
2948 For POST_INC / POST_DEC / POST_MODIFY, the access to the
2949 first word will be done later. In either case, the access
2950 to the first word will do the modify, and we only have
2951 to add an offset of four here. */
2952 if (GET_CODE (XEXP (x
, 0)) == PRE_INC
2953 || GET_CODE (XEXP (x
, 0)) == PRE_DEC
2954 || GET_CODE (XEXP (x
, 0)) == PRE_MODIFY
2955 || GET_CODE (XEXP (x
, 0)) == POST_INC
2956 || GET_CODE (XEXP (x
, 0)) == POST_DEC
2957 || GET_CODE (XEXP (x
, 0)) == POST_MODIFY
)
2958 output_address (plus_constant (Pmode
, XEXP (XEXP (x
, 0), 0), 4));
2959 else if (output_scaled
)
2961 rtx addr
= XEXP (x
, 0);
2962 int size
= GET_MODE_SIZE (GET_MODE (x
));
2964 output_address (plus_constant (Pmode
, XEXP (addr
, 0),
2965 ((INTVAL (XEXP (addr
, 1)) + 4)
2966 >> (size
== 2 ? 1 : 2))));
2970 output_address (plus_constant (Pmode
, XEXP (x
, 0), 4));
2974 output_operand_lossage ("invalid operand to %%R code");
2977 /* FIXME: remove %S option. */
2979 case 'B' /* Branch or other LIMM ref - must not use sda references. */ :
2982 output_addr_const (file
, x
);
2988 if (GET_CODE (x
) == REG
)
2990 /* L = least significant word, H = most significant word. */
2991 if ((WORDS_BIG_ENDIAN
!= 0) ^ (code
== 'L'))
2992 fputs (reg_names
[REGNO (x
)], file
);
2994 fputs (reg_names
[REGNO (x
)+1], file
);
2996 else if (GET_CODE (x
) == CONST_INT
2997 || GET_CODE (x
) == CONST_DOUBLE
)
3001 split_double (x
, &first
, &second
);
3003 if((WORDS_BIG_ENDIAN
) == 0)
3004 fprintf (file
, "0x%08" PRIx64
,
3005 code
== 'L' ? INTVAL (first
) : INTVAL (second
));
3007 fprintf (file
, "0x%08" PRIx64
,
3008 code
== 'L' ? INTVAL (second
) : INTVAL (first
));
3013 output_operand_lossage ("invalid operand to %%H/%%L code");
3019 gcc_assert (GET_CODE (x
) == CONST_DOUBLE
3020 && GET_MODE_CLASS (GET_MODE (x
)) == MODE_FLOAT
);
3022 real_to_decimal (str
, CONST_DOUBLE_REAL_VALUE (x
), sizeof (str
), 0, 1);
3023 fprintf (file
, "%s", str
);
3027 /* Output a load/store with update indicator if appropriate. */
3028 if (GET_CODE (x
) == MEM
)
3030 rtx addr
= XEXP (x
, 0);
3031 switch (GET_CODE (addr
))
3033 case PRE_INC
: case PRE_DEC
: case PRE_MODIFY
:
3034 fputs (".a", file
); break;
3035 case POST_INC
: case POST_DEC
: case POST_MODIFY
:
3036 fputs (".ab", file
); break;
3038 /* Are we using a scaled index? */
3039 if (GET_CODE (XEXP (addr
, 0)) == MULT
)
3040 fputs (".as", file
);
3041 /* Can we use a scaled offset? */
3042 else if (CONST_INT_P (XEXP (addr
, 1))
3043 && GET_MODE_SIZE (GET_MODE (x
)) > 1
3044 && (!(INTVAL (XEXP (addr
, 1))
3045 & (GET_MODE_SIZE (GET_MODE (x
)) - 1) & 3))
3046 /* Does it make a difference? */
3047 && !SMALL_INT_RANGE(INTVAL (XEXP (addr
, 1)),
3048 GET_MODE_SIZE (GET_MODE (x
)) - 2, 0))
3050 fputs (".as", file
);
3057 gcc_assert (CONSTANT_P (addr
)); break;
3061 output_operand_lossage ("invalid operand to %%U code");
3064 /* Output cache bypass indicator for a load/store insn. Volatile memory
3065 refs are defined to use the cache bypass mechanism. */
3066 if (GET_CODE (x
) == MEM
)
3068 if (MEM_VOLATILE_P (x
) && !TARGET_VOLATILE_CACHE_SET
)
3069 fputs (".di", file
);
3072 output_operand_lossage ("invalid operand to %%V code");
3077 /* Do nothing special. */
3080 fputs (reg_names
[REGNO (x
)]+1, file
);
3083 /* This punctuation character is needed because label references are
3084 printed in the output template using %l. This is a front end
3085 character, and when we want to emit a '@' before it, we have to use
3091 /* Output an operator. */
3092 switch (GET_CODE (x
))
3094 case PLUS
: fputs ("add", file
); return;
3095 case SS_PLUS
: fputs ("adds", file
); return;
3096 case AND
: fputs ("and", file
); return;
3097 case IOR
: fputs ("or", file
); return;
3098 case XOR
: fputs ("xor", file
); return;
3099 case MINUS
: fputs ("sub", file
); return;
3100 case SS_MINUS
: fputs ("subs", file
); return;
3101 case ASHIFT
: fputs ("asl", file
); return;
3102 case ASHIFTRT
: fputs ("asr", file
); return;
3103 case LSHIFTRT
: fputs ("lsr", file
); return;
3104 case ROTATERT
: fputs ("ror", file
); return;
3105 case MULT
: fputs ("mpy", file
); return;
3106 case ABS
: fputs ("abs", file
); return; /* Unconditional. */
3107 case NEG
: fputs ("neg", file
); return;
3108 case SS_NEG
: fputs ("negs", file
); return;
3109 case NOT
: fputs ("not", file
); return; /* Unconditional. */
3111 fputs ("ext", file
); /* bmsk allows predication. */
3113 case SIGN_EXTEND
: /* Unconditional. */
3114 fputs ("sex", file
);
3116 switch (GET_MODE (XEXP (x
, 0)))
3118 case QImode
: fputs ("b", file
); return;
3119 case HImode
: fputs ("w", file
); return;
3124 if (GET_MODE (x
) != HImode
)
3126 fputs ("sat16", file
);
3129 output_operand_lossage ("invalid operand to %%O code"); return;
3131 if (GET_CODE (x
) == SYMBOL_REF
)
3133 assemble_name (file
, XSTR (x
, 0));
3138 if (TARGET_ANNOTATE_ALIGN
&& cfun
->machine
->size_reason
)
3139 fprintf (file
, "; unalign: %d", cfun
->machine
->unalign
);
3143 output_operand_lossage ("invalid operand output code");
3146 switch (GET_CODE (x
))
3149 fputs (reg_names
[REGNO (x
)], file
);
3153 rtx addr
= XEXP (x
, 0);
3154 int size
= GET_MODE_SIZE (GET_MODE (x
));
3158 switch (GET_CODE (addr
))
3160 case PRE_INC
: case POST_INC
:
3161 output_address (plus_constant (Pmode
, XEXP (addr
, 0), size
)); break;
3162 case PRE_DEC
: case POST_DEC
:
3163 output_address (plus_constant (Pmode
, XEXP (addr
, 0), -size
));
3165 case PRE_MODIFY
: case POST_MODIFY
:
3166 output_address (XEXP (addr
, 1)); break;
3170 output_address (plus_constant (Pmode
, XEXP (addr
, 0),
3171 (INTVAL (XEXP (addr
, 1))
3172 >> (size
== 2 ? 1 : 2))));
3176 output_address (addr
);
3179 if (flag_pic
&& CONSTANT_ADDRESS_P (addr
))
3180 arc_output_pic_addr_const (file
, addr
, code
);
3182 output_address (addr
);
3189 /* We handle SFmode constants here as output_addr_const doesn't. */
3190 if (GET_MODE (x
) == SFmode
)
3195 REAL_VALUE_FROM_CONST_DOUBLE (d
, x
);
3196 REAL_VALUE_TO_TARGET_SINGLE (d
, l
);
3197 fprintf (file
, "0x%08lx", l
);
3200 /* Fall through. Let output_addr_const deal with it. */
3203 arc_output_pic_addr_const (file
, x
, code
);
3206 /* FIXME: Dirty way to handle @var@sda+const. Shd be handled
3207 with asm_output_symbol_ref */
3208 if (GET_CODE (x
) == CONST
&& GET_CODE (XEXP (x
, 0)) == PLUS
)
3211 output_addr_const (file
, XEXP (x
, 0));
3212 if (GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
&& SYMBOL_REF_SMALL_P (XEXP (x
, 0)))
3213 fprintf (file
, "@sda");
3215 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
3216 || INTVAL (XEXP (x
, 1)) >= 0)
3217 fprintf (file
, "+");
3218 output_addr_const (file
, XEXP (x
, 1));
3221 output_addr_const (file
, x
);
3223 if (GET_CODE (x
) == SYMBOL_REF
&& SYMBOL_REF_SMALL_P (x
))
3224 fprintf (file
, "@sda");
3229 /* Print a memory address as an operand to reference that memory location. */
3232 arc_print_operand_address (FILE *file
, rtx addr
)
3234 register rtx base
, index
= 0;
3236 switch (GET_CODE (addr
))
3239 fputs (reg_names
[REGNO (addr
)], file
);
3242 output_addr_const (file
, addr
);
3243 if (SYMBOL_REF_SMALL_P (addr
))
3244 fprintf (file
, "@sda");
3247 if (GET_CODE (XEXP (addr
, 0)) == MULT
)
3248 index
= XEXP (XEXP (addr
, 0), 0), base
= XEXP (addr
, 1);
3249 else if (CONST_INT_P (XEXP (addr
, 0)))
3250 index
= XEXP (addr
, 0), base
= XEXP (addr
, 1);
3252 base
= XEXP (addr
, 0), index
= XEXP (addr
, 1);
3254 gcc_assert (OBJECT_P (base
));
3255 arc_print_operand_address (file
, base
);
3256 if (CONSTANT_P (base
) && CONST_INT_P (index
))
3260 gcc_assert (OBJECT_P (index
));
3261 arc_print_operand_address (file
, index
);
3265 rtx c
= XEXP (addr
, 0);
3267 gcc_assert (GET_CODE (XEXP (c
, 0)) == SYMBOL_REF
);
3268 gcc_assert (GET_CODE (XEXP (c
, 1)) == CONST_INT
);
3270 output_address(XEXP(addr
,0));
3276 /* We shouldn't get here as we've lost the mode of the memory object
3277 (which says how much to inc/dec by. */
3282 arc_output_pic_addr_const (file
, addr
, 0);
3284 output_addr_const (file
, addr
);
3289 /* Called via walk_stores. DATA points to a hash table we can use to
3290 establish a unique SYMBOL_REF for each counter, which corresponds to
3291 a caller-callee pair.
3292 X is a store which we want to examine for an UNSPEC_PROF, which
3293 would be an address loaded into a register, or directly used in a MEM.
3294 If we found an UNSPEC_PROF, if we encounter a new counter the first time,
3295 write out a description and a data allocation for a 32 bit counter.
3296 Also, fill in the appropriate symbol_ref into each UNSPEC_PROF instance. */
3299 write_profile_sections (rtx dest ATTRIBUTE_UNUSED
, rtx x
, void *data
)
3302 htab_t htab
= (htab_t
) data
;
3305 if (GET_CODE (x
) != SET
)
3307 srcp
= &SET_SRC (x
);
3309 srcp
= &XEXP (*srcp
, 0);
3310 else if (MEM_P (SET_DEST (x
)))
3311 srcp
= &XEXP (SET_DEST (x
), 0);
3313 if (GET_CODE (src
) != CONST
)
3315 src
= XEXP (src
, 0);
3316 if (GET_CODE (src
) != UNSPEC
|| XINT (src
, 1) != UNSPEC_PROF
)
3319 gcc_assert (XVECLEN (src
, 0) == 3);
3320 if (!htab_elements (htab
))
3322 output_asm_insn (".section .__arc_profile_desc, \"a\"\n"
3324 &XVECEXP (src
, 0, 0));
3326 slot
= (rtx
*) htab_find_slot (htab
, src
, INSERT
);
3327 if (*slot
== HTAB_EMPTY_ENTRY
)
3329 static int count_nr
;
3334 sprintf (buf
, "__prof_count%d", count_nr
++);
3335 count
= gen_rtx_SYMBOL_REF (Pmode
, xstrdup (buf
));
3336 XVECEXP (src
, 0, 2) = count
;
3337 output_asm_insn (".section\t.__arc_profile_desc, \"a\"\n"
3339 "\t.section\t.__arc_profile_counters, \"aw\"\n"
3340 "\t.type\t%o2, @object\n"
3343 &XVECEXP (src
, 0, 0));
3347 *srcp
= XVECEXP (*slot
, 0, 2);
3350 /* Hash function for UNSPEC_PROF htab. Use both the caller's name and
3351 the callee's name (if known). */
3354 unspec_prof_hash (const void *x
)
3356 const_rtx u
= (const_rtx
) x
;
3357 const_rtx s1
= XVECEXP (u
, 0, 1);
3359 return (htab_hash_string (XSTR (XVECEXP (u
, 0, 0), 0))
3360 ^ (s1
->code
== SYMBOL_REF
? htab_hash_string (XSTR (s1
, 0)) : 0));
3363 /* Equality function for UNSPEC_PROF htab. Two pieces of UNSPEC_PROF rtl
3364 shall refer to the same counter if both caller name and callee rtl
3368 unspec_prof_htab_eq (const void *x
, const void *y
)
3370 const_rtx u0
= (const_rtx
) x
;
3371 const_rtx u1
= (const_rtx
) y
;
3372 const_rtx s01
= XVECEXP (u0
, 0, 1);
3373 const_rtx s11
= XVECEXP (u1
, 0, 1);
3375 return (!strcmp (XSTR (XVECEXP (u0
, 0, 0), 0),
3376 XSTR (XVECEXP (u1
, 0, 0), 0))
3377 && rtx_equal_p (s01
, s11
));
3380 /* Conditional execution support.
3382 This is based on the ARM port but for now is much simpler.
3384 A finite state machine takes care of noticing whether or not instructions
3385 can be conditionally executed, and thus decrease execution time and code
3386 size by deleting branch instructions. The fsm is controlled by
3387 arc_ccfsm_advance (called by arc_final_prescan_insn), and controls the
3388 actions of PRINT_OPERAND. The patterns in the .md file for the branch
3389 insns also have a hand in this. */
3390 /* The way we leave dealing with non-anulled or annull-false delay slot
3391 insns to the consumer is awkward. */
3393 /* The state of the fsm controlling condition codes are:
3394 0: normal, do nothing special
3395 1: don't output this insn
3396 2: don't output this insn
3397 3: make insns conditional
3398 4: make insns conditional
3399 5: make insn conditional (only for outputting anulled delay slot insns)
3401 special value for cfun->machine->uid_ccfsm_state:
3402 6: return with but one insn before it since function start / call
3404 State transitions (state->state by whom, under what condition):
3405 0 -> 1 arc_ccfsm_advance, if insn is a conditional branch skipping over
3407 0 -> 2 arc_ccfsm_advance, if insn is a conditional branch followed
3408 by zero or more non-jump insns and an unconditional branch with
3409 the same target label as the condbranch.
3410 1 -> 3 branch patterns, after having not output the conditional branch
3411 2 -> 4 branch patterns, after having not output the conditional branch
3412 0 -> 5 branch patterns, for anulled delay slot insn.
3413 3 -> 0 ASM_OUTPUT_INTERNAL_LABEL, if the `target' label is reached
3414 (the target label has CODE_LABEL_NUMBER equal to
3415 arc_ccfsm_target_label).
3416 4 -> 0 arc_ccfsm_advance, if `target' unconditional branch is reached
3417 3 -> 1 arc_ccfsm_advance, finding an 'else' jump skipping over some insns.
3418 5 -> 0 when outputting the delay slot insn
3420 If the jump clobbers the conditions then we use states 2 and 4.
3422 A similar thing can be done with conditional return insns.
3424 We also handle separating branches from sets of the condition code.
3425 This is done here because knowledge of the ccfsm state is required,
3426 we may not be outputting the branch. */
3428 /* arc_final_prescan_insn calls arc_ccfsm_advance to adjust arc_ccfsm_current,
3429 before letting final output INSN. */
3432 arc_ccfsm_advance (rtx_insn
*insn
, struct arc_ccfsm
*state
)
3434 /* BODY will hold the body of INSN. */
3437 /* This will be 1 if trying to repeat the trick (ie: do the `else' part of
3438 an if/then/else), and things need to be reversed. */
3441 /* If we start with a return insn, we only succeed if we find another one. */
3442 int seeking_return
= 0;
3444 /* START_INSN will hold the insn from where we start looking. This is the
3445 first insn after the following code_label if REVERSE is true. */
3446 rtx_insn
*start_insn
= insn
;
3448 /* Type of the jump_insn. Brcc insns don't affect ccfsm changes,
3449 since they don't rely on a cmp preceding the. */
3450 enum attr_type jump_insn_type
;
3452 /* Allow -mdebug-ccfsm to turn this off so we can see how well it does.
3453 We can't do this in macro FINAL_PRESCAN_INSN because its called from
3454 final_scan_insn which has `optimize' as a local. */
3455 if (optimize
< 2 || TARGET_NO_COND_EXEC
)
3458 /* Ignore notes and labels. */
3461 body
= PATTERN (insn
);
3462 /* If in state 4, check if the target branch is reached, in order to
3463 change back to state 0. */
3464 if (state
->state
== 4)
3466 if (insn
== state
->target_insn
)
3468 state
->target_insn
= NULL
;
3474 /* If in state 3, it is possible to repeat the trick, if this insn is an
3475 unconditional branch to a label, and immediately following this branch
3476 is the previous target label which is only used once, and the label this
3477 branch jumps to is not too far off. Or in other words "we've done the
3478 `then' part, see if we can do the `else' part." */
3479 if (state
->state
== 3)
3481 if (simplejump_p (insn
))
3483 start_insn
= next_nonnote_insn (start_insn
);
3484 if (GET_CODE (start_insn
) == BARRIER
)
3486 /* ??? Isn't this always a barrier? */
3487 start_insn
= next_nonnote_insn (start_insn
);
3489 if (GET_CODE (start_insn
) == CODE_LABEL
3490 && CODE_LABEL_NUMBER (start_insn
) == state
->target_label
3491 && LABEL_NUSES (start_insn
) == 1)
3496 else if (GET_CODE (body
) == SIMPLE_RETURN
)
3498 start_insn
= next_nonnote_insn (start_insn
);
3499 if (GET_CODE (start_insn
) == BARRIER
)
3500 start_insn
= next_nonnote_insn (start_insn
);
3501 if (GET_CODE (start_insn
) == CODE_LABEL
3502 && CODE_LABEL_NUMBER (start_insn
) == state
->target_label
3503 && LABEL_NUSES (start_insn
) == 1)
3515 if (GET_CODE (insn
) != JUMP_INSN
3516 || GET_CODE (PATTERN (insn
)) == ADDR_VEC
3517 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
3520 /* We can't predicate BRCC or loop ends.
3521 Also, when generating PIC code, and considering a medium range call,
3522 we can't predicate the call. */
3523 jump_insn_type
= get_attr_type (insn
);
3524 if (jump_insn_type
== TYPE_BRCC
3525 || jump_insn_type
== TYPE_BRCC_NO_DELAY_SLOT
3526 || jump_insn_type
== TYPE_LOOP_END
3527 || (jump_insn_type
== TYPE_CALL
&& !get_attr_predicable (insn
)))
3530 /* This jump might be paralleled with a clobber of the condition codes,
3531 the jump should always come first. */
3532 if (GET_CODE (body
) == PARALLEL
&& XVECLEN (body
, 0) > 0)
3533 body
= XVECEXP (body
, 0, 0);
3536 || (GET_CODE (body
) == SET
&& GET_CODE (SET_DEST (body
)) == PC
3537 && GET_CODE (SET_SRC (body
)) == IF_THEN_ELSE
))
3539 int insns_skipped
= 0, fail
= FALSE
, succeed
= FALSE
;
3540 /* Flag which part of the IF_THEN_ELSE is the LABEL_REF. */
3541 int then_not_else
= TRUE
;
3542 /* Nonzero if next insn must be the target label. */
3543 int next_must_be_target_label_p
;
3544 rtx_insn
*this_insn
= start_insn
;
3547 /* Register the insn jumped to. */
3550 if (!seeking_return
)
3551 label
= XEXP (SET_SRC (body
), 0);
3553 else if (GET_CODE (XEXP (SET_SRC (body
), 1)) == LABEL_REF
)
3554 label
= XEXP (XEXP (SET_SRC (body
), 1), 0);
3555 else if (GET_CODE (XEXP (SET_SRC (body
), 2)) == LABEL_REF
)
3557 label
= XEXP (XEXP (SET_SRC (body
), 2), 0);
3558 then_not_else
= FALSE
;
3560 else if (GET_CODE (XEXP (SET_SRC (body
), 1)) == SIMPLE_RETURN
)
3562 else if (GET_CODE (XEXP (SET_SRC (body
), 2)) == SIMPLE_RETURN
)
3565 then_not_else
= FALSE
;
3570 /* If this is a non-annulled branch with a delay slot, there is
3571 no need to conditionalize the delay slot. */
3572 if (NEXT_INSN (PREV_INSN (insn
)) != insn
3573 && state
->state
== 0 && !INSN_ANNULLED_BRANCH_P (insn
))
3575 this_insn
= NEXT_INSN (this_insn
);
3576 gcc_assert (NEXT_INSN (NEXT_INSN (PREV_INSN (start_insn
)))
3577 == NEXT_INSN (this_insn
));
3579 /* See how many insns this branch skips, and what kind of insns. If all
3580 insns are okay, and the label or unconditional branch to the same
3581 label is not too far away, succeed. */
3582 for (insns_skipped
= 0, next_must_be_target_label_p
= FALSE
;
3583 !fail
&& !succeed
&& insns_skipped
< MAX_INSNS_SKIPPED
;
3588 this_insn
= next_nonnote_insn (this_insn
);
3592 if (next_must_be_target_label_p
)
3594 if (GET_CODE (this_insn
) == BARRIER
)
3596 if (GET_CODE (this_insn
) == CODE_LABEL
3597 && this_insn
== label
)
3607 scanbody
= PATTERN (this_insn
);
3609 switch (GET_CODE (this_insn
))
3612 /* Succeed if it is the target label, otherwise fail since
3613 control falls in from somewhere else. */
3614 if (this_insn
== label
)
3624 /* Succeed if the following insn is the target label.
3626 If return insns are used then the last insn in a function
3627 will be a barrier. */
3628 next_must_be_target_label_p
= TRUE
;
3632 /* Can handle a call insn if there are no insns after it.
3633 IE: The next "insn" is the target label. We don't have to
3634 worry about delay slots as such insns are SEQUENCE's inside
3635 INSN's. ??? It is possible to handle such insns though. */
3636 if (get_attr_cond (this_insn
) == COND_CANUSE
)
3637 next_must_be_target_label_p
= TRUE
;
3643 /* If this is an unconditional branch to the same label, succeed.
3644 If it is to another label, do nothing. If it is conditional,
3646 /* ??? Probably, the test for the SET and the PC are
3649 if (GET_CODE (scanbody
) == SET
3650 && GET_CODE (SET_DEST (scanbody
)) == PC
)
3652 if (GET_CODE (SET_SRC (scanbody
)) == LABEL_REF
3653 && XEXP (SET_SRC (scanbody
), 0) == label
&& !reverse
)
3658 else if (GET_CODE (SET_SRC (scanbody
)) == IF_THEN_ELSE
)
3660 else if (get_attr_cond (this_insn
) != COND_CANUSE
)
3663 else if (GET_CODE (scanbody
) == SIMPLE_RETURN
3669 else if (GET_CODE (scanbody
) == PARALLEL
)
3671 if (get_attr_cond (this_insn
) != COND_CANUSE
)
3677 /* We can only do this with insns that can use the condition
3678 codes (and don't set them). */
3679 if (GET_CODE (scanbody
) == SET
3680 || GET_CODE (scanbody
) == PARALLEL
)
3682 if (get_attr_cond (this_insn
) != COND_CANUSE
)
3685 /* We can't handle other insns like sequences. */
3697 if ((!seeking_return
) && (state
->state
== 1 || reverse
))
3698 state
->target_label
= CODE_LABEL_NUMBER (label
);
3699 else if (seeking_return
|| state
->state
== 2)
3701 while (this_insn
&& GET_CODE (PATTERN (this_insn
)) == USE
)
3703 this_insn
= next_nonnote_insn (this_insn
);
3705 gcc_assert (!this_insn
||
3706 (GET_CODE (this_insn
) != BARRIER
3707 && GET_CODE (this_insn
) != CODE_LABEL
));
3711 /* Oh dear! we ran off the end, give up. */
3712 extract_insn_cached (insn
);
3714 state
->target_insn
= NULL
;
3717 state
->target_insn
= this_insn
;
3722 /* If REVERSE is true, ARM_CURRENT_CC needs to be inverted from
3726 state
->cond
= XEXP (SET_SRC (body
), 0);
3727 state
->cc
= get_arc_condition_code (XEXP (SET_SRC (body
), 0));
3730 if (reverse
|| then_not_else
)
3731 state
->cc
= ARC_INVERSE_CONDITION_CODE (state
->cc
);
3734 /* Restore recog_operand. Getting the attributes of other insns can
3735 destroy this array, but final.c assumes that it remains intact
3736 across this call; since the insn has been recognized already we
3737 call insn_extract direct. */
3738 extract_insn_cached (insn
);
3742 /* Record that we are currently outputting label NUM with prefix PREFIX.
3743 It it's the label we're looking for, reset the ccfsm machinery.
3745 Called from ASM_OUTPUT_INTERNAL_LABEL. */
3748 arc_ccfsm_at_label (const char *prefix
, int num
, struct arc_ccfsm
*state
)
3750 if (state
->state
== 3 && state
->target_label
== num
3751 && !strcmp (prefix
, "L"))
3754 state
->target_insn
= NULL
;
3758 /* We are considering a conditional branch with the condition COND.
3759 Check if we want to conditionalize a delay slot insn, and if so modify
3760 the ccfsm state accordingly.
3761 REVERSE says branch will branch when the condition is false. */
3763 arc_ccfsm_record_condition (rtx cond
, bool reverse
, rtx_insn
*jump
,
3764 struct arc_ccfsm
*state
)
3766 rtx_insn
*seq_insn
= NEXT_INSN (PREV_INSN (jump
));
3768 state
= &arc_ccfsm_current
;
3770 gcc_assert (state
->state
== 0);
3771 if (seq_insn
!= jump
)
3773 rtx insn
= XVECEXP (PATTERN (seq_insn
), 0, 1);
3775 if (!as_a
<rtx_insn
*> (insn
)->deleted ()
3776 && INSN_ANNULLED_BRANCH_P (jump
)
3777 && (TARGET_AT_DBR_CONDEXEC
|| INSN_FROM_TARGET_P (insn
)))
3780 state
->cc
= get_arc_condition_code (cond
);
3782 arc_ccfsm_current
.cc
3783 = ARC_INVERSE_CONDITION_CODE (state
->cc
);
3784 rtx pat
= PATTERN (insn
);
3785 if (GET_CODE (pat
) == COND_EXEC
)
3786 gcc_assert ((INSN_FROM_TARGET_P (insn
)
3787 ? ARC_INVERSE_CONDITION_CODE (state
->cc
) : state
->cc
)
3788 == get_arc_condition_code (XEXP (pat
, 0)));
3795 /* Update *STATE as we would when we emit INSN. */
3798 arc_ccfsm_post_advance (rtx_insn
*insn
, struct arc_ccfsm
*state
)
3800 enum attr_type type
;
3803 arc_ccfsm_at_label ("L", CODE_LABEL_NUMBER (insn
), state
);
3804 else if (JUMP_P (insn
)
3805 && GET_CODE (PATTERN (insn
)) != ADDR_VEC
3806 && GET_CODE (PATTERN (insn
)) != ADDR_DIFF_VEC
3807 && ((type
= get_attr_type (insn
)) == TYPE_BRANCH
3808 || (type
== TYPE_UNCOND_BRANCH
3809 /* ??? Maybe should also handle TYPE_RETURN here,
3810 but we don't have a testcase for that. */
3811 && ARC_CCFSM_BRANCH_DELETED_P (state
))))
3813 if (ARC_CCFSM_BRANCH_DELETED_P (state
))
3814 ARC_CCFSM_RECORD_BRANCH_DELETED (state
);
3817 rtx src
= SET_SRC (PATTERN (insn
));
3818 arc_ccfsm_record_condition (XEXP (src
, 0), XEXP (src
, 1) == pc_rtx
,
3822 else if (arc_ccfsm_current
.state
== 5)
3823 arc_ccfsm_current
.state
= 0;
3826 /* Return true if the current insn, which is a conditional branch, is to be
3830 arc_ccfsm_branch_deleted_p (void)
3832 return ARC_CCFSM_BRANCH_DELETED_P (&arc_ccfsm_current
);
3835 /* Record a branch isn't output because subsequent insns can be
3839 arc_ccfsm_record_branch_deleted (void)
3841 ARC_CCFSM_RECORD_BRANCH_DELETED (&arc_ccfsm_current
);
3844 /* During insn output, indicate if the current insn is predicated. */
3847 arc_ccfsm_cond_exec_p (void)
3849 return (cfun
->machine
->prescan_initialized
3850 && ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current
));
3853 /* Like next_active_insn, but return NULL if we find an ADDR_(DIFF_)VEC,
3854 and look inside SEQUENCEs. */
3857 arc_next_active_insn (rtx_insn
*insn
, struct arc_ccfsm
*statep
)
3864 arc_ccfsm_post_advance (insn
, statep
);
3865 insn
= NEXT_INSN (insn
);
3866 if (!insn
|| BARRIER_P (insn
))
3869 arc_ccfsm_advance (insn
, statep
);
3871 while (NOTE_P (insn
)
3872 || (cfun
->machine
->arc_reorg_started
3873 && LABEL_P (insn
) && !label_to_alignment (insn
))
3874 || (NONJUMP_INSN_P (insn
)
3875 && (GET_CODE (PATTERN (insn
)) == USE
3876 || GET_CODE (PATTERN (insn
)) == CLOBBER
)));
3877 if (!LABEL_P (insn
))
3879 gcc_assert (INSN_P (insn
));
3880 pat
= PATTERN (insn
);
3881 if (GET_CODE (pat
) == ADDR_VEC
|| GET_CODE (pat
) == ADDR_DIFF_VEC
)
3883 if (GET_CODE (pat
) == SEQUENCE
)
3884 return as_a
<rtx_insn
*> (XVECEXP (pat
, 0, 0));
3889 /* When deciding if an insn should be output short, we want to know something
3890 about the following insns:
3891 - if another insn follows which we know we can output as a short insn
3892 before an alignment-sensitive point, we can output this insn short:
3893 the decision about the eventual alignment can be postponed.
3894 - if a to-be-aligned label comes next, we should output this insn such
3895 as to get / preserve 4-byte alignment.
3896 - if a likely branch without delay slot insn, or a call with an immediately
3897 following short insn comes next, we should out output this insn such as to
3898 get / preserve 2 mod 4 unalignment.
3899 - do the same for a not completely unlikely branch with a short insn
3900 following before any other branch / label.
3901 - in order to decide if we are actually looking at a branch, we need to
3902 call arc_ccfsm_advance.
3903 - in order to decide if we are looking at a short insn, we should know
3904 if it is conditionalized. To a first order of approximation this is
3905 the case if the state from arc_ccfsm_advance from before this insn
3906 indicates the insn is conditionalized. However, a further refinement
3907 could be to not conditionalize an insn if the destination register(s)
3908 is/are dead in the non-executed case. */
3909 /* Return non-zero if INSN should be output as a short insn. UNALIGN is
3910 zero if the current insn is aligned to a 4-byte-boundary, two otherwise.
3911 If CHECK_ATTR is greater than 0, check the iscompact attribute first. */
3914 arc_verify_short (rtx_insn
*insn
, int, int check_attr
)
3916 enum attr_iscompact iscompact
;
3917 struct machine_function
*machine
;
3921 iscompact
= get_attr_iscompact (insn
);
3922 if (iscompact
== ISCOMPACT_FALSE
)
3925 machine
= cfun
->machine
;
3927 if (machine
->force_short_suffix
>= 0)
3928 return machine
->force_short_suffix
;
3930 return (get_attr_length (insn
) & 2) != 0;
3933 /* When outputting an instruction (alternative) that can potentially be short,
3934 output the short suffix if the insn is in fact short, and update
3935 cfun->machine->unalign accordingly. */
3938 output_short_suffix (FILE *file
)
3940 rtx_insn
*insn
= current_output_insn
;
3942 if (arc_verify_short (insn
, cfun
->machine
->unalign
, 1))
3944 fprintf (file
, "_s");
3945 cfun
->machine
->unalign
^= 2;
3947 /* Restore recog_operand. */
3948 extract_insn_cached (insn
);
3951 /* Implement FINAL_PRESCAN_INSN. */
3954 arc_final_prescan_insn (rtx_insn
*insn
, rtx
*opvec ATTRIBUTE_UNUSED
,
3955 int noperands ATTRIBUTE_UNUSED
)
3957 if (TARGET_DUMPISIZE
)
3958 fprintf (asm_out_file
, "\n; at %04x\n", INSN_ADDRESSES (INSN_UID (insn
)));
3960 /* Output a nop if necessary to prevent a hazard.
3961 Don't do this for delay slots: inserting a nop would
3962 alter semantics, and the only time we would find a hazard is for a
3963 call function result - and in that case, the hazard is spurious to
3965 if (PREV_INSN (insn
)
3966 && PREV_INSN (NEXT_INSN (insn
)) == insn
3967 && arc_hazard (prev_real_insn (insn
), insn
))
3969 current_output_insn
=
3970 emit_insn_before (gen_nop (), NEXT_INSN (PREV_INSN (insn
)));
3971 final_scan_insn (current_output_insn
, asm_out_file
, optimize
, 1, NULL
);
3972 current_output_insn
= insn
;
3974 /* Restore extraction data which might have been clobbered by arc_hazard. */
3975 extract_constrain_insn_cached (insn
);
3977 if (!cfun
->machine
->prescan_initialized
)
3979 /* Clear lingering state from branch shortening. */
3980 memset (&arc_ccfsm_current
, 0, sizeof arc_ccfsm_current
);
3981 cfun
->machine
->prescan_initialized
= 1;
3983 arc_ccfsm_advance (insn
, &arc_ccfsm_current
);
3985 cfun
->machine
->size_reason
= 0;
3988 /* Given FROM and TO register numbers, say whether this elimination is allowed.
3989 Frame pointer elimination is automatically handled.
3991 All eliminations are permissible. If we need a frame
3992 pointer, we must eliminate ARG_POINTER_REGNUM into
3993 FRAME_POINTER_REGNUM and not into STACK_POINTER_REGNUM. */
3996 arc_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to
)
3998 return to
== FRAME_POINTER_REGNUM
|| !arc_frame_pointer_required ();
4001 /* Define the offset between two registers, one to be eliminated, and
4002 the other its replacement, at the start of a routine. */
4005 arc_initial_elimination_offset (int from
, int to
)
4007 if (! cfun
->machine
->frame_info
.initialized
)
4008 arc_compute_frame_size (get_frame_size ());
4010 if (from
== ARG_POINTER_REGNUM
&& to
== FRAME_POINTER_REGNUM
)
4012 return (cfun
->machine
->frame_info
.extra_size
4013 + cfun
->machine
->frame_info
.reg_size
);
4016 if (from
== ARG_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
4018 return (cfun
->machine
->frame_info
.total_size
4019 - cfun
->machine
->frame_info
.pretend_size
);
4022 if ((from
== FRAME_POINTER_REGNUM
) && (to
== STACK_POINTER_REGNUM
))
4024 return (cfun
->machine
->frame_info
.total_size
4025 - (cfun
->machine
->frame_info
.pretend_size
4026 + cfun
->machine
->frame_info
.extra_size
4027 + cfun
->machine
->frame_info
.reg_size
));
4034 arc_frame_pointer_required (void)
4036 return cfun
->calls_alloca
;
4040 /* Return the destination address of a branch. */
4043 branch_dest (rtx branch
)
4045 rtx pat
= PATTERN (branch
);
4046 rtx dest
= (GET_CODE (pat
) == PARALLEL
4047 ? SET_SRC (XVECEXP (pat
, 0, 0)) : SET_SRC (pat
));
4050 if (GET_CODE (dest
) == IF_THEN_ELSE
)
4051 dest
= XEXP (dest
, XEXP (dest
, 1) == pc_rtx
? 2 : 1);
4053 dest
= XEXP (dest
, 0);
4054 dest_uid
= INSN_UID (dest
);
4056 return INSN_ADDRESSES (dest_uid
);
4060 /* Implement TARGET_ENCODE_SECTION_INFO hook. */
4063 arc_encode_section_info (tree decl
, rtx rtl
, int first
)
4065 /* For sdata, SYMBOL_FLAG_LOCAL and SYMBOL_FLAG_FUNCTION.
4066 This clears machine specific flags, so has to come first. */
4067 default_encode_section_info (decl
, rtl
, first
);
4069 /* Check if it is a function, and whether it has the
4070 [long/medium/short]_call attribute specified. */
4071 if (TREE_CODE (decl
) == FUNCTION_DECL
)
4073 rtx symbol
= XEXP (rtl
, 0);
4074 int flags
= SYMBOL_REF_FLAGS (symbol
);
4076 tree attr
= (TREE_TYPE (decl
) != error_mark_node
4077 ? TYPE_ATTRIBUTES (TREE_TYPE (decl
)) : NULL_TREE
);
4078 tree long_call_attr
= lookup_attribute ("long_call", attr
);
4079 tree medium_call_attr
= lookup_attribute ("medium_call", attr
);
4080 tree short_call_attr
= lookup_attribute ("short_call", attr
);
4082 if (long_call_attr
!= NULL_TREE
)
4083 flags
|= SYMBOL_FLAG_LONG_CALL
;
4084 else if (medium_call_attr
!= NULL_TREE
)
4085 flags
|= SYMBOL_FLAG_MEDIUM_CALL
;
4086 else if (short_call_attr
!= NULL_TREE
)
4087 flags
|= SYMBOL_FLAG_SHORT_CALL
;
4089 SYMBOL_REF_FLAGS (symbol
) = flags
;
4093 /* This is how to output a definition of an internal numbered label where
4094 PREFIX is the class of label and NUM is the number within the class. */
4096 static void arc_internal_label (FILE *stream
, const char *prefix
, unsigned long labelno
)
4099 arc_ccfsm_at_label (prefix
, labelno
, &arc_ccfsm_current
);
4100 default_internal_label (stream
, prefix
, labelno
);
4103 /* Set the cpu type and print out other fancy things,
4104 at the top of the file. */
4106 static void arc_file_start (void)
4108 default_file_start ();
4109 fprintf (asm_out_file
, "\t.cpu %s\n", arc_cpu_string
);
4112 /* Cost functions. */
4114 /* Compute a (partial) cost for rtx X. Return true if the complete
4115 cost has been computed, and false if subexpressions should be
4116 scanned. In either case, *TOTAL contains the cost result. */
4119 arc_rtx_costs (rtx x
, int code
, int outer_code
, int opno ATTRIBUTE_UNUSED
,
4120 int *total
, bool speed
)
4124 /* Small integers are as cheap as registers. */
4127 bool nolimm
= false; /* Can we do without long immediate? */
4128 bool fast
= false; /* Is the result available immediately? */
4129 bool condexec
= false; /* Does this allow conditiobnal execution? */
4130 bool compact
= false; /* Is a 16 bit opcode available? */
4131 /* CONDEXEC also implies that we can have an unconditional
4132 3-address operation. */
4134 nolimm
= compact
= condexec
= false;
4135 if (UNSIGNED_INT6 (INTVAL (x
)))
4136 nolimm
= condexec
= compact
= true;
4139 if (SMALL_INT (INTVAL (x
)))
4140 nolimm
= fast
= true;
4143 case AND
: /* bclr, bmsk, ext[bw] */
4144 if (satisfies_constraint_Ccp (x
) /* bclr */
4145 || satisfies_constraint_C1p (x
) /* bmsk */)
4146 nolimm
= fast
= condexec
= compact
= true;
4148 case IOR
: /* bset */
4149 if (satisfies_constraint_C0p (x
)) /* bset */
4150 nolimm
= fast
= condexec
= compact
= true;
4153 if (satisfies_constraint_C0p (x
)) /* bxor */
4154 nolimm
= fast
= condexec
= true;
4157 if (satisfies_constraint_Crr (x
)) /* ror b,u6 */
4163 /* FIXME: Add target options to attach a small cost if
4164 condexec / compact is not true. */
4173 /* 4 byte values can be fetched as immediate constants -
4174 let's give that the cost of an extra insn. */
4178 *total
= COSTS_N_INSNS (1);
4187 *total
= COSTS_N_INSNS (1);
4190 /* FIXME: correct the order of high,low */
4191 split_double (x
, &high
, &low
);
4192 *total
= COSTS_N_INSNS (!SMALL_INT (INTVAL (high
))
4193 + !SMALL_INT (INTVAL (low
)));
4197 /* Encourage synth_mult to find a synthetic multiply when reasonable.
4198 If we need more than 12 insns to do a multiply, then go out-of-line,
4199 since the call overhead will be < 10% of the cost of the multiply. */
4203 if (TARGET_BARREL_SHIFTER
)
4205 /* If we want to shift a constant, we need a LIMM. */
4206 /* ??? when the optimizers want to know if a constant should be
4207 hoisted, they ask for the cost of the constant. OUTER_CODE is
4208 insufficient context for shifts since we don't know which operand
4209 we are looking at. */
4210 if (CONSTANT_P (XEXP (x
, 0)))
4212 *total
+= (COSTS_N_INSNS (2)
4213 + rtx_cost (XEXP (x
, 1), (enum rtx_code
) code
, 0, speed
));
4216 *total
= COSTS_N_INSNS (1);
4218 else if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
4219 *total
= COSTS_N_INSNS (16);
4222 *total
= COSTS_N_INSNS (INTVAL (XEXP ((x
), 1)));
4223 /* ??? want_to_gcse_p can throw negative shift counts at us,
4224 and then panics when it gets a negative cost as result.
4225 Seen for gcc.c-torture/compile/20020710-1.c -Os . */
4234 *total
= COSTS_N_INSNS(30);
4236 *total
= COSTS_N_INSNS(1);
4240 if ((TARGET_DPFP
&& GET_MODE (x
) == DFmode
))
4241 *total
= COSTS_N_INSNS (1);
4243 *total
= arc_multcost
;
4244 /* We do not want synth_mult sequences when optimizing
4246 else if (TARGET_MUL64_SET
|| (TARGET_ARC700
&& !TARGET_NOMPY_SET
))
4247 *total
= COSTS_N_INSNS (1);
4249 *total
= COSTS_N_INSNS (2);
4252 if (GET_CODE (XEXP (x
, 0)) == MULT
4253 && _2_4_8_operand (XEXP (XEXP (x
, 0), 1), VOIDmode
))
4255 *total
+= (rtx_cost (XEXP (x
, 1), PLUS
, 0, speed
)
4256 + rtx_cost (XEXP (XEXP (x
, 0), 0), PLUS
, 1, speed
));
4261 if (GET_CODE (XEXP (x
, 1)) == MULT
4262 && _2_4_8_operand (XEXP (XEXP (x
, 1), 1), VOIDmode
))
4264 *total
+= (rtx_cost (XEXP (x
, 0), PLUS
, 0, speed
)
4265 + rtx_cost (XEXP (XEXP (x
, 1), 0), PLUS
, 1, speed
));
4271 rtx op0
= XEXP (x
, 0);
4272 rtx op1
= XEXP (x
, 1);
4274 if (GET_CODE (op0
) == ZERO_EXTRACT
&& op1
== const0_rtx
4275 && XEXP (op0
, 1) == const1_rtx
)
4277 /* btst / bbit0 / bbit1:
4278 Small integers and registers are free; everything else can
4279 be put in a register. */
4280 *total
= (rtx_cost (XEXP (op0
, 0), SET
, 1, speed
)
4281 + rtx_cost (XEXP (op0
, 2), SET
, 1, speed
));
4284 if (GET_CODE (op0
) == AND
&& op1
== const0_rtx
4285 && satisfies_constraint_C1p (XEXP (op0
, 1)))
4288 *total
= rtx_cost (XEXP (op0
, 0), SET
, 1, speed
);
4292 if (GET_CODE (op1
) == NEG
)
4294 /* op0 might be constant, the inside of op1 is rather
4295 unlikely to be so. So swapping the operands might lower
4297 *total
= (rtx_cost (op0
, PLUS
, 1, speed
)
4298 + rtx_cost (XEXP (op1
, 0), PLUS
, 0, speed
));
4303 if (outer_code
== IF_THEN_ELSE
4304 && GET_CODE (XEXP (x
, 0)) == ZERO_EXTRACT
4305 && XEXP (x
, 1) == const0_rtx
4306 && XEXP (XEXP (x
, 0), 1) == const1_rtx
)
4308 /* btst / bbit0 / bbit1:
4309 Small integers and registers are free; everything else can
4310 be put in a register. */
4311 rtx op0
= XEXP (x
, 0);
4313 *total
= (rtx_cost (XEXP (op0
, 0), SET
, 1, speed
)
4314 + rtx_cost (XEXP (op0
, 2), SET
, 1, speed
));
4318 /* scc_insn expands into two insns. */
4319 case GTU
: case GEU
: case LEU
:
4320 if (GET_MODE (x
) == SImode
)
4321 *total
+= COSTS_N_INSNS (1);
4323 case LTU
: /* might use adc. */
4324 if (GET_MODE (x
) == SImode
)
4325 *total
+= COSTS_N_INSNS (1) - 1;
4332 /* Return true if ADDR is an address that needs to be expressed as an
4333 explicit sum of pcl + offset. */
4336 arc_legitimate_pc_offset_p (rtx addr
)
4338 if (GET_CODE (addr
) != CONST
)
4340 addr
= XEXP (addr
, 0);
4341 if (GET_CODE (addr
) == PLUS
)
4343 if (GET_CODE (XEXP (addr
, 1)) != CONST_INT
)
4345 addr
= XEXP (addr
, 0);
4347 return (GET_CODE (addr
) == UNSPEC
4348 && XVECLEN (addr
, 0) == 1
4349 && XINT (addr
, 1) == ARC_UNSPEC_GOT
4350 && GET_CODE (XVECEXP (addr
, 0, 0)) == SYMBOL_REF
);
4353 /* Return true if ADDR is a valid pic address.
4354 A valid pic address on arc should look like
4355 const (unspec (SYMBOL_REF/LABEL) (ARC_UNSPEC_GOTOFF/ARC_UNSPEC_GOT)) */
4358 arc_legitimate_pic_addr_p (rtx addr
)
4360 if (GET_CODE (addr
) == LABEL_REF
)
4362 if (GET_CODE (addr
) != CONST
)
4365 addr
= XEXP (addr
, 0);
4368 if (GET_CODE (addr
) == PLUS
)
4370 if (GET_CODE (XEXP (addr
, 1)) != CONST_INT
)
4372 addr
= XEXP (addr
, 0);
4375 if (GET_CODE (addr
) != UNSPEC
4376 || XVECLEN (addr
, 0) != 1)
4379 /* Must be @GOT or @GOTOFF. */
4380 if (XINT (addr
, 1) != ARC_UNSPEC_GOT
4381 && XINT (addr
, 1) != ARC_UNSPEC_GOTOFF
)
4384 if (GET_CODE (XVECEXP (addr
, 0, 0)) != SYMBOL_REF
4385 && GET_CODE (XVECEXP (addr
, 0, 0)) != LABEL_REF
)
4393 /* Return true if OP contains a symbol reference. */
4396 symbolic_reference_mentioned_p (rtx op
)
4398 register const char *fmt
;
4401 if (GET_CODE (op
) == SYMBOL_REF
|| GET_CODE (op
) == LABEL_REF
)
4404 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
4405 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
4411 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
4412 if (symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
)))
4416 else if (fmt
[i
] == 'e' && symbolic_reference_mentioned_p (XEXP (op
, i
)))
4423 /* Return true if OP contains a SYMBOL_REF that is not wrapped in an unspec.
4424 If SKIP_LOCAL is true, skip symbols that bind locally.
4425 This is used further down in this file, and, without SKIP_LOCAL,
4426 in the addsi3 / subsi3 expanders when generating PIC code. */
4429 arc_raw_symbolic_reference_mentioned_p (rtx op
, bool skip_local
)
4431 register const char *fmt
;
4434 if (GET_CODE(op
) == UNSPEC
)
4437 if (GET_CODE (op
) == SYMBOL_REF
)
4439 tree decl
= SYMBOL_REF_DECL (op
);
4440 return !skip_local
|| !decl
|| !default_binds_local_p (decl
);
4443 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
4444 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
4450 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
4451 if (arc_raw_symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
),
4456 else if (fmt
[i
] == 'e'
4457 && arc_raw_symbolic_reference_mentioned_p (XEXP (op
, i
),
4465 /* Legitimize a pic address reference in ORIG.
4466 The return value is the legitimated address.
4467 If OLDX is non-zero, it is the target to assign the address to first. */
4470 arc_legitimize_pic_address (rtx orig
, rtx oldx
)
4479 if (GET_CODE (addr
) == LABEL_REF
)
4481 else if (GET_CODE (addr
) == SYMBOL_REF
4482 && (CONSTANT_POOL_ADDRESS_P (addr
)
4483 || SYMBOL_REF_LOCAL_P (addr
)))
4485 /* This symbol may be referenced via a displacement from the PIC
4486 base address (@GOTOFF). */
4488 /* FIXME: if we had a way to emit pc-relative adds that don't
4489 create a GOT entry, we could do without the use of the gp register. */
4490 crtl
->uses_pic_offset_table
= 1;
4491 pat
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, addr
), ARC_UNSPEC_GOTOFF
);
4492 pat
= gen_rtx_CONST (Pmode
, pat
);
4493 pat
= gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, pat
);
4496 oldx
= gen_reg_rtx (Pmode
);
4500 emit_move_insn (oldx
, pat
);
4505 else if (GET_CODE (addr
) == SYMBOL_REF
)
4507 /* This symbol must be referenced via a load from the
4508 Global Offset Table (@GOTPC). */
4510 pat
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, addr
), ARC_UNSPEC_GOT
);
4511 pat
= gen_rtx_CONST (Pmode
, pat
);
4512 pat
= gen_const_mem (Pmode
, pat
);
4515 oldx
= gen_reg_rtx (Pmode
);
4517 emit_move_insn (oldx
, pat
);
4522 if (GET_CODE (addr
) == CONST
)
4524 addr
= XEXP (addr
, 0);
4525 if (GET_CODE (addr
) == UNSPEC
)
4527 /* Check that the unspec is one of the ones we generate? */
4530 gcc_assert (GET_CODE (addr
) == PLUS
);
4533 if (GET_CODE (addr
) == PLUS
)
4535 rtx op0
= XEXP (addr
, 0), op1
= XEXP (addr
, 1);
4537 /* Check first to see if this is a constant offset from a @GOTOFF
4538 symbol reference. */
4539 if ((GET_CODE (op0
) == LABEL_REF
4540 || (GET_CODE (op0
) == SYMBOL_REF
4541 && (CONSTANT_POOL_ADDRESS_P (op0
)
4542 || SYMBOL_REF_LOCAL_P (op0
))))
4543 && GET_CODE (op1
) == CONST_INT
)
4545 /* FIXME: like above, could do without gp reference. */
4546 crtl
->uses_pic_offset_table
= 1;
4548 = gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, op0
), ARC_UNSPEC_GOTOFF
);
4549 pat
= gen_rtx_PLUS (Pmode
, pat
, op1
);
4550 pat
= gen_rtx_CONST (Pmode
, pat
);
4551 pat
= gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, pat
);
4555 emit_move_insn (oldx
, pat
);
4561 base
= arc_legitimize_pic_address (XEXP (addr
, 0), oldx
);
4562 pat
= arc_legitimize_pic_address (XEXP (addr
, 1),
4563 base
== oldx
? NULL_RTX
: oldx
);
4565 if (GET_CODE (pat
) == CONST_INT
)
4566 pat
= plus_constant (Pmode
, base
, INTVAL (pat
));
4569 if (GET_CODE (pat
) == PLUS
&& CONSTANT_P (XEXP (pat
, 1)))
4571 base
= gen_rtx_PLUS (Pmode
, base
, XEXP (pat
, 0));
4572 pat
= XEXP (pat
, 1);
4574 pat
= gen_rtx_PLUS (Pmode
, base
, pat
);
4583 /* Output address constant X to FILE, taking PIC into account. */
4586 arc_output_pic_addr_const (FILE * file
, rtx x
, int code
)
4591 switch (GET_CODE (x
))
4601 output_addr_const (file
, x
);
4603 /* Local functions do not get references through the PLT. */
4604 if (code
== 'P' && ! SYMBOL_REF_LOCAL_P (x
))
4605 fputs ("@plt", file
);
4609 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (XEXP (x
, 0)));
4610 assemble_name (file
, buf
);
4614 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (x
));
4615 assemble_name (file
, buf
);
4619 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
));
4623 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4627 if (GET_MODE (x
) == VOIDmode
)
4629 /* We can use %d if the number is one word and positive. */
4630 if (CONST_DOUBLE_HIGH (x
))
4631 fprintf (file
, HOST_WIDE_INT_PRINT_DOUBLE_HEX
,
4632 CONST_DOUBLE_HIGH (x
), CONST_DOUBLE_LOW (x
));
4633 else if (CONST_DOUBLE_LOW (x
) < 0)
4634 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, CONST_DOUBLE_LOW (x
));
4636 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, CONST_DOUBLE_LOW (x
));
4639 /* We can't handle floating point constants;
4640 PRINT_OPERAND must handle them. */
4641 output_operand_lossage ("floating constant misused");
4645 /* FIXME: Not needed here. */
4646 /* Some assemblers need integer constants to appear last (eg masm). */
4647 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
4649 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4650 fprintf (file
, "+");
4651 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4653 else if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
4655 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4656 if (INTVAL (XEXP (x
, 1)) >= 0)
4657 fprintf (file
, "+");
4658 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4665 /* Avoid outputting things like x-x or x+5-x,
4666 since some assemblers can't handle that. */
4667 x
= simplify_subtraction (x
);
4668 if (GET_CODE (x
) != MINUS
)
4671 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4672 fprintf (file
, "-");
4673 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
4674 && INTVAL (XEXP (x
, 1)) < 0)
4676 fprintf (file
, "(");
4677 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4678 fprintf (file
, ")");
4681 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
4686 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
4691 gcc_assert (XVECLEN (x
, 0) == 1);
4692 if (XINT (x
, 1) == ARC_UNSPEC_GOT
)
4693 fputs ("pcl,", file
);
4694 arc_output_pic_addr_const (file
, XVECEXP (x
, 0, 0), code
);
4695 switch (XINT (x
, 1))
4697 case ARC_UNSPEC_GOT
:
4698 fputs ("@gotpc", file
);
4700 case ARC_UNSPEC_GOTOFF
:
4701 fputs ("@gotoff", file
);
4703 case ARC_UNSPEC_PLT
:
4704 fputs ("@plt", file
);
4707 output_operand_lossage ("invalid UNSPEC as operand: %d", XINT (x
,1));
4713 output_operand_lossage ("invalid expression as operand");
4717 #define SYMBOLIC_CONST(X) \
4718 (GET_CODE (X) == SYMBOL_REF \
4719 || GET_CODE (X) == LABEL_REF \
4720 || (GET_CODE (X) == CONST && symbolic_reference_mentioned_p (X)))
4722 /* Emit insns to move operands[1] into operands[0]. */
4725 emit_pic_move (rtx
*operands
, machine_mode
)
4727 rtx temp
= reload_in_progress
? operands
[0] : gen_reg_rtx (Pmode
);
4729 if (GET_CODE (operands
[0]) == MEM
&& SYMBOLIC_CONST (operands
[1]))
4730 operands
[1] = force_reg (Pmode
, operands
[1]);
4732 operands
[1] = arc_legitimize_pic_address (operands
[1], temp
);
4736 /* The function returning the number of words, at the beginning of an
4737 argument, must be put in registers. The returned value must be
4738 zero for arguments that are passed entirely in registers or that
4739 are entirely pushed on the stack.
4741 On some machines, certain arguments must be passed partially in
4742 registers and partially in memory. On these machines, typically
4743 the first N words of arguments are passed in registers, and the
4744 rest on the stack. If a multi-word argument (a `double' or a
4745 structure) crosses that boundary, its first few words must be
4746 passed in registers and the rest must be pushed. This function
4747 tells the compiler when this occurs, and how many of the words
4748 should go in registers.
4750 `FUNCTION_ARG' for these arguments should return the first register
4751 to be used by the caller for this argument; likewise
4752 `FUNCTION_INCOMING_ARG', for the called function.
4754 The function is used to implement macro FUNCTION_ARG_PARTIAL_NREGS. */
4756 /* If REGNO is the least arg reg available then what is the total number of arg
4758 #define GPR_REST_ARG_REGS(REGNO) \
4759 ((REGNO) <= MAX_ARC_PARM_REGS ? MAX_ARC_PARM_REGS - (REGNO) : 0 )
4761 /* Since arc parm regs are contiguous. */
4762 #define ARC_NEXT_ARG_REG(REGNO) ( (REGNO) + 1 )
4764 /* Implement TARGET_ARG_PARTIAL_BYTES. */
4767 arc_arg_partial_bytes (cumulative_args_t cum_v
, machine_mode mode
,
4768 tree type
, bool named ATTRIBUTE_UNUSED
)
4770 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
4771 int bytes
= (mode
== BLKmode
4772 ? int_size_in_bytes (type
) : (int) GET_MODE_SIZE (mode
));
4773 int words
= (bytes
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
4777 arg_num
= ROUND_ADVANCE_CUM (arg_num
, mode
, type
);
4778 ret
= GPR_REST_ARG_REGS (arg_num
);
4780 /* ICEd at function.c:2361, and ret is copied to data->partial */
4781 ret
= (ret
>= words
? 0 : ret
* UNITS_PER_WORD
);
4788 /* This function is used to control a function argument is passed in a
4789 register, and which register.
4791 The arguments are CUM, of type CUMULATIVE_ARGS, which summarizes
4792 (in a way defined by INIT_CUMULATIVE_ARGS and FUNCTION_ARG_ADVANCE)
4793 all of the previous arguments so far passed in registers; MODE, the
4794 machine mode of the argument; TYPE, the data type of the argument
4795 as a tree node or 0 if that is not known (which happens for C
4796 support library functions); and NAMED, which is 1 for an ordinary
4797 argument and 0 for nameless arguments that correspond to `...' in
4798 the called function's prototype.
4800 The returned value should either be a `reg' RTX for the hard
4801 register in which to pass the argument, or zero to pass the
4802 argument on the stack.
4804 For machines like the Vax and 68000, where normally all arguments
4805 are pushed, zero suffices as a definition.
4807 The usual way to make the ANSI library `stdarg.h' work on a machine
4808 where some arguments are usually passed in registers, is to cause
4809 nameless arguments to be passed on the stack instead. This is done
4810 by making the function return 0 whenever NAMED is 0.
4812 You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the
4813 definition of this function to determine if this argument is of a
4814 type that must be passed in the stack. If `REG_PARM_STACK_SPACE'
4815 is not defined and the function returns non-zero for such an
4816 argument, the compiler will abort. If `REG_PARM_STACK_SPACE' is
4817 defined, the argument will be computed in the stack and then loaded
4820 The function is used to implement macro FUNCTION_ARG. */
4821 /* On the ARC the first MAX_ARC_PARM_REGS args are normally in registers
4822 and the rest are pushed. */
4825 arc_function_arg (cumulative_args_t cum_v
, machine_mode mode
,
4826 const_tree type ATTRIBUTE_UNUSED
, bool named ATTRIBUTE_UNUSED
)
4828 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
4831 const char *debstr ATTRIBUTE_UNUSED
;
4833 arg_num
= ROUND_ADVANCE_CUM (arg_num
, mode
, type
);
4834 /* Return a marker for use in the call instruction. */
4835 if (mode
== VOIDmode
)
4840 else if (GPR_REST_ARG_REGS (arg_num
) > 0)
4842 ret
= gen_rtx_REG (mode
, arg_num
);
4843 debstr
= reg_names
[arg_num
];
4853 /* The function to update the summarizer variable *CUM to advance past
4854 an argument in the argument list. The values MODE, TYPE and NAMED
4855 describe that argument. Once this is done, the variable *CUM is
4856 suitable for analyzing the *following* argument with
4857 `FUNCTION_ARG', etc.
4859 This function need not do anything if the argument in question was
4860 passed on the stack. The compiler knows how to track the amount of
4861 stack space used for arguments without any special help.
4863 The function is used to implement macro FUNCTION_ARG_ADVANCE. */
4864 /* For the ARC: the cum set here is passed on to function_arg where we
4865 look at its value and say which reg to use. Strategy: advance the
4866 regnumber here till we run out of arg regs, then set *cum to last
4867 reg. In function_arg, since *cum > last arg reg we would return 0
4868 and thus the arg will end up on the stack. For straddling args of
4869 course function_arg_partial_nregs will come into play. */
4872 arc_function_arg_advance (cumulative_args_t cum_v
, machine_mode mode
,
4873 const_tree type
, bool named ATTRIBUTE_UNUSED
)
4875 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
4876 int bytes
= (mode
== BLKmode
4877 ? int_size_in_bytes (type
) : (int) GET_MODE_SIZE (mode
));
4878 int words
= (bytes
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
4882 *cum
= ROUND_ADVANCE_CUM (*cum
, mode
, type
);
4883 for (i
= 0; i
< words
; i
++)
4884 *cum
= ARC_NEXT_ARG_REG (*cum
);
4888 /* Define how to find the value returned by a function.
4889 VALTYPE is the data type of the value (as a tree).
4890 If the precise function being called is known, FN_DECL_OR_TYPE is its
4891 FUNCTION_DECL; otherwise, FN_DECL_OR_TYPE is its type. */
4894 arc_function_value (const_tree valtype
,
4895 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
4896 bool outgoing ATTRIBUTE_UNUSED
)
4898 machine_mode mode
= TYPE_MODE (valtype
);
4899 int unsignedp ATTRIBUTE_UNUSED
;
4901 unsignedp
= TYPE_UNSIGNED (valtype
);
4902 if (INTEGRAL_TYPE_P (valtype
) || TREE_CODE (valtype
) == OFFSET_TYPE
)
4903 PROMOTE_MODE (mode
, unsignedp
, valtype
);
4904 return gen_rtx_REG (mode
, 0);
4907 /* Returns the return address that is used by builtin_return_address. */
4910 arc_return_addr_rtx (int count
, ATTRIBUTE_UNUSED rtx frame
)
4915 return get_hard_reg_initial_val (Pmode
, RETURN_ADDR_REGNUM
);
4918 /* Nonzero if the constant value X is a legitimate general operand
4919 when generating PIC code. It is given that flag_pic is on and
4920 that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
4923 arc_legitimate_pic_operand_p (rtx x
)
4925 return !arc_raw_symbolic_reference_mentioned_p (x
, true);
4928 /* Determine if a given RTX is a valid constant. We already know this
4929 satisfies CONSTANT_P. */
4932 arc_legitimate_constant_p (machine_mode
, rtx x
)
4937 switch (GET_CODE (x
))
4942 if (GET_CODE (x
) == PLUS
)
4944 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
4949 /* Only some unspecs are valid as "constants". */
4950 if (GET_CODE (x
) == UNSPEC
)
4951 switch (XINT (x
, 1))
4953 case ARC_UNSPEC_PLT
:
4954 case ARC_UNSPEC_GOTOFF
:
4955 case ARC_UNSPEC_GOT
:
4963 /* We must have drilled down to a symbol. */
4964 if (arc_raw_symbolic_reference_mentioned_p (x
, false))
4978 /* Otherwise we handle everything else in the move patterns. */
4983 arc_legitimate_address_p (machine_mode mode
, rtx x
, bool strict
)
4985 if (RTX_OK_FOR_BASE_P (x
, strict
))
4987 if (LEGITIMATE_OFFSET_ADDRESS_P (mode
, x
, TARGET_INDEXED_LOADS
, strict
))
4989 if (LEGITIMATE_SCALED_ADDRESS_P (mode
, x
, strict
))
4991 if (LEGITIMATE_SMALL_DATA_ADDRESS_P (x
))
4993 if (GET_CODE (x
) == CONST_INT
&& LARGE_INT (INTVAL (x
)))
4995 if ((GET_MODE_SIZE (mode
) != 16)
4996 && (GET_CODE (x
) == SYMBOL_REF
4997 || GET_CODE (x
) == LABEL_REF
4998 || GET_CODE (x
) == CONST
))
5000 if (!flag_pic
|| arc_legitimate_pic_addr_p (x
))
5003 if ((GET_CODE (x
) == PRE_DEC
|| GET_CODE (x
) == PRE_INC
5004 || GET_CODE (x
) == POST_DEC
|| GET_CODE (x
) == POST_INC
)
5005 && RTX_OK_FOR_BASE_P (XEXP (x
, 0), strict
))
5007 /* We're restricted here by the `st' insn. */
5008 if ((GET_CODE (x
) == PRE_MODIFY
|| GET_CODE (x
) == POST_MODIFY
)
5009 && GET_CODE (XEXP ((x
), 1)) == PLUS
5010 && rtx_equal_p (XEXP ((x
), 0), XEXP (XEXP (x
, 1), 0))
5011 && LEGITIMATE_OFFSET_ADDRESS_P (QImode
, XEXP (x
, 1),
5012 TARGET_AUTO_MODIFY_REG
, strict
))
5017 /* Return true iff ADDR (a legitimate address expression)
5018 has an effect that depends on the machine mode it is used for. */
5021 arc_mode_dependent_address_p (const_rtx addr
, addr_space_t
)
5023 /* SYMBOL_REF is not mode dependent: it is either a small data reference,
5024 which is valid for loads and stores, or a limm offset, which is valid for
5026 /* Scaled indices are scaled by the access mode; likewise for scaled
5027 offsets, which are needed for maximum offset stores. */
5028 if (GET_CODE (addr
) == PLUS
5029 && (GET_CODE (XEXP ((addr
), 0)) == MULT
5030 || (CONST_INT_P (XEXP ((addr
), 1))
5031 && !SMALL_INT (INTVAL (XEXP ((addr
), 1))))))
5036 /* Determine if it's legal to put X into the constant pool. */
5039 arc_cannot_force_const_mem (machine_mode mode
, rtx x
)
5041 return !arc_legitimate_constant_p (mode
, x
);
5045 /* Generic function to define a builtin. */
5046 #define def_mbuiltin(MASK, NAME, TYPE, CODE) \
5050 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL, NULL_TREE); \
5056 arc_init_builtins (void)
5058 tree endlink
= void_list_node
;
5060 tree void_ftype_void
5061 = build_function_type (void_type_node
,
5065 = build_function_type (integer_type_node
,
5066 tree_cons (NULL_TREE
, integer_type_node
, endlink
));
5068 tree pcvoid_type_node
5069 = build_pointer_type (build_qualified_type (void_type_node
, TYPE_QUAL_CONST
));
5070 tree int_ftype_pcvoid_int
5071 = build_function_type (integer_type_node
,
5072 tree_cons (NULL_TREE
, pcvoid_type_node
,
5073 tree_cons (NULL_TREE
, integer_type_node
,
5076 tree int_ftype_short_int
5077 = build_function_type (integer_type_node
,
5078 tree_cons (NULL_TREE
, short_integer_type_node
, endlink
));
5080 tree void_ftype_int_int
5081 = build_function_type (void_type_node
,
5082 tree_cons (NULL_TREE
, integer_type_node
,
5083 tree_cons (NULL_TREE
, integer_type_node
, endlink
)));
5084 tree void_ftype_usint_usint
5085 = build_function_type (void_type_node
,
5086 tree_cons (NULL_TREE
, long_unsigned_type_node
,
5087 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
)));
5089 tree int_ftype_int_int
5090 = build_function_type (integer_type_node
,
5091 tree_cons (NULL_TREE
, integer_type_node
,
5092 tree_cons (NULL_TREE
, integer_type_node
, endlink
)));
5094 tree usint_ftype_usint
5095 = build_function_type (long_unsigned_type_node
,
5096 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
));
5098 tree void_ftype_usint
5099 = build_function_type (void_type_node
,
5100 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
));
5102 /* Add the builtins. */
5103 def_mbuiltin (1,"__builtin_arc_nop", void_ftype_void
, ARC_BUILTIN_NOP
);
5104 def_mbuiltin (TARGET_NORM
, "__builtin_arc_norm", int_ftype_int
, ARC_BUILTIN_NORM
);
5105 def_mbuiltin (TARGET_NORM
, "__builtin_arc_normw", int_ftype_short_int
, ARC_BUILTIN_NORMW
);
5106 def_mbuiltin (TARGET_SWAP
, "__builtin_arc_swap", int_ftype_int
, ARC_BUILTIN_SWAP
);
5107 def_mbuiltin (TARGET_MUL64_SET
,"__builtin_arc_mul64", void_ftype_int_int
, ARC_BUILTIN_MUL64
);
5108 def_mbuiltin (TARGET_MUL64_SET
,"__builtin_arc_mulu64", void_ftype_usint_usint
, ARC_BUILTIN_MULU64
);
5109 def_mbuiltin (1,"__builtin_arc_rtie", void_ftype_void
, ARC_BUILTIN_RTIE
);
5110 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_sync", void_ftype_void
, ARC_BUILTIN_SYNC
);
5111 def_mbuiltin ((TARGET_EA_SET
),"__builtin_arc_divaw", int_ftype_int_int
, ARC_BUILTIN_DIVAW
);
5112 def_mbuiltin (1,"__builtin_arc_brk", void_ftype_void
, ARC_BUILTIN_BRK
);
5113 def_mbuiltin (1,"__builtin_arc_flag", void_ftype_usint
, ARC_BUILTIN_FLAG
);
5114 def_mbuiltin (1,"__builtin_arc_sleep", void_ftype_usint
, ARC_BUILTIN_SLEEP
);
5115 def_mbuiltin (1,"__builtin_arc_swi", void_ftype_void
, ARC_BUILTIN_SWI
);
5116 def_mbuiltin (1,"__builtin_arc_core_read", usint_ftype_usint
, ARC_BUILTIN_CORE_READ
);
5117 def_mbuiltin (1,"__builtin_arc_core_write", void_ftype_usint_usint
, ARC_BUILTIN_CORE_WRITE
);
5118 def_mbuiltin (1,"__builtin_arc_lr", usint_ftype_usint
, ARC_BUILTIN_LR
);
5119 def_mbuiltin (1,"__builtin_arc_sr", void_ftype_usint_usint
, ARC_BUILTIN_SR
);
5120 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_trap_s", void_ftype_usint
, ARC_BUILTIN_TRAP_S
);
5121 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_unimp_s", void_ftype_void
, ARC_BUILTIN_UNIMP_S
);
5122 def_mbuiltin (1,"__builtin_arc_aligned", int_ftype_pcvoid_int
, ARC_BUILTIN_ALIGNED
);
5124 if (TARGET_SIMD_SET
)
5125 arc_init_simd_builtins ();
5128 static rtx
arc_expand_simd_builtin (tree
, rtx
, rtx
, machine_mode
, int);
5130 /* Expand an expression EXP that calls a built-in function,
5131 with result going to TARGET if that's convenient
5132 (and in mode MODE if that's convenient).
5133 SUBTARGET may be used as the target for computing one of EXP's operands.
5134 IGNORE is nonzero if the value is to be ignored. */
5137 arc_expand_builtin (tree exp
,
5143 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
5148 int fcode
= DECL_FUNCTION_CODE (fndecl
);
5153 if (fcode
> ARC_SIMD_BUILTIN_BEGIN
&& fcode
< ARC_SIMD_BUILTIN_END
)
5154 return arc_expand_simd_builtin (exp
, target
, subtarget
, mode
, ignore
);
5158 case ARC_BUILTIN_NOP
:
5159 emit_insn (gen_nop ());
5162 case ARC_BUILTIN_NORM
:
5163 icode
= CODE_FOR_clrsbsi2
;
5164 arg0
= CALL_EXPR_ARG (exp
, 0);
5165 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5166 mode0
= insn_data
[icode
].operand
[1].mode
;
5167 target
= gen_reg_rtx (SImode
);
5169 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5170 op0
= copy_to_mode_reg (mode0
, op0
);
5172 emit_insn (gen_clrsbsi2 (target
, op0
));
5175 case ARC_BUILTIN_NORMW
:
5177 /* FIXME : This should all be HImode, not SImode. */
5178 icode
= CODE_FOR_normw
;
5179 arg0
= CALL_EXPR_ARG (exp
, 0);
5180 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5181 mode0
= insn_data
[icode
].operand
[1].mode
;
5182 target
= gen_reg_rtx (SImode
);
5184 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5185 op0
= copy_to_mode_reg (mode0
, convert_to_mode (mode0
, op0
,0));
5187 emit_insn (gen_normw (target
, op0
));
5190 case ARC_BUILTIN_MUL64
:
5191 icode
= CODE_FOR_mul64
;
5192 arg0
= CALL_EXPR_ARG (exp
, 0);
5193 arg1
= CALL_EXPR_ARG (exp
, 1);
5194 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5195 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5197 mode0
= insn_data
[icode
].operand
[0].mode
;
5198 mode1
= insn_data
[icode
].operand
[1].mode
;
5200 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5201 op0
= copy_to_mode_reg (mode0
, op0
);
5203 if (! (*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
5204 op1
= copy_to_mode_reg (mode1
, op1
);
5206 emit_insn (gen_mul64 (op0
,op1
));
5209 case ARC_BUILTIN_MULU64
:
5210 icode
= CODE_FOR_mulu64
;
5211 arg0
= CALL_EXPR_ARG (exp
, 0);
5212 arg1
= CALL_EXPR_ARG (exp
, 1);
5213 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5214 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5216 mode0
= insn_data
[icode
].operand
[0].mode
;
5217 mode1
= insn_data
[icode
].operand
[1].mode
;
5219 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5220 op0
= copy_to_mode_reg (mode0
, op0
);
5222 if (! (*insn_data
[icode
].operand
[0].predicate
) (op1
, mode1
))
5223 op1
= copy_to_mode_reg (mode1
, op1
);
5225 emit_insn (gen_mulu64 (op0
,op1
));
5228 case ARC_BUILTIN_RTIE
:
5229 icode
= CODE_FOR_rtie
;
5230 emit_insn (gen_rtie (const1_rtx
));
5233 case ARC_BUILTIN_SYNC
:
5234 icode
= CODE_FOR_sync
;
5235 emit_insn (gen_sync (const1_rtx
));
5238 case ARC_BUILTIN_SWAP
:
5239 icode
= CODE_FOR_swap
;
5240 arg0
= CALL_EXPR_ARG (exp
, 0);
5241 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5242 mode0
= insn_data
[icode
].operand
[1].mode
;
5243 target
= gen_reg_rtx (SImode
);
5245 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5246 op0
= copy_to_mode_reg (mode0
, op0
);
5248 emit_insn (gen_swap (target
, op0
));
5251 case ARC_BUILTIN_DIVAW
:
5252 icode
= CODE_FOR_divaw
;
5253 arg0
= CALL_EXPR_ARG (exp
, 0);
5254 arg1
= CALL_EXPR_ARG (exp
, 1);
5256 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5257 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5258 target
= gen_reg_rtx (SImode
);
5260 mode0
= insn_data
[icode
].operand
[0].mode
;
5261 mode1
= insn_data
[icode
].operand
[1].mode
;
5263 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5264 op0
= copy_to_mode_reg (mode0
, op0
);
5266 if (! (*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
5267 op1
= copy_to_mode_reg (mode1
, op1
);
5269 emit_insn (gen_divaw (target
, op0
, op1
));
5272 case ARC_BUILTIN_BRK
:
5273 icode
= CODE_FOR_brk
;
5274 emit_insn (gen_brk (const1_rtx
));
5277 case ARC_BUILTIN_SLEEP
:
5278 icode
= CODE_FOR_sleep
;
5279 arg0
= CALL_EXPR_ARG (exp
, 0);
5283 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5284 mode0
= insn_data
[icode
].operand
[1].mode
;
5286 emit_insn (gen_sleep (op0
));
5289 case ARC_BUILTIN_SWI
:
5290 icode
= CODE_FOR_swi
;
5291 emit_insn (gen_swi (const1_rtx
));
5294 case ARC_BUILTIN_FLAG
:
5295 icode
= CODE_FOR_flag
;
5296 arg0
= CALL_EXPR_ARG (exp
, 0);
5297 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5298 mode0
= insn_data
[icode
].operand
[0].mode
;
5300 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5301 op0
= copy_to_mode_reg (mode0
, op0
);
5303 emit_insn (gen_flag (op0
));
5306 case ARC_BUILTIN_CORE_READ
:
5307 icode
= CODE_FOR_core_read
;
5308 arg0
= CALL_EXPR_ARG (exp
, 0);
5309 target
= gen_reg_rtx (SImode
);
5313 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5314 mode0
= insn_data
[icode
].operand
[1].mode
;
5316 emit_insn (gen_core_read (target
, op0
));
5319 case ARC_BUILTIN_CORE_WRITE
:
5320 icode
= CODE_FOR_core_write
;
5321 arg0
= CALL_EXPR_ARG (exp
, 0);
5322 arg1
= CALL_EXPR_ARG (exp
, 1);
5326 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5327 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5329 mode0
= insn_data
[icode
].operand
[0].mode
;
5330 mode1
= insn_data
[icode
].operand
[1].mode
;
5332 emit_insn (gen_core_write (op0
, op1
));
5335 case ARC_BUILTIN_LR
:
5336 icode
= CODE_FOR_lr
;
5337 arg0
= CALL_EXPR_ARG (exp
, 0);
5338 target
= gen_reg_rtx (SImode
);
5342 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5343 mode0
= insn_data
[icode
].operand
[1].mode
;
5345 emit_insn (gen_lr (target
, op0
));
5348 case ARC_BUILTIN_SR
:
5349 icode
= CODE_FOR_sr
;
5350 arg0
= CALL_EXPR_ARG (exp
, 0);
5351 arg1
= CALL_EXPR_ARG (exp
, 1);
5355 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5356 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5358 mode0
= insn_data
[icode
].operand
[0].mode
;
5359 mode1
= insn_data
[icode
].operand
[1].mode
;
5361 emit_insn (gen_sr (op0
, op1
));
5364 case ARC_BUILTIN_TRAP_S
:
5365 icode
= CODE_FOR_trap_s
;
5366 arg0
= CALL_EXPR_ARG (exp
, 0);
5370 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5371 mode0
= insn_data
[icode
].operand
[1].mode
;
5373 /* We don't give an error for non-cost values here because
5374 we still want to allow things to be fixed up by later inlining /
5375 constant folding / dead code elimination. */
5376 if (CONST_INT_P (op0
) && !satisfies_constraint_L (op0
))
5378 /* Keep this message in sync with the one in arc.md:trap_s,
5379 because *.md files don't get scanned by exgettext. */
5380 error ("operand to trap_s should be an unsigned 6-bit value");
5382 emit_insn (gen_trap_s (op0
));
5385 case ARC_BUILTIN_UNIMP_S
:
5386 icode
= CODE_FOR_unimp_s
;
5387 emit_insn (gen_unimp_s (const1_rtx
));
5390 case ARC_BUILTIN_ALIGNED
:
5391 /* __builtin_arc_aligned (void* val, int alignval) */
5392 arg0
= CALL_EXPR_ARG (exp
, 0);
5393 arg1
= CALL_EXPR_ARG (exp
, 1);
5395 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5396 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, EXPAND_NORMAL
);
5397 target
= gen_reg_rtx (SImode
);
5399 if (!CONST_INT_P (op1
))
5401 /* If we can't fold the alignment to a constant integer
5402 whilst optimizing, this is probably a user error. */
5404 warning (0, "__builtin_arc_aligned with non-constant alignment");
5408 HOST_WIDE_INT alignTest
= INTVAL (op1
);
5409 /* Check alignTest is positive, and a power of two. */
5410 if (alignTest
<= 0 || alignTest
!= (alignTest
& -alignTest
))
5412 error ("invalid alignment value for __builtin_arc_aligned");
5416 if (CONST_INT_P (op0
))
5418 HOST_WIDE_INT pnt
= INTVAL (op0
);
5420 if ((pnt
& (alignTest
- 1)) == 0)
5425 unsigned align
= get_pointer_alignment (arg0
);
5426 unsigned numBits
= alignTest
* BITS_PER_UNIT
;
5428 if (align
&& align
>= numBits
)
5430 /* Another attempt to ascertain alignment. Check the type
5431 we are pointing to. */
5432 if (POINTER_TYPE_P (TREE_TYPE (arg0
))
5433 && TYPE_ALIGN (TREE_TYPE (TREE_TYPE (arg0
))) >= numBits
)
5438 /* Default to false. */
5445 /* @@@ Should really do something sensible here. */
5449 /* Returns true if the operands[opno] is a valid compile-time constant to be
5450 used as register number in the code for builtins. Else it flags an error
5451 and returns false. */
5454 check_if_valid_regno_const (rtx
*operands
, int opno
)
5457 switch (GET_CODE (operands
[opno
]))
5464 error ("register number must be a compile-time constant. Try giving higher optimization levels");
5470 /* Check that after all the constant folding, whether the operand to
5471 __builtin_arc_sleep is an unsigned int of 6 bits. If not, flag an error. */
5474 check_if_valid_sleep_operand (rtx
*operands
, int opno
)
5476 switch (GET_CODE (operands
[opno
]))
5480 if( UNSIGNED_INT6 (INTVAL (operands
[opno
])))
5483 fatal_error("operand for sleep instruction must be an unsigned 6 bit compile-time constant");
5489 /* Return true if it is ok to make a tail-call to DECL. */
5492 arc_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED
,
5493 tree exp ATTRIBUTE_UNUSED
)
5495 /* Never tailcall from an ISR routine - it needs a special exit sequence. */
5496 if (ARC_INTERRUPT_P (arc_compute_function_type (cfun
)))
5499 /* Everything else is ok. */
5503 /* Output code to add DELTA to the first argument, and then jump
5504 to FUNCTION. Used for C++ multiple inheritance. */
5507 arc_output_mi_thunk (FILE *file
, tree thunk ATTRIBUTE_UNUSED
,
5508 HOST_WIDE_INT delta
,
5509 HOST_WIDE_INT vcall_offset
,
5512 int mi_delta
= delta
;
5513 const char *const mi_op
= mi_delta
< 0 ? "sub" : "add";
5516 = aggregate_value_p (TREE_TYPE (TREE_TYPE (function
)), function
) ? 1 : 0;
5520 mi_delta
= - mi_delta
;
5522 /* Add DELTA. When possible use a plain add, otherwise load it into
5523 a register first. */
5525 while (mi_delta
!= 0)
5527 if ((mi_delta
& (3 << shift
)) == 0)
5531 asm_fprintf (file
, "\t%s\t%s, %s, %d\n",
5532 mi_op
, reg_names
[this_regno
], reg_names
[this_regno
],
5533 mi_delta
& (0xff << shift
));
5534 mi_delta
&= ~(0xff << shift
);
5539 /* If needed, add *(*THIS + VCALL_OFFSET) to THIS. */
5540 if (vcall_offset
!= 0)
5542 /* ld r12,[this] --> temp = *this
5543 add r12,r12,vcall_offset --> temp = *(*this + vcall_offset)
5545 add this,this,r12 --> this+ = *(*this + vcall_offset) */
5546 asm_fprintf (file
, "\tld\t%s, [%s]\n",
5547 ARC_TEMP_SCRATCH_REG
, reg_names
[this_regno
]);
5548 asm_fprintf (file
, "\tadd\t%s, %s, " HOST_WIDE_INT_PRINT_DEC
"\n",
5549 ARC_TEMP_SCRATCH_REG
, ARC_TEMP_SCRATCH_REG
, vcall_offset
);
5550 asm_fprintf (file
, "\tld\t%s, [%s]\n",
5551 ARC_TEMP_SCRATCH_REG
, ARC_TEMP_SCRATCH_REG
);
5552 asm_fprintf (file
, "\tadd\t%s, %s, %s\n", reg_names
[this_regno
],
5553 reg_names
[this_regno
], ARC_TEMP_SCRATCH_REG
);
5556 fnaddr
= XEXP (DECL_RTL (function
), 0);
5558 if (arc_is_longcall_p (fnaddr
))
5559 fputs ("\tj\t", file
);
5561 fputs ("\tb\t", file
);
5562 assemble_name (file
, XSTR (fnaddr
, 0));
5566 /* Return true if a 32 bit "long_call" should be generated for
5567 this calling SYM_REF. We generate a long_call if the function:
5569 a. has an __attribute__((long call))
5570 or b. the -mlong-calls command line switch has been specified
5572 However we do not generate a long call if the function has an
5573 __attribute__ ((short_call)) or __attribute__ ((medium_call))
5575 This function will be called by C fragments contained in the machine
5576 description file. */
5579 arc_is_longcall_p (rtx sym_ref
)
5581 if (GET_CODE (sym_ref
) != SYMBOL_REF
)
5584 return (SYMBOL_REF_LONG_CALL_P (sym_ref
)
5585 || (TARGET_LONG_CALLS_SET
5586 && !SYMBOL_REF_SHORT_CALL_P (sym_ref
)
5587 && !SYMBOL_REF_MEDIUM_CALL_P (sym_ref
)));
5591 /* Likewise for short calls. */
5594 arc_is_shortcall_p (rtx sym_ref
)
5596 if (GET_CODE (sym_ref
) != SYMBOL_REF
)
5599 return (SYMBOL_REF_SHORT_CALL_P (sym_ref
)
5600 || (!TARGET_LONG_CALLS_SET
&& !TARGET_MEDIUM_CALLS
5601 && !SYMBOL_REF_LONG_CALL_P (sym_ref
)
5602 && !SYMBOL_REF_MEDIUM_CALL_P (sym_ref
)));
5606 /* Emit profiling code for calling CALLEE. Return true if a special
5607 call pattern needs to be generated. */
5610 arc_profile_call (rtx callee
)
5612 rtx from
= XEXP (DECL_RTL (current_function_decl
), 0);
5614 if (TARGET_UCB_MCOUNT
)
5615 /* Profiling is done by instrumenting the callee. */
5618 if (CONSTANT_P (callee
))
5621 = gen_rtx_CONST (Pmode
,
5622 gen_rtx_UNSPEC (Pmode
,
5623 gen_rtvec (3, from
, callee
,
5624 CONST0_RTX (Pmode
)),
5626 rtx counter
= gen_rtx_MEM (SImode
, count_ptr
);
5627 /* ??? The increment would better be done atomically, but as there is
5628 no proper hardware support, that would be too expensive. */
5629 emit_move_insn (counter
,
5630 force_reg (SImode
, plus_constant (SImode
, counter
, 1)));
5636 = gen_rtx_CONST (Pmode
,
5637 gen_rtx_UNSPEC (Pmode
,
5638 gen_rtvec (3, from
, CONST0_RTX (Pmode
),
5639 CONST0_RTX (Pmode
)),
5641 emit_move_insn (gen_rtx_REG (Pmode
, 8), count_list_ptr
);
5642 emit_move_insn (gen_rtx_REG (Pmode
, 9), callee
);
5647 /* Worker function for TARGET_RETURN_IN_MEMORY. */
5650 arc_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
5652 if (AGGREGATE_TYPE_P (type
) || TREE_ADDRESSABLE (type
))
5656 HOST_WIDE_INT size
= int_size_in_bytes (type
);
5657 return (size
== -1 || size
> 8);
5662 /* This was in rtlanal.c, and can go in there when we decide we want
5663 to submit the change for inclusion in the GCC tree. */
5664 /* Like note_stores, but allow the callback to have side effects on the rtl
5665 (like the note_stores of yore):
5666 Call FUN on each register or MEM that is stored into or clobbered by X.
5667 (X would be the pattern of an insn). DATA is an arbitrary pointer,
5668 ignored by note_stores, but passed to FUN.
5669 FUN may alter parts of the RTL.
5671 FUN receives three arguments:
5672 1. the REG, MEM, CC0 or PC being stored in or clobbered,
5673 2. the SET or CLOBBER rtx that does the store,
5674 3. the pointer DATA provided to note_stores.
5676 If the item being stored in or clobbered is a SUBREG of a hard register,
5677 the SUBREG will be passed. */
5679 /* For now. */ static
5681 walk_stores (rtx x
, void (*fun
) (rtx
, rtx
, void *), void *data
)
5685 if (GET_CODE (x
) == COND_EXEC
)
5686 x
= COND_EXEC_CODE (x
);
5688 if (GET_CODE (x
) == SET
|| GET_CODE (x
) == CLOBBER
)
5690 rtx dest
= SET_DEST (x
);
5692 while ((GET_CODE (dest
) == SUBREG
5693 && (!REG_P (SUBREG_REG (dest
))
5694 || REGNO (SUBREG_REG (dest
)) >= FIRST_PSEUDO_REGISTER
))
5695 || GET_CODE (dest
) == ZERO_EXTRACT
5696 || GET_CODE (dest
) == STRICT_LOW_PART
)
5697 dest
= XEXP (dest
, 0);
5699 /* If we have a PARALLEL, SET_DEST is a list of EXPR_LIST expressions,
5700 each of whose first operand is a register. */
5701 if (GET_CODE (dest
) == PARALLEL
)
5703 for (i
= XVECLEN (dest
, 0) - 1; i
>= 0; i
--)
5704 if (XEXP (XVECEXP (dest
, 0, i
), 0) != 0)
5705 (*fun
) (XEXP (XVECEXP (dest
, 0, i
), 0), x
, data
);
5708 (*fun
) (dest
, x
, data
);
5711 else if (GET_CODE (x
) == PARALLEL
)
5712 for (i
= XVECLEN (x
, 0) - 1; i
>= 0; i
--)
5713 walk_stores (XVECEXP (x
, 0, i
), fun
, data
);
5717 arc_pass_by_reference (cumulative_args_t ca_v ATTRIBUTE_UNUSED
,
5718 machine_mode mode ATTRIBUTE_UNUSED
,
5720 bool named ATTRIBUTE_UNUSED
)
5723 && (TREE_CODE (TYPE_SIZE (type
)) != INTEGER_CST
5724 || TREE_ADDRESSABLE (type
)));
5727 /* Implement TARGET_CAN_USE_DOLOOP_P. */
5730 arc_can_use_doloop_p (const widest_int
&iterations
, const widest_int
&,
5731 unsigned int loop_depth
, bool entered_at_top
)
5735 /* Setting up the loop with two sr instructions costs 6 cycles. */
5738 && wi::gtu_p (iterations
, 0)
5739 && wi::leu_p (iterations
, flag_pic
? 6 : 3))
5744 /* NULL if INSN insn is valid within a low-overhead loop.
5745 Otherwise return why doloop cannot be applied. */
5748 arc_invalid_within_doloop (const rtx_insn
*insn
)
5751 return "Function call in the loop.";
5755 static int arc_reorg_in_progress
= 0;
5757 /* ARC's machince specific reorg function. */
5768 cfun
->machine
->arc_reorg_started
= 1;
5769 arc_reorg_in_progress
= 1;
5771 /* Emit special sections for profiling. */
5774 section
*save_text_section
;
5776 int size
= get_max_uid () >> 4;
5777 htab_t htab
= htab_create (size
, unspec_prof_hash
, unspec_prof_htab_eq
,
5780 save_text_section
= in_section
;
5781 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
5782 if (NONJUMP_INSN_P (insn
))
5783 walk_stores (PATTERN (insn
), write_profile_sections
, htab
);
5784 if (htab_elements (htab
))
5786 switch_to_section (save_text_section
);
5790 /* Link up loop ends with their loop start. */
5792 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
5793 if (GET_CODE (insn
) == JUMP_INSN
5794 && recog_memoized (insn
) == CODE_FOR_doloop_end_i
)
5797 = as_a
<rtx_insn
*> (XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn
), 0, 0)), 1), 0));
5798 rtx num
= GEN_INT (CODE_LABEL_NUMBER (top_label
));
5799 rtx_insn
*lp
, *prev
= prev_nonnote_insn (top_label
);
5800 rtx_insn
*lp_simple
= NULL
;
5801 rtx_insn
*next
= NULL
;
5802 rtx op0
= XEXP (XVECEXP (PATTERN (insn
), 0, 1), 0);
5803 HOST_WIDE_INT loop_end_id
5804 = -INTVAL (XEXP (XVECEXP (PATTERN (insn
), 0, 4), 0));
5808 (lp
&& NONJUMP_INSN_P (lp
)
5809 && recog_memoized (lp
) != CODE_FOR_doloop_begin_i
);
5810 lp
= prev_nonnote_insn (lp
))
5812 if (!lp
|| !NONJUMP_INSN_P (lp
)
5813 || dead_or_set_regno_p (lp
, LP_COUNT
))
5815 for (prev
= next
= insn
, lp
= NULL
; prev
|| next
;)
5819 if (NONJUMP_INSN_P (prev
)
5820 && recog_memoized (prev
) == CODE_FOR_doloop_begin_i
5821 && (INTVAL (XEXP (XVECEXP (PATTERN (prev
), 0, 5), 0))
5827 else if (LABEL_P (prev
))
5829 prev
= prev_nonnote_insn (prev
);
5833 if (NONJUMP_INSN_P (next
)
5834 && recog_memoized (next
) == CODE_FOR_doloop_begin_i
5835 && (INTVAL (XEXP (XVECEXP (PATTERN (next
), 0, 5), 0))
5841 next
= next_nonnote_insn (next
);
5848 if (lp
&& !dead_or_set_regno_p (lp
, LP_COUNT
))
5850 rtx begin_cnt
= XEXP (XVECEXP (PATTERN (lp
), 0 ,3), 0);
5851 if (INTVAL (XEXP (XVECEXP (PATTERN (lp
), 0, 4), 0)))
5852 /* The loop end insn has been duplicated. That can happen
5853 when there is a conditional block at the very end of
5856 /* If Register allocation failed to allocate to the right
5857 register, There is no point into teaching reload to
5858 fix this up with reloads, as that would cost more
5859 than using an ordinary core register with the
5860 doloop_fallback pattern. */
5861 if ((true_regnum (op0
) != LP_COUNT
|| !REG_P (begin_cnt
))
5862 /* Likewise, if the loop setup is evidently inside the loop,
5864 || (!lp_simple
&& lp
!= next
&& !seen_label
))
5869 /* It is common that the optimizers copy the loop count from
5870 another register, and doloop_begin_i is stuck with the
5871 source of the move. Making doloop_begin_i only accept "l"
5872 is nonsentical, as this then makes reload evict the pseudo
5873 used for the loop end. The underlying cause is that the
5874 optimizers don't understand that the register allocation for
5875 doloop_begin_i should be treated as part of the loop.
5876 Try to work around this problem by verifying the previous
5878 if (true_regnum (begin_cnt
) != LP_COUNT
)
5883 for (mov
= prev_nonnote_insn (lp
); mov
;
5884 mov
= prev_nonnote_insn (mov
))
5886 if (!NONJUMP_INSN_P (mov
))
5888 else if ((set
= single_set (mov
))
5889 && rtx_equal_p (SET_SRC (set
), begin_cnt
)
5890 && rtx_equal_p (SET_DEST (set
), op0
))
5895 XEXP (XVECEXP (PATTERN (lp
), 0 ,3), 0) = op0
;
5896 note
= find_regno_note (lp
, REG_DEAD
, REGNO (begin_cnt
));
5898 remove_note (lp
, note
);
5906 XEXP (XVECEXP (PATTERN (insn
), 0, 4), 0) = num
;
5907 XEXP (XVECEXP (PATTERN (lp
), 0, 4), 0) = num
;
5909 XEXP (XVECEXP (PATTERN (lp
), 0, 6), 0) = const2_rtx
;
5910 else if (!lp_simple
)
5911 XEXP (XVECEXP (PATTERN (lp
), 0, 6), 0) = const1_rtx
;
5912 else if (prev
!= lp
)
5915 add_insn_after (lp
, prev
, NULL
);
5919 XEXP (XVECEXP (PATTERN (lp
), 0, 7), 0)
5920 = gen_rtx_LABEL_REF (Pmode
, top_label
);
5921 add_reg_note (lp
, REG_LABEL_OPERAND
, top_label
);
5922 LABEL_NUSES (top_label
)++;
5924 /* We can avoid tedious loop start / end setting for empty loops
5925 be merely setting the loop count to its final value. */
5926 if (next_active_insn (top_label
) == insn
)
5929 = gen_rtx_SET (VOIDmode
,
5930 XEXP (XVECEXP (PATTERN (lp
), 0, 3), 0),
5933 rtx_insn
*lc_set_insn
= emit_insn_before (lc_set
, insn
);
5938 /* If the loop is non-empty with zero length, we can't make it
5939 a zero-overhead loop. That can happen for empty asms. */
5944 for (scan
= top_label
;
5945 (scan
&& scan
!= insn
5946 && (!NONJUMP_INSN_P (scan
) || !get_attr_length (scan
)));
5947 scan
= NEXT_INSN (scan
));
5957 /* Sometimes the loop optimizer makes a complete hash of the
5958 loop. If it were only that the loop is not entered at the
5959 top, we could fix this up by setting LP_START with SR .
5960 However, if we can't find the loop begin were it should be,
5961 chances are that it does not even dominate the loop, but is
5962 inside the loop instead. Using SR there would kill
5964 We use the doloop_fallback pattern here, which executes
5965 in two cycles on the ARC700 when predicted correctly. */
5969 rtx op3
= XEXP (XVECEXP (PATTERN (insn
), 0, 5), 0);
5971 emit_insn_before (gen_move_insn (op3
, op0
), insn
);
5973 = gen_doloop_fallback_m (op3
, JUMP_LABEL (insn
), op0
);
5976 XVEC (PATTERN (insn
), 0)
5977 = gen_rtvec (2, XVECEXP (PATTERN (insn
), 0, 0),
5978 XVECEXP (PATTERN (insn
), 0, 1));
5979 INSN_CODE (insn
) = -1;
5984 /* FIXME: should anticipate ccfsm action, generate special patterns for
5985 to-be-deleted branches that have no delay slot and have at least the
5986 length of the size increase forced on other insns that are conditionalized.
5987 This can also have an insn_list inside that enumerates insns which are
5988 not actually conditionalized because the destinations are dead in the
5990 Could also tag branches that we want to be unaligned if they get no delay
5991 slot, or even ones that we don't want to do delay slot sheduling for
5992 because we can unalign them.
5994 However, there are cases when conditional execution is only possible after
5995 delay slot scheduling:
5997 - If a delay slot is filled with a nocond/set insn from above, the previous
5998 basic block can become elegible for conditional execution.
5999 - If a delay slot is filled with a nocond insn from the fall-through path,
6000 the branch with that delay slot can become eligble for conditional
6001 execution (however, with the same sort of data flow analysis that dbr
6002 does, we could have figured out before that we don't need to
6003 conditionalize this insn.)
6004 - If a delay slot insn is filled with an insn from the target, the
6005 target label gets its uses decremented (even deleted if falling to zero),
6006 thus possibly creating more condexec opportunities there.
6007 Therefore, we should still be prepared to apply condexec optimization on
6008 non-prepared branches if the size increase of conditionalized insns is no
6009 more than the size saved from eliminating the branch. An invocation option
6010 could also be used to reserve a bit of extra size for condbranches so that
6011 this'll work more often (could also test in arc_reorg if the block is
6012 'close enough' to be eligible for condexec to make this likely, and
6013 estimate required size increase). */
6014 /* Generate BRcc insns, by combining cmp and Bcc insns wherever possible. */
6015 if (TARGET_NO_BRCC_SET
)
6020 init_insn_lengths();
6023 if (optimize
> 1 && !TARGET_NO_COND_EXEC
)
6026 unsigned int flags
= pass_data_arc_ifcvt
.todo_flags_finish
;
6027 df_finish_pass ((flags
& TODO_df_verify
) != 0);
6030 /* Call shorten_branches to calculate the insn lengths. */
6031 shorten_branches (get_insns());
6032 cfun
->machine
->ccfsm_current_insn
= NULL_RTX
;
6034 if (!INSN_ADDRESSES_SET_P())
6035 fatal_error ("Insn addresses not set after shorten_branches");
6037 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
6040 enum attr_type insn_type
;
6042 /* If a non-jump insn (or a casesi jump table), continue. */
6043 if (GET_CODE (insn
) != JUMP_INSN
||
6044 GET_CODE (PATTERN (insn
)) == ADDR_VEC
6045 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
6048 /* If we already have a brcc, note if it is suitable for brcc_s.
6049 Be a bit generous with the brcc_s range so that we can take
6050 advantage of any code shortening from delay slot scheduling. */
6051 if (recog_memoized (insn
) == CODE_FOR_cbranchsi4_scratch
)
6053 rtx pat
= PATTERN (insn
);
6054 rtx op
= XEXP (SET_SRC (XVECEXP (pat
, 0, 0)), 0);
6055 rtx
*ccp
= &XEXP (XVECEXP (pat
, 0, 1), 0);
6057 offset
= branch_dest (insn
) - INSN_ADDRESSES (INSN_UID (insn
));
6058 if ((offset
>= -140 && offset
< 140)
6059 && rtx_equal_p (XEXP (op
, 1), const0_rtx
)
6060 && compact_register_operand (XEXP (op
, 0), VOIDmode
)
6061 && equality_comparison_operator (op
, VOIDmode
))
6062 PUT_MODE (*ccp
, CC_Zmode
);
6063 else if (GET_MODE (*ccp
) == CC_Zmode
)
6064 PUT_MODE (*ccp
, CC_ZNmode
);
6067 if ((insn_type
= get_attr_type (insn
)) == TYPE_BRCC
6068 || insn_type
== TYPE_BRCC_NO_DELAY_SLOT
)
6071 /* OK. so we have a jump insn. */
6072 /* We need to check that it is a bcc. */
6073 /* Bcc => set (pc) (if_then_else ) */
6074 pattern
= PATTERN (insn
);
6075 if (GET_CODE (pattern
) != SET
6076 || GET_CODE (SET_SRC (pattern
)) != IF_THEN_ELSE
6077 || ANY_RETURN_P (XEXP (SET_SRC (pattern
), 1)))
6080 /* Now check if the jump is beyond the s9 range. */
6081 if (CROSSING_JUMP_P (insn
))
6083 offset
= branch_dest (insn
) - INSN_ADDRESSES (INSN_UID (insn
));
6085 if(offset
> 253 || offset
< -254)
6088 pc_target
= SET_SRC (pattern
);
6090 /* Now go back and search for the set cc insn. */
6092 label
= XEXP (pc_target
, 1);
6096 rtx_insn
*scan
, *link_insn
= NULL
;
6098 for (scan
= PREV_INSN (insn
);
6099 scan
&& GET_CODE (scan
) != CODE_LABEL
;
6100 scan
= PREV_INSN (scan
))
6102 if (! INSN_P (scan
))
6104 pat
= PATTERN (scan
);
6105 if (GET_CODE (pat
) == SET
6106 && cc_register (SET_DEST (pat
), VOIDmode
))
6115 /* Check if this is a data dependency. */
6117 rtx op
, cc_clob_rtx
, op0
, op1
, brcc_insn
, note
;
6120 /* Ok this is the set cc. copy args here. */
6121 op
= XEXP (pc_target
, 0);
6123 op0
= cmp0
= XEXP (SET_SRC (pat
), 0);
6124 op1
= cmp1
= XEXP (SET_SRC (pat
), 1);
6125 if (GET_CODE (op0
) == ZERO_EXTRACT
6126 && XEXP (op0
, 1) == const1_rtx
6127 && (GET_CODE (op
) == EQ
6128 || GET_CODE (op
) == NE
))
6130 /* btst / b{eq,ne} -> bbit{0,1} */
6131 op0
= XEXP (cmp0
, 0);
6132 op1
= XEXP (cmp0
, 2);
6134 else if (!register_operand (op0
, VOIDmode
)
6135 || !general_operand (op1
, VOIDmode
))
6137 /* Be careful not to break what cmpsfpx_raw is
6138 trying to create for checking equality of
6139 single-precision floats. */
6140 else if (TARGET_SPFP
6141 && GET_MODE (op0
) == SFmode
6142 && GET_MODE (op1
) == SFmode
)
6145 /* None of the two cmp operands should be set between the
6146 cmp and the branch. */
6147 if (reg_set_between_p (op0
, link_insn
, insn
))
6150 if (reg_set_between_p (op1
, link_insn
, insn
))
6153 /* Since the MODE check does not work, check that this is
6154 CC reg's last set location before insn, and also no
6155 instruction between the cmp and branch uses the
6157 if ((reg_set_between_p (SET_DEST (pat
), link_insn
, insn
))
6158 || (reg_used_between_p (SET_DEST (pat
), link_insn
, insn
)))
6161 /* CC reg should be dead after insn. */
6162 if (!find_regno_note (insn
, REG_DEAD
, CC_REG
))
6165 op
= gen_rtx_fmt_ee (GET_CODE (op
),
6166 GET_MODE (op
), cmp0
, cmp1
);
6167 /* If we create a LIMM where there was none before,
6168 we only benefit if we can avoid a scheduling bubble
6169 for the ARC600. Otherwise, we'd only forgo chances
6170 at short insn generation, and risk out-of-range
6172 if (!brcc_nolimm_operator (op
, VOIDmode
)
6173 && !long_immediate_operand (op1
, VOIDmode
)
6175 || next_active_insn (link_insn
) != insn
))
6178 /* Emit bbit / brcc (or brcc_s if possible).
6179 CC_Zmode indicates that brcc_s is possible. */
6182 cc_clob_rtx
= gen_rtx_REG (CC_ZNmode
, CC_REG
);
6183 else if ((offset
>= -140 && offset
< 140)
6184 && rtx_equal_p (op1
, const0_rtx
)
6185 && compact_register_operand (op0
, VOIDmode
)
6186 && (GET_CODE (op
) == EQ
6187 || GET_CODE (op
) == NE
))
6188 cc_clob_rtx
= gen_rtx_REG (CC_Zmode
, CC_REG
);
6190 cc_clob_rtx
= gen_rtx_REG (CCmode
, CC_REG
);
6193 = gen_rtx_IF_THEN_ELSE (VOIDmode
, op
, label
, pc_rtx
);
6194 brcc_insn
= gen_rtx_SET (VOIDmode
, pc_rtx
, brcc_insn
);
6195 cc_clob_rtx
= gen_rtx_CLOBBER (VOIDmode
, cc_clob_rtx
);
6198 (VOIDmode
, gen_rtvec (2, brcc_insn
, cc_clob_rtx
));
6199 brcc_insn
= emit_jump_insn_before (brcc_insn
, insn
);
6201 JUMP_LABEL (brcc_insn
) = JUMP_LABEL (insn
);
6202 note
= find_reg_note (insn
, REG_BR_PROB
, 0);
6205 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6206 REG_NOTES (brcc_insn
) = note
;
6208 note
= find_reg_note (link_insn
, REG_DEAD
, op0
);
6211 remove_note (link_insn
, note
);
6212 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6213 REG_NOTES (brcc_insn
) = note
;
6215 note
= find_reg_note (link_insn
, REG_DEAD
, op1
);
6218 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6219 REG_NOTES (brcc_insn
) = note
;
6224 /* Delete the bcc insn. */
6225 set_insn_deleted (insn
);
6227 /* Delete the cmp insn. */
6228 set_insn_deleted (link_insn
);
6233 /* Clear out insn_addresses. */
6234 INSN_ADDRESSES_FREE ();
6238 if (INSN_ADDRESSES_SET_P())
6239 fatal_error ("insn addresses not freed");
6241 arc_reorg_in_progress
= 0;
6244 /* Check if the operands are valid for BRcc.d generation
6245 Valid Brcc.d patterns are
6249 For cc={GT, LE, GTU, LEU}, u6=63 can not be allowed,
6250 since they are encoded by the assembler as {GE, LT, HS, LS} 64, which
6251 does not have a delay slot
6253 Assumed precondition: Second operand is either a register or a u6 value. */
6256 valid_brcc_with_delay_p (rtx
*operands
)
6258 if (optimize_size
&& GET_MODE (operands
[4]) == CC_Zmode
)
6260 return brcc_nolimm_operator (operands
[0], VOIDmode
);
6263 /* ??? Hack. This should no really be here. See PR32143. */
6265 arc_decl_anon_ns_mem_p (const_tree decl
)
6269 if (decl
== NULL_TREE
|| decl
== error_mark_node
)
6271 if (TREE_CODE (decl
) == NAMESPACE_DECL
6272 && DECL_NAME (decl
) == NULL_TREE
)
6274 /* Classes and namespaces inside anonymous namespaces have
6275 TREE_PUBLIC == 0, so we can shortcut the search. */
6276 else if (TYPE_P (decl
))
6277 return (TREE_PUBLIC (TYPE_NAME (decl
)) == 0);
6278 else if (TREE_CODE (decl
) == NAMESPACE_DECL
)
6279 return (TREE_PUBLIC (decl
) == 0);
6281 decl
= DECL_CONTEXT (decl
);
6285 /* Implement TARGET_IN_SMALL_DATA_P. Return true if it would be safe to
6286 access DECL using %gp_rel(...)($gp). */
6289 arc_in_small_data_p (const_tree decl
)
6293 if (TREE_CODE (decl
) == STRING_CST
|| TREE_CODE (decl
) == FUNCTION_DECL
)
6297 /* We don't yet generate small-data references for -mabicalls. See related
6298 -G handling in override_options. */
6299 if (TARGET_NO_SDATA_SET
)
6302 if (TREE_CODE (decl
) == VAR_DECL
&& DECL_SECTION_NAME (decl
) != 0)
6306 /* Reject anything that isn't in a known small-data section. */
6307 name
= DECL_SECTION_NAME (decl
);
6308 if (strcmp (name
, ".sdata") != 0 && strcmp (name
, ".sbss") != 0)
6311 /* If a symbol is defined externally, the assembler will use the
6312 usual -G rules when deciding how to implement macros. */
6313 if (!DECL_EXTERNAL (decl
))
6316 /* Only global variables go into sdata section for now. */
6319 /* Don't put constants into the small data section: we want them
6320 to be in ROM rather than RAM. */
6321 if (TREE_CODE (decl
) != VAR_DECL
)
6324 if (TREE_READONLY (decl
)
6325 && !TREE_SIDE_EFFECTS (decl
)
6326 && (!DECL_INITIAL (decl
) || TREE_CONSTANT (DECL_INITIAL (decl
))))
6329 /* TREE_PUBLIC might change after the first call, because of the patch
6331 if (default_binds_local_p_1 (decl
, 1)
6332 || arc_decl_anon_ns_mem_p (decl
))
6335 /* To ensure -mvolatile-cache works
6336 ld.di does not have a gp-relative variant. */
6337 if (TREE_THIS_VOLATILE (decl
))
6341 /* Disable sdata references to weak variables. */
6342 if (DECL_WEAK (decl
))
6345 size
= int_size_in_bytes (TREE_TYPE (decl
));
6347 /* if (AGGREGATE_TYPE_P (TREE_TYPE (decl))) */
6350 /* Allow only <=4B long data types into sdata. */
6351 return (size
> 0 && size
<= 4);
6354 /* Return true if X is a small data address that can be rewritten
6358 arc_rewrite_small_data_p (const_rtx x
)
6360 if (GET_CODE (x
) == CONST
)
6363 if (GET_CODE (x
) == PLUS
)
6365 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
6369 return (GET_CODE (x
) == SYMBOL_REF
6370 && SYMBOL_REF_SMALL_P(x
));
6373 /* If possible, rewrite OP so that it refers to small data using
6374 explicit relocations. */
6377 arc_rewrite_small_data (rtx op
)
6379 op
= copy_insn (op
);
6380 subrtx_ptr_iterator::array_type array
;
6381 FOR_EACH_SUBRTX_PTR (iter
, array
, &op
, ALL
)
6384 if (arc_rewrite_small_data_p (*loc
))
6386 gcc_assert (SDATA_BASE_REGNUM
== PIC_OFFSET_TABLE_REGNUM
);
6387 *loc
= gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, *loc
);
6390 if (GET_CODE (op
) == MEM
&& &XEXP (op
, 0) == loc
)
6392 else if (GET_CODE (op
) == MEM
6393 && GET_CODE (XEXP (op
, 0)) == PLUS
6394 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == MULT
)
6395 *loc
= force_reg (Pmode
, *loc
);
6399 iter
.skip_subrtxes ();
6401 else if (GET_CODE (*loc
) == PLUS
6402 && rtx_equal_p (XEXP (*loc
, 0), pic_offset_table_rtx
))
6403 iter
.skip_subrtxes ();
6408 /* Return true if OP refers to small data symbols directly, not through
6412 small_data_pattern (rtx op
, machine_mode
)
6414 if (GET_CODE (op
) == SEQUENCE
)
6416 subrtx_iterator::array_type array
;
6417 FOR_EACH_SUBRTX (iter
, array
, op
, ALL
)
6419 const_rtx x
= *iter
;
6420 if (GET_CODE (x
) == PLUS
6421 && rtx_equal_p (XEXP (x
, 0), pic_offset_table_rtx
))
6422 iter
.skip_subrtxes ();
6423 else if (arc_rewrite_small_data_p (x
))
6429 /* Return true if OP is an acceptable memory operand for ARCompact
6430 16-bit gp-relative load instructions.
6431 op shd look like : [r26, symref@sda]
6432 i.e. (mem (plus (reg 26) (symref with smalldata flag set))
6434 /* volatile cache option still to be handled. */
6437 compact_sda_memory_operand (rtx op
, machine_mode mode
)
6442 /* Eliminate non-memory operations. */
6443 if (GET_CODE (op
) != MEM
)
6446 if (mode
== VOIDmode
)
6447 mode
= GET_MODE (op
);
6449 size
= GET_MODE_SIZE (mode
);
6451 /* dword operations really put out 2 instructions, so eliminate them. */
6452 if (size
> UNITS_PER_WORD
)
6455 /* Decode the address now. */
6456 addr
= XEXP (op
, 0);
6458 return LEGITIMATE_SMALL_DATA_ADDRESS_P (addr
);
6461 /* Implement ASM_OUTPUT_ALIGNED_DECL_LOCAL. */
6464 arc_asm_output_aligned_decl_local (FILE * stream
, tree decl
, const char * name
,
6465 unsigned HOST_WIDE_INT size
,
6466 unsigned HOST_WIDE_INT align
,
6467 unsigned HOST_WIDE_INT globalize_p
)
6469 int in_small_data
= arc_in_small_data_p (decl
);
6472 switch_to_section (get_named_section (NULL
, ".sbss", 0));
6473 /* named_section (0,".sbss",0); */
6475 switch_to_section (bss_section
);
6478 (*targetm
.asm_out
.globalize_label
) (stream
, name
);
6480 ASM_OUTPUT_ALIGN (stream
, floor_log2 ((align
) / BITS_PER_UNIT
));
6481 ASM_OUTPUT_TYPE_DIRECTIVE (stream
, name
, "object");
6482 ASM_OUTPUT_SIZE_DIRECTIVE (stream
, name
, size
);
6483 ASM_OUTPUT_LABEL (stream
, name
);
6486 ASM_OUTPUT_SKIP (stream
, size
);
6522 /* SIMD builtins support. */
6523 enum simd_insn_args_type
{
6546 struct builtin_description
6548 enum simd_insn_args_type args_type
;
6549 const enum insn_code icode
;
6550 const char * const name
;
6551 const enum arc_builtins code
;
6554 static const struct builtin_description arc_simd_builtin_desc_list
[] =
6556 /* VVV builtins go first. */
6557 #define SIMD_BUILTIN(type, code, string, builtin) \
6558 { type,CODE_FOR_##code, "__builtin_arc_" string, \
6559 ARC_SIMD_BUILTIN_##builtin },
6561 SIMD_BUILTIN (Va_Vb_Vc
, vaddaw_insn
, "vaddaw", VADDAW
)
6562 SIMD_BUILTIN (Va_Vb_Vc
, vaddw_insn
, "vaddw", VADDW
)
6563 SIMD_BUILTIN (Va_Vb_Vc
, vavb_insn
, "vavb", VAVB
)
6564 SIMD_BUILTIN (Va_Vb_Vc
, vavrb_insn
, "vavrb", VAVRB
)
6565 SIMD_BUILTIN (Va_Vb_Vc
, vdifaw_insn
, "vdifaw", VDIFAW
)
6566 SIMD_BUILTIN (Va_Vb_Vc
, vdifw_insn
, "vdifw", VDIFW
)
6567 SIMD_BUILTIN (Va_Vb_Vc
, vmaxaw_insn
, "vmaxaw", VMAXAW
)
6568 SIMD_BUILTIN (Va_Vb_Vc
, vmaxw_insn
, "vmaxw", VMAXW
)
6569 SIMD_BUILTIN (Va_Vb_Vc
, vminaw_insn
, "vminaw", VMINAW
)
6570 SIMD_BUILTIN (Va_Vb_Vc
, vminw_insn
, "vminw", VMINW
)
6571 SIMD_BUILTIN (Va_Vb_Vc
, vmulaw_insn
, "vmulaw", VMULAW
)
6572 SIMD_BUILTIN (Va_Vb_Vc
, vmulfaw_insn
, "vmulfaw", VMULFAW
)
6573 SIMD_BUILTIN (Va_Vb_Vc
, vmulfw_insn
, "vmulfw", VMULFW
)
6574 SIMD_BUILTIN (Va_Vb_Vc
, vmulw_insn
, "vmulw", VMULW
)
6575 SIMD_BUILTIN (Va_Vb_Vc
, vsubaw_insn
, "vsubaw", VSUBAW
)
6576 SIMD_BUILTIN (Va_Vb_Vc
, vsubw_insn
, "vsubw", VSUBW
)
6577 SIMD_BUILTIN (Va_Vb_Vc
, vsummw_insn
, "vsummw", VSUMMW
)
6578 SIMD_BUILTIN (Va_Vb_Vc
, vand_insn
, "vand", VAND
)
6579 SIMD_BUILTIN (Va_Vb_Vc
, vandaw_insn
, "vandaw", VANDAW
)
6580 SIMD_BUILTIN (Va_Vb_Vc
, vbic_insn
, "vbic", VBIC
)
6581 SIMD_BUILTIN (Va_Vb_Vc
, vbicaw_insn
, "vbicaw", VBICAW
)
6582 SIMD_BUILTIN (Va_Vb_Vc
, vor_insn
, "vor", VOR
)
6583 SIMD_BUILTIN (Va_Vb_Vc
, vxor_insn
, "vxor", VXOR
)
6584 SIMD_BUILTIN (Va_Vb_Vc
, vxoraw_insn
, "vxoraw", VXORAW
)
6585 SIMD_BUILTIN (Va_Vb_Vc
, veqw_insn
, "veqw", VEQW
)
6586 SIMD_BUILTIN (Va_Vb_Vc
, vlew_insn
, "vlew", VLEW
)
6587 SIMD_BUILTIN (Va_Vb_Vc
, vltw_insn
, "vltw", VLTW
)
6588 SIMD_BUILTIN (Va_Vb_Vc
, vnew_insn
, "vnew", VNEW
)
6589 SIMD_BUILTIN (Va_Vb_Vc
, vmr1aw_insn
, "vmr1aw", VMR1AW
)
6590 SIMD_BUILTIN (Va_Vb_Vc
, vmr1w_insn
, "vmr1w", VMR1W
)
6591 SIMD_BUILTIN (Va_Vb_Vc
, vmr2aw_insn
, "vmr2aw", VMR2AW
)
6592 SIMD_BUILTIN (Va_Vb_Vc
, vmr2w_insn
, "vmr2w", VMR2W
)
6593 SIMD_BUILTIN (Va_Vb_Vc
, vmr3aw_insn
, "vmr3aw", VMR3AW
)
6594 SIMD_BUILTIN (Va_Vb_Vc
, vmr3w_insn
, "vmr3w", VMR3W
)
6595 SIMD_BUILTIN (Va_Vb_Vc
, vmr4aw_insn
, "vmr4aw", VMR4AW
)
6596 SIMD_BUILTIN (Va_Vb_Vc
, vmr4w_insn
, "vmr4w", VMR4W
)
6597 SIMD_BUILTIN (Va_Vb_Vc
, vmr5aw_insn
, "vmr5aw", VMR5AW
)
6598 SIMD_BUILTIN (Va_Vb_Vc
, vmr5w_insn
, "vmr5w", VMR5W
)
6599 SIMD_BUILTIN (Va_Vb_Vc
, vmr6aw_insn
, "vmr6aw", VMR6AW
)
6600 SIMD_BUILTIN (Va_Vb_Vc
, vmr6w_insn
, "vmr6w", VMR6W
)
6601 SIMD_BUILTIN (Va_Vb_Vc
, vmr7aw_insn
, "vmr7aw", VMR7AW
)
6602 SIMD_BUILTIN (Va_Vb_Vc
, vmr7w_insn
, "vmr7w", VMR7W
)
6603 SIMD_BUILTIN (Va_Vb_Vc
, vmrb_insn
, "vmrb", VMRB
)
6604 SIMD_BUILTIN (Va_Vb_Vc
, vh264f_insn
, "vh264f", VH264F
)
6605 SIMD_BUILTIN (Va_Vb_Vc
, vh264ft_insn
, "vh264ft", VH264FT
)
6606 SIMD_BUILTIN (Va_Vb_Vc
, vh264fw_insn
, "vh264fw", VH264FW
)
6607 SIMD_BUILTIN (Va_Vb_Vc
, vvc1f_insn
, "vvc1f", VVC1F
)
6608 SIMD_BUILTIN (Va_Vb_Vc
, vvc1ft_insn
, "vvc1ft", VVC1FT
)
6610 SIMD_BUILTIN (Va_Vb_rlimm
, vbaddw_insn
, "vbaddw", VBADDW
)
6611 SIMD_BUILTIN (Va_Vb_rlimm
, vbmaxw_insn
, "vbmaxw", VBMAXW
)
6612 SIMD_BUILTIN (Va_Vb_rlimm
, vbminw_insn
, "vbminw", VBMINW
)
6613 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulaw_insn
, "vbmulaw", VBMULAW
)
6614 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulfw_insn
, "vbmulfw", VBMULFW
)
6615 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulw_insn
, "vbmulw", VBMULW
)
6616 SIMD_BUILTIN (Va_Vb_rlimm
, vbrsubw_insn
, "vbrsubw", VBRSUBW
)
6617 SIMD_BUILTIN (Va_Vb_rlimm
, vbsubw_insn
, "vbsubw", VBSUBW
)
6619 /* Va, Vb, Ic instructions. */
6620 SIMD_BUILTIN (Va_Vb_Ic
, vasrw_insn
, "vasrw", VASRW
)
6621 SIMD_BUILTIN (Va_Vb_Ic
, vsr8_insn
, "vsr8", VSR8
)
6622 SIMD_BUILTIN (Va_Vb_Ic
, vsr8aw_insn
, "vsr8aw", VSR8AW
)
6624 /* Va, Vb, u6 instructions. */
6625 SIMD_BUILTIN (Va_Vb_u6
, vasrrwi_insn
, "vasrrwi", VASRRWi
)
6626 SIMD_BUILTIN (Va_Vb_u6
, vasrsrwi_insn
, "vasrsrwi", VASRSRWi
)
6627 SIMD_BUILTIN (Va_Vb_u6
, vasrwi_insn
, "vasrwi", VASRWi
)
6628 SIMD_BUILTIN (Va_Vb_u6
, vasrpwbi_insn
, "vasrpwbi", VASRPWBi
)
6629 SIMD_BUILTIN (Va_Vb_u6
, vasrrpwbi_insn
,"vasrrpwbi", VASRRPWBi
)
6630 SIMD_BUILTIN (Va_Vb_u6
, vsr8awi_insn
, "vsr8awi", VSR8AWi
)
6631 SIMD_BUILTIN (Va_Vb_u6
, vsr8i_insn
, "vsr8i", VSR8i
)
6633 /* Va, Vb, u8 (simm) instructions. */
6634 SIMD_BUILTIN (Va_Vb_u8
, vmvaw_insn
, "vmvaw", VMVAW
)
6635 SIMD_BUILTIN (Va_Vb_u8
, vmvw_insn
, "vmvw", VMVW
)
6636 SIMD_BUILTIN (Va_Vb_u8
, vmvzw_insn
, "vmvzw", VMVZW
)
6637 SIMD_BUILTIN (Va_Vb_u8
, vd6tapf_insn
, "vd6tapf", VD6TAPF
)
6639 /* Va, rlimm, u8 (simm) instructions. */
6640 SIMD_BUILTIN (Va_rlimm_u8
, vmovaw_insn
, "vmovaw", VMOVAW
)
6641 SIMD_BUILTIN (Va_rlimm_u8
, vmovw_insn
, "vmovw", VMOVW
)
6642 SIMD_BUILTIN (Va_rlimm_u8
, vmovzw_insn
, "vmovzw", VMOVZW
)
6644 /* Va, Vb instructions. */
6645 SIMD_BUILTIN (Va_Vb
, vabsaw_insn
, "vabsaw", VABSAW
)
6646 SIMD_BUILTIN (Va_Vb
, vabsw_insn
, "vabsw", VABSW
)
6647 SIMD_BUILTIN (Va_Vb
, vaddsuw_insn
, "vaddsuw", VADDSUW
)
6648 SIMD_BUILTIN (Va_Vb
, vsignw_insn
, "vsignw", VSIGNW
)
6649 SIMD_BUILTIN (Va_Vb
, vexch1_insn
, "vexch1", VEXCH1
)
6650 SIMD_BUILTIN (Va_Vb
, vexch2_insn
, "vexch2", VEXCH2
)
6651 SIMD_BUILTIN (Va_Vb
, vexch4_insn
, "vexch4", VEXCH4
)
6652 SIMD_BUILTIN (Va_Vb
, vupbaw_insn
, "vupbaw", VUPBAW
)
6653 SIMD_BUILTIN (Va_Vb
, vupbw_insn
, "vupbw", VUPBW
)
6654 SIMD_BUILTIN (Va_Vb
, vupsbaw_insn
, "vupsbaw", VUPSBAW
)
6655 SIMD_BUILTIN (Va_Vb
, vupsbw_insn
, "vupsbw", VUPSBW
)
6657 /* DIb, rlimm, rlimm instructions. */
6658 SIMD_BUILTIN (Da_rlimm_rlimm
, vdirun_insn
, "vdirun", VDIRUN
)
6659 SIMD_BUILTIN (Da_rlimm_rlimm
, vdorun_insn
, "vdorun", VDORUN
)
6661 /* DIb, limm, rlimm instructions. */
6662 SIMD_BUILTIN (Da_u3_rlimm
, vdiwr_insn
, "vdiwr", VDIWR
)
6663 SIMD_BUILTIN (Da_u3_rlimm
, vdowr_insn
, "vdowr", VDOWR
)
6665 /* rlimm instructions. */
6666 SIMD_BUILTIN (void_rlimm
, vrec_insn
, "vrec", VREC
)
6667 SIMD_BUILTIN (void_rlimm
, vrun_insn
, "vrun", VRUN
)
6668 SIMD_BUILTIN (void_rlimm
, vrecrun_insn
, "vrecrun", VRECRUN
)
6669 SIMD_BUILTIN (void_rlimm
, vendrec_insn
, "vendrec", VENDREC
)
6671 /* Va, [Ib,u8] instructions. */
6672 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32wh_insn
, "vld32wh", VLD32WH
)
6673 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32wl_insn
, "vld32wl", VLD32WL
)
6674 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld64_insn
, "vld64", VLD64
)
6675 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32_insn
, "vld32", VLD32
)
6677 SIMD_BUILTIN (Va_Ib_u8
, vld64w_insn
, "vld64w", VLD64W
)
6678 SIMD_BUILTIN (Va_Ib_u8
, vld128_insn
, "vld128", VLD128
)
6679 SIMD_BUILTIN (void_Va_Ib_u8
, vst128_insn
, "vst128", VST128
)
6680 SIMD_BUILTIN (void_Va_Ib_u8
, vst64_insn
, "vst64", VST64
)
6682 /* Va, [Ib, u8] instructions. */
6683 SIMD_BUILTIN (void_Va_u3_Ib_u8
, vst16_n_insn
, "vst16_n", VST16_N
)
6684 SIMD_BUILTIN (void_Va_u3_Ib_u8
, vst32_n_insn
, "vst32_n", VST32_N
)
6686 SIMD_BUILTIN (void_u6
, vinti_insn
, "vinti", VINTI
)
6690 arc_init_simd_builtins (void)
6693 tree endlink
= void_list_node
;
6694 tree V8HI_type_node
= build_vector_type_for_mode (intHI_type_node
, V8HImode
);
6696 tree v8hi_ftype_v8hi_v8hi
6697 = build_function_type (V8HI_type_node
,
6698 tree_cons (NULL_TREE
, V8HI_type_node
,
6699 tree_cons (NULL_TREE
, V8HI_type_node
,
6701 tree v8hi_ftype_v8hi_int
6702 = build_function_type (V8HI_type_node
,
6703 tree_cons (NULL_TREE
, V8HI_type_node
,
6704 tree_cons (NULL_TREE
, integer_type_node
,
6707 tree v8hi_ftype_v8hi_int_int
6708 = build_function_type (V8HI_type_node
,
6709 tree_cons (NULL_TREE
, V8HI_type_node
,
6710 tree_cons (NULL_TREE
, integer_type_node
,
6711 tree_cons (NULL_TREE
,
6715 tree void_ftype_v8hi_int_int
6716 = build_function_type (void_type_node
,
6717 tree_cons (NULL_TREE
, V8HI_type_node
,
6718 tree_cons (NULL_TREE
, integer_type_node
,
6719 tree_cons (NULL_TREE
,
6723 tree void_ftype_v8hi_int_int_int
6724 = (build_function_type
6726 tree_cons (NULL_TREE
, V8HI_type_node
,
6727 tree_cons (NULL_TREE
, integer_type_node
,
6728 tree_cons (NULL_TREE
, integer_type_node
,
6729 tree_cons (NULL_TREE
,
6733 tree v8hi_ftype_int_int
6734 = build_function_type (V8HI_type_node
,
6735 tree_cons (NULL_TREE
, integer_type_node
,
6736 tree_cons (NULL_TREE
, integer_type_node
,
6739 tree void_ftype_int_int
6740 = build_function_type (void_type_node
,
6741 tree_cons (NULL_TREE
, integer_type_node
,
6742 tree_cons (NULL_TREE
, integer_type_node
,
6746 = build_function_type (void_type_node
,
6747 tree_cons (NULL_TREE
, integer_type_node
, endlink
));
6749 tree v8hi_ftype_v8hi
6750 = build_function_type (V8HI_type_node
, tree_cons (NULL_TREE
, V8HI_type_node
,
6753 /* These asserts have been introduced to ensure that the order of builtins
6754 does not get messed up, else the initialization goes wrong. */
6755 gcc_assert (arc_simd_builtin_desc_list
[0].args_type
== Va_Vb_Vc
);
6756 for (i
=0; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Vc
; i
++)
6757 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6758 v8hi_ftype_v8hi_v8hi
, arc_simd_builtin_desc_list
[i
].code
);
6760 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_rlimm
);
6761 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_rlimm
; i
++)
6762 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6763 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6765 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic
);
6766 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic
; i
++)
6767 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6768 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6770 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u6
);
6771 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u6
; i
++)
6772 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6773 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6775 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u8
);
6776 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u8
; i
++)
6777 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6778 v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
6780 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_rlimm_u8
);
6781 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_rlimm_u8
; i
++)
6782 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6783 v8hi_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6785 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb
);
6786 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb
; i
++)
6787 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6788 v8hi_ftype_v8hi
, arc_simd_builtin_desc_list
[i
].code
);
6790 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Da_rlimm_rlimm
);
6791 for (; arc_simd_builtin_desc_list
[i
].args_type
== Da_rlimm_rlimm
; i
++)
6792 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6793 void_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6795 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Da_u3_rlimm
);
6796 for (; arc_simd_builtin_desc_list
[i
].args_type
== Da_u3_rlimm
; i
++)
6797 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6798 void_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6800 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_rlimm
);
6801 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_rlimm
; i
++)
6802 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6803 void_ftype_int
, arc_simd_builtin_desc_list
[i
].code
);
6805 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic_u8
);
6806 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic_u8
; i
++)
6807 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6808 v8hi_ftype_v8hi_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6810 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Ib_u8
);
6811 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Ib_u8
; i
++)
6812 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6813 v8hi_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6815 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_Va_Ib_u8
);
6816 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_Va_Ib_u8
; i
++)
6817 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6818 void_ftype_v8hi_int_int
, arc_simd_builtin_desc_list
[i
].code
);
6820 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_Va_u3_Ib_u8
);
6821 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_Va_u3_Ib_u8
; i
++)
6822 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6823 void_ftype_v8hi_int_int_int
,
6824 arc_simd_builtin_desc_list
[i
].code
);
6826 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_u6
);
6827 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_u6
; i
++)
6828 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
,
6829 void_ftype_int
, arc_simd_builtin_desc_list
[i
].code
);
6831 gcc_assert(i
== ARRAY_SIZE (arc_simd_builtin_desc_list
));
6834 /* Helper function of arc_expand_builtin; has the same parameters,
6835 except that EXP is now known to be a call to a simd builtin. */
6838 arc_expand_simd_builtin (tree exp
,
6840 rtx subtarget ATTRIBUTE_UNUSED
,
6841 machine_mode mode ATTRIBUTE_UNUSED
,
6842 int ignore ATTRIBUTE_UNUSED
)
6844 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
6856 int fcode
= DECL_FUNCTION_CODE (fndecl
);
6863 const struct builtin_description
* d
;
6865 for (i
= 0, d
= arc_simd_builtin_desc_list
;
6866 i
< ARRAY_SIZE (arc_simd_builtin_desc_list
); i
++, d
++)
6867 if (d
->code
== (const enum arc_builtins
) fcode
)
6870 /* We must get an entry here. */
6871 gcc_assert (i
< ARRAY_SIZE (arc_simd_builtin_desc_list
));
6873 switch (d
->args_type
)
6877 arg0
= CALL_EXPR_ARG (exp
, 0);
6878 arg1
= CALL_EXPR_ARG (exp
, 1);
6879 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6880 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6882 target
= gen_reg_rtx (V8HImode
);
6883 mode0
= insn_data
[icode
].operand
[1].mode
;
6884 mode1
= insn_data
[icode
].operand
[2].mode
;
6886 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6887 op0
= copy_to_mode_reg (mode0
, op0
);
6889 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6890 op1
= copy_to_mode_reg (mode1
, op1
);
6892 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
6902 arg0
= CALL_EXPR_ARG (exp
, 0);
6903 arg1
= CALL_EXPR_ARG (exp
, 1);
6904 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6905 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6907 target
= gen_reg_rtx (V8HImode
);
6908 mode0
= insn_data
[icode
].operand
[1].mode
;
6909 mode1
= insn_data
[icode
].operand
[2].mode
;
6911 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6912 op0
= copy_to_mode_reg (mode0
, op0
);
6914 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
)
6915 || (d
->args_type
== Va_Vb_u6
&& !UNSIGNED_INT6 (INTVAL (op1
)))
6916 || (d
->args_type
== Va_Vb_u8
&& !UNSIGNED_INT8 (INTVAL (op1
))))
6917 error ("operand 2 of %s instruction should be an unsigned %d-bit value",
6919 (d
->args_type
== Va_Vb_u6
)? 6: 8);
6921 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
6930 arg0
= CALL_EXPR_ARG (exp
, 0);
6931 arg1
= CALL_EXPR_ARG (exp
, 1);
6932 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6933 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6935 target
= gen_reg_rtx (V8HImode
);
6936 mode0
= insn_data
[icode
].operand
[1].mode
;
6937 mode1
= insn_data
[icode
].operand
[2].mode
;
6939 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6940 op0
= copy_to_mode_reg (mode0
, op0
);
6942 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6943 || !(UNSIGNED_INT8 (INTVAL (op1
))))
6944 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
6947 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
6956 arg0
= CALL_EXPR_ARG (exp
, 0);
6957 arg1
= CALL_EXPR_ARG (exp
, 1);
6958 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6959 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
6960 op2
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
);
6962 target
= gen_reg_rtx (V8HImode
);
6963 mode0
= insn_data
[icode
].operand
[1].mode
;
6964 mode1
= insn_data
[icode
].operand
[2].mode
;
6966 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6967 op0
= copy_to_mode_reg (mode0
, op0
);
6969 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6970 || !(UNSIGNED_INT3 (INTVAL (op1
))))
6971 error ("operand 2 of %s instruction should be an unsigned 3-bit value (I0-I7)",
6974 pat
= GEN_FCN (icode
) (target
, op0
, op1
, op2
);
6983 arg0
= CALL_EXPR_ARG (exp
, 0);
6984 arg1
= CALL_EXPR_ARG (exp
, 1);
6985 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6986 op1
= expand_expr (arg1
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
6988 target
= gen_reg_rtx (V8HImode
);
6989 mode0
= insn_data
[icode
].operand
[1].mode
;
6990 mode1
= insn_data
[icode
].operand
[2].mode
;
6992 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
6993 op0
= copy_to_mode_reg (mode0
, op0
);
6995 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
6996 op1
= copy_to_mode_reg (mode1
, op1
);
6998 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
7007 arg0
= CALL_EXPR_ARG (exp
, 0);
7008 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
7010 target
= gen_reg_rtx (V8HImode
);
7011 mode0
= insn_data
[icode
].operand
[1].mode
;
7013 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
7014 op0
= copy_to_mode_reg (mode0
, op0
);
7016 pat
= GEN_FCN (icode
) (target
, op0
);
7023 case Da_rlimm_rlimm
:
7025 arg0
= CALL_EXPR_ARG (exp
, 0);
7026 arg1
= CALL_EXPR_ARG (exp
, 1);
7027 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7028 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7031 if (icode
== CODE_FOR_vdirun_insn
)
7032 target
= gen_rtx_REG (SImode
, 131);
7033 else if (icode
== CODE_FOR_vdorun_insn
)
7034 target
= gen_rtx_REG (SImode
, 139);
7038 mode0
= insn_data
[icode
].operand
[1].mode
;
7039 mode1
= insn_data
[icode
].operand
[2].mode
;
7041 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
7042 op0
= copy_to_mode_reg (mode0
, op0
);
7044 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7045 op1
= copy_to_mode_reg (mode1
, op1
);
7048 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
7057 arg0
= CALL_EXPR_ARG (exp
, 0);
7058 arg1
= CALL_EXPR_ARG (exp
, 1);
7059 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7060 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7063 if (! (GET_CODE (op0
) == CONST_INT
)
7064 || !(UNSIGNED_INT3 (INTVAL (op0
))))
7065 error ("operand 1 of %s instruction should be an unsigned 3-bit value (DR0-DR7)",
7068 mode1
= insn_data
[icode
].operand
[1].mode
;
7070 if (icode
== CODE_FOR_vdiwr_insn
)
7071 target
= gen_rtx_REG (SImode
,
7072 ARC_FIRST_SIMD_DMA_CONFIG_IN_REG
+ INTVAL (op0
));
7073 else if (icode
== CODE_FOR_vdowr_insn
)
7074 target
= gen_rtx_REG (SImode
,
7075 ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG
+ INTVAL (op0
));
7079 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7080 op1
= copy_to_mode_reg (mode1
, op1
);
7082 pat
= GEN_FCN (icode
) (target
, op1
);
7091 arg0
= CALL_EXPR_ARG (exp
, 0);
7095 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7096 mode0
= insn_data
[icode
].operand
[0].mode
;
7098 /* op0 should be u6. */
7099 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
)
7100 || !(UNSIGNED_INT6 (INTVAL (op0
))))
7101 error ("operand of %s instruction should be an unsigned 6-bit value",
7104 pat
= GEN_FCN (icode
) (op0
);
7113 arg0
= CALL_EXPR_ARG (exp
, 0);
7117 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
);
7118 mode0
= insn_data
[icode
].operand
[0].mode
;
7120 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
7121 op0
= copy_to_mode_reg (mode0
, op0
);
7123 pat
= GEN_FCN (icode
) (op0
);
7134 arg0
= CALL_EXPR_ARG (exp
, 0); /* source vreg */
7135 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7136 arg2
= CALL_EXPR_ARG (exp
, 2); /* u8 */
7138 src_vreg
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);
7139 op0
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* [I]0-7 */
7140 op1
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7141 op2
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7143 /* target <- src vreg */
7144 emit_insn (gen_move_insn (target
, src_vreg
));
7146 /* target <- vec_concat: target, mem(Ib, u8) */
7147 mode0
= insn_data
[icode
].operand
[3].mode
;
7148 mode1
= insn_data
[icode
].operand
[1].mode
;
7150 if ( (!(*insn_data
[icode
].operand
[3].predicate
) (op0
, mode0
))
7151 || !(UNSIGNED_INT3 (INTVAL (op0
))))
7152 error ("operand 1 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7155 if ( (!(*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
7156 || !(UNSIGNED_INT8 (INTVAL (op1
))))
7157 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
7160 pat
= GEN_FCN (icode
) (target
, op1
, op2
, op0
);
7170 arg0
= CALL_EXPR_ARG (exp
, 0); /* src vreg */
7171 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7172 arg2
= CALL_EXPR_ARG (exp
, 2); /* u8 */
7174 op0
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7175 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* I[0-7] */
7176 op2
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7177 op3
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
); /* Vdest */
7179 mode0
= insn_data
[icode
].operand
[0].mode
;
7180 mode1
= insn_data
[icode
].operand
[1].mode
;
7181 mode2
= insn_data
[icode
].operand
[2].mode
;
7182 mode3
= insn_data
[icode
].operand
[3].mode
;
7184 if ( (!(*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
7185 || !(UNSIGNED_INT3 (INTVAL (op1
))))
7186 error ("operand 2 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7189 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op2
, mode2
))
7190 || !(UNSIGNED_INT8 (INTVAL (op2
))))
7191 error ("operand 3 of %s instruction should be an unsigned 8-bit value",
7194 if (!(*insn_data
[icode
].operand
[3].predicate
) (op3
, mode3
))
7195 op3
= copy_to_mode_reg (mode3
, op3
);
7197 pat
= GEN_FCN (icode
) (op0
, op1
, op2
, op3
);
7206 arg0
= CALL_EXPR_ARG (exp
, 0); /* dest vreg */
7207 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7209 op0
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7210 op1
= expand_expr (arg0
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* I[0-7] */
7211 op2
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7213 /* target <- src vreg */
7214 target
= gen_reg_rtx (V8HImode
);
7216 /* target <- vec_concat: target, mem(Ib, u8) */
7217 mode0
= insn_data
[icode
].operand
[1].mode
;
7218 mode1
= insn_data
[icode
].operand
[2].mode
;
7219 mode2
= insn_data
[icode
].operand
[3].mode
;
7221 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7222 || !(UNSIGNED_INT3 (INTVAL (op1
))))
7223 error ("operand 1 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7226 if ( (!(*insn_data
[icode
].operand
[3].predicate
) (op2
, mode2
))
7227 || !(UNSIGNED_INT8 (INTVAL (op2
))))
7228 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
7231 pat
= GEN_FCN (icode
) (target
, op0
, op1
, op2
);
7238 case void_Va_u3_Ib_u8
:
7240 arg0
= CALL_EXPR_ARG (exp
, 0); /* source vreg */
7241 arg1
= CALL_EXPR_ARG (exp
, 1); /* u3 */
7242 arg2
= CALL_EXPR_ARG (exp
, 2); /* [I]0-7 */
7243 arg3
= CALL_EXPR_ARG (exp
, 3); /* u8 */
7245 op0
= expand_expr (arg3
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* u8 */
7246 op1
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR */
7247 op2
= expand_expr (arg2
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* [I]0-7 */
7248 op3
= expand_expr (arg0
, NULL_RTX
, V8HImode
, EXPAND_NORMAL
);/* vreg to be stored */
7249 op4
= expand_expr (arg1
, NULL_RTX
, SImode
, EXPAND_NORMAL
); /* vreg 0-7 subreg no. */
7251 mode0
= insn_data
[icode
].operand
[0].mode
;
7252 mode2
= insn_data
[icode
].operand
[2].mode
;
7253 mode3
= insn_data
[icode
].operand
[3].mode
;
7254 mode4
= insn_data
[icode
].operand
[4].mode
;
7256 /* Do some correctness checks for the operands. */
7257 if ( (!(*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
7258 || !(UNSIGNED_INT8 (INTVAL (op0
))))
7259 error ("operand 4 of %s instruction should be an unsigned 8-bit value (0-255)",
7262 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op2
, mode2
))
7263 || !(UNSIGNED_INT3 (INTVAL (op2
))))
7264 error ("operand 3 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7267 if (!(*insn_data
[icode
].operand
[3].predicate
) (op3
, mode3
))
7268 op3
= copy_to_mode_reg (mode3
, op3
);
7270 if ( (!(*insn_data
[icode
].operand
[4].predicate
) (op4
, mode4
))
7271 || !(UNSIGNED_INT3 (INTVAL (op4
))))
7272 error ("operand 2 of %s instruction should be an unsigned 3-bit value (subreg 0-7)",
7274 else if (icode
== CODE_FOR_vst32_n_insn
7275 && ((INTVAL(op4
) % 2 ) != 0))
7276 error ("operand 2 of %s instruction should be an even 3-bit value (subreg 0,2,4,6)",
7279 pat
= GEN_FCN (icode
) (op0
, op1
, op2
, op3
, op4
);
7293 arc_preserve_reload_p (rtx in
)
7295 return (GET_CODE (in
) == PLUS
7296 && RTX_OK_FOR_BASE_P (XEXP (in
, 0), true)
7297 && CONST_INT_P (XEXP (in
, 1))
7298 && !((INTVAL (XEXP (in
, 1)) & 511)));
7302 arc_register_move_cost (machine_mode
,
7303 enum reg_class from_class
, enum reg_class to_class
)
7305 /* The ARC600 has no bypass for extension registers, hence a nop might be
7306 needed to be inserted after a write so that reads are safe. */
7309 if (to_class
== MPY_WRITABLE_CORE_REGS
)
7311 /* Instructions modifying LP_COUNT need 4 additional cycles before
7312 the register will actually contain the value. */
7313 else if (to_class
== LPCOUNT_REG
)
7315 else if (to_class
== WRITABLE_CORE_REGS
)
7319 /* The ARC700 stalls for 3 cycles when *reading* from lp_count. */
7321 && (from_class
== LPCOUNT_REG
|| from_class
== ALL_CORE_REGS
7322 || from_class
== WRITABLE_CORE_REGS
))
7325 /* Force an attempt to 'mov Dy,Dx' to spill. */
7326 if (TARGET_ARC700
&& TARGET_DPFP
7327 && from_class
== DOUBLE_REGS
&& to_class
== DOUBLE_REGS
)
7333 /* Emit code for an addsi3 instruction with OPERANDS.
7334 COND_P indicates if this will use conditional execution.
7335 Return the length of the instruction.
7336 If OUTPUT_P is false, don't actually output the instruction, just return
7339 arc_output_addsi (rtx
*operands
, bool cond_p
, bool output_p
)
7343 int match
= operands_match_p (operands
[0], operands
[1]);
7344 int match2
= operands_match_p (operands
[0], operands
[2]);
7345 int intval
= (REG_P (operands
[2]) ? 1
7346 : CONST_INT_P (operands
[2]) ? INTVAL (operands
[2]) : 0xbadc057);
7347 int neg_intval
= -intval
;
7348 int short_0
= satisfies_constraint_Rcq (operands
[0]);
7349 int short_p
= (!cond_p
&& short_0
&& satisfies_constraint_Rcq (operands
[1]));
7352 #define ADDSI_OUTPUT1(FORMAT) do {\
7354 output_asm_insn (FORMAT, operands);\
7357 #define ADDSI_OUTPUT(LIST) do {\
7360 ADDSI_OUTPUT1 (format);\
7364 /* First try to emit a 16 bit insn. */
7367 /* If we are actually about to output this insn, don't try a 16 bit
7368 variant if we already decided that we don't want that
7369 (I.e. we upsized this insn to align some following insn.)
7370 E.g. add_s r0,sp,70 is 16 bit, but add r0,sp,70 requires a LIMM -
7371 but add1 r0,sp,35 doesn't. */
7372 && (!output_p
|| (get_attr_length (current_output_insn
) & 2)))
7375 && (REG_P (operands
[2])
7376 ? (match
|| satisfies_constraint_Rcq (operands
[2]))
7377 : (unsigned) intval
<= (match
? 127 : 7)))
7378 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7379 if (short_0
&& REG_P (operands
[1]) && match2
)
7380 ADDSI_OUTPUT1 ("add%? %0,%2,%1");
7381 if ((short_0
|| REGNO (operands
[0]) == STACK_POINTER_REGNUM
)
7382 && REGNO (operands
[1]) == STACK_POINTER_REGNUM
&& !(intval
& ~124))
7383 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7385 if ((short_p
&& (unsigned) neg_intval
<= (match
? 31 : 7))
7386 || (REGNO (operands
[0]) == STACK_POINTER_REGNUM
7387 && match
&& !(neg_intval
& ~124)))
7388 ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
7391 /* Now try to emit a 32 bit insn without long immediate. */
7393 if (!match
&& match2
&& REG_P (operands
[1]))
7394 ADDSI_OUTPUT1 ("add%? %0,%2,%1");
7395 if (match
|| !cond_p
)
7397 int limit
= (match
&& !cond_p
) ? 0x7ff : 0x3f;
7398 int range_factor
= neg_intval
& intval
;
7401 if (intval
== -1 << 31)
7402 ADDSI_OUTPUT1 ("bxor%? %0,%1,31");
7404 /* If we can use a straight add / sub instead of a {add,sub}[123] of
7405 same size, do, so - the insn latency is lower. */
7406 /* -0x800 is a 12-bit constant for add /add3 / sub / sub3, but
7408 if ((intval
>= 0 && intval
<= limit
)
7409 || (intval
== -0x800 && limit
== 0x7ff))
7410 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7411 else if ((intval
< 0 && neg_intval
<= limit
)
7412 || (intval
== 0x800 && limit
== 0x7ff))
7413 ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
7414 shift
= range_factor
>= 8 ? 3 : (range_factor
>> 1);
7415 gcc_assert (shift
== 0 || shift
== 1 || shift
== 2 || shift
== 3);
7416 gcc_assert ((((1 << shift
) - 1) & intval
) == 0);
7417 if (((intval
< 0 && intval
!= -0x4000)
7418 /* sub[123] is slower than add_s / sub, only use it if it
7419 avoids a long immediate. */
7420 && neg_intval
<= limit
<< shift
)
7421 || (intval
== 0x4000 && limit
== 0x7ff))
7422 ADDSI_OUTPUT ((format
, "sub%d%%? %%0,%%1,%d",
7423 shift
, neg_intval
>> shift
));
7424 else if ((intval
>= 0 && intval
<= limit
<< shift
)
7425 || (intval
== -0x4000 && limit
== 0x7ff))
7426 ADDSI_OUTPUT ((format
, "add%d%%? %%0,%%1,%d", shift
, intval
>> shift
));
7428 /* Try to emit a 16 bit opcode with long immediate. */
7430 if (short_p
&& match
)
7431 ADDSI_OUTPUT1 ("add%? %0,%1,%S2");
7433 /* We have to use a 32 bit opcode, and with a long immediate. */
7435 ADDSI_OUTPUT1 (intval
< 0 ? "sub%? %0,%1,%n2" : "add%? %0,%1,%S2");
7438 /* Emit code for an commutative_cond_exec instruction with OPERANDS.
7439 Return the length of the instruction.
7440 If OUTPUT_P is false, don't actually output the instruction, just return
7443 arc_output_commutative_cond_exec (rtx
*operands
, bool output_p
)
7445 enum rtx_code commutative_op
= GET_CODE (operands
[3]);
7446 const char *pat
= NULL
;
7448 /* Canonical rtl should not have a constant in the first operand position. */
7449 gcc_assert (!CONSTANT_P (operands
[1]));
7451 switch (commutative_op
)
7454 if (satisfies_constraint_C1p (operands
[2]))
7455 pat
= "bmsk%? %0,%1,%Z2";
7456 else if (satisfies_constraint_Ccp (operands
[2]))
7457 pat
= "bclr%? %0,%1,%M2";
7458 else if (satisfies_constraint_CnL (operands
[2]))
7459 pat
= "bic%? %0,%1,%n2-1";
7462 if (satisfies_constraint_C0p (operands
[2]))
7463 pat
= "bset%? %0,%1,%z2";
7466 if (satisfies_constraint_C0p (operands
[2]))
7467 pat
= "bxor%? %0,%1,%z2";
7470 return arc_output_addsi (operands
, true, output_p
);
7474 output_asm_insn (pat
? pat
: "%O3.%d5 %0,%1,%2", operands
);
7475 if (pat
|| REG_P (operands
[2]) || satisfies_constraint_L (operands
[2]))
7480 /* Helper function of arc_expand_movmem. ADDR points to a chunk of memory.
7481 Emit code and return an potentially modified address such that offsets
7482 up to SIZE are can be added to yield a legitimate address.
7483 if REUSE is set, ADDR is a register that may be modified. */
7486 force_offsettable (rtx addr
, HOST_WIDE_INT size
, bool reuse
)
7489 rtx offs
= const0_rtx
;
7491 if (GET_CODE (base
) == PLUS
)
7493 offs
= XEXP (base
, 1);
7494 base
= XEXP (base
, 0);
7497 || (REGNO (base
) != STACK_POINTER_REGNUM
7498 && REGNO_PTR_FRAME_P (REGNO (addr
)))
7499 || !CONST_INT_P (offs
) || !SMALL_INT (INTVAL (offs
))
7500 || !SMALL_INT (INTVAL (offs
) + size
))
7503 emit_insn (gen_add2_insn (addr
, offs
));
7505 addr
= copy_to_mode_reg (Pmode
, addr
);
7510 /* Like move_by_pieces, but take account of load latency,
7511 and actual offset ranges.
7512 Return true on success. */
7515 arc_expand_movmem (rtx
*operands
)
7517 rtx dst
= operands
[0];
7518 rtx src
= operands
[1];
7519 rtx dst_addr
, src_addr
;
7521 int align
= INTVAL (operands
[3]);
7528 if (!CONST_INT_P (operands
[2]))
7530 size
= INTVAL (operands
[2]);
7531 /* move_by_pieces_ninsns is static, so we can't use it. */
7533 n_pieces
= (size
+ 2) / 4U + (size
& 1);
7534 else if (align
== 2)
7535 n_pieces
= (size
+ 1) / 2U;
7538 if (n_pieces
>= (unsigned int) (optimize_size
? 3 : 15))
7542 dst_addr
= force_offsettable (XEXP (operands
[0], 0), size
, 0);
7543 src_addr
= force_offsettable (XEXP (operands
[1], 0), size
, 0);
7544 store
[0] = store
[1] = NULL_RTX
;
7545 tmpx
[0] = tmpx
[1] = NULL_RTX
;
7546 for (i
= 0; size
> 0; i
^= 1, size
-= piece
)
7552 piece
= size
& -size
;
7553 mode
= smallest_mode_for_size (piece
* BITS_PER_UNIT
, MODE_INT
);
7554 /* If we don't re-use temporaries, the scheduler gets carried away,
7555 and the register pressure gets unnecessarily high. */
7556 if (0 && tmpx
[i
] && GET_MODE (tmpx
[i
]) == mode
)
7559 tmpx
[i
] = tmp
= gen_reg_rtx (mode
);
7560 dst_addr
= force_offsettable (dst_addr
, piece
, 1);
7561 src_addr
= force_offsettable (src_addr
, piece
, 1);
7563 emit_insn (store
[i
]);
7564 emit_move_insn (tmp
, change_address (src
, mode
, src_addr
));
7565 store
[i
] = gen_move_insn (change_address (dst
, mode
, dst_addr
), tmp
);
7566 dst_addr
= plus_constant (Pmode
, dst_addr
, piece
);
7567 src_addr
= plus_constant (Pmode
, src_addr
, piece
);
7570 emit_insn (store
[i
]);
7572 emit_insn (store
[i
^1]);
7576 /* Prepare operands for move in MODE. Return true iff the move has
7580 prepare_move_operands (rtx
*operands
, machine_mode mode
)
7582 /* We used to do this only for MODE_INT Modes, but addresses to floating
7583 point variables may well be in the small data section. */
7586 if (!TARGET_NO_SDATA_SET
&& small_data_pattern (operands
[0], Pmode
))
7587 operands
[0] = arc_rewrite_small_data (operands
[0]);
7588 else if (mode
== SImode
&& flag_pic
&& SYMBOLIC_CONST (operands
[1]))
7590 emit_pic_move (operands
, SImode
);
7592 /* Disable any REG_EQUALs associated with the symref
7593 otherwise the optimization pass undoes the work done
7594 here and references the variable directly. */
7596 else if (GET_CODE (operands
[0]) != MEM
7597 && !TARGET_NO_SDATA_SET
7598 && small_data_pattern (operands
[1], Pmode
))
7600 /* This is to take care of address calculations involving sdata
7602 operands
[1] = arc_rewrite_small_data (operands
[1]);
7604 emit_insn (gen_rtx_SET (mode
, operands
[0],operands
[1]));
7605 /* ??? This note is useless, since it only restates the set itself.
7606 We should rather use the original SYMBOL_REF. However, there is
7607 the problem that we are lying to the compiler about these
7608 SYMBOL_REFs to start with. symbol@sda should be encoded specially
7609 so that we can tell it apart from an actual symbol. */
7610 set_unique_reg_note (get_last_insn (), REG_EQUAL
, operands
[1]);
7612 /* Take care of the REG_EQUAL note that will be attached to mark the
7613 output reg equal to the initial symbol_ref after this code is
7615 emit_move_insn (operands
[0], operands
[0]);
7620 if (MEM_P (operands
[0])
7621 && !(reload_in_progress
|| reload_completed
))
7623 operands
[1] = force_reg (mode
, operands
[1]);
7624 if (!move_dest_operand (operands
[0], mode
))
7626 rtx addr
= copy_to_mode_reg (Pmode
, XEXP (operands
[0], 0));
7627 /* This is like change_address_1 (operands[0], mode, 0, 1) ,
7628 except that we can't use that function because it is static. */
7629 rtx pat
= change_address (operands
[0], mode
, addr
);
7630 MEM_COPY_ATTRIBUTES (pat
, operands
[0]);
7633 if (!cse_not_expected
)
7635 rtx pat
= XEXP (operands
[0], 0);
7637 pat
= arc_legitimize_address_0 (pat
, pat
, mode
);
7640 pat
= change_address (operands
[0], mode
, pat
);
7641 MEM_COPY_ATTRIBUTES (pat
, operands
[0]);
7647 if (MEM_P (operands
[1]) && !cse_not_expected
)
7649 rtx pat
= XEXP (operands
[1], 0);
7651 pat
= arc_legitimize_address_0 (pat
, pat
, mode
);
7654 pat
= change_address (operands
[1], mode
, pat
);
7655 MEM_COPY_ATTRIBUTES (pat
, operands
[1]);
7663 /* Prepare OPERANDS for an extension using CODE to OMODE.
7664 Return true iff the move has been emitted. */
7667 prepare_extend_operands (rtx
*operands
, enum rtx_code code
,
7670 if (!TARGET_NO_SDATA_SET
&& small_data_pattern (operands
[1], Pmode
))
7672 /* This is to take care of address calculations involving sdata
7675 = gen_rtx_fmt_e (code
, omode
, arc_rewrite_small_data (operands
[1]));
7676 emit_insn (gen_rtx_SET (omode
, operands
[0], operands
[1]));
7677 set_unique_reg_note (get_last_insn (), REG_EQUAL
, operands
[1]);
7679 /* Take care of the REG_EQUAL note that will be attached to mark the
7680 output reg equal to the initial extension after this code is
7682 emit_move_insn (operands
[0], operands
[0]);
7688 /* Output a library call to a function called FNAME that has been arranged
7689 to be local to any dso. */
7692 arc_output_libcall (const char *fname
)
7694 unsigned len
= strlen (fname
);
7695 static char buf
[64];
7697 gcc_assert (len
< sizeof buf
- 35);
7698 if (TARGET_LONG_CALLS_SET
7699 || (TARGET_MEDIUM_CALLS
&& arc_ccfsm_cond_exec_p ()))
7702 sprintf (buf
, "add r12,pcl,@%s-(.&-4)\n\tjl%%!%%* [r12]", fname
);
7704 sprintf (buf
, "jl%%! @%s", fname
);
7707 sprintf (buf
, "bl%%!%%* @%s", fname
);
7711 /* Return the SImode highpart of the DImode value IN. */
7714 disi_highpart (rtx in
)
7716 return simplify_gen_subreg (SImode
, in
, DImode
, TARGET_BIG_ENDIAN
? 0 : 4);
7719 /* Return length adjustment for INSN.
7721 A write to a core reg greater or equal to 32 must not be immediately
7722 followed by a use. Anticipate the length requirement to insert a nop
7723 between PRED and SUCC to prevent a hazard. */
7726 arc600_corereg_hazard (rtx_insn
*pred
, rtx_insn
*succ
)
7730 /* If SUCC is a doloop_end_i with a preceding label, we must output a nop
7731 in front of SUCC anyway, so there will be separation between PRED and
7733 if (recog_memoized (succ
) == CODE_FOR_doloop_end_i
7734 && LABEL_P (prev_nonnote_insn (succ
)))
7736 if (recog_memoized (succ
) == CODE_FOR_doloop_begin_i
)
7738 if (GET_CODE (PATTERN (pred
)) == SEQUENCE
)
7739 pred
= as_a
<rtx_sequence
*> (PATTERN (pred
))->insn (1);
7740 if (GET_CODE (PATTERN (succ
)) == SEQUENCE
)
7741 succ
= as_a
<rtx_sequence
*> (PATTERN (succ
))->insn (0);
7742 if (recog_memoized (pred
) == CODE_FOR_mulsi_600
7743 || recog_memoized (pred
) == CODE_FOR_umul_600
7744 || recog_memoized (pred
) == CODE_FOR_mac_600
7745 || recog_memoized (pred
) == CODE_FOR_mul64_600
7746 || recog_memoized (pred
) == CODE_FOR_mac64_600
7747 || recog_memoized (pred
) == CODE_FOR_umul64_600
7748 || recog_memoized (pred
) == CODE_FOR_umac64_600
)
7750 subrtx_iterator::array_type array
;
7751 FOR_EACH_SUBRTX (iter
, array
, PATTERN (pred
), NONCONST
)
7753 const_rtx x
= *iter
;
7754 switch (GET_CODE (x
))
7756 case SET
: case POST_INC
: case POST_DEC
: case PRE_INC
: case PRE_DEC
:
7759 /* This is also fine for PRE/POST_MODIFY, because they
7763 rtx dest
= XEXP (x
, 0);
7764 /* Check if this sets a an extension register. N.B. we use 61 for the
7765 condition codes, which is definitely not an extension register. */
7766 if (REG_P (dest
) && REGNO (dest
) >= 32 && REGNO (dest
) < 61
7767 /* Check if the same register is used by the PAT. */
7768 && (refers_to_regno_p
7770 REGNO (dest
) + (GET_MODE_SIZE (GET_MODE (dest
)) + 3) / 4U,
7771 PATTERN (succ
), 0)))
7778 A write to a core reg greater or equal to 32 must not be immediately
7779 followed by a use. Anticipate the length requirement to insert a nop
7780 between PRED and SUCC to prevent a hazard. */
7783 arc_hazard (rtx_insn
*pred
, rtx_insn
*succ
)
7787 if (!pred
|| !INSN_P (pred
) || !succ
|| !INSN_P (succ
))
7789 /* We might have a CALL to a non-returning function before a loop end.
7790 ??? Although the manual says that's OK (the target is outside the loop,
7791 and the loop counter unused there), the assembler barfs on this, so we
7792 must instert a nop before such a call too. */
7793 if (recog_memoized (succ
) == CODE_FOR_doloop_end_i
7794 && (JUMP_P (pred
) || CALL_P (pred
)
7795 || GET_CODE (PATTERN (pred
)) == SEQUENCE
))
7797 return arc600_corereg_hazard (pred
, succ
);
7800 /* Return length adjustment for INSN. */
7803 arc_adjust_insn_length (rtx_insn
*insn
, int len
, bool)
7807 /* We already handle sequences by ignoring the delay sequence flag. */
7808 if (GET_CODE (PATTERN (insn
)) == SEQUENCE
)
7811 /* It is impossible to jump to the very end of a Zero-Overhead Loop, as
7812 the ZOL mechanism only triggers when advancing to the end address,
7813 so if there's a label at the end of a ZOL, we need to insert a nop.
7814 The ARC600 ZOL also has extra restrictions on jumps at the end of a
7816 if (recog_memoized (insn
) == CODE_FOR_doloop_end_i
)
7818 rtx_insn
*prev
= prev_nonnote_insn (insn
);
7820 return ((LABEL_P (prev
)
7823 || CALL_P (prev
) /* Could be a noreturn call. */
7824 || (NONJUMP_INSN_P (prev
)
7825 && GET_CODE (PATTERN (prev
)) == SEQUENCE
))))
7829 /* Check for return with but one preceding insn since function
7831 if (TARGET_PAD_RETURN
7833 && GET_CODE (PATTERN (insn
)) != ADDR_VEC
7834 && GET_CODE (PATTERN (insn
)) != ADDR_DIFF_VEC
7835 && get_attr_type (insn
) == TYPE_RETURN
)
7837 rtx_insn
*prev
= prev_active_insn (insn
);
7839 if (!prev
|| !(prev
= prev_active_insn (prev
))
7840 || ((NONJUMP_INSN_P (prev
)
7841 && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
7842 ? CALL_ATTR (as_a
<rtx_sequence
*> (PATTERN (prev
))->insn (0),
7844 : CALL_ATTR (prev
, NON_SIBCALL
)))
7849 rtx_insn
*succ
= next_real_insn (insn
);
7851 /* One the ARC600, a write to an extension register must be separated
7853 if (succ
&& INSN_P (succ
))
7854 len
+= arc600_corereg_hazard (insn
, succ
);
7857 /* Restore extracted operands - otherwise splitters like the addsi3_mixed one
7859 extract_constrain_insn_cached (insn
);
7864 /* Values for length_sensitive. */
7868 ARC_LS_25
, // 25 bit offset, B
7869 ARC_LS_21
, // 21 bit offset, Bcc
7870 ARC_LS_U13
,// 13 bit unsigned offset, LP
7871 ARC_LS_10
, // 10 bit offset, B_s, Beq_s, Bne_s
7872 ARC_LS_9
, // 9 bit offset, BRcc
7873 ARC_LS_8
, // 8 bit offset, BRcc_s
7874 ARC_LS_U7
, // 7 bit unsigned offset, LPcc
7875 ARC_LS_7
// 7 bit offset, Bcc_s
7878 /* While the infrastructure patch is waiting for review, duplicate the
7879 struct definitions, to allow this file to compile. */
7884 /* Cost as a branch / call target or call return address. */
7886 int fallthrough_cost
;
7889 /* 0 for not length sensitive, 1 for largest offset range,
7890 * 2 for next smaller etc. */
7891 unsigned length_sensitive
: 8;
7893 } insn_length_variant_t
;
7895 typedef struct insn_length_parameters_s
7900 int (*get_variants
) (rtx_insn
*, int, bool, bool, insn_length_variant_t
*);
7901 } insn_length_parameters_t
;
7904 arc_insn_length_parameters (insn_length_parameters_t
*ilp
) ATTRIBUTE_UNUSED
;
7908 arc_get_insn_variants (rtx_insn
*insn
, int len
, bool, bool target_p
,
7909 insn_length_variant_t
*ilv
)
7911 if (!NONDEBUG_INSN_P (insn
))
7913 enum attr_type type
;
7914 /* shorten_branches doesn't take optimize_size into account yet for the
7915 get_variants mechanism, so turn this off for now. */
7918 if (rtx_sequence
*pat
= dyn_cast
<rtx_sequence
*> (PATTERN (insn
)))
7920 /* The interaction of a short delay slot insn with a short branch is
7921 too weird for shorten_branches to piece together, so describe the
7924 if (TARGET_UPSIZE_DBR
7925 && get_attr_length (pat
->insn (1)) <= 2
7926 && (((type
= get_attr_type (inner
= pat
->insn (0)))
7927 == TYPE_UNCOND_BRANCH
)
7928 || type
== TYPE_BRANCH
)
7929 && get_attr_delay_slot_filled (inner
) == DELAY_SLOT_FILLED_YES
)
7932 = arc_get_insn_variants (inner
, get_attr_length (inner
), true,
7934 /* The short variant gets split into a higher-cost aligned
7935 and a lower cost unaligned variant. */
7936 gcc_assert (n_variants
);
7937 gcc_assert (ilv
[1].length_sensitive
== ARC_LS_7
7938 || ilv
[1].length_sensitive
== ARC_LS_10
);
7939 gcc_assert (ilv
[1].align_set
== 3);
7941 ilv
[0].align_set
= 1;
7942 ilv
[0].branch_cost
+= 1;
7943 ilv
[1].align_set
= 2;
7945 for (int i
= 0; i
< n_variants
; i
++)
7947 /* In case an instruction with aligned size is wanted, and
7948 the short variants are unavailable / too expensive, add
7949 versions of long branch + long delay slot. */
7950 for (int i
= 2, end
= n_variants
; i
< end
; i
++, n_variants
++)
7952 ilv
[n_variants
] = ilv
[i
];
7953 ilv
[n_variants
].length
+= 2;
7959 insn_length_variant_t
*first_ilv
= ilv
;
7960 type
= get_attr_type (insn
);
7962 = (get_attr_delay_slot_filled (insn
) == DELAY_SLOT_FILLED_YES
);
7963 int branch_align_cost
= delay_filled
? 0 : 1;
7964 int branch_unalign_cost
= delay_filled
? 0 : TARGET_UNALIGN_BRANCH
? 0 : 1;
7965 /* If the previous instruction is an sfunc call, this insn is always
7966 a target, even though the middle-end is unaware of this. */
7967 bool force_target
= false;
7968 rtx_insn
*prev
= prev_active_insn (insn
);
7969 if (prev
&& arc_next_active_insn (prev
, 0) == insn
7970 && ((NONJUMP_INSN_P (prev
) && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
7971 ? CALL_ATTR (as_a
<rtx_sequence
*> (PATTERN (prev
))->insn (0),
7973 : (CALL_ATTR (prev
, NON_SIBCALL
)
7974 && NEXT_INSN (PREV_INSN (prev
)) == prev
)))
7975 force_target
= true;
7980 /* Short BRCC only comes in no-delay-slot version, and without limm */
7985 ilv
->branch_cost
= 1;
7986 ilv
->enabled
= (len
== 2);
7987 ilv
->length_sensitive
= ARC_LS_8
;
7991 case TYPE_BRCC_NO_DELAY_SLOT
:
7992 /* doloop_fallback* patterns are TYPE_BRCC_NO_DELAY_SLOT for
7993 (delay slot) scheduling purposes, but they are longer. */
7994 if (GET_CODE (PATTERN (insn
)) == PARALLEL
7995 && GET_CODE (XVECEXP (PATTERN (insn
), 0, 1)) == SET
)
7997 /* Standard BRCC: 4 bytes, or 8 bytes with limm. */
7998 ilv
->length
= ((type
== TYPE_BRCC
) ? 4 : 8);
8000 ilv
->branch_cost
= branch_align_cost
;
8001 ilv
->enabled
= (len
<= ilv
->length
);
8002 ilv
->length_sensitive
= ARC_LS_9
;
8003 if ((target_p
|| force_target
)
8004 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8010 ilv
->target_cost
= 1;
8011 ilv
->branch_cost
= branch_unalign_cost
;
8016 op
= XEXP (SET_SRC (XVECEXP (PATTERN (insn
), 0, 0)), 0);
8019 if (GET_CODE (op0
) == ZERO_EXTRACT
8020 && satisfies_constraint_L (XEXP (op0
, 2)))
8021 op0
= XEXP (op0
, 0);
8022 if (satisfies_constraint_Rcq (op0
))
8024 ilv
->length
= ((type
== TYPE_BRCC
) ? 6 : 10);
8026 ilv
->branch_cost
= 1 + branch_align_cost
;
8027 ilv
->fallthrough_cost
= 1;
8028 ilv
->enabled
= true;
8029 ilv
->length_sensitive
= ARC_LS_21
;
8030 if (!delay_filled
&& TARGET_UNALIGN_BRANCH
)
8036 ilv
->branch_cost
= 1 + branch_unalign_cost
;
8040 ilv
->length
= ((type
== TYPE_BRCC
) ? 8 : 12);
8042 ilv
->branch_cost
= 1 + branch_align_cost
;
8043 ilv
->fallthrough_cost
= 1;
8044 ilv
->enabled
= true;
8045 ilv
->length_sensitive
= ARC_LS_21
;
8046 if ((target_p
|| force_target
)
8047 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8053 ilv
->target_cost
= 1;
8054 ilv
->branch_cost
= 1 + branch_unalign_cost
;
8062 case TYPE_CALL_NO_DELAY_SLOT
:
8067 ilv
->length_sensitive
8068 = GET_CODE (PATTERN (insn
)) == COND_EXEC
? ARC_LS_21
: ARC_LS_25
;
8071 ilv
->fallthrough_cost
= branch_align_cost
;
8072 ilv
->enabled
= true;
8073 if ((target_p
|| force_target
)
8074 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8080 ilv
->target_cost
= 1;
8081 ilv
->fallthrough_cost
= branch_unalign_cost
;
8085 case TYPE_UNCOND_BRANCH
:
8086 /* Strictly speaking, this should be ARC_LS_10 for equality comparisons,
8087 but that makes no difference at the moment. */
8088 ilv
->length_sensitive
= ARC_LS_7
;
8089 ilv
[1].length_sensitive
= ARC_LS_25
;
8092 ilv
->length_sensitive
= ARC_LS_10
;
8093 ilv
[1].length_sensitive
= ARC_LS_21
;
8097 ilv
->branch_cost
= branch_align_cost
;
8098 ilv
->enabled
= (len
== ilv
->length
);
8102 ilv
->branch_cost
= branch_align_cost
;
8103 ilv
->enabled
= true;
8104 if ((target_p
|| force_target
)
8105 || (!delay_filled
&& TARGET_UNALIGN_BRANCH
))
8111 ilv
->target_cost
= 1;
8112 ilv
->branch_cost
= branch_unalign_cost
;
8119 /* For every short insn, there is generally also a long insn.
8120 trap_s is an exception. */
8121 if ((len
& 2) == 0 || recog_memoized (insn
) == CODE_FOR_trap_s
)
8128 ilv
->length
= len
+ 2;
8130 if (target_p
|| force_target
)
8136 ilv
->target_cost
= 1;
8140 /* If the previous instruction is an sfunc call, this insn is always
8141 a target, even though the middle-end is unaware of this.
8142 Therefore, if we have a call predecessor, transfer the target cost
8143 to the fallthrough and branch costs. */
8146 for (insn_length_variant_t
*p
= first_ilv
; p
< ilv
; p
++)
8148 p
->fallthrough_cost
+= p
->target_cost
;
8149 p
->branch_cost
+= p
->target_cost
;
8154 return ilv
- first_ilv
;
8158 arc_insn_length_parameters (insn_length_parameters_t
*ilp
)
8160 ilp
->align_unit_log
= 1;
8161 ilp
->align_base_log
= 1;
8162 ilp
->max_variants
= 7;
8163 ilp
->get_variants
= arc_get_insn_variants
;
8166 /* Return a copy of COND from *STATEP, inverted if that is indicated by the
8167 CC field of *STATEP. */
8170 arc_get_ccfsm_cond (struct arc_ccfsm
*statep
, bool reverse
)
8172 rtx cond
= statep
->cond
;
8173 int raw_cc
= get_arc_condition_code (cond
);
8175 raw_cc
= ARC_INVERSE_CONDITION_CODE (raw_cc
);
8177 if (statep
->cc
== raw_cc
)
8178 return copy_rtx (cond
);
8180 gcc_assert (ARC_INVERSE_CONDITION_CODE (raw_cc
) == statep
->cc
);
8182 machine_mode ccm
= GET_MODE (XEXP (cond
, 0));
8183 enum rtx_code code
= reverse_condition (GET_CODE (cond
));
8184 if (code
== UNKNOWN
|| ccm
== CC_FP_GTmode
|| ccm
== CC_FP_GEmode
)
8185 code
= reverse_condition_maybe_unordered (GET_CODE (cond
));
8187 return gen_rtx_fmt_ee (code
, GET_MODE (cond
),
8188 copy_rtx (XEXP (cond
, 0)), copy_rtx (XEXP (cond
, 1)));
8191 /* Return version of PAT conditionalized with COND, which is part of INSN.
8192 ANNULLED indicates if INSN is an annulled delay-slot insn.
8193 Register further changes if necessary. */
8195 conditionalize_nonjump (rtx pat
, rtx cond
, rtx insn
, bool annulled
)
8197 /* For commutative operators, we generally prefer to have
8198 the first source match the destination. */
8199 if (GET_CODE (pat
) == SET
)
8201 rtx src
= SET_SRC (pat
);
8203 if (COMMUTATIVE_P (src
))
8205 rtx src0
= XEXP (src
, 0);
8206 rtx src1
= XEXP (src
, 1);
8207 rtx dst
= SET_DEST (pat
);
8209 if (rtx_equal_p (src1
, dst
) && !rtx_equal_p (src0
, dst
)
8210 /* Leave add_n alone - the canonical form is to
8211 have the complex summand first. */
8213 pat
= gen_rtx_SET (VOIDmode
, dst
,
8214 gen_rtx_fmt_ee (GET_CODE (src
), GET_MODE (src
),
8219 /* dwarf2out.c:dwarf2out_frame_debug_expr doesn't know
8220 what to do with COND_EXEC. */
8221 if (RTX_FRAME_RELATED_P (insn
))
8223 /* If this is the delay slot insn of an anulled branch,
8224 dwarf2out.c:scan_trace understands the anulling semantics
8225 without the COND_EXEC. */
8226 gcc_assert (annulled
);
8227 rtx note
= alloc_reg_note (REG_FRAME_RELATED_EXPR
, pat
,
8229 validate_change (insn
, ®_NOTES (insn
), note
, 1);
8231 pat
= gen_rtx_COND_EXEC (VOIDmode
, cond
, pat
);
8235 /* Use the ccfsm machinery to do if conversion. */
8240 struct arc_ccfsm
*statep
= &cfun
->machine
->ccfsm_current
;
8241 basic_block merge_bb
= 0;
8243 memset (statep
, 0, sizeof *statep
);
8244 for (rtx_insn
*insn
= get_insns (); insn
; insn
= next_insn (insn
))
8246 arc_ccfsm_advance (insn
, statep
);
8248 switch (statep
->state
)
8256 /* Deleted branch. */
8257 gcc_assert (!merge_bb
);
8258 merge_bb
= BLOCK_FOR_INSN (insn
);
8260 = BLOCK_FOR_INSN (NEXT_INSN (NEXT_INSN (PREV_INSN (insn
))));
8261 arc_ccfsm_post_advance (insn
, statep
);
8262 gcc_assert (!IN_RANGE (statep
->state
, 1, 2));
8263 rtx_insn
*seq
= NEXT_INSN (PREV_INSN (insn
));
8266 rtx slot
= XVECEXP (PATTERN (seq
), 0, 1);
8267 rtx pat
= PATTERN (slot
);
8268 if (INSN_ANNULLED_BRANCH_P (insn
))
8271 = arc_get_ccfsm_cond (statep
, INSN_FROM_TARGET_P (slot
));
8272 pat
= gen_rtx_COND_EXEC (VOIDmode
, cond
, pat
);
8274 if (!validate_change (seq
, &PATTERN (seq
), pat
, 0))
8276 PUT_CODE (slot
, NOTE
);
8277 NOTE_KIND (slot
) = NOTE_INSN_DELETED
;
8278 if (merge_bb
&& succ_bb
)
8279 merge_blocks (merge_bb
, succ_bb
);
8281 else if (merge_bb
&& succ_bb
)
8283 set_insn_deleted (insn
);
8284 merge_blocks (merge_bb
, succ_bb
);
8288 PUT_CODE (insn
, NOTE
);
8289 NOTE_KIND (insn
) = NOTE_INSN_DELETED
;
8295 && statep
->target_label
== CODE_LABEL_NUMBER (insn
))
8297 arc_ccfsm_post_advance (insn
, statep
);
8298 basic_block succ_bb
= BLOCK_FOR_INSN (insn
);
8299 if (merge_bb
&& succ_bb
)
8300 merge_blocks (merge_bb
, succ_bb
);
8301 else if (--LABEL_NUSES (insn
) == 0)
8303 const char *name
= LABEL_NAME (insn
);
8304 PUT_CODE (insn
, NOTE
);
8305 NOTE_KIND (insn
) = NOTE_INSN_DELETED_LABEL
;
8306 NOTE_DELETED_LABEL_NAME (insn
) = name
;
8313 if (!NONDEBUG_INSN_P (insn
))
8316 /* Conditionalized insn. */
8318 rtx_insn
*prev
, *pprev
;
8319 rtx
*patp
, pat
, cond
;
8320 bool annulled
; annulled
= false;
8322 /* If this is a delay slot insn in a non-annulled branch,
8323 don't conditionalize it. N.B., this should be fine for
8324 conditional return too. However, don't do this for
8325 unconditional branches, as these would be encountered when
8326 processing an 'else' part. */
8327 prev
= PREV_INSN (insn
);
8328 pprev
= PREV_INSN (prev
);
8329 if (pprev
&& NEXT_INSN (NEXT_INSN (pprev
)) == NEXT_INSN (insn
)
8330 && JUMP_P (prev
) && get_attr_cond (prev
) == COND_USE
)
8332 if (!INSN_ANNULLED_BRANCH_P (prev
))
8337 patp
= &PATTERN (insn
);
8339 cond
= arc_get_ccfsm_cond (statep
, INSN_FROM_TARGET_P (insn
));
8340 if (NONJUMP_INSN_P (insn
) || CALL_P (insn
))
8342 /* ??? don't conditionalize if all side effects are dead
8343 in the not-execute case. */
8345 pat
= conditionalize_nonjump (pat
, cond
, insn
, annulled
);
8347 else if (simplejump_p (insn
))
8349 patp
= &SET_SRC (pat
);
8350 pat
= gen_rtx_IF_THEN_ELSE (VOIDmode
, cond
, *patp
, pc_rtx
);
8352 else if (JUMP_P (insn
) && ANY_RETURN_P (PATTERN (insn
)))
8354 pat
= gen_rtx_IF_THEN_ELSE (VOIDmode
, cond
, pat
, pc_rtx
);
8355 pat
= gen_rtx_SET (VOIDmode
, pc_rtx
, pat
);
8359 validate_change (insn
, patp
, pat
, 1);
8360 if (!apply_change_group ())
8364 rtx_insn
*next
= next_nonnote_insn (insn
);
8365 if (GET_CODE (next
) == BARRIER
)
8367 if (statep
->state
== 3)
8374 arc_ccfsm_post_advance (insn
, statep
);
8379 /* Find annulled delay insns and convert them to use the appropriate predicate.
8380 This allows branch shortening to size up these insns properly. */
8383 arc_predicate_delay_insns (void)
8385 for (rtx_insn
*insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
8387 rtx pat
, jump
, dlay
, src
, cond
, *patp
;
8390 if (!NONJUMP_INSN_P (insn
)
8391 || GET_CODE (pat
= PATTERN (insn
)) != SEQUENCE
)
8393 jump
= XVECEXP (pat
, 0, 0);
8394 dlay
= XVECEXP (pat
, 0, 1);
8395 if (!JUMP_P (jump
) || !INSN_ANNULLED_BRANCH_P (jump
))
8397 /* If the branch insn does the annulling, leave the delay insn alone. */
8398 if (!TARGET_AT_DBR_CONDEXEC
&& !INSN_FROM_TARGET_P (dlay
))
8400 /* ??? Could also leave DLAY un-conditionalized if its target is dead
8401 on the other path. */
8402 gcc_assert (GET_CODE (PATTERN (jump
)) == SET
);
8403 gcc_assert (SET_DEST (PATTERN (jump
)) == pc_rtx
);
8404 src
= SET_SRC (PATTERN (jump
));
8405 gcc_assert (GET_CODE (src
) == IF_THEN_ELSE
);
8406 cond
= XEXP (src
, 0);
8407 if (XEXP (src
, 2) == pc_rtx
)
8409 else if (XEXP (src
, 1) == pc_rtx
)
8413 if (reverse
!= !INSN_FROM_TARGET_P (dlay
))
8415 machine_mode ccm
= GET_MODE (XEXP (cond
, 0));
8416 enum rtx_code code
= reverse_condition (GET_CODE (cond
));
8417 if (code
== UNKNOWN
|| ccm
== CC_FP_GTmode
|| ccm
== CC_FP_GEmode
)
8418 code
= reverse_condition_maybe_unordered (GET_CODE (cond
));
8420 cond
= gen_rtx_fmt_ee (code
, GET_MODE (cond
),
8421 copy_rtx (XEXP (cond
, 0)),
8422 copy_rtx (XEXP (cond
, 1)));
8425 cond
= copy_rtx (cond
);
8426 patp
= &PATTERN (dlay
);
8428 pat
= conditionalize_nonjump (pat
, cond
, dlay
, true);
8429 validate_change (dlay
, patp
, pat
, 1);
8430 if (!apply_change_group ())
8436 /* For ARC600: If a write to a core reg >=32 appears in a delay slot
8437 (other than of a forward brcc), it creates a hazard when there is a read
8438 of the same register at the branch target. We can't know what is at the
8439 branch target of calls, and for branches, we don't really know before the
8440 end of delay slot scheduling, either. Not only can individual instruction
8441 be hoisted out into a delay slot, a basic block can also be emptied this
8442 way, and branch and/or fall through targets be redirected. Hence we don't
8443 want such writes in a delay slot. */
8445 /* Return nonzreo iff INSN writes to an extension core register. */
8448 arc_write_ext_corereg (rtx insn
)
8450 subrtx_iterator::array_type array
;
8451 FOR_EACH_SUBRTX (iter
, array
, PATTERN (insn
), NONCONST
)
8453 const_rtx x
= *iter
;
8454 switch (GET_CODE (x
))
8456 case SET
: case POST_INC
: case POST_DEC
: case PRE_INC
: case PRE_DEC
:
8459 /* This is also fine for PRE/POST_MODIFY, because they
8463 const_rtx dest
= XEXP (x
, 0);
8464 if (REG_P (dest
) && REGNO (dest
) >= 32 && REGNO (dest
) < 61)
8470 /* This is like the hook, but returns NULL when it can't / won't generate
8471 a legitimate address. */
8474 arc_legitimize_address_0 (rtx x
, rtx oldx ATTRIBUTE_UNUSED
,
8479 if (flag_pic
&& SYMBOLIC_CONST (x
))
8480 (x
) = arc_legitimize_pic_address (x
, 0);
8482 if (GET_CODE (addr
) == CONST
)
8483 addr
= XEXP (addr
, 0);
8484 if (GET_CODE (addr
) == PLUS
8485 && CONST_INT_P (XEXP (addr
, 1))
8486 && ((GET_CODE (XEXP (addr
, 0)) == SYMBOL_REF
8487 && !SYMBOL_REF_FUNCTION_P (XEXP (addr
, 0)))
8488 || (REG_P (XEXP (addr
, 0))
8489 && (INTVAL (XEXP (addr
, 1)) & 252))))
8491 HOST_WIDE_INT offs
, upper
;
8492 int size
= GET_MODE_SIZE (mode
);
8494 offs
= INTVAL (XEXP (addr
, 1));
8495 upper
= (offs
+ 256 * size
) & ~511 * size
;
8496 inner
= plus_constant (Pmode
, XEXP (addr
, 0), upper
);
8497 #if 0 /* ??? this produces worse code for EEMBC idctrn01 */
8498 if (GET_CODE (x
) == CONST
)
8499 inner
= gen_rtx_CONST (Pmode
, inner
);
8501 addr
= plus_constant (Pmode
, force_reg (Pmode
, inner
), offs
- upper
);
8504 else if (GET_CODE (addr
) == SYMBOL_REF
&& !SYMBOL_REF_FUNCTION_P (addr
))
8505 x
= force_reg (Pmode
, x
);
8506 if (memory_address_p ((machine_mode
) mode
, x
))
8512 arc_legitimize_address (rtx orig_x
, rtx oldx
, machine_mode mode
)
8514 rtx new_x
= arc_legitimize_address_0 (orig_x
, oldx
, mode
);
8522 arc_delegitimize_address_0 (rtx x
)
8526 if (GET_CODE (x
) == CONST
&& GET_CODE (u
= XEXP (x
, 0)) == UNSPEC
)
8528 if (XINT (u
, 1) == ARC_UNSPEC_GOT
)
8529 return XVECEXP (u
, 0, 0);
8531 else if (GET_CODE (x
) == PLUS
8532 && ((REG_P (gp
= XEXP (x
, 0))
8533 && REGNO (gp
) == PIC_OFFSET_TABLE_REGNUM
)
8534 || (GET_CODE (gp
) == CONST
8535 && GET_CODE (u
= XEXP (gp
, 0)) == UNSPEC
8536 && XINT (u
, 1) == ARC_UNSPEC_GOT
8537 && GET_CODE (XVECEXP (u
, 0, 0)) == SYMBOL_REF
8538 && !strcmp (XSTR (XVECEXP (u
, 0, 0), 0), "_DYNAMIC")))
8539 && GET_CODE (XEXP (x
, 1)) == CONST
8540 && GET_CODE (u
= XEXP (XEXP (x
, 1), 0)) == UNSPEC
8541 && XINT (u
, 1) == ARC_UNSPEC_GOTOFF
)
8542 return XVECEXP (u
, 0, 0);
8543 else if (GET_CODE (x
) == PLUS
&& GET_CODE (XEXP (x
, 0)) == PLUS
8544 && ((REG_P (gp
= XEXP (XEXP (x
, 0), 1))
8545 && REGNO (gp
) == PIC_OFFSET_TABLE_REGNUM
)
8546 || (GET_CODE (gp
) == CONST
8547 && GET_CODE (u
= XEXP (gp
, 0)) == UNSPEC
8548 && XINT (u
, 1) == ARC_UNSPEC_GOT
8549 && GET_CODE (XVECEXP (u
, 0, 0)) == SYMBOL_REF
8550 && !strcmp (XSTR (XVECEXP (u
, 0, 0), 0), "_DYNAMIC")))
8551 && GET_CODE (XEXP (x
, 1)) == CONST
8552 && GET_CODE (u
= XEXP (XEXP (x
, 1), 0)) == UNSPEC
8553 && XINT (u
, 1) == ARC_UNSPEC_GOTOFF
)
8554 return gen_rtx_PLUS (GET_MODE (x
), XEXP (XEXP (x
, 0), 0),
8556 else if (GET_CODE (x
) == PLUS
8557 && (u
= arc_delegitimize_address_0 (XEXP (x
, 1))))
8558 return gen_rtx_PLUS (GET_MODE (x
), XEXP (x
, 0), u
);
8563 arc_delegitimize_address (rtx x
)
8565 rtx orig_x
= x
= delegitimize_mem_from_attrs (x
);
8566 if (GET_CODE (x
) == MEM
)
8568 x
= arc_delegitimize_address_0 (x
);
8572 x
= replace_equiv_address_nv (orig_x
, x
);
8578 /* Return a REG rtx for acc1. N.B. the gcc-internal representation may
8579 differ from the hardware register number in order to allow the generic
8580 code to correctly split the concatenation of acc1 and acc2. */
8585 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 56: 57);
8588 /* Return a REG rtx for acc2. N.B. the gcc-internal representation may
8589 differ from the hardware register number in order to allow the generic
8590 code to correctly split the concatenation of acc1 and acc2. */
8595 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 57: 56);
8598 /* Return a REG rtx for mlo. N.B. the gcc-internal representation may
8599 differ from the hardware register number in order to allow the generic
8600 code to correctly split the concatenation of mhi and mlo. */
8605 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 59: 58);
8608 /* Return a REG rtx for mhi. N.B. the gcc-internal representation may
8609 differ from the hardware register number in order to allow the generic
8610 code to correctly split the concatenation of mhi and mlo. */
8615 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 58: 59);
8618 /* FIXME: a parameter should be added, and code added to final.c,
8619 to reproduce this functionality in shorten_branches. */
8621 /* Return nonzero iff BRANCH should be unaligned if possible by upsizing
8622 a previous instruction. */
8624 arc_unalign_branch_p (rtx branch
)
8628 if (!TARGET_UNALIGN_BRANCH
)
8630 /* Do not do this if we have a filled delay slot. */
8631 if (get_attr_delay_slot_filled (branch
) == DELAY_SLOT_FILLED_YES
8632 && !NEXT_INSN (branch
)->deleted ())
8634 note
= find_reg_note (branch
, REG_BR_PROB
, 0);
8636 || (arc_unalign_prob_threshold
&& !br_prob_note_reliable_p (note
))
8637 || INTVAL (XEXP (note
, 0)) < arc_unalign_prob_threshold
);
8641 /* When estimating sizes during arc_reorg, when optimizing for speed, there
8642 are three reasons why we need to consider branches to be length 6:
8643 - annull-false delay slot insns are implemented using conditional execution,
8644 thus preventing short insn formation where used.
8645 - for ARC600: annul-true delay slot insns are implemented where possible
8646 using conditional execution, preventing short insn formation where used.
8647 - for ARC700: likely or somewhat likely taken branches are made long and
8648 unaligned if possible to avoid branch penalty. */
8651 arc_branch_size_unknown_p (void)
8653 return !optimize_size
&& arc_reorg_in_progress
;
8656 /* We are about to output a return insn. Add padding if necessary to avoid
8657 a mispredict. A return could happen immediately after the function
8658 start, but after a call we know that there will be at least a blink
8662 arc_pad_return (void)
8664 rtx_insn
*insn
= current_output_insn
;
8665 rtx_insn
*prev
= prev_active_insn (insn
);
8670 fputs ("\tnop_s\n", asm_out_file
);
8671 cfun
->machine
->unalign
^= 2;
8674 /* If PREV is a sequence, we know it must be a branch / jump or a tailcall,
8675 because after a call, we'd have to restore blink first. */
8676 else if (GET_CODE (PATTERN (prev
)) == SEQUENCE
)
8680 want_long
= (get_attr_length (prev
) == 2);
8681 prev
= prev_active_insn (prev
);
8684 || ((NONJUMP_INSN_P (prev
) && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
8685 ? CALL_ATTR (as_a
<rtx_sequence
*> (PATTERN (prev
))->insn (0),
8687 : CALL_ATTR (prev
, NON_SIBCALL
)))
8690 cfun
->machine
->size_reason
8691 = "call/return and return/return must be 6 bytes apart to avoid mispredict";
8692 else if (TARGET_UNALIGN_BRANCH
&& cfun
->machine
->unalign
)
8694 cfun
->machine
->size_reason
8695 = "Long unaligned jump avoids non-delay slot penalty";
8698 /* Disgorge delay insn, if there is any, and it may be moved. */
8700 /* ??? Annulled would be OK if we can and do conditionalize
8701 the delay slot insn accordingly. */
8702 && !INSN_ANNULLED_BRANCH_P (insn
)
8703 && (get_attr_cond (insn
) != COND_USE
8704 || !reg_set_p (gen_rtx_REG (CCmode
, CC_REG
),
8705 XVECEXP (final_sequence
, 0, 1))))
8707 prev
= as_a
<rtx_insn
*> (XVECEXP (final_sequence
, 0, 1));
8708 gcc_assert (!prev_real_insn (insn
)
8709 || !arc_hazard (prev_real_insn (insn
), prev
));
8710 cfun
->machine
->force_short_suffix
= !want_long
;
8711 rtx save_pred
= current_insn_predicate
;
8712 final_scan_insn (prev
, asm_out_file
, optimize
, 1, NULL
);
8713 cfun
->machine
->force_short_suffix
= -1;
8714 prev
->set_deleted ();
8715 current_output_insn
= insn
;
8716 current_insn_predicate
= save_pred
;
8719 fputs ("\tnop\n", asm_out_file
);
8722 fputs ("\tnop_s\n", asm_out_file
);
8723 cfun
->machine
->unalign
^= 2;
8729 /* The usual; we set up our machine_function data. */
8731 static struct machine_function
*
8732 arc_init_machine_status (void)
8734 struct machine_function
*machine
;
8735 machine
= ggc_cleared_alloc
<machine_function
> ();
8736 machine
->fn_type
= ARC_FUNCTION_UNKNOWN
;
8737 machine
->force_short_suffix
= -1;
8742 /* Implements INIT_EXPANDERS. We just set up to call the above
8746 arc_init_expanders (void)
8748 init_machine_status
= arc_init_machine_status
;
8751 /* Check if OP is a proper parallel of a millicode call pattern. OFFSET
8752 indicates a number of elements to ignore - that allows to have a
8753 sibcall pattern that starts with (return). LOAD_P is zero for store
8754 multiple (for prologues), and one for load multiples (for epilogues),
8755 and two for load multiples where no final clobber of blink is required.
8756 We also skip the first load / store element since this is supposed to
8757 be checked in the instruction pattern. */
8760 arc_check_millicode (rtx op
, int offset
, int load_p
)
8762 int len
= XVECLEN (op
, 0) - offset
;
8767 if (len
< 2 || len
> 13)
8773 rtx elt
= XVECEXP (op
, 0, --len
);
8775 if (GET_CODE (elt
) != CLOBBER
8776 || !REG_P (XEXP (elt
, 0))
8777 || REGNO (XEXP (elt
, 0)) != RETURN_ADDR_REGNUM
8778 || len
< 3 || len
> 13)
8781 for (i
= 1; i
< len
; i
++)
8783 rtx elt
= XVECEXP (op
, 0, i
+ offset
);
8786 if (GET_CODE (elt
) != SET
)
8788 mem
= XEXP (elt
, load_p
);
8789 reg
= XEXP (elt
, 1-load_p
);
8790 if (!REG_P (reg
) || REGNO (reg
) != 13U+i
|| !MEM_P (mem
))
8792 addr
= XEXP (mem
, 0);
8793 if (GET_CODE (addr
) != PLUS
8794 || !rtx_equal_p (stack_pointer_rtx
, XEXP (addr
, 0))
8795 || !CONST_INT_P (XEXP (addr
, 1)) || INTVAL (XEXP (addr
, 1)) != i
*4)
8801 /* Accessor functions for cfun->machine->unalign. */
8804 arc_get_unalign (void)
8806 return cfun
->machine
->unalign
;
8810 arc_clear_unalign (void)
8813 cfun
->machine
->unalign
= 0;
8817 arc_toggle_unalign (void)
8819 cfun
->machine
->unalign
^= 2;
8822 /* Operands 0..2 are the operands of a addsi which uses a 12 bit
8823 constant in operand 2, but which would require a LIMM because of
8825 operands 3 and 4 are new SET_SRCs for operands 0. */
8828 split_addsi (rtx
*operands
)
8830 int val
= INTVAL (operands
[2]);
8832 /* Try for two short insns first. Lengths being equal, we prefer
8833 expansions with shorter register lifetimes. */
8834 if (val
> 127 && val
<= 255
8835 && satisfies_constraint_Rcq (operands
[0]))
8837 operands
[3] = operands
[2];
8838 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[1]);
8842 operands
[3] = operands
[1];
8843 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[2]);
8847 /* Operands 0..2 are the operands of a subsi which uses a 12 bit
8848 constant in operand 1, but which would require a LIMM because of
8850 operands 3 and 4 are new SET_SRCs for operands 0. */
8853 split_subsi (rtx
*operands
)
8855 int val
= INTVAL (operands
[1]);
8857 /* Try for two short insns first. Lengths being equal, we prefer
8858 expansions with shorter register lifetimes. */
8859 if (satisfies_constraint_Rcq (operands
[0])
8860 && satisfies_constraint_Rcq (operands
[2]))
8862 if (val
>= -31 && val
<= 127)
8864 operands
[3] = gen_rtx_NEG (SImode
, operands
[2]);
8865 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[1]);
8868 else if (val
>= 0 && val
< 255)
8870 operands
[3] = operands
[1];
8871 operands
[4] = gen_rtx_MINUS (SImode
, operands
[0], operands
[2]);
8875 /* If the destination is not an ARCompact16 register, we might
8876 still have a chance to make a short insn if the source is;
8877 we need to start with a reg-reg move for this. */
8878 operands
[3] = operands
[2];
8879 operands
[4] = gen_rtx_MINUS (SImode
, operands
[1], operands
[0]);
8882 /* Handle DOUBLE_REGS uses.
8883 Operand 0: destination register
8884 Operand 1: source register */
8887 arc_process_double_reg_moves (rtx
*operands
)
8889 rtx dest
= operands
[0];
8890 rtx src
= operands
[1];
8893 enum usesDxState
{ none
, srcDx
, destDx
, maxDx
};
8894 enum usesDxState state
= none
;
8896 if (refers_to_regno_p (40, 44, src
, 0))
8898 if (refers_to_regno_p (40, 44, dest
, 0))
8900 /* Via arc_register_move_cost, we should never see D,D moves. */
8901 gcc_assert (state
== none
);
8912 /* Without the LR insn, we need to split this into a
8913 sequence of insns which will use the DEXCLx and DADDHxy
8914 insns to be able to read the Dx register in question. */
8915 if (TARGET_DPFP_DISABLE_LRSR
)
8917 /* gen *movdf_insn_nolrsr */
8918 rtx set
= gen_rtx_SET (VOIDmode
, dest
, src
);
8919 rtx use1
= gen_rtx_USE (VOIDmode
, const1_rtx
);
8920 emit_insn (gen_rtx_PARALLEL (VOIDmode
, gen_rtvec (2, set
, use1
)));
8924 /* When we have 'mov D, r' or 'mov D, D' then get the target
8925 register pair for use with LR insn. */
8926 rtx destHigh
= simplify_gen_subreg(SImode
, dest
, DFmode
, 4);
8927 rtx destLow
= simplify_gen_subreg(SImode
, dest
, DFmode
, 0);
8929 /* Produce the two LR insns to get the high and low parts. */
8930 emit_insn (gen_rtx_SET (VOIDmode
,
8932 gen_rtx_UNSPEC_VOLATILE (Pmode
, gen_rtvec (1, src
),
8934 emit_insn (gen_rtx_SET (VOIDmode
,
8936 gen_rtx_UNSPEC_VOLATILE (Pmode
, gen_rtvec (1, src
),
8940 else if (state
== destDx
)
8942 /* When we have 'mov r, D' or 'mov D, D' and we have access to the
8943 LR insn get the target register pair. */
8944 rtx srcHigh
= simplify_gen_subreg(SImode
, src
, DFmode
, 4);
8945 rtx srcLow
= simplify_gen_subreg(SImode
, src
, DFmode
, 0);
8947 emit_insn (gen_rtx_UNSPEC_VOLATILE (Pmode
,
8948 gen_rtvec (3, dest
, srcHigh
, srcLow
),
8949 VUNSPEC_DEXCL_NORES
));
8960 /* operands 0..1 are the operands of a 64 bit move instruction.
8961 split it into two moves with operands 2/3 and 4/5. */
8964 arc_split_move (rtx
*operands
)
8966 machine_mode mode
= GET_MODE (operands
[0]);
8974 val
= arc_process_double_reg_moves (operands
);
8979 for (i
= 0; i
< 2; i
++)
8981 if (MEM_P (operands
[i
]) && auto_inc_p (XEXP (operands
[i
], 0)))
8983 rtx addr
= XEXP (operands
[i
], 0);
8987 gcc_assert (!reg_overlap_mentioned_p (operands
[0], addr
));
8988 switch (GET_CODE (addr
))
8990 case PRE_DEC
: o
= GEN_INT (-8); goto pre_modify
;
8991 case PRE_INC
: o
= GEN_INT (8); goto pre_modify
;
8992 case PRE_MODIFY
: o
= XEXP (XEXP (addr
, 1), 1);
8996 case POST_DEC
: o
= GEN_INT (-8); goto post_modify
;
8997 case POST_INC
: o
= GEN_INT (8); goto post_modify
;
8998 case POST_MODIFY
: o
= XEXP (XEXP (addr
, 1), 1);
9007 xop
[0+i
] = adjust_automodify_address_nv
9008 (operands
[i
], SImode
,
9009 gen_rtx_fmt_ee (code
, Pmode
, r
,
9010 gen_rtx_PLUS (Pmode
, r
, o
)),
9012 xop
[2+i
] = adjust_automodify_address_nv
9013 (operands
[i
], SImode
, plus_constant (Pmode
, r
, 4), 4);
9017 xop
[0+i
] = operand_subword (operands
[i
], 0, 0, mode
);
9018 xop
[2+i
] = operand_subword (operands
[i
], 1, 0, mode
);
9021 if (reg_overlap_mentioned_p (xop
[0], xop
[3]))
9024 gcc_assert (!reg_overlap_mentioned_p (xop
[2], xop
[1]));
9026 operands
[2+swap
] = xop
[0];
9027 operands
[3+swap
] = xop
[1];
9028 operands
[4-swap
] = xop
[2];
9029 operands
[5-swap
] = xop
[3];
9032 emit_insn (gen_rtx_SET (VOIDmode
, operands
[2], operands
[3]));
9033 emit_insn (gen_rtx_SET (VOIDmode
, operands
[4], operands
[5]));
9040 /* Select between the instruction output templates s_tmpl (for short INSNs)
9041 and l_tmpl (for long INSNs). */
9044 arc_short_long (rtx_insn
*insn
, const char *s_tmpl
, const char *l_tmpl
)
9046 int is_short
= arc_verify_short (insn
, cfun
->machine
->unalign
, -1);
9048 extract_constrain_insn_cached (insn
);
9049 return is_short
? s_tmpl
: l_tmpl
;
9052 /* Searches X for any reference to REGNO, returning the rtx of the
9053 reference found if any. Otherwise, returns NULL_RTX. */
9056 arc_regno_use_in (unsigned int regno
, rtx x
)
9062 if (REG_P (x
) && refers_to_regno_p (regno
, regno
+1, x
, (rtx
*) 0))
9065 fmt
= GET_RTX_FORMAT (GET_CODE (x
));
9066 for (i
= GET_RTX_LENGTH (GET_CODE (x
)) - 1; i
>= 0; i
--)
9070 if ((tem
= regno_use_in (regno
, XEXP (x
, i
))))
9073 else if (fmt
[i
] == 'E')
9074 for (j
= XVECLEN (x
, i
) - 1; j
>= 0; j
--)
9075 if ((tem
= regno_use_in (regno
, XVECEXP (x
, i
, j
))))
9082 /* Return the integer value of the "type" attribute for INSN, or -1 if
9083 INSN can't have attributes. */
9086 arc_attr_type (rtx_insn
*insn
)
9088 if (NONJUMP_INSN_P (insn
)
9089 ? (GET_CODE (PATTERN (insn
)) == USE
9090 || GET_CODE (PATTERN (insn
)) == CLOBBER
)
9092 ? (GET_CODE (PATTERN (insn
)) == ADDR_VEC
9093 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
9096 return get_attr_type (insn
);
9099 /* Return true if insn sets the condition codes. */
9102 arc_sets_cc_p (rtx_insn
*insn
)
9104 if (NONJUMP_INSN_P (insn
))
9105 if (rtx_sequence
*seq
= dyn_cast
<rtx_sequence
*> (PATTERN (insn
)))
9106 insn
= seq
->insn (seq
->len () - 1);
9107 return arc_attr_type (insn
) == TYPE_COMPARE
;
9110 /* Return true if INSN is an instruction with a delay slot we may want
9114 arc_need_delay (rtx_insn
*insn
)
9118 if (!flag_delayed_branch
)
9120 /* The return at the end of a function needs a delay slot. */
9121 if (NONJUMP_INSN_P (insn
) && GET_CODE (PATTERN (insn
)) == USE
9122 && (!(next
= next_active_insn (insn
))
9123 || ((!NONJUMP_INSN_P (next
) || GET_CODE (PATTERN (next
)) != SEQUENCE
)
9124 && arc_attr_type (next
) == TYPE_RETURN
))
9125 && (!TARGET_PAD_RETURN
9126 || (prev_active_insn (insn
)
9127 && prev_active_insn (prev_active_insn (insn
))
9128 && prev_active_insn (prev_active_insn (prev_active_insn (insn
))))))
9130 if (NONJUMP_INSN_P (insn
)
9131 ? (GET_CODE (PATTERN (insn
)) == USE
9132 || GET_CODE (PATTERN (insn
)) == CLOBBER
9133 || GET_CODE (PATTERN (insn
)) == SEQUENCE
)
9135 ? (GET_CODE (PATTERN (insn
)) == ADDR_VEC
9136 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
9139 return num_delay_slots (insn
) != 0;
9142 /* Return true if the scheduling pass(es) has/have already run,
9143 i.e. where possible, we should try to mitigate high latencies
9144 by different instruction selection. */
9147 arc_scheduling_not_expected (void)
9149 return cfun
->machine
->arc_reorg_started
;
9152 /* Oddly enough, sometimes we get a zero overhead loop that branch
9153 shortening doesn't think is a loop - observed with compile/pr24883.c
9154 -O3 -fomit-frame-pointer -funroll-loops. Make sure to include the
9155 alignment visible for branch shortening (we actually align the loop
9156 insn before it, but that is equivalent since the loop insn is 4 byte
9160 arc_label_align (rtx label
)
9162 int loop_align
= LOOP_ALIGN (LABEL
);
9164 if (loop_align
> align_labels_log
)
9166 rtx_insn
*prev
= prev_nonnote_insn (label
);
9168 if (prev
&& NONJUMP_INSN_P (prev
)
9169 && GET_CODE (PATTERN (prev
)) == PARALLEL
9170 && recog_memoized (prev
) == CODE_FOR_doloop_begin_i
)
9173 /* Code has a minimum p2 alignment of 1, which we must restore after an
9175 if (align_labels_log
< 1)
9177 rtx_insn
*next
= next_nonnote_nondebug_insn (label
);
9178 if (INSN_P (next
) && recog_memoized (next
) >= 0)
9181 return align_labels_log
;
9184 /* Return true if LABEL is in executable code. */
9187 arc_text_label (rtx_insn
*label
)
9191 /* ??? We use deleted labels like they were still there, see
9192 gcc.c-torture/compile/20000326-2.c . */
9193 gcc_assert (GET_CODE (label
) == CODE_LABEL
9194 || (GET_CODE (label
) == NOTE
9195 && NOTE_KIND (label
) == NOTE_INSN_DELETED_LABEL
));
9196 next
= next_nonnote_insn (label
);
9198 return (!JUMP_TABLE_DATA_P (next
)
9199 || GET_CODE (PATTERN (next
)) != ADDR_VEC
);
9200 else if (!PREV_INSN (label
))
9201 /* ??? sometimes text labels get inserted very late, see
9202 gcc.dg/torture/stackalign/comp-goto-1.c */
9207 /* Return the size of the pretend args for DECL. */
9210 arc_decl_pretend_args (tree decl
)
9212 /* struct function is in DECL_STRUCT_FUNCTION (decl), but no
9213 pretend_args there... See PR38391. */
9214 gcc_assert (decl
== current_function_decl
);
9215 return crtl
->args
.pretend_args_size
;
9218 /* Without this, gcc.dg/tree-prof/bb-reorg.c fails to assemble
9219 when compiling with -O2 -freorder-blocks-and-partition -fprofile-use
9220 -D_PROFILE_USE; delay branch scheduling then follows a crossing jump
9221 to redirect two breqs. */
9224 arc_can_follow_jump (const rtx_insn
*follower
, const rtx_insn
*followee
)
9226 /* ??? get_attr_type is declared to take an rtx. */
9227 union { const rtx_insn
*c
; rtx_insn
*r
; } u
;
9230 if (CROSSING_JUMP_P (followee
))
9231 switch (get_attr_type (u
.r
))
9234 case TYPE_BRCC_NO_DELAY_SLOT
:
9242 /* Implement EPILOGUE__USES.
9243 Return true if REGNO should be added to the deemed uses of the epilogue.
9245 We use the return address
9246 arc_return_address_regs[arc_compute_function_type (cfun)] .
9247 But also, we have to make sure all the register restore instructions
9248 are known to be live in interrupt functions. */
9251 arc_epilogue_uses (int regno
)
9253 if (reload_completed
)
9255 if (ARC_INTERRUPT_P (cfun
->machine
->fn_type
))
9257 if (!fixed_regs
[regno
])
9259 return regno
== arc_return_address_regs
[cfun
->machine
->fn_type
];
9262 return regno
== RETURN_ADDR_REGNUM
;
9265 return regno
== arc_return_address_regs
[arc_compute_function_type (cfun
)];
9268 #ifndef TARGET_NO_LRA
9269 #define TARGET_NO_LRA !TARGET_LRA
9275 return !TARGET_NO_LRA
;
9278 /* ??? Should we define TARGET_REGISTER_PRIORITY? We might perfer to use
9279 Rcq registers, because some insn are shorter with them. OTOH we already
9280 have separate alternatives for this purpose, and other insns don't
9281 mind, so maybe we should rather prefer the other registers?
9282 We need more data, and we can only get that if we allow people to
9285 arc_register_priority (int r
)
9287 switch (arc_lra_priority_tag
)
9289 case ARC_LRA_PRIORITY_NONE
:
9291 case ARC_LRA_PRIORITY_NONCOMPACT
:
9292 return ((((r
& 7) ^ 4) - 4) & 15) != r
;
9293 case ARC_LRA_PRIORITY_COMPACT
:
9294 return ((((r
& 7) ^ 4) - 4) & 15) == r
;
9301 arc_spill_class (reg_class_t
/* orig_class */, machine_mode
)
9303 return GENERAL_REGS
;
9307 arc_legitimize_reload_address (rtx
*p
, machine_mode mode
, int opnum
,
9311 enum reload_type type
= (enum reload_type
) itype
;
9313 if (GET_CODE (x
) == PLUS
9314 && CONST_INT_P (XEXP (x
, 1))
9315 && (RTX_OK_FOR_BASE_P (XEXP (x
, 0), true)
9316 || (REG_P (XEXP (x
, 0))
9317 && reg_equiv_constant (REGNO (XEXP (x
, 0))))))
9319 int scale
= GET_MODE_SIZE (mode
);
9321 rtx index_rtx
= XEXP (x
, 1);
9322 HOST_WIDE_INT offset
= INTVAL (index_rtx
), offset_base
;
9327 if ((scale
-1) & offset
)
9330 offset_base
= (offset
+ (256 << shift
)) & (-512 << shift
);
9331 /* Sometimes the normal form does not suit DImode. We
9332 could avoid that by using smaller ranges, but that
9333 would give less optimized code when SImode is
9335 if (GET_MODE_SIZE (mode
) + offset
- offset_base
<= (256 << shift
))
9340 regno
= REGNO (reg
);
9341 sum2
= sum
= plus_constant (Pmode
, reg
, offset_base
);
9343 if (reg_equiv_constant (regno
))
9345 sum2
= plus_constant (Pmode
, reg_equiv_constant (regno
),
9347 if (GET_CODE (sum2
) == PLUS
)
9348 sum2
= gen_rtx_CONST (Pmode
, sum2
);
9350 *p
= gen_rtx_PLUS (Pmode
, sum
, GEN_INT (offset
- offset_base
));
9351 push_reload (sum2
, NULL_RTX
, &XEXP (*p
, 0), NULL
,
9352 BASE_REG_CLASS
, Pmode
, VOIDmode
, 0, 0, opnum
,
9357 /* We must re-recognize what we created before. */
9358 else if (GET_CODE (x
) == PLUS
9359 && GET_CODE (XEXP (x
, 0)) == PLUS
9360 && CONST_INT_P (XEXP (XEXP (x
, 0), 1))
9361 && REG_P (XEXP (XEXP (x
, 0), 0))
9362 && CONST_INT_P (XEXP (x
, 1)))
9364 /* Because this address is so complex, we know it must have
9365 been created by LEGITIMIZE_RELOAD_ADDRESS before; thus,
9366 it is already unshared, and needs no further unsharing. */
9367 push_reload (XEXP (x
, 0), NULL_RTX
, &XEXP (x
, 0), NULL
,
9368 BASE_REG_CLASS
, Pmode
, VOIDmode
, 0, 0, opnum
, type
);
9374 /* Implement TARGET_USE_BY_PIECES_INFRASTRUCTURE_P. */
9377 arc_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size
,
9379 enum by_pieces_operation op
,
9382 /* Let the movmem expander handle small block moves. */
9383 if (op
== MOVE_BY_PIECES
)
9386 return default_use_by_pieces_infrastructure_p (size
, align
, op
, speed_p
);
9389 struct gcc_target targetm
= TARGET_INITIALIZER
;