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