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