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