]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arc/arc.c
re PR fortran/58579 (Memory allocation fails when calling character-valued function)
[thirdparty/gcc.git] / gcc / config / arc / arc.c
CommitLineData
526b7aee
SV
1/* Subroutines used for code generation on the Synopsys DesignWare ARC cpu.
2 Copyright (C) 1994, 1995, 1997, 2004, 2007-2013
3 Free Software Foundation, Inc.
4
5 Sources derived from work done by Sankhya Technologies (www.sankhya.com) on
6 behalf of Synopsys Inc.
7
8 Position Independent Code support added,Code cleaned up,
9 Comments and Support For ARC700 instructions added by
10 Saurabh Verma (saurabh.verma@codito.com)
11 Ramana Radhakrishnan(ramana.radhakrishnan@codito.com)
12
13 Fixing ABI inconsistencies, optimizations for ARC600 / ARC700 pipelines,
14 profiling support added by Joern Rennecke <joern.rennecke@embecosm.com>
15
16This file is part of GCC.
17
18GCC is free software; you can redistribute it and/or modify
19it under the terms of the GNU General Public License as published by
20the Free Software Foundation; either version 3, or (at your option)
21any later version.
22
23GCC is distributed in the hope that it will be useful,
24but WITHOUT ANY WARRANTY; without even the implied warranty of
25MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26GNU General Public License for more details.
27
28You should have received a copy of the GNU General Public License
29along with GCC; see the file COPYING3. If not see
30<http://www.gnu.org/licenses/>. */
31
32#include "config.h"
33#include <stdio.h>
34#include "system.h"
35#include "coretypes.h"
36#include "tm.h"
37#include "tree.h"
38#include "rtl.h"
39#include "regs.h"
40#include "hard-reg-set.h"
41#include "real.h"
42#include "insn-config.h"
43#include "conditions.h"
44#include "insn-flags.h"
45#include "function.h"
46#include "toplev.h"
47#include "ggc.h"
48#include "tm_p.h"
49#include "target.h"
50#include "output.h"
51#include "insn-attr.h"
52#include "flags.h"
53#include "expr.h"
54#include "recog.h"
55#include "debug.h"
56#include "diagnostic.h"
57#include "insn-codes.h"
58#include "langhooks.h"
59#include "optabs.h"
60#include "tm-constrs.h"
61#include "reload.h" /* For operands_match_p */
62#include "df.h"
63#include "tree-pass.h"
64#include "context.h"
65#include "pass_manager.h"
66
67/* Which cpu we're compiling for (A5, ARC600, ARC601, ARC700). */
68static const char *arc_cpu_string = "";
69
70/* ??? Loads can handle any constant, stores can only handle small ones. */
71/* OTOH, LIMMs cost extra, so their usefulness is limited. */
72#define RTX_OK_FOR_OFFSET_P(MODE, X) \
73(GET_CODE (X) == CONST_INT \
74 && SMALL_INT_RANGE (INTVAL (X), (GET_MODE_SIZE (MODE) - 1) & -4, \
75 (INTVAL (X) & (GET_MODE_SIZE (MODE) - 1) & 3 \
76 ? 0 \
77 : -(-GET_MODE_SIZE (MODE) | -4) >> 1)))
78
79#define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X, INDEX, STRICT) \
80(GET_CODE (X) == PLUS \
81 && RTX_OK_FOR_BASE_P (XEXP (X, 0), (STRICT)) \
82 && ((INDEX && RTX_OK_FOR_INDEX_P (XEXP (X, 1), (STRICT)) \
83 && GET_MODE_SIZE ((MODE)) <= 4) \
84 || RTX_OK_FOR_OFFSET_P (MODE, XEXP (X, 1))))
85
86#define LEGITIMATE_SCALED_ADDRESS_P(MODE, X, STRICT) \
87(GET_CODE (X) == PLUS \
88 && GET_CODE (XEXP (X, 0)) == MULT \
89 && RTX_OK_FOR_INDEX_P (XEXP (XEXP (X, 0), 0), (STRICT)) \
90 && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \
91 && ((GET_MODE_SIZE (MODE) == 2 && INTVAL (XEXP (XEXP (X, 0), 1)) == 2) \
92 || (GET_MODE_SIZE (MODE) == 4 && INTVAL (XEXP (XEXP (X, 0), 1)) == 4)) \
93 && (RTX_OK_FOR_BASE_P (XEXP (X, 1), (STRICT)) \
94 || (flag_pic ? CONST_INT_P (XEXP (X, 1)) : CONSTANT_P (XEXP (X, 1)))))
95
96#define LEGITIMATE_SMALL_DATA_ADDRESS_P(X) \
97 (GET_CODE (X) == PLUS \
98 && (REG_P (XEXP ((X), 0)) && REGNO (XEXP ((X), 0)) == SDATA_BASE_REGNUM) \
99 && ((GET_CODE (XEXP((X),1)) == SYMBOL_REF \
100 && SYMBOL_REF_SMALL_P (XEXP ((X), 1))) \
101 || (GET_CODE (XEXP ((X), 1)) == CONST \
102 && GET_CODE (XEXP (XEXP ((X), 1), 0)) == PLUS \
103 && GET_CODE (XEXP (XEXP (XEXP ((X), 1), 0), 0)) == SYMBOL_REF \
104 && SYMBOL_REF_SMALL_P (XEXP (XEXP (XEXP ((X), 1), 0), 0)) \
105 && GET_CODE (XEXP(XEXP (XEXP ((X), 1), 0), 1)) == CONST_INT)))
106
107/* Array of valid operand punctuation characters. */
108char arc_punct_chars[256];
109
110/* State used by arc_ccfsm_advance to implement conditional execution. */
111struct GTY (()) arc_ccfsm
112{
113 int state;
114 int cc;
115 rtx cond;
116 rtx target_insn;
117 int target_label;
118};
119
120#define arc_ccfsm_current cfun->machine->ccfsm_current
121
122#define ARC_CCFSM_BRANCH_DELETED_P(STATE) \
123 ((STATE)->state == 1 || (STATE)->state == 2)
124
125/* Indicate we're conditionalizing insns now. */
126#define ARC_CCFSM_RECORD_BRANCH_DELETED(STATE) \
127 ((STATE)->state += 2)
128
129#define ARC_CCFSM_COND_EXEC_P(STATE) \
130 ((STATE)->state == 3 || (STATE)->state == 4 || (STATE)->state == 5 \
131 || current_insn_predicate)
132
133/* Check if INSN has a 16 bit opcode considering struct arc_ccfsm *STATE. */
134#define CCFSM_ISCOMPACT(INSN,STATE) \
135 (ARC_CCFSM_COND_EXEC_P (STATE) \
136 ? (get_attr_iscompact (INSN) == ISCOMPACT_TRUE \
137 || get_attr_iscompact (INSN) == ISCOMPACT_TRUE_LIMM) \
138 : get_attr_iscompact (INSN) != ISCOMPACT_FALSE)
139
140/* Likewise, but also consider that INSN might be in a delay slot of JUMP. */
141#define CCFSM_DBR_ISCOMPACT(INSN,JUMP,STATE) \
142 ((ARC_CCFSM_COND_EXEC_P (STATE) \
143 || (JUMP_P (JUMP) \
144 && INSN_ANNULLED_BRANCH_P (JUMP) \
145 && (TARGET_AT_DBR_CONDEXEC || INSN_FROM_TARGET_P (INSN)))) \
146 ? (get_attr_iscompact (INSN) == ISCOMPACT_TRUE \
147 || get_attr_iscompact (INSN) == ISCOMPACT_TRUE_LIMM) \
148 : get_attr_iscompact (INSN) != ISCOMPACT_FALSE)
149
150/* The maximum number of insns skipped which will be conditionalised if
151 possible. */
152/* When optimizing for speed:
153 Let p be the probability that the potentially skipped insns need to
154 be executed, pn the cost of a correctly predicted non-taken branch,
155 mt the cost of a mis/non-predicted taken branch,
156 mn mispredicted non-taken, pt correctly predicted taken ;
157 costs expressed in numbers of instructions like the ones considered
158 skipping.
159 Unfortunately we don't have a measure of predictability - this
160 is linked to probability only in that in the no-eviction-scenario
161 there is a lower bound 1 - 2 * min (p, 1-p), and a somewhat larger
162 value that can be assumed *if* the distribution is perfectly random.
163 A predictability of 1 is perfectly plausible not matter what p is,
164 because the decision could be dependent on an invocation parameter
165 of the program.
166 For large p, we want MAX_INSNS_SKIPPED == pn/(1-p) + mt - pn
167 For small p, we want MAX_INSNS_SKIPPED == pt
168
169 When optimizing for size:
170 We want to skip insn unless we could use 16 opcodes for the
171 non-conditionalized insn to balance the branch length or more.
172 Performance can be tie-breaker. */
173/* If the potentially-skipped insns are likely to be executed, we'll
174 generally save one non-taken branch
175 o
176 this to be no less than the 1/p */
177#define MAX_INSNS_SKIPPED 3
178
179/* The values of unspec's first field. */
180enum {
181 ARC_UNSPEC_PLT = 3,
182 ARC_UNSPEC_GOT,
183 ARC_UNSPEC_GOTOFF
184} ;
185
186
187enum arc_builtins {
188 ARC_BUILTIN_NOP = 2,
189 ARC_BUILTIN_NORM = 3,
190 ARC_BUILTIN_NORMW = 4,
191 ARC_BUILTIN_SWAP = 5,
192 ARC_BUILTIN_BRK = 6,
193 ARC_BUILTIN_DIVAW = 7,
194 ARC_BUILTIN_EX = 8,
195 ARC_BUILTIN_MUL64 = 9,
196 ARC_BUILTIN_MULU64 = 10,
197 ARC_BUILTIN_RTIE = 11,
198 ARC_BUILTIN_SYNC = 12,
199 ARC_BUILTIN_CORE_READ = 13,
200 ARC_BUILTIN_CORE_WRITE = 14,
201 ARC_BUILTIN_FLAG = 15,
202 ARC_BUILTIN_LR = 16,
203 ARC_BUILTIN_SR = 17,
204 ARC_BUILTIN_SLEEP = 18,
205 ARC_BUILTIN_SWI = 19,
206 ARC_BUILTIN_TRAP_S = 20,
207 ARC_BUILTIN_UNIMP_S = 21,
208 ARC_BUILTIN_ALIGNED = 22,
209
210 /* Sentinel to mark start of simd builtins. */
211 ARC_SIMD_BUILTIN_BEGIN = 1000,
212
213 ARC_SIMD_BUILTIN_VADDAW = 1001,
214 ARC_SIMD_BUILTIN_VADDW = 1002,
215 ARC_SIMD_BUILTIN_VAVB = 1003,
216 ARC_SIMD_BUILTIN_VAVRB = 1004,
217 ARC_SIMD_BUILTIN_VDIFAW = 1005,
218 ARC_SIMD_BUILTIN_VDIFW = 1006,
219 ARC_SIMD_BUILTIN_VMAXAW = 1007,
220 ARC_SIMD_BUILTIN_VMAXW = 1008,
221 ARC_SIMD_BUILTIN_VMINAW = 1009,
222 ARC_SIMD_BUILTIN_VMINW = 1010,
223 ARC_SIMD_BUILTIN_VMULAW = 1011,
224 ARC_SIMD_BUILTIN_VMULFAW = 1012,
225 ARC_SIMD_BUILTIN_VMULFW = 1013,
226 ARC_SIMD_BUILTIN_VMULW = 1014,
227 ARC_SIMD_BUILTIN_VSUBAW = 1015,
228 ARC_SIMD_BUILTIN_VSUBW = 1016,
229 ARC_SIMD_BUILTIN_VSUMMW = 1017,
230 ARC_SIMD_BUILTIN_VAND = 1018,
231 ARC_SIMD_BUILTIN_VANDAW = 1019,
232 ARC_SIMD_BUILTIN_VBIC = 1020,
233 ARC_SIMD_BUILTIN_VBICAW = 1021,
234 ARC_SIMD_BUILTIN_VOR = 1022,
235 ARC_SIMD_BUILTIN_VXOR = 1023,
236 ARC_SIMD_BUILTIN_VXORAW = 1024,
237 ARC_SIMD_BUILTIN_VEQW = 1025,
238 ARC_SIMD_BUILTIN_VLEW = 1026,
239 ARC_SIMD_BUILTIN_VLTW = 1027,
240 ARC_SIMD_BUILTIN_VNEW = 1028,
241 ARC_SIMD_BUILTIN_VMR1AW = 1029,
242 ARC_SIMD_BUILTIN_VMR1W = 1030,
243 ARC_SIMD_BUILTIN_VMR2AW = 1031,
244 ARC_SIMD_BUILTIN_VMR2W = 1032,
245 ARC_SIMD_BUILTIN_VMR3AW = 1033,
246 ARC_SIMD_BUILTIN_VMR3W = 1034,
247 ARC_SIMD_BUILTIN_VMR4AW = 1035,
248 ARC_SIMD_BUILTIN_VMR4W = 1036,
249 ARC_SIMD_BUILTIN_VMR5AW = 1037,
250 ARC_SIMD_BUILTIN_VMR5W = 1038,
251 ARC_SIMD_BUILTIN_VMR6AW = 1039,
252 ARC_SIMD_BUILTIN_VMR6W = 1040,
253 ARC_SIMD_BUILTIN_VMR7AW = 1041,
254 ARC_SIMD_BUILTIN_VMR7W = 1042,
255 ARC_SIMD_BUILTIN_VMRB = 1043,
256 ARC_SIMD_BUILTIN_VH264F = 1044,
257 ARC_SIMD_BUILTIN_VH264FT = 1045,
258 ARC_SIMD_BUILTIN_VH264FW = 1046,
259 ARC_SIMD_BUILTIN_VVC1F = 1047,
260 ARC_SIMD_BUILTIN_VVC1FT = 1048,
261
262 /* Va, Vb, rlimm instructions. */
263 ARC_SIMD_BUILTIN_VBADDW = 1050,
264 ARC_SIMD_BUILTIN_VBMAXW = 1051,
265 ARC_SIMD_BUILTIN_VBMINW = 1052,
266 ARC_SIMD_BUILTIN_VBMULAW = 1053,
267 ARC_SIMD_BUILTIN_VBMULFW = 1054,
268 ARC_SIMD_BUILTIN_VBMULW = 1055,
269 ARC_SIMD_BUILTIN_VBRSUBW = 1056,
270 ARC_SIMD_BUILTIN_VBSUBW = 1057,
271
272 /* Va, Vb, Ic instructions. */
273 ARC_SIMD_BUILTIN_VASRW = 1060,
274 ARC_SIMD_BUILTIN_VSR8 = 1061,
275 ARC_SIMD_BUILTIN_VSR8AW = 1062,
276
277 /* Va, Vb, u6 instructions. */
278 ARC_SIMD_BUILTIN_VASRRWi = 1065,
279 ARC_SIMD_BUILTIN_VASRSRWi = 1066,
280 ARC_SIMD_BUILTIN_VASRWi = 1067,
281 ARC_SIMD_BUILTIN_VASRPWBi = 1068,
282 ARC_SIMD_BUILTIN_VASRRPWBi = 1069,
283 ARC_SIMD_BUILTIN_VSR8AWi = 1070,
284 ARC_SIMD_BUILTIN_VSR8i = 1071,
285
286 /* Va, Vb, u8 (simm) instructions. */
287 ARC_SIMD_BUILTIN_VMVAW = 1075,
288 ARC_SIMD_BUILTIN_VMVW = 1076,
289 ARC_SIMD_BUILTIN_VMVZW = 1077,
290 ARC_SIMD_BUILTIN_VD6TAPF = 1078,
291
292 /* Va, rlimm, u8 (simm) instructions. */
293 ARC_SIMD_BUILTIN_VMOVAW = 1080,
294 ARC_SIMD_BUILTIN_VMOVW = 1081,
295 ARC_SIMD_BUILTIN_VMOVZW = 1082,
296
297 /* Va, Vb instructions. */
298 ARC_SIMD_BUILTIN_VABSAW = 1085,
299 ARC_SIMD_BUILTIN_VABSW = 1086,
300 ARC_SIMD_BUILTIN_VADDSUW = 1087,
301 ARC_SIMD_BUILTIN_VSIGNW = 1088,
302 ARC_SIMD_BUILTIN_VEXCH1 = 1089,
303 ARC_SIMD_BUILTIN_VEXCH2 = 1090,
304 ARC_SIMD_BUILTIN_VEXCH4 = 1091,
305 ARC_SIMD_BUILTIN_VUPBAW = 1092,
306 ARC_SIMD_BUILTIN_VUPBW = 1093,
307 ARC_SIMD_BUILTIN_VUPSBAW = 1094,
308 ARC_SIMD_BUILTIN_VUPSBW = 1095,
309
310 ARC_SIMD_BUILTIN_VDIRUN = 1100,
311 ARC_SIMD_BUILTIN_VDORUN = 1101,
312 ARC_SIMD_BUILTIN_VDIWR = 1102,
313 ARC_SIMD_BUILTIN_VDOWR = 1103,
314
315 ARC_SIMD_BUILTIN_VREC = 1105,
316 ARC_SIMD_BUILTIN_VRUN = 1106,
317 ARC_SIMD_BUILTIN_VRECRUN = 1107,
318 ARC_SIMD_BUILTIN_VENDREC = 1108,
319
320 ARC_SIMD_BUILTIN_VLD32WH = 1110,
321 ARC_SIMD_BUILTIN_VLD32WL = 1111,
322 ARC_SIMD_BUILTIN_VLD64 = 1112,
323 ARC_SIMD_BUILTIN_VLD32 = 1113,
324 ARC_SIMD_BUILTIN_VLD64W = 1114,
325 ARC_SIMD_BUILTIN_VLD128 = 1115,
326 ARC_SIMD_BUILTIN_VST128 = 1116,
327 ARC_SIMD_BUILTIN_VST64 = 1117,
328
329 ARC_SIMD_BUILTIN_VST16_N = 1120,
330 ARC_SIMD_BUILTIN_VST32_N = 1121,
331
332 ARC_SIMD_BUILTIN_VINTI = 1201,
333
334 ARC_SIMD_BUILTIN_END
335};
336
337/* A nop is needed between a 4 byte insn that sets the condition codes and
338 a branch that uses them (the same isn't true for an 8 byte insn that sets
339 the condition codes). Set by arc_ccfsm_advance. Used by
340 arc_print_operand. */
341
342static int get_arc_condition_code (rtx);
343
344static tree arc_handle_interrupt_attribute (tree *, tree, tree, int, bool *);
345
346/* Initialized arc_attribute_table to NULL since arc doesnot have any
347 machine specific supported attributes. */
348const struct attribute_spec arc_attribute_table[] =
349{
350 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
351 affects_type_identity } */
352 { "interrupt", 1, 1, true, false, false, arc_handle_interrupt_attribute, true },
353 /* Function calls made to this symbol must be done indirectly, because
354 it may lie outside of the 21/25 bit addressing range of a normal function
355 call. */
356 { "long_call", 0, 0, false, true, true, NULL, false },
357 /* Whereas these functions are always known to reside within the 25 bit
358 addressing range of unconditionalized bl. */
359 { "medium_call", 0, 0, false, true, true, NULL, false },
360 /* And these functions are always known to reside within the 21 bit
361 addressing range of blcc. */
362 { "short_call", 0, 0, false, true, true, NULL, false },
363 { NULL, 0, 0, false, false, false, NULL, false }
364};
365static int arc_comp_type_attributes (const_tree, const_tree);
366static void arc_file_start (void);
367static void arc_internal_label (FILE *, const char *, unsigned long);
368static void arc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT,
369 tree);
370static int arc_address_cost (rtx, enum machine_mode, addr_space_t, bool);
371static void arc_encode_section_info (tree decl, rtx rtl, int first);
372
373static void arc_init_builtins (void);
374static rtx arc_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
375
376static int branch_dest (rtx);
377
378static void arc_output_pic_addr_const (FILE *, rtx, int);
379void emit_pic_move (rtx *, enum machine_mode);
380bool arc_legitimate_pic_operand_p (rtx);
381static bool arc_function_ok_for_sibcall (tree, tree);
382static rtx arc_function_value (const_tree, const_tree, bool);
383const char * output_shift (rtx *);
384static void arc_reorg (void);
385static bool arc_in_small_data_p (const_tree);
386
387static void arc_init_reg_tables (void);
388static bool arc_return_in_memory (const_tree, const_tree);
389static void arc_init_simd_builtins (void);
390static bool arc_vector_mode_supported_p (enum machine_mode);
391
392static const char *arc_invalid_within_doloop (const_rtx);
393
394static void output_short_suffix (FILE *file);
395
396static bool arc_frame_pointer_required (void);
397
398/* Implements target hook vector_mode_supported_p. */
399
400static bool
401arc_vector_mode_supported_p (enum machine_mode mode)
402{
403 if (!TARGET_SIMD_SET)
404 return false;
405
406 if ((mode == V4SImode)
407 || (mode == V8HImode))
408 return true;
409
410 return false;
411}
412
413
414/* TARGET_PRESERVE_RELOAD_P is still awaiting patch re-evaluation / review. */
415static bool arc_preserve_reload_p (rtx in) ATTRIBUTE_UNUSED;
416static rtx arc_delegitimize_address (rtx);
417static bool arc_can_follow_jump (const_rtx follower, const_rtx followee);
418
419static rtx frame_insn (rtx);
420static void arc_function_arg_advance (cumulative_args_t, enum machine_mode,
421 const_tree, bool);
422static rtx arc_legitimize_address_0 (rtx, rtx, enum machine_mode mode);
423
424static void arc_finalize_pic (void);
425
426/* initialize the GCC target structure. */
427#undef TARGET_COMP_TYPE_ATTRIBUTES
428#define TARGET_COMP_TYPE_ATTRIBUTES arc_comp_type_attributes
429#undef TARGET_ASM_FILE_START
430#define TARGET_ASM_FILE_START arc_file_start
431#undef TARGET_ATTRIBUTE_TABLE
432#define TARGET_ATTRIBUTE_TABLE arc_attribute_table
433#undef TARGET_ASM_INTERNAL_LABEL
434#define TARGET_ASM_INTERNAL_LABEL arc_internal_label
435#undef TARGET_RTX_COSTS
436#define TARGET_RTX_COSTS arc_rtx_costs
437#undef TARGET_ADDRESS_COST
438#define TARGET_ADDRESS_COST arc_address_cost
439
440#undef TARGET_ENCODE_SECTION_INFO
441#define TARGET_ENCODE_SECTION_INFO arc_encode_section_info
442
443#undef TARGET_CANNOT_FORCE_CONST_MEM
444#define TARGET_CANNOT_FORCE_CONST_MEM arc_cannot_force_const_mem
445
446#undef TARGET_INIT_BUILTINS
447#define TARGET_INIT_BUILTINS arc_init_builtins
448
449#undef TARGET_EXPAND_BUILTIN
450#define TARGET_EXPAND_BUILTIN arc_expand_builtin
451
452#undef TARGET_ASM_OUTPUT_MI_THUNK
453#define TARGET_ASM_OUTPUT_MI_THUNK arc_output_mi_thunk
454
455#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
456#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
457
458#undef TARGET_FUNCTION_OK_FOR_SIBCALL
459#define TARGET_FUNCTION_OK_FOR_SIBCALL arc_function_ok_for_sibcall
460
461#undef TARGET_MACHINE_DEPENDENT_REORG
462#define TARGET_MACHINE_DEPENDENT_REORG arc_reorg
463
464#undef TARGET_IN_SMALL_DATA_P
465#define TARGET_IN_SMALL_DATA_P arc_in_small_data_p
466
467#undef TARGET_PROMOTE_FUNCTION_MODE
468#define TARGET_PROMOTE_FUNCTION_MODE \
469 default_promote_function_mode_always_promote
470
471#undef TARGET_PROMOTE_PROTOTYPES
472#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
473
474#undef TARGET_RETURN_IN_MEMORY
475#define TARGET_RETURN_IN_MEMORY arc_return_in_memory
476#undef TARGET_PASS_BY_REFERENCE
477#define TARGET_PASS_BY_REFERENCE arc_pass_by_reference
478
479#undef TARGET_SETUP_INCOMING_VARARGS
480#define TARGET_SETUP_INCOMING_VARARGS arc_setup_incoming_varargs
481
482#undef TARGET_ARG_PARTIAL_BYTES
483#define TARGET_ARG_PARTIAL_BYTES arc_arg_partial_bytes
484
485#undef TARGET_MUST_PASS_IN_STACK
486#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
487
488#undef TARGET_FUNCTION_VALUE
489#define TARGET_FUNCTION_VALUE arc_function_value
490
491#undef TARGET_SCHED_ADJUST_PRIORITY
492#define TARGET_SCHED_ADJUST_PRIORITY arc_sched_adjust_priority
493
494#undef TARGET_VECTOR_MODE_SUPPORTED_P
495#define TARGET_VECTOR_MODE_SUPPORTED_P arc_vector_mode_supported_p
496
497#undef TARGET_INVALID_WITHIN_DOLOOP
498#define TARGET_INVALID_WITHIN_DOLOOP arc_invalid_within_doloop
499
500#undef TARGET_PRESERVE_RELOAD_P
501#define TARGET_PRESERVE_RELOAD_P arc_preserve_reload_p
502
503#undef TARGET_CAN_FOLLOW_JUMP
504#define TARGET_CAN_FOLLOW_JUMP arc_can_follow_jump
505
506#undef TARGET_DELEGITIMIZE_ADDRESS
507#define TARGET_DELEGITIMIZE_ADDRESS arc_delegitimize_address
508
509/* Usually, we will be able to scale anchor offsets.
510 When this fails, we want LEGITIMIZE_ADDRESS to kick in. */
511#undef TARGET_MIN_ANCHOR_OFFSET
512#define TARGET_MIN_ANCHOR_OFFSET (-1024)
513#undef TARGET_MAX_ANCHOR_OFFSET
514#define TARGET_MAX_ANCHOR_OFFSET (1020)
515
516#undef TARGET_SECONDARY_RELOAD
517#define TARGET_SECONDARY_RELOAD arc_secondary_reload
518
519#define TARGET_OPTION_OVERRIDE arc_override_options
520
521#define TARGET_CONDITIONAL_REGISTER_USAGE arc_conditional_register_usage
522
523#define TARGET_TRAMPOLINE_INIT arc_initialize_trampoline
524
525#define TARGET_TRAMPOLINE_ADJUST_ADDRESS arc_trampoline_adjust_address
526
527#define TARGET_CAN_ELIMINATE arc_can_eliminate
528
529#define TARGET_FRAME_POINTER_REQUIRED arc_frame_pointer_required
530
531#define TARGET_FUNCTION_ARG arc_function_arg
532
533#define TARGET_FUNCTION_ARG_ADVANCE arc_function_arg_advance
534
535#define TARGET_LEGITIMATE_CONSTANT_P arc_legitimate_constant_p
536
537#define TARGET_LEGITIMATE_ADDRESS_P arc_legitimate_address_p
538
539#define TARGET_MODE_DEPENDENT_ADDRESS_P arc_mode_dependent_address_p
540
541#define TARGET_LEGITIMIZE_ADDRESS arc_legitimize_address
542
543#define TARGET_ADJUST_INSN_LENGTH arc_adjust_insn_length
544
545#define TARGET_INSN_LENGTH_PARAMETERS arc_insn_length_parameters
546
547#define TARGET_LRA_P arc_lra_p
548#define TARGET_REGISTER_PRIORITY arc_register_priority
549/* Stores with scaled offsets have different displacement ranges. */
550#define TARGET_DIFFERENT_ADDR_DISPLACEMENT_P hook_bool_void_true
551#define TARGET_SPILL_CLASS arc_spill_class
552
553#include "target-def.h"
554
555#undef TARGET_ASM_ALIGNED_HI_OP
556#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
557#undef TARGET_ASM_ALIGNED_SI_OP
558#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
559
560/* Try to keep the (mov:DF _, reg) as early as possible so
561 that the d<add/sub/mul>h-lr insns appear together and can
562 use the peephole2 pattern. */
563
564static int
565arc_sched_adjust_priority (rtx insn, int priority)
566{
567 rtx set = single_set (insn);
568 if (set
569 && GET_MODE (SET_SRC(set)) == DFmode
570 && GET_CODE (SET_SRC(set)) == REG)
571 {
572 /* Incrementing priority by 20 (empirically derived). */
573 return priority + 20;
574 }
575
576 return priority;
577}
578
579static reg_class_t
580arc_secondary_reload (bool in_p, rtx x, reg_class_t cl, enum machine_mode,
581 secondary_reload_info *)
582{
583 if (cl == DOUBLE_REGS)
584 return GENERAL_REGS;
585
586 /* The loop counter register can be stored, but not loaded directly. */
587 if ((cl == LPCOUNT_REG || cl == WRITABLE_CORE_REGS)
588 && in_p && MEM_P (x))
589 return GENERAL_REGS;
590 return NO_REGS;
591}
592
593static unsigned arc_ifcvt (void);
594
595namespace {
596
597const pass_data pass_data_arc_ifcvt =
598{
599 RTL_PASS,
600 "arc_ifcvt", /* name */
601 OPTGROUP_NONE, /* optinfo_flags */
602 false, /* has_gate */
603 true, /* has_execute */
604 TV_IFCVT2, /* tv_id */
605 0, /* properties_required */
606 0, /* properties_provided */
607 0, /* properties_destroyed */
608 0, /* todo_flags_start */
609 TODO_df_finish /* todo_flags_finish */
610};
611
612class pass_arc_ifcvt : public rtl_opt_pass
613{
614public:
615 pass_arc_ifcvt(gcc::context *ctxt)
616 : rtl_opt_pass(pass_data_arc_ifcvt, ctxt)
617 {}
618
619 /* opt_pass methods: */
620 opt_pass * clone () { return new pass_arc_ifcvt (ctxt_); }
621 unsigned int execute () { return arc_ifcvt (); }
622};
623
624} // anon namespace
625
626rtl_opt_pass *
627make_pass_arc_ifcvt (gcc::context *ctxt)
628{
629 return new pass_arc_ifcvt (ctxt);
630}
631
632/* Called by OVERRIDE_OPTIONS to initialize various things. */
633
634void
635arc_init (void)
636{
637 enum attr_tune tune_dflt = TUNE_NONE;
638
639 if (TARGET_A5)
640 {
641 arc_cpu_string = "A5";
642 }
643 else if (TARGET_ARC600)
644 {
645 arc_cpu_string = "ARC600";
646 tune_dflt = TUNE_ARC600;
647 }
648 else if (TARGET_ARC601)
649 {
650 arc_cpu_string = "ARC601";
651 tune_dflt = TUNE_ARC600;
652 }
653 else if (TARGET_ARC700)
654 {
655 arc_cpu_string = "ARC700";
656 tune_dflt = TUNE_ARC700_4_2_STD;
657 }
658 else
659 gcc_unreachable ();
660 if (arc_tune == TUNE_NONE)
661 arc_tune = tune_dflt;
662 /* Note: arc_multcost is only used in rtx_cost if speed is true. */
663 if (arc_multcost < 0)
664 switch (arc_tune)
665 {
666 case TUNE_ARC700_4_2_STD:
667 /* latency 7;
668 max throughput (1 multiply + 4 other insns) / 5 cycles. */
669 arc_multcost = COSTS_N_INSNS (4);
670 if (TARGET_NOMPY_SET)
671 arc_multcost = COSTS_N_INSNS (30);
672 break;
673 case TUNE_ARC700_4_2_XMAC:
674 /* latency 5;
675 max throughput (1 multiply + 2 other insns) / 3 cycles. */
676 arc_multcost = COSTS_N_INSNS (3);
677 if (TARGET_NOMPY_SET)
678 arc_multcost = COSTS_N_INSNS (30);
679 break;
680 case TUNE_ARC600:
681 if (TARGET_MUL64_SET)
682 {
683 arc_multcost = COSTS_N_INSNS (4);
684 break;
685 }
686 /* Fall through. */
687 default:
688 arc_multcost = COSTS_N_INSNS (30);
689 break;
690 }
691
692 /* Support mul64 generation only for A5 and ARC600. */
693 if (TARGET_MUL64_SET && TARGET_ARC700)
694 error ("-mmul64 not supported for ARC700");
695
696 /* MPY instructions valid only for ARC700. */
697 if (TARGET_NOMPY_SET && !TARGET_ARC700)
698 error ("-mno-mpy supported only for ARC700");
699
700 /* mul/mac instructions only for ARC600. */
701 if (TARGET_MULMAC_32BY16_SET && !(TARGET_ARC600 || TARGET_ARC601))
702 error ("-mmul32x16 supported only for ARC600 or ARC601");
703
704 if (!TARGET_DPFP && TARGET_DPFP_DISABLE_LRSR)
705 error ("-mno-dpfp-lrsr suppforted only with -mdpfp");
706
707 /* FPX-1. No fast and compact together. */
708 if ((TARGET_DPFP_FAST_SET && TARGET_DPFP_COMPACT_SET)
709 || (TARGET_SPFP_FAST_SET && TARGET_SPFP_COMPACT_SET))
710 error ("FPX fast and compact options cannot be specified together");
711
712 /* FPX-2. No fast-spfp for arc600 or arc601. */
713 if (TARGET_SPFP_FAST_SET && (TARGET_ARC600 || TARGET_ARC601))
714 error ("-mspfp_fast not available on ARC600 or ARC601");
715
716 /* FPX-3. No FPX extensions on pre-ARC600 cores. */
717 if ((TARGET_DPFP || TARGET_SPFP)
718 && !(TARGET_ARC600 || TARGET_ARC601 || TARGET_ARC700))
719 error ("FPX extensions not available on pre-ARC600 cores");
720
721 /* Warn for unimplemented PIC in pre-ARC700 cores, and disable flag_pic. */
722 if (flag_pic && !TARGET_ARC700)
723 {
724 warning (DK_WARNING, "PIC is not supported for %s. Generating non-PIC code only..", arc_cpu_string);
725 flag_pic = 0;
726 }
727
728 arc_init_reg_tables ();
729
730 /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P. */
731 memset (arc_punct_chars, 0, sizeof (arc_punct_chars));
732 arc_punct_chars['#'] = 1;
733 arc_punct_chars['*'] = 1;
734 arc_punct_chars['?'] = 1;
735 arc_punct_chars['!'] = 1;
736 arc_punct_chars['^'] = 1;
737 arc_punct_chars['&'] = 1;
738
739 if (optimize > 1 && !TARGET_NO_COND_EXEC)
740 {
741 /* There are two target-independent ifcvt passes, and arc_reorg may do
742 one or more arc_ifcvt calls. */
743 opt_pass *pass_arc_ifcvt_4 = make_pass_arc_ifcvt (g);
744 struct register_pass_info arc_ifcvt4_info
745 = { pass_arc_ifcvt_4, "dbr", 1, PASS_POS_INSERT_AFTER };
746 struct register_pass_info arc_ifcvt5_info
747 = { pass_arc_ifcvt_4->clone (), "shorten", 1, PASS_POS_INSERT_BEFORE };
748
749 register_pass (&arc_ifcvt4_info);
750 register_pass (&arc_ifcvt5_info);
751 }
752}
753
754/* Check ARC options, generate derived target attributes. */
755
756static void
757arc_override_options (void)
758{
759 if (arc_cpu == PROCESSOR_NONE)
760 arc_cpu = PROCESSOR_ARC700;
761
762 if (arc_size_opt_level == 3)
763 optimize_size = 1;
764
765 if (flag_pic)
766 target_flags |= MASK_NO_SDATA_SET;
767
768 if (flag_no_common == 255)
769 flag_no_common = !TARGET_NO_SDATA_SET;
770
771 /* TARGET_COMPACT_CASESI needs the "q" register class. */ \
772 if (TARGET_MIXED_CODE)
773 TARGET_Q_CLASS = 1;
774 if (!TARGET_Q_CLASS)
775 TARGET_COMPACT_CASESI = 0;
776 if (TARGET_COMPACT_CASESI)
777 TARGET_CASE_VECTOR_PC_RELATIVE = 1;
778
779 /* These need to be done at start up. It's convenient to do them here. */
780 arc_init ();
781}
782
783/* The condition codes of the ARC, and the inverse function. */
784/* For short branches, the "c" / "nc" names are not defined in the ARC
785 Programmers manual, so we have to use "lo" / "hs"" instead. */
786static const char *arc_condition_codes[] =
787{
788 "al", 0, "eq", "ne", "p", "n", "lo", "hs", "v", "nv",
789 "gt", "le", "ge", "lt", "hi", "ls", "pnz", 0
790};
791
792enum arc_cc_code_index
793{
794 ARC_CC_AL, ARC_CC_EQ = ARC_CC_AL+2, ARC_CC_NE, ARC_CC_P, ARC_CC_N,
795 ARC_CC_C, ARC_CC_NC, ARC_CC_V, ARC_CC_NV,
796 ARC_CC_GT, ARC_CC_LE, ARC_CC_GE, ARC_CC_LT, ARC_CC_HI, ARC_CC_LS, ARC_CC_PNZ,
797 ARC_CC_LO = ARC_CC_C, ARC_CC_HS = ARC_CC_NC
798};
799
800#define ARC_INVERSE_CONDITION_CODE(X) ((X) ^ 1)
801
802/* Returns the index of the ARC condition code string in
803 `arc_condition_codes'. COMPARISON should be an rtx like
804 `(eq (...) (...))'. */
805
806static int
807get_arc_condition_code (rtx comparison)
808{
809 switch (GET_MODE (XEXP (comparison, 0)))
810 {
811 case CCmode:
812 case SImode: /* For BRcc. */
813 switch (GET_CODE (comparison))
814 {
815 case EQ : return ARC_CC_EQ;
816 case NE : return ARC_CC_NE;
817 case GT : return ARC_CC_GT;
818 case LE : return ARC_CC_LE;
819 case GE : return ARC_CC_GE;
820 case LT : return ARC_CC_LT;
821 case GTU : return ARC_CC_HI;
822 case LEU : return ARC_CC_LS;
823 case LTU : return ARC_CC_LO;
824 case GEU : return ARC_CC_HS;
825 default : gcc_unreachable ();
826 }
827 case CC_ZNmode:
828 switch (GET_CODE (comparison))
829 {
830 case EQ : return ARC_CC_EQ;
831 case NE : return ARC_CC_NE;
832 case GE: return ARC_CC_P;
833 case LT: return ARC_CC_N;
834 case GT : return ARC_CC_PNZ;
835 default : gcc_unreachable ();
836 }
837 case CC_Zmode:
838 switch (GET_CODE (comparison))
839 {
840 case EQ : return ARC_CC_EQ;
841 case NE : return ARC_CC_NE;
842 default : gcc_unreachable ();
843 }
844 case CC_Cmode:
845 switch (GET_CODE (comparison))
846 {
847 case LTU : return ARC_CC_C;
848 case GEU : return ARC_CC_NC;
849 default : gcc_unreachable ();
850 }
851 case CC_FP_GTmode:
852 if (TARGET_ARGONAUT_SET && TARGET_SPFP)
853 switch (GET_CODE (comparison))
854 {
855 case GT : return ARC_CC_N;
856 case UNLE: return ARC_CC_P;
857 default : gcc_unreachable ();
858 }
859 else
860 switch (GET_CODE (comparison))
861 {
862 case GT : return ARC_CC_HI;
863 case UNLE : return ARC_CC_LS;
864 default : gcc_unreachable ();
865 }
866 case CC_FP_GEmode:
867 /* Same for FPX and non-FPX. */
868 switch (GET_CODE (comparison))
869 {
870 case GE : return ARC_CC_HS;
871 case UNLT : return ARC_CC_LO;
872 default : gcc_unreachable ();
873 }
874 case CC_FP_UNEQmode:
875 switch (GET_CODE (comparison))
876 {
877 case UNEQ : return ARC_CC_EQ;
878 case LTGT : return ARC_CC_NE;
879 default : gcc_unreachable ();
880 }
881 case CC_FP_ORDmode:
882 switch (GET_CODE (comparison))
883 {
884 case UNORDERED : return ARC_CC_C;
885 case ORDERED : return ARC_CC_NC;
886 default : gcc_unreachable ();
887 }
888 case CC_FPXmode:
889 switch (GET_CODE (comparison))
890 {
891 case EQ : return ARC_CC_EQ;
892 case NE : return ARC_CC_NE;
893 case UNORDERED : return ARC_CC_C;
894 case ORDERED : return ARC_CC_NC;
895 case LTGT : return ARC_CC_HI;
896 case UNEQ : return ARC_CC_LS;
897 default : gcc_unreachable ();
898 }
899 default : gcc_unreachable ();
900 }
901 /*NOTREACHED*/
902 return (42);
903}
904
905/* Return true if COMPARISON has a short form that can accomodate OFFSET. */
906
907bool
908arc_short_comparison_p (rtx comparison, int offset)
909{
910 gcc_assert (ARC_CC_NC == ARC_CC_HS);
911 gcc_assert (ARC_CC_C == ARC_CC_LO);
912 switch (get_arc_condition_code (comparison))
913 {
914 case ARC_CC_EQ: case ARC_CC_NE:
915 return offset >= -512 && offset <= 506;
916 case ARC_CC_GT: case ARC_CC_LE: case ARC_CC_GE: case ARC_CC_LT:
917 case ARC_CC_HI: case ARC_CC_LS: case ARC_CC_LO: case ARC_CC_HS:
918 return offset >= -64 && offset <= 58;
919 default:
920 return false;
921 }
922}
923
924/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
925 return the mode to be used for the comparison. */
926
927enum machine_mode
928arc_select_cc_mode (enum rtx_code op, rtx x, rtx y)
929{
930 enum machine_mode mode = GET_MODE (x);
931 rtx x1;
932
933 /* For an operation that sets the condition codes as a side-effect, the
934 C and V flags is not set as for cmp, so we can only use comparisons where
935 this doesn't matter. (For LT and GE we can use "mi" and "pl"
936 instead.) */
937 /* ??? We could use "pnz" for greater than zero, however, we could then
938 get into trouble because the comparison could not be reversed. */
939 if (GET_MODE_CLASS (mode) == MODE_INT
940 && y == const0_rtx
941 && (op == EQ || op == NE
942 || ((op == LT || op == GE) && GET_MODE_SIZE (GET_MODE (x) <= 4))))
943 return CC_ZNmode;
944
945 /* add.f for if (a+b) */
946 if (mode == SImode
947 && GET_CODE (y) == NEG
948 && (op == EQ || op == NE))
949 return CC_ZNmode;
950
951 /* Check if this is a test suitable for bxor.f . */
952 if (mode == SImode && (op == EQ || op == NE) && CONST_INT_P (y)
953 && ((INTVAL (y) - 1) & INTVAL (y)) == 0
954 && INTVAL (y))
955 return CC_Zmode;
956
957 /* Check if this is a test suitable for add / bmsk.f . */
958 if (mode == SImode && (op == EQ || op == NE) && CONST_INT_P (y)
959 && GET_CODE (x) == AND && CONST_INT_P ((x1 = XEXP (x, 1)))
960 && ((INTVAL (x1) + 1) & INTVAL (x1)) == 0
961 && (~INTVAL (x1) | INTVAL (y)) < 0
962 && (~INTVAL (x1) | INTVAL (y)) > -0x800)
963 return CC_Zmode;
964
965 if (GET_MODE (x) == SImode && (op == LTU || op == GEU)
966 && GET_CODE (x) == PLUS
967 && (rtx_equal_p (XEXP (x, 0), y) || rtx_equal_p (XEXP (x, 1), y)))
968 return CC_Cmode;
969
970 if (TARGET_ARGONAUT_SET
971 && ((mode == SFmode && TARGET_SPFP) || (mode == DFmode && TARGET_DPFP)))
972 switch (op)
973 {
974 case EQ: case NE: case UNEQ: case LTGT: case ORDERED: case UNORDERED:
975 return CC_FPXmode;
976 case LT: case UNGE: case GT: case UNLE:
977 return CC_FP_GTmode;
978 case LE: case UNGT: case GE: case UNLT:
979 return CC_FP_GEmode;
980 default: gcc_unreachable ();
981 }
982 else if (GET_MODE_CLASS (mode) == MODE_FLOAT && TARGET_OPTFPE)
983 switch (op)
984 {
985 case EQ: case NE: return CC_Zmode;
986 case LT: case UNGE:
987 case GT: case UNLE: return CC_FP_GTmode;
988 case LE: case UNGT:
989 case GE: case UNLT: return CC_FP_GEmode;
990 case UNEQ: case LTGT: return CC_FP_UNEQmode;
991 case ORDERED: case UNORDERED: return CC_FP_ORDmode;
992 default: gcc_unreachable ();
993 }
994
995 return CCmode;
996}
997
998/* Vectors to keep interesting information about registers where it can easily
999 be got. We use to use the actual mode value as the bit number, but there
1000 is (or may be) more than 32 modes now. Instead we use two tables: one
1001 indexed by hard register number, and one indexed by mode. */
1002
1003/* The purpose of arc_mode_class is to shrink the range of modes so that
1004 they all fit (as bit numbers) in a 32-bit word (again). Each real mode is
1005 mapped into one arc_mode_class mode. */
1006
1007enum arc_mode_class {
1008 C_MODE,
1009 S_MODE, D_MODE, T_MODE, O_MODE,
1010 SF_MODE, DF_MODE, TF_MODE, OF_MODE,
1011 V_MODE
1012};
1013
1014/* Modes for condition codes. */
1015#define C_MODES (1 << (int) C_MODE)
1016
1017/* Modes for single-word and smaller quantities. */
1018#define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
1019
1020/* Modes for double-word and smaller quantities. */
1021#define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))
1022
1023/* Mode for 8-byte DF values only. */
1024#define DF_MODES (1 << DF_MODE)
1025
1026/* Modes for quad-word and smaller quantities. */
1027#define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE))
1028
1029/* Modes for 128-bit vectors. */
1030#define V_MODES (1 << (int) V_MODE)
1031
1032/* Value is 1 if register/mode pair is acceptable on arc. */
1033
1034unsigned int arc_hard_regno_mode_ok[] = {
1035 T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES,
1036 T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES,
1037 T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, D_MODES,
1038 D_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
1039
1040 /* ??? Leave these as S_MODES for now. */
1041 S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
1042 DF_MODES, 0, DF_MODES, 0, S_MODES, S_MODES, S_MODES, S_MODES,
1043 S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
1044 S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, C_MODES, S_MODES,
1045
1046 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1047 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1048 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1049 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1050
1051 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1052 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1053 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1054 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1055
1056 S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
1057 S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES
1058};
1059
1060unsigned int arc_mode_class [NUM_MACHINE_MODES];
1061
1062enum reg_class arc_regno_reg_class[FIRST_PSEUDO_REGISTER];
1063
1064enum reg_class
1065arc_preferred_reload_class (rtx, enum reg_class cl)
1066{
1067 if ((cl) == CHEAP_CORE_REGS || (cl) == WRITABLE_CORE_REGS)
1068 return GENERAL_REGS;
1069 return cl;
1070}
1071
1072/* Initialize the arc_mode_class array. */
1073
1074static void
1075arc_init_reg_tables (void)
1076{
1077 int i;
1078
1079 for (i = 0; i < NUM_MACHINE_MODES; i++)
1080 {
1081 switch (GET_MODE_CLASS (i))
1082 {
1083 case MODE_INT:
1084 case MODE_PARTIAL_INT:
1085 case MODE_COMPLEX_INT:
1086 if (GET_MODE_SIZE (i) <= 4)
1087 arc_mode_class[i] = 1 << (int) S_MODE;
1088 else if (GET_MODE_SIZE (i) == 8)
1089 arc_mode_class[i] = 1 << (int) D_MODE;
1090 else if (GET_MODE_SIZE (i) == 16)
1091 arc_mode_class[i] = 1 << (int) T_MODE;
1092 else if (GET_MODE_SIZE (i) == 32)
1093 arc_mode_class[i] = 1 << (int) O_MODE;
1094 else
1095 arc_mode_class[i] = 0;
1096 break;
1097 case MODE_FLOAT:
1098 case MODE_COMPLEX_FLOAT:
1099 if (GET_MODE_SIZE (i) <= 4)
1100 arc_mode_class[i] = 1 << (int) SF_MODE;
1101 else if (GET_MODE_SIZE (i) == 8)
1102 arc_mode_class[i] = 1 << (int) DF_MODE;
1103 else if (GET_MODE_SIZE (i) == 16)
1104 arc_mode_class[i] = 1 << (int) TF_MODE;
1105 else if (GET_MODE_SIZE (i) == 32)
1106 arc_mode_class[i] = 1 << (int) OF_MODE;
1107 else
1108 arc_mode_class[i] = 0;
1109 break;
1110 case MODE_VECTOR_INT:
1111 arc_mode_class [i] = (1<< (int) V_MODE);
1112 break;
1113 case MODE_CC:
1114 default:
1115 /* mode_class hasn't been initialized yet for EXTRA_CC_MODES, so
1116 we must explicitly check for them here. */
1117 if (i == (int) CCmode || i == (int) CC_ZNmode || i == (int) CC_Zmode
1118 || i == (int) CC_Cmode
1119 || i == CC_FP_GTmode || i == CC_FP_GEmode || i == CC_FP_ORDmode)
1120 arc_mode_class[i] = 1 << (int) C_MODE;
1121 else
1122 arc_mode_class[i] = 0;
1123 break;
1124 }
1125 }
1126}
1127
1128/* Core registers 56..59 are used for multiply extension options.
1129 The dsp option uses r56 and r57, these are then named acc1 and acc2.
1130 acc1 is the highpart, and acc2 the lowpart, so which register gets which
1131 number depends on endianness.
1132 The mul64 multiplier options use r57 for mlo, r58 for mmid and r59 for mhi.
1133 Because mlo / mhi form a 64 bit value, we use different gcc internal
1134 register numbers to make them form a register pair as the gcc internals
1135 know it. mmid gets number 57, if still available, and mlo / mhi get
1136 number 58 and 59, depending on endianness. We use DBX_REGISTER_NUMBER
1137 to map this back. */
1138 char rname56[5] = "r56";
1139 char rname57[5] = "r57";
1140 char rname58[5] = "r58";
1141 char rname59[5] = "r59";
1142
1143static void
1144arc_conditional_register_usage (void)
1145{
1146 int regno;
1147 int i;
1148 int fix_start = 60, fix_end = 55;
1149
1150 if (TARGET_MUL64_SET)
1151 {
1152 fix_start = 57;
1153 fix_end = 59;
1154
1155 /* We don't provide a name for mmed. In rtl / assembly resource lists,
1156 you are supposed to refer to it as mlo & mhi, e.g
1157 (zero_extract:SI (reg:DI 58) (const_int 32) (16)) .
1158 In an actual asm instruction, you are of course use mmed.
1159 The point of avoiding having a separate register for mmed is that
1160 this way, we don't have to carry clobbers of that reg around in every
1161 isntruction that modifies mlo and/or mhi. */
1162 strcpy (rname57, "");
1163 strcpy (rname58, TARGET_BIG_ENDIAN ? "mhi" : "mlo");
1164 strcpy (rname59, TARGET_BIG_ENDIAN ? "mlo" : "mhi");
1165 }
1166 if (TARGET_MULMAC_32BY16_SET)
1167 {
1168 fix_start = 56;
1169 fix_end = fix_end > 57 ? fix_end : 57;
1170 strcpy (rname56, TARGET_BIG_ENDIAN ? "acc1" : "acc2");
1171 strcpy (rname57, TARGET_BIG_ENDIAN ? "acc2" : "acc1");
1172 }
1173 for (regno = fix_start; regno <= fix_end; regno++)
1174 {
1175 if (!fixed_regs[regno])
1176 warning (0, "multiply option implies r%d is fixed", regno);
1177 fixed_regs [regno] = call_used_regs[regno] = 1;
1178 }
1179 if (TARGET_Q_CLASS)
1180 {
1181 reg_alloc_order[2] = 12;
1182 reg_alloc_order[3] = 13;
1183 reg_alloc_order[4] = 14;
1184 reg_alloc_order[5] = 15;
1185 reg_alloc_order[6] = 1;
1186 reg_alloc_order[7] = 0;
1187 reg_alloc_order[8] = 4;
1188 reg_alloc_order[9] = 5;
1189 reg_alloc_order[10] = 6;
1190 reg_alloc_order[11] = 7;
1191 reg_alloc_order[12] = 8;
1192 reg_alloc_order[13] = 9;
1193 reg_alloc_order[14] = 10;
1194 reg_alloc_order[15] = 11;
1195 }
1196 if (TARGET_SIMD_SET)
1197 {
1198 int i;
6462fab0
JR
1199 for (i = ARC_FIRST_SIMD_VR_REG; i <= ARC_LAST_SIMD_VR_REG; i++)
1200 reg_alloc_order [i] = i;
1201 for (i = ARC_FIRST_SIMD_DMA_CONFIG_REG;
1202 i <= ARC_LAST_SIMD_DMA_CONFIG_REG; i++)
526b7aee
SV
1203 reg_alloc_order [i] = i;
1204 }
1205 /* For Arctangent-A5 / ARC600, lp_count may not be read in an instruction
1206 following immediately after another one setting it to a new value.
1207 There was some discussion on how to enforce scheduling constraints for
1208 processors with missing interlocks on the gcc mailing list:
1209 http://gcc.gnu.org/ml/gcc/2008-05/msg00021.html .
1210 However, we can't actually use this approach, because for ARC the
1211 delay slot scheduling pass is active, which runs after
1212 machine_dependent_reorg. */
1213 if (TARGET_ARC600)
1214 CLEAR_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], LP_COUNT);
1215 else if (!TARGET_ARC700)
1216 fixed_regs[LP_COUNT] = 1;
1217 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1218 if (!call_used_regs[regno])
1219 CLEAR_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], regno);
1220 for (regno = 32; regno < 60; regno++)
1221 if (!fixed_regs[regno])
1222 SET_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS], regno);
1223 if (TARGET_ARC700)
1224 {
1225 for (regno = 32; regno <= 60; regno++)
1226 CLEAR_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], regno);
1227
1228 /* If they have used -ffixed-lp_count, make sure it takes
1229 effect. */
1230 if (fixed_regs[LP_COUNT])
1231 {
1232 CLEAR_HARD_REG_BIT (reg_class_contents[LPCOUNT_REG], LP_COUNT);
1233 CLEAR_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], LP_COUNT);
1234 CLEAR_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS], LP_COUNT);
1235
1236 /* Instead of taking out SF_MODE like below, forbid it outright. */
1237 arc_hard_regno_mode_ok[60] = 0;
1238 }
1239 else
1240 arc_hard_regno_mode_ok[60] = 1 << (int) S_MODE;
1241 }
1242
1243 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1244 {
1245 if (i < 29)
1246 {
1247 if (TARGET_Q_CLASS && ((i <= 3) || ((i >= 12) && (i <= 15))))
1248 arc_regno_reg_class[i] = ARCOMPACT16_REGS;
1249 else
1250 arc_regno_reg_class[i] = GENERAL_REGS;
1251 }
1252 else if (i < 60)
1253 arc_regno_reg_class[i]
1254 = (fixed_regs[i]
1255 ? (TEST_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], i)
1256 ? CHEAP_CORE_REGS : ALL_CORE_REGS)
1257 : ((TARGET_ARC700
1258 && TEST_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], i))
1259 ? CHEAP_CORE_REGS : WRITABLE_CORE_REGS));
1260 else
1261 arc_regno_reg_class[i] = NO_REGS;
1262 }
1263
1264 /* ARCOMPACT16_REGS is empty, if TARGET_Q_CLASS has not been activated. */
1265 if (!TARGET_Q_CLASS)
1266 {
1267 CLEAR_HARD_REG_SET(reg_class_contents [ARCOMPACT16_REGS]);
1268 CLEAR_HARD_REG_SET(reg_class_contents [AC16_BASE_REGS]);
1269 }
1270
1271 gcc_assert (FIRST_PSEUDO_REGISTER >= 144);
1272
1273 /* Handle Special Registers. */
1274 arc_regno_reg_class[29] = LINK_REGS; /* ilink1 register. */
1275 arc_regno_reg_class[30] = LINK_REGS; /* ilink2 register. */
1276 arc_regno_reg_class[31] = LINK_REGS; /* blink register. */
1277 arc_regno_reg_class[60] = LPCOUNT_REG;
1278 arc_regno_reg_class[61] = NO_REGS; /* CC_REG: must be NO_REGS. */
1279 arc_regno_reg_class[62] = GENERAL_REGS;
1280
1281 if (TARGET_DPFP)
1282 {
1283 for (i = 40; i < 44; ++i)
1284 {
1285 arc_regno_reg_class[i] = DOUBLE_REGS;
1286
1287 /* Unless they want us to do 'mov d1, 0x00000000' make sure
1288 no attempt is made to use such a register as a destination
1289 operand in *movdf_insn. */
1290 if (!TARGET_ARGONAUT_SET)
1291 {
1292 /* Make sure no 'c', 'w', 'W', or 'Rac' constraint is
1293 interpreted to mean they can use D1 or D2 in their insn. */
1294 CLEAR_HARD_REG_BIT(reg_class_contents[CHEAP_CORE_REGS ], i);
1295 CLEAR_HARD_REG_BIT(reg_class_contents[ALL_CORE_REGS ], i);
1296 CLEAR_HARD_REG_BIT(reg_class_contents[WRITABLE_CORE_REGS ], i);
1297 CLEAR_HARD_REG_BIT(reg_class_contents[MPY_WRITABLE_CORE_REGS], i);
1298 }
1299 }
1300 }
1301 else
1302 {
1303 /* Disable all DOUBLE_REGISTER settings,
1304 if not generating DPFP code. */
1305 arc_regno_reg_class[40] = ALL_REGS;
1306 arc_regno_reg_class[41] = ALL_REGS;
1307 arc_regno_reg_class[42] = ALL_REGS;
1308 arc_regno_reg_class[43] = ALL_REGS;
1309
1310 arc_hard_regno_mode_ok[40] = 0;
1311 arc_hard_regno_mode_ok[42] = 0;
1312
1313 CLEAR_HARD_REG_SET(reg_class_contents [DOUBLE_REGS]);
1314 }
1315
1316 if (TARGET_SIMD_SET)
1317 {
1318 gcc_assert (ARC_FIRST_SIMD_VR_REG == 64);
1319 gcc_assert (ARC_LAST_SIMD_VR_REG == 127);
1320
1321 for (i = ARC_FIRST_SIMD_VR_REG; i <= ARC_LAST_SIMD_VR_REG; i++)
1322 arc_regno_reg_class [i] = SIMD_VR_REGS;
1323
1324 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_REG == 128);
1325 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_IN_REG == 128);
1326 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG == 136);
1327 gcc_assert (ARC_LAST_SIMD_DMA_CONFIG_REG == 143);
1328
1329 for (i = ARC_FIRST_SIMD_DMA_CONFIG_REG;
1330 i <= ARC_LAST_SIMD_DMA_CONFIG_REG; i++)
1331 arc_regno_reg_class [i] = SIMD_DMA_CONFIG_REGS;
1332 }
1333
1334 /* pc : r63 */
1335 arc_regno_reg_class[PROGRAM_COUNTER_REGNO] = GENERAL_REGS;
1336}
1337
1338/* Handle an "interrupt" attribute; arguments as in
1339 struct attribute_spec.handler. */
1340
1341static tree
1342arc_handle_interrupt_attribute (tree *, tree name, tree args, int,
1343 bool *no_add_attrs)
1344{
1345 gcc_assert (args);
1346
1347 tree value = TREE_VALUE (args);
1348
1349 if (TREE_CODE (value) != STRING_CST)
1350 {
1351 warning (OPT_Wattributes,
1352 "argument of %qE attribute is not a string constant",
1353 name);
1354 *no_add_attrs = true;
1355 }
1356 else if (strcmp (TREE_STRING_POINTER (value), "ilink1")
1357 && strcmp (TREE_STRING_POINTER (value), "ilink2"))
1358 {
1359 warning (OPT_Wattributes,
1360 "argument of %qE attribute is not \"ilink1\" or \"ilink2\"",
1361 name);
1362 *no_add_attrs = true;
1363 }
1364 return NULL_TREE;
1365}
1366
1367/* Return zero if TYPE1 and TYPE are incompatible, one if they are compatible,
1368 and two if they are nearly compatible (which causes a warning to be
1369 generated). */
1370
1371static int
1372arc_comp_type_attributes (const_tree type1,
1373 const_tree type2)
1374{
1375 int l1, l2, m1, m2, s1, s2;
1376
1377 /* Check for mismatch of non-default calling convention. */
1378 if (TREE_CODE (type1) != FUNCTION_TYPE)
1379 return 1;
1380
1381 /* Check for mismatched call attributes. */
1382 l1 = lookup_attribute ("long_call", TYPE_ATTRIBUTES (type1)) != NULL;
1383 l2 = lookup_attribute ("long_call", TYPE_ATTRIBUTES (type2)) != NULL;
1384 m1 = lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type1)) != NULL;
1385 m2 = lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type2)) != NULL;
1386 s1 = lookup_attribute ("short_call", TYPE_ATTRIBUTES (type1)) != NULL;
1387 s2 = lookup_attribute ("short_call", TYPE_ATTRIBUTES (type2)) != NULL;
1388
1389 /* Only bother to check if an attribute is defined. */
1390 if (l1 | l2 | m1 | m2 | s1 | s2)
1391 {
1392 /* If one type has an attribute, the other must have the same attribute. */
1393 if ((l1 != l2) || (m1 != m2) || (s1 != s2))
1394 return 0;
1395
1396 /* Disallow mixed attributes. */
1397 if (l1 + m1 + s1 > 1)
1398 return 0;
1399 }
1400
1401
1402 return 1;
1403}
1404
1405/* Set the default attributes for TYPE. */
1406
1407void
1408arc_set_default_type_attributes (tree type ATTRIBUTE_UNUSED)
1409{
1410 gcc_unreachable();
1411}
1412
1413/* Misc. utilities. */
1414
1415/* X and Y are two things to compare using CODE. Emit the compare insn and
1416 return the rtx for the cc reg in the proper mode. */
1417
1418rtx
1419gen_compare_reg (rtx comparison, enum machine_mode omode)
1420{
1421 enum rtx_code code = GET_CODE (comparison);
1422 rtx x = XEXP (comparison, 0);
1423 rtx y = XEXP (comparison, 1);
1424 rtx tmp, cc_reg;
1425 enum machine_mode mode, cmode;
1426
1427
1428 cmode = GET_MODE (x);
1429 if (cmode == VOIDmode)
1430 cmode = GET_MODE (y);
1431 gcc_assert (cmode == SImode || cmode == SFmode || cmode == DFmode);
1432 if (cmode == SImode)
1433 {
1434 if (!register_operand (x, SImode))
1435 {
1436 if (register_operand (y, SImode))
1437 {
1438 tmp = x;
1439 x = y;
1440 y = tmp;
1441 code = swap_condition (code);
1442 }
1443 else
1444 x = copy_to_mode_reg (SImode, x);
1445 }
1446 if (GET_CODE (y) == SYMBOL_REF && flag_pic)
1447 y = copy_to_mode_reg (SImode, y);
1448 }
1449 else
1450 {
1451 x = force_reg (cmode, x);
1452 y = force_reg (cmode, y);
1453 }
1454 mode = SELECT_CC_MODE (code, x, y);
1455
1456 cc_reg = gen_rtx_REG (mode, CC_REG);
1457
1458 /* ??? FIXME (x-y)==0, as done by both cmpsfpx_raw and
1459 cmpdfpx_raw, is not a correct comparison for floats:
1460 http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
1461 */
1462 if (TARGET_ARGONAUT_SET
1463 && ((cmode == SFmode && TARGET_SPFP) || (cmode == DFmode && TARGET_DPFP)))
1464 {
1465 switch (code)
1466 {
1467 case NE: case EQ: case LT: case UNGE: case LE: case UNGT:
1468 case UNEQ: case LTGT: case ORDERED: case UNORDERED:
1469 break;
1470 case GT: case UNLE: case GE: case UNLT:
1471 code = swap_condition (code);
1472 tmp = x;
1473 x = y;
1474 y = tmp;
1475 break;
1476 default:
1477 gcc_unreachable ();
1478 }
1479 if (cmode == SFmode)
1480 {
1481 emit_insn (gen_cmpsfpx_raw (x, y));
1482 }
1483 else /* DFmode */
1484 {
1485 /* Accepts Dx regs directly by insns. */
1486 emit_insn (gen_cmpdfpx_raw (x, y));
1487 }
1488
1489 if (mode != CC_FPXmode)
1490 emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
1491 gen_rtx_COMPARE (mode,
1492 gen_rtx_REG (CC_FPXmode, 61),
1493 const0_rtx)));
1494 }
1495 else if (GET_MODE_CLASS (cmode) == MODE_FLOAT && TARGET_OPTFPE)
1496 {
1497 rtx op0 = gen_rtx_REG (cmode, 0);
1498 rtx op1 = gen_rtx_REG (cmode, GET_MODE_SIZE (cmode) / UNITS_PER_WORD);
1499
1500 switch (code)
1501 {
1502 case NE: case EQ: case GT: case UNLE: case GE: case UNLT:
1503 case UNEQ: case LTGT: case ORDERED: case UNORDERED:
1504 break;
1505 case LT: case UNGE: case LE: case UNGT:
1506 code = swap_condition (code);
1507 tmp = x;
1508 x = y;
1509 y = tmp;
1510 break;
1511 default:
1512 gcc_unreachable ();
1513 }
1514 if (currently_expanding_to_rtl)
1515 {
1516 emit_move_insn (op0, x);
1517 emit_move_insn (op1, y);
1518 }
1519 else
1520 {
1521 gcc_assert (rtx_equal_p (op0, x));
1522 gcc_assert (rtx_equal_p (op1, y));
1523 }
1524 emit_insn (gen_cmp_float (cc_reg, gen_rtx_COMPARE (mode, op0, op1)));
1525 }
1526 else
1527 emit_insn (gen_rtx_SET (omode, cc_reg,
1528 gen_rtx_COMPARE (mode, x, y)));
1529 return gen_rtx_fmt_ee (code, omode, cc_reg, const0_rtx);
1530}
1531
1532/* Return true if VALUE, a const_double, will fit in a limm (4 byte number).
1533 We assume the value can be either signed or unsigned. */
1534
1535bool
1536arc_double_limm_p (rtx value)
1537{
1538 HOST_WIDE_INT low, high;
1539
1540 gcc_assert (GET_CODE (value) == CONST_DOUBLE);
1541
1542 if (TARGET_DPFP)
1543 return true;
1544
1545 low = CONST_DOUBLE_LOW (value);
1546 high = CONST_DOUBLE_HIGH (value);
1547
1548 if (low & 0x80000000)
1549 {
1550 return (((unsigned HOST_WIDE_INT) low <= 0xffffffff && high == 0)
1551 || (((low & - (unsigned HOST_WIDE_INT) 0x80000000)
1552 == - (unsigned HOST_WIDE_INT) 0x80000000)
1553 && high == -1));
1554 }
1555 else
1556 {
1557 return (unsigned HOST_WIDE_INT) low <= 0x7fffffff && high == 0;
1558 }
1559}
1560
1561/* Do any needed setup for a variadic function. For the ARC, we must
1562 create a register parameter block, and then copy any anonymous arguments
1563 in registers to memory.
1564
1565 CUM has not been updated for the last named argument which has type TYPE
1566 and mode MODE, and we rely on this fact. */
1567
1568static void
1569arc_setup_incoming_varargs (cumulative_args_t args_so_far,
1570 enum machine_mode mode, tree type,
1571 int *pretend_size, int no_rtl)
1572{
1573 int first_anon_arg;
1574 CUMULATIVE_ARGS next_cum;
1575
1576 /* We must treat `__builtin_va_alist' as an anonymous arg. */
1577
1578 next_cum = *get_cumulative_args (args_so_far);
1579 arc_function_arg_advance (pack_cumulative_args (&next_cum), mode, type, 1);
1580 first_anon_arg = next_cum;
1581
1582 if (first_anon_arg < MAX_ARC_PARM_REGS)
1583 {
1584 /* First anonymous (unnamed) argument is in a reg. */
1585
1586 /* Note that first_reg_offset < MAX_ARC_PARM_REGS. */
1587 int first_reg_offset = first_anon_arg;
1588
1589 if (!no_rtl)
1590 {
1591 rtx regblock
1592 = gen_rtx_MEM (BLKmode, plus_constant (Pmode, arg_pointer_rtx,
1593 FIRST_PARM_OFFSET (0)));
1594 move_block_from_reg (first_reg_offset, regblock,
1595 MAX_ARC_PARM_REGS - first_reg_offset);
1596 }
1597
1598 *pretend_size
1599 = ((MAX_ARC_PARM_REGS - first_reg_offset ) * UNITS_PER_WORD);
1600 }
1601}
1602
1603/* Cost functions. */
1604
1605/* Provide the costs of an addressing mode that contains ADDR.
1606 If ADDR is not a valid address, its cost is irrelevant. */
1607
1608int
1609arc_address_cost (rtx addr, enum machine_mode, addr_space_t, bool speed)
1610{
1611 switch (GET_CODE (addr))
1612 {
1613 case REG :
1614 return speed || satisfies_constraint_Rcq (addr) ? 0 : 1;
1615 case PRE_INC: case PRE_DEC: case POST_INC: case POST_DEC:
1616 case PRE_MODIFY: case POST_MODIFY:
1617 return !speed;
1618
1619 case LABEL_REF :
1620 case SYMBOL_REF :
1621 case CONST :
1622 /* Most likely needs a LIMM. */
1623 return COSTS_N_INSNS (1);
1624
1625 case PLUS :
1626 {
1627 register rtx plus0 = XEXP (addr, 0);
1628 register rtx plus1 = XEXP (addr, 1);
1629
1630 if (GET_CODE (plus0) != REG
1631 && (GET_CODE (plus0) != MULT
1632 || !CONST_INT_P (XEXP (plus0, 1))
1633 || (INTVAL (XEXP (plus0, 1)) != 2
1634 && INTVAL (XEXP (plus0, 1)) != 4)))
1635 break;
1636
1637 switch (GET_CODE (plus1))
1638 {
1639 case CONST_INT :
1640 return (!RTX_OK_FOR_OFFSET_P (SImode, plus1)
1641 ? COSTS_N_INSNS (1)
1642 : speed
1643 ? 0
1644 : (satisfies_constraint_Rcq (plus0)
1645 && satisfies_constraint_O (plus1))
1646 ? 0
1647 : 1);
1648 case REG:
1649 return (speed < 1 ? 0
1650 : (satisfies_constraint_Rcq (plus0)
1651 && satisfies_constraint_Rcq (plus1))
1652 ? 0 : 1);
1653 case CONST :
1654 case SYMBOL_REF :
1655 case LABEL_REF :
1656 return COSTS_N_INSNS (1);
1657 default:
1658 break;
1659 }
1660 break;
1661 }
1662 default:
1663 break;
1664 }
1665
1666 return 4;
1667}
1668
1669/* Emit instruction X with the frame related bit set. */
1670
1671static rtx
1672frame_insn (rtx x)
1673{
1674 x = emit_insn (x);
1675 RTX_FRAME_RELATED_P (x) = 1;
1676 return x;
1677}
1678
1679/* Emit a frame insn to move SRC to DST. */
1680
1681static rtx
1682frame_move (rtx dst, rtx src)
1683{
1684 return frame_insn (gen_rtx_SET (VOIDmode, dst, src));
1685}
1686
1687/* Like frame_move, but add a REG_INC note for REG if ADDR contains an
1688 auto increment address, or is zero. */
1689
1690static rtx
1691frame_move_inc (rtx dst, rtx src, rtx reg, rtx addr)
1692{
1693 rtx insn = frame_move (dst, src);
1694
1695 if (!addr
1696 || GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == POST_INC
1697 || GET_CODE (addr) == PRE_MODIFY || GET_CODE (addr) == POST_MODIFY)
1698 add_reg_note (insn, REG_INC, reg);
1699 return insn;
1700}
1701
1702/* Emit a frame insn which adjusts a frame address register REG by OFFSET. */
1703
1704static rtx
1705frame_add (rtx reg, HOST_WIDE_INT offset)
1706{
1707 gcc_assert ((offset & 0x3) == 0);
1708 if (!offset)
1709 return NULL_RTX;
1710 return frame_move (reg, plus_constant (Pmode, reg, offset));
1711}
1712
1713/* Emit a frame insn which adjusts stack pointer by OFFSET. */
1714
1715static rtx
1716frame_stack_add (HOST_WIDE_INT offset)
1717{
1718 return frame_add (stack_pointer_rtx, offset);
1719}
1720
1721/* Traditionally, we push saved registers first in the prologue,
1722 then we allocate the rest of the frame - and reverse in the epilogue.
1723 This has still its merits for ease of debugging, or saving code size
1724 or even execution time if the stack frame is so large that some accesses
1725 can't be encoded anymore with offsets in the instruction code when using
1726 a different scheme.
1727 Also, it would be a good starting point if we got instructions to help
1728 with register save/restore.
1729
1730 However, often stack frames are small, and the pushing / popping has
1731 some costs:
1732 - the stack modification prevents a lot of scheduling.
1733 - frame allocation / deallocation needs extra instructions.
1734 - unless we know that we compile ARC700 user code, we need to put
1735 a memory barrier after frame allocation / before deallocation to
1736 prevent interrupts clobbering our data in the frame.
1737 In particular, we don't have any such guarantees for library functions,
1738 which tend to, on the other hand, to have small frames.
1739
1740 Thus, for small frames, we'd like to use a different scheme:
1741 - The frame is allocated in full with the first prologue instruction,
1742 and deallocated in full with the last epilogue instruction.
1743 Thus, the instructions in-betwen can be freely scheduled.
1744 - If the function has no outgoing arguments on the stack, we can allocate
1745 one register save slot at the top of the stack. This register can then
1746 be saved simultanously with frame allocation, and restored with
1747 frame deallocation.
1748 This register can be picked depending on scheduling considerations,
1749 although same though should go into having some set of registers
1750 to be potentially lingering after a call, and others to be available
1751 immediately - i.e. in the absence of interprocedual optimization, we
1752 can use an ABI-like convention for register allocation to reduce
1753 stalls after function return. */
1754/* Function prologue/epilogue handlers. */
1755
1756/* ARCompact stack frames look like:
1757
1758 Before call After call
1759 high +-----------------------+ +-----------------------+
1760 mem | reg parm save area | | reg parm save area |
1761 | only created for | | only created for |
1762 | variable arg fns | | variable arg fns |
1763 AP +-----------------------+ +-----------------------+
1764 | return addr register | | return addr register |
1765 | (if required) | | (if required) |
1766 +-----------------------+ +-----------------------+
1767 | | | |
1768 | reg save area | | reg save area |
1769 | | | |
1770 +-----------------------+ +-----------------------+
1771 | frame pointer | | frame pointer |
1772 | (if required) | | (if required) |
1773 FP +-----------------------+ +-----------------------+
1774 | | | |
1775 | local/temp variables | | local/temp variables |
1776 | | | |
1777 +-----------------------+ +-----------------------+
1778 | | | |
1779 | arguments on stack | | arguments on stack |
1780 | | | |
1781 SP +-----------------------+ +-----------------------+
1782 | reg parm save area |
1783 | only created for |
1784 | variable arg fns |
1785 AP +-----------------------+
1786 | return addr register |
1787 | (if required) |
1788 +-----------------------+
1789 | |
1790 | reg save area |
1791 | |
1792 +-----------------------+
1793 | frame pointer |
1794 | (if required) |
1795 FP +-----------------------+
1796 | |
1797 | local/temp variables |
1798 | |
1799 +-----------------------+
1800 | |
1801 | arguments on stack |
1802 low | |
1803 mem SP +-----------------------+
1804
1805Notes:
18061) The "reg parm save area" does not exist for non variable argument fns.
1807 The "reg parm save area" can be eliminated completely if we created our
1808 own va-arc.h, but that has tradeoffs as well (so it's not done). */
1809
1810/* Structure to be filled in by arc_compute_frame_size with register
1811 save masks, and offsets for the current function. */
1812struct GTY (()) arc_frame_info
1813{
1814 unsigned int total_size; /* # bytes that the entire frame takes up. */
1815 unsigned int extra_size; /* # bytes of extra stuff. */
1816 unsigned int pretend_size; /* # bytes we push and pretend caller did. */
1817 unsigned int args_size; /* # bytes that outgoing arguments take up. */
1818 unsigned int reg_size; /* # bytes needed to store regs. */
1819 unsigned int var_size; /* # bytes that variables take up. */
1820 unsigned int reg_offset; /* Offset from new sp to store regs. */
1821 unsigned int gmask; /* Mask of saved gp registers. */
1822 int initialized; /* Nonzero if frame size already calculated. */
1823 short millicode_start_reg;
1824 short millicode_end_reg;
1825 bool save_return_addr;
1826};
1827
1828/* Defining data structures for per-function information. */
1829
1830typedef struct GTY (()) machine_function
1831{
1832 enum arc_function_type fn_type;
1833 struct arc_frame_info frame_info;
1834 /* To keep track of unalignment caused by short insns. */
1835 int unalign;
1836 int force_short_suffix; /* Used when disgorging return delay slot insns. */
1837 const char *size_reason;
1838 struct arc_ccfsm ccfsm_current;
1839 /* Map from uid to ccfsm state during branch shortening. */
1840 rtx ccfsm_current_insn;
1841 char arc_reorg_started;
1842 char prescan_initialized;
1843} machine_function;
1844
1845/* Type of function DECL.
1846
1847 The result is cached. To reset the cache at the end of a function,
1848 call with DECL = NULL_TREE. */
1849
1850enum arc_function_type
1851arc_compute_function_type (struct function *fun)
1852{
1853 tree decl = fun->decl;
1854 tree a;
1855 enum arc_function_type fn_type = fun->machine->fn_type;
1856
1857 if (fn_type != ARC_FUNCTION_UNKNOWN)
1858 return fn_type;
1859
1860 /* Assume we have a normal function (not an interrupt handler). */
1861 fn_type = ARC_FUNCTION_NORMAL;
1862
1863 /* Now see if this is an interrupt handler. */
1864 for (a = DECL_ATTRIBUTES (decl);
1865 a;
1866 a = TREE_CHAIN (a))
1867 {
1868 tree name = TREE_PURPOSE (a), args = TREE_VALUE (a);
1869
1870 if (name == get_identifier ("interrupt")
1871 && list_length (args) == 1
1872 && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
1873 {
1874 tree value = TREE_VALUE (args);
1875
1876 if (!strcmp (TREE_STRING_POINTER (value), "ilink1"))
1877 fn_type = ARC_FUNCTION_ILINK1;
1878 else if (!strcmp (TREE_STRING_POINTER (value), "ilink2"))
1879 fn_type = ARC_FUNCTION_ILINK2;
1880 else
1881 gcc_unreachable ();
1882 break;
1883 }
1884 }
1885
1886 return fun->machine->fn_type = fn_type;
1887}
1888
1889#define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
1890#define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM))
1891
1892/* Tell prologue and epilogue if register REGNO should be saved / restored.
1893 The return address and frame pointer are treated separately.
1894 Don't consider them here.
1895 Addition for pic: The gp register needs to be saved if the current
1896 function changes it to access gotoff variables.
1897 FIXME: This will not be needed if we used some arbitrary register
1898 instead of r26.
1899*/
1900#define MUST_SAVE_REGISTER(regno, interrupt_p) \
1901(((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \
1902 && (df_regs_ever_live_p (regno) && (!call_used_regs[regno] || interrupt_p))) \
1903 || (flag_pic && crtl->uses_pic_offset_table \
1904 && regno == PIC_OFFSET_TABLE_REGNUM) )
1905
1906#define MUST_SAVE_RETURN_ADDR \
1907 (cfun->machine->frame_info.save_return_addr)
1908
1909/* Return non-zero if there are registers to be saved or loaded using
1910 millicode thunks. We can only use consecutive sequences starting
1911 with r13, and not going beyond r25.
1912 GMASK is a bitmask of registers to save. This function sets
1913 FRAME->millicod_start_reg .. FRAME->millicode_end_reg to the range
1914 of registers to be saved / restored with a millicode call. */
1915
1916static int
1917arc_compute_millicode_save_restore_regs (unsigned int gmask,
1918 struct arc_frame_info *frame)
1919{
1920 int regno;
1921
1922 int start_reg = 13, end_reg = 25;
1923
1924 for (regno = start_reg; regno <= end_reg && (gmask & (1L << regno));)
1925 regno++;
1926 end_reg = regno - 1;
1927 /* There is no point in using millicode thunks if we don't save/restore
1928 at least three registers. For non-leaf functions we also have the
1929 blink restore. */
1930 if (regno - start_reg >= 3 - (crtl->is_leaf == 0))
1931 {
1932 frame->millicode_start_reg = 13;
1933 frame->millicode_end_reg = regno - 1;
1934 return 1;
1935 }
1936 return 0;
1937}
1938
1939/* Return the bytes needed to compute the frame pointer from the current
1940 stack pointer.
1941
1942 SIZE is the size needed for local variables. */
1943
1944unsigned int
1945arc_compute_frame_size (int size) /* size = # of var. bytes allocated. */
1946{
1947 int regno;
1948 unsigned int total_size, var_size, args_size, pretend_size, extra_size;
1949 unsigned int reg_size, reg_offset;
1950 unsigned int gmask;
1951 enum arc_function_type fn_type;
1952 int interrupt_p;
1953 struct arc_frame_info *frame_info = &cfun->machine->frame_info;
1954
1955 size = ARC_STACK_ALIGN (size);
1956
1957 /* 1) Size of locals and temporaries */
1958 var_size = size;
1959
1960 /* 2) Size of outgoing arguments */
1961 args_size = crtl->outgoing_args_size;
1962
1963 /* 3) Calculate space needed for saved registers.
1964 ??? We ignore the extension registers for now. */
1965
1966 /* See if this is an interrupt handler. Call used registers must be saved
1967 for them too. */
1968
1969 reg_size = 0;
1970 gmask = 0;
1971 fn_type = arc_compute_function_type (cfun);
1972 interrupt_p = ARC_INTERRUPT_P (fn_type);
1973
1974 for (regno = 0; regno <= 31; regno++)
1975 {
1976 if (MUST_SAVE_REGISTER (regno, interrupt_p))
1977 {
1978 reg_size += UNITS_PER_WORD;
1979 gmask |= 1 << regno;
1980 }
1981 }
1982
1983 /* 4) Space for back trace data structure.
1984 <return addr reg size> (if required) + <fp size> (if required). */
1985 frame_info->save_return_addr
1986 = (!crtl->is_leaf || df_regs_ever_live_p (RETURN_ADDR_REGNUM));
1987 /* Saving blink reg in case of leaf function for millicode thunk calls. */
1988 if (optimize_size && !TARGET_NO_MILLICODE_THUNK_SET)
1989 {
1990 if (arc_compute_millicode_save_restore_regs (gmask, frame_info))
1991 frame_info->save_return_addr = true;
1992 }
1993
1994 extra_size = 0;
1995 if (MUST_SAVE_RETURN_ADDR)
1996 extra_size = 4;
1997 if (frame_pointer_needed)
1998 extra_size += 4;
1999
2000 /* 5) Space for variable arguments passed in registers */
2001 pretend_size = crtl->args.pretend_args_size;
2002
2003 /* Ensure everything before the locals is aligned appropriately. */
2004 {
2005 unsigned int extra_plus_reg_size;
2006 unsigned int extra_plus_reg_size_aligned;
2007
2008 extra_plus_reg_size = extra_size + reg_size;
2009 extra_plus_reg_size_aligned = ARC_STACK_ALIGN(extra_plus_reg_size);
2010 reg_size = extra_plus_reg_size_aligned - extra_size;
2011 }
2012
2013 /* Compute total frame size. */
2014 total_size = var_size + args_size + extra_size + pretend_size + reg_size;
2015
2016 total_size = ARC_STACK_ALIGN (total_size);
2017
2018 /* Compute offset of register save area from stack pointer:
2019 A5 Frame: pretend_size <blink> reg_size <fp> var_size args_size <--sp
2020 */
2021 reg_offset = (total_size - (pretend_size + reg_size + extra_size)
2022 + (frame_pointer_needed ? 4 : 0));
2023
2024 /* Save computed information. */
2025 frame_info->total_size = total_size;
2026 frame_info->extra_size = extra_size;
2027 frame_info->pretend_size = pretend_size;
2028 frame_info->var_size = var_size;
2029 frame_info->args_size = args_size;
2030 frame_info->reg_size = reg_size;
2031 frame_info->reg_offset = reg_offset;
2032 frame_info->gmask = gmask;
2033 frame_info->initialized = reload_completed;
2034
2035 /* Ok, we're done. */
2036 return total_size;
2037}
2038
2039/* Common code to save/restore registers. */
2040/* BASE_REG is the base register to use for addressing and to adjust.
2041 GMASK is a bitmask of general purpose registers to save/restore.
2042 epilogue_p 0: prologue 1:epilogue 2:epilogue, sibling thunk
2043 If *FIRST_OFFSET is non-zero, add it first to BASE_REG - preferably
2044 using a pre-modify for the first memory access. *FIRST_OFFSET is then
2045 zeroed. */
2046
2047static void
2048arc_save_restore (rtx base_reg,
2049 unsigned int gmask, int epilogue_p, int *first_offset)
2050{
2051 unsigned int offset = 0;
2052 int regno;
2053 struct arc_frame_info *frame = &cfun->machine->frame_info;
2054 rtx sibthunk_insn = NULL_RTX;
2055
2056 if (gmask)
2057 {
2058 /* Millicode thunks implementation:
2059 Generates calls to millicodes for registers starting from r13 to r25
2060 Present Limitations:
2061 - Only one range supported. The remaining regs will have the ordinary
2062 st and ld instructions for store and loads. Hence a gmask asking
2063 to store r13-14, r16-r25 will only generate calls to store and
2064 load r13 to r14 while store and load insns will be generated for
2065 r16 to r25 in the prologue and epilogue respectively.
2066
2067 - Presently library only supports register ranges starting from r13.
2068 */
2069 if (epilogue_p == 2 || frame->millicode_end_reg > 14)
2070 {
2071 int start_call = frame->millicode_start_reg;
2072 int end_call = frame->millicode_end_reg;
2073 int n_regs = end_call - start_call + 1;
2074 int i = 0, r, off = 0;
2075 rtx insn;
2076 rtx ret_addr = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
2077
2078 if (*first_offset)
2079 {
2080 /* "reg_size" won't be more than 127 . */
2081 gcc_assert (epilogue_p || abs (*first_offset <= 127));
2082 frame_add (base_reg, *first_offset);
2083 *first_offset = 0;
2084 }
2085 insn = gen_rtx_PARALLEL
2086 (VOIDmode, rtvec_alloc ((epilogue_p == 2) + n_regs + 1));
2087 if (epilogue_p == 2)
2088 i += 2;
2089 else
2090 XVECEXP (insn, 0, n_regs) = gen_rtx_CLOBBER (VOIDmode, ret_addr);
2091 for (r = start_call; r <= end_call; r++, off += UNITS_PER_WORD, i++)
2092 {
2093 rtx reg = gen_rtx_REG (SImode, r);
2094 rtx mem
2095 = gen_frame_mem (SImode, plus_constant (Pmode, base_reg, off));
2096
2097 if (epilogue_p)
2098 XVECEXP (insn, 0, i) = gen_rtx_SET (VOIDmode, reg, mem);
2099 else
2100 XVECEXP (insn, 0, i) = gen_rtx_SET (VOIDmode, mem, reg);
2101 gmask = gmask & ~(1L << r);
2102 }
2103 if (epilogue_p == 2)
2104 sibthunk_insn = insn;
2105 else
2106 frame_insn (insn);
2107 offset += off;
2108 }
2109
2110 for (regno = 0; regno <= 31; regno++)
2111 {
2112 if ((gmask & (1L << regno)) != 0)
2113 {
2114 rtx reg = gen_rtx_REG (SImode, regno);
2115 rtx addr, mem;
2116
2117 if (*first_offset)
2118 {
2119 gcc_assert (!offset);
2120 addr = plus_constant (Pmode, base_reg, *first_offset);
2121 addr = gen_rtx_PRE_MODIFY (Pmode, base_reg, addr);
2122 *first_offset = 0;
2123 }
2124 else
2125 {
2126 gcc_assert (SMALL_INT (offset));
2127 addr = plus_constant (Pmode, base_reg, offset);
2128 }
2129 mem = gen_frame_mem (SImode, addr);
2130 if (epilogue_p)
2131 frame_move_inc (reg, mem, base_reg, addr);
2132 else
2133 frame_move_inc (mem, reg, base_reg, addr);
2134 offset += UNITS_PER_WORD;
2135 } /* if */
2136 } /* for */
2137 }/* if */
2138 if (sibthunk_insn)
2139 {
2140 rtx r12 = gen_rtx_REG (Pmode, 12);
2141
2142 frame_insn (gen_rtx_SET (VOIDmode, r12, GEN_INT (offset)));
2143 XVECEXP (sibthunk_insn, 0, 0) = ret_rtx;
2144 XVECEXP (sibthunk_insn, 0, 1)
2145 = gen_rtx_SET (VOIDmode, stack_pointer_rtx,
2146 gen_rtx_PLUS (Pmode, stack_pointer_rtx, r12));
2147 sibthunk_insn = emit_jump_insn (sibthunk_insn);
2148 RTX_FRAME_RELATED_P (sibthunk_insn) = 1;
2149 }
2150} /* arc_save_restore */
2151
2152
2153int arc_return_address_regs[4]
2154 = {0, RETURN_ADDR_REGNUM, ILINK1_REGNUM, ILINK2_REGNUM};
2155
2156/* Set up the stack and frame pointer (if desired) for the function. */
2157
2158void
2159arc_expand_prologue (void)
2160{
2161 int size = get_frame_size ();
2162 unsigned int gmask = cfun->machine->frame_info.gmask;
2163 /* unsigned int frame_pointer_offset;*/
2164 unsigned int frame_size_to_allocate;
2165 /* (FIXME: The first store will use a PRE_MODIFY; this will usually be r13.
2166 Change the stack layout so that we rather store a high register with the
2167 PRE_MODIFY, thus enabling more short insn generation.) */
2168 int first_offset = 0;
2169
2170 size = ARC_STACK_ALIGN (size);
2171
2172 /* Compute/get total frame size. */
2173 size = (!cfun->machine->frame_info.initialized
2174 ? arc_compute_frame_size (size)
2175 : cfun->machine->frame_info.total_size);
2176
2177 if (flag_stack_usage_info)
2178 current_function_static_stack_size = size;
2179
2180 /* Keep track of frame size to be allocated. */
2181 frame_size_to_allocate = size;
2182
2183 /* These cases shouldn't happen. Catch them now. */
2184 gcc_assert (!(size == 0 && gmask));
2185
2186 /* Allocate space for register arguments if this is a variadic function. */
2187 if (cfun->machine->frame_info.pretend_size != 0)
2188 {
2189 /* Ensure pretend_size is maximum of 8 * word_size. */
2190 gcc_assert (cfun->machine->frame_info.pretend_size <= 32);
2191
2192 frame_stack_add (-(HOST_WIDE_INT)cfun->machine->frame_info.pretend_size);
2193 frame_size_to_allocate -= cfun->machine->frame_info.pretend_size;
2194 }
2195
2196 /* The home-grown ABI says link register is saved first. */
2197 if (MUST_SAVE_RETURN_ADDR)
2198 {
2199 rtx ra = gen_rtx_REG (SImode, RETURN_ADDR_REGNUM);
2200 rtx mem = gen_frame_mem (Pmode, gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
2201
2202 frame_move_inc (mem, ra, stack_pointer_rtx, 0);
2203 frame_size_to_allocate -= UNITS_PER_WORD;
2204
2205 } /* MUST_SAVE_RETURN_ADDR */
2206
2207 /* Save any needed call-saved regs (and call-used if this is an
2208 interrupt handler) for ARCompact ISA. */
2209 if (cfun->machine->frame_info.reg_size)
2210 {
2211 first_offset = -cfun->machine->frame_info.reg_size;
2212 /* N.B. FRAME_POINTER_MASK and RETURN_ADDR_MASK are cleared in gmask. */
2213 arc_save_restore (stack_pointer_rtx, gmask, 0, &first_offset);
2214 frame_size_to_allocate -= cfun->machine->frame_info.reg_size;
2215 }
2216
2217
2218 /* Save frame pointer if needed. */
2219 if (frame_pointer_needed)
2220 {
2221 rtx addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
2222 GEN_INT (-UNITS_PER_WORD + first_offset));
2223 rtx mem = gen_frame_mem (Pmode, gen_rtx_PRE_MODIFY (Pmode,
2224 stack_pointer_rtx,
2225 addr));
2226 frame_move_inc (mem, frame_pointer_rtx, stack_pointer_rtx, 0);
2227 frame_size_to_allocate -= UNITS_PER_WORD;
2228 first_offset = 0;
2229 frame_move (frame_pointer_rtx, stack_pointer_rtx);
2230 }
2231
2232 /* ??? We don't handle the case where the saved regs are more than 252
2233 bytes away from sp. This can be handled by decrementing sp once, saving
2234 the regs, and then decrementing it again. The epilogue doesn't have this
2235 problem as the `ld' insn takes reg+limm values (though it would be more
2236 efficient to avoid reg+limm). */
2237
2238 frame_size_to_allocate -= first_offset;
2239 /* Allocate the stack frame. */
2240 if (frame_size_to_allocate > 0)
2241 frame_stack_add ((HOST_WIDE_INT) 0 - frame_size_to_allocate);
2242
2243 /* Setup the gp register, if needed. */
2244 if (crtl->uses_pic_offset_table)
2245 arc_finalize_pic ();
2246}
2247
2248/* Do any necessary cleanup after a function to restore stack, frame,
2249 and regs. */
2250
2251void
2252arc_expand_epilogue (int sibcall_p)
2253{
2254 int size = get_frame_size ();
2255 enum arc_function_type fn_type = arc_compute_function_type (cfun);
2256
2257 size = ARC_STACK_ALIGN (size);
2258 size = (!cfun->machine->frame_info.initialized
2259 ? arc_compute_frame_size (size)
2260 : cfun->machine->frame_info.total_size);
2261
2262 if (1)
2263 {
2264 unsigned int pretend_size = cfun->machine->frame_info.pretend_size;
2265 unsigned int frame_size;
2266 unsigned int size_to_deallocate;
2267 int restored;
2268#if 0
2269 bool fp_restored_p;
2270#endif
2271 int can_trust_sp_p = !cfun->calls_alloca;
2272 int first_offset = 0;
2273 int millicode_p = cfun->machine->frame_info.millicode_end_reg > 0;
2274
2275 size_to_deallocate = size;
2276
2277 frame_size = size - (pretend_size +
2278 cfun->machine->frame_info.reg_size +
2279 cfun->machine->frame_info.extra_size);
2280
2281 /* ??? There are lots of optimizations that can be done here.
2282 EG: Use fp to restore regs if it's closer.
2283 Maybe in time we'll do them all. For now, always restore regs from
2284 sp, but don't restore sp if we don't have to. */
2285
2286 if (!can_trust_sp_p)
2287 gcc_assert (frame_pointer_needed);
2288
2289 /* Restore stack pointer to the beginning of saved register area for
2290 ARCompact ISA. */
2291 if (frame_size)
2292 {
2293 if (frame_pointer_needed)
2294 frame_move (stack_pointer_rtx, frame_pointer_rtx);
2295 else
2296 first_offset = frame_size;
2297 size_to_deallocate -= frame_size;
2298 }
2299 else if (!can_trust_sp_p)
2300 frame_stack_add (-frame_size);
2301
2302
2303 /* Restore any saved registers. */
2304 if (frame_pointer_needed)
2305 {
2306 rtx addr = gen_rtx_POST_INC (Pmode, stack_pointer_rtx);
2307
2308 frame_move_inc (frame_pointer_rtx, gen_frame_mem (Pmode, addr),
2309 stack_pointer_rtx, 0);
2310 size_to_deallocate -= UNITS_PER_WORD;
2311 }
2312
2313 /* Load blink after the calls to thunk calls in case of optimize size. */
2314 if (millicode_p)
2315 {
2316 int sibthunk_p = (!sibcall_p
2317 && fn_type == ARC_FUNCTION_NORMAL
2318 && !cfun->machine->frame_info.pretend_size);
2319
2320 gcc_assert (!(cfun->machine->frame_info.gmask
2321 & (FRAME_POINTER_MASK | RETURN_ADDR_MASK)));
2322 arc_save_restore (stack_pointer_rtx,
2323 cfun->machine->frame_info.gmask,
2324 1 + sibthunk_p, &first_offset);
2325 if (sibthunk_p)
2326 goto epilogue_done;
2327 }
2328 /* If we are to restore registers, and first_offset would require
2329 a limm to be encoded in a PRE_MODIFY, yet we can add it with a
2330 fast add to the stack pointer, do this now. */
2331 if ((!SMALL_INT (first_offset)
2332 && cfun->machine->frame_info.gmask
2333 && ((TARGET_ARC700 && !optimize_size)
2334 ? first_offset <= 0x800
2335 : satisfies_constraint_C2a (GEN_INT (first_offset))))
2336 /* Also do this if we have both gprs and return
2337 address to restore, and they both would need a LIMM. */
2338 || (MUST_SAVE_RETURN_ADDR
2339 && !SMALL_INT ((cfun->machine->frame_info.reg_size + first_offset) >> 2)
2340 && cfun->machine->frame_info.gmask))
2341 {
2342 frame_stack_add (first_offset);
2343 first_offset = 0;
2344 }
2345 if (MUST_SAVE_RETURN_ADDR)
2346 {
2347 rtx ra = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
2348 int ra_offs = cfun->machine->frame_info.reg_size + first_offset;
2349 rtx addr = plus_constant (Pmode, stack_pointer_rtx, ra_offs);
2350
2351 /* If the load of blink would need a LIMM, but we can add
2352 the offset quickly to sp, do the latter. */
2353 if (!SMALL_INT (ra_offs >> 2)
2354 && !cfun->machine->frame_info.gmask
2355 && ((TARGET_ARC700 && !optimize_size)
2356 ? ra_offs <= 0x800
2357 : satisfies_constraint_C2a (GEN_INT (ra_offs))))
2358 {
2359 size_to_deallocate -= ra_offs - first_offset;
2360 first_offset = 0;
2361 frame_stack_add (ra_offs);
2362 ra_offs = 0;
2363 addr = stack_pointer_rtx;
2364 }
2365 /* See if we can combine the load of the return address with the
2366 final stack adjustment.
2367 We need a separate load if there are still registers to
2368 restore. We also want a separate load if the combined insn
2369 would need a limm, but a separate load doesn't. */
2370 if (ra_offs
2371 && !cfun->machine->frame_info.gmask
2372 && (SMALL_INT (ra_offs) || !SMALL_INT (ra_offs >> 2)))
2373 {
2374 addr = gen_rtx_PRE_MODIFY (Pmode, stack_pointer_rtx, addr);
2375 first_offset = 0;
2376 size_to_deallocate -= cfun->machine->frame_info.reg_size;
2377 }
2378 else if (!ra_offs && size_to_deallocate == UNITS_PER_WORD)
2379 {
2380 addr = gen_rtx_POST_INC (Pmode, addr);
2381 size_to_deallocate = 0;
2382 }
2383 frame_move_inc (ra, gen_frame_mem (Pmode, addr), stack_pointer_rtx, addr);
2384 }
2385
2386 if (!millicode_p)
2387 {
2388 if (cfun->machine->frame_info.reg_size)
2389 arc_save_restore (stack_pointer_rtx,
2390 /* The zeroing of these two bits is unnecessary, but leave this in for clarity. */
2391 cfun->machine->frame_info.gmask
2392 & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK), 1, &first_offset);
2393 }
2394
2395
2396 /* The rest of this function does the following:
2397 ARCompact : handle epilogue_delay, restore sp (phase-2), return
2398 */
2399
2400 /* Keep track of how much of the stack pointer we've restored.
2401 It makes the following a lot more readable. */
2402 size_to_deallocate += first_offset;
2403 restored = size - size_to_deallocate;
2404#if 0
2405 fp_restored_p = 1;
2406#endif
2407
2408 if (size > restored)
2409 frame_stack_add (size - restored);
2410 /* Emit the return instruction. */
2411 if (sibcall_p == FALSE)
2412 emit_jump_insn (gen_simple_return ());
2413 }
2414 epilogue_done:
2415 if (!TARGET_EPILOGUE_CFI)
2416 {
2417 rtx insn;
2418
2419 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2420 RTX_FRAME_RELATED_P (insn) = 0;
2421 }
2422}
2423
2424/* Return the offset relative to the stack pointer where the return address
2425 is stored, or -1 if it is not stored. */
2426
2427int
2428arc_return_slot_offset ()
2429{
2430 struct arc_frame_info *afi = &cfun->machine->frame_info;
2431
2432 return (afi->save_return_addr
2433 ? afi->total_size - afi->pretend_size - afi->extra_size : -1);
2434}
2435
2436/* PIC */
2437
2438/* Emit special PIC prologues and epilogues. */
2439/* If the function has any GOTOFF relocations, then the GOTBASE
2440 register has to be setup in the prologue
2441 The instruction needed at the function start for setting up the
2442 GOTBASE register is
2443 add rdest, pc,
2444 ----------------------------------------------------------
2445 The rtl to be emitted for this should be:
2446 set (reg basereg)
2447 (plus (reg pc)
2448 (const (unspec (symref _DYNAMIC) 3)))
2449 ---------------------------------------------------------- */
2450
2451static void
2452arc_finalize_pic (void)
2453{
2454 rtx pat;
2455 rtx baseptr_rtx = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
2456
2457 if (crtl->uses_pic_offset_table == 0)
2458 return;
2459
2460 gcc_assert (flag_pic != 0);
2461
2462 pat = gen_rtx_SYMBOL_REF (Pmode, "_DYNAMIC");
2463 pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, pat), ARC_UNSPEC_GOT);
2464 pat = gen_rtx_CONST (Pmode, pat);
2465
2466 pat = gen_rtx_SET (VOIDmode, baseptr_rtx, pat);
2467
2468 emit_insn (pat);
2469}
2470\f
2471/* !TARGET_BARREL_SHIFTER support. */
2472/* Emit a shift insn to set OP0 to OP1 shifted by OP2; CODE specifies what
2473 kind of shift. */
2474
2475void
2476emit_shift (enum rtx_code code, rtx op0, rtx op1, rtx op2)
2477{
2478 rtx shift = gen_rtx_fmt_ee (code, SImode, op1, op2);
2479 rtx pat
2480 = ((shift4_operator (shift, SImode) ? gen_shift_si3 : gen_shift_si3_loop)
2481 (op0, op1, op2, shift));
2482 emit_insn (pat);
2483}
2484
2485/* Output the assembler code for doing a shift.
2486 We go to a bit of trouble to generate efficient code as the ARC601 only has
2487 single bit shifts. This is taken from the h8300 port. We only have one
2488 mode of shifting and can't access individual bytes like the h8300 can, so
2489 this is greatly simplified (at the expense of not generating hyper-
2490 efficient code).
2491
2492 This function is not used if the variable shift insns are present. */
2493
2494/* FIXME: This probably can be done using a define_split in arc.md.
2495 Alternately, generate rtx rather than output instructions. */
2496
2497const char *
2498output_shift (rtx *operands)
2499{
2500 /* static int loopend_lab;*/
2501 rtx shift = operands[3];
2502 enum machine_mode mode = GET_MODE (shift);
2503 enum rtx_code code = GET_CODE (shift);
2504 const char *shift_one;
2505
2506 gcc_assert (mode == SImode);
2507
2508 switch (code)
2509 {
2510 case ASHIFT: shift_one = "add %0,%1,%1"; break;
2511 case ASHIFTRT: shift_one = "asr %0,%1"; break;
2512 case LSHIFTRT: shift_one = "lsr %0,%1"; break;
2513 default: gcc_unreachable ();
2514 }
2515
2516 if (GET_CODE (operands[2]) != CONST_INT)
2517 {
2518 output_asm_insn ("and.f lp_count,%2, 0x1f", operands);
2519 goto shiftloop;
2520 }
2521 else
2522 {
2523 int n;
2524
2525 n = INTVAL (operands[2]);
2526
2527 /* Only consider the lower 5 bits of the shift count. */
2528 n = n & 0x1f;
2529
2530 /* First see if we can do them inline. */
2531 /* ??? We could get better scheduling & shorter code (using short insns)
2532 by using splitters. Alas, that'd be even more verbose. */
2533 if (code == ASHIFT && n <= 9 && n > 2
2534 && dest_reg_operand (operands[4], SImode))
2535 {
2536 output_asm_insn ("mov %4,0\n\tadd3 %0,%4,%1", operands);
2537 for (n -=3 ; n >= 3; n -= 3)
2538 output_asm_insn ("add3 %0,%4,%0", operands);
2539 if (n == 2)
2540 output_asm_insn ("add2 %0,%4,%0", operands);
2541 else if (n)
2542 output_asm_insn ("add %0,%0,%0", operands);
2543 }
2544 else if (n <= 4)
2545 {
2546 while (--n >= 0)
2547 {
2548 output_asm_insn (shift_one, operands);
2549 operands[1] = operands[0];
2550 }
2551 }
2552 /* See if we can use a rotate/and. */
2553 else if (n == BITS_PER_WORD - 1)
2554 {
2555 switch (code)
2556 {
2557 case ASHIFT :
2558 output_asm_insn ("and %0,%1,1\n\tror %0,%0", operands);
2559 break;
2560 case ASHIFTRT :
2561 /* The ARC doesn't have a rol insn. Use something else. */
2562 output_asm_insn ("add.f 0,%1,%1\n\tsbc %0,%0,%0", operands);
2563 break;
2564 case LSHIFTRT :
2565 /* The ARC doesn't have a rol insn. Use something else. */
2566 output_asm_insn ("add.f 0,%1,%1\n\trlc %0,0", operands);
2567 break;
2568 default:
2569 break;
2570 }
2571 }
2572 else if (n == BITS_PER_WORD - 2 && dest_reg_operand (operands[4], SImode))
2573 {
2574 switch (code)
2575 {
2576 case ASHIFT :
2577 output_asm_insn ("and %0,%1,3\n\tror %0,%0\n\tror %0,%0", operands);
2578 break;
2579 case ASHIFTRT :
2580#if 1 /* Need some scheduling comparisons. */
2581 output_asm_insn ("add.f %4,%1,%1\n\tsbc %0,%0,%0\n\t"
2582 "add.f 0,%4,%4\n\trlc %0,%0", operands);
2583#else
2584 output_asm_insn ("add.f %4,%1,%1\n\tbxor %0,%4,31\n\t"
2585 "sbc.f %0,%0,%4\n\trlc %0,%0", operands);
2586#endif
2587 break;
2588 case LSHIFTRT :
2589#if 1
2590 output_asm_insn ("add.f %4,%1,%1\n\trlc %0,0\n\t"
2591 "add.f 0,%4,%4\n\trlc %0,%0", operands);
2592#else
2593 output_asm_insn ("add.f %0,%1,%1\n\trlc.f %0,0\n\t"
2594 "and %0,%0,1\n\trlc %0,%0", operands);
2595#endif
2596 break;
2597 default:
2598 break;
2599 }
2600 }
2601 else if (n == BITS_PER_WORD - 3 && code == ASHIFT)
2602 output_asm_insn ("and %0,%1,7\n\tror %0,%0\n\tror %0,%0\n\tror %0,%0",
2603 operands);
2604 /* Must loop. */
2605 else
2606 {
2607 operands[2] = GEN_INT (n);
2608 output_asm_insn ("mov.f lp_count, %2", operands);
2609
2610 shiftloop:
2611 {
2612 output_asm_insn ("lpnz\t2f", operands);
2613 output_asm_insn (shift_one, operands);
2614 output_asm_insn ("nop", operands);
2615 fprintf (asm_out_file, "2:\t%s end single insn loop\n",
2616 ASM_COMMENT_START);
2617 }
2618 }
2619 }
2620
2621 return "";
2622}
2623\f
2624/* Nested function support. */
2625
2626/* Directly store VALUE into memory object BLOCK at OFFSET. */
2627
2628static void
2629emit_store_direct (rtx block, int offset, int value)
2630{
2631 emit_insn (gen_store_direct (adjust_address (block, SImode, offset),
2632 force_reg (SImode,
2633 gen_int_mode (value, SImode))));
2634}
2635
2636/* Emit RTL insns to initialize the variable parts of a trampoline.
2637 FNADDR is an RTX for the address of the function's pure code.
2638 CXT is an RTX for the static chain value for the function. */
2639/* With potentially multiple shared objects loaded, and multiple stacks
2640 present for multiple thereds where trampolines might reside, a simple
2641 range check will likely not suffice for the profiler to tell if a callee
2642 is a trampoline. We a speedier check by making the trampoline start at
2643 an address that is not 4-byte aligned.
2644 A trampoline looks like this:
2645
2646 nop_s 0x78e0
2647entry:
2648 ld_s r12,[pcl,12] 0xd403
2649 ld r11,[pcl,12] 0x170c 700b
2650 j_s [r12] 0x7c00
2651 nop_s 0x78e0
2652
2653 The fastest trampoline to execute for trampolines within +-8KB of CTX
2654 would be:
2655 add2 r11,pcl,s12
2656 j [limm] 0x20200f80 limm
2657 and that would also be faster to write to the stack by computing the offset
2658 from CTX to TRAMP at compile time. However, it would really be better to
2659 get rid of the high cost of cache invalidation when generating trampolines,
2660 which requires that the code part of trampolines stays constant, and
2661 additionally either
2662 - making sure that no executable code but trampolines is on the stack,
2663 no icache entries linger for the area of the stack from when before the
2664 stack was allocated, and allocating trampolines in trampoline-only
2665 cache lines
2666 or
2667 - allocate trampolines fram a special pool of pre-allocated trampolines. */
2668
2669static void
2670arc_initialize_trampoline (rtx tramp, tree fndecl, rtx cxt)
2671{
2672 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
2673
2674 emit_store_direct (tramp, 0, TARGET_BIG_ENDIAN ? 0x78e0d403 : 0xd40378e0);
2675 emit_store_direct (tramp, 4, TARGET_BIG_ENDIAN ? 0x170c700b : 0x700b170c);
2676 emit_store_direct (tramp, 8, TARGET_BIG_ENDIAN ? 0x7c0078e0 : 0x78e07c00);
2677 emit_move_insn (adjust_address (tramp, SImode, 12), fnaddr);
2678 emit_move_insn (adjust_address (tramp, SImode, 16), cxt);
2679 emit_insn (gen_flush_icache (adjust_address (tramp, SImode, 0)));
2680}
2681
2682/* Allow the profiler to easily distinguish trampolines from normal
2683 functions. */
2684
2685static rtx
2686arc_trampoline_adjust_address (rtx addr)
2687{
2688 return plus_constant (Pmode, addr, 2);
2689}
2690
2691/* This is set briefly to 1 when we output a ".as" address modifer, and then
2692 reset when we output the scaled address. */
2693static int output_scaled = 0;
2694
2695/* Print operand X (an rtx) in assembler syntax to file FILE.
2696 CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
2697 For `%' followed by punctuation, CODE is the punctuation and X is null. */
2698/* In final.c:output_asm_insn:
2699 'l' : label
2700 'a' : address
2701 'c' : constant address if CONSTANT_ADDRESS_P
2702 'n' : negative
2703 Here:
2704 'Z': log2(x+1)-1
2705 'z': log2
2706 'M': log2(~x)
2707 '#': condbranch delay slot suffix
2708 '*': jump delay slot suffix
2709 '?' : nonjump-insn suffix for conditional execution or short instruction
2710 '!' : jump / call suffix for conditional execution or short instruction
2711 '`': fold constant inside unary o-perator, re-recognize, and emit.
2712 'd'
2713 'D'
2714 'R': Second word
2715 'S'
2716 'B': Branch comparison operand - suppress sda reference
2717 'H': Most significant word
2718 'L': Least significant word
2719 'A': ASCII decimal representation of floating point value
2720 'U': Load/store update or scaling indicator
2721 'V': cache bypass indicator for volatile
2722 'P'
2723 'F'
2724 '^'
2725 'O': Operator
2726 'o': original symbol - no @ prepending. */
2727
2728void
2729arc_print_operand (FILE *file, rtx x, int code)
2730{
2731 switch (code)
2732 {
2733 case 'Z':
2734 if (GET_CODE (x) == CONST_INT)
2735 fprintf (file, "%d",exact_log2(INTVAL (x) + 1) - 1 );
2736 else
2737 output_operand_lossage ("invalid operand to %%Z code");
2738
2739 return;
2740
2741 case 'z':
2742 if (GET_CODE (x) == CONST_INT)
2743 fprintf (file, "%d",exact_log2(INTVAL (x)) );
2744 else
2745 output_operand_lossage ("invalid operand to %%z code");
2746
2747 return;
2748
2749 case 'M':
2750 if (GET_CODE (x) == CONST_INT)
2751 fprintf (file, "%d",exact_log2(~INTVAL (x)) );
2752 else
2753 output_operand_lossage ("invalid operand to %%M code");
2754
2755 return;
2756
2757 case '#' :
2758 /* Conditional branches depending on condition codes.
2759 Note that this is only for branches that were known to depend on
2760 condition codes before delay slot scheduling;
2761 out-of-range brcc / bbit expansions should use '*'.
2762 This distinction is important because of the different
2763 allowable delay slot insns and the output of the delay suffix
2764 for TARGET_AT_DBR_COND_EXEC. */
2765 case '*' :
2766 /* Unconditional branches / branches not depending on condition codes.
2767 This could also be a CALL_INSN.
2768 Output the appropriate delay slot suffix. */
2769 if (final_sequence && XVECLEN (final_sequence, 0) != 1)
2770 {
2771 rtx jump = XVECEXP (final_sequence, 0, 0);
2772 rtx delay = XVECEXP (final_sequence, 0, 1);
2773
2774 /* For TARGET_PAD_RETURN we might have grabbed the delay insn. */
2775 if (INSN_DELETED_P (delay))
2776 return;
2777 if (JUMP_P (jump) && INSN_ANNULLED_BRANCH_P (jump))
2778 fputs (INSN_FROM_TARGET_P (delay) ? ".d"
2779 : TARGET_AT_DBR_CONDEXEC && code == '#' ? ".d"
2780 : get_attr_type (jump) == TYPE_RETURN && code == '#' ? ""
2781 : ".nd",
2782 file);
2783 else
2784 fputs (".d", file);
2785 }
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 (current_insn_predicate)
2795 arc_ccfsm_current.cc
2796 = get_arc_condition_code (current_insn_predicate);
2797 if (ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current))
2798 {
2799 /* Is this insn in a delay slot sequence? */
2800 if (!final_sequence || XVECLEN (final_sequence, 0) < 2
2801 || current_insn_predicate
2802 || CALL_P (XVECEXP (final_sequence, 0, 0))
2803 || simplejump_p (XVECEXP (final_sequence, 0, 0)))
2804 {
2805 /* This insn isn't in a delay slot sequence, or conditionalized
2806 independently of its position in a delay slot. */
2807 fprintf (file, "%s%s",
2808 code == '?' ? "." : "",
2809 arc_condition_codes[arc_ccfsm_current.cc]);
2810 /* If this is a jump, there are still short variants. However,
2811 only beq_s / bne_s have the same offset range as b_s,
2812 and the only short conditional returns are jeq_s and jne_s. */
2813 if (code == '!'
2814 && (arc_ccfsm_current.cc == ARC_CC_EQ
2815 || arc_ccfsm_current.cc == ARC_CC_NE
2816 || 0 /* FIXME: check if branch in 7 bit range. */))
2817 output_short_suffix (file);
2818 }
2819 else if (code == '!') /* Jump with delay slot. */
2820 fputs (arc_condition_codes[arc_ccfsm_current.cc], file);
2821 else /* An Instruction in a delay slot of a jump or call. */
2822 {
2823 rtx jump = XVECEXP (final_sequence, 0, 0);
2824 rtx insn = XVECEXP (final_sequence, 0, 1);
2825
2826 /* If the insn is annulled and is from the target path, we need
2827 to inverse the condition test. */
2828 if (JUMP_P (jump) && INSN_ANNULLED_BRANCH_P (jump))
2829 {
2830 if (INSN_FROM_TARGET_P (insn))
2831 fprintf (file, "%s%s",
2832 code == '?' ? "." : "",
2833 arc_condition_codes[ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current.cc)]);
2834 else
2835 fprintf (file, "%s%s",
2836 code == '?' ? "." : "",
2837 arc_condition_codes[arc_ccfsm_current.cc]);
2838 if (arc_ccfsm_current.state == 5)
2839 arc_ccfsm_current.state = 0;
2840 }
2841 else
2842 /* This insn is executed for either path, so don't
2843 conditionalize it at all. */
2844 output_short_suffix (file);
2845
2846 }
2847 }
2848 else
2849 output_short_suffix (file);
2850 return;
2851 case'`':
2852 /* FIXME: fold constant inside unary operator, re-recognize, and emit. */
2853 gcc_unreachable ();
2854 case 'd' :
2855 fputs (arc_condition_codes[get_arc_condition_code (x)], file);
2856 return;
2857 case 'D' :
2858 fputs (arc_condition_codes[ARC_INVERSE_CONDITION_CODE
2859 (get_arc_condition_code (x))],
2860 file);
2861 return;
2862 case 'R' :
2863 /* Write second word of DImode or DFmode reference,
2864 register or memory. */
2865 if (GET_CODE (x) == REG)
2866 fputs (reg_names[REGNO (x)+1], file);
2867 else if (GET_CODE (x) == MEM)
2868 {
2869 fputc ('[', file);
2870
2871 /* Handle possible auto-increment. For PRE_INC / PRE_DEC /
2872 PRE_MODIFY, we will have handled the first word already;
2873 For POST_INC / POST_DEC / POST_MODIFY, the access to the
2874 first word will be done later. In either case, the access
2875 to the first word will do the modify, and we only have
2876 to add an offset of four here. */
2877 if (GET_CODE (XEXP (x, 0)) == PRE_INC
2878 || GET_CODE (XEXP (x, 0)) == PRE_DEC
2879 || GET_CODE (XEXP (x, 0)) == PRE_MODIFY
2880 || GET_CODE (XEXP (x, 0)) == POST_INC
2881 || GET_CODE (XEXP (x, 0)) == POST_DEC
2882 || GET_CODE (XEXP (x, 0)) == POST_MODIFY)
2883 output_address (plus_constant (Pmode, XEXP (XEXP (x, 0), 0), 4));
2884 else if (output_scaled)
2885 {
2886 rtx addr = XEXP (x, 0);
2887 int size = GET_MODE_SIZE (GET_MODE (x));
2888
2889 output_address (plus_constant (Pmode, XEXP (addr, 0),
2890 ((INTVAL (XEXP (addr, 1)) + 4)
2891 >> (size == 2 ? 1 : 2))));
2892 output_scaled = 0;
2893 }
2894 else
2895 output_address (plus_constant (Pmode, XEXP (x, 0), 4));
2896 fputc (']', file);
2897 }
2898 else
2899 output_operand_lossage ("invalid operand to %%R code");
2900 return;
2901 case 'S' :
2902 /* FIXME: remove %S option. */
2903 break;
2904 case 'B' /* Branch or other LIMM ref - must not use sda references. */ :
2905 if (CONSTANT_P (x))
2906 {
2907 output_addr_const (file, x);
2908 return;
2909 }
2910 break;
2911 case 'H' :
2912 case 'L' :
2913 if (GET_CODE (x) == REG)
2914 {
2915 /* L = least significant word, H = most significant word. */
2916 if ((WORDS_BIG_ENDIAN != 0) ^ (code == 'L'))
2917 fputs (reg_names[REGNO (x)], file);
2918 else
2919 fputs (reg_names[REGNO (x)+1], file);
2920 }
2921 else if (GET_CODE (x) == CONST_INT
2922 || GET_CODE (x) == CONST_DOUBLE)
2923 {
2924 rtx first, second;
2925
2926 split_double (x, &first, &second);
2927
2928 if((WORDS_BIG_ENDIAN) == 0)
2929 fprintf (file, "0x%08lx",
2930 code == 'L' ? INTVAL (first) : INTVAL (second));
2931 else
2932 fprintf (file, "0x%08lx",
2933 code == 'L' ? INTVAL (second) : INTVAL (first));
2934
2935
2936 }
2937 else
2938 output_operand_lossage ("invalid operand to %%H/%%L code");
2939 return;
2940 case 'A' :
2941 {
2942 char str[30];
2943
2944 gcc_assert (GET_CODE (x) == CONST_DOUBLE
2945 && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT);
2946
2947 real_to_decimal (str, CONST_DOUBLE_REAL_VALUE (x), sizeof (str), 0, 1);
2948 fprintf (file, "%s", str);
2949 return;
2950 }
2951 case 'U' :
2952 /* Output a load/store with update indicator if appropriate. */
2953 if (GET_CODE (x) == MEM)
2954 {
2955 rtx addr = XEXP (x, 0);
2956 switch (GET_CODE (addr))
2957 {
2958 case PRE_INC: case PRE_DEC: case PRE_MODIFY:
2959 fputs (".a", file); break;
2960 case POST_INC: case POST_DEC: case POST_MODIFY:
2961 fputs (".ab", file); break;
2962 case PLUS:
2963 /* Are we using a scaled index? */
2964 if (GET_CODE (XEXP (addr, 0)) == MULT)
2965 fputs (".as", file);
2966 /* Can we use a scaled offset? */
2967 else if (CONST_INT_P (XEXP (addr, 1))
2968 && GET_MODE_SIZE (GET_MODE (x)) > 1
2969 && (!(INTVAL (XEXP (addr, 1))
2970 & (GET_MODE_SIZE (GET_MODE (x)) - 1) & 3))
2971 /* Does it make a difference? */
2972 && !SMALL_INT_RANGE(INTVAL (XEXP (addr, 1)),
2973 GET_MODE_SIZE (GET_MODE (x)) - 2, 0))
2974 {
2975 fputs (".as", file);
2976 output_scaled = 1;
2977 }
2978 break;
2979 case REG:
2980 break;
2981 default:
2982 gcc_assert (CONSTANT_P (addr)); break;
2983 }
2984 }
2985 else
2986 output_operand_lossage ("invalid operand to %%U code");
2987 return;
2988 case 'V' :
2989 /* Output cache bypass indicator for a load/store insn. Volatile memory
2990 refs are defined to use the cache bypass mechanism. */
2991 if (GET_CODE (x) == MEM)
2992 {
2993 if (MEM_VOLATILE_P (x) && !TARGET_VOLATILE_CACHE_SET )
2994 fputs (".di", file);
2995 }
2996 else
2997 output_operand_lossage ("invalid operand to %%V code");
2998 return;
2999 /* plt code. */
3000 case 'P':
3001 case 0 :
3002 /* Do nothing special. */
3003 break;
3004 case 'F':
3005 fputs (reg_names[REGNO (x)]+1, file);
3006 return;
3007 case '^':
3008 /* This punctuation character is needed because label references are
3009 printed in the output template using %l. This is a front end
3010 character, and when we want to emit a '@' before it, we have to use
3011 this '^'. */
3012
3013 fputc('@',file);
3014 return;
3015 case 'O':
3016 /* Output an operator. */
3017 switch (GET_CODE (x))
3018 {
3019 case PLUS: fputs ("add", file); return;
3020 case SS_PLUS: fputs ("adds", file); return;
3021 case AND: fputs ("and", file); return;
3022 case IOR: fputs ("or", file); return;
3023 case XOR: fputs ("xor", file); return;
3024 case MINUS: fputs ("sub", file); return;
3025 case SS_MINUS: fputs ("subs", file); return;
3026 case ASHIFT: fputs ("asl", file); return;
3027 case ASHIFTRT: fputs ("asr", file); return;
3028 case LSHIFTRT: fputs ("lsr", file); return;
3029 case ROTATERT: fputs ("ror", file); return;
3030 case MULT: fputs ("mpy", file); return;
3031 case ABS: fputs ("abs", file); return; /* Unconditional. */
3032 case NEG: fputs ("neg", file); return;
3033 case SS_NEG: fputs ("negs", file); return;
3034 case NOT: fputs ("not", file); return; /* Unconditional. */
3035 case ZERO_EXTEND:
3036 fputs ("ext", file); /* bmsk allows predication. */
3037 goto size_suffix;
3038 case SIGN_EXTEND: /* Unconditional. */
3039 fputs ("sex", file);
3040 size_suffix:
3041 switch (GET_MODE (XEXP (x, 0)))
3042 {
3043 case QImode: fputs ("b", file); return;
3044 case HImode: fputs ("w", file); return;
3045 default: break;
3046 }
3047 break;
3048 case SS_TRUNCATE:
3049 if (GET_MODE (x) != HImode)
3050 break;
3051 fputs ("sat16", file);
3052 default: break;
3053 }
3054 output_operand_lossage ("invalid operand to %%O code"); return;
3055 case 'o':
3056 if (GET_CODE (x) == SYMBOL_REF)
3057 {
3058 assemble_name (file, XSTR (x, 0));
3059 return;
3060 }
3061 break;
3062 case '&':
3063 if (TARGET_ANNOTATE_ALIGN && cfun->machine->size_reason)
3064 fprintf (file, "; unalign: %d", cfun->machine->unalign);
3065 return;
3066 default :
3067 /* Unknown flag. */
3068 output_operand_lossage ("invalid operand output code");
3069 }
3070
3071 switch (GET_CODE (x))
3072 {
3073 case REG :
3074 fputs (reg_names[REGNO (x)], file);
3075 break;
3076 case MEM :
3077 {
3078 rtx addr = XEXP (x, 0);
3079 int size = GET_MODE_SIZE (GET_MODE (x));
3080
3081 fputc ('[', file);
3082
3083 switch (GET_CODE (addr))
3084 {
3085 case PRE_INC: case POST_INC:
3086 output_address (plus_constant (Pmode, XEXP (addr, 0), size)); break;
3087 case PRE_DEC: case POST_DEC:
3088 output_address (plus_constant (Pmode, XEXP (addr, 0), -size));
3089 break;
3090 case PRE_MODIFY: case POST_MODIFY:
3091 output_address (XEXP (addr, 1)); break;
3092 case PLUS:
3093 if (output_scaled)
3094 {
3095 output_address (plus_constant (Pmode, XEXP (addr, 0),
3096 (INTVAL (XEXP (addr, 1))
3097 >> (size == 2 ? 1 : 2))));
3098 output_scaled = 0;
3099 }
3100 else
3101 output_address (addr);
3102 break;
3103 default:
3104 if (flag_pic && CONSTANT_ADDRESS_P (addr))
3105 arc_output_pic_addr_const (file, addr, code);
3106 else
3107 output_address (addr);
3108 break;
3109 }
3110 fputc (']', file);
3111 break;
3112 }
3113 case CONST_DOUBLE :
3114 /* We handle SFmode constants here as output_addr_const doesn't. */
3115 if (GET_MODE (x) == SFmode)
3116 {
3117 REAL_VALUE_TYPE d;
3118 long l;
3119
3120 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
3121 REAL_VALUE_TO_TARGET_SINGLE (d, l);
3122 fprintf (file, "0x%08lx", l);
3123 break;
3124 }
3125 /* Fall through. Let output_addr_const deal with it. */
3126 default :
3127 if (flag_pic)
3128 arc_output_pic_addr_const (file, x, code);
3129 else
3130 {
3131 /* FIXME: Dirty way to handle @var@sda+const. Shd be handled
3132 with asm_output_symbol_ref */
3133 if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS)
3134 {
3135 x = XEXP (x, 0);
3136 output_addr_const (file, XEXP (x, 0));
3137 if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF && SYMBOL_REF_SMALL_P (XEXP (x, 0)))
3138 fprintf (file, "@sda");
3139
3140 if (GET_CODE (XEXP (x, 1)) != CONST_INT
3141 || INTVAL (XEXP (x, 1)) >= 0)
3142 fprintf (file, "+");
3143 output_addr_const (file, XEXP (x, 1));
3144 }
3145 else
3146 output_addr_const (file, x);
3147 }
3148 if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_SMALL_P (x))
3149 fprintf (file, "@sda");
3150 break;
3151 }
3152}
3153
3154/* Print a memory address as an operand to reference that memory location. */
3155
3156void
3157arc_print_operand_address (FILE *file , rtx addr)
3158{
3159 register rtx base, index = 0;
3160
3161 switch (GET_CODE (addr))
3162 {
3163 case REG :
3164 fputs (reg_names[REGNO (addr)], file);
3165 break;
3166 case SYMBOL_REF :
3167 output_addr_const (file, addr);
3168 if (SYMBOL_REF_SMALL_P (addr))
3169 fprintf (file, "@sda");
3170 break;
3171 case PLUS :
3172 if (GET_CODE (XEXP (addr, 0)) == MULT)
3173 index = XEXP (XEXP (addr, 0), 0), base = XEXP (addr, 1);
3174 else if (CONST_INT_P (XEXP (addr, 0)))
3175 index = XEXP (addr, 0), base = XEXP (addr, 1);
3176 else
3177 base = XEXP (addr, 0), index = XEXP (addr, 1);
3178
3179 gcc_assert (OBJECT_P (base));
3180 arc_print_operand_address (file, base);
3181 if (CONSTANT_P (base) && CONST_INT_P (index))
3182 fputc ('+', file);
3183 else
3184 fputc (',', file);
3185 gcc_assert (OBJECT_P (index));
3186 arc_print_operand_address (file, index);
3187 break;
3188 case CONST:
3189 {
3190 rtx c = XEXP (addr, 0);
3191
3192 gcc_assert (GET_CODE (XEXP (c, 0)) == SYMBOL_REF);
3193 gcc_assert (GET_CODE (XEXP (c, 1)) == CONST_INT);
3194
3195 output_address(XEXP(addr,0));
3196
3197 break;
3198 }
3199 case PRE_INC :
3200 case PRE_DEC :
3201 /* We shouldn't get here as we've lost the mode of the memory object
3202 (which says how much to inc/dec by. */
3203 gcc_unreachable ();
3204 break;
3205 default :
3206 if (flag_pic)
3207 arc_output_pic_addr_const (file, addr, 0);
3208 else
3209 output_addr_const (file, addr);
3210 break;
3211 }
3212}
3213
3214/* Called via walk_stores. DATA points to a hash table we can use to
3215 establish a unique SYMBOL_REF for each counter, which corresponds to
3216 a caller-callee pair.
3217 X is a store which we want to examine for an UNSPEC_PROF, which
3218 would be an address loaded into a register, or directly used in a MEM.
3219 If we found an UNSPEC_PROF, if we encounter a new counter the first time,
3220 write out a description and a data allocation for a 32 bit counter.
3221 Also, fill in the appropriate symbol_ref into each UNSPEC_PROF instance. */
3222
3223static void
3224write_profile_sections (rtx dest ATTRIBUTE_UNUSED, rtx x, void *data)
3225{
3226 rtx *srcp, src;
3227 htab_t htab = (htab_t) data;
3228 rtx *slot;
3229
3230 if (GET_CODE (x) != SET)
3231 return;
3232 srcp = &SET_SRC (x);
3233 if (MEM_P (*srcp))
3234 srcp = &XEXP (*srcp, 0);
3235 else if (MEM_P (SET_DEST (x)))
3236 srcp = &XEXP (SET_DEST (x), 0);
3237 src = *srcp;
3238 if (GET_CODE (src) != CONST)
3239 return;
3240 src = XEXP (src, 0);
3241 if (GET_CODE (src) != UNSPEC || XINT (src, 1) != UNSPEC_PROF)
3242 return;
3243
3244 gcc_assert (XVECLEN (src, 0) == 3);
3245 if (!htab_elements (htab))
3246 {
3247 output_asm_insn (".section .__arc_profile_desc, \"a\"\n"
3248 "\t.long %0 + 1\n",
3249 &XVECEXP (src, 0, 0));
3250 }
3251 slot = (rtx *) htab_find_slot (htab, src, INSERT);
3252 if (*slot == HTAB_EMPTY_ENTRY)
3253 {
3254 static int count_nr;
3255 char buf[24];
3256 rtx count;
3257
3258 *slot = src;
3259 sprintf (buf, "__prof_count%d", count_nr++);
3260 count = gen_rtx_SYMBOL_REF (Pmode, xstrdup (buf));
3261 XVECEXP (src, 0, 2) = count;
3262 output_asm_insn (".section\t.__arc_profile_desc, \"a\"\n"
3263 "\t.long\t%1\n"
3264 "\t.section\t.__arc_profile_counters, \"aw\"\n"
3265 "\t.type\t%o2, @object\n"
3266 "\t.size\t%o2, 4\n"
3267 "%o2:\t.zero 4",
3268 &XVECEXP (src, 0, 0));
3269 *srcp = count;
3270 }
3271 else
3272 *srcp = XVECEXP (*slot, 0, 2);
3273}
3274
3275/* Hash function for UNSPEC_PROF htab. Use both the caller's name and
3276 the callee's name (if known). */
3277
3278static hashval_t
3279unspec_prof_hash (const void *x)
3280{
3281 const_rtx u = (const_rtx) x;
3282 const_rtx s1 = XVECEXP (u, 0, 1);
3283
3284 return (htab_hash_string (XSTR (XVECEXP (u, 0, 0), 0))
3285 ^ (s1->code == SYMBOL_REF ? htab_hash_string (XSTR (s1, 0)) : 0));
3286}
3287
3288/* Equality function for UNSPEC_PROF htab. Two pieces of UNSPEC_PROF rtl
3289 shall refer to the same counter if both caller name and callee rtl
3290 are identical. */
3291
3292static int
3293unspec_prof_htab_eq (const void *x, const void *y)
3294{
3295 const_rtx u0 = (const_rtx) x;
3296 const_rtx u1 = (const_rtx) y;
3297 const_rtx s01 = XVECEXP (u0, 0, 1);
3298 const_rtx s11 = XVECEXP (u1, 0, 1);
3299
3300 return (!strcmp (XSTR (XVECEXP (u0, 0, 0), 0),
3301 XSTR (XVECEXP (u1, 0, 0), 0))
3302 && rtx_equal_p (s01, s11));
3303}
3304
3305/* Conditional execution support.
3306
3307 This is based on the ARM port but for now is much simpler.
3308
3309 A finite state machine takes care of noticing whether or not instructions
3310 can be conditionally executed, and thus decrease execution time and code
3311 size by deleting branch instructions. The fsm is controlled by
3312 arc_ccfsm_advance (called by arc_final_prescan_insn), and controls the
3313 actions of PRINT_OPERAND. The patterns in the .md file for the branch
3314 insns also have a hand in this. */
3315/* The way we leave dealing with non-anulled or annull-false delay slot
3316 insns to the consumer is awkward. */
3317
3318/* The state of the fsm controlling condition codes are:
3319 0: normal, do nothing special
3320 1: don't output this insn
3321 2: don't output this insn
3322 3: make insns conditional
3323 4: make insns conditional
3324 5: make insn conditional (only for outputting anulled delay slot insns)
3325
3326 special value for cfun->machine->uid_ccfsm_state:
3327 6: return with but one insn before it since function start / call
3328
3329 State transitions (state->state by whom, under what condition):
3330 0 -> 1 arc_ccfsm_advance, if insn is a conditional branch skipping over
3331 some instructions.
3332 0 -> 2 arc_ccfsm_advance, if insn is a conditional branch followed
3333 by zero or more non-jump insns and an unconditional branch with
3334 the same target label as the condbranch.
3335 1 -> 3 branch patterns, after having not output the conditional branch
3336 2 -> 4 branch patterns, after having not output the conditional branch
3337 0 -> 5 branch patterns, for anulled delay slot insn.
3338 3 -> 0 ASM_OUTPUT_INTERNAL_LABEL, if the `target' label is reached
3339 (the target label has CODE_LABEL_NUMBER equal to
3340 arc_ccfsm_target_label).
3341 4 -> 0 arc_ccfsm_advance, if `target' unconditional branch is reached
3342 3 -> 1 arc_ccfsm_advance, finding an 'else' jump skipping over some insns.
3343 5 -> 0 when outputting the delay slot insn
3344
3345 If the jump clobbers the conditions then we use states 2 and 4.
3346
3347 A similar thing can be done with conditional return insns.
3348
3349 We also handle separating branches from sets of the condition code.
3350 This is done here because knowledge of the ccfsm state is required,
3351 we may not be outputting the branch. */
3352
3353/* arc_final_prescan_insn calls arc_ccfsm_advance to adjust arc_ccfsm_current,
3354 before letting final output INSN. */
3355
3356static void
3357arc_ccfsm_advance (rtx insn, struct arc_ccfsm *state)
3358{
3359 /* BODY will hold the body of INSN. */
3360 register rtx body;
3361
3362 /* This will be 1 if trying to repeat the trick (ie: do the `else' part of
3363 an if/then/else), and things need to be reversed. */
3364 int reverse = 0;
3365
3366 /* If we start with a return insn, we only succeed if we find another one. */
3367 int seeking_return = 0;
3368
3369 /* START_INSN will hold the insn from where we start looking. This is the
3370 first insn after the following code_label if REVERSE is true. */
3371 rtx start_insn = insn;
3372
3373 /* Type of the jump_insn. Brcc insns don't affect ccfsm changes,
3374 since they don't rely on a cmp preceding the. */
3375 enum attr_type jump_insn_type;
3376
3377 /* Allow -mdebug-ccfsm to turn this off so we can see how well it does.
3378 We can't do this in macro FINAL_PRESCAN_INSN because its called from
3379 final_scan_insn which has `optimize' as a local. */
3380 if (optimize < 2 || TARGET_NO_COND_EXEC)
3381 return;
3382
3383 /* Ignore notes and labels. */
3384 if (!INSN_P (insn))
3385 return;
3386 body = PATTERN (insn);
3387 /* If in state 4, check if the target branch is reached, in order to
3388 change back to state 0. */
3389 if (state->state == 4)
3390 {
3391 if (insn == state->target_insn)
3392 {
3393 state->target_insn = NULL;
3394 state->state = 0;
3395 }
3396 return;
3397 }
3398
3399 /* If in state 3, it is possible to repeat the trick, if this insn is an
3400 unconditional branch to a label, and immediately following this branch
3401 is the previous target label which is only used once, and the label this
3402 branch jumps to is not too far off. Or in other words "we've done the
3403 `then' part, see if we can do the `else' part." */
3404 if (state->state == 3)
3405 {
3406 if (simplejump_p (insn))
3407 {
3408 start_insn = next_nonnote_insn (start_insn);
3409 if (GET_CODE (start_insn) == BARRIER)
3410 {
3411 /* ??? Isn't this always a barrier? */
3412 start_insn = next_nonnote_insn (start_insn);
3413 }
3414 if (GET_CODE (start_insn) == CODE_LABEL
3415 && CODE_LABEL_NUMBER (start_insn) == state->target_label
3416 && LABEL_NUSES (start_insn) == 1)
3417 reverse = TRUE;
3418 else
3419 return;
3420 }
3421 else if (GET_CODE (body) == SIMPLE_RETURN)
3422 {
3423 start_insn = next_nonnote_insn (start_insn);
3424 if (GET_CODE (start_insn) == BARRIER)
3425 start_insn = next_nonnote_insn (start_insn);
3426 if (GET_CODE (start_insn) == CODE_LABEL
3427 && CODE_LABEL_NUMBER (start_insn) == state->target_label
3428 && LABEL_NUSES (start_insn) == 1)
3429 {
3430 reverse = TRUE;
3431 seeking_return = 1;
3432 }
3433 else
3434 return;
3435 }
3436 else
3437 return;
3438 }
3439
3440 if (GET_CODE (insn) != JUMP_INSN
3441 || GET_CODE (PATTERN (insn)) == ADDR_VEC
3442 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
3443 return;
3444
3445 /* We can't predicate BRCC or loop ends.
3446 Also, when generating PIC code, and considering a medium range call,
3447 we can't predicate the call. */
3448 jump_insn_type = get_attr_type (insn);
3449 if (jump_insn_type == TYPE_BRCC
3450 || jump_insn_type == TYPE_BRCC_NO_DELAY_SLOT
3451 || jump_insn_type == TYPE_LOOP_END
3452 || (jump_insn_type == TYPE_CALL && !get_attr_predicable (insn)))
3453 return;
3454
3455 /* This jump might be paralleled with a clobber of the condition codes,
3456 the jump should always come first. */
3457 if (GET_CODE (body) == PARALLEL && XVECLEN (body, 0) > 0)
3458 body = XVECEXP (body, 0, 0);
3459
3460 if (reverse
3461 || (GET_CODE (body) == SET && GET_CODE (SET_DEST (body)) == PC
3462 && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE))
3463 {
3464 int insns_skipped = 0, fail = FALSE, succeed = FALSE;
3465 /* Flag which part of the IF_THEN_ELSE is the LABEL_REF. */
3466 int then_not_else = TRUE;
3467 /* Nonzero if next insn must be the target label. */
3468 int next_must_be_target_label_p;
3469 rtx this_insn = start_insn, label = 0;
3470
3471 /* Register the insn jumped to. */
3472 if (reverse)
3473 {
3474 if (!seeking_return)
3475 label = XEXP (SET_SRC (body), 0);
3476 }
3477 else if (GET_CODE (XEXP (SET_SRC (body), 1)) == LABEL_REF)
3478 label = XEXP (XEXP (SET_SRC (body), 1), 0);
3479 else if (GET_CODE (XEXP (SET_SRC (body), 2)) == LABEL_REF)
3480 {
3481 label = XEXP (XEXP (SET_SRC (body), 2), 0);
3482 then_not_else = FALSE;
3483 }
3484 else if (GET_CODE (XEXP (SET_SRC (body), 1)) == SIMPLE_RETURN)
3485 seeking_return = 1;
3486 else if (GET_CODE (XEXP (SET_SRC (body), 2)) == SIMPLE_RETURN)
3487 {
3488 seeking_return = 1;
3489 then_not_else = FALSE;
3490 }
3491 else
3492 gcc_unreachable ();
3493
3494 /* If this is a non-annulled branch with a delay slot, there is
3495 no need to conditionalize the delay slot. */
3496 if (NEXT_INSN (PREV_INSN (insn)) != insn
3497 && state->state == 0 && !INSN_ANNULLED_BRANCH_P (insn))
3498 {
3499 this_insn = NEXT_INSN (this_insn);
3500 gcc_assert (NEXT_INSN (NEXT_INSN (PREV_INSN (start_insn)))
3501 == NEXT_INSN (this_insn));
3502 }
3503 /* See how many insns this branch skips, and what kind of insns. If all
3504 insns are okay, and the label or unconditional branch to the same
3505 label is not too far away, succeed. */
3506 for (insns_skipped = 0, next_must_be_target_label_p = FALSE;
3507 !fail && !succeed && insns_skipped < MAX_INSNS_SKIPPED;
3508 insns_skipped++)
3509 {
3510 rtx scanbody;
3511
3512 this_insn = next_nonnote_insn (this_insn);
3513 if (!this_insn)
3514 break;
3515
3516 if (next_must_be_target_label_p)
3517 {
3518 if (GET_CODE (this_insn) == BARRIER)
3519 continue;
3520 if (GET_CODE (this_insn) == CODE_LABEL
3521 && this_insn == label)
3522 {
3523 state->state = 1;
3524 succeed = TRUE;
3525 }
3526 else
3527 fail = TRUE;
3528 break;
3529 }
3530
3531 scanbody = PATTERN (this_insn);
3532
3533 switch (GET_CODE (this_insn))
3534 {
3535 case CODE_LABEL:
3536 /* Succeed if it is the target label, otherwise fail since
3537 control falls in from somewhere else. */
3538 if (this_insn == label)
3539 {
3540 state->state = 1;
3541 succeed = TRUE;
3542 }
3543 else
3544 fail = TRUE;
3545 break;
3546
3547 case BARRIER:
3548 /* Succeed if the following insn is the target label.
3549 Otherwise fail.
3550 If return insns are used then the last insn in a function
3551 will be a barrier. */
3552 next_must_be_target_label_p = TRUE;
3553 break;
3554
3555 case CALL_INSN:
3556 /* Can handle a call insn if there are no insns after it.
3557 IE: The next "insn" is the target label. We don't have to
3558 worry about delay slots as such insns are SEQUENCE's inside
3559 INSN's. ??? It is possible to handle such insns though. */
3560 if (get_attr_cond (this_insn) == COND_CANUSE)
3561 next_must_be_target_label_p = TRUE;
3562 else
3563 fail = TRUE;
3564 break;
3565
3566 case JUMP_INSN:
3567 /* If this is an unconditional branch to the same label, succeed.
3568 If it is to another label, do nothing. If it is conditional,
3569 fail. */
3570 /* ??? Probably, the test for the SET and the PC are
3571 unnecessary. */
3572
3573 if (GET_CODE (scanbody) == SET
3574 && GET_CODE (SET_DEST (scanbody)) == PC)
3575 {
3576 if (GET_CODE (SET_SRC (scanbody)) == LABEL_REF
3577 && XEXP (SET_SRC (scanbody), 0) == label && !reverse)
3578 {
3579 state->state = 2;
3580 succeed = TRUE;
3581 }
3582 else if (GET_CODE (SET_SRC (scanbody)) == IF_THEN_ELSE)
3583 fail = TRUE;
3584 else if (get_attr_cond (this_insn) != COND_CANUSE)
3585 fail = TRUE;
3586 }
3587 else if (GET_CODE (scanbody) == SIMPLE_RETURN
3588 && seeking_return)
3589 {
3590 state->state = 2;
3591 succeed = TRUE;
3592 }
3593 else if (GET_CODE (scanbody) == PARALLEL)
3594 {
3595 if (get_attr_cond (this_insn) != COND_CANUSE)
3596 fail = TRUE;
3597 }
3598 break;
3599
3600 case INSN:
3601 /* We can only do this with insns that can use the condition
3602 codes (and don't set them). */
3603 if (GET_CODE (scanbody) == SET
3604 || GET_CODE (scanbody) == PARALLEL)
3605 {
3606 if (get_attr_cond (this_insn) != COND_CANUSE)
3607 fail = TRUE;
3608 }
3609 /* We can't handle other insns like sequences. */
3610 else
3611 fail = TRUE;
3612 break;
3613
3614 default:
3615 break;
3616 }
3617 }
3618
3619 if (succeed)
3620 {
3621 if ((!seeking_return) && (state->state == 1 || reverse))
3622 state->target_label = CODE_LABEL_NUMBER (label);
3623 else if (seeking_return || state->state == 2)
3624 {
3625 while (this_insn && GET_CODE (PATTERN (this_insn)) == USE)
3626 {
3627 this_insn = next_nonnote_insn (this_insn);
3628
3629 gcc_assert (!this_insn ||
3630 (GET_CODE (this_insn) != BARRIER
3631 && GET_CODE (this_insn) != CODE_LABEL));
3632 }
3633 if (!this_insn)
3634 {
3635 /* Oh dear! we ran off the end, give up. */
3636 extract_insn_cached (insn);
3637 state->state = 0;
3638 state->target_insn = NULL;
3639 return;
3640 }
3641 state->target_insn = this_insn;
3642 }
3643 else
3644 gcc_unreachable ();
3645
3646 /* If REVERSE is true, ARM_CURRENT_CC needs to be inverted from
3647 what it was. */
3648 if (!reverse)
3649 {
3650 state->cond = XEXP (SET_SRC (body), 0);
3651 state->cc = get_arc_condition_code (XEXP (SET_SRC (body), 0));
3652 }
3653
3654 if (reverse || then_not_else)
3655 state->cc = ARC_INVERSE_CONDITION_CODE (state->cc);
3656 }
3657
3658 /* Restore recog_operand. Getting the attributes of other insns can
3659 destroy this array, but final.c assumes that it remains intact
3660 across this call; since the insn has been recognized already we
3661 call insn_extract direct. */
3662 extract_insn_cached (insn);
3663 }
3664}
3665
3666/* Record that we are currently outputting label NUM with prefix PREFIX.
3667 It it's the label we're looking for, reset the ccfsm machinery.
3668
3669 Called from ASM_OUTPUT_INTERNAL_LABEL. */
3670
3671static void
3672arc_ccfsm_at_label (const char *prefix, int num, struct arc_ccfsm *state)
3673{
3674 if (state->state == 3 && state->target_label == num
3675 && !strcmp (prefix, "L"))
3676 {
3677 state->state = 0;
3678 state->target_insn = NULL_RTX;
3679 }
3680}
3681
3682/* We are considering a conditional branch with the condition COND.
3683 Check if we want to conditionalize a delay slot insn, and if so modify
3684 the ccfsm state accordingly.
3685 REVERSE says branch will branch when the condition is false. */
3686void
3687arc_ccfsm_record_condition (rtx cond, bool reverse, rtx jump,
3688 struct arc_ccfsm *state)
3689{
3690 rtx seq_insn = NEXT_INSN (PREV_INSN (jump));
3691 if (!state)
3692 state = &arc_ccfsm_current;
3693
3694 gcc_assert (state->state == 0);
3695 if (seq_insn != jump)
3696 {
3697 rtx insn = XVECEXP (PATTERN (seq_insn), 0, 1);
3698
3699 if (!INSN_DELETED_P (insn)
3700 && INSN_ANNULLED_BRANCH_P (jump)
3701 && (TARGET_AT_DBR_CONDEXEC || INSN_FROM_TARGET_P (insn)))
3702 {
3703 state->cond = cond;
3704 state->cc = get_arc_condition_code (cond);
3705 if (!reverse)
3706 arc_ccfsm_current.cc
3707 = ARC_INVERSE_CONDITION_CODE (state->cc);
3708 rtx pat = PATTERN (insn);
3709 if (GET_CODE (pat) == COND_EXEC)
3710 gcc_assert ((INSN_FROM_TARGET_P (insn)
3711 ? ARC_INVERSE_CONDITION_CODE (state->cc) : state->cc)
3712 == get_arc_condition_code (XEXP (pat, 0)));
3713 else
3714 state->state = 5;
3715 }
3716 }
3717}
3718
3719/* Update *STATE as we would when we emit INSN. */
3720
3721static void
3722arc_ccfsm_post_advance (rtx insn, struct arc_ccfsm *state)
3723{
3724 if (LABEL_P (insn))
3725 arc_ccfsm_at_label ("L", CODE_LABEL_NUMBER (insn), state);
3726 else if (JUMP_P (insn)
3727 && GET_CODE (PATTERN (insn)) != ADDR_VEC
3728 && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC
3729 && get_attr_type (insn) == TYPE_BRANCH)
3730 {
3731 if (ARC_CCFSM_BRANCH_DELETED_P (state))
3732 ARC_CCFSM_RECORD_BRANCH_DELETED (state);
3733 else
3734 {
3735 rtx src = SET_SRC (PATTERN (insn));
3736 arc_ccfsm_record_condition (XEXP (src, 0), XEXP (src, 1) == pc_rtx,
3737 insn, state);
3738 }
3739 }
3740 else if (arc_ccfsm_current.state == 5)
3741 arc_ccfsm_current.state = 0;
3742}
3743
3744/* Return true if the current insn, which is a conditional branch, is to be
3745 deleted. */
3746
3747bool
3748arc_ccfsm_branch_deleted_p (void)
3749{
3750 return ARC_CCFSM_BRANCH_DELETED_P (&arc_ccfsm_current);
3751}
3752
3753/* Record a branch isn't output because subsequent insns can be
3754 conditionalized. */
3755
3756void
3757arc_ccfsm_record_branch_deleted (void)
3758{
3759 ARC_CCFSM_RECORD_BRANCH_DELETED (&arc_ccfsm_current);
3760}
3761
3762/* During insn output, indicate if the current insn is predicated. */
3763
3764bool
3765arc_ccfsm_cond_exec_p (void)
3766{
3767 return (cfun->machine->prescan_initialized
3768 && ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current));
3769}
3770
3771/* Like next_active_insn, but return NULL if we find an ADDR_(DIFF_)VEC,
3772 and look inside SEQUENCEs. */
3773
3774static rtx
3775arc_next_active_insn (rtx insn, struct arc_ccfsm *statep)
3776{
3777 rtx pat;
3778
3779 do
3780 {
3781 if (statep)
3782 arc_ccfsm_post_advance (insn, statep);
3783 insn = NEXT_INSN (insn);
3784 if (!insn || BARRIER_P (insn))
3785 return NULL_RTX;
3786 if (statep)
3787 arc_ccfsm_advance (insn, statep);
3788 }
3789 while (NOTE_P (insn)
3790 || (cfun->machine->arc_reorg_started
3791 && LABEL_P (insn) && !label_to_alignment (insn))
3792 || (NONJUMP_INSN_P (insn)
3793 && (GET_CODE (PATTERN (insn)) == USE
3794 || GET_CODE (PATTERN (insn)) == CLOBBER)));
3795 if (!LABEL_P (insn))
3796 {
3797 gcc_assert (INSN_P (insn));
3798 pat = PATTERN (insn);
3799 if (GET_CODE (pat) == ADDR_VEC || GET_CODE (pat) == ADDR_DIFF_VEC)
3800 return NULL_RTX;
3801 if (GET_CODE (pat) == SEQUENCE)
3802 return XVECEXP (pat, 0, 0);
3803 }
3804 return insn;
3805}
3806
3807/* When deciding if an insn should be output short, we want to know something
3808 about the following insns:
3809 - if another insn follows which we know we can output as a short insn
3810 before an alignment-sensitive point, we can output this insn short:
3811 the decision about the eventual alignment can be postponed.
3812 - if a to-be-aligned label comes next, we should output this insn such
3813 as to get / preserve 4-byte alignment.
3814 - if a likely branch without delay slot insn, or a call with an immediately
3815 following short insn comes next, we should out output this insn such as to
3816 get / preserve 2 mod 4 unalignment.
3817 - do the same for a not completely unlikely branch with a short insn
3818 following before any other branch / label.
3819 - in order to decide if we are actually looking at a branch, we need to
3820 call arc_ccfsm_advance.
3821 - in order to decide if we are looking at a short insn, we should know
3822 if it is conditionalized. To a first order of approximation this is
3823 the case if the state from arc_ccfsm_advance from before this insn
3824 indicates the insn is conditionalized. However, a further refinement
3825 could be to not conditionalize an insn if the destination register(s)
3826 is/are dead in the non-executed case. */
3827/* Return non-zero if INSN should be output as a short insn. UNALIGN is
3828 zero if the current insn is aligned to a 4-byte-boundary, two otherwise.
3829 If CHECK_ATTR is greater than 0, check the iscompact attribute first. */
3830
3831int
3832arc_verify_short (rtx insn, int, int check_attr)
3833{
3834 enum attr_iscompact iscompact;
3835 struct machine_function *machine;
3836
3837 if (check_attr > 0)
3838 {
3839 iscompact = get_attr_iscompact (insn);
3840 if (iscompact == ISCOMPACT_FALSE)
3841 return 0;
3842 }
3843 machine = cfun->machine;
3844
3845 if (machine->force_short_suffix >= 0)
3846 return machine->force_short_suffix;
3847
3848 return (get_attr_length (insn) & 2) != 0;
3849}
3850
3851/* When outputting an instruction (alternative) that can potentially be short,
3852 output the short suffix if the insn is in fact short, and update
3853 cfun->machine->unalign accordingly. */
3854
3855static void
3856output_short_suffix (FILE *file)
3857{
3858 rtx insn = current_output_insn;
3859
3860 if (arc_verify_short (insn, cfun->machine->unalign, 1))
3861 {
3862 fprintf (file, "_s");
3863 cfun->machine->unalign ^= 2;
3864 }
3865 /* Restore recog_operand. */
3866 extract_insn_cached (insn);
3867}
3868
3869/* Implement FINAL_PRESCAN_INSN. */
3870
3871void
3872arc_final_prescan_insn (rtx insn, rtx *opvec ATTRIBUTE_UNUSED,
3873 int noperands ATTRIBUTE_UNUSED)
3874{
3875 if (TARGET_DUMPISIZE)
3876 fprintf (asm_out_file, "\n; at %04x\n", INSN_ADDRESSES (INSN_UID (insn)));
3877
3878 /* Output a nop if necessary to prevent a hazard.
3879 Don't do this for delay slots: inserting a nop would
3880 alter semantics, and the only time we would find a hazard is for a
3881 call function result - and in that case, the hazard is spurious to
3882 start with. */
3883 if (PREV_INSN (insn)
3884 && PREV_INSN (NEXT_INSN (insn)) == insn
3885 && arc_hazard (prev_real_insn (insn), insn))
3886 {
3887 current_output_insn =
3888 emit_insn_before (gen_nop (), NEXT_INSN (PREV_INSN (insn)));
3889 final_scan_insn (current_output_insn, asm_out_file, optimize, 1, NULL);
3890 current_output_insn = insn;
3891 }
3892 /* Restore extraction data which might have been clobbered by arc_hazard. */
3893 extract_constrain_insn_cached (insn);
3894
3895 if (!cfun->machine->prescan_initialized)
3896 {
3897 /* Clear lingering state from branch shortening. */
3898 memset (&arc_ccfsm_current, 0, sizeof arc_ccfsm_current);
3899 cfun->machine->prescan_initialized = 1;
3900 }
3901 arc_ccfsm_advance (insn, &arc_ccfsm_current);
3902
3903 cfun->machine->size_reason = 0;
3904}
3905
3906/* Given FROM and TO register numbers, say whether this elimination is allowed.
3907 Frame pointer elimination is automatically handled.
3908
3909 All eliminations are permissible. If we need a frame
3910 pointer, we must eliminate ARG_POINTER_REGNUM into
3911 FRAME_POINTER_REGNUM and not into STACK_POINTER_REGNUM. */
3912
3913static bool
3914arc_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
3915{
3916 return to == FRAME_POINTER_REGNUM || !arc_frame_pointer_required ();
3917}
3918
3919/* Define the offset between two registers, one to be eliminated, and
3920 the other its replacement, at the start of a routine. */
3921
3922int
3923arc_initial_elimination_offset (int from, int to)
3924{
3925 if (! cfun->machine->frame_info.initialized)
3926 arc_compute_frame_size (get_frame_size ());
3927
3928 if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
3929 {
3930 return (cfun->machine->frame_info.extra_size
3931 + cfun->machine->frame_info.reg_size);
3932 }
3933
3934 if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
3935 {
3936 return (cfun->machine->frame_info.total_size
3937 - cfun->machine->frame_info.pretend_size);
3938 }
3939
3940 if ((from == FRAME_POINTER_REGNUM) && (to == STACK_POINTER_REGNUM))
3941 {
3942 return (cfun->machine->frame_info.total_size
3943 - (cfun->machine->frame_info.pretend_size
3944 + cfun->machine->frame_info.extra_size
3945 + cfun->machine->frame_info.reg_size));
3946 }
3947
3948 gcc_unreachable ();
3949}
3950
3951static bool
3952arc_frame_pointer_required (void)
3953{
3954 return cfun->calls_alloca;
3955}
3956
3957
3958/* Return the destination address of a branch. */
3959
3960int
3961branch_dest (rtx branch)
3962{
3963 rtx pat = PATTERN (branch);
3964 rtx dest = (GET_CODE (pat) == PARALLEL
3965 ? SET_SRC (XVECEXP (pat, 0, 0)) : SET_SRC (pat));
3966 int dest_uid;
3967
3968 if (GET_CODE (dest) == IF_THEN_ELSE)
3969 dest = XEXP (dest, XEXP (dest, 1) == pc_rtx ? 2 : 1);
3970
3971 dest = XEXP (dest, 0);
3972 dest_uid = INSN_UID (dest);
3973
3974 return INSN_ADDRESSES (dest_uid);
3975}
3976
3977
3978/* Symbols in the text segment can be accessed without indirecting via the
3979 constant pool; it may take an extra binary operation, but this is still
3980 faster than indirecting via memory. Don't do this when not optimizing,
3981 since we won't be calculating al of the offsets necessary to do this
3982 simplification. */
3983
3984static void
3985arc_encode_section_info (tree decl, rtx rtl, int first)
3986{
3987 /* For sdata, SYMBOL_FLAG_LOCAL and SYMBOL_FLAG_FUNCTION.
3988 This clears machine specific flags, so has to come first. */
3989 default_encode_section_info (decl, rtl, first);
3990
3991 /* Check if it is a function, and whether it has the
3992 [long/medium/short]_call attribute specified. */
3993 if (TREE_CODE (decl) == FUNCTION_DECL)
3994 {
3995 rtx symbol = XEXP (rtl, 0);
3996 int flags = SYMBOL_REF_FLAGS (symbol);
3997
3998 tree attr = (TREE_TYPE (decl) != error_mark_node
3999 ? TYPE_ATTRIBUTES (TREE_TYPE (decl)) : NULL_TREE);
4000 tree long_call_attr = lookup_attribute ("long_call", attr);
4001 tree medium_call_attr = lookup_attribute ("medium_call", attr);
4002 tree short_call_attr = lookup_attribute ("short_call", attr);
4003
4004 if (long_call_attr != NULL_TREE)
4005 flags |= SYMBOL_FLAG_LONG_CALL;
4006 else if (medium_call_attr != NULL_TREE)
4007 flags |= SYMBOL_FLAG_MEDIUM_CALL;
4008 else if (short_call_attr != NULL_TREE)
4009 flags |= SYMBOL_FLAG_SHORT_CALL;
4010
4011 SYMBOL_REF_FLAGS (symbol) = flags;
4012 }
4013}
4014
4015/* This is how to output a definition of an internal numbered label where
4016 PREFIX is the class of label and NUM is the number within the class. */
4017
4018static void arc_internal_label (FILE *stream, const char *prefix, unsigned long labelno)
4019{
4020 if (cfun)
4021 arc_ccfsm_at_label (prefix, labelno, &arc_ccfsm_current);
4022 default_internal_label (stream, prefix, labelno);
4023}
4024
4025/* Set the cpu type and print out other fancy things,
4026 at the top of the file. */
4027
4028static void arc_file_start (void)
4029{
4030 default_file_start ();
4031 fprintf (asm_out_file, "\t.cpu %s\n", arc_cpu_string);
4032}
4033
4034/* Cost functions. */
4035
4036/* Compute a (partial) cost for rtx X. Return true if the complete
4037 cost has been computed, and false if subexpressions should be
4038 scanned. In either case, *TOTAL contains the cost result. */
4039
4040static bool
4041arc_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
4042 int *total, bool speed)
4043{
4044 switch (code)
4045 {
4046 /* Small integers are as cheap as registers. */
4047 case CONST_INT:
4048 {
4049 bool nolimm = false; /* Can we do without long immediate? */
4050 bool fast = false; /* Is the result available immediately? */
4051 bool condexec = false; /* Does this allow conditiobnal execution? */
4052 bool compact = false; /* Is a 16 bit opcode available? */
4053 /* CONDEXEC also implies that we can have an unconditional
4054 3-address operation. */
4055
4056 nolimm = compact = condexec = false;
4057 if (UNSIGNED_INT6 (INTVAL (x)))
4058 nolimm = condexec = compact = true;
4059 else
4060 {
4061 if (SMALL_INT (INTVAL (x)))
4062 nolimm = fast = true;
4063 switch (outer_code)
4064 {
4065 case AND: /* bclr, bmsk, ext[bw] */
4066 if (satisfies_constraint_Ccp (x) /* bclr */
4067 || satisfies_constraint_C1p (x) /* bmsk */)
4068 nolimm = fast = condexec = compact = true;
4069 break;
4070 case IOR: /* bset */
4071 if (satisfies_constraint_C0p (x)) /* bset */
4072 nolimm = fast = condexec = compact = true;
4073 break;
4074 case XOR:
4075 if (satisfies_constraint_C0p (x)) /* bxor */
4076 nolimm = fast = condexec = true;
4077 break;
4078 case SET:
4079 if (satisfies_constraint_Crr (x)) /* ror b,u6 */
4080 nolimm = true;
4081 default:
4082 break;
4083 }
4084 }
4085 /* FIXME: Add target options to attach a small cost if
4086 condexec / compact is not true. */
4087 if (nolimm)
4088 {
4089 *total = 0;
4090 return true;
4091 }
4092 }
4093 /* FALLTHRU */
4094
4095 /* 4 byte values can be fetched as immediate constants -
4096 let's give that the cost of an extra insn. */
4097 case CONST:
4098 case LABEL_REF:
4099 case SYMBOL_REF:
4100 *total = COSTS_N_INSNS (1);
4101 return true;
4102
4103 case CONST_DOUBLE:
4104 {
4105 rtx high, low;
4106
4107 if (TARGET_DPFP)
4108 {
4109 *total = COSTS_N_INSNS (1);
4110 return true;
4111 }
4112 /* FIXME: correct the order of high,low */
4113 split_double (x, &high, &low);
4114 *total = COSTS_N_INSNS (!SMALL_INT (INTVAL (high))
4115 + !SMALL_INT (INTVAL (low)));
4116 return true;
4117 }
4118
4119 /* Encourage synth_mult to find a synthetic multiply when reasonable.
4120 If we need more than 12 insns to do a multiply, then go out-of-line,
4121 since the call overhead will be < 10% of the cost of the multiply. */
4122 case ASHIFT:
4123 case ASHIFTRT:
4124 case LSHIFTRT:
4125 if (TARGET_BARREL_SHIFTER)
4126 {
4127 /* If we want to shift a constant, we need a LIMM. */
4128 /* ??? when the optimizers want to know if a constant should be
4129 hoisted, they ask for the cost of the constant. OUTER_CODE is
4130 insufficient context for shifts since we don't know which operand
4131 we are looking at. */
4132 if (CONSTANT_P (XEXP (x, 0)))
4133 {
4134 *total += (COSTS_N_INSNS (2)
4135 + rtx_cost (XEXP (x, 1), (enum rtx_code) code, 0, speed));
4136 return true;
4137 }
4138 *total = COSTS_N_INSNS (1);
4139 }
4140 else if (GET_CODE (XEXP (x, 1)) != CONST_INT)
4141 *total = COSTS_N_INSNS (16);
4142 else
4143 {
4144 *total = COSTS_N_INSNS (INTVAL (XEXP ((x), 1)));
4145 /* ??? want_to_gcse_p can throw negative shift counts at us,
4146 and then panics when it gets a negative cost as result.
4147 Seen for gcc.c-torture/compile/20020710-1.c -Os . */
4148 if (*total < 0)
4149 *total = 0;
4150 }
4151 return false;
4152
4153 case DIV:
4154 case UDIV:
4155 if (speed)
4156 *total = COSTS_N_INSNS(30);
4157 else
4158 *total = COSTS_N_INSNS(1);
4159 return false;
4160
4161 case MULT:
4162 if ((TARGET_DPFP && GET_MODE (x) == DFmode))
4163 *total = COSTS_N_INSNS (1);
4164 else if (speed)
4165 *total= arc_multcost;
4166 /* We do not want synth_mult sequences when optimizing
4167 for size. */
4168 else if (TARGET_MUL64_SET || (TARGET_ARC700 && !TARGET_NOMPY_SET))
4169 *total = COSTS_N_INSNS (1);
4170 else
4171 *total = COSTS_N_INSNS (2);
4172 return false;
4173 case PLUS:
4174 if (GET_CODE (XEXP (x, 0)) == MULT
4175 && _2_4_8_operand (XEXP (XEXP (x, 0), 1), VOIDmode))
4176 {
4177 *total += (rtx_cost (XEXP (x, 1), PLUS, 0, speed)
4178 + rtx_cost (XEXP (XEXP (x, 0), 0), PLUS, 1, speed));
4179 return true;
4180 }
4181 return false;
4182 case MINUS:
4183 if (GET_CODE (XEXP (x, 1)) == MULT
4184 && _2_4_8_operand (XEXP (XEXP (x, 1), 1), VOIDmode))
4185 {
4186 *total += (rtx_cost (XEXP (x, 0), PLUS, 0, speed)
4187 + rtx_cost (XEXP (XEXP (x, 1), 0), PLUS, 1, speed));
4188 return true;
4189 }
4190 return false;
4191 case COMPARE:
4192 {
4193 rtx op0 = XEXP (x, 0);
4194 rtx op1 = XEXP (x, 1);
4195
4196 if (GET_CODE (op0) == ZERO_EXTRACT && op1 == const0_rtx
4197 && XEXP (op0, 1) == const1_rtx)
4198 {
4199 /* btst / bbit0 / bbit1:
4200 Small integers and registers are free; everything else can
4201 be put in a register. */
4202 *total = (rtx_cost (XEXP (op0, 0), SET, 1, speed)
4203 + rtx_cost (XEXP (op0, 2), SET, 1, speed));
4204 return true;
4205 }
4206 if (GET_CODE (op0) == AND && op1 == const0_rtx
4207 && satisfies_constraint_C1p (XEXP (op0, 1)))
4208 {
4209 /* bmsk.f */
4210 *total = rtx_cost (XEXP (op0, 0), SET, 1, speed);
4211 return true;
4212 }
4213 /* add.f */
4214 if (GET_CODE (op1) == NEG)
4215 {
4216 /* op0 might be constant, the inside of op1 is rather
4217 unlikely to be so. So swapping the operands might lower
4218 the cost. */
4219 *total = (rtx_cost (op0, PLUS, 1, speed)
4220 + rtx_cost (XEXP (op1, 0), PLUS, 0, speed));
4221 }
4222 return false;
4223 }
4224 case EQ: case NE:
4225 if (outer_code == IF_THEN_ELSE
4226 && GET_CODE (XEXP (x, 0)) == ZERO_EXTRACT
4227 && XEXP (x, 1) == const0_rtx
4228 && XEXP (XEXP (x, 0), 1) == const1_rtx)
4229 {
4230 /* btst / bbit0 / bbit1:
4231 Small integers and registers are free; everything else can
4232 be put in a register. */
4233 rtx op0 = XEXP (x, 0);
4234
4235 *total = (rtx_cost (XEXP (op0, 0), SET, 1, speed)
4236 + rtx_cost (XEXP (op0, 2), SET, 1, speed));
4237 return true;
4238 }
4239 /* Fall through. */
4240 /* scc_insn expands into two insns. */
4241 case GTU: case GEU: case LEU:
4242 if (GET_MODE (x) == SImode)
4243 *total += COSTS_N_INSNS (1);
4244 return false;
4245 case LTU: /* might use adc. */
4246 if (GET_MODE (x) == SImode)
4247 *total += COSTS_N_INSNS (1) - 1;
4248 return false;
4249 default:
4250 return false;
4251 }
4252}
4253
4254/* Return true if ADDR is an address that needs to be expressed as an
4255 explicit sum of pcl + offset. */
4256
4257bool
4258arc_legitimate_pc_offset_p (rtx addr)
4259{
4260 if (GET_CODE (addr) != CONST)
4261 return false;
4262 addr = XEXP (addr, 0);
4263 if (GET_CODE (addr) == PLUS)
4264 {
4265 if (GET_CODE (XEXP (addr, 1)) != CONST_INT)
4266 return false;
4267 addr = XEXP (addr, 0);
4268 }
4269 return (GET_CODE (addr) == UNSPEC
4270 && XVECLEN (addr, 0) == 1
4271 && XINT (addr, 1) == ARC_UNSPEC_GOT
4272 && GET_CODE (XVECEXP (addr, 0, 0)) == SYMBOL_REF);
4273}
4274
4275/* Return true if ADDR is a valid pic address.
4276 A valid pic address on arc should look like
4277 const (unspec (SYMBOL_REF/LABEL) (ARC_UNSPEC_GOTOFF/ARC_UNSPEC_GOT)) */
4278
4279bool
4280arc_legitimate_pic_addr_p (rtx addr)
4281{
4282 if (GET_CODE (addr) == LABEL_REF)
4283 return true;
4284 if (GET_CODE (addr) != CONST)
4285 return false;
4286
4287 addr = XEXP (addr, 0);
4288
4289
4290 if (GET_CODE (addr) == PLUS)
4291 {
4292 if (GET_CODE (XEXP (addr, 1)) != CONST_INT)
4293 return false;
4294 addr = XEXP (addr, 0);
4295 }
4296
4297 if (GET_CODE (addr) != UNSPEC
4298 || XVECLEN (addr, 0) != 1)
4299 return false;
4300
4301 /* Must be @GOT or @GOTOFF. */
4302 if (XINT (addr, 1) != ARC_UNSPEC_GOT
4303 && XINT (addr, 1) != ARC_UNSPEC_GOTOFF)
4304 return false;
4305
4306 if (GET_CODE (XVECEXP (addr, 0, 0)) != SYMBOL_REF
4307 && GET_CODE (XVECEXP (addr, 0, 0)) != LABEL_REF)
4308 return false;
4309
4310 return true;
4311}
4312
4313
4314
4315/* Return true if OP contains a symbol reference. */
4316
4317static bool
4318symbolic_reference_mentioned_p (rtx op)
4319{
4320 register const char *fmt;
4321 register int i;
4322
4323 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
4324 return true;
4325
4326 fmt = GET_RTX_FORMAT (GET_CODE (op));
4327 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
4328 {
4329 if (fmt[i] == 'E')
4330 {
4331 register int j;
4332
4333 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
4334 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
4335 return true;
4336 }
4337
4338 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
4339 return true;
4340 }
4341
4342 return false;
4343}
4344
4345/* Return true if OP contains a SYMBOL_REF that is not wrapped in an unspec.
4346 If SKIP_LOCAL is true, skip symbols that bind locally.
4347 This is used further down in this file, and, without SKIP_LOCAL,
4348 in the addsi3 / subsi3 expanders when generating PIC code. */
4349
4350bool
4351arc_raw_symbolic_reference_mentioned_p (rtx op, bool skip_local)
4352{
4353 register const char *fmt;
4354 register int i;
4355
4356 if (GET_CODE(op) == UNSPEC)
4357 return false;
4358
4359 if (GET_CODE (op) == SYMBOL_REF)
4360 {
4361 tree decl = SYMBOL_REF_DECL (op);
4362 return !skip_local || !decl || !default_binds_local_p (decl);
4363 }
4364
4365 fmt = GET_RTX_FORMAT (GET_CODE (op));
4366 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
4367 {
4368 if (fmt[i] == 'E')
4369 {
4370 register int j;
4371
4372 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
4373 if (arc_raw_symbolic_reference_mentioned_p (XVECEXP (op, i, j),
4374 skip_local))
4375 return true;
4376 }
4377
4378 else if (fmt[i] == 'e'
4379 && arc_raw_symbolic_reference_mentioned_p (XEXP (op, i),
4380 skip_local))
4381 return true;
4382 }
4383
4384 return false;
4385}
4386
4387/* Legitimize a pic address reference in ORIG.
4388 The return value is the legitimated address.
4389 If OLDX is non-zero, it is the target to assign the address to first. */
4390
4391rtx
4392arc_legitimize_pic_address (rtx orig, rtx oldx)
4393{
4394 rtx addr = orig;
4395 rtx pat = orig;
4396 rtx base;
4397
4398 if (oldx == orig)
4399 oldx = NULL;
4400
4401 if (GET_CODE (addr) == LABEL_REF)
4402 ; /* Do nothing. */
4403 else if (GET_CODE (addr) == SYMBOL_REF
4404 && (CONSTANT_POOL_ADDRESS_P (addr)
4405 || SYMBOL_REF_LOCAL_P (addr)))
4406 {
4407 /* This symbol may be referenced via a displacement from the PIC
4408 base address (@GOTOFF). */
4409
4410 /* FIXME: if we had a way to emit pc-relative adds that don't
4411 create a GOT entry, we could do without the use of the gp register. */
4412 crtl->uses_pic_offset_table = 1;
4413 pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), ARC_UNSPEC_GOTOFF);
4414 pat = gen_rtx_CONST (Pmode, pat);
4415 pat = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pat);
4416
4417 if (oldx == NULL)
4418 oldx = gen_reg_rtx (Pmode);
4419
4420 if (oldx != 0)
4421 {
4422 emit_move_insn (oldx, pat);
4423 pat = oldx;
4424 }
4425
4426 }
4427 else if (GET_CODE (addr) == SYMBOL_REF)
4428 {
4429 /* This symbol must be referenced via a load from the
4430 Global Offset Table (@GOTPC). */
4431
4432 pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), ARC_UNSPEC_GOT);
4433 pat = gen_rtx_CONST (Pmode, pat);
4434 pat = gen_const_mem (Pmode, pat);
4435
4436 if (oldx == 0)
4437 oldx = gen_reg_rtx (Pmode);
4438
4439 emit_move_insn (oldx, pat);
4440 pat = oldx;
4441 }
4442 else
4443 {
4444 if (GET_CODE (addr) == CONST)
4445 {
4446 addr = XEXP (addr, 0);
4447 if (GET_CODE (addr) == UNSPEC)
4448 {
4449 /* Check that the unspec is one of the ones we generate? */
4450 }
4451 else
4452 gcc_assert (GET_CODE (addr) == PLUS);
4453 }
4454
4455 if (GET_CODE (addr) == PLUS)
4456 {
4457 rtx op0 = XEXP (addr, 0), op1 = XEXP (addr, 1);
4458
4459 /* Check first to see if this is a constant offset from a @GOTOFF
4460 symbol reference. */
4461 if ((GET_CODE (op0) == LABEL_REF
4462 || (GET_CODE (op0) == SYMBOL_REF
4463 && (CONSTANT_POOL_ADDRESS_P (op0)
4464 || SYMBOL_REF_LOCAL_P (op0))))
4465 && GET_CODE (op1) == CONST_INT)
4466 {
4467 /* FIXME: like above, could do without gp reference. */
4468 crtl->uses_pic_offset_table = 1;
4469 pat
4470 = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, op0), ARC_UNSPEC_GOTOFF);
4471 pat = gen_rtx_PLUS (Pmode, pat, op1);
4472 pat = gen_rtx_CONST (Pmode, pat);
4473 pat = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, pat);
4474
4475 if (oldx != 0)
4476 {
4477 emit_move_insn (oldx, pat);
4478 pat = oldx;
4479 }
4480 }
4481 else
4482 {
4483 base = arc_legitimize_pic_address (XEXP (addr, 0), oldx);
4484 pat = arc_legitimize_pic_address (XEXP (addr, 1),
4485 base == oldx ? NULL_RTX : oldx);
4486
4487 if (GET_CODE (pat) == CONST_INT)
4488 pat = plus_constant (Pmode, base, INTVAL (pat));
4489 else
4490 {
4491 if (GET_CODE (pat) == PLUS && CONSTANT_P (XEXP (pat, 1)))
4492 {
4493 base = gen_rtx_PLUS (Pmode, base, XEXP (pat, 0));
4494 pat = XEXP (pat, 1);
4495 }
4496 pat = gen_rtx_PLUS (Pmode, base, pat);
4497 }
4498 }
4499 }
4500 }
4501
4502 return pat;
4503}
4504
4505/* Output address constant X to FILE, taking PIC into account. */
4506
4507void
4508arc_output_pic_addr_const (FILE * file, rtx x, int code)
4509{
4510 char buf[256];
4511
4512 restart:
4513 switch (GET_CODE (x))
4514 {
4515 case PC:
4516 if (flag_pic)
4517 putc ('.', file);
4518 else
4519 gcc_unreachable ();
4520 break;
4521
4522 case SYMBOL_REF:
4523 output_addr_const (file, x);
4524
4525 /* Local functions do not get references through the PLT. */
4526 if (code == 'P' && ! SYMBOL_REF_LOCAL_P (x))
4527 fputs ("@plt", file);
4528 break;
4529
4530 case LABEL_REF:
4531 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (XEXP (x, 0)));
4532 assemble_name (file, buf);
4533 break;
4534
4535 case CODE_LABEL:
4536 ASM_GENERATE_INTERNAL_LABEL (buf, "L", CODE_LABEL_NUMBER (x));
4537 assemble_name (file, buf);
4538 break;
4539
4540 case CONST_INT:
4541 fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x));
4542 break;
4543
4544 case CONST:
4545 arc_output_pic_addr_const (file, XEXP (x, 0), code);
4546 break;
4547
4548 case CONST_DOUBLE:
4549 if (GET_MODE (x) == VOIDmode)
4550 {
4551 /* We can use %d if the number is one word and positive. */
4552 if (CONST_DOUBLE_HIGH (x))
4553 fprintf (file, HOST_WIDE_INT_PRINT_DOUBLE_HEX,
4554 CONST_DOUBLE_HIGH (x), CONST_DOUBLE_LOW (x));
4555 else if (CONST_DOUBLE_LOW (x) < 0)
4556 fprintf (file, HOST_WIDE_INT_PRINT_HEX, CONST_DOUBLE_LOW (x));
4557 else
4558 fprintf (file, HOST_WIDE_INT_PRINT_DEC, CONST_DOUBLE_LOW (x));
4559 }
4560 else
4561 /* We can't handle floating point constants;
4562 PRINT_OPERAND must handle them. */
4563 output_operand_lossage ("floating constant misused");
4564 break;
4565
4566 case PLUS:
4567 /* FIXME: Not needed here. */
4568 /* Some assemblers need integer constants to appear last (eg masm). */
4569 if (GET_CODE (XEXP (x, 0)) == CONST_INT)
4570 {
4571 arc_output_pic_addr_const (file, XEXP (x, 1), code);
4572 fprintf (file, "+");
4573 arc_output_pic_addr_const (file, XEXP (x, 0), code);
4574 }
4575 else if (GET_CODE (XEXP (x, 1)) == CONST_INT)
4576 {
4577 arc_output_pic_addr_const (file, XEXP (x, 0), code);
4578 if (INTVAL (XEXP (x, 1)) >= 0)
4579 fprintf (file, "+");
4580 arc_output_pic_addr_const (file, XEXP (x, 1), code);
4581 }
4582 else
4583 gcc_unreachable();
4584 break;
4585
4586 case MINUS:
4587 /* Avoid outputting things like x-x or x+5-x,
4588 since some assemblers can't handle that. */
4589 x = simplify_subtraction (x);
4590 if (GET_CODE (x) != MINUS)
4591 goto restart;
4592
4593 arc_output_pic_addr_const (file, XEXP (x, 0), code);
4594 fprintf (file, "-");
4595 if (GET_CODE (XEXP (x, 1)) == CONST_INT
4596 && INTVAL (XEXP (x, 1)) < 0)
4597 {
4598 fprintf (file, "(");
4599 arc_output_pic_addr_const (file, XEXP (x, 1), code);
4600 fprintf (file, ")");
4601 }
4602 else
4603 arc_output_pic_addr_const (file, XEXP (x, 1), code);
4604 break;
4605
4606 case ZERO_EXTEND:
4607 case SIGN_EXTEND:
4608 arc_output_pic_addr_const (file, XEXP (x, 0), code);
4609 break;
4610
4611
4612 case UNSPEC:
4613 gcc_assert (XVECLEN (x, 0) == 1);
4614 if (XINT (x, 1) == ARC_UNSPEC_GOT)
4615 fputs ("pcl,", file);
4616 arc_output_pic_addr_const (file, XVECEXP (x, 0, 0), code);
4617 switch (XINT (x, 1))
4618 {
4619 case ARC_UNSPEC_GOT:
4620 fputs ("@gotpc", file);
4621 break;
4622 case ARC_UNSPEC_GOTOFF:
4623 fputs ("@gotoff", file);
4624 break;
4625 case ARC_UNSPEC_PLT:
4626 fputs ("@plt", file);
4627 break;
4628 default:
4629 output_operand_lossage ("invalid UNSPEC as operand: %d", XINT (x,1));
4630 break;
4631 }
4632 break;
4633
4634 default:
4635 output_operand_lossage ("invalid expression as operand");
4636 }
4637}
4638
4639#define SYMBOLIC_CONST(X) \
4640(GET_CODE (X) == SYMBOL_REF \
4641 || GET_CODE (X) == LABEL_REF \
4642 || (GET_CODE (X) == CONST && symbolic_reference_mentioned_p (X)))
4643
4644/* Emit insns to move operands[1] into operands[0]. */
4645
4646void
4647emit_pic_move (rtx *operands, enum machine_mode)
4648{
4649 rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
4650
4651 if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
4652 operands[1] = force_reg (Pmode, operands[1]);
4653 else
4654 operands[1] = arc_legitimize_pic_address (operands[1], temp);
4655}
4656
4657
4658/* The function returning the number of words, at the beginning of an
4659 argument, must be put in registers. The returned value must be
4660 zero for arguments that are passed entirely in registers or that
4661 are entirely pushed on the stack.
4662
4663 On some machines, certain arguments must be passed partially in
4664 registers and partially in memory. On these machines, typically
4665 the first N words of arguments are passed in registers, and the
4666 rest on the stack. If a multi-word argument (a `double' or a
4667 structure) crosses that boundary, its first few words must be
4668 passed in registers and the rest must be pushed. This function
4669 tells the compiler when this occurs, and how many of the words
4670 should go in registers.
4671
4672 `FUNCTION_ARG' for these arguments should return the first register
4673 to be used by the caller for this argument; likewise
4674 `FUNCTION_INCOMING_ARG', for the called function.
4675
4676 The function is used to implement macro FUNCTION_ARG_PARTIAL_NREGS. */
4677
4678/* If REGNO is the least arg reg available then what is the total number of arg
4679 regs available. */
4680#define GPR_REST_ARG_REGS(REGNO) \
4681 ((REGNO) <= MAX_ARC_PARM_REGS ? MAX_ARC_PARM_REGS - (REGNO) : 0 )
4682
4683/* Since arc parm regs are contiguous. */
4684#define ARC_NEXT_ARG_REG(REGNO) ( (REGNO) + 1 )
4685
4686/* Implement TARGET_ARG_PARTIAL_BYTES. */
4687
4688static int
4689arc_arg_partial_bytes (cumulative_args_t cum_v, enum machine_mode mode,
4690 tree type, bool named ATTRIBUTE_UNUSED)
4691{
4692 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
4693 int bytes = (mode == BLKmode
4694 ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode));
4695 int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
4696 int arg_num = *cum;
4697 int ret;
4698
4699 arg_num = ROUND_ADVANCE_CUM (arg_num, mode, type);
4700 ret = GPR_REST_ARG_REGS (arg_num);
4701
4702 /* ICEd at function.c:2361, and ret is copied to data->partial */
4703 ret = (ret >= words ? 0 : ret * UNITS_PER_WORD);
4704
4705 return ret;
4706}
4707
4708
4709
4710/* This function is used to control a function argument is passed in a
4711 register, and which register.
4712
4713 The arguments are CUM, of type CUMULATIVE_ARGS, which summarizes
4714 (in a way defined by INIT_CUMULATIVE_ARGS and FUNCTION_ARG_ADVANCE)
4715 all of the previous arguments so far passed in registers; MODE, the
4716 machine mode of the argument; TYPE, the data type of the argument
4717 as a tree node or 0 if that is not known (which happens for C
4718 support library functions); and NAMED, which is 1 for an ordinary
4719 argument and 0 for nameless arguments that correspond to `...' in
4720 the called function's prototype.
4721
4722 The returned value should either be a `reg' RTX for the hard
4723 register in which to pass the argument, or zero to pass the
4724 argument on the stack.
4725
4726 For machines like the Vax and 68000, where normally all arguments
4727 are pushed, zero suffices as a definition.
4728
4729 The usual way to make the ANSI library `stdarg.h' work on a machine
4730 where some arguments are usually passed in registers, is to cause
4731 nameless arguments to be passed on the stack instead. This is done
4732 by making the function return 0 whenever NAMED is 0.
4733
4734 You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the
4735 definition of this function to determine if this argument is of a
4736 type that must be passed in the stack. If `REG_PARM_STACK_SPACE'
4737 is not defined and the function returns non-zero for such an
4738 argument, the compiler will abort. If `REG_PARM_STACK_SPACE' is
4739 defined, the argument will be computed in the stack and then loaded
4740 into a register.
4741
4742 The function is used to implement macro FUNCTION_ARG. */
4743/* On the ARC the first MAX_ARC_PARM_REGS args are normally in registers
4744 and the rest are pushed. */
4745
4746static rtx
4747arc_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
4748 const_tree type ATTRIBUTE_UNUSED, bool named ATTRIBUTE_UNUSED)
4749{
4750 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
4751 int arg_num = *cum;
4752 rtx ret;
4753 const char *debstr ATTRIBUTE_UNUSED;
4754
4755 arg_num = ROUND_ADVANCE_CUM (arg_num, mode, type);
4756 /* Return a marker for use in the call instruction. */
4757 if (mode == VOIDmode)
4758 {
4759 ret = const0_rtx;
4760 debstr = "<0>";
4761 }
4762 else if (GPR_REST_ARG_REGS (arg_num) > 0)
4763 {
4764 ret = gen_rtx_REG (mode, arg_num);
4765 debstr = reg_names [arg_num];
4766 }
4767 else
4768 {
4769 ret = NULL_RTX;
4770 debstr = "memory";
4771 }
4772 return ret;
4773}
4774
4775/* The function to update the summarizer variable *CUM to advance past
4776 an argument in the argument list. The values MODE, TYPE and NAMED
4777 describe that argument. Once this is done, the variable *CUM is
4778 suitable for analyzing the *following* argument with
4779 `FUNCTION_ARG', etc.
4780
4781 This function need not do anything if the argument in question was
4782 passed on the stack. The compiler knows how to track the amount of
4783 stack space used for arguments without any special help.
4784
4785 The function is used to implement macro FUNCTION_ARG_ADVANCE. */
4786/* For the ARC: the cum set here is passed on to function_arg where we
4787 look at its value and say which reg to use. Strategy: advance the
4788 regnumber here till we run out of arg regs, then set *cum to last
4789 reg. In function_arg, since *cum > last arg reg we would return 0
4790 and thus the arg will end up on the stack. For straddling args of
4791 course function_arg_partial_nregs will come into play. */
4792
4793static void
4794arc_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
4795 const_tree type, bool named ATTRIBUTE_UNUSED)
4796{
4797 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
4798 int bytes = (mode == BLKmode
4799 ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode));
4800 int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
4801 int i;
4802
4803 if (words)
4804 *cum = ROUND_ADVANCE_CUM (*cum, mode, type);
4805 for (i = 0; i < words; i++)
4806 *cum = ARC_NEXT_ARG_REG (*cum);
4807
4808}
4809
4810/* Define how to find the value returned by a function.
4811 VALTYPE is the data type of the value (as a tree).
4812 If the precise function being called is known, FN_DECL_OR_TYPE is its
4813 FUNCTION_DECL; otherwise, FN_DECL_OR_TYPE is its type. */
4814
4815static rtx
4816arc_function_value (const_tree valtype,
4817 const_tree fn_decl_or_type ATTRIBUTE_UNUSED,
4818 bool outgoing ATTRIBUTE_UNUSED)
4819{
4820 enum machine_mode mode = TYPE_MODE (valtype);
4821 int unsignedp ATTRIBUTE_UNUSED;
4822
4823 unsignedp = TYPE_UNSIGNED (valtype);
4824 if (INTEGRAL_TYPE_P (valtype) || TREE_CODE (valtype) == OFFSET_TYPE)
4825 PROMOTE_MODE (mode, unsignedp, valtype);
4826 return gen_rtx_REG (mode, 0);
4827}
4828
4829/* Returns the return address that is used by builtin_return_address. */
4830
4831rtx
4832arc_return_addr_rtx (int count, ATTRIBUTE_UNUSED rtx frame)
4833{
4834 if (count != 0)
4835 return const0_rtx;
4836
4837 return get_hard_reg_initial_val (Pmode , RETURN_ADDR_REGNUM);
4838}
4839
4840/* Nonzero if the constant value X is a legitimate general operand
4841 when generating PIC code. It is given that flag_pic is on and
4842 that X satisfies CONSTANT_P or is a CONST_DOUBLE. */
4843
4844bool
4845arc_legitimate_pic_operand_p (rtx x)
4846{
4847 return !arc_raw_symbolic_reference_mentioned_p (x, true);
4848}
4849
4850/* Determine if a given RTX is a valid constant. We already know this
4851 satisfies CONSTANT_P. */
4852
4853bool
4854arc_legitimate_constant_p (enum machine_mode, rtx x)
4855{
4856 if (!flag_pic)
4857 return true;
4858
4859 switch (GET_CODE (x))
4860 {
4861 case CONST:
4862 x = XEXP (x, 0);
4863
4864 if (GET_CODE (x) == PLUS)
4865 {
4866 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
4867 return false;
4868 x = XEXP (x, 0);
4869 }
4870
4871 /* Only some unspecs are valid as "constants". */
4872 if (GET_CODE (x) == UNSPEC)
4873 switch (XINT (x, 1))
4874 {
4875 case ARC_UNSPEC_PLT:
4876 case ARC_UNSPEC_GOTOFF:
4877 case ARC_UNSPEC_GOT:
4878 case UNSPEC_PROF:
4879 return true;
4880
4881 default:
4882 gcc_unreachable ();
4883 }
4884
4885 /* We must have drilled down to a symbol. */
4886 if (arc_raw_symbolic_reference_mentioned_p (x, false))
4887 return false;
4888
4889 /* Return true. */
4890 break;
4891
4892 case LABEL_REF:
4893 case SYMBOL_REF:
4894 return false;
4895
4896 default:
4897 break;
4898 }
4899
4900 /* Otherwise we handle everything else in the move patterns. */
4901 return true;
4902}
4903
4904static bool
4905arc_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
4906{
4907 if (RTX_OK_FOR_BASE_P (x, strict))
4908 return true;
4909 if (LEGITIMATE_OFFSET_ADDRESS_P (mode, x, TARGET_INDEXED_LOADS, strict))
4910 return true;
4911 if (LEGITIMATE_SCALED_ADDRESS_P (mode, x, strict))
4912 return true;
4913 if (LEGITIMATE_SMALL_DATA_ADDRESS_P (x))
4914 return true;
4915 if (GET_CODE (x) == CONST_INT && LARGE_INT (INTVAL (x)))
4916 return true;
4917 if ((GET_MODE_SIZE (mode) != 16)
4918 && (GET_CODE (x) == SYMBOL_REF
4919 || GET_CODE (x) == LABEL_REF
4920 || GET_CODE (x) == CONST))
4921 {
4922 if (!flag_pic || arc_legitimate_pic_addr_p (x))
4923 return true;
4924 }
4925 if ((GET_CODE (x) == PRE_DEC || GET_CODE (x) == PRE_INC
4926 || GET_CODE (x) == POST_DEC || GET_CODE (x) == POST_INC)
4927 && RTX_OK_FOR_BASE_P (XEXP (x, 0), strict))
4928 return true;
4929 /* We're restricted here by the `st' insn. */
4930 if ((GET_CODE (x) == PRE_MODIFY || GET_CODE (x) == POST_MODIFY)
4931 && GET_CODE (XEXP ((x), 1)) == PLUS
4932 && rtx_equal_p (XEXP ((x), 0), XEXP (XEXP (x, 1), 0))
4933 && LEGITIMATE_OFFSET_ADDRESS_P (QImode, XEXP (x, 1),
4934 TARGET_AUTO_MODIFY_REG, strict))
4935 return true;
4936 return false;
4937}
4938
4939/* Return true iff ADDR (a legitimate address expression)
4940 has an effect that depends on the machine mode it is used for. */
4941
4942static bool
4943arc_mode_dependent_address_p (const_rtx addr, addr_space_t)
4944{
4945 /* SYMBOL_REF is not mode dependent: it is either a small data reference,
4946 which is valid for loads and stores, or a limm offset, which is valid for
4947 loads. */
4948 /* Scaled indices are scaled by the access mode; likewise for scaled
4949 offsets, which are needed for maximum offset stores. */
4950 if (GET_CODE (addr) == PLUS
4951 && (GET_CODE (XEXP ((addr), 0)) == MULT
4952 || (CONST_INT_P (XEXP ((addr), 1))
4953 && !SMALL_INT (INTVAL (XEXP ((addr), 1))))))
4954 return true;
4955 return false;
4956}
4957
4958/* Determine if it's legal to put X into the constant pool. */
4959
4960static bool
4961arc_cannot_force_const_mem (enum machine_mode mode, rtx x)
4962{
4963 return !arc_legitimate_constant_p (mode, x);
4964}
4965
4966
4967/* Generic function to define a builtin. */
4968#define def_mbuiltin(MASK, NAME, TYPE, CODE) \
4969 do \
4970 { \
4971 if (MASK) \
4972 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, NULL, NULL_TREE); \
4973 } \
4974 while (0)
4975
4976
4977static void
4978arc_init_builtins (void)
4979{
4980 tree endlink = void_list_node;
4981
4982 tree void_ftype_void
4983 = build_function_type (void_type_node,
4984 endlink);
4985
4986 tree int_ftype_int
4987 = build_function_type (integer_type_node,
4988 tree_cons (NULL_TREE, integer_type_node, endlink));
4989
4990 tree pcvoid_type_node
4991 = build_pointer_type (build_qualified_type (void_type_node, TYPE_QUAL_CONST));
4992 tree int_ftype_pcvoid_int
4993 = build_function_type (integer_type_node,
4994 tree_cons (NULL_TREE, pcvoid_type_node,
4995 tree_cons (NULL_TREE, integer_type_node,
4996 endlink)));
4997
4998 tree int_ftype_short_int
4999 = build_function_type (integer_type_node,
5000 tree_cons (NULL_TREE, short_integer_type_node, endlink));
5001
5002 tree void_ftype_int_int
5003 = build_function_type (void_type_node,
5004 tree_cons (NULL_TREE, integer_type_node,
5005 tree_cons (NULL_TREE, integer_type_node, endlink)));
5006 tree void_ftype_usint_usint
5007 = build_function_type (void_type_node,
5008 tree_cons (NULL_TREE, long_unsigned_type_node,
5009 tree_cons (NULL_TREE, long_unsigned_type_node, endlink)));
5010
5011 tree int_ftype_int_int
5012 = build_function_type (integer_type_node,
5013 tree_cons (NULL_TREE, integer_type_node,
5014 tree_cons (NULL_TREE, integer_type_node, endlink)));
5015
5016 tree usint_ftype_usint
5017 = build_function_type (long_unsigned_type_node,
5018 tree_cons (NULL_TREE, long_unsigned_type_node, endlink));
5019
5020 tree void_ftype_usint
5021 = build_function_type (void_type_node,
5022 tree_cons (NULL_TREE, long_unsigned_type_node, endlink));
5023
5024 /* Add the builtins. */
5025 def_mbuiltin (1,"__builtin_arc_nop", void_ftype_void, ARC_BUILTIN_NOP);
5026 def_mbuiltin (TARGET_NORM, "__builtin_arc_norm", int_ftype_int, ARC_BUILTIN_NORM);
5027 def_mbuiltin (TARGET_NORM, "__builtin_arc_normw", int_ftype_short_int, ARC_BUILTIN_NORMW);
5028 def_mbuiltin (TARGET_SWAP, "__builtin_arc_swap", int_ftype_int, ARC_BUILTIN_SWAP);
5029 def_mbuiltin (TARGET_MUL64_SET,"__builtin_arc_mul64", void_ftype_int_int, ARC_BUILTIN_MUL64);
5030 def_mbuiltin (TARGET_MUL64_SET,"__builtin_arc_mulu64", void_ftype_usint_usint, ARC_BUILTIN_MULU64);
5031 def_mbuiltin (1,"__builtin_arc_rtie", void_ftype_void, ARC_BUILTIN_RTIE);
5032 def_mbuiltin (TARGET_ARC700,"__builtin_arc_sync", void_ftype_void, ARC_BUILTIN_SYNC);
5033 def_mbuiltin ((TARGET_EA_SET),"__builtin_arc_divaw", int_ftype_int_int, ARC_BUILTIN_DIVAW);
5034 def_mbuiltin (1,"__builtin_arc_brk", void_ftype_void, ARC_BUILTIN_BRK);
5035 def_mbuiltin (1,"__builtin_arc_flag", void_ftype_usint, ARC_BUILTIN_FLAG);
5036 def_mbuiltin (1,"__builtin_arc_sleep", void_ftype_usint, ARC_BUILTIN_SLEEP);
5037 def_mbuiltin (1,"__builtin_arc_swi", void_ftype_void, ARC_BUILTIN_SWI);
5038 def_mbuiltin (1,"__builtin_arc_core_read", usint_ftype_usint, ARC_BUILTIN_CORE_READ);
5039 def_mbuiltin (1,"__builtin_arc_core_write", void_ftype_usint_usint, ARC_BUILTIN_CORE_WRITE);
5040 def_mbuiltin (1,"__builtin_arc_lr", usint_ftype_usint, ARC_BUILTIN_LR);
5041 def_mbuiltin (1,"__builtin_arc_sr", void_ftype_usint_usint, ARC_BUILTIN_SR);
5042 def_mbuiltin (TARGET_ARC700,"__builtin_arc_trap_s", void_ftype_usint, ARC_BUILTIN_TRAP_S);
5043 def_mbuiltin (TARGET_ARC700,"__builtin_arc_unimp_s", void_ftype_void, ARC_BUILTIN_UNIMP_S);
5044 def_mbuiltin (1,"__builtin_arc_aligned", int_ftype_pcvoid_int, ARC_BUILTIN_ALIGNED);
5045
5046 if (TARGET_SIMD_SET)
5047 arc_init_simd_builtins ();
5048}
5049
5050static rtx arc_expand_simd_builtin (tree, rtx, rtx, enum machine_mode, int);
5051
5052/* Expand an expression EXP that calls a built-in function,
5053 with result going to TARGET if that's convenient
5054 (and in mode MODE if that's convenient).
5055 SUBTARGET may be used as the target for computing one of EXP's operands.
5056 IGNORE is nonzero if the value is to be ignored. */
5057
5058static rtx
5059arc_expand_builtin (tree exp,
5060 rtx target,
5061 rtx subtarget,
5062 enum machine_mode mode,
5063 int ignore)
5064{
5065 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
5066 tree arg0;
5067 tree arg1;
5068 rtx op0;
5069 rtx op1;
5070 int fcode = DECL_FUNCTION_CODE (fndecl);
5071 int icode;
5072 enum machine_mode mode0;
5073 enum machine_mode mode1;
5074
5075 if (fcode > ARC_SIMD_BUILTIN_BEGIN && fcode < ARC_SIMD_BUILTIN_END)
5076 return arc_expand_simd_builtin (exp, target, subtarget, mode, ignore);
5077
5078 switch (fcode)
5079 {
5080 case ARC_BUILTIN_NOP:
5081 emit_insn (gen_nop ());
5082 return NULL_RTX;
5083
5084 case ARC_BUILTIN_NORM:
5085 icode = CODE_FOR_clrsbsi2;
5086 arg0 = CALL_EXPR_ARG (exp, 0);
5087 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5088 mode0 = insn_data[icode].operand[1].mode;
5089 target = gen_reg_rtx (SImode);
5090
5091 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5092 op0 = copy_to_mode_reg (mode0, op0);
5093
5094 emit_insn (gen_clrsbsi2 (target, op0));
5095 return target;
5096
5097 case ARC_BUILTIN_NORMW:
5098
5099 /* FIXME : This should all be HImode, not SImode. */
5100 icode = CODE_FOR_normw;
5101 arg0 = CALL_EXPR_ARG (exp, 0);
5102 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5103 mode0 = insn_data[icode].operand[1].mode;
5104 target = gen_reg_rtx (SImode);
5105
5106 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5107 op0 = copy_to_mode_reg (mode0, convert_to_mode (mode0, op0,0));
5108
5109 emit_insn (gen_normw (target, op0));
5110 return target;
5111
5112 case ARC_BUILTIN_MUL64:
5113 icode = CODE_FOR_mul64;
5114 arg0 = CALL_EXPR_ARG (exp, 0);
5115 arg1 = CALL_EXPR_ARG (exp, 1);
5116 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5117 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5118
5119 mode0 = insn_data[icode].operand[0].mode;
5120 mode1 = insn_data[icode].operand[1].mode;
5121
5122 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
5123 op0 = copy_to_mode_reg (mode0, op0);
5124
5125 if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
5126 op1 = copy_to_mode_reg (mode1, op1);
5127
5128 emit_insn (gen_mul64 (op0,op1));
5129 return NULL_RTX;
5130
5131 case ARC_BUILTIN_MULU64:
5132 icode = CODE_FOR_mulu64;
5133 arg0 = CALL_EXPR_ARG (exp, 0);
5134 arg1 = CALL_EXPR_ARG (exp, 1);
5135 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5136 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5137
5138 mode0 = insn_data[icode].operand[0].mode;
5139 mode1 = insn_data[icode].operand[1].mode;
5140
5141 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
5142 op0 = copy_to_mode_reg (mode0, op0);
5143
5144 if (! (*insn_data[icode].operand[0].predicate) (op1, mode1))
5145 op1 = copy_to_mode_reg (mode1, op1);
5146
5147 emit_insn (gen_mulu64 (op0,op1));
5148 return NULL_RTX;
5149
5150 case ARC_BUILTIN_RTIE:
5151 icode = CODE_FOR_rtie;
5152 emit_insn (gen_rtie (const1_rtx));
5153 return NULL_RTX;
5154
5155 case ARC_BUILTIN_SYNC:
5156 icode = CODE_FOR_sync;
5157 emit_insn (gen_sync (const1_rtx));
5158 return NULL_RTX;
5159
5160 case ARC_BUILTIN_SWAP:
5161 icode = CODE_FOR_swap;
5162 arg0 = CALL_EXPR_ARG (exp, 0);
5163 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5164 mode0 = insn_data[icode].operand[1].mode;
5165 target = gen_reg_rtx (SImode);
5166
5167 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5168 op0 = copy_to_mode_reg (mode0, op0);
5169
5170 emit_insn (gen_swap (target, op0));
5171 return target;
5172
5173 case ARC_BUILTIN_DIVAW:
5174 icode = CODE_FOR_divaw;
5175 arg0 = CALL_EXPR_ARG (exp, 0);
5176 arg1 = CALL_EXPR_ARG (exp, 1);
5177
5178 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5179 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5180 target = gen_reg_rtx (SImode);
5181
5182 mode0 = insn_data[icode].operand[0].mode;
5183 mode1 = insn_data[icode].operand[1].mode;
5184
5185 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
5186 op0 = copy_to_mode_reg (mode0, op0);
5187
5188 if (! (*insn_data[icode].operand[1].predicate) (op1, mode1))
5189 op1 = copy_to_mode_reg (mode1, op1);
5190
5191 emit_insn (gen_divaw (target, op0, op1));
5192 return target;
5193
5194 case ARC_BUILTIN_BRK:
5195 icode = CODE_FOR_brk;
5196 emit_insn (gen_brk (const1_rtx));
5197 return NULL_RTX;
5198
5199 case ARC_BUILTIN_SLEEP:
5200 icode = CODE_FOR_sleep;
5201 arg0 = CALL_EXPR_ARG (exp, 0);
5202
5203 fold (arg0);
5204
5205 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5206 mode0 = insn_data[icode].operand[1].mode;
5207
5208 emit_insn (gen_sleep (op0));
5209 return NULL_RTX;
5210
5211 case ARC_BUILTIN_SWI:
5212 icode = CODE_FOR_swi;
5213 emit_insn (gen_swi (const1_rtx));
5214 return NULL_RTX;
5215
5216 case ARC_BUILTIN_FLAG:
5217 icode = CODE_FOR_flag;
5218 arg0 = CALL_EXPR_ARG (exp, 0);
5219 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5220 mode0 = insn_data[icode].operand[0].mode;
5221
5222 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
5223 op0 = copy_to_mode_reg (mode0, op0);
5224
5225 emit_insn (gen_flag (op0));
5226 return NULL_RTX;
5227
5228 case ARC_BUILTIN_CORE_READ:
5229 icode = CODE_FOR_core_read;
5230 arg0 = CALL_EXPR_ARG (exp, 0);
5231 target = gen_reg_rtx (SImode);
5232
5233 fold (arg0);
5234
5235 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5236 mode0 = insn_data[icode].operand[1].mode;
5237
5238 emit_insn (gen_core_read (target, op0));
5239 return target;
5240
5241 case ARC_BUILTIN_CORE_WRITE:
5242 icode = CODE_FOR_core_write;
5243 arg0 = CALL_EXPR_ARG (exp, 0);
5244 arg1 = CALL_EXPR_ARG (exp, 1);
5245
5246 fold (arg1);
5247
5248 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5249 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5250
5251 mode0 = insn_data[icode].operand[0].mode;
5252 mode1 = insn_data[icode].operand[1].mode;
5253
5254 emit_insn (gen_core_write (op0, op1));
5255 return NULL_RTX;
5256
5257 case ARC_BUILTIN_LR:
5258 icode = CODE_FOR_lr;
5259 arg0 = CALL_EXPR_ARG (exp, 0);
5260 target = gen_reg_rtx (SImode);
5261
5262 fold (arg0);
5263
5264 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5265 mode0 = insn_data[icode].operand[1].mode;
5266
5267 emit_insn (gen_lr (target, op0));
5268 return target;
5269
5270 case ARC_BUILTIN_SR:
5271 icode = CODE_FOR_sr;
5272 arg0 = CALL_EXPR_ARG (exp, 0);
5273 arg1 = CALL_EXPR_ARG (exp, 1);
5274
5275 fold (arg1);
5276
5277 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5278 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5279
5280 mode0 = insn_data[icode].operand[0].mode;
5281 mode1 = insn_data[icode].operand[1].mode;
5282
5283 emit_insn (gen_sr (op0, op1));
5284 return NULL_RTX;
5285
5286 case ARC_BUILTIN_TRAP_S:
5287 icode = CODE_FOR_trap_s;
5288 arg0 = CALL_EXPR_ARG (exp, 0);
5289
5290 fold (arg0);
5291
5292 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5293 mode0 = insn_data[icode].operand[1].mode;
5294
5295 /* We don't give an error for non-cost values here because
5296 we still want to allow things to be fixed up by later inlining /
5297 constant folding / dead code elimination. */
5298 if (CONST_INT_P (op0) && !satisfies_constraint_L (op0))
5299 {
5300 /* Keep this message in sync with the one in arc.md:trap_s,
5301 because *.md files don't get scanned by exgettext. */
5302 error ("operand to trap_s should be an unsigned 6-bit value");
5303 }
5304 emit_insn (gen_trap_s (op0));
5305 return NULL_RTX;
5306
5307 case ARC_BUILTIN_UNIMP_S:
5308 icode = CODE_FOR_unimp_s;
5309 emit_insn (gen_unimp_s (const1_rtx));
5310 return NULL_RTX;
5311
5312 case ARC_BUILTIN_ALIGNED:
5313 /* __builtin_arc_aligned (void* val, int alignval) */
5314 arg0 = CALL_EXPR_ARG (exp, 0);
5315 arg1 = CALL_EXPR_ARG (exp, 1);
5316 fold (arg1);
5317 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5318 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, EXPAND_NORMAL);
5319 target = gen_reg_rtx (SImode);
5320
5321 if (!CONST_INT_P (op1))
5322 {
5323 /* If we can't fold the alignment to a constant integer
5324 whilst optimizing, this is probably a user error. */
5325 if (optimize)
5326 warning (0, "__builtin_arc_aligned with non-constant alignment");
5327 }
5328 else
5329 {
5330 HOST_WIDE_INT alignTest = INTVAL (op1);
5331 /* Check alignTest is positive, and a power of two. */
5332 if (alignTest <= 0 || alignTest != (alignTest & -alignTest))
5333 {
5334 error ("invalid alignment value for __builtin_arc_aligned");
5335 return NULL_RTX;
5336 }
5337
5338 if (CONST_INT_P (op0))
5339 {
5340 HOST_WIDE_INT pnt = INTVAL (op0);
5341
5342 if ((pnt & (alignTest - 1)) == 0)
5343 return const1_rtx;
5344 }
5345 else
5346 {
5347 unsigned align = get_pointer_alignment (arg0);
5348 unsigned numBits = alignTest * BITS_PER_UNIT;
5349
5350 if (align && align >= numBits)
5351 return const1_rtx;
5352 /* Another attempt to ascertain alignment. Check the type
5353 we are pointing to. */
5354 if (POINTER_TYPE_P (TREE_TYPE (arg0))
5355 && TYPE_ALIGN (TREE_TYPE (TREE_TYPE (arg0))) >= numBits)
5356 return const1_rtx;
5357 }
5358 }
5359
5360 /* Default to false. */
5361 return const0_rtx;
5362
5363 default:
5364 break;
5365 }
5366
5367 /* @@@ Should really do something sensible here. */
5368 return NULL_RTX;
5369}
5370
5371/* Returns true if the operands[opno] is a valid compile-time constant to be
5372 used as register number in the code for builtins. Else it flags an error
5373 and returns false. */
5374
5375bool
5376check_if_valid_regno_const (rtx *operands, int opno)
5377{
5378
5379 switch (GET_CODE (operands[opno]))
5380 {
5381 case SYMBOL_REF :
5382 case CONST :
5383 case CONST_INT :
5384 return true;
5385 default:
5386 error ("register number must be a compile-time constant. Try giving higher optimization levels");
5387 break;
5388 }
5389 return false;
5390}
5391
5392/* Check that after all the constant folding, whether the operand to
5393 __builtin_arc_sleep is an unsigned int of 6 bits. If not, flag an error. */
5394
5395bool
5396check_if_valid_sleep_operand (rtx *operands, int opno)
5397{
5398 switch (GET_CODE (operands[opno]))
5399 {
5400 case CONST :
5401 case CONST_INT :
5402 if( UNSIGNED_INT6 (INTVAL (operands[opno])))
5403 return true;
5404 default:
5405 fatal_error("operand for sleep instruction must be an unsigned 6 bit compile-time constant");
5406 break;
5407 }
5408 return false;
5409}
5410
5411/* Return true if it is ok to make a tail-call to DECL. */
5412
5413static bool
5414arc_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
5415 tree exp ATTRIBUTE_UNUSED)
5416{
5417 /* Never tailcall from an ISR routine - it needs a special exit sequence. */
5418 if (ARC_INTERRUPT_P (arc_compute_function_type (cfun)))
5419 return false;
5420
5421 /* Everything else is ok. */
5422 return true;
5423}
5424
5425/* Output code to add DELTA to the first argument, and then jump
5426 to FUNCTION. Used for C++ multiple inheritance. */
5427
5428static void
5429arc_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
5430 HOST_WIDE_INT delta,
5431 HOST_WIDE_INT vcall_offset,
5432 tree function)
5433{
5434 int mi_delta = delta;
5435 const char *const mi_op = mi_delta < 0 ? "sub" : "add";
5436 int shift = 0;
5437 int this_regno
5438 = aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function) ? 1 : 0;
5439 rtx fnaddr;
5440
5441 if (mi_delta < 0)
5442 mi_delta = - mi_delta;
5443
5444 /* Add DELTA. When possible use a plain add, otherwise load it into
5445 a register first. */
5446
5447 while (mi_delta != 0)
5448 {
5449 if ((mi_delta & (3 << shift)) == 0)
5450 shift += 2;
5451 else
5452 {
5453 asm_fprintf (file, "\t%s\t%s, %s, %d\n",
5454 mi_op, reg_names[this_regno], reg_names[this_regno],
5455 mi_delta & (0xff << shift));
5456 mi_delta &= ~(0xff << shift);
5457 shift += 8;
5458 }
5459 }
5460
5461 /* If needed, add *(*THIS + VCALL_OFFSET) to THIS. */
5462 if (vcall_offset != 0)
5463 {
5464 /* ld r12,[this] --> temp = *this
5465 add r12,r12,vcall_offset --> temp = *(*this + vcall_offset)
5466 ld r12,[r12]
5467 add this,this,r12 --> this+ = *(*this + vcall_offset) */
5468 asm_fprintf (file, "\tld\t%s, [%s]\n",
5469 ARC_TEMP_SCRATCH_REG, reg_names[this_regno]);
5470 asm_fprintf (file, "\tadd\t%s, %s, %ld\n",
5471 ARC_TEMP_SCRATCH_REG, ARC_TEMP_SCRATCH_REG, vcall_offset);
5472 asm_fprintf (file, "\tld\t%s, [%s]\n",
5473 ARC_TEMP_SCRATCH_REG, ARC_TEMP_SCRATCH_REG);
5474 asm_fprintf (file, "\tadd\t%s, %s, %s\n", reg_names[this_regno],
5475 reg_names[this_regno], ARC_TEMP_SCRATCH_REG);
5476 }
5477
5478 fnaddr = XEXP (DECL_RTL (function), 0);
5479
5480 if (arc_is_longcall_p (fnaddr))
5481 fputs ("\tj\t", file);
5482 else
5483 fputs ("\tb\t", file);
5484 assemble_name (file, XSTR (fnaddr, 0));
5485 fputc ('\n', file);
5486}
5487
5488/* Return true if a 32 bit "long_call" should be generated for
5489 this calling SYM_REF. We generate a long_call if the function:
5490
5491 a. has an __attribute__((long call))
5492 or b. the -mlong-calls command line switch has been specified
5493
5494 However we do not generate a long call if the function has an
5495 __attribute__ ((short_call)) or __attribute__ ((medium_call))
5496
5497 This function will be called by C fragments contained in the machine
5498 description file. */
5499
5500bool
5501arc_is_longcall_p (rtx sym_ref)
5502{
5503 if (GET_CODE (sym_ref) != SYMBOL_REF)
5504 return false;
5505
5506 return (SYMBOL_REF_LONG_CALL_P (sym_ref)
5507 || (TARGET_LONG_CALLS_SET
5508 && !SYMBOL_REF_SHORT_CALL_P (sym_ref)
5509 && !SYMBOL_REF_MEDIUM_CALL_P (sym_ref)));
5510
5511}
5512
5513/* Likewise for short calls. */
5514
5515bool
5516arc_is_shortcall_p (rtx sym_ref)
5517{
5518 if (GET_CODE (sym_ref) != SYMBOL_REF)
5519 return false;
5520
5521 return (SYMBOL_REF_SHORT_CALL_P (sym_ref)
5522 || (!TARGET_LONG_CALLS_SET && !TARGET_MEDIUM_CALLS
5523 && !SYMBOL_REF_LONG_CALL_P (sym_ref)
5524 && !SYMBOL_REF_MEDIUM_CALL_P (sym_ref)));
5525
5526}
5527
5528/* Emit profiling code for calling CALLEE. Return true if a special
5529 call pattern needs to be generated. */
5530
5531bool
5532arc_profile_call (rtx callee)
5533{
5534 rtx from = XEXP (DECL_RTL (current_function_decl), 0);
5535
5536 if (TARGET_UCB_MCOUNT)
5537 /* Profiling is done by instrumenting the callee. */
5538 return false;
5539
5540 if (CONSTANT_P (callee))
5541 {
5542 rtx count_ptr
5543 = gen_rtx_CONST (Pmode,
5544 gen_rtx_UNSPEC (Pmode,
5545 gen_rtvec (3, from, callee,
5546 CONST0_RTX (Pmode)),
5547 UNSPEC_PROF));
5548 rtx counter = gen_rtx_MEM (SImode, count_ptr);
5549 /* ??? The increment would better be done atomically, but as there is
5550 no proper hardware support, that would be too expensive. */
5551 emit_move_insn (counter,
5552 force_reg (SImode, plus_constant (SImode, counter, 1)));
5553 return false;
5554 }
5555 else
5556 {
5557 rtx count_list_ptr
5558 = gen_rtx_CONST (Pmode,
5559 gen_rtx_UNSPEC (Pmode,
5560 gen_rtvec (3, from, CONST0_RTX (Pmode),
5561 CONST0_RTX (Pmode)),
5562 UNSPEC_PROF));
5563 emit_move_insn (gen_rtx_REG (Pmode, 8), count_list_ptr);
5564 emit_move_insn (gen_rtx_REG (Pmode, 9), callee);
5565 return true;
5566 }
5567}
5568
5569/* Worker function for TARGET_RETURN_IN_MEMORY. */
5570
5571static bool
5572arc_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
5573{
5574 if (AGGREGATE_TYPE_P (type) || TREE_ADDRESSABLE (type))
5575 return true;
5576 else
5577 {
5578 HOST_WIDE_INT size = int_size_in_bytes (type);
5579 return (size == -1 || size > 8);
5580 }
5581}
5582
5583
5584/* This was in rtlanal.c, and can go in there when we decide we want
5585 to submit the change for inclusion in the GCC tree. */
5586/* Like note_stores, but allow the callback to have side effects on the rtl
5587 (like the note_stores of yore):
5588 Call FUN on each register or MEM that is stored into or clobbered by X.
5589 (X would be the pattern of an insn). DATA is an arbitrary pointer,
5590 ignored by note_stores, but passed to FUN.
5591 FUN may alter parts of the RTL.
5592
5593 FUN receives three arguments:
5594 1. the REG, MEM, CC0 or PC being stored in or clobbered,
5595 2. the SET or CLOBBER rtx that does the store,
5596 3. the pointer DATA provided to note_stores.
5597
5598 If the item being stored in or clobbered is a SUBREG of a hard register,
5599 the SUBREG will be passed. */
5600
5601/* For now. */ static
5602void
5603walk_stores (rtx x, void (*fun) (rtx, rtx, void *), void *data)
5604{
5605 int i;
5606
5607 if (GET_CODE (x) == COND_EXEC)
5608 x = COND_EXEC_CODE (x);
5609
5610 if (GET_CODE (x) == SET || GET_CODE (x) == CLOBBER)
5611 {
5612 rtx dest = SET_DEST (x);
5613
5614 while ((GET_CODE (dest) == SUBREG
5615 && (!REG_P (SUBREG_REG (dest))
5616 || REGNO (SUBREG_REG (dest)) >= FIRST_PSEUDO_REGISTER))
5617 || GET_CODE (dest) == ZERO_EXTRACT
5618 || GET_CODE (dest) == STRICT_LOW_PART)
5619 dest = XEXP (dest, 0);
5620
5621 /* If we have a PARALLEL, SET_DEST is a list of EXPR_LIST expressions,
5622 each of whose first operand is a register. */
5623 if (GET_CODE (dest) == PARALLEL)
5624 {
5625 for (i = XVECLEN (dest, 0) - 1; i >= 0; i--)
5626 if (XEXP (XVECEXP (dest, 0, i), 0) != 0)
5627 (*fun) (XEXP (XVECEXP (dest, 0, i), 0), x, data);
5628 }
5629 else
5630 (*fun) (dest, x, data);
5631 }
5632
5633 else if (GET_CODE (x) == PARALLEL)
5634 for (i = XVECLEN (x, 0) - 1; i >= 0; i--)
5635 walk_stores (XVECEXP (x, 0, i), fun, data);
5636}
5637
5638static bool
5639arc_pass_by_reference (cumulative_args_t ca_v ATTRIBUTE_UNUSED,
5640 enum machine_mode mode ATTRIBUTE_UNUSED,
5641 const_tree type,
5642 bool named ATTRIBUTE_UNUSED)
5643{
5644 return (type != 0
5645 && (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
5646 || TREE_ADDRESSABLE (type)));
5647}
5648
5649
5650/* NULL if INSN insn is valid within a low-overhead loop.
5651 Otherwise return why doloop cannot be applied. */
5652
5653static const char *
5654arc_invalid_within_doloop (const_rtx insn)
5655{
5656 if (CALL_P (insn))
5657 return "Function call in the loop.";
5658 return NULL;
5659}
5660
5661static int arc_reorg_in_progress = 0;
5662
5663/* ARC's machince specific reorg function. */
5664
5665static void
5666arc_reorg (void)
5667{
5668 rtx insn, pattern;
5669 rtx pc_target;
5670 long offset;
5671 int changed;
5672
5673 cfun->machine->arc_reorg_started = 1;
5674 arc_reorg_in_progress = 1;
5675
5676 /* Emit special sections for profiling. */
5677 if (crtl->profile)
5678 {
5679 section *save_text_section;
5680 rtx insn;
5681 int size = get_max_uid () >> 4;
5682 htab_t htab = htab_create (size, unspec_prof_hash, unspec_prof_htab_eq,
5683 NULL);
5684
5685 save_text_section = in_section;
5686 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5687 if (NONJUMP_INSN_P (insn))
5688 walk_stores (PATTERN (insn), write_profile_sections, htab);
5689 if (htab_elements (htab))
5690 in_section = 0;
5691 switch_to_section (save_text_section);
5692 htab_delete (htab);
5693 }
5694
5695 /* Link up loop ends with their loop start. */
5696 {
5697 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5698 if (GET_CODE (insn) == JUMP_INSN
5699 && recog_memoized (insn) == CODE_FOR_doloop_end_i)
5700 {
5701 rtx top_label
5702 = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 1), 0);
5703 rtx num = GEN_INT (CODE_LABEL_NUMBER (top_label));
5704 rtx lp, prev = prev_nonnote_insn (top_label);
5705 rtx lp_simple = NULL_RTX;
5706 rtx next = NULL_RTX;
5707 rtx op0 = XEXP (XVECEXP (PATTERN (insn), 0, 1), 0);
5708 HOST_WIDE_INT loop_end_id
5709 = -INTVAL (XEXP (XVECEXP (PATTERN (insn), 0, 4), 0));
5710 int seen_label = 0;
5711
5712 for (lp = prev;
5713 (lp && NONJUMP_INSN_P (lp)
5714 && recog_memoized (lp) != CODE_FOR_doloop_begin_i);
5715 lp = prev_nonnote_insn (lp))
5716 ;
5717 if (!lp || !NONJUMP_INSN_P (lp)
5718 || dead_or_set_regno_p (lp, LP_COUNT))
5719 {
5720 for (prev = next = insn, lp = NULL_RTX ; prev || next;)
5721 {
5722 if (prev)
5723 {
5724 if (NONJUMP_INSN_P (prev)
5725 && recog_memoized (prev) == CODE_FOR_doloop_begin_i
5726 && (INTVAL (XEXP (XVECEXP (PATTERN (prev), 0, 5), 0))
5727 == loop_end_id))
5728 {
5729 lp = prev;
5730 break;
5731 }
5732 else if (LABEL_P (prev))
5733 seen_label = 1;
5734 prev = prev_nonnote_insn (prev);
5735 }
5736 if (next)
5737 {
5738 if (NONJUMP_INSN_P (next)
5739 && recog_memoized (next) == CODE_FOR_doloop_begin_i
5740 && (INTVAL (XEXP (XVECEXP (PATTERN (next), 0, 5), 0))
5741 == loop_end_id))
5742 {
5743 lp = next;
5744 break;
5745 }
5746 next = next_nonnote_insn (next);
5747 }
5748 }
5749 prev = NULL_RTX;
5750 }
5751 else
5752 lp_simple = lp;
5753 if (lp && !dead_or_set_regno_p (lp, LP_COUNT))
5754 {
5755 rtx begin_cnt = XEXP (XVECEXP (PATTERN (lp), 0 ,3), 0);
5756 if (INTVAL (XEXP (XVECEXP (PATTERN (lp), 0, 4), 0)))
5757 /* The loop end insn has been duplicated. That can happen
5758 when there is a conditional block at the very end of
5759 the loop. */
5760 goto failure;
5761 /* If Register allocation failed to allocate to the right
5762 register, There is no point into teaching reload to
5763 fix this up with reloads, as that would cost more
5764 than using an ordinary core register with the
5765 doloop_fallback pattern. */
5766 if ((true_regnum (op0) != LP_COUNT || !REG_P (begin_cnt))
5767 /* Likewise, if the loop setup is evidently inside the loop,
5768 we loose. */
5769 || (!lp_simple && lp != next && !seen_label))
5770 {
5771 remove_insn (lp);
5772 goto failure;
5773 }
5774 /* It is common that the optimizers copy the loop count from
5775 another register, and doloop_begin_i is stuck with the
5776 source of the move. Making doloop_begin_i only accept "l"
5777 is nonsentical, as this then makes reload evict the pseudo
5778 used for the loop end. The underlying cause is that the
5779 optimizers don't understand that the register allocation for
5780 doloop_begin_i should be treated as part of the loop.
5781 Try to work around this problem by verifying the previous
5782 move exists. */
5783 if (true_regnum (begin_cnt) != LP_COUNT)
5784 {
5785 rtx mov, set, note;
5786
5787 for (mov = prev_nonnote_insn (lp); mov;
5788 mov = prev_nonnote_insn (mov))
5789 {
5790 if (!NONJUMP_INSN_P (mov))
5791 mov = 0;
5792 else if ((set = single_set (mov))
5793 && rtx_equal_p (SET_SRC (set), begin_cnt)
5794 && rtx_equal_p (SET_DEST (set), op0))
5795 break;
5796 }
5797 if (mov)
5798 {
5799 XEXP (XVECEXP (PATTERN (lp), 0 ,3), 0) = op0;
5800 note = find_regno_note (lp, REG_DEAD, REGNO (begin_cnt));
5801 if (note)
5802 remove_note (lp, note);
5803 }
5804 else
5805 {
5806 remove_insn (lp);
5807 goto failure;
5808 }
5809 }
5810 XEXP (XVECEXP (PATTERN (insn), 0, 4), 0) = num;
5811 XEXP (XVECEXP (PATTERN (lp), 0, 4), 0) = num;
5812 if (next == lp)
5813 XEXP (XVECEXP (PATTERN (lp), 0, 6), 0) = const2_rtx;
5814 else if (!lp_simple)
5815 XEXP (XVECEXP (PATTERN (lp), 0, 6), 0) = const1_rtx;
5816 else if (prev != lp)
5817 {
5818 remove_insn (lp);
5819 add_insn_after (lp, prev, NULL);
5820 }
5821 if (!lp_simple)
5822 {
5823 XEXP (XVECEXP (PATTERN (lp), 0, 7), 0)
5824 = gen_rtx_LABEL_REF (Pmode, top_label);
5825 add_reg_note (lp, REG_LABEL_OPERAND, top_label);
5826 LABEL_NUSES (top_label)++;
5827 }
5828 /* We can avoid tedious loop start / end setting for empty loops
5829 be merely setting the loop count to its final value. */
5830 if (next_active_insn (top_label) == insn)
5831 {
5832 rtx lc_set
5833 = gen_rtx_SET (VOIDmode,
5834 XEXP (XVECEXP (PATTERN (lp), 0, 3), 0),
5835 const0_rtx);
5836
5837 lc_set = emit_insn_before (lc_set, insn);
5838 delete_insn (lp);
5839 delete_insn (insn);
5840 insn = lc_set;
5841 }
5842 /* If the loop is non-empty with zero length, we can't make it
5843 a zero-overhead loop. That can happen for empty asms. */
5844 else
5845 {
5846 rtx scan;
5847
5848 for (scan = top_label;
5849 (scan && scan != insn
5850 && (!NONJUMP_INSN_P (scan) || !get_attr_length (scan)));
5851 scan = NEXT_INSN (scan));
5852 if (scan == insn)
5853 {
5854 remove_insn (lp);
5855 goto failure;
5856 }
5857 }
5858 }
5859 else
5860 {
5861 /* Sometimes the loop optimizer makes a complete hash of the
5862 loop. If it were only that the loop is not entered at the
5863 top, we could fix this up by setting LP_START with SR .
5864 However, if we can't find the loop begin were it should be,
5865 chances are that it does not even dominate the loop, but is
5866 inside the loop instead. Using SR there would kill
5867 performance.
5868 We use the doloop_fallback pattern here, which executes
5869 in two cycles on the ARC700 when predicted correctly. */
5870 failure:
5871 if (!REG_P (op0))
5872 {
5873 rtx op3 = XEXP (XVECEXP (PATTERN (insn), 0, 5), 0);
5874
5875 emit_insn_before (gen_move_insn (op3, op0), insn);
5876 PATTERN (insn)
5877 = gen_doloop_fallback_m (op3, JUMP_LABEL (insn), op0);
5878 }
5879 else
5880 XVEC (PATTERN (insn), 0)
5881 = gen_rtvec (2, XVECEXP (PATTERN (insn), 0, 0),
5882 XVECEXP (PATTERN (insn), 0, 1));
5883 INSN_CODE (insn) = -1;
5884 }
5885 }
5886 }
5887
5888/* FIXME: should anticipate ccfsm action, generate special patterns for
5889 to-be-deleted branches that have no delay slot and have at least the
5890 length of the size increase forced on other insns that are conditionalized.
5891 This can also have an insn_list inside that enumerates insns which are
5892 not actually conditionalized because the destinations are dead in the
5893 not-execute case.
5894 Could also tag branches that we want to be unaligned if they get no delay
5895 slot, or even ones that we don't want to do delay slot sheduling for
5896 because we can unalign them.
5897
5898 However, there are cases when conditional execution is only possible after
5899 delay slot scheduling:
5900
5901 - If a delay slot is filled with a nocond/set insn from above, the previous
5902 basic block can become elegible for conditional execution.
5903 - If a delay slot is filled with a nocond insn from the fall-through path,
5904 the branch with that delay slot can become eligble for conditional
5905 execution (however, with the same sort of data flow analysis that dbr
5906 does, we could have figured out before that we don't need to
5907 conditionalize this insn.)
5908 - If a delay slot insn is filled with an insn from the target, the
5909 target label gets its uses decremented (even deleted if falling to zero),
5910 thus possibly creating more condexec opportunities there.
5911 Therefore, we should still be prepared to apply condexec optimization on
5912 non-prepared branches if the size increase of conditionalized insns is no
5913 more than the size saved from eliminating the branch. An invocation option
5914 could also be used to reserve a bit of extra size for condbranches so that
5915 this'll work more often (could also test in arc_reorg if the block is
5916 'close enough' to be eligible for condexec to make this likely, and
5917 estimate required size increase). */
5918 /* Generate BRcc insns, by combining cmp and Bcc insns wherever possible. */
5919 if (TARGET_NO_BRCC_SET)
5920 return;
5921
5922 do
5923 {
5924 init_insn_lengths();
5925 changed = 0;
5926
5927 if (optimize > 1 && !TARGET_NO_COND_EXEC)
5928 {
5929 arc_ifcvt ();
5930 unsigned int flags = pass_data_arc_ifcvt.todo_flags_finish;
5931 df_finish_pass ((flags & TODO_df_verify) != 0);
5932 }
5933
5934 /* Call shorten_branches to calculate the insn lengths. */
5935 shorten_branches (get_insns());
5936 cfun->machine->ccfsm_current_insn = NULL_RTX;
5937
5938 if (!INSN_ADDRESSES_SET_P())
5939 fatal_error ("Insn addresses not set after shorten_branches");
5940
5941 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5942 {
5943 rtx label;
5944 enum attr_type insn_type;
5945
5946 /* If a non-jump insn (or a casesi jump table), continue. */
5947 if (GET_CODE (insn) != JUMP_INSN ||
5948 GET_CODE (PATTERN (insn)) == ADDR_VEC
5949 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
5950 continue;
5951
5952 /* If we already have a brcc, note if it is suitable for brcc_s.
5953 Be a bit generous with the brcc_s range so that we can take
5954 advantage of any code shortening from delay slot scheduling. */
5955 if (recog_memoized (insn) == CODE_FOR_cbranchsi4_scratch)
5956 {
5957 rtx pat = PATTERN (insn);
5958 rtx op = XEXP (SET_SRC (XVECEXP (pat, 0, 0)), 0);
5959 rtx *ccp = &XEXP (XVECEXP (pat, 0, 1), 0);
5960
5961 offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
5962 if ((offset >= -140 && offset < 140)
5963 && rtx_equal_p (XEXP (op, 1), const0_rtx)
5964 && compact_register_operand (XEXP (op, 0), VOIDmode)
5965 && equality_comparison_operator (op, VOIDmode))
5966 PUT_MODE (*ccp, CC_Zmode);
5967 else if (GET_MODE (*ccp) == CC_Zmode)
5968 PUT_MODE (*ccp, CC_ZNmode);
5969 continue;
5970 }
5971 if ((insn_type = get_attr_type (insn)) == TYPE_BRCC
5972 || insn_type == TYPE_BRCC_NO_DELAY_SLOT)
5973 continue;
5974
5975 /* OK. so we have a jump insn. */
5976 /* We need to check that it is a bcc. */
5977 /* Bcc => set (pc) (if_then_else ) */
5978 pattern = PATTERN (insn);
5979 if (GET_CODE (pattern) != SET
5980 || GET_CODE (SET_SRC (pattern)) != IF_THEN_ELSE
5981 || ANY_RETURN_P (XEXP (SET_SRC (pattern), 1)))
5982 continue;
5983
5984 /* Now check if the jump is beyond the s9 range. */
5985 if (find_reg_note (insn, REG_CROSSING_JUMP, NULL_RTX))
5986 continue;
5987 offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
5988
5989 if(offset > 253 || offset < -254)
5990 continue;
5991
5992 pc_target = SET_SRC (pattern);
5993
5994 /* Now go back and search for the set cc insn. */
5995
5996 label = XEXP (pc_target, 1);
5997
5998 {
5999 rtx pat, scan, link_insn = NULL;
6000
6001 for (scan = PREV_INSN (insn);
6002 scan && GET_CODE (scan) != CODE_LABEL;
6003 scan = PREV_INSN (scan))
6004 {
6005 if (! INSN_P (scan))
6006 continue;
6007 pat = PATTERN (scan);
6008 if (GET_CODE (pat) == SET
6009 && cc_register (SET_DEST (pat), VOIDmode))
6010 {
6011 link_insn = scan;
6012 break;
6013 }
6014 }
6015 if (! link_insn)
6016 continue;
6017 else
6018 /* Check if this is a data dependency. */
6019 {
6020 rtx op, cc_clob_rtx, op0, op1, brcc_insn, note;
6021 rtx cmp0, cmp1;
6022
6023 /* Ok this is the set cc. copy args here. */
6024 op = XEXP (pc_target, 0);
6025
6026 op0 = cmp0 = XEXP (SET_SRC (pat), 0);
6027 op1 = cmp1 = XEXP (SET_SRC (pat), 1);
6028 if (GET_CODE (op0) == ZERO_EXTRACT
6029 && XEXP (op0, 1) == const1_rtx
6030 && (GET_CODE (op) == EQ
6031 || GET_CODE (op) == NE))
6032 {
6033 /* btst / b{eq,ne} -> bbit{0,1} */
6034 op0 = XEXP (cmp0, 0);
6035 op1 = XEXP (cmp0, 2);
6036 }
6037 else if (!register_operand (op0, VOIDmode)
6038 || !general_operand (op1, VOIDmode))
6039 continue;
6040 /* Be careful not to break what cmpsfpx_raw is
6041 trying to create for checking equality of
6042 single-precision floats. */
6043 else if (TARGET_SPFP
6044 && GET_MODE (op0) == SFmode
6045 && GET_MODE (op1) == SFmode)
6046 continue;
6047
6048 /* None of the two cmp operands should be set between the
6049 cmp and the branch. */
6050 if (reg_set_between_p (op0, link_insn, insn))
6051 continue;
6052
6053 if (reg_set_between_p (op1, link_insn, insn))
6054 continue;
6055
6056 /* Since the MODE check does not work, check that this is
6057 CC reg's last set location before insn, and also no
6058 instruction between the cmp and branch uses the
6059 condition codes. */
6060 if ((reg_set_between_p (SET_DEST (pat), link_insn, insn))
6061 || (reg_used_between_p (SET_DEST (pat), link_insn, insn)))
6062 continue;
6063
6064 /* CC reg should be dead after insn. */
6065 if (!find_regno_note (insn, REG_DEAD, CC_REG))
6066 continue;
6067
6068 op = gen_rtx_fmt_ee (GET_CODE (op),
6069 GET_MODE (op), cmp0, cmp1);
6070 /* If we create a LIMM where there was none before,
6071 we only benefit if we can avoid a scheduling bubble
6072 for the ARC600. Otherwise, we'd only forgo chances
6073 at short insn generation, and risk out-of-range
6074 branches. */
6075 if (!brcc_nolimm_operator (op, VOIDmode)
6076 && !long_immediate_operand (op1, VOIDmode)
6077 && (TARGET_ARC700
6078 || next_active_insn (link_insn) != insn))
6079 continue;
6080
6081 /* Emit bbit / brcc (or brcc_s if possible).
6082 CC_Zmode indicates that brcc_s is possible. */
6083
6084 if (op0 != cmp0)
6085 cc_clob_rtx = gen_rtx_REG (CC_ZNmode, CC_REG);
6086 else if ((offset >= -140 && offset < 140)
6087 && rtx_equal_p (op1, const0_rtx)
6088 && compact_register_operand (op0, VOIDmode)
6089 && (GET_CODE (op) == EQ
6090 || GET_CODE (op) == NE))
6091 cc_clob_rtx = gen_rtx_REG (CC_Zmode, CC_REG);
6092 else
6093 cc_clob_rtx = gen_rtx_REG (CCmode, CC_REG);
6094
6095 brcc_insn
6096 = gen_rtx_IF_THEN_ELSE (VOIDmode, op, label, pc_rtx);
6097 brcc_insn = gen_rtx_SET (VOIDmode, pc_rtx, brcc_insn);
6098 cc_clob_rtx = gen_rtx_CLOBBER (VOIDmode, cc_clob_rtx);
6099 brcc_insn
6100 = gen_rtx_PARALLEL
6101 (VOIDmode, gen_rtvec (2, brcc_insn, cc_clob_rtx));
6102 brcc_insn = emit_jump_insn_before (brcc_insn, insn);
6103
6104 JUMP_LABEL (brcc_insn) = JUMP_LABEL (insn);
6105 note = find_reg_note (insn, REG_BR_PROB, 0);
6106 if (note)
6107 {
6108 XEXP (note, 1) = REG_NOTES (brcc_insn);
6109 REG_NOTES (brcc_insn) = note;
6110 }
6111 note = find_reg_note (link_insn, REG_DEAD, op0);
6112 if (note)
6113 {
6114 remove_note (link_insn, note);
6115 XEXP (note, 1) = REG_NOTES (brcc_insn);
6116 REG_NOTES (brcc_insn) = note;
6117 }
6118 note = find_reg_note (link_insn, REG_DEAD, op1);
6119 if (note)
6120 {
6121 XEXP (note, 1) = REG_NOTES (brcc_insn);
6122 REG_NOTES (brcc_insn) = note;
6123 }
6124
6125 changed = 1;
6126
6127 /* Delete the bcc insn. */
6128 set_insn_deleted (insn);
6129
6130 /* Delete the cmp insn. */
6131 set_insn_deleted (link_insn);
6132
6133 }
6134 }
6135 }
6136 /* Clear out insn_addresses. */
6137 INSN_ADDRESSES_FREE ();
6138
6139 } while (changed);
6140
6141 if (INSN_ADDRESSES_SET_P())
6142 fatal_error ("insn addresses not freed");
6143
6144 arc_reorg_in_progress = 0;
6145}
6146
6147 /* Check if the operands are valid for BRcc.d generation
6148 Valid Brcc.d patterns are
6149 Brcc.d b, c, s9
6150 Brcc.d b, u6, s9
6151
6152 For cc={GT, LE, GTU, LEU}, u6=63 can not be allowed,
6153 since they are encoded by the assembler as {GE, LT, HS, LS} 64, which
6154 does not have a delay slot
6155
6156 Assumed precondition: Second operand is either a register or a u6 value. */
6157
6158bool
6159valid_brcc_with_delay_p (rtx *operands)
6160{
6161 if (optimize_size && GET_MODE (operands[4]) == CC_Zmode)
6162 return false;
6163 return brcc_nolimm_operator (operands[0], VOIDmode);
6164}
6165
6166/* ??? Hack. This should no really be here. See PR32143. */
6167static bool
6168arc_decl_anon_ns_mem_p (const_tree decl)
6169{
6170 while (1)
6171 {
6172 if (decl == NULL_TREE || decl == error_mark_node)
6173 return false;
6174 if (TREE_CODE (decl) == NAMESPACE_DECL
6175 && DECL_NAME (decl) == NULL_TREE)
6176 return true;
6177 /* Classes and namespaces inside anonymous namespaces have
6178 TREE_PUBLIC == 0, so we can shortcut the search. */
6179 else if (TYPE_P (decl))
6180 return (TREE_PUBLIC (TYPE_NAME (decl)) == 0);
6181 else if (TREE_CODE (decl) == NAMESPACE_DECL)
6182 return (TREE_PUBLIC (decl) == 0);
6183 else
6184 decl = DECL_CONTEXT (decl);
6185 }
6186}
6187
6188/* Implement TARGET_IN_SMALL_DATA_P. Return true if it would be safe to
6189 access DECL using %gp_rel(...)($gp). */
6190
6191static bool
6192arc_in_small_data_p (const_tree decl)
6193{
6194 HOST_WIDE_INT size;
6195
6196 if (TREE_CODE (decl) == STRING_CST || TREE_CODE (decl) == FUNCTION_DECL)
6197 return false;
6198
6199
6200 /* We don't yet generate small-data references for -mabicalls. See related
6201 -G handling in override_options. */
6202 if (TARGET_NO_SDATA_SET)
6203 return false;
6204
6205 if (TREE_CODE (decl) == VAR_DECL && DECL_SECTION_NAME (decl) != 0)
6206 {
6207 const char *name;
6208
6209 /* Reject anything that isn't in a known small-data section. */
6210 name = TREE_STRING_POINTER (DECL_SECTION_NAME (decl));
6211 if (strcmp (name, ".sdata") != 0 && strcmp (name, ".sbss") != 0)
6212 return false;
6213
6214 /* If a symbol is defined externally, the assembler will use the
6215 usual -G rules when deciding how to implement macros. */
6216 if (!DECL_EXTERNAL (decl))
6217 return true;
6218 }
6219 /* Only global variables go into sdata section for now. */
6220 else if (1)
6221 {
6222 /* Don't put constants into the small data section: we want them
6223 to be in ROM rather than RAM. */
6224 if (TREE_CODE (decl) != VAR_DECL)
6225 return false;
6226
6227 if (TREE_READONLY (decl)
6228 && !TREE_SIDE_EFFECTS (decl)
6229 && (!DECL_INITIAL (decl) || TREE_CONSTANT (DECL_INITIAL (decl))))
6230 return false;
6231
6232 /* TREE_PUBLIC might change after the first call, because of the patch
6233 for PR19238. */
6234 if (default_binds_local_p_1 (decl, 1)
6235 || arc_decl_anon_ns_mem_p (decl))
6236 return false;
6237
6238 /* To ensure -mvolatile-cache works
6239 ld.di does not have a gp-relative variant. */
6240 if (TREE_THIS_VOLATILE (decl))
6241 return false;
6242 }
6243
6244 /* Disable sdata references to weak variables. */
6245 if (DECL_WEAK (decl))
6246 return false;
6247
6248 size = int_size_in_bytes (TREE_TYPE (decl));
6249
6250/* if (AGGREGATE_TYPE_P (TREE_TYPE (decl))) */
6251/* return false; */
6252
6253 /* Allow only <=4B long data types into sdata. */
6254 return (size > 0 && size <= 4);
6255}
6256
6257/* Return true if X is a small data address that can be rewritten
6258 as a gp+symref. */
6259
6260static bool
6261arc_rewrite_small_data_p (rtx x)
6262{
6263 if (GET_CODE (x) == CONST)
6264 x = XEXP (x, 0);
6265
6266 if (GET_CODE (x) == PLUS)
6267 {
6268 if (GET_CODE (XEXP (x, 1)) == CONST_INT)
6269 x = XEXP (x, 0);
6270 }
6271
6272 return (GET_CODE (x) == SYMBOL_REF
6273 && SYMBOL_REF_SMALL_P(x));
6274}
6275
6276/* A for_each_rtx callback, used by arc_rewrite_small_data. */
6277
6278static int
6279arc_rewrite_small_data_1 (rtx *loc, void *data)
6280{
6281 if (arc_rewrite_small_data_p (*loc))
6282 {
6283 rtx top;
6284
6285 gcc_assert (SDATA_BASE_REGNUM == PIC_OFFSET_TABLE_REGNUM);
6286 *loc = gen_rtx_PLUS (Pmode, pic_offset_table_rtx, *loc);
6287 if (loc == data)
6288 return -1;
6289 top = *(rtx*) data;
6290 if (GET_CODE (top) == MEM && &XEXP (top, 0) == loc)
6291 ; /* OK. */
6292 else if (GET_CODE (top) == MEM
6293 && GET_CODE (XEXP (top, 0)) == PLUS
6294 && GET_CODE (XEXP (XEXP (top, 0), 0)) == MULT)
6295 *loc = force_reg (Pmode, *loc);
6296 else
6297 gcc_unreachable ();
6298 return -1;
6299 }
6300
6301 if (GET_CODE (*loc) == PLUS
6302 && rtx_equal_p (XEXP (*loc, 0), pic_offset_table_rtx))
6303 return -1;
6304
6305 return 0;
6306}
6307
6308/* If possible, rewrite OP so that it refers to small data using
6309 explicit relocations. */
6310
6311rtx
6312arc_rewrite_small_data (rtx op)
6313{
6314 op = copy_insn (op);
6315 for_each_rtx (&op, arc_rewrite_small_data_1, &op);
6316 return op;
6317}
6318
6319/* A for_each_rtx callback for small_data_pattern. */
6320
6321static int
6322small_data_pattern_1 (rtx *loc, void *data ATTRIBUTE_UNUSED)
6323{
6324 if (GET_CODE (*loc) == PLUS
6325 && rtx_equal_p (XEXP (*loc, 0), pic_offset_table_rtx))
6326 return -1;
6327
6328 return arc_rewrite_small_data_p (*loc);
6329}
6330
6331/* Return true if OP refers to small data symbols directly, not through
6332 a PLUS. */
6333
6334bool
6335small_data_pattern (rtx op, enum machine_mode)
6336{
6337 return (GET_CODE (op) != SEQUENCE
6338 && for_each_rtx (&op, small_data_pattern_1, 0));
6339}
6340
6341/* Return true if OP is an acceptable memory operand for ARCompact
6342 16-bit gp-relative load instructions.
6343 op shd look like : [r26, symref@sda]
6344 i.e. (mem (plus (reg 26) (symref with smalldata flag set))
6345 */
6346/* volatile cache option still to be handled. */
6347
6348bool
6349compact_sda_memory_operand (rtx op, enum machine_mode mode)
6350{
6351 rtx addr;
6352 int size;
6353
6354 /* Eliminate non-memory operations. */
6355 if (GET_CODE (op) != MEM)
6356 return false;
6357
6358 if (mode == VOIDmode)
6359 mode = GET_MODE (op);
6360
6361 size = GET_MODE_SIZE (mode);
6362
6363 /* dword operations really put out 2 instructions, so eliminate them. */
6364 if (size > UNITS_PER_WORD)
6365 return false;
6366
6367 /* Decode the address now. */
6368 addr = XEXP (op, 0);
6369
6370 return LEGITIMATE_SMALL_DATA_ADDRESS_P (addr);
6371}
6372
6373/* Implement ASM_OUTPUT_ALIGNED_DECL_LOCAL. */
6374
6375void
6376arc_asm_output_aligned_decl_local (FILE * stream, tree decl, const char * name,
6377 unsigned HOST_WIDE_INT size,
6378 unsigned HOST_WIDE_INT align,
6379 unsigned HOST_WIDE_INT globalize_p)
6380{
6381 int in_small_data = arc_in_small_data_p (decl);
6382
6383 if (in_small_data)
6384 switch_to_section (get_named_section (NULL, ".sbss", 0));
6385 /* named_section (0,".sbss",0); */
6386 else
6387 switch_to_section (bss_section);
6388
6389 if (globalize_p)
6390 (*targetm.asm_out.globalize_label) (stream, name);
6391
6392 ASM_OUTPUT_ALIGN (stream, floor_log2 ((align) / BITS_PER_UNIT));
6393 ASM_OUTPUT_TYPE_DIRECTIVE (stream, name, "object");
6394 ASM_OUTPUT_SIZE_DIRECTIVE (stream, name, size);
6395 ASM_OUTPUT_LABEL (stream, name);
6396
6397 if (size != 0)
6398 ASM_OUTPUT_SKIP (stream, size);
6399}
6400
6401
6402
6403
6404
6405
6406
6407
6408
6409
6410
6411
6412
6413
6414
6415
6416
6417
6418
6419
6420
6421
6422
6423
6424
6425
6426
6427
6428
6429
6430
6431
6432
6433
6434/* SIMD builtins support. */
6435enum simd_insn_args_type {
6436 Va_Vb_Vc,
6437 Va_Vb_rlimm,
6438 Va_Vb_Ic,
6439 Va_Vb_u6,
6440 Va_Vb_u8,
6441 Va_rlimm_u8,
6442
6443 Va_Vb,
6444
6445 void_rlimm,
6446 void_u6,
6447
6448 Da_u3_rlimm,
6449 Da_rlimm_rlimm,
6450
6451 Va_Ib_u8,
6452 void_Va_Ib_u8,
6453
6454 Va_Vb_Ic_u8,
6455 void_Va_u3_Ib_u8
6456};
6457
6458struct builtin_description
6459{
6460 enum simd_insn_args_type args_type;
6461 const enum insn_code icode;
6462 const char * const name;
6463 const enum arc_builtins code;
6464};
6465
6466static const struct builtin_description arc_simd_builtin_desc_list[] =
6467{
6468 /* VVV builtins go first. */
6469#define SIMD_BUILTIN(type, code, string, builtin) \
6470 { type,CODE_FOR_##code, "__builtin_arc_" string, \
6471 ARC_SIMD_BUILTIN_##builtin },
6472
6473 SIMD_BUILTIN (Va_Vb_Vc, vaddaw_insn, "vaddaw", VADDAW)
6474 SIMD_BUILTIN (Va_Vb_Vc, vaddw_insn, "vaddw", VADDW)
6475 SIMD_BUILTIN (Va_Vb_Vc, vavb_insn, "vavb", VAVB)
6476 SIMD_BUILTIN (Va_Vb_Vc, vavrb_insn, "vavrb", VAVRB)
6477 SIMD_BUILTIN (Va_Vb_Vc, vdifaw_insn, "vdifaw", VDIFAW)
6478 SIMD_BUILTIN (Va_Vb_Vc, vdifw_insn, "vdifw", VDIFW)
6479 SIMD_BUILTIN (Va_Vb_Vc, vmaxaw_insn, "vmaxaw", VMAXAW)
6480 SIMD_BUILTIN (Va_Vb_Vc, vmaxw_insn, "vmaxw", VMAXW)
6481 SIMD_BUILTIN (Va_Vb_Vc, vminaw_insn, "vminaw", VMINAW)
6482 SIMD_BUILTIN (Va_Vb_Vc, vminw_insn, "vminw", VMINW)
6483 SIMD_BUILTIN (Va_Vb_Vc, vmulaw_insn, "vmulaw", VMULAW)
6484 SIMD_BUILTIN (Va_Vb_Vc, vmulfaw_insn, "vmulfaw", VMULFAW)
6485 SIMD_BUILTIN (Va_Vb_Vc, vmulfw_insn, "vmulfw", VMULFW)
6486 SIMD_BUILTIN (Va_Vb_Vc, vmulw_insn, "vmulw", VMULW)
6487 SIMD_BUILTIN (Va_Vb_Vc, vsubaw_insn, "vsubaw", VSUBAW)
6488 SIMD_BUILTIN (Va_Vb_Vc, vsubw_insn, "vsubw", VSUBW)
6489 SIMD_BUILTIN (Va_Vb_Vc, vsummw_insn, "vsummw", VSUMMW)
6490 SIMD_BUILTIN (Va_Vb_Vc, vand_insn, "vand", VAND)
6491 SIMD_BUILTIN (Va_Vb_Vc, vandaw_insn, "vandaw", VANDAW)
6492 SIMD_BUILTIN (Va_Vb_Vc, vbic_insn, "vbic", VBIC)
6493 SIMD_BUILTIN (Va_Vb_Vc, vbicaw_insn, "vbicaw", VBICAW)
6494 SIMD_BUILTIN (Va_Vb_Vc, vor_insn, "vor", VOR)
6495 SIMD_BUILTIN (Va_Vb_Vc, vxor_insn, "vxor", VXOR)
6496 SIMD_BUILTIN (Va_Vb_Vc, vxoraw_insn, "vxoraw", VXORAW)
6497 SIMD_BUILTIN (Va_Vb_Vc, veqw_insn, "veqw", VEQW)
6498 SIMD_BUILTIN (Va_Vb_Vc, vlew_insn, "vlew", VLEW)
6499 SIMD_BUILTIN (Va_Vb_Vc, vltw_insn, "vltw", VLTW)
6500 SIMD_BUILTIN (Va_Vb_Vc, vnew_insn, "vnew", VNEW)
6501 SIMD_BUILTIN (Va_Vb_Vc, vmr1aw_insn, "vmr1aw", VMR1AW)
6502 SIMD_BUILTIN (Va_Vb_Vc, vmr1w_insn, "vmr1w", VMR1W)
6503 SIMD_BUILTIN (Va_Vb_Vc, vmr2aw_insn, "vmr2aw", VMR2AW)
6504 SIMD_BUILTIN (Va_Vb_Vc, vmr2w_insn, "vmr2w", VMR2W)
6505 SIMD_BUILTIN (Va_Vb_Vc, vmr3aw_insn, "vmr3aw", VMR3AW)
6506 SIMD_BUILTIN (Va_Vb_Vc, vmr3w_insn, "vmr3w", VMR3W)
6507 SIMD_BUILTIN (Va_Vb_Vc, vmr4aw_insn, "vmr4aw", VMR4AW)
6508 SIMD_BUILTIN (Va_Vb_Vc, vmr4w_insn, "vmr4w", VMR4W)
6509 SIMD_BUILTIN (Va_Vb_Vc, vmr5aw_insn, "vmr5aw", VMR5AW)
6510 SIMD_BUILTIN (Va_Vb_Vc, vmr5w_insn, "vmr5w", VMR5W)
6511 SIMD_BUILTIN (Va_Vb_Vc, vmr6aw_insn, "vmr6aw", VMR6AW)
6512 SIMD_BUILTIN (Va_Vb_Vc, vmr6w_insn, "vmr6w", VMR6W)
6513 SIMD_BUILTIN (Va_Vb_Vc, vmr7aw_insn, "vmr7aw", VMR7AW)
6514 SIMD_BUILTIN (Va_Vb_Vc, vmr7w_insn, "vmr7w", VMR7W)
6515 SIMD_BUILTIN (Va_Vb_Vc, vmrb_insn, "vmrb", VMRB)
6516 SIMD_BUILTIN (Va_Vb_Vc, vh264f_insn, "vh264f", VH264F)
6517 SIMD_BUILTIN (Va_Vb_Vc, vh264ft_insn, "vh264ft", VH264FT)
6518 SIMD_BUILTIN (Va_Vb_Vc, vh264fw_insn, "vh264fw", VH264FW)
6519 SIMD_BUILTIN (Va_Vb_Vc, vvc1f_insn, "vvc1f", VVC1F)
6520 SIMD_BUILTIN (Va_Vb_Vc, vvc1ft_insn, "vvc1ft", VVC1FT)
6521
6522 SIMD_BUILTIN (Va_Vb_rlimm, vbaddw_insn, "vbaddw", VBADDW)
6523 SIMD_BUILTIN (Va_Vb_rlimm, vbmaxw_insn, "vbmaxw", VBMAXW)
6524 SIMD_BUILTIN (Va_Vb_rlimm, vbminw_insn, "vbminw", VBMINW)
6525 SIMD_BUILTIN (Va_Vb_rlimm, vbmulaw_insn, "vbmulaw", VBMULAW)
6526 SIMD_BUILTIN (Va_Vb_rlimm, vbmulfw_insn, "vbmulfw", VBMULFW)
6527 SIMD_BUILTIN (Va_Vb_rlimm, vbmulw_insn, "vbmulw", VBMULW)
6528 SIMD_BUILTIN (Va_Vb_rlimm, vbrsubw_insn, "vbrsubw", VBRSUBW)
6529 SIMD_BUILTIN (Va_Vb_rlimm, vbsubw_insn, "vbsubw", VBSUBW)
6530
6531 /* Va, Vb, Ic instructions. */
6532 SIMD_BUILTIN (Va_Vb_Ic, vasrw_insn, "vasrw", VASRW)
6533 SIMD_BUILTIN (Va_Vb_Ic, vsr8_insn, "vsr8", VSR8)
6534 SIMD_BUILTIN (Va_Vb_Ic, vsr8aw_insn, "vsr8aw", VSR8AW)
6535
6536 /* Va, Vb, u6 instructions. */
6537 SIMD_BUILTIN (Va_Vb_u6, vasrrwi_insn, "vasrrwi", VASRRWi)
6538 SIMD_BUILTIN (Va_Vb_u6, vasrsrwi_insn, "vasrsrwi", VASRSRWi)
6539 SIMD_BUILTIN (Va_Vb_u6, vasrwi_insn, "vasrwi", VASRWi)
6540 SIMD_BUILTIN (Va_Vb_u6, vasrpwbi_insn, "vasrpwbi", VASRPWBi)
6541 SIMD_BUILTIN (Va_Vb_u6, vasrrpwbi_insn,"vasrrpwbi", VASRRPWBi)
6542 SIMD_BUILTIN (Va_Vb_u6, vsr8awi_insn, "vsr8awi", VSR8AWi)
6543 SIMD_BUILTIN (Va_Vb_u6, vsr8i_insn, "vsr8i", VSR8i)
6544
6545 /* Va, Vb, u8 (simm) instructions. */
6546 SIMD_BUILTIN (Va_Vb_u8, vmvaw_insn, "vmvaw", VMVAW)
6547 SIMD_BUILTIN (Va_Vb_u8, vmvw_insn, "vmvw", VMVW)
6548 SIMD_BUILTIN (Va_Vb_u8, vmvzw_insn, "vmvzw", VMVZW)
6549 SIMD_BUILTIN (Va_Vb_u8, vd6tapf_insn, "vd6tapf", VD6TAPF)
6550
6551 /* Va, rlimm, u8 (simm) instructions. */
6552 SIMD_BUILTIN (Va_rlimm_u8, vmovaw_insn, "vmovaw", VMOVAW)
6553 SIMD_BUILTIN (Va_rlimm_u8, vmovw_insn, "vmovw", VMOVW)
6554 SIMD_BUILTIN (Va_rlimm_u8, vmovzw_insn, "vmovzw", VMOVZW)
6555
6556 /* Va, Vb instructions. */
6557 SIMD_BUILTIN (Va_Vb, vabsaw_insn, "vabsaw", VABSAW)
6558 SIMD_BUILTIN (Va_Vb, vabsw_insn, "vabsw", VABSW)
6559 SIMD_BUILTIN (Va_Vb, vaddsuw_insn, "vaddsuw", VADDSUW)
6560 SIMD_BUILTIN (Va_Vb, vsignw_insn, "vsignw", VSIGNW)
6561 SIMD_BUILTIN (Va_Vb, vexch1_insn, "vexch1", VEXCH1)
6562 SIMD_BUILTIN (Va_Vb, vexch2_insn, "vexch2", VEXCH2)
6563 SIMD_BUILTIN (Va_Vb, vexch4_insn, "vexch4", VEXCH4)
6564 SIMD_BUILTIN (Va_Vb, vupbaw_insn, "vupbaw", VUPBAW)
6565 SIMD_BUILTIN (Va_Vb, vupbw_insn, "vupbw", VUPBW)
6566 SIMD_BUILTIN (Va_Vb, vupsbaw_insn, "vupsbaw", VUPSBAW)
6567 SIMD_BUILTIN (Va_Vb, vupsbw_insn, "vupsbw", VUPSBW)
6568
6569 /* DIb, rlimm, rlimm instructions. */
6570 SIMD_BUILTIN (Da_rlimm_rlimm, vdirun_insn, "vdirun", VDIRUN)
6571 SIMD_BUILTIN (Da_rlimm_rlimm, vdorun_insn, "vdorun", VDORUN)
6572
6573 /* DIb, limm, rlimm instructions. */
6574 SIMD_BUILTIN (Da_u3_rlimm, vdiwr_insn, "vdiwr", VDIWR)
6575 SIMD_BUILTIN (Da_u3_rlimm, vdowr_insn, "vdowr", VDOWR)
6576
6577 /* rlimm instructions. */
6578 SIMD_BUILTIN (void_rlimm, vrec_insn, "vrec", VREC)
6579 SIMD_BUILTIN (void_rlimm, vrun_insn, "vrun", VRUN)
6580 SIMD_BUILTIN (void_rlimm, vrecrun_insn, "vrecrun", VRECRUN)
6581 SIMD_BUILTIN (void_rlimm, vendrec_insn, "vendrec", VENDREC)
6582
6583 /* Va, [Ib,u8] instructions. */
6584 SIMD_BUILTIN (Va_Vb_Ic_u8, vld32wh_insn, "vld32wh", VLD32WH)
6585 SIMD_BUILTIN (Va_Vb_Ic_u8, vld32wl_insn, "vld32wl", VLD32WL)
6586 SIMD_BUILTIN (Va_Vb_Ic_u8, vld64_insn, "vld64", VLD64)
6587 SIMD_BUILTIN (Va_Vb_Ic_u8, vld32_insn, "vld32", VLD32)
6588
6589 SIMD_BUILTIN (Va_Ib_u8, vld64w_insn, "vld64w", VLD64W)
6590 SIMD_BUILTIN (Va_Ib_u8, vld128_insn, "vld128", VLD128)
6591 SIMD_BUILTIN (void_Va_Ib_u8, vst128_insn, "vst128", VST128)
6592 SIMD_BUILTIN (void_Va_Ib_u8, vst64_insn, "vst64", VST64)
6593
6594 /* Va, [Ib, u8] instructions. */
6595 SIMD_BUILTIN (void_Va_u3_Ib_u8, vst16_n_insn, "vst16_n", VST16_N)
6596 SIMD_BUILTIN (void_Va_u3_Ib_u8, vst32_n_insn, "vst32_n", VST32_N)
6597
6598 SIMD_BUILTIN (void_u6, vinti_insn, "vinti", VINTI)
6599};
6600
6601static void
6602arc_init_simd_builtins (void)
6603{
6604 int i;
6605 tree endlink = void_list_node;
6606 tree V8HI_type_node = build_vector_type_for_mode (intHI_type_node, V8HImode);
6607
6608 tree v8hi_ftype_v8hi_v8hi
6609 = build_function_type (V8HI_type_node,
6610 tree_cons (NULL_TREE, V8HI_type_node,
6611 tree_cons (NULL_TREE, V8HI_type_node,
6612 endlink)));
6613 tree v8hi_ftype_v8hi_int
6614 = build_function_type (V8HI_type_node,
6615 tree_cons (NULL_TREE, V8HI_type_node,
6616 tree_cons (NULL_TREE, integer_type_node,
6617 endlink)));
6618
6619 tree v8hi_ftype_v8hi_int_int
6620 = build_function_type (V8HI_type_node,
6621 tree_cons (NULL_TREE, V8HI_type_node,
6622 tree_cons (NULL_TREE, integer_type_node,
6623 tree_cons (NULL_TREE,
6624 integer_type_node,
6625 endlink))));
6626
6627 tree void_ftype_v8hi_int_int
6628 = build_function_type (void_type_node,
6629 tree_cons (NULL_TREE, V8HI_type_node,
6630 tree_cons (NULL_TREE, integer_type_node,
6631 tree_cons (NULL_TREE,
6632 integer_type_node,
6633 endlink))));
6634
6635 tree void_ftype_v8hi_int_int_int
6636 = (build_function_type
6637 (void_type_node,
6638 tree_cons (NULL_TREE, V8HI_type_node,
6639 tree_cons (NULL_TREE, integer_type_node,
6640 tree_cons (NULL_TREE, integer_type_node,
6641 tree_cons (NULL_TREE,
6642 integer_type_node,
6643 endlink))))));
6644
6645 tree v8hi_ftype_int_int
6646 = build_function_type (V8HI_type_node,
6647 tree_cons (NULL_TREE, integer_type_node,
6648 tree_cons (NULL_TREE, integer_type_node,
6649 endlink)));
6650
6651 tree void_ftype_int_int
6652 = build_function_type (void_type_node,
6653 tree_cons (NULL_TREE, integer_type_node,
6654 tree_cons (NULL_TREE, integer_type_node,
6655 endlink)));
6656
6657 tree void_ftype_int
6658 = build_function_type (void_type_node,
6659 tree_cons (NULL_TREE, integer_type_node, endlink));
6660
6661 tree v8hi_ftype_v8hi
6662 = build_function_type (V8HI_type_node, tree_cons (NULL_TREE, V8HI_type_node,
6663 endlink));
6664
6665 /* These asserts have been introduced to ensure that the order of builtins
6666 does not get messed up, else the initialization goes wrong. */
6667 gcc_assert (arc_simd_builtin_desc_list [0].args_type == Va_Vb_Vc);
6668 for (i=0; arc_simd_builtin_desc_list [i].args_type == Va_Vb_Vc; i++)
6669 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6670 v8hi_ftype_v8hi_v8hi, arc_simd_builtin_desc_list[i].code);
6671
6672 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Vb_rlimm);
6673 for (; arc_simd_builtin_desc_list [i].args_type == Va_Vb_rlimm; i++)
6674 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6675 v8hi_ftype_v8hi_int, arc_simd_builtin_desc_list[i].code);
6676
6677 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Vb_Ic);
6678 for (; arc_simd_builtin_desc_list [i].args_type == Va_Vb_Ic; i++)
6679 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6680 v8hi_ftype_v8hi_int, arc_simd_builtin_desc_list[i].code);
6681
6682 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Vb_u6);
6683 for (; arc_simd_builtin_desc_list [i].args_type == Va_Vb_u6; i++)
6684 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6685 v8hi_ftype_v8hi_int, arc_simd_builtin_desc_list[i].code);
6686
6687 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Vb_u8);
6688 for (; arc_simd_builtin_desc_list [i].args_type == Va_Vb_u8; i++)
6689 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6690 v8hi_ftype_v8hi_int, arc_simd_builtin_desc_list[i].code);
6691
6692 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_rlimm_u8);
6693 for (; arc_simd_builtin_desc_list [i].args_type == Va_rlimm_u8; i++)
6694 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6695 v8hi_ftype_int_int, arc_simd_builtin_desc_list[i].code);
6696
6697 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Vb);
6698 for (; arc_simd_builtin_desc_list [i].args_type == Va_Vb; i++)
6699 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6700 v8hi_ftype_v8hi, arc_simd_builtin_desc_list[i].code);
6701
6702 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Da_rlimm_rlimm);
6703 for (; arc_simd_builtin_desc_list [i].args_type == Da_rlimm_rlimm; i++)
6704 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list [i].name,
6705 void_ftype_int_int, arc_simd_builtin_desc_list[i].code);
6706
6707 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Da_u3_rlimm);
6708 for (; arc_simd_builtin_desc_list [i].args_type == Da_u3_rlimm; i++)
6709 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6710 void_ftype_int_int, arc_simd_builtin_desc_list[i].code);
6711
6712 gcc_assert (arc_simd_builtin_desc_list [i].args_type == void_rlimm);
6713 for (; arc_simd_builtin_desc_list [i].args_type == void_rlimm; i++)
6714 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6715 void_ftype_int, arc_simd_builtin_desc_list[i].code);
6716
6717 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Vb_Ic_u8);
6718 for (; arc_simd_builtin_desc_list [i].args_type == Va_Vb_Ic_u8; i++)
6719 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6720 v8hi_ftype_v8hi_int_int, arc_simd_builtin_desc_list[i].code);
6721
6722 gcc_assert (arc_simd_builtin_desc_list [i].args_type == Va_Ib_u8);
6723 for (; arc_simd_builtin_desc_list [i].args_type == Va_Ib_u8; i++)
6724 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6725 v8hi_ftype_int_int, arc_simd_builtin_desc_list[i].code);
6726
6727 gcc_assert (arc_simd_builtin_desc_list [i].args_type == void_Va_Ib_u8);
6728 for (; arc_simd_builtin_desc_list [i].args_type == void_Va_Ib_u8; i++)
6729 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list [i].name,
6730 void_ftype_v8hi_int_int, arc_simd_builtin_desc_list[i].code);
6731
6732 gcc_assert (arc_simd_builtin_desc_list [i].args_type == void_Va_u3_Ib_u8);
6733 for (; arc_simd_builtin_desc_list [i].args_type == void_Va_u3_Ib_u8; i++)
6734 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6735 void_ftype_v8hi_int_int_int,
6736 arc_simd_builtin_desc_list[i].code);
6737
6738 gcc_assert (arc_simd_builtin_desc_list [i].args_type == void_u6);
6739 for (; arc_simd_builtin_desc_list [i].args_type == void_u6; i++)
6740 def_mbuiltin (TARGET_SIMD_SET, arc_simd_builtin_desc_list[i].name,
6741 void_ftype_int, arc_simd_builtin_desc_list[i].code);
6742
6743 gcc_assert(i == ARRAY_SIZE (arc_simd_builtin_desc_list));
6744}
6745
6746/* Helper function of arc_expand_builtin; has the same parameters,
6747 except that EXP is now known to be a call to a simd builtin. */
6748
6749static rtx
6750arc_expand_simd_builtin (tree exp,
6751 rtx target,
6752 rtx subtarget ATTRIBUTE_UNUSED,
6753 enum machine_mode mode ATTRIBUTE_UNUSED,
6754 int ignore ATTRIBUTE_UNUSED)
6755{
6756 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
6757 tree arg0;
6758 tree arg1;
6759 tree arg2;
6760 tree arg3;
6761 rtx op0;
6762 rtx op1;
6763 rtx op2;
6764 rtx op3;
6765 rtx op4;
6766 rtx pat;
6767 unsigned int i;
6768 int fcode = DECL_FUNCTION_CODE (fndecl);
6769 int icode;
6770 enum machine_mode mode0;
6771 enum machine_mode mode1;
6772 enum machine_mode mode2;
6773 enum machine_mode mode3;
6774 enum machine_mode mode4;
6775 const struct builtin_description * d;
6776
6777 for (i = 0, d = arc_simd_builtin_desc_list;
6778 i < ARRAY_SIZE (arc_simd_builtin_desc_list); i++, d++)
6779 if (d->code == (const enum arc_builtins) fcode)
6780 break;
6781
6782 /* We must get an entry here. */
6783 gcc_assert (i < ARRAY_SIZE (arc_simd_builtin_desc_list));
6784
6785 switch (d->args_type)
6786 {
6787 case Va_Vb_rlimm:
6788 icode = d->icode;
6789 arg0 = CALL_EXPR_ARG (exp, 0);
6790 arg1 = CALL_EXPR_ARG (exp, 1);
6791 op0 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);
6792 op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL);
6793
6794 target = gen_reg_rtx (V8HImode);
6795 mode0 = insn_data[icode].operand[1].mode;
6796 mode1 = insn_data[icode].operand[2].mode;
6797
6798 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6799 op0 = copy_to_mode_reg (mode0, op0);
6800
6801 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
6802 op1 = copy_to_mode_reg (mode1, op1);
6803
6804 pat = GEN_FCN (icode) (target, op0, op1);
6805 if (! pat)
6806 return 0;
6807
6808 emit_insn (pat);
6809 return target;
6810
6811 case Va_Vb_u6:
6812 case Va_Vb_u8:
6813 icode = d->icode;
6814 arg0 = CALL_EXPR_ARG (exp, 0);
6815 arg1 = CALL_EXPR_ARG (exp, 1);
6816 op0 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);
6817 op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL);
6818
6819 target = gen_reg_rtx (V8HImode);
6820 mode0 = insn_data[icode].operand[1].mode;
6821 mode1 = insn_data[icode].operand[2].mode;
6822
6823 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6824 op0 = copy_to_mode_reg (mode0, op0);
6825
6826 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1)
6827 || (d->args_type == Va_Vb_u6 && !UNSIGNED_INT6 (INTVAL (op1)))
6828 || (d->args_type == Va_Vb_u8 && !UNSIGNED_INT8 (INTVAL (op1))))
6829 error ("operand 2 of %s instruction should be an unsigned %d-bit value",
6830 d->name,
6831 (d->args_type == Va_Vb_u6)? 6: 8);
6832
6833 pat = GEN_FCN (icode) (target, op0, op1);
6834 if (! pat)
6835 return 0;
6836
6837 emit_insn (pat);
6838 return target;
6839
6840 case Va_rlimm_u8:
6841 icode = d->icode;
6842 arg0 = CALL_EXPR_ARG (exp, 0);
6843 arg1 = CALL_EXPR_ARG (exp, 1);
6844 op0 = expand_expr (arg0, NULL_RTX, SImode, EXPAND_NORMAL);
6845 op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL);
6846
6847 target = gen_reg_rtx (V8HImode);
6848 mode0 = insn_data[icode].operand[1].mode;
6849 mode1 = insn_data[icode].operand[2].mode;
6850
6851 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6852 op0 = copy_to_mode_reg (mode0, op0);
6853
6854 if ( (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
6855 || !(UNSIGNED_INT8 (INTVAL (op1))))
6856 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
6857 d->name);
6858
6859 pat = GEN_FCN (icode) (target, op0, op1);
6860 if (! pat)
6861 return 0;
6862
6863 emit_insn (pat);
6864 return target;
6865
6866 case Va_Vb_Ic:
6867 icode = d->icode;
6868 arg0 = CALL_EXPR_ARG (exp, 0);
6869 arg1 = CALL_EXPR_ARG (exp, 1);
6870 op0 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);
6871 op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL);
6872 op2 = gen_rtx_REG (V8HImode, ARC_FIRST_SIMD_VR_REG);
6873
6874 target = gen_reg_rtx (V8HImode);
6875 mode0 = insn_data[icode].operand[1].mode;
6876 mode1 = insn_data[icode].operand[2].mode;
6877
6878 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6879 op0 = copy_to_mode_reg (mode0, op0);
6880
6881 if ( (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
6882 || !(UNSIGNED_INT3 (INTVAL (op1))))
6883 error ("operand 2 of %s instruction should be an unsigned 3-bit value (I0-I7)",
6884 d->name);
6885
6886 pat = GEN_FCN (icode) (target, op0, op1, op2);
6887 if (! pat)
6888 return 0;
6889
6890 emit_insn (pat);
6891 return target;
6892
6893 case Va_Vb_Vc:
6894 icode = d->icode;
6895 arg0 = CALL_EXPR_ARG (exp, 0);
6896 arg1 = CALL_EXPR_ARG (exp, 1);
6897 op0 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);
6898 op1 = expand_expr (arg1, NULL_RTX, V8HImode, EXPAND_NORMAL);
6899
6900 target = gen_reg_rtx (V8HImode);
6901 mode0 = insn_data[icode].operand[1].mode;
6902 mode1 = insn_data[icode].operand[2].mode;
6903
6904 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6905 op0 = copy_to_mode_reg (mode0, op0);
6906
6907 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
6908 op1 = copy_to_mode_reg (mode1, op1);
6909
6910 pat = GEN_FCN (icode) (target, op0, op1);
6911 if (! pat)
6912 return 0;
6913
6914 emit_insn (pat);
6915 return target;
6916
6917 case Va_Vb:
6918 icode = d->icode;
6919 arg0 = CALL_EXPR_ARG (exp, 0);
6920 op0 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);
6921
6922 target = gen_reg_rtx (V8HImode);
6923 mode0 = insn_data[icode].operand[1].mode;
6924
6925 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6926 op0 = copy_to_mode_reg (mode0, op0);
6927
6928 pat = GEN_FCN (icode) (target, op0);
6929 if (! pat)
6930 return 0;
6931
6932 emit_insn (pat);
6933 return target;
6934
6935 case Da_rlimm_rlimm:
6936 icode = d->icode;
6937 arg0 = CALL_EXPR_ARG (exp, 0);
6938 arg1 = CALL_EXPR_ARG (exp, 1);
6939 op0 = expand_expr (arg0, NULL_RTX, SImode, EXPAND_NORMAL);
6940 op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL);
6941
6942
6943 if (icode == CODE_FOR_vdirun_insn)
6944 target = gen_rtx_REG (SImode, 131);
6945 else if (icode == CODE_FOR_vdorun_insn)
6946 target = gen_rtx_REG (SImode, 139);
6947 else
6948 gcc_unreachable ();
6949
6950 mode0 = insn_data[icode].operand[1].mode;
6951 mode1 = insn_data[icode].operand[2].mode;
6952
6953 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6954 op0 = copy_to_mode_reg (mode0, op0);
6955
6956 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
6957 op1 = copy_to_mode_reg (mode1, op1);
6958
6959
6960 pat = GEN_FCN (icode) (target, op0, op1);
6961 if (! pat)
6962 return 0;
6963
6964 emit_insn (pat);
6965 return NULL_RTX;
6966
6967 case Da_u3_rlimm:
6968 icode = d->icode;
6969 arg0 = CALL_EXPR_ARG (exp, 0);
6970 arg1 = CALL_EXPR_ARG (exp, 1);
6971 op0 = expand_expr (arg0, NULL_RTX, SImode, EXPAND_NORMAL);
6972 op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL);
6973
6974
6975 if (! (GET_CODE (op0) == CONST_INT)
6976 || !(UNSIGNED_INT3 (INTVAL (op0))))
6977 error ("operand 1 of %s instruction should be an unsigned 3-bit value (DR0-DR7)",
6978 d->name);
6979
6980 mode1 = insn_data[icode].operand[1].mode;
6981
6982 if (icode == CODE_FOR_vdiwr_insn)
6983 target = gen_rtx_REG (SImode,
6984 ARC_FIRST_SIMD_DMA_CONFIG_IN_REG + INTVAL (op0));
6985 else if (icode == CODE_FOR_vdowr_insn)
6986 target = gen_rtx_REG (SImode,
6987 ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG + INTVAL (op0));
6988 else
6989 gcc_unreachable ();
6990
6991 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
6992 op1 = copy_to_mode_reg (mode1, op1);
6993
6994 pat = GEN_FCN (icode) (target, op1);
6995 if (! pat)
6996 return 0;
6997
6998 emit_insn (pat);
6999 return NULL_RTX;
7000
7001 case void_u6:
7002 icode = d->icode;
7003 arg0 = CALL_EXPR_ARG (exp, 0);
7004
7005 fold (arg0);
7006
7007 op0 = expand_expr (arg0, NULL_RTX, SImode, EXPAND_NORMAL);
7008 mode0 = insn_data[icode].operand[0].mode;
7009
7010 /* op0 should be u6. */
7011 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0)
7012 || !(UNSIGNED_INT6 (INTVAL (op0))))
7013 error ("operand of %s instruction should be an unsigned 6-bit value",
7014 d->name);
7015
7016 pat = GEN_FCN (icode) (op0);
7017 if (! pat)
7018 return 0;
7019
7020 emit_insn (pat);
7021 return NULL_RTX;
7022
7023 case void_rlimm:
7024 icode = d->icode;
7025 arg0 = CALL_EXPR_ARG (exp, 0);
7026
7027 fold (arg0);
7028
7029 op0 = expand_expr (arg0, NULL_RTX, SImode, EXPAND_NORMAL);
7030 mode0 = insn_data[icode].operand[0].mode;
7031
7032 if (! (*insn_data[icode].operand[0].predicate) (op0, mode0))
7033 op0 = copy_to_mode_reg (mode0, op0);
7034
7035 pat = GEN_FCN (icode) (op0);
7036 if (! pat)
7037 return 0;
7038
7039 emit_insn (pat);
7040 return NULL_RTX;
7041
7042 case Va_Vb_Ic_u8:
7043 {
7044 rtx src_vreg;
7045 icode = d->icode;
7046 arg0 = CALL_EXPR_ARG (exp, 0); /* source vreg */
7047 arg1 = CALL_EXPR_ARG (exp, 1); /* [I]0-7 */
7048 arg2 = CALL_EXPR_ARG (exp, 2); /* u8 */
7049
7050 src_vreg = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);
7051 op0 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL); /* [I]0-7 */
7052 op1 = expand_expr (arg2, NULL_RTX, SImode, EXPAND_NORMAL); /* u8 */
7053 op2 = gen_rtx_REG (V8HImode, ARC_FIRST_SIMD_VR_REG); /* VR0 */
7054
7055 /* target <- src vreg */
7056 emit_insn (gen_move_insn (target, src_vreg));
7057
7058 /* target <- vec_concat: target, mem(Ib, u8) */
7059 mode0 = insn_data[icode].operand[3].mode;
7060 mode1 = insn_data[icode].operand[1].mode;
7061
7062 if ( (!(*insn_data[icode].operand[3].predicate) (op0, mode0))
7063 || !(UNSIGNED_INT3 (INTVAL (op0))))
7064 error ("operand 1 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7065 d->name);
7066
7067 if ( (!(*insn_data[icode].operand[1].predicate) (op1, mode1))
7068 || !(UNSIGNED_INT8 (INTVAL (op1))))
7069 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
7070 d->name);
7071
7072 pat = GEN_FCN (icode) (target, op1, op2, op0);
7073 if (! pat)
7074 return 0;
7075
7076 emit_insn (pat);
7077 return target;
7078 }
7079
7080 case void_Va_Ib_u8:
7081 icode = d->icode;
7082 arg0 = CALL_EXPR_ARG (exp, 0); /* src vreg */
7083 arg1 = CALL_EXPR_ARG (exp, 1); /* [I]0-7 */
7084 arg2 = CALL_EXPR_ARG (exp, 2); /* u8 */
7085
7086 op0 = gen_rtx_REG (V8HImode, ARC_FIRST_SIMD_VR_REG); /* VR0 */
7087 op1 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL); /* I[0-7] */
7088 op2 = expand_expr (arg2, NULL_RTX, SImode, EXPAND_NORMAL); /* u8 */
7089 op3 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL); /* Vdest */
7090
7091 mode0 = insn_data[icode].operand[0].mode;
7092 mode1 = insn_data[icode].operand[1].mode;
7093 mode2 = insn_data[icode].operand[2].mode;
7094 mode3 = insn_data[icode].operand[3].mode;
7095
7096 if ( (!(*insn_data[icode].operand[1].predicate) (op1, mode1))
7097 || !(UNSIGNED_INT3 (INTVAL (op1))))
7098 error ("operand 2 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7099 d->name);
7100
7101 if ( (!(*insn_data[icode].operand[2].predicate) (op2, mode2))
7102 || !(UNSIGNED_INT8 (INTVAL (op2))))
7103 error ("operand 3 of %s instruction should be an unsigned 8-bit value",
7104 d->name);
7105
7106 if (!(*insn_data[icode].operand[3].predicate) (op3, mode3))
7107 op3 = copy_to_mode_reg (mode3, op3);
7108
7109 pat = GEN_FCN (icode) (op0, op1, op2, op3);
7110 if (! pat)
7111 return 0;
7112
7113 emit_insn (pat);
7114 return NULL_RTX;
7115
7116 case Va_Ib_u8:
7117 icode = d->icode;
7118 arg0 = CALL_EXPR_ARG (exp, 0); /* dest vreg */
7119 arg1 = CALL_EXPR_ARG (exp, 1); /* [I]0-7 */
7120
7121 op0 = gen_rtx_REG (V8HImode, ARC_FIRST_SIMD_VR_REG); /* VR0 */
7122 op1 = expand_expr (arg0, NULL_RTX, SImode, EXPAND_NORMAL); /* I[0-7] */
7123 op2 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL); /* u8 */
7124
7125 /* target <- src vreg */
7126 target = gen_reg_rtx (V8HImode);
7127
7128 /* target <- vec_concat: target, mem(Ib, u8) */
7129 mode0 = insn_data[icode].operand[1].mode;
7130 mode1 = insn_data[icode].operand[2].mode;
7131 mode2 = insn_data[icode].operand[3].mode;
7132
7133 if ( (!(*insn_data[icode].operand[2].predicate) (op1, mode1))
7134 || !(UNSIGNED_INT3 (INTVAL (op1))))
7135 error ("operand 1 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7136 d->name);
7137
7138 if ( (!(*insn_data[icode].operand[3].predicate) (op2, mode2))
7139 || !(UNSIGNED_INT8 (INTVAL (op2))))
7140 error ("operand 2 of %s instruction should be an unsigned 8-bit value",
7141 d->name);
7142
7143 pat = GEN_FCN (icode) (target, op0, op1, op2);
7144 if (! pat)
7145 return 0;
7146
7147 emit_insn (pat);
7148 return target;
7149
7150 case void_Va_u3_Ib_u8:
7151 icode = d->icode;
7152 arg0 = CALL_EXPR_ARG (exp, 0); /* source vreg */
7153 arg1 = CALL_EXPR_ARG (exp, 1); /* u3 */
7154 arg2 = CALL_EXPR_ARG (exp, 2); /* [I]0-7 */
7155 arg3 = CALL_EXPR_ARG (exp, 3); /* u8 */
7156
7157 op0 = expand_expr (arg3, NULL_RTX, SImode, EXPAND_NORMAL); /* u8 */
7158 op1 = gen_rtx_REG (V8HImode, ARC_FIRST_SIMD_VR_REG); /* VR */
7159 op2 = expand_expr (arg2, NULL_RTX, SImode, EXPAND_NORMAL); /* [I]0-7 */
7160 op3 = expand_expr (arg0, NULL_RTX, V8HImode, EXPAND_NORMAL);/* vreg to be stored */
7161 op4 = expand_expr (arg1, NULL_RTX, SImode, EXPAND_NORMAL); /* vreg 0-7 subreg no. */
7162
7163 mode0 = insn_data[icode].operand[0].mode;
7164 mode2 = insn_data[icode].operand[2].mode;
7165 mode3 = insn_data[icode].operand[3].mode;
7166 mode4 = insn_data[icode].operand[4].mode;
7167
7168 /* Do some correctness checks for the operands. */
7169 if ( (!(*insn_data[icode].operand[0].predicate) (op0, mode0))
7170 || !(UNSIGNED_INT8 (INTVAL (op0))))
7171 error ("operand 4 of %s instruction should be an unsigned 8-bit value (0-255)",
7172 d->name);
7173
7174 if ( (!(*insn_data[icode].operand[2].predicate) (op2, mode2))
7175 || !(UNSIGNED_INT3 (INTVAL (op2))))
7176 error ("operand 3 of %s instruction should be an unsigned 3-bit value (I0-I7)",
7177 d->name);
7178
7179 if (!(*insn_data[icode].operand[3].predicate) (op3, mode3))
7180 op3 = copy_to_mode_reg (mode3, op3);
7181
7182 if ( (!(*insn_data[icode].operand[4].predicate) (op4, mode4))
7183 || !(UNSIGNED_INT3 (INTVAL (op4))))
7184 error ("operand 2 of %s instruction should be an unsigned 3-bit value (subreg 0-7)",
7185 d->name);
7186 else if (icode == CODE_FOR_vst32_n_insn
7187 && ((INTVAL(op4) % 2 ) != 0))
7188 error ("operand 2 of %s instruction should be an even 3-bit value (subreg 0,2,4,6)",
7189 d->name);
7190
7191 pat = GEN_FCN (icode) (op0, op1, op2, op3, op4);
7192 if (! pat)
7193 return 0;
7194
7195 emit_insn (pat);
7196 return NULL_RTX;
7197
7198 default:
7199 gcc_unreachable ();
7200 }
7201 return NULL_RTX;
7202}
7203
7204static bool
7205arc_preserve_reload_p (rtx in)
7206{
7207 return (GET_CODE (in) == PLUS
7208 && RTX_OK_FOR_BASE_P (XEXP (in, 0), true)
7209 && CONST_INT_P (XEXP (in, 1))
7210 && !((INTVAL (XEXP (in, 1)) & 511)));
7211}
7212
7213int
7214arc_register_move_cost (enum machine_mode,
7215 enum reg_class from_class, enum reg_class to_class)
7216{
7217 /* The ARC600 has no bypass for extension registers, hence a nop might be
7218 needed to be inserted after a write so that reads are safe. */
7219 if (TARGET_ARC600)
7220 {
7221 if (to_class == MPY_WRITABLE_CORE_REGS)
7222 return 3;
7223 /* Instructions modifying LP_COUNT need 4 additional cycles before
7224 the register will actually contain the value. */
7225 else if (to_class == LPCOUNT_REG)
7226 return 6;
7227 else if (to_class == WRITABLE_CORE_REGS)
7228 return 6;
7229 }
7230
7231 /* The ARC700 stalls for 3 cycles when *reading* from lp_count. */
7232 if (TARGET_ARC700
7233 && (from_class == LPCOUNT_REG || from_class == ALL_CORE_REGS
7234 || from_class == WRITABLE_CORE_REGS))
7235 return 8;
7236
7237 /* Force an attempt to 'mov Dy,Dx' to spill. */
7238 if (TARGET_ARC700 && TARGET_DPFP
7239 && from_class == DOUBLE_REGS && to_class == DOUBLE_REGS)
7240 return 100;
7241
7242 return 2;
7243}
7244
7245/* Emit code for an addsi3 instruction with OPERANDS.
7246 COND_P indicates if this will use conditional execution.
7247 Return the length of the instruction.
7248 If OUTPUT_P is false, don't actually output the instruction, just return
7249 its length. */
7250int
7251arc_output_addsi (rtx *operands, bool cond_p, bool output_p)
7252{
7253 char format[32];
7254
7255 int match = operands_match_p (operands[0], operands[1]);
7256 int match2 = operands_match_p (operands[0], operands[2]);
7257 int intval = (REG_P (operands[2]) ? 1
7258 : CONST_INT_P (operands[2]) ? INTVAL (operands[2]) : 0xbadc057);
7259 int neg_intval = -intval;
7260 int short_0 = satisfies_constraint_Rcq (operands[0]);
7261 int short_p = (!cond_p && short_0 && satisfies_constraint_Rcq (operands[1]));
7262 int ret = 0;
7263
7264#define ADDSI_OUTPUT1(FORMAT) do {\
7265 if (output_p) \
7266 output_asm_insn (FORMAT, operands);\
7267 return ret; \
7268} while (0)
7269#define ADDSI_OUTPUT(LIST) do {\
7270 if (output_p) \
7271 sprintf LIST;\
7272 ADDSI_OUTPUT1 (format);\
7273 return ret; \
7274} while (0)
7275
7276 /* First try to emit a 16 bit insn. */
7277 ret = 2;
7278 if (!cond_p
7279 /* If we are actually about to output this insn, don't try a 16 bit
7280 variant if we already decided that we don't want that
7281 (I.e. we upsized this insn to align some following insn.)
7282 E.g. add_s r0,sp,70 is 16 bit, but add r0,sp,70 requires a LIMM -
7283 but add1 r0,sp,35 doesn't. */
7284 && (!output_p || (get_attr_length (current_output_insn) & 2)))
7285 {
7286 if (short_p
7287 && (REG_P (operands[2])
7288 ? (match || satisfies_constraint_Rcq (operands[2]))
7289 : (unsigned) intval <= (match ? 127 : 7)))
7290 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7291 if (short_0 && REG_P (operands[1]) && match2)
7292 ADDSI_OUTPUT1 ("add%? %0,%2,%1");
7293 if ((short_0 || REGNO (operands[0]) == STACK_POINTER_REGNUM)
7294 && REGNO (operands[1]) == STACK_POINTER_REGNUM && !(intval & ~124))
7295 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7296
7297 if ((short_p && (unsigned) neg_intval <= (match ? 31 : 7))
7298 || (REGNO (operands[0]) == STACK_POINTER_REGNUM
7299 && match && !(neg_intval & ~124)))
7300 ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
7301 }
7302
7303 /* Now try to emit a 32 bit insn without long immediate. */
7304 ret = 4;
7305 if (!match && match2 && REG_P (operands[1]))
7306 ADDSI_OUTPUT1 ("add%? %0,%2,%1");
7307 if (match || !cond_p)
7308 {
7309 int limit = (match && !cond_p) ? 0x7ff : 0x3f;
7310 int range_factor = neg_intval & intval;
7311 int shift;
7312
7313 if (intval == -1 << 31)
7314 ADDSI_OUTPUT1 ("bxor%? %0,%1,31");
7315
7316 /* If we can use a straight add / sub instead of a {add,sub}[123] of
7317 same size, do, so - the insn latency is lower. */
7318 /* -0x800 is a 12-bit constant for add /add3 / sub / sub3, but
7319 0x800 is not. */
7320 if ((intval >= 0 && intval <= limit)
7321 || (intval == -0x800 && limit == 0x7ff))
7322 ADDSI_OUTPUT1 ("add%? %0,%1,%2");
7323 else if ((intval < 0 && neg_intval <= limit)
7324 || (intval == 0x800 && limit == 0x7ff))
7325 ADDSI_OUTPUT1 ("sub%? %0,%1,%n2");
7326 shift = range_factor >= 8 ? 3 : (range_factor >> 1);
7327 gcc_assert (shift == 0 || shift == 1 || shift == 2 || shift == 3);
7328 gcc_assert ((((1 << shift) - 1) & intval) == 0);
7329 if (((intval < 0 && intval != -0x4000)
7330 /* sub[123] is slower than add_s / sub, only use it if it
7331 avoids a long immediate. */
7332 && neg_intval <= limit << shift)
7333 || (intval == 0x4000 && limit == 0x7ff))
7334 ADDSI_OUTPUT ((format, "sub%d%%? %%0,%%1,%d",
7335 shift, neg_intval >> shift));
7336 else if ((intval >= 0 && intval <= limit << shift)
7337 || (intval == -0x4000 && limit == 0x7ff))
7338 ADDSI_OUTPUT ((format, "add%d%%? %%0,%%1,%d", shift, intval >> shift));
7339 }
7340 /* Try to emit a 16 bit opcode with long immediate. */
7341 ret = 6;
7342 if (short_p && match)
7343 ADDSI_OUTPUT1 ("add%? %0,%1,%S2");
7344
7345 /* We have to use a 32 bit opcode, and with a long immediate. */
7346 ret = 8;
7347 ADDSI_OUTPUT1 (intval < 0 ? "sub%? %0,%1,%n2" : "add%? %0,%1,%S2");
7348}
7349
7350/* Emit code for an commutative_cond_exec instruction with OPERANDS.
7351 Return the length of the instruction.
7352 If OUTPUT_P is false, don't actually output the instruction, just return
7353 its length. */
7354int
7355arc_output_commutative_cond_exec (rtx *operands, bool output_p)
7356{
7357 enum rtx_code commutative_op = GET_CODE (operands[3]);
7358 const char *pat = NULL;
7359
7360 /* Canonical rtl should not have a constant in the first operand position. */
7361 gcc_assert (!CONSTANT_P (operands[1]));
7362
7363 switch (commutative_op)
7364 {
7365 case AND:
7366 if (satisfies_constraint_C1p (operands[2]))
7367 pat = "bmsk%? %0,%1,%Z2";
7368 else if (satisfies_constraint_Ccp (operands[2]))
7369 pat = "bclr%? %0,%1,%M2";
7370 else if (satisfies_constraint_CnL (operands[2]))
7371 pat = "bic%? %0,%1,%n2-1";
7372 break;
7373 case IOR:
7374 if (satisfies_constraint_C0p (operands[2]))
7375 pat = "bset%? %0,%1,%z2";
7376 break;
7377 case XOR:
7378 if (satisfies_constraint_C0p (operands[2]))
7379 pat = "bxor%? %0,%1,%z2";
7380 break;
7381 case PLUS:
7382 return arc_output_addsi (operands, true, output_p);
7383 default: break;
7384 }
7385 if (output_p)
7386 output_asm_insn (pat ? pat : "%O3.%d5 %0,%1,%2", operands);
7387 if (pat || REG_P (operands[2]) || satisfies_constraint_L (operands[2]))
7388 return 4;
7389 return 8;
7390}
7391
7392/* Helper function of arc_expand_movmem. ADDR points to a chunk of memory.
7393 Emit code and return an potentially modified address such that offsets
7394 up to SIZE are can be added to yield a legitimate address.
7395 if REUSE is set, ADDR is a register that may be modified. */
7396
7397static rtx
7398force_offsettable (rtx addr, HOST_WIDE_INT size, bool reuse)
7399{
7400 rtx base = addr;
7401 rtx offs = const0_rtx;
7402
7403 if (GET_CODE (base) == PLUS)
7404 {
7405 offs = XEXP (base, 1);
7406 base = XEXP (base, 0);
7407 }
7408 if (!REG_P (base)
7409 || (REGNO (base) != STACK_POINTER_REGNUM
7410 && REGNO_PTR_FRAME_P (REGNO (addr)))
7411 || !CONST_INT_P (offs) || !SMALL_INT (INTVAL (offs))
7412 || !SMALL_INT (INTVAL (offs) + size))
7413 {
7414 if (reuse)
7415 emit_insn (gen_add2_insn (addr, offs));
7416 else
7417 addr = copy_to_mode_reg (Pmode, addr);
7418 }
7419 return addr;
7420}
7421
7422/* Like move_by_pieces, but take account of load latency,
7423 and actual offset ranges.
7424 Return true on success. */
7425
7426bool
7427arc_expand_movmem (rtx *operands)
7428{
7429 rtx dst = operands[0];
7430 rtx src = operands[1];
7431 rtx dst_addr, src_addr;
7432 HOST_WIDE_INT size;
7433 int align = INTVAL (operands[3]);
7434 unsigned n_pieces;
7435 int piece = align;
7436 rtx store[2];
7437 rtx tmpx[2];
7438 int i;
7439
7440 if (!CONST_INT_P (operands[2]))
7441 return false;
7442 size = INTVAL (operands[2]);
7443 /* move_by_pieces_ninsns is static, so we can't use it. */
7444 if (align >= 4)
7445 n_pieces = (size + 2) / 4U + (size & 1);
7446 else if (align == 2)
7447 n_pieces = (size + 1) / 2U;
7448 else
7449 n_pieces = size;
7450 if (n_pieces >= (unsigned int) (optimize_size ? 3 : 15))
7451 return false;
7452 if (piece > 4)
7453 piece = 4;
7454 dst_addr = force_offsettable (XEXP (operands[0], 0), size, 0);
7455 src_addr = force_offsettable (XEXP (operands[1], 0), size, 0);
7456 store[0] = store[1] = NULL_RTX;
7457 tmpx[0] = tmpx[1] = NULL_RTX;
7458 for (i = 0; size > 0; i ^= 1, size -= piece)
7459 {
7460 rtx tmp;
7461 enum machine_mode mode;
7462
7463 if (piece > size)
7464 piece = size & -size;
7465 mode = smallest_mode_for_size (piece * BITS_PER_UNIT, MODE_INT);
7466 /* If we don't re-use temporaries, the scheduler gets carried away,
7467 and the register pressure gets unnecessarily high. */
7468 if (0 && tmpx[i] && GET_MODE (tmpx[i]) == mode)
7469 tmp = tmpx[i];
7470 else
7471 tmpx[i] = tmp = gen_reg_rtx (mode);
7472 dst_addr = force_offsettable (dst_addr, piece, 1);
7473 src_addr = force_offsettable (src_addr, piece, 1);
7474 if (store[i])
7475 emit_insn (store[i]);
7476 emit_move_insn (tmp, change_address (src, mode, src_addr));
7477 store[i] = gen_move_insn (change_address (dst, mode, dst_addr), tmp);
7478 dst_addr = plus_constant (Pmode, dst_addr, piece);
7479 src_addr = plus_constant (Pmode, src_addr, piece);
7480 }
7481 if (store[i])
7482 emit_insn (store[i]);
7483 if (store[i^1])
7484 emit_insn (store[i^1]);
7485 return true;
7486}
7487
7488/* Prepare operands for move in MODE. Return true iff the move has
7489 been emitted. */
7490
7491bool
7492prepare_move_operands (rtx *operands, enum machine_mode mode)
7493{
7494 /* We used to do this only for MODE_INT Modes, but addresses to floating
7495 point variables may well be in the small data section. */
7496 if (1)
7497 {
7498 if (!TARGET_NO_SDATA_SET && small_data_pattern (operands[0], Pmode))
7499 operands[0] = arc_rewrite_small_data (operands[0]);
7500 else if (mode == SImode && flag_pic && SYMBOLIC_CONST (operands[1]))
7501 {
7502 emit_pic_move (operands, SImode);
7503
7504 /* Disable any REG_EQUALs associated with the symref
7505 otherwise the optimization pass undoes the work done
7506 here and references the variable directly. */
7507 }
7508 else if (GET_CODE (operands[0]) != MEM
7509 && !TARGET_NO_SDATA_SET
7510 && small_data_pattern (operands[1], Pmode))
7511 {
7512 /* This is to take care of address calculations involving sdata
7513 variables. */
7514 operands[1] = arc_rewrite_small_data (operands[1]);
7515
7516 emit_insn (gen_rtx_SET (mode, operands[0],operands[1]));
7517 /* ??? This note is useless, since it only restates the set itself.
7518 We should rather use the original SYMBOL_REF. However, there is
7519 the problem that we are lying to the compiler about these
7520 SYMBOL_REFs to start with. symbol@sda should be encoded specially
7521 so that we can tell it apart from an actual symbol. */
7522 set_unique_reg_note (get_last_insn (), REG_EQUAL, operands[1]);
7523
7524 /* Take care of the REG_EQUAL note that will be attached to mark the
7525 output reg equal to the initial symbol_ref after this code is
7526 executed. */
7527 emit_move_insn (operands[0], operands[0]);
7528 return true;
7529 }
7530 }
7531
7532 if (MEM_P (operands[0])
7533 && !(reload_in_progress || reload_completed))
7534 {
7535 operands[1] = force_reg (mode, operands[1]);
7536 if (!move_dest_operand (operands[0], mode))
7537 {
7538 rtx addr = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
7539 /* This is like change_address_1 (operands[0], mode, 0, 1) ,
7540 except that we can't use that function because it is static. */
7541 rtx pat = change_address (operands[0], mode, addr);
7542 MEM_COPY_ATTRIBUTES (pat, operands[0]);
7543 operands[0] = pat;
7544 }
7545 if (!cse_not_expected)
7546 {
7547 rtx pat = XEXP (operands[0], 0);
7548
7549 pat = arc_legitimize_address_0 (pat, pat, mode);
7550 if (pat)
7551 {
7552 pat = change_address (operands[0], mode, pat);
7553 MEM_COPY_ATTRIBUTES (pat, operands[0]);
7554 operands[0] = pat;
7555 }
7556 }
7557 }
7558
7559 if (MEM_P (operands[1]) && !cse_not_expected)
7560 {
7561 rtx pat = XEXP (operands[1], 0);
7562
7563 pat = arc_legitimize_address_0 (pat, pat, mode);
7564 if (pat)
7565 {
7566 pat = change_address (operands[1], mode, pat);
7567 MEM_COPY_ATTRIBUTES (pat, operands[1]);
7568 operands[1] = pat;
7569 }
7570 }
7571
7572 return false;
7573}
7574
7575/* Prepare OPERANDS for an extension using CODE to OMODE.
7576 Return true iff the move has been emitted. */
7577
7578bool
7579prepare_extend_operands (rtx *operands, enum rtx_code code,
7580 enum machine_mode omode)
7581{
7582 if (!TARGET_NO_SDATA_SET && small_data_pattern (operands[1], Pmode))
7583 {
7584 /* This is to take care of address calculations involving sdata
7585 variables. */
7586 operands[1]
7587 = gen_rtx_fmt_e (code, omode, arc_rewrite_small_data (operands[1]));
7588 emit_insn (gen_rtx_SET (omode, operands[0], operands[1]));
7589 set_unique_reg_note (get_last_insn (), REG_EQUAL, operands[1]);
7590
7591 /* Take care of the REG_EQUAL note that will be attached to mark the
7592 output reg equal to the initial extension after this code is
7593 executed. */
7594 emit_move_insn (operands[0], operands[0]);
7595 return true;
7596 }
7597 return false;
7598}
7599
7600/* Output a library call to a function called FNAME that has been arranged
7601 to be local to any dso. */
7602
7603const char *
7604arc_output_libcall (const char *fname)
7605{
7606 unsigned len = strlen (fname);
7607 static char buf[64];
7608
7609 gcc_assert (len < sizeof buf - 35);
7610 if (TARGET_LONG_CALLS_SET
7611 || (TARGET_MEDIUM_CALLS && arc_ccfsm_cond_exec_p ()))
7612 {
7613 if (flag_pic)
7614 sprintf (buf, "add r12,pcl,@%s-(.&-4)\n\tjl%%!%%* [r12]", fname);
7615 else
7616 sprintf (buf, "jl%%! @%s", fname);
7617 }
7618 else
7619 sprintf (buf, "bl%%!%%* @%s", fname);
7620 return buf;
7621}
7622
7623/* Return the SImode highpart of the DImode value IN. */
7624
7625rtx
7626disi_highpart (rtx in)
7627{
7628 return simplify_gen_subreg (SImode, in, DImode, TARGET_BIG_ENDIAN ? 0 : 4);
7629}
7630
7631/* Called by arc600_corereg_hazard via for_each_rtx.
7632 If a hazard is found, return a conservative estimate of the required
7633 length adjustment to accomodate a nop. */
7634
7635static int
7636arc600_corereg_hazard_1 (rtx *xp, void *data)
7637{
7638 rtx x = *xp;
7639 rtx dest;
7640 rtx pat = (rtx) data;
7641
7642 switch (GET_CODE (x))
7643 {
7644 case SET: case POST_INC: case POST_DEC: case PRE_INC: case PRE_DEC:
7645 break;
7646 default:
7647 /* This is also fine for PRE/POST_MODIFY, because they contain a SET. */
7648 return 0;
7649 }
7650 dest = XEXP (x, 0);
7651 /* Check if this sets a an extension register. N.B. we use 61 for the
7652 condition codes, which is definitely not an extension register. */
7653 if (REG_P (dest) && REGNO (dest) >= 32 && REGNO (dest) < 61
7654 /* Check if the same register is used by the PAT. */
7655 && (refers_to_regno_p
7656 (REGNO (dest),
7657 REGNO (dest) + (GET_MODE_SIZE (GET_MODE (dest)) + 3) / 4U, pat, 0)))
7658 return 4;
7659
7660 return 0;
7661}
7662
7663/* Return length adjustment for INSN.
7664 For ARC600:
7665 A write to a core reg greater or equal to 32 must not be immediately
7666 followed by a use. Anticipate the length requirement to insert a nop
7667 between PRED and SUCC to prevent a hazard. */
7668
7669static int
7670arc600_corereg_hazard (rtx pred, rtx succ)
7671{
7672 if (!TARGET_ARC600)
7673 return 0;
7674 /* If SUCC is a doloop_end_i with a preceding label, we must output a nop
7675 in front of SUCC anyway, so there will be separation between PRED and
7676 SUCC. */
7677 if (recog_memoized (succ) == CODE_FOR_doloop_end_i
7678 && LABEL_P (prev_nonnote_insn (succ)))
7679 return 0;
7680 if (recog_memoized (succ) == CODE_FOR_doloop_begin_i)
7681 return 0;
7682 if (GET_CODE (PATTERN (pred)) == SEQUENCE)
7683 pred = XVECEXP (PATTERN (pred), 0, 1);
7684 if (GET_CODE (PATTERN (succ)) == SEQUENCE)
7685 succ = XVECEXP (PATTERN (succ), 0, 0);
7686 if (recog_memoized (pred) == CODE_FOR_mulsi_600
7687 || recog_memoized (pred) == CODE_FOR_umul_600
7688 || recog_memoized (pred) == CODE_FOR_mac_600
7689 || recog_memoized (pred) == CODE_FOR_mul64_600
7690 || recog_memoized (pred) == CODE_FOR_mac64_600
7691 || recog_memoized (pred) == CODE_FOR_umul64_600
7692 || recog_memoized (pred) == CODE_FOR_umac64_600)
7693 return 0;
7694 return for_each_rtx (&PATTERN (pred), arc600_corereg_hazard_1,
7695 PATTERN (succ));
7696}
7697
7698/* For ARC600:
7699 A write to a core reg greater or equal to 32 must not be immediately
7700 followed by a use. Anticipate the length requirement to insert a nop
7701 between PRED and SUCC to prevent a hazard. */
7702
7703int
7704arc_hazard (rtx pred, rtx succ)
7705{
7706 if (!TARGET_ARC600)
7707 return 0;
7708 if (!pred || !INSN_P (pred) || !succ || !INSN_P (succ))
7709 return 0;
7710 /* We might have a CALL to a non-returning function before a loop end.
7711 ??? Although the manual says that's OK (the target is outside the loop,
7712 and the loop counter unused there), the assembler barfs on this, so we
7713 must instert a nop before such a call too. */
7714 if (recog_memoized (succ) == CODE_FOR_doloop_end_i
7715 && (JUMP_P (pred) || CALL_P (pred)
7716 || GET_CODE (PATTERN (pred)) == SEQUENCE))
7717 return 4;
7718 return arc600_corereg_hazard (pred, succ);
7719}
7720
7721/* Return length adjustment for INSN. */
7722
7723int
7724arc_adjust_insn_length (rtx insn, int len, bool)
7725{
7726 if (!INSN_P (insn))
7727 return len;
7728 /* We already handle sequences by ignoring the delay sequence flag. */
7729 if (GET_CODE (PATTERN (insn)) == SEQUENCE)
7730 return len;
7731
7732 /* It is impossible to jump to the very end of a Zero-Overhead Loop, as
7733 the ZOL mechanism only triggers when advancing to the end address,
7734 so if there's a label at the end of a ZOL, we need to insert a nop.
7735 The ARC600 ZOL also has extra restrictions on jumps at the end of a
7736 loop. */
7737 if (recog_memoized (insn) == CODE_FOR_doloop_end_i)
7738 {
7739 rtx prev = prev_nonnote_insn (insn);
7740
7741 return ((LABEL_P (prev)
7742 || (TARGET_ARC600
7743 && (JUMP_P (prev)
7744 || CALL_P (prev) /* Could be a noreturn call. */
7745 || (NONJUMP_INSN_P (prev)
7746 && GET_CODE (PATTERN (prev)) == SEQUENCE))))
7747 ? len + 4 : len);
7748 }
7749
7750 /* Check for return with but one preceding insn since function
7751 start / call. */
7752 if (TARGET_PAD_RETURN
7753 && JUMP_P (insn)
7754 && GET_CODE (PATTERN (insn)) != ADDR_VEC
7755 && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC
7756 && get_attr_type (insn) == TYPE_RETURN)
7757 {
7758 rtx prev = prev_active_insn (insn);
7759
7760 if (!prev || !(prev = prev_active_insn (prev))
7761 || ((NONJUMP_INSN_P (prev)
7762 && GET_CODE (PATTERN (prev)) == SEQUENCE)
7763 ? CALL_ATTR (XVECEXP (PATTERN (prev), 0, 0), NON_SIBCALL)
7764 : CALL_ATTR (prev, NON_SIBCALL)))
7765 return len + 4;
7766 }
7767 if (TARGET_ARC600)
7768 {
7769 rtx succ = next_real_insn (insn);
7770
7771 /* One the ARC600, a write to an extension register must be separated
7772 from a read. */
7773 if (succ && INSN_P (succ))
7774 len += arc600_corereg_hazard (insn, succ);
7775 }
7776
7777 /* Restore extracted operands - otherwise splitters like the addsi3_mixed one
7778 can go awry. */
7779 extract_constrain_insn_cached (insn);
7780
7781 return len;
7782}
7783
7784/* Values for length_sensitive. */
7785enum
7786{
7787 ARC_LS_NONE,// Jcc
7788 ARC_LS_25, // 25 bit offset, B
7789 ARC_LS_21, // 21 bit offset, Bcc
7790 ARC_LS_U13,// 13 bit unsigned offset, LP
7791 ARC_LS_10, // 10 bit offset, B_s, Beq_s, Bne_s
7792 ARC_LS_9, // 9 bit offset, BRcc
7793 ARC_LS_8, // 8 bit offset, BRcc_s
7794 ARC_LS_U7, // 7 bit unsigned offset, LPcc
7795 ARC_LS_7 // 7 bit offset, Bcc_s
7796};
7797
7798/* While the infrastructure patch is waiting for review, duplicate the
7799 struct definitions, to allow this file to compile. */
7800#if 1
7801typedef struct
7802{
7803 unsigned align_set;
7804 /* Cost as a branch / call target or call return address. */
7805 int target_cost;
7806 int fallthrough_cost;
7807 int branch_cost;
7808 int length;
7809 /* 0 for not length sensitive, 1 for largest offset range,
7810 * 2 for next smaller etc. */
7811 unsigned length_sensitive : 8;
7812 bool enabled;
7813} insn_length_variant_t;
7814
7815typedef struct insn_length_parameters_s
7816{
7817 int align_unit_log;
7818 int align_base_log;
7819 int max_variants;
7820 int (*get_variants) (rtx, int, bool, bool, insn_length_variant_t *);
7821} insn_length_parameters_t;
7822
7823static void
7824arc_insn_length_parameters (insn_length_parameters_t *ilp) ATTRIBUTE_UNUSED;
7825#endif
7826
7827static int
7828arc_get_insn_variants (rtx insn, int len, bool, bool target_p,
7829 insn_length_variant_t *ilv)
7830{
7831 if (!NONDEBUG_INSN_P (insn))
7832 return 0;
7833 enum attr_type type;
7834 /* shorten_branches doesn't take optimize_size into account yet for the
7835 get_variants mechanism, so turn this off for now. */
7836 if (optimize_size)
7837 return 0;
7838 if (GET_CODE (PATTERN (insn)) == SEQUENCE)
7839 {
7840 /* The interaction of a short delay slot insn with a short branch is
7841 too weird for shorten_branches to piece together, so describe the
7842 entire SEQUENCE. */
7843 rtx pat, inner;
7844 if (TARGET_UPSIZE_DBR
7845 && get_attr_length (XVECEXP ((pat = PATTERN (insn)), 0, 1)) <= 2
7846 && (((type = get_attr_type (inner = XVECEXP (pat, 0, 0)))
7847 == TYPE_UNCOND_BRANCH)
7848 || type == TYPE_BRANCH)
7849 && get_attr_delay_slot_filled (inner) == DELAY_SLOT_FILLED_YES)
7850 {
7851 int n_variants
7852 = arc_get_insn_variants (inner, get_attr_length (inner), true,
7853 target_p, ilv+1);
7854 /* The short variant gets split into a higher-cost aligned
7855 and a lower cost unaligned variant. */
7856 gcc_assert (n_variants);
7857 gcc_assert (ilv[1].length_sensitive == ARC_LS_7
7858 || ilv[1].length_sensitive == ARC_LS_10);
7859 gcc_assert (ilv[1].align_set == 3);
7860 ilv[0] = ilv[1];
7861 ilv[0].align_set = 1;
7862 ilv[0].branch_cost += 1;
7863 ilv[1].align_set = 2;
7864 n_variants++;
7865 for (int i = 0; i < n_variants; i++)
7866 ilv[i].length += 2;
7867 /* In case an instruction with aligned size is wanted, and
7868 the short variants are unavailable / too expensive, add
7869 versions of long branch + long delay slot. */
7870 for (int i = 2, end = n_variants; i < end; i++, n_variants++)
7871 {
7872 ilv[n_variants] = ilv[i];
7873 ilv[n_variants].length += 2;
7874 }
7875 return n_variants;
7876 }
7877 return 0;
7878 }
7879 insn_length_variant_t *first_ilv = ilv;
7880 type = get_attr_type (insn);
7881 bool delay_filled
7882 = (get_attr_delay_slot_filled (insn) == DELAY_SLOT_FILLED_YES);
7883 int branch_align_cost = delay_filled ? 0 : 1;
7884 int branch_unalign_cost = delay_filled ? 0 : TARGET_UNALIGN_BRANCH ? 0 : 1;
7885 /* If the previous instruction is an sfunc call, this insn is always
7886 a target, even though the middle-end is unaware of this. */
7887 bool force_target = false;
7888 rtx prev = prev_active_insn (insn);
7889 if (prev && arc_next_active_insn (prev, 0) == insn
7890 && ((NONJUMP_INSN_P (prev) && GET_CODE (PATTERN (prev)) == SEQUENCE)
7891 ? CALL_ATTR (XVECEXP (PATTERN (prev), 0, 0), NON_SIBCALL)
7892 : (CALL_ATTR (prev, NON_SIBCALL)
7893 && NEXT_INSN (PREV_INSN (prev)) == prev)))
7894 force_target = true;
7895
7896 switch (type)
7897 {
7898 case TYPE_BRCC:
7899 /* Short BRCC only comes in no-delay-slot version, and without limm */
7900 if (!delay_filled)
7901 {
7902 ilv->align_set = 3;
7903 ilv->length = 2;
7904 ilv->branch_cost = 1;
7905 ilv->enabled = (len == 2);
7906 ilv->length_sensitive = ARC_LS_8;
7907 ilv++;
7908 }
7909 /* Fall through. */
7910 case TYPE_BRCC_NO_DELAY_SLOT:
7911 /* doloop_fallback* patterns are TYPE_BRCC_NO_DELAY_SLOT for
7912 (delay slot) scheduling purposes, but they are longer. */
7913 if (GET_CODE (PATTERN (insn)) == PARALLEL
7914 && GET_CODE (XVECEXP (PATTERN (insn), 0, 1)) == SET)
7915 return 0;
7916 /* Standard BRCC: 4 bytes, or 8 bytes with limm. */
7917 ilv->length = ((type == TYPE_BRCC) ? 4 : 8);
7918 ilv->align_set = 3;
7919 ilv->branch_cost = branch_align_cost;
7920 ilv->enabled = (len <= ilv->length);
7921 ilv->length_sensitive = ARC_LS_9;
7922 if ((target_p || force_target)
7923 || (!delay_filled && TARGET_UNALIGN_BRANCH))
7924 {
7925 ilv[1] = *ilv;
7926 ilv->align_set = 1;
7927 ilv++;
7928 ilv->align_set = 2;
7929 ilv->target_cost = 1;
7930 ilv->branch_cost = branch_unalign_cost;
7931 }
7932 ilv++;
7933
7934 rtx op, op0;
7935 op = XEXP (SET_SRC (XVECEXP (PATTERN (insn), 0, 0)), 0);
7936 op0 = XEXP (op, 0);
7937
7938 if (GET_CODE (op0) == ZERO_EXTRACT
7939 && satisfies_constraint_L (XEXP (op0, 2)))
7940 op0 = XEXP (op0, 0);
7941 if (satisfies_constraint_Rcq (op0))
7942 {
7943 ilv->length = ((type == TYPE_BRCC) ? 6 : 10);
7944 ilv->align_set = 3;
7945 ilv->branch_cost = 1 + branch_align_cost;
7946 ilv->fallthrough_cost = 1;
7947 ilv->enabled = true;
7948 ilv->length_sensitive = ARC_LS_21;
7949 if (!delay_filled && TARGET_UNALIGN_BRANCH)
7950 {
7951 ilv[1] = *ilv;
7952 ilv->align_set = 1;
7953 ilv++;
7954 ilv->align_set = 2;
7955 ilv->branch_cost = 1 + branch_unalign_cost;
7956 }
7957 ilv++;
7958 }
7959 ilv->length = ((type == TYPE_BRCC) ? 8 : 12);
7960 ilv->align_set = 3;
7961 ilv->branch_cost = 1 + branch_align_cost;
7962 ilv->fallthrough_cost = 1;
7963 ilv->enabled = true;
7964 ilv->length_sensitive = ARC_LS_21;
7965 if ((target_p || force_target)
7966 || (!delay_filled && TARGET_UNALIGN_BRANCH))
7967 {
7968 ilv[1] = *ilv;
7969 ilv->align_set = 1;
7970 ilv++;
7971 ilv->align_set = 2;
7972 ilv->target_cost = 1;
7973 ilv->branch_cost = 1 + branch_unalign_cost;
7974 }
7975 ilv++;
7976 break;
7977
7978 case TYPE_SFUNC:
7979 ilv->length = 12;
7980 goto do_call;
7981 case TYPE_CALL_NO_DELAY_SLOT:
7982 ilv->length = 8;
7983 goto do_call;
7984 case TYPE_CALL:
7985 ilv->length = 4;
7986 ilv->length_sensitive
7987 = GET_CODE (PATTERN (insn)) == COND_EXEC ? ARC_LS_21 : ARC_LS_25;
7988 do_call:
7989 ilv->align_set = 3;
7990 ilv->fallthrough_cost = branch_align_cost;
7991 ilv->enabled = true;
7992 if ((target_p || force_target)
7993 || (!delay_filled && TARGET_UNALIGN_BRANCH))
7994 {
7995 ilv[1] = *ilv;
7996 ilv->align_set = 1;
7997 ilv++;
7998 ilv->align_set = 2;
7999 ilv->target_cost = 1;
8000 ilv->fallthrough_cost = branch_unalign_cost;
8001 }
8002 ilv++;
8003 break;
8004 case TYPE_UNCOND_BRANCH:
8005 /* Strictly speaking, this should be ARC_LS_10 for equality comparisons,
8006 but that makes no difference at the moment. */
8007 ilv->length_sensitive = ARC_LS_7;
8008 ilv[1].length_sensitive = ARC_LS_25;
8009 goto do_branch;
8010 case TYPE_BRANCH:
8011 ilv->length_sensitive = ARC_LS_10;
8012 ilv[1].length_sensitive = ARC_LS_21;
8013 do_branch:
8014 ilv->align_set = 3;
8015 ilv->length = 2;
8016 ilv->branch_cost = branch_align_cost;
8017 ilv->enabled = (len == ilv->length);
8018 ilv++;
8019 ilv->length = 4;
8020 ilv->align_set = 3;
8021 ilv->branch_cost = branch_align_cost;
8022 ilv->enabled = true;
8023 if ((target_p || force_target)
8024 || (!delay_filled && TARGET_UNALIGN_BRANCH))
8025 {
8026 ilv[1] = *ilv;
8027 ilv->align_set = 1;
8028 ilv++;
8029 ilv->align_set = 2;
8030 ilv->target_cost = 1;
8031 ilv->branch_cost = branch_unalign_cost;
8032 }
8033 ilv++;
8034 break;
8035 case TYPE_JUMP:
8036 return 0;
8037 default:
8038 /* For every short insn, there is generally also a long insn.
8039 trap_s is an exception. */
8040 if ((len & 2) == 0 || recog_memoized (insn) == CODE_FOR_trap_s)
8041 return 0;
8042 ilv->align_set = 3;
8043 ilv->length = len;
8044 ilv->enabled = 1;
8045 ilv++;
8046 ilv->align_set = 3;
8047 ilv->length = len + 2;
8048 ilv->enabled = 1;
8049 if (target_p || force_target)
8050 {
8051 ilv[1] = *ilv;
8052 ilv->align_set = 1;
8053 ilv++;
8054 ilv->align_set = 2;
8055 ilv->target_cost = 1;
8056 }
8057 ilv++;
8058 }
8059 /* If the previous instruction is an sfunc call, this insn is always
8060 a target, even though the middle-end is unaware of this.
8061 Therefore, if we have a call predecessor, transfer the target cost
8062 to the fallthrough and branch costs. */
8063 if (force_target)
8064 {
8065 for (insn_length_variant_t *p = first_ilv; p < ilv; p++)
8066 {
8067 p->fallthrough_cost += p->target_cost;
8068 p->branch_cost += p->target_cost;
8069 p->target_cost = 0;
8070 }
8071 }
8072
8073 return ilv - first_ilv;
8074}
8075
8076static void
8077arc_insn_length_parameters (insn_length_parameters_t *ilp)
8078{
8079 ilp->align_unit_log = 1;
8080 ilp->align_base_log = 1;
8081 ilp->max_variants = 7;
8082 ilp->get_variants = arc_get_insn_variants;
8083}
8084
8085/* Return a copy of COND from *STATEP, inverted if that is indicated by the
8086 CC field of *STATEP. */
8087
8088static rtx
8089arc_get_ccfsm_cond (struct arc_ccfsm *statep, bool reverse)
8090{
8091 rtx cond = statep->cond;
8092 int raw_cc = get_arc_condition_code (cond);
8093 if (reverse)
8094 raw_cc = ARC_INVERSE_CONDITION_CODE (raw_cc);
8095
8096 if (statep->cc == raw_cc)
8097 return copy_rtx (cond);
8098
8099 gcc_assert (ARC_INVERSE_CONDITION_CODE (raw_cc) == statep->cc);
8100
8101 enum machine_mode ccm = GET_MODE (XEXP (cond, 0));
8102 enum rtx_code code = reverse_condition (GET_CODE (cond));
8103 if (code == UNKNOWN || ccm == CC_FP_GTmode || ccm == CC_FP_GEmode)
8104 code = reverse_condition_maybe_unordered (GET_CODE (cond));
8105
8106 return gen_rtx_fmt_ee (code, GET_MODE (cond),
8107 copy_rtx (XEXP (cond, 0)), copy_rtx (XEXP (cond, 1)));
8108}
8109
8110/* Use the ccfsm machinery to do if conversion. */
8111
8112static unsigned
8113arc_ifcvt (void)
8114{
8115 struct arc_ccfsm *statep = &cfun->machine->ccfsm_current;
8116 basic_block merge_bb = 0;
8117
8118 memset (statep, 0, sizeof *statep);
8119 for (rtx insn = get_insns (); insn; insn = next_insn (insn))
8120 {
8121 arc_ccfsm_advance (insn, statep);
8122
8123 switch (statep->state)
8124 {
8125 case 0:
8126 if (JUMP_P (insn))
8127 merge_bb = 0;
8128 break;
8129 case 1: case 2:
8130 {
8131 /* Deleted branch. */
8132 gcc_assert (!merge_bb);
8133 merge_bb = BLOCK_FOR_INSN (insn);
8134 basic_block succ_bb
8135 = BLOCK_FOR_INSN (NEXT_INSN (NEXT_INSN (PREV_INSN (insn))));
8136 arc_ccfsm_post_advance (insn, statep);
8137 rtx seq = NEXT_INSN (PREV_INSN (insn));
8138 if (seq != insn)
8139 {
8140 rtx slot = XVECEXP (PATTERN (seq), 0, 1);
8141 rtx pat = PATTERN (slot);
8142 if (INSN_ANNULLED_BRANCH_P (insn))
8143 {
8144 rtx cond
8145 = arc_get_ccfsm_cond (statep, INSN_FROM_TARGET_P (slot));
8146 pat = gen_rtx_COND_EXEC (VOIDmode, cond, pat);
8147 }
8148 if (!validate_change (seq, &PATTERN (seq), pat, 0))
8149 gcc_unreachable ();
8150 PUT_CODE (slot, NOTE);
8151 NOTE_KIND (slot) = NOTE_INSN_DELETED;
8152 if (merge_bb && succ_bb)
8153 merge_blocks (merge_bb, succ_bb);
8154 }
8155 else if (merge_bb && succ_bb)
8156 {
8157 set_insn_deleted (insn);
8158 merge_blocks (merge_bb, succ_bb);
8159 }
8160 else
8161 {
8162 PUT_CODE (insn, NOTE);
8163 NOTE_KIND (insn) = NOTE_INSN_DELETED;
8164 }
8165 continue;
8166 }
8167 case 3:
8168 if (LABEL_P (insn)
8169 && statep->target_label == CODE_LABEL_NUMBER (insn))
8170 {
8171 arc_ccfsm_post_advance (insn, statep);
8172 basic_block succ_bb = BLOCK_FOR_INSN (insn);
8173 if (merge_bb && succ_bb)
8174 merge_blocks (merge_bb, succ_bb);
8175 else if (--LABEL_NUSES (insn) == 0)
8176 {
8177 const char *name = LABEL_NAME (insn);
8178 PUT_CODE (insn, NOTE);
8179 NOTE_KIND (insn) = NOTE_INSN_DELETED_LABEL;
8180 NOTE_DELETED_LABEL_NAME (insn) = name;
8181 }
8182 merge_bb = 0;
8183 continue;
8184 }
8185 /* Fall through. */
8186 case 4: case 5:
8187 if (!NONDEBUG_INSN_P (insn))
8188 break;
8189
8190 /* Conditionalized insn. */
8191
8192 rtx prev, pprev, *patp, pat, cond;
8193
8194 /* If this is a delay slot insn in a non-annulled branch,
8195 don't conditionalize it. N.B., this should be fine for
8196 conditional return too. However, don't do this for
8197 unconditional branches, as these would be encountered when
8198 processing an 'else' part. */
8199 prev = PREV_INSN (insn);
8200 pprev = PREV_INSN (prev);
8201 if (pprev && NEXT_INSN (NEXT_INSN (pprev)) == NEXT_INSN (insn)
8202 && JUMP_P (prev) && get_attr_cond (prev) == COND_USE
8203 && !INSN_ANNULLED_BRANCH_P (prev))
8204 break;
8205
8206 patp = &PATTERN (insn);
8207 pat = *patp;
8208 cond = arc_get_ccfsm_cond (statep, INSN_FROM_TARGET_P (insn));
8209 if (NONJUMP_INSN_P (insn) || CALL_P (insn))
8210 {
8211 /* ??? don't conditionalize if all side effects are dead
8212 in the not-execute case. */
8213 /* dwarf2out.c:dwarf2out_frame_debug_expr doesn't know
8214 what to do with COND_EXEC. */
8215 if (RTX_FRAME_RELATED_P (insn))
8216 {
8217 /* If this is the delay slot insn of an anulled branch,
8218 dwarf2out.c:scan_trace understands the anulling semantics
8219 without the COND_EXEC. */
8220 gcc_assert
8221 (pprev && NEXT_INSN (NEXT_INSN (pprev)) == NEXT_INSN (insn)
8222 && JUMP_P (prev) && get_attr_cond (prev) == COND_USE
8223 && INSN_ANNULLED_BRANCH_P (prev));
8224 rtx note = alloc_reg_note (REG_FRAME_RELATED_EXPR, pat,
8225 REG_NOTES (insn));
8226 validate_change (insn, &REG_NOTES (insn), note, 1);
8227 }
8228 pat = gen_rtx_COND_EXEC (VOIDmode, cond, pat);
8229 }
8230 else if (simplejump_p (insn))
8231 {
8232 patp = &SET_SRC (pat);
8233 pat = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, *patp, pc_rtx);
8234 }
8235 else if (JUMP_P (insn) && ANY_RETURN_P (PATTERN (insn)))
8236 {
8237 pat = gen_rtx_IF_THEN_ELSE (VOIDmode, cond, pat, pc_rtx);
8238 pat = gen_rtx_SET (VOIDmode, pc_rtx, pat);
8239 }
8240 else
8241 gcc_unreachable ();
8242 validate_change (insn, patp, pat, 1);
8243 if (!apply_change_group ())
8244 gcc_unreachable ();
8245 if (JUMP_P (insn))
8246 {
8247 rtx next = next_nonnote_insn (insn);
8248 if (GET_CODE (next) == BARRIER)
8249 delete_insn (next);
8250 if (statep->state == 3)
8251 continue;
8252 }
8253 break;
8254 default:
8255 gcc_unreachable ();
8256 }
8257 arc_ccfsm_post_advance (insn, statep);
8258 }
8259 return 0;
8260}
8261
8262/* For ARC600: If a write to a core reg >=32 appears in a delay slot
8263 (other than of a forward brcc), it creates a hazard when there is a read
8264 of the same register at the branch target. We can't know what is at the
8265 branch target of calls, and for branches, we don't really know before the
8266 end of delay slot scheduling, either. Not only can individual instruction
8267 be hoisted out into a delay slot, a basic block can also be emptied this
8268 way, and branch and/or fall through targets be redirected. Hence we don't
8269 want such writes in a delay slot. */
8270/* Called by arc_write_ext_corereg via for_each_rtx. */
8271
8272static int
8273write_ext_corereg_1 (rtx *xp, void *data ATTRIBUTE_UNUSED)
8274{
8275 rtx x = *xp;
8276 rtx dest;
8277
8278 switch (GET_CODE (x))
8279 {
8280 case SET: case POST_INC: case POST_DEC: case PRE_INC: case PRE_DEC:
8281 break;
8282 default:
8283 /* This is also fine for PRE/POST_MODIFY, because they contain a SET. */
8284 return 0;
8285 }
8286 dest = XEXP (x, 0);
8287 if (REG_P (dest) && REGNO (dest) >= 32 && REGNO (dest) < 61)
8288 return 1;
8289 return 0;
8290}
8291
8292/* Return nonzreo iff INSN writes to an extension core register. */
8293
8294int
8295arc_write_ext_corereg (rtx insn)
8296{
8297 return for_each_rtx (&PATTERN (insn), write_ext_corereg_1, 0);
8298}
8299
8300/* This is like the hook, but returns NULL when it can't / won't generate
8301 a legitimate address. */
8302
8303static rtx
8304arc_legitimize_address_0 (rtx x, rtx oldx ATTRIBUTE_UNUSED,
8305 enum machine_mode mode)
8306{
8307 rtx addr, inner;
8308
8309 if (flag_pic && SYMBOLIC_CONST (x))
8310 (x) = arc_legitimize_pic_address (x, 0);
8311 addr = x;
8312 if (GET_CODE (addr) == CONST)
8313 addr = XEXP (addr, 0);
8314 if (GET_CODE (addr) == PLUS
8315 && CONST_INT_P (XEXP (addr, 1))
8316 && ((GET_CODE (XEXP (addr, 0)) == SYMBOL_REF
8317 && !SYMBOL_REF_FUNCTION_P (XEXP (addr, 0)))
8318 || (REG_P (XEXP (addr, 0))
8319 && (INTVAL (XEXP (addr, 1)) & 252))))
8320 {
8321 HOST_WIDE_INT offs, upper;
8322 int size = GET_MODE_SIZE (mode);
8323
8324 offs = INTVAL (XEXP (addr, 1));
8325 upper = (offs + 256 * size) & ~511 * size;
8326 inner = plus_constant (Pmode, XEXP (addr, 0), upper);
8327#if 0 /* ??? this produces worse code for EEMBC idctrn01 */
8328 if (GET_CODE (x) == CONST)
8329 inner = gen_rtx_CONST (Pmode, inner);
8330#endif
8331 addr = plus_constant (Pmode, force_reg (Pmode, inner), offs - upper);
8332 x = addr;
8333 }
8334 else if (GET_CODE (addr) == SYMBOL_REF && !SYMBOL_REF_FUNCTION_P (addr))
8335 x = force_reg (Pmode, x);
8336 if (memory_address_p ((enum machine_mode) mode, x))
8337 return x;
8338 return NULL_RTX;
8339}
8340
8341static rtx
8342arc_legitimize_address (rtx orig_x, rtx oldx, enum machine_mode mode)
8343{
8344 rtx new_x = arc_legitimize_address_0 (orig_x, oldx, mode);
8345
8346 if (new_x)
8347 return new_x;
8348 return orig_x;
8349}
8350
8351static rtx
8352arc_delegitimize_address_0 (rtx x)
8353{
8354 rtx u, gp;
8355
8356 if (GET_CODE (x) == CONST && GET_CODE (u = XEXP (x, 0)) == UNSPEC)
8357 {
8358 if (XINT (u, 1) == ARC_UNSPEC_GOT)
8359 return XVECEXP (u, 0, 0);
8360 }
8361 else if (GET_CODE (x) == PLUS
8362 && ((REG_P (gp = XEXP (x, 0))
8363 && REGNO (gp) == PIC_OFFSET_TABLE_REGNUM)
8364 || (GET_CODE (gp) == CONST
8365 && GET_CODE (u = XEXP (gp, 0)) == UNSPEC
8366 && XINT (u, 1) == ARC_UNSPEC_GOT
8367 && GET_CODE (XVECEXP (u, 0, 0)) == SYMBOL_REF
8368 && !strcmp (XSTR (XVECEXP (u, 0, 0), 0), "_DYNAMIC")))
8369 && GET_CODE (XEXP (x, 1)) == CONST
8370 && GET_CODE (u = XEXP (XEXP (x, 1), 0)) == UNSPEC
8371 && XINT (u, 1) == ARC_UNSPEC_GOTOFF)
8372 return XVECEXP (u, 0, 0);
8373 else if (GET_CODE (x) == PLUS && GET_CODE (XEXP (x, 0)) == PLUS
8374 && ((REG_P (gp = XEXP (XEXP (x, 0), 1))
8375 && REGNO (gp) == PIC_OFFSET_TABLE_REGNUM)
8376 || (GET_CODE (gp) == CONST
8377 && GET_CODE (u = XEXP (gp, 0)) == UNSPEC
8378 && XINT (u, 1) == ARC_UNSPEC_GOT
8379 && GET_CODE (XVECEXP (u, 0, 0)) == SYMBOL_REF
8380 && !strcmp (XSTR (XVECEXP (u, 0, 0), 0), "_DYNAMIC")))
8381 && GET_CODE (XEXP (x, 1)) == CONST
8382 && GET_CODE (u = XEXP (XEXP (x, 1), 0)) == UNSPEC
8383 && XINT (u, 1) == ARC_UNSPEC_GOTOFF)
8384 return gen_rtx_PLUS (GET_MODE (x), XEXP (XEXP (x, 0), 0),
8385 XVECEXP (u, 0, 0));
8386 else if (GET_CODE (x) == PLUS
8387 && (u = arc_delegitimize_address_0 (XEXP (x, 1))))
8388 return gen_rtx_PLUS (GET_MODE (x), XEXP (x, 0), u);
8389 return NULL_RTX;
8390}
8391
8392static rtx
8393arc_delegitimize_address (rtx x)
8394{
8395 rtx orig_x = x = delegitimize_mem_from_attrs (x);
8396 if (GET_CODE (x) == MEM)
8397 x = XEXP (x, 0);
8398 x = arc_delegitimize_address_0 (x);
8399 if (x)
8400 {
8401 if (MEM_P (orig_x))
8402 x = replace_equiv_address_nv (orig_x, x);
8403 return x;
8404 }
8405 return orig_x;
8406}
8407
8408/* Return a REG rtx for acc1. N.B. the gcc-internal representation may
8409 differ from the hardware register number in order to allow the generic
8410 code to correctly split the concatenation of acc1 and acc2. */
8411
8412rtx
8413gen_acc1 (void)
8414{
8415 return gen_rtx_REG (SImode, TARGET_BIG_ENDIAN ? 56: 57);
8416}
8417
8418/* Return a REG rtx for acc2. N.B. the gcc-internal representation may
8419 differ from the hardware register number in order to allow the generic
8420 code to correctly split the concatenation of acc1 and acc2. */
8421
8422rtx
8423gen_acc2 (void)
8424{
8425 return gen_rtx_REG (SImode, TARGET_BIG_ENDIAN ? 57: 56);
8426}
8427
8428/* Return a REG rtx for mlo. N.B. the gcc-internal representation may
8429 differ from the hardware register number in order to allow the generic
8430 code to correctly split the concatenation of mhi and mlo. */
8431
8432rtx
8433gen_mlo (void)
8434{
8435 return gen_rtx_REG (SImode, TARGET_BIG_ENDIAN ? 59: 58);
8436}
8437
8438/* Return a REG rtx for mhi. N.B. the gcc-internal representation may
8439 differ from the hardware register number in order to allow the generic
8440 code to correctly split the concatenation of mhi and mlo. */
8441
8442rtx
8443gen_mhi (void)
8444{
8445 return gen_rtx_REG (SImode, TARGET_BIG_ENDIAN ? 58: 59);
8446}
8447
8448/* FIXME: a parameter should be added, and code added to final.c,
8449 to reproduce this functionality in shorten_branches. */
8450#if 0
8451/* Return nonzero iff BRANCH should be unaligned if possible by upsizing
8452 a previous instruction. */
8453int
8454arc_unalign_branch_p (rtx branch)
8455{
8456 rtx note;
8457
8458 if (!TARGET_UNALIGN_BRANCH)
8459 return 0;
8460 /* Do not do this if we have a filled delay slot. */
8461 if (get_attr_delay_slot_filled (branch) == DELAY_SLOT_FILLED_YES
8462 && !INSN_DELETED_P (NEXT_INSN (branch)))
8463 return 0;
8464 note = find_reg_note (branch, REG_BR_PROB, 0);
8465 return (!note
8466 || (arc_unalign_prob_threshold && !br_prob_note_reliable_p (note))
8467 || INTVAL (XEXP (note, 0)) < arc_unalign_prob_threshold);
8468}
8469#endif
8470
8471/* When estimating sizes during arc_reorg, when optimizing for speed, there
8472 are three reasons why we need to consider branches to be length 6:
8473 - annull-false delay slot insns are implemented using conditional execution,
8474 thus preventing short insn formation where used.
8475 - for ARC600: annul-true delay slot insns are implemented where possible
8476 using conditional execution, preventing short insn formation where used.
8477 - for ARC700: likely or somewhat likely taken branches are made long and
8478 unaligned if possible to avoid branch penalty. */
8479
8480bool
8481arc_branch_size_unknown_p (void)
8482{
8483 return !optimize_size && arc_reorg_in_progress;
8484}
8485
8486/* We are about to output a return insn. Add padding if necessary to avoid
8487 a mispredict. A return could happen immediately after the function
8488 start, but after a call we know that there will be at least a blink
8489 restore. */
8490
8491void
8492arc_pad_return (void)
8493{
8494 rtx insn = current_output_insn;
8495 rtx prev = prev_active_insn (insn);
8496 int want_long;
8497
8498 if (!prev)
8499 {
8500 fputs ("\tnop_s\n", asm_out_file);
8501 cfun->machine->unalign ^= 2;
8502 want_long = 1;
8503 }
8504 /* If PREV is a sequence, we know it must be a branch / jump or a tailcall,
8505 because after a call, we'd have to restore blink first. */
8506 else if (GET_CODE (PATTERN (prev)) == SEQUENCE)
8507 return;
8508 else
8509 {
8510 want_long = (get_attr_length (prev) == 2);
8511 prev = prev_active_insn (prev);
8512 }
8513 if (!prev
8514 || ((NONJUMP_INSN_P (prev) && GET_CODE (PATTERN (prev)) == SEQUENCE)
8515 ? CALL_ATTR (XVECEXP (PATTERN (prev), 0, 0), NON_SIBCALL)
8516 : CALL_ATTR (prev, NON_SIBCALL)))
8517 {
8518 if (want_long)
8519 cfun->machine->size_reason
8520 = "call/return and return/return must be 6 bytes apart to avoid mispredict";
8521 else if (TARGET_UNALIGN_BRANCH && cfun->machine->unalign)
8522 {
8523 cfun->machine->size_reason
8524 = "Long unaligned jump avoids non-delay slot penalty";
8525 want_long = 1;
8526 }
8527 /* Disgorge delay insn, if there is any, and it may be moved. */
8528 if (final_sequence
8529 /* ??? Annulled would be OK if we can and do conditionalize
8530 the delay slot insn accordingly. */
8531 && !INSN_ANNULLED_BRANCH_P (insn)
8532 && (get_attr_cond (insn) != COND_USE
8533 || !reg_set_p (gen_rtx_REG (CCmode, CC_REG),
8534 XVECEXP (final_sequence, 0, 1))))
8535 {
8536 prev = XVECEXP (final_sequence, 0, 1);
8537 gcc_assert (!prev_real_insn (insn)
8538 || !arc_hazard (prev_real_insn (insn), prev));
8539 cfun->machine->force_short_suffix = !want_long;
8540 rtx save_pred = current_insn_predicate;
8541 final_scan_insn (prev, asm_out_file, optimize, 1, NULL);
8542 cfun->machine->force_short_suffix = -1;
8543 INSN_DELETED_P (prev) = 1;
8544 current_output_insn = insn;
8545 current_insn_predicate = save_pred;
8546 }
8547 else if (want_long)
8548 fputs ("\tnop\n", asm_out_file);
8549 else
8550 {
8551 fputs ("\tnop_s\n", asm_out_file);
8552 cfun->machine->unalign ^= 2;
8553 }
8554 }
8555 return;
8556}
8557
8558/* The usual; we set up our machine_function data. */
8559
8560static struct machine_function *
8561arc_init_machine_status (void)
8562{
8563 struct machine_function *machine;
8564 machine = ggc_alloc_cleared_machine_function ();
8565 machine->fn_type = ARC_FUNCTION_UNKNOWN;
8566 machine->force_short_suffix = -1;
8567
8568 return machine;
8569}
8570
8571/* Implements INIT_EXPANDERS. We just set up to call the above
8572 function. */
8573
8574void
8575arc_init_expanders (void)
8576{
8577 init_machine_status = arc_init_machine_status;
8578}
8579
8580/* Check if OP is a proper parallel of a millicode call pattern. OFFSET
8581 indicates a number of elements to ignore - that allows to have a
8582 sibcall pattern that starts with (return). LOAD_P is zero for store
8583 multiple (for prologues), and one for load multiples (for epilogues),
8584 and two for load multiples where no final clobber of blink is required.
8585 We also skip the first load / store element since this is supposed to
8586 be checked in the instruction pattern. */
8587
8588int
8589arc_check_millicode (rtx op, int offset, int load_p)
8590{
8591 int len = XVECLEN (op, 0) - offset;
8592 int i;
8593
8594 if (load_p == 2)
8595 {
8596 if (len < 2 || len > 13)
8597 return 0;
8598 load_p = 1;
8599 }
8600 else
8601 {
8602 rtx elt = XVECEXP (op, 0, --len);
8603
8604 if (GET_CODE (elt) != CLOBBER
8605 || !REG_P (XEXP (elt, 0))
8606 || REGNO (XEXP (elt, 0)) != RETURN_ADDR_REGNUM
8607 || len < 3 || len > 13)
8608 return 0;
8609 }
8610 for (i = 1; i < len; i++)
8611 {
8612 rtx elt = XVECEXP (op, 0, i + offset);
8613 rtx reg, mem, addr;
8614
8615 if (GET_CODE (elt) != SET)
8616 return 0;
8617 mem = XEXP (elt, load_p);
8618 reg = XEXP (elt, 1-load_p);
8619 if (!REG_P (reg) || REGNO (reg) != 13U+i || !MEM_P (mem))
8620 return 0;
8621 addr = XEXP (mem, 0);
8622 if (GET_CODE (addr) != PLUS
8623 || !rtx_equal_p (stack_pointer_rtx, XEXP (addr, 0))
8624 || !CONST_INT_P (XEXP (addr, 1)) || INTVAL (XEXP (addr, 1)) != i*4)
8625 return 0;
8626 }
8627 return 1;
8628}
8629
8630/* Accessor functions for cfun->machine->unalign. */
8631
8632int
8633arc_get_unalign (void)
8634{
8635 return cfun->machine->unalign;
8636}
8637
8638void
8639arc_clear_unalign (void)
8640{
8641 if (cfun)
8642 cfun->machine->unalign = 0;
8643}
8644
8645void
8646arc_toggle_unalign (void)
8647{
8648 cfun->machine->unalign ^= 2;
8649}
8650
8651/* Operands 0..2 are the operands of a addsi which uses a 12 bit
8652 constant in operand 2, but which would require a LIMM because of
8653 operand mismatch.
8654 operands 3 and 4 are new SET_SRCs for operands 0. */
8655
8656void
8657split_addsi (rtx *operands)
8658{
8659 int val = INTVAL (operands[2]);
8660
8661 /* Try for two short insns first. Lengths being equal, we prefer
8662 expansions with shorter register lifetimes. */
8663 if (val > 127 && val <= 255
8664 && satisfies_constraint_Rcq (operands[0]))
8665 {
8666 operands[3] = operands[2];
8667 operands[4] = gen_rtx_PLUS (SImode, operands[0], operands[1]);
8668 }
8669 else
8670 {
8671 operands[3] = operands[1];
8672 operands[4] = gen_rtx_PLUS (SImode, operands[0], operands[2]);
8673 }
8674}
8675
8676/* Operands 0..2 are the operands of a subsi which uses a 12 bit
8677 constant in operand 1, but which would require a LIMM because of
8678 operand mismatch.
8679 operands 3 and 4 are new SET_SRCs for operands 0. */
8680
8681void
8682split_subsi (rtx *operands)
8683{
8684 int val = INTVAL (operands[1]);
8685
8686 /* Try for two short insns first. Lengths being equal, we prefer
8687 expansions with shorter register lifetimes. */
8688 if (satisfies_constraint_Rcq (operands[0])
8689 && satisfies_constraint_Rcq (operands[2]))
8690 {
8691 if (val >= -31 && val <= 127)
8692 {
8693 operands[3] = gen_rtx_NEG (SImode, operands[2]);
8694 operands[4] = gen_rtx_PLUS (SImode, operands[0], operands[1]);
8695 return;
8696 }
8697 else if (val >= 0 && val < 255)
8698 {
8699 operands[3] = operands[1];
8700 operands[4] = gen_rtx_MINUS (SImode, operands[0], operands[2]);
8701 return;
8702 }
8703 }
8704 /* If the destination is not an ARCompact16 register, we might
8705 still have a chance to make a short insn if the source is;
8706 we need to start with a reg-reg move for this. */
8707 operands[3] = operands[2];
8708 operands[4] = gen_rtx_MINUS (SImode, operands[1], operands[0]);
8709}
8710
8711/* Handle DOUBLE_REGS uses.
8712 Operand 0: destination register
8713 Operand 1: source register */
8714
8715static rtx
8716arc_process_double_reg_moves (rtx *operands)
8717{
8718 rtx dest = operands[0];
8719 rtx src = operands[1];
8720 rtx val;
8721
8722 enum usesDxState { none, srcDx, destDx, maxDx };
8723 enum usesDxState state = none;
8724
8725 if (refers_to_regno_p (40, 44, src, 0))
8726 state = srcDx;
8727 if (refers_to_regno_p (40, 44, dest, 0))
8728 {
8729 /* Via arc_register_move_cost, we should never see D,D moves. */
8730 gcc_assert (state == none);
8731 state = destDx;
8732 }
8733
8734 if (state == none)
8735 return NULL_RTX;
8736
8737 start_sequence ();
8738
8739 if (state == srcDx)
8740 {
8741 /* Without the LR insn, we need to split this into a
8742 sequence of insns which will use the DEXCLx and DADDHxy
8743 insns to be able to read the Dx register in question. */
8744 if (TARGET_DPFP_DISABLE_LRSR)
8745 {
8746 /* gen *movdf_insn_nolrsr */
8747 rtx set = gen_rtx_SET (VOIDmode, dest, src);
8748 rtx use1 = gen_rtx_USE (VOIDmode, const1_rtx);
8749 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, set, use1)));
8750 }
8751 else
8752 {
8753 /* When we have 'mov D, r' or 'mov D, D' then get the target
8754 register pair for use with LR insn. */
8755 rtx destHigh = simplify_gen_subreg(SImode, dest, DFmode, 4);
8756 rtx destLow = simplify_gen_subreg(SImode, dest, DFmode, 0);
8757
8758 /* Produce the two LR insns to get the high and low parts. */
8759 emit_insn (gen_rtx_SET (VOIDmode,
8760 destHigh,
8761 gen_rtx_UNSPEC_VOLATILE (Pmode, gen_rtvec (1, src),
8762 VUNSPEC_LR_HIGH)));
8763 emit_insn (gen_rtx_SET (VOIDmode,
8764 destLow,
8765 gen_rtx_UNSPEC_VOLATILE (Pmode, gen_rtvec (1, src),
8766 VUNSPEC_LR)));
8767 }
8768 }
8769 else if (state == destDx)
8770 {
8771 /* When we have 'mov r, D' or 'mov D, D' and we have access to the
8772 LR insn get the target register pair. */
8773 rtx srcHigh = simplify_gen_subreg(SImode, src, DFmode, 4);
8774 rtx srcLow = simplify_gen_subreg(SImode, src, DFmode, 0);
8775
8776 emit_insn (gen_rtx_UNSPEC_VOLATILE (Pmode,
8777 gen_rtvec (3, dest, srcHigh, srcLow),
8778 VUNSPEC_DEXCL_NORES));
8779
8780 }
8781 else
8782 gcc_unreachable ();
8783
8784 val = get_insns ();
8785 end_sequence ();
8786 return val;
8787}
8788
8789/* operands 0..1 are the operands of a 64 bit move instruction.
8790 split it into two moves with operands 2/3 and 4/5. */
8791
8792rtx
8793arc_split_move (rtx *operands)
8794{
8795 enum machine_mode mode = GET_MODE (operands[0]);
8796 int i;
8797 int swap = 0;
8798 rtx xop[4];
8799 rtx val;
8800
8801 if (TARGET_DPFP)
8802 {
8803 val = arc_process_double_reg_moves (operands);
8804 if (val)
8805 return val;
8806 }
8807
8808 for (i = 0; i < 2; i++)
8809 {
8810 if (MEM_P (operands[i]) && auto_inc_p (XEXP (operands[i], 0)))
8811 {
8812 rtx addr = XEXP (operands[i], 0);
8813 rtx r, o;
8814 enum rtx_code code;
8815
8816 gcc_assert (!reg_overlap_mentioned_p (operands[0], addr));
8817 switch (GET_CODE (addr))
8818 {
8819 case PRE_DEC: o = GEN_INT (-8); goto pre_modify;
8820 case PRE_INC: o = GEN_INT (8); goto pre_modify;
8821 case PRE_MODIFY: o = XEXP (XEXP (addr, 1), 1);
8822 pre_modify:
8823 code = PRE_MODIFY;
8824 break;
8825 case POST_DEC: o = GEN_INT (-8); goto post_modify;
8826 case POST_INC: o = GEN_INT (8); goto post_modify;
8827 case POST_MODIFY: o = XEXP (XEXP (addr, 1), 1);
8828 post_modify:
8829 code = POST_MODIFY;
8830 swap = 2;
8831 break;
8832 default:
8833 gcc_unreachable ();
8834 }
8835 r = XEXP (addr, 0);
8836 xop[0+i] = adjust_automodify_address_nv
8837 (operands[i], SImode,
8838 gen_rtx_fmt_ee (code, Pmode, r,
8839 gen_rtx_PLUS (Pmode, r, o)),
8840 0);
8841 xop[2+i] = adjust_automodify_address_nv
8842 (operands[i], SImode, plus_constant (Pmode, r, 4), 4);
8843 }
8844 else
8845 {
8846 xop[0+i] = operand_subword (operands[i], 0, 0, mode);
8847 xop[2+i] = operand_subword (operands[i], 1, 0, mode);
8848 }
8849 }
8850 if (reg_overlap_mentioned_p (xop[0], xop[3]))
8851 {
8852 swap = 2;
8853 gcc_assert (!reg_overlap_mentioned_p (xop[2], xop[1]));
8854 }
8855 operands[2+swap] = xop[0];
8856 operands[3+swap] = xop[1];
8857 operands[4-swap] = xop[2];
8858 operands[5-swap] = xop[3];
8859
8860 start_sequence ();
8861 emit_insn (gen_rtx_SET (VOIDmode, operands[2], operands[3]));
8862 emit_insn (gen_rtx_SET (VOIDmode, operands[4], operands[5]));
8863 val = get_insns ();
8864 end_sequence ();
8865
8866 return val;
8867}
8868
8869/* Select between the instruction output templates s_tmpl (for short INSNs)
8870 and l_tmpl (for long INSNs). */
8871
8872const char *
8873arc_short_long (rtx insn, const char *s_tmpl, const char *l_tmpl)
8874{
8875 int is_short = arc_verify_short (insn, cfun->machine->unalign, -1);
8876
8877 extract_constrain_insn_cached (insn);
8878 return is_short ? s_tmpl : l_tmpl;
8879}
8880
8881/* Searches X for any reference to REGNO, returning the rtx of the
8882 reference found if any. Otherwise, returns NULL_RTX. */
8883
8884rtx
8885arc_regno_use_in (unsigned int regno, rtx x)
8886{
8887 const char *fmt;
8888 int i, j;
8889 rtx tem;
8890
8891 if (REG_P (x) && refers_to_regno_p (regno, regno+1, x, (rtx *) 0))
8892 return x;
8893
8894 fmt = GET_RTX_FORMAT (GET_CODE (x));
8895 for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--)
8896 {
8897 if (fmt[i] == 'e')
8898 {
8899 if ((tem = regno_use_in (regno, XEXP (x, i))))
8900 return tem;
8901 }
8902 else if (fmt[i] == 'E')
8903 for (j = XVECLEN (x, i) - 1; j >= 0; j--)
8904 if ((tem = regno_use_in (regno , XVECEXP (x, i, j))))
8905 return tem;
8906 }
8907
8908 return NULL_RTX;
8909}
8910
8911/* Return the integer value of the "type" attribute for INSN, or -1 if
8912 INSN can't have attributes. */
8913
8914int
8915arc_attr_type (rtx insn)
8916{
8917 if (NONJUMP_INSN_P (insn)
8918 ? (GET_CODE (PATTERN (insn)) == USE
8919 || GET_CODE (PATTERN (insn)) == CLOBBER)
8920 : JUMP_P (insn)
8921 ? (GET_CODE (PATTERN (insn)) == ADDR_VEC
8922 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
8923 : !CALL_P (insn))
8924 return -1;
8925 return get_attr_type (insn);
8926}
8927
8928/* Return true if insn sets the condition codes. */
8929
8930bool
8931arc_sets_cc_p (rtx insn)
8932{
8933 if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE)
8934 insn = XVECEXP (PATTERN (insn), 0, XVECLEN (PATTERN (insn), 0) - 1);
8935 return arc_attr_type (insn) == TYPE_COMPARE;
8936}
8937
8938/* Return true if INSN is an instruction with a delay slot we may want
8939 to fill. */
8940
8941bool
8942arc_need_delay (rtx insn)
8943{
8944 rtx next;
8945
8946 if (!flag_delayed_branch)
8947 return false;
8948 /* The return at the end of a function needs a delay slot. */
8949 if (NONJUMP_INSN_P (insn) && GET_CODE (PATTERN (insn)) == USE
8950 && (!(next = next_active_insn (insn))
8951 || ((!NONJUMP_INSN_P (next) || GET_CODE (PATTERN (next)) != SEQUENCE)
8952 && arc_attr_type (next) == TYPE_RETURN))
8953 && (!TARGET_PAD_RETURN
8954 || (prev_active_insn (insn)
8955 && prev_active_insn (prev_active_insn (insn))
8956 && prev_active_insn (prev_active_insn (prev_active_insn (insn))))))
8957 return true;
8958 if (NONJUMP_INSN_P (insn)
8959 ? (GET_CODE (PATTERN (insn)) == USE
8960 || GET_CODE (PATTERN (insn)) == CLOBBER
8961 || GET_CODE (PATTERN (insn)) == SEQUENCE)
8962 : JUMP_P (insn)
8963 ? (GET_CODE (PATTERN (insn)) == ADDR_VEC
8964 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
8965 : !CALL_P (insn))
8966 return false;
8967 return num_delay_slots (insn) != 0;
8968}
8969
8970/* Return true if the scheduling pass(es) has/have already run,
8971 i.e. where possible, we should try to mitigate high latencies
8972 by different instruction selection. */
8973
8974bool
8975arc_scheduling_not_expected (void)
8976{
8977 return cfun->machine->arc_reorg_started;
8978}
8979
8980/* Oddly enough, sometimes we get a zero overhead loop that branch
8981 shortening doesn't think is a loop - observed with compile/pr24883.c
8982 -O3 -fomit-frame-pointer -funroll-loops. Make sure to include the
8983 alignment visible for branch shortening (we actually align the loop
8984 insn before it, but that is equivalent since the loop insn is 4 byte
8985 long.) */
8986
8987int
8988arc_label_align (rtx label)
8989{
8990 int loop_align = LOOP_ALIGN (LABEL);
8991
8992 if (loop_align > align_labels_log)
8993 {
8994 rtx prev = prev_nonnote_insn (label);
8995
8996 if (prev && NONJUMP_INSN_P (prev)
8997 && GET_CODE (PATTERN (prev)) == PARALLEL
8998 && recog_memoized (prev) == CODE_FOR_doloop_begin_i)
8999 return loop_align;
9000 }
9001 /* Code has a minimum p2 alignment of 1, which we must restore after an
9002 ADDR_DIFF_VEC. */
9003 if (align_labels_log < 1)
9004 {
9005 rtx next = next_nonnote_nondebug_insn (label);
9006 if (INSN_P (next) && recog_memoized (next) >= 0)
9007 return 1;
9008 }
9009 return align_labels_log;
9010}
9011
9012/* Return true if LABEL is in executable code. */
9013
9014bool
9015arc_text_label (rtx label)
9016{
9017 rtx next;
9018
9019 /* ??? We use deleted labels like they were still there, see
9020 gcc.c-torture/compile/20000326-2.c . */
9021 gcc_assert (GET_CODE (label) == CODE_LABEL
9022 || (GET_CODE (label) == NOTE
9023 && NOTE_KIND (label) == NOTE_INSN_DELETED_LABEL));
9024 next = next_nonnote_insn (label);
9025 if (next)
9026 return (!JUMP_TABLE_DATA_P (next)
9027 || GET_CODE (PATTERN (next)) != ADDR_VEC);
9028 else if (!PREV_INSN (label))
9029 /* ??? sometimes text labels get inserted very late, see
9030 gcc.dg/torture/stackalign/comp-goto-1.c */
9031 return true;
9032 return false;
9033}
9034
9035/* Return the size of the pretend args for DECL. */
9036
9037int
9038arc_decl_pretend_args (tree decl)
9039{
9040 /* struct function is in DECL_STRUCT_FUNCTION (decl), but no
9041 pretend_args there... See PR38391. */
9042 gcc_assert (decl == current_function_decl);
9043 return crtl->args.pretend_args_size;
9044}
9045
9046/* Without this, gcc.dg/tree-prof/bb-reorg.c fails to assemble
9047 when compiling with -O2 -freorder-blocks-and-partition -fprofile-use
9048 -D_PROFILE_USE; delay branch scheduling then follows a REG_CROSSING_JUMP
9049 to redirect two breqs. */
9050
9051static bool
9052arc_can_follow_jump (const_rtx follower, const_rtx followee)
9053{
9054 /* ??? get_attr_type is declared to take an rtx. */
9055 union { const_rtx c; rtx r; } u;
9056
9057 u.c = follower;
9058 if (find_reg_note (followee, REG_CROSSING_JUMP, NULL_RTX))
9059 switch (get_attr_type (u.r))
9060 {
9061 case TYPE_BRCC:
9062 case TYPE_BRCC_NO_DELAY_SLOT:
9063 return false;
9064 default:
9065 return true;
9066 }
9067 return true;
9068}
9069
9070/* Implement EPILOGUE__USES.
9071 Return true if REGNO should be added to the deemed uses of the epilogue.
9072
9073 We use the return address
9074 arc_return_address_regs[arc_compute_function_type (cfun)] .
9075 But also, we have to make sure all the register restore instructions
9076 are known to be live in interrupt functions. */
9077
9078bool
9079arc_epilogue_uses (int regno)
9080{
9081 if (reload_completed)
9082 {
9083 if (ARC_INTERRUPT_P (cfun->machine->fn_type))
9084 {
9085 if (!fixed_regs[regno])
9086 return true;
9087 return regno == arc_return_address_regs[cfun->machine->fn_type];
9088 }
9089 else
9090 return regno == RETURN_ADDR_REGNUM;
9091 }
9092 else
9093 return regno == arc_return_address_regs[arc_compute_function_type (cfun)];
9094}
9095
9096#ifndef TARGET_NO_LRA
9097#define TARGET_NO_LRA !TARGET_LRA
9098#endif
9099
9100static bool
9101arc_lra_p (void)
9102{
9103 return !TARGET_NO_LRA;
9104}
9105
9106/* ??? Should we define TARGET_REGISTER_PRIORITY? We might perfer to use
9107 Rcq registers, because some insn are shorter with them. OTOH we already
9108 have separate alternatives for this purpose, and other insns don't
9109 mind, so maybe we should rather prefer the other registers?
9110 We need more data, and we can only get that if we allow people to
9111 try all options. */
9112static int
9113arc_register_priority (int r)
9114{
9115 switch (arc_lra_priority_tag)
9116 {
9117 case ARC_LRA_PRIORITY_NONE:
9118 return 0;
9119 case ARC_LRA_PRIORITY_NONCOMPACT:
9120 return ((((r & 7) ^ 4) - 4) & 15) != r;
9121 case ARC_LRA_PRIORITY_COMPACT:
9122 return ((((r & 7) ^ 4) - 4) & 15) == r;
9123 default:
9124 gcc_unreachable ();
9125 }
9126}
9127
9128static reg_class_t
9129arc_spill_class (reg_class_t /* orig_class */, enum machine_mode)
9130{
9131 return GENERAL_REGS;
9132}
9133
9134bool
9135arc_legitimize_reload_address (rtx *p, enum machine_mode mode, int opnum,
9136 int itype)
9137{
9138 rtx x = *p;
9139 enum reload_type type = (enum reload_type) itype;
9140
9141 if (GET_CODE (x) == PLUS
9142 && CONST_INT_P (XEXP (x, 1))
9143 && (RTX_OK_FOR_BASE_P (XEXP (x, 0), true)
9144 || (REG_P (XEXP (x, 0))
9145 && reg_equiv_constant (REGNO (XEXP (x, 0))))))
9146 {
9147 int scale = GET_MODE_SIZE (mode);
9148 int shift;
9149 rtx index_rtx = XEXP (x, 1);
9150 HOST_WIDE_INT offset = INTVAL (index_rtx), offset_base;
9151 rtx reg, sum, sum2;
9152
9153 if (scale > 4)
9154 scale = 4;
9155 if ((scale-1) & offset)
9156 scale = 1;
9157 shift = scale >> 1;
9158 offset_base = (offset + (256 << shift)) & (-512 << shift);
9159 /* Sometimes the normal form does not suit DImode. We
9160 could avoid that by using smaller ranges, but that
9161 would give less optimized code when SImode is
9162 prevalent. */
9163 if (GET_MODE_SIZE (mode) + offset - offset_base <= (256 << shift))
9164 {
9165 int regno;
9166
9167 reg = XEXP (x, 0);
9168 regno = REGNO (reg);
9169 sum2 = sum = plus_constant (Pmode, reg, offset_base);
9170
9171 if (reg_equiv_constant (regno))
9172 {
9173 sum2 = plus_constant (Pmode, reg_equiv_constant (regno),
9174 offset_base);
9175 if (GET_CODE (sum2) == PLUS)
9176 sum2 = gen_rtx_CONST (Pmode, sum2);
9177 }
9178 *p = gen_rtx_PLUS (Pmode, sum, GEN_INT (offset - offset_base));
9179 push_reload (sum2, NULL_RTX, &XEXP (*p, 0), NULL,
9180 BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, opnum,
9181 type);
9182 return true;
9183 }
9184 }
9185 /* We must re-recognize what we created before. */
9186 else if (GET_CODE (x) == PLUS
9187 && GET_CODE (XEXP (x, 0)) == PLUS
9188 && CONST_INT_P (XEXP (XEXP (x, 0), 1))
9189 && REG_P (XEXP (XEXP (x, 0), 0))
9190 && CONST_INT_P (XEXP (x, 1)))
9191 {
9192 /* Because this address is so complex, we know it must have
9193 been created by LEGITIMIZE_RELOAD_ADDRESS before; thus,
9194 it is already unshared, and needs no further unsharing. */
9195 push_reload (XEXP (x, 0), NULL_RTX, &XEXP (x, 0), NULL,
9196 BASE_REG_CLASS, Pmode, VOIDmode, 0, 0, opnum, type);
9197 return true;
9198 }
9199 return false;
9200}
9201
9202struct gcc_target targetm = TARGET_INITIALIZER;
9203
9204#include "gt-arc.h"