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