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