1 /* Subroutines used for code generation on the ARC ARCompact cpu.
2 Copyright (C) 1994, 1995, 1997, 2004, 2007, 2008, 2009
3 Free Software Foundation, Inc.
5 Sources derived from work done by Sankhya Technologies (www.sankhya.com)
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 This file is part of GCC.
14 GCC is free software; you can redistribute it and/or modify
15 it under the terms of the GNU General Public License as published by
16 the Free Software Foundation; either version 3, or (at your option)
19 GCC is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with GCC; see the file COPYING3. If not see
26 <http://www.gnu.org/licenses/>. */
31 #include "coretypes.h"
36 #include "hard-reg-set.h"
38 #include "insn-config.h"
39 #include "conditions.h"
40 #include "insn-flags.h"
45 #include "target-def.h"
47 #include "insn-attr.h"
52 #include "diagnostic.h"
53 #include "insn-codes.h"
54 #include "integrate.h"
56 #include "langhooks.h"
58 #include "tm-constrs.h"
59 #include "reload.h" /* For operands_match_p */
62 /* Which cpu we're compiling for (NULL(=A4), A4, A5, ARC600, ARC700) */
63 const char *arc_cpu_string
;
64 enum processor_type arc_cpu
;
66 /* Save the operands last given to a compare for use when we
67 generate a scc or bcc insn. */
68 rtx arc_compare_op0
, arc_compare_op1
;
70 /* Name of text, data, and rodata sections used in varasm.c. */
71 const char *arc_text_section
;
72 const char *arc_data_section
;
73 const char *arc_rodata_section
;
75 /* Array of valid operand punctuation characters. */
76 char arc_punct_chars
[256];
78 /* State used by arc_ccfsm_advance to implement conditional execution. */
79 struct arc_ccfsm
GTY (())
87 #define arc_ccfsm_current cfun->machine->ccfsm_current
89 #define ARC_CCFSM_BRANCH_DELETED_P(STATE) \
90 ((STATE)->state == 1 || (STATE)->state == 2)
92 /* Indicate we're conditionalizing insns now. */
93 #define ARC_CCFSM_RECORD_BRANCH_DELETED(STATE) \
96 #define ARC_CCFSM_COND_EXEC_P(STATE) \
97 ((STATE)->state == 3 || (STATE)->state == 4 || (STATE)->state == 5)
99 /* Check if INSN has a 16 bit opcode considering struct arc_ccfsm *STATE. */
100 #define CCFSM_ISCOMPACT(INSN,STATE) \
101 (ARC_CCFSM_COND_EXEC_P (STATE) \
102 ? (get_attr_iscompact (INSN) == ISCOMPACT_TRUE \
103 || get_attr_iscompact (INSN) == ISCOMPACT_TRUE_LIMM) \
104 : get_attr_iscompact (INSN) != ISCOMPACT_FALSE)
106 /* Likewise, but also consider that INSN might be in a delay slot of JUMP. */
107 #define CCFSM_DBR_ISCOMPACT(INSN,JUMP,STATE) \
108 ((ARC_CCFSM_COND_EXEC_P (STATE) \
109 || (INSN_ANNULLED_BRANCH_P (JUMP) \
110 && (TARGET_AT_DBR_CONDEXEC || INSN_FROM_TARGET_P (INSN)))) \
111 ? (get_attr_iscompact (INSN) == ISCOMPACT_TRUE \
112 || get_attr_iscompact (INSN) == ISCOMPACT_TRUE_LIMM) \
113 : get_attr_iscompact (INSN) != ISCOMPACT_FALSE)
116 static struct obstack arc_local_obstack
;
118 /* The following definition was shifted to arc.h, since #defines from arc.h
119 can be freely used in predicates.md */
120 /* #define PROGRAM_COUNTER_REGNO 63 */
122 /* The maximum number of insns skipped which will be conditionalised if
124 /* When optimizing for speed:
125 Let p be the probability that the potentially skipped insns need to
126 be executed, pn the cost of a correctly predicted non-taken branch,
127 mt the cost of a mis/non-predicted taken branch,
128 mn mispredicted non-taken, pt correctly predicted taken ;
129 costs expressed in numbers of instructions like the ones considered
131 Unfortunately we don't have a measure of predictability - this
132 is linked to probability only in that in the no-eviction-scenario
133 there is a lower bound 1 - 2 * min (p, 1-p), and a somewhat larger
134 value that can be assumed *if* the distribution is perfectly random.
135 A predictability of 1 is perfectly plausible not matter what p is,
136 because the decision could be dependent on an invocation parameter
138 For large p, we want MAX_INSNS_SKIPPED == pn/(1-p) + mt - pn
139 For small p, we want MAX_INSNS_SKIPPED == pt
141 When optimizing for size:
142 We want to skip insn unless we could use 16 opcodes for the
143 non-conditionalized insn to balance the branch length or more.
144 Performance can be tie-breaker. */
145 /* If the potentially-skipped insns are likely to be executed, we'll
146 generally save one non-taken branch
148 this to be no less than the 1/p */
149 #define MAX_INSNS_SKIPPED 3
151 /* The values of unspec's first field */
161 ARC_BUILTIN_NORM
= 3,
162 ARC_BUILTIN_NORMW
= 4,
163 ARC_BUILTIN_SWAP
= 5,
165 ARC_BUILTIN_DIVAW
= 7,
167 ARC_BUILTIN_MUL64
= 9,
168 ARC_BUILTIN_MULU64
= 10,
169 ARC_BUILTIN_RTIE
= 11,
170 ARC_BUILTIN_SYNC
= 12,
171 ARC_BUILTIN_CORE_READ
= 13,
172 ARC_BUILTIN_CORE_WRITE
= 14,
173 ARC_BUILTIN_FLAG
= 15,
176 ARC_BUILTIN_SLEEP
= 18,
177 ARC_BUILTIN_SWI
= 19,
178 ARC_BUILTIN_TRAP_S
= 20,
179 ARC_BUILTIN_UNIMP_S
= 21,
181 /* Sentinel to mark start of simd builtins */
182 ARC_SIMD_BUILTIN_BEGIN
= 1000,
184 ARC_SIMD_BUILTIN_VADDAW
= 1001,
185 ARC_SIMD_BUILTIN_VADDW
= 1002,
186 ARC_SIMD_BUILTIN_VAVB
= 1003,
187 ARC_SIMD_BUILTIN_VAVRB
= 1004,
188 ARC_SIMD_BUILTIN_VDIFAW
= 1005,
189 ARC_SIMD_BUILTIN_VDIFW
= 1006,
190 ARC_SIMD_BUILTIN_VMAXAW
= 1007,
191 ARC_SIMD_BUILTIN_VMAXW
= 1008,
192 ARC_SIMD_BUILTIN_VMINAW
= 1009,
193 ARC_SIMD_BUILTIN_VMINW
= 1010,
194 ARC_SIMD_BUILTIN_VMULAW
= 1011,
195 ARC_SIMD_BUILTIN_VMULFAW
= 1012,
196 ARC_SIMD_BUILTIN_VMULFW
= 1013,
197 ARC_SIMD_BUILTIN_VMULW
= 1014,
198 ARC_SIMD_BUILTIN_VSUBAW
= 1015,
199 ARC_SIMD_BUILTIN_VSUBW
= 1016,
200 ARC_SIMD_BUILTIN_VSUMMW
= 1017,
201 ARC_SIMD_BUILTIN_VAND
= 1018,
202 ARC_SIMD_BUILTIN_VANDAW
= 1019,
203 ARC_SIMD_BUILTIN_VBIC
= 1020,
204 ARC_SIMD_BUILTIN_VBICAW
= 1021,
205 ARC_SIMD_BUILTIN_VOR
= 1022,
206 ARC_SIMD_BUILTIN_VXOR
= 1023,
207 ARC_SIMD_BUILTIN_VXORAW
= 1024,
208 ARC_SIMD_BUILTIN_VEQW
= 1025,
209 ARC_SIMD_BUILTIN_VLEW
= 1026,
210 ARC_SIMD_BUILTIN_VLTW
= 1027,
211 ARC_SIMD_BUILTIN_VNEW
= 1028,
212 ARC_SIMD_BUILTIN_VMR1AW
= 1029,
213 ARC_SIMD_BUILTIN_VMR1W
= 1030,
214 ARC_SIMD_BUILTIN_VMR2AW
= 1031,
215 ARC_SIMD_BUILTIN_VMR2W
= 1032,
216 ARC_SIMD_BUILTIN_VMR3AW
= 1033,
217 ARC_SIMD_BUILTIN_VMR3W
= 1034,
218 ARC_SIMD_BUILTIN_VMR4AW
= 1035,
219 ARC_SIMD_BUILTIN_VMR4W
= 1036,
220 ARC_SIMD_BUILTIN_VMR5AW
= 1037,
221 ARC_SIMD_BUILTIN_VMR5W
= 1038,
222 ARC_SIMD_BUILTIN_VMR6AW
= 1039,
223 ARC_SIMD_BUILTIN_VMR6W
= 1040,
224 ARC_SIMD_BUILTIN_VMR7AW
= 1041,
225 ARC_SIMD_BUILTIN_VMR7W
= 1042,
226 ARC_SIMD_BUILTIN_VMRB
= 1043,
227 ARC_SIMD_BUILTIN_VH264F
= 1044,
228 ARC_SIMD_BUILTIN_VH264FT
= 1045,
229 ARC_SIMD_BUILTIN_VH264FW
= 1046,
230 ARC_SIMD_BUILTIN_VVC1F
= 1047,
231 ARC_SIMD_BUILTIN_VVC1FT
= 1048,
233 /* Va, Vb, rlimm instructions */
234 ARC_SIMD_BUILTIN_VBADDW
= 1050,
235 ARC_SIMD_BUILTIN_VBMAXW
= 1051,
236 ARC_SIMD_BUILTIN_VBMINW
= 1052,
237 ARC_SIMD_BUILTIN_VBMULAW
= 1053,
238 ARC_SIMD_BUILTIN_VBMULFW
= 1054,
239 ARC_SIMD_BUILTIN_VBMULW
= 1055,
240 ARC_SIMD_BUILTIN_VBRSUBW
= 1056,
241 ARC_SIMD_BUILTIN_VBSUBW
= 1057,
243 /* Va, Vb, Ic instructions */
244 ARC_SIMD_BUILTIN_VASRW
= 1060,
245 ARC_SIMD_BUILTIN_VSR8
= 1061,
246 ARC_SIMD_BUILTIN_VSR8AW
= 1062,
248 /* Va, Vb, u6 instructions */
249 ARC_SIMD_BUILTIN_VASRRWi
= 1065,
250 ARC_SIMD_BUILTIN_VASRSRWi
= 1066,
251 ARC_SIMD_BUILTIN_VASRWi
= 1067,
252 ARC_SIMD_BUILTIN_VASRPWBi
= 1068,
253 ARC_SIMD_BUILTIN_VASRRPWBi
= 1069,
254 ARC_SIMD_BUILTIN_VSR8AWi
= 1070,
255 ARC_SIMD_BUILTIN_VSR8i
= 1071,
257 /* Va, Vb, u8 (simm) instructions*/
258 ARC_SIMD_BUILTIN_VMVAW
= 1075,
259 ARC_SIMD_BUILTIN_VMVW
= 1076,
260 ARC_SIMD_BUILTIN_VMVZW
= 1077,
261 ARC_SIMD_BUILTIN_VD6TAPF
= 1078,
263 /* Va, rlimm, u8 (simm) instructions*/
264 ARC_SIMD_BUILTIN_VMOVAW
= 1080,
265 ARC_SIMD_BUILTIN_VMOVW
= 1081,
266 ARC_SIMD_BUILTIN_VMOVZW
= 1082,
268 /* Va, Vb instructions */
269 ARC_SIMD_BUILTIN_VABSAW
= 1085,
270 ARC_SIMD_BUILTIN_VABSW
= 1086,
271 ARC_SIMD_BUILTIN_VADDSUW
= 1087,
272 ARC_SIMD_BUILTIN_VSIGNW
= 1088,
273 ARC_SIMD_BUILTIN_VEXCH1
= 1089,
274 ARC_SIMD_BUILTIN_VEXCH2
= 1090,
275 ARC_SIMD_BUILTIN_VEXCH4
= 1091,
276 ARC_SIMD_BUILTIN_VUPBAW
= 1092,
277 ARC_SIMD_BUILTIN_VUPBW
= 1093,
278 ARC_SIMD_BUILTIN_VUPSBAW
= 1094,
279 ARC_SIMD_BUILTIN_VUPSBW
= 1095,
281 ARC_SIMD_BUILTIN_VDIRUN
= 1100,
282 ARC_SIMD_BUILTIN_VDORUN
= 1101,
283 ARC_SIMD_BUILTIN_VDIWR
= 1102,
284 ARC_SIMD_BUILTIN_VDOWR
= 1103,
286 ARC_SIMD_BUILTIN_VREC
= 1105,
287 ARC_SIMD_BUILTIN_VRUN
= 1106,
288 ARC_SIMD_BUILTIN_VRECRUN
= 1107,
289 ARC_SIMD_BUILTIN_VENDREC
= 1108,
291 ARC_SIMD_BUILTIN_VLD32WH
= 1110,
292 ARC_SIMD_BUILTIN_VLD32WL
= 1111,
293 ARC_SIMD_BUILTIN_VLD64
= 1112,
294 ARC_SIMD_BUILTIN_VLD32
= 1113,
295 ARC_SIMD_BUILTIN_VLD64W
= 1114,
296 ARC_SIMD_BUILTIN_VLD128
= 1115,
297 ARC_SIMD_BUILTIN_VST128
= 1116,
298 ARC_SIMD_BUILTIN_VST64
= 1117,
300 ARC_SIMD_BUILTIN_VST16_N
= 1120,
301 ARC_SIMD_BUILTIN_VST32_N
= 1121,
303 ARC_SIMD_BUILTIN_VINTI
= 1201,
308 /* A nop is needed between a 4 byte insn that sets the condition codes and
309 a branch that uses them (the same isn't true for an 8 byte insn that sets
310 the condition codes). Set by arc_ccfsm_advance. Used by
311 arc_print_operand. */
313 static int get_arc_condition_code (rtx
);
314 /* Initialized arc_attribute_table to NULL since arc doesnot have any
315 machine specific supported attributes. */
316 const struct attribute_spec arc_attribute_table
[] =
318 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
319 /* Function calls made to this symbol must be done indirectly, because
320 it may lie outside of the 21/25 bit addressing range of a normal function
322 { "long_call", 0, 0, false, true, true, NULL
},
323 /* Whereas these functions are always known to reside within the 21/25 bit
325 { "short_call", 0, 0, false, true, true, NULL
},
326 { NULL
, 0, 0, false, false, false, NULL
}
328 static bool arc_assemble_integer (rtx
, unsigned int, int);
329 static int arc_comp_type_attributes (const_tree
, const_tree
);
330 static void arc_file_start (void);
331 static void arc_asm_file_start (FILE *) ATTRIBUTE_UNUSED
;
332 static void arc_asm_file_end (void);
333 static void arc_internal_label (FILE *, const char *, unsigned long);
334 static void arc_setup_incoming_varargs (CUMULATIVE_ARGS
*, enum machine_mode
,
336 static void arc_output_mi_thunk (FILE *, tree
, HOST_WIDE_INT
, HOST_WIDE_INT
,
338 static bool arc_rtx_costs (rtx
, int, int, int *, bool);
339 static int arc_address_cost (rtx
, bool);
340 static void arc_encode_section_info (tree decl
, rtx rtl
, int first
);
341 static const char *arc_strip_name_encoding (const char *name
);
342 static bool arc_cannot_force_const_mem (rtx
);
344 static void arc_init_builtins (void);
345 static rtx
arc_expand_builtin (tree
, rtx
, rtx
, enum machine_mode
, int);
347 static int branch_dest (rtx
);
348 static void arc_encode_symbol (tree
, const char);
350 static void arc_output_pic_addr_const (FILE *, rtx
, int);
351 int symbolic_reference_mentioned_p (rtx
);
352 void arc_assemble_name (FILE *, const char*);
353 int arc_raw_symbolic_reference_mentioned_p (rtx
);
354 int arc_legitimate_pic_addr_p (rtx
) ATTRIBUTE_UNUSED
;
355 void emit_pic_move (rtx
*, enum machine_mode
) ATTRIBUTE_UNUSED
;
356 bool arc_legitimate_pic_operand_p (rtx
);
357 bool arc_legitimate_constant_p (rtx
);
358 static bool arc_function_ok_for_sibcall (tree
, tree
);
359 static rtx
arc_function_value (const_tree
, const_tree
, bool);
360 const char * output_shift (rtx
*);
361 static void arc_reorg (void);
362 static bool arc_in_small_data_p (const_tree
);
364 static void arc_init_reg_tables (void);
365 static bool arc_return_in_memory (const_tree
, const_tree
);
366 static bool arc_pass_by_reference (CUMULATIVE_ARGS
*, enum machine_mode
,
368 static int arc_arg_partial_bytes (CUMULATIVE_ARGS
*, enum machine_mode
,
371 static void arc_init_simd_builtins (void);
372 static bool arc_vector_mode_supported_p (enum machine_mode
);
374 static const char *arc_invalid_within_doloop (const_rtx
);
376 static void output_short_suffix (FILE *file
);
378 /* Implements target hook vector_mode_supported_p. */
380 arc_vector_mode_supported_p (enum machine_mode mode
)
382 if (!TARGET_SIMD_SET
)
385 if ((mode
== V4SImode
)
386 || (mode
== V8HImode
))
392 /* to be defined for interrupt attribute addition */
393 /*static tree arc_handle_interrupt_attribute (tree *, tree, tree, int, bool *);*/
396 static bool arc_preserve_reload_p (rtx in
);
397 static rtx
arc_delegitimize_address (rtx
);
398 static bool arc_can_follow_jump (const_rtx follower
, const_rtx followee
);
400 static rtx
frame_insn (rtx
);
402 /* initialize the GCC target structure. */
403 #undef TARGET_ASM_ALIGNED_HI_OP
404 #define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
405 #undef TARGET_ASM_ALIGNED_SI_OP
406 #define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
407 #undef TARGET_ASM_INTEGER
408 #define TARGET_ASM_INTEGER arc_assemble_integer
409 #undef TARGET_COMP_TYPE_ATTRIBUTES
410 #define TARGET_COMP_TYPE_ATTRIBUTES arc_comp_type_attributes
411 #undef TARGET_ASM_FILE_START
412 #define TARGET_ASM_FILE_START arc_file_start
413 #undef TARGET_ASM_FILE_END
414 #define TARGET_ASM_FILE_END arc_asm_file_end
415 #undef TARGET_ATTRIBUTE_TABLE
416 #define TARGET_ATTRIBUTE_TABLE arc_attribute_table
417 #undef TARGET_ASM_INTERNAL_LABEL
418 #define TARGET_ASM_INTERNAL_LABEL arc_internal_label
419 #undef TARGET_RTX_COSTS
420 #define TARGET_RTX_COSTS arc_rtx_costs
421 #undef TARGET_ADDRESS_COST
422 #define TARGET_ADDRESS_COST arc_address_cost
424 #undef TARGET_ENCODE_SECTION_INFO
425 #define TARGET_ENCODE_SECTION_INFO arc_encode_section_info
427 #undef TARGET_STRIP_NAME_ENCODING
428 #define TARGET_STRIP_NAME_ENCODING arc_strip_name_encoding
430 #undef TARGET_CANNOT_FORCE_CONST_MEM
431 #define TARGET_CANNOT_FORCE_CONST_MEM arc_cannot_force_const_mem
433 #undef TARGET_INIT_BUILTINS
434 #define TARGET_INIT_BUILTINS arc_init_builtins
436 #undef TARGET_EXPAND_BUILTIN
437 #define TARGET_EXPAND_BUILTIN arc_expand_builtin
439 #undef TARGET_ASM_OUTPUT_MI_THUNK
440 #define TARGET_ASM_OUTPUT_MI_THUNK arc_output_mi_thunk
442 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
443 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
445 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
446 #define TARGET_FUNCTION_OK_FOR_SIBCALL arc_function_ok_for_sibcall
448 #undef TARGET_MACHINE_DEPENDENT_REORG
449 #define TARGET_MACHINE_DEPENDENT_REORG arc_reorg
451 #undef TARGET_IN_SMALL_DATA_P
452 #define TARGET_IN_SMALL_DATA_P arc_in_small_data_p
454 #undef TARGET_PROMOTE_FUNCTION_ARGS
455 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
457 #undef TARGET_PROMOTE_FUNCTION_RETURN
458 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true
460 #undef TARGET_PROMOTE_PROTOTYPES
461 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
463 #undef TARGET_RETURN_IN_MEMORY
464 #define TARGET_RETURN_IN_MEMORY arc_return_in_memory
465 #undef TARGET_PASS_BY_REFERENCE
466 #define TARGET_PASS_BY_REFERENCE arc_pass_by_reference
468 #undef TARGET_SETUP_INCOMING_VARARGS
469 #define TARGET_SETUP_INCOMING_VARARGS arc_setup_incoming_varargs
471 #undef TARGET_ARG_PARTIAL_BYTES
472 #define TARGET_ARG_PARTIAL_BYTES arc_arg_partial_bytes
474 #undef TARGET_MUST_PASS_IN_STACK
475 #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
477 #undef TARGET_FUNCTION_VALUE
478 #define TARGET_FUNCTION_VALUE arc_function_value
481 #define DEFAULT_NO_SDATA MASK_NO_SDATA_SET
483 #define DEFAULT_NO_SDATA 0
485 #undef TARGET_DEFAULT_TARGET_FLAGS
486 #define TARGET_DEFAULT_TARGET_FLAGS (MASK_VOLATILE_CACHE_SET|DEFAULT_NO_SDATA)
488 #undef TARGET_SCHED_ADJUST_PRIORITY
489 #define TARGET_SCHED_ADJUST_PRIORITY arc_sched_adjust_priority
491 #undef TARGET_VECTOR_MODE_SUPPORTED_P
492 #define TARGET_VECTOR_MODE_SUPPORTED_P arc_vector_mode_supported_p
494 #undef TARGET_INVALID_WITHIN_DOLOOP
495 #define TARGET_INVALID_WITHIN_DOLOOP arc_invalid_within_doloop
497 #undef TARGET_PRESERVE_RELOAD_P
498 #define TARGET_PRESERVE_RELOAD_P arc_preserve_reload_p
500 #undef TARGET_CAN_FOLLOW_JUMP
501 #define TARGET_CAN_FOLLOW_JUMP arc_can_follow_jump
503 #undef TARGET_DELEGITIMIZE_ADDRESS
504 #define TARGET_DELEGITIMIZE_ADDRESS arc_delegitimize_address
506 /* Usually, we will be able to scale anchor offsets.
507 When this fails, we want LEGITIMIZE_ADDRESS to kick in. */
508 #undef TARGET_MIN_ANCHOR_OFFSET
509 #define TARGET_MIN_ANCHOR_OFFSET (-1024)
510 #undef TARGET_MAX_ANCHOR_OFFSET
511 #define TARGET_MAX_ANCHOR_OFFSET (1020)
513 /* Try to keep the (mov:DF _, reg) as early as possible so
514 that the d<add/sub/mul>h-lr insns appear together and can
515 use the peephole2 pattern
518 arc_sched_adjust_priority (rtx insn ATTRIBUTE_UNUSED
, int priority
)
520 rtx set
= single_set (insn
);
522 && GET_MODE (SET_SRC(set
)) == DFmode
523 && GET_CODE (SET_SRC(set
)) == REG
)
525 /* Incrementing priority by 20 (empirically derived). */
526 return priority
+ 20;
532 struct gcc_target targetm
= TARGET_INITIALIZER
;
534 /* Called by OVERRIDE_OPTIONS to initialize various things. */
538 int target_found
= 0;
539 enum attr_tune tune_dflt
= TUNE_NONE
;
543 arc_cpu_string
= "A4";
544 arc_cpu
= PROCESSOR_A4
;
549 arc_cpu_string
= "A5";
550 arc_cpu
= PROCESSOR_A5
;
553 else if (TARGET_ARC600
)
555 arc_cpu_string
= "ARC600";
556 arc_cpu
= PROCESSOR_ARC600
;
557 tune_dflt
= TUNE_ARC600
;
560 else if (TARGET_ARC700
)
562 arc_cpu_string
= "ARC700";
563 arc_cpu
= PROCESSOR_ARC700
;
564 tune_dflt
= TUNE_ARC700_4_2_STD
;
567 if (arc_tune
== TUNE_NONE
)
568 arc_tune
= tune_dflt
;
569 /* Note: arc_multcost is only used in rtx_cost if speed is true. */
570 if (arc_multcost
< 0)
573 case TUNE_ARC700_4_2_STD
:
575 max throughput (1 multiply + 4 other insns) / 5 cycles. */
576 arc_multcost
= COSTS_N_INSNS (4);
578 case TUNE_ARC700_4_2_XMAC
:
580 max throughput (1 multiply + 2 other insns) / 3 cycles. */
581 arc_multcost
= COSTS_N_INSNS (3);
584 if (TARGET_MUL64_SET
)
586 arc_multcost
= COSTS_N_INSNS (4);
591 arc_multcost
= COSTS_N_INSNS (30);
594 if (TARGET_MIXED_CODE_SET
)
596 /* -mmixed-code can not be used with the option -mA4. */
599 error ("-mmixed-code can't be used with the option -mA4");
602 /* If -mmixed-code option is given but target option is *not* given,
603 then ARC700 will be automatically selected */
606 target_flags
|= MASK_ARC700
;
607 arc_cpu_string
= "ARC700";
608 arc_cpu
= PROCESSOR_ARC700
;
613 /* If none of the target option (-mA4,-mA5,-mARC600,-mARC700) is given,
614 select -mA5 as default. */
618 target_flags
|= MASK_A5
;
619 arc_cpu_string
= "A5";
620 arc_cpu
= PROCESSOR_A5
;
622 target_flags
|= MASK_ARC700
;
623 arc_cpu_string
= "ARC700";
624 arc_cpu
= PROCESSOR_ARC700
;
629 /* Support mul64 generation only for A4, A5 and ARC600 */
630 if (TARGET_MUL64_SET
&& TARGET_ARC700
)
631 error ("-mmul64 not supported for ARC700");
633 /* MPY instructions valid only for ARC700 */
634 if (TARGET_NOMPY_SET
&& !TARGET_ARC700
)
635 error ("-mno-mpy supported only for ARC700");
637 /* mul/mac instructions only for ARC600 */
638 if (TARGET_MULMAC_32BY16_SET
&& !TARGET_ARC600
)
639 error ("-mmul32x16 supported only for ARC600");
641 /* Sanity checks for usage of the FPX switches */
642 /* FPX-1. No fast and compact together */
643 if ((TARGET_DPFP_FAST_SET
&& TARGET_DPFP_COMPACT_SET
)
644 || (TARGET_SPFP_FAST_SET
&& TARGET_SPFP_COMPACT_SET
))
645 error ("FPX fast and compact options cannot be specified together");
647 /* FPX-2. No fast-spfp for arc600 */
648 if (TARGET_SPFP_FAST_SET
&& TARGET_ARC600
)
649 error ("-mspfp_fast not available on ARC600");
651 /* FPX-3. No FPX extensions on pre-ARC600 cores */
652 if ((TARGET_DPFP
|| TARGET_SPFP
)
653 && !(TARGET_ARC600
|| TARGET_ARC700
))
654 error ("FPX extensions not available on pre-ARC600 cores");
656 /* Warn for unimplemented PIC in pre-ARC700 cores, and disable flag_pic */
657 if (flag_pic
&& !TARGET_ARC700
)
659 warning (DK_WARNING
, "PIC is not supported for %s. Generating non-PIC code only..", arc_cpu_string
);
663 /* Set the pseudo-ops for the various standard sections. */
664 arc_text_section
= tmp
= XNEWVEC (char, strlen (arc_text_string
) + sizeof (ARC_SECTION_FORMAT
) + 1);
665 sprintf (tmp
, ARC_SECTION_FORMAT
, arc_text_string
);
666 arc_data_section
= tmp
= XNEWVEC (char, strlen (arc_data_string
) + sizeof (ARC_SECTION_FORMAT
) + 1);
667 sprintf (tmp
, ARC_SECTION_FORMAT
, arc_data_string
);
668 arc_rodata_section
= tmp
= XNEWVEC (char, strlen (arc_rodata_string
) + sizeof (ARC_SECTION_FORMAT
) + 1);
669 sprintf (tmp
, ARC_SECTION_FORMAT
, arc_rodata_string
);
671 arc_init_reg_tables ();
673 /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P. */
674 memset (arc_punct_chars
, 0, sizeof (arc_punct_chars
));
675 arc_punct_chars
['#'] = 1;
676 arc_punct_chars
['*'] = 1;
677 arc_punct_chars
['?'] = 1;
678 arc_punct_chars
['!'] = 1;
679 arc_punct_chars
['^'] = 1;
680 arc_punct_chars
['&'] = 1;
681 gcc_obstack_init (&arc_local_obstack
);
684 /* The condition codes of the ARC, and the inverse function. */
685 /* For short branches, the "c" / "nc" names are not defined in the ARC
686 Programmers manual, so we have to use "lo" / "hs"" instead. */
687 static const char *arc_condition_codes
[] =
689 "al", 0, "eq", "ne", "p", "n", "lo", "hs", "v", "nv",
690 "gt", "le", "ge", "lt", "hi", "ls", "pnz", 0
693 enum arc_cc_code_index
695 ARC_CC_AL
, ARC_CC_EQ
= ARC_CC_AL
+2, ARC_CC_NE
, ARC_CC_P
, ARC_CC_N
,
696 ARC_CC_C
, ARC_CC_NC
, ARC_CC_V
, ARC_CC_NV
,
697 ARC_CC_GT
, ARC_CC_LE
, ARC_CC_GE
, ARC_CC_LT
, ARC_CC_HI
, ARC_CC_LS
, ARC_CC_PNZ
,
698 ARC_CC_LO
= ARC_CC_C
, ARC_CC_HS
= ARC_CC_NC
701 #define ARC_INVERSE_CONDITION_CODE(X) ((X) ^ 1)
703 /* Returns the index of the ARC condition code string in
704 `arc_condition_codes'. COMPARISON should be an rtx like
705 `(eq (...) (...))'. */
708 get_arc_condition_code (rtx comparison
)
710 switch (GET_MODE (XEXP (comparison
, 0)))
713 case SImode
: /* For BRcc. */
714 switch (GET_CODE (comparison
))
716 case EQ
: return ARC_CC_EQ
;
717 case NE
: return ARC_CC_NE
;
718 case GT
: return ARC_CC_GT
;
719 case LE
: return ARC_CC_LE
;
720 case GE
: return ARC_CC_GE
;
721 case LT
: return ARC_CC_LT
;
722 case GTU
: return ARC_CC_HI
;
723 case LEU
: return ARC_CC_LS
;
724 case LTU
: return ARC_CC_LO
;
725 case GEU
: return ARC_CC_HS
;
726 default : gcc_unreachable ();
729 switch (GET_CODE (comparison
))
731 case EQ
: return ARC_CC_EQ
;
732 case NE
: return ARC_CC_NE
;
733 case GE
: return ARC_CC_P
;
734 case LT
: return ARC_CC_N
;
735 case GT
: return ARC_CC_PNZ
;
736 default : gcc_unreachable ();
739 switch (GET_CODE (comparison
))
741 case EQ
: return ARC_CC_EQ
;
742 case NE
: return ARC_CC_NE
;
743 default : gcc_unreachable ();
746 switch (GET_CODE (comparison
))
748 case LTU
: return ARC_CC_C
;
749 case GEU
: return ARC_CC_NC
;
750 default : gcc_unreachable ();
754 switch (GET_CODE (comparison
))
756 case GT
: return ARC_CC_N
;
757 case UNLE
: return ARC_CC_P
;
758 default : gcc_unreachable ();
761 switch (GET_CODE (comparison
))
763 case GT
: return ARC_CC_HI
;
764 case UNLE
: return ARC_CC_LS
;
765 default : gcc_unreachable ();
768 /* Same for FPX and non-FPX. */
769 switch (GET_CODE (comparison
))
771 case GE
: return ARC_CC_HS
;
772 case UNLT
: return ARC_CC_LO
;
773 default : gcc_unreachable ();
776 switch (GET_CODE (comparison
))
778 case UNEQ
: return ARC_CC_EQ
;
779 case LTGT
: return ARC_CC_NE
;
780 default : gcc_unreachable ();
783 switch (GET_CODE (comparison
))
785 case UNORDERED
: return ARC_CC_C
;
786 case ORDERED
: return ARC_CC_NC
;
787 default : gcc_unreachable ();
790 switch (GET_CODE (comparison
))
792 case EQ
: return ARC_CC_EQ
;
793 case NE
: return ARC_CC_NE
;
794 case UNORDERED
: return ARC_CC_C
;
795 case ORDERED
: return ARC_CC_NC
;
796 case LTGT
: return ARC_CC_HI
;
797 case UNEQ
: return ARC_CC_LS
;
798 default : gcc_unreachable ();
800 default : gcc_unreachable ();
806 /* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
807 return the mode to be used for the comparison. */
810 arc_select_cc_mode (enum rtx_code op
,
811 rtx x ATTRIBUTE_UNUSED
,
812 rtx y ATTRIBUTE_UNUSED
)
814 enum machine_mode mode
= GET_MODE (x
);
817 /* For an operation that sets the condition codes as a side-effect, the
818 C and V flags is not set as for cmp, so we can only use comparisons where
819 this doesn't matter. (For LT and GE we can use "mi" and "pl"
821 /* ??? We could use "pnz" for greater than zero, however, we could then
822 get into trouble because the comparison could not be reversed. */
823 if (GET_MODE_CLASS (mode
) == MODE_INT
825 && (op
== EQ
|| op
== NE
826 || ((op
== LT
|| op
== GE
) && GET_MODE_SIZE (GET_MODE (x
) <= 4))))
829 /* add.f for if (a+b) */
831 && GET_CODE (y
) == NEG
832 && (op
== EQ
|| op
== NE
))
835 /* Check if this is a test suitable for bxor.f . */
836 if (mode
== SImode
&& (op
== EQ
|| op
== NE
) && CONST_INT_P (y
)
837 && ((INTVAL (y
) - 1) & INTVAL (y
)) == 0
841 /* Check if this is a test suitable for add / bmsk.f . */
842 if (mode
== SImode
&& (op
== EQ
|| op
== NE
) && CONST_INT_P (y
)
843 && GET_CODE (x
) == AND
&& CONST_INT_P ((x1
= XEXP (x
, 1)))
844 && ((INTVAL (x1
) + 1) & INTVAL (x1
)) == 0
845 && (~INTVAL (x1
) | INTVAL (y
)) < 0
846 && (~INTVAL (x1
) | INTVAL (y
)) > -0x800)
849 if (GET_MODE (x
) == SImode
&& (op
== LTU
|| op
== GEU
)
850 && GET_CODE (x
) == PLUS
851 && (rtx_equal_p (XEXP (x
, 0), y
) || rtx_equal_p (XEXP (x
, 1), y
)))
854 if ((mode
== SFmode
&& TARGET_SPFP
) || (mode
== DFmode
&& TARGET_DPFP
))
857 case EQ
: case NE
: case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
859 case LT
: case UNGE
: case GT
: case UNLE
:
861 case LE
: case UNGT
: case GE
: case UNLT
:
863 default: gcc_unreachable ();
865 else if (GET_MODE_CLASS (mode
) == MODE_FLOAT
&& TARGET_OPTFPE
)
868 case EQ
: case NE
: return CC_Zmode
;
870 case GT
: case UNLE
: return CC_FP_GTmode
;
872 case GE
: case UNLT
: return CC_FP_GEmode
;
873 case UNEQ
: case LTGT
: return CC_FP_UNEQmode
;
874 case ORDERED
: case UNORDERED
: return CC_FP_ORDmode
;
875 default: gcc_unreachable ();
881 /* Vectors to keep interesting information about registers where it can easily
882 be got. We use to use the actual mode value as the bit number, but there
883 is (or may be) more than 32 modes now. Instead we use two tables: one
884 indexed by hard register number, and one indexed by mode. */
886 /* The purpose of arc_mode_class is to shrink the range of modes so that
887 they all fit (as bit numbers) in a 32-bit word (again). Each real mode is
888 mapped into one arc_mode_class mode. */
890 enum arc_mode_class
{
892 S_MODE
, D_MODE
, T_MODE
, O_MODE
,
893 SF_MODE
, DF_MODE
, TF_MODE
, OF_MODE
,
897 /* Modes for condition codes. */
898 #define C_MODES (1 << (int) C_MODE)
900 /* Modes for single-word and smaller quantities. */
901 #define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
903 /* Modes for double-word and smaller quantities. */
904 #define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))
906 /* Mode for 8-byte DF values only */
907 #define DF_MODES (1 << DF_MODE)
909 /* Modes for quad-word and smaller quantities. */
910 #define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE))
912 /* Modes for 128-bit vectors. */
913 #define V_MODES (1 << (int) V_MODE)
915 /* Value is 1 if register/mode pair is acceptable on arc. */
917 unsigned int arc_hard_regno_mode_ok
[] = {
918 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
,
919 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
,
920 T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, T_MODES
, D_MODES
,
921 D_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
923 /* ??? Leave these as S_MODES for now. */
924 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
925 DF_MODES
, 0, DF_MODES
, 0, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
926 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
927 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, C_MODES
, S_MODES
,
929 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
930 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
931 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
932 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
934 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
935 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
936 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
937 V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
, V_MODES
,
939 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
,
940 S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
, S_MODES
943 unsigned int arc_mode_class
[NUM_MACHINE_MODES
];
945 enum reg_class arc_regno_reg_class
[FIRST_PSEUDO_REGISTER
];
948 arc_init_reg_tables (void)
952 for (i
= 0; i
< NUM_MACHINE_MODES
; i
++)
954 switch (GET_MODE_CLASS (i
))
957 case MODE_PARTIAL_INT
:
958 case MODE_COMPLEX_INT
:
959 if (GET_MODE_SIZE (i
) <= 4)
960 arc_mode_class
[i
] = 1 << (int) S_MODE
;
961 else if (GET_MODE_SIZE (i
) == 8)
962 arc_mode_class
[i
] = 1 << (int) D_MODE
;
963 else if (GET_MODE_SIZE (i
) == 16)
964 arc_mode_class
[i
] = 1 << (int) T_MODE
;
965 else if (GET_MODE_SIZE (i
) == 32)
966 arc_mode_class
[i
] = 1 << (int) O_MODE
;
968 arc_mode_class
[i
] = 0;
971 case MODE_COMPLEX_FLOAT
:
972 if (GET_MODE_SIZE (i
) <= 4)
973 arc_mode_class
[i
] = 1 << (int) SF_MODE
;
974 else if (GET_MODE_SIZE (i
) == 8)
975 arc_mode_class
[i
] = 1 << (int) DF_MODE
;
976 else if (GET_MODE_SIZE (i
) == 16)
977 arc_mode_class
[i
] = 1 << (int) TF_MODE
;
978 else if (GET_MODE_SIZE (i
) == 32)
979 arc_mode_class
[i
] = 1 << (int) OF_MODE
;
981 arc_mode_class
[i
] = 0;
983 case MODE_VECTOR_INT
:
984 arc_mode_class
[i
] = (1<< (int) V_MODE
);
988 /* mode_class hasn't been initialized yet for EXTRA_CC_MODES, so
989 we must explicitly check for them here. */
990 if (i
== (int) CCmode
|| i
== (int) CC_ZNmode
|| i
== (int) CC_Zmode
991 || i
== (int) CC_Cmode
992 || i
== CC_FP_GTmode
|| i
== CC_FP_GEmode
|| i
== CC_FP_ORDmode
)
993 arc_mode_class
[i
] = 1 << (int) C_MODE
;
995 arc_mode_class
[i
] = 0;
1001 /* Core registers 56..59 are used for multiply extension options.
1002 The dsp option uses r56 and r57, these are then named acc1 and acc2.
1003 acc1 is the highpart, and acc2 the lowpart, so which register gets which
1004 number depends on endianness.
1005 The mul64 multiplier options use r57 for mlo, r58 for mmid and r59 for mhi.
1006 Because mlo / mhi form a 64 bit value, we use different gcc internal
1007 register numbers to make them form a register pair as the gcc internals
1008 know it. mmid gets number 57, if still available, and mlo / mhi get
1009 number 58 and 59, depending on endianness. We use DBX_REGISTER_NUMBER
1010 to map this back. */
1011 char rname56
[5] = "r56";
1012 char rname57
[5] = "r57";
1013 char rname58
[5] = "r58";
1014 char rname59
[5] = "r59";
1017 arc_conditional_register_usage (void)
1021 int fix_start
= 60, fix_end
= 55;
1023 if (TARGET_MUL64_SET
)
1028 /* We don't provide a name for mmed. In rtl / assembly resource lists,
1029 you are supposed to refer to it as mlo & mhi, e.g
1030 (zero_extract:SI (reg:DI 58) (const_int 32) (16)) .
1031 In an actual asm instruction, you are of course use mmed.
1032 The point of avoiding having a separate register for mmed is that
1033 this way, we don't have to carry clobbers of that reg around in every
1034 isntruction that modifies mlo and/or mhi. */
1035 strcpy (rname57
, "");
1036 strcpy (rname58
, TARGET_BIG_ENDIAN
? "mhi" : "mlo");
1037 strcpy (rname59
, TARGET_BIG_ENDIAN
? "mlo" : "mhi");
1039 if (TARGET_MULMAC_32BY16_SET
)
1042 fix_end
= fix_end
> 57 ? fix_end
: 57;
1043 strcpy (rname56
, TARGET_BIG_ENDIAN
? "acc1" : "acc2");
1044 strcpy (rname57
, TARGET_BIG_ENDIAN
? "acc2" : "acc1");
1046 for (regno
= fix_start
; regno
<= fix_end
; regno
++)
1048 if (!fixed_regs
[regno
])
1049 warning (0, "multiply option implies r%d is fixed", regno
);
1050 fixed_regs
[regno
] = call_used_regs
[regno
] = 1;
1054 reg_alloc_order
[2] = 12;
1055 reg_alloc_order
[3] = 13;
1056 reg_alloc_order
[4] = 14;
1057 reg_alloc_order
[5] = 15;
1058 reg_alloc_order
[6] = 1;
1059 reg_alloc_order
[7] = 0;
1060 reg_alloc_order
[8] = 4;
1061 reg_alloc_order
[9] = 5;
1062 reg_alloc_order
[10] = 6;
1063 reg_alloc_order
[11] = 7;
1064 reg_alloc_order
[12] = 8;
1065 reg_alloc_order
[13] = 9;
1066 reg_alloc_order
[14] = 10;
1067 reg_alloc_order
[15] = 11;
1069 if (TARGET_SIMD_SET
)
1072 for (i
=64; i
<88; i
++)
1073 reg_alloc_order
[i
] = i
;
1075 /* For Arctangent-A5 / ARC600, lp_count may not be read in an instruction
1076 following immediately after another one setting it to a new value.
1077 There was some discussion on how to enforce scheduling constraints for
1078 processors with missing interlocks on the gcc mailing list:
1079 http://gcc.gnu.org/ml/gcc/2008-05/msg00021.html .
1080 However, we can't actually use this approach, because for ARC the
1081 delay slot scheduling pass is active, which runs after
1082 machine_dependent_reorg. */
1084 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], LP_COUNT
);
1085 else if (!TARGET_ARC700
)
1086 fixed_regs
[LP_COUNT
] = 1;
1087 for (regno
= 0; regno
< FIRST_PSEUDO_REGISTER
; regno
++)
1088 if (!call_used_regs
[regno
])
1089 CLEAR_HARD_REG_BIT (reg_class_contents
[SIBCALL_REGS
], regno
);
1090 for (regno
= 32; regno
< 60; regno
++)
1091 if (!fixed_regs
[regno
])
1092 SET_HARD_REG_BIT (reg_class_contents
[WRITABLE_CORE_REGS
], regno
);
1095 for (regno
= 32; regno
<= 60; regno
++)
1096 CLEAR_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], regno
);
1097 arc_hard_regno_mode_ok
[60] = 1 << (int) S_MODE
;
1100 for (i
= 0; i
< FIRST_PSEUDO_REGISTER
; i
++)
1104 if (TARGET_Q_CLASS
&& ((i
<= 3) || ((i
>= 12) && (i
<= 15))))
1105 arc_regno_reg_class
[i
] = ARCOMPACT16_REGS
;
1107 arc_regno_reg_class
[i
] = GENERAL_REGS
;
1110 arc_regno_reg_class
[i
]
1112 ? (TEST_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], i
)
1113 ? CHEAP_CORE_REGS
: ALL_CORE_REGS
)
1115 && TEST_HARD_REG_BIT (reg_class_contents
[CHEAP_CORE_REGS
], i
))
1116 ? CHEAP_CORE_REGS
: WRITABLE_CORE_REGS
));
1119 arc_regno_reg_class
[i
] = NO_REGS
;
1123 /* ARCOMPACT16_REGS is empty, if TARGET_Q_CLASS has not been activated. */
1124 if (!TARGET_Q_CLASS
)
1126 CLEAR_HARD_REG_SET(reg_class_contents
[ARCOMPACT16_REGS
]);
1127 CLEAR_HARD_REG_SET(reg_class_contents
[AC16_BASE_REGS
]);
1130 gcc_assert (FIRST_PSEUDO_REGISTER
>= 144);
1132 /* Handle Special Registers */
1133 arc_regno_reg_class
[29] = LINK_REGS
; /* ilink1 register */
1134 arc_regno_reg_class
[30] = LINK_REGS
; /* ilink2 register */
1135 arc_regno_reg_class
[31] = LINK_REGS
; /* blink register */
1136 arc_regno_reg_class
[60] = LPCOUNT_REG
;
1137 arc_regno_reg_class
[61] = NO_REGS
; /* CC_REG: must be NO_REGS */
1138 arc_regno_reg_class
[62] = GENERAL_REGS
;
1142 arc_regno_reg_class
[40] = DOUBLE_REGS
;
1143 arc_regno_reg_class
[41] = DOUBLE_REGS
;
1144 arc_regno_reg_class
[42] = DOUBLE_REGS
;
1145 arc_regno_reg_class
[43] = DOUBLE_REGS
;
1149 /* Disable all DOUBLE_REGISTER settings,
1150 if not generating DPFP code */
1151 arc_regno_reg_class
[40] = ALL_REGS
;
1152 arc_regno_reg_class
[41] = ALL_REGS
;
1153 arc_regno_reg_class
[42] = ALL_REGS
;
1154 arc_regno_reg_class
[43] = ALL_REGS
;
1156 arc_hard_regno_mode_ok
[40] = 0;
1157 arc_hard_regno_mode_ok
[42] = 0;
1159 CLEAR_HARD_REG_SET(reg_class_contents
[DOUBLE_REGS
]);
1162 if (TARGET_SIMD_SET
)
1164 gcc_assert (ARC_FIRST_SIMD_VR_REG
== 64);
1165 gcc_assert (ARC_LAST_SIMD_VR_REG
== 127);
1167 for (i
= ARC_FIRST_SIMD_VR_REG
; i
<= ARC_LAST_SIMD_VR_REG
; i
++)
1168 arc_regno_reg_class
[i
] = SIMD_VR_REGS
;
1170 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_REG
== 128);
1171 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_IN_REG
== 128);
1172 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG
== 136);
1173 gcc_assert (ARC_LAST_SIMD_DMA_CONFIG_REG
== 143);
1175 for (i
= ARC_FIRST_SIMD_DMA_CONFIG_REG
; i
<= ARC_LAST_SIMD_DMA_CONFIG_REG
; i
++)
1176 arc_regno_reg_class
[i
] = SIMD_DMA_CONFIG_REGS
;
1180 arc_regno_reg_class
[PROGRAM_COUNTER_REGNO
] = GENERAL_REGS
;
1183 /* ARC specific attribute support.
1185 The ARC has these attributes:
1186 interrupt - for interrupt functions
1189 /* Return nonzero if IDENTIFIER is a valid decl attribute. */
1192 arc_valid_machine_decl_attribute (tree type ATTRIBUTE_UNUSED
,
1193 tree attributes ATTRIBUTE_UNUSED
,
1194 tree identifier ATTRIBUTE_UNUSED
,
1195 tree args ATTRIBUTE_UNUSED
)
1197 if (identifier
== get_identifier ("__nterrupt__")
1198 && list_length (args
) == 1
1199 && TREE_CODE (TREE_VALUE (args
)) == STRING_CST
)
1201 tree value
= TREE_VALUE (args
);
1203 if (!strcmp (TREE_STRING_POINTER (value
), "ilink1")
1204 || !strcmp (TREE_STRING_POINTER (value
), "ilink2"))
1210 /* Return zero if TYPE1 and TYPE are incompatible, one if they are compatible,
1211 and two if they are nearly compatible (which causes a warning to be
1215 arc_comp_type_attributes (const_tree type1
,
1220 /* Check for mismatch of non-default calling convention. */
1221 if (TREE_CODE (type1
) != FUNCTION_TYPE
)
1224 /* Check for mismatched call attributes. */
1225 l1
= lookup_attribute ("long_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
1226 l2
= lookup_attribute ("long_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
1227 s1
= lookup_attribute ("short_call", TYPE_ATTRIBUTES (type1
)) != NULL
;
1228 s2
= lookup_attribute ("short_call", TYPE_ATTRIBUTES (type2
)) != NULL
;
1230 /* Only bother to check if an attribute is defined. */
1231 if (l1
| l2
| s1
| s2
)
1233 /* If one type has an attribute, the other must have the same attribute. */
1234 if ((l1
!= l2
) || (s1
!= s2
))
1237 /* Disallow mixed attributes. */
1238 if ((l1
& s2
) || (l2
& s1
))
1246 /* Set the default attributes for TYPE. */
1249 arc_set_default_type_attributes (tree type ATTRIBUTE_UNUSED
)
1254 /* Misc. utilities. */
1256 /* X and Y are two things to compare using CODE. Emit the compare insn and
1257 return the rtx for the cc reg in the proper mode. */
1260 gen_compare_reg (enum rtx_code code
, enum machine_mode omode
)
1262 rtx x
= arc_compare_op0
, y
= arc_compare_op1
;
1263 enum machine_mode mode
= SELECT_CC_MODE (code
, x
, y
);
1264 enum machine_mode cmode
= GET_MODE (x
);
1267 cc_reg
= gen_rtx_REG (mode
, 61);
1269 if ((cmode
== SFmode
&& TARGET_SPFP
) || (cmode
== DFmode
&& TARGET_DPFP
))
1273 case NE
: case EQ
: case LT
: case UNGE
: case LE
: case UNGT
:
1274 case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1276 case GT
: case UNLE
: case GE
: case UNLT
:
1277 code
= swap_condition (code
);
1278 x
= arc_compare_op1
;
1279 y
= arc_compare_op0
;
1284 emit_insn ((cmode
== SFmode
? gen_cmpsfpx_raw
: gen_cmpdfpx_raw
) (x
, y
));
1285 if (mode
!= CC_FPXmode
)
1286 emit_insn (gen_rtx_SET (VOIDmode
, cc_reg
,
1287 gen_rtx_COMPARE (mode
,
1288 gen_rtx_REG (CC_FPXmode
, 61),
1291 else if (GET_MODE_CLASS (cmode
) == MODE_FLOAT
&& TARGET_OPTFPE
)
1293 rtx op0
= gen_rtx_REG (cmode
, 0);
1294 rtx op1
= gen_rtx_REG (cmode
, GET_MODE_SIZE (cmode
) / UNITS_PER_WORD
);
1298 case NE
: case EQ
: case GT
: case UNLE
: case GE
: case UNLT
:
1299 case UNEQ
: case LTGT
: case ORDERED
: case UNORDERED
:
1301 case LT
: case UNGE
: case LE
: case UNGT
:
1302 code
= swap_condition (code
);
1303 x
= arc_compare_op1
;
1304 y
= arc_compare_op0
;
1309 if (currently_expanding_to_rtl
)
1311 emit_move_insn (op0
, x
);
1312 emit_move_insn (op1
, y
);
1316 gcc_assert (rtx_equal_p (op0
, x
));
1317 gcc_assert (rtx_equal_p (op1
, y
));
1319 emit_insn (gen_cmp_float (cc_reg
, gen_rtx_COMPARE (mode
, op0
, op1
)));
1322 emit_insn (gen_rtx_SET (omode
, cc_reg
,
1323 gen_rtx_COMPARE (mode
, x
, y
)));
1324 return gen_rtx_fmt_ee (code
, omode
, cc_reg
, const0_rtx
);
1327 /* Return 1 if VALUE, a const_double, will fit in a limm (4 byte number).
1328 We assume the value can be either signed or unsigned. */
1331 arc_double_limm_p (rtx value
)
1333 HOST_WIDE_INT low
, high
;
1335 gcc_assert (GET_CODE (value
) == CONST_DOUBLE
);
1340 low
= CONST_DOUBLE_LOW (value
);
1341 high
= CONST_DOUBLE_HIGH (value
);
1343 if (low
& 0x80000000)
1345 return (((unsigned HOST_WIDE_INT
) low
<= 0xffffffff && high
== 0)
1346 || (((low
& - (unsigned HOST_WIDE_INT
) 0x80000000)
1347 == - (unsigned HOST_WIDE_INT
) 0x80000000)
1352 return (unsigned HOST_WIDE_INT
) low
<= 0x7fffffff && high
== 0;
1356 /* Do any needed setup for a variadic function. For the ARC, we must
1357 create a register parameter block, and then copy any anonymous arguments
1358 in registers to memory.
1360 CUM has not been updated for the last named argument which has type TYPE
1361 and mode MODE, and we rely on this fact. */
1363 arc_setup_incoming_varargs (CUMULATIVE_ARGS
*args_so_far
,
1364 enum machine_mode mode
,
1365 tree type ATTRIBUTE_UNUSED
,
1370 CUMULATIVE_ARGS next_cum
;
1372 /* We must treat `__builtin_va_alist' as an anonymous arg. */
1374 next_cum
= *args_so_far
;
1375 arc_function_arg_advance (&next_cum
, mode
, type
, 1);
1376 first_anon_arg
= next_cum
;
1378 if (first_anon_arg
< MAX_ARC_PARM_REGS
)
1380 /* First anonymous (unnamed) argument is in a reg */
1382 /* Note that first_reg_offset < MAX_ARC_PARM_REGS. */
1383 int first_reg_offset
= first_anon_arg
;
1388 = gen_rtx_MEM (BLKmode
, plus_constant (arg_pointer_rtx
,
1389 FIRST_PARM_OFFSET (0)));
1390 move_block_from_reg (first_reg_offset
, regblock
,
1391 MAX_ARC_PARM_REGS
- first_reg_offset
);
1395 = ((MAX_ARC_PARM_REGS
- first_reg_offset
) * UNITS_PER_WORD
);
1399 /* Cost functions. */
1401 /* Provide the costs of an addressing mode that contains ADDR.
1402 If ADDR is not a valid address, its cost is irrelevant. */
1405 arc_address_cost (rtx addr
, bool speed
)
1407 switch (GET_CODE (addr
))
1410 return speed
|| satisfies_constraint_Rcq (addr
) ? 0 : 1;
1411 case PRE_INC
: case PRE_DEC
: case POST_INC
: case POST_DEC
:
1412 case PRE_MODIFY
: case POST_MODIFY
:
1418 /* Most likely needs a LIMM. */
1419 return COSTS_N_INSNS (1);
1423 register rtx plus0
= XEXP (addr
, 0);
1424 register rtx plus1
= XEXP (addr
, 1);
1426 if (GET_CODE (plus0
) != REG
1427 && (GET_CODE (plus0
) != MULT
1428 || !CONST_INT_P (XEXP (plus0
, 1))
1429 || (INTVAL (XEXP (plus0
, 1)) != 2
1430 && INTVAL (XEXP (plus0
, 1)) != 4)))
1433 switch (GET_CODE (plus1
))
1437 ? (SMALL_INT (INTVAL (plus1
)) ? 1 : 2)
1438 : !RTX_OK_FOR_OFFSET_P (SImode
, plus1
)
1442 : (satisfies_constraint_Rcq (plus0
)
1443 && satisfies_constraint_O (plus1
))
1447 return (speed
< 1 ? 0
1448 : (satisfies_constraint_Rcq (plus0
)
1449 && satisfies_constraint_Rcq (plus1
))
1454 return COSTS_N_INSNS (1);
1467 /* Emit instruction X with the frame related bit set. */
1472 RTX_FRAME_RELATED_P (x
) = 1;
1476 /* Emit a frame insn to move SRC to DST. */
1478 frame_move (rtx dst
, rtx src
)
1480 return frame_insn (gen_rtx_SET (VOIDmode
, dst
, src
));
1483 /* Like frame_move, but add a REG_INC note for REG if ADDR contains an
1484 auto increment address, or is zero. */
1486 frame_move_inc (rtx dst
, rtx src
, rtx reg
, rtx addr
)
1488 rtx insn
= frame_move (dst
, src
);
1491 || GET_CODE (addr
) == PRE_DEC
|| GET_CODE (addr
) == POST_INC
1492 || GET_CODE (addr
) == PRE_MODIFY
|| GET_CODE (addr
) == POST_MODIFY
)
1493 REG_NOTES (insn
) = gen_rtx_EXPR_LIST (REG_INC
, reg
, 0);
1497 /* Emit a frame insn which adjusts a frame address register REG by OFFSET. */
1499 frame_add (rtx reg
, HOST_WIDE_INT offset
)
1501 gcc_assert ((offset
& 0x3) == 0);
1504 return frame_move (reg
, plus_constant (reg
, offset
));
1507 /* Emit a frame insn which adjusts stack pointer by OFFSET. */
1509 frame_stack_add (HOST_WIDE_INT offset
)
1511 return frame_add (stack_pointer_rtx
, offset
);
1514 /* Traditionally, we push saved registers first in the prologue,
1515 then we allocate the rest of the frame - and reverse in the epilogue.
1516 This has still its merits for ease of debugging, or saving code size
1517 or even execution time if the stack frame is so large that some accesses
1518 can't be encoded anymore with offsets in the instruction code when using
1520 Also, it would be a good starting point if we got instructions to help
1521 with register save/restore.
1523 However, often stack frames are small, and the pushing / popping has
1525 - the stack modification prevents a lot of scheduling.
1526 - frame allocation / deallocation needs extra instructions.
1527 - unless we know that we compile ARC700 user code, we need to put
1528 a memory barrier after frame allocation / before deallocation to
1529 prevent interrupts clobbering our data in the frame.
1530 In particular, we don't have any such guarantees for library functions,
1531 which tend to, on the other hand, to have small frames.
1533 Thus, for small frames, we'd like to use a different scheme:
1534 - The frame is allocated in full with the first prologue instruction,
1535 and deallocated in full with the last epilogue instruction.
1536 Thus, the instructions in-betwen can be freely scheduled.
1537 - If the function has no outgoing arguments on the stack, we can allocate
1538 one register save slot at the top of the stack. This register can then
1539 be saved simultanously with frame allocation, and restored with
1541 This register can be picked depending on scheduling considerations,
1542 although same though should go into having some set of registers
1543 to be potentially lingering after a call, and others to be available
1544 immediately - i.e. in the absence of interprocedual optimization, we
1545 can use an ABI-like convention for register allocation to reduce
1546 stalls after function return. */
1547 /* Function prologue/epilogue handlers. */
1549 /* ARCtangent-A4 stack frames look like:
1551 Before call After call
1552 +-----------------------+ +-----------------------+
1554 high | local variables, | | local variables, |
1555 mem | reg save area, etc. | | reg save area, etc. |
1557 +-----------------------+ +-----------------------+
1559 | arguments on stack. | | arguments on stack. |
1561 SP+16->+-----------------------+FP+48->+-----------------------+
1562 | 4 word save area for | | reg parm save area, |
1563 | return addr, prev %fp | | only created for |
1564 SP+0->+-----------------------+ | variable argument |
1566 FP+16->+-----------------------+
1567 | 4 word save area for |
1568 | return addr, prev %fp |
1569 FP+0->+-----------------------+
1573 +-----------------------+
1575 | register save area |
1577 +-----------------------+
1579 | alloca allocations |
1581 +-----------------------+
1583 | arguments on stack |
1585 SP+16->+-----------------------+
1586 low | 4 word save area for |
1587 memory | return addr, prev %fp |
1588 SP+0->+-----------------------+
1590 ARCompact stack frames look like:
1592 Before call After call
1593 high +-----------------------+ +-----------------------+
1594 mem | reg parm save area | | reg parm save area |
1595 | only created for | | only created for |
1596 | variable arg fns | | variable arg fns |
1597 AP +-----------------------+ +-----------------------+
1598 | return addr register | | return addr register |
1599 | (if required) | | (if required) |
1600 +-----------------------+ +-----------------------+
1602 | reg save area | | reg save area |
1604 +-----------------------+ +-----------------------+
1605 | frame pointer | | frame pointer |
1606 | (if required) | | (if required) |
1607 FP +-----------------------+ +-----------------------+
1609 | local/temp variables | | local/temp variables |
1611 +-----------------------+ +-----------------------+
1613 | arguments on stack | | arguments on stack |
1615 SP +-----------------------+ +-----------------------+
1616 | reg parm save area |
1617 | only created for |
1618 | variable arg fns |
1619 AP +-----------------------+
1620 | return addr register |
1622 +-----------------------+
1626 +-----------------------+
1629 FP +-----------------------+
1631 | local/temp variables |
1633 +-----------------------+
1635 | arguments on stack |
1637 mem SP +-----------------------+
1640 1) The "reg parm save area" does not exist for non variable argument fns.
1641 The "reg parm save area" can be eliminated completely if we created our
1642 own va-arc.h, but that has tradeoffs as well (so it's not done). */
1644 /* Structure to be filled in by arc_compute_frame_size with register
1645 save masks, and offsets for the current function. */
1646 struct arc_frame_info
GTY (())
1648 unsigned int total_size
; /* # bytes that the entire frame takes up. */
1649 unsigned int extra_size
; /* # bytes of extra stuff. */
1650 unsigned int pretend_size
; /* # bytes we push and pretend caller did. */
1651 unsigned int args_size
; /* # bytes that outgoing arguments take up. */
1652 unsigned int reg_size
; /* # bytes needed to store regs. */
1653 unsigned int var_size
; /* # bytes that variables take up. */
1654 unsigned int reg_offset
; /* Offset from new sp to store regs. */
1655 unsigned int gmask
; /* Mask of saved gp registers. */
1656 int initialized
; /* Nonzero if frame size already calculated. */
1657 short millicode_start_reg
;
1658 short millicode_end_reg
;
1659 bool save_return_addr
;
1662 /* Defining data structures for per-function information */
1664 typedef struct machine_function
GTY (())
1666 enum arc_function_type fn_type
;
1667 struct arc_frame_info frame_info
;
1668 /* To keep track of unalignment caused by short insns. */
1670 int force_short_suffix
; /* Used when disgorging return delay slot insns. */
1671 const char *size_reason
;
1672 struct arc_ccfsm ccfsm_current
;
1673 /* Map from uid to ccfsm state during branch shortening. */
1674 rtx ccfsm_current_insn
;
1675 char arc_reorg_started
;
1676 char prescan_initialized
;
1679 /* Type of function DECL.
1681 The result is cached. To reset the cache at the end of a function,
1682 call with DECL = NULL_TREE. */
1684 enum arc_function_type
1685 arc_compute_function_type (struct function
*fun
)
1687 tree decl
= fun
->decl
;
1689 enum arc_function_type fn_type
= fun
->machine
->fn_type
;
1691 if (fn_type
!= ARC_FUNCTION_UNKNOWN
)
1694 /* Assume we have a normal function (not an interrupt handler). */
1695 fn_type
= ARC_FUNCTION_NORMAL
;
1697 /* Now see if this is an interrupt handler. */
1698 for (a
= DECL_ATTRIBUTES (decl
);
1702 tree name
= TREE_PURPOSE (a
), args
= TREE_VALUE (a
);
1704 if (name
== get_identifier ("__interrupt__")
1705 && list_length (args
) == 1
1706 && TREE_CODE (TREE_VALUE (args
)) == STRING_CST
)
1708 tree value
= TREE_VALUE (args
);
1710 if (!strcmp (TREE_STRING_POINTER (value
), "ilink1"))
1711 fn_type
= ARC_FUNCTION_ILINK1
;
1712 else if (!strcmp (TREE_STRING_POINTER (value
), "ilink2"))
1713 fn_type
= ARC_FUNCTION_ILINK2
;
1720 return fun
->machine
->fn_type
= fn_type
;
1723 #define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
1724 #define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM))
1726 /* Tell prologue and epilogue if register REGNO should be saved / restored.
1727 The return address and frame pointer are treated separately.
1728 Don't consider them here.
1729 Addition for pic: The gp register needs to be saved if the current
1730 function changes it to access gotoff variables.
1731 FIXME: This will not be needed if we used some arbitrary register
1734 #define MUST_SAVE_REGISTER(regno, interrupt_p) \
1735 (((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \
1736 && (df_regs_ever_live_p (regno) && (!call_used_regs[regno] || interrupt_p))) \
1737 || (flag_pic && crtl->uses_pic_offset_table \
1738 && regno == PIC_OFFSET_TABLE_REGNUM) )
1740 #define MUST_SAVE_RETURN_ADDR \
1741 (cfun->machine->frame_info.save_return_addr)
1743 /* Return non-zero if there are registers to be saved or loaded using
1744 millicode thunks. We can only use consecutive sequences starting
1745 with r13, and not going beyond r25.
1746 GMASK is a bitmask of registers to save. This function sets
1747 FRAME->millicod_start_reg .. FRAME->millicode_end_reg to the range
1748 of registers to be saved / restored with a millicode call. */
1750 arc_compute_millicode_save_restore_regs (unsigned int gmask
,
1751 struct arc_frame_info
*frame
)
1755 int start_reg
= 13, end_reg
= 25;
1757 for (regno
= start_reg
; regno
<= end_reg
&& (gmask
& (1L << regno
));)
1759 end_reg
= regno
- 1;
1760 /* There is no point in using millicode thunks if we don't save/restore
1761 at least three registers. For non-leaf functions we also have the
1763 if (regno
- start_reg
>= 3 - (current_function_is_leaf
== 0))
1765 frame
->millicode_start_reg
= 13;
1766 frame
->millicode_end_reg
= regno
- 1;
1772 /* Return the bytes needed to compute the frame pointer from the current
1775 SIZE is the size needed for local variables. */
1778 arc_compute_frame_size (int size
) /* size = # of var. bytes allocated. */
1781 unsigned int total_size
, var_size
, args_size
, pretend_size
, extra_size
;
1782 unsigned int reg_size
, reg_offset
;
1784 enum arc_function_type fn_type
;
1786 struct arc_frame_info
*frame_info
= &cfun
->machine
->frame_info
;
1788 size
= ARC_STACK_ALIGN (size
);
1790 /* 1) Size of locals and temporaries */
1793 /* 2) Size of outgoing arguments */
1794 args_size
= crtl
->outgoing_args_size
;
1796 /* 3) Calculate space needed for saved registers.
1797 ??? We ignore the extension registers for now. */
1799 /* See if this is an interrupt handler. Call used registers must be saved
1804 fn_type
= arc_compute_function_type (cfun
);
1805 interrupt_p
= ARC_INTERRUPT_P (fn_type
);
1807 for (regno
= 0; regno
<= 31; regno
++)
1809 if (MUST_SAVE_REGISTER (regno
, interrupt_p
))
1811 reg_size
+= UNITS_PER_WORD
;
1812 gmask
|= 1 << regno
;
1816 /* 4) Space for back trace data structure.
1819 <return addr reg size> + <fp size> + <static link reg size> +
1823 <return addr reg size> (if required) + <fp size> (if required)
1825 frame_info
->save_return_addr
1826 = (!current_function_is_leaf
|| df_regs_ever_live_p (RETURN_ADDR_REGNUM
));
1827 /* Saving blink reg in case of leaf function for millicode thunk calls */
1828 if (optimize_size
&& !TARGET_NO_MILLICODE_THUNK_SET
)
1830 if (arc_compute_millicode_save_restore_regs (gmask
, frame_info
))
1831 frame_info
->save_return_addr
= true;
1841 if (MUST_SAVE_RETURN_ADDR
)
1843 if (frame_pointer_needed
)
1847 /* 5) Space for variable arguments passed in registers */
1848 pretend_size
= crtl
->args
.pretend_args_size
;
1850 /* Ensure everything before the locals is aligned appropriately */
1851 if (TARGET_ARCOMPACT
)
1853 unsigned int extra_plus_reg_size
;
1854 unsigned int extra_plus_reg_size_aligned
;
1856 extra_plus_reg_size
= extra_size
+ reg_size
;
1857 extra_plus_reg_size_aligned
= ARC_STACK_ALIGN(extra_plus_reg_size
);
1858 reg_size
= extra_plus_reg_size_aligned
- extra_size
;
1861 /* Compute total frame size */
1862 total_size
= var_size
+ args_size
+ extra_size
+ pretend_size
+ reg_size
;
1864 total_size
= ARC_STACK_ALIGN (total_size
);
1866 /* Compute offset of register save area from stack pointer:
1867 A4 Frame: pretend_size var_size reg_size args_size extra_size <--sp
1868 A5 Frame: pretend_size <blink> reg_size <fp> var_size args_size <--sp
1871 reg_offset
= total_size
- (pretend_size
+ var_size
+ reg_size
);
1873 reg_offset
= total_size
- (pretend_size
+ reg_size
+ extra_size
) +
1874 (frame_pointer_needed
? 4 : 0);
1876 /* Save computed information. */
1877 frame_info
->total_size
= total_size
;
1878 frame_info
->extra_size
= extra_size
;
1879 frame_info
->pretend_size
= pretend_size
;
1880 frame_info
->var_size
= var_size
;
1881 frame_info
->args_size
= args_size
;
1882 frame_info
->reg_size
= reg_size
;
1883 frame_info
->reg_offset
= reg_offset
;
1884 frame_info
->gmask
= gmask
;
1885 frame_info
->initialized
= reload_completed
;
1887 /* Ok, we're done. */
1891 /* Common code to save/restore registers. */
1892 /* epilogue_p 0: prologue 1:epilogue 2:epilogue, sibling thunk */
1894 arc_save_restore (rtx base_reg
, unsigned int offset
,
1895 unsigned int gmask
, int epilogue_p
, int *first_offset
)
1898 struct arc_frame_info
*frame
= &cfun
->machine
->frame_info
;
1899 rtx sibthunk_insn
= NULL_RTX
;
1900 rtx extra_pop
= NULL_RTX
;
1904 /* Millicode thunks implementation:
1905 Generates calls to millicodes for registers starting from r13 to r25
1906 Present Limitations:
1907 > Only one range supported. The remaining regs will have the ordinary
1908 st and ld instructions for store and loads. Hence a gmask asking
1909 to store r13-14, r16-r25 will only generate calls to store and
1910 load r13 to r14 while store and load insns will be generated for
1911 r16 to r25 in the prologue and epilogue respectively.
1913 > Presently library only supports register ranges starting from
1916 if (epilogue_p
== 2 || frame
->millicode_end_reg
> 14)
1918 int start_call
= frame
->millicode_start_reg
;
1919 int end_call
= frame
->millicode_end_reg
;
1920 int n_regs
= end_call
- start_call
+ 1;
1921 int i
= 0, r
, off
= 0;
1923 rtx ret_addr
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
1927 /* "reg_size" won't be more than 127 */
1928 gcc_assert (epilogue_p
|| abs (*first_offset
<= 127));
1929 frame_add (base_reg
, *first_offset
);
1932 insn
= gen_rtx_PARALLEL
1933 (VOIDmode
, rtvec_alloc ((epilogue_p
== 2) + n_regs
+ 1));
1934 if (epilogue_p
== 2)
1936 int adj
= n_regs
* 4;
1937 rtx r12
= gen_rtx_REG (Pmode
, 12);
1939 frame_insn (gen_rtx_SET (VOIDmode
, r12
, GEN_INT (adj
)));
1940 XVECEXP (insn
, 0, 0) = gen_rtx_RETURN (VOIDmode
);
1941 XVECEXP (insn
, 0, 1)
1942 = gen_rtx_SET (VOIDmode
, stack_pointer_rtx
,
1943 gen_rtx_PLUS (Pmode
, stack_pointer_rtx
, r12
));
1947 XVECEXP (insn
, 0, n_regs
) = gen_rtx_CLOBBER (VOIDmode
, ret_addr
);
1948 for (r
= start_call
; r
<= end_call
; r
++, off
+= UNITS_PER_WORD
, i
++)
1950 rtx reg
= gen_rtx_REG (SImode
, r
);
1951 rtx mem
= gen_frame_mem (SImode
, plus_constant (base_reg
, off
));
1954 XVECEXP (insn
, 0, i
) = gen_rtx_SET (VOIDmode
, reg
, mem
);
1956 XVECEXP (insn
, 0, i
) = gen_rtx_SET (VOIDmode
, mem
, reg
);
1957 gmask
= gmask
& ~(1L << r
);
1959 if (epilogue_p
== 2)
1960 sibthunk_insn
= insn
;
1968 for (regno
= 0; regno
<= 31; regno
++)
1970 if ((gmask
& (1L << regno
)) != 0)
1972 rtx reg
= gen_rtx_REG (SImode
, regno
);
1973 rtx addr
, mem
, insn
;
1975 if (epilogue_p
== 2 && !extra_pop
)
1978 offset
+= UNITS_PER_WORD
;
1983 gcc_assert (!offset
);
1984 addr
= plus_constant (base_reg
, *first_offset
);
1985 addr
= gen_rtx_PRE_MODIFY (Pmode
, base_reg
, addr
);
1990 gcc_assert (SMALL_INT (offset
));
1991 addr
= plus_constant (base_reg
, offset
);
1993 mem
= gen_frame_mem (SImode
, addr
);
1995 insn
= frame_move_inc (reg
, mem
, base_reg
, addr
);
1997 insn
= frame_move_inc (mem
, reg
, base_reg
, addr
);
1998 offset
+= UNITS_PER_WORD
;
2003 rtx addr
= gen_rtx_POST_MODIFY (Pmode
, base_reg
,
2004 plus_constant (base_reg
, offset
));
2005 rtx mem
= gen_frame_mem (SImode
, addr
);
2006 frame_move_inc (extra_pop
, mem
, base_reg
, addr
);
2011 sibthunk_insn
= emit_jump_insn (sibthunk_insn
);
2012 RTX_FRAME_RELATED_P (sibthunk_insn
) = 1;
2014 } /* arc_save_restore */
2017 /* Target hook to assemble an integer object. The ARC version needs to
2018 emit a special directive for references to labels and function
2022 arc_assemble_integer (rtx x
, unsigned int size
, int aligned_p
)
2024 if (size
== UNITS_PER_WORD
&& aligned_p
2025 && ((GET_CODE (x
) == SYMBOL_REF
&& ARC_FUNCTION_NAME_PREFIX_P(* (XSTR (x
, 0))))
2026 || GET_CODE (x
) == LABEL_REF
))
2028 fputs ("\t.word\t", asm_out_file
);
2029 /* %st is to be generated only for A4 */
2031 fputs("%st(", asm_out_file
);
2032 output_addr_const (asm_out_file
, x
);
2034 fputs (")", asm_out_file
);
2035 fputs("\n", asm_out_file
);
2038 return default_assemble_integer (x
, size
, aligned_p
);
2041 int arc_return_address_regs
[4]
2042 = {0, RETURN_ADDR_REGNUM
, ILINK1_REGNUM
, ILINK2_REGNUM
};
2044 /* Set up the stack and frame pointer (if desired) for the function. */
2046 arc_expand_prologue (void)
2048 int size
= get_frame_size ();
2049 unsigned int gmask
= cfun
->machine
->frame_info
.gmask
;
2050 /* unsigned int frame_pointer_offset;*/
2051 unsigned int frame_size_to_allocate
;
2052 /* (FIXME: The first store will use a PRE_MODIFY; this will usually be r13.
2053 Change the stack layout so that we rather store a high register with the
2054 PRE_MODIFY, thus enabling more short insn generation.) */
2055 int first_offset
= 0;
2057 size
= ARC_STACK_ALIGN (size
);
2059 /* Compute/get total frame size */
2060 size
= (!cfun
->machine
->frame_info
.initialized
2061 ? arc_compute_frame_size (size
)
2062 : cfun
->machine
->frame_info
.total_size
);
2064 /* Keep track of frame size to be allocated */
2065 frame_size_to_allocate
= size
;
2067 /* These cases shouldn't happen. Catch them now. */
2068 gcc_assert (!(size
== 0 && gmask
));
2070 /* Allocate space for register arguments if this is a variadic function. */
2071 if (cfun
->machine
->frame_info
.pretend_size
!= 0)
2073 /* Ensure pretend_size is maximum of 8 * word_size */
2074 gcc_assert (cfun
->machine
->frame_info
.pretend_size
<= 32);
2076 frame_stack_add (-(HOST_WIDE_INT
)cfun
->machine
->frame_info
.pretend_size
);
2077 frame_size_to_allocate
-= cfun
->machine
->frame_info
.pretend_size
;
2080 /* The home-grown ABI says link register is saved first. */
2081 if (MUST_SAVE_RETURN_ADDR
)
2086 /* Save return address register in the space allocated by caller for
2087 backtrace data structure */
2088 fprintf (file
, "\tst %s,[%s,%d]\n",
2089 reg_names
[RETURN_ADDR_REGNUM
], sp_str
, UNITS_PER_WORD
);
2092 dwarf2out_reg_save ("", RETURN_ADDR_REGNUM
, -cfa_offset
+ UNITS_PER_WORD
);
2097 else /* TARGET_ARCOMPACT */
2099 rtx ra
= gen_rtx_REG (SImode
, RETURN_ADDR_REGNUM
);
2101 = gen_frame_mem (Pmode
, gen_rtx_PRE_DEC (Pmode
, stack_pointer_rtx
));
2103 frame_move_inc (mem
, ra
, stack_pointer_rtx
, 0);
2104 frame_size_to_allocate
-= UNITS_PER_WORD
;
2107 } /* MUST_SAVE_RETURN_ADDR */
2109 /* Save any needed call-saved regs (and call-used if this is an
2110 interrupt handler) for ARCompact ISA. */
2111 if (TARGET_ARCOMPACT
&& cfun
->machine
->frame_info
.reg_size
)
2113 first_offset
= -cfun
->machine
->frame_info
.reg_size
;
2114 /* N.B. FRAME_POINTER_MASK and RETURN_ADDR_MASK are cleared in gmask. */
2115 arc_save_restore (stack_pointer_rtx
, 0, gmask
, 0, &first_offset
);
2116 frame_size_to_allocate
-= cfun
->machine
->frame_info
.reg_size
;
2120 /* Save frame pointer if needed */
2121 if (frame_pointer_needed
)
2126 fprintf (file
, "\tst %s,[%s]\n", fp_str
, sp_str
);
2129 dwarf2out_reg_save ("", FRAME_POINTER_REGNUM
, -cfa_offset
);
2133 else /* TARGET_ARCOMPACT */
2135 rtx addr
= gen_rtx_PLUS (Pmode
, stack_pointer_rtx
,
2136 GEN_INT (-UNITS_PER_WORD
+ first_offset
));
2138 = gen_frame_mem (Pmode
,
2139 gen_rtx_PRE_MODIFY (Pmode
, stack_pointer_rtx
,
2141 frame_move_inc (mem
, frame_pointer_rtx
, stack_pointer_rtx
, 0);
2142 frame_size_to_allocate
-= UNITS_PER_WORD
;
2145 frame_move (frame_pointer_rtx
, stack_pointer_rtx
);
2148 /* ??? We don't handle the case where the saved regs are more than 252
2149 bytes away from sp. This can be handled by decrementing sp once, saving
2150 the regs, and then decrementing it again. The epilogue doesn't have this
2151 problem as the `ld' insn takes reg+limm values (though it would be more
2152 efficient to avoid reg+limm). */
2154 frame_size_to_allocate
-= first_offset
;
2155 /* Allocate the stack frame. */
2156 if (frame_size_to_allocate
> 0)
2157 frame_stack_add ((HOST_WIDE_INT
) 0 - frame_size_to_allocate
);
2159 /* For ARCtangent-A4, save any needed call-saved regs (and call-used
2160 if this is an interrupt handler).
2161 This is already taken care for ARCompact architectures */
2165 arc_save_restore (stack_pointer_rtx
, cfun
->machine
->frame_info
.reg_offset
,
2166 /* The zeroing of these two bits is unnecessary,
2167 but leave this in for clarity. */
2168 gmask
& ~(FRAME_POINTER_MASK
| RETURN_ADDR_MASK
), 0, 0);
2171 /* Setup the gp register, if needed */
2172 if (crtl
->uses_pic_offset_table
)
2173 arc_finalize_pic ();
2176 /* Do any necessary cleanup after a function to restore stack, frame,
2180 arc_expand_epilogue (int sibcall_p
)
2182 int size
= get_frame_size ();
2183 enum arc_function_type fn_type
= arc_compute_function_type (cfun
);
2185 size
= ARC_STACK_ALIGN (size
);
2186 size
= (!cfun
->machine
->frame_info
.initialized
2187 ? arc_compute_frame_size (size
)
2188 : cfun
->machine
->frame_info
.total_size
);
2192 unsigned int pretend_size
= cfun
->machine
->frame_info
.pretend_size
;
2193 unsigned int frame_size
;
2194 unsigned int size_to_deallocate
;
2195 int restored
, fp_restored_p
;
2196 int can_trust_sp_p
= !cfun
->calls_alloca
;
2197 int first_offset
= 0;
2198 int millicode_p
= cfun
->machine
->frame_info
.millicode_end_reg
> 0;
2200 size_to_deallocate
= size
;
2203 frame_size
= size
- pretend_size
;
2205 frame_size
= size
- (pretend_size
+
2206 cfun
->machine
->frame_info
.reg_size
+
2207 cfun
->machine
->frame_info
.extra_size
);
2209 /* ??? There are lots of optimizations that can be done here.
2210 EG: Use fp to restore regs if it's closer.
2211 Maybe in time we'll do them all. For now, always restore regs from
2212 sp, but don't restore sp if we don't have to. */
2214 if (!can_trust_sp_p
)
2215 gcc_assert (frame_pointer_needed
);
2217 /* Restore stack pointer to the beginning of saved register area for
2219 if (TARGET_ARCOMPACT
&& frame_size
)
2221 if (frame_pointer_needed
)
2222 frame_move (stack_pointer_rtx
, frame_pointer_rtx
);
2224 first_offset
= frame_size
;
2225 size_to_deallocate
-= frame_size
;
2227 else if (!can_trust_sp_p
)
2228 frame_stack_add (-frame_size
);
2231 /* Restore any saved registers. */
2234 gcc_assert (0); /* Bitrot. */
2236 if (cfun
->machine
->frame_info
.reg_size
)
2237 arc_save_restore (stack_pointer_rtx
,
2238 cfun
->machine
->frame_info
.reg_offset
,
2239 /* The zeroing of these two bits is unnecessary,
2240 but leave this in for clarity. */
2241 cfun
->machine
->frame_info
.gmask
2242 & ~(FRAME_POINTER_MASK
| RETURN_ADDR_MASK
), 1, 0);
2243 if (MUST_SAVE_RETURN_ADDR
)
2244 fprintf (file
, "\tld %s,[%s,%d]\n", reg_names
[RETURN_ADDR_REGNUM
],
2245 (frame_pointer_needed
? fp_str
: sp_str
),
2246 UNITS_PER_WORD
+ (frame_pointer_needed
? 0 : frame_size
));
2249 else /* TARGET_ARCOMPACT */
2252 if (frame_pointer_needed
)
2254 rtx addr
= gen_rtx_POST_INC (Pmode
, stack_pointer_rtx
);
2256 frame_move_inc (frame_pointer_rtx
, gen_frame_mem (Pmode
, addr
),
2257 stack_pointer_rtx
, 0);
2258 size_to_deallocate
-= UNITS_PER_WORD
;
2261 /* Load blink after the calls to thunk calls in case of
2266 int sibthunk_p
= (!sibcall_p
2267 && fn_type
== ARC_FUNCTION_NORMAL
2268 && !cfun
->machine
->frame_info
.pretend_size
);
2270 gcc_assert (!(cfun
->machine
->frame_info
.gmask
2271 & (FRAME_POINTER_MASK
| RETURN_ADDR_MASK
)));
2272 arc_save_restore (stack_pointer_rtx
, 0,
2273 cfun
->machine
->frame_info
.gmask
,
2274 1 + sibthunk_p
, &first_offset
);
2278 /* If we are to restore registers, and first_offset would require
2279 a limm to be encoded in a PRE_MODIFY, yet we can add it with a
2280 fast add to the stack pointer, do this now. */
2281 if ((!SMALL_INT (first_offset
)
2282 && cfun
->machine
->frame_info
.gmask
2283 && ((TARGET_ARC700
&& !optimize_size
)
2284 ? first_offset
<= 0x800
2285 : satisfies_constraint_C2a (GEN_INT (first_offset
))))
2286 /* Also do this if we have both gprs and return
2287 address to restore, and they both would need a LIMM. */
2288 || (MUST_SAVE_RETURN_ADDR
2290 ((cfun
->machine
->frame_info
.reg_size
+ first_offset
)
2292 && cfun
->machine
->frame_info
.gmask
))
2294 frame_stack_add (first_offset
);
2297 if (MUST_SAVE_RETURN_ADDR
)
2299 rtx ra
= gen_rtx_REG (Pmode
, RETURN_ADDR_REGNUM
);
2300 int ra_offs
= cfun
->machine
->frame_info
.reg_size
+ first_offset
;
2301 rtx addr
= plus_constant (stack_pointer_rtx
, ra_offs
);
2303 /* If the load of blink would need a LIMM, but we can add
2304 the offset quickly to sp, do the latter. */
2305 if (!SMALL_INT (ra_offs
>> 2)
2306 && !cfun
->machine
->frame_info
.gmask
2307 && ((TARGET_ARC700
&& !optimize_size
)
2309 : satisfies_constraint_C2a (GEN_INT (ra_offs
))))
2311 size_to_deallocate
-= ra_offs
- first_offset
;
2313 frame_stack_add (ra_offs
);
2315 addr
= stack_pointer_rtx
;
2317 /* See if we can combine the load of the return address with the
2318 final stack adjustment.
2319 We need a separate load if there are still registers to
2320 restore. We also want a separate load if the combined insn
2321 would need a limm, but a separate load doesn't. */
2323 && !cfun
->machine
->frame_info
.gmask
2324 && (SMALL_INT (ra_offs
) || !SMALL_INT (ra_offs
>> 2)))
2326 addr
= gen_rtx_PRE_MODIFY (Pmode
, stack_pointer_rtx
, addr
);
2328 size_to_deallocate
-= cfun
->machine
->frame_info
.reg_size
;
2330 else if (!ra_offs
&& size_to_deallocate
== UNITS_PER_WORD
)
2332 addr
= gen_rtx_POST_INC (Pmode
, addr
);
2333 size_to_deallocate
= 0;
2335 frame_move_inc (ra
, gen_frame_mem (Pmode
, addr
),
2336 stack_pointer_rtx
, addr
);
2341 if (cfun
->machine
->frame_info
.reg_size
)
2342 arc_save_restore (stack_pointer_rtx
, 0,
2343 /* The zeroing of these two bits is unnecessary,
2344 but leave this in for clarity. */
2345 cfun
->machine
->frame_info
.gmask
2346 & ~(FRAME_POINTER_MASK
| RETURN_ADDR_MASK
), 1, &first_offset
);
2351 /* The rest of this function does the following:
2352 ARCtangent-A4: handle epilogue_delay, restore fp, sp, return
2353 ARCompact : handle epilogue_delay, restore sp (phase-2), return
2356 /* Keep track of how much of the stack pointer we've restored.
2357 It makes the following a lot more readable. */
2365 size_to_deallocate
+= first_offset
;
2366 restored
= size
- size_to_deallocate
;
2373 if (frame_pointer_needed
)
2375 gcc_assert (0); /* Bitrot. */
2377 /* Try to restore the frame pointer in the delay slot. We can't,
2378 however, if any of these is true. */
2379 if (epilogue_delay
!= NULL_RTX
2380 || !SMALL_INT (frame_size
)
2382 || ARC_INTERRUPT_P (fn_type
))
2384 fprintf (file
, "\tld.a %s,[%s,%d]\n",
2385 fp_str
, sp_str
, frame_size
);
2386 restored
+= frame_size
;
2390 if (cfun
->calls_alloca
|| frame_pointer_needed
)
2391 dwarf2out_def_cfa("",FRAME_POINTER_REGNUM
,cfa_offset
);
2394 cfa_offset
-=frame_size
;
2395 dwarf2out_def_cfa("",STACK_POINTER_REGNUM
,cfa_offset
);
2401 else if (!SMALL_INT (size
/* frame_size + pretend_size */)
2402 || ARC_INTERRUPT_P (fn_type
))
2404 frame_stack_add (frame_size
);
2405 restored
+= frame_size
;
2409 if (size
> restored
)
2410 frame_stack_add (size
- restored
);
2411 /* Emit the return instruction. */
2412 if (sibcall_p
== FALSE
)
2413 emit_jump_insn (gen_return_i ());
2417 /* Set up the stack and frame pointer (if desired) for the function. */
2419 /* Define the number of delay slots needed for the function epilogue.
2421 Interrupt handlers can't have any epilogue delay slots (it's always needed
2422 for something else, I think). For normal functions, we have to worry about
2423 using call-saved regs as they'll be restored before the delay slot insn.
2424 Functions with non-empty frames already have enough choices for the epilogue
2425 delay slot so for now we only consider functions with empty frames. */
2428 arc_delay_slots_for_epilogue (void)
2430 if (arc_compute_function_type (cfun
) != ARC_FUNCTION_NORMAL
)
2432 if (!cfun
->machine
->frame_info
.initialized
)
2433 (void) arc_compute_frame_size (get_frame_size ());
2434 if (cfun
->machine
->frame_info
.total_size
== 0)
2439 /* Return true if TRIAL is a valid insn for the epilogue delay slot.
2440 Any single length instruction which doesn't reference the stack or frame
2441 pointer or any call-saved register is OK. SLOT will always be 0. */
2444 arc_eligible_for_epilogue_delay (rtx trial
,int slot
)
2446 int trial_length
= get_attr_length (trial
);
2448 gcc_assert (slot
== 0);
2450 if ( ( (trial_length
== 4) || (trial_length
== 2) )
2451 /* If registers where saved, presumably there's more than enough
2452 possibilities for the delay slot. The alternative is something
2453 more complicated (of course, if we expanded the epilogue as rtl
2454 this problem would go away). */
2455 /* ??? Note that this will always be true since only functions with
2456 empty frames have epilogue delay slots. See
2457 arc_delay_slots_for_epilogue. */
2458 && cfun
->machine
->frame_info
.gmask
== 0
2459 && ! reg_mentioned_p (stack_pointer_rtx
, PATTERN (trial
))
2460 && ! reg_mentioned_p (frame_pointer_rtx
, PATTERN (trial
)))
2468 /* Emit special PIC prologues and epilogues. */
2469 /* If the function has any GOTOFF relocations, then the GOTBASE
2470 * register has to be setup in the prologue
2471 * The instruction needed at the function start for setting up the
2472 * GOTBASE register is
2474 * ----------------------------------------------------------
2475 * The rtl to be emitted for this should be:
2476 * set ( reg basereg)
2478 * ( const (unspec (symref _DYNAMIC) 3)))
2479 * ----------------------------------------------------------
2481 /* Can be used when rtl pro/epilog comes in.
2484 arc_finalize_pic (void)
2487 rtx baseptr_rtx
= gen_rtx_REG (Pmode
, PIC_OFFSET_TABLE_REGNUM
);
2489 if (crtl
->uses_pic_offset_table
== 0)
2492 gcc_assert (flag_pic
!= 0);
2494 new = gen_rtx_SYMBOL_REF (Pmode
, "_DYNAMIC");
2495 new = gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, new), ARC_UNSPEC_GOT
);
2496 new = gen_rtx_CONST (Pmode
, new);
2498 new = gen_rtx_SET (VOIDmode
, baseptr_rtx
, new);
2500 return emit_insn (new);
2503 /* Output the assembler code for doing a shift.
2504 We go to a bit of trouble to generate efficient code as the ARC only has
2505 single bit shifts. This is taken from the h8300 port. We only have one
2506 mode of shifting and can't access individual bytes like the h8300 can, so
2507 this is greatly simplified (at the expense of not generating hyper-
2510 This function is not used if the variable shift insns are present. */
2512 /* ??? We assume the output operand is the same as operand 1.
2513 This can be optimized (deleted) in the case of 1 bit shifts. */
2514 /* ??? We use the loop register here. We don't use it elsewhere (yet) and
2515 using it here will give us a chance to play with it. */
2518 output_shift (rtx
*operands
)
2520 /* static int loopend_lab;*/
2521 rtx shift
= operands
[3];
2522 enum machine_mode mode
= GET_MODE (shift
);
2523 enum rtx_code code
= GET_CODE (shift
);
2524 const char *shift_one
;
2526 gcc_assert (mode
== SImode
);
2530 case ASHIFT
: shift_one
= "asl %0,%0"; break;
2531 case ASHIFTRT
: shift_one
= "asr %0,%0"; break;
2532 case LSHIFTRT
: shift_one
= "lsr %0,%0"; break;
2533 default: gcc_unreachable ();
2536 if (GET_CODE (operands
[2]) != CONST_INT
)
2538 output_asm_insn ("and.f %2, %2, 0x1f", operands
);
2539 output_asm_insn ("mov lp_count,%2", operands
);
2540 output_asm_insn ("bz 2f", operands
);
2546 int n
= INTVAL (operands
[2]);
2548 /* Only consider the lower 5 bits of the shift count */
2551 /* If the count is negative, take only lower 5 bits. */
2552 /* FIXME: No longer needed */
2556 /* If the count is too big, truncate it.
2557 ANSI says shifts of GET_MODE_BITSIZE are undefined - we choose to
2558 do the intuitive thing. */
2559 else if (n
> GET_MODE_BITSIZE (mode
))
2560 n
= GET_MODE_BITSIZE (mode
);
2562 /* First see if we can do them inline. */
2566 output_asm_insn (shift_one
, operands
);
2568 /* See if we can use a rotate/and. */
2569 else if (n
== BITS_PER_WORD
- 1)
2574 output_asm_insn ("and %0,%0,1\n\tror %0,%0", operands
);
2577 /* The ARC doesn't have a rol insn. Use something else. */
2578 output_asm_insn ("asl.f 0,%0\n\tsbc %0,0,0", operands
);
2581 /* The ARC doesn't have a rol insn. Use something else. */
2582 output_asm_insn ("asl.f 0,%0\n\tadc %0,0,0", operands
);
2593 sprintf (buf
, "mov lp_count,%ld", INTVAL (operands
[2]) & 0x1f );
2594 output_asm_insn (buf
, operands
);
2599 sprintf (buf
, "lr %%4,[status]\n\tadd %%4,%%4,6\t%s single insn loop start",
2602 sprintf (buf
, "mov %%4,%%%%st(1f)\t%s (single insn loop start) >> 2",
2604 output_asm_insn (buf
, operands
);
2605 output_asm_insn ("sr %4,[lp_start]", operands
);
2606 output_asm_insn ("add %4,%4,1", operands
);
2607 output_asm_insn ("sr %4,[lp_end]", operands
);
2608 output_asm_insn ("nop\n\tnop", operands
);
2610 asm_fprintf (asm_out_file
, "\t%s single insn loop\n",
2613 asm_fprintf (asm_out_file
, "1:\t%s single insn loop\n",
2615 output_asm_insn (shift_one
, operands
);
2616 fprintf (asm_out_file
, "2:\t%s end single insn loop\n",
2625 /* Nested function support. */
2627 /* Directly store VALUE at BASE plus OFFSET. */
2629 emit_store_direct (rtx base
, int offset
, int value
)
2631 emit_insn (gen_store_direct (gen_rtx_MEM (SImode
,
2632 plus_constant (base
, offset
)),
2634 gen_int_mode (value
, SImode
))));
2637 /* Emit RTL insns to initialize the variable parts of a trampoline.
2638 FNADDR is an RTX for the address of the function's pure code.
2639 CXT is an RTX for the static chain value for the function. */
2640 /* With potentially multiple shared objects loaded, and multiple stacks
2641 present for multiple thereds where trampolines might reside, a simple
2642 range check will likely not suffice for the profiler to tell if a callee
2643 is a trampoline. We a speedier check by making the trampoline start at
2644 an address that is not 4-byte aligned.
2645 A trampoline looks like this:
2649 ld_s r12,[pcl,12] 0xd403
2650 ld r11,[pcl,12] 0x170c 700b
2654 The fastest trampoline to execute for trampolines within +-8KB of CTX
2657 j [limm] 0x20200f80 limm
2658 and that would also be faster to write to the stack by computing the offset
2659 from CTX to TRAMP at compile time. However, it would really be better to
2660 get rid of the high cost of cache invalidation when generating trampolines,
2661 which requires that the code part of trampolines stays constant, and
2663 - making sure that no executable code but trampolines is on the stack,
2664 no icache entries linger for the area of the stack from when before the
2665 stack was allocated, and allocating trampolines in trampoline-only
2668 - allocate trampolines fram a special pool of pre-allocated trampolines. */
2672 arc_initialize_trampoline (rtx tramp ATTRIBUTE_UNUSED
,
2673 rtx fnaddr ATTRIBUTE_UNUSED
,
2674 rtx cxt ATTRIBUTE_UNUSED
)
2676 emit_store_direct (tramp
, 0, TARGET_BIG_ENDIAN
? 0x78e0d403 : 0xd40378e0);
2677 emit_store_direct (tramp
, 4, TARGET_BIG_ENDIAN
? 0x170c700b : 0x700b170c);
2678 emit_store_direct (tramp
, 8, TARGET_BIG_ENDIAN
? 0x7c0078e0 : 0x78e07c00);
2679 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (tramp
, 12)), fnaddr
);
2680 emit_move_insn (gen_rtx_MEM (SImode
, plus_constant (tramp
, 16)), cxt
);
2681 emit_insn (gen_flush_icache (validize_mem (gen_rtx_MEM (SImode
, tramp
))));
2684 /* Set the cpu type and print out other fancy things,
2685 at the top of the file. */
2688 arc_asm_file_start (FILE *file
)
2690 fprintf (file
, "\t.cpu %s\n", arc_cpu_string
);
2693 /* This is set briefly to 1 when we output a ".as" address modifer, and then
2694 reset when we output the scaled address. */
2695 static int output_scaled
= 0;
2697 /* Print operand X (an rtx) in assembler syntax to file FILE.
2698 CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
2699 For `%' followed by punctuation, CODE is the punctuation and X is null. */
2700 /* In final.c:output_asm_insn:
2703 'c' : constant address if CONSTANT_ADDRESS_P
2709 '#': condbranch delay slot suffix
2710 '*': jump delay slot suffix
2711 '?' : nonjump-insn suffix for conditional execution or short instruction
2712 '!' : jump / call suffix for conditional execution or short instruction
2713 '`': fold constant inside unary o-perator, re-recognize, and emit.
2718 'B': Branch comparison operand - suppress sda reference
2719 'H': Most significant word
2720 'L': Least significant word
2721 'A': ASCII decimal representation of floating point value
2722 'U': Load/store update or scaling indicator
2723 'V': cache bypass indicator for volatile
2728 'o': original symbol - no @ prepending. */
2731 arc_print_operand (FILE *file
,rtx x
,int code
)
2736 if (GET_CODE (x
) == CONST_INT
)
2737 fprintf (file
, "%d",exact_log2(INTVAL (x
) + 1) - 1 );
2739 output_operand_lossage ("invalid operand to %%Z code");
2744 if (GET_CODE (x
) == CONST_INT
)
2745 fprintf (file
, "%d",exact_log2(INTVAL (x
)) );
2747 output_operand_lossage ("invalid operand to %%z code");
2752 if (GET_CODE (x
) == CONST_INT
)
2753 fprintf (file
, "%d",exact_log2(~INTVAL (x
)) );
2755 output_operand_lossage ("invalid operand to %%M code");
2760 /* Conditional branches depending on condition codes.
2761 Note that this is only for branches that were known to depend on
2762 condition codes before delay slot scheduling;
2763 out-of-range brcc / bbit expansions should use '*'.
2764 This distinction is important because of the different
2765 allowable delay slot insns and the output of the delay suffix
2766 for TARGET_AT_DBR_COND_EXEC. */
2768 /* Unconditional branches / branches not depending on condition codes.
2769 Output the appropriate delay slot suffix. */
2770 if (final_sequence
&& XVECLEN (final_sequence
, 0) != 1)
2772 rtx jump
= XVECEXP (final_sequence
, 0, 0);
2773 rtx delay
= XVECEXP (final_sequence
, 0, 1);
2775 /* For TARGET_PAD_RETURN we might have grabbed the delay insn. */
2776 if (INSN_DELETED_P (delay
))
2778 if (INSN_ANNULLED_BRANCH_P (jump
))
2779 fputs (INSN_FROM_TARGET_P (delay
)
2780 ? ((arc_cpu
== PROCESSOR_A4
) ? ".jd" : ".d")
2781 : (TARGET_AT_DBR_CONDEXEC
&& code
== '#' ? ".d" : ".nd"),
2787 case '?' : /* with leading "." */
2788 case '!' : /* without leading "." */
2789 /* This insn can be conditionally executed. See if the ccfsm machinery
2790 says it should be conditionalized.
2791 If it shouldn't, we'll check the compact attribute if this insn
2792 has a short variant, which may be used depending on code size and
2793 alignment considerations. */
2794 if (ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current
))
2796 /* Is this insn in a delay slot sequence? */
2797 if (!final_sequence
|| XVECLEN (final_sequence
, 0) < 2)
2799 /* This insn isn't in a delay slot sequence. */
2800 fprintf (file
, "%s%s",
2801 code
== '?' ? "." : "",
2802 arc_condition_codes
[arc_ccfsm_current
.cc
]);
2803 /* If this is a jump, there are still short variants. However,
2804 only beq_s / bne_s have the same offset range as b_s,
2805 and the only short conditional returns are jeq_s and jne_s. */
2807 && (arc_ccfsm_current
.cc
== ARC_CC_EQ
2808 || arc_ccfsm_current
.cc
== ARC_CC_NE
2809 || 0 /* FIXME: check if branch in 7 bit range. */))
2810 output_short_suffix (file
);
2812 else if (code
== '!') /* Jump with delay slot. */
2813 fputs (arc_condition_codes
[arc_ccfsm_current
.cc
], file
);
2814 else /* An Instruction in a delay slot. */
2816 rtx jump
= XVECEXP (final_sequence
, 0, 0);
2817 rtx insn
= XVECEXP (final_sequence
, 0, 1);
2819 /* If the insn is annulled and is from the target path, we need
2820 to inverse the condition test. */
2821 if (INSN_ANNULLED_BRANCH_P (jump
))
2823 if (INSN_FROM_TARGET_P (insn
))
2824 fprintf (file
, "%s%s",
2825 code
== '?' ? "." : "",
2826 arc_condition_codes
[ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current
.cc
)]);
2828 fprintf (file
, "%s%s",
2829 code
== '?' ? "." : "",
2830 arc_condition_codes
[arc_ccfsm_current
.cc
]);
2831 if (arc_ccfsm_current
.state
== 5)
2832 arc_ccfsm_current
.state
= 0;
2835 /* This insn is executed for either path, so don't
2836 conditionalize it at all. */
2837 output_short_suffix (file
);
2842 output_short_suffix (file
);
2845 /* FIXME: fold constant inside unary operator, re-recognize, and emit. */
2848 fputs (arc_condition_codes
[get_arc_condition_code (x
)], file
);
2851 fputs (arc_condition_codes
[ARC_INVERSE_CONDITION_CODE
2852 (get_arc_condition_code (x
))],
2856 /* Write second word of DImode or DFmode reference,
2857 register or memory. */
2858 if (GET_CODE (x
) == REG
)
2859 fputs (reg_names
[REGNO (x
)+1], file
);
2860 else if (GET_CODE (x
) == MEM
)
2864 /* Handle possible auto-increment. For PRE_INC / PRE_DEC /
2865 PRE_MODIFY, we will have handled the first word already;
2866 For POST_INC / POST_DEC / POST_MODIFY, the access to the
2867 first word will be done later. In either case, the access
2868 to the first word will do the modify, and we only have
2869 to add an offset of four here. */
2870 if (GET_CODE (XEXP (x
, 0)) == PRE_INC
2871 || GET_CODE (XEXP (x
, 0)) == PRE_DEC
2872 || GET_CODE (XEXP (x
, 0)) == PRE_MODIFY
2873 || GET_CODE (XEXP (x
, 0)) == POST_INC
2874 || GET_CODE (XEXP (x
, 0)) == POST_DEC
2875 || GET_CODE (XEXP (x
, 0)) == POST_MODIFY
)
2876 output_address (plus_constant (XEXP (XEXP (x
, 0), 0), 4));
2877 else if (output_scaled
)
2879 rtx addr
= XEXP (x
, 0);
2880 int size
= GET_MODE_SIZE (GET_MODE (x
));
2882 output_address (plus_constant (XEXP (addr
, 0),
2883 ((INTVAL (XEXP (addr
, 1)) + 4)
2884 >> (size
== 2 ? 1 : 2))));
2888 output_address (plus_constant (XEXP (x
, 0), 4));
2892 output_operand_lossage ("invalid operand to %%R code");
2895 if (GET_CODE (x
) == CONST
2896 && GET_CODE( XEXP( XEXP (x
,0),0)) == SYMBOL_REF
2897 && GET_CODE (XEXP( XEXP (x
,0),1)) == CONST_INT
2898 && GET_CODE (XEXP (x
,0)) == PLUS
)
2900 if (TARGET_A4
&& ARC_FUNCTION_NAME_PREFIX_P (* (XSTR (XEXP( XEXP (x
,0),0), 0))))
2902 error ("Function address arithmetic is not supported.\n");
2907 else if (symbolic_reference_mentioned_p(x
))
2909 if(TARGET_A4
&& ARC_FUNCTION_NAME_PREFIX_P (* (XSTR (x
, 0))))
2911 fprintf (file
, "%%st(");
2912 output_addr_const (file
, x
);
2913 fprintf (file
, ")");
2916 else if (TARGET_A4
&& GET_CODE (x
) == LABEL_REF
)
2918 fprintf (file
, "%%st(");
2919 output_addr_const (file
, x
);
2920 fprintf (file
, ")");
2925 else if (GET_CODE (x
) == LABEL_REF
)
2929 fprintf (file
, "%%st(");
2930 output_addr_const (file
, x
);
2931 fprintf (file
, ")");
2936 case 'B' /* Branch or other LIMM ref - must not use sda references. */ :
2939 output_addr_const (file
, x
);
2945 if (GET_CODE (x
) == REG
)
2947 /* L = least significant word, H = most significant word */
2948 if ((WORDS_BIG_ENDIAN
!= 0) ^ (code
== 'L'))
2949 fputs (reg_names
[REGNO (x
)], file
);
2951 fputs (reg_names
[REGNO (x
)+1], file
);
2953 else if (GET_CODE (x
) == CONST_INT
2954 || GET_CODE (x
) == CONST_DOUBLE
)
2958 split_double (x
, &first
, &second
);
2960 if((WORDS_BIG_ENDIAN
) == 0)
2961 fprintf (file
, "0x%08lx",
2962 code
== 'L' ? INTVAL (first
) : INTVAL (second
));
2964 fprintf (file
, "0x%08lx",
2965 code
== 'L' ? INTVAL (second
) : INTVAL (first
));
2970 output_operand_lossage ("invalid operand to %%H/%%L code");
2976 gcc_assert (GET_CODE (x
) == CONST_DOUBLE
2977 && GET_MODE_CLASS (GET_MODE (x
)) == MODE_FLOAT
);
2979 real_to_decimal (str
, CONST_DOUBLE_REAL_VALUE (x
), sizeof (str
), 0, 1);
2980 fprintf (file
, "%s", str
);
2984 /* Output a load/store with update indicator if appropriate. */
2985 if (GET_CODE (x
) == MEM
)
2987 rtx addr
= XEXP (x
, 0);
2988 switch (GET_CODE (addr
))
2990 case PRE_INC
: case PRE_DEC
: case PRE_MODIFY
:
2991 fputs (".a", file
); break;
2992 case POST_INC
: case POST_DEC
: case POST_MODIFY
:
2993 fputs (".ab", file
); break;
2995 /* Can we use a scaled offset? */
2996 if (CONST_INT_P (XEXP (addr
, 1))
2997 && GET_MODE_SIZE (GET_MODE (x
)) > 1
2998 && (!(INTVAL (XEXP (addr
, 1))
2999 & (GET_MODE_SIZE (GET_MODE (x
)) - 1) & 3))
3000 /* Does it make a difference? */
3001 && !SMALL_INT_RANGE(INTVAL (XEXP (addr
, 1)),
3002 GET_MODE_SIZE (GET_MODE (x
)) - 2, 0))
3004 fputs (".as", file
);
3007 /* Are we using a scaled index? */
3008 else if (GET_CODE (XEXP (addr
, 0)) == MULT
)
3009 fputs (".as", file
);
3014 gcc_assert (CONSTANT_P (addr
)); break;
3018 output_operand_lossage ("invalid operand to %%U code");
3021 /* Output cache bypass indicator for a load/store insn. Volatile memory
3022 refs are defined to use the cache bypass mechanism. */
3023 if (GET_CODE (x
) == MEM
)
3025 if (MEM_VOLATILE_P (x
) && !TARGET_VOLATILE_CACHE_SET
)
3026 fputs (".di", file
);
3029 output_operand_lossage ("invalid operand to %%V code");
3034 /* Do nothing special. */
3037 fputs (reg_names
[REGNO (x
)]+1, file
);
3040 /* This punctuation character is needed because label references are
3041 printed in the output template using %l. This is a front end
3042 character, and when we want to emit a '@' before it, we have to use
3048 /* Output an operator. */
3049 switch (GET_CODE (x
))
3051 case PLUS
: fputs ("add", file
); return;
3052 case SS_PLUS
: fputs ("adds", file
); return;
3053 case AND
: fputs ("and", file
); return;
3054 case IOR
: fputs ("or", file
); return;
3055 case XOR
: fputs ("xor", file
); return;
3056 case MINUS
: fputs ("sub", file
); return;
3057 case SS_MINUS
: fputs ("subs", file
); return;
3058 case ASHIFT
: fputs ("asl", file
); return;
3059 case ASHIFTRT
: fputs ("asr", file
); return;
3060 case LSHIFTRT
: fputs ("lsr", file
); return;
3061 case ROTATERT
: fputs ("ror", file
); return;
3062 case MULT
: fputs ("mpy", file
); return;
3063 case ABS
: fputs ("abs", file
); return; /* unconditional */
3064 case NEG
: fputs ("neg", file
); return;
3065 case SS_NEG
: fputs ("negs", file
); return;
3066 case NOT
: fputs ("not", file
); return; /* unconditional */
3068 fputs ("ext", file
); /* bmsk allows predication. */
3070 case SIGN_EXTEND
: /* unconditional */
3071 fputs ("sex", file
);
3073 switch (GET_MODE (XEXP (x
, 0)))
3075 case QImode
: fputs ("b", file
); return;
3076 case HImode
: fputs ("w", file
); return;
3081 if (GET_MODE (x
) != HImode
)
3083 fputs ("sat16", file
);
3086 output_operand_lossage ("invalid operand to %%O code"); return;
3088 if (GET_CODE (x
) == SYMBOL_REF
)
3090 assemble_name (file
, XSTR (x
, 0));
3095 if (TARGET_ANNOTATE_ALIGN
&& cfun
->machine
->size_reason
)
3096 fprintf (file
, "; %s. unalign: %d", cfun
->machine
->size_reason
,
3097 cfun
->machine
->unalign
);
3101 output_operand_lossage ("invalid operand output code");
3104 switch (GET_CODE (x
))
3107 fputs (reg_names
[REGNO (x
)], file
);
3111 rtx addr
= XEXP (x
, 0);
3112 int size
= GET_MODE_SIZE (GET_MODE (x
));
3116 switch (GET_CODE (addr
))
3118 case PRE_INC
: case POST_INC
:
3119 output_address (plus_constant (XEXP (addr
, 0), size
)); break;
3120 case PRE_DEC
: case POST_DEC
:
3121 output_address (plus_constant (XEXP (addr
, 0), -size
)); break;
3122 case PRE_MODIFY
: case POST_MODIFY
:
3123 output_address (XEXP (addr
, 1)); break;
3127 output_address (plus_constant (XEXP (addr
, 0),
3128 (INTVAL (XEXP (addr
, 1))
3129 >> (size
== 2 ? 1 : 2))));
3133 output_address (addr
);
3136 if (flag_pic
&& CONSTANT_ADDRESS_P (addr
))
3137 arc_output_pic_addr_const (file
, addr
, code
);
3139 output_address (addr
);
3146 /* We handle SFmode constants here as output_addr_const doesn't. */
3147 if (GET_MODE (x
) == SFmode
)
3152 REAL_VALUE_FROM_CONST_DOUBLE (d
, x
);
3153 REAL_VALUE_TO_TARGET_SINGLE (d
, l
);
3154 fprintf (file
, "0x%08lx", l
);
3157 /* Fall through. Let output_addr_const deal with it. */
3160 arc_output_pic_addr_const (file
, x
, code
);
3163 /* FIXME: Dirty way to handle @var@sda+const. Shd be handled
3164 with asm_output_symbol_ref */
3165 if (GET_CODE (x
) == CONST
&& GET_CODE (XEXP (x
, 0)) == PLUS
)
3168 output_addr_const (file
, XEXP (x
, 0));
3169 if (GET_CODE (XEXP (x
, 0)) == SYMBOL_REF
&& SYMBOL_REF_SMALL_P (XEXP (x
, 0)))
3170 fprintf (file
, "@sda");
3172 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
3173 || INTVAL (XEXP (x
, 1)) >= 0)
3174 fprintf (file
, "+");
3175 output_addr_const (file
, XEXP (x
, 1));
3178 output_addr_const (file
, x
);
3180 if (GET_CODE (x
) == SYMBOL_REF
&& SYMBOL_REF_SMALL_P (x
))
3181 fprintf (file
, "@sda");
3186 /* Print a memory address as an operand to reference that memory location. */
3189 arc_print_operand_address (FILE *file
, rtx addr
)
3191 register rtx base
, index
= 0;
3193 switch (GET_CODE (addr
))
3196 fputs (reg_names
[REGNO (addr
)], file
);
3199 if (TARGET_A4
&& ARC_FUNCTION_NAME_PREFIX_P (* (XSTR (addr
, 0))))
3201 fprintf (file
, "%%st(");
3202 output_addr_const (file
, addr
);
3203 fprintf (file
, ")");
3207 output_addr_const (file
, addr
);
3208 if (SYMBOL_REF_SMALL_P (addr
))
3209 fprintf (file
, "@sda");
3213 if (GET_CODE (XEXP (addr
, 0)) == MULT
)
3214 index
= XEXP (XEXP (addr
, 0), 0), base
= XEXP (addr
, 1);
3215 else if (CONST_INT_P (XEXP (addr
, 0)))
3216 index
= XEXP (addr
, 0), base
= XEXP (addr
, 1);
3218 base
= XEXP (addr
, 0), index
= XEXP (addr
, 1);
3220 gcc_assert (OBJECT_P (base
));
3221 arc_print_operand_address (file
, base
);
3222 if (CONSTANT_P (base
) && CONST_INT_P (index
))
3226 gcc_assert (OBJECT_P (index
));
3227 arc_print_operand_address (file
, index
);
3231 rtx c
= XEXP (addr
, 0);
3233 gcc_assert (GET_CODE (XEXP (c
, 0)) == SYMBOL_REF
);
3234 gcc_assert (GET_CODE (XEXP (c
, 1)) == CONST_INT
);
3236 output_address(XEXP(addr
,0));
3242 /* We shouldn't get here as we've lost the mode of the memory object
3243 (which says how much to inc/dec by. */
3248 arc_output_pic_addr_const (file
, addr
, 0);
3250 output_addr_const (file
, addr
);
3255 /* Called via note_stores. */
3257 write_profile_sections (rtx dest ATTRIBUTE_UNUSED
, rtx x
, void *data
)
3260 htab_t htab
= (htab_t
) data
;
3263 if (GET_CODE (x
) != SET
)
3265 srcp
= &SET_SRC (x
);
3267 srcp
= &XEXP (*srcp
, 0);
3268 else if (MEM_P (SET_DEST (x
)))
3269 srcp
= &XEXP (SET_DEST (x
), 0);
3271 if (GET_CODE (src
) != CONST
)
3273 src
= XEXP (src
, 0);
3274 if (GET_CODE (src
) != UNSPEC
|| XINT (src
, 1) != UNSPEC_PROF
)
3277 gcc_assert (XVECLEN (src
, 0) == 3);
3278 if (!htab_elements (htab
))
3280 output_asm_insn (".section .__arc_profile_desc, \"a\"\n"
3282 &XVECEXP (src
, 0, 0));
3284 slot
= (rtx
*) htab_find_slot (htab
, src
, INSERT
);
3285 if (*slot
== HTAB_EMPTY_ENTRY
)
3287 static int count_nr
;
3292 sprintf (buf
, "__prof_count%d", count_nr
++);
3293 count
= gen_rtx_SYMBOL_REF (Pmode
, xstrdup (buf
));
3294 XVECEXP (src
, 0, 2) = count
;
3295 output_asm_insn (".section\t.__arc_profile_desc, \"a\"\n"
3297 "\t.section\t.__arc_profile_counters, \"aw\"\n"
3298 "\t.type\t%o2, @object\n"
3301 &XVECEXP (src
, 0, 0));
3305 *srcp
= XVECEXP (*slot
, 0, 2);
3309 unspec_prof_hash (const void *x
)
3311 const_rtx u
= (const_rtx
) x
;
3312 const_rtx s1
= XVECEXP (u
, 0, 1);
3314 return (htab_hash_string (XSTR (XVECEXP (u
, 0, 0), 0))
3315 ^ (s1
->code
== SYMBOL_REF
? htab_hash_string (XSTR (s1
, 0)) : 0));
3319 unspec_prof_htab_eq (const void *x
, const void *y
)
3321 const_rtx u0
= (const_rtx
) x
;
3322 const_rtx u1
= (const_rtx
) y
;
3323 const_rtx s01
= XVECEXP (u0
, 0, 1);
3324 const_rtx s11
= XVECEXP (u1
, 0, 1);
3326 return (!strcmp (XSTR (XVECEXP (u0
, 0, 0), 0),
3327 XSTR (XVECEXP (u1
, 0, 0), 0))
3328 && rtx_equal_p (s01
, s11
));
3331 /* Conditional execution support.
3333 This is based on the ARM port but for now is much simpler.
3335 A finite state machine takes care of noticing whether or not instructions
3336 can be conditionally executed, and thus decrease execution time and code
3337 size by deleting branch instructions. The fsm is controlled by
3338 arc_ccfsm_advance (called by arc_final_prescan_insn), and controls the
3339 actions of PRINT_OPERAND. The patterns in the .md file for the branch
3340 insns also have a hand in this. */
3342 /* The state of the fsm controlling condition codes are:
3343 0: normal, do nothing special
3344 1: don't output this insn
3345 2: don't output this insn
3346 3: make insns conditional
3347 4: make insns conditional
3348 5: make insn conditional (only for outputting anulled delay slot insns)
3350 special value for cfun->machine->uid_ccfsm_state:
3351 6: return with but one insn before it since function start / call
3353 State transitions (state->state by whom, under what condition):
3354 0 -> 1 arc_ccfsm_advance, if insn is a conditional branch skipping over
3356 0 -> 2 arc_ccfsm_advance, if insn is a conditional branch followed
3357 by zero or more non-jump insns and an unconditional branch with
3358 the same target label as the condbranch.
3359 1 -> 3 branch patterns, after having not output the conditional branch
3360 2 -> 4 branch patterns, after having not output the conditional branch
3361 0 -> 5 branch patterns, for anulled delay slot insn.
3362 3 -> 0 ASM_OUTPUT_INTERNAL_LABEL, if the `target' label is reached
3363 (the target label has CODE_LABEL_NUMBER equal to
3364 arc_ccfsm_target_label).
3365 4 -> 0 arc_ccfsm_advance, if `target' unconditional branch is reached
3366 3 -> 1 arc_ccfsm_advance, finding an 'else' jump skipping over some insns.
3367 5 -> 0 when outputting the delay slot insn
3369 If the jump clobbers the conditions then we use states 2 and 4.
3371 A similar thing can be done with conditional return insns.
3373 We also handle separating branches from sets of the condition code.
3374 This is done here because knowledge of the ccfsm state is required,
3375 we may not be outputting the branch. */
3377 /* arc_final_prescan_insn calls arc_ccfsm_advance to adjust arc_ccfsm_current.
3378 before letting final output INSN. */
3380 arc_ccfsm_advance (rtx insn
, struct arc_ccfsm
*state
)
3382 /* BODY will hold the body of INSN. */
3385 /* This will be 1 if trying to repeat the trick (ie: do the `else' part of
3386 an if/then/else), and things need to be reversed. */
3389 /* If we start with a return insn, we only succeed if we find another one. */
3390 int seeking_return
= 0;
3392 /* START_INSN will hold the insn from where we start looking. This is the
3393 first insn after the following code_label if REVERSE is true. */
3394 rtx start_insn
= insn
;
3396 /* Type of the jump_insn. Brcc insns don't affect ccfsm changes,
3397 since they don't rely on a cmp preceding them */
3398 enum attr_type jump_insn_type
;
3400 /* Allow -mdebug-ccfsm to turn this off so we can see how well it does.
3401 We can't do this in macro FINAL_PRESCAN_INSN because its called from
3402 final_scan_insn which has `optimize' as a local. */
3403 if (optimize
< 2 || TARGET_NO_COND_EXEC
)
3406 /* Ignore notes and labels. */
3409 body
= PATTERN (insn
);
3410 /* If in state 4, check if the target branch is reached, in order to
3411 change back to state 0. */
3412 if (state
->state
== 4)
3414 if (insn
== state
->target_insn
)
3416 state
->target_insn
= NULL
;
3422 /* If in state 3, it is possible to repeat the trick, if this insn is an
3423 unconditional branch to a label, and immediately following this branch
3424 is the previous target label which is only used once, and the label this
3425 branch jumps to is not too far off. Or in other words "we've done the
3426 `then' part, see if we can do the `else' part." */
3427 if (state
->state
== 3)
3429 if (simplejump_p (insn
))
3431 start_insn
= next_nonnote_insn (start_insn
);
3432 if (GET_CODE (start_insn
) == BARRIER
)
3434 /* ??? Isn't this always a barrier? */
3435 start_insn
= next_nonnote_insn (start_insn
);
3437 if (GET_CODE (start_insn
) == CODE_LABEL
3438 && CODE_LABEL_NUMBER (start_insn
) == state
->target_label
3439 && LABEL_NUSES (start_insn
) == 1)
3444 else if (GET_CODE (body
) == RETURN
)
3446 start_insn
= next_nonnote_insn (start_insn
);
3447 if (GET_CODE (start_insn
) == BARRIER
)
3448 start_insn
= next_nonnote_insn (start_insn
);
3449 if (GET_CODE (start_insn
) == CODE_LABEL
3450 && CODE_LABEL_NUMBER (start_insn
) == state
->target_label
3451 && LABEL_NUSES (start_insn
) == 1)
3463 if (GET_CODE (insn
) != JUMP_INSN
3464 || GET_CODE (PATTERN (insn
)) == ADDR_VEC
3465 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
3468 jump_insn_type
= get_attr_type (insn
);
3469 if (jump_insn_type
== TYPE_BRCC
3470 || jump_insn_type
== TYPE_BRCC_NO_DELAY_SLOT
3471 || jump_insn_type
== TYPE_LOOP_END
)
3474 /* This jump might be paralleled with a clobber of the condition codes,
3475 the jump should always come first. */
3476 if (GET_CODE (body
) == PARALLEL
&& XVECLEN (body
, 0) > 0)
3477 body
= XVECEXP (body
, 0, 0);
3480 || (GET_CODE (body
) == SET
&& GET_CODE (SET_DEST (body
)) == PC
3481 && GET_CODE (SET_SRC (body
)) == IF_THEN_ELSE
))
3483 int insns_skipped
= 0, fail
= FALSE
, succeed
= FALSE
;
3484 /* Flag which part of the IF_THEN_ELSE is the LABEL_REF. */
3485 int then_not_else
= TRUE
;
3486 /* Nonzero if next insn must be the target label. */
3487 int next_must_be_target_label_p
;
3488 rtx this_insn
= start_insn
, label
= 0;
3490 /* Register the insn jumped to. */
3493 if (!seeking_return
)
3494 label
= XEXP (SET_SRC (body
), 0);
3496 else if (GET_CODE (XEXP (SET_SRC (body
), 1)) == LABEL_REF
)
3497 label
= XEXP (XEXP (SET_SRC (body
), 1), 0);
3498 else if (GET_CODE (XEXP (SET_SRC (body
), 2)) == LABEL_REF
)
3500 label
= XEXP (XEXP (SET_SRC (body
), 2), 0);
3501 then_not_else
= FALSE
;
3503 else if (GET_CODE (XEXP (SET_SRC (body
), 1)) == RETURN
)
3505 else if (GET_CODE (XEXP (SET_SRC (body
), 2)) == RETURN
)
3508 then_not_else
= FALSE
;
3513 /* See how many insns this branch skips, and what kind of insns. If all
3514 insns are okay, and the label or unconditional branch to the same
3515 label is not too far away, succeed. */
3516 for (insns_skipped
= 0, next_must_be_target_label_p
= FALSE
;
3517 !fail
&& !succeed
&& insns_skipped
< MAX_INSNS_SKIPPED
;
3522 this_insn
= next_nonnote_insn (this_insn
);
3526 if (next_must_be_target_label_p
)
3528 if (GET_CODE (this_insn
) == BARRIER
)
3530 if (GET_CODE (this_insn
) == CODE_LABEL
3531 && this_insn
== label
)
3541 scanbody
= PATTERN (this_insn
);
3543 switch (GET_CODE (this_insn
))
3546 /* Succeed if it is the target label, otherwise fail since
3547 control falls in from somewhere else. */
3548 if (this_insn
== label
)
3558 /* Succeed if the following insn is the target label.
3560 If return insns are used then the last insn in a function
3561 will be a barrier. */
3562 next_must_be_target_label_p
= TRUE
;
3566 /* Can handle a call insn if there are no insns after it.
3567 IE: The next "insn" is the target label. We don't have to
3568 worry about delay slots as such insns are SEQUENCE's inside
3569 INSN's. ??? It is possible to handle such insns though. */
3570 if (get_attr_cond (this_insn
) == COND_CANUSE
)
3571 next_must_be_target_label_p
= TRUE
;
3577 /* If this is an unconditional branch to the same label, succeed.
3578 If it is to another label, do nothing. If it is conditional,
3580 /* ??? Probably, the test for the SET and the PC are unnecessary. */
3582 if (GET_CODE (scanbody
) == SET
3583 && GET_CODE (SET_DEST (scanbody
)) == PC
)
3585 if (GET_CODE (SET_SRC (scanbody
)) == LABEL_REF
3586 && XEXP (SET_SRC (scanbody
), 0) == label
&& !reverse
)
3591 else if (GET_CODE (SET_SRC (scanbody
)) == IF_THEN_ELSE
)
3593 else if (get_attr_cond (this_insn
) != COND_CANUSE
)
3596 else if (GET_CODE (scanbody
) == RETURN
3602 else if (GET_CODE (scanbody
) == PARALLEL
)
3604 if (get_attr_cond (this_insn
) != COND_CANUSE
)
3610 /* We can only do this with insns that can use the condition
3611 codes (and don't set them). */
3612 if (GET_CODE (scanbody
) == SET
3613 || GET_CODE (scanbody
) == PARALLEL
)
3615 if (get_attr_cond (this_insn
) != COND_CANUSE
)
3618 /* We can't handle other insns like sequences. */
3630 if ((!seeking_return
) && (state
->state
== 1 || reverse
))
3631 state
->target_label
= CODE_LABEL_NUMBER (label
);
3632 else if (seeking_return
|| state
->state
== 2)
3634 while (this_insn
&& GET_CODE (PATTERN (this_insn
)) == USE
)
3636 this_insn
= next_nonnote_insn (this_insn
);
3638 gcc_assert (!this_insn
||
3639 (GET_CODE (this_insn
) != BARRIER
3640 && GET_CODE (this_insn
) != CODE_LABEL
));
3644 /* Oh dear! we ran off the end, give up. */
3645 extract_insn_cached (insn
);
3647 state
->target_insn
= NULL
;
3650 state
->target_insn
= this_insn
;
3655 /* If REVERSE is true, ARM_CURRENT_CC needs to be inverted from
3658 state
->cc
= get_arc_condition_code (XEXP (SET_SRC (body
), 0));
3660 if (reverse
|| then_not_else
)
3661 state
->cc
= ARC_INVERSE_CONDITION_CODE (state
->cc
);
3664 /* Restore recog_operand. Getting the attributes of other insns can
3665 destroy this array, but final.c assumes that it remains intact
3666 across this call; since the insn has been recognized already we
3667 call insn_extract direct. */
3668 extract_insn_cached (insn
);
3672 /* Record that we are currently outputting label NUM with prefix PREFIX.
3673 It it's the label we're looking for, reset the ccfsm machinery.
3675 Called from ASM_OUTPUT_INTERNAL_LABEL. */
3678 arc_ccfsm_at_label (const char *prefix
, int num
, struct arc_ccfsm
*state
)
3680 if (state
->state
== 3 && state
->target_label
== num
3681 && !strcmp (prefix
, "L"))
3684 state
->target_insn
= NULL_RTX
;
3688 /* We are considering a conditional branch with the condition COND.
3689 Check if we want to conditionalize a delay slot insn, and if so modify
3690 the ccfsm state accordingly.
3691 REVERSE says branch will branch when the condition is false. */
3693 arc_ccfsm_record_condition (rtx cond
, int reverse
, rtx jump
,
3694 struct arc_ccfsm
*state
)
3696 rtx seq_insn
= NEXT_INSN (PREV_INSN (jump
));
3698 state
= &arc_ccfsm_current
;
3700 gcc_assert (state
->state
== 0);
3701 if (seq_insn
!= jump
)
3703 rtx insn
= XVECEXP (PATTERN (seq_insn
), 0, 1);
3705 if (INSN_ANNULLED_BRANCH_P (jump
)
3706 && (TARGET_AT_DBR_CONDEXEC
|| INSN_FROM_TARGET_P (insn
)))
3708 state
->cc
= get_arc_condition_code (cond
);
3710 arc_ccfsm_current
.cc
3711 = ARC_INVERSE_CONDITION_CODE (state
->cc
);
3712 arc_ccfsm_current
.state
= 5;
3717 /* Update *STATE as we would when we emit INSN. */
3719 arc_ccfsm_post_advance (rtx insn
, struct arc_ccfsm
*state
)
3722 arc_ccfsm_at_label ("L", CODE_LABEL_NUMBER (insn
), state
);
3723 else if (JUMP_P (insn
)
3724 && GET_CODE (PATTERN (insn
)) != ADDR_VEC
3725 && GET_CODE (PATTERN (insn
)) != ADDR_DIFF_VEC
3726 && get_attr_type (insn
) == TYPE_BRANCH
)
3728 if (ARC_CCFSM_BRANCH_DELETED_P (state
))
3729 ARC_CCFSM_RECORD_BRANCH_DELETED (state
);
3732 rtx src
= SET_SRC (PATTERN (insn
));
3733 arc_ccfsm_record_condition (XEXP (src
, 0), XEXP (src
, 1) == pc_rtx
,
3737 else if (arc_ccfsm_current
.state
== 5)
3738 arc_ccfsm_current
.state
= 0;
3741 /* See if the current insn, which is a conditional branch, is to be
3744 arc_ccfsm_branch_deleted_p (void)
3746 return ARC_CCFSM_BRANCH_DELETED_P (&arc_ccfsm_current
);
3749 /* Record a branch isn't output because subsequent insns can be
3753 arc_ccfsm_record_branch_deleted (void)
3755 ARC_CCFSM_RECORD_BRANCH_DELETED (&arc_ccfsm_current
);
3759 arc_ccfsm_cond_exec_p (void)
3761 return (cfun
->machine
->prescan_initialized
3762 && ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current
));
3766 arc_ccfsm_advance_to (rtx insn
)
3768 struct machine_function
*machine
= cfun
->machine
;
3769 rtx scan
= machine
->ccfsm_current_insn
;
3771 struct arc_ccfsm
*statep
= &arc_ccfsm_current
;
3773 /* Rtl changes too much before arc_reorg to keep ccfsm state.
3774 But we are not required to calculate exact lengths then. */
3775 if (!machine
->arc_reorg_started
)
3777 while (scan
!= insn
)
3781 arc_ccfsm_post_advance (scan
, statep
);
3782 scan
= next_insn (scan
);
3786 gcc_assert (!restarted
);
3787 scan
= get_insns ();
3788 memset (statep
, 0, sizeof *statep
);
3792 arc_ccfsm_advance (scan
, statep
);
3794 machine
->ccfsm_current_insn
= scan
;
3797 /* Like next_active_insn, but return NULL if we find an ADDR_(DIFF_)VEC,
3798 and look inside SEQUENCEs. */
3800 arc_next_active_insn (rtx insn
, struct arc_ccfsm
*statep
)
3807 arc_ccfsm_post_advance (insn
, statep
);
3808 insn
= NEXT_INSN (insn
);
3809 if (!insn
|| BARRIER_P (insn
))
3812 arc_ccfsm_advance (insn
, statep
);
3814 while (NOTE_P (insn
)
3815 || (cfun
->machine
->arc_reorg_started
3816 && LABEL_P (insn
) && !label_to_alignment (insn
))
3817 || (NONJUMP_INSN_P (insn
)
3818 && (GET_CODE (PATTERN (insn
)) == USE
3819 || GET_CODE (PATTERN (insn
)) == CLOBBER
)));
3820 if (!LABEL_P (insn
))
3822 gcc_assert (INSN_P (insn
));
3823 pat
= PATTERN (insn
);
3824 if (GET_CODE (pat
) == ADDR_VEC
|| GET_CODE (pat
) == ADDR_DIFF_VEC
)
3826 if (GET_CODE (pat
) == SEQUENCE
)
3827 return XVECEXP (pat
, 0, 0);
3832 /* When deciding if an insn should be output short, we want to know something
3833 about the following insns:
3834 - if another insn follows which we know we can output as a short insn
3835 before an alignemnt-sensitive point, we can output this insn short:
3836 the decision about the eventual alignment can be postponed.
3837 - if a to-be-aligned label comes next, we should output this insn such
3838 as to get / preserve 4-byte alignment.
3839 - if a likely branch without delay slot insn, or a call with an immediately
3840 following short insn comes next, we should out output this insn such as to
3841 get / preserve 2 mod 4 unalignment.
3842 - do the same for a not completely unlikely branch with a short insn
3843 following before any other branch / label.
3844 - in order to decide if we are actually looking at a branch, we need to
3845 call arc_ccfsm_advance.
3846 - in order to decide if we are looking at a short insn, we should know
3847 if it is conditionalized. To a first order of approximation this is
3848 the case if the state from arc_ccfsm_advance from before this insn
3849 indicates the insn is conditionalized. However, a further refinement
3850 could be to not conditionalize an insn if the destination register(s)
3851 is/are dead in the non-executed case. */
3853 arc_verify_short (rtx insn
, int unalign
, int check_attr
)
3855 rtx scan
, next
, later
, prev
;
3856 struct arc_ccfsm
*statep
, old_state
, save_state
;
3857 int odd
= 3; /* 0/2: (mis)alignment specified; 3: keep short. */
3858 enum attr_iscompact iscompact
;
3859 struct machine_function
*machine
;
3860 const char **rp
= &cfun
->machine
->size_reason
;
3862 rtx this_sequence
= NULL_RTX
;
3863 rtx recog_insn
= recog_data
.insn
;
3867 iscompact
= get_attr_iscompact (insn
);
3868 if (iscompact
== ISCOMPACT_FALSE
)
3871 machine
= cfun
->machine
;
3873 if (machine
->force_short_suffix
>= 0)
3874 return machine
->force_short_suffix
;
3876 /* Now we know that the insn may be output with a "_s" suffix. But even
3877 when optimizing for size, we still want to look ahead, because if we
3878 find a mandatory alignment, we might find that keeping the insn long
3879 doesn't increase size, but gains speed. */
3881 /* The iscompact attribute depends on arc_ccfsm_current, thus, in order to
3882 read the attributes relevant to our forward scan, we must modify
3883 arc_ccfsm_current while scanning. */
3884 if (check_attr
== 0)
3885 arc_ccfsm_advance_to (insn
);
3886 statep
= &arc_ccfsm_current
;
3887 old_state
= *statep
;
3888 jump_p
= (TARGET_ALIGN_CALL
3889 ? (JUMP_P (insn
) || CALL_ATTR (insn
, CALL
))
3890 : (JUMP_P (insn
) && get_attr_type (insn
) != TYPE_RETURN
));
3892 /* Check if this is an out-of-range brcc / bbit which is expanded with
3893 a short cmp / btst. */
3894 if (JUMP_P (insn
) && GET_CODE (PATTERN (insn
)) == PARALLEL
)
3896 enum attr_type type
= get_attr_type (insn
);
3897 int len
= get_attr_lock_length (insn
);
3899 /* Since both the length and lock_length attribute use insn_lengths,
3900 which has ADJUST_INSN_LENGTH applied, we can't rely on equality
3901 with 6 / 10 here. */
3902 if ((type
== TYPE_BRCC
&& len
> 4)
3903 || (type
== TYPE_BRCC_NO_DELAY_SLOT
&& len
> 8))
3905 rtx
operator = XEXP (SET_SRC (XVECEXP (PATTERN (insn
), 0, 0)), 0);
3906 rtx op0
= XEXP (operator, 0);
3908 if (GET_CODE (op0
) == ZERO_EXTRACT
)
3909 op0
= XEXP (op0
, 0);
3910 if (satisfies_constraint_Rcq (op0
))
3912 /* Check if the branch should be unaligned. */
3913 if (arc_unalign_branch_p (insn
))
3916 *rp
= "Long unaligned jump avoids non-delay slot penalty";
3919 /* If we have a short delay slot insn, make this insn 'short'
3920 (actually, short compare & long jump) and defer alignment
3921 decision to processing of the delay insn. Without this test
3922 here, we'd reason that a short jump with a short delay insn
3923 should be lengthened to avoid a stall if it's aligned - that
3924 is not just suboptimal, but can leads to infinitel loops as
3925 the delay insn is assumed to be long the next time, since we
3926 don't have independent delay slot size information. */
3927 else if ((get_attr_delay_slot_filled (insn
)
3928 == DELAY_SLOT_FILLED_YES
)
3929 && (get_attr_iscompact (NEXT_INSN (insn
))
3930 != ISCOMPACT_FALSE
))
3932 *rp
= "Small is beautiful";
3939 /* If INSN is at the an unaligned return address of a preceding call,
3941 if (TARGET_ALIGN_CALL
3943 && (prev
= prev_active_insn (insn
)) != NULL_RTX
3944 && arc_next_active_insn (prev
, 0) == insn
3945 && ((NONJUMP_INSN_P (prev
) && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
3946 ? CALL_ATTR (XVECEXP (PATTERN (prev
), 0, 0), NON_SIBCALL
)
3947 : (CALL_ATTR (prev
, NON_SIBCALL
)
3948 && NEXT_INSN (PREV_INSN (prev
)) == prev
)))
3950 *rp
= "Call return to unaligned long insn would stall";
3954 prev
= PREV_INSN (insn
);
3955 next
= NEXT_INSN (insn
);
3957 /* Basic block reordering calculates insn lengths while it has the insns
3958 at the end of a basic block detached from the remainder of the insn
3960 gcc_assert (next
|| !cfun
->machine
->arc_reorg_started
);
3961 if (NEXT_INSN (prev
) != insn
)
3962 this_sequence
= PATTERN (NEXT_INSN (prev
));
3963 else if (next
&& PREV_INSN (next
) != insn
)
3964 this_sequence
= PATTERN (PREV_INSN (next
));
3967 gcc_assert (GET_CODE (this_sequence
) == SEQUENCE
);
3968 gcc_assert (XVECLEN (this_sequence
, 0) == 2);
3969 gcc_assert (insn
== XVECEXP (this_sequence
, 0, 0)
3970 || insn
== XVECEXP (this_sequence
, 0, 1));
3973 /* If this is a jump without a delay slot, keep it long if we have
3974 unalignment. Don't do this for non sibling calls returning to a long
3975 insn, because what we'd gain when calling, we'd loose when returning. */
3976 if (jump_p
&& unalign
3977 && arc_unalign_branch_p (insn
)
3978 && (!CALL_ATTR (insn
, NON_SIBCALL
)
3979 || (((next
= arc_next_active_insn (insn
, statep
))
3981 && CCFSM_ISCOMPACT (next
, statep
)
3982 && arc_verify_short (next
, 2, 1))
3983 ? (*statep
= old_state
, 1)
3984 : (*statep
= old_state
, 0))))
3986 *rp
= "Long unaligned jump avoids non-delay slot penalty";
3988 extract_insn_cached (recog_insn
);
3992 /* ARC700 stalls if an aligned short branch has a short delay insn. */
3993 if (TARGET_UPSIZE_DBR
&& this_sequence
&& !unalign
&& jump_p
3994 && !INSN_DELETED_P (next
= XVECEXP (this_sequence
, 0, 1))
3995 && CCFSM_DBR_ISCOMPACT (next
, insn
, statep
))
3997 *rp
= "Aligned short jumps with short delay insn stall when taken";
3999 extract_insn_cached (recog_insn
);
4003 /* If this is a call with a long delay insn, or the delay slot insn to
4004 a call, we want to choose INSN's length so that the return address
4005 will be aligned, unless the following insn is short. */
4006 if (TARGET_ALIGN_CALL
&& this_sequence
4007 && CALL_ATTR (XVECEXP (this_sequence
, 0, 0), NON_SIBCALL
)
4008 && ((next
= XVECEXP (this_sequence
, 0, 1)) == insn
4009 || !CCFSM_ISCOMPACT (next
, statep
)))
4011 /* If we curently have unalignment, getting alignment by using a
4012 short insn now is the smart choice, and we don't want to prejudice
4013 the short/long decision for the following insn. */
4014 *rp
= "Function return stalls if the return address is unaligned";
4017 scan
= XVECEXP (this_sequence
, 0, 1);
4018 arc_ccfsm_advance (scan
, statep
);
4019 scan
= arc_next_active_insn (scan
, statep
);
4027 if (!CCFSM_ISCOMPACT (scan
, statep
) || !arc_verify_short (scan
, 2, 1))
4030 *rp
= "Small is beautiful";
4033 /* Likewise, if this is a call without a delay slot, except we want to
4034 unalign this call. */
4035 if (jump_p
&& !this_sequence
&& CALL_ATTR (insn
, NON_SIBCALL
))
4037 *rp
= "Function return stalls if the return address is unaligned";
4038 if (!TARGET_UNALIGN_BRANCH
&& unalign
)
4040 scan
= arc_next_active_insn (insn
, statep
);
4043 /* Apparently a non-return call. */
4045 ? "Long unaligned jump avoids non-delay slot penalty"
4046 : "Small is beautiful");
4052 *rp
= "Avoid nop insertion before label";
4056 if (!CCFSM_ISCOMPACT (scan
, statep
) || !arc_verify_short (scan
, 2, 1))
4062 ? "Long unaligned jump avoids non-delay slot penalty"
4063 : "Small is beautiful");
4068 scan
= arc_next_active_insn (insn
, statep
);
4070 /* If this and the previous insn are the only ones between function start
4071 or an outgoing function call, and a return insn, avoid having them
4073 N.B. we check that the next insn is a return, and this implies that
4074 INSN can't be a CALL / SFUNC or in the delay slot of one, because
4075 there has to be a restore of blink before the return. */
4076 if (TARGET_PAD_RETURN
4077 && scan
&& JUMP_P (scan
) && get_attr_type (scan
) == TYPE_RETURN
4078 && (prev
= prev_active_insn (insn
))
4079 && arc_next_active_insn (prev
, 0) == insn
4080 && (INSN_ADDRESSES (INSN_UID (insn
)) - INSN_ADDRESSES (INSN_UID (prev
))
4082 && ((prev
= prev_active_insn (prev
)) == NULL_RTX
4083 || CALL_ATTR (GET_CODE (PATTERN (prev
)) == SEQUENCE
4084 ? XVECEXP (PATTERN (prev
), 0, 0) : prev
, CALL
)))
4086 *rp
= "call/return and return/return must be 6 bytes apart to avoid mispredict";
4087 *statep
= old_state
;
4089 extract_insn_cached (recog_insn
);
4093 *rp
= "Small is beautiful";
4096 if (JUMP_P (scan
) && GET_CODE (PATTERN (scan
)) == PARALLEL
4097 && arc_unalign_branch_p (scan
))
4099 /* If this is an out-of-range brcc / bbit which is expanded with
4100 a compact cmp / btst, emit the curent insn short. */
4102 enum attr_type type
= get_attr_type (scan
);
4103 int len
= get_attr_lock_length (scan
);
4105 /* Since both the length and lock_length attribute use insn_lengths,
4106 which has ADJUST_INSN_LENGTH applied, we can't rely on equality
4107 with 6 / 10 here. */
4108 if ((type
== TYPE_BRCC
&& len
> 4)
4109 || (type
== TYPE_BRCC_NO_DELAY_SLOT
&& len
> 8))
4111 rtx
operator = XEXP (SET_SRC (XVECEXP (PATTERN (scan
), 0, 0)), 0);
4112 rtx op0
= XEXP (operator, 0);
4114 if (GET_CODE (op0
) == ZERO_EXTRACT
)
4115 op0
= XEXP (op0
, 0);
4116 if (satisfies_constraint_Rcq (op0
))
4121 if ((JUMP_P (scan
) || CALL_P (scan
))
4122 && arc_unalign_branch_p (scan
)
4123 && (TARGET_ALIGN_CALL
4124 ? (JUMP_P (scan
) || CALL_ATTR (scan
, SIBCALL
))
4125 : (JUMP_P (scan
) && get_attr_type (scan
) != TYPE_RETURN
))
4126 && !ARC_CCFSM_BRANCH_DELETED_P (statep
))
4128 /* Assume for now that the branch is sufficiently likely to
4129 warrant unaligning. */
4130 *rp
= "Long unaligned jump avoids non-delay slot penalty";
4134 /* A call without a delay slot insn with a short insn following
4135 should be unaligned. */
4136 if (TARGET_UNALIGN_BRANCH
&& TARGET_ALIGN_CALL
4137 && CALL_ATTR (scan
, CALL
)
4138 && NEXT_INSN (PREV_INSN (scan
)) == scan
/* No delay insn. */
4139 && (((save_state
= *statep
,
4140 next
= arc_next_active_insn (scan
, statep
)) == NULL_RTX
4141 || (!LABEL_P (next
) && CCFSM_ISCOMPACT (next
, statep
)))
4142 ? 1 : (*statep
= save_state
, 0)))
4144 *rp
= "Long unaligned jump avoids non-delay slot penalty";
4148 /* A long call with a long delay slot insn should be aligned,
4149 unless a short insn follows. */
4150 if (TARGET_ALIGN_CALL
4151 && CALL_ATTR (scan
, CALL
)
4152 && NEXT_INSN (PREV_INSN (scan
)) != scan
4153 && !CCFSM_ISCOMPACT (scan
, statep
)
4154 && !CCFSM_ISCOMPACT ((next
= NEXT_INSN (scan
)) , statep
)
4155 && (((save_state
= *statep
,
4156 later
= arc_next_active_insn (next
, statep
))
4158 || !CCFSM_ISCOMPACT (later
, statep
)
4159 || !arc_verify_short (later
, 2, 1)))
4160 ? 1 : (*statep
= save_state
, 0)))
4162 *rp
= "Function return stalls if the return address is unaligned";
4166 if (LABEL_P (scan
) && label_to_alignment (scan
) > 1)
4168 *rp
= "Avoid nop insertion before label";
4173 && GET_CODE (PATTERN (scan
)) != USE
4174 && GET_CODE (PATTERN (scan
)) != CLOBBER
4175 && CCFSM_ISCOMPACT (scan
, statep
))
4177 /* Go ahead making INSN short, we decide about SCAN later. */
4180 if (GET_CODE (scan
) == BARRIER
)
4182 arc_ccfsm_post_advance (scan
, statep
);
4183 scan
= NEXT_INSN (scan
);
4186 if (GET_CODE (scan
) == INSN
&& GET_CODE (PATTERN (scan
)) == SEQUENCE
)
4187 scan
= XVECEXP (PATTERN (scan
), 0, 0);
4189 && (GET_CODE (PATTERN (scan
)) == ADDR_VEC
4190 || GET_CODE (PATTERN (scan
)) == ADDR_DIFF_VEC
))
4194 arc_ccfsm_advance (scan
, statep
);
4197 *statep
= old_state
;
4199 extract_insn_cached (recog_insn
);
4206 output_short_suffix (FILE *file
)
4208 rtx insn
= current_output_insn
;
4210 if (arc_verify_short (insn
, cfun
->machine
->unalign
, 1))
4212 fprintf (file
, "_s");
4213 cfun
->machine
->unalign
^= 2;
4215 /* Restore recog_operand. */
4216 extract_insn_cached (insn
);
4220 arc_final_prescan_insn (rtx insn
,rtx
*opvec ATTRIBUTE_UNUSED
,
4221 int noperands ATTRIBUTE_UNUSED
)
4223 if (TARGET_DUMPISIZE
)
4224 fprintf (asm_out_file
, "\n; at %04x\n", INSN_ADDRESSES (INSN_UID (insn
)));
4226 /* Output a nop if necessary to prevent a hazard.
4227 Don't do this for delay slots: inserting a nop would
4228 alter semantics, and the only time we would find a hazard is for a
4229 call function result - and in that case, the hazard is spurious to
4231 if (PREV_INSN (insn
)
4232 && PREV_INSN (NEXT_INSN (insn
)) == insn
4233 && arc_hazard (prev_real_insn (insn
), insn
))
4235 current_output_insn
=
4236 emit_insn_before (gen_nop (), NEXT_INSN (PREV_INSN (insn
)));
4237 final_scan_insn (current_output_insn
, asm_out_file
, optimize
, 1, NULL
);
4238 current_output_insn
= insn
;
4240 /* Restore extraction data which might have been clobbered by arc_hazard. */
4241 extract_constrain_insn_cached (insn
);
4243 if (!cfun
->machine
->prescan_initialized
)
4245 /* Clear lingering state from branch shortening. */
4246 memset (&arc_ccfsm_current
, 0, sizeof arc_ccfsm_current
);
4247 cfun
->machine
->prescan_initialized
= 1;
4249 arc_ccfsm_advance (insn
, &arc_ccfsm_current
);
4251 cfun
->machine
->size_reason
= 0;
4254 /* Define the offset between two registers, one to be eliminated, and
4255 the other its replacement, at the start of a routine. */
4258 arc_initial_elimination_offset (int from
,int to
)
4260 if (! cfun
->machine
->frame_info
.initialized
)
4261 arc_compute_frame_size (get_frame_size ());
4263 if (from
== ARG_POINTER_REGNUM
&& to
== FRAME_POINTER_REGNUM
)
4268 return (cfun
->machine
->frame_info
.extra_size
4269 + cfun
->machine
->frame_info
.reg_size
);
4272 if (from
== ARG_POINTER_REGNUM
&& to
== STACK_POINTER_REGNUM
)
4274 return (cfun
->machine
->frame_info
.total_size
4275 - cfun
->machine
->frame_info
.pretend_size
);
4278 if ((from
== FRAME_POINTER_REGNUM
) && (to
== STACK_POINTER_REGNUM
))
4281 return (cfun
->machine
->frame_info
.total_size
4282 - cfun
->machine
->frame_info
.pretend_size
);
4284 return (cfun
->machine
->frame_info
.total_size
4285 - (cfun
->machine
->frame_info
.pretend_size
4286 + cfun
->machine
->frame_info
.extra_size
4287 + cfun
->machine
->frame_info
.reg_size
));
4294 /* Generate a bbit{0,1} insn for the current pattern
4295 * bbit instructions are used as an optimized alternative to
4296 * a sequence of bic,cmp and branch instructions
4297 * Similar to gen_bbit_insns(), with conditions reversed
4300 gen_bbit_bic_insns(rtx
* operands
)
4303 switch (INTVAL(operands
[3]))
4305 /* bic r%0,imm%1,r%2
4306 * cmp r%0,0<- the value we have switched on
4310 * bbit{0,1} r%1,log2(imm%2),label%5
4313 if ( GET_CODE (operands
[4]) == EQ
) {
4314 return "bbit1%# %1,%z2,%^%l5";
4316 else if ( GET_CODE (operands
[4]) == NE
)
4317 return "bbit0%# %1,%z2,%^%l5";
4321 /* bic r%0,imm%1,r%2
4322 * cmp r%0,0<- the value we have switched on
4326 * bbit{0,1} r%1,log2(imm%2),label%5
4327 * the bne case does not make sense here as it gives too little
4328 * information for us to generate an insn.
4329 * Such a case is therefore disallowed in the condition itself.
4330 * ( ref: valid_bbit_pattern_p )
4333 if ( GET_CODE (operands
[4]) == EQ
)
4334 return "bbit0%# %1,%z2,%l5";
4345 /* Generate a bbit{0,1} insn for the current pattern
4346 * bbit instructions are used as an optimized alternative to
4347 * a sequence of and,cmp and branch instructions
4350 gen_bbit_insns(rtx
* operands
)
4353 switch (INTVAL(operands
[3]))
4355 /* and r%0,r%1,imm%2
4356 * cmp r%0,0<- the value we have switched on
4360 * bbit{0,1} r%0,log2(imm%2),label%5
4363 if ( GET_CODE (operands
[4]) == EQ
)
4364 return "bbit0%# %1,%z2,%^%l5";
4365 else if ( GET_CODE (operands
[4]) == NE
)
4366 return "bbit1%# %1,%z2,%^%l5";
4370 /* and r%0,r%1,imm%2
4371 * cmp r%0,1<- the value we have switched on
4375 * bbit1 r%0,log2(imm%2),label%5
4376 * the bne case does not make sense here as it gives too little
4377 * information for us to generate an insn.
4378 * Such a case is therefore disallowed in the condition itself.
4379 * ( ref: valid_bbit_pattern_p )
4382 if ( GET_CODE (operands
[4]) == EQ
)
4383 return "bbit1%# %1,%z2,%l5";
4393 /* Return the destination address of a branch. */
4395 branch_dest (rtx branch
)
4397 rtx pat
= PATTERN (branch
);
4398 rtx dest
= (GET_CODE (pat
) == PARALLEL
4399 ? SET_SRC (XVECEXP (pat
, 0, 0)) : SET_SRC (pat
));
4402 if (GET_CODE (dest
) == IF_THEN_ELSE
)
4403 dest
= XEXP (dest
, XEXP (dest
, 1) == pc_rtx
? 2 : 1);
4405 dest
= XEXP (dest
, 0);
4406 dest_uid
= INSN_UID (dest
);
4408 return INSN_ADDRESSES (dest_uid
);
4412 /* Predicate for judging if a pattern is valid for bbit generation
4413 * The rtl pattern is:
4416 * pc = (cmp cc, 0) ? label%5 : pc
4417 * The conditions required are:
4418 * 1. imm%2 shd be an exact power of 2
4419 * 2. imm%3 shd be 0 or 1
4420 * 3. the comparison operator should be either EQ or NE
4421 * NOTE: imm%3 = 1 and comparion = NE is not valid
4424 valid_bbit_pattern_p (rtx
* operands
,rtx insn
)
4428 /* ret = (imm%2 == power of 2 */
4429 retval
= !( (INTVAL(operands
[2]) & (INTVAL(operands
[2]) - 1)) );
4431 /* now check for the right combinations
4432 * ( ref: comments in gen_bbit_insns above )
4436 ( INTVAL(operands
[3]) == 1 && GET_CODE (operands
[4]) == EQ
)
4437 || ( ( INTVAL(operands
[3]) == 0)
4438 && ( GET_CODE (operands
[4]) == EQ
|| GET_CODE (operands
[4]) == NE
))
4441 retval
= retval
&& SMALL_INT(branch_dest(insn
)-INSN_ADDRESSES(INSN_UID(insn
)));
4447 /* Symbols in the text segment can be accessed without indirecting via the
4448 constant pool; it may take an extra binary operation, but this is still
4449 faster than indirecting via memory. Don't do this when not optimizing,
4450 since we won't be calculating al of the offsets necessary to do this
4453 /* On the ARC, function addresses are not the same as normal addresses.
4454 Branch to absolute address insns take an address that is right-shifted
4455 by 2. We encode the fact that we have a function here, and then emit a
4456 special assembler op when outputting the address.
4457 The encoding involves adding an *_CALL_FLAG_CHAR to the symbol name
4458 (depending on whether any of short_call/long_call attributes were specified
4459 in the function's declaration) and unmangling the name at the time of
4460 printing the symbol name.
4462 Also if the symbol is a local, then the machine specific
4463 SYMBOL_REF_FLAG is set in the rtx.This flag is later used to print
4464 the reference to local symbols as @GOTOFF references instead of
4465 @GOT references so that the symbol does not get a GOT entry unlike
4467 Also calls to local functions are relative and not through the
4468 Procedure Linkage Table.
4472 arc_encode_section_info (tree decl
, rtx rtl
, int first
)
4474 /* Check if it is a function, and whether it has the [long/short]_call
4475 attribute specified */
4476 if (TREE_CODE (decl
) == FUNCTION_DECL
)
4478 tree attr
= (TREE_TYPE (decl
) != error_mark_node
4479 ? TYPE_ATTRIBUTES (TREE_TYPE (decl
)) : NULL_TREE
);
4480 tree long_call_attr
= lookup_attribute ("long_call", attr
);
4481 tree short_call_attr
= lookup_attribute ("short_call", attr
);
4483 if (long_call_attr
!= NULL_TREE
)
4484 arc_encode_symbol (decl
, LONG_CALL_FLAG_CHAR
);
4485 else if (short_call_attr
!= NULL_TREE
)
4486 arc_encode_symbol (decl
, SHORT_CALL_FLAG_CHAR
);
4488 arc_encode_symbol (decl
, SIMPLE_CALL_FLAG_CHAR
);
4493 if (!DECL_P (decl
) || targetm
.binds_local_p (decl
))
4494 SYMBOL_REF_FLAG (XEXP (rtl
, 0)) = 1;
4497 /* for sdata and SYMBOL_FLAG_FUNCTION */
4498 default_encode_section_info (decl
, rtl
, first
);
4501 /* This is how to output a definition of an internal numbered label where
4502 PREFIX is the class of label and NUM is the number within the class. */
4504 static void arc_internal_label (FILE *stream
, const char *prefix
, unsigned long labelno
)
4507 arc_ccfsm_at_label (prefix
, labelno
, &arc_ccfsm_current
);
4508 default_internal_label (stream
, prefix
, labelno
);
4511 /* Set the cpu type and print out other fancy things,
4512 at the top of the file. */
4514 static void arc_file_start (void)
4516 default_file_start ();
4517 fprintf (asm_out_file
, "\t.cpu %s\n", arc_cpu_string
);
4520 static void arc_asm_file_end (void)
4522 /* Free the obstack */
4523 /* obstack_free (&arc_local_obstack, NULL);*/
4526 /* Cost functions. */
4528 /* Compute a (partial) cost for rtx X. Return true if the complete
4529 cost has been computed, and false if subexpressions should be
4530 scanned. In either case, *TOTAL contains the cost result. */
4533 arc_rtx_costs (rtx x
, int code
, int outer_code
, int *total
, bool speed
)
4537 /* Small integers are as cheap as registers. */
4540 bool nolimm
= false; /* Can we do without long immediate? */
4541 bool fast
= false; /* Is the result available immediately? */
4542 bool condexec
= false; /* Does this allow conditiobnal execution? */
4543 bool compact
= false; /* Is a 16 bit opcode available? */
4544 /* CONDEXEC also implies that we can have an unconditional
4545 3-address operation. */
4547 nolimm
= compact
= condexec
= false;
4548 if (UNSIGNED_INT6 (INTVAL (x
)))
4549 nolimm
= condexec
= compact
= true;
4552 if (SMALL_INT (INTVAL (x
)))
4553 nolimm
= fast
= true;
4556 case AND
: /* bclr, bmsk, ext[bw] */
4557 if (satisfies_constraint_Ccp (x
) /* bclr */
4558 || satisfies_constraint_C1p (x
) /* bmsk */)
4559 nolimm
= fast
= condexec
= compact
= true;
4561 case IOR
: /* bset */
4562 if (satisfies_constraint_C0p (x
)) /* bset */
4563 nolimm
= fast
= condexec
= compact
= true;
4566 if (satisfies_constraint_C0p (x
)) /* bxor */
4567 nolimm
= fast
= condexec
= true;
4570 if (satisfies_constraint_Crr (x
)) /* ror b,u6 */
4576 /* FIXME: Add target options to attach a small cost if
4577 condexec / compact is not true. */
4586 /* 4 byte values can be fetched as immediate constants -
4587 let's give that the cost of an extra insn. */
4591 *total
= COSTS_N_INSNS (1);
4600 *total
= COSTS_N_INSNS (1);
4603 /* FIXME: correct the order of high,low */
4604 split_double (x
, &high
, &low
);
4605 *total
= COSTS_N_INSNS (!SMALL_INT (INTVAL (high
))
4606 + !SMALL_INT (INTVAL (low
)));
4610 /* Encourage synth_mult to find a synthetic multiply when reasonable.
4611 If we need more than 12 insns to do a multiply, then go out-of-line,
4612 since the call overhead will be < 10% of the cost of the multiply. */
4618 /* If we want to shift a constant, we need a LIMM. */
4619 /* ??? when the optimizers want to know if a constant should be
4620 hoisted, they ask for the cost of the constant. OUTER_CODE is
4621 insufficient context for shifts since we don't know which operand
4622 we are looking at. */
4623 if (CONSTANT_P (XEXP (x
, 0)))
4625 *total
+= COSTS_N_INSNS (2) + rtx_cost (XEXP (x
, 1), code
, speed
);
4628 *total
= COSTS_N_INSNS (1);
4630 else if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
4631 *total
= COSTS_N_INSNS (16);
4633 *total
= COSTS_N_INSNS (INTVAL (XEXP ((x
), 1)));
4639 *total
= COSTS_N_INSNS(30);
4641 *total
= COSTS_N_INSNS(1);
4645 if ((TARGET_DPFP
&& GET_MODE (x
) == DFmode
))
4646 *total
= COSTS_N_INSNS (1);
4648 *total
= arc_multcost
;
4649 /* We do not want synth_mult sequences when optimizing
4651 else if (TARGET_MUL64_SET
|| TARGET_ARC700
)
4652 *total
= COSTS_N_INSNS (1);
4654 *total
= COSTS_N_INSNS (2);
4657 if (GET_CODE (XEXP (x
, 0)) == MULT
4658 && _2_4_8_operand (XEXP (XEXP (x
, 0), 1), VOIDmode
))
4660 *total
+= (rtx_cost (XEXP (x
, 1), PLUS
, speed
)
4661 + rtx_cost (XEXP (XEXP (x
, 0), 0), PLUS
, speed
));
4666 if (GET_CODE (XEXP (x
, 1)) == MULT
4667 && _2_4_8_operand (XEXP (XEXP (x
, 1), 1), VOIDmode
))
4669 *total
+= (rtx_cost (XEXP (x
, 0), PLUS
, speed
)
4670 + rtx_cost (XEXP (XEXP (x
, 1), 0), PLUS
, speed
));
4676 rtx op0
= XEXP (x
, 0);
4677 rtx op1
= XEXP (x
, 1);
4679 if (GET_CODE (op0
) == ZERO_EXTRACT
&& op1
== const0_rtx
4680 && XEXP (op0
, 1) == const1_rtx
)
4682 /* btst / bbit0 / bbit1:
4683 Small integers and registers are free; everything else can
4684 be put in a register. */
4685 *total
= (rtx_cost (XEXP (op0
, 0), SET
, speed
)
4686 + rtx_cost (XEXP (op0
, 2), SET
, speed
));
4689 if (GET_CODE (op0
) == AND
&& op1
== const0_rtx
4690 && satisfies_constraint_C1p (XEXP (op0
, 1)))
4693 *total
= rtx_cost (XEXP (op0
, 0), SET
, speed
);
4697 if (GET_CODE (op1
) == NEG
)
4699 *total
= (rtx_cost (op0
, PLUS
,speed
)
4700 + rtx_cost (XEXP (op1
, 0), PLUS
, speed
));
4705 if (outer_code
== IF_THEN_ELSE
4706 && GET_CODE (XEXP (x
, 0)) == ZERO_EXTRACT
4707 && XEXP (x
, 1) == const0_rtx
4708 && XEXP (XEXP (x
, 0), 1) == const1_rtx
)
4710 /* btst / bbit0 / bbit1:
4711 Small integers and registers are free; everything else can
4712 be put in a register. */
4713 rtx op0
= XEXP (x
, 0);
4715 *total
= (rtx_cost (XEXP (op0
, 0), SET
, speed
)
4716 + rtx_cost (XEXP (op0
, 2), SET
, speed
));
4720 /* scc_insn expands into two insns. */
4721 case GTU
: case GEU
: case LEU
:
4722 if (GET_MODE (x
) == SImode
)
4723 *total
+= COSTS_N_INSNS (1);
4725 case LTU
: /* might use adc. */
4726 if (GET_MODE (x
) == SImode
)
4727 *total
+= COSTS_N_INSNS (1) - 1;
4735 arc_va_arg (tree valist
, tree type
)
4739 tree type_ptr
= build_pointer_type (type
);
4742 /* All aggregates are passed by reference. All scalar types larger
4743 than 8 bytes are passed by reference. */
4744 /* FIXME: delete this */
4745 if (0 && (AGGREGATE_TYPE_P (type
) || int_size_in_bytes (type
) > 8))
4748 && (TREE_CODE (TYPE_SIZE (type
)) != INTEGER_CST
4749 || TREE_ADDRESSABLE (type
)))
4752 tree type_ptr_ptr
= build_pointer_type (type_ptr
);
4754 addr
= build1 (INDIRECT_REF
, type_ptr
,
4755 build1 (NOP_EXPR
, type_ptr_ptr
, valist
));
4757 incr
= build2 (PLUS_EXPR
, TREE_TYPE (valist
),
4758 valist
, build_int_cst (NULL_TREE
, UNITS_PER_WORD
));
4762 HOST_WIDE_INT align
, rounded_size
;
4764 /* Compute the rounded size of the type. */
4765 align
= PARM_BOUNDARY
/ BITS_PER_UNIT
;
4767 = (((TREE_INT_CST_LOW (TYPE_SIZE (type
)) / BITS_PER_UNIT
+ align
- 1)
4771 /* Align 8 byte operands. */
4773 gcc_assert (TYPE_ALIGN (type
) <= BITS_PER_WORD
);
4774 if (TYPE_ALIGN (type
) > BITS_PER_WORD
)
4777 /* AP = (TYPE *)(((int)AP + 7) & -8) */
4779 addr
= build1 (NOP_EXPR
, integer_type_node
, valist
);
4780 addr
= fold (build2 (PLUS_EXPR
, integer_type_node
, addr
,
4781 build_int_cst (NULL_TREE
, 7)));
4782 addr
= fold (build2 (BIT_AND_EXPR
, integer_type_node
, addr
,
4783 build_int_cst (NULL_TREE
, -8)));
4784 addr
= fold (build1 (NOP_EXPR
, TREE_TYPE (valist
), addr
));
4787 /* The increment is always rounded_size past the aligned pointer. */
4788 incr
= fold (build2 (PLUS_EXPR
, TREE_TYPE (addr
), addr
,
4789 build_int_cst (NULL_TREE
, rounded_size
)));
4791 /* Adjust the pointer in big-endian mode. */
4792 if (BYTES_BIG_ENDIAN
)
4795 adj
= TREE_INT_CST_LOW (TYPE_SIZE (type
)) / BITS_PER_UNIT
;
4796 if (rounded_size
> align
)
4799 addr
= fold (build2 (PLUS_EXPR
, TREE_TYPE (addr
), addr
,
4800 build_int_cst (NULL_TREE
, rounded_size
- adj
)));
4804 /* Evaluate the data address. */
4805 addr_rtx
= expand_expr (addr
, NULL_RTX
, Pmode
, EXPAND_NORMAL
);
4806 addr_rtx
= copy_to_reg (addr_rtx
);
4808 /* Compute new value for AP. */
4809 incr
= build2 (MODIFY_EXPR
, TREE_TYPE (valist
), valist
, incr
);
4810 TREE_SIDE_EFFECTS (incr
) = 1;
4811 expand_expr (incr
, const0_rtx
, VOIDmode
, EXPAND_NORMAL
);
4816 /* Return a pointer to a function's name with any
4817 and all prefix encodings stripped from it. */
4819 arc_strip_name_encoding (const char *name
)
4823 case SIMPLE_CALL_FLAG_CHAR
:
4824 case LONG_CALL_FLAG_CHAR
:
4825 case SHORT_CALL_FLAG_CHAR
:
4828 return (name
) + ((name
)[0] == '*') ;
4833 /* An address that needs to be expressed as an explicit sum of pcl + offset. */
4835 arc_legitimate_pc_offset_p (rtx addr
)
4837 if (GET_CODE (addr
) != CONST
)
4839 addr
= XEXP (addr
, 0);
4840 if (GET_CODE (addr
) == PLUS
)
4842 if (GET_CODE (XEXP (addr
, 1)) != CONST_INT
)
4844 addr
= XEXP (addr
, 0);
4846 return (GET_CODE (addr
) == UNSPEC
4847 && XVECLEN (addr
, 0) == 1
4848 && XINT (addr
, 1) == ARC_UNSPEC_GOT
4849 && GET_CODE (XVECEXP (addr
, 0, 0)) == SYMBOL_REF
);
4852 /* check whether it is a valid pic address or not
4853 * A valid pic address on arc should look like
4854 * const (unspec (SYMBOL_REF/LABEL) (ARC_UNSPEC_GOTOFF/ARC_UNSPEC_GOT))
4857 arc_legitimate_pic_addr_p (rtx addr
)
4859 if (GET_CODE (addr
) == LABEL_REF
)
4861 if (GET_CODE (addr
) != CONST
)
4864 addr
= XEXP (addr
, 0);
4867 if (GET_CODE (addr
) == PLUS
)
4869 if (GET_CODE (XEXP (addr
, 1)) != CONST_INT
)
4871 addr
= XEXP (addr
, 0);
4874 if (GET_CODE (addr
) != UNSPEC
4875 || XVECLEN (addr
, 0) != 1)
4878 /* Must be @GOT or @GOTOFF. */
4879 if (XINT (addr
, 1) != ARC_UNSPEC_GOT
4880 && XINT (addr
, 1) != ARC_UNSPEC_GOTOFF
)
4883 if (GET_CODE (XVECEXP (addr
, 0, 0)) != SYMBOL_REF
4884 && GET_CODE (XVECEXP (addr
, 0, 0)) != LABEL_REF
)
4892 /* Returns 1 if OP contains a symbol reference */
4895 symbolic_reference_mentioned_p (rtx op
)
4897 register const char *fmt
;
4900 if (GET_CODE (op
) == SYMBOL_REF
|| GET_CODE (op
) == LABEL_REF
)
4903 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
4904 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
4910 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
4911 if (symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
)))
4915 else if (fmt
[i
] == 'e' && symbolic_reference_mentioned_p (XEXP (op
, i
)))
4923 arc_raw_symbolic_reference_mentioned_p (rtx op
)
4925 register const char *fmt
;
4928 if (GET_CODE(op
) == UNSPEC
)
4931 if (GET_CODE (op
) == SYMBOL_REF
)
4934 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
4935 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
4941 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
4942 if (arc_raw_symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
)))
4946 else if (fmt
[i
] == 'e' && arc_raw_symbolic_reference_mentioned_p (XEXP (op
, i
)))
4953 /* Legitimize a pic address reference
4955 * oldx = target if reload_in_progress
4959 arc_legitimize_pic_address (rtx orig
, rtx oldx
)
4968 if (GET_CODE (addr
) == LABEL_REF
)
4970 else if (GET_CODE (addr
) == SYMBOL_REF
4971 && (CONSTANT_POOL_ADDRESS_P (addr
)
4972 || SYMBOL_REF_FLAG (addr
)))
4974 /* This symbol may be referenced via a displacement from the PIC
4975 base address (@GOTOFF). */
4977 /* FIXME: if we had a way to emit pc-relative adds that don't
4978 create a GOT entry, we could do without the use of the gp register. */
4979 crtl
->uses_pic_offset_table
= 1;
4980 new = gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, addr
), ARC_UNSPEC_GOTOFF
);
4981 new = gen_rtx_CONST (Pmode
, new);
4982 new = gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, new);
4985 oldx
= gen_reg_rtx (Pmode
);
4989 emit_move_insn (oldx
, new);
4994 else if (GET_CODE (addr
) == SYMBOL_REF
)
4996 /* This symbol must be referenced via a load from the
4997 Global Offset Table (@GOTPC). */
4999 new = gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, addr
), ARC_UNSPEC_GOT
);
5000 new = gen_rtx_CONST (Pmode
, new);
5001 new = gen_const_mem (Pmode
, new);
5004 oldx
= gen_reg_rtx (Pmode
);
5006 emit_move_insn (oldx
, new);
5011 if (GET_CODE (addr
) == CONST
)
5013 addr
= XEXP (addr
, 0);
5014 if (GET_CODE (addr
) == UNSPEC
)
5016 /* Check that the unspec is one of the ones we generate? */
5019 gcc_assert (GET_CODE (addr
) == PLUS
);
5022 if (GET_CODE (addr
) == PLUS
)
5024 rtx op0
= XEXP (addr
, 0), op1
= XEXP (addr
, 1);
5026 /* Check first to see if this is a constant offset from a @GOTOFF
5027 symbol reference. */
5028 if ((GET_CODE (op0
) == LABEL_REF
5029 || (GET_CODE (op0
) == SYMBOL_REF
5030 && (CONSTANT_POOL_ADDRESS_P (op0
)
5031 || SYMBOL_REF_FLAG (op0
))))
5032 && GET_CODE (op1
) == CONST_INT
)
5034 /* FIXME: like above, could do without gp reference. */
5035 crtl
->uses_pic_offset_table
= 1;
5036 new = gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, op0
), ARC_UNSPEC_GOTOFF
);
5037 new = gen_rtx_PLUS (Pmode
, new, op1
);
5038 new = gen_rtx_CONST (Pmode
, new);
5039 new = gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, new);
5043 emit_move_insn (oldx
, new);
5049 base
= arc_legitimize_pic_address (XEXP (addr
, 0), oldx
);
5050 new = arc_legitimize_pic_address (XEXP (addr
, 1),
5051 base
== oldx
? NULL_RTX
: oldx
);
5053 if (GET_CODE (new) == CONST_INT
)
5054 new = plus_constant (base
, INTVAL (new));
5057 if (GET_CODE (new) == PLUS
&& CONSTANT_P (XEXP (new, 1)))
5059 base
= gen_rtx_PLUS (Pmode
, base
, XEXP (new, 0));
5060 new = XEXP (new, 1);
5062 new = gen_rtx_PLUS (Pmode
, base
, new);
5072 arc_output_pic_addr_const (FILE * file
, rtx x
, int code
)
5077 switch (GET_CODE (x
))
5087 output_addr_const (file
, x
);
5089 /* Local functions do not get references through the PLT */
5090 if (code
== 'P' && ! SYMBOL_REF_FLAG (x
))
5091 fputs ("@plt", file
);
5095 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (XEXP (x
, 0)));
5096 arc_assemble_name (file
, buf
);
5100 ASM_GENERATE_INTERNAL_LABEL (buf
, "L", CODE_LABEL_NUMBER (x
));
5101 arc_assemble_name (file
, buf
);
5105 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, INTVAL (x
));
5109 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
5113 if (GET_MODE (x
) == VOIDmode
)
5115 /* We can use %d if the number is one word and positive. */
5116 if (CONST_DOUBLE_HIGH (x
))
5117 fprintf (file
, HOST_WIDE_INT_PRINT_DOUBLE_HEX
,
5118 CONST_DOUBLE_HIGH (x
), CONST_DOUBLE_LOW (x
));
5119 else if (CONST_DOUBLE_LOW (x
) < 0)
5120 fprintf (file
, HOST_WIDE_INT_PRINT_HEX
, CONST_DOUBLE_LOW (x
));
5122 fprintf (file
, HOST_WIDE_INT_PRINT_DEC
, CONST_DOUBLE_LOW (x
));
5125 /* We can't handle floating point constants;
5126 PRINT_OPERAND must handle them. */
5127 output_operand_lossage ("floating constant misused");
5131 /* FIXME: Not needed here */
5132 /* Some assemblers need integer constants to appear last (eg masm). */
5133 if (GET_CODE (XEXP (x
, 0)) == CONST_INT
)
5135 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
5136 fprintf (file
, "+");
5137 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
5139 else if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
5141 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
5142 if (INTVAL (XEXP (x
, 1)) >= 0)
5143 fprintf (file
, "+");
5144 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
5151 /* Avoid outputting things like x-x or x+5-x,
5152 since some assemblers can't handle that. */
5153 x
= simplify_subtraction (x
);
5154 if (GET_CODE (x
) != MINUS
)
5157 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
5158 fprintf (file
, "-");
5159 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
5160 && INTVAL (XEXP (x
, 1)) < 0)
5162 fprintf (file
, "(");
5163 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
5164 fprintf (file
, ")");
5167 arc_output_pic_addr_const (file
, XEXP (x
, 1), code
);
5172 arc_output_pic_addr_const (file
, XEXP (x
, 0), code
);
5177 gcc_assert (XVECLEN (x
, 0) == 1);
5178 if (XINT (x
, 1) == ARC_UNSPEC_GOT
)
5179 fputs ("pcl,", file
);
5180 arc_output_pic_addr_const (file
, XVECEXP (x
, 0, 0), code
);
5181 switch (XINT (x
, 1))
5183 case ARC_UNSPEC_GOT
:
5184 fputs ("@gotpc", file
);
5186 case ARC_UNSPEC_GOTOFF
:
5187 fputs ("@gotoff", file
);
5189 case ARC_UNSPEC_PLT
:
5190 fputs ("@plt", file
);
5193 fprintf(stderr
, "%d seen\n",XINT (x
,1));
5194 output_operand_lossage ("invalid UNSPEC as operand");
5201 output_operand_lossage ("invalid expression as operand");
5205 /* Emit insns to move operands[1] into operands[0]. */
5208 emit_pic_move (rtx
*operands
, enum machine_mode mode ATTRIBUTE_UNUSED
)
5210 rtx temp
= reload_in_progress
? operands
[0] : gen_reg_rtx (Pmode
);
5212 if (GET_CODE (operands
[0]) == MEM
&& SYMBOLIC_CONST (operands
[1]))
5213 operands
[1] = force_reg (Pmode
, operands
[1]);
5215 operands
[1] = arc_legitimize_pic_address (operands
[1], temp
);
5219 /* Prepend the symbol passed as argument to the name */
5221 arc_encode_symbol (tree decl
, const char prefix
)
5223 const char *str
= XSTR (XEXP (DECL_RTL (decl
), 0), 0);
5224 int len
= strlen (str
);
5229 newstr
= (char*) obstack_alloc (&arc_local_obstack
, len
+ 2);
5231 strcpy (newstr
+ 1, str
);
5233 XSTR (XEXP (DECL_RTL (decl
), 0), 0) = newstr
;
5239 /* Output to FILE a reference to the assembler name of a C-level name NAME.
5240 If NAME starts with a *, the rest of NAME is output verbatim.
5241 Otherwise NAME is transformed in an implementation-defined way
5242 (usually by the addition of an underscore).
5243 Many macros in the tm file are defined to call this function. */
5244 /* FIXME: This can be deleted */
5246 arc_assemble_name (FILE *file
, const char *name
)
5248 const char *real_name
=name
;
5250 /*real_name = arc_strip_name_encoding (name);*/
5251 assemble_name(file
, real_name
);
5255 /* The function returning the number of words, at the beginning of an
5256 argument, must be put in registers. The returned value must be
5257 zero for arguments that are passed entirely in registers or that
5258 are entirely pushed on the stack.
5260 On some machines, certain arguments must be passed partially in
5261 registers and partially in memory. On these machines, typically
5262 the first N words of arguments are passed in registers, and the
5263 rest on the stack. If a multi-word argument (a `double' or a
5264 structure) crosses that boundary, its first few words must be
5265 passed in registers and the rest must be pushed. This function
5266 tells the compiler when this occurs, and how many of the words
5267 should go in registers.
5269 `FUNCTION_ARG' for these arguments should return the first register
5270 to be used by the caller for this argument; likewise
5271 `FUNCTION_INCOMING_ARG', for the called function.
5273 The function is used to implement macro FUNCTION_ARG_PARTIAL_NREGS. */
5275 /* if REGNO is the least arg reg available then what is the total number of arg
5277 #define GPR_REST_ARG_REGS(REGNO) ( ((REGNO) <= (MAX_ARC_PARM_REGS)) \
5278 ? ((MAX_ARC_PARM_REGS) - (REGNO)) \
5281 /* since arc parm regs are contiguous */
5282 #define ARC_NEXT_ARG_REG(REGNO) ( (REGNO) + 1 )
5284 /* Implement TARGET_ARG_PARTIAL_BYTES. */
5287 /* arc_function_arg_partial_nregs (cum, mode, type, named) */
5288 arc_arg_partial_bytes (CUMULATIVE_ARGS
*cum
, enum machine_mode mode
, tree type
, bool named ATTRIBUTE_UNUSED
)
5290 int bytes
= (mode
== BLKmode
5291 ? int_size_in_bytes (type
) : (int) GET_MODE_SIZE (mode
));
5292 int words
= (bytes
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
5296 arg_num
= ROUND_ADVANCE_CUM (arg_num
, mode
, type
);
5297 ret
= GPR_REST_ARG_REGS (arg_num
);
5299 /* ICEd at function.c:2361, and ret is copied to data->partial */
5300 ret
= (ret
>= words
? 0 : ret
* UNITS_PER_WORD
);
5307 /* This function is used to control a function argument is passed in a
5308 register, and which register.
5310 The arguments are CUM, of type CUMULATIVE_ARGS, which summarizes
5311 (in a way defined by INIT_CUMULATIVE_ARGS and FUNCTION_ARG_ADVANCE)
5312 all of the previous arguments so far passed in registers; MODE, the
5313 machine mode of the argument; TYPE, the data type of the argument
5314 as a tree node or 0 if that is not known (which happens for C
5315 support library functions); and NAMED, which is 1 for an ordinary
5316 argument and 0 for nameless arguments that correspond to `...' in
5317 the called function's prototype.
5319 The returned value should either be a `reg' RTX for the hard
5320 register in which to pass the argument, or zero to pass the
5321 argument on the stack.
5323 For machines like the Vax and 68000, where normally all arguments
5324 are pushed, zero suffices as a definition.
5326 The usual way to make the ANSI library `stdarg.h' work on a machine
5327 where some arguments are usually passed in registers, is to cause
5328 nameless arguments to be passed on the stack instead. This is done
5329 by making the function return 0 whenever NAMED is 0.
5331 You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the
5332 definition of this function to determine if this argument is of a
5333 type that must be passed in the stack. If `REG_PARM_STACK_SPACE'
5334 is not defined and the function returns non-zero for such an
5335 argument, the compiler will abort. If `REG_PARM_STACK_SPACE' is
5336 defined, the argument will be computed in the stack and then loaded
5339 The function is used to implement macro FUNCTION_ARG. */
5342 arc_function_arg (CUMULATIVE_ARGS
*cum
, enum machine_mode mode
,
5343 tree type ATTRIBUTE_UNUSED
, int named ATTRIBUTE_UNUSED
)
5349 arg_num
= ROUND_ADVANCE_CUM (arg_num
, mode
, type
);
5350 /* Return a marker for use in the call instruction. */
5351 if (mode
== VOIDmode
)
5356 else if (GPR_REST_ARG_REGS (arg_num
) > 0)
5358 ret
= gen_rtx_REG (mode
, arg_num
);
5359 debstr
= reg_names
[arg_num
];
5369 /* The function to update the summarizer variable *CUM to advance past
5370 an argument in the argument list. The values MODE, TYPE and NAMED
5371 describe that argument. Once this is done, the variable *CUM is
5372 suitable for analyzing the *following* argument with
5373 `FUNCTION_ARG', etc.
5375 This function need not do anything if the argument in question was
5376 passed on the stack. The compiler knows how to track the amount of
5377 stack space used for arguments without any special help.
5379 The function is used to implement macro FUNCTION_ARG_ADVANCE. */
5380 /* For the ARC: the cum set here is passed on to function_arg where we
5381 look at its value and say which reg to use. Strategy: advance the
5382 regnumber here till we run out of arg regs, then set *cum to last
5383 reg. In function_arg, since *cum > last arg reg we would return 0
5384 and thus the arg will end up on the stack. For straddling args of
5385 course function_arg_partial_nregs will come into play */
5387 arc_function_arg_advance (CUMULATIVE_ARGS
*cum
, enum machine_mode mode
, tree type
, int named ATTRIBUTE_UNUSED
)
5389 int bytes
= (mode
== BLKmode
5390 ? int_size_in_bytes (type
) : (int) GET_MODE_SIZE (mode
));
5391 int words
= (bytes
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
5395 *cum
= ROUND_ADVANCE_CUM (*cum
, mode
, type
);
5396 for (i
= 0; i
< words
; i
++)
5397 *cum
= ARC_NEXT_ARG_REG (*cum
);
5401 /* Define how to find the value returned by a function.
5402 VALTYPE is the data type of the value (as a tree).
5403 If the precise function being called is known, FN_DECL_OR_TYPE is its
5404 FUNCTION_DECL; otherwise, FN_DECL_OR_TYPE is its type. */
5406 arc_function_value (const_tree valtype
,
5407 const_tree fn_decl_or_type ATTRIBUTE_UNUSED
,
5408 bool outgoing ATTRIBUTE_UNUSED
)
5410 enum machine_mode mode
= TYPE_MODE (valtype
);
5411 int unsignedp ATTRIBUTE_UNUSED
;
5413 unsignedp
= TYPE_UNSIGNED (valtype
);
5414 if (INTEGRAL_TYPE_P (valtype
) || TREE_CODE (valtype
) == OFFSET_TYPE
)
5415 PROMOTE_MODE(mode
, unsignedp
, valtype
);
5416 return gen_rtx_REG (mode
, 0);
5419 /* Returns the return address that is used by builtin_return_address */
5421 arc_return_addr_rtx (int count
, ATTRIBUTE_UNUSED rtx frame
)
5428 /* Only the lower 24 bits of blink are valid */
5429 rtx temp
= get_hard_reg_initial_val (Pmode
, RETURN_ADDR_REGNUM
);
5430 emit_insn (gen_andsi3(temp
,temp
,gen_rtx_CONST_INT (SImode
,0x00ffffff)));
5434 return get_hard_reg_initial_val (Pmode
, RETURN_ADDR_REGNUM
);
5437 /* Nonzero if the constant value X is a legitimate general operand
5438 when generating PIC code. It is given that flag_pic is on and
5439 that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
5440 /* TODO: This should not be a separate function */
5442 arc_legitimate_pic_operand_p (rtx x
)
5444 return !arc_raw_symbolic_reference_mentioned_p (x
);
5447 /* Determine if a given RTX is a valid constant. We already know this
5448 satisfies CONSTANT_P. */
5450 arc_legitimate_constant_p (rtx x
)
5455 switch (GET_CODE (x
))
5460 if (GET_CODE (x
) == PLUS
)
5462 if (GET_CODE (XEXP (x
, 1)) != CONST_INT
)
5467 /* Only some unspecs are valid as "constants". */
5468 if (GET_CODE (x
) == UNSPEC
)
5469 switch (XINT (x
, 1))
5471 case ARC_UNSPEC_PLT
:
5472 case ARC_UNSPEC_GOTOFF
:
5473 case ARC_UNSPEC_GOT
:
5481 /* We must have drilled down to a symbol. */
5482 if ( arc_raw_symbolic_reference_mentioned_p (x
))
5496 /* Otherwise we handle everything else in the move patterns. */
5500 /* Determine if it's legal to put X into the constant pool. */
5502 arc_cannot_force_const_mem (rtx x
)
5504 return !arc_legitimate_constant_p (x
);
5508 /* Generic function to define a builtin */
5509 #define def_mbuiltin(MASK, NAME, TYPE, CODE) \
5513 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL, NULL_TREE); \
5519 arc_init_builtins (void)
5521 tree endlink
= void_list_node
;
5523 tree void_ftype_void
5524 = build_function_type (void_type_node
,
5528 = build_function_type (integer_type_node
,
5529 tree_cons (NULL_TREE
, integer_type_node
, endlink
));
5531 tree int_ftype_short_int
5532 = build_function_type (integer_type_node
,
5533 tree_cons (NULL_TREE
, short_integer_type_node
, endlink
));
5535 tree void_ftype_int_int
5536 = build_function_type (void_type_node
,
5537 tree_cons (NULL_TREE
, integer_type_node
,
5538 tree_cons (NULL_TREE
, integer_type_node
, endlink
)));
5539 tree void_ftype_usint_usint
5540 = build_function_type (void_type_node
,
5541 tree_cons (NULL_TREE
, long_unsigned_type_node
,
5542 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
)));
5544 tree int_ftype_int_int
5545 = build_function_type (integer_type_node
,
5546 tree_cons (NULL_TREE
, integer_type_node
,
5547 tree_cons (NULL_TREE
, integer_type_node
, endlink
)));
5549 tree usint_ftype_usint
5550 = build_function_type (long_unsigned_type_node
,
5551 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
));
5553 tree void_ftype_usint
5554 = build_function_type (void_type_node
,
5555 tree_cons (NULL_TREE
, long_unsigned_type_node
, endlink
));
5557 /* Add the builtins */
5558 def_mbuiltin (1,"__builtin_arc_nop", void_ftype_void
, ARC_BUILTIN_NOP
);
5559 def_mbuiltin (TARGET_NORM
, "__builtin_arc_norm", int_ftype_int
, ARC_BUILTIN_NORM
);
5560 def_mbuiltin (TARGET_NORM
, "__builtin_arc_normw", int_ftype_short_int
, ARC_BUILTIN_NORMW
);
5561 def_mbuiltin (TARGET_SWAP
, "__builtin_arc_swap", int_ftype_int
, ARC_BUILTIN_SWAP
);
5562 def_mbuiltin (TARGET_MUL64_SET
,"__builtin_arc_mul64", void_ftype_int_int
, ARC_BUILTIN_MUL64
);
5563 def_mbuiltin (TARGET_MUL64_SET
,"__builtin_arc_mulu64", void_ftype_usint_usint
, ARC_BUILTIN_MULU64
);
5564 def_mbuiltin (1,"__builtin_arc_rtie", void_ftype_void
, ARC_BUILTIN_RTIE
);
5565 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_sync", void_ftype_void
, ARC_BUILTIN_SYNC
);
5566 def_mbuiltin ((TARGET_EA_SET
&& TARGET_ARCOMPACT
),"__builtin_arc_divaw", int_ftype_int_int
, ARC_BUILTIN_DIVAW
);
5567 def_mbuiltin (1,"__builtin_arc_brk", void_ftype_void
, ARC_BUILTIN_BRK
);
5568 def_mbuiltin (1,"__builtin_arc_flag", void_ftype_usint
, ARC_BUILTIN_FLAG
);
5569 def_mbuiltin (1,"__builtin_arc_sleep", void_ftype_usint
, ARC_BUILTIN_SLEEP
);
5570 def_mbuiltin (1,"__builtin_arc_swi", void_ftype_void
, ARC_BUILTIN_SWI
);
5571 def_mbuiltin (1,"__builtin_arc_core_read", usint_ftype_usint
, ARC_BUILTIN_CORE_READ
);
5572 def_mbuiltin (1,"__builtin_arc_core_write", void_ftype_usint_usint
, ARC_BUILTIN_CORE_WRITE
);
5573 def_mbuiltin (1,"__builtin_arc_lr", usint_ftype_usint
, ARC_BUILTIN_LR
);
5574 def_mbuiltin (1,"__builtin_arc_sr", void_ftype_usint_usint
, ARC_BUILTIN_SR
);
5575 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_trap_s", void_ftype_usint
, ARC_BUILTIN_TRAP_S
);
5576 def_mbuiltin (TARGET_ARC700
,"__builtin_arc_unimp_s", void_ftype_void
, ARC_BUILTIN_UNIMP_S
);
5578 if (TARGET_SIMD_SET
)
5579 arc_init_simd_builtins ();
5582 static rtx
arc_expand_simd_builtin (tree
, rtx
, rtx
, enum machine_mode
, int);
5584 /* Expand an expression EXP that calls a built-in function,
5585 with result going to TARGET if that's convenient
5586 (and in mode MODE if that's convenient).
5587 SUBTARGET may be used as the target for computing one of EXP's operands.
5588 IGNORE is nonzero if the value is to be ignored. */
5591 arc_expand_builtin (tree exp
,
5593 rtx subtarget ATTRIBUTE_UNUSED
,
5594 enum machine_mode mode ATTRIBUTE_UNUSED
,
5595 int ignore ATTRIBUTE_UNUSED
)
5597 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
5602 int fcode
= DECL_FUNCTION_CODE (fndecl
);
5604 enum machine_mode mode0
;
5605 enum machine_mode mode1
;
5607 if (fcode
> ARC_SIMD_BUILTIN_BEGIN
&& fcode
< ARC_SIMD_BUILTIN_END
)
5608 return arc_expand_simd_builtin (exp
, target
, subtarget
, mode
, ignore
);
5612 case ARC_BUILTIN_NOP
:
5613 emit_insn (gen_nop ());
5616 case ARC_BUILTIN_NORM
:
5617 icode
= CODE_FOR_norm
;
5618 arg0
= CALL_EXPR_ARG (exp
, 0);
5619 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, 0);
5620 mode0
= insn_data
[icode
].operand
[1].mode
;
5621 target
= gen_reg_rtx (SImode
);
5623 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5624 op0
= copy_to_mode_reg (mode0
, op0
);
5626 emit_insn (gen_norm (target
,op0
));
5629 case ARC_BUILTIN_NORMW
:
5631 /* FIXME : This should all be HI mode, not SI mode */
5632 icode
= CODE_FOR_normw
;
5633 arg0
= CALL_EXPR_ARG (exp
, 0);
5634 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, 0);
5635 mode0
= insn_data
[icode
].operand
[1].mode
;
5636 target
= gen_reg_rtx (SImode
);
5638 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5639 op0
= copy_to_mode_reg (mode0
, convert_to_mode (mode0
, op0
,0));
5641 emit_insn (gen_normw (target
, op0
));
5644 case ARC_BUILTIN_MUL64
:
5645 icode
= CODE_FOR_mul64
;
5646 arg0
= CALL_EXPR_ARG (exp
, 0);
5647 arg1
= CALL_EXPR_ARG (exp
, 1);
5648 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, 0);
5649 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, 0);
5651 mode0
= insn_data
[icode
].operand
[0].mode
;
5652 mode1
= insn_data
[icode
].operand
[1].mode
;
5654 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5655 op0
= copy_to_mode_reg (mode0
, op0
);
5657 if (! (*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
5658 op1
= copy_to_mode_reg (mode1
, op1
);
5660 emit_insn (gen_mul64 (op0
,op1
));
5663 case ARC_BUILTIN_MULU64
:
5664 icode
= CODE_FOR_mulu64
;
5665 arg0
= CALL_EXPR_ARG (exp
, 0);
5666 arg1
= CALL_EXPR_ARG (exp
, 1);
5667 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, 0);
5668 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, 0);
5670 mode0
= insn_data
[icode
].operand
[0].mode
;
5671 mode1
= insn_data
[icode
].operand
[1].mode
;
5673 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5674 op0
= copy_to_mode_reg (mode0
, op0
);
5676 if (! (*insn_data
[icode
].operand
[0].predicate
) (op1
, mode1
))
5677 op1
= copy_to_mode_reg (mode1
, op1
);
5679 emit_insn (gen_mulu64 (op0
,op1
));
5682 case ARC_BUILTIN_RTIE
:
5683 icode
= CODE_FOR_rtie
;
5684 emit_insn (gen_rtie (const1_rtx
));
5687 case ARC_BUILTIN_SYNC
:
5688 icode
= CODE_FOR_sync
;
5689 emit_insn (gen_sync (const1_rtx
));
5692 case ARC_BUILTIN_SWAP
:
5693 icode
= CODE_FOR_swap
;
5694 arg0
= CALL_EXPR_ARG (exp
, 0);
5695 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, 0);
5696 mode0
= insn_data
[icode
].operand
[1].mode
;
5697 target
= gen_reg_rtx (SImode
);
5699 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5700 op0
= copy_to_mode_reg (mode0
, op0
);
5702 emit_insn (gen_swap (target
,op0
));
5705 case ARC_BUILTIN_DIVAW
:
5706 icode
= CODE_FOR_divaw
;
5707 arg0
= CALL_EXPR_ARG (exp
, 0);
5708 arg1
= CALL_EXPR_ARG (exp
, 1);
5710 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, 0);
5711 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, 0);
5712 target
= gen_reg_rtx (SImode
);
5714 mode0
= insn_data
[icode
].operand
[0].mode
;
5715 mode1
= insn_data
[icode
].operand
[1].mode
;
5717 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5718 op0
= copy_to_mode_reg (mode0
, op0
);
5720 if (! (*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
5721 op1
= copy_to_mode_reg (mode1
, op1
);
5723 emit_insn (gen_divaw (target
,op0
,op1
));
5726 case ARC_BUILTIN_BRK
:
5727 icode
= CODE_FOR_brk
;
5728 emit_insn (gen_brk (const1_rtx
));
5731 case ARC_BUILTIN_SLEEP
:
5732 icode
= CODE_FOR_sleep
;
5733 arg0
= CALL_EXPR_ARG (exp
, 0);
5737 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, 0);
5738 mode0
= insn_data
[icode
].operand
[1].mode
;
5740 emit_insn (gen_sleep (op0
));
5743 case ARC_BUILTIN_SWI
:
5744 icode
= CODE_FOR_swi
;
5745 emit_insn (gen_swi (const1_rtx
));
5748 case ARC_BUILTIN_FLAG
:
5749 icode
= CODE_FOR_flag
;
5750 arg0
= CALL_EXPR_ARG (exp
, 0);
5751 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, 0);
5752 mode0
= insn_data
[icode
].operand
[0].mode
;
5754 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
5755 op0
= copy_to_mode_reg (mode0
, op0
);
5757 emit_insn (gen_flag (op0
));
5760 case ARC_BUILTIN_CORE_READ
:
5761 icode
= CODE_FOR_core_read
;
5762 arg0
= CALL_EXPR_ARG (exp
, 0);
5763 target
= gen_reg_rtx (SImode
);
5767 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, 0);
5768 mode0
= insn_data
[icode
].operand
[1].mode
;
5770 emit_insn (gen_core_read (target
, op0
));
5773 case ARC_BUILTIN_CORE_WRITE
:
5774 icode
= CODE_FOR_core_write
;
5775 arg0
= CALL_EXPR_ARG (exp
, 0);
5776 arg1
= CALL_EXPR_ARG (exp
, 1);
5780 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, 0);
5781 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, 0);
5783 mode0
= insn_data
[icode
].operand
[0].mode
;
5784 mode1
= insn_data
[icode
].operand
[1].mode
;
5786 emit_insn (gen_core_write (op0
, op1
));
5789 case ARC_BUILTIN_LR
:
5790 icode
= CODE_FOR_lr
;
5791 arg0
= CALL_EXPR_ARG (exp
, 0);
5792 target
= gen_reg_rtx (SImode
);
5796 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, 0);
5797 mode0
= insn_data
[icode
].operand
[1].mode
;
5799 emit_insn (gen_lr (target
, op0
));
5802 case ARC_BUILTIN_SR
:
5803 icode
= CODE_FOR_sr
;
5804 arg0
= CALL_EXPR_ARG (exp
, 0);
5805 arg1
= CALL_EXPR_ARG (exp
, 1);
5809 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, 0);
5810 op1
= expand_expr (arg1
, NULL_RTX
, VOIDmode
, 0);
5812 mode0
= insn_data
[icode
].operand
[0].mode
;
5813 mode1
= insn_data
[icode
].operand
[1].mode
;
5815 emit_insn (gen_sr (op0
, op1
));
5818 case ARC_BUILTIN_TRAP_S
:
5819 icode
= CODE_FOR_trap_s
;
5820 arg0
= CALL_EXPR_ARG (exp
, 0);
5824 op0
= expand_expr (arg0
, NULL_RTX
, VOIDmode
, 0);
5825 mode0
= insn_data
[icode
].operand
[1].mode
;
5827 emit_insn (gen_trap_s (op0
));
5830 case ARC_BUILTIN_UNIMP_S
:
5831 icode
= CODE_FOR_unimp_s
;
5832 emit_insn (gen_unimp_s (const1_rtx
));
5839 /* @@@ Should really do something sensible here. */
5843 /* Returns if the operands[ opno ] is a valid compile-time constant to be used
5844 as register number in the code for builtins. Else it flags an error. */
5847 check_if_valid_regno_const (rtx
*operands
, int opno
)
5850 switch (GET_CODE (operands
[opno
]))
5857 error("register number must be a compile-time constant. Try giving higher optimization levels");
5863 /* Check that after all the constant folding, whether the operand to
5864 __builtin_arc_sleep is an unsigned int of 6 bits. If not, flag an error
5867 check_if_valid_sleep_operand (rtx
*operands
, int opno
)
5869 switch (GET_CODE (operands
[opno
]))
5873 if( UNSIGNED_INT6 (INTVAL (operands
[opno
])))
5876 fatal_error("operand for sleep instruction must be a unsigned 6 bit compile-time constant.");
5882 /* Return nonzero if it is ok to make a tail-call to DECL. */
5884 arc_function_ok_for_sibcall (tree decl
, tree exp ATTRIBUTE_UNUSED
)
5888 if (!TARGET_ARCOMPACT
)
5890 /* Never tailcall something for which we have no decl. */
5894 /* Extract the function name from the decl node */
5895 fname
= XSTR (XEXP (DECL_RTL (decl
), 0), 0);
5897 /* ARC does not have a branch [reg], so no sibcalls with -mlong-calls, unless
5898 the called function has short_call attribute set */
5899 if (TARGET_LONG_CALLS_SET
&& !ARC_ENCODED_SHORT_CALL_ATTR_P(fname
))
5902 /* Is this a long_call attributed function. If so, return false */
5903 if (ARC_ENCODED_LONG_CALL_ATTR_P(fname
))
5907 /* Never tailcall from an ISR routine - it needs a special exit sequence. */
5908 if (ARC_INTERRUPT_P (arc_compute_function_type (cfun
)))
5911 /* Everything else is ok. */
5915 /* Output code to add DELTA to the first argument, and then jump
5916 to FUNCTION. Used for C++ multiple inheritance. */
5918 arc_output_mi_thunk (FILE *file
, tree thunk ATTRIBUTE_UNUSED
,
5919 HOST_WIDE_INT delta
,
5920 HOST_WIDE_INT vcall_offset
,
5923 int mi_delta
= delta
;
5924 const char *const mi_op
= mi_delta
< 0 ? "sub" : "add";
5927 = aggregate_value_p (TREE_TYPE (TREE_TYPE (function
)), function
) ? 1 : 0;
5931 mi_delta
= - mi_delta
;
5933 /* Add DELTA. When possible use a plain add, otherwise load it into
5934 a register first. */
5936 while (mi_delta
!= 0)
5938 if ((mi_delta
& (3 << shift
)) == 0)
5942 asm_fprintf (file
, "\t%s\t%s, %s, %d\n",
5943 mi_op
, reg_names
[this_regno
], reg_names
[this_regno
],
5944 mi_delta
& (0xff << shift
));
5945 mi_delta
&= ~(0xff << shift
);
5950 /* If needed, add *(*THIS + VCALL_OFFSET) to THIS. */
5951 if (vcall_offset
!= 0)
5953 /* ld r12,[this] --> temp = *this
5954 add r12,r12,vcall_offset --> temp = *(*this + vcall_offset)
5956 add this,this,r12 --> this+ = *(*this + vcall_offset) */
5957 asm_fprintf (file
, "\tld\t%s, [%s]\n",
5958 ARC_TEMP_SCRATCH_REG
, reg_names
[this_regno
]);
5959 asm_fprintf (file
, "\tadd\t%s, %s, %ld\n",
5960 ARC_TEMP_SCRATCH_REG
, ARC_TEMP_SCRATCH_REG
, vcall_offset
);
5961 asm_fprintf (file
, "\tld\t%s, [%s]\n",
5962 ARC_TEMP_SCRATCH_REG
, ARC_TEMP_SCRATCH_REG
);
5963 asm_fprintf (file
, "\tadd\t%s, %s, %s\n", reg_names
[this_regno
],
5964 reg_names
[this_regno
], ARC_TEMP_SCRATCH_REG
);
5967 fname
= XSTR (XEXP (DECL_RTL (function
), 0), 0);
5968 if (TARGET_LONG_CALLS_SET
5969 ? !ARC_ENCODED_SHORT_CALL_ATTR_P (fname
)
5970 : ARC_ENCODED_LONG_CALL_ATTR_P (fname
))
5971 fputs ("\tj\t", file
);
5973 fputs ("\tb\t", file
);
5974 assemble_name (file
, XSTR (XEXP (DECL_RTL (function
), 0), 0));
5978 /* Return nonzero if a 32 bit "long_call" should be generated for
5979 this call. We generate a long_call if the function:
5981 a. has an __attribute__((long call))
5982 or b. the -mlong-calls command line switch has been specified
5984 However we do not generate a long call if the function has an
5985 __attribute__ ((short_call))
5987 This function will be called by C fragments contained in the machine
5988 description file. */
5990 arc_is_longcall_p (rtx sym_ref
)
5992 if (GET_CODE (sym_ref
) != SYMBOL_REF
)
5995 return ARC_ENCODED_LONG_CALL_ATTR_P (XSTR (sym_ref
, 0))
5996 || ( TARGET_LONG_CALLS_SET
&& !ARC_ENCODED_SHORT_CALL_ATTR_P (XSTR (sym_ref
,0)));
6000 /* Emit profiling code for calling CALLEE. Return nonzero if a special
6001 call pattern needs to be generated. */
6003 arc_profile_call (rtx callee
)
6005 rtx from
= XEXP (DECL_RTL (current_function_decl
), 0);
6007 if (CONSTANT_P (callee
))
6010 = gen_rtx_CONST (Pmode
,
6011 gen_rtx_UNSPEC (Pmode
,
6012 gen_rtvec (3, from
, callee
,
6013 CONST0_RTX (Pmode
)),
6015 rtx counter
= gen_rtx_MEM (SImode
, count_ptr
);
6016 /* ??? The increment would better be done atomically, but as there is
6017 no proper hardware support, that would be too expensive. */
6018 emit_move_insn (counter
, force_reg (SImode
, plus_constant (counter
, 1)));
6024 = gen_rtx_CONST (Pmode
,
6025 gen_rtx_UNSPEC (Pmode
,
6026 gen_rtvec (3, from
, CONST0_RTX (Pmode
),
6027 CONST0_RTX (Pmode
)),
6029 emit_move_insn (gen_rtx_REG (Pmode
, 8), count_list_ptr
);
6030 emit_move_insn (gen_rtx_REG (Pmode
, 9), callee
);
6035 /* Worker function for TARGET_RETURN_IN_MEMORY. */
6038 arc_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
6040 if (AGGREGATE_TYPE_P (type
) || TREE_ADDRESSABLE (type
))
6044 HOST_WIDE_INT size
= int_size_in_bytes (type
);
6045 return (size
== -1 || size
> 8);
6049 /* ashwin : taken from gcc-4.2-FSF clean sources */
6050 /* For ARC, All aggregates and arguments greater than 8 bytes are
6051 passed by reference. */
6053 arc_pass_by_reference (CUMULATIVE_ARGS
*ca ATTRIBUTE_UNUSED
,
6054 enum machine_mode mode ATTRIBUTE_UNUSED
,
6055 const_tree type ATTRIBUTE_UNUSED
,
6056 bool named ATTRIBUTE_UNUSED
)
6059 && (TREE_CODE (TYPE_SIZE (type
)) != INTEGER_CST
6060 || TREE_ADDRESSABLE (type
)));
6062 /* ashwin : We always pass arguments are passed by value */
6065 /* unsigned HOST_WIDE_INT size; */
6069 /* if (AGGREGATE_TYPE_P (type)) */
6071 /* size = int_size_in_bytes (type); */
6074 /* size = GET_MODE_SIZE (mode); */
6076 /* return size > 8; */
6081 /* NULL if INSN insn is valid within a low-overhead loop.
6082 Otherwise return why doloop cannot be applied. */
6085 arc_invalid_within_doloop (const_rtx insn
)
6088 return "Function call in the loop.";
6092 static int arc_reorg_in_progress
= 0;
6094 /* ARC's machince specific reorg function. */
6103 cfun
->machine
->arc_reorg_started
= 1;
6104 arc_reorg_in_progress
= 1;
6106 /* Emit special sections for profiling. */
6109 section
*save_text_section
;
6111 int size
= get_max_uid () >> 4;
6112 htab_t htab
= htab_create (size
, unspec_prof_hash
, unspec_prof_htab_eq
,
6115 save_text_section
= in_section
;
6116 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
6117 if (NONJUMP_INSN_P (insn
))
6118 walk_stores (PATTERN (insn
), write_profile_sections
, htab
);
6119 if (htab_elements (htab
))
6121 switch_to_section (save_text_section
);
6125 /* Link up loop ends with their loop start. */
6127 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
6128 if (GET_CODE (insn
) == JUMP_INSN
6129 && recog_memoized (insn
) == CODE_FOR_doloop_end_i
)
6132 = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn
), 0, 0)), 1), 0);
6133 rtx num
= GEN_INT (CODE_LABEL_NUMBER (top_label
));
6134 rtx lp
, prev
= prev_nonnote_insn (top_label
);
6135 rtx next
= NULL_RTX
;
6136 rtx op0
= XEXP (XVECEXP (PATTERN (insn
), 0, 1), 0);
6140 (lp
&& NONJUMP_INSN_P (lp
)
6141 && recog_memoized (lp
) != CODE_FOR_doloop_begin_i
);
6142 lp
= prev_nonnote_insn (lp
))
6144 if (!lp
|| !NONJUMP_INSN_P (lp
)
6145 || dead_or_set_regno_p (lp
, LP_COUNT
))
6147 for (prev
= next
= insn
, lp
= NULL_RTX
; prev
|| next
;)
6151 if (NONJUMP_INSN_P (prev
)
6152 && recog_memoized (prev
) == CODE_FOR_doloop_begin_i
6153 && (INTVAL (XEXP (XVECEXP (PATTERN (prev
), 0, 5), 0))
6154 == INSN_UID (insn
)))
6159 else if (LABEL_P (prev
))
6161 prev
= prev_nonnote_insn (prev
);
6165 if (NONJUMP_INSN_P (next
)
6166 && recog_memoized (next
) == CODE_FOR_doloop_begin_i
6167 && (INTVAL (XEXP (XVECEXP (PATTERN (next
), 0, 5), 0))
6168 == INSN_UID (insn
)))
6173 next
= next_nonnote_insn (next
);
6178 if (lp
&& !dead_or_set_regno_p (lp
, LP_COUNT
))
6180 rtx begin_cnt
= XEXP (XVECEXP (PATTERN (lp
), 0 ,3), 0);
6181 if (INTVAL (XEXP (XVECEXP (PATTERN (lp
), 0, 4), 0)))
6182 /* The loop end insn has been duplicated. That can happen
6183 when there is a conditional block at the very end of
6186 /* If Register allocation failed to allocate to the right
6187 register, There is no point into teaching reload to
6188 fix this up with reloads, as that would cost more
6189 than using an ordinary core register with the
6190 doloop_fallback pattern. */
6191 if ((true_regnum (op0
) != LP_COUNT
|| !REG_P (begin_cnt
))
6192 /* Likewise, if the loop setup is evidently inside the loop,
6194 || (!prev
&& lp
!= next
&& !seen_label
))
6199 /* It is common that the optimizers copy the loop count from
6200 another register, and doloop_begin_i is stuck with the
6201 source of the move. Making doloop_begin_i only accept "l"
6202 is nonsentical, as this then makes reload evict the pseudo
6203 used for the loop end. The underlying cause is that the
6204 optimizers don't understand that the register allocation for
6205 doloop_begin_i should be treated as part of the loop.
6206 Try to work around this problem by verifying the previous
6208 if (true_regnum (begin_cnt
) != LP_COUNT
)
6212 for (mov
= prev_nonnote_insn (lp
); mov
;
6213 mov
= prev_nonnote_insn (mov
))
6215 if (!NONJUMP_INSN_P (mov
))
6217 else if ((set
= single_set (mov
))
6218 && rtx_equal_p (SET_SRC (set
), begin_cnt
)
6219 && rtx_equal_p (SET_DEST (set
), op0
))
6224 XEXP (XVECEXP (PATTERN (lp
), 0 ,3), 0) = op0
;
6225 note
= find_regno_note (lp
, REG_DEAD
, REGNO (begin_cnt
));
6227 remove_note (lp
, note
);
6235 XEXP (XVECEXP (PATTERN (insn
), 0, 4), 0) = num
;
6236 XEXP (XVECEXP (PATTERN (lp
), 0, 4), 0) = num
;
6238 XEXP (XVECEXP (PATTERN (lp
), 0, 6), 0) = const2_rtx
;
6240 XEXP (XVECEXP (PATTERN (lp
), 0, 6), 0) = const1_rtx
;
6241 else if (prev
!= lp
)
6244 add_insn_after (lp
, prev
, NULL
);
6248 XEXP (XVECEXP (PATTERN (lp
), 0, 7), 0)
6249 = gen_rtx_LABEL_REF (Pmode
, top_label
);
6251 = gen_rtx_INSN_LIST (REG_LABEL_OPERAND
, top_label
,
6253 LABEL_NUSES (top_label
)++;
6255 /* We can avoid tedious loop start / end setting for empty loops
6256 be merely setting the loop count to its final value. */
6257 if (next_active_insn (top_label
) == insn
)
6260 = gen_rtx_SET (VOIDmode
,
6261 XEXP (XVECEXP (PATTERN (lp
), 0, 3), 0),
6264 lc_set
= emit_insn_before (lc_set
, insn
);
6269 /* If the loop is non-empty with zero length, we can't make it
6270 a zero-overhead loop. That can happen for empty asms. */
6275 for (scan
= top_label
;
6276 (scan
&& scan
!= insn
6277 && (!NONJUMP_INSN_P (scan
) || !get_attr_length (scan
)));
6278 scan
= NEXT_INSN (scan
));
6288 /* Sometimes the loop optimizer makes a complete hash of the
6289 loop. If it were only that the loop is not entered at the
6290 top, we could fix this up by setting LP_START with SR .
6291 However, if we can't find the loop begin were it should be,
6292 chances are that it does not even dominate the loop, but is
6293 inside the loop instead. Using SR there would kill
6295 We use the doloop_fallback pattern here, which executes
6296 in two cycles on the ARC700 when predicted correctly. */
6300 rtx op3
= XEXP (XVECEXP (PATTERN (insn
), 0, 5), 0);
6302 emit_insn_before (gen_move_insn (op3
, op0
), insn
);
6304 = gen_doloop_fallback_m (op3
, JUMP_LABEL (insn
), op0
);
6307 XVEC (PATTERN (insn
), 0)
6308 = gen_rtvec (2, XVECEXP (PATTERN (insn
), 0, 0),
6309 XVECEXP (PATTERN (insn
), 0, 1));
6310 INSN_CODE (insn
) = -1;
6316 FIXME: should anticipate ccfsm action, generate special patterns for
6317 to-be-deleted branches that have no delay slot and have at least the
6318 length of the size increase forced on other insns that are conditionalized.
6319 This can also have an insn_list inside that enumerates insns which are
6320 not actually conditionalized because the destinations are dead in the
6322 Could also tag branches that we want to be unaligned if they get no delay
6323 slot, or even ones that we don't want to do delay slot sheduling for
6324 because we can unalign them.
6325 However, there are cases when conditional execution is only possible after
6326 delay slot scheduling:
6328 - If a delay slot is filled with a nocond/set insn from above, the previous
6329 basic block can become elegible for conditional execution.
6330 - If a delay slot is filled with a nocond insn from the fall-through path,
6331 the branch with that delay slot can become eligble for conditional execution
6332 (however, with the same sort of data flow analysis that dbr does, we could
6333 have figured out before that we don't need to conditionalize this insn.)
6334 - If a delay slot insn is filled with an insn from the target, the
6335 target label gets its uses decremented (even deleted if falling to zero),
6336 thus possibly creating more condexec opportunities there.
6337 Therefore, we should still be prepared to apply condexec optimization on
6338 non-prepared branches if the size increase of conditionalized insns is no
6339 more than the size saved from eliminating the branch. An invocation option
6340 could also be used to reserve a bit of extra size for condbranches so that
6341 this'll work more often (could also test in arc_reorg if the block is
6342 'close enough' to be eligible for condexec to make this likely, and
6343 estimate required size increase).
6345 /* Generate BRcc insns, by combining cmp and Bcc insns wherever possible */
6346 /* BRcc only for arcompact ISA */
6347 if (!TARGET_ARCOMPACT
|| TARGET_NO_BRCC_SET
)
6350 /* /\* Compute LOG_LINKS. *\/ */
6351 /* for (bb = 0; bb < current_nr_blocks; bb++) */
6352 /* compute_block_backward_dependences (bb); */
6356 init_insn_lengths();
6359 /* Call shorten_branches to calculate the insn lengths */
6360 shorten_branches (get_insns());
6361 cfun
->machine
->ccfsm_current_insn
= NULL_RTX
;
6363 if (!INSN_ADDRESSES_SET_P())
6364 fatal_error ("Insn addresses not set after shorten_branches");
6366 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
6369 enum attr_type insn_type
;
6371 /* If a non-jump insn (or a casesi jump table), continue */
6372 if (GET_CODE (insn
) != JUMP_INSN
||
6373 GET_CODE (PATTERN (insn
)) == ADDR_VEC
6374 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
6377 /* If we already have a brcc, note if it is suitable for brcc_s.
6378 Be a bit generous with the brcc_s range so that we can take
6379 advantage of any code shortening from delay slot scheduling. */
6380 if (recog_memoized (insn
) == CODE_FOR_cbranchsi4_scratch
)
6382 rtx pat
= PATTERN (insn
);
6383 rtx
operator = XEXP (SET_SRC (XVECEXP (pat
, 0, 0)), 0);
6384 rtx
*ccp
= &XEXP (XVECEXP (pat
, 0, 1), 0);
6386 offset
= branch_dest (insn
) - INSN_ADDRESSES (INSN_UID (insn
));
6387 if ((offset
>= -140 && offset
< 140)
6388 && rtx_equal_p (XEXP (operator, 1), const0_rtx
)
6389 && compact_register_operand (XEXP (operator, 0), VOIDmode
)
6390 && equality_comparison_operator (operator, VOIDmode
))
6391 PUT_MODE (*ccp
, CC_Zmode
);
6392 else if (GET_MODE (*ccp
) == CC_Zmode
)
6393 PUT_MODE (*ccp
, CC_ZNmode
);
6396 if ((insn_type
= get_attr_type (insn
)) == TYPE_BRCC
6397 || insn_type
== TYPE_BRCC_NO_DELAY_SLOT
)
6400 /* OK. so we have a jump insn */
6401 /* We need to check that it is a bcc */
6402 /* Bcc => set (pc) (if_then_else ) */
6403 pattern
= PATTERN (insn
);
6404 if (GET_CODE (pattern
) != SET
||
6405 GET_CODE (SET_SRC(pattern
)) != IF_THEN_ELSE
)
6408 /* Now check if the jump is beyond the s9 range */
6409 if (find_reg_note (insn
, REG_CROSSING_JUMP
, NULL_RTX
))
6411 offset
= branch_dest (insn
) - INSN_ADDRESSES (INSN_UID (insn
));
6413 if(offset
> 253 || offset
< -254)
6416 pc_target
= SET_SRC (pattern
);
6418 /* Now go back and search for the set cc insn */
6420 label
= XEXP (pc_target
, 1);
6423 rtx pat
, scan
, link_insn
= NULL
;
6425 for (scan
= PREV_INSN (insn
);
6426 scan
&& GET_CODE (scan
) != CODE_LABEL
;
6427 scan
= PREV_INSN (scan
))
6429 if (! INSN_P (scan
))
6431 pat
= PATTERN (scan
);
6432 if (GET_CODE (pat
) == SET
6433 && cc_register (SET_DEST (pat
), VOIDmode
))
6442 /* Check if this is a data dependency */
6444 rtx
operator, cc_clob_rtx
, op0
, op1
, brcc_insn
, note
;
6447 /* ok this is the set cc. copy args here */
6448 operator = XEXP (pc_target
, 0);
6450 op0
= cmp0
= XEXP (SET_SRC (pat
), 0);
6451 op1
= cmp1
= XEXP (SET_SRC (pat
), 1);
6452 if (GET_CODE (op0
) == ZERO_EXTRACT
6453 && XEXP (op0
, 1) == const1_rtx
6454 && (GET_CODE (operator) == EQ
6455 || GET_CODE (operator) == NE
))
6457 /* btst / b{eq,ne} -> bbit{0,1} */
6458 op0
= XEXP (cmp0
, 0);
6459 op1
= XEXP (cmp0
, 2);
6461 else if (!register_operand (op0
, VOIDmode
)
6462 || !general_operand (op1
, VOIDmode
))
6464 /* None of the two cmp operands should be set between the
6465 cmp and the branch */
6466 if (reg_set_between_p (op0
, link_insn
, insn
))
6469 if (reg_set_between_p (op1
, link_insn
, insn
))
6472 /* Since the MODE check does not work, check that this is
6473 CC reg's last set location before insn, and also no instruction
6474 between the cmp and branch uses the condition codes */
6475 if ((reg_set_between_p (SET_DEST (pat
), link_insn
, insn
))
6476 || (reg_used_between_p (SET_DEST (pat
), link_insn
, insn
)))
6479 /* CC reg should be dead after insn */
6480 if (!find_regno_note (insn
, REG_DEAD
, CC_REG
))
6483 operator = gen_rtx_fmt_ee (GET_CODE (operator),
6484 GET_MODE (operator), cmp0
, cmp1
);
6485 /* If we create a LIMM where there was none before,
6486 we only benefit if we can avoid a scheduling bubble
6487 for the ARC600. Otherwise, we'd only forgo chances
6488 at short insn generation, and risk out-of-range
6490 if (!brcc_nolimm_operator (operator, VOIDmode
)
6491 && !long_immediate_operand (op1
, VOIDmode
)
6493 || next_active_insn (link_insn
) != insn
))
6496 /* Emit bbit / brcc (or brcc_s if possible).
6497 CC_Zmode indicates that brcc_s is possible. */
6500 cc_clob_rtx
= gen_rtx_REG (CC_ZNmode
, CC_REG
);
6501 else if ((offset
>= -140 && offset
< 140)
6502 && rtx_equal_p (op1
, const0_rtx
)
6503 && compact_register_operand (op0
, VOIDmode
)
6504 && (GET_CODE (operator) == EQ
6505 || GET_CODE (operator) == NE
))
6506 cc_clob_rtx
= gen_rtx_REG (CC_Zmode
, CC_REG
);
6508 cc_clob_rtx
= gen_rtx_REG (CCmode
, CC_REG
);
6511 = gen_rtx_IF_THEN_ELSE (VOIDmode
, operator, label
, pc_rtx
);
6512 brcc_insn
= gen_rtx_SET (VOIDmode
, pc_rtx
, brcc_insn
);
6513 cc_clob_rtx
= gen_rtx_CLOBBER (VOIDmode
, cc_clob_rtx
);
6516 (VOIDmode
, gen_rtvec (2, brcc_insn
, cc_clob_rtx
));
6517 brcc_insn
= emit_jump_insn_before (brcc_insn
, insn
);
6519 JUMP_LABEL (brcc_insn
) = JUMP_LABEL (insn
);
6520 note
= find_reg_note (insn
, REG_BR_PROB
, 0);
6523 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6524 REG_NOTES (brcc_insn
) = note
;
6526 note
= find_reg_note (link_insn
, REG_DEAD
, op0
);
6529 remove_note (link_insn
, note
);
6530 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6531 REG_NOTES (brcc_insn
) = note
;
6533 note
= find_reg_note (link_insn
, REG_DEAD
, op1
);
6536 XEXP (note
, 1) = REG_NOTES (brcc_insn
);
6537 REG_NOTES (brcc_insn
) = note
;
6542 /* Delete the bcc insn */
6543 set_insn_deleted (insn
);
6545 /* Delete the cmp insn */
6546 set_insn_deleted (link_insn
);
6551 /* Clear out insn_addresses */
6552 INSN_ADDRESSES_FREE ();
6556 if (INSN_ADDRESSES_SET_P())
6557 fatal_error ("Insn addresses not freed\n");
6559 arc_reorg_in_progress
= 0;
6562 /* Check if the operands are valid for BRcc.d generation
6563 Valid Brcc.d patterns are
6567 For cc={GT, LE, GTU, LEU}, u6=63 can not be allowed,
6568 since they are encoded by the assembler as {GE, LT, HS, LS} 64, which
6569 does not have a delay slot
6571 Assumed precondition: Second operand is either a register or a u6 value. */
6573 valid_brcc_with_delay_p (rtx
*operands
)
6575 if (optimize_size
&& GET_MODE (operands
[4]) == CC_Zmode
)
6577 return brcc_nolimm_operator (operands
[0], VOIDmode
);
6580 /* ??? Hack. This should no really be here. See PR32143. */
6582 arc_decl_anon_ns_mem_p (const_tree decl
)
6586 if (decl
== NULL_TREE
|| decl
== error_mark_node
)
6588 if (TREE_CODE (decl
) == NAMESPACE_DECL
6589 && DECL_NAME (decl
) == NULL_TREE
)
6591 /* Classes and namespaces inside anonymous namespaces have
6592 TREE_PUBLIC == 0, so we can shortcut the search. */
6593 else if (TYPE_P (decl
))
6594 return (TREE_PUBLIC (TYPE_NAME (decl
)) == 0);
6595 else if (TREE_CODE (decl
) == NAMESPACE_DECL
)
6596 return (TREE_PUBLIC (decl
) == 0);
6598 decl
= DECL_CONTEXT (decl
);
6602 /* Implement TARGET_IN_SMALL_DATA_P. Return true if it would be safe to
6603 access DECL using %gp_rel(...)($gp). */
6606 arc_in_small_data_p (const_tree decl
)
6613 if (TREE_CODE (decl
) == STRING_CST
|| TREE_CODE (decl
) == FUNCTION_DECL
)
6617 /* We don't yet generate small-data references for -mabicalls. See related
6618 -G handling in override_options. */
6619 if (TARGET_NO_SDATA_SET
)
6622 if (TREE_CODE (decl
) == VAR_DECL
&& DECL_SECTION_NAME (decl
) != 0)
6626 /* Reject anything that isn't in a known small-data section. */
6627 name
= TREE_STRING_POINTER (DECL_SECTION_NAME (decl
));
6628 if (strcmp (name
, ".sdata") != 0 && strcmp (name
, ".sbss") != 0)
6631 /* If a symbol is defined externally, the assembler will use the
6632 usual -G rules when deciding how to implement macros. */
6633 if (!DECL_EXTERNAL (decl
))
6636 /* Only global variables go into sdata section for now */
6639 /* Don't put constants into the small data section: we want them
6640 to be in ROM rather than RAM. */
6641 if (TREE_CODE (decl
) != VAR_DECL
)
6644 if (TREE_READONLY (decl
)
6645 && !TREE_SIDE_EFFECTS (decl
)
6646 && (!DECL_INITIAL (decl
) || TREE_CONSTANT (DECL_INITIAL (decl
))))
6649 /* TREE_PUBLIC might change after the first call, because of the patch
6651 if (default_binds_local_p_1 (decl
, 1)
6652 || arc_decl_anon_ns_mem_p (decl
))
6655 /* To ensure -mvolatile-cache works
6656 ld.di does not have a gp-relative variant */
6657 if (TREE_THIS_VOLATILE (decl
))
6661 /* Disable sdata references to weak variables */
6662 if (DECL_WEAK (decl
))
6665 size
= int_size_in_bytes (TREE_TYPE (decl
));
6667 /* if (AGGREGATE_TYPE_P (TREE_TYPE (decl))) */
6670 /* Allow only <=4B long data types into sdata */
6671 return (size
> 0 && size
<= 4);
6674 /* Return true if X is a small data address that can be rewritten
6678 arc_rewrite_small_data_p (rtx x
)
6680 if (GET_CODE (x
) == CONST
)
6683 if (GET_CODE (x
) == PLUS
)
6685 if (GET_CODE (XEXP (x
, 1)) == CONST_INT
)
6689 return (GET_CODE (x
) == SYMBOL_REF
6690 && SYMBOL_REF_SMALL_P(x
));
6693 /* A for_each_rtx callback, used by arc_rewrite_small_data. */
6696 arc_rewrite_small_data_1 (rtx
*loc
, void *data ATTRIBUTE_UNUSED
)
6698 if (arc_rewrite_small_data_p (*loc
))
6702 *loc
= gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
, *loc
);
6706 if (GET_CODE (top
) == MEM
&& &XEXP (top
, 0) == loc
)
6708 else if (GET_CODE (top
) == MEM
6709 && GET_CODE (XEXP (top
, 0)) == PLUS
6710 && GET_CODE (XEXP (XEXP (top
, 0), 0)) == MULT
)
6711 *loc
= force_reg (Pmode
, *loc
);
6717 if (GET_CODE (*loc
) == PLUS
6718 && rtx_equal_p (XEXP (*loc
, 0), pic_offset_table_rtx
))
6724 /* If possible, rewrite OP so that it refers to small data using
6725 explicit relocations. */
6728 arc_rewrite_small_data (rtx op
)
6730 op
= copy_insn (op
);
6731 for_each_rtx (&op
, arc_rewrite_small_data_1
, &op
);
6735 /* A for_each_rtx callback for small_data_pattern. */
6738 small_data_pattern_1 (rtx
*loc
, void *data ATTRIBUTE_UNUSED
)
6740 if (GET_CODE (*loc
) == PLUS
6741 && rtx_equal_p (XEXP (*loc
, 0), pic_offset_table_rtx
))
6744 return arc_rewrite_small_data_p (*loc
);
6747 /* Return true if OP refers to small data symbols directly, not through
6751 small_data_pattern (rtx op
, enum machine_mode mode ATTRIBUTE_UNUSED
)
6753 return (GET_CODE (op
) != SEQUENCE
6754 && for_each_rtx (&op
, small_data_pattern_1
, 0));
6757 /* Return true if OP is an acceptable memory operand for ARCompact
6758 16-bit gp-relative load instructions.
6759 op shd look like : [r26, symref@sda]
6760 i.e. (mem (plus (reg 26) (symref with smalldata flag set))
6762 /* volatile cache option still to be handled */
6765 compact_sda_memory_operand (rtx op
,enum machine_mode mode
)
6770 /* Eliminate non-memory operations */
6771 if (GET_CODE (op
) != MEM
)
6774 if (mode
== VOIDmode
)
6775 mode
= GET_MODE (op
);
6777 size
= GET_MODE_SIZE (mode
);
6779 /* dword operations really put out 2 instructions, so eliminate them. */
6780 if (size
> UNITS_PER_WORD
)
6783 /* Decode the address now. */
6784 addr
= XEXP (op
, 0);
6786 return LEGITIMATE_SMALL_DATA_ADDRESS_P (addr
);
6790 arc_asm_output_aligned_decl_local (FILE * stream
, tree decl
, const char * name
,
6791 unsigned HOST_WIDE_INT size
,
6792 unsigned HOST_WIDE_INT align
,
6793 unsigned HOST_WIDE_INT globalize_p
)
6795 int in_small_data
= arc_in_small_data_p (decl
);
6798 switch_to_section (get_named_section (NULL
, ".sbss", 0));
6799 /* named_section (0,".sbss",0); */
6801 switch_to_section (bss_section
);
6804 (*targetm
.asm_out
.globalize_label
) (stream
, name
);
6806 ASM_OUTPUT_ALIGN (stream
, floor_log2 ((align
) / BITS_PER_UNIT
));
6807 ASM_OUTPUT_TYPE_DIRECTIVE (stream
, name
, "object");
6808 ASM_OUTPUT_SIZE_DIRECTIVE (stream
, name
, size
);
6809 ASM_OUTPUT_LABEL (stream
, name
);
6812 ASM_OUTPUT_SKIP (stream
, size
);
6848 /* SIMD builtins support */
6849 enum simd_insn_args_type
{
6872 struct builtin_description
6874 enum simd_insn_args_type args_type
;
6875 const enum insn_code icode
;
6876 const char * const name
;
6877 const enum arc_builtins code
;
6878 const enum rtx_code comparison
;
6879 const unsigned int flag
;
6882 static const struct builtin_description arc_simd_builtin_desc_list
[] =
6884 /* VVV builtins go first */
6885 #define SIMD_BUILTIN(type,code, string, builtin) \
6886 { type,CODE_FOR_##code, "__builtin_arc_" string, \
6887 ARC_SIMD_BUILTIN_##builtin, 0, 0 },
6889 SIMD_BUILTIN (Va_Vb_Vc
, vaddaw_insn
, "vaddaw", VADDAW
)
6890 SIMD_BUILTIN (Va_Vb_Vc
, vaddw_insn
, "vaddw", VADDW
)
6891 SIMD_BUILTIN (Va_Vb_Vc
, vavb_insn
, "vavb", VAVB
)
6892 SIMD_BUILTIN (Va_Vb_Vc
, vavrb_insn
, "vavrb", VAVRB
)
6893 SIMD_BUILTIN (Va_Vb_Vc
, vdifaw_insn
, "vdifaw", VDIFAW
)
6894 SIMD_BUILTIN (Va_Vb_Vc
, vdifw_insn
, "vdifw", VDIFW
)
6895 SIMD_BUILTIN (Va_Vb_Vc
, vmaxaw_insn
, "vmaxaw", VMAXAW
)
6896 SIMD_BUILTIN (Va_Vb_Vc
, vmaxw_insn
, "vmaxw", VMAXW
)
6897 SIMD_BUILTIN (Va_Vb_Vc
, vminaw_insn
, "vminaw", VMINAW
)
6898 SIMD_BUILTIN (Va_Vb_Vc
, vminw_insn
, "vminw", VMINW
)
6899 SIMD_BUILTIN (Va_Vb_Vc
, vmulaw_insn
, "vmulaw", VMULAW
)
6900 SIMD_BUILTIN (Va_Vb_Vc
, vmulfaw_insn
, "vmulfaw", VMULFAW
)
6901 SIMD_BUILTIN (Va_Vb_Vc
, vmulfw_insn
, "vmulfw", VMULFW
)
6902 SIMD_BUILTIN (Va_Vb_Vc
, vmulw_insn
, "vmulw", VMULW
)
6903 SIMD_BUILTIN (Va_Vb_Vc
, vsubaw_insn
, "vsubaw", VSUBAW
)
6904 SIMD_BUILTIN (Va_Vb_Vc
, vsubw_insn
, "vsubw", VSUBW
)
6905 SIMD_BUILTIN (Va_Vb_Vc
, vsummw_insn
, "vsummw", VSUMMW
)
6906 SIMD_BUILTIN (Va_Vb_Vc
, vand_insn
, "vand", VAND
)
6907 SIMD_BUILTIN (Va_Vb_Vc
, vandaw_insn
, "vandaw", VANDAW
)
6908 SIMD_BUILTIN (Va_Vb_Vc
, vbic_insn
, "vbic", VBIC
)
6909 SIMD_BUILTIN (Va_Vb_Vc
, vbicaw_insn
, "vbicaw", VBICAW
)
6910 SIMD_BUILTIN (Va_Vb_Vc
, vor_insn
, "vor", VOR
)
6911 SIMD_BUILTIN (Va_Vb_Vc
, vxor_insn
, "vxor", VXOR
)
6912 SIMD_BUILTIN (Va_Vb_Vc
, vxoraw_insn
, "vxoraw", VXORAW
)
6913 SIMD_BUILTIN (Va_Vb_Vc
, veqw_insn
, "veqw", VEQW
)
6914 SIMD_BUILTIN (Va_Vb_Vc
, vlew_insn
, "vlew", VLEW
)
6915 SIMD_BUILTIN (Va_Vb_Vc
, vltw_insn
, "vltw", VLTW
)
6916 SIMD_BUILTIN (Va_Vb_Vc
, vnew_insn
, "vnew", VNEW
)
6917 SIMD_BUILTIN (Va_Vb_Vc
, vmr1aw_insn
, "vmr1aw", VMR1AW
)
6918 SIMD_BUILTIN (Va_Vb_Vc
, vmr1w_insn
, "vmr1w", VMR1W
)
6919 SIMD_BUILTIN (Va_Vb_Vc
, vmr2aw_insn
, "vmr2aw", VMR2AW
)
6920 SIMD_BUILTIN (Va_Vb_Vc
, vmr2w_insn
, "vmr2w", VMR2W
)
6921 SIMD_BUILTIN (Va_Vb_Vc
, vmr3aw_insn
, "vmr3aw", VMR3AW
)
6922 SIMD_BUILTIN (Va_Vb_Vc
, vmr3w_insn
, "vmr3w", VMR3W
)
6923 SIMD_BUILTIN (Va_Vb_Vc
, vmr4aw_insn
, "vmr4aw", VMR4AW
)
6924 SIMD_BUILTIN (Va_Vb_Vc
, vmr4w_insn
, "vmr4w", VMR4W
)
6925 SIMD_BUILTIN (Va_Vb_Vc
, vmr5aw_insn
, "vmr5aw", VMR5AW
)
6926 SIMD_BUILTIN (Va_Vb_Vc
, vmr5w_insn
, "vmr5w", VMR5W
)
6927 SIMD_BUILTIN (Va_Vb_Vc
, vmr6aw_insn
, "vmr6aw", VMR6AW
)
6928 SIMD_BUILTIN (Va_Vb_Vc
, vmr6w_insn
, "vmr6w", VMR6W
)
6929 SIMD_BUILTIN (Va_Vb_Vc
, vmr7aw_insn
, "vmr7aw", VMR7AW
)
6930 SIMD_BUILTIN (Va_Vb_Vc
, vmr7w_insn
, "vmr7w", VMR7W
)
6931 SIMD_BUILTIN (Va_Vb_Vc
, vmrb_insn
, "vmrb", VMRB
)
6932 SIMD_BUILTIN (Va_Vb_Vc
, vh264f_insn
, "vh264f", VH264F
)
6933 SIMD_BUILTIN (Va_Vb_Vc
, vh264ft_insn
, "vh264ft", VH264FT
)
6934 SIMD_BUILTIN (Va_Vb_Vc
, vh264fw_insn
, "vh264fw", VH264FW
)
6935 SIMD_BUILTIN (Va_Vb_Vc
, vvc1f_insn
, "vvc1f", VVC1F
)
6936 SIMD_BUILTIN (Va_Vb_Vc
, vvc1ft_insn
, "vvc1ft", VVC1FT
)
6938 SIMD_BUILTIN (Va_Vb_rlimm
, vbaddw_insn
, "vbaddw", VBADDW
)
6939 SIMD_BUILTIN (Va_Vb_rlimm
, vbmaxw_insn
, "vbmaxw", VBMAXW
)
6940 SIMD_BUILTIN (Va_Vb_rlimm
, vbminw_insn
, "vbminw", VBMINW
)
6941 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulaw_insn
, "vbmulaw", VBMULAW
)
6942 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulfw_insn
, "vbmulfw", VBMULFW
)
6943 SIMD_BUILTIN (Va_Vb_rlimm
, vbmulw_insn
, "vbmulw", VBMULW
)
6944 SIMD_BUILTIN (Va_Vb_rlimm
, vbrsubw_insn
, "vbrsubw", VBRSUBW
)
6945 SIMD_BUILTIN (Va_Vb_rlimm
, vbsubw_insn
, "vbsubw", VBSUBW
)
6947 /* Va, Vb, Ic instructions */
6948 SIMD_BUILTIN (Va_Vb_Ic
, vasrw_insn
, "vasrw", VASRW
)
6949 SIMD_BUILTIN (Va_Vb_Ic
, vsr8_insn
, "vsr8", VSR8
)
6950 SIMD_BUILTIN (Va_Vb_Ic
, vsr8aw_insn
, "vsr8aw", VSR8AW
)
6952 /* Va, Vb, u6 instructions */
6953 SIMD_BUILTIN (Va_Vb_u6
, vasrrwi_insn
, "vasrrwi", VASRRWi
)
6954 SIMD_BUILTIN (Va_Vb_u6
, vasrsrwi_insn
, "vasrsrwi", VASRSRWi
)
6955 SIMD_BUILTIN (Va_Vb_u6
, vasrwi_insn
, "vasrwi", VASRWi
)
6956 SIMD_BUILTIN (Va_Vb_u6
, vasrpwbi_insn
, "vasrpwbi", VASRPWBi
)
6957 SIMD_BUILTIN (Va_Vb_u6
, vasrrpwbi_insn
,"vasrrpwbi", VASRRPWBi
)
6958 SIMD_BUILTIN (Va_Vb_u6
, vsr8awi_insn
, "vsr8awi", VSR8AWi
)
6959 SIMD_BUILTIN (Va_Vb_u6
, vsr8i_insn
, "vsr8i", VSR8i
)
6961 /* Va, Vb, u8 (simm) instructions */
6962 SIMD_BUILTIN (Va_Vb_u8
, vmvaw_insn
, "vmvaw", VMVAW
)
6963 SIMD_BUILTIN (Va_Vb_u8
, vmvw_insn
, "vmvw", VMVW
)
6964 SIMD_BUILTIN (Va_Vb_u8
, vmvzw_insn
, "vmvzw", VMVZW
)
6965 SIMD_BUILTIN (Va_Vb_u8
, vd6tapf_insn
, "vd6tapf", VD6TAPF
)
6967 /* Va, rlimm, u8 (simm) instructions */
6968 SIMD_BUILTIN (Va_rlimm_u8
, vmovaw_insn
, "vmovaw", VMOVAW
)
6969 SIMD_BUILTIN (Va_rlimm_u8
, vmovw_insn
, "vmovw", VMOVW
)
6970 SIMD_BUILTIN (Va_rlimm_u8
, vmovzw_insn
, "vmovzw", VMOVZW
)
6972 /* Va, Vb instructions */
6973 SIMD_BUILTIN (Va_Vb
, vabsaw_insn
, "vabsaw", VABSAW
)
6974 SIMD_BUILTIN (Va_Vb
, vabsw_insn
, "vabsw", VABSW
)
6975 SIMD_BUILTIN (Va_Vb
, vaddsuw_insn
, "vaddsuw", VADDSUW
)
6976 SIMD_BUILTIN (Va_Vb
, vsignw_insn
, "vsignw", VSIGNW
)
6977 SIMD_BUILTIN (Va_Vb
, vexch1_insn
, "vexch1", VEXCH1
)
6978 SIMD_BUILTIN (Va_Vb
, vexch2_insn
, "vexch2", VEXCH2
)
6979 SIMD_BUILTIN (Va_Vb
, vexch4_insn
, "vexch4", VEXCH4
)
6980 SIMD_BUILTIN (Va_Vb
, vupbaw_insn
, "vupbaw", VUPBAW
)
6981 SIMD_BUILTIN (Va_Vb
, vupbw_insn
, "vupbw", VUPBW
)
6982 SIMD_BUILTIN (Va_Vb
, vupsbaw_insn
, "vupsbaw", VUPSBAW
)
6983 SIMD_BUILTIN (Va_Vb
, vupsbw_insn
, "vupsbw", VUPSBW
)
6985 /* DIb, rlimm, rlimm instructions */
6986 SIMD_BUILTIN (Da_rlimm_rlimm
, vdirun_insn
, "vdirun", VDIRUN
)
6987 SIMD_BUILTIN (Da_rlimm_rlimm
, vdorun_insn
, "vdorun", VDORUN
)
6989 /* DIb, limm, rlimm instructions */
6990 SIMD_BUILTIN (Da_u3_rlimm
, vdiwr_insn
, "vdiwr", VDIWR
)
6991 SIMD_BUILTIN (Da_u3_rlimm
, vdowr_insn
, "vdowr", VDOWR
)
6993 /* rlimm instructions */
6994 SIMD_BUILTIN (void_rlimm
, vrec_insn
, "vrec", VREC
)
6995 SIMD_BUILTIN (void_rlimm
, vrun_insn
, "vrun", VRUN
)
6996 SIMD_BUILTIN (void_rlimm
, vrecrun_insn
, "vrecrun", VRECRUN
)
6997 SIMD_BUILTIN (void_rlimm
, vendrec_insn
, "vendrec", VENDREC
)
6999 /* Va, [Ib,u8] instructions */
7000 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32wh_insn
, "vld32wh", VLD32WH
)
7001 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32wl_insn
, "vld32wl", VLD32WL
)
7002 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld64_insn
, "vld64", VLD64
)
7003 SIMD_BUILTIN (Va_Vb_Ic_u8
, vld32_insn
, "vld32", VLD32
)
7005 SIMD_BUILTIN (Va_Ib_u8
, vld64w_insn
, "vld64w", VLD64W
)
7006 SIMD_BUILTIN (Va_Ib_u8
, vld128_insn
, "vld128", VLD128
)
7007 SIMD_BUILTIN (void_Va_Ib_u8
, vst128_insn
, "vst128", VST128
)
7008 SIMD_BUILTIN (void_Va_Ib_u8
, vst64_insn
, "vst64", VST64
)
7010 /* Va, [Ib, u8] instructions */
7011 SIMD_BUILTIN (void_Va_u3_Ib_u8
, vst16_n_insn
, "vst16_n", VST16_N
)
7012 SIMD_BUILTIN (void_Va_u3_Ib_u8
, vst32_n_insn
, "vst32_n", VST32_N
)
7014 SIMD_BUILTIN (void_u6
, vinti_insn
, "vinti", VINTI
)
7018 arc_init_simd_builtins (void)
7021 tree endlink
= void_list_node
;
7022 tree V8HI_type_node
= build_vector_type_for_mode (intHI_type_node
, V8HImode
);
7024 tree v8hi_ftype_v8hi_v8hi
7025 = build_function_type (V8HI_type_node
,
7026 tree_cons (NULL_TREE
, V8HI_type_node
,
7027 tree_cons (NULL_TREE
, V8HI_type_node
, endlink
)));
7028 tree v8hi_ftype_v8hi_int
7029 = build_function_type (V8HI_type_node
,
7030 tree_cons (NULL_TREE
, V8HI_type_node
,
7031 tree_cons (NULL_TREE
, integer_type_node
, endlink
)));
7033 tree v8hi_ftype_v8hi_int_int
7034 = build_function_type (V8HI_type_node
,
7035 tree_cons (NULL_TREE
, V8HI_type_node
,
7036 tree_cons (NULL_TREE
, integer_type_node
,
7037 tree_cons (NULL_TREE
, integer_type_node
, endlink
))));
7039 tree void_ftype_v8hi_int_int
7040 = build_function_type (void_type_node
,
7041 tree_cons (NULL_TREE
, V8HI_type_node
,
7042 tree_cons (NULL_TREE
, integer_type_node
,
7043 tree_cons (NULL_TREE
, integer_type_node
, endlink
))));
7045 tree void_ftype_v8hi_int_int_int
7046 = build_function_type (void_type_node
,
7047 tree_cons (NULL_TREE
, V8HI_type_node
,
7048 tree_cons (NULL_TREE
, integer_type_node
,
7049 tree_cons (NULL_TREE
, integer_type_node
,
7050 tree_cons (NULL_TREE
, integer_type_node
, endlink
)))));
7052 tree v8hi_ftype_int_int
7053 = build_function_type (V8HI_type_node
,
7054 tree_cons (NULL_TREE
, integer_type_node
,
7055 tree_cons (NULL_TREE
, integer_type_node
, endlink
)));
7057 tree void_ftype_int_int
7058 = build_function_type (void_type_node
,
7059 tree_cons (NULL_TREE
, integer_type_node
,
7060 tree_cons (NULL_TREE
, integer_type_node
, endlink
)));
7063 = build_function_type (void_type_node
,
7064 tree_cons (NULL_TREE
, integer_type_node
, endlink
));
7066 tree v8hi_ftype_v8hi
7067 = build_function_type (V8HI_type_node
, tree_cons (NULL_TREE
, V8HI_type_node
,endlink
));
7069 /* These asserts have been introduced to ensure that the order of builtins
7070 does not get messed up, else the initialization goes wrong */
7071 gcc_assert (arc_simd_builtin_desc_list
[0].args_type
== Va_Vb_Vc
);
7072 for (i
=0; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Vc
; i
++)
7073 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
, v8hi_ftype_v8hi_v8hi
, arc_simd_builtin_desc_list
[i
].code
);
7075 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_rlimm
);
7076 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_rlimm
; i
++)
7077 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
, v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
7079 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic
);
7080 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic
; i
++)
7081 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
, v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
7083 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u6
);
7084 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u6
; i
++)
7085 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
, v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
7087 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u8
);
7088 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_u8
; i
++)
7089 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
, v8hi_ftype_v8hi_int
, arc_simd_builtin_desc_list
[i
].code
);
7091 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_rlimm_u8
);
7092 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_rlimm_u8
; i
++)
7093 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
, v8hi_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
7095 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb
);
7096 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb
; i
++)
7097 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
, v8hi_ftype_v8hi
, arc_simd_builtin_desc_list
[i
].code
);
7099 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Da_rlimm_rlimm
);
7100 for (; arc_simd_builtin_desc_list
[i
].args_type
== Da_rlimm_rlimm
; i
++)
7101 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
, void_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
7103 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Da_u3_rlimm
);
7104 for (; arc_simd_builtin_desc_list
[i
].args_type
== Da_u3_rlimm
; i
++)
7105 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
, void_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
7107 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_rlimm
);
7108 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_rlimm
; i
++)
7109 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
, void_ftype_int
, arc_simd_builtin_desc_list
[i
].code
);
7111 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic_u8
);
7112 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Vb_Ic_u8
; i
++)
7113 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
, v8hi_ftype_v8hi_int_int
, arc_simd_builtin_desc_list
[i
].code
);
7115 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== Va_Ib_u8
);
7116 for (; arc_simd_builtin_desc_list
[i
].args_type
== Va_Ib_u8
; i
++)
7117 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
, v8hi_ftype_int_int
, arc_simd_builtin_desc_list
[i
].code
);
7119 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_Va_Ib_u8
);
7120 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_Va_Ib_u8
; i
++)
7121 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
, void_ftype_v8hi_int_int
, arc_simd_builtin_desc_list
[i
].code
);
7123 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_Va_u3_Ib_u8
);
7124 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_Va_u3_Ib_u8
; i
++)
7125 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
, void_ftype_v8hi_int_int_int
, arc_simd_builtin_desc_list
[i
].code
);
7127 gcc_assert (arc_simd_builtin_desc_list
[i
].args_type
== void_u6
);
7128 for (; arc_simd_builtin_desc_list
[i
].args_type
== void_u6
; i
++)
7129 def_mbuiltin (TARGET_SIMD_SET
, arc_simd_builtin_desc_list
[i
].name
, void_ftype_int
, arc_simd_builtin_desc_list
[i
].code
);
7131 gcc_assert(i
== ARRAY_SIZE (arc_simd_builtin_desc_list
));
7135 arc_expand_simd_builtin (tree exp
,
7137 rtx subtarget ATTRIBUTE_UNUSED
,
7138 enum machine_mode mode ATTRIBUTE_UNUSED
,
7139 int ignore ATTRIBUTE_UNUSED
)
7141 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
7153 int fcode
= DECL_FUNCTION_CODE (fndecl
);
7155 enum machine_mode mode0
;
7156 enum machine_mode mode1
;
7157 enum machine_mode mode2
;
7158 enum machine_mode mode3
;
7159 enum machine_mode mode4
;
7160 const struct builtin_description
* d
;
7162 for (i
= 0, d
= arc_simd_builtin_desc_list
; i
< ARRAY_SIZE (arc_simd_builtin_desc_list
); i
++, d
++)
7163 if (d
->code
== (const enum arc_builtins
) fcode
)
7166 /* We must get an enty here */
7167 gcc_assert (i
< ARRAY_SIZE (arc_simd_builtin_desc_list
));
7169 switch (d
->args_type
) {
7172 arg0
= CALL_EXPR_ARG (exp
, 0);
7173 arg1
= CALL_EXPR_ARG (exp
, 1);
7174 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, 0);
7175 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, 0);
7177 target
= gen_reg_rtx (V8HImode
);
7178 mode0
= insn_data
[icode
].operand
[1].mode
;
7179 mode1
= insn_data
[icode
].operand
[2].mode
;
7181 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
7182 op0
= copy_to_mode_reg (mode0
, op0
);
7184 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7185 op1
= copy_to_mode_reg (mode1
, op1
);
7187 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
7197 arg0
= CALL_EXPR_ARG (exp
, 0);
7198 arg1
= CALL_EXPR_ARG (exp
, 1);
7199 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, 0);
7200 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, 0);
7202 target
= gen_reg_rtx (V8HImode
);
7203 mode0
= insn_data
[icode
].operand
[1].mode
;
7204 mode1
= insn_data
[icode
].operand
[2].mode
;
7206 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
7207 op0
= copy_to_mode_reg (mode0
, op0
);
7209 if ((! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7210 || (d
->args_type
== Va_Vb_u6
&& !(UNSIGNED_INT6 (INTVAL (op1
))))
7211 || (d
->args_type
== Va_Vb_u8
&& !(UNSIGNED_INT8 (INTVAL (op1
))))
7213 error ("Operand 2 of %s instruction should be an unsigned %d-bit value.",
7215 (d
->args_type
== Va_Vb_u6
)? 6: 8);
7217 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
7226 arg0
= CALL_EXPR_ARG (exp
, 0);
7227 arg1
= CALL_EXPR_ARG (exp
, 1);
7228 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, 0);
7229 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, 0);
7231 target
= gen_reg_rtx (V8HImode
);
7232 mode0
= insn_data
[icode
].operand
[1].mode
;
7233 mode1
= insn_data
[icode
].operand
[2].mode
;
7235 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
7236 op0
= copy_to_mode_reg (mode0
, op0
);
7238 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7239 || !(UNSIGNED_INT8 (INTVAL (op1
))))
7240 error ("Operand 2 of %s instruction should be an unsigned 8-bit value.",
7243 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
7252 arg0
= CALL_EXPR_ARG (exp
, 0);
7253 arg1
= CALL_EXPR_ARG (exp
, 1);
7254 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, 0);
7255 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, 0);
7256 op2
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
);
7258 target
= gen_reg_rtx (V8HImode
);
7259 mode0
= insn_data
[icode
].operand
[1].mode
;
7260 mode1
= insn_data
[icode
].operand
[2].mode
;
7262 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
7263 op0
= copy_to_mode_reg (mode0
, op0
);
7265 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7266 || !(UNSIGNED_INT3 (INTVAL (op1
))))
7267 error ("Operand 2 of %s instruction should be an unsigned 3-bit value (I0-I7).",
7270 pat
= GEN_FCN (icode
) (target
, op0
, op1
, op2
);
7279 arg0
= CALL_EXPR_ARG (exp
, 0);
7280 arg1
= CALL_EXPR_ARG (exp
, 1);
7281 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, 0);
7282 op1
= expand_expr (arg1
, NULL_RTX
, V8HImode
, 0);
7284 target
= gen_reg_rtx (V8HImode
);
7285 mode0
= insn_data
[icode
].operand
[1].mode
;
7286 mode1
= insn_data
[icode
].operand
[2].mode
;
7288 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
7289 op0
= copy_to_mode_reg (mode0
, op0
);
7291 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7292 op1
= copy_to_mode_reg (mode1
, op1
);
7294 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
7303 arg0
= CALL_EXPR_ARG (exp
, 0);
7304 op0
= expand_expr (arg0
, NULL_RTX
, V8HImode
, 0);
7306 target
= gen_reg_rtx (V8HImode
);
7307 mode0
= insn_data
[icode
].operand
[1].mode
;
7309 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
7310 op0
= copy_to_mode_reg (mode0
, op0
);
7312 pat
= GEN_FCN (icode
) (target
, op0
);
7319 case Da_rlimm_rlimm
:
7321 arg0
= CALL_EXPR_ARG (exp
, 0);
7322 arg1
= CALL_EXPR_ARG (exp
, 1);
7323 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, 0);
7324 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, 0);
7327 if (icode
== CODE_FOR_vdirun_insn
)
7328 target
= gen_rtx_REG (SImode
, 131);
7329 else if (icode
== CODE_FOR_vdorun_insn
)
7330 target
= gen_rtx_REG (SImode
, 139);
7334 mode0
= insn_data
[icode
].operand
[1].mode
;
7335 mode1
= insn_data
[icode
].operand
[2].mode
;
7337 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
7338 op0
= copy_to_mode_reg (mode0
, op0
);
7340 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7341 op1
= copy_to_mode_reg (mode1
, op1
);
7344 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
7353 arg0
= CALL_EXPR_ARG (exp
, 0);
7354 arg1
= CALL_EXPR_ARG (exp
, 1);
7355 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, 0);
7356 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, 0);
7359 if (! (GET_CODE (op0
) == CONST_INT
)
7360 || !(UNSIGNED_INT3 (INTVAL (op0
))))
7361 error ("Operand 1 of %s instruction should be an unsigned 3-bit value (DR0-DR7).",
7364 mode1
= insn_data
[icode
].operand
[1].mode
;
7366 if (icode
== CODE_FOR_vdiwr_insn
)
7367 target
= gen_rtx_REG (SImode
, ARC_FIRST_SIMD_DMA_CONFIG_IN_REG
+ INTVAL (op0
));
7368 else if (icode
== CODE_FOR_vdowr_insn
)
7369 target
= gen_rtx_REG (SImode
, ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG
+ INTVAL (op0
));
7373 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7374 op1
= copy_to_mode_reg (mode1
, op1
);
7376 pat
= GEN_FCN (icode
) (target
, op1
);
7385 arg0
= CALL_EXPR_ARG (exp
, 0);
7389 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, 0);
7390 mode0
= insn_data
[icode
].operand
[0].mode
;
7392 /* op0 should be u6 */
7393 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
)
7394 || !(UNSIGNED_INT6 (INTVAL (op0
))))
7395 error ("Operand of %s instruction should be an unsigned 6-bit value.",
7398 pat
= GEN_FCN (icode
) (op0
);
7407 arg0
= CALL_EXPR_ARG (exp
, 0);
7411 op0
= expand_expr (arg0
, NULL_RTX
, SImode
, 0);
7412 mode0
= insn_data
[icode
].operand
[0].mode
;
7414 if (! (*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
7415 op0
= copy_to_mode_reg (mode0
, op0
);
7417 pat
= GEN_FCN (icode
) (op0
);
7428 arg0
= CALL_EXPR_ARG (exp
, 0); /* source vreg */
7429 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7430 arg2
= CALL_EXPR_ARG (exp
, 2); /* u8 */
7432 src_vreg
= expand_expr (arg0
, NULL_RTX
, V8HImode
, 0);
7433 op0
= expand_expr (arg1
, NULL_RTX
, SImode
, 0); /* [I]0-7 */
7434 op1
= expand_expr (arg2
, NULL_RTX
, SImode
, 0); /* u8 */
7435 op2
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7437 /* target <- src vreg */
7438 emit_insn (gen_move_insn (target
, src_vreg
));
7440 /* target <- vec_concat: target, mem(Ib, u8) */
7441 mode0
= insn_data
[icode
].operand
[3].mode
;
7442 mode1
= insn_data
[icode
].operand
[1].mode
;
7444 if ( (!(*insn_data
[icode
].operand
[3].predicate
) (op0
, mode0
))
7445 || !(UNSIGNED_INT3 (INTVAL (op0
))))
7446 error ("Operand 1 of %s instruction should be an unsigned 3-bit value (I0-I7).",
7449 if ( (!(*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
7450 || !(UNSIGNED_INT8 (INTVAL (op1
))))
7451 error ("Operand 2 of %s instruction should be an unsigned 8-bit value.",
7454 pat
= GEN_FCN (icode
) (target
, op1
, op2
, op0
);
7464 arg0
= CALL_EXPR_ARG (exp
, 0); /* src vreg */
7465 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7466 arg2
= CALL_EXPR_ARG (exp
, 2); /* u8 */
7468 op0
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7469 op1
= expand_expr (arg1
, NULL_RTX
, SImode
, 0); /* I[0-7] */
7470 op2
= expand_expr (arg2
, NULL_RTX
, SImode
, 0); /* u8 */
7471 op3
= expand_expr (arg0
, NULL_RTX
, V8HImode
, 0); /* Vdest */
7473 mode0
= insn_data
[icode
].operand
[0].mode
;
7474 mode1
= insn_data
[icode
].operand
[1].mode
;
7475 mode2
= insn_data
[icode
].operand
[2].mode
;
7476 mode3
= insn_data
[icode
].operand
[3].mode
;
7478 if ( (!(*insn_data
[icode
].operand
[1].predicate
) (op1
, mode1
))
7479 || !(UNSIGNED_INT3 (INTVAL (op1
))))
7480 error ("Operand 2 of %s instruction should be an unsigned 3-bit value (I0-I7).",
7483 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op2
, mode2
))
7484 || !(UNSIGNED_INT8 (INTVAL (op2
))))
7485 error ("Operand 3 of %s instruction should be an unsigned 8-bit value.",
7488 if (!(*insn_data
[icode
].operand
[3].predicate
) (op3
, mode3
))
7489 op3
= copy_to_mode_reg (mode3
, op3
);
7491 pat
= GEN_FCN (icode
) (op0
, op1
, op2
, op3
);
7500 arg0
= CALL_EXPR_ARG (exp
, 0); /* dest vreg */
7501 arg1
= CALL_EXPR_ARG (exp
, 1); /* [I]0-7 */
7503 op0
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR0 */
7504 op1
= expand_expr (arg0
, NULL_RTX
, SImode
, 0); /* I[0-7] */
7505 op2
= expand_expr (arg1
, NULL_RTX
, SImode
, 0); /* u8 */
7507 /* target <- src vreg */
7508 target
= gen_reg_rtx (V8HImode
);
7510 /* target <- vec_concat: target, mem(Ib, u8) */
7511 mode0
= insn_data
[icode
].operand
[1].mode
;
7512 mode1
= insn_data
[icode
].operand
[2].mode
;
7513 mode2
= insn_data
[icode
].operand
[3].mode
;
7515 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
7516 || !(UNSIGNED_INT3 (INTVAL (op1
))))
7517 error ("Operand 1 of %s instruction should be an unsigned 3-bit value (I0-I7).",
7520 if ( (!(*insn_data
[icode
].operand
[3].predicate
) (op2
, mode2
))
7521 || !(UNSIGNED_INT8 (INTVAL (op2
))))
7522 error ("Operand 2 of %s instruction should be an unsigned 8-bit value.",
7525 pat
= GEN_FCN (icode
) (target
, op0
, op1
, op2
);
7532 case void_Va_u3_Ib_u8
:
7534 arg0
= CALL_EXPR_ARG (exp
, 0); /* source vreg */
7535 arg1
= CALL_EXPR_ARG (exp
, 1); /* u3 */
7536 arg2
= CALL_EXPR_ARG (exp
, 2); /* [I]0-7 */
7537 arg3
= CALL_EXPR_ARG (exp
, 3); /* u8 */
7539 op0
= expand_expr (arg3
, NULL_RTX
, SImode
, 0); /* u8 */
7540 op1
= gen_rtx_REG (V8HImode
, ARC_FIRST_SIMD_VR_REG
); /* VR */
7541 op2
= expand_expr (arg2
, NULL_RTX
, SImode
, 0); /* [I]0-7 */
7542 op3
= expand_expr (arg0
, NULL_RTX
, V8HImode
, 0); /* vreg to be stored */
7543 op4
= expand_expr (arg1
, NULL_RTX
, SImode
, 0); /* vreg 0-7 subreg no. */
7545 mode0
= insn_data
[icode
].operand
[0].mode
;
7546 mode2
= insn_data
[icode
].operand
[2].mode
;
7547 mode3
= insn_data
[icode
].operand
[3].mode
;
7548 mode4
= insn_data
[icode
].operand
[4].mode
;
7550 /* correctness checks for the operands */
7551 if ( (!(*insn_data
[icode
].operand
[0].predicate
) (op0
, mode0
))
7552 || !(UNSIGNED_INT8 (INTVAL (op0
))))
7553 error ("Operand 4 of %s instruction should be an unsigned 8-bit value (0-255).",
7556 if ( (!(*insn_data
[icode
].operand
[2].predicate
) (op2
, mode2
))
7557 || !(UNSIGNED_INT3 (INTVAL (op2
))))
7558 error ("Operand 3 of %s instruction should be an unsigned 3-bit value (I0-I7).",
7561 if (!(*insn_data
[icode
].operand
[3].predicate
) (op3
, mode3
))
7562 op3
= copy_to_mode_reg (mode3
, op3
);
7564 if ( (!(*insn_data
[icode
].operand
[4].predicate
) (op4
, mode4
))
7565 || !(UNSIGNED_INT3 (INTVAL (op4
))))
7566 error ("Operand 2 of %s instruction should be an unsigned 3-bit value (subreg 0-7).",
7568 else if (icode
== CODE_FOR_vst32_n_insn
7569 && ((INTVAL(op4
) % 2 ) != 0))
7570 error ("Operand 2 of %s instruction should be an even 3-bit value (subreg 0,2,4,6).",
7573 pat
= GEN_FCN (icode
) (op0
, op1
, op2
, op3
, op4
);
7587 arc_secondary_reload (bool in_p
, rtx x
, enum reg_class
class,
7588 enum machine_mode mode ATTRIBUTE_UNUSED
,
7589 secondary_reload_info
*sri ATTRIBUTE_UNUSED
)
7591 /* We can't load/store the D-registers directly */
7592 if (class == DOUBLE_REGS
&& (GET_CODE (x
) == MEM
))
7593 return GENERAL_REGS
;
7594 /* The loop counter register can be stored, but not loaded directly. */
7595 if ((class == LPCOUNT_REG
|| class == WRITABLE_CORE_REGS
)
7596 && in_p
&& GET_CODE (x
) == MEM
)
7597 return GENERAL_REGS
;
7602 arc_preserve_reload_p (rtx in
)
7604 return (GET_CODE (in
) == PLUS
7605 && RTX_OK_FOR_BASE_P (XEXP (in
, 0))
7606 && CONST_INT_P (XEXP (in
, 1))
7607 && !((INTVAL (XEXP (in
, 1)) & 511)));
7611 arc_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED
,
7612 enum reg_class from_class
,
7613 enum reg_class to_class
)
7615 /* The ARC600 has no bypass for extension registers, hence a nop might be
7616 needed to be inserted after a write so that reads are safe. */
7618 && (to_class
== LPCOUNT_REG
|| to_class
== WRITABLE_CORE_REGS
))
7620 /* The ARC700 stalls for 3 cycles when *reading* from lp_count. */
7622 && (from_class
== LPCOUNT_REG
|| from_class
== ALL_CORE_REGS
7623 || from_class
== WRITABLE_CORE_REGS
))
7629 /* Emit code and return a template suitable for outputting an addsi
7630 instruction with OPERANDS and the conditional execution specifier
7631 COND. If COND is zero, don't output anything, just return an
7632 empty string for instructions with 32 bit opcode, and a non-empty one
7633 for insns with a 16 bit opcode. */
7635 arc_output_addsi (rtx
*operands
, const char *cond
)
7639 int cond_p
= cond
? *cond
: 0;
7640 int match
= operands_match_p (operands
[0], operands
[1]);
7641 int match2
= operands_match_p (operands
[0], operands
[2]);
7642 int intval
= (REG_P (operands
[2]) ? 1
7643 : CONST_INT_P (operands
[2]) ? INTVAL (operands
[2]) : 0xbadc057);
7644 int neg_intval
= -intval
;
7648 /* First try to emit a 16 bit insn. */
7651 int short_0
= satisfies_constraint_Rcq (operands
[0]);
7653 short_p
= (!cond_p
&& short_0
&& satisfies_constraint_Rcq (operands
[1]));
7655 && (REG_P (operands
[2])
7656 ? (match
|| satisfies_constraint_Rcq (operands
[2]))
7657 : (unsigned) intval
<= (match
? 127 : 7)))
7658 return "add%? %0,%1,%2%&";
7659 if (!cond_p
&& short_0
&& satisfies_constraint_Rcq (operands
[2])
7660 && REG_P (operands
[1]) && match2
)
7661 return "add%? %0,%2,%1%&";
7662 if (!cond_p
&& (short_0
|| REGNO (operands
[0]) == STACK_POINTER_REGNUM
)
7663 && REGNO (operands
[1]) == STACK_POINTER_REGNUM
&& !(intval
& ~124))
7664 return "add%? %0,%1,%2%&";
7666 if ((short_p
&& (unsigned) neg_intval
<= (match
? 31 : 7))
7667 || (!cond_p
&& REGNO (operands
[0]) == STACK_POINTER_REGNUM
7668 && match
&& !(neg_intval
& ~124)))
7669 return "sub%? %0,%1,%n2%&";
7672 #define ADDSI_OUTPUT(LIST) do {\
7674 sprintf LIST, output_asm_insn (format, operands);\
7677 #define ADDSI_OUTPUT1(FORMAT) ADDSI_OUTPUT ((format, FORMAT, cond))
7679 /* Now try to emit a 32 bit insn without long immediate. */
7680 if (!match
&& match2
&& REG_P (operands
[1]))
7681 ADDSI_OUTPUT1 ("add%s %%0,%%2,%%1");
7682 if (match
|| !cond_p
)
7684 int limit
= (match
&& !cond_p
) ? 0x7ff : 0x3f;
7685 int range_factor
= neg_intval
& intval
;
7687 if (intval
== -1 << 31)
7688 ADDSI_OUTPUT1 ("bxor%s %%0,%%1,31");
7690 /* If we can use a straight add / sub instead of a {add,sub}[123] of
7691 same size, do, so - the insn latency is lower. */
7692 /* -0x800 is a 12-bit constant for add /add3 / sub / sub3, but
7694 if ((intval
>= 0 && intval
<= limit
)
7695 || (intval
== -0x800 && limit
== 0x7ff))
7696 ADDSI_OUTPUT1 ("add%s %%0,%%1,%%2");
7697 else if ((intval
< 0 && neg_intval
<= limit
)
7698 || (intval
== 0x800 && limit
== 0x7ff))
7699 ADDSI_OUTPUT1 ("sub%s %%0,%%1,%%n2");
7700 shift
= range_factor
>= 8 ? 3 : (range_factor
>> 1 & 3);
7701 if (((intval
< 0 && intval
!= -0x4000)
7702 /* sub[123] is slower than add_s / sub, only use it if it
7703 avoids a long immediate. */
7704 && neg_intval
<= limit
<< shift
)
7705 || (intval
== 0x4000 && limit
== 0x7ff))
7706 ADDSI_OUTPUT ((format
, "sub%d%s %%0,%%1,%d",
7707 shift
, cond
, neg_intval
>> shift
));
7708 else if ((intval
>= 0 && intval
<= limit
<< shift
)
7709 || (intval
== -0x4000 && limit
== 0x7ff))
7710 ADDSI_OUTPUT ((format
, "add%d%s %%0,%%1,%d", shift
, cond
,
7713 /* Try to emit a 16 bit opcode with long immediate. */
7714 if (short_p
&& match
)
7715 return "add%? %0,%1,%S2%&";
7717 /* We have to use a 32 bit opcode, possibly with a long immediate.
7718 (We also get here for add a,b,u6) */
7719 ADDSI_OUTPUT ((format
,
7720 intval
< 0 ? "sub%s %%0,%%1,%%n2" : "add%s %%0,%%1,%%S2",
7725 force_offsettable (rtx addr
, HOST_WIDE_INT size
, int reuse
)
7728 rtx offs
= const0_rtx
;
7730 if (GET_CODE (base
) == PLUS
)
7732 offs
= XEXP (base
, 1);
7733 base
= XEXP (base
, 0);
7736 || (REGNO (base
) != STACK_POINTER_REGNUM
7737 && REGNO_PTR_FRAME_P (REGNO (addr
)))
7738 || !CONST_INT_P (offs
) || !SMALL_INT (INTVAL (offs
))
7739 || !SMALL_INT (INTVAL (offs
) + size
))
7742 emit_insn (gen_add2_insn (addr
, offs
));
7744 addr
= copy_to_mode_reg (Pmode
, addr
);
7749 /* Like move_by_pieces, but take account of load latency,
7750 and actual offset ranges.
7751 Return nonzero on success. */
7753 arc_expand_movmem (rtx
*operands
)
7755 rtx dst
= operands
[0];
7756 rtx src
= operands
[1];
7757 rtx dst_addr
, src_addr
;
7759 int align
= INTVAL (operands
[3]);
7766 if (!CONST_INT_P (operands
[2]))
7768 size
= INTVAL (operands
[2]);
7769 /* move_by_pieces_ninsns is static, so we can't use it. */
7771 n_pieces
= (size
+ 2) / 4U + (size
& 1);
7772 else if (align
== 2)
7773 n_pieces
= (size
+ 1) / 2U;
7776 if (n_pieces
>= (unsigned int) (optimize_size
? 3 : 15))
7780 dst_addr
= force_offsettable (XEXP (operands
[0], 0), size
, 0);
7781 src_addr
= force_offsettable (XEXP (operands
[1], 0), size
, 0);
7782 store
[0] = store
[1] = NULL_RTX
;
7783 tmpx
[0] = tmpx
[1] = NULL_RTX
;
7784 for (i
= 0; size
> 0; i
^= 1, size
-= piece
)
7787 enum machine_mode mode
;
7790 piece
= size
& -size
;
7791 mode
= smallest_mode_for_size (piece
* BITS_PER_UNIT
, MODE_INT
);
7792 /* If we don't re-use temporaries, the scheduler gets carried away,
7793 and the register pressure gets unnecessarily high. */
7794 if (0 && tmpx
[i
] && GET_MODE (tmpx
[i
]) == mode
)
7797 tmpx
[i
] = tmp
= gen_reg_rtx (mode
);
7798 dst_addr
= force_offsettable (dst_addr
, piece
, 1);
7799 src_addr
= force_offsettable (src_addr
, piece
, 1);
7801 emit_insn (store
[i
]);
7802 emit_move_insn (tmp
, change_address (src
, mode
, src_addr
));
7803 store
[i
] = gen_move_insn (change_address (dst
, mode
, dst_addr
), tmp
);
7804 dst_addr
= plus_constant (dst_addr
, piece
);
7805 src_addr
= plus_constant (src_addr
, piece
);
7808 emit_insn (store
[i
]);
7810 emit_insn (store
[i
^1]);
7814 /* Prepare operands for move in MODE. Return nonzero iff the move has
7817 prepare_move_operands (rtx
*operands
, enum machine_mode mode
)
7819 /* We used to do this only for MODE_INT Modes, but addresses to floating
7820 point variables may well be in the small data section. */
7823 if (!TARGET_NO_SDATA_SET
&& small_data_pattern (operands
[0], Pmode
))
7824 operands
[0] = arc_rewrite_small_data (operands
[0]);
7825 else if (mode
== SImode
&& flag_pic
&& SYMBOLIC_CONST (operands
[1]))
7827 emit_pic_move (operands
, SImode
);
7829 /* Disable any REG_EQUALs associated with the symref
7830 otherwise the optimization pass undoes the work done
7831 here and references the variable directly. */
7833 else if (GET_CODE (operands
[0]) != MEM
7834 && !TARGET_NO_SDATA_SET
7835 && small_data_pattern (operands
[1], Pmode
))
7837 /* This is to take care of address calculations involving sdata
7839 operands
[1] = arc_rewrite_small_data (operands
[1]);
7841 emit_insn (gen_rtx_SET (mode
, operands
[0],operands
[1]));
7842 /* ??? This note is useless, since it only restates the set itself.
7843 We should rather use the original SYMBOL_REF. However, there is
7844 the problem that we are lying to the compiler about these
7845 SYMBOL_REFs to start with. symbol@sda should be encoded specially
7846 so that we can tell it apart from an actual symbol. */
7847 set_unique_reg_note (get_last_insn (), REG_EQUAL
, operands
[1]);
7849 /* Take care of the REG_EQUAL note that will be attached to mark the
7850 output reg equal to the initial symbol_ref after this code is
7852 emit_move_insn (operands
[0], operands
[0]);
7857 if (MEM_P (operands
[0])
7858 && !(reload_in_progress
|| reload_completed
))
7860 operands
[1] = force_reg (mode
, operands
[1]);
7861 if (!move_dest_operand (operands
[0], mode
))
7863 rtx addr
= copy_to_mode_reg (Pmode
, XEXP (operands
[0], 0));
7864 /* This is like change_address_1 (operands[0], mode, 0, 1) ,
7865 except that we can't use that function because it is static. */
7866 rtx
new = change_address (operands
[0], mode
, addr
);
7867 MEM_COPY_ATTRIBUTES (new, operands
[0]);
7870 if (!cse_not_expected
)
7872 rtx
new = XEXP (operands
[0], 0);
7874 new = arc_legitimize_address (new, new, mode
);
7877 new = change_address (operands
[0], mode
, new);
7878 MEM_COPY_ATTRIBUTES (new, operands
[0]);
7883 if (MEM_P (operands
[1]) && !cse_not_expected
)
7885 rtx
new = XEXP (operands
[1], 0);
7887 new = arc_legitimize_address (new, new, mode
);
7890 new = change_address (operands
[1], mode
, new);
7891 MEM_COPY_ATTRIBUTES (new, operands
[1]);
7898 /* Prepare OPERANDS for an extension using CODE to OMODE.
7899 Return nonzero iff the move has been emitted. */
7901 prepare_extend_operands (rtx
*operands
, enum rtx_code code
,
7902 enum machine_mode omode
)
7904 if (!TARGET_NO_SDATA_SET
&& small_data_pattern (operands
[1], Pmode
))
7906 /* This is to take care of address calculations involving sdata
7909 = gen_rtx_fmt_e (code
, omode
, arc_rewrite_small_data (operands
[1]));
7910 emit_insn (gen_rtx_SET (omode
, operands
[0], operands
[1]));
7911 set_unique_reg_note (get_last_insn (), REG_EQUAL
, operands
[1]);
7913 /* Take care of the REG_EQUAL note that will be attached to mark the
7914 output reg equal to the initial extension after this code is
7916 emit_move_insn (operands
[0], operands
[0]);
7922 /* Output a library call to a function called FNAME that has been arranged
7923 to be local to be any dso. */
7925 arc_output_libcall (const char *fname
)
7927 unsigned len
= strlen (fname
);
7928 static char buf
[64];
7930 gcc_assert (len
< sizeof buf
- 35);
7931 if (TARGET_LONG_CALLS_SET
7932 || (TARGET_MEDIUM_CALLS
&& arc_ccfsm_cond_exec_p ()))
7935 sprintf (buf
, "add r12,pcl,@%s-(.&2)\n\tjl%%!%%* [r12]", fname
);
7937 sprintf (buf
, "jl%%! @%s", fname
);
7940 sprintf (buf
, "bl%%!%%* @%s", fname
);
7945 disi_highpart (rtx in
)
7947 return simplify_gen_subreg (SImode
, in
, DImode
, TARGET_BIG_ENDIAN
? 0 : 4);
7950 /* Called by arc600_corereg_hazard via for_each_rtx.
7951 If a hazard is found, return a conservative estimate of the required
7952 length adjustment to accomodate a nop. */
7954 arc600_corereg_hazard_1 (rtx
*xp
, void *data
)
7958 rtx pat
= (rtx
) data
;
7960 switch (GET_CODE (x
))
7962 case SET
: case POST_INC
: case POST_DEC
: case PRE_INC
: case PRE_DEC
:
7965 /* This is also fine for PRE/POST_MODIFY, because they contain a SET. */
7969 /* Check if this sets a an extension register. N.B. we use 61 for the
7970 condition codes, which is definitely not an extension register. */
7971 if (REG_P (dest
) && REGNO (dest
) >= 32 && REGNO (dest
) < 61
7972 /* Check if the same register is used by the PAT. */
7973 && (refers_to_regno_p
7975 REGNO (dest
) + (GET_MODE_SIZE (GET_MODE (dest
)) + 3) / 4U, pat
, 0)))
7981 /* return length adjustment for INSN.
7983 A write to a core reg greater or equal to 32 must not be immediately
7984 followed by a use. Anticipate the length requirement to insert a nop
7985 between PRED and SUCC to prevent a hazard. */
7987 arc600_corereg_hazard (rtx pred
, rtx succ
)
7991 /* If SUCC is a doloop_end_i with a preceding label, we must output a nop
7992 in front of SUCC anyway, so there will be separation between PRED and
7994 if (recog_memoized (succ
) == CODE_FOR_doloop_end_i
7995 && LABEL_P (prev_nonnote_insn (succ
)))
7997 if (recog_memoized (succ
) == CODE_FOR_doloop_begin_i
)
7999 if (GET_CODE (PATTERN (pred
)) == SEQUENCE
)
8000 pred
= XVECEXP (PATTERN (pred
), 0, 1);
8001 if (GET_CODE (PATTERN (succ
)) == SEQUENCE
)
8002 succ
= XVECEXP (PATTERN (succ
), 0, 0);
8003 if (recog_memoized (pred
) == CODE_FOR_mulsi_600
8004 || recog_memoized (pred
) == CODE_FOR_umul_600
8005 || recog_memoized (pred
) == CODE_FOR_mac_600
8006 || recog_memoized (pred
) == CODE_FOR_mul64_600
8007 || recog_memoized (pred
) == CODE_FOR_mac64_600
8008 || recog_memoized (pred
) == CODE_FOR_umul64_600
8009 || recog_memoized (pred
) == CODE_FOR_umac64_600
)
8011 return for_each_rtx (&PATTERN (pred
), arc600_corereg_hazard_1
,
8016 A write to a core reg greater or equal to 32 must not be immediately
8017 followed by a use. Anticipate the length requirement to insert a nop
8018 between PRED and SUCC to prevent a hazard. */
8020 arc_hazard (rtx pred
, rtx succ
)
8024 if (!pred
|| !INSN_P (pred
) || !succ
|| !INSN_P (succ
))
8026 if (recog_memoized (succ
) == CODE_FOR_doloop_end_i
8027 && (JUMP_P (pred
) || GET_CODE (PATTERN (pred
)) == SEQUENCE
))
8029 return arc600_corereg_hazard (pred
, succ
);
8032 /* Return length adjustment for INSN. */
8034 arc_adjust_insn_length (rtx insn
, int len
)
8040 if (GET_CODE (PATTERN (insn
)) == SEQUENCE
)
8042 int adj0
, adj1
, len1
;
8043 rtx pat
= PATTERN (insn
);
8044 rtx i0
= XVECEXP (pat
, 0, 0);
8045 rtx i1
= XVECEXP (pat
, 0, 1);
8047 len1
= get_attr_lock_length (i1
);
8048 gcc_assert (!len
|| len
>= 4 || (len
== 2 && get_attr_iscompact (i1
)));
8050 len1
= get_attr_iscompact (i1
) != ISCOMPACT_FALSE
? 2 : 4;
8051 adj0
= arc_adjust_insn_length (i0
, len
- len1
);
8052 adj1
= arc_adjust_insn_length (i1
, len1
);
8055 if (recog_memoized (insn
) == CODE_FOR_doloop_end_i
)
8057 rtx prev
= prev_nonnote_insn (insn
);
8059 return ((LABEL_P (prev
)
8061 && (JUMP_P (prev
) || GET_CODE (PATTERN (prev
)) == SEQUENCE
)))
8065 /* Check for return with but one preceding insn since function
8067 if (TARGET_PAD_RETURN
8069 && GET_CODE (PATTERN (insn
)) != ADDR_VEC
8070 && GET_CODE (PATTERN (insn
)) != ADDR_DIFF_VEC
8071 && get_attr_type (insn
) == TYPE_RETURN
)
8073 rtx prev
= prev_active_insn (insn
);
8075 if (!prev
|| !(prev
= prev_active_insn (prev
))
8076 || ((NONJUMP_INSN_P (prev
)
8077 && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
8078 ? CALL_ATTR (XVECEXP (PATTERN (prev
), 0, 0), NON_SIBCALL
)
8079 : CALL_ATTR (prev
, NON_SIBCALL
)))
8082 /* Rtl changes too much before arc_reorg to keep ccfsm state.
8083 But we are not required to give exact answers then. */
8084 if (cfun
->machine
->arc_reorg_started
8085 && (JUMP_P (insn
) || (len
& 2)))
8087 struct arc_ccfsm
*statep
= &cfun
->machine
->ccfsm_current
;
8089 arc_ccfsm_advance_to (insn
);
8090 switch (statep
->state
)
8095 /* Deleted branch. */
8097 case 3: case 4: case 5:
8098 /* Conditionalized insn. */
8100 || (get_attr_type (insn
) != TYPE_BRANCH
8101 && get_attr_type (insn
) != TYPE_UNCOND_BRANCH
8102 && (get_attr_type (insn
) != TYPE_RETURN
8103 || (statep
->cc
!= ARC_CC_EQ
&& statep
->cc
!= ARC_CC_NE
)
8104 || NEXT_INSN (PREV_INSN (insn
)) != insn
)))
8112 /* Restore extracted operands - otherwise splitters like the addsi3_mixed one
8114 extract_constrain_insn_cached (insn
);
8118 rtx succ
= next_real_insn (insn
);
8120 if (!succ
|| !INSN_P (succ
))
8122 return adj
+ arc600_corereg_hazard (insn
, succ
);
8126 /* For ARC600: If a write to a core reg >=32 appears in a delay slot
8127 (other than of a forward brcc), it creates a hazard when there is a read
8128 of the same register at the branch target. We can't know what is at the
8129 branch target of calls, and for branches, we don't really know before the
8130 end of delay slot scheduling, either. Not only can individual instruction
8131 be hoisted out into a delay slot, a basic block can also be emptied this
8132 way, and branch and/or fall through targets be redirected. Hence we don't
8133 want such writes in a delay slot. */
8134 /* Called by arc_write_ext_corereg via for_each_rtx. */
8136 write_ext_corereg_1 (rtx
*xp
, void *data ATTRIBUTE_UNUSED
)
8141 switch (GET_CODE (x
))
8143 case SET
: case POST_INC
: case POST_DEC
: case PRE_INC
: case PRE_DEC
:
8146 /* This is also fine for PRE/POST_MODIFY, because they contain a SET. */
8150 if (REG_P (dest
) && REGNO (dest
) >= 32 && REGNO (dest
) < 61)
8155 /* Return nonzreo iff INSN writes to an extension core register. */
8157 arc_write_ext_corereg (rtx insn
)
8159 return for_each_rtx (&PATTERN (insn
), write_ext_corereg_1
, 0);
8163 arc_legitimize_address (rtx x
, rtx oldx ATTRIBUTE_UNUSED
,
8164 int /* enum machine_mode */ mode
)
8168 if (flag_pic
&& SYMBOLIC_CONST (x
))
8169 (x
) = arc_legitimize_pic_address (x
, 0);
8171 if (GET_CODE (addr
) == CONST
)
8172 addr
= XEXP (addr
, 0);
8173 if (GET_CODE (addr
) == PLUS
8174 && CONST_INT_P (XEXP (addr
, 1))
8175 && ((GET_CODE (XEXP (addr
, 0)) == SYMBOL_REF
8176 && !SYMBOL_REF_FUNCTION_P (XEXP (addr
, 0)))
8177 || (REG_P (XEXP (addr
, 0))
8178 && (INTVAL (XEXP (addr
, 1)) & 252))))
8180 HOST_WIDE_INT offs
, upper
;
8181 int size
= GET_MODE_SIZE (mode
);
8183 offs
= INTVAL (XEXP (addr
, 1));
8184 upper
= (offs
+ 256 * size
) & ~511 * size
;
8185 inner
= plus_constant (XEXP (addr
, 0), upper
);
8186 #if 0 /* ??? this produces worse code for EEMBC idctrn01 */
8187 if (GET_CODE (x
) == CONST
)
8188 inner
= gen_rtx_CONST (Pmode
, inner
);
8190 addr
= plus_constant (force_reg (Pmode
, inner
), offs
- upper
);
8193 else if (GET_CODE (addr
) == SYMBOL_REF
&& !SYMBOL_REF_FUNCTION_P (addr
))
8194 x
= force_reg (Pmode
, x
);
8195 if (memory_address_p (mode
, x
))
8201 arc_delegitimize_address (rtx x
)
8203 if (GET_CODE (x
) == MEM
&& GET_CODE (XEXP (x
, 0)) == CONST
8204 && GET_CODE (XEXP (XEXP (x
, 0), 0)) == UNSPEC
8205 && XINT (XEXP (XEXP (x
, 0), 0), 1) == ARC_UNSPEC_GOT
)
8206 return XVECEXP (XEXP (XEXP (x
, 0), 0), 0, 0);
8213 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 56: 57);
8219 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 57: 56);
8225 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 59: 58);
8231 return gen_rtx_REG (SImode
, TARGET_BIG_ENDIAN
? 58: 59);
8234 /* Return nonzero iff BRANCH should be unaligned if possible by upsizing
8235 a previous instruction. */
8237 arc_unalign_branch_p (rtx branch
)
8241 if (!TARGET_UNALIGN_BRANCH
)
8243 /* Do not do this if we have a filled delay slot. */
8244 if (get_attr_delay_slot_filled (branch
) == DELAY_SLOT_FILLED_YES
8245 && !INSN_DELETED_P (NEXT_INSN (branch
)))
8247 note
= find_reg_note (branch
, REG_BR_PROB
, 0);
8249 || (arc_unalign_prob_threshold
&& !br_prob_note_reliable_p (note
))
8250 || INTVAL (XEXP (note
, 0)) < arc_unalign_prob_threshold
);
8253 /* When estimating sizes during arc_reorg, when optimizing for speed, there
8254 are three reasons why we need to consider branches to be length 6:
8255 - annull-false delay slot insns are implemented using conditional execution,
8256 thus preventing short insn formation where used.
8257 - for ARC600: annul-true delay slot insns are implemented where possible
8258 using conditional execution, preventing short insn formation where used.
8259 - for ARC700: likely or somewhat likely taken branches are made long and
8260 unaligned if possible to avoid branch penalty. */
8262 arc_branch_size_unknown_p (void)
8264 return !optimize_size
&& arc_reorg_in_progress
;
8267 /* We are about to output a return insn. Add padding if necessary to avoid
8268 a mispredict. A return could happen immediately after the function
8269 start, but after a call we know that there will be at least a blink
8272 arc_pad_return (void)
8274 rtx insn
= current_output_insn
;
8275 rtx prev
= prev_active_insn (insn
);
8280 fputs ("\tnop_s\n", asm_out_file
);
8281 cfun
->machine
->unalign
^= 2;
8284 /* If PREV is a sequence, we know it must be a branch / jump or a tailcall,
8285 because after a call, we'd have to restore blink first. */
8286 else if (GET_CODE (PATTERN (prev
)) == SEQUENCE
)
8290 want_long
= (get_attr_length (prev
) == 2);
8291 prev
= prev_active_insn (prev
);
8294 || ((NONJUMP_INSN_P (prev
) && GET_CODE (PATTERN (prev
)) == SEQUENCE
)
8295 ? CALL_ATTR (XVECEXP (PATTERN (prev
), 0, 0), NON_SIBCALL
)
8296 : CALL_ATTR (prev
, NON_SIBCALL
)))
8299 cfun
->machine
->size_reason
8300 = "call/return and return/return must be 6 bytes apart to avoid mispredict";
8301 else if (TARGET_UNALIGN_BRANCH
&& cfun
->machine
->unalign
)
8303 cfun
->machine
->size_reason
8304 = "Long unaligned jump avoids non-delay slot penalty";
8307 /* Disgorge delay insn, if there is any. */
8310 prev
= XVECEXP (final_sequence
, 0, 1);
8311 gcc_assert (!prev_real_insn (insn
)
8312 || !arc_hazard (prev_real_insn (insn
), prev
));
8313 cfun
->machine
->force_short_suffix
= !want_long
;
8314 final_scan_insn (prev
, asm_out_file
, optimize
, 1, NULL
);
8315 cfun
->machine
->force_short_suffix
= -1;
8316 INSN_DELETED_P (prev
) = 1;
8317 current_output_insn
= insn
;
8320 fputs ("\tnop\n", asm_out_file
);
8323 fputs ("\tnop_s\n", asm_out_file
);
8324 cfun
->machine
->unalign
^= 2;
8330 /* The usual; we set up our machine_function data. */
8331 static struct machine_function
*
8332 arc_init_machine_status (void)
8334 struct machine_function
*machine
;
8336 (machine_function
*) ggc_alloc_cleared (sizeof (machine_function
));
8337 machine
->fn_type
= ARC_FUNCTION_UNKNOWN
;
8338 machine
->force_short_suffix
= -1;
8343 /* Implements INIT_EXPANDERS. We just set up to call the above
8346 arc_init_expanders (void)
8348 init_machine_status
= arc_init_machine_status
;
8351 /* Check if OP is a proper parallel of a millicode call pattern. OFFSET
8352 indicates a number of elements to ignore - that allows to have a
8353 sibcall pattern that starts with (return). LOAD_P is zero for store
8354 multiple (for prologues), and one for load multiples (for epilogues),
8355 and two for load multiples where no final clobber of blink is required.
8356 We also skip the first load / store element since this is supposed to
8357 be checked in the instruction pattern. */
8359 arc_check_millicode (rtx op
, int offset
, int load_p
)
8361 int len
= XVECLEN (op
, 0) - offset
;
8366 if (len
< 2 || len
> 13)
8372 rtx elt
= XVECEXP (op
, 0, --len
);
8374 if (GET_CODE (elt
) != CLOBBER
8375 || !REG_P (XEXP (elt
, 0))
8376 || REGNO (XEXP (elt
, 0)) != RETURN_ADDR_REGNUM
8377 || len
< 3 || len
> 13)
8380 for (i
= 1; i
< len
; i
++)
8382 rtx elt
= XVECEXP (op
, 0, i
+ offset
);
8385 if (GET_CODE (elt
) != SET
)
8387 mem
= XEXP (elt
, load_p
);
8388 reg
= XEXP (elt
, 1-load_p
);
8389 if (!REG_P (reg
) || REGNO (reg
) != 13+i
|| !MEM_P (mem
))
8391 addr
= XEXP (mem
, 0);
8392 if (GET_CODE (addr
) != PLUS
8393 || !rtx_equal_p (stack_pointer_rtx
, XEXP (addr
, 0))
8394 || !CONST_INT_P (XEXP (addr
, 1)) || INTVAL (XEXP (addr
, 1)) != i
*4)
8401 arc_get_unalign (void)
8403 return cfun
->machine
->unalign
;
8407 arc_clear_unalign (void)
8410 cfun
->machine
->unalign
= 0;
8414 arc_toggle_unalign (void)
8416 cfun
->machine
->unalign
^= 2;
8419 /* Operands 0..2 are the operands of a addsi which uses a 12 bit
8420 constant in operand 2, but which would require a LIMM because of
8422 operands 3 and 4 are new SET_SRCs for operands 0. */
8424 split_addsi (rtx
*operands
)
8426 int val
= INTVAL (operands
[2]);
8428 /* Try for two short insns first. Lengths being equal, we prefer
8429 expansions with shorter register lifetimes. */
8430 if (val
> 127 && val
<= 255
8431 && satisfies_constraint_Rcq (operands
[0]))
8433 operands
[3] = operands
[2];
8434 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[1]);
8438 operands
[3] = operands
[1];
8439 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[2]);
8443 /* Operands 0..2 are the operands of a subsi which uses a 12 bit
8444 constant in operand 1, but which would require a LIMM because of
8446 operands 3 and 4 are new SET_SRCs for operands 0. */
8448 split_subsi (rtx
*operands
)
8450 int val
= INTVAL (operands
[1]);
8452 /* Try for two short insns first. Lengths being equal, we prefer
8453 expansions with shorter register lifetimes. */
8454 if (satisfies_constraint_Rcq (operands
[0])
8455 && satisfies_constraint_Rcq (operands
[2]))
8457 if (val
>= -31 && val
<= 127)
8459 operands
[3] = gen_rtx_NEG (SImode
, operands
[2]);
8460 operands
[4] = gen_rtx_PLUS (SImode
, operands
[0], operands
[1]);
8463 else if (val
>= 0 && val
< 255)
8465 operands
[3] = operands
[1];
8466 operands
[4] = gen_rtx_MINUS (SImode
, operands
[0], operands
[2]);
8470 /* If the destination is not an ARCompact16 register, we might
8471 still have a chance to make a short insn if the source is;
8472 we need to start with a reg-reg move for this. */
8473 operands
[3] = operands
[2];
8474 operands
[4] = gen_rtx_MINUS (SImode
, operands
[1], operands
[0]);
8477 /* operands 0..1 are the operands of a 64 bit move instruction.
8478 split it into two moves with operands 2/3 and 4/5. */
8480 arc_split_move (rtx
*operands
)
8482 enum machine_mode mode
= GET_MODE (operands
[0]);
8487 for (i
= 0; i
< 2; i
++)
8489 if (MEM_P (operands
[i
]) && auto_inc_p (XEXP (operands
[i
], 0)))
8491 rtx addr
= XEXP (operands
[i
], 0);
8495 gcc_assert (!reg_overlap_mentioned_p (operands
[0], addr
));
8496 switch (GET_CODE (addr
))
8498 case PRE_DEC
: o
= GEN_INT (-8); goto pre_modify
;
8499 case PRE_INC
: o
= GEN_INT (8); goto pre_modify
;
8500 case PRE_MODIFY
: o
= XEXP (XEXP (addr
, 1), 1);
8504 case POST_DEC
: o
= GEN_INT (-8); goto post_modify
;
8505 case POST_INC
: o
= GEN_INT (8); goto post_modify
;
8506 case POST_MODIFY
: o
= XEXP (XEXP (addr
, 1), 1);
8515 xop
[0+i
] = adjust_automodify_address_nv
8516 (operands
[i
], SImode
,
8517 gen_rtx_fmt_ee (code
, Pmode
, r
,
8518 gen_rtx_PLUS (Pmode
, r
, o
)),
8520 xop
[2+i
] = adjust_automodify_address_nv
8521 (operands
[i
], SImode
, plus_constant (r
, 4), 4);
8525 xop
[0+i
] = operand_subword (operands
[i
], 0, 0, mode
);
8526 xop
[2+i
] = operand_subword (operands
[i
], 1, 0, mode
);
8529 if (reg_overlap_mentioned_p (xop
[0], xop
[3]))
8532 gcc_assert (!reg_overlap_mentioned_p (xop
[2], xop
[1]));
8534 operands
[2+swap
] = xop
[0];
8535 operands
[3+swap
] = xop
[1];
8536 operands
[4-swap
] = xop
[2];
8537 operands
[5-swap
] = xop
[3];
8541 arc_split_dilogic (rtx
*operands
, enum rtx_code code
)
8545 for (word
= 0; word
< 2; word
++)
8546 for (i
= 0; i
< 3; i
++)
8547 operands
[3+word
*3+i
] = operand_subword (operands
[i
], word
, 0, DImode
);
8548 if (reg_overlap_mentioned_p (operands
[3], operands
[7])
8549 || reg_overlap_mentioned_p (operands
[3], operands
[8]))
8553 for (i
= 0; i
< 3; i
++)
8555 tmp
= operands
[3+i
];
8556 operands
[3+i
] = operands
[6+i
];
8557 operands
[6+i
] = tmp
;
8559 gcc_assert (!reg_overlap_mentioned_p (operands
[3], operands
[7]));
8560 gcc_assert (!reg_overlap_mentioned_p (operands
[3], operands
[8]));
8562 for (word
= 0, i
= 0; word
< 2; word
++)
8564 rtx src
= simplify_gen_binary (code
, SImode
, operands
[3+word
*3+1],
8565 operands
[3+word
*3+2]);
8566 rtx dst
= operands
[3+word
*3];
8568 if (!rtx_equal_p (src
, dst
) || !optimize
)
8569 emit_insn (gen_rtx_SET (VOIDmode
, dst
, src
));
8572 emit_note (NOTE_INSN_DELETED
);
8576 arc_short_long (rtx insn
, const char *s_tmpl
, const char *l_tmpl
)
8578 int is_short
= arc_verify_short (insn
, cfun
->machine
->unalign
, -1);
8580 extract_constrain_insn_cached (insn
);
8581 return is_short
? s_tmpl
: l_tmpl
;
8584 /* Searches X for any reference to REGNO, returning the rtx of the
8585 reference found if any. Otherwise, returns NULL_RTX. */
8587 arc_regno_use_in (unsigned int regno
, rtx x
)
8593 if (REG_P (x
) && refers_to_regno_p (regno
, regno
+1, x
, (rtx
*) 0))
8596 fmt
= GET_RTX_FORMAT (GET_CODE (x
));
8597 for (i
= GET_RTX_LENGTH (GET_CODE (x
)) - 1; i
>= 0; i
--)
8601 if ((tem
= regno_use_in (regno
, XEXP (x
, i
))))
8604 else if (fmt
[i
] == 'E')
8605 for (j
= XVECLEN (x
, i
) - 1; j
>= 0; j
--)
8606 if ((tem
= regno_use_in (regno
, XVECEXP (x
, i
, j
))))
8614 arc_attr_type (rtx insn
)
8616 if (NONJUMP_INSN_P (insn
)
8617 ? (GET_CODE (PATTERN (insn
)) == USE
8618 || GET_CODE (PATTERN (insn
)) == CLOBBER
)
8620 ? (GET_CODE (PATTERN (insn
)) == ADDR_VEC
8621 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
8624 return get_attr_type (insn
);
8628 arc_sets_cc_p (rtx insn
)
8630 if (NONJUMP_INSN_P (insn
) && GET_CODE (PATTERN (insn
)) == SEQUENCE
)
8631 insn
= XVECEXP (PATTERN (insn
), 0, XVECLEN (PATTERN (insn
), 0) - 1);
8632 return arc_attr_type (insn
) == TYPE_COMPARE
;
8635 /* Return nonzero if INSN is an instruction with a delay slot we may want
8638 arc_need_delay (rtx insn
)
8642 if (!flag_delayed_branch
)
8644 /* The return at the end of a function needs a delay slot. */
8645 if (NONJUMP_INSN_P (insn
) && GET_CODE (PATTERN (insn
)) == USE
8646 && (!(next
= next_active_insn (insn
))
8647 || ((!NONJUMP_INSN_P (next
) || GET_CODE (PATTERN (next
)) != SEQUENCE
)
8648 && arc_attr_type (next
) == TYPE_RETURN
))
8649 && (!TARGET_PAD_RETURN
8650 || (prev_active_insn (insn
)
8651 && prev_active_insn (prev_active_insn (insn
))
8652 && prev_active_insn (prev_active_insn (prev_active_insn (insn
))))))
8654 if (NONJUMP_INSN_P (insn
)
8655 ? (GET_CODE (PATTERN (insn
)) == USE
8656 || GET_CODE (PATTERN (insn
)) == CLOBBER
8657 || GET_CODE (PATTERN (insn
)) == SEQUENCE
)
8659 ? (GET_CODE (PATTERN (insn
)) == ADDR_VEC
8660 || GET_CODE (PATTERN (insn
)) == ADDR_DIFF_VEC
)
8663 return num_delay_slots (insn
);
8667 arc_scheduling_not_expected (void)
8669 return cfun
->machine
->arc_reorg_started
;
8672 /* Oddly enough, sometimes we get a zero overhead loop that branch
8673 shortening doesn't think is a loop - ovserved with compile/pr24883.c
8674 -O3 -fomit-frame-pointer -funroll-loops. Make sure to include the
8675 alignment visible for branch shortening (we actually align the loop
8676 insn before it, but that is equivalent since the loop insn is 4 byte
8679 arc_label_align (rtx label
)
8681 int loop_align
= LOOP_ALIGN (LABEL
);
8683 if (loop_align
> align_labels_log
)
8685 rtx prev
= prev_nonnote_insn (label
);
8687 if (prev
&& NONJUMP_INSN_P (prev
)
8688 && GET_CODE (PATTERN (prev
)) == PARALLEL
8689 && recog_memoized (prev
) == CODE_FOR_doloop_begin_i
)
8692 return align_labels_log
;
8696 arc_text_label (rtx label
)
8700 /* ??? We use deleted labels like they were still there, see
8701 gcc.c-torture/compile/20000326-2.c . */
8702 gcc_assert (GET_CODE (label
) == CODE_LABEL
8703 || (GET_CODE (label
) == NOTE
8704 && NOTE_KIND (label
) == NOTE_INSN_DELETED_LABEL
));
8705 next
= next_nonnote_insn (label
);
8707 return (GET_CODE (next
) != JUMP_INSN
8708 || GET_CODE (PATTERN (next
)) != ADDR_VEC
);
8713 arc_decl_pretend_args (tree decl
)
8715 /* struct function is in DECL_STRUCT_FUNCTION (decl), but no
8716 pretend_args there... See PR38391. */
8717 gcc_assert (decl
== current_function_decl
);
8718 return crtl
->args
.pretend_args_size
;
8721 /* Without this, gcc.dg/tree-prof/bb-reorg.c fails to assemble
8722 when compiling with -O2 -freorder-blocks-and-partition -fprofile-use
8723 -D_PROFILE_USE; delay branch scheduling then follows a REG_CROSSING_JUMP
8724 to redirect two breqs. */
8726 arc_can_follow_jump (const_rtx follower
, const_rtx followee
)
8728 /* ??? get_attr_type is declared to take an rtx. */
8729 union { const_rtx c
; rtx r
; } u
;
8732 if (find_reg_note (followee
, REG_CROSSING_JUMP
, NULL_RTX
))
8733 switch (get_attr_type (u
.r
))
8736 case TYPE_BRCC_NO_DELAY_SLOT
:
8744 /* Called via note_stores. */
8746 arc_dead_or_set_postreload_1 (rtx dest
, const_rtx x ATTRIBUTE_UNUSED
,
8749 rtx reg
= *(rtx
*)data
;
8751 if (REG_P (dest
) && reg
8752 && REGNO (reg
) >= REGNO (dest
)
8753 && (REGNO (reg
) + HARD_REGNO_NREGS (REGNO (reg
), GET_MODE (reg
))
8754 <= REGNO (dest
) + HARD_REGNO_NREGS (REGNO (dest
), GET_MODE (dest
))))
8755 *(rtx
*)data
= NULL_RTX
;
8758 /* Return nonzero if REG is set in or not used after INSN.
8759 After reload, REG_DEAD notes may precede the actual death in of a register
8760 in the same basic block. Additional labels may be added by reorg, so
8761 we only know we can trust a REG_DEAD note when we find a jump. */
8763 arc_dead_or_set_postreload_p (const_rtx insn
, const_rtx reg
)
8768 /* If the reg is set by this instruction, then it is safe for our case. */
8769 note_stores (PATTERN (insn
), arc_dead_or_set_postreload_1
, ®
);
8773 dead
= find_regno_note (insn
, REG_DEAD
, REGNO (reg
));
8775 && (HARD_REGNO_NREGS (REGNO (reg
), GET_MODE (reg
))
8776 > HARD_REGNO_NREGS (REGNO (XEXP (dead
, 0)),
8777 GET_MODE (XEXP (dead
, 0)))))
8779 while ((insn
= NEXT_INSN (insn
)))
8784 code
= GET_CODE (insn
);
8786 /* If this is a sequence, we must handle them all at once.
8787 We could have for instance a call that sets the target register,
8788 and an insn in a delay slot that uses the register. In this case,
8789 we must return 0. */
8790 if (code
== INSN
&& GET_CODE (PATTERN (insn
)) == SEQUENCE
)
8796 for (i
= 0; i
< XVECLEN (PATTERN (insn
), 0); i
++)
8798 rtx this_insn
= XVECEXP (PATTERN (insn
), 0, i
);
8800 if (reg_referenced_p (reg
, PATTERN (this_insn
)))
8804 const_rtx tmp
= reg
;
8806 note_stores (PATTERN (this_insn
),
8807 arc_dead_or_set_postreload_1
, &tmp
);
8811 if (GET_CODE (this_insn
) == CALL_INSN
)
8813 if (find_reg_fusage (this_insn
, USE
, reg
))
8817 else if (GET_CODE (this_insn
) == JUMP_INSN
)
8819 if (INSN_ANNULLED_BRANCH_P (this_insn
))
8829 if (reg_referenced_p (reg
, PATTERN (insn
)))
8831 if (GET_CODE (insn
) == CALL_INSN
8832 && find_reg_fusage (insn
, USE
, reg
))
8834 note_stores ( PATTERN (insn
), arc_dead_or_set_postreload_1
, ®
);
8839 if (code
== JUMP_INSN
)
8840 return dead
!= NULL_RTX
;
8842 if (code
== CALL_INSN
&& call_used_regs
[REGNO (reg
)])