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