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