]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arc/arc.c
Daily bump.
[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"
34#include "tm.h"
40e23961
MC
35#include "alias.h"
36#include "symtab.h"
526b7aee 37#include "tree.h"
40e23961 38#include "fold-const.h"
d8a2d370
DN
39#include "varasm.h"
40#include "stor-layout.h"
41#include "stringpool.h"
42#include "calls.h"
526b7aee
SV
43#include "rtl.h"
44#include "regs.h"
45#include "hard-reg-set.h"
526b7aee
SV
46#include "insn-config.h"
47#include "conditions.h"
48#include "insn-flags.h"
49#include "function.h"
50#include "toplev.h"
526b7aee
SV
51#include "tm_p.h"
52#include "target.h"
53#include "output.h"
54#include "insn-attr.h"
55#include "flags.h"
36566b39
PK
56#include "expmed.h"
57#include "dojump.h"
58#include "explow.h"
59#include "emit-rtl.h"
60#include "stmt.h"
526b7aee
SV
61#include "expr.h"
62#include "recog.h"
63#include "debug.h"
64#include "diagnostic.h"
65#include "insn-codes.h"
66#include "langhooks.h"
67#include "optabs.h"
68#include "tm-constrs.h"
69#include "reload.h" /* For operands_match_p */
60393bbc
AM
70#include "dominance.h"
71#include "cfg.h"
72#include "cfgrtl.h"
73#include "cfganal.h"
74#include "lcm.h"
75#include "cfgbuild.h"
76#include "cfgcleanup.h"
77#include "predict.h"
78#include "basic-block.h"
526b7aee
SV
79#include "df.h"
80#include "tree-pass.h"
81#include "context.h"
82#include "pass_manager.h"
9b2b7279 83#include "builtins.h"
6733978e 84#include "rtl-iter.h"
526b7aee
SV
85
86/* Which cpu we're compiling for (A5, ARC600, ARC601, ARC700). */
87static const char *arc_cpu_string = "";
88
89/* ??? Loads can handle any constant, stores can only handle small ones. */
90/* OTOH, LIMMs cost extra, so their usefulness is limited. */
91#define RTX_OK_FOR_OFFSET_P(MODE, X) \
92(GET_CODE (X) == CONST_INT \
93 && SMALL_INT_RANGE (INTVAL (X), (GET_MODE_SIZE (MODE) - 1) & -4, \
94 (INTVAL (X) & (GET_MODE_SIZE (MODE) - 1) & 3 \
95 ? 0 \
96 : -(-GET_MODE_SIZE (MODE) | -4) >> 1)))
97
98#define LEGITIMATE_OFFSET_ADDRESS_P(MODE, X, INDEX, STRICT) \
99(GET_CODE (X) == PLUS \
100 && RTX_OK_FOR_BASE_P (XEXP (X, 0), (STRICT)) \
101 && ((INDEX && RTX_OK_FOR_INDEX_P (XEXP (X, 1), (STRICT)) \
102 && GET_MODE_SIZE ((MODE)) <= 4) \
103 || RTX_OK_FOR_OFFSET_P (MODE, XEXP (X, 1))))
104
105#define LEGITIMATE_SCALED_ADDRESS_P(MODE, X, STRICT) \
106(GET_CODE (X) == PLUS \
107 && GET_CODE (XEXP (X, 0)) == MULT \
108 && RTX_OK_FOR_INDEX_P (XEXP (XEXP (X, 0), 0), (STRICT)) \
109 && GET_CODE (XEXP (XEXP (X, 0), 1)) == CONST_INT \
110 && ((GET_MODE_SIZE (MODE) == 2 && INTVAL (XEXP (XEXP (X, 0), 1)) == 2) \
111 || (GET_MODE_SIZE (MODE) == 4 && INTVAL (XEXP (XEXP (X, 0), 1)) == 4)) \
112 && (RTX_OK_FOR_BASE_P (XEXP (X, 1), (STRICT)) \
113 || (flag_pic ? CONST_INT_P (XEXP (X, 1)) : CONSTANT_P (XEXP (X, 1)))))
114
115#define LEGITIMATE_SMALL_DATA_ADDRESS_P(X) \
116 (GET_CODE (X) == PLUS \
117 && (REG_P (XEXP ((X), 0)) && REGNO (XEXP ((X), 0)) == SDATA_BASE_REGNUM) \
118 && ((GET_CODE (XEXP((X),1)) == SYMBOL_REF \
119 && SYMBOL_REF_SMALL_P (XEXP ((X), 1))) \
120 || (GET_CODE (XEXP ((X), 1)) == CONST \
121 && GET_CODE (XEXP (XEXP ((X), 1), 0)) == PLUS \
122 && GET_CODE (XEXP (XEXP (XEXP ((X), 1), 0), 0)) == SYMBOL_REF \
123 && SYMBOL_REF_SMALL_P (XEXP (XEXP (XEXP ((X), 1), 0), 0)) \
124 && GET_CODE (XEXP(XEXP (XEXP ((X), 1), 0), 1)) == CONST_INT)))
125
126/* Array of valid operand punctuation characters. */
127char arc_punct_chars[256];
128
129/* State used by arc_ccfsm_advance to implement conditional execution. */
130struct GTY (()) arc_ccfsm
131{
132 int state;
133 int cc;
134 rtx cond;
b3458f61 135 rtx_insn *target_insn;
526b7aee
SV
136 int target_label;
137};
138
139#define arc_ccfsm_current cfun->machine->ccfsm_current
140
141#define ARC_CCFSM_BRANCH_DELETED_P(STATE) \
142 ((STATE)->state == 1 || (STATE)->state == 2)
143
144/* Indicate we're conditionalizing insns now. */
145#define ARC_CCFSM_RECORD_BRANCH_DELETED(STATE) \
146 ((STATE)->state += 2)
147
148#define ARC_CCFSM_COND_EXEC_P(STATE) \
149 ((STATE)->state == 3 || (STATE)->state == 4 || (STATE)->state == 5 \
150 || current_insn_predicate)
151
152/* Check if INSN has a 16 bit opcode considering struct arc_ccfsm *STATE. */
153#define CCFSM_ISCOMPACT(INSN,STATE) \
154 (ARC_CCFSM_COND_EXEC_P (STATE) \
155 ? (get_attr_iscompact (INSN) == ISCOMPACT_TRUE \
156 || get_attr_iscompact (INSN) == ISCOMPACT_TRUE_LIMM) \
157 : get_attr_iscompact (INSN) != ISCOMPACT_FALSE)
158
159/* Likewise, but also consider that INSN might be in a delay slot of JUMP. */
160#define CCFSM_DBR_ISCOMPACT(INSN,JUMP,STATE) \
161 ((ARC_CCFSM_COND_EXEC_P (STATE) \
162 || (JUMP_P (JUMP) \
163 && INSN_ANNULLED_BRANCH_P (JUMP) \
164 && (TARGET_AT_DBR_CONDEXEC || INSN_FROM_TARGET_P (INSN)))) \
165 ? (get_attr_iscompact (INSN) == ISCOMPACT_TRUE \
166 || get_attr_iscompact (INSN) == ISCOMPACT_TRUE_LIMM) \
167 : get_attr_iscompact (INSN) != ISCOMPACT_FALSE)
168
169/* The maximum number of insns skipped which will be conditionalised if
170 possible. */
171/* When optimizing for speed:
172 Let p be the probability that the potentially skipped insns need to
173 be executed, pn the cost of a correctly predicted non-taken branch,
174 mt the cost of a mis/non-predicted taken branch,
175 mn mispredicted non-taken, pt correctly predicted taken ;
176 costs expressed in numbers of instructions like the ones considered
177 skipping.
178 Unfortunately we don't have a measure of predictability - this
179 is linked to probability only in that in the no-eviction-scenario
180 there is a lower bound 1 - 2 * min (p, 1-p), and a somewhat larger
181 value that can be assumed *if* the distribution is perfectly random.
182 A predictability of 1 is perfectly plausible not matter what p is,
183 because the decision could be dependent on an invocation parameter
184 of the program.
185 For large p, we want MAX_INSNS_SKIPPED == pn/(1-p) + mt - pn
186 For small p, we want MAX_INSNS_SKIPPED == pt
187
188 When optimizing for size:
189 We want to skip insn unless we could use 16 opcodes for the
190 non-conditionalized insn to balance the branch length or more.
191 Performance can be tie-breaker. */
192/* If the potentially-skipped insns are likely to be executed, we'll
193 generally save one non-taken branch
194 o
195 this to be no less than the 1/p */
196#define MAX_INSNS_SKIPPED 3
197
198/* The values of unspec's first field. */
199enum {
200 ARC_UNSPEC_PLT = 3,
201 ARC_UNSPEC_GOT,
202 ARC_UNSPEC_GOTOFF
203} ;
204
205
206enum arc_builtins {
207 ARC_BUILTIN_NOP = 2,
208 ARC_BUILTIN_NORM = 3,
209 ARC_BUILTIN_NORMW = 4,
210 ARC_BUILTIN_SWAP = 5,
211 ARC_BUILTIN_BRK = 6,
212 ARC_BUILTIN_DIVAW = 7,
213 ARC_BUILTIN_EX = 8,
214 ARC_BUILTIN_MUL64 = 9,
215 ARC_BUILTIN_MULU64 = 10,
216 ARC_BUILTIN_RTIE = 11,
217 ARC_BUILTIN_SYNC = 12,
218 ARC_BUILTIN_CORE_READ = 13,
219 ARC_BUILTIN_CORE_WRITE = 14,
220 ARC_BUILTIN_FLAG = 15,
221 ARC_BUILTIN_LR = 16,
222 ARC_BUILTIN_SR = 17,
223 ARC_BUILTIN_SLEEP = 18,
224 ARC_BUILTIN_SWI = 19,
225 ARC_BUILTIN_TRAP_S = 20,
226 ARC_BUILTIN_UNIMP_S = 21,
227 ARC_BUILTIN_ALIGNED = 22,
228
229 /* Sentinel to mark start of simd builtins. */
230 ARC_SIMD_BUILTIN_BEGIN = 1000,
231
232 ARC_SIMD_BUILTIN_VADDAW = 1001,
233 ARC_SIMD_BUILTIN_VADDW = 1002,
234 ARC_SIMD_BUILTIN_VAVB = 1003,
235 ARC_SIMD_BUILTIN_VAVRB = 1004,
236 ARC_SIMD_BUILTIN_VDIFAW = 1005,
237 ARC_SIMD_BUILTIN_VDIFW = 1006,
238 ARC_SIMD_BUILTIN_VMAXAW = 1007,
239 ARC_SIMD_BUILTIN_VMAXW = 1008,
240 ARC_SIMD_BUILTIN_VMINAW = 1009,
241 ARC_SIMD_BUILTIN_VMINW = 1010,
242 ARC_SIMD_BUILTIN_VMULAW = 1011,
243 ARC_SIMD_BUILTIN_VMULFAW = 1012,
244 ARC_SIMD_BUILTIN_VMULFW = 1013,
245 ARC_SIMD_BUILTIN_VMULW = 1014,
246 ARC_SIMD_BUILTIN_VSUBAW = 1015,
247 ARC_SIMD_BUILTIN_VSUBW = 1016,
248 ARC_SIMD_BUILTIN_VSUMMW = 1017,
249 ARC_SIMD_BUILTIN_VAND = 1018,
250 ARC_SIMD_BUILTIN_VANDAW = 1019,
251 ARC_SIMD_BUILTIN_VBIC = 1020,
252 ARC_SIMD_BUILTIN_VBICAW = 1021,
253 ARC_SIMD_BUILTIN_VOR = 1022,
254 ARC_SIMD_BUILTIN_VXOR = 1023,
255 ARC_SIMD_BUILTIN_VXORAW = 1024,
256 ARC_SIMD_BUILTIN_VEQW = 1025,
257 ARC_SIMD_BUILTIN_VLEW = 1026,
258 ARC_SIMD_BUILTIN_VLTW = 1027,
259 ARC_SIMD_BUILTIN_VNEW = 1028,
260 ARC_SIMD_BUILTIN_VMR1AW = 1029,
261 ARC_SIMD_BUILTIN_VMR1W = 1030,
262 ARC_SIMD_BUILTIN_VMR2AW = 1031,
263 ARC_SIMD_BUILTIN_VMR2W = 1032,
264 ARC_SIMD_BUILTIN_VMR3AW = 1033,
265 ARC_SIMD_BUILTIN_VMR3W = 1034,
266 ARC_SIMD_BUILTIN_VMR4AW = 1035,
267 ARC_SIMD_BUILTIN_VMR4W = 1036,
268 ARC_SIMD_BUILTIN_VMR5AW = 1037,
269 ARC_SIMD_BUILTIN_VMR5W = 1038,
270 ARC_SIMD_BUILTIN_VMR6AW = 1039,
271 ARC_SIMD_BUILTIN_VMR6W = 1040,
272 ARC_SIMD_BUILTIN_VMR7AW = 1041,
273 ARC_SIMD_BUILTIN_VMR7W = 1042,
274 ARC_SIMD_BUILTIN_VMRB = 1043,
275 ARC_SIMD_BUILTIN_VH264F = 1044,
276 ARC_SIMD_BUILTIN_VH264FT = 1045,
277 ARC_SIMD_BUILTIN_VH264FW = 1046,
278 ARC_SIMD_BUILTIN_VVC1F = 1047,
279 ARC_SIMD_BUILTIN_VVC1FT = 1048,
280
281 /* Va, Vb, rlimm instructions. */
282 ARC_SIMD_BUILTIN_VBADDW = 1050,
283 ARC_SIMD_BUILTIN_VBMAXW = 1051,
284 ARC_SIMD_BUILTIN_VBMINW = 1052,
285 ARC_SIMD_BUILTIN_VBMULAW = 1053,
286 ARC_SIMD_BUILTIN_VBMULFW = 1054,
287 ARC_SIMD_BUILTIN_VBMULW = 1055,
288 ARC_SIMD_BUILTIN_VBRSUBW = 1056,
289 ARC_SIMD_BUILTIN_VBSUBW = 1057,
290
291 /* Va, Vb, Ic instructions. */
292 ARC_SIMD_BUILTIN_VASRW = 1060,
293 ARC_SIMD_BUILTIN_VSR8 = 1061,
294 ARC_SIMD_BUILTIN_VSR8AW = 1062,
295
296 /* Va, Vb, u6 instructions. */
297 ARC_SIMD_BUILTIN_VASRRWi = 1065,
298 ARC_SIMD_BUILTIN_VASRSRWi = 1066,
299 ARC_SIMD_BUILTIN_VASRWi = 1067,
300 ARC_SIMD_BUILTIN_VASRPWBi = 1068,
301 ARC_SIMD_BUILTIN_VASRRPWBi = 1069,
302 ARC_SIMD_BUILTIN_VSR8AWi = 1070,
303 ARC_SIMD_BUILTIN_VSR8i = 1071,
304
305 /* Va, Vb, u8 (simm) instructions. */
306 ARC_SIMD_BUILTIN_VMVAW = 1075,
307 ARC_SIMD_BUILTIN_VMVW = 1076,
308 ARC_SIMD_BUILTIN_VMVZW = 1077,
309 ARC_SIMD_BUILTIN_VD6TAPF = 1078,
310
311 /* Va, rlimm, u8 (simm) instructions. */
312 ARC_SIMD_BUILTIN_VMOVAW = 1080,
313 ARC_SIMD_BUILTIN_VMOVW = 1081,
314 ARC_SIMD_BUILTIN_VMOVZW = 1082,
315
316 /* Va, Vb instructions. */
317 ARC_SIMD_BUILTIN_VABSAW = 1085,
318 ARC_SIMD_BUILTIN_VABSW = 1086,
319 ARC_SIMD_BUILTIN_VADDSUW = 1087,
320 ARC_SIMD_BUILTIN_VSIGNW = 1088,
321 ARC_SIMD_BUILTIN_VEXCH1 = 1089,
322 ARC_SIMD_BUILTIN_VEXCH2 = 1090,
323 ARC_SIMD_BUILTIN_VEXCH4 = 1091,
324 ARC_SIMD_BUILTIN_VUPBAW = 1092,
325 ARC_SIMD_BUILTIN_VUPBW = 1093,
326 ARC_SIMD_BUILTIN_VUPSBAW = 1094,
327 ARC_SIMD_BUILTIN_VUPSBW = 1095,
328
329 ARC_SIMD_BUILTIN_VDIRUN = 1100,
330 ARC_SIMD_BUILTIN_VDORUN = 1101,
331 ARC_SIMD_BUILTIN_VDIWR = 1102,
332 ARC_SIMD_BUILTIN_VDOWR = 1103,
333
334 ARC_SIMD_BUILTIN_VREC = 1105,
335 ARC_SIMD_BUILTIN_VRUN = 1106,
336 ARC_SIMD_BUILTIN_VRECRUN = 1107,
337 ARC_SIMD_BUILTIN_VENDREC = 1108,
338
339 ARC_SIMD_BUILTIN_VLD32WH = 1110,
340 ARC_SIMD_BUILTIN_VLD32WL = 1111,
341 ARC_SIMD_BUILTIN_VLD64 = 1112,
342 ARC_SIMD_BUILTIN_VLD32 = 1113,
343 ARC_SIMD_BUILTIN_VLD64W = 1114,
344 ARC_SIMD_BUILTIN_VLD128 = 1115,
345 ARC_SIMD_BUILTIN_VST128 = 1116,
346 ARC_SIMD_BUILTIN_VST64 = 1117,
347
348 ARC_SIMD_BUILTIN_VST16_N = 1120,
349 ARC_SIMD_BUILTIN_VST32_N = 1121,
350
351 ARC_SIMD_BUILTIN_VINTI = 1201,
352
353 ARC_SIMD_BUILTIN_END
354};
355
356/* A nop is needed between a 4 byte insn that sets the condition codes and
357 a branch that uses them (the same isn't true for an 8 byte insn that sets
358 the condition codes). Set by arc_ccfsm_advance. Used by
359 arc_print_operand. */
360
361static int get_arc_condition_code (rtx);
362
363static tree arc_handle_interrupt_attribute (tree *, tree, tree, int, bool *);
364
365/* Initialized arc_attribute_table to NULL since arc doesnot have any
366 machine specific supported attributes. */
367const struct attribute_spec arc_attribute_table[] =
368{
369 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
370 affects_type_identity } */
371 { "interrupt", 1, 1, true, false, false, arc_handle_interrupt_attribute, true },
372 /* Function calls made to this symbol must be done indirectly, because
373 it may lie outside of the 21/25 bit addressing range of a normal function
374 call. */
375 { "long_call", 0, 0, false, true, true, NULL, false },
376 /* Whereas these functions are always known to reside within the 25 bit
377 addressing range of unconditionalized bl. */
378 { "medium_call", 0, 0, false, true, true, NULL, false },
379 /* And these functions are always known to reside within the 21 bit
380 addressing range of blcc. */
381 { "short_call", 0, 0, false, true, true, NULL, false },
382 { NULL, 0, 0, false, false, false, NULL, false }
383};
384static int arc_comp_type_attributes (const_tree, const_tree);
385static void arc_file_start (void);
386static void arc_internal_label (FILE *, const char *, unsigned long);
387static void arc_output_mi_thunk (FILE *, tree, HOST_WIDE_INT, HOST_WIDE_INT,
388 tree);
ef4bddc2 389static int arc_address_cost (rtx, machine_mode, addr_space_t, bool);
526b7aee
SV
390static void arc_encode_section_info (tree decl, rtx rtl, int first);
391
392static void arc_init_builtins (void);
ef4bddc2 393static rtx arc_expand_builtin (tree, rtx, rtx, machine_mode, int);
526b7aee
SV
394
395static int branch_dest (rtx);
396
397static void arc_output_pic_addr_const (FILE *, rtx, int);
ef4bddc2 398void emit_pic_move (rtx *, machine_mode);
526b7aee
SV
399bool arc_legitimate_pic_operand_p (rtx);
400static bool arc_function_ok_for_sibcall (tree, tree);
401static rtx arc_function_value (const_tree, const_tree, bool);
402const char * output_shift (rtx *);
403static void arc_reorg (void);
404static bool arc_in_small_data_p (const_tree);
405
406static void arc_init_reg_tables (void);
407static bool arc_return_in_memory (const_tree, const_tree);
408static void arc_init_simd_builtins (void);
ef4bddc2 409static bool arc_vector_mode_supported_p (machine_mode);
526b7aee 410
807e902e
KZ
411static bool arc_can_use_doloop_p (const widest_int &, const widest_int &,
412 unsigned int, bool);
ac44248e 413static const char *arc_invalid_within_doloop (const rtx_insn *);
526b7aee
SV
414
415static void output_short_suffix (FILE *file);
416
417static bool arc_frame_pointer_required (void);
418
445d7826 419static bool arc_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT,
ad23f5d4
JG
420 unsigned int,
421 enum by_pieces_operation op,
422 bool);
423
526b7aee
SV
424/* Implements target hook vector_mode_supported_p. */
425
426static bool
ef4bddc2 427arc_vector_mode_supported_p (machine_mode mode)
526b7aee
SV
428{
429 if (!TARGET_SIMD_SET)
430 return false;
431
432 if ((mode == V4SImode)
433 || (mode == V8HImode))
434 return true;
435
436 return false;
437}
438
439
440/* TARGET_PRESERVE_RELOAD_P is still awaiting patch re-evaluation / review. */
441static bool arc_preserve_reload_p (rtx in) ATTRIBUTE_UNUSED;
442static rtx arc_delegitimize_address (rtx);
c1ce59ab
DM
443static bool arc_can_follow_jump (const rtx_insn *follower,
444 const rtx_insn *followee);
526b7aee
SV
445
446static rtx frame_insn (rtx);
ef4bddc2 447static void arc_function_arg_advance (cumulative_args_t, machine_mode,
526b7aee 448 const_tree, bool);
ef4bddc2 449static rtx arc_legitimize_address_0 (rtx, rtx, machine_mode mode);
526b7aee
SV
450
451static void arc_finalize_pic (void);
452
453/* initialize the GCC target structure. */
454#undef TARGET_COMP_TYPE_ATTRIBUTES
455#define TARGET_COMP_TYPE_ATTRIBUTES arc_comp_type_attributes
456#undef TARGET_ASM_FILE_START
457#define TARGET_ASM_FILE_START arc_file_start
458#undef TARGET_ATTRIBUTE_TABLE
459#define TARGET_ATTRIBUTE_TABLE arc_attribute_table
460#undef TARGET_ASM_INTERNAL_LABEL
461#define TARGET_ASM_INTERNAL_LABEL arc_internal_label
462#undef TARGET_RTX_COSTS
463#define TARGET_RTX_COSTS arc_rtx_costs
464#undef TARGET_ADDRESS_COST
465#define TARGET_ADDRESS_COST arc_address_cost
466
467#undef TARGET_ENCODE_SECTION_INFO
468#define TARGET_ENCODE_SECTION_INFO arc_encode_section_info
469
470#undef TARGET_CANNOT_FORCE_CONST_MEM
471#define TARGET_CANNOT_FORCE_CONST_MEM arc_cannot_force_const_mem
472
473#undef TARGET_INIT_BUILTINS
474#define TARGET_INIT_BUILTINS arc_init_builtins
475
476#undef TARGET_EXPAND_BUILTIN
477#define TARGET_EXPAND_BUILTIN arc_expand_builtin
478
479#undef TARGET_ASM_OUTPUT_MI_THUNK
480#define TARGET_ASM_OUTPUT_MI_THUNK arc_output_mi_thunk
481
482#undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
483#define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
484
485#undef TARGET_FUNCTION_OK_FOR_SIBCALL
486#define TARGET_FUNCTION_OK_FOR_SIBCALL arc_function_ok_for_sibcall
487
488#undef TARGET_MACHINE_DEPENDENT_REORG
489#define TARGET_MACHINE_DEPENDENT_REORG arc_reorg
490
491#undef TARGET_IN_SMALL_DATA_P
492#define TARGET_IN_SMALL_DATA_P arc_in_small_data_p
493
494#undef TARGET_PROMOTE_FUNCTION_MODE
495#define TARGET_PROMOTE_FUNCTION_MODE \
496 default_promote_function_mode_always_promote
497
498#undef TARGET_PROMOTE_PROTOTYPES
499#define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
500
501#undef TARGET_RETURN_IN_MEMORY
502#define TARGET_RETURN_IN_MEMORY arc_return_in_memory
503#undef TARGET_PASS_BY_REFERENCE
504#define TARGET_PASS_BY_REFERENCE arc_pass_by_reference
505
506#undef TARGET_SETUP_INCOMING_VARARGS
507#define TARGET_SETUP_INCOMING_VARARGS arc_setup_incoming_varargs
508
509#undef TARGET_ARG_PARTIAL_BYTES
510#define TARGET_ARG_PARTIAL_BYTES arc_arg_partial_bytes
511
512#undef TARGET_MUST_PASS_IN_STACK
513#define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
514
515#undef TARGET_FUNCTION_VALUE
516#define TARGET_FUNCTION_VALUE arc_function_value
517
518#undef TARGET_SCHED_ADJUST_PRIORITY
519#define TARGET_SCHED_ADJUST_PRIORITY arc_sched_adjust_priority
520
521#undef TARGET_VECTOR_MODE_SUPPORTED_P
522#define TARGET_VECTOR_MODE_SUPPORTED_P arc_vector_mode_supported_p
523
1d0216c8
RS
524#undef TARGET_CAN_USE_DOLOOP_P
525#define TARGET_CAN_USE_DOLOOP_P arc_can_use_doloop_p
526
526b7aee
SV
527#undef TARGET_INVALID_WITHIN_DOLOOP
528#define TARGET_INVALID_WITHIN_DOLOOP arc_invalid_within_doloop
529
530#undef TARGET_PRESERVE_RELOAD_P
531#define TARGET_PRESERVE_RELOAD_P arc_preserve_reload_p
532
533#undef TARGET_CAN_FOLLOW_JUMP
534#define TARGET_CAN_FOLLOW_JUMP arc_can_follow_jump
535
536#undef TARGET_DELEGITIMIZE_ADDRESS
537#define TARGET_DELEGITIMIZE_ADDRESS arc_delegitimize_address
538
ad23f5d4
JG
539#undef TARGET_USE_BY_PIECES_INFRASTRUCTURE_P
540#define TARGET_USE_BY_PIECES_INFRASTRUCTURE_P \
541 arc_use_by_pieces_infrastructure_p
542
526b7aee
SV
543/* Usually, we will be able to scale anchor offsets.
544 When this fails, we want LEGITIMIZE_ADDRESS to kick in. */
545#undef TARGET_MIN_ANCHOR_OFFSET
546#define TARGET_MIN_ANCHOR_OFFSET (-1024)
547#undef TARGET_MAX_ANCHOR_OFFSET
548#define TARGET_MAX_ANCHOR_OFFSET (1020)
549
550#undef TARGET_SECONDARY_RELOAD
551#define TARGET_SECONDARY_RELOAD arc_secondary_reload
552
553#define TARGET_OPTION_OVERRIDE arc_override_options
554
555#define TARGET_CONDITIONAL_REGISTER_USAGE arc_conditional_register_usage
556
557#define TARGET_TRAMPOLINE_INIT arc_initialize_trampoline
558
559#define TARGET_TRAMPOLINE_ADJUST_ADDRESS arc_trampoline_adjust_address
560
561#define TARGET_CAN_ELIMINATE arc_can_eliminate
562
563#define TARGET_FRAME_POINTER_REQUIRED arc_frame_pointer_required
564
565#define TARGET_FUNCTION_ARG arc_function_arg
566
567#define TARGET_FUNCTION_ARG_ADVANCE arc_function_arg_advance
568
569#define TARGET_LEGITIMATE_CONSTANT_P arc_legitimate_constant_p
570
571#define TARGET_LEGITIMATE_ADDRESS_P arc_legitimate_address_p
572
573#define TARGET_MODE_DEPENDENT_ADDRESS_P arc_mode_dependent_address_p
574
575#define TARGET_LEGITIMIZE_ADDRESS arc_legitimize_address
576
577#define TARGET_ADJUST_INSN_LENGTH arc_adjust_insn_length
578
579#define TARGET_INSN_LENGTH_PARAMETERS arc_insn_length_parameters
580
53c8d5a7 581#undef TARGET_LRA_P
526b7aee
SV
582#define TARGET_LRA_P arc_lra_p
583#define TARGET_REGISTER_PRIORITY arc_register_priority
584/* Stores with scaled offsets have different displacement ranges. */
585#define TARGET_DIFFERENT_ADDR_DISPLACEMENT_P hook_bool_void_true
586#define TARGET_SPILL_CLASS arc_spill_class
587
588#include "target-def.h"
589
590#undef TARGET_ASM_ALIGNED_HI_OP
591#define TARGET_ASM_ALIGNED_HI_OP "\t.hword\t"
592#undef TARGET_ASM_ALIGNED_SI_OP
593#define TARGET_ASM_ALIGNED_SI_OP "\t.word\t"
594
595/* Try to keep the (mov:DF _, reg) as early as possible so
596 that the d<add/sub/mul>h-lr insns appear together and can
597 use the peephole2 pattern. */
598
599static int
ac44248e 600arc_sched_adjust_priority (rtx_insn *insn, int priority)
526b7aee
SV
601{
602 rtx set = single_set (insn);
603 if (set
604 && GET_MODE (SET_SRC(set)) == DFmode
605 && GET_CODE (SET_SRC(set)) == REG)
606 {
607 /* Incrementing priority by 20 (empirically derived). */
608 return priority + 20;
609 }
610
611 return priority;
612}
613
614static reg_class_t
ef4bddc2 615arc_secondary_reload (bool in_p, rtx x, reg_class_t cl, machine_mode,
526b7aee
SV
616 secondary_reload_info *)
617{
618 if (cl == DOUBLE_REGS)
619 return GENERAL_REGS;
620
621 /* The loop counter register can be stored, but not loaded directly. */
622 if ((cl == LPCOUNT_REG || cl == WRITABLE_CORE_REGS)
623 && in_p && MEM_P (x))
624 return GENERAL_REGS;
625 return NO_REGS;
626}
627
628static unsigned arc_ifcvt (void);
629
630namespace {
631
632const pass_data pass_data_arc_ifcvt =
633{
634 RTL_PASS,
635 "arc_ifcvt", /* name */
636 OPTGROUP_NONE, /* optinfo_flags */
526b7aee
SV
637 TV_IFCVT2, /* tv_id */
638 0, /* properties_required */
639 0, /* properties_provided */
640 0, /* properties_destroyed */
641 0, /* todo_flags_start */
642 TODO_df_finish /* todo_flags_finish */
643};
644
645class pass_arc_ifcvt : public rtl_opt_pass
646{
647public:
648 pass_arc_ifcvt(gcc::context *ctxt)
649 : rtl_opt_pass(pass_data_arc_ifcvt, ctxt)
650 {}
651
652 /* opt_pass methods: */
cd4dd8f0 653 opt_pass * clone () { return new pass_arc_ifcvt (m_ctxt); }
be55bfe6 654 virtual unsigned int execute (function *) { return arc_ifcvt (); }
526b7aee
SV
655};
656
657} // anon namespace
658
659rtl_opt_pass *
660make_pass_arc_ifcvt (gcc::context *ctxt)
661{
662 return new pass_arc_ifcvt (ctxt);
663}
664
0bc69b81
JR
665static unsigned arc_predicate_delay_insns (void);
666
667namespace {
668
669const pass_data pass_data_arc_predicate_delay_insns =
670{
671 RTL_PASS,
672 "arc_predicate_delay_insns", /* name */
673 OPTGROUP_NONE, /* optinfo_flags */
0bc69b81
JR
674 TV_IFCVT2, /* tv_id */
675 0, /* properties_required */
676 0, /* properties_provided */
677 0, /* properties_destroyed */
678 0, /* todo_flags_start */
679 TODO_df_finish /* todo_flags_finish */
680};
681
682class pass_arc_predicate_delay_insns : public rtl_opt_pass
683{
684public:
685 pass_arc_predicate_delay_insns(gcc::context *ctxt)
686 : rtl_opt_pass(pass_data_arc_predicate_delay_insns, ctxt)
687 {}
688
689 /* opt_pass methods: */
be55bfe6
TS
690 virtual unsigned int execute (function *)
691 {
692 return arc_predicate_delay_insns ();
693 }
0bc69b81
JR
694};
695
696} // anon namespace
697
698rtl_opt_pass *
699make_pass_arc_predicate_delay_insns (gcc::context *ctxt)
700{
701 return new pass_arc_predicate_delay_insns (ctxt);
702}
703
526b7aee
SV
704/* Called by OVERRIDE_OPTIONS to initialize various things. */
705
706void
707arc_init (void)
708{
709 enum attr_tune tune_dflt = TUNE_NONE;
710
711 if (TARGET_A5)
712 {
713 arc_cpu_string = "A5";
714 }
715 else if (TARGET_ARC600)
716 {
717 arc_cpu_string = "ARC600";
718 tune_dflt = TUNE_ARC600;
719 }
720 else if (TARGET_ARC601)
721 {
722 arc_cpu_string = "ARC601";
723 tune_dflt = TUNE_ARC600;
724 }
725 else if (TARGET_ARC700)
726 {
727 arc_cpu_string = "ARC700";
728 tune_dflt = TUNE_ARC700_4_2_STD;
729 }
730 else
731 gcc_unreachable ();
732 if (arc_tune == TUNE_NONE)
733 arc_tune = tune_dflt;
734 /* Note: arc_multcost is only used in rtx_cost if speed is true. */
735 if (arc_multcost < 0)
736 switch (arc_tune)
737 {
738 case TUNE_ARC700_4_2_STD:
739 /* latency 7;
740 max throughput (1 multiply + 4 other insns) / 5 cycles. */
741 arc_multcost = COSTS_N_INSNS (4);
742 if (TARGET_NOMPY_SET)
743 arc_multcost = COSTS_N_INSNS (30);
744 break;
745 case TUNE_ARC700_4_2_XMAC:
746 /* latency 5;
747 max throughput (1 multiply + 2 other insns) / 3 cycles. */
748 arc_multcost = COSTS_N_INSNS (3);
749 if (TARGET_NOMPY_SET)
750 arc_multcost = COSTS_N_INSNS (30);
751 break;
752 case TUNE_ARC600:
753 if (TARGET_MUL64_SET)
754 {
755 arc_multcost = COSTS_N_INSNS (4);
756 break;
757 }
758 /* Fall through. */
759 default:
760 arc_multcost = COSTS_N_INSNS (30);
761 break;
762 }
763
764 /* Support mul64 generation only for A5 and ARC600. */
765 if (TARGET_MUL64_SET && TARGET_ARC700)
766 error ("-mmul64 not supported for ARC700");
767
768 /* MPY instructions valid only for ARC700. */
769 if (TARGET_NOMPY_SET && !TARGET_ARC700)
770 error ("-mno-mpy supported only for ARC700");
771
772 /* mul/mac instructions only for ARC600. */
773 if (TARGET_MULMAC_32BY16_SET && !(TARGET_ARC600 || TARGET_ARC601))
774 error ("-mmul32x16 supported only for ARC600 or ARC601");
775
776 if (!TARGET_DPFP && TARGET_DPFP_DISABLE_LRSR)
2236746b 777 error ("-mno-dpfp-lrsr supported only with -mdpfp");
526b7aee
SV
778
779 /* FPX-1. No fast and compact together. */
780 if ((TARGET_DPFP_FAST_SET && TARGET_DPFP_COMPACT_SET)
781 || (TARGET_SPFP_FAST_SET && TARGET_SPFP_COMPACT_SET))
782 error ("FPX fast and compact options cannot be specified together");
783
784 /* FPX-2. No fast-spfp for arc600 or arc601. */
785 if (TARGET_SPFP_FAST_SET && (TARGET_ARC600 || TARGET_ARC601))
786 error ("-mspfp_fast not available on ARC600 or ARC601");
787
788 /* FPX-3. No FPX extensions on pre-ARC600 cores. */
789 if ((TARGET_DPFP || TARGET_SPFP)
790 && !(TARGET_ARC600 || TARGET_ARC601 || TARGET_ARC700))
791 error ("FPX extensions not available on pre-ARC600 cores");
792
793 /* Warn for unimplemented PIC in pre-ARC700 cores, and disable flag_pic. */
794 if (flag_pic && !TARGET_ARC700)
795 {
796 warning (DK_WARNING, "PIC is not supported for %s. Generating non-PIC code only..", arc_cpu_string);
797 flag_pic = 0;
798 }
799
800 arc_init_reg_tables ();
801
802 /* Initialize array for PRINT_OPERAND_PUNCT_VALID_P. */
803 memset (arc_punct_chars, 0, sizeof (arc_punct_chars));
804 arc_punct_chars['#'] = 1;
805 arc_punct_chars['*'] = 1;
806 arc_punct_chars['?'] = 1;
807 arc_punct_chars['!'] = 1;
808 arc_punct_chars['^'] = 1;
809 arc_punct_chars['&'] = 1;
810
811 if (optimize > 1 && !TARGET_NO_COND_EXEC)
812 {
813 /* There are two target-independent ifcvt passes, and arc_reorg may do
814 one or more arc_ifcvt calls. */
815 opt_pass *pass_arc_ifcvt_4 = make_pass_arc_ifcvt (g);
816 struct register_pass_info arc_ifcvt4_info
817 = { pass_arc_ifcvt_4, "dbr", 1, PASS_POS_INSERT_AFTER };
818 struct register_pass_info arc_ifcvt5_info
819 = { pass_arc_ifcvt_4->clone (), "shorten", 1, PASS_POS_INSERT_BEFORE };
820
821 register_pass (&arc_ifcvt4_info);
822 register_pass (&arc_ifcvt5_info);
823 }
0bc69b81
JR
824
825 if (flag_delayed_branch)
826 {
827 opt_pass *pass_arc_predicate_delay_insns
828 = make_pass_arc_predicate_delay_insns (g);
829 struct register_pass_info arc_predicate_delay_info
830 = { pass_arc_predicate_delay_insns, "dbr", 1, PASS_POS_INSERT_AFTER };
831
832 register_pass (&arc_predicate_delay_info);
833 }
526b7aee
SV
834}
835
836/* Check ARC options, generate derived target attributes. */
837
838static void
839arc_override_options (void)
840{
841 if (arc_cpu == PROCESSOR_NONE)
842 arc_cpu = PROCESSOR_ARC700;
843
844 if (arc_size_opt_level == 3)
845 optimize_size = 1;
846
847 if (flag_pic)
848 target_flags |= MASK_NO_SDATA_SET;
849
850 if (flag_no_common == 255)
851 flag_no_common = !TARGET_NO_SDATA_SET;
852
853 /* TARGET_COMPACT_CASESI needs the "q" register class. */ \
854 if (TARGET_MIXED_CODE)
855 TARGET_Q_CLASS = 1;
856 if (!TARGET_Q_CLASS)
857 TARGET_COMPACT_CASESI = 0;
858 if (TARGET_COMPACT_CASESI)
859 TARGET_CASE_VECTOR_PC_RELATIVE = 1;
860
861 /* These need to be done at start up. It's convenient to do them here. */
862 arc_init ();
863}
864
865/* The condition codes of the ARC, and the inverse function. */
866/* For short branches, the "c" / "nc" names are not defined in the ARC
867 Programmers manual, so we have to use "lo" / "hs"" instead. */
868static const char *arc_condition_codes[] =
869{
870 "al", 0, "eq", "ne", "p", "n", "lo", "hs", "v", "nv",
871 "gt", "le", "ge", "lt", "hi", "ls", "pnz", 0
872};
873
874enum arc_cc_code_index
875{
876 ARC_CC_AL, ARC_CC_EQ = ARC_CC_AL+2, ARC_CC_NE, ARC_CC_P, ARC_CC_N,
877 ARC_CC_C, ARC_CC_NC, ARC_CC_V, ARC_CC_NV,
878 ARC_CC_GT, ARC_CC_LE, ARC_CC_GE, ARC_CC_LT, ARC_CC_HI, ARC_CC_LS, ARC_CC_PNZ,
879 ARC_CC_LO = ARC_CC_C, ARC_CC_HS = ARC_CC_NC
880};
881
882#define ARC_INVERSE_CONDITION_CODE(X) ((X) ^ 1)
883
884/* Returns the index of the ARC condition code string in
885 `arc_condition_codes'. COMPARISON should be an rtx like
886 `(eq (...) (...))'. */
887
888static int
889get_arc_condition_code (rtx comparison)
890{
891 switch (GET_MODE (XEXP (comparison, 0)))
892 {
893 case CCmode:
894 case SImode: /* For BRcc. */
895 switch (GET_CODE (comparison))
896 {
897 case EQ : return ARC_CC_EQ;
898 case NE : return ARC_CC_NE;
899 case GT : return ARC_CC_GT;
900 case LE : return ARC_CC_LE;
901 case GE : return ARC_CC_GE;
902 case LT : return ARC_CC_LT;
903 case GTU : return ARC_CC_HI;
904 case LEU : return ARC_CC_LS;
905 case LTU : return ARC_CC_LO;
906 case GEU : return ARC_CC_HS;
907 default : gcc_unreachable ();
908 }
909 case CC_ZNmode:
910 switch (GET_CODE (comparison))
911 {
912 case EQ : return ARC_CC_EQ;
913 case NE : return ARC_CC_NE;
914 case GE: return ARC_CC_P;
915 case LT: return ARC_CC_N;
916 case GT : return ARC_CC_PNZ;
917 default : gcc_unreachable ();
918 }
919 case CC_Zmode:
920 switch (GET_CODE (comparison))
921 {
922 case EQ : return ARC_CC_EQ;
923 case NE : return ARC_CC_NE;
924 default : gcc_unreachable ();
925 }
926 case CC_Cmode:
927 switch (GET_CODE (comparison))
928 {
929 case LTU : return ARC_CC_C;
930 case GEU : return ARC_CC_NC;
931 default : gcc_unreachable ();
932 }
933 case CC_FP_GTmode:
934 if (TARGET_ARGONAUT_SET && TARGET_SPFP)
935 switch (GET_CODE (comparison))
936 {
937 case GT : return ARC_CC_N;
938 case UNLE: return ARC_CC_P;
939 default : gcc_unreachable ();
940 }
941 else
942 switch (GET_CODE (comparison))
943 {
944 case GT : return ARC_CC_HI;
945 case UNLE : return ARC_CC_LS;
946 default : gcc_unreachable ();
947 }
948 case CC_FP_GEmode:
949 /* Same for FPX and non-FPX. */
950 switch (GET_CODE (comparison))
951 {
952 case GE : return ARC_CC_HS;
953 case UNLT : return ARC_CC_LO;
954 default : gcc_unreachable ();
955 }
956 case CC_FP_UNEQmode:
957 switch (GET_CODE (comparison))
958 {
959 case UNEQ : return ARC_CC_EQ;
960 case LTGT : return ARC_CC_NE;
961 default : gcc_unreachable ();
962 }
963 case CC_FP_ORDmode:
964 switch (GET_CODE (comparison))
965 {
966 case UNORDERED : return ARC_CC_C;
967 case ORDERED : return ARC_CC_NC;
968 default : gcc_unreachable ();
969 }
970 case CC_FPXmode:
971 switch (GET_CODE (comparison))
972 {
973 case EQ : return ARC_CC_EQ;
974 case NE : return ARC_CC_NE;
975 case UNORDERED : return ARC_CC_C;
976 case ORDERED : return ARC_CC_NC;
977 case LTGT : return ARC_CC_HI;
978 case UNEQ : return ARC_CC_LS;
979 default : gcc_unreachable ();
980 }
981 default : gcc_unreachable ();
982 }
983 /*NOTREACHED*/
984 return (42);
985}
986
987/* Return true if COMPARISON has a short form that can accomodate OFFSET. */
988
989bool
990arc_short_comparison_p (rtx comparison, int offset)
991{
992 gcc_assert (ARC_CC_NC == ARC_CC_HS);
993 gcc_assert (ARC_CC_C == ARC_CC_LO);
994 switch (get_arc_condition_code (comparison))
995 {
996 case ARC_CC_EQ: case ARC_CC_NE:
997 return offset >= -512 && offset <= 506;
998 case ARC_CC_GT: case ARC_CC_LE: case ARC_CC_GE: case ARC_CC_LT:
999 case ARC_CC_HI: case ARC_CC_LS: case ARC_CC_LO: case ARC_CC_HS:
1000 return offset >= -64 && offset <= 58;
1001 default:
1002 return false;
1003 }
1004}
1005
1006/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
1007 return the mode to be used for the comparison. */
1008
ef4bddc2 1009machine_mode
526b7aee
SV
1010arc_select_cc_mode (enum rtx_code op, rtx x, rtx y)
1011{
ef4bddc2 1012 machine_mode mode = GET_MODE (x);
526b7aee
SV
1013 rtx x1;
1014
1015 /* For an operation that sets the condition codes as a side-effect, the
1016 C and V flags is not set as for cmp, so we can only use comparisons where
1017 this doesn't matter. (For LT and GE we can use "mi" and "pl"
1018 instead.) */
1019 /* ??? We could use "pnz" for greater than zero, however, we could then
1020 get into trouble because the comparison could not be reversed. */
1021 if (GET_MODE_CLASS (mode) == MODE_INT
1022 && y == const0_rtx
1023 && (op == EQ || op == NE
486c559b 1024 || ((op == LT || op == GE) && GET_MODE_SIZE (GET_MODE (x)) <= 4)))
526b7aee
SV
1025 return CC_ZNmode;
1026
1027 /* add.f for if (a+b) */
1028 if (mode == SImode
1029 && GET_CODE (y) == NEG
1030 && (op == EQ || op == NE))
1031 return CC_ZNmode;
1032
1033 /* Check if this is a test suitable for bxor.f . */
1034 if (mode == SImode && (op == EQ || op == NE) && CONST_INT_P (y)
1035 && ((INTVAL (y) - 1) & INTVAL (y)) == 0
1036 && INTVAL (y))
1037 return CC_Zmode;
1038
1039 /* Check if this is a test suitable for add / bmsk.f . */
1040 if (mode == SImode && (op == EQ || op == NE) && CONST_INT_P (y)
1041 && GET_CODE (x) == AND && CONST_INT_P ((x1 = XEXP (x, 1)))
1042 && ((INTVAL (x1) + 1) & INTVAL (x1)) == 0
1043 && (~INTVAL (x1) | INTVAL (y)) < 0
1044 && (~INTVAL (x1) | INTVAL (y)) > -0x800)
1045 return CC_Zmode;
1046
1047 if (GET_MODE (x) == SImode && (op == LTU || op == GEU)
1048 && GET_CODE (x) == PLUS
1049 && (rtx_equal_p (XEXP (x, 0), y) || rtx_equal_p (XEXP (x, 1), y)))
1050 return CC_Cmode;
1051
1052 if (TARGET_ARGONAUT_SET
1053 && ((mode == SFmode && TARGET_SPFP) || (mode == DFmode && TARGET_DPFP)))
1054 switch (op)
1055 {
1056 case EQ: case NE: case UNEQ: case LTGT: case ORDERED: case UNORDERED:
1057 return CC_FPXmode;
1058 case LT: case UNGE: case GT: case UNLE:
1059 return CC_FP_GTmode;
1060 case LE: case UNGT: case GE: case UNLT:
1061 return CC_FP_GEmode;
1062 default: gcc_unreachable ();
1063 }
1064 else if (GET_MODE_CLASS (mode) == MODE_FLOAT && TARGET_OPTFPE)
1065 switch (op)
1066 {
1067 case EQ: case NE: return CC_Zmode;
1068 case LT: case UNGE:
1069 case GT: case UNLE: return CC_FP_GTmode;
1070 case LE: case UNGT:
1071 case GE: case UNLT: return CC_FP_GEmode;
1072 case UNEQ: case LTGT: return CC_FP_UNEQmode;
1073 case ORDERED: case UNORDERED: return CC_FP_ORDmode;
1074 default: gcc_unreachable ();
1075 }
1076
1077 return CCmode;
1078}
1079
1080/* Vectors to keep interesting information about registers where it can easily
1081 be got. We use to use the actual mode value as the bit number, but there
1082 is (or may be) more than 32 modes now. Instead we use two tables: one
1083 indexed by hard register number, and one indexed by mode. */
1084
1085/* The purpose of arc_mode_class is to shrink the range of modes so that
1086 they all fit (as bit numbers) in a 32-bit word (again). Each real mode is
1087 mapped into one arc_mode_class mode. */
1088
1089enum arc_mode_class {
1090 C_MODE,
1091 S_MODE, D_MODE, T_MODE, O_MODE,
1092 SF_MODE, DF_MODE, TF_MODE, OF_MODE,
1093 V_MODE
1094};
1095
1096/* Modes for condition codes. */
1097#define C_MODES (1 << (int) C_MODE)
1098
1099/* Modes for single-word and smaller quantities. */
1100#define S_MODES ((1 << (int) S_MODE) | (1 << (int) SF_MODE))
1101
1102/* Modes for double-word and smaller quantities. */
1103#define D_MODES (S_MODES | (1 << (int) D_MODE) | (1 << DF_MODE))
1104
1105/* Mode for 8-byte DF values only. */
1106#define DF_MODES (1 << DF_MODE)
1107
1108/* Modes for quad-word and smaller quantities. */
1109#define T_MODES (D_MODES | (1 << (int) T_MODE) | (1 << (int) TF_MODE))
1110
1111/* Modes for 128-bit vectors. */
1112#define V_MODES (1 << (int) V_MODE)
1113
1114/* Value is 1 if register/mode pair is acceptable on arc. */
1115
1116unsigned int arc_hard_regno_mode_ok[] = {
1117 T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES,
1118 T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES,
1119 T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, T_MODES, D_MODES,
1120 D_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
1121
1122 /* ??? Leave these as S_MODES for now. */
1123 S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
1124 DF_MODES, 0, DF_MODES, 0, S_MODES, S_MODES, S_MODES, S_MODES,
1125 S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
1126 S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, C_MODES, S_MODES,
1127
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 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1132
1133 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1134 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1135 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1136 V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES, V_MODES,
1137
1138 S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES,
1139 S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES, S_MODES
1140};
1141
1142unsigned int arc_mode_class [NUM_MACHINE_MODES];
1143
1144enum reg_class arc_regno_reg_class[FIRST_PSEUDO_REGISTER];
1145
1146enum reg_class
1147arc_preferred_reload_class (rtx, enum reg_class cl)
1148{
1149 if ((cl) == CHEAP_CORE_REGS || (cl) == WRITABLE_CORE_REGS)
1150 return GENERAL_REGS;
1151 return cl;
1152}
1153
1154/* Initialize the arc_mode_class array. */
1155
1156static void
1157arc_init_reg_tables (void)
1158{
1159 int i;
1160
1161 for (i = 0; i < NUM_MACHINE_MODES; i++)
1162 {
ef4bddc2 1163 machine_mode m = (machine_mode) i;
f8d91e80
NC
1164
1165 switch (GET_MODE_CLASS (m))
526b7aee
SV
1166 {
1167 case MODE_INT:
1168 case MODE_PARTIAL_INT:
1169 case MODE_COMPLEX_INT:
f8d91e80 1170 if (GET_MODE_SIZE (m) <= 4)
526b7aee 1171 arc_mode_class[i] = 1 << (int) S_MODE;
f8d91e80 1172 else if (GET_MODE_SIZE (m) == 8)
526b7aee 1173 arc_mode_class[i] = 1 << (int) D_MODE;
f8d91e80 1174 else if (GET_MODE_SIZE (m) == 16)
526b7aee 1175 arc_mode_class[i] = 1 << (int) T_MODE;
f8d91e80 1176 else if (GET_MODE_SIZE (m) == 32)
526b7aee
SV
1177 arc_mode_class[i] = 1 << (int) O_MODE;
1178 else
1179 arc_mode_class[i] = 0;
1180 break;
1181 case MODE_FLOAT:
1182 case MODE_COMPLEX_FLOAT:
f8d91e80 1183 if (GET_MODE_SIZE (m) <= 4)
526b7aee 1184 arc_mode_class[i] = 1 << (int) SF_MODE;
f8d91e80 1185 else if (GET_MODE_SIZE (m) == 8)
526b7aee 1186 arc_mode_class[i] = 1 << (int) DF_MODE;
f8d91e80 1187 else if (GET_MODE_SIZE (m) == 16)
526b7aee 1188 arc_mode_class[i] = 1 << (int) TF_MODE;
f8d91e80 1189 else if (GET_MODE_SIZE (m) == 32)
526b7aee
SV
1190 arc_mode_class[i] = 1 << (int) OF_MODE;
1191 else
1192 arc_mode_class[i] = 0;
1193 break;
1194 case MODE_VECTOR_INT:
1195 arc_mode_class [i] = (1<< (int) V_MODE);
1196 break;
1197 case MODE_CC:
1198 default:
1199 /* mode_class hasn't been initialized yet for EXTRA_CC_MODES, so
1200 we must explicitly check for them here. */
1201 if (i == (int) CCmode || i == (int) CC_ZNmode || i == (int) CC_Zmode
1202 || i == (int) CC_Cmode
1203 || i == CC_FP_GTmode || i == CC_FP_GEmode || i == CC_FP_ORDmode)
1204 arc_mode_class[i] = 1 << (int) C_MODE;
1205 else
1206 arc_mode_class[i] = 0;
1207 break;
1208 }
1209 }
1210}
1211
1212/* Core registers 56..59 are used for multiply extension options.
1213 The dsp option uses r56 and r57, these are then named acc1 and acc2.
1214 acc1 is the highpart, and acc2 the lowpart, so which register gets which
1215 number depends on endianness.
1216 The mul64 multiplier options use r57 for mlo, r58 for mmid and r59 for mhi.
1217 Because mlo / mhi form a 64 bit value, we use different gcc internal
1218 register numbers to make them form a register pair as the gcc internals
1219 know it. mmid gets number 57, if still available, and mlo / mhi get
1220 number 58 and 59, depending on endianness. We use DBX_REGISTER_NUMBER
1221 to map this back. */
1222 char rname56[5] = "r56";
1223 char rname57[5] = "r57";
1224 char rname58[5] = "r58";
1225 char rname59[5] = "r59";
1226
1227static void
1228arc_conditional_register_usage (void)
1229{
1230 int regno;
1231 int i;
1232 int fix_start = 60, fix_end = 55;
1233
1234 if (TARGET_MUL64_SET)
1235 {
1236 fix_start = 57;
1237 fix_end = 59;
1238
1239 /* We don't provide a name for mmed. In rtl / assembly resource lists,
1240 you are supposed to refer to it as mlo & mhi, e.g
1241 (zero_extract:SI (reg:DI 58) (const_int 32) (16)) .
1242 In an actual asm instruction, you are of course use mmed.
1243 The point of avoiding having a separate register for mmed is that
1244 this way, we don't have to carry clobbers of that reg around in every
1245 isntruction that modifies mlo and/or mhi. */
1246 strcpy (rname57, "");
1247 strcpy (rname58, TARGET_BIG_ENDIAN ? "mhi" : "mlo");
1248 strcpy (rname59, TARGET_BIG_ENDIAN ? "mlo" : "mhi");
1249 }
1250 if (TARGET_MULMAC_32BY16_SET)
1251 {
1252 fix_start = 56;
1253 fix_end = fix_end > 57 ? fix_end : 57;
1254 strcpy (rname56, TARGET_BIG_ENDIAN ? "acc1" : "acc2");
1255 strcpy (rname57, TARGET_BIG_ENDIAN ? "acc2" : "acc1");
1256 }
1257 for (regno = fix_start; regno <= fix_end; regno++)
1258 {
1259 if (!fixed_regs[regno])
1260 warning (0, "multiply option implies r%d is fixed", regno);
1261 fixed_regs [regno] = call_used_regs[regno] = 1;
1262 }
1263 if (TARGET_Q_CLASS)
1264 {
1265 reg_alloc_order[2] = 12;
1266 reg_alloc_order[3] = 13;
1267 reg_alloc_order[4] = 14;
1268 reg_alloc_order[5] = 15;
1269 reg_alloc_order[6] = 1;
1270 reg_alloc_order[7] = 0;
1271 reg_alloc_order[8] = 4;
1272 reg_alloc_order[9] = 5;
1273 reg_alloc_order[10] = 6;
1274 reg_alloc_order[11] = 7;
1275 reg_alloc_order[12] = 8;
1276 reg_alloc_order[13] = 9;
1277 reg_alloc_order[14] = 10;
1278 reg_alloc_order[15] = 11;
1279 }
1280 if (TARGET_SIMD_SET)
1281 {
1282 int i;
6462fab0
JR
1283 for (i = ARC_FIRST_SIMD_VR_REG; i <= ARC_LAST_SIMD_VR_REG; i++)
1284 reg_alloc_order [i] = i;
1285 for (i = ARC_FIRST_SIMD_DMA_CONFIG_REG;
1286 i <= ARC_LAST_SIMD_DMA_CONFIG_REG; i++)
526b7aee
SV
1287 reg_alloc_order [i] = i;
1288 }
1289 /* For Arctangent-A5 / ARC600, lp_count may not be read in an instruction
1290 following immediately after another one setting it to a new value.
1291 There was some discussion on how to enforce scheduling constraints for
1292 processors with missing interlocks on the gcc mailing list:
1293 http://gcc.gnu.org/ml/gcc/2008-05/msg00021.html .
1294 However, we can't actually use this approach, because for ARC the
1295 delay slot scheduling pass is active, which runs after
1296 machine_dependent_reorg. */
1297 if (TARGET_ARC600)
1298 CLEAR_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], LP_COUNT);
1299 else if (!TARGET_ARC700)
1300 fixed_regs[LP_COUNT] = 1;
1301 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
1302 if (!call_used_regs[regno])
1303 CLEAR_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], regno);
1304 for (regno = 32; regno < 60; regno++)
1305 if (!fixed_regs[regno])
1306 SET_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS], regno);
1307 if (TARGET_ARC700)
1308 {
1309 for (regno = 32; regno <= 60; regno++)
1310 CLEAR_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], regno);
1311
1312 /* If they have used -ffixed-lp_count, make sure it takes
1313 effect. */
1314 if (fixed_regs[LP_COUNT])
1315 {
1316 CLEAR_HARD_REG_BIT (reg_class_contents[LPCOUNT_REG], LP_COUNT);
1317 CLEAR_HARD_REG_BIT (reg_class_contents[SIBCALL_REGS], LP_COUNT);
1318 CLEAR_HARD_REG_BIT (reg_class_contents[WRITABLE_CORE_REGS], LP_COUNT);
1319
1320 /* Instead of taking out SF_MODE like below, forbid it outright. */
1321 arc_hard_regno_mode_ok[60] = 0;
1322 }
1323 else
1324 arc_hard_regno_mode_ok[60] = 1 << (int) S_MODE;
1325 }
1326
1327 for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
1328 {
1329 if (i < 29)
1330 {
1331 if (TARGET_Q_CLASS && ((i <= 3) || ((i >= 12) && (i <= 15))))
1332 arc_regno_reg_class[i] = ARCOMPACT16_REGS;
1333 else
1334 arc_regno_reg_class[i] = GENERAL_REGS;
1335 }
1336 else if (i < 60)
1337 arc_regno_reg_class[i]
1338 = (fixed_regs[i]
1339 ? (TEST_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], i)
1340 ? CHEAP_CORE_REGS : ALL_CORE_REGS)
1341 : ((TARGET_ARC700
1342 && TEST_HARD_REG_BIT (reg_class_contents[CHEAP_CORE_REGS], i))
1343 ? CHEAP_CORE_REGS : WRITABLE_CORE_REGS));
1344 else
1345 arc_regno_reg_class[i] = NO_REGS;
1346 }
1347
1348 /* ARCOMPACT16_REGS is empty, if TARGET_Q_CLASS has not been activated. */
1349 if (!TARGET_Q_CLASS)
1350 {
1351 CLEAR_HARD_REG_SET(reg_class_contents [ARCOMPACT16_REGS]);
1352 CLEAR_HARD_REG_SET(reg_class_contents [AC16_BASE_REGS]);
1353 }
1354
1355 gcc_assert (FIRST_PSEUDO_REGISTER >= 144);
1356
1357 /* Handle Special Registers. */
1358 arc_regno_reg_class[29] = LINK_REGS; /* ilink1 register. */
1359 arc_regno_reg_class[30] = LINK_REGS; /* ilink2 register. */
1360 arc_regno_reg_class[31] = LINK_REGS; /* blink register. */
1361 arc_regno_reg_class[60] = LPCOUNT_REG;
1362 arc_regno_reg_class[61] = NO_REGS; /* CC_REG: must be NO_REGS. */
1363 arc_regno_reg_class[62] = GENERAL_REGS;
1364
1365 if (TARGET_DPFP)
1366 {
1367 for (i = 40; i < 44; ++i)
1368 {
1369 arc_regno_reg_class[i] = DOUBLE_REGS;
1370
1371 /* Unless they want us to do 'mov d1, 0x00000000' make sure
1372 no attempt is made to use such a register as a destination
1373 operand in *movdf_insn. */
1374 if (!TARGET_ARGONAUT_SET)
1375 {
1376 /* Make sure no 'c', 'w', 'W', or 'Rac' constraint is
1377 interpreted to mean they can use D1 or D2 in their insn. */
1378 CLEAR_HARD_REG_BIT(reg_class_contents[CHEAP_CORE_REGS ], i);
1379 CLEAR_HARD_REG_BIT(reg_class_contents[ALL_CORE_REGS ], i);
1380 CLEAR_HARD_REG_BIT(reg_class_contents[WRITABLE_CORE_REGS ], i);
1381 CLEAR_HARD_REG_BIT(reg_class_contents[MPY_WRITABLE_CORE_REGS], i);
1382 }
1383 }
1384 }
1385 else
1386 {
1387 /* Disable all DOUBLE_REGISTER settings,
1388 if not generating DPFP code. */
1389 arc_regno_reg_class[40] = ALL_REGS;
1390 arc_regno_reg_class[41] = ALL_REGS;
1391 arc_regno_reg_class[42] = ALL_REGS;
1392 arc_regno_reg_class[43] = ALL_REGS;
1393
1394 arc_hard_regno_mode_ok[40] = 0;
1395 arc_hard_regno_mode_ok[42] = 0;
1396
1397 CLEAR_HARD_REG_SET(reg_class_contents [DOUBLE_REGS]);
1398 }
1399
1400 if (TARGET_SIMD_SET)
1401 {
1402 gcc_assert (ARC_FIRST_SIMD_VR_REG == 64);
1403 gcc_assert (ARC_LAST_SIMD_VR_REG == 127);
1404
1405 for (i = ARC_FIRST_SIMD_VR_REG; i <= ARC_LAST_SIMD_VR_REG; i++)
1406 arc_regno_reg_class [i] = SIMD_VR_REGS;
1407
1408 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_REG == 128);
1409 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_IN_REG == 128);
1410 gcc_assert (ARC_FIRST_SIMD_DMA_CONFIG_OUT_REG == 136);
1411 gcc_assert (ARC_LAST_SIMD_DMA_CONFIG_REG == 143);
1412
1413 for (i = ARC_FIRST_SIMD_DMA_CONFIG_REG;
1414 i <= ARC_LAST_SIMD_DMA_CONFIG_REG; i++)
1415 arc_regno_reg_class [i] = SIMD_DMA_CONFIG_REGS;
1416 }
1417
1418 /* pc : r63 */
1419 arc_regno_reg_class[PROGRAM_COUNTER_REGNO] = GENERAL_REGS;
1420}
1421
1422/* Handle an "interrupt" attribute; arguments as in
1423 struct attribute_spec.handler. */
1424
1425static tree
1426arc_handle_interrupt_attribute (tree *, tree name, tree args, int,
1427 bool *no_add_attrs)
1428{
1429 gcc_assert (args);
1430
1431 tree value = TREE_VALUE (args);
1432
1433 if (TREE_CODE (value) != STRING_CST)
1434 {
1435 warning (OPT_Wattributes,
1436 "argument of %qE attribute is not a string constant",
1437 name);
1438 *no_add_attrs = true;
1439 }
1440 else if (strcmp (TREE_STRING_POINTER (value), "ilink1")
1441 && strcmp (TREE_STRING_POINTER (value), "ilink2"))
1442 {
1443 warning (OPT_Wattributes,
1444 "argument of %qE attribute is not \"ilink1\" or \"ilink2\"",
1445 name);
1446 *no_add_attrs = true;
1447 }
1448 return NULL_TREE;
1449}
1450
1451/* Return zero if TYPE1 and TYPE are incompatible, one if they are compatible,
1452 and two if they are nearly compatible (which causes a warning to be
1453 generated). */
1454
1455static int
1456arc_comp_type_attributes (const_tree type1,
1457 const_tree type2)
1458{
1459 int l1, l2, m1, m2, s1, s2;
1460
1461 /* Check for mismatch of non-default calling convention. */
1462 if (TREE_CODE (type1) != FUNCTION_TYPE)
1463 return 1;
1464
1465 /* Check for mismatched call attributes. */
1466 l1 = lookup_attribute ("long_call", TYPE_ATTRIBUTES (type1)) != NULL;
1467 l2 = lookup_attribute ("long_call", TYPE_ATTRIBUTES (type2)) != NULL;
1468 m1 = lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type1)) != NULL;
1469 m2 = lookup_attribute ("medium_call", TYPE_ATTRIBUTES (type2)) != NULL;
1470 s1 = lookup_attribute ("short_call", TYPE_ATTRIBUTES (type1)) != NULL;
1471 s2 = lookup_attribute ("short_call", TYPE_ATTRIBUTES (type2)) != NULL;
1472
1473 /* Only bother to check if an attribute is defined. */
1474 if (l1 | l2 | m1 | m2 | s1 | s2)
1475 {
1476 /* If one type has an attribute, the other must have the same attribute. */
1477 if ((l1 != l2) || (m1 != m2) || (s1 != s2))
1478 return 0;
1479
1480 /* Disallow mixed attributes. */
1481 if (l1 + m1 + s1 > 1)
1482 return 0;
1483 }
1484
1485
1486 return 1;
1487}
1488
1489/* Set the default attributes for TYPE. */
1490
1491void
1492arc_set_default_type_attributes (tree type ATTRIBUTE_UNUSED)
1493{
1494 gcc_unreachable();
1495}
1496
1497/* Misc. utilities. */
1498
1499/* X and Y are two things to compare using CODE. Emit the compare insn and
1500 return the rtx for the cc reg in the proper mode. */
1501
1502rtx
ef4bddc2 1503gen_compare_reg (rtx comparison, machine_mode omode)
526b7aee
SV
1504{
1505 enum rtx_code code = GET_CODE (comparison);
1506 rtx x = XEXP (comparison, 0);
1507 rtx y = XEXP (comparison, 1);
1508 rtx tmp, cc_reg;
ef4bddc2 1509 machine_mode mode, cmode;
526b7aee
SV
1510
1511
1512 cmode = GET_MODE (x);
1513 if (cmode == VOIDmode)
1514 cmode = GET_MODE (y);
1515 gcc_assert (cmode == SImode || cmode == SFmode || cmode == DFmode);
1516 if (cmode == SImode)
1517 {
1518 if (!register_operand (x, SImode))
1519 {
1520 if (register_operand (y, SImode))
1521 {
1522 tmp = x;
1523 x = y;
1524 y = tmp;
1525 code = swap_condition (code);
1526 }
1527 else
1528 x = copy_to_mode_reg (SImode, x);
1529 }
1530 if (GET_CODE (y) == SYMBOL_REF && flag_pic)
1531 y = copy_to_mode_reg (SImode, y);
1532 }
1533 else
1534 {
1535 x = force_reg (cmode, x);
1536 y = force_reg (cmode, y);
1537 }
1538 mode = SELECT_CC_MODE (code, x, y);
1539
1540 cc_reg = gen_rtx_REG (mode, CC_REG);
1541
1542 /* ??? FIXME (x-y)==0, as done by both cmpsfpx_raw and
1543 cmpdfpx_raw, is not a correct comparison for floats:
1544 http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
1545 */
1546 if (TARGET_ARGONAUT_SET
1547 && ((cmode == SFmode && TARGET_SPFP) || (cmode == DFmode && TARGET_DPFP)))
1548 {
1549 switch (code)
1550 {
1551 case NE: case EQ: case LT: case UNGE: case LE: case UNGT:
1552 case UNEQ: case LTGT: case ORDERED: case UNORDERED:
1553 break;
1554 case GT: case UNLE: case GE: case UNLT:
1555 code = swap_condition (code);
1556 tmp = x;
1557 x = y;
1558 y = tmp;
1559 break;
1560 default:
1561 gcc_unreachable ();
1562 }
1563 if (cmode == SFmode)
1564 {
1565 emit_insn (gen_cmpsfpx_raw (x, y));
1566 }
1567 else /* DFmode */
1568 {
1569 /* Accepts Dx regs directly by insns. */
1570 emit_insn (gen_cmpdfpx_raw (x, y));
1571 }
1572
1573 if (mode != CC_FPXmode)
f7df4a84 1574 emit_insn (gen_rtx_SET (cc_reg,
526b7aee
SV
1575 gen_rtx_COMPARE (mode,
1576 gen_rtx_REG (CC_FPXmode, 61),
1577 const0_rtx)));
1578 }
1579 else if (GET_MODE_CLASS (cmode) == MODE_FLOAT && TARGET_OPTFPE)
1580 {
1581 rtx op0 = gen_rtx_REG (cmode, 0);
1582 rtx op1 = gen_rtx_REG (cmode, GET_MODE_SIZE (cmode) / UNITS_PER_WORD);
1583
1584 switch (code)
1585 {
1586 case NE: case EQ: case GT: case UNLE: case GE: case UNLT:
1587 case UNEQ: case LTGT: case ORDERED: case UNORDERED:
1588 break;
1589 case LT: case UNGE: case LE: case UNGT:
1590 code = swap_condition (code);
1591 tmp = x;
1592 x = y;
1593 y = tmp;
1594 break;
1595 default:
1596 gcc_unreachable ();
1597 }
1598 if (currently_expanding_to_rtl)
1599 {
1600 emit_move_insn (op0, x);
1601 emit_move_insn (op1, y);
1602 }
1603 else
1604 {
1605 gcc_assert (rtx_equal_p (op0, x));
1606 gcc_assert (rtx_equal_p (op1, y));
1607 }
1608 emit_insn (gen_cmp_float (cc_reg, gen_rtx_COMPARE (mode, op0, op1)));
1609 }
1610 else
f7df4a84 1611 emit_insn (gen_rtx_SET (cc_reg, gen_rtx_COMPARE (mode, x, y)));
526b7aee
SV
1612 return gen_rtx_fmt_ee (code, omode, cc_reg, const0_rtx);
1613}
1614
1615/* Return true if VALUE, a const_double, will fit in a limm (4 byte number).
1616 We assume the value can be either signed or unsigned. */
1617
1618bool
1619arc_double_limm_p (rtx value)
1620{
1621 HOST_WIDE_INT low, high;
1622
1623 gcc_assert (GET_CODE (value) == CONST_DOUBLE);
1624
1625 if (TARGET_DPFP)
1626 return true;
1627
1628 low = CONST_DOUBLE_LOW (value);
1629 high = CONST_DOUBLE_HIGH (value);
1630
1631 if (low & 0x80000000)
1632 {
1633 return (((unsigned HOST_WIDE_INT) low <= 0xffffffff && high == 0)
1634 || (((low & - (unsigned HOST_WIDE_INT) 0x80000000)
1635 == - (unsigned HOST_WIDE_INT) 0x80000000)
1636 && high == -1));
1637 }
1638 else
1639 {
1640 return (unsigned HOST_WIDE_INT) low <= 0x7fffffff && high == 0;
1641 }
1642}
1643
1644/* Do any needed setup for a variadic function. For the ARC, we must
1645 create a register parameter block, and then copy any anonymous arguments
1646 in registers to memory.
1647
1648 CUM has not been updated for the last named argument which has type TYPE
1649 and mode MODE, and we rely on this fact. */
1650
1651static void
1652arc_setup_incoming_varargs (cumulative_args_t args_so_far,
ef4bddc2 1653 machine_mode mode, tree type,
526b7aee
SV
1654 int *pretend_size, int no_rtl)
1655{
1656 int first_anon_arg;
1657 CUMULATIVE_ARGS next_cum;
1658
1659 /* We must treat `__builtin_va_alist' as an anonymous arg. */
1660
1661 next_cum = *get_cumulative_args (args_so_far);
1662 arc_function_arg_advance (pack_cumulative_args (&next_cum), mode, type, 1);
1663 first_anon_arg = next_cum;
1664
1665 if (first_anon_arg < MAX_ARC_PARM_REGS)
1666 {
1667 /* First anonymous (unnamed) argument is in a reg. */
1668
1669 /* Note that first_reg_offset < MAX_ARC_PARM_REGS. */
1670 int first_reg_offset = first_anon_arg;
1671
1672 if (!no_rtl)
1673 {
1674 rtx regblock
1675 = gen_rtx_MEM (BLKmode, plus_constant (Pmode, arg_pointer_rtx,
1676 FIRST_PARM_OFFSET (0)));
1677 move_block_from_reg (first_reg_offset, regblock,
1678 MAX_ARC_PARM_REGS - first_reg_offset);
1679 }
1680
1681 *pretend_size
1682 = ((MAX_ARC_PARM_REGS - first_reg_offset ) * UNITS_PER_WORD);
1683 }
1684}
1685
1686/* Cost functions. */
1687
1688/* Provide the costs of an addressing mode that contains ADDR.
1689 If ADDR is not a valid address, its cost is irrelevant. */
1690
1691int
ef4bddc2 1692arc_address_cost (rtx addr, machine_mode, addr_space_t, bool speed)
526b7aee
SV
1693{
1694 switch (GET_CODE (addr))
1695 {
1696 case REG :
1697 return speed || satisfies_constraint_Rcq (addr) ? 0 : 1;
1698 case PRE_INC: case PRE_DEC: case POST_INC: case POST_DEC:
1699 case PRE_MODIFY: case POST_MODIFY:
1700 return !speed;
1701
1702 case LABEL_REF :
1703 case SYMBOL_REF :
1704 case CONST :
1705 /* Most likely needs a LIMM. */
1706 return COSTS_N_INSNS (1);
1707
1708 case PLUS :
1709 {
1710 register rtx plus0 = XEXP (addr, 0);
1711 register rtx plus1 = XEXP (addr, 1);
1712
1713 if (GET_CODE (plus0) != REG
1714 && (GET_CODE (plus0) != MULT
1715 || !CONST_INT_P (XEXP (plus0, 1))
1716 || (INTVAL (XEXP (plus0, 1)) != 2
1717 && INTVAL (XEXP (plus0, 1)) != 4)))
1718 break;
1719
1720 switch (GET_CODE (plus1))
1721 {
1722 case CONST_INT :
1723 return (!RTX_OK_FOR_OFFSET_P (SImode, plus1)
1724 ? COSTS_N_INSNS (1)
1725 : speed
1726 ? 0
1727 : (satisfies_constraint_Rcq (plus0)
1728 && satisfies_constraint_O (plus1))
1729 ? 0
1730 : 1);
1731 case REG:
1732 return (speed < 1 ? 0
1733 : (satisfies_constraint_Rcq (plus0)
1734 && satisfies_constraint_Rcq (plus1))
1735 ? 0 : 1);
1736 case CONST :
1737 case SYMBOL_REF :
1738 case LABEL_REF :
1739 return COSTS_N_INSNS (1);
1740 default:
1741 break;
1742 }
1743 break;
1744 }
1745 default:
1746 break;
1747 }
1748
1749 return 4;
1750}
1751
1752/* Emit instruction X with the frame related bit set. */
1753
1754static rtx
1755frame_insn (rtx x)
1756{
1757 x = emit_insn (x);
1758 RTX_FRAME_RELATED_P (x) = 1;
1759 return x;
1760}
1761
1762/* Emit a frame insn to move SRC to DST. */
1763
1764static rtx
1765frame_move (rtx dst, rtx src)
1766{
f7df4a84 1767 return frame_insn (gen_rtx_SET (dst, src));
526b7aee
SV
1768}
1769
1770/* Like frame_move, but add a REG_INC note for REG if ADDR contains an
1771 auto increment address, or is zero. */
1772
1773static rtx
1774frame_move_inc (rtx dst, rtx src, rtx reg, rtx addr)
1775{
1776 rtx insn = frame_move (dst, src);
1777
1778 if (!addr
1779 || GET_CODE (addr) == PRE_DEC || GET_CODE (addr) == POST_INC
1780 || GET_CODE (addr) == PRE_MODIFY || GET_CODE (addr) == POST_MODIFY)
1781 add_reg_note (insn, REG_INC, reg);
1782 return insn;
1783}
1784
1785/* Emit a frame insn which adjusts a frame address register REG by OFFSET. */
1786
1787static rtx
1788frame_add (rtx reg, HOST_WIDE_INT offset)
1789{
1790 gcc_assert ((offset & 0x3) == 0);
1791 if (!offset)
1792 return NULL_RTX;
1793 return frame_move (reg, plus_constant (Pmode, reg, offset));
1794}
1795
1796/* Emit a frame insn which adjusts stack pointer by OFFSET. */
1797
1798static rtx
1799frame_stack_add (HOST_WIDE_INT offset)
1800{
1801 return frame_add (stack_pointer_rtx, offset);
1802}
1803
1804/* Traditionally, we push saved registers first in the prologue,
1805 then we allocate the rest of the frame - and reverse in the epilogue.
1806 This has still its merits for ease of debugging, or saving code size
1807 or even execution time if the stack frame is so large that some accesses
1808 can't be encoded anymore with offsets in the instruction code when using
1809 a different scheme.
1810 Also, it would be a good starting point if we got instructions to help
1811 with register save/restore.
1812
1813 However, often stack frames are small, and the pushing / popping has
1814 some costs:
1815 - the stack modification prevents a lot of scheduling.
1816 - frame allocation / deallocation needs extra instructions.
1817 - unless we know that we compile ARC700 user code, we need to put
1818 a memory barrier after frame allocation / before deallocation to
1819 prevent interrupts clobbering our data in the frame.
1820 In particular, we don't have any such guarantees for library functions,
1821 which tend to, on the other hand, to have small frames.
1822
1823 Thus, for small frames, we'd like to use a different scheme:
1824 - The frame is allocated in full with the first prologue instruction,
1825 and deallocated in full with the last epilogue instruction.
1826 Thus, the instructions in-betwen can be freely scheduled.
1827 - If the function has no outgoing arguments on the stack, we can allocate
1828 one register save slot at the top of the stack. This register can then
1829 be saved simultanously with frame allocation, and restored with
1830 frame deallocation.
1831 This register can be picked depending on scheduling considerations,
1832 although same though should go into having some set of registers
1833 to be potentially lingering after a call, and others to be available
1834 immediately - i.e. in the absence of interprocedual optimization, we
1835 can use an ABI-like convention for register allocation to reduce
1836 stalls after function return. */
1837/* Function prologue/epilogue handlers. */
1838
1839/* ARCompact stack frames look like:
1840
1841 Before call After call
1842 high +-----------------------+ +-----------------------+
1843 mem | reg parm save area | | reg parm save area |
1844 | only created for | | only created for |
1845 | variable arg fns | | variable arg fns |
1846 AP +-----------------------+ +-----------------------+
1847 | return addr register | | return addr register |
1848 | (if required) | | (if required) |
1849 +-----------------------+ +-----------------------+
1850 | | | |
1851 | reg save area | | reg save area |
1852 | | | |
1853 +-----------------------+ +-----------------------+
1854 | frame pointer | | frame pointer |
1855 | (if required) | | (if required) |
1856 FP +-----------------------+ +-----------------------+
1857 | | | |
1858 | local/temp variables | | local/temp variables |
1859 | | | |
1860 +-----------------------+ +-----------------------+
1861 | | | |
1862 | arguments on stack | | arguments on stack |
1863 | | | |
1864 SP +-----------------------+ +-----------------------+
1865 | reg parm save area |
1866 | only created for |
1867 | variable arg fns |
1868 AP +-----------------------+
1869 | return addr register |
1870 | (if required) |
1871 +-----------------------+
1872 | |
1873 | reg save area |
1874 | |
1875 +-----------------------+
1876 | frame pointer |
1877 | (if required) |
1878 FP +-----------------------+
1879 | |
1880 | local/temp variables |
1881 | |
1882 +-----------------------+
1883 | |
1884 | arguments on stack |
1885 low | |
1886 mem SP +-----------------------+
1887
1888Notes:
18891) The "reg parm save area" does not exist for non variable argument fns.
1890 The "reg parm save area" can be eliminated completely if we created our
1891 own va-arc.h, but that has tradeoffs as well (so it's not done). */
1892
1893/* Structure to be filled in by arc_compute_frame_size with register
1894 save masks, and offsets for the current function. */
6cdfeeb4 1895struct GTY (()) arc_frame_info
526b7aee
SV
1896{
1897 unsigned int total_size; /* # bytes that the entire frame takes up. */
1898 unsigned int extra_size; /* # bytes of extra stuff. */
1899 unsigned int pretend_size; /* # bytes we push and pretend caller did. */
1900 unsigned int args_size; /* # bytes that outgoing arguments take up. */
1901 unsigned int reg_size; /* # bytes needed to store regs. */
1902 unsigned int var_size; /* # bytes that variables take up. */
1903 unsigned int reg_offset; /* Offset from new sp to store regs. */
1904 unsigned int gmask; /* Mask of saved gp registers. */
1905 int initialized; /* Nonzero if frame size already calculated. */
1906 short millicode_start_reg;
1907 short millicode_end_reg;
1908 bool save_return_addr;
1909};
1910
1911/* Defining data structures for per-function information. */
1912
1913typedef struct GTY (()) machine_function
1914{
1915 enum arc_function_type fn_type;
1916 struct arc_frame_info frame_info;
1917 /* To keep track of unalignment caused by short insns. */
1918 int unalign;
1919 int force_short_suffix; /* Used when disgorging return delay slot insns. */
1920 const char *size_reason;
1921 struct arc_ccfsm ccfsm_current;
1922 /* Map from uid to ccfsm state during branch shortening. */
1923 rtx ccfsm_current_insn;
1924 char arc_reorg_started;
1925 char prescan_initialized;
1926} machine_function;
1927
1928/* Type of function DECL.
1929
1930 The result is cached. To reset the cache at the end of a function,
1931 call with DECL = NULL_TREE. */
1932
1933enum arc_function_type
1934arc_compute_function_type (struct function *fun)
1935{
1936 tree decl = fun->decl;
1937 tree a;
1938 enum arc_function_type fn_type = fun->machine->fn_type;
1939
1940 if (fn_type != ARC_FUNCTION_UNKNOWN)
1941 return fn_type;
1942
1943 /* Assume we have a normal function (not an interrupt handler). */
1944 fn_type = ARC_FUNCTION_NORMAL;
1945
1946 /* Now see if this is an interrupt handler. */
1947 for (a = DECL_ATTRIBUTES (decl);
1948 a;
1949 a = TREE_CHAIN (a))
1950 {
1951 tree name = TREE_PURPOSE (a), args = TREE_VALUE (a);
1952
1953 if (name == get_identifier ("interrupt")
1954 && list_length (args) == 1
1955 && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
1956 {
1957 tree value = TREE_VALUE (args);
1958
1959 if (!strcmp (TREE_STRING_POINTER (value), "ilink1"))
1960 fn_type = ARC_FUNCTION_ILINK1;
1961 else if (!strcmp (TREE_STRING_POINTER (value), "ilink2"))
1962 fn_type = ARC_FUNCTION_ILINK2;
1963 else
1964 gcc_unreachable ();
1965 break;
1966 }
1967 }
1968
1969 return fun->machine->fn_type = fn_type;
1970}
1971
1972#define FRAME_POINTER_MASK (1 << (FRAME_POINTER_REGNUM))
1973#define RETURN_ADDR_MASK (1 << (RETURN_ADDR_REGNUM))
1974
1975/* Tell prologue and epilogue if register REGNO should be saved / restored.
1976 The return address and frame pointer are treated separately.
1977 Don't consider them here.
1978 Addition for pic: The gp register needs to be saved if the current
1979 function changes it to access gotoff variables.
1980 FIXME: This will not be needed if we used some arbitrary register
1981 instead of r26.
1982*/
1983#define MUST_SAVE_REGISTER(regno, interrupt_p) \
1984(((regno) != RETURN_ADDR_REGNUM && (regno) != FRAME_POINTER_REGNUM \
1985 && (df_regs_ever_live_p (regno) && (!call_used_regs[regno] || interrupt_p))) \
1986 || (flag_pic && crtl->uses_pic_offset_table \
1987 && regno == PIC_OFFSET_TABLE_REGNUM) )
1988
1989#define MUST_SAVE_RETURN_ADDR \
1990 (cfun->machine->frame_info.save_return_addr)
1991
1992/* Return non-zero if there are registers to be saved or loaded using
1993 millicode thunks. We can only use consecutive sequences starting
1994 with r13, and not going beyond r25.
1995 GMASK is a bitmask of registers to save. This function sets
1996 FRAME->millicod_start_reg .. FRAME->millicode_end_reg to the range
1997 of registers to be saved / restored with a millicode call. */
1998
1999static int
2000arc_compute_millicode_save_restore_regs (unsigned int gmask,
2001 struct arc_frame_info *frame)
2002{
2003 int regno;
2004
2005 int start_reg = 13, end_reg = 25;
2006
2007 for (regno = start_reg; regno <= end_reg && (gmask & (1L << regno));)
2008 regno++;
2009 end_reg = regno - 1;
2010 /* There is no point in using millicode thunks if we don't save/restore
2011 at least three registers. For non-leaf functions we also have the
2012 blink restore. */
2013 if (regno - start_reg >= 3 - (crtl->is_leaf == 0))
2014 {
2015 frame->millicode_start_reg = 13;
2016 frame->millicode_end_reg = regno - 1;
2017 return 1;
2018 }
2019 return 0;
2020}
2021
2022/* Return the bytes needed to compute the frame pointer from the current
2023 stack pointer.
2024
2025 SIZE is the size needed for local variables. */
2026
2027unsigned int
2028arc_compute_frame_size (int size) /* size = # of var. bytes allocated. */
2029{
2030 int regno;
2031 unsigned int total_size, var_size, args_size, pretend_size, extra_size;
2032 unsigned int reg_size, reg_offset;
2033 unsigned int gmask;
2034 enum arc_function_type fn_type;
2035 int interrupt_p;
2036 struct arc_frame_info *frame_info = &cfun->machine->frame_info;
2037
2038 size = ARC_STACK_ALIGN (size);
2039
2040 /* 1) Size of locals and temporaries */
2041 var_size = size;
2042
2043 /* 2) Size of outgoing arguments */
2044 args_size = crtl->outgoing_args_size;
2045
2046 /* 3) Calculate space needed for saved registers.
2047 ??? We ignore the extension registers for now. */
2048
2049 /* See if this is an interrupt handler. Call used registers must be saved
2050 for them too. */
2051
2052 reg_size = 0;
2053 gmask = 0;
2054 fn_type = arc_compute_function_type (cfun);
2055 interrupt_p = ARC_INTERRUPT_P (fn_type);
2056
2057 for (regno = 0; regno <= 31; regno++)
2058 {
2059 if (MUST_SAVE_REGISTER (regno, interrupt_p))
2060 {
2061 reg_size += UNITS_PER_WORD;
2062 gmask |= 1 << regno;
2063 }
2064 }
2065
2066 /* 4) Space for back trace data structure.
2067 <return addr reg size> (if required) + <fp size> (if required). */
2068 frame_info->save_return_addr
2069 = (!crtl->is_leaf || df_regs_ever_live_p (RETURN_ADDR_REGNUM));
2070 /* Saving blink reg in case of leaf function for millicode thunk calls. */
2071 if (optimize_size && !TARGET_NO_MILLICODE_THUNK_SET)
2072 {
2073 if (arc_compute_millicode_save_restore_regs (gmask, frame_info))
2074 frame_info->save_return_addr = true;
2075 }
2076
2077 extra_size = 0;
2078 if (MUST_SAVE_RETURN_ADDR)
2079 extra_size = 4;
2080 if (frame_pointer_needed)
2081 extra_size += 4;
2082
2083 /* 5) Space for variable arguments passed in registers */
2084 pretend_size = crtl->args.pretend_args_size;
2085
2086 /* Ensure everything before the locals is aligned appropriately. */
2087 {
2088 unsigned int extra_plus_reg_size;
2089 unsigned int extra_plus_reg_size_aligned;
2090
2091 extra_plus_reg_size = extra_size + reg_size;
2092 extra_plus_reg_size_aligned = ARC_STACK_ALIGN(extra_plus_reg_size);
2093 reg_size = extra_plus_reg_size_aligned - extra_size;
2094 }
2095
2096 /* Compute total frame size. */
2097 total_size = var_size + args_size + extra_size + pretend_size + reg_size;
2098
2099 total_size = ARC_STACK_ALIGN (total_size);
2100
2101 /* Compute offset of register save area from stack pointer:
2102 A5 Frame: pretend_size <blink> reg_size <fp> var_size args_size <--sp
2103 */
2104 reg_offset = (total_size - (pretend_size + reg_size + extra_size)
2105 + (frame_pointer_needed ? 4 : 0));
2106
2107 /* Save computed information. */
2108 frame_info->total_size = total_size;
2109 frame_info->extra_size = extra_size;
2110 frame_info->pretend_size = pretend_size;
2111 frame_info->var_size = var_size;
2112 frame_info->args_size = args_size;
2113 frame_info->reg_size = reg_size;
2114 frame_info->reg_offset = reg_offset;
2115 frame_info->gmask = gmask;
2116 frame_info->initialized = reload_completed;
2117
2118 /* Ok, we're done. */
2119 return total_size;
2120}
2121
2122/* Common code to save/restore registers. */
2123/* BASE_REG is the base register to use for addressing and to adjust.
2124 GMASK is a bitmask of general purpose registers to save/restore.
2125 epilogue_p 0: prologue 1:epilogue 2:epilogue, sibling thunk
2126 If *FIRST_OFFSET is non-zero, add it first to BASE_REG - preferably
2127 using a pre-modify for the first memory access. *FIRST_OFFSET is then
2128 zeroed. */
2129
2130static void
2131arc_save_restore (rtx base_reg,
2132 unsigned int gmask, int epilogue_p, int *first_offset)
2133{
2134 unsigned int offset = 0;
2135 int regno;
2136 struct arc_frame_info *frame = &cfun->machine->frame_info;
2137 rtx sibthunk_insn = NULL_RTX;
2138
2139 if (gmask)
2140 {
2141 /* Millicode thunks implementation:
2142 Generates calls to millicodes for registers starting from r13 to r25
2143 Present Limitations:
2144 - Only one range supported. The remaining regs will have the ordinary
2145 st and ld instructions for store and loads. Hence a gmask asking
2146 to store r13-14, r16-r25 will only generate calls to store and
2147 load r13 to r14 while store and load insns will be generated for
2148 r16 to r25 in the prologue and epilogue respectively.
2149
2150 - Presently library only supports register ranges starting from r13.
2151 */
2152 if (epilogue_p == 2 || frame->millicode_end_reg > 14)
2153 {
2154 int start_call = frame->millicode_start_reg;
2155 int end_call = frame->millicode_end_reg;
2156 int n_regs = end_call - start_call + 1;
2157 int i = 0, r, off = 0;
2158 rtx insn;
2159 rtx ret_addr = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
2160
2161 if (*first_offset)
2162 {
2163 /* "reg_size" won't be more than 127 . */
6ace1161 2164 gcc_assert (epilogue_p || abs (*first_offset) <= 127);
526b7aee
SV
2165 frame_add (base_reg, *first_offset);
2166 *first_offset = 0;
2167 }
2168 insn = gen_rtx_PARALLEL
2169 (VOIDmode, rtvec_alloc ((epilogue_p == 2) + n_regs + 1));
2170 if (epilogue_p == 2)
2171 i += 2;
2172 else
2173 XVECEXP (insn, 0, n_regs) = gen_rtx_CLOBBER (VOIDmode, ret_addr);
2174 for (r = start_call; r <= end_call; r++, off += UNITS_PER_WORD, i++)
2175 {
2176 rtx reg = gen_rtx_REG (SImode, r);
2177 rtx mem
2178 = gen_frame_mem (SImode, plus_constant (Pmode, base_reg, off));
2179
2180 if (epilogue_p)
f7df4a84 2181 XVECEXP (insn, 0, i) = gen_rtx_SET (reg, mem);
526b7aee 2182 else
f7df4a84 2183 XVECEXP (insn, 0, i) = gen_rtx_SET (mem, reg);
526b7aee
SV
2184 gmask = gmask & ~(1L << r);
2185 }
2186 if (epilogue_p == 2)
2187 sibthunk_insn = insn;
2188 else
2189 frame_insn (insn);
2190 offset += off;
2191 }
2192
2193 for (regno = 0; regno <= 31; regno++)
2194 {
2195 if ((gmask & (1L << regno)) != 0)
2196 {
2197 rtx reg = gen_rtx_REG (SImode, regno);
2198 rtx addr, mem;
2199
2200 if (*first_offset)
2201 {
2202 gcc_assert (!offset);
2203 addr = plus_constant (Pmode, base_reg, *first_offset);
2204 addr = gen_rtx_PRE_MODIFY (Pmode, base_reg, addr);
2205 *first_offset = 0;
2206 }
2207 else
2208 {
2209 gcc_assert (SMALL_INT (offset));
2210 addr = plus_constant (Pmode, base_reg, offset);
2211 }
2212 mem = gen_frame_mem (SImode, addr);
2213 if (epilogue_p)
2214 frame_move_inc (reg, mem, base_reg, addr);
2215 else
2216 frame_move_inc (mem, reg, base_reg, addr);
2217 offset += UNITS_PER_WORD;
2218 } /* if */
2219 } /* for */
2220 }/* if */
2221 if (sibthunk_insn)
2222 {
2223 rtx r12 = gen_rtx_REG (Pmode, 12);
2224
f7df4a84 2225 frame_insn (gen_rtx_SET (r12, GEN_INT (offset)));
526b7aee
SV
2226 XVECEXP (sibthunk_insn, 0, 0) = ret_rtx;
2227 XVECEXP (sibthunk_insn, 0, 1)
f7df4a84 2228 = gen_rtx_SET (stack_pointer_rtx,
526b7aee
SV
2229 gen_rtx_PLUS (Pmode, stack_pointer_rtx, r12));
2230 sibthunk_insn = emit_jump_insn (sibthunk_insn);
2231 RTX_FRAME_RELATED_P (sibthunk_insn) = 1;
2232 }
2233} /* arc_save_restore */
2234
2235
2236int arc_return_address_regs[4]
2237 = {0, RETURN_ADDR_REGNUM, ILINK1_REGNUM, ILINK2_REGNUM};
2238
2239/* Set up the stack and frame pointer (if desired) for the function. */
2240
2241void
2242arc_expand_prologue (void)
2243{
2244 int size = get_frame_size ();
2245 unsigned int gmask = cfun->machine->frame_info.gmask;
2246 /* unsigned int frame_pointer_offset;*/
2247 unsigned int frame_size_to_allocate;
2248 /* (FIXME: The first store will use a PRE_MODIFY; this will usually be r13.
2249 Change the stack layout so that we rather store a high register with the
2250 PRE_MODIFY, thus enabling more short insn generation.) */
2251 int first_offset = 0;
2252
2253 size = ARC_STACK_ALIGN (size);
2254
2255 /* Compute/get total frame size. */
2256 size = (!cfun->machine->frame_info.initialized
2257 ? arc_compute_frame_size (size)
2258 : cfun->machine->frame_info.total_size);
2259
2260 if (flag_stack_usage_info)
2261 current_function_static_stack_size = size;
2262
2263 /* Keep track of frame size to be allocated. */
2264 frame_size_to_allocate = size;
2265
2266 /* These cases shouldn't happen. Catch them now. */
2267 gcc_assert (!(size == 0 && gmask));
2268
2269 /* Allocate space for register arguments if this is a variadic function. */
2270 if (cfun->machine->frame_info.pretend_size != 0)
2271 {
2272 /* Ensure pretend_size is maximum of 8 * word_size. */
2273 gcc_assert (cfun->machine->frame_info.pretend_size <= 32);
2274
2275 frame_stack_add (-(HOST_WIDE_INT)cfun->machine->frame_info.pretend_size);
2276 frame_size_to_allocate -= cfun->machine->frame_info.pretend_size;
2277 }
2278
2279 /* The home-grown ABI says link register is saved first. */
2280 if (MUST_SAVE_RETURN_ADDR)
2281 {
2282 rtx ra = gen_rtx_REG (SImode, RETURN_ADDR_REGNUM);
2283 rtx mem = gen_frame_mem (Pmode, gen_rtx_PRE_DEC (Pmode, stack_pointer_rtx));
2284
2285 frame_move_inc (mem, ra, stack_pointer_rtx, 0);
2286 frame_size_to_allocate -= UNITS_PER_WORD;
2287
2288 } /* MUST_SAVE_RETURN_ADDR */
2289
2290 /* Save any needed call-saved regs (and call-used if this is an
2291 interrupt handler) for ARCompact ISA. */
2292 if (cfun->machine->frame_info.reg_size)
2293 {
2294 first_offset = -cfun->machine->frame_info.reg_size;
2295 /* N.B. FRAME_POINTER_MASK and RETURN_ADDR_MASK are cleared in gmask. */
2296 arc_save_restore (stack_pointer_rtx, gmask, 0, &first_offset);
2297 frame_size_to_allocate -= cfun->machine->frame_info.reg_size;
2298 }
2299
2300
2301 /* Save frame pointer if needed. */
2302 if (frame_pointer_needed)
2303 {
2304 rtx addr = gen_rtx_PLUS (Pmode, stack_pointer_rtx,
2305 GEN_INT (-UNITS_PER_WORD + first_offset));
2306 rtx mem = gen_frame_mem (Pmode, gen_rtx_PRE_MODIFY (Pmode,
2307 stack_pointer_rtx,
2308 addr));
2309 frame_move_inc (mem, frame_pointer_rtx, stack_pointer_rtx, 0);
2310 frame_size_to_allocate -= UNITS_PER_WORD;
2311 first_offset = 0;
2312 frame_move (frame_pointer_rtx, stack_pointer_rtx);
2313 }
2314
2315 /* ??? We don't handle the case where the saved regs are more than 252
2316 bytes away from sp. This can be handled by decrementing sp once, saving
2317 the regs, and then decrementing it again. The epilogue doesn't have this
2318 problem as the `ld' insn takes reg+limm values (though it would be more
2319 efficient to avoid reg+limm). */
2320
2321 frame_size_to_allocate -= first_offset;
2322 /* Allocate the stack frame. */
2323 if (frame_size_to_allocate > 0)
2324 frame_stack_add ((HOST_WIDE_INT) 0 - frame_size_to_allocate);
2325
2326 /* Setup the gp register, if needed. */
2327 if (crtl->uses_pic_offset_table)
2328 arc_finalize_pic ();
2329}
2330
2331/* Do any necessary cleanup after a function to restore stack, frame,
2332 and regs. */
2333
2334void
2335arc_expand_epilogue (int sibcall_p)
2336{
2337 int size = get_frame_size ();
2338 enum arc_function_type fn_type = arc_compute_function_type (cfun);
2339
2340 size = ARC_STACK_ALIGN (size);
2341 size = (!cfun->machine->frame_info.initialized
2342 ? arc_compute_frame_size (size)
2343 : cfun->machine->frame_info.total_size);
2344
5719867d
JR
2345 unsigned int pretend_size = cfun->machine->frame_info.pretend_size;
2346 unsigned int frame_size;
2347 unsigned int size_to_deallocate;
2348 int restored;
2349 int can_trust_sp_p = !cfun->calls_alloca;
2350 int first_offset = 0;
2351 int millicode_p = cfun->machine->frame_info.millicode_end_reg > 0;
526b7aee 2352
5719867d 2353 size_to_deallocate = size;
526b7aee 2354
5719867d
JR
2355 frame_size = size - (pretend_size +
2356 cfun->machine->frame_info.reg_size +
2357 cfun->machine->frame_info.extra_size);
526b7aee 2358
5719867d
JR
2359 /* ??? There are lots of optimizations that can be done here.
2360 EG: Use fp to restore regs if it's closer.
2361 Maybe in time we'll do them all. For now, always restore regs from
2362 sp, but don't restore sp if we don't have to. */
526b7aee 2363
5719867d
JR
2364 if (!can_trust_sp_p)
2365 gcc_assert (frame_pointer_needed);
526b7aee 2366
5719867d
JR
2367 /* Restore stack pointer to the beginning of saved register area for
2368 ARCompact ISA. */
2369 if (frame_size)
2370 {
526b7aee 2371 if (frame_pointer_needed)
5719867d
JR
2372 frame_move (stack_pointer_rtx, frame_pointer_rtx);
2373 else
2374 first_offset = frame_size;
2375 size_to_deallocate -= frame_size;
2376 }
2377 else if (!can_trust_sp_p)
2378 frame_stack_add (-frame_size);
526b7aee 2379
526b7aee 2380
5719867d
JR
2381 /* Restore any saved registers. */
2382 if (frame_pointer_needed)
2383 {
2384 rtx addr = gen_rtx_POST_INC (Pmode, stack_pointer_rtx);
2385
2386 frame_move_inc (frame_pointer_rtx, gen_frame_mem (Pmode, addr),
2387 stack_pointer_rtx, 0);
2388 size_to_deallocate -= UNITS_PER_WORD;
2389 }
2390
2391 /* Load blink after the calls to thunk calls in case of optimize size. */
2392 if (millicode_p)
2393 {
2394 int sibthunk_p = (!sibcall_p
2395 && fn_type == ARC_FUNCTION_NORMAL
2396 && !cfun->machine->frame_info.pretend_size);
2397
2398 gcc_assert (!(cfun->machine->frame_info.gmask
2399 & (FRAME_POINTER_MASK | RETURN_ADDR_MASK)));
2400 arc_save_restore (stack_pointer_rtx,
2401 cfun->machine->frame_info.gmask,
2402 1 + sibthunk_p, &first_offset);
2403 if (sibthunk_p)
2404 goto epilogue_done;
2405 }
2406 /* If we are to restore registers, and first_offset would require
2407 a limm to be encoded in a PRE_MODIFY, yet we can add it with a
2408 fast add to the stack pointer, do this now. */
2409 if ((!SMALL_INT (first_offset)
2410 && cfun->machine->frame_info.gmask
2411 && ((TARGET_ARC700 && !optimize_size)
2412 ? first_offset <= 0x800
2413 : satisfies_constraint_C2a (GEN_INT (first_offset))))
2414 /* Also do this if we have both gprs and return
2415 address to restore, and they both would need a LIMM. */
2416 || (MUST_SAVE_RETURN_ADDR
2417 && !SMALL_INT ((cfun->machine->frame_info.reg_size + first_offset) >> 2)
2418 && cfun->machine->frame_info.gmask))
2419 {
2420 frame_stack_add (first_offset);
2421 first_offset = 0;
2422 }
2423 if (MUST_SAVE_RETURN_ADDR)
2424 {
2425 rtx ra = gen_rtx_REG (Pmode, RETURN_ADDR_REGNUM);
2426 int ra_offs = cfun->machine->frame_info.reg_size + first_offset;
2427 rtx addr = plus_constant (Pmode, stack_pointer_rtx, ra_offs);
2428
2429 /* If the load of blink would need a LIMM, but we can add
2430 the offset quickly to sp, do the latter. */
2431 if (!SMALL_INT (ra_offs >> 2)
2432 && !cfun->machine->frame_info.gmask
2433 && ((TARGET_ARC700 && !optimize_size)
2434 ? ra_offs <= 0x800
2435 : satisfies_constraint_C2a (GEN_INT (ra_offs))))
526b7aee 2436 {
5719867d
JR
2437 size_to_deallocate -= ra_offs - first_offset;
2438 first_offset = 0;
2439 frame_stack_add (ra_offs);
2440 ra_offs = 0;
2441 addr = stack_pointer_rtx;
526b7aee 2442 }
5719867d
JR
2443 /* See if we can combine the load of the return address with the
2444 final stack adjustment.
2445 We need a separate load if there are still registers to
2446 restore. We also want a separate load if the combined insn
2447 would need a limm, but a separate load doesn't. */
2448 if (ra_offs
2449 && !cfun->machine->frame_info.gmask
2450 && (SMALL_INT (ra_offs) || !SMALL_INT (ra_offs >> 2)))
526b7aee 2451 {
5719867d 2452 addr = gen_rtx_PRE_MODIFY (Pmode, stack_pointer_rtx, addr);
526b7aee 2453 first_offset = 0;
5719867d 2454 size_to_deallocate -= cfun->machine->frame_info.reg_size;
526b7aee 2455 }
5719867d 2456 else if (!ra_offs && size_to_deallocate == UNITS_PER_WORD)
526b7aee 2457 {
5719867d
JR
2458 addr = gen_rtx_POST_INC (Pmode, addr);
2459 size_to_deallocate = 0;
526b7aee 2460 }
5719867d
JR
2461 frame_move_inc (ra, gen_frame_mem (Pmode, addr), stack_pointer_rtx, addr);
2462 }
526b7aee 2463
5719867d
JR
2464 if (!millicode_p)
2465 {
2466 if (cfun->machine->frame_info.reg_size)
2467 arc_save_restore (stack_pointer_rtx,
2468 /* The zeroing of these two bits is unnecessary, but leave this in for clarity. */
2469 cfun->machine->frame_info.gmask
2470 & ~(FRAME_POINTER_MASK | RETURN_ADDR_MASK), 1, &first_offset);
2471 }
526b7aee
SV
2472
2473
5719867d
JR
2474 /* The rest of this function does the following:
2475 ARCompact : handle epilogue_delay, restore sp (phase-2), return
2476 */
526b7aee 2477
5719867d
JR
2478 /* Keep track of how much of the stack pointer we've restored.
2479 It makes the following a lot more readable. */
2480 size_to_deallocate += first_offset;
2481 restored = size - size_to_deallocate;
526b7aee 2482
5719867d
JR
2483 if (size > restored)
2484 frame_stack_add (size - restored);
2485 /* Emit the return instruction. */
2486 if (sibcall_p == FALSE)
2487 emit_jump_insn (gen_simple_return ());
526b7aee
SV
2488 epilogue_done:
2489 if (!TARGET_EPILOGUE_CFI)
2490 {
b32d5189 2491 rtx_insn *insn;
526b7aee
SV
2492
2493 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2494 RTX_FRAME_RELATED_P (insn) = 0;
2495 }
2496}
2497
2498/* Return the offset relative to the stack pointer where the return address
2499 is stored, or -1 if it is not stored. */
2500
2501int
2502arc_return_slot_offset ()
2503{
2504 struct arc_frame_info *afi = &cfun->machine->frame_info;
2505
2506 return (afi->save_return_addr
2507 ? afi->total_size - afi->pretend_size - afi->extra_size : -1);
2508}
2509
2510/* PIC */
2511
2512/* Emit special PIC prologues and epilogues. */
2513/* If the function has any GOTOFF relocations, then the GOTBASE
2514 register has to be setup in the prologue
2515 The instruction needed at the function start for setting up the
2516 GOTBASE register is
2517 add rdest, pc,
2518 ----------------------------------------------------------
2519 The rtl to be emitted for this should be:
2520 set (reg basereg)
2521 (plus (reg pc)
2522 (const (unspec (symref _DYNAMIC) 3)))
2523 ---------------------------------------------------------- */
2524
2525static void
2526arc_finalize_pic (void)
2527{
2528 rtx pat;
2529 rtx baseptr_rtx = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM);
2530
2531 if (crtl->uses_pic_offset_table == 0)
2532 return;
2533
2534 gcc_assert (flag_pic != 0);
2535
2536 pat = gen_rtx_SYMBOL_REF (Pmode, "_DYNAMIC");
2537 pat = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, pat), ARC_UNSPEC_GOT);
2538 pat = gen_rtx_CONST (Pmode, pat);
2539
f7df4a84 2540 pat = gen_rtx_SET (baseptr_rtx, pat);
526b7aee
SV
2541
2542 emit_insn (pat);
2543}
2544\f
2545/* !TARGET_BARREL_SHIFTER support. */
2546/* Emit a shift insn to set OP0 to OP1 shifted by OP2; CODE specifies what
2547 kind of shift. */
2548
2549void
2550emit_shift (enum rtx_code code, rtx op0, rtx op1, rtx op2)
2551{
2552 rtx shift = gen_rtx_fmt_ee (code, SImode, op1, op2);
2553 rtx pat
2554 = ((shift4_operator (shift, SImode) ? gen_shift_si3 : gen_shift_si3_loop)
2555 (op0, op1, op2, shift));
2556 emit_insn (pat);
2557}
2558
2559/* Output the assembler code for doing a shift.
2560 We go to a bit of trouble to generate efficient code as the ARC601 only has
2561 single bit shifts. This is taken from the h8300 port. We only have one
2562 mode of shifting and can't access individual bytes like the h8300 can, so
2563 this is greatly simplified (at the expense of not generating hyper-
2564 efficient code).
2565
2566 This function is not used if the variable shift insns are present. */
2567
2568/* FIXME: This probably can be done using a define_split in arc.md.
2569 Alternately, generate rtx rather than output instructions. */
2570
2571const char *
2572output_shift (rtx *operands)
2573{
2574 /* static int loopend_lab;*/
2575 rtx shift = operands[3];
ef4bddc2 2576 machine_mode mode = GET_MODE (shift);
526b7aee
SV
2577 enum rtx_code code = GET_CODE (shift);
2578 const char *shift_one;
2579
2580 gcc_assert (mode == SImode);
2581
2582 switch (code)
2583 {
2584 case ASHIFT: shift_one = "add %0,%1,%1"; break;
2585 case ASHIFTRT: shift_one = "asr %0,%1"; break;
2586 case LSHIFTRT: shift_one = "lsr %0,%1"; break;
2587 default: gcc_unreachable ();
2588 }
2589
2590 if (GET_CODE (operands[2]) != CONST_INT)
2591 {
2592 output_asm_insn ("and.f lp_count,%2, 0x1f", operands);
2593 goto shiftloop;
2594 }
2595 else
2596 {
2597 int n;
2598
2599 n = INTVAL (operands[2]);
2600
2601 /* Only consider the lower 5 bits of the shift count. */
2602 n = n & 0x1f;
2603
2604 /* First see if we can do them inline. */
2605 /* ??? We could get better scheduling & shorter code (using short insns)
2606 by using splitters. Alas, that'd be even more verbose. */
2607 if (code == ASHIFT && n <= 9 && n > 2
2608 && dest_reg_operand (operands[4], SImode))
2609 {
2610 output_asm_insn ("mov %4,0\n\tadd3 %0,%4,%1", operands);
2611 for (n -=3 ; n >= 3; n -= 3)
2612 output_asm_insn ("add3 %0,%4,%0", operands);
2613 if (n == 2)
2614 output_asm_insn ("add2 %0,%4,%0", operands);
2615 else if (n)
2616 output_asm_insn ("add %0,%0,%0", operands);
2617 }
2618 else if (n <= 4)
2619 {
2620 while (--n >= 0)
2621 {
2622 output_asm_insn (shift_one, operands);
2623 operands[1] = operands[0];
2624 }
2625 }
2626 /* See if we can use a rotate/and. */
2627 else if (n == BITS_PER_WORD - 1)
2628 {
2629 switch (code)
2630 {
2631 case ASHIFT :
2632 output_asm_insn ("and %0,%1,1\n\tror %0,%0", operands);
2633 break;
2634 case ASHIFTRT :
2635 /* The ARC doesn't have a rol insn. Use something else. */
2636 output_asm_insn ("add.f 0,%1,%1\n\tsbc %0,%0,%0", operands);
2637 break;
2638 case LSHIFTRT :
2639 /* The ARC doesn't have a rol insn. Use something else. */
2640 output_asm_insn ("add.f 0,%1,%1\n\trlc %0,0", operands);
2641 break;
2642 default:
2643 break;
2644 }
2645 }
2646 else if (n == BITS_PER_WORD - 2 && dest_reg_operand (operands[4], SImode))
2647 {
2648 switch (code)
2649 {
2650 case ASHIFT :
2651 output_asm_insn ("and %0,%1,3\n\tror %0,%0\n\tror %0,%0", operands);
2652 break;
2653 case ASHIFTRT :
2654#if 1 /* Need some scheduling comparisons. */
2655 output_asm_insn ("add.f %4,%1,%1\n\tsbc %0,%0,%0\n\t"
2656 "add.f 0,%4,%4\n\trlc %0,%0", operands);
2657#else
2658 output_asm_insn ("add.f %4,%1,%1\n\tbxor %0,%4,31\n\t"
2659 "sbc.f %0,%0,%4\n\trlc %0,%0", operands);
2660#endif
2661 break;
2662 case LSHIFTRT :
2663#if 1
2664 output_asm_insn ("add.f %4,%1,%1\n\trlc %0,0\n\t"
2665 "add.f 0,%4,%4\n\trlc %0,%0", operands);
2666#else
2667 output_asm_insn ("add.f %0,%1,%1\n\trlc.f %0,0\n\t"
2668 "and %0,%0,1\n\trlc %0,%0", operands);
2669#endif
2670 break;
2671 default:
2672 break;
2673 }
2674 }
2675 else if (n == BITS_PER_WORD - 3 && code == ASHIFT)
2676 output_asm_insn ("and %0,%1,7\n\tror %0,%0\n\tror %0,%0\n\tror %0,%0",
2677 operands);
2678 /* Must loop. */
2679 else
2680 {
2681 operands[2] = GEN_INT (n);
2682 output_asm_insn ("mov.f lp_count, %2", operands);
2683
2684 shiftloop:
2685 {
2686 output_asm_insn ("lpnz\t2f", operands);
2687 output_asm_insn (shift_one, operands);
2688 output_asm_insn ("nop", operands);
2689 fprintf (asm_out_file, "2:\t%s end single insn loop\n",
2690 ASM_COMMENT_START);
2691 }
2692 }
2693 }
2694
2695 return "";
2696}
2697\f
2698/* Nested function support. */
2699
2700/* Directly store VALUE into memory object BLOCK at OFFSET. */
2701
2702static void
2703emit_store_direct (rtx block, int offset, int value)
2704{
2705 emit_insn (gen_store_direct (adjust_address (block, SImode, offset),
2706 force_reg (SImode,
2707 gen_int_mode (value, SImode))));
2708}
2709
2710/* Emit RTL insns to initialize the variable parts of a trampoline.
2711 FNADDR is an RTX for the address of the function's pure code.
2712 CXT is an RTX for the static chain value for the function. */
2713/* With potentially multiple shared objects loaded, and multiple stacks
2714 present for multiple thereds where trampolines might reside, a simple
2715 range check will likely not suffice for the profiler to tell if a callee
2716 is a trampoline. We a speedier check by making the trampoline start at
2717 an address that is not 4-byte aligned.
2718 A trampoline looks like this:
2719
2720 nop_s 0x78e0
2721entry:
2722 ld_s r12,[pcl,12] 0xd403
2723 ld r11,[pcl,12] 0x170c 700b
2724 j_s [r12] 0x7c00
2725 nop_s 0x78e0
2726
2727 The fastest trampoline to execute for trampolines within +-8KB of CTX
2728 would be:
2729 add2 r11,pcl,s12
2730 j [limm] 0x20200f80 limm
2731 and that would also be faster to write to the stack by computing the offset
2732 from CTX to TRAMP at compile time. However, it would really be better to
2733 get rid of the high cost of cache invalidation when generating trampolines,
2734 which requires that the code part of trampolines stays constant, and
2735 additionally either
2736 - making sure that no executable code but trampolines is on the stack,
2737 no icache entries linger for the area of the stack from when before the
2738 stack was allocated, and allocating trampolines in trampoline-only
2739 cache lines
2740 or
2741 - allocate trampolines fram a special pool of pre-allocated trampolines. */
2742
2743static void
2744arc_initialize_trampoline (rtx tramp, tree fndecl, rtx cxt)
2745{
2746 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
2747
2748 emit_store_direct (tramp, 0, TARGET_BIG_ENDIAN ? 0x78e0d403 : 0xd40378e0);
2749 emit_store_direct (tramp, 4, TARGET_BIG_ENDIAN ? 0x170c700b : 0x700b170c);
2750 emit_store_direct (tramp, 8, TARGET_BIG_ENDIAN ? 0x7c0078e0 : 0x78e07c00);
2751 emit_move_insn (adjust_address (tramp, SImode, 12), fnaddr);
2752 emit_move_insn (adjust_address (tramp, SImode, 16), cxt);
2753 emit_insn (gen_flush_icache (adjust_address (tramp, SImode, 0)));
2754}
2755
2756/* Allow the profiler to easily distinguish trampolines from normal
2757 functions. */
2758
2759static rtx
2760arc_trampoline_adjust_address (rtx addr)
2761{
2762 return plus_constant (Pmode, addr, 2);
2763}
2764
2765/* This is set briefly to 1 when we output a ".as" address modifer, and then
2766 reset when we output the scaled address. */
2767static int output_scaled = 0;
2768
2769/* Print operand X (an rtx) in assembler syntax to file FILE.
2770 CODE is a letter or dot (`z' in `%z0') or 0 if no letter was specified.
2771 For `%' followed by punctuation, CODE is the punctuation and X is null. */
2772/* In final.c:output_asm_insn:
2773 'l' : label
2774 'a' : address
2775 'c' : constant address if CONSTANT_ADDRESS_P
2776 'n' : negative
2777 Here:
2778 'Z': log2(x+1)-1
2779 'z': log2
2780 'M': log2(~x)
2781 '#': condbranch delay slot suffix
2782 '*': jump delay slot suffix
2783 '?' : nonjump-insn suffix for conditional execution or short instruction
2784 '!' : jump / call suffix for conditional execution or short instruction
2785 '`': fold constant inside unary o-perator, re-recognize, and emit.
2786 'd'
2787 'D'
2788 'R': Second word
2789 'S'
2790 'B': Branch comparison operand - suppress sda reference
2791 'H': Most significant word
2792 'L': Least significant word
2793 'A': ASCII decimal representation of floating point value
2794 'U': Load/store update or scaling indicator
2795 'V': cache bypass indicator for volatile
2796 'P'
2797 'F'
2798 '^'
2799 'O': Operator
2800 'o': original symbol - no @ prepending. */
2801
2802void
2803arc_print_operand (FILE *file, rtx x, int code)
2804{
2805 switch (code)
2806 {
2807 case 'Z':
2808 if (GET_CODE (x) == CONST_INT)
2809 fprintf (file, "%d",exact_log2(INTVAL (x) + 1) - 1 );
2810 else
2811 output_operand_lossage ("invalid operand to %%Z code");
2812
2813 return;
2814
2815 case 'z':
2816 if (GET_CODE (x) == CONST_INT)
2817 fprintf (file, "%d",exact_log2(INTVAL (x)) );
2818 else
2819 output_operand_lossage ("invalid operand to %%z code");
2820
2821 return;
2822
2823 case 'M':
2824 if (GET_CODE (x) == CONST_INT)
2825 fprintf (file, "%d",exact_log2(~INTVAL (x)) );
2826 else
2827 output_operand_lossage ("invalid operand to %%M code");
2828
2829 return;
2830
2831 case '#' :
2832 /* Conditional branches depending on condition codes.
2833 Note that this is only for branches that were known to depend on
2834 condition codes before delay slot scheduling;
2835 out-of-range brcc / bbit expansions should use '*'.
2836 This distinction is important because of the different
2837 allowable delay slot insns and the output of the delay suffix
2838 for TARGET_AT_DBR_COND_EXEC. */
2839 case '*' :
2840 /* Unconditional branches / branches not depending on condition codes.
2841 This could also be a CALL_INSN.
2842 Output the appropriate delay slot suffix. */
84034c69 2843 if (final_sequence && final_sequence->len () != 1)
526b7aee 2844 {
84034c69
DM
2845 rtx_insn *jump = final_sequence->insn (0);
2846 rtx_insn *delay = final_sequence->insn (1);
526b7aee
SV
2847
2848 /* For TARGET_PAD_RETURN we might have grabbed the delay insn. */
4654c0cf 2849 if (delay->deleted ())
526b7aee
SV
2850 return;
2851 if (JUMP_P (jump) && INSN_ANNULLED_BRANCH_P (jump))
2852 fputs (INSN_FROM_TARGET_P (delay) ? ".d"
2853 : TARGET_AT_DBR_CONDEXEC && code == '#' ? ".d"
2854 : get_attr_type (jump) == TYPE_RETURN && code == '#' ? ""
2855 : ".nd",
2856 file);
2857 else
2858 fputs (".d", file);
2859 }
2860 return;
2861 case '?' : /* with leading "." */
2862 case '!' : /* without leading "." */
2863 /* This insn can be conditionally executed. See if the ccfsm machinery
2864 says it should be conditionalized.
2865 If it shouldn't, we'll check the compact attribute if this insn
2866 has a short variant, which may be used depending on code size and
2867 alignment considerations. */
2868 if (current_insn_predicate)
2869 arc_ccfsm_current.cc
2870 = get_arc_condition_code (current_insn_predicate);
2871 if (ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current))
2872 {
2873 /* Is this insn in a delay slot sequence? */
2874 if (!final_sequence || XVECLEN (final_sequence, 0) < 2
2875 || current_insn_predicate
68a1a6c0
DM
2876 || CALL_P (final_sequence->insn (0))
2877 || simplejump_p (final_sequence->insn (0)))
526b7aee
SV
2878 {
2879 /* This insn isn't in a delay slot sequence, or conditionalized
2880 independently of its position in a delay slot. */
2881 fprintf (file, "%s%s",
2882 code == '?' ? "." : "",
2883 arc_condition_codes[arc_ccfsm_current.cc]);
2884 /* If this is a jump, there are still short variants. However,
2885 only beq_s / bne_s have the same offset range as b_s,
2886 and the only short conditional returns are jeq_s and jne_s. */
2887 if (code == '!'
2888 && (arc_ccfsm_current.cc == ARC_CC_EQ
2889 || arc_ccfsm_current.cc == ARC_CC_NE
2890 || 0 /* FIXME: check if branch in 7 bit range. */))
2891 output_short_suffix (file);
2892 }
2893 else if (code == '!') /* Jump with delay slot. */
2894 fputs (arc_condition_codes[arc_ccfsm_current.cc], file);
2895 else /* An Instruction in a delay slot of a jump or call. */
2896 {
2897 rtx jump = XVECEXP (final_sequence, 0, 0);
2898 rtx insn = XVECEXP (final_sequence, 0, 1);
2899
2900 /* If the insn is annulled and is from the target path, we need
2901 to inverse the condition test. */
2902 if (JUMP_P (jump) && INSN_ANNULLED_BRANCH_P (jump))
2903 {
2904 if (INSN_FROM_TARGET_P (insn))
2905 fprintf (file, "%s%s",
2906 code == '?' ? "." : "",
2907 arc_condition_codes[ARC_INVERSE_CONDITION_CODE (arc_ccfsm_current.cc)]);
2908 else
2909 fprintf (file, "%s%s",
2910 code == '?' ? "." : "",
2911 arc_condition_codes[arc_ccfsm_current.cc]);
2912 if (arc_ccfsm_current.state == 5)
2913 arc_ccfsm_current.state = 0;
2914 }
2915 else
2916 /* This insn is executed for either path, so don't
2917 conditionalize it at all. */
2918 output_short_suffix (file);
2919
2920 }
2921 }
2922 else
2923 output_short_suffix (file);
2924 return;
2925 case'`':
2926 /* FIXME: fold constant inside unary operator, re-recognize, and emit. */
2927 gcc_unreachable ();
2928 case 'd' :
2929 fputs (arc_condition_codes[get_arc_condition_code (x)], file);
2930 return;
2931 case 'D' :
2932 fputs (arc_condition_codes[ARC_INVERSE_CONDITION_CODE
2933 (get_arc_condition_code (x))],
2934 file);
2935 return;
2936 case 'R' :
2937 /* Write second word of DImode or DFmode reference,
2938 register or memory. */
2939 if (GET_CODE (x) == REG)
2940 fputs (reg_names[REGNO (x)+1], file);
2941 else if (GET_CODE (x) == MEM)
2942 {
2943 fputc ('[', file);
2944
2945 /* Handle possible auto-increment. For PRE_INC / PRE_DEC /
2946 PRE_MODIFY, we will have handled the first word already;
2947 For POST_INC / POST_DEC / POST_MODIFY, the access to the
2948 first word will be done later. In either case, the access
2949 to the first word will do the modify, and we only have
2950 to add an offset of four here. */
2951 if (GET_CODE (XEXP (x, 0)) == PRE_INC
2952 || GET_CODE (XEXP (x, 0)) == PRE_DEC
2953 || GET_CODE (XEXP (x, 0)) == PRE_MODIFY
2954 || GET_CODE (XEXP (x, 0)) == POST_INC
2955 || GET_CODE (XEXP (x, 0)) == POST_DEC
2956 || GET_CODE (XEXP (x, 0)) == POST_MODIFY)
2957 output_address (plus_constant (Pmode, XEXP (XEXP (x, 0), 0), 4));
2958 else if (output_scaled)
2959 {
2960 rtx addr = XEXP (x, 0);
2961 int size = GET_MODE_SIZE (GET_MODE (x));
2962
2963 output_address (plus_constant (Pmode, XEXP (addr, 0),
2964 ((INTVAL (XEXP (addr, 1)) + 4)
2965 >> (size == 2 ? 1 : 2))));
2966 output_scaled = 0;
2967 }
2968 else
2969 output_address (plus_constant (Pmode, XEXP (x, 0), 4));
2970 fputc (']', file);
2971 }
2972 else
2973 output_operand_lossage ("invalid operand to %%R code");
2974 return;
2975 case 'S' :
2976 /* FIXME: remove %S option. */
2977 break;
2978 case 'B' /* Branch or other LIMM ref - must not use sda references. */ :
2979 if (CONSTANT_P (x))
2980 {
2981 output_addr_const (file, x);
2982 return;
2983 }
2984 break;
2985 case 'H' :
2986 case 'L' :
2987 if (GET_CODE (x) == REG)
2988 {
2989 /* L = least significant word, H = most significant word. */
2990 if ((WORDS_BIG_ENDIAN != 0) ^ (code == 'L'))
2991 fputs (reg_names[REGNO (x)], file);
2992 else
2993 fputs (reg_names[REGNO (x)+1], file);
2994 }
2995 else if (GET_CODE (x) == CONST_INT
2996 || GET_CODE (x) == CONST_DOUBLE)
2997 {
2998 rtx first, second;
2999
3000 split_double (x, &first, &second);
3001
3002 if((WORDS_BIG_ENDIAN) == 0)
dfca07ea 3003 fprintf (file, "0x%08" PRIx64,
526b7aee
SV
3004 code == 'L' ? INTVAL (first) : INTVAL (second));
3005 else
dfca07ea 3006 fprintf (file, "0x%08" PRIx64,
526b7aee
SV
3007 code == 'L' ? INTVAL (second) : INTVAL (first));
3008
3009
3010 }
3011 else
3012 output_operand_lossage ("invalid operand to %%H/%%L code");
3013 return;
3014 case 'A' :
3015 {
3016 char str[30];
3017
3018 gcc_assert (GET_CODE (x) == CONST_DOUBLE
3019 && GET_MODE_CLASS (GET_MODE (x)) == MODE_FLOAT);
3020
3021 real_to_decimal (str, CONST_DOUBLE_REAL_VALUE (x), sizeof (str), 0, 1);
3022 fprintf (file, "%s", str);
3023 return;
3024 }
3025 case 'U' :
3026 /* Output a load/store with update indicator if appropriate. */
3027 if (GET_CODE (x) == MEM)
3028 {
3029 rtx addr = XEXP (x, 0);
3030 switch (GET_CODE (addr))
3031 {
3032 case PRE_INC: case PRE_DEC: case PRE_MODIFY:
3033 fputs (".a", file); break;
3034 case POST_INC: case POST_DEC: case POST_MODIFY:
3035 fputs (".ab", file); break;
3036 case PLUS:
3037 /* Are we using a scaled index? */
3038 if (GET_CODE (XEXP (addr, 0)) == MULT)
3039 fputs (".as", file);
3040 /* Can we use a scaled offset? */
3041 else if (CONST_INT_P (XEXP (addr, 1))
3042 && GET_MODE_SIZE (GET_MODE (x)) > 1
3043 && (!(INTVAL (XEXP (addr, 1))
3044 & (GET_MODE_SIZE (GET_MODE (x)) - 1) & 3))
3045 /* Does it make a difference? */
3046 && !SMALL_INT_RANGE(INTVAL (XEXP (addr, 1)),
3047 GET_MODE_SIZE (GET_MODE (x)) - 2, 0))
3048 {
3049 fputs (".as", file);
3050 output_scaled = 1;
3051 }
3052 break;
3053 case REG:
3054 break;
3055 default:
3056 gcc_assert (CONSTANT_P (addr)); break;
3057 }
3058 }
3059 else
3060 output_operand_lossage ("invalid operand to %%U code");
3061 return;
3062 case 'V' :
3063 /* Output cache bypass indicator for a load/store insn. Volatile memory
3064 refs are defined to use the cache bypass mechanism. */
3065 if (GET_CODE (x) == MEM)
3066 {
3067 if (MEM_VOLATILE_P (x) && !TARGET_VOLATILE_CACHE_SET )
3068 fputs (".di", file);
3069 }
3070 else
3071 output_operand_lossage ("invalid operand to %%V code");
3072 return;
3073 /* plt code. */
3074 case 'P':
3075 case 0 :
3076 /* Do nothing special. */
3077 break;
3078 case 'F':
3079 fputs (reg_names[REGNO (x)]+1, file);
3080 return;
3081 case '^':
3082 /* This punctuation character is needed because label references are
3083 printed in the output template using %l. This is a front end
3084 character, and when we want to emit a '@' before it, we have to use
3085 this '^'. */
3086
3087 fputc('@',file);
3088 return;
3089 case 'O':
3090 /* Output an operator. */
3091 switch (GET_CODE (x))
3092 {
3093 case PLUS: fputs ("add", file); return;
3094 case SS_PLUS: fputs ("adds", file); return;
3095 case AND: fputs ("and", file); return;
3096 case IOR: fputs ("or", file); return;
3097 case XOR: fputs ("xor", file); return;
3098 case MINUS: fputs ("sub", file); return;
3099 case SS_MINUS: fputs ("subs", file); return;
3100 case ASHIFT: fputs ("asl", file); return;
3101 case ASHIFTRT: fputs ("asr", file); return;
3102 case LSHIFTRT: fputs ("lsr", file); return;
3103 case ROTATERT: fputs ("ror", file); return;
3104 case MULT: fputs ("mpy", file); return;
3105 case ABS: fputs ("abs", file); return; /* Unconditional. */
3106 case NEG: fputs ("neg", file); return;
3107 case SS_NEG: fputs ("negs", file); return;
3108 case NOT: fputs ("not", file); return; /* Unconditional. */
3109 case ZERO_EXTEND:
3110 fputs ("ext", file); /* bmsk allows predication. */
3111 goto size_suffix;
3112 case SIGN_EXTEND: /* Unconditional. */
3113 fputs ("sex", file);
3114 size_suffix:
3115 switch (GET_MODE (XEXP (x, 0)))
3116 {
3117 case QImode: fputs ("b", file); return;
3118 case HImode: fputs ("w", file); return;
3119 default: break;
3120 }
3121 break;
3122 case SS_TRUNCATE:
3123 if (GET_MODE (x) != HImode)
3124 break;
3125 fputs ("sat16", file);
3126 default: break;
3127 }
3128 output_operand_lossage ("invalid operand to %%O code"); return;
3129 case 'o':
3130 if (GET_CODE (x) == SYMBOL_REF)
3131 {
3132 assemble_name (file, XSTR (x, 0));
3133 return;
3134 }
3135 break;
3136 case '&':
3137 if (TARGET_ANNOTATE_ALIGN && cfun->machine->size_reason)
3138 fprintf (file, "; unalign: %d", cfun->machine->unalign);
3139 return;
3140 default :
3141 /* Unknown flag. */
3142 output_operand_lossage ("invalid operand output code");
3143 }
3144
3145 switch (GET_CODE (x))
3146 {
3147 case REG :
3148 fputs (reg_names[REGNO (x)], file);
3149 break;
3150 case MEM :
3151 {
3152 rtx addr = XEXP (x, 0);
3153 int size = GET_MODE_SIZE (GET_MODE (x));
3154
3155 fputc ('[', file);
3156
3157 switch (GET_CODE (addr))
3158 {
3159 case PRE_INC: case POST_INC:
3160 output_address (plus_constant (Pmode, XEXP (addr, 0), size)); break;
3161 case PRE_DEC: case POST_DEC:
3162 output_address (plus_constant (Pmode, XEXP (addr, 0), -size));
3163 break;
3164 case PRE_MODIFY: case POST_MODIFY:
3165 output_address (XEXP (addr, 1)); break;
3166 case PLUS:
3167 if (output_scaled)
3168 {
3169 output_address (plus_constant (Pmode, XEXP (addr, 0),
3170 (INTVAL (XEXP (addr, 1))
3171 >> (size == 2 ? 1 : 2))));
3172 output_scaled = 0;
3173 }
3174 else
3175 output_address (addr);
3176 break;
3177 default:
3178 if (flag_pic && CONSTANT_ADDRESS_P (addr))
3179 arc_output_pic_addr_const (file, addr, code);
3180 else
3181 output_address (addr);
3182 break;
3183 }
3184 fputc (']', file);
3185 break;
3186 }
3187 case CONST_DOUBLE :
3188 /* We handle SFmode constants here as output_addr_const doesn't. */
3189 if (GET_MODE (x) == SFmode)
3190 {
3191 REAL_VALUE_TYPE d;
3192 long l;
3193
3194 REAL_VALUE_FROM_CONST_DOUBLE (d, x);
3195 REAL_VALUE_TO_TARGET_SINGLE (d, l);
3196 fprintf (file, "0x%08lx", l);
3197 break;
3198 }
3199 /* Fall through. Let output_addr_const deal with it. */
3200 default :
3201 if (flag_pic)
3202 arc_output_pic_addr_const (file, x, code);
3203 else
3204 {
3205 /* FIXME: Dirty way to handle @var@sda+const. Shd be handled
3206 with asm_output_symbol_ref */
3207 if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS)
3208 {
3209 x = XEXP (x, 0);
3210 output_addr_const (file, XEXP (x, 0));
3211 if (GET_CODE (XEXP (x, 0)) == SYMBOL_REF && SYMBOL_REF_SMALL_P (XEXP (x, 0)))
3212 fprintf (file, "@sda");
3213
3214 if (GET_CODE (XEXP (x, 1)) != CONST_INT
3215 || INTVAL (XEXP (x, 1)) >= 0)
3216 fprintf (file, "+");
3217 output_addr_const (file, XEXP (x, 1));
3218 }
3219 else
3220 output_addr_const (file, x);
3221 }
3222 if (GET_CODE (x) == SYMBOL_REF && SYMBOL_REF_SMALL_P (x))
3223 fprintf (file, "@sda");
3224 break;
3225 }
3226}
3227
3228/* Print a memory address as an operand to reference that memory location. */
3229
3230void
3231arc_print_operand_address (FILE *file , rtx addr)
3232{
3233 register rtx base, index = 0;
3234
3235 switch (GET_CODE (addr))
3236 {
3237 case REG :
3238 fputs (reg_names[REGNO (addr)], file);
3239 break;
3240 case SYMBOL_REF :
3241 output_addr_const (file, addr);
3242 if (SYMBOL_REF_SMALL_P (addr))
3243 fprintf (file, "@sda");
3244 break;
3245 case PLUS :
3246 if (GET_CODE (XEXP (addr, 0)) == MULT)
3247 index = XEXP (XEXP (addr, 0), 0), base = XEXP (addr, 1);
3248 else if (CONST_INT_P (XEXP (addr, 0)))
3249 index = XEXP (addr, 0), base = XEXP (addr, 1);
3250 else
3251 base = XEXP (addr, 0), index = XEXP (addr, 1);
3252
3253 gcc_assert (OBJECT_P (base));
3254 arc_print_operand_address (file, base);
3255 if (CONSTANT_P (base) && CONST_INT_P (index))
3256 fputc ('+', file);
3257 else
3258 fputc (',', file);
3259 gcc_assert (OBJECT_P (index));
3260 arc_print_operand_address (file, index);
3261 break;
3262 case CONST:
3263 {
3264 rtx c = XEXP (addr, 0);
3265
3266 gcc_assert (GET_CODE (XEXP (c, 0)) == SYMBOL_REF);
3267 gcc_assert (GET_CODE (XEXP (c, 1)) == CONST_INT);
3268
3269 output_address(XEXP(addr,0));
3270
3271 break;
3272 }
3273 case PRE_INC :
3274 case PRE_DEC :
3275 /* We shouldn't get here as we've lost the mode of the memory object
3276 (which says how much to inc/dec by. */
3277 gcc_unreachable ();
3278 break;
3279 default :
3280 if (flag_pic)
3281 arc_output_pic_addr_const (file, addr, 0);
3282 else
3283 output_addr_const (file, addr);
3284 break;
3285 }
3286}
3287
3288/* Called via walk_stores. DATA points to a hash table we can use to
3289 establish a unique SYMBOL_REF for each counter, which corresponds to
3290 a caller-callee pair.
3291 X is a store which we want to examine for an UNSPEC_PROF, which
3292 would be an address loaded into a register, or directly used in a MEM.
3293 If we found an UNSPEC_PROF, if we encounter a new counter the first time,
3294 write out a description and a data allocation for a 32 bit counter.
3295 Also, fill in the appropriate symbol_ref into each UNSPEC_PROF instance. */
3296
3297static void
3298write_profile_sections (rtx dest ATTRIBUTE_UNUSED, rtx x, void *data)
3299{
3300 rtx *srcp, src;
3301 htab_t htab = (htab_t) data;
3302 rtx *slot;
3303
3304 if (GET_CODE (x) != SET)
3305 return;
3306 srcp = &SET_SRC (x);
3307 if (MEM_P (*srcp))
3308 srcp = &XEXP (*srcp, 0);
3309 else if (MEM_P (SET_DEST (x)))
3310 srcp = &XEXP (SET_DEST (x), 0);
3311 src = *srcp;
3312 if (GET_CODE (src) != CONST)
3313 return;
3314 src = XEXP (src, 0);
3315 if (GET_CODE (src) != UNSPEC || XINT (src, 1) != UNSPEC_PROF)
3316 return;
3317
3318 gcc_assert (XVECLEN (src, 0) == 3);
3319 if (!htab_elements (htab))
3320 {
3321 output_asm_insn (".section .__arc_profile_desc, \"a\"\n"
3322 "\t.long %0 + 1\n",
3323 &XVECEXP (src, 0, 0));
3324 }
3325 slot = (rtx *) htab_find_slot (htab, src, INSERT);
3326 if (*slot == HTAB_EMPTY_ENTRY)
3327 {
3328 static int count_nr;
3329 char buf[24];
3330 rtx count;
3331
3332 *slot = src;
3333 sprintf (buf, "__prof_count%d", count_nr++);
3334 count = gen_rtx_SYMBOL_REF (Pmode, xstrdup (buf));
3335 XVECEXP (src, 0, 2) = count;
3336 output_asm_insn (".section\t.__arc_profile_desc, \"a\"\n"
3337 "\t.long\t%1\n"
3338 "\t.section\t.__arc_profile_counters, \"aw\"\n"
3339 "\t.type\t%o2, @object\n"
3340 "\t.size\t%o2, 4\n"
3341 "%o2:\t.zero 4",
3342 &XVECEXP (src, 0, 0));
3343 *srcp = count;
3344 }
3345 else
3346 *srcp = XVECEXP (*slot, 0, 2);
3347}
3348
3349/* Hash function for UNSPEC_PROF htab. Use both the caller's name and
3350 the callee's name (if known). */
3351
3352static hashval_t
3353unspec_prof_hash (const void *x)
3354{
3355 const_rtx u = (const_rtx) x;
3356 const_rtx s1 = XVECEXP (u, 0, 1);
3357
3358 return (htab_hash_string (XSTR (XVECEXP (u, 0, 0), 0))
3359 ^ (s1->code == SYMBOL_REF ? htab_hash_string (XSTR (s1, 0)) : 0));
3360}
3361
3362/* Equality function for UNSPEC_PROF htab. Two pieces of UNSPEC_PROF rtl
3363 shall refer to the same counter if both caller name and callee rtl
3364 are identical. */
3365
3366static int
3367unspec_prof_htab_eq (const void *x, const void *y)
3368{
3369 const_rtx u0 = (const_rtx) x;
3370 const_rtx u1 = (const_rtx) y;
3371 const_rtx s01 = XVECEXP (u0, 0, 1);
3372 const_rtx s11 = XVECEXP (u1, 0, 1);
3373
3374 return (!strcmp (XSTR (XVECEXP (u0, 0, 0), 0),
3375 XSTR (XVECEXP (u1, 0, 0), 0))
3376 && rtx_equal_p (s01, s11));
3377}
3378
3379/* Conditional execution support.
3380
3381 This is based on the ARM port but for now is much simpler.
3382
3383 A finite state machine takes care of noticing whether or not instructions
3384 can be conditionally executed, and thus decrease execution time and code
3385 size by deleting branch instructions. The fsm is controlled by
3386 arc_ccfsm_advance (called by arc_final_prescan_insn), and controls the
3387 actions of PRINT_OPERAND. The patterns in the .md file for the branch
3388 insns also have a hand in this. */
3389/* The way we leave dealing with non-anulled or annull-false delay slot
3390 insns to the consumer is awkward. */
3391
3392/* The state of the fsm controlling condition codes are:
3393 0: normal, do nothing special
3394 1: don't output this insn
3395 2: don't output this insn
3396 3: make insns conditional
3397 4: make insns conditional
3398 5: make insn conditional (only for outputting anulled delay slot insns)
3399
3400 special value for cfun->machine->uid_ccfsm_state:
3401 6: return with but one insn before it since function start / call
3402
3403 State transitions (state->state by whom, under what condition):
3404 0 -> 1 arc_ccfsm_advance, if insn is a conditional branch skipping over
3405 some instructions.
3406 0 -> 2 arc_ccfsm_advance, if insn is a conditional branch followed
3407 by zero or more non-jump insns and an unconditional branch with
3408 the same target label as the condbranch.
3409 1 -> 3 branch patterns, after having not output the conditional branch
3410 2 -> 4 branch patterns, after having not output the conditional branch
3411 0 -> 5 branch patterns, for anulled delay slot insn.
3412 3 -> 0 ASM_OUTPUT_INTERNAL_LABEL, if the `target' label is reached
3413 (the target label has CODE_LABEL_NUMBER equal to
3414 arc_ccfsm_target_label).
3415 4 -> 0 arc_ccfsm_advance, if `target' unconditional branch is reached
3416 3 -> 1 arc_ccfsm_advance, finding an 'else' jump skipping over some insns.
3417 5 -> 0 when outputting the delay slot insn
3418
3419 If the jump clobbers the conditions then we use states 2 and 4.
3420
3421 A similar thing can be done with conditional return insns.
3422
3423 We also handle separating branches from sets of the condition code.
3424 This is done here because knowledge of the ccfsm state is required,
3425 we may not be outputting the branch. */
3426
3427/* arc_final_prescan_insn calls arc_ccfsm_advance to adjust arc_ccfsm_current,
3428 before letting final output INSN. */
3429
3430static void
b3458f61 3431arc_ccfsm_advance (rtx_insn *insn, struct arc_ccfsm *state)
526b7aee
SV
3432{
3433 /* BODY will hold the body of INSN. */
3434 register rtx body;
3435
3436 /* This will be 1 if trying to repeat the trick (ie: do the `else' part of
3437 an if/then/else), and things need to be reversed. */
3438 int reverse = 0;
3439
3440 /* If we start with a return insn, we only succeed if we find another one. */
3441 int seeking_return = 0;
3442
3443 /* START_INSN will hold the insn from where we start looking. This is the
3444 first insn after the following code_label if REVERSE is true. */
b3458f61 3445 rtx_insn *start_insn = insn;
526b7aee
SV
3446
3447 /* Type of the jump_insn. Brcc insns don't affect ccfsm changes,
3448 since they don't rely on a cmp preceding the. */
3449 enum attr_type jump_insn_type;
3450
3451 /* Allow -mdebug-ccfsm to turn this off so we can see how well it does.
3452 We can't do this in macro FINAL_PRESCAN_INSN because its called from
3453 final_scan_insn which has `optimize' as a local. */
3454 if (optimize < 2 || TARGET_NO_COND_EXEC)
3455 return;
3456
3457 /* Ignore notes and labels. */
3458 if (!INSN_P (insn))
3459 return;
3460 body = PATTERN (insn);
3461 /* If in state 4, check if the target branch is reached, in order to
3462 change back to state 0. */
3463 if (state->state == 4)
3464 {
3465 if (insn == state->target_insn)
3466 {
3467 state->target_insn = NULL;
3468 state->state = 0;
3469 }
3470 return;
3471 }
3472
3473 /* If in state 3, it is possible to repeat the trick, if this insn is an
3474 unconditional branch to a label, and immediately following this branch
3475 is the previous target label which is only used once, and the label this
3476 branch jumps to is not too far off. Or in other words "we've done the
3477 `then' part, see if we can do the `else' part." */
3478 if (state->state == 3)
3479 {
3480 if (simplejump_p (insn))
3481 {
3482 start_insn = next_nonnote_insn (start_insn);
3483 if (GET_CODE (start_insn) == BARRIER)
3484 {
3485 /* ??? Isn't this always a barrier? */
3486 start_insn = next_nonnote_insn (start_insn);
3487 }
3488 if (GET_CODE (start_insn) == CODE_LABEL
3489 && CODE_LABEL_NUMBER (start_insn) == state->target_label
3490 && LABEL_NUSES (start_insn) == 1)
3491 reverse = TRUE;
3492 else
3493 return;
3494 }
3495 else if (GET_CODE (body) == SIMPLE_RETURN)
3496 {
3497 start_insn = next_nonnote_insn (start_insn);
3498 if (GET_CODE (start_insn) == BARRIER)
3499 start_insn = next_nonnote_insn (start_insn);
3500 if (GET_CODE (start_insn) == CODE_LABEL
3501 && CODE_LABEL_NUMBER (start_insn) == state->target_label
3502 && LABEL_NUSES (start_insn) == 1)
3503 {
3504 reverse = TRUE;
3505 seeking_return = 1;
3506 }
3507 else
3508 return;
3509 }
3510 else
3511 return;
3512 }
3513
3514 if (GET_CODE (insn) != JUMP_INSN
3515 || GET_CODE (PATTERN (insn)) == ADDR_VEC
3516 || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC)
3517 return;
3518
3519 /* We can't predicate BRCC or loop ends.
3520 Also, when generating PIC code, and considering a medium range call,
3521 we can't predicate the call. */
3522 jump_insn_type = get_attr_type (insn);
3523 if (jump_insn_type == TYPE_BRCC
3524 || jump_insn_type == TYPE_BRCC_NO_DELAY_SLOT
3525 || jump_insn_type == TYPE_LOOP_END
3526 || (jump_insn_type == TYPE_CALL && !get_attr_predicable (insn)))
3527 return;
3528
3529 /* This jump might be paralleled with a clobber of the condition codes,
3530 the jump should always come first. */
3531 if (GET_CODE (body) == PARALLEL && XVECLEN (body, 0) > 0)
3532 body = XVECEXP (body, 0, 0);
3533
3534 if (reverse
3535 || (GET_CODE (body) == SET && GET_CODE (SET_DEST (body)) == PC
3536 && GET_CODE (SET_SRC (body)) == IF_THEN_ELSE))
3537 {
3538 int insns_skipped = 0, fail = FALSE, succeed = FALSE;
3539 /* Flag which part of the IF_THEN_ELSE is the LABEL_REF. */
3540 int then_not_else = TRUE;
3541 /* Nonzero if next insn must be the target label. */
3542 int next_must_be_target_label_p;
b3458f61
DM
3543 rtx_insn *this_insn = start_insn;
3544 rtx label = 0;
526b7aee
SV
3545
3546 /* Register the insn jumped to. */
3547 if (reverse)
3548 {
3549 if (!seeking_return)
3550 label = XEXP (SET_SRC (body), 0);
3551 }
3552 else if (GET_CODE (XEXP (SET_SRC (body), 1)) == LABEL_REF)
3553 label = XEXP (XEXP (SET_SRC (body), 1), 0);
3554 else if (GET_CODE (XEXP (SET_SRC (body), 2)) == LABEL_REF)
3555 {
3556 label = XEXP (XEXP (SET_SRC (body), 2), 0);
3557 then_not_else = FALSE;
3558 }
3559 else if (GET_CODE (XEXP (SET_SRC (body), 1)) == SIMPLE_RETURN)
3560 seeking_return = 1;
3561 else if (GET_CODE (XEXP (SET_SRC (body), 2)) == SIMPLE_RETURN)
3562 {
3563 seeking_return = 1;
3564 then_not_else = FALSE;
3565 }
3566 else
3567 gcc_unreachable ();
3568
3569 /* If this is a non-annulled branch with a delay slot, there is
3570 no need to conditionalize the delay slot. */
3571 if (NEXT_INSN (PREV_INSN (insn)) != insn
3572 && state->state == 0 && !INSN_ANNULLED_BRANCH_P (insn))
3573 {
3574 this_insn = NEXT_INSN (this_insn);
3575 gcc_assert (NEXT_INSN (NEXT_INSN (PREV_INSN (start_insn)))
3576 == NEXT_INSN (this_insn));
3577 }
3578 /* See how many insns this branch skips, and what kind of insns. If all
3579 insns are okay, and the label or unconditional branch to the same
3580 label is not too far away, succeed. */
3581 for (insns_skipped = 0, next_must_be_target_label_p = FALSE;
3582 !fail && !succeed && insns_skipped < MAX_INSNS_SKIPPED;
3583 insns_skipped++)
3584 {
3585 rtx scanbody;
3586
3587 this_insn = next_nonnote_insn (this_insn);
3588 if (!this_insn)
3589 break;
3590
3591 if (next_must_be_target_label_p)
3592 {
3593 if (GET_CODE (this_insn) == BARRIER)
3594 continue;
3595 if (GET_CODE (this_insn) == CODE_LABEL
3596 && this_insn == label)
3597 {
3598 state->state = 1;
3599 succeed = TRUE;
3600 }
3601 else
3602 fail = TRUE;
3603 break;
3604 }
3605
3606 scanbody = PATTERN (this_insn);
3607
3608 switch (GET_CODE (this_insn))
3609 {
3610 case CODE_LABEL:
3611 /* Succeed if it is the target label, otherwise fail since
3612 control falls in from somewhere else. */
3613 if (this_insn == label)
3614 {
3615 state->state = 1;
3616 succeed = TRUE;
3617 }
3618 else
3619 fail = TRUE;
3620 break;
3621
3622 case BARRIER:
3623 /* Succeed if the following insn is the target label.
3624 Otherwise fail.
3625 If return insns are used then the last insn in a function
3626 will be a barrier. */
3627 next_must_be_target_label_p = TRUE;
3628 break;
3629
3630 case CALL_INSN:
3631 /* Can handle a call insn if there are no insns after it.
3632 IE: The next "insn" is the target label. We don't have to
3633 worry about delay slots as such insns are SEQUENCE's inside
3634 INSN's. ??? It is possible to handle such insns though. */
3635 if (get_attr_cond (this_insn) == COND_CANUSE)
3636 next_must_be_target_label_p = TRUE;
3637 else
3638 fail = TRUE;
3639 break;
3640
3641 case JUMP_INSN:
3642 /* If this is an unconditional branch to the same label, succeed.
3643 If it is to another label, do nothing. If it is conditional,
3644 fail. */
3645 /* ??? Probably, the test for the SET and the PC are
3646 unnecessary. */
3647
3648 if (GET_CODE (scanbody) == SET
3649 && GET_CODE (SET_DEST (scanbody)) == PC)
3650 {
3651 if (GET_CODE (SET_SRC (scanbody)) == LABEL_REF
3652 && XEXP (SET_SRC (scanbody), 0) == label && !reverse)
3653 {
3654 state->state = 2;
3655 succeed = TRUE;
3656 }
3657 else if (GET_CODE (SET_SRC (scanbody)) == IF_THEN_ELSE)
3658 fail = TRUE;
3659 else if (get_attr_cond (this_insn) != COND_CANUSE)
3660 fail = TRUE;
3661 }
3662 else if (GET_CODE (scanbody) == SIMPLE_RETURN
3663 && seeking_return)
3664 {
3665 state->state = 2;
3666 succeed = TRUE;
3667 }
3668 else if (GET_CODE (scanbody) == PARALLEL)
3669 {
3670 if (get_attr_cond (this_insn) != COND_CANUSE)
3671 fail = TRUE;
3672 }
3673 break;
3674
3675 case INSN:
3676 /* We can only do this with insns that can use the condition
3677 codes (and don't set them). */
3678 if (GET_CODE (scanbody) == SET
3679 || GET_CODE (scanbody) == PARALLEL)
3680 {
3681 if (get_attr_cond (this_insn) != COND_CANUSE)
3682 fail = TRUE;
3683 }
3684 /* We can't handle other insns like sequences. */
3685 else
3686 fail = TRUE;
3687 break;
3688
3689 default:
3690 break;
3691 }
3692 }
3693
3694 if (succeed)
3695 {
3696 if ((!seeking_return) && (state->state == 1 || reverse))
3697 state->target_label = CODE_LABEL_NUMBER (label);
3698 else if (seeking_return || state->state == 2)
3699 {
3700 while (this_insn && GET_CODE (PATTERN (this_insn)) == USE)
3701 {
3702 this_insn = next_nonnote_insn (this_insn);
3703
3704 gcc_assert (!this_insn ||
3705 (GET_CODE (this_insn) != BARRIER
3706 && GET_CODE (this_insn) != CODE_LABEL));
3707 }
3708 if (!this_insn)
3709 {
3710 /* Oh dear! we ran off the end, give up. */
3711 extract_insn_cached (insn);
3712 state->state = 0;
3713 state->target_insn = NULL;
3714 return;
3715 }
3716 state->target_insn = this_insn;
3717 }
3718 else
3719 gcc_unreachable ();
3720
3721 /* If REVERSE is true, ARM_CURRENT_CC needs to be inverted from
3722 what it was. */
3723 if (!reverse)
3724 {
3725 state->cond = XEXP (SET_SRC (body), 0);
3726 state->cc = get_arc_condition_code (XEXP (SET_SRC (body), 0));
3727 }
3728
3729 if (reverse || then_not_else)
3730 state->cc = ARC_INVERSE_CONDITION_CODE (state->cc);
3731 }
3732
3733 /* Restore recog_operand. Getting the attributes of other insns can
3734 destroy this array, but final.c assumes that it remains intact
3735 across this call; since the insn has been recognized already we
3736 call insn_extract direct. */
3737 extract_insn_cached (insn);
3738 }
3739}
3740
3741/* Record that we are currently outputting label NUM with prefix PREFIX.
3742 It it's the label we're looking for, reset the ccfsm machinery.
3743
3744 Called from ASM_OUTPUT_INTERNAL_LABEL. */
3745
3746static void
3747arc_ccfsm_at_label (const char *prefix, int num, struct arc_ccfsm *state)
3748{
3749 if (state->state == 3 && state->target_label == num
3750 && !strcmp (prefix, "L"))
3751 {
3752 state->state = 0;
b3458f61 3753 state->target_insn = NULL;
526b7aee
SV
3754 }
3755}
3756
3757/* We are considering a conditional branch with the condition COND.
3758 Check if we want to conditionalize a delay slot insn, and if so modify
3759 the ccfsm state accordingly.
3760 REVERSE says branch will branch when the condition is false. */
3761void
b32d5189 3762arc_ccfsm_record_condition (rtx cond, bool reverse, rtx_insn *jump,
526b7aee
SV
3763 struct arc_ccfsm *state)
3764{
b3458f61 3765 rtx_insn *seq_insn = NEXT_INSN (PREV_INSN (jump));
526b7aee
SV
3766 if (!state)
3767 state = &arc_ccfsm_current;
3768
3769 gcc_assert (state->state == 0);
3770 if (seq_insn != jump)
3771 {
3772 rtx insn = XVECEXP (PATTERN (seq_insn), 0, 1);
3773
4654c0cf 3774 if (!as_a<rtx_insn *> (insn)->deleted ()
526b7aee
SV
3775 && INSN_ANNULLED_BRANCH_P (jump)
3776 && (TARGET_AT_DBR_CONDEXEC || INSN_FROM_TARGET_P (insn)))
3777 {
3778 state->cond = cond;
3779 state->cc = get_arc_condition_code (cond);
3780 if (!reverse)
3781 arc_ccfsm_current.cc
3782 = ARC_INVERSE_CONDITION_CODE (state->cc);
3783 rtx pat = PATTERN (insn);
3784 if (GET_CODE (pat) == COND_EXEC)
3785 gcc_assert ((INSN_FROM_TARGET_P (insn)
3786 ? ARC_INVERSE_CONDITION_CODE (state->cc) : state->cc)
3787 == get_arc_condition_code (XEXP (pat, 0)));
3788 else
3789 state->state = 5;
3790 }
3791 }
3792}
3793
3794/* Update *STATE as we would when we emit INSN. */
3795
3796static void
b3458f61 3797arc_ccfsm_post_advance (rtx_insn *insn, struct arc_ccfsm *state)
526b7aee 3798{
53ea364f
JR
3799 enum attr_type type;
3800
526b7aee
SV
3801 if (LABEL_P (insn))
3802 arc_ccfsm_at_label ("L", CODE_LABEL_NUMBER (insn), state);
3803 else if (JUMP_P (insn)
3804 && GET_CODE (PATTERN (insn)) != ADDR_VEC
3805 && GET_CODE (PATTERN (insn)) != ADDR_DIFF_VEC
53ea364f
JR
3806 && ((type = get_attr_type (insn)) == TYPE_BRANCH
3807 || (type == TYPE_UNCOND_BRANCH
1ea1e1b5
JR
3808 /* ??? Maybe should also handle TYPE_RETURN here,
3809 but we don't have a testcase for that. */
53ea364f 3810 && ARC_CCFSM_BRANCH_DELETED_P (state))))
526b7aee
SV
3811 {
3812 if (ARC_CCFSM_BRANCH_DELETED_P (state))
3813 ARC_CCFSM_RECORD_BRANCH_DELETED (state);
3814 else
3815 {
3816 rtx src = SET_SRC (PATTERN (insn));
3817 arc_ccfsm_record_condition (XEXP (src, 0), XEXP (src, 1) == pc_rtx,
3818 insn, state);
3819 }
3820 }
3821 else if (arc_ccfsm_current.state == 5)
3822 arc_ccfsm_current.state = 0;
3823}
3824
3825/* Return true if the current insn, which is a conditional branch, is to be
3826 deleted. */
3827
3828bool
3829arc_ccfsm_branch_deleted_p (void)
3830{
3831 return ARC_CCFSM_BRANCH_DELETED_P (&arc_ccfsm_current);
3832}
3833
3834/* Record a branch isn't output because subsequent insns can be
3835 conditionalized. */
3836
3837void
3838arc_ccfsm_record_branch_deleted (void)
3839{
3840 ARC_CCFSM_RECORD_BRANCH_DELETED (&arc_ccfsm_current);
3841}
3842
3843/* During insn output, indicate if the current insn is predicated. */
3844
3845bool
3846arc_ccfsm_cond_exec_p (void)
3847{
3848 return (cfun->machine->prescan_initialized
3849 && ARC_CCFSM_COND_EXEC_P (&arc_ccfsm_current));
3850}
3851
3852/* Like next_active_insn, but return NULL if we find an ADDR_(DIFF_)VEC,
3853 and look inside SEQUENCEs. */
3854
b3458f61
DM
3855static rtx_insn *
3856arc_next_active_insn (rtx_insn *insn, struct arc_ccfsm *statep)
526b7aee
SV
3857{
3858 rtx pat;
3859
3860 do
3861 {
3862 if (statep)
3863 arc_ccfsm_post_advance (insn, statep);
3864 insn = NEXT_INSN (insn);
3865 if (!insn || BARRIER_P (insn))
b3458f61 3866 return NULL;
526b7aee
SV
3867 if (statep)
3868 arc_ccfsm_advance (insn, statep);
3869 }
3870 while (NOTE_P (insn)
3871 || (cfun->machine->arc_reorg_started
3872 && LABEL_P (insn) && !label_to_alignment (insn))
3873 || (NONJUMP_INSN_P (insn)
3874 && (GET_CODE (PATTERN (insn)) == USE
3875 || GET_CODE (PATTERN (insn)) == CLOBBER)));
3876 if (!LABEL_P (insn))
3877 {
3878 gcc_assert (INSN_P (insn));
3879 pat = PATTERN (insn);
3880 if (GET_CODE (pat) == ADDR_VEC || GET_CODE (pat) == ADDR_DIFF_VEC)
b3458f61 3881 return NULL;
526b7aee 3882 if (GET_CODE (pat) == SEQUENCE)
b3458f61 3883 return as_a <rtx_insn *> (XVECEXP (pat, 0, 0));
526b7aee
SV
3884 }
3885 return insn;
3886}
3887
3888/* When deciding if an insn should be output short, we want to know something
3889 about the following insns:
3890 - if another insn follows which we know we can output as a short insn
3891 before an alignment-sensitive point, we can output this insn short:
3892 the decision about the eventual alignment can be postponed.
3893 - if a to-be-aligned label comes next, we should output this insn such
3894 as to get / preserve 4-byte alignment.
3895 - if a likely branch without delay slot insn, or a call with an immediately
3896 following short insn comes next, we should out output this insn such as to
3897 get / preserve 2 mod 4 unalignment.
3898 - do the same for a not completely unlikely branch with a short insn
3899 following before any other branch / label.
3900 - in order to decide if we are actually looking at a branch, we need to
3901 call arc_ccfsm_advance.
3902 - in order to decide if we are looking at a short insn, we should know
3903 if it is conditionalized. To a first order of approximation this is
3904 the case if the state from arc_ccfsm_advance from before this insn
3905 indicates the insn is conditionalized. However, a further refinement
3906 could be to not conditionalize an insn if the destination register(s)
3907 is/are dead in the non-executed case. */
3908/* Return non-zero if INSN should be output as a short insn. UNALIGN is
3909 zero if the current insn is aligned to a 4-byte-boundary, two otherwise.
3910 If CHECK_ATTR is greater than 0, check the iscompact attribute first. */
3911
3912int
b3458f61 3913arc_verify_short (rtx_insn *insn, int, int check_attr)
526b7aee
SV
3914{
3915 enum attr_iscompact iscompact;
3916 struct machine_function *machine;
3917
3918 if (check_attr > 0)
3919 {
3920 iscompact = get_attr_iscompact (insn);
3921 if (iscompact == ISCOMPACT_FALSE)
3922 return 0;
3923 }
3924 machine = cfun->machine;
3925
3926 if (machine->force_short_suffix >= 0)
3927 return machine->force_short_suffix;
3928
3929 return (get_attr_length (insn) & 2) != 0;
3930}
3931
3932/* When outputting an instruction (alternative) that can potentially be short,
3933 output the short suffix if the insn is in fact short, and update
3934 cfun->machine->unalign accordingly. */
3935
3936static void
3937output_short_suffix (FILE *file)
3938{
b3458f61 3939 rtx_insn *insn = current_output_insn;
526b7aee
SV
3940
3941 if (arc_verify_short (insn, cfun->machine->unalign, 1))
3942 {
3943 fprintf (file, "_s");
3944 cfun->machine->unalign ^= 2;
3945 }
3946 /* Restore recog_operand. */
3947 extract_insn_cached (insn);
3948}
3949
3950/* Implement FINAL_PRESCAN_INSN. */
3951
3952void
b3458f61 3953arc_final_prescan_insn (rtx_insn *insn, rtx *opvec ATTRIBUTE_UNUSED,
526b7aee
SV
3954 int noperands ATTRIBUTE_UNUSED)
3955{
3956 if (TARGET_DUMPISIZE)
3957 fprintf (asm_out_file, "\n; at %04x\n", INSN_ADDRESSES (INSN_UID (insn)));
3958
3959 /* Output a nop if necessary to prevent a hazard.
3960 Don't do this for delay slots: inserting a nop would
3961 alter semantics, and the only time we would find a hazard is for a
3962 call function result - and in that case, the hazard is spurious to
3963 start with. */
3964 if (PREV_INSN (insn)
3965 && PREV_INSN (NEXT_INSN (insn)) == insn
3966 && arc_hazard (prev_real_insn (insn), insn))
3967 {
3968 current_output_insn =
3969 emit_insn_before (gen_nop (), NEXT_INSN (PREV_INSN (insn)));
3970 final_scan_insn (current_output_insn, asm_out_file, optimize, 1, NULL);
b3458f61 3971 current_output_insn = insn;
526b7aee
SV
3972 }
3973 /* Restore extraction data which might have been clobbered by arc_hazard. */
3974 extract_constrain_insn_cached (insn);
3975
3976 if (!cfun->machine->prescan_initialized)
3977 {
3978 /* Clear lingering state from branch shortening. */
3979 memset (&arc_ccfsm_current, 0, sizeof arc_ccfsm_current);
3980 cfun->machine->prescan_initialized = 1;
3981 }
3982 arc_ccfsm_advance (insn, &arc_ccfsm_current);
3983
3984 cfun->machine->size_reason = 0;
3985}
3986
3987/* Given FROM and TO register numbers, say whether this elimination is allowed.
3988 Frame pointer elimination is automatically handled.
3989
3990 All eliminations are permissible. If we need a frame
3991 pointer, we must eliminate ARG_POINTER_REGNUM into
3992 FRAME_POINTER_REGNUM and not into STACK_POINTER_REGNUM. */
3993
3994static bool
3995arc_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
3996{
3997 return to == FRAME_POINTER_REGNUM || !arc_frame_pointer_required ();
3998}
3999
4000/* Define the offset between two registers, one to be eliminated, and
4001 the other its replacement, at the start of a routine. */
4002
4003int
4004arc_initial_elimination_offset (int from, int to)
4005{
4006 if (! cfun->machine->frame_info.initialized)
4007 arc_compute_frame_size (get_frame_size ());
4008
4009 if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
4010 {
4011 return (cfun->machine->frame_info.extra_size
4012 + cfun->machine->frame_info.reg_size);
4013 }
4014
4015 if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
4016 {
4017 return (cfun->machine->frame_info.total_size
4018 - cfun->machine->frame_info.pretend_size);
4019 }
4020
4021 if ((from == FRAME_POINTER_REGNUM) && (to == STACK_POINTER_REGNUM))
4022 {
4023 return (cfun->machine->frame_info.total_size
4024 - (cfun->machine->frame_info.pretend_size
4025 + cfun->machine->frame_info.extra_size
4026 + cfun->machine->frame_info.reg_size));
4027 }
4028
4029 gcc_unreachable ();
4030}
4031
4032static bool
4033arc_frame_pointer_required (void)
4034{
4035 return cfun->calls_alloca;
4036}
4037
4038
4039/* Return the destination address of a branch. */
4040
4041int
4042branch_dest (rtx branch)
4043{
4044 rtx pat = PATTERN (branch);
4045 rtx dest = (GET_CODE (pat) == PARALLEL
4046 ? SET_SRC (XVECEXP (pat, 0, 0)) : SET_SRC (pat));
4047 int dest_uid;
4048
4049 if (GET_CODE (dest) == IF_THEN_ELSE)
4050 dest = XEXP (dest, XEXP (dest, 1) == pc_rtx ? 2 : 1);
4051
4052 dest = XEXP (dest, 0);
4053 dest_uid = INSN_UID (dest);
4054
4055 return INSN_ADDRESSES (dest_uid);
4056}
4057
4058
5719867d 4059/* Implement TARGET_ENCODE_SECTION_INFO hook. */
526b7aee
SV
4060
4061static void
4062arc_encode_section_info (tree decl, rtx rtl, int first)
4063{
4064 /* For sdata, SYMBOL_FLAG_LOCAL and SYMBOL_FLAG_FUNCTION.
4065 This clears machine specific flags, so has to come first. */
4066 default_encode_section_info (decl, rtl, first);
4067
4068 /* Check if it is a function, and whether it has the
4069 [long/medium/short]_call attribute specified. */
4070 if (TREE_CODE (decl) == FUNCTION_DECL)
4071 {
4072 rtx symbol = XEXP (rtl, 0);
4073 int flags = SYMBOL_REF_FLAGS (symbol);
4074
4075 tree attr = (TREE_TYPE (decl) != error_mark_node
4076 ? TYPE_ATTRIBUTES (TREE_TYPE (decl)) : NULL_TREE);
4077 tree long_call_attr = lookup_attribute ("long_call", attr);
4078 tree medium_call_attr = lookup_attribute ("medium_call", attr);
4079 tree short_call_attr = lookup_attribute ("short_call", attr);
4080
4081 if (long_call_attr != NULL_TREE)
4082 flags |= SYMBOL_FLAG_LONG_CALL;
4083 else if (medium_call_attr != NULL_TREE)
4084 flags |= SYMBOL_FLAG_MEDIUM_CALL;
4085 else if (short_call_attr != NULL_TREE)
4086 flags |= SYMBOL_FLAG_SHORT_CALL;
4087
4088 SYMBOL_REF_FLAGS (symbol) = flags;
4089 }
4090}
4091
4092/* This is how to output a definition of an internal numbered label where
4093 PREFIX is the class of label and NUM is the number within the class. */
4094
4095static void arc_internal_label (FILE *stream, const char *prefix, unsigned long labelno)
4096{
4097 if (cfun)
4098 arc_ccfsm_at_label (prefix, labelno, &arc_ccfsm_current);
4099 default_internal_label (stream, prefix, labelno);
4100}
4101
4102/* Set the cpu type and print out other fancy things,
4103 at the top of the file. */
4104
4105static void arc_file_start (void)
4106{
4107 default_file_start ();
4108 fprintf (asm_out_file, "\t.cpu %s\n", arc_cpu_string);
4109}
4110
4111/* Cost functions. */
4112
4113/* Compute a (partial) cost for rtx X. Return true if the complete
4114 cost has been computed, and false if subexpressions should be
4115 scanned. In either case, *TOTAL contains the cost result. */
4116
4117static bool
4118arc_rtx_costs (rtx x, int code, int outer_code, int opno ATTRIBUTE_UNUSED,
4119 int *total, bool speed)
4120{
4121 switch (code)
4122 {
4123 /* Small integers are as cheap as registers. */
4124 case CONST_INT:
4125 {
4126 bool nolimm = false; /* Can we do without long immediate? */
4127 bool fast = false; /* Is the result available immediately? */
4128 bool condexec = false; /* Does this allow conditiobnal execution? */
4129 bool compact = false; /* Is a 16 bit opcode available? */
4130 /* CONDEXEC also implies that we can have an unconditional
4131 3-address operation. */
4132
4133 nolimm = compact = condexec = false;
4134 if (UNSIGNED_INT6 (INTVAL (x)))
4135 nolimm = condexec = compact = true;
4136 else
4137 {
4138 if (SMALL_INT (INTVAL (x)))
4139 nolimm = fast = true;
4140 switch (outer_code)
4141 {
4142 case AND: /* bclr, bmsk, ext[bw] */
4143 if (satisfies_constraint_Ccp (x) /* bclr */
4144 || satisfies_constraint_C1p (x) /* bmsk */)
4145 nolimm = fast = condexec = compact = true;
4146 break;
4147 case IOR: /* bset */
4148 if (satisfies_constraint_C0p (x)) /* bset */
4149 nolimm = fast = condexec = compact = true;
4150 break;
4151 case XOR:
4152 if (satisfies_constraint_C0p (x)) /* bxor */
4153 nolimm = fast = condexec = true;
4154 break;
4155 case SET:
4156 if (satisfies_constraint_Crr (x)) /* ror b,u6 */
4157 nolimm = true;
4158 default:
4159 break;
4160 }
4161 }
4162 /* FIXME: Add target options to attach a small cost if
4163 condexec / compact is not true. */
4164 if (nolimm)
4165 {
4166 *total = 0;
4167 return true;
4168 }
4169 }
4170 /* FALLTHRU */
4171
4172 /* 4 byte values can be fetched as immediate constants -
4173 let's give that the cost of an extra insn. */
4174 case CONST:
4175 case LABEL_REF:
4176 case SYMBOL_REF:
4177 *total = COSTS_N_INSNS (1);
4178 return true;
4179
4180 case CONST_DOUBLE:
4181 {
4182 rtx high, low;
4183
4184 if (TARGET_DPFP)
4185 {
4186 *total = COSTS_N_INSNS (1);
4187 return true;
4188 }
4189 /* FIXME: correct the order of high,low */
4190 split_double (x, &high, &low);
4191 *total = COSTS_N_INSNS (!SMALL_INT (INTVAL (high))
4192 + !SMALL_INT (INTVAL (low)));
4193 return true;
4194 }
4195
4196 /* Encourage synth_mult to find a synthetic multiply when reasonable.
4197 If we need more than 12 insns to do a multiply, then go out-of-line,
4198 since the call overhead will be < 10% of the cost of the multiply. */
4199 case ASHIFT:
4200 case ASHIFTRT:
4201 case LSHIFTRT:
4202 if (TARGET_BARREL_SHIFTER)
4203 {
4204 /* If we want to shift a constant, we need a LIMM. */
4205 /* ??? when the optimizers want to know if a constant should be
4206 hoisted, they ask for the cost of the constant. OUTER_CODE is
4207 insufficient context for shifts since we don't know which operand
4208 we are looking at. */
4209 if (CONSTANT_P (XEXP (x, 0)))
4210 {
4211 *total += (COSTS_N_INSNS (2)
4212 + rtx_cost (XEXP (x, 1), (enum rtx_code) code, 0, speed));
4213 return true;
4214 }
4215 *total = COSTS_N_INSNS (1);
4216 }
4217 else if (GET_CODE (XEXP (x, 1)) != CONST_INT)
4218 *total = COSTS_N_INSNS (16);
4219 else
4220 {
4221 *total = COSTS_N_INSNS (INTVAL (XEXP ((x), 1)));
4222 /* ??? want_to_gcse_p can throw negative shift counts at us,
4223 and then panics when it gets a negative cost as result.
4224 Seen for gcc.c-torture/compile/20020710-1.c -Os . */
4225 if (*total < 0)
4226 *total = 0;
4227 }
4228 return false;
4229
4230 case DIV:
4231 case UDIV:
4232 if (speed)
4233 *total = COSTS_N_INSNS(30);
4234 else
4235 *total = COSTS_N_INSNS(1);
4236 return false;
4237
4238 case MULT:
4239 if ((TARGET_DPFP && GET_MODE (x) == DFmode))
4240 *total = COSTS_N_INSNS (1);
4241 else if (speed)
4242 *total= arc_multcost;
4243 /* We do not want synth_mult sequences when optimizing
4244 for size. */
4245 else if (TARGET_MUL64_SET || (TARGET_ARC700 && !TARGET_NOMPY_SET))
4246 *total = COSTS_N_INSNS (1);
4247 else
4248 *total = COSTS_N_INSNS (2);
4249 return false;
4250 case PLUS:
4251 if (GET_CODE (XEXP (x, 0)) == MULT
4252 && _2_4_8_operand (XEXP (XEXP (x, 0), 1), VOIDmode))
4253 {
4254 *total += (rtx_cost (XEXP (x, 1), PLUS, 0, speed)
4255 + rtx_cost (XEXP (XEXP (x, 0), 0), PLUS, 1, speed));
4256 return true;
4257 }
4258 return false;
4259 case MINUS:
4260 if (GET_CODE (XEXP (x, 1)) == MULT
4261 && _2_4_8_operand (XEXP (XEXP (x, 1), 1), VOIDmode))
4262 {
4263 *total += (rtx_cost (XEXP (x, 0), PLUS, 0, speed)
4264 + rtx_cost (XEXP (XEXP (x, 1), 0), PLUS, 1, speed));
4265 return true;
4266 }
4267 return false;
4268 case COMPARE:
4269 {
4270 rtx op0 = XEXP (x, 0);
4271 rtx op1 = XEXP (x, 1);
4272
4273 if (GET_CODE (op0) == ZERO_EXTRACT && op1 == const0_rtx
4274 && XEXP (op0, 1) == const1_rtx)
4275 {
4276 /* btst / bbit0 / bbit1:
4277 Small integers and registers are free; everything else can
4278 be put in a register. */
4279 *total = (rtx_cost (XEXP (op0, 0), SET, 1, speed)
4280 + rtx_cost (XEXP (op0, 2), SET, 1, speed));
4281 return true;
4282 }
4283 if (GET_CODE (op0) == AND && op1 == const0_rtx
4284 && satisfies_constraint_C1p (XEXP (op0, 1)))
4285 {
4286 /* bmsk.f */
4287 *total = rtx_cost (XEXP (op0, 0), SET, 1, speed);
4288 return true;
4289 }
4290 /* add.f */
4291 if (GET_CODE (op1) == NEG)
4292 {
4293 /* op0 might be constant, the inside of op1 is rather
4294 unlikely to be so. So swapping the operands might lower
4295 the cost. */
4296 *total = (rtx_cost (op0, PLUS, 1, speed)
4297 + rtx_cost (XEXP (op1, 0), PLUS, 0, speed));
4298 }
4299 return false;
4300 }
4301 case EQ: case NE:
4302 if (outer_code == IF_THEN_ELSE
4303 && GET_CODE (XEXP (x, 0)) == ZERO_EXTRACT
4304 && XEXP (x, 1) == const0_rtx
4305 && XEXP (XEXP (x, 0), 1) == const1_rtx)
4306 {
4307 /* btst / bbit0 / bbit1:
4308 Small integers and registers are free; everything else can
4309 be put in a register. */
4310 rtx op0 = XEXP (x, 0);
4311
4312 *total = (rtx_cost (XEXP (op0, 0), SET, 1, speed)
4313 + rtx_cost (XEXP (op0, 2), SET, 1, speed));
4314 return true;
4315 }
4316 /* Fall through. */
4317 /* scc_insn expands into two insns. */
4318 case GTU: case GEU: case LEU:
4319 if (GET_MODE (x) == SImode)
4320 *total += COSTS_N_INSNS (1);
4321 return false;
4322 case LTU: /* might use adc. */
4323 if (GET_MODE (x) == SImode)
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"