merge selected patches from milepost-integration:
[official-gcc.git] / gcc / config / arc / arc.c
blob2a60b0d4feb0c6aa822ac88baf124386bf03f6f2
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)
17 any later version.
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/>. */
28 #include "config.h"
29 #include <stdio.h>
30 #include "system.h"
31 #include "coretypes.h"
32 #include "tm.h"
33 #include "tree.h"
34 #include "rtl.h"
35 #include "regs.h"
36 #include "hard-reg-set.h"
37 #include "real.h"
38 #include "insn-config.h"
39 #include "conditions.h"
40 #include "insn-flags.h"
41 #include "function.h"
42 #include "toplev.h"
43 #include "tm_p.h"
44 #include "target.h"
45 #include "target-def.h"
46 #include "output.h"
47 #include "insn-attr.h"
48 #include "flags.h"
49 #include "expr.h"
50 #include "recog.h"
51 #include "debug.h"
52 #include "diagnostic.h"
53 #include "insn-codes.h"
54 #include "integrate.h"
55 #include "c-tree.h"
56 #include "langhooks.h"
57 #include "optabs.h"
58 #include "tm-constrs.h"
59 #include "reload.h" /* For operands_match_p */
60 #include "df.h"
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 (())
81 int state;
82 int cc;
83 rtx target_insn;
84 int target_label;
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) \
94 ((STATE)->state += 2)
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)
115 /* local obstack */
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
123 possible. */
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
130 skipping.
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
137 of the program.
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 */
152 enum {
153 ARC_UNSPEC_PLT = 3,
154 ARC_UNSPEC_GOT,
155 ARC_UNSPEC_GOTOFF
159 enum arc_builtins {
160 ARC_BUILTIN_NOP = 2,
161 ARC_BUILTIN_NORM = 3,
162 ARC_BUILTIN_NORMW = 4,
163 ARC_BUILTIN_SWAP = 5,
164 ARC_BUILTIN_BRK = 6,
165 ARC_BUILTIN_DIVAW = 7,
166 ARC_BUILTIN_EX = 8,
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,
174 ARC_BUILTIN_LR = 16,
175 ARC_BUILTIN_SR = 17,
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,
305 ARC_SIMD_BUILTIN_END
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
321 call. */
322 { "long_call", 0, 0, false, true, true, NULL },
323 /* Whereas these functions are always known to reside within the 21/25 bit
324 addressing range. */
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,
335 tree, int *, int);
336 static void arc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT,
337 tree);
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,
367 const_tree, bool);
368 static int arc_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,
369 tree, bool);
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. */
379 static bool
380 arc_vector_mode_supported_p (enum machine_mode mode)
382 if (!TARGET_SIMD_SET)
383 return false;
385 if ((mode == V4SImode)
386 || (mode == V8HImode))
387 return true;
389 return false;
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
480 #if UCLIBC_DEFAULT
481 #define DEFAULT_NO_SDATA MASK_NO_SDATA_SET
482 #else
483 #define DEFAULT_NO_SDATA 0
484 #endif
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
517 static int
518 arc_sched_adjust_priority (rtx insn ATTRIBUTE_UNUSED, int priority)
520 rtx set = single_set (insn);
521 if (set
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;
529 return priority;
532 struct gcc_target targetm = TARGET_INITIALIZER;
534 /* Called by OVERRIDE_OPTIONS to initialize various things. */
535 void arc_init (void)
537 char *tmp;
538 int target_found = 0;
539 enum attr_tune tune_dflt = TUNE_NONE;
541 if (TARGET_A4)
543 arc_cpu_string = "A4";
544 arc_cpu = PROCESSOR_A4;
545 target_found = 1;
547 else if (TARGET_A5)
549 arc_cpu_string = "A5";
550 arc_cpu = PROCESSOR_A5;
551 target_found = 1;
553 else if (TARGET_ARC600)
555 arc_cpu_string = "ARC600";
556 arc_cpu = PROCESSOR_ARC600;
557 tune_dflt = TUNE_ARC600;
558 target_found = 1;
560 else if (TARGET_ARC700)
562 arc_cpu_string = "ARC700";
563 arc_cpu = PROCESSOR_ARC700;
564 tune_dflt = TUNE_ARC700_4_2_STD;
565 target_found = 1;
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)
571 switch (arc_tune)
573 case TUNE_ARC700_4_2_STD:
574 /* latency 7;
575 max throughput (1 multiply + 4 other insns) / 5 cycles. */
576 arc_multcost = COSTS_N_INSNS (4);
577 break;
578 case TUNE_ARC700_4_2_XMAC:
579 /* latency 5;
580 max throughput (1 multiply + 2 other insns) / 3 cycles. */
581 arc_multcost = COSTS_N_INSNS (3);
582 break;
583 case TUNE_ARC600:
584 if (TARGET_MUL64_SET)
586 arc_multcost = COSTS_N_INSNS (4);
587 break;
589 /* Fall through. */
590 default:
591 arc_multcost = COSTS_N_INSNS (30);
592 break;
594 if (TARGET_MIXED_CODE_SET)
596 /* -mmixed-code can not be used with the option -mA4. */
597 if (TARGET_A4)
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 */
604 if (!target_found)
606 target_flags |= MASK_ARC700;
607 arc_cpu_string = "ARC700";
608 arc_cpu = PROCESSOR_ARC700;
609 target_found = 1;
613 /* If none of the target option (-mA4,-mA5,-mARC600,-mARC700) is given,
614 select -mA5 as default. */
615 if (!target_found)
617 #if !UCLIBC_DEFAULT
618 target_flags |= MASK_A5;
619 arc_cpu_string = "A5";
620 arc_cpu = PROCESSOR_A5;
621 #else
622 target_flags |= MASK_ARC700;
623 arc_cpu_string = "ARC700";
624 arc_cpu = PROCESSOR_ARC700;
626 #endif
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);
660 flag_pic = 0;
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 (...) (...))'. */
707 static int
708 get_arc_condition_code (rtx comparison)
710 switch (GET_MODE (XEXP (comparison, 0)))
712 case CCmode:
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 ();
728 case CC_ZNmode:
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 ();
738 case CC_Zmode:
739 switch (GET_CODE (comparison))
741 case EQ : return ARC_CC_EQ;
742 case NE : return ARC_CC_NE;
743 default : gcc_unreachable ();
745 case CC_Cmode:
746 switch (GET_CODE (comparison))
748 case LTU : return ARC_CC_C;
749 case GEU : return ARC_CC_NC;
750 default : gcc_unreachable ();
752 case CC_FP_GTmode:
753 if (TARGET_SPFP)
754 switch (GET_CODE (comparison))
756 case GT : return ARC_CC_N;
757 case UNLE: return ARC_CC_P;
758 default : gcc_unreachable ();
760 else
761 switch (GET_CODE (comparison))
763 case GT : return ARC_CC_HI;
764 case UNLE : return ARC_CC_LS;
765 default : gcc_unreachable ();
767 case CC_FP_GEmode:
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 ();
775 case CC_FP_UNEQmode:
776 switch (GET_CODE (comparison))
778 case UNEQ : return ARC_CC_EQ;
779 case LTGT : return ARC_CC_NE;
780 default : gcc_unreachable ();
782 case CC_FP_ORDmode:
783 switch (GET_CODE (comparison))
785 case UNORDERED : return ARC_CC_C;
786 case ORDERED : return ARC_CC_NC;
787 default : gcc_unreachable ();
789 case CC_FPXmode:
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 ();
802 /*NOTREACHED*/
803 return (42);
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. */
809 enum machine_mode
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);
815 rtx x1;
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"
820 instead.) */
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
824 && y == const0_rtx
825 && (op == EQ || op == NE
826 || ((op == LT || op == GE) && GET_MODE_SIZE (GET_MODE (x) <= 4))))
827 return CC_ZNmode;
829 /* add.f for if (a+b) */
830 if (mode == SImode
831 && GET_CODE (y) == NEG
832 && (op == EQ || op == NE))
833 return CC_ZNmode;
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
838 && INTVAL (y))
839 return CC_Zmode;
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)
847 return CC_Zmode;
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)))
852 return CC_Cmode;
854 if ((mode == SFmode && TARGET_SPFP) || (mode == DFmode && TARGET_DPFP))
855 switch (op)
857 case EQ: case NE: case UNEQ: case LTGT: case ORDERED: case UNORDERED:
858 return CC_FPXmode;
859 case LT: case UNGE: case GT: case UNLE:
860 return CC_FP_GTmode;
861 case LE: case UNGT: case GE: case UNLT:
862 return CC_FP_GEmode;
863 default: gcc_unreachable ();
865 else if (GET_MODE_CLASS (mode) == MODE_FLOAT && TARGET_OPTFPE)
866 switch (op)
868 case EQ: case NE: return CC_Zmode;
869 case LT: case UNGE:
870 case GT: case UNLE: return CC_FP_GTmode;
871 case LE: case UNGT:
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 ();
878 return CCmode;
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 {
891 C_MODE,
892 S_MODE, D_MODE, T_MODE, O_MODE,
893 SF_MODE, DF_MODE, TF_MODE, OF_MODE,
894 V_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];
947 static void
948 arc_init_reg_tables (void)
950 int i;
952 for (i = 0; i < NUM_MACHINE_MODES; i++)
954 switch (GET_MODE_CLASS (i))
956 case MODE_INT:
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;
967 else
968 arc_mode_class[i] = 0;
969 break;
970 case MODE_FLOAT:
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;
980 else
981 arc_mode_class[i] = 0;
982 break;
983 case MODE_VECTOR_INT:
984 arc_mode_class [i] = (1<< (int) V_MODE);
985 break;
986 case MODE_CC:
987 default:
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;
994 else
995 arc_mode_class[i] = 0;
996 break;
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";
1016 void
1017 arc_conditional_register_usage (void)
1019 int regno;
1020 int i;
1021 int fix_start = 60, fix_end = 55;
1023 if (TARGET_MUL64_SET)
1025 fix_start = 57;
1026 fix_end = 59;
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)
1041 fix_start = 56;
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;
1052 if (TARGET_Q_CLASS)
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)
1071 int i;
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. */
1083 if (TARGET_ARC600)
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);
1093 if (TARGET_ARC700)
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++)
1102 if (i < 29)
1104 if (TARGET_Q_CLASS && ((i <= 3) || ((i >= 12) && (i <= 15))))
1105 arc_regno_reg_class[i] = ARCOMPACT16_REGS;
1106 else
1107 arc_regno_reg_class[i] = GENERAL_REGS;
1109 else if (i < 60)
1110 arc_regno_reg_class[i]
1111 = (fixed_regs[i]
1112 ? (TEST_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], i)
1113 ? CHEAP_CORE_REGS : ALL_CORE_REGS)
1114 : ((TARGET_ARC700
1115 && TEST_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], i))
1116 ? CHEAP_CORE_REGS : WRITABLE_CORE_REGS));
1117 else
1119 arc_regno_reg_class[i] = NO_REGS;
1120 } /* if */
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;
1140 if (TARGET_DPFP)
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;
1147 else
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;
1179 /* pc : r63 */
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"))
1205 return 1;
1207 return 0;
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
1212 generated). */
1214 static int
1215 arc_comp_type_attributes (const_tree type1,
1216 const_tree type2)
1218 int l1, l2, s1, s2;
1220 /* Check for mismatch of non-default calling convention. */
1221 if (TREE_CODE (type1) != FUNCTION_TYPE)
1222 return 1;
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))
1235 return 0;
1237 /* Disallow mixed attributes. */
1238 if ((l1 & s2) || (l2 & s1))
1239 return 0;
1243 return 1;
1246 /* Set the default attributes for TYPE. */
1248 void
1249 arc_set_default_type_attributes (tree type ATTRIBUTE_UNUSED)
1251 gcc_unreachable();
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);
1265 rtx cc_reg;
1267 cc_reg = gen_rtx_REG (mode, 61);
1269 if ((cmode == SFmode && TARGET_SPFP) || (cmode == DFmode && TARGET_DPFP))
1271 switch (code)
1273 case NE: case EQ: case LT: case UNGE: case LE: case UNGT:
1274 case UNEQ: case LTGT: case ORDERED: case UNORDERED:
1275 break;
1276 case GT: case UNLE: case GE: case UNLT:
1277 code = swap_condition (code);
1278 x = arc_compare_op1;
1279 y = arc_compare_op0;
1280 break;
1281 default:
1282 gcc_unreachable ();
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),
1289 const0_rtx)));
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);
1296 switch (code)
1298 case NE: case EQ: case GT: case UNLE: case GE: case UNLT:
1299 case UNEQ: case LTGT: case ORDERED: case UNORDERED:
1300 break;
1301 case LT: case UNGE: case LE: case UNGT:
1302 code = swap_condition (code);
1303 x = arc_compare_op1;
1304 y = arc_compare_op0;
1305 break;
1306 default:
1307 gcc_unreachable ();
1309 if (currently_expanding_to_rtl)
1311 emit_move_insn (op0, x);
1312 emit_move_insn (op1, y);
1314 else
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)));
1321 else
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);
1337 if(TARGET_DPFP)
1338 return 1;
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)
1348 && high == -1));
1350 else
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. */
1362 void
1363 arc_setup_incoming_varargs (CUMULATIVE_ARGS *args_so_far,
1364 enum machine_mode mode,
1365 tree type ATTRIBUTE_UNUSED,
1366 int *pretend_size,
1367 int no_rtl)
1369 int first_anon_arg;
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;
1385 if (!no_rtl)
1387 rtx regblock
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);
1394 *pretend_size
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))
1409 case REG :
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:
1413 return !speed;
1415 case LABEL_REF :
1416 case SYMBOL_REF :
1417 case CONST :
1418 /* Most likely needs a LIMM. */
1419 return COSTS_N_INSNS (1);
1421 case PLUS :
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)))
1431 break;
1433 switch (GET_CODE (plus1))
1435 case CONST_INT :
1436 return (TARGET_A4
1437 ? (SMALL_INT (INTVAL (plus1)) ? 1 : 2)
1438 : !RTX_OK_FOR_OFFSET_P (SImode, plus1)
1439 ? COSTS_N_INSNS (1)
1440 : speed
1442 : (satisfies_constraint_Rcq (plus0)
1443 && satisfies_constraint_O (plus1))
1445 : 1);
1446 case REG:
1447 return (speed < 1 ? 0
1448 : (satisfies_constraint_Rcq (plus0)
1449 && satisfies_constraint_Rcq (plus1))
1450 ? 0 : 1);
1451 case CONST :
1452 case SYMBOL_REF :
1453 case LABEL_REF :
1454 return COSTS_N_INSNS (1);
1455 default:
1456 break;
1458 break;
1460 default:
1461 break;
1464 return 4;
1467 /* Emit instruction X with the frame related bit set. */
1468 static rtx
1469 frame_insn (rtx x)
1471 x = emit_insn (x);
1472 RTX_FRAME_RELATED_P (x) = 1;
1473 return x;
1476 /* Emit a frame insn to move SRC to DST. */
1477 static rtx
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. */
1485 static rtx
1486 frame_move_inc (rtx dst, rtx src, rtx reg, rtx addr)
1488 rtx insn = frame_move (dst, src);
1490 if (!addr
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);
1494 return insn;
1497 /* Emit a frame insn which adjusts a frame address register REG by OFFSET. */
1498 static rtx
1499 frame_add (rtx reg, HOST_WIDE_INT offset)
1501 gcc_assert ((offset & 0x3) == 0);
1502 if (!offset)
1503 return NULL_RTX;
1504 return frame_move (reg, plus_constant (reg, offset));
1507 /* Emit a frame insn which adjusts stack pointer by OFFSET. */
1508 static rtx
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
1519 a different scheme.
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
1524 some costs:
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
1540 frame deallocation.
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 +-----------------------+ +-----------------------+
1553 | | | |
1554 high | local variables, | | local variables, |
1555 mem | reg save area, etc. | | reg save area, etc. |
1556 | | | |
1557 +-----------------------+ +-----------------------+
1558 | | | |
1559 | arguments on stack. | | arguments on stack. |
1560 | | | |
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 |
1565 | functions |
1566 FP+16->+-----------------------+
1567 | 4 word save area for |
1568 | return addr, prev %fp |
1569 FP+0->+-----------------------+
1570 | |
1571 | local variables |
1572 | |
1573 +-----------------------+
1574 | |
1575 | register save area |
1576 | |
1577 +-----------------------+
1578 | |
1579 | alloca allocations |
1580 | |
1581 +-----------------------+
1582 | |
1583 | arguments on stack |
1584 | |
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 +-----------------------+ +-----------------------+
1601 | | | |
1602 | reg save area | | reg save area |
1603 | | | |
1604 +-----------------------+ +-----------------------+
1605 | frame pointer | | frame pointer |
1606 | (if required) | | (if required) |
1607 FP +-----------------------+ +-----------------------+
1608 | | | |
1609 | local/temp variables | | local/temp variables |
1610 | | | |
1611 +-----------------------+ +-----------------------+
1612 | | | |
1613 | arguments on stack | | arguments on stack |
1614 | | | |
1615 SP +-----------------------+ +-----------------------+
1616 | reg parm save area |
1617 | only created for |
1618 | variable arg fns |
1619 AP +-----------------------+
1620 | return addr register |
1621 | (if required) |
1622 +-----------------------+
1624 | reg save area |
1626 +-----------------------+
1627 | frame pointer |
1628 | (if required) |
1629 FP +-----------------------+
1631 | local/temp variables |
1633 +-----------------------+
1634 | |
1635 | arguments on stack |
1636 low | |
1637 mem SP +-----------------------+
1639 Notes:
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. */
1669 int unalign;
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;
1677 } machine_function;
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;
1688 tree a;
1689 enum arc_function_type fn_type = fun->machine->fn_type;
1691 if (fn_type != ARC_FUNCTION_UNKNOWN)
1692 return fn_type;
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);
1700 a = TREE_CHAIN (a))
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;
1714 else
1715 gcc_unreachable ();
1716 break;
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
1732 instead of r26.
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. */
1749 static int
1750 arc_compute_millicode_save_restore_regs (unsigned int gmask,
1751 struct arc_frame_info *frame)
1753 int regno;
1755 int start_reg = 13, end_reg = 25;
1757 for (regno = start_reg; regno <= end_reg && (gmask & (1L << regno));)
1758 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
1762 blink restore. */
1763 if (regno - start_reg >= 3 - (current_function_is_leaf == 0))
1765 frame->millicode_start_reg = 13;
1766 frame->millicode_end_reg = regno - 1;
1767 return 1;
1769 return 0;
1772 /* Return the bytes needed to compute the frame pointer from the current
1773 stack pointer.
1775 SIZE is the size needed for local variables. */
1777 unsigned int
1778 arc_compute_frame_size (int size) /* size = # of var. bytes allocated. */
1780 int regno;
1781 unsigned int total_size, var_size, args_size, pretend_size, extra_size;
1782 unsigned int reg_size, reg_offset;
1783 unsigned int gmask;
1784 enum arc_function_type fn_type;
1785 int interrupt_p;
1786 struct arc_frame_info *frame_info = &cfun->machine->frame_info;
1788 size = ARC_STACK_ALIGN (size);
1790 /* 1) Size of locals and temporaries */
1791 var_size = size;
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
1800 for them too. */
1802 reg_size = 0;
1803 gmask = 0;
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.
1818 For ARCtangent-A4:
1819 <return addr reg size> + <fp size> + <static link reg size> +
1820 <reserved-word>
1822 For ARCompact:
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;
1834 if (TARGET_A4)
1836 extra_size = 16;
1838 else
1840 extra_size = 0;
1841 if (MUST_SAVE_RETURN_ADDR)
1842 extra_size = 4;
1843 if (frame_pointer_needed)
1844 extra_size += 4;
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;
1859 } /* if */
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
1870 if (TARGET_A4)
1871 reg_offset = total_size - (pretend_size + var_size + reg_size);
1872 else
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. */
1888 return total_size;
1891 /* Common code to save/restore registers. */
1892 /* epilogue_p 0: prologue 1:epilogue 2:epilogue, sibling thunk */
1893 static void
1894 arc_save_restore (rtx base_reg, unsigned int offset,
1895 unsigned int gmask, int epilogue_p, int *first_offset)
1897 int regno;
1898 struct arc_frame_info *frame = &cfun->machine->frame_info;
1899 rtx sibthunk_insn = NULL_RTX;
1900 rtx extra_pop = NULL_RTX;
1902 if (gmask)
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;
1922 rtx insn;
1923 rtx ret_addr = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
1925 if (*first_offset)
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);
1930 *first_offset = 0;
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));
1944 i += 2;
1946 else
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));
1953 if (epilogue_p)
1954 XVECEXP (insn, 0, i) = gen_rtx_SET (VOIDmode, reg, mem);
1955 else
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;
1961 else
1963 frame_insn (insn);
1964 offset += off;
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)
1977 extra_pop = reg;
1978 offset += UNITS_PER_WORD;
1979 continue;
1981 if (*first_offset)
1983 gcc_assert (!offset);
1984 addr = plus_constant (base_reg, *first_offset);
1985 addr = gen_rtx_PRE_MODIFY (Pmode, base_reg, addr);
1986 *first_offset = 0;
1988 else
1990 gcc_assert (SMALL_INT (offset));
1991 addr = plus_constant (base_reg, offset);
1993 mem = gen_frame_mem (SImode, addr);
1994 if (epilogue_p)
1995 insn = frame_move_inc (reg, mem, base_reg, addr);
1996 else
1997 insn = frame_move_inc (mem, reg, base_reg, addr);
1998 offset += UNITS_PER_WORD;
1999 } /* if */
2000 } /* for */
2001 if (extra_pop)
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);
2008 }/* if */
2009 if (sibthunk_insn)
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
2019 symbols. */
2021 static bool
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 */
2030 if( TARGET_A4 )
2031 fputs("%st(", asm_out_file);
2032 output_addr_const (asm_out_file, x);
2033 if( TARGET_A4 )
2034 fputs (")", asm_out_file);
2035 fputs("\n", asm_out_file);
2036 return true;
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. */
2045 void
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)
2083 if (TARGET_A4)
2085 #if 0
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);
2090 if(doing_dwarf)
2092 dwarf2out_reg_save ("", RETURN_ADDR_REGNUM, -cfa_offset + UNITS_PER_WORD);
2094 #endif
2097 else /* TARGET_ARCOMPACT */
2099 rtx ra = gen_rtx_REG (SImode, RETURN_ADDR_REGNUM);
2100 rtx mem
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;
2106 } /* if */
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;
2117 } /* if */
2120 /* Save frame pointer if needed */
2121 if (frame_pointer_needed)
2123 if (TARGET_A4)
2125 #if 0
2126 fprintf (file, "\tst %s,[%s]\n", fp_str, sp_str);
2127 if(doing_dwarf)
2129 dwarf2out_reg_save ("", FRAME_POINTER_REGNUM, -cfa_offset);
2131 #endif
2133 else /* TARGET_ARCOMPACT */
2135 rtx addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
2136 GEN_INT (-UNITS_PER_WORD + first_offset));
2137 rtx mem
2138 = gen_frame_mem (Pmode,
2139 gen_rtx_PRE_MODIFY (Pmode, stack_pointer_rtx,
2140 addr));
2141 frame_move_inc (mem, frame_pointer_rtx, stack_pointer_rtx, 0);
2142 frame_size_to_allocate -= UNITS_PER_WORD;
2143 first_offset = 0;
2144 } /* if */
2145 frame_move (frame_pointer_rtx, stack_pointer_rtx);
2146 } /* if */
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 */
2163 if (TARGET_A4)
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);
2169 } /* if */
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,
2177 and regs. */
2179 void
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);
2190 if (1)
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;
2202 if (TARGET_A4)
2203 frame_size = size - pretend_size;
2204 else
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
2218 ARCompact ISA */
2219 if (TARGET_ARCOMPACT && frame_size)
2221 if (frame_pointer_needed)
2222 frame_move (stack_pointer_rtx, frame_pointer_rtx);
2223 else
2224 first_offset = frame_size;
2225 size_to_deallocate -= frame_size;
2226 } /* if */
2227 else if (!can_trust_sp_p)
2228 frame_stack_add (-frame_size);
2231 /* Restore any saved registers. */
2232 if (TARGET_A4)
2234 gcc_assert (0); /* Bitrot. */
2235 #if 0
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));
2247 #endif
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;
2259 } /* if */
2261 /* Load blink after the calls to thunk calls in case of
2262 optimize size.
2264 if (millicode_p)
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);
2275 if (sibthunk_p)
2276 return;
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
2289 && !SMALL_INT
2290 ((cfun->machine->frame_info.reg_size + first_offset)
2291 >> 2)
2292 && cfun->machine->frame_info.gmask))
2294 frame_stack_add (first_offset);
2295 first_offset = 0;
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)
2308 ? ra_offs <= 0x800
2309 : satisfies_constraint_C2a (GEN_INT (ra_offs))))
2311 size_to_deallocate -= ra_offs - first_offset;
2312 first_offset = 0;
2313 frame_stack_add (ra_offs);
2314 ra_offs = 0;
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. */
2322 if (ra_offs
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);
2327 first_offset = 0;
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);
2339 if (!millicode_p)
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);
2349 } /* ARCOMPACT */
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. */
2358 if (TARGET_A4)
2360 restored = 0;
2361 fp_restored_p = 0;
2363 else
2365 size_to_deallocate += first_offset;
2366 restored = size - size_to_deallocate;
2367 fp_restored_p = 1;
2368 } /* if */
2371 if (TARGET_A4)
2373 if (frame_pointer_needed)
2375 gcc_assert (0); /* Bitrot. */
2376 #if 0
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)
2381 || pretend_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;
2387 fp_restored_p = 1;
2388 if(doing_dwarf)
2390 if (cfun->calls_alloca || frame_pointer_needed)
2391 dwarf2out_def_cfa("",FRAME_POINTER_REGNUM,cfa_offset);
2392 else
2394 cfa_offset-=frame_size;
2395 dwarf2out_def_cfa("",STACK_POINTER_REGNUM,cfa_offset);
2399 #endif
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;
2407 } /* TARGET_A4 */
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)
2431 return 0;
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)
2435 return 1;
2436 return 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)))
2461 return 1;
2462 return 0;
2466 /* PIC */
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
2473 * add rdest, pc,
2474 * ----------------------------------------------------------
2475 * The rtl to be emitted for this should be:
2476 * set ( reg basereg)
2477 * ( plus ( reg pc)
2478 * ( const (unspec (symref _DYNAMIC) 3)))
2479 * ----------------------------------------------------------
2481 /* Can be used when rtl pro/epilog comes in.
2482 Unused till then */
2484 arc_finalize_pic (void)
2486 rtx new;
2487 rtx baseptr_rtx = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
2489 if (crtl->uses_pic_offset_table == 0)
2490 return NULL_RTX;
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-
2508 efficient code).
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. */
2517 const char *
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);
2528 switch (code)
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);
2542 goto shiftloop;
2544 else
2546 int n = INTVAL (operands[2]);
2548 /* Only consider the lower 5 bits of the shift count */
2549 n = n & 0x1f;
2551 /* If the count is negative, take only lower 5 bits. */
2552 /* FIXME: No longer needed */
2553 if (n < 0)
2554 n = n & 0x1f;
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. */
2563 if (n <= 8)
2565 while (--n >= 0)
2566 output_asm_insn (shift_one, operands);
2568 /* See if we can use a rotate/and. */
2569 else if (n == BITS_PER_WORD - 1)
2571 switch (code)
2573 case ASHIFT :
2574 output_asm_insn ("and %0,%0,1\n\tror %0,%0", operands);
2575 break;
2576 case ASHIFTRT :
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);
2579 break;
2580 case LSHIFTRT :
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);
2583 break;
2584 default:
2585 break;
2588 /* Must loop. */
2589 else
2591 char buf[100];
2593 sprintf (buf, "mov lp_count,%ld", INTVAL (operands[2]) & 0x1f );
2594 output_asm_insn (buf, operands);
2596 shiftloop:
2598 if (flag_pic)
2599 sprintf (buf, "lr %%4,[status]\n\tadd %%4,%%4,6\t%s single insn loop start",
2600 ASM_COMMENT_START);
2601 else
2602 sprintf (buf, "mov %%4,%%%%st(1f)\t%s (single insn loop start) >> 2",
2603 ASM_COMMENT_START);
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);
2609 if (flag_pic)
2610 asm_fprintf (asm_out_file, "\t%s single insn loop\n",
2611 ASM_COMMENT_START);
2612 else
2613 asm_fprintf (asm_out_file, "1:\t%s single insn loop\n",
2614 ASM_COMMENT_START);
2615 output_asm_insn (shift_one, operands);
2616 fprintf (asm_out_file, "2:\t%s end single insn loop\n",
2617 ASM_COMMENT_START);
2622 return "";
2625 /* Nested function support. */
2627 /* Directly store VALUE at BASE plus OFFSET. */
2628 static void
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)),
2633 force_reg (SImode,
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:
2647 nop_s 0x78e0
2648 entry:
2649 ld_s r12,[pcl,12] 0xd403
2650 ld r11,[pcl,12] 0x170c 700b
2651 j_s [r12] 0x7c00
2652 nop_s 0x78e0
2654 The fastest trampoline to execute for trampolines within +-8KB of CTX
2655 would be:
2656 add2 r11,pcl,s12
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
2662 additionally either
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
2666 cache lines
2668 - allocate trampolines fram a special pool of pre-allocated trampolines. */
2671 void
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. */
2687 void
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:
2701 'l' : label
2702 'a' : address
2703 'c' : constant address if CONSTANT_ADDRESS_P
2704 'n' : negative
2705 Here:
2706 'Z': log2(x+1)-1
2707 'z': log2
2708 'M': log2(~x)
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.
2716 'R': Second word
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
2727 'O': Operator
2728 'o': original symbol - no @ prepending. */
2730 void
2731 arc_print_operand (FILE *file,rtx x,int code)
2733 switch (code)
2735 case 'Z':
2736 if (GET_CODE (x) == CONST_INT)
2737 fprintf (file, "%d",exact_log2(INTVAL (x) + 1) - 1 );
2738 else
2739 output_operand_lossage ("invalid operand to %%Z code");
2741 return;
2743 case 'z':
2744 if (GET_CODE (x) == CONST_INT)
2745 fprintf (file, "%d",exact_log2(INTVAL (x)) );
2746 else
2747 output_operand_lossage ("invalid operand to %%z code");
2749 return;
2751 case 'M':
2752 if (GET_CODE (x) == CONST_INT)
2753 fprintf (file, "%d",exact_log2(~INTVAL (x)) );
2754 else
2755 output_operand_lossage ("invalid operand to %%M code");
2757 return;
2759 case '#' :
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. */
2767 case '*' :
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))
2777 return;
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"),
2782 file);
2783 else
2784 fputs (".d", file);
2786 return;
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. */
2806 if (code == '!'
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)]);
2827 else
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;
2834 else
2835 /* This insn is executed for either path, so don't
2836 conditionalize it at all. */
2837 output_short_suffix (file);
2841 else
2842 output_short_suffix (file);
2843 return;
2844 case'`':
2845 /* FIXME: fold constant inside unary operator, re-recognize, and emit. */
2846 gcc_unreachable ();
2847 case 'd' :
2848 fputs (arc_condition_codes[get_arc_condition_code (x)], file);
2849 return;
2850 case 'D' :
2851 fputs (arc_condition_codes[ARC_INVERSE_CONDITION_CODE
2852 (get_arc_condition_code (x))],
2853 file);
2854 return;
2855 case 'R' :
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)
2862 fputc ('[', file);
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))));
2885 output_scaled = 0;
2887 else
2888 output_address (plus_constant (XEXP (x, 0), 4));
2889 fputc (']', file);
2891 else
2892 output_operand_lossage ("invalid operand to %%R code");
2893 return;
2894 case 'S' :
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");
2903 return;
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, ")");
2914 return;
2916 else if (TARGET_A4 && GET_CODE (x) == LABEL_REF)
2918 fprintf (file, "%%st(");
2919 output_addr_const (file, x);
2920 fprintf (file, ")");
2921 return;
2925 else if (GET_CODE (x) == LABEL_REF)
2927 if (TARGET_A4)
2929 fprintf (file, "%%st(");
2930 output_addr_const (file, x);
2931 fprintf (file, ")");
2932 return;
2935 break;
2936 case 'B' /* Branch or other LIMM ref - must not use sda references. */ :
2937 if (CONSTANT_P (x))
2939 output_addr_const (file, x);
2940 return;
2942 break;
2943 case 'H' :
2944 case 'L' :
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);
2950 else
2951 fputs (reg_names[REGNO (x)+1], file);
2953 else if (GET_CODE (x) == CONST_INT
2954 || GET_CODE (x) == CONST_DOUBLE)
2956 rtx first, second;
2958 split_double (x, &first, &second);
2960 if((WORDS_BIG_ENDIAN) == 0)
2961 fprintf (file, "0x%08lx",
2962 code == 'L' ? INTVAL (first) : INTVAL (second));
2963 else
2964 fprintf (file, "0x%08lx",
2965 code == 'L' ? INTVAL (second) : INTVAL (first));
2969 else
2970 output_operand_lossage ("invalid operand to %%H/%%L code");
2971 return;
2972 case 'A' :
2974 char str[30];
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);
2981 return;
2983 case 'U' :
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;
2994 case PLUS:
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);
3005 output_scaled = 1;
3007 /* Are we using a scaled index? */
3008 else if (GET_CODE (XEXP (addr, 0)) == MULT)
3009 fputs (".as", file);
3010 break;
3011 case REG:
3012 break;
3013 default:
3014 gcc_assert (CONSTANT_P (addr)); break;
3017 else
3018 output_operand_lossage ("invalid operand to %%U code");
3019 return;
3020 case 'V' :
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);
3028 else
3029 output_operand_lossage ("invalid operand to %%V code");
3030 return;
3031 /* plt code */
3032 case 'P':
3033 case 0 :
3034 /* Do nothing special. */
3035 break;
3036 case 'F':
3037 fputs (reg_names[REGNO (x)]+1, file);
3038 return;
3039 case '^':
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
3043 this '^'. */
3045 fputc('@',file);
3046 return;
3047 case 'O':
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 */
3067 case ZERO_EXTEND:
3068 fputs ("ext", file); /* bmsk allows predication. */
3069 goto size_suffix;
3070 case SIGN_EXTEND: /* unconditional */
3071 fputs ("sex", file);
3072 size_suffix:
3073 switch (GET_MODE (XEXP (x, 0)))
3075 case QImode: fputs ("b", file); return;
3076 case HImode: fputs ("w", file); return;
3077 default: break;
3079 break;
3080 case SS_TRUNCATE:
3081 if (GET_MODE (x) != HImode)
3082 break;
3083 fputs ("sat16", file);
3084 default: break;
3086 output_operand_lossage ("invalid operand to %%O code"); return;
3087 case 'o':
3088 if (GET_CODE (x) == SYMBOL_REF)
3090 assemble_name (file, XSTR (x, 0));
3091 return;
3093 break;
3094 case '&':
3095 if (TARGET_ANNOTATE_ALIGN && cfun->machine->size_reason)
3096 fprintf (file, "; %s. unalign: %d", cfun->machine->size_reason,
3097 cfun->machine->unalign);
3098 return;
3099 default :
3100 /* Unknown flag. */
3101 output_operand_lossage ("invalid operand output code");
3104 switch (GET_CODE (x))
3106 case REG :
3107 fputs (reg_names[REGNO (x)], file);
3108 break;
3109 case MEM :
3111 rtx addr = XEXP (x, 0);
3112 int size = GET_MODE_SIZE (GET_MODE (x));
3114 fputc ('[', file);
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;
3124 case PLUS:
3125 if (output_scaled)
3127 output_address (plus_constant (XEXP (addr, 0),
3128 (INTVAL (XEXP (addr, 1))
3129 >> (size == 2 ? 1 : 2))));
3130 output_scaled = 0;
3132 else
3133 output_address (addr);
3134 break;
3135 default:
3136 if (flag_pic && CONSTANT_ADDRESS_P (addr))
3137 arc_output_pic_addr_const (file, addr, code);
3138 else
3139 output_address (addr);
3140 break;
3142 fputc (']', file);
3143 break;
3145 case CONST_DOUBLE :
3146 /* We handle SFmode constants here as output_addr_const doesn't. */
3147 if (GET_MODE (x) == SFmode)
3149 REAL_VALUE_TYPE d;
3150 long l;
3152 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
3153 REAL_VALUE_TO_TARGET_SINGLE (d, l);
3154 fprintf (file, "0x%08lx", l);
3155 break;
3157 /* Fall through. Let output_addr_const deal with it. */
3158 default :
3159 if (flag_pic)
3160 arc_output_pic_addr_const (file, x, code);
3161 else
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)
3167 x = XEXP (x, 0);
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));
3177 else
3178 output_addr_const (file, x);
3180 if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_SMALL_P (x))
3181 fprintf (file, "@sda");
3182 break;
3186 /* Print a memory address as an operand to reference that memory location. */
3188 void
3189 arc_print_operand_address (FILE *file , rtx addr)
3191 register rtx base, index = 0;
3193 switch (GET_CODE (addr))
3195 case REG :
3196 fputs (reg_names[REGNO (addr)], file);
3197 break;
3198 case SYMBOL_REF :
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, ")");
3205 else
3207 output_addr_const (file, addr);
3208 if (SYMBOL_REF_SMALL_P (addr))
3209 fprintf (file, "@sda");
3211 break;
3212 case PLUS :
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);
3217 else
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))
3223 fputc ('+', file);
3224 else
3225 fputc (',', file);
3226 gcc_assert (OBJECT_P (index));
3227 arc_print_operand_address (file, index);
3228 break;
3229 case CONST:
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));
3238 break;
3240 case PRE_INC :
3241 case PRE_DEC :
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. */
3244 gcc_unreachable ();
3245 break;
3246 default :
3247 if (flag_pic)
3248 arc_output_pic_addr_const (file, addr, 0);
3249 else
3250 output_addr_const (file, addr);
3251 break;
3255 /* Called via note_stores. */
3256 static void
3257 write_profile_sections (rtx dest ATTRIBUTE_UNUSED, rtx x, void *data)
3259 rtx *srcp, src;
3260 htab_t htab = (htab_t) data;
3261 rtx *slot;
3263 if (GET_CODE (x) != SET)
3264 return;
3265 srcp = &SET_SRC (x);
3266 if (MEM_P (*srcp))
3267 srcp = &XEXP (*srcp, 0);
3268 else if (MEM_P (SET_DEST (x)))
3269 srcp = &XEXP (SET_DEST (x), 0);
3270 src = *srcp;
3271 if (GET_CODE (src) != CONST)
3272 return;
3273 src = XEXP (src, 0);
3274 if (GET_CODE (src) != UNSPEC || XINT (src, 1) != UNSPEC_PROF)
3275 return;
3277 gcc_assert (XVECLEN (src, 0) == 3);
3278 if (!htab_elements (htab))
3280 output_asm_insn (".section .__arc_profile_desc, \"a\"\n"
3281 "\t.long %0 + 1\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;
3288 char buf[24];
3289 rtx count;
3291 *slot = src;
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"
3296 "\t.long\t%1\n"
3297 "\t.section\t.__arc_profile_counters, \"aw\"\n"
3298 "\t.type\t%o2, @object\n"
3299 "\t.size\t%o2, 4\n"
3300 "%o2:\t.zero 4",
3301 &XVECEXP (src, 0, 0));
3302 *srcp = count;
3304 else
3305 *srcp = XVECEXP (*slot, 0, 2);
3308 static hashval_t
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));
3318 static int
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
3355 some instructions.
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. */
3379 static void
3380 arc_ccfsm_advance (rtx insn, struct arc_ccfsm *state)
3382 /* BODY will hold the body of INSN. */
3383 register rtx body;
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. */
3387 int reverse = 0;
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)
3404 return;
3406 /* Ignore notes and labels. */
3407 if (!INSN_P (insn))
3408 return;
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;
3417 state->state = 0;
3419 return;
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)
3440 reverse = TRUE;
3441 else
3442 return;
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)
3453 reverse = TRUE;
3454 seeking_return = 1;
3456 else
3457 return;
3459 else
3460 return;
3463 if (GET_CODE (insn) != JUMP_INSN
3464 || GET_CODE (PATTERN (insn)) == ADDR_VEC
3465 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
3466 return;
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)
3472 return;
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);
3479 if (reverse
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. */
3491 if (reverse)
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)
3504 seeking_return = 1;
3505 else if (GET_CODE (XEXP (SET_SRC (body), 2)) == RETURN)
3507 seeking_return = 1;
3508 then_not_else = FALSE;
3510 else
3511 gcc_unreachable ();
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;
3518 insns_skipped++)
3520 rtx scanbody;
3522 this_insn = next_nonnote_insn (this_insn);
3523 if (!this_insn)
3524 break;
3526 if (next_must_be_target_label_p)
3528 if (GET_CODE (this_insn) == BARRIER)
3529 continue;
3530 if (GET_CODE (this_insn) == CODE_LABEL
3531 && this_insn == label)
3533 state->state = 1;
3534 succeed = TRUE;
3536 else
3537 fail = TRUE;
3538 break;
3541 scanbody = PATTERN (this_insn);
3543 switch (GET_CODE (this_insn))
3545 case CODE_LABEL:
3546 /* Succeed if it is the target label, otherwise fail since
3547 control falls in from somewhere else. */
3548 if (this_insn == label)
3550 state->state = 1;
3551 succeed = TRUE;
3553 else
3554 fail = TRUE;
3555 break;
3557 case BARRIER:
3558 /* Succeed if the following insn is the target label.
3559 Otherwise fail.
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;
3563 break;
3565 case CALL_INSN:
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;
3572 else
3573 fail = TRUE;
3574 break;
3576 case JUMP_INSN:
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,
3579 fail. */
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)
3588 state->state = 2;
3589 succeed = TRUE;
3591 else if (GET_CODE (SET_SRC (scanbody)) == IF_THEN_ELSE)
3592 fail = TRUE;
3593 else if (get_attr_cond (this_insn) != COND_CANUSE)
3594 fail = TRUE;
3596 else if (GET_CODE (scanbody) == RETURN
3597 && seeking_return)
3599 state->state = 2;
3600 succeed = TRUE;
3602 else if (GET_CODE (scanbody) == PARALLEL)
3604 if (get_attr_cond (this_insn) != COND_CANUSE)
3605 fail = TRUE;
3607 break;
3609 case INSN:
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)
3616 fail = TRUE;
3618 /* We can't handle other insns like sequences. */
3619 else
3620 fail = TRUE;
3621 break;
3623 default:
3624 break;
3628 if (succeed)
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));
3642 if (!this_insn)
3644 /* Oh dear! we ran off the end, give up. */
3645 extract_insn_cached (insn);
3646 state->state = 0;
3647 state->target_insn = NULL;
3648 return;
3650 state->target_insn = this_insn;
3652 else
3653 gcc_unreachable ();
3655 /* If REVERSE is true, ARM_CURRENT_CC needs to be inverted from
3656 what it was. */
3657 if (!reverse)
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. */
3677 static void
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"))
3683 state->state = 0;
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. */
3692 void
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));
3697 if (!state)
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);
3709 if (!reverse)
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. */
3718 static void
3719 arc_ccfsm_post_advance (rtx insn, struct arc_ccfsm *state)
3721 if (LABEL_P (insn))
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);
3730 else
3732 rtx src = SET_SRC (PATTERN (insn));
3733 arc_ccfsm_record_condition (XEXP (src, 0), XEXP (src, 1) == pc_rtx,
3734 insn, state);
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
3742 deleted. */
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
3750 conditionalized. */
3752 void
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));
3765 void
3766 arc_ccfsm_advance_to (rtx insn)
3768 struct machine_function *machine = cfun->machine;
3769 rtx scan = machine->ccfsm_current_insn;
3770 int restarted = 0;
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)
3776 return;
3777 while (scan != insn)
3779 if (scan)
3781 arc_ccfsm_post_advance (scan, statep);
3782 scan = next_insn (scan);
3784 else
3786 gcc_assert (!restarted);
3787 scan = get_insns ();
3788 memset (statep, 0, sizeof *statep);
3789 restarted = 1;
3791 if (scan)
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. */
3799 static rtx
3800 arc_next_active_insn (rtx insn, struct arc_ccfsm *statep)
3802 rtx pat;
3806 if (statep)
3807 arc_ccfsm_post_advance (insn, statep);
3808 insn = NEXT_INSN (insn);
3809 if (!insn || BARRIER_P (insn))
3810 return NULL_RTX;
3811 if (statep)
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)
3825 return NULL_RTX;
3826 if (GET_CODE (pat) == SEQUENCE)
3827 return XVECEXP (pat, 0, 0);
3829 return insn;
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;
3861 int jump_p;
3862 rtx this_sequence = NULL_RTX;
3863 rtx recog_insn = recog_data.insn;
3865 if (check_attr > 0)
3867 iscompact = get_attr_iscompact (insn);
3868 if (iscompact == ISCOMPACT_FALSE)
3869 return 0;
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))
3915 odd = 2;
3916 *rp = "Long unaligned jump avoids non-delay slot penalty";
3917 goto found_align;
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";
3933 goto found_align;
3939 /* If INSN is at the an unaligned return address of a preceding call,
3940 make INSN short. */
3941 if (TARGET_ALIGN_CALL
3942 && unalign
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";
3951 goto found_align;
3954 prev = PREV_INSN (insn);
3955 next = NEXT_INSN (insn);
3956 gcc_assert (prev);
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
3959 chain. */
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));
3965 if (this_sequence)
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))
3980 && INSN_P (next)
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";
3987 if (recog_insn)
3988 extract_insn_cached (recog_insn);
3989 return 0;
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";
3998 if (recog_insn)
3999 extract_insn_cached (recog_insn);
4000 return 0;
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";
4015 if (unalign)
4016 goto found_align;
4017 scan = XVECEXP (this_sequence, 0, 1);
4018 arc_ccfsm_advance (scan, statep);
4019 scan = arc_next_active_insn (scan, statep);
4020 if (!scan)
4021 goto found_align;
4022 if (LABEL_P (scan))
4024 odd = 0;
4025 goto found_align;
4027 if (!CCFSM_ISCOMPACT (scan, statep) || !arc_verify_short (scan, 2, 1))
4028 odd = 0;
4029 else
4030 *rp = "Small is beautiful";
4031 goto found_align;
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)
4039 goto found_align;
4040 scan = arc_next_active_insn (insn, statep);
4041 if (!scan)
4043 /* Apparently a non-return call. */
4044 *rp = (unalign
4045 ? "Long unaligned jump avoids non-delay slot penalty"
4046 : "Small is beautiful");
4047 odd = 2;
4048 goto found_align;
4050 if (LABEL_P (scan))
4052 *rp = "Avoid nop insertion before label";
4053 odd = 0;
4054 goto found_align;
4056 if (!CCFSM_ISCOMPACT (scan, statep) || !arc_verify_short (scan, 2, 1))
4057 odd = 0;
4058 else
4060 odd = 2;
4061 *rp = (unalign
4062 ? "Long unaligned jump avoids non-delay slot penalty"
4063 : "Small is beautiful");
4065 goto found_align;
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
4072 both be short.
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))
4081 == 2)
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;
4088 if (recog_insn)
4089 extract_insn_cached (recog_insn);
4090 return 0;
4093 *rp = "Small is beautiful";
4094 if (scan) for (;;)
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))
4117 break;
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";
4131 odd = 2;
4132 break;
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";
4145 odd = 2;
4146 break;
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))
4157 && (LABEL_P (later)
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";
4163 odd = 0;
4164 break;
4166 if (LABEL_P (scan) && label_to_alignment (scan) > 1)
4168 *rp = "Avoid nop insertion before label";
4169 odd = 0;
4170 break;
4172 if (INSN_P (scan)
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. */
4178 break;
4180 if (GET_CODE (scan) == BARRIER)
4181 break;
4182 arc_ccfsm_post_advance (scan, statep);
4183 scan = NEXT_INSN (scan);
4184 if (!scan)
4185 break;
4186 if (GET_CODE (scan) == INSN && GET_CODE (PATTERN (scan)) == SEQUENCE)
4187 scan = XVECEXP (PATTERN (scan), 0, 0);
4188 if (JUMP_P (scan)
4189 && (GET_CODE (PATTERN (scan)) == ADDR_VEC
4190 || GET_CODE (PATTERN (scan)) == ADDR_DIFF_VEC))
4192 break;
4194 arc_ccfsm_advance (scan, statep);
4196 found_align:
4197 *statep = old_state;
4198 if (recog_insn)
4199 extract_insn_cached (recog_insn);
4200 if (odd != unalign)
4201 return 1;
4202 return 0;
4205 static void
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);
4219 void
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
4230 start with. */
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)
4265 if (TARGET_A4)
4266 return 0;
4267 else
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))
4280 if (TARGET_A4)
4281 return (cfun->machine->frame_info.total_size
4282 - cfun->machine->frame_info.pretend_size);
4283 else
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));
4290 gcc_unreachable ();
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
4299 const char *
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
4307 * b{eq,ne} label%5
4308 * ||
4309 * \/
4310 * bbit{0,1} r%1,log2(imm%2),label%5
4312 case 0:
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";
4318 else
4319 gcc_unreachable();
4321 /* bic r%0,imm%1,r%2
4322 * cmp r%0,0<- the value we have switched on
4323 * b{eq,ne} label%5
4324 * ||
4325 * \/
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 )
4332 case 1:
4333 if ( GET_CODE (operands[4]) == EQ )
4334 return "bbit0%# %1,%z2,%l5";
4335 else
4336 gcc_unreachable();
4338 default:
4339 gcc_unreachable();
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
4349 const char *
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
4357 * b{eq,ne} label%5
4358 * ||
4359 * \/
4360 * bbit{0,1} r%0,log2(imm%2),label%5
4362 case 0:
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";
4367 else
4368 gcc_unreachable();
4370 /* and r%0,r%1,imm%2
4371 * cmp r%0,1<- the value we have switched on
4372 * beq label%5
4373 * ||
4374 * \/
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 )
4381 case 1:
4382 if ( GET_CODE (operands[4]) == EQ )
4383 return "bbit1%# %1,%z2,%l5";
4384 else
4385 gcc_unreachable();
4387 default:
4388 gcc_unreachable();
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));
4400 int dest_uid;
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:
4414 * and r%0,r%1,imm%2
4415 * cmp r%0, imm%3
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)
4426 int retval;
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 )
4434 retval = retval &&
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)));
4443 return retval;
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
4451 simplification. */
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
4466 the global symbols.
4467 Also calls to local functions are relative and not through the
4468 Procedure Linkage Table.
4471 static void
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);
4487 else
4488 arc_encode_symbol (decl, SIMPLE_CALL_FLAG_CHAR);
4491 if (flag_pic)
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)
4506 if (cfun)
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. */
4532 static bool
4533 arc_rtx_costs (rtx x, int code, int outer_code, int *total, bool speed)
4535 switch (code)
4537 /* Small integers are as cheap as registers. */
4538 case CONST_INT:
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;
4550 else
4552 if (SMALL_INT (INTVAL (x)))
4553 nolimm = fast = true;
4554 switch (outer_code)
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;
4560 break;
4561 case IOR: /* bset */
4562 if (satisfies_constraint_C0p (x)) /* bset */
4563 nolimm = fast = condexec = compact = true;
4564 break;
4565 case XOR:
4566 if (satisfies_constraint_C0p (x)) /* bxor */
4567 nolimm = fast = condexec = true;
4568 break;
4569 case SET:
4570 if (satisfies_constraint_Crr (x)) /* ror b,u6 */
4571 nolimm = true;
4572 default:
4573 break;
4576 /* FIXME: Add target options to attach a small cost if
4577 condexec / compact is not true. */
4578 if (nolimm)
4580 *total = 0;
4581 return true;
4584 /* FALLTHRU */
4586 /* 4 byte values can be fetched as immediate constants -
4587 let's give that the cost of an extra insn. */
4588 case CONST:
4589 case LABEL_REF:
4590 case SYMBOL_REF:
4591 *total = COSTS_N_INSNS (1);
4592 return true;
4594 case CONST_DOUBLE:
4596 rtx high, low;
4598 if (TARGET_DPFP)
4600 *total = COSTS_N_INSNS (1);
4601 return true;
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)));
4607 return true;
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. */
4613 case ASHIFT:
4614 case ASHIFTRT:
4615 case LSHIFTRT:
4616 if (TARGET_SHIFTER)
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);
4626 return true;
4628 *total = COSTS_N_INSNS (1);
4630 else if (GET_CODE (XEXP (x, 1)) != CONST_INT)
4631 *total = COSTS_N_INSNS (16);
4632 else
4633 *total = COSTS_N_INSNS (INTVAL (XEXP ((x), 1)));
4634 return false;
4636 case DIV:
4637 case UDIV:
4638 if (speed)
4639 *total = COSTS_N_INSNS(30);
4640 else
4641 *total = COSTS_N_INSNS(1);
4642 return false;
4644 case MULT:
4645 if ((TARGET_DPFP && GET_MODE (x) == DFmode))
4646 *total = COSTS_N_INSNS (1);
4647 else if (speed)
4648 *total= arc_multcost;
4649 /* We do not want synth_mult sequences when optimizing
4650 for size */
4651 else if (TARGET_MUL64_SET || TARGET_ARC700)
4652 *total = COSTS_N_INSNS (1);
4653 else
4654 *total = COSTS_N_INSNS (2);
4655 return false;
4656 case PLUS:
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));
4662 return true;
4664 return false;
4665 case MINUS:
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));
4671 return true;
4673 return false;
4674 case COMPARE:
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));
4687 return true;
4689 if (GET_CODE (op0) == AND && op1 == const0_rtx
4690 && satisfies_constraint_C1p (XEXP (op0, 1)))
4692 /* bmsk.f */
4693 *total = rtx_cost (XEXP (op0, 0), SET, speed);
4694 return true;
4696 /* add.f */
4697 if (GET_CODE (op1) == NEG)
4699 *total = (rtx_cost (op0, PLUS,speed)
4700 + rtx_cost (XEXP (op1, 0), PLUS, speed));
4702 return false;
4704 case EQ: case NE:
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));
4717 return true;
4719 /* Fall through. */
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);
4724 return false;
4725 case LTU: /* might use adc. */
4726 if (GET_MODE (x) == SImode)
4727 *total += COSTS_N_INSNS (1) - 1;
4728 return false;
4729 default:
4730 return false;
4735 arc_va_arg (tree valist, tree type)
4737 rtx addr_rtx;
4738 tree addr, incr;
4739 tree type_ptr = build_pointer_type (type);
4741 #if 0
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))
4746 #else
4747 if (type != 0
4748 && (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
4749 || TREE_ADDRESSABLE (type)))
4750 #endif
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));
4760 else
4762 HOST_WIDE_INT align, rounded_size;
4764 /* Compute the rounded size of the type. */
4765 align = PARM_BOUNDARY / BITS_PER_UNIT;
4766 rounded_size
4767 = (((TREE_INT_CST_LOW (TYPE_SIZE (type)) / BITS_PER_UNIT + align - 1)
4768 / align)
4769 * align);
4771 /* Align 8 byte operands. */
4772 addr = valist;
4773 gcc_assert (TYPE_ALIGN (type) <= BITS_PER_WORD);
4774 if (TYPE_ALIGN (type) > BITS_PER_WORD)
4776 abort ();
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)
4794 HOST_WIDE_INT adj;
4795 adj = TREE_INT_CST_LOW (TYPE_SIZE (type)) / BITS_PER_UNIT;
4796 if (rounded_size > align)
4797 adj = rounded_size;
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);
4813 return addr_rtx;
4816 /* Return a pointer to a function's name with any
4817 and all prefix encodings stripped from it. */
4818 const char *
4819 arc_strip_name_encoding (const char *name)
4821 switch (*name)
4823 case SIMPLE_CALL_FLAG_CHAR:
4824 case LONG_CALL_FLAG_CHAR:
4825 case SHORT_CALL_FLAG_CHAR:
4826 name++;
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)
4838 return 0;
4839 addr = XEXP (addr, 0);
4840 if (GET_CODE (addr) == PLUS)
4842 if (GET_CODE (XEXP (addr, 1)) != CONST_INT)
4843 return 0;
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)
4860 return 1;
4861 if (GET_CODE (addr) != CONST)
4862 return 0;
4864 addr = XEXP (addr, 0);
4867 if (GET_CODE (addr) == PLUS)
4869 if (GET_CODE (XEXP (addr, 1)) != CONST_INT)
4870 return 0;
4871 addr = XEXP (addr, 0);
4874 if (GET_CODE (addr) != UNSPEC
4875 || XVECLEN (addr, 0) != 1)
4876 return 0;
4878 /* Must be @GOT or @GOTOFF. */
4879 if (XINT (addr, 1) != ARC_UNSPEC_GOT
4880 && XINT (addr, 1) != ARC_UNSPEC_GOTOFF)
4881 return 0;
4883 if (GET_CODE (XVECEXP (addr, 0, 0)) != SYMBOL_REF
4884 && GET_CODE (XVECEXP (addr, 0, 0)) != LABEL_REF)
4885 return 0;
4887 return 1;
4892 /* Returns 1 if OP contains a symbol reference */
4895 symbolic_reference_mentioned_p (rtx op)
4897 register const char *fmt;
4898 register int i;
4900 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
4901 return 1;
4903 fmt = GET_RTX_FORMAT (GET_CODE (op));
4904 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
4906 if (fmt[i] == 'E')
4908 register int j;
4910 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
4911 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
4912 return 1;
4915 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
4916 return 1;
4919 return 0;
4923 arc_raw_symbolic_reference_mentioned_p (rtx op)
4925 register const char *fmt;
4926 register int i;
4928 if (GET_CODE(op) == UNSPEC)
4929 return 0;
4931 if (GET_CODE (op) == SYMBOL_REF)
4932 return 1;
4934 fmt = GET_RTX_FORMAT (GET_CODE (op));
4935 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
4937 if (fmt[i] == 'E')
4939 register int j;
4941 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
4942 if (arc_raw_symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
4943 return 1;
4946 else if (fmt[i] == 'e' && arc_raw_symbolic_reference_mentioned_p (XEXP (op, i)))
4947 return 1;
4950 return 0;
4953 /* Legitimize a pic address reference
4954 * orig = src
4955 * oldx = target if reload_in_progress
4956 * src otherwise
4959 arc_legitimize_pic_address (rtx orig, rtx oldx)
4961 rtx addr = orig;
4962 rtx new = orig;
4963 rtx base;
4965 if (oldx == orig)
4966 oldx = NULL;
4968 if (GET_CODE (addr) == LABEL_REF)
4969 ; /* Do nothing. */
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);
4984 if (oldx == NULL)
4985 oldx = gen_reg_rtx (Pmode);
4987 if (oldx != 0)
4989 emit_move_insn (oldx, new);
4990 new = oldx;
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);
5003 if (oldx == 0)
5004 oldx = gen_reg_rtx (Pmode);
5006 emit_move_insn (oldx, new);
5007 new = oldx;
5009 else
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? */
5018 else
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);
5041 if (oldx != 0)
5043 emit_move_insn (oldx, new);
5044 new = oldx;
5047 else
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));
5055 else
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);
5068 return new;
5071 void
5072 arc_output_pic_addr_const (FILE * file, rtx x, int code)
5074 char buf[256];
5076 restart:
5077 switch (GET_CODE (x))
5079 case PC:
5080 if (flag_pic)
5081 putc ('.', file);
5082 else
5083 gcc_unreachable ();
5084 break;
5086 case SYMBOL_REF:
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);
5092 break;
5094 case LABEL_REF:
5095 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
5096 arc_assemble_name (file, buf);
5097 break;
5099 case CODE_LABEL:
5100 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
5101 arc_assemble_name (file, buf);
5102 break;
5104 case CONST_INT:
5105 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
5106 break;
5108 case CONST:
5109 arc_output_pic_addr_const (file, XEXP (x, 0), code);
5110 break;
5112 case CONST_DOUBLE:
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));
5121 else
5122 fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x));
5124 else
5125 /* We can't handle floating point constants;
5126 PRINT_OPERAND must handle them. */
5127 output_operand_lossage ("floating constant misused");
5128 break;
5130 case PLUS:
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);
5146 else
5147 gcc_unreachable();
5148 break;
5150 case MINUS:
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)
5155 goto restart;
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, ")");
5166 else
5167 arc_output_pic_addr_const (file, XEXP (x, 1), code);
5168 break;
5170 case ZERO_EXTEND:
5171 case SIGN_EXTEND:
5172 arc_output_pic_addr_const (file, XEXP (x, 0), code);
5173 break;
5176 case UNSPEC:
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);
5185 break;
5186 case ARC_UNSPEC_GOTOFF:
5187 fputs ("@gotoff", file);
5188 break;
5189 case ARC_UNSPEC_PLT:
5190 fputs ("@plt", file);
5191 break;
5192 default:
5193 fprintf(stderr, "%d seen\n",XINT (x,1));
5194 output_operand_lossage ("invalid UNSPEC as operand");
5196 break;
5198 break;
5200 default:
5201 output_operand_lossage ("invalid expression as operand");
5205 /* Emit insns to move operands[1] into operands[0]. */
5207 void
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]);
5214 else
5215 operands[1] = arc_legitimize_pic_address (operands[1], temp);
5219 /* Prepend the symbol passed as argument to the name */
5220 static void
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);
5225 char *newstr;
5227 if(*str == prefix)
5228 return;
5229 newstr = (char*) obstack_alloc (&arc_local_obstack, len + 2);
5231 strcpy (newstr + 1, str);
5232 *newstr = prefix;
5233 XSTR (XEXP (DECL_RTL (decl), 0), 0) = newstr;
5235 return;
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 */
5245 void
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
5276 regs available */
5277 #define GPR_REST_ARG_REGS(REGNO) ( ((REGNO) <= (MAX_ARC_PARM_REGS)) \
5278 ? ((MAX_ARC_PARM_REGS) - (REGNO)) \
5279 : 0 )
5281 /* since arc parm regs are contiguous */
5282 #define ARC_NEXT_ARG_REG(REGNO) ( (REGNO) + 1 )
5284 /* Implement TARGET_ARG_PARTIAL_BYTES. */
5286 static int
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;
5293 int arg_num = *cum;
5294 int ret;
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);
5302 return ret;
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
5337 into a register.
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)
5345 int arg_num = *cum;
5346 rtx ret;
5347 const char *debstr;
5349 arg_num = ROUND_ADVANCE_CUM (arg_num, mode, type);
5350 /* Return a marker for use in the call instruction. */
5351 if (mode == VOIDmode)
5353 ret = const0_rtx;
5354 debstr = "<0>";
5356 else if (GPR_REST_ARG_REGS (arg_num) > 0)
5358 ret = gen_rtx_REG (mode, arg_num);
5359 debstr = reg_names [arg_num];
5361 else
5363 ret = NULL_RTX;
5364 debstr = "memory";
5366 return ret;
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 */
5386 void
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;
5392 int i;
5394 if (words)
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. */
5405 static rtx
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)
5423 if (count != 0)
5424 return const0_rtx;
5426 if(TARGET_A4)
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)));
5431 return temp;
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 */
5441 bool
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. */
5449 bool
5450 arc_legitimate_constant_p (rtx x)
5452 if (!flag_pic)
5453 return true;
5455 switch (GET_CODE (x))
5457 case CONST:
5458 x = XEXP (x, 0);
5460 if (GET_CODE (x) == PLUS)
5462 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
5463 return false;
5464 x = XEXP (x, 0);
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:
5474 case UNSPEC_PROF:
5475 return true;
5477 default:
5478 gcc_unreachable ();
5481 /* We must have drilled down to a symbol. */
5482 if ( arc_raw_symbolic_reference_mentioned_p (x))
5483 return false;
5485 /* return true */
5486 break;
5488 case LABEL_REF:
5489 case SYMBOL_REF:
5490 return false;
5492 default:
5493 break;
5496 /* Otherwise we handle everything else in the move patterns. */
5497 return true;
5500 /* Determine if it's legal to put X into the constant pool. */
5501 static bool
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) \
5510 do \
5512 if (MASK) \
5513 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL, NULL_TREE); \
5515 while (0)
5518 static void
5519 arc_init_builtins (void)
5521 tree endlink = void_list_node;
5523 tree void_ftype_void
5524 = build_function_type (void_type_node,
5525 endlink);
5527 tree int_ftype_int
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. */
5590 static rtx
5591 arc_expand_builtin (tree exp,
5592 rtx target,
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);
5598 tree arg0;
5599 tree arg1;
5600 rtx op0;
5601 rtx op1;
5602 int fcode = DECL_FUNCTION_CODE (fndecl);
5603 int icode;
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);
5610 switch (fcode)
5612 case ARC_BUILTIN_NOP:
5613 emit_insn (gen_nop ());
5614 return NULL_RTX;
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));
5627 return target;
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));
5642 return target;
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));
5661 return NULL_RTX;
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));
5680 return NULL_RTX;
5682 case ARC_BUILTIN_RTIE:
5683 icode = CODE_FOR_rtie;
5684 emit_insn (gen_rtie (const1_rtx));
5685 return NULL_RTX;
5687 case ARC_BUILTIN_SYNC:
5688 icode = CODE_FOR_sync;
5689 emit_insn (gen_sync (const1_rtx));
5690 return NULL_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));
5703 return target;
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));
5724 return target;
5726 case ARC_BUILTIN_BRK:
5727 icode = CODE_FOR_brk;
5728 emit_insn (gen_brk (const1_rtx));
5729 return NULL_RTX;
5731 case ARC_BUILTIN_SLEEP:
5732 icode = CODE_FOR_sleep;
5733 arg0 = CALL_EXPR_ARG (exp, 0);
5735 fold (arg0);
5737 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5738 mode0 = insn_data[icode].operand[1].mode;
5740 emit_insn (gen_sleep (op0));
5741 return NULL_RTX;
5743 case ARC_BUILTIN_SWI:
5744 icode = CODE_FOR_swi;
5745 emit_insn (gen_swi (const1_rtx));
5746 return NULL_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));
5758 return NULL_RTX;
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);
5765 fold (arg0);
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));
5771 return target;
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);
5778 fold (arg1);
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));
5787 return NULL_RTX;
5789 case ARC_BUILTIN_LR:
5790 icode = CODE_FOR_lr;
5791 arg0 = CALL_EXPR_ARG (exp, 0);
5792 target = gen_reg_rtx (SImode);
5794 fold (arg0);
5796 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5797 mode0 = insn_data[icode].operand[1].mode;
5799 emit_insn (gen_lr (target, op0));
5800 return target;
5802 case ARC_BUILTIN_SR:
5803 icode = CODE_FOR_sr;
5804 arg0 = CALL_EXPR_ARG (exp, 0);
5805 arg1 = CALL_EXPR_ARG (exp, 1);
5807 fold (arg1);
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));
5816 return NULL_RTX;
5818 case ARC_BUILTIN_TRAP_S:
5819 icode = CODE_FOR_trap_s;
5820 arg0 = CALL_EXPR_ARG (exp, 0);
5822 fold (arg0);
5824 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5825 mode0 = insn_data[icode].operand[1].mode;
5827 emit_insn (gen_trap_s (op0));
5828 return NULL_RTX;
5830 case ARC_BUILTIN_UNIMP_S:
5831 icode = CODE_FOR_unimp_s;
5832 emit_insn (gen_unimp_s (const1_rtx));
5833 return NULL_RTX;
5835 default:
5836 break;
5839 /* @@@ Should really do something sensible here. */
5840 return NULL_RTX;
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]))
5852 case SYMBOL_REF :
5853 case CONST :
5854 case CONST_INT :
5855 return 1;
5856 default:
5857 error("register number must be a compile-time constant. Try giving higher optimization levels");
5858 break;
5860 return 0;
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]))
5871 case CONST :
5872 case CONST_INT :
5873 if( UNSIGNED_INT6 (INTVAL (operands[opno])))
5874 return 1;
5875 default:
5876 fatal_error("operand for sleep instruction must be a unsigned 6 bit compile-time constant.");
5877 break;
5879 return 0;
5882 /* Return nonzero if it is ok to make a tail-call to DECL. */
5883 static bool
5884 arc_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
5886 const char * fname;
5888 if (!TARGET_ARCOMPACT)
5890 /* Never tailcall something for which we have no decl. */
5891 if (decl == NULL)
5892 return false;
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))
5900 return false;
5902 /* Is this a long_call attributed function. If so, return false */
5903 if (ARC_ENCODED_LONG_CALL_ATTR_P(fname))
5904 return false;
5907 /* Never tailcall from an ISR routine - it needs a special exit sequence. */
5908 if (ARC_INTERRUPT_P (arc_compute_function_type (cfun)))
5909 return false;
5911 /* Everything else is ok. */
5912 return true;
5915 /* Output code to add DELTA to the first argument, and then jump
5916 to FUNCTION. Used for C++ multiple inheritance. */
5917 static void
5918 arc_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
5919 HOST_WIDE_INT delta,
5920 HOST_WIDE_INT vcall_offset,
5921 tree function)
5923 int mi_delta = delta;
5924 const char *const mi_op = mi_delta < 0 ? "sub" : "add";
5925 int shift = 0;
5926 int this_regno
5927 = aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function) ? 1 : 0;
5928 const char *fname;
5930 if (mi_delta < 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)
5939 shift += 2;
5940 else
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);
5946 shift += 8;
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)
5955 ld r12,[r12]
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);
5972 else
5973 fputs ("\tb\t", file);
5974 assemble_name (file, XSTR (XEXP (DECL_RTL (function), 0), 0));
5975 fputc ('\n', file);
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)
5993 return 0;
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))
6009 rtx count_ptr
6010 = gen_rtx_CONST (Pmode,
6011 gen_rtx_UNSPEC (Pmode,
6012 gen_rtvec (3, from, callee,
6013 CONST0_RTX (Pmode)),
6014 UNSPEC_PROF));
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)));
6019 return 0;
6021 else
6023 rtx count_list_ptr
6024 = gen_rtx_CONST (Pmode,
6025 gen_rtx_UNSPEC (Pmode,
6026 gen_rtvec (3, from, CONST0_RTX (Pmode),
6027 CONST0_RTX (Pmode)),
6028 UNSPEC_PROF));
6029 emit_move_insn (gen_rtx_REG (Pmode, 8), count_list_ptr);
6030 emit_move_insn (gen_rtx_REG (Pmode, 9), callee);
6031 return 1;
6035 /* Worker function for TARGET_RETURN_IN_MEMORY. */
6037 static bool
6038 arc_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
6040 if (AGGREGATE_TYPE_P (type) || TREE_ADDRESSABLE (type))
6041 return true;
6042 else
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. */
6052 static bool
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)
6058 return (type != 0
6059 && (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
6060 || TREE_ADDRESSABLE (type)));
6062 /* ashwin : We always pass arguments are passed by value */
6063 return 0;
6065 /* unsigned HOST_WIDE_INT size; */
6067 /* if (type) */
6068 /* { */
6069 /* if (AGGREGATE_TYPE_P (type)) */
6070 /* return true; */
6071 /* size = int_size_in_bytes (type); */
6072 /* } */
6073 /* else */
6074 /* size = GET_MODE_SIZE (mode); */
6076 /* return size > 8; */
6078 /* ~ashwin */
6081 /* NULL if INSN insn is valid within a low-overhead loop.
6082 Otherwise return why doloop cannot be applied. */
6084 static const char *
6085 arc_invalid_within_doloop (const_rtx insn)
6087 if (CALL_P (insn))
6088 return "Function call in the loop.";
6089 return NULL;
6092 static int arc_reorg_in_progress = 0;
6094 /* ARC's machince specific reorg function. */
6095 static void
6096 arc_reorg (void)
6098 rtx insn, pattern;
6099 rtx pc_target;
6100 long offset;
6101 int changed;
6103 cfun->machine->arc_reorg_started = 1;
6104 arc_reorg_in_progress = 1;
6106 /* Emit special sections for profiling. */
6107 if (crtl->profile)
6109 section *save_text_section;
6110 rtx insn;
6111 int size = get_max_uid () >> 4;
6112 htab_t htab = htab_create (size, unspec_prof_hash, unspec_prof_htab_eq,
6113 NULL);
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))
6120 in_section = 0;
6121 switch_to_section (save_text_section);
6122 htab_delete (htab);
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)
6131 rtx top_label
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);
6137 int seen_label = 0;
6139 for (lp = prev;
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;)
6149 if (prev)
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)))
6156 lp = prev;
6157 break;
6159 else if (LABEL_P (prev))
6160 seen_label = 1;
6161 prev = prev_nonnote_insn (prev);
6163 if (next)
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)))
6170 lp = next;
6171 break;
6173 next = next_nonnote_insn (next);
6176 prev = NULL_RTX;
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
6184 the loop. */
6185 goto failure;
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,
6193 we loose. */
6194 || (!prev && lp != next && !seen_label))
6196 remove_insn (lp);
6197 goto failure;
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
6207 move exists. */
6208 if (true_regnum (begin_cnt) != LP_COUNT)
6210 rtx mov, set, note;
6212 for (mov = prev_nonnote_insn (lp); mov;
6213 mov = prev_nonnote_insn (mov))
6215 if (!NONJUMP_INSN_P (mov))
6216 mov = 0;
6217 else if ((set = single_set (mov))
6218 && rtx_equal_p (SET_SRC (set), begin_cnt)
6219 && rtx_equal_p (SET_DEST (set), op0))
6220 break;
6222 if (mov)
6224 XEXP (XVECEXP (PATTERN (lp), 0 ,3), 0) = op0;
6225 note = find_regno_note (lp, REG_DEAD, REGNO (begin_cnt));
6226 if (note)
6227 remove_note (lp, note);
6229 else
6231 remove_insn (lp);
6232 goto failure;
6235 XEXP (XVECEXP (PATTERN (insn), 0, 4), 0) = num;
6236 XEXP (XVECEXP (PATTERN (lp), 0, 4), 0) = num;
6237 if (next == lp)
6238 XEXP (XVECEXP (PATTERN (lp), 0, 6), 0) = const2_rtx;
6239 else if (!prev)
6240 XEXP (XVECEXP (PATTERN (lp), 0, 6), 0) = const1_rtx;
6241 else if (prev != lp)
6243 remove_insn (lp);
6244 add_insn_after (lp, prev, NULL);
6246 if (!prev)
6248 XEXP (XVECEXP (PATTERN (lp), 0, 7), 0)
6249 = gen_rtx_LABEL_REF (Pmode, top_label);
6250 REG_NOTES (lp)
6251 = gen_rtx_INSN_LIST (REG_LABEL_OPERAND, top_label,
6252 REG_NOTES (lp));
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)
6259 rtx lc_set
6260 = gen_rtx_SET (VOIDmode,
6261 XEXP (XVECEXP (PATTERN (lp), 0, 3), 0),
6262 const0_rtx);
6264 lc_set = emit_insn_before (lc_set, insn);
6265 delete_insn (lp);
6266 delete_insn (insn);
6267 insn = lc_set;
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. */
6271 else
6273 rtx scan;
6275 for (scan = top_label;
6276 (scan && scan != insn
6277 && (!NONJUMP_INSN_P (scan) || !get_attr_length (scan)));
6278 scan = NEXT_INSN (scan));
6279 if (scan == insn)
6281 remove_insn (lp);
6282 goto failure;
6286 else
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
6294 performance.
6295 We use the doloop_fallback pattern here, which executes
6296 in two cycles on the ARC700 when predicted correctly. */
6297 failure:
6298 if (!REG_P (op0))
6300 rtx op3 = XEXP (XVECEXP (PATTERN (insn), 0, 5), 0);
6302 emit_insn_before (gen_move_insn (op3, op0), insn);
6303 PATTERN (insn)
6304 = gen_doloop_fallback_m (op3, JUMP_LABEL (insn), op0);
6306 else
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
6321 not-execute case.
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)
6348 return;
6350 /* /\* Compute LOG_LINKS. *\/ */
6351 /* for (bb = 0; bb < current_nr_blocks; bb++) */
6352 /* compute_block_backward_dependences (bb); */
6356 init_insn_lengths();
6357 changed = 0;
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))
6368 rtx label;
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)
6375 continue;
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);
6394 continue;
6396 if ((insn_type = get_attr_type (insn)) == TYPE_BRCC
6397 || insn_type == TYPE_BRCC_NO_DELAY_SLOT)
6398 continue;
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)
6406 continue;
6408 /* Now check if the jump is beyond the s9 range */
6409 if (find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX))
6410 continue;
6411 offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
6413 if(offset > 253 || offset < -254)
6414 continue;
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))
6430 continue;
6431 pat = PATTERN (scan);
6432 if (GET_CODE (pat) == SET
6433 && cc_register (SET_DEST (pat), VOIDmode))
6435 link_insn = scan;
6436 break;
6439 if (! link_insn)
6440 continue;
6441 else
6442 /* Check if this is a data dependency */
6444 rtx operator, cc_clob_rtx, op0, op1, brcc_insn, note;
6445 rtx cmp0, cmp1;
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))
6463 continue;
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))
6467 continue;
6469 if (reg_set_between_p (op1, link_insn, insn))
6470 continue;
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)))
6477 continue;
6479 /* CC reg should be dead after insn */
6480 if (!find_regno_note (insn, REG_DEAD, CC_REG))
6481 continue;
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
6489 branches. */
6490 if (!brcc_nolimm_operator (operator, VOIDmode)
6491 && !long_immediate_operand (op1, VOIDmode)
6492 && (TARGET_ARC700
6493 || next_active_insn (link_insn) != insn))
6494 continue;
6496 /* Emit bbit / brcc (or brcc_s if possible).
6497 CC_Zmode indicates that brcc_s is possible. */
6499 if (op0 != cmp0)
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);
6507 else
6508 cc_clob_rtx = gen_rtx_REG (CCmode, CC_REG);
6510 brcc_insn
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);
6514 brcc_insn
6515 = gen_rtx_PARALLEL
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);
6521 if (note)
6523 XEXP (note, 1) = REG_NOTES (brcc_insn);
6524 REG_NOTES (brcc_insn) = note;
6526 note = find_reg_note (link_insn, REG_DEAD, op0);
6527 if (note)
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);
6534 if (note)
6536 XEXP (note, 1) = REG_NOTES (brcc_insn);
6537 REG_NOTES (brcc_insn) = note;
6540 changed = 1;
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 ();
6554 } while (changed);
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
6564 Brcc.d b, c, s9
6565 Brcc.d b, u6, s9
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)
6576 return 0;
6577 return brcc_nolimm_operator (operands[0], VOIDmode);
6580 /* ??? Hack. This should no really be here. See PR32143. */
6581 static bool
6582 arc_decl_anon_ns_mem_p (const_tree decl)
6584 while (1)
6586 if (decl == NULL_TREE || decl == error_mark_node)
6587 return false;
6588 if (TREE_CODE (decl) == NAMESPACE_DECL
6589 && DECL_NAME (decl) == NULL_TREE)
6590 return true;
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);
6597 else
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). */
6605 static bool
6606 arc_in_small_data_p (const_tree decl)
6608 HOST_WIDE_INT size;
6610 if (TARGET_A4)
6611 return false;
6613 if (TREE_CODE (decl) == STRING_CST || TREE_CODE (decl) == FUNCTION_DECL)
6614 return false;
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)
6620 return false;
6622 if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl) != 0)
6624 const char *name;
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)
6629 return false;
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))
6634 return true;
6636 /* Only global variables go into sdata section for now */
6637 else if (1)
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)
6642 return false;
6644 if (TREE_READONLY (decl)
6645 && !TREE_SIDE_EFFECTS (decl)
6646 && (!DECL_INITIAL (decl) || TREE_CONSTANT (DECL_INITIAL (decl))))
6647 return false;
6649 /* TREE_PUBLIC might change after the first call, because of the patch
6650 for PR19238. */
6651 if (default_binds_local_p_1 (decl, 1)
6652 || arc_decl_anon_ns_mem_p (decl))
6653 return false;
6655 /* To ensure -mvolatile-cache works
6656 ld.di does not have a gp-relative variant */
6657 if (TREE_THIS_VOLATILE (decl))
6658 return false;
6661 /* Disable sdata references to weak variables */
6662 if (DECL_WEAK (decl))
6663 return false;
6665 size = int_size_in_bytes (TREE_TYPE (decl));
6667 /* if (AGGREGATE_TYPE_P (TREE_TYPE (decl))) */
6668 /* return false; */
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
6675 as a gp+symref. */
6677 static bool
6678 arc_rewrite_small_data_p (rtx x)
6680 if (GET_CODE (x) == CONST)
6681 x = XEXP (x, 0);
6683 if (GET_CODE (x) == PLUS)
6685 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
6686 x = XEXP (x, 0);
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. */
6695 static int
6696 arc_rewrite_small_data_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
6698 if (arc_rewrite_small_data_p (*loc))
6700 rtx top;
6702 *loc = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, *loc);
6703 if (loc == data)
6704 return -1;
6705 top = *(rtx*) data;
6706 if (GET_CODE (top) == MEM && &XEXP (top, 0) == loc)
6707 ; /* OK. */
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);
6712 else
6713 gcc_unreachable ();
6714 return -1;
6717 if (GET_CODE (*loc) == PLUS
6718 && rtx_equal_p (XEXP (*loc, 0), pic_offset_table_rtx))
6719 return -1;
6721 return 0;
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);
6732 return op;
6735 /* A for_each_rtx callback for small_data_pattern. */
6737 static int
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))
6742 return -1;
6744 return arc_rewrite_small_data_p (*loc);
6747 /* Return true if OP refers to small data symbols directly, not through
6748 a PLUS. */
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)
6767 rtx addr;
6768 int size;
6770 /* Eliminate non-memory operations */
6771 if (GET_CODE (op) != MEM)
6772 return 0;
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)
6781 return 0;
6783 /* Decode the address now. */
6784 addr = XEXP (op, 0);
6786 return LEGITIMATE_SMALL_DATA_ADDRESS_P (addr);
6789 void
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);
6797 if (in_small_data)
6798 switch_to_section (get_named_section (NULL, ".sbss", 0));
6799 /* named_section (0,".sbss",0); */
6800 else
6801 switch_to_section (bss_section);
6803 if (globalize_p)
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);
6811 if (size != 0)
6812 ASM_OUTPUT_SKIP (stream, size);
6848 /* SIMD builtins support */
6849 enum simd_insn_args_type {
6850 Va_Vb_Vc,
6851 Va_Vb_rlimm,
6852 Va_Vb_Ic,
6853 Va_Vb_u6,
6854 Va_Vb_u8,
6855 Va_rlimm_u8,
6857 Va_Vb,
6859 void_rlimm,
6860 void_u6,
6862 Da_u3_rlimm,
6863 Da_rlimm_rlimm,
6865 Va_Ib_u8,
6866 void_Va_Ib_u8,
6868 Va_Vb_Ic_u8,
6869 void_Va_u3_Ib_u8
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)
7017 static void
7018 arc_init_simd_builtins (void)
7020 int i;
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)));
7062 tree void_ftype_int
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));
7134 static rtx
7135 arc_expand_simd_builtin (tree exp,
7136 rtx target,
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);
7142 tree arg0;
7143 tree arg1;
7144 tree arg2;
7145 tree arg3;
7146 rtx op0;
7147 rtx op1;
7148 rtx op2;
7149 rtx op3;
7150 rtx op4;
7151 rtx pat;
7152 unsigned int i;
7153 int fcode = DECL_FUNCTION_CODE (fndecl);
7154 int icode;
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)
7164 break;
7166 /* We must get an enty here */
7167 gcc_assert (i < ARRAY_SIZE (arc_simd_builtin_desc_list));
7169 switch (d->args_type) {
7170 case Va_Vb_rlimm:
7171 icode = d->icode;
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);
7188 if (! pat)
7189 return 0;
7191 emit_insn (pat);
7192 return target;
7194 case Va_Vb_u6:
7195 case Va_Vb_u8:
7196 icode = d->icode;
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.",
7214 d->name,
7215 (d->args_type == Va_Vb_u6)? 6: 8);
7217 pat = GEN_FCN (icode) (target, op0, op1);
7218 if (! pat)
7219 return 0;
7221 emit_insn (pat);
7222 return target;
7224 case Va_rlimm_u8:
7225 icode = d->icode;
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.",
7241 d->name);
7243 pat = GEN_FCN (icode) (target, op0, op1);
7244 if (! pat)
7245 return 0;
7247 emit_insn (pat);
7248 return target;
7250 case Va_Vb_Ic:
7251 icode = d->icode;
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).",
7268 d->name);
7270 pat = GEN_FCN (icode) (target, op0, op1, op2);
7271 if (! pat)
7272 return 0;
7274 emit_insn (pat);
7275 return target;
7277 case Va_Vb_Vc:
7278 icode = d->icode;
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);
7295 if (! pat)
7296 return 0;
7298 emit_insn (pat);
7299 return target;
7301 case Va_Vb:
7302 icode = d->icode;
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);
7313 if (! pat)
7314 return 0;
7316 emit_insn (pat);
7317 return target;
7319 case Da_rlimm_rlimm:
7320 icode = d->icode;
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);
7331 else
7332 gcc_unreachable ();
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);
7345 if (! pat)
7346 return 0;
7348 emit_insn (pat);
7349 return NULL_RTX;
7351 case Da_u3_rlimm:
7352 icode = d->icode;
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).",
7362 d->name);
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));
7370 else
7371 gcc_unreachable ();
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);
7377 if (! pat)
7378 return 0;
7380 emit_insn (pat);
7381 return NULL_RTX;
7383 case void_u6:
7384 icode = d->icode;
7385 arg0 = CALL_EXPR_ARG (exp, 0);
7387 fold (arg0);
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.",
7396 d->name);
7398 pat = GEN_FCN (icode) (op0);
7399 if (! pat)
7400 return 0;
7402 emit_insn (pat);
7403 return NULL_RTX;
7405 case void_rlimm:
7406 icode = d->icode;
7407 arg0 = CALL_EXPR_ARG (exp, 0);
7409 fold (arg0);
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);
7418 if (! pat)
7419 return 0;
7421 emit_insn (pat);
7422 return NULL_RTX;
7424 case Va_Vb_Ic_u8:
7426 rtx src_vreg;
7427 icode = d->icode;
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).",
7447 d->name);
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.",
7452 d->name);
7454 pat = GEN_FCN (icode) (target, op1, op2, op0);
7455 if (! pat)
7456 return 0;
7458 emit_insn (pat);
7459 return target;
7462 case void_Va_Ib_u8:
7463 icode = d->icode;
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).",
7481 d->name);
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.",
7486 d->name);
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);
7492 if (! pat)
7493 return 0;
7495 emit_insn (pat);
7496 return NULL_RTX;
7498 case Va_Ib_u8:
7499 icode = d->icode;
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).",
7518 d->name);
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.",
7523 d->name);
7525 pat = GEN_FCN (icode) (target, op0, op1, op2);
7526 if (! pat)
7527 return 0;
7529 emit_insn (pat);
7530 return target;
7532 case void_Va_u3_Ib_u8:
7533 icode = d->icode;
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).",
7554 d->name);
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).",
7559 d->name);
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).",
7567 d->name);
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).",
7571 d->name);
7573 pat = GEN_FCN (icode) (op0, op1, op2, op3, op4);
7574 if (! pat)
7575 return 0;
7577 emit_insn (pat);
7578 return NULL_RTX;
7580 default:
7581 gcc_unreachable ();
7583 return NULL_RTX;
7586 enum reg_class
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;
7598 return NO_REGS;
7601 static bool
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. */
7617 if (TARGET_ARC600
7618 && (to_class == LPCOUNT_REG || to_class == WRITABLE_CORE_REGS))
7619 return 3;
7620 /* The ARC700 stalls for 3 cycles when *reading* from lp_count. */
7621 if (TARGET_ARC700
7622 && (from_class == LPCOUNT_REG || from_class == ALL_CORE_REGS
7623 || from_class == WRITABLE_CORE_REGS))
7624 return 8;
7625 return 2;
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. */
7634 const char*
7635 arc_output_addsi (rtx *operands, const char *cond)
7637 char format[32];
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;
7645 int shift = 0;
7646 int short_p = 0;
7648 /* First try to emit a 16 bit insn. */
7649 if (1)
7651 int short_0 = satisfies_constraint_Rcq (operands[0]);
7653 short_p = (!cond_p && short_0 && satisfies_constraint_Rcq (operands[1]));
7654 if (short_p
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 {\
7673 if (cond) \
7674 sprintf LIST, output_asm_insn (format, operands);\
7675 return ""; \
7676 } while (0)
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
7693 0x800 is not. */
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,
7711 intval >> shift));
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",
7721 cond));
7724 static rtx
7725 force_offsettable (rtx addr, HOST_WIDE_INT size, int reuse)
7727 rtx base = addr;
7728 rtx offs = const0_rtx;
7730 if (GET_CODE (base) == PLUS)
7732 offs = XEXP (base, 1);
7733 base = XEXP (base, 0);
7735 if (!REG_P (base)
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))
7741 if (reuse)
7742 emit_insn (gen_add2_insn (addr, offs));
7743 else
7744 addr = copy_to_mode_reg (Pmode, addr);
7746 return 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;
7758 HOST_WIDE_INT size;
7759 int align = INTVAL (operands[3]);
7760 unsigned n_pieces;
7761 int piece = align;
7762 rtx store[2];
7763 rtx tmpx[2];
7764 int i;
7766 if (!CONST_INT_P (operands[2]))
7767 return 0;
7768 size = INTVAL (operands[2]);
7769 /* move_by_pieces_ninsns is static, so we can't use it. */
7770 if (align >= 4)
7771 n_pieces = (size + 2) / 4U + (size & 1);
7772 else if (align == 2)
7773 n_pieces = (size + 1) / 2U;
7774 else
7775 n_pieces = size;
7776 if (n_pieces >= (unsigned int) (optimize_size ? 3 : 15))
7777 return 0;
7778 if (piece > 4)
7779 piece = 4;
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)
7786 rtx tmp;
7787 enum machine_mode mode;
7789 if (piece > size)
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)
7795 tmp = tmpx[i];
7796 else
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);
7800 if (store[i])
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);
7807 if (store[i])
7808 emit_insn (store[i]);
7809 if (store[i^1])
7810 emit_insn (store[i^1]);
7811 return 1;
7814 /* Prepare operands for move in MODE. Return nonzero iff the move has
7815 been emitted. */
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. */
7821 if (1)
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
7838 variables. */
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
7851 executed. */
7852 emit_move_insn (operands[0], operands[0]);
7853 return 1;
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]);
7868 operands[0] = new;
7870 if (!cse_not_expected)
7872 rtx new = XEXP (operands[0], 0);
7874 new = arc_legitimize_address (new, new, mode);
7875 if (new)
7877 new = change_address (operands[0], mode, new);
7878 MEM_COPY_ATTRIBUTES (new, operands[0]);
7879 operands[0] = new;
7883 if (MEM_P (operands[1]) && !cse_not_expected)
7885 rtx new = XEXP (operands[1], 0);
7887 new = arc_legitimize_address (new, new, mode);
7888 if (new)
7890 new = change_address (operands[1], mode, new);
7891 MEM_COPY_ATTRIBUTES (new, operands[1]);
7892 operands[1] = new;
7895 return 0;
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
7907 variables. */
7908 operands[1]
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
7915 executed. */
7916 emit_move_insn (operands[0], operands[0]);
7917 return 1;
7919 return 0;
7922 /* Output a library call to a function called FNAME that has been arranged
7923 to be local to be any dso. */
7924 const char *
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 ()))
7934 if (flag_pic)
7935 sprintf (buf, "add r12,pcl,@%s-(.&2)\n\tjl%%!%%* [r12]", fname);
7936 else
7937 sprintf (buf, "jl%%! @%s", fname);
7939 else
7940 sprintf (buf, "bl%%!%%* @%s", fname);
7941 return buf;
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. */
7953 static int
7954 arc600_corereg_hazard_1 (rtx *xp, void *data)
7956 rtx x = *xp;
7957 rtx dest;
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:
7963 break;
7964 default:
7965 /* This is also fine for PRE/POST_MODIFY, because they contain a SET. */
7966 return 0;
7968 dest = XEXP (x, 0);
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
7974 (REGNO (dest),
7975 REGNO (dest) + (GET_MODE_SIZE (GET_MODE (dest)) + 3) / 4U, pat, 0)))
7976 return 4;
7978 return 0;
7981 /* return length adjustment for INSN.
7982 For ARC600:
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. */
7986 static int
7987 arc600_corereg_hazard (rtx pred, rtx succ)
7989 if (!TARGET_ARC600)
7990 return 0;
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
7993 SUCC. */
7994 if (recog_memoized (succ) == CODE_FOR_doloop_end_i
7995 && LABEL_P (prev_nonnote_insn (succ)))
7996 return 0;
7997 if (recog_memoized (succ) == CODE_FOR_doloop_begin_i)
7998 return 0;
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)
8010 return 0;
8011 return for_each_rtx (&PATTERN (pred), arc600_corereg_hazard_1,
8012 PATTERN (succ));
8015 /* For ARC600:
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)
8022 if (!TARGET_ARC600)
8023 return 0;
8024 if (!pred || !INSN_P (pred) || !succ || !INSN_P (succ))
8025 return 0;
8026 if (recog_memoized (succ) == CODE_FOR_doloop_end_i
8027 && (JUMP_P (pred) || GET_CODE (PATTERN (pred)) == SEQUENCE))
8028 return 4;
8029 return arc600_corereg_hazard (pred, succ);
8032 /* Return length adjustment for INSN. */
8034 arc_adjust_insn_length (rtx insn, int len)
8036 int adj = 0;
8038 if (!INSN_P (insn))
8039 return 0;
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)));
8049 if (!len1)
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);
8053 return adj0 + adj1;
8055 if (recog_memoized (insn) == CODE_FOR_doloop_end_i)
8057 rtx prev = prev_nonnote_insn (insn);
8059 return ((LABEL_P (prev)
8060 || (TARGET_ARC600
8061 && (JUMP_P (prev) || GET_CODE (PATTERN (prev)) == SEQUENCE)))
8062 ? 4 : 0);
8065 /* Check for return with but one preceding insn since function
8066 start / call. */
8067 if (TARGET_PAD_RETURN
8068 && JUMP_P (insn)
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)))
8080 return 4;
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)
8092 case 0:
8093 break;
8094 case 1: case 2:
8095 /* Deleted branch. */
8096 return -len;
8097 case 3: case 4: case 5:
8098 /* Conditionalized insn. */
8099 if ((!JUMP_P (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)))
8105 && (len & 2))
8106 adj = 2;
8107 break;
8108 default:
8109 gcc_unreachable ();
8112 /* Restore extracted operands - otherwise splitters like the addsi3_mixed one
8113 can go awry. */
8114 extract_constrain_insn_cached (insn);
8116 if (TARGET_ARC600)
8118 rtx succ = next_real_insn (insn);
8120 if (!succ || !INSN_P (succ))
8121 return adj;
8122 return adj + arc600_corereg_hazard (insn, succ);
8124 return adj;
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. */
8135 static int
8136 write_ext_corereg_1 (rtx *xp, void *data ATTRIBUTE_UNUSED)
8138 rtx x = *xp;
8139 rtx dest;
8141 switch (GET_CODE (x))
8143 case SET: case POST_INC: case POST_DEC: case PRE_INC: case PRE_DEC:
8144 break;
8145 default:
8146 /* This is also fine for PRE/POST_MODIFY, because they contain a SET. */
8147 return 0;
8149 dest = XEXP (x, 0);
8150 if (REG_P (dest) && REGNO (dest) >= 32 && REGNO (dest) < 61)
8151 return 1;
8152 return 0;
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)
8166 rtx addr, inner;
8168 if (flag_pic && SYMBOLIC_CONST (x))
8169 (x) = arc_legitimize_pic_address (x, 0);
8170 addr = x;
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);
8189 #endif
8190 addr = plus_constant (force_reg (Pmode, inner), offs - upper);
8191 x = addr;
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))
8196 return x;
8197 return NULL_RTX;
8200 static rtx
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);
8207 return x;
8211 gen_acc1 (void)
8213 return gen_rtx_REG (SImode, TARGET_BIG_ENDIAN ? 56: 57);
8217 gen_acc2 (void)
8219 return gen_rtx_REG (SImode, TARGET_BIG_ENDIAN ? 57: 56);
8223 gen_mlo (void)
8225 return gen_rtx_REG (SImode, TARGET_BIG_ENDIAN ? 59: 58);
8229 gen_mhi (void)
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)
8239 rtx note;
8241 if (!TARGET_UNALIGN_BRANCH)
8242 return 0;
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)))
8246 return 0;
8247 note = find_reg_note (branch, REG_BR_PROB, 0);
8248 return (!note
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
8270 restore. */
8271 void
8272 arc_pad_return (void)
8274 rtx insn = current_output_insn;
8275 rtx prev = prev_active_insn (insn);
8276 int want_long;
8278 if (!prev)
8280 fputs ("\tnop_s\n", asm_out_file);
8281 cfun->machine->unalign ^= 2;
8282 want_long = 1;
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)
8287 return;
8288 else
8290 want_long = (get_attr_length (prev) == 2);
8291 prev = prev_active_insn (prev);
8293 if (!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)))
8298 if (want_long)
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";
8305 want_long = 1;
8307 /* Disgorge delay insn, if there is any. */
8308 if (final_sequence)
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;
8319 else if (want_long)
8320 fputs ("\tnop\n", asm_out_file);
8321 else
8323 fputs ("\tnop_s\n", asm_out_file);
8324 cfun->machine->unalign ^= 2;
8327 return;
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;
8335 machine =
8336 (machine_function *) ggc_alloc_cleared (sizeof (machine_function));
8337 machine->fn_type = ARC_FUNCTION_UNKNOWN;
8338 machine->force_short_suffix = -1;
8340 return machine;
8343 /* Implements INIT_EXPANDERS. We just set up to call the above
8344 function. */
8345 void
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;
8362 int i;
8364 if (load_p == 2)
8366 if (len < 2 || len > 13)
8367 return 0;
8368 load_p = 1;
8370 else
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)
8378 return 0;
8380 for (i = 1; i < len; i++)
8382 rtx elt = XVECEXP (op, 0, i + offset);
8383 rtx reg, mem, addr;
8385 if (GET_CODE (elt) != SET)
8386 return 0;
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))
8390 return 0;
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)
8395 return 0;
8397 return 1;
8401 arc_get_unalign (void)
8403 return cfun->machine->unalign;
8406 void
8407 arc_clear_unalign (void)
8409 if (cfun)
8410 cfun->machine->unalign = 0;
8413 void
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
8421 operand mismatch.
8422 operands 3 and 4 are new SET_SRCs for operands 0. */
8423 void
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]);
8436 else
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
8445 operand mismatch.
8446 operands 3 and 4 are new SET_SRCs for operands 0. */
8447 void
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]);
8461 return;
8463 else if (val >= 0 && val < 255)
8465 operands[3] = operands[1];
8466 operands[4] = gen_rtx_MINUS (SImode, operands[0], operands[2]);
8467 return;
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. */
8479 void
8480 arc_split_move (rtx *operands)
8482 enum machine_mode mode = GET_MODE (operands[0]);
8483 int i;
8484 int swap = 0;
8485 rtx xop[4];
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);
8492 rtx r, o;
8493 enum rtx_code code;
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);
8501 pre_modify:
8502 code = PRE_MODIFY;
8503 break;
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);
8507 post_modify:
8508 code = POST_MODIFY;
8509 swap = 2;
8510 break;
8511 default:
8512 gcc_unreachable ();
8514 r = XEXP (addr, 0);
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);
8523 else
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]))
8531 swap = 2;
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];
8540 void
8541 arc_split_dilogic (rtx *operands, enum rtx_code code)
8543 int word, i;
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]))
8551 rtx tmp;
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));
8571 if (!get_insns ())
8572 emit_note (NOTE_INSN_DELETED);
8575 const char *
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)
8589 const char *fmt;
8590 int i, j;
8591 rtx tem;
8593 if (REG_P (x) && refers_to_regno_p (regno, regno+1, x, (rtx *) 0))
8594 return x;
8596 fmt = GET_RTX_FORMAT (GET_CODE (x));
8597 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
8599 if (fmt[i] == 'e')
8601 if ((tem = regno_use_in (regno, XEXP (x, i))))
8602 return tem;
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))))
8607 return tem;
8610 return NULL_RTX;
8614 arc_attr_type (rtx insn)
8616 if (NONJUMP_INSN_P (insn)
8617 ? (GET_CODE (PATTERN (insn)) == USE
8618 || GET_CODE (PATTERN (insn)) == CLOBBER)
8619 : JUMP_P (insn)
8620 ? (GET_CODE (PATTERN (insn)) == ADDR_VEC
8621 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
8622 : !CALL_P (insn))
8623 return -1;
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
8636 to fill. */
8638 arc_need_delay (rtx insn)
8640 rtx next;
8642 if (!flag_delayed_branch)
8643 return 0;
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))))))
8653 return 1;
8654 if (NONJUMP_INSN_P (insn)
8655 ? (GET_CODE (PATTERN (insn)) == USE
8656 || GET_CODE (PATTERN (insn)) == CLOBBER
8657 || GET_CODE (PATTERN (insn)) == SEQUENCE)
8658 : JUMP_P (insn)
8659 ? (GET_CODE (PATTERN (insn)) == ADDR_VEC
8660 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
8661 : !CALL_P (insn))
8662 return 0;
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
8677 long.) */
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)
8690 return loop_align;
8692 return align_labels_log;
8696 arc_text_label (rtx label)
8698 rtx next;
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);
8706 if (next)
8707 return (GET_CODE (next) != JUMP_INSN
8708 || GET_CODE (PATTERN (next)) != ADDR_VEC);
8709 return 0;
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. */
8725 static bool
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;
8731 u.c = follower;
8732 if (find_reg_note (followee, REG_CROSSING_JUMP, NULL_RTX))
8733 switch (get_attr_type (u.r))
8735 case TYPE_BRCC:
8736 case TYPE_BRCC_NO_DELAY_SLOT:
8737 return false;
8738 default:
8739 return true;
8741 return true;
8744 /* Called via note_stores. */
8745 static void
8746 arc_dead_or_set_postreload_1 (rtx dest, const_rtx x ATTRIBUTE_UNUSED,
8747 void *data)
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)
8765 enum rtx_code code;
8766 rtx dead;
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, &reg);
8770 if (!reg)
8771 return 1;
8773 dead = find_regno_note (insn, REG_DEAD, REGNO (reg));
8774 if (dead
8775 && (HARD_REGNO_NREGS (REGNO (reg), GET_MODE (reg))
8776 > HARD_REGNO_NREGS (REGNO (XEXP (dead, 0)),
8777 GET_MODE (XEXP (dead, 0)))))
8778 dead = NULL_RTX;
8779 while ((insn = NEXT_INSN (insn)))
8781 if (!INSN_P (insn))
8782 continue;
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)
8792 int i;
8793 int retval = 0;
8794 int annull = 0;
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)))
8801 return 0;
8802 if (!annull)
8804 const_rtx tmp = reg;
8806 note_stores (PATTERN (this_insn),
8807 arc_dead_or_set_postreload_1, &tmp);
8808 if (!tmp)
8809 retval = 1;
8811 if (GET_CODE (this_insn) == CALL_INSN)
8813 if (find_reg_fusage (this_insn, USE, reg))
8814 return 0;
8815 code = CALL_INSN;
8817 else if (GET_CODE (this_insn) == JUMP_INSN)
8819 if (INSN_ANNULLED_BRANCH_P (this_insn))
8820 annull = 1;
8821 code = JUMP_INSN;
8824 if (retval == 1)
8825 return 1;
8827 else
8829 if (reg_referenced_p (reg, PATTERN (insn)))
8830 return 0;
8831 if (GET_CODE (insn) == CALL_INSN
8832 && find_reg_fusage (insn, USE, reg))
8833 return 0;
8834 note_stores ( PATTERN (insn), arc_dead_or_set_postreload_1, &reg);
8835 if (!reg)
8836 return 1;
8839 if (code == JUMP_INSN)
8840 return dead != NULL_RTX;
8842 if (code == CALL_INSN && call_used_regs[REGNO (reg)])
8843 return 1;
8845 return 1;
8848 #include "gt-arc.h"