1 /* Target Code for TI C6X
2    Copyright (C) 2010-2021 Free Software Foundation, Inc.
3    Contributed by Andrew Jenner <andrew@codesourcery.com>
4    Contributed by Bernd Schmidt <bernds@codesourcery.com>
5 
6    This file is part of GCC.
7 
8    GCC is free software; you can redistribute it and/or modify it
9    under the terms of the GNU General Public License as published
10    by the Free Software Foundation; either version 3, or (at your
11    option) any later version.
12 
13    GCC is distributed in the hope that it will be useful, but WITHOUT
14    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
15    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
16    License for more details.
17 
18    You should have received a copy of the GNU General Public License
19    along with GCC; see the file COPYING3.  If not see
20    <http://www.gnu.org/licenses/>.  */
21 
22 #define IN_TARGET_CODE 1
23 
24 #include "config.h"
25 #include "system.h"
26 #include "coretypes.h"
27 #include "backend.h"
28 #include "target.h"
29 #include "rtl.h"
30 #include "tree.h"
31 #include "gimple-expr.h"
32 #include "cfghooks.h"
33 #include "df.h"
34 #include "memmodel.h"
35 #include "tm_p.h"
36 #include "stringpool.h"
37 #include "attribs.h"
38 #include "optabs.h"
39 #include "regs.h"
40 #include "emit-rtl.h"
41 #include "recog.h"
42 #include "cgraph.h"
43 #include "diagnostic-core.h"
44 #include "stor-layout.h"
45 #include "varasm.h"
46 #include "calls.h"
47 #include "output.h"
48 #include "insn-attr.h"
49 #include "explow.h"
50 #include "expr.h"
51 #include "cfgrtl.h"
52 #include "sched-int.h"
53 #include "tm-constrs.h"
54 #include "langhooks.h"
55 #include "sel-sched.h"
56 #include "debug.h"
57 #include "hw-doloop.h"
58 #include "function-abi.h"
59 #include "regrename.h"
60 #include "dumpfile.h"
61 #include "builtins.h"
62 
63 /* This file should be included last.  */
64 #include "target-def.h"
65 
66 /* Table of supported architecture variants.  */
67 typedef struct
68 {
69   const char *arch;
70   enum c6x_cpu_type type;
71   unsigned short features;
72 } c6x_arch_table;
73 
74 /* A list of all ISAs, mapping each one to a representative device.
75    Used for -march selection.  */
76 static const c6x_arch_table all_isas[] =
77 {
78 #define C6X_ISA(NAME,DEVICE,FLAGS) \
79   { NAME, DEVICE, FLAGS },
80 #include "c6x-isas.def"
81 #undef C6X_ISA
82   { NULL, C6X_CPU_C62X, 0 }
83 };
84 
85 /* This is the parsed result of the "-march=" option, if given.  */
86 enum c6x_cpu_type c6x_arch = C6X_DEFAULT_ARCH;
87 
88 /* A mask of insn types that are allowed by the architecture selected by
89    the -march option.  */
90 unsigned long c6x_insn_mask = C6X_DEFAULT_INSN_MASK;
91 
92 /* The instruction that is being output (as obtained from FINAL_PRESCAN_INSN).
93  */
94 static rtx_insn *c6x_current_insn = NULL;
95 
96 /* A decl we build to access __c6xabi_DSBT_base.  */
97 static GTY(()) tree dsbt_decl;
98 
99 /* Determines whether we run our final scheduling pass or not.  We always
100    avoid the normal second scheduling pass.  */
101 static int c6x_flag_schedule_insns2;
102 
103 /* Determines whether we run variable tracking in machine dependent
104    reorganization.  */
105 static int c6x_flag_var_tracking;
106 
107 /* Determines whether we use modulo scheduling.  */
108 static int c6x_flag_modulo_sched;
109 
110 /* Record the state of flag_pic before we set it to 1 for DSBT.  */
111 int c6x_initial_flag_pic;
112 
113 typedef struct
114 {
115   /* We record the clock cycle for every insn during scheduling.  */
116   int clock;
117   /* After scheduling, we run assign_reservations to choose unit
118      reservations for all insns.  These are recorded here.  */
119   int reservation;
120   /* Records the new condition for insns which must be made
121      conditional after scheduling.  An entry of NULL_RTX means no such
122      change is necessary.  */
123   rtx new_cond;
124   /* True for the first insn that was scheduled in an ebb.  */
125   bool ebb_start;
126   /* The scheduler state after the insn, transformed into a mask of UNIT_QID
127      bits rather than storing the state.  Meaningful only for the last
128      insn in a cycle.  */
129   unsigned int unit_mask;
130 } c6x_sched_insn_info;
131 
132 
133 /* Record a c6x_sched_insn_info structure for every insn in the function.  */
134 static vec<c6x_sched_insn_info> insn_info;
135 
136 #define INSN_INFO_LENGTH (insn_info).length ()
137 #define INSN_INFO_ENTRY(N) (insn_info[(N)])
138 
139 static bool done_cfi_sections;
140 
141 #define RESERVATION_FLAG_D 1
142 #define RESERVATION_FLAG_L 2
143 #define RESERVATION_FLAG_S 4
144 #define RESERVATION_FLAG_M 8
145 #define RESERVATION_FLAG_DL (RESERVATION_FLAG_D | RESERVATION_FLAG_L)
146 #define RESERVATION_FLAG_DS (RESERVATION_FLAG_D | RESERVATION_FLAG_S)
147 #define RESERVATION_FLAG_LS (RESERVATION_FLAG_L | RESERVATION_FLAG_S)
148 #define RESERVATION_FLAG_DLS (RESERVATION_FLAG_D | RESERVATION_FLAG_LS)
149 
150 /* The DFA names of the units.  */
151 static const char *const c6x_unit_names[] =
152 {
153   "d1", "l1", "s1", "m1", "fps1", "fpl1", "adddps1", "adddpl1",
154   "d2", "l2", "s2", "m2", "fps2", "fpl2", "adddps2", "adddpl2"
155 };
156 
157 /* The DFA unit number for each unit in c6x_unit_names[].  */
158 static int c6x_unit_codes[ARRAY_SIZE (c6x_unit_names)];
159 
160 /* Unit query IDs.  */
161 #define UNIT_QID_D1 0
162 #define UNIT_QID_L1 1
163 #define UNIT_QID_S1 2
164 #define UNIT_QID_M1 3
165 #define UNIT_QID_FPS1 4
166 #define UNIT_QID_FPL1 5
167 #define UNIT_QID_ADDDPS1 6
168 #define UNIT_QID_ADDDPL1 7
169 #define UNIT_QID_SIDE_OFFSET 8
170 
171 #define RESERVATION_S1 2
172 #define RESERVATION_S2 10
173 
174 /* An enum for the unit requirements we count in the UNIT_REQS table.  */
175 enum unitreqs
176 {
177   UNIT_REQ_D,
178   UNIT_REQ_L,
179   UNIT_REQ_S,
180   UNIT_REQ_M,
181   UNIT_REQ_DL,
182   UNIT_REQ_DS,
183   UNIT_REQ_LS,
184   UNIT_REQ_DLS,
185   UNIT_REQ_T,
186   UNIT_REQ_X,
187   UNIT_REQ_MAX
188 };
189 
190 /* A table used to count unit requirements.  Used when computing minimum
191    iteration intervals.  */
192 typedef int unit_req_table[2][UNIT_REQ_MAX];
193 static unit_req_table unit_reqs;
194 
195 /* Register map for debugging.  */
196 unsigned const dbx_register_map[FIRST_PSEUDO_REGISTER] =
197 {
198   0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,	/* A0 - A15.  */
199   37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,	/* A16 - A32.  */
200   50, 51, 52,
201   16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,	/* B0 - B15.  */
202   29, 30, 31,
203   53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65,	/* B16 - B32.  */
204   66, 67, 68,
205   -1, -1, -1						/* FP, ARGP, ILC.  */
206 };
207 
208 /* Allocate a new, cleared machine_function structure.  */
209 
210 static struct machine_function *
c6x_init_machine_status(void)211 c6x_init_machine_status (void)
212 {
213   return ggc_cleared_alloc<machine_function> ();
214 }
215 
216 /* Implement TARGET_OPTION_OVERRIDE.  */
217 
218 static void
c6x_option_override(void)219 c6x_option_override (void)
220 {
221   unsigned i;
222 
223   if (global_options_set.x_c6x_arch_option)
224     {
225       c6x_arch = all_isas[c6x_arch_option].type;
226       c6x_insn_mask &= ~C6X_INSNS_ALL_CPU_BITS;
227       c6x_insn_mask |= all_isas[c6x_arch_option].features;
228     }
229 
230   c6x_flag_schedule_insns2 = flag_schedule_insns_after_reload;
231   flag_schedule_insns_after_reload = 0;
232 
233   c6x_flag_modulo_sched = flag_modulo_sched;
234   flag_modulo_sched = 0;
235 
236   init_machine_status = c6x_init_machine_status;
237 
238   for (i = 0; i < ARRAY_SIZE (c6x_unit_names); i++)
239     c6x_unit_codes[i] = get_cpu_unit_code (c6x_unit_names[i]);
240 
241   if (flag_pic && !TARGET_DSBT)
242     {
243       error ("%<-fpic%> and %<-fPIC%> not supported without %<-mdsbt%> "
244 	     "on this target");
245       flag_pic = 0;
246     }
247   c6x_initial_flag_pic = flag_pic;
248   if (TARGET_DSBT && !flag_pic)
249     flag_pic = 1;
250 }
251 
252 
253 /* Implement the TARGET_CONDITIONAL_REGISTER_USAGE hook.  */
254 
255 static void
c6x_conditional_register_usage(void)256 c6x_conditional_register_usage (void)
257 {
258   int i;
259   if (c6x_arch == C6X_CPU_C62X || c6x_arch == C6X_CPU_C67X)
260     for (i = 16; i < 32; i++)
261       {
262 	fixed_regs[i] = 1;
263 	fixed_regs[32 + i] = 1;
264       }
265   if (TARGET_INSNS_64)
266     {
267       SET_HARD_REG_BIT (reg_class_contents[(int)PREDICATE_A_REGS],
268 			REG_A0);
269       SET_HARD_REG_BIT (reg_class_contents[(int)PREDICATE_REGS],
270 			REG_A0);
271       CLEAR_HARD_REG_BIT (reg_class_contents[(int)NONPREDICATE_A_REGS],
272 			  REG_A0);
273       CLEAR_HARD_REG_BIT (reg_class_contents[(int)NONPREDICATE_REGS],
274 			  REG_A0);
275     }
276 }
277 
278 static GTY(()) rtx eqdf_libfunc;
279 static GTY(()) rtx nedf_libfunc;
280 static GTY(()) rtx ledf_libfunc;
281 static GTY(()) rtx ltdf_libfunc;
282 static GTY(()) rtx gedf_libfunc;
283 static GTY(()) rtx gtdf_libfunc;
284 static GTY(()) rtx eqsf_libfunc;
285 static GTY(()) rtx nesf_libfunc;
286 static GTY(()) rtx lesf_libfunc;
287 static GTY(()) rtx ltsf_libfunc;
288 static GTY(()) rtx gesf_libfunc;
289 static GTY(()) rtx gtsf_libfunc;
290 static GTY(()) rtx strasgi_libfunc;
291 static GTY(()) rtx strasgi64p_libfunc;
292 
293 /* Implement the TARGET_INIT_LIBFUNCS macro.  We use this to rename library
294    functions to match the C6x ABI.  */
295 
296 static void
c6x_init_libfuncs(void)297 c6x_init_libfuncs (void)
298 {
299   /* Double-precision floating-point arithmetic.  */
300   set_optab_libfunc (add_optab, DFmode, "__c6xabi_addd");
301   set_optab_libfunc (sdiv_optab, DFmode, "__c6xabi_divd");
302   set_optab_libfunc (smul_optab, DFmode, "__c6xabi_mpyd");
303   set_optab_libfunc (neg_optab, DFmode, "__c6xabi_negd");
304   set_optab_libfunc (sub_optab, DFmode, "__c6xabi_subd");
305 
306   /* Single-precision floating-point arithmetic.  */
307   set_optab_libfunc (add_optab, SFmode, "__c6xabi_addf");
308   set_optab_libfunc (sdiv_optab, SFmode, "__c6xabi_divf");
309   set_optab_libfunc (smul_optab, SFmode, "__c6xabi_mpyf");
310   set_optab_libfunc (neg_optab, SFmode, "__c6xabi_negf");
311   set_optab_libfunc (sub_optab, SFmode, "__c6xabi_subf");
312 
313   /* Floating-point comparisons.  */
314   eqsf_libfunc = init_one_libfunc ("__c6xabi_eqf");
315   nesf_libfunc = init_one_libfunc ("__c6xabi_neqf");
316   lesf_libfunc = init_one_libfunc ("__c6xabi_lef");
317   ltsf_libfunc = init_one_libfunc ("__c6xabi_ltf");
318   gesf_libfunc = init_one_libfunc ("__c6xabi_gef");
319   gtsf_libfunc = init_one_libfunc ("__c6xabi_gtf");
320   eqdf_libfunc = init_one_libfunc ("__c6xabi_eqd");
321   nedf_libfunc = init_one_libfunc ("__c6xabi_neqd");
322   ledf_libfunc = init_one_libfunc ("__c6xabi_led");
323   ltdf_libfunc = init_one_libfunc ("__c6xabi_ltd");
324   gedf_libfunc = init_one_libfunc ("__c6xabi_ged");
325   gtdf_libfunc = init_one_libfunc ("__c6xabi_gtd");
326 
327   set_optab_libfunc (eq_optab, SFmode, NULL);
328   set_optab_libfunc (ne_optab, SFmode, "__c6xabi_neqf");
329   set_optab_libfunc (gt_optab, SFmode, NULL);
330   set_optab_libfunc (ge_optab, SFmode, NULL);
331   set_optab_libfunc (lt_optab, SFmode, NULL);
332   set_optab_libfunc (le_optab, SFmode, NULL);
333   set_optab_libfunc (unord_optab, SFmode, "__c6xabi_unordf");
334   set_optab_libfunc (eq_optab, DFmode, NULL);
335   set_optab_libfunc (ne_optab, DFmode, "__c6xabi_neqd");
336   set_optab_libfunc (gt_optab, DFmode, NULL);
337   set_optab_libfunc (ge_optab, DFmode, NULL);
338   set_optab_libfunc (lt_optab, DFmode, NULL);
339   set_optab_libfunc (le_optab, DFmode, NULL);
340   set_optab_libfunc (unord_optab, DFmode, "__c6xabi_unordd");
341 
342   /* Floating-point to integer conversions.  */
343   set_conv_libfunc (sfix_optab, SImode, DFmode, "__c6xabi_fixdi");
344   set_conv_libfunc (ufix_optab, SImode, DFmode, "__c6xabi_fixdu");
345   set_conv_libfunc (sfix_optab, DImode, DFmode, "__c6xabi_fixdlli");
346   set_conv_libfunc (ufix_optab, DImode, DFmode, "__c6xabi_fixdull");
347   set_conv_libfunc (sfix_optab, SImode, SFmode, "__c6xabi_fixfi");
348   set_conv_libfunc (ufix_optab, SImode, SFmode, "__c6xabi_fixfu");
349   set_conv_libfunc (sfix_optab, DImode, SFmode, "__c6xabi_fixflli");
350   set_conv_libfunc (ufix_optab, DImode, SFmode, "__c6xabi_fixfull");
351 
352   /* Conversions between floating types.  */
353   set_conv_libfunc (trunc_optab, SFmode, DFmode, "__c6xabi_cvtdf");
354   set_conv_libfunc (sext_optab, DFmode, SFmode, "__c6xabi_cvtfd");
355 
356   /* Integer to floating-point conversions.  */
357   set_conv_libfunc (sfloat_optab, DFmode, SImode, "__c6xabi_fltid");
358   set_conv_libfunc (ufloat_optab, DFmode, SImode, "__c6xabi_fltud");
359   set_conv_libfunc (sfloat_optab, DFmode, DImode, "__c6xabi_fltllid");
360   set_conv_libfunc (ufloat_optab, DFmode, DImode, "__c6xabi_fltulld");
361   set_conv_libfunc (sfloat_optab, SFmode, SImode, "__c6xabi_fltif");
362   set_conv_libfunc (ufloat_optab, SFmode, SImode, "__c6xabi_fltuf");
363   set_conv_libfunc (sfloat_optab, SFmode, DImode, "__c6xabi_fltllif");
364   set_conv_libfunc (ufloat_optab, SFmode, DImode, "__c6xabi_fltullf");
365 
366   /* Long long.  */
367   set_optab_libfunc (smul_optab, DImode, "__c6xabi_mpyll");
368   set_optab_libfunc (ashl_optab, DImode, "__c6xabi_llshl");
369   set_optab_libfunc (lshr_optab, DImode, "__c6xabi_llshru");
370   set_optab_libfunc (ashr_optab, DImode, "__c6xabi_llshr");
371 
372   set_optab_libfunc (sdiv_optab, SImode, "__c6xabi_divi");
373   set_optab_libfunc (udiv_optab, SImode, "__c6xabi_divu");
374   set_optab_libfunc (smod_optab, SImode, "__c6xabi_remi");
375   set_optab_libfunc (umod_optab, SImode, "__c6xabi_remu");
376   set_optab_libfunc (sdivmod_optab, SImode, "__c6xabi_divremi");
377   set_optab_libfunc (udivmod_optab, SImode, "__c6xabi_divremu");
378   set_optab_libfunc (sdiv_optab, DImode, "__c6xabi_divlli");
379   set_optab_libfunc (udiv_optab, DImode, "__c6xabi_divull");
380   set_optab_libfunc (smod_optab, DImode, "__c6xabi_remlli");
381   set_optab_libfunc (umod_optab, DImode, "__c6xabi_remull");
382   set_optab_libfunc (udivmod_optab, DImode, "__c6xabi_divremull");
383 
384   /* Block move.  */
385   strasgi_libfunc = init_one_libfunc ("__c6xabi_strasgi");
386   strasgi64p_libfunc = init_one_libfunc ("__c6xabi_strasgi_64plus");
387 }
388 
389 /* Begin the assembly file.  */
390 
391 static void
c6x_file_start(void)392 c6x_file_start (void)
393 {
394   /* Variable tracking should be run after all optimizations which change order
395      of insns.  It also needs a valid CFG.  This can't be done in
396      c6x_override_options, because flag_var_tracking is finalized after
397      that.  */
398   c6x_flag_var_tracking = flag_var_tracking;
399   flag_var_tracking = 0;
400 
401   done_cfi_sections = false;
402   default_file_start ();
403 
404   /* Arrays are aligned to 8-byte boundaries.  */
405   asm_fprintf (asm_out_file,
406 	       "\t.c6xabi_attribute Tag_ABI_array_object_alignment, 0\n");
407   asm_fprintf (asm_out_file,
408 	       "\t.c6xabi_attribute Tag_ABI_array_object_align_expected, 0\n");
409 
410   /* Stack alignment is 8 bytes.  */
411   asm_fprintf (asm_out_file,
412 	       "\t.c6xabi_attribute Tag_ABI_stack_align_needed, 0\n");
413   asm_fprintf (asm_out_file,
414 	       "\t.c6xabi_attribute Tag_ABI_stack_align_preserved, 0\n");
415 
416 #if 0 /* FIXME: Reenable when TI's tools are fixed.  */
417   /* ??? Ideally we'd check flag_short_wchar somehow.  */
418   asm_fprintf (asm_out_file, "\t.c6xabi_attribute Tag_ABI_wchar_t, %d\n", 2);
419 #endif
420 
421   /* We conform to version 1.0 of the ABI.  */
422   asm_fprintf (asm_out_file,
423 	       "\t.c6xabi_attribute Tag_ABI_conformance, \"1.0\"\n");
424 
425 }
426 
427 /* The LTO frontend only enables exceptions when it sees a function that
428    uses it.  This changes the return value of dwarf2out_do_frame, so we
429    have to check before every function.  */
430 
431 void
c6x_output_file_unwind(FILE * f)432 c6x_output_file_unwind (FILE * f)
433 {
434   if (done_cfi_sections)
435     return;
436 
437   /* Output a .cfi_sections directive.  */
438   if (dwarf2out_do_frame ())
439     {
440       if (flag_unwind_tables || flag_exceptions)
441 	{
442 	  if (write_symbols == DWARF2_DEBUG
443 	      || write_symbols == VMS_AND_DWARF2_DEBUG)
444 	    asm_fprintf (f, "\t.cfi_sections .debug_frame, .c6xabi.exidx\n");
445 	  else
446 	    asm_fprintf (f, "\t.cfi_sections .c6xabi.exidx\n");
447 	}
448       else
449 	asm_fprintf (f, "\t.cfi_sections .debug_frame\n");
450       done_cfi_sections = true;
451     }
452 }
453 
454 /* Output unwind directives at the end of a function.  */
455 
456 static void
c6x_output_fn_unwind(FILE * f)457 c6x_output_fn_unwind (FILE * f)
458 {
459   /* Return immediately if we are not generating unwinding tables.  */
460   if (! (flag_unwind_tables || flag_exceptions))
461     return;
462 
463   /* If this function will never be unwound, then mark it as such.  */
464   if (!(flag_unwind_tables || crtl->uses_eh_lsda)
465       && (TREE_NOTHROW (current_function_decl)
466 	  || crtl->all_throwers_are_sibcalls))
467     fputs("\t.cantunwind\n", f);
468 
469   fputs ("\t.endp\n", f);
470 }
471 
472 
473 /* Stack and Calling.  */
474 
475 int argument_registers[10] =
476 {
477   REG_A4, REG_B4,
478   REG_A6, REG_B6,
479   REG_A8, REG_B8,
480   REG_A10, REG_B10,
481   REG_A12, REG_B12
482 };
483 
484 /* Implements the macro INIT_CUMULATIVE_ARGS defined in c6x.h.  */
485 
486 void
c6x_init_cumulative_args(CUMULATIVE_ARGS * cum,const_tree fntype,rtx libname,int n_named_args ATTRIBUTE_UNUSED)487 c6x_init_cumulative_args (CUMULATIVE_ARGS *cum, const_tree fntype, rtx libname,
488 			  int n_named_args ATTRIBUTE_UNUSED)
489 {
490   cum->count = 0;
491   cum->nregs = 10;
492   if (!libname && fntype)
493     {
494       /* We need to find out the number of named arguments.  Unfortunately,
495 	 for incoming arguments, N_NAMED_ARGS is set to -1.  */
496       if (stdarg_p (fntype))
497 	cum->nregs = type_num_arguments (fntype) - 1;
498       if (cum->nregs > 10)
499 	cum->nregs = 10;
500     }
501 }
502 
503 /* Implement TARGET_FUNCTION_ARG.  */
504 
505 static rtx
c6x_function_arg(cumulative_args_t cum_v,const function_arg_info & arg)506 c6x_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
507 {
508   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
509   if (cum->count >= cum->nregs)
510     return NULL_RTX;
511   if (tree type = arg.type)
512     {
513       HOST_WIDE_INT size = int_size_in_bytes (type);
514       if (TARGET_BIG_ENDIAN && AGGREGATE_TYPE_P (type))
515 	{
516 	  if (size > 4)
517 	    {
518 	      rtx reg1 = gen_rtx_REG (SImode, argument_registers[cum->count] + 1);
519 	      rtx reg2 = gen_rtx_REG (SImode, argument_registers[cum->count]);
520 	      rtvec vec = gen_rtvec (2, gen_rtx_EXPR_LIST (VOIDmode, reg1, const0_rtx),
521 				     gen_rtx_EXPR_LIST (VOIDmode, reg2, GEN_INT (4)));
522 	      return gen_rtx_PARALLEL (arg.mode, vec);
523 	    }
524 	}
525     }
526   return gen_rtx_REG (arg.mode, argument_registers[cum->count]);
527 }
528 
529 static void
c6x_function_arg_advance(cumulative_args_t cum_v,const function_arg_info &)530 c6x_function_arg_advance (cumulative_args_t cum_v, const function_arg_info &)
531 {
532   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
533   cum->count++;
534 }
535 
536 
537 /* Return true if BLOCK_REG_PADDING (MODE, TYPE, FIRST) should return
538    upward rather than downward.  */
539 
540 bool
c6x_block_reg_pad_upward(machine_mode mode ATTRIBUTE_UNUSED,const_tree type,bool first)541 c6x_block_reg_pad_upward (machine_mode mode ATTRIBUTE_UNUSED,
542 			  const_tree type, bool first)
543 {
544   HOST_WIDE_INT size;
545 
546   if (!TARGET_BIG_ENDIAN)
547     return true;
548   if (!first)
549     return true;
550   if (!type)
551     return true;
552   size = int_size_in_bytes (type);
553   return size == 3;
554 }
555 
556 /* Implement TARGET_FUNCTION_ARG_BOUNDARY.  */
557 
558 static unsigned int
c6x_function_arg_boundary(machine_mode mode,const_tree type)559 c6x_function_arg_boundary (machine_mode mode, const_tree type)
560 {
561   unsigned int boundary = type ? TYPE_ALIGN (type) : GET_MODE_BITSIZE (mode);
562 
563   if (boundary > BITS_PER_WORD)
564     return 2 * BITS_PER_WORD;
565 
566   if (mode == BLKmode)
567     {
568       HOST_WIDE_INT size = int_size_in_bytes (type);
569       if (size > 4)
570 	return 2 * BITS_PER_WORD;
571       if (boundary < BITS_PER_WORD)
572 	{
573 	  if (size >= 3)
574 	    return BITS_PER_WORD;
575 	  if (size >= 2)
576 	    return 2 * BITS_PER_UNIT;
577 	}
578     }
579   return boundary;
580 }
581 
582 /* Implement TARGET_FUNCTION_ARG_ROUND_BOUNDARY.  */
583 static unsigned int
c6x_function_arg_round_boundary(machine_mode mode,const_tree type)584 c6x_function_arg_round_boundary (machine_mode mode, const_tree type)
585 {
586   return c6x_function_arg_boundary (mode, type);
587 }
588 
589 /* TARGET_FUNCTION_VALUE implementation.  Returns an RTX representing the place
590    where function FUNC returns or receives a value of data type TYPE.  */
591 
592 static rtx
c6x_function_value(const_tree type,const_tree func ATTRIBUTE_UNUSED,bool outgoing ATTRIBUTE_UNUSED)593 c6x_function_value (const_tree type, const_tree func ATTRIBUTE_UNUSED,
594 		    bool outgoing ATTRIBUTE_UNUSED)
595 {
596   /* Functions return values in register A4.  When returning aggregates, we may
597      have to adjust for endianness.  */
598   if (TARGET_BIG_ENDIAN && type && AGGREGATE_TYPE_P (type))
599     {
600       HOST_WIDE_INT size = int_size_in_bytes (type);
601       if (size > 4)
602 	{
603 
604 	  rtx reg1 = gen_rtx_REG (SImode, REG_A4 + 1);
605 	  rtx reg2 = gen_rtx_REG (SImode, REG_A4);
606 	  rtvec vec = gen_rtvec (2, gen_rtx_EXPR_LIST (VOIDmode, reg1, const0_rtx),
607 				 gen_rtx_EXPR_LIST (VOIDmode, reg2, GEN_INT (4)));
608 	  return gen_rtx_PARALLEL (TYPE_MODE (type), vec);
609 	}
610     }
611   return gen_rtx_REG (TYPE_MODE (type), REG_A4);
612 }
613 
614 /* Implement TARGET_LIBCALL_VALUE.  */
615 
616 static rtx
c6x_libcall_value(machine_mode mode,const_rtx fun ATTRIBUTE_UNUSED)617 c6x_libcall_value (machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
618 {
619   return gen_rtx_REG (mode, REG_A4);
620 }
621 
622 /* TARGET_STRUCT_VALUE_RTX implementation.  */
623 
624 static rtx
c6x_struct_value_rtx(tree type ATTRIBUTE_UNUSED,int incoming ATTRIBUTE_UNUSED)625 c6x_struct_value_rtx (tree type ATTRIBUTE_UNUSED, int incoming ATTRIBUTE_UNUSED)
626 {
627   return gen_rtx_REG (Pmode, REG_A3);
628 }
629 
630 /* Implement TARGET_FUNCTION_VALUE_REGNO_P.  */
631 
632 static bool
c6x_function_value_regno_p(const unsigned int regno)633 c6x_function_value_regno_p (const unsigned int regno)
634 {
635   return regno == REG_A4;
636 }
637 
638 /* Types larger than 64 bit, and variable sized types, are passed by
639    reference.  The callee must copy them; see TARGET_CALLEE_COPIES.  */
640 
641 static bool
c6x_pass_by_reference(cumulative_args_t,const function_arg_info & arg)642 c6x_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
643 {
644   int size = -1;
645   if (arg.type)
646     size = int_size_in_bytes (arg.type);
647   else if (arg.mode != VOIDmode)
648     size = GET_MODE_SIZE (arg.mode);
649   return size > 2 * UNITS_PER_WORD || size == -1;
650 }
651 
652 /* Decide whether a type should be returned in memory (true)
653    or in a register (false).  This is called by the macro
654    TARGET_RETURN_IN_MEMORY.  */
655 
656 static bool
c6x_return_in_memory(const_tree type,const_tree fntype ATTRIBUTE_UNUSED)657 c6x_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
658 {
659   int size = int_size_in_bytes (type);
660   return size > 2 * UNITS_PER_WORD || size == -1;
661 }
662 
663 /* Values which must be returned in the most-significant end of the return
664    register.  */
665 
666 static bool
c6x_return_in_msb(const_tree valtype)667 c6x_return_in_msb (const_tree valtype)
668 {
669   HOST_WIDE_INT size = int_size_in_bytes (valtype);
670   return TARGET_BIG_ENDIAN && AGGREGATE_TYPE_P (valtype) && size == 3;
671 }
672 
673 /* Return the type to use as __builtin_va_list.  */
674 static tree
c6x_build_builtin_va_list(void)675 c6x_build_builtin_va_list (void)
676 {
677   return build_pointer_type (char_type_node);
678 }
679 
680 static void
c6x_asm_trampoline_template(FILE * f)681 c6x_asm_trampoline_template (FILE *f)
682 {
683   fprintf (f, "\t.long\t0x0000002b\n"); /* mvkl .s2 fnlow,B0 */
684   fprintf (f, "\t.long\t0x01000028\n"); /* || mvkl .s1 sclow,A2 */
685   fprintf (f, "\t.long\t0x0000006b\n"); /* mvkh .s2 fnhigh,B0 */
686   fprintf (f, "\t.long\t0x01000068\n"); /* || mvkh .s1 schigh,A2 */
687   fprintf (f, "\t.long\t0x00000362\n"); /* b .s2 B0 */
688   fprintf (f, "\t.long\t0x00008000\n"); /* nop 5 */
689   fprintf (f, "\t.long\t0x00000000\n"); /* nop */
690   fprintf (f, "\t.long\t0x00000000\n"); /* nop */
691 }
692 
693 /* Emit RTL insns to initialize the variable parts of a trampoline at
694    TRAMP. FNADDR is an RTX for the address of the function's pure
695    code.  CXT is an RTX for the static chain value for the function.  */
696 
697 static void
c6x_initialize_trampoline(rtx tramp,tree fndecl,rtx cxt)698 c6x_initialize_trampoline (rtx tramp, tree fndecl, rtx cxt)
699 {
700   rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
701   rtx t1 = copy_to_reg (fnaddr);
702   rtx t2 = copy_to_reg (cxt);
703   rtx mask = gen_reg_rtx (SImode);
704   int i;
705 
706   emit_block_move (tramp, assemble_trampoline_template (),
707 		   GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
708 
709   emit_move_insn (mask, GEN_INT (0xffff << 7));
710 
711   for (i = 0; i < 4; i++)
712     {
713       rtx mem = adjust_address (tramp, SImode, i * 4);
714       rtx t = (i & 1) ? t2 : t1;
715       rtx v1 = gen_reg_rtx (SImode);
716       rtx v2 = gen_reg_rtx (SImode);
717       emit_move_insn (v1, mem);
718       if (i < 2)
719 	emit_insn (gen_ashlsi3 (v2, t, GEN_INT (7)));
720       else
721 	emit_insn (gen_lshrsi3 (v2, t, GEN_INT (9)));
722       emit_insn (gen_andsi3 (v2, v2, mask));
723       emit_insn (gen_iorsi3 (v2, v2, v1));
724       emit_move_insn (mem, v2);
725     }
726 #ifdef CLEAR_INSN_CACHE
727   tramp = XEXP (tramp, 0);
728   maybe_emit_call_builtin___clear_cache (tramp,
729 					 plus_constant (Pmode,
730 							tramp,
731 							TRAMPOLINE_SIZE));
732 #endif
733 }
734 
735 /* Determine whether c6x_output_mi_thunk can succeed.  */
736 
737 static bool
c6x_can_output_mi_thunk(const_tree thunk ATTRIBUTE_UNUSED,HOST_WIDE_INT delta ATTRIBUTE_UNUSED,HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,const_tree function ATTRIBUTE_UNUSED)738 c6x_can_output_mi_thunk (const_tree thunk ATTRIBUTE_UNUSED,
739 			 HOST_WIDE_INT delta ATTRIBUTE_UNUSED,
740 			 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
741 			 const_tree function ATTRIBUTE_UNUSED)
742 {
743   return !TARGET_LONG_CALLS;
744 }
745 
746 /* Output the assembler code for a thunk function.  THUNK is the
747    declaration for the thunk function itself, FUNCTION is the decl for
748    the target function.  DELTA is an immediate constant offset to be
749    added to THIS.  If VCALL_OFFSET is nonzero, the word at
750    *(*this + vcall_offset) should be added to THIS.  */
751 
752 static void
c6x_output_mi_thunk(FILE * file ATTRIBUTE_UNUSED,tree thunk ATTRIBUTE_UNUSED,HOST_WIDE_INT delta,HOST_WIDE_INT vcall_offset,tree function)753 c6x_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
754 		     tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
755 		     HOST_WIDE_INT vcall_offset, tree function)
756 {
757   const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk));
758   rtx xops[5];
759   /* The this parameter is passed as the first argument.  */
760   rtx this_rtx = gen_rtx_REG (Pmode, REG_A4);
761 
762   assemble_start_function (thunk, fnname);
763   c6x_current_insn = NULL;
764 
765   xops[4] = XEXP (DECL_RTL (function), 0);
766   if (!vcall_offset)
767     {
768       output_asm_insn ("b .s2 \t%4", xops);
769       if (!delta)
770 	output_asm_insn ("nop 5", xops);
771     }
772 
773   /* Adjust the this parameter by a fixed constant.  */
774   if (delta)
775     {
776       xops[0] = GEN_INT (delta);
777       xops[1] = this_rtx;
778       if (delta >= -16 && delta <= 15)
779 	{
780 	  output_asm_insn ("add .s1 %0, %1, %1", xops);
781 	  if (!vcall_offset)
782 	    output_asm_insn ("nop 4", xops);
783 	}
784       else if (delta >= 16 && delta < 32)
785 	{
786 	  output_asm_insn ("add .d1 %0, %1, %1", xops);
787 	  if (!vcall_offset)
788 	    output_asm_insn ("nop 4", xops);
789 	}
790       else if (delta >= -32768 && delta < 32768)
791 	{
792 	  output_asm_insn ("mvk .s1 %0, A0", xops);
793 	  output_asm_insn ("add .d1 %1, A0, %1", xops);
794 	  if (!vcall_offset)
795 	    output_asm_insn ("nop 3", xops);
796 	}
797       else
798 	{
799 	  output_asm_insn ("mvkl .s1 %0, A0", xops);
800 	  output_asm_insn ("mvkh .s1 %0, A0", xops);
801 	  output_asm_insn ("add .d1 %1, A0, %1", xops);
802 	  if (!vcall_offset)
803 	    output_asm_insn ("nop 3", xops);
804 	}
805     }
806 
807   /* Adjust the this parameter by a value stored in the vtable.  */
808   if (vcall_offset)
809     {
810       rtx a0tmp = gen_rtx_REG (Pmode, REG_A0);
811       rtx a3tmp = gen_rtx_REG (Pmode, REG_A3);
812 
813       xops[1] = a3tmp;
814       xops[2] = a0tmp;
815       xops[3] = gen_rtx_MEM (Pmode, a0tmp);
816       output_asm_insn ("mv .s1 a4, %2", xops);
817       output_asm_insn ("ldw .d1t1 %3, %2", xops);
818 
819       /* Adjust the this parameter.  */
820       xops[0] = gen_rtx_MEM (Pmode, plus_constant (Pmode, a0tmp,
821 						   vcall_offset));
822       if (!memory_operand (xops[0], Pmode))
823 	{
824 	  rtx tmp2 = gen_rtx_REG (Pmode, REG_A1);
825 	  xops[0] = GEN_INT (vcall_offset);
826 	  xops[1] = tmp2;
827 	  output_asm_insn ("mvkl .s1 %0, %1", xops);
828 	  output_asm_insn ("mvkh .s1 %0, %1", xops);
829 	  output_asm_insn ("nop 2", xops);
830 	  output_asm_insn ("add .d1 %2, %1, %2", xops);
831 	  xops[0] = gen_rtx_MEM (Pmode, a0tmp);
832 	}
833       else
834 	output_asm_insn ("nop 4", xops);
835       xops[2] = this_rtx;
836       output_asm_insn ("ldw .d1t1 %0, %1", xops);
837       output_asm_insn ("|| b .s2 \t%4", xops);
838       output_asm_insn ("nop 4", xops);
839       output_asm_insn ("add .d1 %2, %1, %2", xops);
840     }
841   assemble_end_function (thunk, fnname);
842 }
843 
844 /* Return true if EXP goes in small data/bss.  */
845 
846 static bool
c6x_in_small_data_p(const_tree exp)847 c6x_in_small_data_p (const_tree exp)
848 {
849   /* We want to merge strings, so we never consider them small data.  */
850   if (TREE_CODE (exp) == STRING_CST)
851     return false;
852 
853   /* Functions are never small data.  */
854   if (TREE_CODE (exp) == FUNCTION_DECL)
855     return false;
856 
857   if (TREE_CODE (exp) == VAR_DECL && DECL_WEAK (exp))
858     return false;
859 
860   if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp))
861     {
862       const char *section = DECL_SECTION_NAME (exp);
863 
864       if (strcmp (section, ".neardata") == 0
865 	  || strncmp (section, ".neardata.", 10) == 0
866 	  || strncmp (section, ".gnu.linkonce.s.", 16) == 0
867 	  || strcmp (section, ".bss") == 0
868 	  || strncmp (section, ".bss.", 5) == 0
869 	  || strncmp (section, ".gnu.linkonce.sb.", 17) == 0
870 	  || strcmp (section, ".rodata") == 0
871 	  || strncmp (section, ".rodata.", 8) == 0
872 	  || strncmp (section, ".gnu.linkonce.s2.", 17) == 0)
873 	return true;
874     }
875   else
876     return PLACE_IN_SDATA_P (exp);
877 
878   return false;
879 }
880 
881 /* Return a section for X.  The only special thing we do here is to
882    honor small data.  We don't have a tree type, so we can't use the
883    PLACE_IN_SDATA_P macro we use everywhere else; we choose to place
884    everything sized 8 bytes or smaller into small data.  */
885 
886 static section *
c6x_select_rtx_section(machine_mode mode,rtx x,unsigned HOST_WIDE_INT align)887 c6x_select_rtx_section (machine_mode mode, rtx x,
888 			unsigned HOST_WIDE_INT align)
889 {
890   if (c6x_sdata_mode == C6X_SDATA_ALL
891       || (c6x_sdata_mode != C6X_SDATA_NONE && GET_MODE_SIZE (mode) <= 8))
892     /* ??? Consider using mergeable sdata sections.  */
893     return sdata_section;
894   else
895     return default_elf_select_rtx_section (mode, x, align);
896 }
897 
898 static section *
c6x_elf_select_section(tree decl,int reloc,unsigned HOST_WIDE_INT align)899 c6x_elf_select_section (tree decl, int reloc,
900 			unsigned HOST_WIDE_INT align)
901 {
902   const char *sname = NULL;
903   unsigned int flags = SECTION_WRITE;
904   if (c6x_in_small_data_p (decl))
905     {
906       switch (categorize_decl_for_section (decl, reloc))
907 	{
908 	case SECCAT_SRODATA:
909 	  sname = ".rodata";
910 	  flags = 0;
911 	  break;
912 	case SECCAT_SDATA:
913 	  sname = ".neardata";
914 	  break;
915 	case SECCAT_SBSS:
916 	  sname = ".bss";
917 	  flags |= SECTION_BSS;
918 	default:
919 	  break;
920 	}
921     }
922   else
923     {
924       switch (categorize_decl_for_section (decl, reloc))
925 	{
926 	case SECCAT_DATA:
927 	  sname = ".fardata";
928 	  break;
929 	case SECCAT_DATA_REL:
930 	  sname = ".fardata.rel";
931 	  break;
932 	case SECCAT_DATA_REL_LOCAL:
933 	  sname = ".fardata.rel.local";
934 	  break;
935 	case SECCAT_DATA_REL_RO:
936 	  sname = ".fardata.rel.ro";
937 	  break;
938 	case SECCAT_DATA_REL_RO_LOCAL:
939 	  sname = ".fardata.rel.ro.local";
940 	  break;
941 	case SECCAT_BSS:
942 	  sname = ".far";
943 	  flags |= SECTION_BSS;
944 	  break;
945 	case SECCAT_RODATA:
946 	  sname = ".const";
947 	  flags = 0;
948 	  break;
949 	case SECCAT_SRODATA:
950 	case SECCAT_SDATA:
951 	case SECCAT_SBSS:
952 	  gcc_unreachable ();
953 	default:
954 	  break;
955 	}
956     }
957   if (sname)
958     {
959       /* We might get called with string constants, but get_named_section
960 	 doesn't like them as they are not DECLs.  Also, we need to set
961 	 flags in that case.  */
962       if (!DECL_P (decl))
963 	return get_section (sname, flags, NULL);
964       return get_named_section (decl, sname, reloc);
965     }
966 
967   return default_elf_select_section (decl, reloc, align);
968 }
969 
970 /* Build up a unique section name, expressed as a
971    STRING_CST node, and assign it to DECL_SECTION_NAME (decl).
972    RELOC indicates whether the initial value of EXP requires
973    link-time relocations.  */
974 
975 static void ATTRIBUTE_UNUSED
c6x_elf_unique_section(tree decl,int reloc)976 c6x_elf_unique_section (tree decl, int reloc)
977 {
978   const char *prefix = NULL;
979   /* We only need to use .gnu.linkonce if we don't have COMDAT groups.  */
980   bool one_only = DECL_COMDAT_GROUP (decl) && !HAVE_COMDAT_GROUP;
981 
982   if (c6x_in_small_data_p (decl))
983     {
984       switch (categorize_decl_for_section (decl, reloc))
985 	{
986 	case SECCAT_SDATA:
987           prefix = one_only ? ".s" : ".neardata";
988 	  break;
989 	case SECCAT_SBSS:
990           prefix = one_only ? ".sb" : ".bss";
991 	  break;
992 	case SECCAT_SRODATA:
993           prefix = one_only ? ".s2" : ".rodata";
994 	  break;
995 	case SECCAT_RODATA_MERGE_STR:
996 	case SECCAT_RODATA_MERGE_STR_INIT:
997 	case SECCAT_RODATA_MERGE_CONST:
998 	case SECCAT_RODATA:
999 	case SECCAT_DATA:
1000 	case SECCAT_DATA_REL:
1001 	case SECCAT_DATA_REL_LOCAL:
1002 	case SECCAT_DATA_REL_RO:
1003 	case SECCAT_DATA_REL_RO_LOCAL:
1004 	  gcc_unreachable ();
1005 	default:
1006 	  /* Everything else we place into default sections and hope for the
1007 	     best.  */
1008 	  break;
1009 	}
1010     }
1011   else
1012     {
1013       switch (categorize_decl_for_section (decl, reloc))
1014 	{
1015 	case SECCAT_DATA:
1016 	case SECCAT_DATA_REL:
1017 	case SECCAT_DATA_REL_LOCAL:
1018 	case SECCAT_DATA_REL_RO:
1019 	case SECCAT_DATA_REL_RO_LOCAL:
1020           prefix = one_only ? ".fd" : ".fardata";
1021 	  break;
1022 	case SECCAT_BSS:
1023           prefix = one_only ? ".fb" : ".far";
1024 	  break;
1025 	case SECCAT_RODATA:
1026 	case SECCAT_RODATA_MERGE_STR:
1027 	case SECCAT_RODATA_MERGE_STR_INIT:
1028 	case SECCAT_RODATA_MERGE_CONST:
1029           prefix = one_only ? ".fr" : ".const";
1030 	  break;
1031 	case SECCAT_SRODATA:
1032 	case SECCAT_SDATA:
1033 	case SECCAT_SBSS:
1034 	  gcc_unreachable ();
1035 	default:
1036 	  break;
1037 	}
1038     }
1039 
1040   if (prefix)
1041     {
1042       const char *name, *linkonce;
1043       char *string;
1044 
1045       name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
1046       name = targetm.strip_name_encoding (name);
1047 
1048       /* If we're using one_only, then there needs to be a .gnu.linkonce
1049 	 prefix to the section name.  */
1050       linkonce = one_only ? ".gnu.linkonce" : "";
1051 
1052       string = ACONCAT ((linkonce, prefix, ".", name, NULL));
1053 
1054       set_decl_section_name (decl, string);
1055       return;
1056     }
1057   default_unique_section (decl, reloc);
1058 }
1059 
1060 static unsigned int
c6x_section_type_flags(tree decl,const char * name,int reloc)1061 c6x_section_type_flags (tree decl, const char *name, int reloc)
1062 {
1063   unsigned int flags = 0;
1064 
1065   if (strcmp (name, ".far") == 0
1066       || strncmp (name, ".far.", 5) == 0)
1067     flags |= SECTION_BSS;
1068 
1069   flags |= default_section_type_flags (decl, name, reloc);
1070 
1071   /* The ".far" section will be declared with @nobits elsewhere.
1072      But when declared via this path it will not have the @nobits
1073      flag because of SECTION_NOTYPE.  This causes linker warnings
1074      due to the mismatched attribute.  Clearing SECTION_NOTYPE
1075      for the ".far" section is sufficient to fix this problem.  */
1076   if (strcmp (name, ".far") == 0)
1077     flags &= ~SECTION_NOTYPE;
1078 
1079   return flags;
1080 }
1081 
1082 /* Checks whether the given CALL_EXPR would use a caller saved
1083    register.  This is used to decide whether sibling call optimization
1084    could be performed on the respective function call.  */
1085 
1086 static bool
c6x_call_saved_register_used(tree call_expr)1087 c6x_call_saved_register_used (tree call_expr)
1088 {
1089   CUMULATIVE_ARGS cum_v;
1090   cumulative_args_t cum;
1091   HARD_REG_SET call_saved_regset;
1092   tree parameter;
1093   rtx parm_rtx;
1094   int i;
1095 
1096   INIT_CUMULATIVE_ARGS (cum_v, NULL, NULL, 0, 0);
1097   cum = pack_cumulative_args (&cum_v);
1098 
1099   call_saved_regset = ~call_used_or_fixed_regs;
1100   for (i = 0; i < call_expr_nargs (call_expr); i++)
1101     {
1102       parameter = CALL_EXPR_ARG (call_expr, i);
1103       gcc_assert (parameter);
1104 
1105       /* For an undeclared variable passed as parameter we will get
1106 	 an ERROR_MARK node here.  */
1107       if (TREE_CODE (parameter) == ERROR_MARK)
1108 	return true;
1109 
1110       function_arg_info arg (TREE_TYPE (parameter), /*named=*/true);
1111       apply_pass_by_reference_rules (&cum_v, arg);
1112 
1113        parm_rtx = c6x_function_arg (cum, arg);
1114 
1115        c6x_function_arg_advance (cum, arg);
1116 
1117        if (!parm_rtx)
1118 	 continue;
1119 
1120        if (REG_P (parm_rtx)
1121 	   && overlaps_hard_reg_set_p (call_saved_regset, GET_MODE (parm_rtx),
1122 				       REGNO (parm_rtx)))
1123 	 return true;
1124        if (GET_CODE (parm_rtx) == PARALLEL)
1125 	 {
1126 	   int n = XVECLEN (parm_rtx, 0);
1127 	   while (n-- > 0)
1128 	     {
1129 	       rtx x = XEXP (XVECEXP (parm_rtx, 0, n), 0);
1130 	       if (REG_P (x)
1131 		   && overlaps_hard_reg_set_p (call_saved_regset,
1132 					       GET_MODE (x), REGNO (x)))
1133 		 return true;
1134 	     }
1135 	 }
1136     }
1137   return false;
1138 }
1139 
1140 /* Decide whether we can make a sibling call to a function.  DECL is the
1141    declaration of the function being targeted by the call and EXP is the
1142    CALL_EXPR representing the call.  */
1143 
1144 static bool
c6x_function_ok_for_sibcall(tree decl,tree exp)1145 c6x_function_ok_for_sibcall (tree decl, tree exp)
1146 {
1147   /* Registers A10, A12, B10 and B12 are available as arguments
1148      register but unfortunately caller saved. This makes functions
1149      needing these registers for arguments not suitable for
1150      sibcalls.  */
1151   if (c6x_call_saved_register_used (exp))
1152     return false;
1153 
1154   if (!flag_pic)
1155     return true;
1156 
1157   if (TARGET_DSBT)
1158     {
1159       /* When compiling for DSBT, the calling function must be local,
1160 	 so that when we reload B14 in the sibcall epilogue, it will
1161 	 not change its value.  */
1162 
1163       if (!decl)
1164 	/* Not enough information.  */
1165 	return false;
1166 
1167       cgraph_node *this_func
1168 	= cgraph_node::local_info_node (current_function_decl);
1169       return this_func->local;
1170     }
1171 
1172   return true;
1173 }
1174 
1175 /* Return true if DECL is known to be linked into section SECTION.  */
1176 
1177 static bool
c6x_function_in_section_p(tree decl,section * section)1178 c6x_function_in_section_p (tree decl, section *section)
1179 {
1180   /* We can only be certain about functions defined in the same
1181      compilation unit.  */
1182   if (!TREE_STATIC (decl))
1183     return false;
1184 
1185   /* Make sure that SYMBOL always binds to the definition in this
1186      compilation unit.  */
1187   if (!targetm.binds_local_p (decl))
1188     return false;
1189 
1190   /* If DECL_SECTION_NAME is set, assume it is trustworthy.  */
1191   if (!DECL_SECTION_NAME (decl))
1192     {
1193       /* Make sure that we will not create a unique section for DECL.  */
1194       if (flag_function_sections || DECL_COMDAT_GROUP (decl))
1195 	return false;
1196     }
1197 
1198   return function_section (decl) == section;
1199 }
1200 
1201 /* Return true if a call to OP, which is a SYMBOL_REF, must be expanded
1202    as a long call.  */
1203 bool
c6x_long_call_p(rtx op)1204 c6x_long_call_p (rtx op)
1205 {
1206   tree decl;
1207 
1208   if (!TARGET_LONG_CALLS)
1209     return false;
1210 
1211   decl = SYMBOL_REF_DECL (op);
1212 
1213   /* Try to determine whether the symbol is in the same section as the current
1214      function.  Be conservative, and only cater for cases in which the
1215      whole of the current function is placed in the same section.  */
1216   if (decl != NULL_TREE
1217       && !flag_reorder_blocks_and_partition
1218       && TREE_CODE (decl) == FUNCTION_DECL
1219       && c6x_function_in_section_p (decl, current_function_section ()))
1220     return false;
1221 
1222   return true;
1223 }
1224 
1225 /* Emit the sequence for a call.  */
1226 void
c6x_expand_call(rtx retval,rtx address,bool sibcall)1227 c6x_expand_call (rtx retval, rtx address, bool sibcall)
1228 {
1229   rtx callee = XEXP (address, 0);
1230   rtx call_insn;
1231 
1232   if (!c6x_call_operand (callee, Pmode))
1233     {
1234       callee = force_reg (Pmode, callee);
1235       address = change_address (address, Pmode, callee);
1236     }
1237   call_insn = gen_rtx_CALL (VOIDmode, address, const0_rtx);
1238   if (sibcall)
1239     {
1240       call_insn = emit_call_insn (call_insn);
1241       use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn),
1242 	       gen_rtx_REG (Pmode, REG_B3));
1243     }
1244   else
1245     {
1246       if (retval == NULL_RTX)
1247 	call_insn = emit_call_insn (call_insn);
1248       else
1249 	call_insn = emit_call_insn (gen_rtx_SET (retval, call_insn));
1250     }
1251   if (flag_pic)
1252     use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), pic_offset_table_rtx);
1253 }
1254 
1255 /* Legitimize PIC addresses.  If the address is already position-independent,
1256    we return ORIG.  Newly generated position-independent addresses go into a
1257    reg.  This is REG if nonzero, otherwise we allocate register(s) as
1258    necessary.  PICREG is the register holding the pointer to the PIC offset
1259    table.  */
1260 
1261 static rtx
legitimize_pic_address(rtx orig,rtx reg,rtx picreg)1262 legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
1263 {
1264   rtx addr = orig;
1265   rtx new_rtx = orig;
1266 
1267   if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
1268     {
1269       int unspec = UNSPEC_LOAD_GOT;
1270       rtx tmp;
1271 
1272       if (reg == 0)
1273 	{
1274 	  gcc_assert (can_create_pseudo_p ());
1275 	  reg = gen_reg_rtx (Pmode);
1276 	}
1277       if (flag_pic == 2)
1278 	{
1279 	  if (can_create_pseudo_p ())
1280 	    tmp = gen_reg_rtx (Pmode);
1281 	  else
1282 	    tmp = reg;
1283 	  emit_insn (gen_movsi_gotoff_high (tmp, addr));
1284 	  emit_insn (gen_movsi_gotoff_lo_sum (tmp, tmp, addr));
1285 	  emit_insn (gen_load_got_gotoff (reg, picreg, tmp));
1286 	}
1287       else
1288 	{
1289 	  tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), unspec);
1290 	  new_rtx = gen_const_mem (Pmode, gen_rtx_PLUS (Pmode, picreg, tmp));
1291 
1292 	  emit_move_insn (reg, new_rtx);
1293 	}
1294       if (picreg == pic_offset_table_rtx)
1295 	crtl->uses_pic_offset_table = 1;
1296       return reg;
1297     }
1298 
1299   else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
1300     {
1301       rtx base;
1302 
1303       if (GET_CODE (addr) == CONST)
1304 	{
1305 	  addr = XEXP (addr, 0);
1306 	  gcc_assert (GET_CODE (addr) == PLUS);
1307 	}
1308 
1309       if (XEXP (addr, 0) == picreg)
1310 	return orig;
1311 
1312       if (reg == 0)
1313 	{
1314 	  gcc_assert (can_create_pseudo_p ());
1315 	  reg = gen_reg_rtx (Pmode);
1316 	}
1317 
1318       base = legitimize_pic_address (XEXP (addr, 0), reg, picreg);
1319       addr = legitimize_pic_address (XEXP (addr, 1),
1320 				     base == reg ? NULL_RTX : reg,
1321 				     picreg);
1322 
1323       if (GET_CODE (addr) == CONST_INT)
1324 	{
1325 	  gcc_assert (! reload_in_progress && ! reload_completed);
1326 	  addr = force_reg (Pmode, addr);
1327 	}
1328 
1329       if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
1330 	{
1331 	  base = gen_rtx_PLUS (Pmode, base, XEXP (addr, 0));
1332 	  addr = XEXP (addr, 1);
1333 	}
1334 
1335       return gen_rtx_PLUS (Pmode, base, addr);
1336     }
1337 
1338   return new_rtx;
1339 }
1340 
1341 /* Expand a move operation in mode MODE.  The operands are in OPERANDS.
1342    Returns true if no further code must be generated, false if the caller
1343    should generate an insn to move OPERANDS[1] to OPERANDS[0].  */
1344 
1345 bool
expand_move(rtx * operands,machine_mode mode)1346 expand_move (rtx *operands, machine_mode mode)
1347 {
1348   rtx dest = operands[0];
1349   rtx op = operands[1];
1350 
1351   if ((reload_in_progress | reload_completed) == 0
1352       && GET_CODE (dest) == MEM && GET_CODE (op) != REG)
1353     operands[1] = force_reg (mode, op);
1354   else if (mode == SImode && symbolic_operand (op, SImode))
1355     {
1356       if (flag_pic)
1357 	{
1358 	  if (sdata_symbolic_operand (op, SImode))
1359 	    {
1360 	      emit_insn (gen_load_sdata_pic (dest, pic_offset_table_rtx, op));
1361 	      crtl->uses_pic_offset_table = 1;
1362 	      return true;
1363 	    }
1364 	  else
1365 	    {
1366 	      rtx temp = (reload_completed || reload_in_progress
1367 			  ? dest : gen_reg_rtx (Pmode));
1368 
1369 	      operands[1] = legitimize_pic_address (op, temp,
1370 						    pic_offset_table_rtx);
1371 	    }
1372 	}
1373       else if (reload_completed
1374 	       && !sdata_symbolic_operand (op, SImode))
1375 	{
1376 	  emit_insn (gen_movsi_high (dest, op));
1377 	  emit_insn (gen_movsi_lo_sum (dest, dest, op));
1378 	  return true;
1379 	}
1380     }
1381   return false;
1382 }
1383 
1384 /* This function is called when we're about to expand an integer compare
1385    operation which performs COMPARISON.  It examines the second operand,
1386    and if it is an integer constant that cannot be used directly on the
1387    current machine in a comparison insn, it returns true.  */
1388 bool
c6x_force_op_for_comparison_p(enum rtx_code code,rtx op)1389 c6x_force_op_for_comparison_p (enum rtx_code code, rtx op)
1390 {
1391   if (!CONST_INT_P (op) || satisfies_constraint_Iu4 (op))
1392     return false;
1393 
1394   if ((code == EQ || code == LT || code == GT)
1395        && !satisfies_constraint_Is5 (op))
1396     return true;
1397   if ((code == GTU || code == LTU)
1398       && (!TARGET_INSNS_64 || !satisfies_constraint_Iu5 (op)))
1399     return true;
1400 
1401   return false;
1402 }
1403 
1404 /* Emit comparison instruction if necessary, returning the expression
1405    that holds the compare result in the proper mode.  Return the comparison
1406    that should be used in the jump insn.  */
1407 
1408 rtx
c6x_expand_compare(rtx comparison,machine_mode mode)1409 c6x_expand_compare (rtx comparison, machine_mode mode)
1410 {
1411   enum rtx_code code = GET_CODE (comparison);
1412   rtx op0 = XEXP (comparison, 0);
1413   rtx op1 = XEXP (comparison, 1);
1414   rtx cmp;
1415   enum rtx_code jump_code = code;
1416   machine_mode op_mode = GET_MODE (op0);
1417 
1418   if (op_mode == DImode && (code == NE || code == EQ) && op1 == const0_rtx)
1419     {
1420       rtx t = gen_reg_rtx (SImode);
1421       emit_insn (gen_iorsi3 (t, gen_lowpart (SImode, op0),
1422 			     gen_highpart (SImode, op0)));
1423       op_mode = SImode;
1424       cmp = t;
1425     }
1426   else if (op_mode == DImode)
1427     {
1428       rtx lo[2], high[2];
1429       rtx cmp1, cmp2;
1430 
1431       if (code == NE || code == GEU || code == LEU || code == GE || code == LE)
1432 	{
1433 	  code = reverse_condition (code);
1434 	  jump_code = EQ;
1435 	}
1436       else
1437 	jump_code = NE;
1438 
1439       split_di (&op0, 1, lo, high);
1440       split_di (&op1, 1, lo + 1, high + 1);
1441 
1442       if (c6x_force_op_for_comparison_p (code, high[1])
1443 	  || c6x_force_op_for_comparison_p (EQ, high[1]))
1444 	high[1] = force_reg (SImode, high[1]);
1445 
1446       cmp1 = gen_reg_rtx (SImode);
1447       cmp2 = gen_reg_rtx (SImode);
1448       emit_insn (gen_rtx_SET (cmp1, gen_rtx_fmt_ee (code, SImode,
1449 						    high[0], high[1])));
1450       if (code == EQ)
1451 	{
1452 	  if (c6x_force_op_for_comparison_p (code, lo[1]))
1453 	    lo[1] = force_reg (SImode, lo[1]);
1454 	  emit_insn (gen_rtx_SET (cmp2, gen_rtx_fmt_ee (code, SImode,
1455 							lo[0], lo[1])));
1456 	  emit_insn (gen_andsi3 (cmp1, cmp1, cmp2));
1457 	}
1458       else
1459 	{
1460 	  emit_insn (gen_rtx_SET (cmp2, gen_rtx_EQ (SImode, high[0],
1461 						    high[1])));
1462 	  if (code == GT)
1463 	    code = GTU;
1464 	  else if (code == LT)
1465 	    code = LTU;
1466 	  if (c6x_force_op_for_comparison_p (code, lo[1]))
1467 	    lo[1] = force_reg (SImode, lo[1]);
1468 	  emit_insn (gen_cmpsi_and (cmp2, gen_rtx_fmt_ee (code, SImode,
1469 							  lo[0], lo[1]),
1470 				    lo[0], lo[1], cmp2));
1471 	  emit_insn (gen_iorsi3 (cmp1, cmp1, cmp2));
1472 	}
1473       cmp = cmp1;
1474     }
1475   else if (TARGET_FP && !flag_finite_math_only
1476 	   && (op_mode == DFmode || op_mode == SFmode)
1477 	   && code != EQ && code != NE && code != LT && code != GT
1478 	   && code != UNLE && code != UNGE)
1479     {
1480       enum rtx_code code1, code2, code3;
1481       rtx (*fn) (rtx, rtx, rtx, rtx, rtx);
1482 
1483       jump_code = NE;
1484       code3 = UNKNOWN;
1485       switch (code)
1486 	{
1487 	case UNLT:
1488 	case UNGT:
1489 	  jump_code = EQ;
1490 	  /* fall through */
1491 	case LE:
1492 	case GE:
1493 	  code1 = code == LE || code == UNGT ? LT : GT;
1494 	  code2 = EQ;
1495 	  break;
1496 
1497 	case UNORDERED:
1498 	  jump_code = EQ;
1499 	  /* fall through */
1500 	case ORDERED:
1501 	  code3 = EQ;
1502 	  /* fall through */
1503 	case LTGT:
1504 	  code1 = LT;
1505 	  code2 = GT;
1506 	  break;
1507 
1508 	case UNEQ:
1509 	  code1 = LT;
1510 	  code2 = GT;
1511 	  jump_code = EQ;
1512 	  break;
1513 
1514 	default:
1515 	  gcc_unreachable ();
1516 	}
1517 
1518       cmp = gen_reg_rtx (SImode);
1519       emit_insn (gen_rtx_SET (cmp, gen_rtx_fmt_ee (code1, SImode, op0, op1)));
1520       fn = op_mode == DFmode ? gen_cmpdf_ior : gen_cmpsf_ior;
1521       emit_insn (fn (cmp, gen_rtx_fmt_ee (code2, SImode, op0, op1),
1522 		     op0, op1, cmp));
1523       if (code3 != UNKNOWN)
1524 	emit_insn (fn (cmp, gen_rtx_fmt_ee (code3, SImode, op0, op1),
1525 		       op0, op1, cmp));
1526     }
1527   else if (op_mode == SImode && (code == NE || code == EQ) && op1 == const0_rtx)
1528     cmp = op0;
1529   else
1530     {
1531       bool is_fp_libfunc;
1532       is_fp_libfunc = !TARGET_FP && (op_mode == DFmode || op_mode == SFmode);
1533 
1534       if ((code == NE || code == GEU || code == LEU || code == GE || code == LE)
1535 	  && !is_fp_libfunc)
1536 	{
1537 	  code = reverse_condition (code);
1538 	  jump_code = EQ;
1539 	}
1540       else if (code == UNGE)
1541 	{
1542 	  code = LT;
1543 	  jump_code = EQ;
1544 	}
1545       else if (code == UNLE)
1546 	{
1547 	  code = GT;
1548 	  jump_code = EQ;
1549 	}
1550       else
1551 	jump_code = NE;
1552 
1553       if (is_fp_libfunc)
1554 	{
1555 	  rtx_insn *insns;
1556 	  rtx libfunc;
1557 	  switch (code)
1558 	    {
1559 	    case EQ:
1560 	      libfunc = op_mode == DFmode ? eqdf_libfunc : eqsf_libfunc;
1561 	      break;
1562 	    case NE:
1563 	      libfunc = op_mode == DFmode ? nedf_libfunc : nesf_libfunc;
1564 	      break;
1565 	    case GT:
1566 	      libfunc = op_mode == DFmode ? gtdf_libfunc : gtsf_libfunc;
1567 	      break;
1568 	    case GE:
1569 	      libfunc = op_mode == DFmode ? gedf_libfunc : gesf_libfunc;
1570 	      break;
1571 	    case LT:
1572 	      libfunc = op_mode == DFmode ? ltdf_libfunc : ltsf_libfunc;
1573 	      break;
1574 	    case LE:
1575 	      libfunc = op_mode == DFmode ? ledf_libfunc : lesf_libfunc;
1576 	      break;
1577 	    default:
1578 	      gcc_unreachable ();
1579 	    }
1580 	  start_sequence ();
1581 
1582 	  cmp = emit_library_call_value (libfunc, 0, LCT_CONST, SImode,
1583 					 op0, op_mode, op1, op_mode);
1584 	  insns = get_insns ();
1585 	  end_sequence ();
1586 
1587 	  emit_libcall_block (insns, cmp, cmp,
1588 			      gen_rtx_fmt_ee (code, SImode, op0, op1));
1589 	}
1590       else
1591 	{
1592 	  cmp = gen_reg_rtx (SImode);
1593 	  if (c6x_force_op_for_comparison_p (code, op1))
1594 	    op1 = force_reg (SImode, op1);
1595 	  emit_insn (gen_rtx_SET (cmp, gen_rtx_fmt_ee (code, SImode,
1596 						       op0, op1)));
1597 	}
1598     }
1599 
1600   return gen_rtx_fmt_ee (jump_code, mode, cmp, const0_rtx);
1601 }
1602 
1603 /* Return one word of double-word value OP.  HIGH_P is true to select the
1604    high part, false to select the low part.  When encountering auto-increment
1605    addressing, we make the assumption that the low part is going to be accessed
1606    first.  */
1607 
1608 rtx
c6x_subword(rtx op,bool high_p)1609 c6x_subword (rtx op, bool high_p)
1610 {
1611   unsigned int byte;
1612   machine_mode mode;
1613 
1614   mode = GET_MODE (op);
1615   if (mode == VOIDmode)
1616     mode = DImode;
1617 
1618   if (TARGET_BIG_ENDIAN ? !high_p : high_p)
1619     byte = UNITS_PER_WORD;
1620   else
1621     byte = 0;
1622 
1623   if (MEM_P (op))
1624     {
1625       rtx addr = XEXP (op, 0);
1626       if (GET_CODE (addr) == PLUS || REG_P (addr))
1627 	return adjust_address (op, word_mode, byte);
1628       /* FIXME: should really support autoincrement addressing for
1629 	 multi-word modes.  */
1630       gcc_unreachable ();
1631     }
1632 
1633   return simplify_gen_subreg (word_mode, op, mode, byte);
1634 }
1635 
1636 /* Split one or more DImode RTL references into pairs of SImode
1637    references.  The RTL can be REG, offsettable MEM, integer constant, or
1638    CONST_DOUBLE.  "operands" is a pointer to an array of DImode RTL to
1639    split and "num" is its length.  lo_half and hi_half are output arrays
1640    that parallel "operands".  */
1641 
1642 void
split_di(rtx operands[],int num,rtx lo_half[],rtx hi_half[])1643 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
1644 {
1645   while (num--)
1646     {
1647       rtx op = operands[num];
1648 
1649       lo_half[num] = c6x_subword (op, false);
1650       hi_half[num] = c6x_subword (op, true);
1651     }
1652 }
1653 
1654 /* Return true if VAL is a mask valid for a clr instruction.  */
1655 bool
c6x_valid_mask_p(HOST_WIDE_INT val)1656 c6x_valid_mask_p (HOST_WIDE_INT val)
1657 {
1658   int i;
1659   for (i = 0; i < 32; i++)
1660     if (!(val & ((unsigned HOST_WIDE_INT)1 << i)))
1661       break;
1662   for (; i < 32; i++)
1663     if (val & ((unsigned HOST_WIDE_INT)1 << i))
1664       break;
1665   for (; i < 32; i++)
1666     if (!(val & ((unsigned HOST_WIDE_INT)1 << i)))
1667       return false;
1668   return true;
1669 }
1670 
1671 /* Expand a block move for a cpymemM pattern.  */
1672 
1673 bool
c6x_expand_cpymem(rtx dst,rtx src,rtx count_exp,rtx align_exp,rtx expected_align_exp ATTRIBUTE_UNUSED,rtx expected_size_exp ATTRIBUTE_UNUSED)1674 c6x_expand_cpymem (rtx dst, rtx src, rtx count_exp, rtx align_exp,
1675 		   rtx expected_align_exp ATTRIBUTE_UNUSED,
1676 		   rtx expected_size_exp ATTRIBUTE_UNUSED)
1677 {
1678   unsigned HOST_WIDE_INT align = 1;
1679   unsigned HOST_WIDE_INT src_mem_align, dst_mem_align, min_mem_align;
1680   unsigned HOST_WIDE_INT count = 0, offset = 0;
1681   unsigned int biggest_move = TARGET_STDW ? 8 : 4;
1682 
1683   if (CONST_INT_P (align_exp))
1684     align = INTVAL (align_exp);
1685 
1686   src_mem_align = MEM_ALIGN (src) / BITS_PER_UNIT;
1687   dst_mem_align = MEM_ALIGN (dst) / BITS_PER_UNIT;
1688   min_mem_align = MIN (src_mem_align, dst_mem_align);
1689 
1690   if (min_mem_align > align)
1691     align = min_mem_align / BITS_PER_UNIT;
1692   if (src_mem_align < align)
1693     src_mem_align = align;
1694   if (dst_mem_align < align)
1695     dst_mem_align = align;
1696 
1697   if (CONST_INT_P (count_exp))
1698     count = INTVAL (count_exp);
1699   else
1700     return false;
1701 
1702   /* Make sure we don't need to care about overflow later on.  */
1703   if (count > ((unsigned HOST_WIDE_INT) 1 << 30))
1704     return false;
1705 
1706   if (count >= 28 && (count & 3) == 0 && align >= 4)
1707     {
1708       tree dst_expr = MEM_EXPR (dst);
1709       tree src_expr = MEM_EXPR (src);
1710       rtx fn = TARGET_INSNS_64PLUS ? strasgi64p_libfunc : strasgi_libfunc;
1711       rtx srcreg = force_reg (Pmode, XEXP (src, 0));
1712       rtx dstreg = force_reg (Pmode, XEXP (dst, 0));
1713 
1714       if (src_expr)
1715 	mark_addressable (src_expr);
1716       if (dst_expr)
1717 	mark_addressable (dst_expr);
1718       emit_library_call (fn, LCT_NORMAL, VOIDmode,
1719 			 dstreg, Pmode, srcreg, Pmode, count_exp, SImode);
1720       return true;
1721     }
1722 
1723   if (biggest_move > align && !TARGET_INSNS_64)
1724     biggest_move = align;
1725 
1726   if (count / biggest_move > 7)
1727     return false;
1728 
1729   while (count > 0)
1730     {
1731       rtx reg, reg_lowpart;
1732       machine_mode srcmode, dstmode;
1733       unsigned HOST_WIDE_INT src_size, dst_size, src_left;
1734       int shift;
1735       rtx srcmem, dstmem;
1736 
1737       while (biggest_move > count)
1738 	biggest_move /= 2;
1739 
1740       src_size = dst_size = biggest_move;
1741       if (src_size > src_mem_align && src_size == 2)
1742 	src_size = 1;
1743       if (dst_size > dst_mem_align && dst_size == 2)
1744 	dst_size = 1;
1745 
1746       if (dst_size > src_size)
1747 	dst_size = src_size;
1748 
1749       srcmode = int_mode_for_size (src_size * BITS_PER_UNIT, 0).require ();
1750       dstmode = int_mode_for_size (dst_size * BITS_PER_UNIT, 0).require ();
1751       if (src_size >= 4)
1752 	reg_lowpart = reg = gen_reg_rtx (srcmode);
1753       else
1754 	{
1755 	  reg = gen_reg_rtx (SImode);
1756 	  reg_lowpart = gen_lowpart (srcmode, reg);
1757 	}
1758 
1759       srcmem = adjust_address (copy_rtx (src), srcmode, offset);
1760 
1761       if (src_size > src_mem_align)
1762 	{
1763 	  enum insn_code icode = (srcmode == SImode ? CODE_FOR_movmisalignsi
1764 				  : CODE_FOR_movmisaligndi);
1765 	  emit_insn (GEN_FCN (icode) (reg_lowpart, srcmem));
1766 	}
1767       else
1768 	emit_move_insn (reg_lowpart, srcmem);
1769 
1770       src_left = src_size;
1771       shift = TARGET_BIG_ENDIAN ? (src_size - dst_size) * BITS_PER_UNIT  : 0;
1772       while (src_left > 0)
1773 	{
1774 	  rtx dstreg = reg_lowpart;
1775 
1776 	  if (src_size > dst_size)
1777 	    {
1778 	      rtx srcword = reg;
1779 	      int shift_amount = shift & (BITS_PER_WORD - 1);
1780 	      if (src_size > 4)
1781 		srcword = operand_subword_force (srcword, src_left >= 4 ? 0 : 4,
1782 						 SImode);
1783 	      if (shift_amount > 0)
1784 		{
1785 		  dstreg = gen_reg_rtx (SImode);
1786 		  emit_insn (gen_lshrsi3 (dstreg, srcword,
1787 					  GEN_INT (shift_amount)));
1788 		}
1789 	      else
1790 		dstreg = srcword;
1791 	      dstreg = gen_lowpart (dstmode, dstreg);
1792 	    }
1793 
1794 	  dstmem = adjust_address (copy_rtx (dst), dstmode, offset);
1795 	  if (dst_size > dst_mem_align)
1796 	    {
1797 	      enum insn_code icode = (dstmode == SImode ? CODE_FOR_movmisalignsi
1798 				      : CODE_FOR_movmisaligndi);
1799 	      emit_insn (GEN_FCN (icode) (dstmem, dstreg));
1800 	    }
1801 	  else
1802 	    emit_move_insn (dstmem, dstreg);
1803 
1804 	  if (TARGET_BIG_ENDIAN)
1805 	    shift -= dst_size * BITS_PER_UNIT;
1806 	  else
1807 	    shift += dst_size * BITS_PER_UNIT;
1808 	  offset += dst_size;
1809 	  src_left -= dst_size;
1810 	}
1811       count -= src_size;
1812     }
1813   return true;
1814 }
1815 
1816 /* Subroutine of print_address_operand, print a single address offset OFF for
1817    a memory access of mode MEM_MODE, choosing between normal form and scaled
1818    form depending on the type of the insn.  Misaligned memory references must
1819    use the scaled form.  */
1820 
1821 static void
print_address_offset(FILE * file,rtx off,machine_mode mem_mode)1822 print_address_offset (FILE *file, rtx off, machine_mode mem_mode)
1823 {
1824   rtx pat;
1825 
1826   if (c6x_current_insn != NULL_RTX)
1827     {
1828       pat = PATTERN (c6x_current_insn);
1829       if (GET_CODE (pat) == COND_EXEC)
1830 	pat = COND_EXEC_CODE (pat);
1831       if (GET_CODE (pat) == PARALLEL)
1832 	pat = XVECEXP (pat, 0, 0);
1833 
1834       if (GET_CODE (pat) == SET
1835 	  && GET_CODE (SET_SRC (pat)) == UNSPEC
1836 	  && XINT (SET_SRC (pat), 1) == UNSPEC_MISALIGNED_ACCESS)
1837 	{
1838 	  gcc_assert (CONST_INT_P (off)
1839 		      && (INTVAL (off) & (GET_MODE_SIZE (mem_mode) - 1)) == 0);
1840 	  fprintf (file, "[" HOST_WIDE_INT_PRINT_DEC "]",
1841 		   INTVAL (off) / GET_MODE_SIZE (mem_mode));
1842 	  return;
1843 	}
1844     }
1845   fputs ("(", file);
1846   output_address (mem_mode, off);
1847   fputs (")", file);
1848 }
1849 
1850 static bool
c6x_print_operand_punct_valid_p(unsigned char c)1851 c6x_print_operand_punct_valid_p (unsigned char c)
1852 {
1853   return c == '$' || c == '.' || c == '|';
1854 }
1855 
1856 static void c6x_print_operand (FILE *, rtx, int);
1857 
1858 /* Subroutine of c6x_print_operand; used to print a memory reference X to FILE.  */
1859 
1860 static void
c6x_print_address_operand(FILE * file,rtx x,machine_mode mem_mode)1861 c6x_print_address_operand (FILE *file, rtx x, machine_mode mem_mode)
1862 {
1863   rtx off;
1864   switch (GET_CODE (x))
1865     {
1866     case PRE_MODIFY:
1867     case POST_MODIFY:
1868       if (GET_CODE (x) == POST_MODIFY)
1869 	output_address (mem_mode, XEXP (x, 0));
1870       off = XEXP (XEXP (x, 1), 1);
1871       if (XEXP (x, 0) == stack_pointer_rtx)
1872 	{
1873 	  if (GET_CODE (x) == PRE_MODIFY)
1874 	    gcc_assert (INTVAL (off) > 0);
1875 	  else
1876 	    gcc_assert (INTVAL (off) < 0);
1877 	}
1878       if (CONST_INT_P (off) && INTVAL (off) < 0)
1879 	{
1880 	  fprintf (file, "--");
1881 	  off = GEN_INT (-INTVAL (off));
1882 	}
1883       else
1884 	fprintf (file, "++");
1885       if (GET_CODE (x) == PRE_MODIFY)
1886 	output_address (mem_mode, XEXP (x, 0));
1887       print_address_offset (file, off, mem_mode);
1888       break;
1889 
1890     case PLUS:
1891       off = XEXP (x, 1);
1892       if (CONST_INT_P (off) && INTVAL (off) < 0)
1893 	{
1894 	  fprintf (file, "-");
1895 	  off = GEN_INT (-INTVAL (off));
1896 	}
1897       else
1898 	fprintf (file, "+");
1899       output_address (mem_mode, XEXP (x, 0));
1900       print_address_offset (file, off, mem_mode);
1901       break;
1902 
1903     case PRE_DEC:
1904       gcc_assert (XEXP (x, 0) != stack_pointer_rtx);
1905       fprintf (file, "--");
1906       output_address (mem_mode, XEXP (x, 0));
1907       fprintf (file, "[1]");
1908       break;
1909     case PRE_INC:
1910       fprintf (file, "++");
1911       output_address (mem_mode, XEXP (x, 0));
1912       fprintf (file, "[1]");
1913       break;
1914     case POST_INC:
1915       gcc_assert (XEXP (x, 0) != stack_pointer_rtx);
1916       output_address (mem_mode, XEXP (x, 0));
1917       fprintf (file, "++[1]");
1918       break;
1919     case POST_DEC:
1920       output_address (mem_mode, XEXP (x, 0));
1921       fprintf (file, "--[1]");
1922       break;
1923 
1924     case SYMBOL_REF:
1925     case CONST:
1926     case LABEL_REF:
1927       gcc_assert (sdata_symbolic_operand (x, Pmode));
1928       fprintf (file, "+B14(");
1929       output_addr_const (file, x);
1930       fprintf (file, ")");
1931       break;
1932 
1933     case UNSPEC:
1934       switch (XINT (x, 1))
1935 	{
1936 	case UNSPEC_LOAD_GOT:
1937 	  fputs ("$GOT(", file);
1938 	  output_addr_const (file, XVECEXP (x, 0, 0));
1939 	  fputs (")", file);
1940 	  break;
1941 	case UNSPEC_LOAD_SDATA:
1942 	  output_addr_const (file, XVECEXP (x, 0, 0));
1943 	  break;
1944 	default:
1945 	  gcc_unreachable ();
1946 	}
1947       break;
1948 
1949     default:
1950       gcc_assert (GET_CODE (x) != MEM);
1951       c6x_print_operand (file, x, 0);
1952       break;
1953     }
1954 }
1955 
1956 /* Return a single character, which is either 'l', 's', 'd' or 'm', which
1957    specifies the functional unit used by INSN.  */
1958 
1959 char
c6x_get_unit_specifier(rtx_insn * insn)1960 c6x_get_unit_specifier (rtx_insn *insn)
1961 {
1962   enum attr_units units;
1963 
1964   if (insn_info.exists ())
1965     {
1966       int unit = INSN_INFO_ENTRY (INSN_UID (insn)).reservation;
1967       return c6x_unit_names[unit][0];
1968     }
1969 
1970   units = get_attr_units (insn);
1971   switch (units)
1972     {
1973     case UNITS_D:
1974     case UNITS_DL:
1975     case UNITS_DS:
1976     case UNITS_DLS:
1977     case UNITS_D_ADDR:
1978       return 'd';
1979     case UNITS_L:
1980     case UNITS_LS:
1981       return 'l';
1982     case UNITS_S:
1983       return 's';
1984     case UNITS_M:
1985       return 'm';
1986     default:
1987       gcc_unreachable ();
1988     }
1989 }
1990 
1991 /* Prints the unit specifier field.  */
1992 static void
c6x_print_unit_specifier_field(FILE * file,rtx_insn * insn)1993 c6x_print_unit_specifier_field (FILE *file, rtx_insn *insn)
1994 {
1995   enum attr_units units = get_attr_units (insn);
1996   enum attr_cross cross = get_attr_cross (insn);
1997   enum attr_dest_regfile rf = get_attr_dest_regfile (insn);
1998   int half;
1999   char unitspec;
2000 
2001   if (units == UNITS_D_ADDR)
2002     {
2003       enum attr_addr_regfile arf = get_attr_addr_regfile (insn);
2004       int t_half;
2005       gcc_assert (arf != ADDR_REGFILE_UNKNOWN);
2006       half = arf == ADDR_REGFILE_A ? 1 : 2;
2007       t_half = rf == DEST_REGFILE_A ? 1 : 2;
2008       fprintf (file, ".d%dt%d", half, t_half);
2009       return;
2010     }
2011 
2012   if (insn_info.exists ())
2013     {
2014       int unit = INSN_INFO_ENTRY (INSN_UID (insn)).reservation;
2015       fputs (".", file);
2016       fputs (c6x_unit_names[unit], file);
2017       if (cross == CROSS_Y)
2018 	fputs ("x", file);
2019       return;
2020     }
2021 
2022   gcc_assert (rf != DEST_REGFILE_UNKNOWN);
2023   unitspec = c6x_get_unit_specifier (insn);
2024   half = rf == DEST_REGFILE_A ? 1 : 2;
2025   fprintf (file, ".%c%d%s", unitspec, half, cross == CROSS_Y ? "x" : "");
2026 }
2027 
2028 /* Output assembly language output for the address ADDR to FILE.  */
2029 static void
c6x_print_operand_address(FILE * file,machine_mode mode,rtx addr)2030 c6x_print_operand_address (FILE *file, machine_mode mode, rtx addr)
2031 {
2032   c6x_print_address_operand (file, addr, mode);
2033 }
2034 
2035 /* Print an operand, X, to FILE, with an optional modifier in CODE.
2036 
2037    Meaning of CODE:
2038    $ -- print the unit specifier field for the instruction.
2039    . -- print the predicate for the instruction or an emptry string for an
2040         unconditional one.
2041    | -- print "||" if the insn should be issued in parallel with the previous
2042         one.
2043 
2044    C -- print an opcode suffix for a reversed condition
2045    d -- H, W or D as a suffix for ADDA, based on the factor given by the
2046         operand
2047    D -- print either B, H, W or D as a suffix for ADDA, based on the size of
2048         the operand
2049    J -- print a predicate
2050    j -- like J, but use reverse predicate
2051    k -- treat a CONST_INT as a register number and print it as a register
2052    k -- like k, but print out a doubleword register
2053    n -- print an integer operand, negated
2054    p -- print the low part of a DImode register
2055    P -- print the high part of a DImode register
2056    r -- print the absolute value of an integer operand, shifted right by 1
2057    R -- print the absolute value of an integer operand, shifted right by 2
2058    f -- the first clear bit in an integer operand assumed to be a mask for
2059         a clr instruction
2060    F -- the last clear bit in such a mask
2061    s -- the first set bit in an integer operand assumed to be a mask for
2062         a set instruction
2063    S -- the last set bit in such a mask
2064    U -- print either 1 or 2, depending on the side of the machine used by
2065         the operand  */
2066 
2067 static void
c6x_print_operand(FILE * file,rtx x,int code)2068 c6x_print_operand (FILE *file, rtx x, int code)
2069 {
2070   int i;
2071   HOST_WIDE_INT v;
2072   tree t;
2073   machine_mode mode;
2074 
2075   if (code == '|')
2076     {
2077       if (GET_MODE (c6x_current_insn) != TImode)
2078 	fputs ("||", file);
2079       return;
2080     }
2081   if (code == '$')
2082     {
2083       c6x_print_unit_specifier_field (file, c6x_current_insn);
2084       return;
2085     }
2086 
2087   if (code == '.')
2088     {
2089       x = current_insn_predicate;
2090       if (x)
2091 	{
2092 	  unsigned int regno = REGNO (XEXP (x, 0));
2093 	  fputs ("[", file);
2094  	  if (GET_CODE (x) == EQ)
2095 	    fputs ("!", file);
2096 	  fputs (reg_names [regno], file);
2097 	  fputs ("]", file);
2098 	}
2099       return;
2100     }
2101 
2102   mode = GET_MODE (x);
2103 
2104   switch (code)
2105     {
2106     case 'C':
2107     case 'c':
2108       {
2109 	enum rtx_code c = GET_CODE (x);
2110 	if (code == 'C')
2111 	  c = swap_condition (c);
2112 	fputs (GET_RTX_NAME (c), file);
2113       }
2114       return;
2115 
2116     case 'J':
2117     case 'j':
2118       {
2119 	unsigned int regno = REGNO (XEXP (x, 0));
2120 	if ((GET_CODE (x) == EQ) == (code == 'J'))
2121 	  fputs ("!", file);
2122         fputs (reg_names [regno], file);
2123       }
2124       return;
2125 
2126     case 'k':
2127       gcc_assert (GET_CODE (x) == CONST_INT);
2128       v = INTVAL (x);
2129       fprintf (file, "%s", reg_names[v]);
2130       return;
2131     case 'K':
2132       gcc_assert (GET_CODE (x) == CONST_INT);
2133       v = INTVAL (x);
2134       gcc_assert ((v & 1) == 0);
2135       fprintf (file, "%s:%s", reg_names[v + 1], reg_names[v]);
2136       return;
2137 
2138     case 's':
2139     case 'S':
2140     case 'f':
2141     case 'F':
2142       gcc_assert (GET_CODE (x) == CONST_INT);
2143       v = INTVAL (x);
2144       for (i = 0; i < 32; i++)
2145 	{
2146 	  HOST_WIDE_INT tst = v & 1;
2147 	  if (((code == 'f' || code == 'F') && !tst)
2148 	      || ((code == 's' || code == 'S') && tst))
2149 	    break;
2150 	  v >>= 1;
2151 	}
2152       if (code == 'f' || code == 's')
2153 	{
2154 	  fprintf (file, "%d", i);
2155 	  return;
2156 	}
2157       for (;i < 32; i++)
2158 	{
2159 	  HOST_WIDE_INT tst = v & 1;
2160 	  if ((code == 'F' && tst) || (code == 'S' && !tst))
2161 	    break;
2162 	  v >>= 1;
2163 	}
2164       fprintf (file, "%d", i - 1);
2165       return;
2166 
2167     case 'n':
2168       gcc_assert (GET_CODE (x) == CONST_INT);
2169       output_addr_const (file, GEN_INT (-INTVAL (x)));
2170       return;
2171 
2172     case 'r':
2173       gcc_assert (GET_CODE (x) == CONST_INT);
2174       v = INTVAL (x);
2175       if (v < 0)
2176 	v = -v;
2177       output_addr_const (file, GEN_INT (v >> 1));
2178       return;
2179 
2180     case 'R':
2181       gcc_assert (GET_CODE (x) == CONST_INT);
2182       v = INTVAL (x);
2183       if (v < 0)
2184 	v = -v;
2185       output_addr_const (file, GEN_INT (v >> 2));
2186       return;
2187 
2188     case 'd':
2189       gcc_assert (GET_CODE (x) == CONST_INT);
2190       v = INTVAL (x);
2191       fputs (v == 2 ? "h" : v == 4 ? "w" : "d", file);
2192       return;
2193 
2194     case 'p':
2195     case 'P':
2196       gcc_assert (GET_CODE (x) == REG);
2197       v = REGNO (x);
2198       if (code == 'P')
2199 	v++;
2200       fputs (reg_names[v], file);
2201       return;
2202 
2203     case 'D':
2204       v = 0;
2205       if (GET_CODE (x) == CONST)
2206 	{
2207 	  x = XEXP (x, 0);
2208 	  gcc_assert (GET_CODE (x) == PLUS);
2209 	  gcc_assert (GET_CODE (XEXP (x, 1)) == CONST_INT);
2210 	  v = INTVAL (XEXP (x, 1));
2211 	  x = XEXP (x, 0);
2212 
2213 	}
2214       gcc_assert (GET_CODE (x) == SYMBOL_REF);
2215 
2216       t = SYMBOL_REF_DECL (x);
2217       if (DECL_P (t))
2218 	v |= DECL_ALIGN_UNIT (t);
2219       else
2220 	v |= TYPE_ALIGN_UNIT (TREE_TYPE (t));
2221       if (v & 1)
2222 	fputs ("b", file);
2223       else if (v & 2)
2224 	fputs ("h", file);
2225       else
2226 	fputs ("w", file);
2227       return;
2228 
2229     case 'U':
2230       if (MEM_P (x))
2231 	{
2232 	  x = XEXP (x, 0);
2233 	  if (GET_CODE (x) == PLUS
2234 	      || GET_RTX_CLASS (GET_CODE (x)) == RTX_AUTOINC)
2235 	    x = XEXP (x, 0);
2236 	  if (GET_CODE (x) == CONST || GET_CODE (x) == SYMBOL_REF)
2237 	    {
2238 	      gcc_assert (sdata_symbolic_operand (x, Pmode));
2239 	      fputs ("2", file);
2240 	      return;
2241 	    }
2242 	}
2243       gcc_assert (REG_P (x));
2244       if (A_REGNO_P (REGNO (x)))
2245 	fputs ("1", file);
2246       if (B_REGNO_P (REGNO (x)))
2247 	fputs ("2", file);
2248       return;
2249 
2250     default:
2251       switch (GET_CODE (x))
2252 	{
2253 	case REG:
2254 	  if (GET_MODE_SIZE (mode) == 8)
2255 	    fprintf (file, "%s:%s", reg_names[REGNO (x) + 1],
2256 		     reg_names[REGNO (x)]);
2257 	  else
2258 	    fprintf (file, "%s", reg_names[REGNO (x)]);
2259 	  break;
2260 
2261 	case MEM:
2262 	  fputc ('*', file);
2263 	  gcc_assert (XEXP (x, 0) != stack_pointer_rtx);
2264 	  c6x_print_address_operand (file, XEXP (x, 0), GET_MODE (x));
2265 	  break;
2266 
2267 	case SYMBOL_REF:
2268 	  fputc ('(', file);
2269 	  output_addr_const (file, x);
2270 	  fputc (')', file);
2271 	  break;
2272 
2273 	case CONST_INT:
2274 	  output_addr_const (file, x);
2275 	  break;
2276 
2277 	case CONST_DOUBLE:
2278 	  output_operand_lossage ("invalid const_double operand");
2279 	  break;
2280 
2281 	default:
2282 	  output_addr_const (file, x);
2283 	}
2284     }
2285 }
2286 
2287 /* Return TRUE if OP is a valid memory address with a base register of
2288    class C.  If SMALL_OFFSET is true, we disallow memory references which would
2289    require a long offset with B14/B15.  */
2290 
2291 bool
c6x_mem_operand(rtx op,enum reg_class c,bool small_offset)2292 c6x_mem_operand (rtx op, enum reg_class c, bool small_offset)
2293 {
2294   machine_mode mode = GET_MODE (op);
2295   rtx base = XEXP (op, 0);
2296   switch (GET_CODE (base))
2297     {
2298     case REG:
2299       break;
2300     case PLUS:
2301       if (small_offset
2302 	  && (XEXP (base, 0) == stack_pointer_rtx
2303 	      || XEXP (base, 0) == pic_offset_table_rtx))
2304 	{
2305 	  if (!c6x_legitimate_address_p_1 (mode, base, true, true))
2306 	    return false;
2307 	}
2308 
2309       /* fall through */
2310     case PRE_INC:
2311     case PRE_DEC:
2312     case PRE_MODIFY:
2313     case POST_INC:
2314     case POST_DEC:
2315     case POST_MODIFY:
2316       base = XEXP (base, 0);
2317       break;
2318 
2319     case CONST:
2320     case LABEL_REF:
2321     case SYMBOL_REF:
2322       gcc_assert (sdata_symbolic_operand (base, Pmode));
2323       return !small_offset && c == B_REGS;
2324 
2325     default:
2326       return false;
2327     }
2328   return TEST_HARD_REG_BIT (reg_class_contents[ (int) (c)], REGNO (base));
2329 }
2330 
2331 /* Returns true if X is a valid address for use in a memory reference
2332    of mode MODE.  If STRICT is true, we do not allow pseudo registers
2333    in the address.  NO_LARGE_OFFSET is true if we are examining an
2334    address for use in a load or store misaligned instruction, or
2335    recursively examining an operand inside a PRE/POST_MODIFY.  */
2336 
2337 bool
c6x_legitimate_address_p_1(machine_mode mode,rtx x,bool strict,bool no_large_offset)2338 c6x_legitimate_address_p_1 (machine_mode mode, rtx x, bool strict,
2339 			    bool no_large_offset)
2340 {
2341   int size, size1;
2342   HOST_WIDE_INT off;
2343   enum rtx_code code = GET_CODE (x);
2344 
2345   switch (code)
2346     {
2347     case PRE_MODIFY:
2348     case POST_MODIFY:
2349       /* We can't split these into word-sized pieces yet.  */
2350       if (!TARGET_STDW && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
2351 	return false;
2352       if (GET_CODE (XEXP (x, 1)) != PLUS)
2353 	return false;
2354       if (!c6x_legitimate_address_p_1 (mode, XEXP (x, 1), strict, true))
2355 	return false;
2356       if (!rtx_equal_p (XEXP (x, 0), XEXP (XEXP (x, 1), 0)))
2357 	return false;
2358 
2359       /* fall through */
2360     case PRE_INC:
2361     case PRE_DEC:
2362     case POST_INC:
2363     case POST_DEC:
2364       /* We can't split these into word-sized pieces yet.  */
2365       if (!TARGET_STDW && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
2366 	return false;
2367       x = XEXP (x, 0);
2368       if (!REG_P (x))
2369 	return false;
2370 
2371       /* fall through */
2372     case REG:
2373       if (strict)
2374 	return REGNO_OK_FOR_BASE_STRICT_P (REGNO (x));
2375       else
2376 	return REGNO_OK_FOR_BASE_NONSTRICT_P (REGNO (x));
2377 
2378     case PLUS:
2379       if (!REG_P (XEXP (x, 0))
2380 	  || !c6x_legitimate_address_p_1 (mode, XEXP (x, 0), strict, false))
2381 	return false;
2382       /* We cannot ensure currently that both registers end up in the
2383 	 same register file.  */
2384       if (REG_P (XEXP (x, 1)))
2385 	return false;
2386 
2387       if (mode == BLKmode)
2388 	size = 4;
2389       else if (mode == VOIDmode)
2390 	/* ??? This can happen during ivopts.  */
2391 	size = 1;
2392       else
2393 	size = GET_MODE_SIZE (mode);
2394 
2395       if (flag_pic
2396 	  && GET_CODE (XEXP (x, 1)) == UNSPEC
2397 	  && XINT (XEXP (x, 1), 1) == UNSPEC_LOAD_SDATA
2398 	  && XEXP (x, 0) == pic_offset_table_rtx
2399 	  && sdata_symbolic_operand (XVECEXP (XEXP (x, 1), 0, 0), SImode))
2400 	return !no_large_offset && size <= 4;
2401       if (flag_pic == 1
2402 	  && mode == Pmode
2403 	  && GET_CODE (XEXP (x, 1)) == UNSPEC
2404 	  && XINT (XEXP (x, 1), 1) == UNSPEC_LOAD_GOT
2405 	  && XEXP (x, 0) == pic_offset_table_rtx
2406 	  && (GET_CODE (XVECEXP (XEXP (x, 1), 0, 0)) == SYMBOL_REF
2407 	      || GET_CODE (XVECEXP (XEXP (x, 1), 0, 0)) == LABEL_REF))
2408 	return !no_large_offset;
2409       if (GET_CODE (XEXP (x, 1)) != CONST_INT)
2410 	return false;
2411 
2412       off = INTVAL (XEXP (x, 1));
2413 
2414       /* If the machine does not have doubleword load/stores, we'll use
2415 	 word size accesses.  */
2416       size1 = size;
2417       if (size == 2 * UNITS_PER_WORD && !TARGET_STDW)
2418 	size = UNITS_PER_WORD;
2419 
2420       if (((HOST_WIDE_INT)size1 - 1) & off)
2421 	return false;
2422       off /= size;
2423       if (off > -32 && off < (size1 == size ? 32 : 28))
2424 	return true;
2425       if (no_large_offset || code != PLUS || XEXP (x, 0) != stack_pointer_rtx
2426 	  || size1 > UNITS_PER_WORD)
2427 	return false;
2428       return off >= 0 && off < 32768;
2429 
2430     case CONST:
2431     case SYMBOL_REF:
2432     case LABEL_REF:
2433       return (!no_large_offset
2434 	      /* With -fpic, we must wrap it in an unspec to show the B14
2435 		 dependency.  */
2436 	      && !flag_pic
2437 	      && GET_MODE_SIZE (mode) <= UNITS_PER_WORD
2438 	      && sdata_symbolic_operand (x, Pmode));
2439 
2440     default:
2441       return false;
2442     }
2443 }
2444 
2445 static bool
c6x_legitimate_address_p(machine_mode mode,rtx x,bool strict)2446 c6x_legitimate_address_p (machine_mode mode, rtx x, bool strict)
2447 {
2448   return c6x_legitimate_address_p_1 (mode, x, strict, false);
2449 }
2450 
2451 static bool
c6x_legitimate_constant_p(machine_mode mode ATTRIBUTE_UNUSED,rtx x ATTRIBUTE_UNUSED)2452 c6x_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED,
2453 			   rtx x ATTRIBUTE_UNUSED)
2454 {
2455   return true;
2456 }
2457 
2458 /* Implements TARGET_PREFERRED_RENAME_CLASS.  */
2459 static reg_class_t
c6x_preferred_rename_class(reg_class_t cl)2460 c6x_preferred_rename_class (reg_class_t cl)
2461 {
2462   if (cl == A_REGS)
2463     return NONPREDICATE_A_REGS;
2464   if (cl == B_REGS)
2465     return NONPREDICATE_B_REGS;
2466   if (cl == ALL_REGS || cl == GENERAL_REGS)
2467     return NONPREDICATE_REGS;
2468   return NO_REGS;
2469 }
2470 
2471 /* Implements FINAL_PRESCAN_INSN.  */
2472 void
c6x_final_prescan_insn(rtx_insn * insn,rtx * opvec ATTRIBUTE_UNUSED,int noperands ATTRIBUTE_UNUSED)2473 c6x_final_prescan_insn (rtx_insn *insn, rtx *opvec ATTRIBUTE_UNUSED,
2474 			int noperands ATTRIBUTE_UNUSED)
2475 {
2476   c6x_current_insn = insn;
2477 }
2478 
2479 /* A structure to describe the stack layout of a function.  The layout is
2480    as follows:
2481 
2482    [saved frame pointer (or possibly padding0)]
2483    --> incoming stack pointer, new hard frame pointer
2484    [saved call-used regs]
2485    [optional padding1]
2486    --> soft frame pointer
2487    [frame]
2488    [outgoing arguments]
2489    [optional padding2]
2490 
2491   The structure members are laid out in this order.  */
2492 
2493 struct c6x_frame
2494 {
2495   int padding0;
2496   /* Number of registers to save.  */
2497   int nregs;
2498   int padding1;
2499   HOST_WIDE_INT frame;
2500   int outgoing_arguments_size;
2501   int padding2;
2502 
2503   HOST_WIDE_INT to_allocate;
2504   /* The offsets relative to the incoming stack pointer (which
2505      becomes HARD_FRAME_POINTER).  */
2506   HOST_WIDE_INT frame_pointer_offset;
2507   HOST_WIDE_INT b3_offset;
2508 
2509   /* True if we should call push_rts/pop_rts to save and restore
2510      registers.  */
2511   bool push_rts;
2512 };
2513 
2514 /* Return true if we need to save and modify the PIC register in the
2515    prologue.  */
2516 
2517 static bool
must_reload_pic_reg_p(void)2518 must_reload_pic_reg_p (void)
2519 {
2520   if (!TARGET_DSBT)
2521     return false;
2522 
2523   cgraph_node *local_info_node
2524     = cgraph_node::local_info_node (current_function_decl);
2525   if ((crtl->uses_pic_offset_table || !crtl->is_leaf)
2526       && !local_info_node->local)
2527     return true;
2528   return false;
2529 }
2530 
2531 /* Return 1 if we need to save REGNO.  */
2532 static int
c6x_save_reg(unsigned int regno)2533 c6x_save_reg (unsigned int regno)
2534 {
2535   return ((df_regs_ever_live_p (regno)
2536 	   && !call_used_or_fixed_reg_p (regno))
2537 	  || (regno == RETURN_ADDR_REGNO
2538 	      && (df_regs_ever_live_p (regno)
2539 		  || !crtl->is_leaf))
2540 	  || (regno == PIC_OFFSET_TABLE_REGNUM && must_reload_pic_reg_p ()));
2541 }
2542 
2543 /* Examine the number of regs NREGS we've determined we must save.
2544    Return true if we should use __c6xabi_push_rts/__c6xabi_pop_rts for
2545    prologue and epilogue.  */
2546 
2547 static bool
use_push_rts_p(int nregs)2548 use_push_rts_p (int nregs)
2549 {
2550   if (TARGET_INSNS_64PLUS && optimize_function_for_size_p (cfun)
2551       && !cfun->machine->contains_sibcall
2552       && !cfun->returns_struct
2553       && !TARGET_LONG_CALLS
2554       && nregs >= 6 && !frame_pointer_needed)
2555     return true;
2556   return false;
2557 }
2558 
2559 /* Return number of saved general prupose registers.  */
2560 
2561 int
c6x_nsaved_regs(void)2562 c6x_nsaved_regs (void)
2563 {
2564   int nregs = 0;
2565   int regno;
2566 
2567   for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
2568     if (c6x_save_reg (regno))
2569       nregs++;
2570   return nregs;
2571 }
2572 
2573 /* The safe debug order mandated by the ABI.  */
2574 static unsigned reg_save_order[] =
2575 {
2576   REG_A10, REG_A11, REG_A12, REG_A13,
2577   REG_A14, REG_B3,
2578   REG_B10, REG_B11, REG_B12, REG_B13,
2579   REG_B14, REG_A15
2580 };
2581 
2582 #define N_SAVE_ORDER (sizeof reg_save_order / sizeof *reg_save_order)
2583 
2584 /* Compute the layout of the stack frame and store it in FRAME.  */
2585 
2586 static void
c6x_compute_frame_layout(struct c6x_frame * frame)2587 c6x_compute_frame_layout (struct c6x_frame *frame)
2588 {
2589   HOST_WIDE_INT size = get_frame_size ();
2590   HOST_WIDE_INT offset;
2591   int nregs;
2592 
2593   /* We use the four bytes which are technically inside the caller's frame,
2594      usually to save the frame pointer.  */
2595   offset = -4;
2596   frame->padding0 = 0;
2597   nregs = c6x_nsaved_regs ();
2598   frame->push_rts = false;
2599   frame->b3_offset = 0;
2600   if (use_push_rts_p (nregs))
2601     {
2602       frame->push_rts = true;
2603       frame->b3_offset = (TARGET_BIG_ENDIAN ? -12 : -13) * 4;
2604       nregs = 14;
2605     }
2606   else if (c6x_save_reg (REG_B3))
2607     {
2608       int idx;
2609       for (idx = N_SAVE_ORDER - 1; reg_save_order[idx] != REG_B3; idx--)
2610 	{
2611 	  if (c6x_save_reg (reg_save_order[idx]))
2612 	    frame->b3_offset -= 4;
2613 	}
2614     }
2615   frame->nregs = nregs;
2616 
2617   if (size == 0 && nregs == 0)
2618     {
2619       frame->padding0 = 4;
2620       frame->padding1 = frame->padding2 = 0;
2621       frame->frame_pointer_offset = frame->to_allocate = 0;
2622       frame->outgoing_arguments_size = 0;
2623       return;
2624     }
2625 
2626   if (!frame->push_rts)
2627     offset += frame->nregs * 4;
2628 
2629   if (offset == 0 && size == 0 && crtl->outgoing_args_size == 0
2630       && !crtl->is_leaf)
2631     /* Don't use the bottom of the caller's frame if we have no
2632        allocation of our own and call other functions.  */
2633     frame->padding0 = frame->padding1 = 4;
2634   else if (offset & 4)
2635     frame->padding1 = 4;
2636   else
2637     frame->padding1 = 0;
2638 
2639   offset += frame->padding0 + frame->padding1;
2640   frame->frame_pointer_offset = offset;
2641   offset += size;
2642 
2643   frame->outgoing_arguments_size = crtl->outgoing_args_size;
2644   offset += frame->outgoing_arguments_size;
2645 
2646   if ((offset & 4) == 0)
2647     frame->padding2 = 8;
2648   else
2649     frame->padding2 = 4;
2650   frame->to_allocate = offset + frame->padding2;
2651 }
2652 
2653 /* Return the offset between two registers, one to be eliminated, and the other
2654    its replacement, at the start of a routine.  */
2655 
2656 HOST_WIDE_INT
c6x_initial_elimination_offset(int from,int to)2657 c6x_initial_elimination_offset (int from, int to)
2658 {
2659   struct c6x_frame frame;
2660   c6x_compute_frame_layout (&frame);
2661 
2662   if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
2663     return 0;
2664   else if (from == FRAME_POINTER_REGNUM
2665 	   && to == HARD_FRAME_POINTER_REGNUM)
2666     return -frame.frame_pointer_offset;
2667   else
2668     {
2669       gcc_assert (to == STACK_POINTER_REGNUM);
2670 
2671       if (from == ARG_POINTER_REGNUM)
2672 	return frame.to_allocate + (frame.push_rts ? 56 : 0);
2673 
2674       gcc_assert (from == FRAME_POINTER_REGNUM);
2675       return frame.to_allocate - frame.frame_pointer_offset;
2676     }
2677 }
2678 
2679 /* Given FROM and TO register numbers, say whether this elimination is
2680    allowed.  Frame pointer elimination is automatically handled.  */
2681 
2682 static bool
c6x_can_eliminate(const int from ATTRIBUTE_UNUSED,const int to)2683 c6x_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
2684 {
2685   if (to == STACK_POINTER_REGNUM)
2686     return !frame_pointer_needed;
2687   return true;
2688 }
2689 
2690 /* Emit insns to increment the stack pointer by OFFSET.  If
2691    FRAME_RELATED_P, set the RTX_FRAME_RELATED_P flag on the insns.
2692    Does nothing if the offset is zero.  */
2693 
2694 static void
emit_add_sp_const(HOST_WIDE_INT offset,bool frame_related_p)2695 emit_add_sp_const (HOST_WIDE_INT offset, bool frame_related_p)
2696 {
2697   rtx to_add = GEN_INT (offset);
2698   rtx orig_to_add = to_add;
2699   rtx_insn *insn;
2700 
2701   if (offset == 0)
2702     return;
2703 
2704   if (offset < -32768 || offset > 32767)
2705     {
2706       rtx reg = gen_rtx_REG (SImode, REG_A0);
2707       rtx low = GEN_INT (trunc_int_for_mode (offset, HImode));
2708 
2709       insn = emit_insn (gen_movsi_high (reg, low));
2710       if (frame_related_p)
2711 	RTX_FRAME_RELATED_P (insn) = 1;
2712       insn = emit_insn (gen_movsi_lo_sum (reg, reg, to_add));
2713       if (frame_related_p)
2714 	RTX_FRAME_RELATED_P (insn) = 1;
2715       to_add = reg;
2716     }
2717   insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
2718 				to_add));
2719   if (frame_related_p)
2720     {
2721       if (REG_P (to_add))
2722 	add_reg_note (insn, REG_FRAME_RELATED_EXPR,
2723 		      gen_rtx_SET (stack_pointer_rtx,
2724 				   gen_rtx_PLUS (Pmode, stack_pointer_rtx,
2725 						 orig_to_add)));
2726 
2727       RTX_FRAME_RELATED_P (insn) = 1;
2728     }
2729 }
2730 
2731 /* Prologue and epilogue.  */
2732 void
c6x_expand_prologue(void)2733 c6x_expand_prologue (void)
2734 {
2735   struct c6x_frame frame;
2736   rtx_insn *insn;
2737   rtx mem;
2738   int nsaved = 0;
2739   HOST_WIDE_INT initial_offset, off, added_already;
2740 
2741   c6x_compute_frame_layout (&frame);
2742 
2743   if (flag_stack_usage_info)
2744     current_function_static_stack_size = frame.to_allocate;
2745 
2746   initial_offset = -frame.to_allocate;
2747   if (frame.push_rts)
2748     {
2749       emit_insn (gen_push_rts ());
2750       nsaved = frame.nregs;
2751     }
2752 
2753   /* If the offsets would be too large for the memory references we will
2754      create to save registers, do the stack allocation in two parts.
2755      Ensure by subtracting 8 that we don't store to the word pointed to
2756      by the stack pointer.  */
2757   if (initial_offset < -32768)
2758     initial_offset = -frame.frame_pointer_offset - 8;
2759 
2760   if (frame.to_allocate > 0)
2761     gcc_assert (initial_offset != 0);
2762 
2763   off = -initial_offset + 4 - frame.padding0;
2764 
2765   mem = gen_frame_mem (Pmode, stack_pointer_rtx);
2766 
2767   added_already = 0;
2768   if (frame_pointer_needed)
2769     {
2770       rtx fp_reg = gen_rtx_REG (SImode, REG_A15);
2771       /* We go through some contortions here to both follow the ABI's
2772 	 recommendation that FP == incoming SP, and to avoid writing or
2773 	 reading the word pointed to by the stack pointer.  */
2774       rtx addr = gen_rtx_POST_MODIFY (Pmode, stack_pointer_rtx,
2775 				      gen_rtx_PLUS (Pmode, stack_pointer_rtx,
2776 						    GEN_INT (-8)));
2777       insn = emit_move_insn (gen_frame_mem (Pmode, addr), fp_reg);
2778       RTX_FRAME_RELATED_P (insn) = 1;
2779       nsaved++;
2780       insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx, stack_pointer_rtx,
2781 				    GEN_INT (8)));
2782       RTX_FRAME_RELATED_P (insn) = 1;
2783       off -= 4;
2784       added_already = -8;
2785     }
2786 
2787   emit_add_sp_const (initial_offset - added_already, true);
2788 
2789   if (nsaved < frame.nregs)
2790     {
2791       unsigned i;
2792 
2793       for (i = 0; i < N_SAVE_ORDER; i++)
2794 	{
2795 	  int idx = N_SAVE_ORDER - i - 1;
2796 	  unsigned regno = reg_save_order[idx];
2797 	  rtx reg;
2798 	  machine_mode save_mode = SImode;
2799 
2800 	  if (regno == REG_A15 && frame_pointer_needed)
2801 	    /* Already saved.  */
2802 	    continue;
2803 	  if (!c6x_save_reg (regno))
2804 	    continue;
2805 
2806 	  if (TARGET_STDW && (off & 4) == 0 && off <= 256
2807 	      && (regno & 1) == 1
2808 	      && i + 1 < N_SAVE_ORDER
2809 	      && reg_save_order[idx - 1] == regno - 1
2810 	      && c6x_save_reg (regno - 1))
2811 	    {
2812 	      save_mode = DImode;
2813 	      regno--;
2814 	      i++;
2815 	    }
2816 	  reg = gen_rtx_REG (save_mode, regno);
2817 	  off -= GET_MODE_SIZE (save_mode);
2818 
2819 	  insn = emit_move_insn (adjust_address (mem, save_mode, off),
2820 				 reg);
2821 	  RTX_FRAME_RELATED_P (insn) = 1;
2822 
2823 	  nsaved += hard_regno_nregs (regno, save_mode);
2824 	}
2825     }
2826   gcc_assert (nsaved == frame.nregs);
2827   emit_add_sp_const (-frame.to_allocate - initial_offset, true);
2828   if (must_reload_pic_reg_p ())
2829     {
2830       if (dsbt_decl == NULL)
2831 	{
2832 	  tree t;
2833 
2834 	  t = build_index_type (integer_one_node);
2835 	  t = build_array_type (integer_type_node, t);
2836 	  t = build_decl (BUILTINS_LOCATION, VAR_DECL,
2837 			  get_identifier ("__c6xabi_DSBT_BASE"), t);
2838 	  DECL_ARTIFICIAL (t) = 1;
2839 	  DECL_IGNORED_P (t) = 1;
2840 	  DECL_EXTERNAL (t) = 1;
2841 	  TREE_STATIC (t) = 1;
2842 	  TREE_PUBLIC (t) = 1;
2843 	  TREE_USED (t) = 1;
2844 
2845 	  dsbt_decl = t;
2846 	}
2847       emit_insn (gen_setup_dsbt (pic_offset_table_rtx,
2848 				 XEXP (DECL_RTL (dsbt_decl), 0)));
2849     }
2850 }
2851 
2852 void
c6x_expand_epilogue(bool sibcall)2853 c6x_expand_epilogue (bool sibcall)
2854 {
2855   unsigned i;
2856   struct c6x_frame frame;
2857   rtx mem;
2858   HOST_WIDE_INT off;
2859   int nsaved = 0;
2860 
2861   c6x_compute_frame_layout (&frame);
2862 
2863   mem = gen_frame_mem (Pmode, stack_pointer_rtx);
2864 
2865   /* Insert a dummy set/use of the stack pointer.  This creates a
2866      scheduler barrier between the prologue saves and epilogue restores. */
2867   emit_insn (gen_epilogue_barrier (stack_pointer_rtx, stack_pointer_rtx));
2868 
2869   /* If the offsets would be too large for the memory references we will
2870      create to restore registers, do a preliminary stack adjustment here.  */
2871   off = frame.to_allocate - frame.frame_pointer_offset + frame.padding1;
2872   if (frame.push_rts)
2873     {
2874       nsaved = frame.nregs;
2875     }
2876   else
2877     {
2878       if (frame.to_allocate > 32768)
2879 	{
2880 	  /* Don't add the entire offset so that we leave an unused word
2881 	     above the stack pointer.  */
2882 	  emit_add_sp_const ((off - 16) & ~7, false);
2883 	  off &= 7;
2884 	  off += 16;
2885 	}
2886       for (i = 0; i < N_SAVE_ORDER; i++)
2887 	{
2888 	  unsigned regno = reg_save_order[i];
2889 	  rtx reg;
2890 	  machine_mode save_mode = SImode;
2891 
2892 	  if (!c6x_save_reg (regno))
2893 	    continue;
2894 	  if (regno == REG_A15 && frame_pointer_needed)
2895 	    continue;
2896 
2897 	  if (TARGET_STDW && (off & 4) == 0 && off < 256
2898 	      && (regno & 1) == 0
2899 	      && i + 1 < N_SAVE_ORDER
2900 	      && reg_save_order[i + 1] == regno + 1
2901 	      && c6x_save_reg (regno + 1))
2902 	    {
2903 	      save_mode = DImode;
2904 	      i++;
2905 	    }
2906 	  reg = gen_rtx_REG (save_mode, regno);
2907 
2908 	  emit_move_insn (reg, adjust_address (mem, save_mode, off));
2909 
2910 	  off += GET_MODE_SIZE (save_mode);
2911 	  nsaved += hard_regno_nregs (regno, save_mode);
2912 	}
2913     }
2914   if (!frame_pointer_needed)
2915     emit_add_sp_const (off + frame.padding0 - 4, false);
2916   else
2917     {
2918       rtx fp_reg = gen_rtx_REG (SImode, REG_A15);
2919       rtx addr = gen_rtx_PRE_MODIFY (Pmode, stack_pointer_rtx,
2920 				      gen_rtx_PLUS (Pmode, stack_pointer_rtx,
2921 						    GEN_INT (8)));
2922       emit_insn (gen_addsi3 (stack_pointer_rtx, hard_frame_pointer_rtx,
2923 			     GEN_INT (-8)));
2924       emit_move_insn (fp_reg, gen_frame_mem (Pmode, addr));
2925       nsaved++;
2926     }
2927   gcc_assert (nsaved == frame.nregs);
2928   if (!sibcall)
2929     {
2930       if (frame.push_rts)
2931 	emit_jump_insn (gen_pop_rts ());
2932       else
2933 	emit_jump_insn (gen_return_internal (gen_rtx_REG (SImode,
2934 							  RETURN_ADDR_REGNO)));
2935     }
2936 }
2937 
2938 /* Return the value of the return address for the frame COUNT steps up
2939    from the current frame, after the prologue.
2940    We punt for everything but the current frame by returning const0_rtx.  */
2941 
2942 rtx
c6x_return_addr_rtx(int count)2943 c6x_return_addr_rtx (int count)
2944 {
2945   if (count != 0)
2946     return const0_rtx;
2947 
2948   return get_hard_reg_initial_val (Pmode, RETURN_ADDR_REGNO);
2949 }
2950 
2951 /* Return true iff TYPE is one of the shadow types.  */
2952 static bool
shadow_type_p(enum attr_type type)2953 shadow_type_p (enum attr_type type)
2954 {
2955   return (type == TYPE_SHADOW || type == TYPE_LOAD_SHADOW
2956 	  || type == TYPE_MULT_SHADOW);
2957 }
2958 
2959 /* Return true iff INSN is a shadow pattern.  */
2960 static bool
shadow_p(rtx_insn * insn)2961 shadow_p (rtx_insn *insn)
2962 {
2963   if (!NONDEBUG_INSN_P (insn) || recog_memoized (insn) < 0)
2964     return false;
2965   return shadow_type_p (get_attr_type (insn));
2966 }
2967 
2968 /* Return true iff INSN is a shadow or blockage pattern.  */
2969 static bool
shadow_or_blockage_p(rtx_insn * insn)2970 shadow_or_blockage_p (rtx_insn *insn)
2971 {
2972   enum attr_type type;
2973   if (!NONDEBUG_INSN_P (insn) || recog_memoized (insn) < 0)
2974     return false;
2975   type = get_attr_type (insn);
2976   return shadow_type_p (type) || type == TYPE_BLOCKAGE;
2977 }
2978 
2979 /* Translate UNITS into a bitmask of units we can reserve for this
2980    insn.  */
2981 static int
get_reservation_flags(enum attr_units units)2982 get_reservation_flags (enum attr_units units)
2983 {
2984   switch (units)
2985     {
2986     case UNITS_D:
2987     case UNITS_D_ADDR:
2988       return RESERVATION_FLAG_D;
2989     case UNITS_L:
2990       return RESERVATION_FLAG_L;
2991     case UNITS_S:
2992       return RESERVATION_FLAG_S;
2993     case UNITS_M:
2994       return RESERVATION_FLAG_M;
2995     case UNITS_LS:
2996       return RESERVATION_FLAG_LS;
2997     case UNITS_DL:
2998       return RESERVATION_FLAG_DL;
2999     case UNITS_DS:
3000       return RESERVATION_FLAG_DS;
3001     case UNITS_DLS:
3002       return RESERVATION_FLAG_DLS;
3003     default:
3004       return 0;
3005     }
3006 }
3007 
3008 /* Compute the side of the machine used by INSN, which reserves UNITS.
3009    This must match the reservations in the scheduling description.  */
3010 static int
get_insn_side(rtx_insn * insn,enum attr_units units)3011 get_insn_side (rtx_insn *insn, enum attr_units units)
3012 {
3013   if (units == UNITS_D_ADDR)
3014     return (get_attr_addr_regfile (insn) == ADDR_REGFILE_A ? 0 : 1);
3015   else
3016     {
3017       enum attr_dest_regfile rf = get_attr_dest_regfile (insn);
3018       if (rf == DEST_REGFILE_ANY)
3019 	return get_attr_type (insn) == TYPE_BRANCH ? 0 : 1;
3020       else
3021 	return rf == DEST_REGFILE_A ? 0 : 1;
3022     }
3023 }
3024 
3025 /* After scheduling, walk the insns between HEAD and END and assign unit
3026    reservations.  */
3027 static void
assign_reservations(rtx_insn * head,rtx_insn * end)3028 assign_reservations (rtx_insn *head, rtx_insn *end)
3029 {
3030   rtx_insn *insn;
3031   for (insn = head; insn != NEXT_INSN (end); insn = NEXT_INSN (insn))
3032     {
3033       unsigned int sched_mask, reserved;
3034       rtx_insn *within, *last;
3035       int pass;
3036       int rsrv[2];
3037       int rsrv_count[2][4];
3038       int i;
3039 
3040       if (GET_MODE (insn) != TImode)
3041 	continue;
3042 
3043       reserved = 0;
3044       last = NULL;
3045       /* Find the last insn in the packet.  It has a state recorded for it,
3046 	 which we can use to determine the units we should be using.  */
3047       for (within = insn;
3048 	   (within != NEXT_INSN (end)
3049 	    && (within == insn || GET_MODE (within) != TImode));
3050 	   within = NEXT_INSN (within))
3051 	{
3052 	  int icode;
3053 	  if (!NONDEBUG_INSN_P (within))
3054 	    continue;
3055 	  icode = recog_memoized (within);
3056 	  if (icode < 0)
3057 	    continue;
3058 	  if (shadow_p (within))
3059 	    continue;
3060 	  if (INSN_INFO_ENTRY (INSN_UID (within)).reservation != 0)
3061 	    reserved |= 1 << INSN_INFO_ENTRY (INSN_UID (within)).reservation;
3062 	  last = within;
3063 	}
3064       if (last == NULL_RTX)
3065 	continue;
3066 
3067       sched_mask = INSN_INFO_ENTRY (INSN_UID (last)).unit_mask;
3068       sched_mask &= ~reserved;
3069 
3070       memset (rsrv_count, 0, sizeof rsrv_count);
3071       rsrv[0] = rsrv[1] = ~0;
3072       for (i = 0; i < 8; i++)
3073 	{
3074 	  int side = i / 4;
3075 	  int unit = i & 3;
3076 	  unsigned unit_bit = 1 << (unit + side * UNIT_QID_SIDE_OFFSET);
3077 	  /* Clear the bits which we expect to reserve in the following loop,
3078 	     leaving the ones set which aren't present in the scheduler's
3079 	     state and shouldn't be reserved.  */
3080 	  if (sched_mask & unit_bit)
3081 	    rsrv[i / 4] &= ~(1 << unit);
3082 	}
3083 
3084       /* Walk through the insns that occur in the same cycle.  We use multiple
3085 	 passes to assign units, assigning for insns with the most specific
3086 	 requirements first.  */
3087       for (pass = 0; pass < 4; pass++)
3088 	for (within = insn;
3089 	     (within != NEXT_INSN (end)
3090 	      && (within == insn || GET_MODE (within) != TImode));
3091 	     within = NEXT_INSN (within))
3092 	  {
3093 	    int uid = INSN_UID (within);
3094 	    int this_rsrv, side;
3095 	    int icode;
3096 	    enum attr_units units;
3097 	    enum attr_type type;
3098 	    int j;
3099 
3100 	    if (!NONDEBUG_INSN_P (within))
3101 	      continue;
3102 	    icode = recog_memoized (within);
3103 	    if (icode < 0)
3104 	      continue;
3105 	    if (INSN_INFO_ENTRY (uid).reservation != 0)
3106 	      continue;
3107 	    units = get_attr_units (within);
3108 	    type = get_attr_type (within);
3109 	    this_rsrv = get_reservation_flags (units);
3110 	    if (this_rsrv == 0)
3111 	      continue;
3112 	    side = get_insn_side (within, units);
3113 
3114 	    /* Certain floating point instructions are treated specially.  If
3115 	       an insn can choose between units it can reserve, and its
3116 	       reservation spans more than one cycle, the reservation contains
3117 	       special markers in the first cycle to help us reconstruct what
3118 	       the automaton chose.  */
3119 	    if ((type == TYPE_ADDDP || type == TYPE_FP4)
3120 		&& units == UNITS_LS)
3121 	      {
3122 		int test1_code = ((type == TYPE_FP4 ? UNIT_QID_FPL1 : UNIT_QID_ADDDPL1)
3123 				  + side * UNIT_QID_SIDE_OFFSET);
3124 		int test2_code = ((type == TYPE_FP4 ? UNIT_QID_FPS1 : UNIT_QID_ADDDPS1)
3125 				  + side * UNIT_QID_SIDE_OFFSET);
3126 		if ((sched_mask & (1 << test1_code)) != 0)
3127 		  {
3128 		    this_rsrv = RESERVATION_FLAG_L;
3129 		    sched_mask &= ~(1 << test1_code);
3130 		  }
3131 		else if ((sched_mask & (1 << test2_code)) != 0)
3132 		  {
3133 		    this_rsrv = RESERVATION_FLAG_S;
3134 		    sched_mask &= ~(1 << test2_code);
3135 		  }
3136 	      }
3137 
3138 	    if ((this_rsrv & (this_rsrv - 1)) == 0)
3139 	      {
3140 		int t = exact_log2 (this_rsrv) + side * UNIT_QID_SIDE_OFFSET;
3141 		rsrv[side] |= this_rsrv;
3142 		INSN_INFO_ENTRY (uid).reservation = t;
3143 		continue;
3144 	      }
3145 
3146 	    if (pass == 1)
3147 	      {
3148 		for (j = 0; j < 4; j++)
3149 		  if (this_rsrv & (1 << j))
3150 		    rsrv_count[side][j]++;
3151 		continue;
3152 	      }
3153 	    if ((pass == 2 && this_rsrv != RESERVATION_FLAG_DLS)
3154 		|| (pass == 3 && this_rsrv == RESERVATION_FLAG_DLS))
3155 	      {
3156 		int best = -1, best_cost = INT_MAX;
3157 		for (j = 0; j < 4; j++)
3158 		  if ((this_rsrv & (1 << j))
3159 		      && !(rsrv[side] & (1 << j))
3160 		      && rsrv_count[side][j] < best_cost)
3161 		    {
3162 		      best_cost = rsrv_count[side][j];
3163 		      best = j;
3164 		    }
3165 		gcc_assert (best != -1);
3166 		rsrv[side] |= 1 << best;
3167 		for (j = 0; j < 4; j++)
3168 		  if ((this_rsrv & (1 << j)) && j != best)
3169 		    rsrv_count[side][j]--;
3170 
3171 		INSN_INFO_ENTRY (uid).reservation
3172 		  = best + side * UNIT_QID_SIDE_OFFSET;
3173 	      }
3174 	  }
3175     }
3176 }
3177 
3178 /* Return a factor by which to weight unit imbalances for a reservation
3179    R.  */
3180 static int
unit_req_factor(enum unitreqs r)3181 unit_req_factor (enum unitreqs r)
3182 {
3183   switch (r)
3184     {
3185     case UNIT_REQ_D:
3186     case UNIT_REQ_L:
3187     case UNIT_REQ_S:
3188     case UNIT_REQ_M:
3189     case UNIT_REQ_X:
3190     case UNIT_REQ_T:
3191       return 1;
3192     case UNIT_REQ_DL:
3193     case UNIT_REQ_LS:
3194     case UNIT_REQ_DS:
3195       return 2;
3196     case UNIT_REQ_DLS:
3197       return 3;
3198     default:
3199       gcc_unreachable ();
3200     }
3201 }
3202 
3203 /* Examine INSN, and store in REQ1/SIDE1 and REQ2/SIDE2 the unit
3204    requirements.  Returns zero if INSN can't be handled, otherwise
3205    either one or two to show how many of the two pairs are in use.
3206    REQ1 is always used, it holds what is normally thought of as the
3207    instructions reservation, e.g. UNIT_REQ_DL.  REQ2 is used to either
3208    describe a cross path, or for loads/stores, the T unit.  */
3209 static int
get_unit_reqs(rtx_insn * insn,int * req1,int * side1,int * req2,int * side2)3210 get_unit_reqs (rtx_insn *insn, int *req1, int *side1, int *req2, int *side2)
3211 {
3212   enum attr_units units;
3213   enum attr_cross cross;
3214   int side, req;
3215 
3216   if (!NONDEBUG_INSN_P (insn) || recog_memoized (insn) < 0)
3217     return 0;
3218   units = get_attr_units (insn);
3219   if (units == UNITS_UNKNOWN)
3220     return 0;
3221   side = get_insn_side (insn, units);
3222   cross = get_attr_cross (insn);
3223 
3224   req = (units == UNITS_D ? UNIT_REQ_D
3225 	 : units == UNITS_D_ADDR ? UNIT_REQ_D
3226 	 : units == UNITS_DL ? UNIT_REQ_DL
3227 	 : units == UNITS_DS ? UNIT_REQ_DS
3228 	 : units == UNITS_L ? UNIT_REQ_L
3229 	 : units == UNITS_LS ? UNIT_REQ_LS
3230 	 : units == UNITS_S ? UNIT_REQ_S
3231 	 : units == UNITS_M ? UNIT_REQ_M
3232 	 : units == UNITS_DLS ? UNIT_REQ_DLS
3233 	 : -1);
3234   gcc_assert (req != -1);
3235   *req1 = req;
3236   *side1 = side;
3237   if (units == UNITS_D_ADDR)
3238     {
3239       *req2 = UNIT_REQ_T;
3240       *side2 = side ^ (cross == CROSS_Y ? 1 : 0);
3241       return 2;
3242     }
3243   else if (cross == CROSS_Y)
3244     {
3245       *req2 = UNIT_REQ_X;
3246       *side2 = side;
3247       return 2;
3248     }
3249   return 1;
3250 }
3251 
3252 /* Walk the insns between and including HEAD and TAIL, and mark the
3253    resource requirements in the unit_reqs table.  */
3254 static void
count_unit_reqs(unit_req_table reqs,rtx_insn * head,rtx_insn * tail)3255 count_unit_reqs (unit_req_table reqs, rtx_insn *head, rtx_insn *tail)
3256 {
3257   rtx_insn *insn;
3258 
3259   memset (reqs, 0, sizeof (unit_req_table));
3260 
3261   for (insn = head; insn != NEXT_INSN (tail); insn = NEXT_INSN (insn))
3262     {
3263       int side1, side2, req1, req2;
3264 
3265       switch (get_unit_reqs (insn, &req1, &side1, &req2, &side2))
3266 	{
3267 	case 2:
3268 	  reqs[side2][req2]++;
3269 	  /* fall through */
3270 	case 1:
3271 	  reqs[side1][req1]++;
3272 	  break;
3273 	}
3274     }
3275 }
3276 
3277 /* Update the table REQS by merging more specific unit reservations into
3278    more general ones, i.e. counting (for example) UNIT_REQ_D also in
3279    UNIT_REQ_DL, DS, and DLS.  */
3280 static void
merge_unit_reqs(unit_req_table reqs)3281 merge_unit_reqs (unit_req_table reqs)
3282 {
3283   int side;
3284   for (side = 0; side < 2; side++)
3285     {
3286       int d = reqs[side][UNIT_REQ_D];
3287       int l = reqs[side][UNIT_REQ_L];
3288       int s = reqs[side][UNIT_REQ_S];
3289       int dl = reqs[side][UNIT_REQ_DL];
3290       int ls = reqs[side][UNIT_REQ_LS];
3291       int ds = reqs[side][UNIT_REQ_DS];
3292 
3293       reqs[side][UNIT_REQ_DL] += d;
3294       reqs[side][UNIT_REQ_DL] += l;
3295       reqs[side][UNIT_REQ_DS] += d;
3296       reqs[side][UNIT_REQ_DS] += s;
3297       reqs[side][UNIT_REQ_LS] += l;
3298       reqs[side][UNIT_REQ_LS] += s;
3299       reqs[side][UNIT_REQ_DLS] += ds + dl + ls + d + l + s;
3300     }
3301 }
3302 
3303 /* Examine the table REQS and return a measure of unit imbalance by comparing
3304    the two sides of the machine.  If, for example, D1 is used twice and D2
3305    used not at all, the return value should be 1 in the absence of other
3306    imbalances.  */
3307 static int
unit_req_imbalance(unit_req_table reqs)3308 unit_req_imbalance (unit_req_table reqs)
3309 {
3310   int val = 0;
3311   int i;
3312 
3313   for (i = 0; i < UNIT_REQ_MAX; i++)
3314     {
3315       int factor = unit_req_factor ((enum unitreqs) i);
3316       int diff = abs (reqs[0][i] - reqs[1][i]);
3317       val += (diff + factor - 1) / factor / 2;
3318     }
3319   return val;
3320 }
3321 
3322 /* Return the resource-constrained minimum iteration interval given the
3323    data in the REQS table.  This must have been processed with
3324    merge_unit_reqs already.  */
3325 static int
res_mii(unit_req_table reqs)3326 res_mii (unit_req_table reqs)
3327 {
3328   int side, req;
3329   int worst = 1;
3330   for (side = 0; side < 2; side++)
3331     for (req = 0; req < UNIT_REQ_MAX; req++)
3332       {
3333 	int factor = unit_req_factor ((enum unitreqs) req);
3334 	worst = MAX ((reqs[side][UNIT_REQ_D] + factor - 1) / factor, worst);
3335       }
3336 
3337   return worst;
3338 }
3339 
3340 /* Examine INSN, and store in PMASK1 and PMASK2 bitmasks that represent
3341    the operands that are involved in the (up to) two reservations, as
3342    found by get_unit_reqs.  Return true if we did this successfully, false
3343    if we couldn't identify what to do with INSN.  */
3344 static bool
get_unit_operand_masks(rtx_insn * insn,unsigned int * pmask1,unsigned int * pmask2)3345 get_unit_operand_masks (rtx_insn *insn, unsigned int *pmask1,
3346 			unsigned int *pmask2)
3347 {
3348   enum attr_op_pattern op_pat;
3349 
3350   if (recog_memoized (insn) < 0)
3351     return 0;
3352   if (GET_CODE (PATTERN (insn)) == COND_EXEC)
3353     return false;
3354   extract_insn (insn);
3355   op_pat = get_attr_op_pattern (insn);
3356   if (op_pat == OP_PATTERN_DT)
3357     {
3358       gcc_assert (recog_data.n_operands == 2);
3359       *pmask1 = 1 << 0;
3360       *pmask2 = 1 << 1;
3361       return true;
3362     }
3363   else if (op_pat == OP_PATTERN_TD)
3364     {
3365       gcc_assert (recog_data.n_operands == 2);
3366       *pmask1 = 1 << 1;
3367       *pmask2 = 1 << 0;
3368       return true;
3369     }
3370   else if (op_pat == OP_PATTERN_SXS)
3371     {
3372       gcc_assert (recog_data.n_operands == 3);
3373       *pmask1 = (1 << 0) | (1 << 2);
3374       *pmask2 = 1 << 1;
3375       return true;
3376     }
3377   else if (op_pat == OP_PATTERN_SX)
3378     {
3379       gcc_assert (recog_data.n_operands == 2);
3380       *pmask1 = 1 << 0;
3381       *pmask2 = 1 << 1;
3382       return true;
3383     }
3384   else if (op_pat == OP_PATTERN_SSX)
3385     {
3386       gcc_assert (recog_data.n_operands == 3);
3387       *pmask1 = (1 << 0) | (1 << 1);
3388       *pmask2 = 1 << 2;
3389       return true;
3390     }
3391   return false;
3392 }
3393 
3394 /* Try to replace a register in INSN, which has corresponding rename info
3395    from regrename_analyze in INFO.  OP_MASK and ORIG_SIDE provide information
3396    about the operands that must be renamed and the side they are on.
3397    REQS is the table of unit reservations in the loop between HEAD and TAIL.
3398    We recompute this information locally after our transformation, and keep
3399    it only if we managed to improve the balance.  */
3400 static void
try_rename_operands(rtx_insn * head,rtx_insn * tail,unit_req_table reqs,rtx insn,insn_rr_info * info,unsigned int op_mask,int orig_side)3401 try_rename_operands (rtx_insn *head, rtx_insn *tail, unit_req_table reqs,
3402 		     rtx insn,
3403 		     insn_rr_info *info, unsigned int op_mask, int orig_side)
3404 {
3405   enum reg_class super_class = orig_side == 0 ? B_REGS : A_REGS;
3406   HARD_REG_SET unavailable;
3407   du_head_p this_head;
3408   struct du_chain *chain;
3409   int i;
3410   unsigned tmp_mask;
3411   int best_reg, old_reg;
3412   vec<du_head_p> involved_chains = vNULL;
3413   unit_req_table new_reqs;
3414   bool ok;
3415 
3416   for (i = 0, tmp_mask = op_mask; tmp_mask; i++)
3417     {
3418       du_head_p op_chain;
3419       if ((tmp_mask & (1 << i)) == 0)
3420 	continue;
3421       if (info->op_info[i].n_chains != 1)
3422 	goto out_fail;
3423       op_chain = regrename_chain_from_id (info->op_info[i].heads[0]->id);
3424       involved_chains.safe_push (op_chain);
3425       tmp_mask &= ~(1 << i);
3426     }
3427 
3428   if (involved_chains.length () > 1)
3429     goto out_fail;
3430 
3431   this_head = involved_chains[0];
3432   if (this_head->cannot_rename)
3433     goto out_fail;
3434 
3435   for (chain = this_head->first; chain; chain = chain->next_use)
3436     {
3437       unsigned int mask1, mask2, mask_changed;
3438       int count, side1, side2, req1, req2;
3439       insn_rr_info *this_rr = &insn_rr[INSN_UID (chain->insn)];
3440 
3441       count = get_unit_reqs (chain->insn, &req1, &side1, &req2, &side2);
3442 
3443       if (count == 0)
3444 	goto out_fail;
3445 
3446       if (!get_unit_operand_masks (chain->insn, &mask1, &mask2))
3447 	goto out_fail;
3448 
3449       extract_insn (chain->insn);
3450 
3451       mask_changed = 0;
3452       for (i = 0; i < recog_data.n_operands; i++)
3453 	{
3454 	  int j;
3455 	  int n_this_op = this_rr->op_info[i].n_chains;
3456 	  for (j = 0; j < n_this_op; j++)
3457 	    {
3458 	      du_head_p other = this_rr->op_info[i].heads[j];
3459 	      if (regrename_chain_from_id (other->id) == this_head)
3460 		break;
3461 	    }
3462 	  if (j == n_this_op)
3463 	    continue;
3464 
3465 	  if (n_this_op != 1)
3466 	    goto out_fail;
3467 	  mask_changed |= 1 << i;
3468 	}
3469       gcc_assert (mask_changed != 0);
3470       if (mask_changed != mask1 && mask_changed != mask2)
3471 	goto out_fail;
3472     }
3473 
3474   /* If we get here, we can do the renaming.  */
3475   unavailable = ~reg_class_contents[super_class];
3476 
3477   old_reg = this_head->regno;
3478   best_reg =
3479     find_rename_reg (this_head, super_class, &unavailable, old_reg, true);
3480 
3481   ok = regrename_do_replace (this_head, best_reg);
3482   gcc_assert (ok);
3483 
3484   count_unit_reqs (new_reqs, head, PREV_INSN (tail));
3485   merge_unit_reqs (new_reqs);
3486   if (dump_file)
3487     {
3488       fprintf (dump_file, "reshuffle for insn %d, op_mask %x, "
3489 	       "original side %d, new reg %d\n",
3490 	       INSN_UID (insn), op_mask, orig_side, best_reg);
3491       fprintf (dump_file, "  imbalance %d -> %d\n",
3492 	       unit_req_imbalance (reqs), unit_req_imbalance (new_reqs));
3493     }
3494   if (unit_req_imbalance (new_reqs) > unit_req_imbalance (reqs))
3495     {
3496       ok = regrename_do_replace (this_head, old_reg);
3497       gcc_assert (ok);
3498     }
3499   else
3500     memcpy (reqs, new_reqs, sizeof (unit_req_table));
3501 
3502  out_fail:
3503   involved_chains.release ();
3504 }
3505 
3506 /* Find insns in LOOP which would, if shifted to the other side
3507    of the machine, reduce an imbalance in the unit reservations.  */
3508 static void
reshuffle_units(basic_block loop)3509 reshuffle_units (basic_block loop)
3510 {
3511   rtx_insn *head = BB_HEAD (loop);
3512   rtx_insn *tail = BB_END (loop);
3513   rtx_insn *insn;
3514   unit_req_table reqs;
3515   edge e;
3516   edge_iterator ei;
3517   bitmap_head bbs;
3518 
3519   count_unit_reqs (reqs, head, PREV_INSN (tail));
3520   merge_unit_reqs (reqs);
3521 
3522   regrename_init (true);
3523 
3524   bitmap_initialize (&bbs, &bitmap_default_obstack);
3525 
3526   FOR_EACH_EDGE (e, ei, loop->preds)
3527     bitmap_set_bit (&bbs, e->src->index);
3528 
3529   bitmap_set_bit (&bbs, loop->index);
3530   regrename_analyze (&bbs);
3531 
3532   for (insn = head; insn != NEXT_INSN (tail); insn = NEXT_INSN (insn))
3533     {
3534       enum attr_units units;
3535       int count, side1, side2, req1, req2;
3536       unsigned int mask1, mask2;
3537       insn_rr_info *info;
3538 
3539       if (!NONDEBUG_INSN_P (insn))
3540 	continue;
3541 
3542       count = get_unit_reqs (insn, &req1, &side1, &req2, &side2);
3543 
3544       if (count == 0)
3545 	continue;
3546 
3547       if (!get_unit_operand_masks (insn, &mask1, &mask2))
3548 	continue;
3549 
3550       info = &insn_rr[INSN_UID (insn)];
3551       if (info->op_info == NULL)
3552 	continue;
3553 
3554       if (reqs[side1][req1] > 1
3555 	  && reqs[side1][req1] > 2 * reqs[side1 ^ 1][req1])
3556 	{
3557 	  try_rename_operands (head, tail, reqs, insn, info, mask1, side1);
3558 	}
3559 
3560       units = get_attr_units (insn);
3561       if (units == UNITS_D_ADDR)
3562 	{
3563 	  gcc_assert (count == 2);
3564 	  if (reqs[side2][req2] > 1
3565 	      && reqs[side2][req2] > 2 * reqs[side2 ^ 1][req2])
3566 	    {
3567 	      try_rename_operands (head, tail, reqs, insn, info, mask2, side2);
3568 	    }
3569 	}
3570     }
3571   regrename_finish ();
3572 }
3573 
3574 /* Backend scheduling state.  */
3575 typedef struct c6x_sched_context
3576 {
3577   /* The current scheduler clock, saved in the sched_reorder hook.  */
3578   int curr_sched_clock;
3579 
3580   /* Number of insns issued so far in this cycle.  */
3581   int issued_this_cycle;
3582 
3583   /* We record the time at which each jump occurs in JUMP_CYCLES.  The
3584      theoretical maximum for number of jumps in flight is 12: 2 every
3585      cycle, with a latency of 6 cycles each.  This is a circular
3586      buffer; JUMP_CYCLE_INDEX is the pointer to the start.  Earlier
3587      jumps have a higher index.  This array should be accessed through
3588      the jump_cycle function.  */
3589   int jump_cycles[12];
3590   int jump_cycle_index;
3591 
3592   /* In parallel with jump_cycles, this array records the opposite of
3593      the condition used in each pending jump.  This is used to
3594      predicate insns that are scheduled in the jump's delay slots.  If
3595      this is NULL_RTX no such predication happens.  */
3596   rtx jump_cond[12];
3597 
3598   /* Similar to the jump_cycles mechanism, but here we take into
3599      account all insns with delay slots, to avoid scheduling asms into
3600      the delay slots.  */
3601   int delays_finished_at;
3602 
3603   /* The following variable value is the last issued insn.  */
3604   rtx_insn *last_scheduled_insn;
3605   /* The last issued insn that isn't a shadow of another.  */
3606   rtx_insn *last_scheduled_iter0;
3607 
3608   /* The following variable value is DFA state before issuing the
3609      first insn in the current clock cycle.  We do not use this member
3610      of the structure directly; we copy the data in and out of
3611      prev_cycle_state.  */
3612   state_t prev_cycle_state_ctx;
3613 
3614   int reg_n_accesses[FIRST_PSEUDO_REGISTER];
3615   int reg_n_xaccesses[FIRST_PSEUDO_REGISTER];
3616   int reg_set_in_cycle[FIRST_PSEUDO_REGISTER];
3617 
3618   int tmp_reg_n_accesses[FIRST_PSEUDO_REGISTER];
3619   int tmp_reg_n_xaccesses[FIRST_PSEUDO_REGISTER];
3620 } *c6x_sched_context_t;
3621 
3622 /* The current scheduling state.  */
3623 static struct c6x_sched_context ss;
3624 
3625 /* The following variable value is DFA state before issuing the first insn
3626    in the current clock cycle.  This is used in c6x_variable_issue for
3627    comparison with the state after issuing the last insn in a cycle.  */
3628 static state_t prev_cycle_state;
3629 
3630 /* Set when we discover while processing an insn that it would lead to too
3631    many accesses of the same register.  */
3632 static bool reg_access_stall;
3633 
3634 /* The highest insn uid after delayed insns were split, but before loop bodies
3635    were copied by the modulo scheduling code.  */
3636 static int sploop_max_uid_iter0;
3637 
3638 /* Look up the jump cycle with index N.  For an out-of-bounds N, we return 0,
3639    so the caller does not specifically have to test for it.  */
3640 static int
get_jump_cycle(int n)3641 get_jump_cycle (int n)
3642 {
3643   if (n >= 12)
3644     return 0;
3645   n += ss.jump_cycle_index;
3646   if (n >= 12)
3647     n -= 12;
3648   return ss.jump_cycles[n];
3649 }
3650 
3651 /* Look up the jump condition with index N.  */
3652 static rtx
get_jump_cond(int n)3653 get_jump_cond (int n)
3654 {
3655   if (n >= 12)
3656     return NULL_RTX;
3657   n += ss.jump_cycle_index;
3658   if (n >= 12)
3659     n -= 12;
3660   return ss.jump_cond[n];
3661 }
3662 
3663 /* Return the index of the first jump that occurs after CLOCK_VAR.  If no jump
3664    has delay slots beyond CLOCK_VAR, return -1.  */
3665 static int
first_jump_index(int clock_var)3666 first_jump_index (int clock_var)
3667 {
3668   int retval = -1;
3669   int n = 0;
3670   for (;;)
3671     {
3672       int t = get_jump_cycle (n);
3673       if (t <= clock_var)
3674 	break;
3675       retval = n;
3676       n++;
3677     }
3678   return retval;
3679 }
3680 
3681 /* Add a new entry in our scheduling state for a jump that occurs in CYCLE
3682    and has the opposite condition of COND.  */
3683 static void
record_jump(int cycle,rtx cond)3684 record_jump (int cycle, rtx cond)
3685 {
3686   if (ss.jump_cycle_index == 0)
3687     ss.jump_cycle_index = 11;
3688   else
3689     ss.jump_cycle_index--;
3690   ss.jump_cycles[ss.jump_cycle_index] = cycle;
3691   ss.jump_cond[ss.jump_cycle_index] = cond;
3692 }
3693 
3694 /* Set the clock cycle of INSN to CYCLE.  Also clears the insn's entry in
3695    new_conditions.  */
3696 static void
insn_set_clock(rtx insn,int cycle)3697 insn_set_clock (rtx insn, int cycle)
3698 {
3699   unsigned uid = INSN_UID (insn);
3700 
3701   if (uid >= INSN_INFO_LENGTH)
3702     insn_info.safe_grow (uid * 5 / 4 + 10, true);
3703 
3704   INSN_INFO_ENTRY (uid).clock = cycle;
3705   INSN_INFO_ENTRY (uid).new_cond = NULL;
3706   INSN_INFO_ENTRY (uid).reservation = 0;
3707   INSN_INFO_ENTRY (uid).ebb_start = false;
3708 }
3709 
3710 /* Return the clock cycle we set for the insn with uid UID.  */
3711 static int
insn_uid_get_clock(int uid)3712 insn_uid_get_clock (int uid)
3713 {
3714   return INSN_INFO_ENTRY (uid).clock;
3715 }
3716 
3717 /* Return the clock cycle we set for INSN.  */
3718 static int
insn_get_clock(rtx insn)3719 insn_get_clock (rtx insn)
3720 {
3721   return insn_uid_get_clock (INSN_UID (insn));
3722 }
3723 
3724 /* Examine INSN, and if it is a conditional jump of any kind, return
3725    the opposite of the condition in which it branches.  Otherwise,
3726    return NULL_RTX.  */
3727 static rtx
condjump_opposite_condition(rtx insn)3728 condjump_opposite_condition (rtx insn)
3729 {
3730   rtx pat = PATTERN (insn);
3731   int icode = INSN_CODE (insn);
3732   rtx x = NULL;
3733 
3734   if (icode == CODE_FOR_br_true || icode == CODE_FOR_br_false)
3735     {
3736       x = XEXP (SET_SRC (pat), 0);
3737       if (icode == CODE_FOR_br_false)
3738 	return x;
3739     }
3740   if (GET_CODE (pat) == COND_EXEC)
3741     {
3742       rtx t = COND_EXEC_CODE (pat);
3743       if ((GET_CODE (t) == PARALLEL
3744 	   && GET_CODE (XVECEXP (t, 0, 0)) == RETURN)
3745 	  || (GET_CODE (t) == UNSPEC && XINT (t, 1) == UNSPEC_REAL_JUMP)
3746 	  || (GET_CODE (t) == SET && SET_DEST (t) == pc_rtx))
3747 	x = COND_EXEC_TEST (pat);
3748     }
3749 
3750   if (x != NULL_RTX)
3751     {
3752       enum rtx_code code = GET_CODE (x);
3753       x = gen_rtx_fmt_ee (code == EQ ? NE : EQ,
3754 			  GET_MODE (x), XEXP (x, 0),
3755 			  XEXP (x, 1));
3756     }
3757   return x;
3758 }
3759 
3760 /* Return true iff COND1 and COND2 are exactly opposite conditions
3761    one of them NE and the other EQ.  */
3762 static bool
conditions_opposite_p(rtx cond1,rtx cond2)3763 conditions_opposite_p (rtx cond1, rtx cond2)
3764 {
3765   return (rtx_equal_p (XEXP (cond1, 0), XEXP (cond2, 0))
3766 	  && rtx_equal_p (XEXP (cond1, 1), XEXP (cond2, 1))
3767 	  && GET_CODE (cond1) == reverse_condition (GET_CODE (cond2)));
3768 }
3769 
3770 /* Return true if we can add a predicate COND to INSN, or if INSN
3771    already has that predicate.  If DOIT is true, also perform the
3772    modification.  */
3773 static bool
predicate_insn(rtx_insn * insn,rtx cond,bool doit)3774 predicate_insn (rtx_insn *insn, rtx cond, bool doit)
3775 {
3776   int icode;
3777   if (cond == NULL_RTX)
3778     {
3779       gcc_assert (!doit);
3780       return false;
3781     }
3782 
3783   if (get_attr_predicable (insn) == PREDICABLE_YES
3784       && GET_CODE (PATTERN (insn)) != COND_EXEC)
3785     {
3786       if (doit)
3787 	{
3788 	  cond = copy_rtx (cond);
3789 	  rtx newpat = gen_rtx_COND_EXEC (VOIDmode, cond, PATTERN (insn));
3790 	  PATTERN (insn) = newpat;
3791 	  INSN_CODE (insn) = -1;
3792 	}
3793       return true;
3794     }
3795   if (GET_CODE (PATTERN (insn)) == COND_EXEC
3796       && rtx_equal_p (COND_EXEC_TEST (PATTERN (insn)), cond))
3797     return true;
3798   icode = INSN_CODE (insn);
3799   if (icode == CODE_FOR_real_jump
3800       || icode == CODE_FOR_jump
3801       || icode == CODE_FOR_indirect_jump)
3802     {
3803       rtx pat = PATTERN (insn);
3804       rtx dest = (icode == CODE_FOR_real_jump ? XVECEXP (pat, 0, 0)
3805 		  : icode == CODE_FOR_jump ? XEXP (SET_SRC (pat), 0)
3806 		  : SET_SRC (pat));
3807       if (doit)
3808 	{
3809 	  rtx newpat;
3810 	  if (REG_P (dest))
3811 	    newpat = gen_rtx_COND_EXEC (VOIDmode, cond, PATTERN (insn));
3812 	  else
3813 	    newpat = gen_br_true (cond, XEXP (cond, 0), dest);
3814 	  PATTERN (insn) = newpat;
3815 	  INSN_CODE (insn) = -1;
3816 	}
3817       return true;
3818     }
3819   if (INSN_CODE (insn) == CODE_FOR_br_true)
3820     {
3821       rtx br_cond = XEXP (SET_SRC (PATTERN (insn)), 0);
3822       return rtx_equal_p (br_cond, cond);
3823     }
3824   if (INSN_CODE (insn) == CODE_FOR_br_false)
3825     {
3826       rtx br_cond = XEXP (SET_SRC (PATTERN (insn)), 0);
3827       return conditions_opposite_p (br_cond, cond);
3828     }
3829   return false;
3830 }
3831 
3832 /* Initialize SC.  Used by c6x_init_sched_context and c6x_sched_init.  */
3833 static void
init_sched_state(c6x_sched_context_t sc)3834 init_sched_state (c6x_sched_context_t sc)
3835 {
3836   sc->last_scheduled_insn = NULL;
3837   sc->last_scheduled_iter0 = NULL;
3838   sc->issued_this_cycle = 0;
3839   memset (sc->jump_cycles, 0, sizeof sc->jump_cycles);
3840   memset (sc->jump_cond, 0, sizeof sc->jump_cond);
3841   sc->jump_cycle_index = 0;
3842   sc->delays_finished_at = 0;
3843   sc->curr_sched_clock = 0;
3844 
3845   sc->prev_cycle_state_ctx = xmalloc (dfa_state_size);
3846 
3847   memset (sc->reg_n_accesses, 0, sizeof sc->reg_n_accesses);
3848   memset (sc->reg_n_xaccesses, 0, sizeof sc->reg_n_xaccesses);
3849   memset (sc->reg_set_in_cycle, 0, sizeof sc->reg_set_in_cycle);
3850 
3851   state_reset (sc->prev_cycle_state_ctx);
3852 }
3853 
3854 /* Allocate store for new scheduling context.  */
3855 static void *
c6x_alloc_sched_context(void)3856 c6x_alloc_sched_context (void)
3857 {
3858   return xmalloc (sizeof (struct c6x_sched_context));
3859 }
3860 
3861 /* If CLEAN_P is true then initializes _SC with clean data,
3862    and from the global context otherwise.  */
3863 static void
c6x_init_sched_context(void * _sc,bool clean_p)3864 c6x_init_sched_context (void *_sc, bool clean_p)
3865 {
3866   c6x_sched_context_t sc = (c6x_sched_context_t) _sc;
3867 
3868   if (clean_p)
3869     {
3870       init_sched_state (sc);
3871     }
3872   else
3873     {
3874       *sc = ss;
3875       sc->prev_cycle_state_ctx = xmalloc (dfa_state_size);
3876       memcpy (sc->prev_cycle_state_ctx, prev_cycle_state, dfa_state_size);
3877     }
3878 }
3879 
3880 /* Sets the global scheduling context to the one pointed to by _SC.  */
3881 static void
c6x_set_sched_context(void * _sc)3882 c6x_set_sched_context (void *_sc)
3883 {
3884   c6x_sched_context_t sc = (c6x_sched_context_t) _sc;
3885 
3886   gcc_assert (sc != NULL);
3887   ss = *sc;
3888   memcpy (prev_cycle_state, sc->prev_cycle_state_ctx, dfa_state_size);
3889 }
3890 
3891 /* Clear data in _SC.  */
3892 static void
c6x_clear_sched_context(void * _sc)3893 c6x_clear_sched_context (void *_sc)
3894 {
3895   c6x_sched_context_t sc = (c6x_sched_context_t) _sc;
3896   gcc_assert (_sc != NULL);
3897 
3898   free (sc->prev_cycle_state_ctx);
3899 }
3900 
3901 /* Free _SC.  */
3902 static void
c6x_free_sched_context(void * _sc)3903 c6x_free_sched_context (void *_sc)
3904 {
3905   free (_sc);
3906 }
3907 
3908 /* True if we are currently performing a preliminary scheduling
3909    pass before modulo scheduling; we can't allow the scheduler to
3910    modify instruction patterns using packetization assumptions,
3911    since there will be another scheduling pass later if modulo
3912    scheduling fails.  */
3913 static bool in_hwloop;
3914 
3915 /* Provide information about speculation capabilities, and set the
3916    DO_BACKTRACKING flag.  */
3917 static void
c6x_set_sched_flags(spec_info_t spec_info)3918 c6x_set_sched_flags (spec_info_t spec_info)
3919 {
3920   unsigned int *flags = &(current_sched_info->flags);
3921 
3922   if (*flags & SCHED_EBB)
3923     {
3924       *flags |= DO_BACKTRACKING | DO_PREDICATION;
3925     }
3926   if (in_hwloop)
3927     *flags |= DONT_BREAK_DEPENDENCIES;
3928 
3929   spec_info->mask = 0;
3930 }
3931 
3932 /* Implement the TARGET_SCHED_ISSUE_RATE hook.  */
3933 
3934 static int
c6x_issue_rate(void)3935 c6x_issue_rate (void)
3936 {
3937   return 8;
3938 }
3939 
3940 /* Used together with the collapse_ndfa option, this ensures that we reach a
3941    deterministic automaton state before trying to advance a cycle.
3942    With collapse_ndfa, genautomata creates advance cycle arcs only for
3943    such deterministic states.  */
3944 
3945 static rtx
c6x_sched_dfa_pre_cycle_insn(void)3946 c6x_sched_dfa_pre_cycle_insn (void)
3947 {
3948   return const0_rtx;
3949 }
3950 
3951 /* We're beginning a new block.  Initialize data structures as necessary.  */
3952 
3953 static void
c6x_sched_init(FILE * dump ATTRIBUTE_UNUSED,int sched_verbose ATTRIBUTE_UNUSED,int max_ready ATTRIBUTE_UNUSED)3954 c6x_sched_init (FILE *dump ATTRIBUTE_UNUSED,
3955 		int sched_verbose ATTRIBUTE_UNUSED,
3956 		int max_ready ATTRIBUTE_UNUSED)
3957 {
3958   if (prev_cycle_state == NULL)
3959     {
3960       prev_cycle_state = xmalloc (dfa_state_size);
3961     }
3962   init_sched_state (&ss);
3963   state_reset (prev_cycle_state);
3964 }
3965 
3966 /* We are about to being issuing INSN.  Return nonzero if we cannot
3967    issue it on given cycle CLOCK and return zero if we should not sort
3968    the ready queue on the next clock start.
3969    For C6X, we use this function just to copy the previous DFA state
3970    for comparison purposes.  */
3971 
3972 static int
c6x_dfa_new_cycle(FILE * dump ATTRIBUTE_UNUSED,int verbose ATTRIBUTE_UNUSED,rtx_insn * insn ATTRIBUTE_UNUSED,int last_clock ATTRIBUTE_UNUSED,int clock ATTRIBUTE_UNUSED,int * sort_p ATTRIBUTE_UNUSED)3973 c6x_dfa_new_cycle (FILE *dump ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED,
3974 		   rtx_insn *insn ATTRIBUTE_UNUSED,
3975 		   int last_clock ATTRIBUTE_UNUSED,
3976 		   int clock ATTRIBUTE_UNUSED, int *sort_p ATTRIBUTE_UNUSED)
3977 {
3978   if (clock != last_clock)
3979     memcpy (prev_cycle_state, curr_state, dfa_state_size);
3980   return 0;
3981 }
3982 
3983 static void
c6x_mark_regno_read(int regno,bool cross)3984 c6x_mark_regno_read (int regno, bool cross)
3985 {
3986   int t = ++ss.tmp_reg_n_accesses[regno];
3987 
3988   if (t > 4)
3989     reg_access_stall = true;
3990 
3991   if (cross)
3992     {
3993       int set_cycle = ss.reg_set_in_cycle[regno];
3994       /* This must be done in this way rather than by tweaking things in
3995 	 adjust_cost, since the stall occurs even for insns with opposite
3996 	 predicates, and the scheduler may not even see a dependency.  */
3997       if (set_cycle > 0 && set_cycle == ss.curr_sched_clock)
3998 	reg_access_stall = true;
3999       /* This doesn't quite do anything yet as we're only modeling one
4000 	 x unit.  */
4001       ++ss.tmp_reg_n_xaccesses[regno];
4002     }
4003 }
4004 
4005 /* Note that REG is read in the insn being examined.  If CROSS, it
4006    means the access is through a cross path.  Update the temporary reg
4007    access arrays, and set REG_ACCESS_STALL if the insn can't be issued
4008    in the current cycle.  */
4009 
4010 static void
c6x_mark_reg_read(rtx reg,bool cross)4011 c6x_mark_reg_read (rtx reg, bool cross)
4012 {
4013   unsigned regno = REGNO (reg);
4014   unsigned nregs = REG_NREGS (reg);
4015 
4016   while (nregs-- > 0)
4017     c6x_mark_regno_read (regno + nregs, cross);
4018 }
4019 
4020 /* Note that register REG is written in cycle CYCLES.  */
4021 
4022 static void
c6x_mark_reg_written(rtx reg,int cycles)4023 c6x_mark_reg_written (rtx reg, int cycles)
4024 {
4025   unsigned regno = REGNO (reg);
4026   unsigned nregs = REG_NREGS (reg);
4027 
4028   while (nregs-- > 0)
4029     ss.reg_set_in_cycle[regno + nregs] = cycles;
4030 }
4031 
4032 /* Update the register state information for an instruction whose
4033    body is X.  Return true if the instruction has to be delayed until the
4034    next cycle.  */
4035 
4036 static bool
c6x_registers_update(rtx_insn * insn)4037 c6x_registers_update (rtx_insn *insn)
4038 {
4039   enum attr_cross cross;
4040   enum attr_dest_regfile destrf;
4041   int i, nops;
4042   rtx x;
4043 
4044   if (!reload_completed || recog_memoized (insn) < 0)
4045     return false;
4046 
4047   reg_access_stall = false;
4048   memcpy (ss.tmp_reg_n_accesses, ss.reg_n_accesses,
4049 	  sizeof ss.tmp_reg_n_accesses);
4050   memcpy (ss.tmp_reg_n_xaccesses, ss.reg_n_xaccesses,
4051 	  sizeof ss.tmp_reg_n_xaccesses);
4052 
4053   extract_insn (insn);
4054 
4055   cross = get_attr_cross (insn);
4056   destrf = get_attr_dest_regfile (insn);
4057 
4058   nops = recog_data.n_operands;
4059   x = PATTERN (insn);
4060   if (GET_CODE (x) == COND_EXEC)
4061     {
4062       c6x_mark_reg_read (XEXP (XEXP (x, 0), 0), false);
4063       nops -= 2;
4064     }
4065 
4066   for (i = 0; i < nops; i++)
4067     {
4068       rtx op = recog_data.operand[i];
4069       if (recog_data.operand_type[i] == OP_OUT)
4070 	continue;
4071       if (REG_P (op))
4072 	{
4073 	  bool this_cross = cross;
4074 	  if (destrf == DEST_REGFILE_A && A_REGNO_P (REGNO (op)))
4075 	    this_cross = false;
4076 	  if (destrf == DEST_REGFILE_B && B_REGNO_P (REGNO (op)))
4077 	    this_cross = false;
4078 	  c6x_mark_reg_read (op, this_cross);
4079 	}
4080       else if (MEM_P (op))
4081 	{
4082 	  op = XEXP (op, 0);
4083 	  switch (GET_CODE (op))
4084 	    {
4085 	    case POST_INC:
4086 	    case PRE_INC:
4087 	    case POST_DEC:
4088 	    case PRE_DEC:
4089 	      op = XEXP (op, 0);
4090 	      /* fall through */
4091 	    case REG:
4092 	      c6x_mark_reg_read (op, false);
4093 	      break;
4094 	    case POST_MODIFY:
4095 	    case PRE_MODIFY:
4096 	      op = XEXP (op, 1);
4097 	      gcc_assert (GET_CODE (op) == PLUS);
4098 	      /* fall through */
4099 	    case PLUS:
4100 	      c6x_mark_reg_read (XEXP (op, 0), false);
4101 	      if (REG_P (XEXP (op, 1)))
4102 		c6x_mark_reg_read (XEXP (op, 1), false);
4103 	      break;
4104 	    case SYMBOL_REF:
4105 	    case LABEL_REF:
4106 	    case CONST:
4107 	      c6x_mark_regno_read (REG_B14, false);
4108 	      break;
4109 	    default:
4110 	      gcc_unreachable ();
4111 	    }
4112 	}
4113       else if (!CONSTANT_P (op) && strlen (recog_data.constraints[i]) > 0)
4114 	gcc_unreachable ();
4115     }
4116   return reg_access_stall;
4117 }
4118 
4119 /* Helper function for the TARGET_SCHED_REORDER and
4120    TARGET_SCHED_REORDER2 hooks.  If scheduling an insn would be unsafe
4121    in the current cycle, move it down in the ready list and return the
4122    number of non-unsafe insns.  */
4123 
4124 static int
c6x_sched_reorder_1(rtx_insn ** ready,int * pn_ready,int clock_var)4125 c6x_sched_reorder_1 (rtx_insn **ready, int *pn_ready, int clock_var)
4126 {
4127   int n_ready = *pn_ready;
4128   rtx_insn **e_ready = ready + n_ready;
4129   rtx_insn **insnp;
4130   int first_jump;
4131 
4132   /* Keep track of conflicts due to a limit number of register accesses,
4133      and due to stalls incurred by too early accesses of registers using
4134      cross paths.  */
4135 
4136   for (insnp = ready; insnp < e_ready; insnp++)
4137     {
4138       rtx_insn *insn = *insnp;
4139       int icode = recog_memoized (insn);
4140       bool is_asm = (icode < 0
4141 		     && (GET_CODE (PATTERN (insn)) == ASM_INPUT
4142 			 || asm_noperands (PATTERN (insn)) >= 0));
4143       bool no_parallel = (is_asm || icode == CODE_FOR_sploop
4144 			  || (icode >= 0
4145 			      && get_attr_type (insn) == TYPE_ATOMIC));
4146 
4147       /* We delay asm insns until all delay slots are exhausted.  We can't
4148 	 accurately tell how many cycles an asm takes, and the main scheduling
4149 	 code always assumes at least 1 cycle, which may be wrong.  */
4150       if ((no_parallel
4151 	   && (ss.issued_this_cycle > 0 || clock_var < ss.delays_finished_at))
4152 	  || c6x_registers_update (insn)
4153 	  || (ss.issued_this_cycle > 0 && icode == CODE_FOR_sploop))
4154 	{
4155 	  memmove (ready + 1, ready, (insnp - ready) * sizeof (rtx));
4156 	  *ready = insn;
4157 	  n_ready--;
4158 	  ready++;
4159 	}
4160       else if (shadow_p (insn))
4161 	{
4162 	  memmove (ready + 1, ready, (insnp - ready) * sizeof (rtx));
4163 	  *ready = insn;
4164 	}
4165     }
4166 
4167   /* Ensure that no other jump is scheduled in jump delay slots, since
4168      it would put the machine into the wrong state.  Also, we must
4169      avoid scheduling insns that have a latency longer than the
4170      remaining jump delay slots, as the code at the jump destination
4171      won't be prepared for it.
4172 
4173      However, we can relax this condition somewhat.  The rest of the
4174      scheduler will automatically avoid scheduling an insn on which
4175      the jump shadow depends so late that its side effect happens
4176      after the jump.  This means that if we see an insn with a longer
4177      latency here, it can safely be scheduled if we can ensure that it
4178      has a predicate opposite of the previous jump: the side effect
4179      will happen in what we think of as the same basic block.  In
4180      c6x_variable_issue, we will record the necessary predicate in
4181      new_conditions, and after scheduling is finished, we will modify
4182      the insn.
4183 
4184      Special care must be taken whenever there is more than one jump
4185      in flight.  */
4186 
4187   first_jump = first_jump_index (clock_var);
4188   if (first_jump != -1)
4189     {
4190       int first_cycle = get_jump_cycle (first_jump);
4191       rtx first_cond = get_jump_cond (first_jump);
4192       int second_cycle = 0;
4193 
4194       if (first_jump > 0)
4195 	second_cycle = get_jump_cycle (first_jump - 1);
4196 
4197       for (insnp = ready; insnp < e_ready; insnp++)
4198 	{
4199 	  rtx_insn *insn = *insnp;
4200 	  int icode = recog_memoized (insn);
4201 	  bool is_asm = (icode < 0
4202 			 && (GET_CODE (PATTERN (insn)) == ASM_INPUT
4203 			     || asm_noperands (PATTERN (insn)) >= 0));
4204 	  int this_cycles, rsrv_cycles;
4205 	  enum attr_type type;
4206 
4207 	  gcc_assert (!is_asm);
4208 	  if (icode < 0)
4209 	    continue;
4210 	  this_cycles = get_attr_cycles (insn);
4211 	  rsrv_cycles = get_attr_reserve_cycles (insn);
4212 	  type = get_attr_type (insn);
4213 	  /* Treat branches specially; there is also a hazard if two jumps
4214 	     end at the same cycle.  */
4215 	  if (type == TYPE_BRANCH || type == TYPE_CALL)
4216 	    this_cycles++;
4217 	  if (clock_var + this_cycles <= first_cycle)
4218 	    continue;
4219 	  if ((first_jump > 0 && clock_var + this_cycles > second_cycle)
4220 	      || clock_var + rsrv_cycles > first_cycle
4221 	      || !predicate_insn (insn, first_cond, false))
4222 	    {
4223 	      memmove (ready + 1, ready, (insnp - ready) * sizeof (rtx));
4224 	      *ready = insn;
4225 	      n_ready--;
4226 	      ready++;
4227 	    }
4228 	}
4229     }
4230 
4231   return n_ready;
4232 }
4233 
4234 /* Implement the TARGET_SCHED_REORDER hook.  We save the current clock
4235    for later and clear the register access information for the new
4236    cycle.  We also move asm statements out of the way if they would be
4237    scheduled in a delay slot.  */
4238 
4239 static int
c6x_sched_reorder(FILE * dump ATTRIBUTE_UNUSED,int sched_verbose ATTRIBUTE_UNUSED,rtx_insn ** ready ATTRIBUTE_UNUSED,int * pn_ready ATTRIBUTE_UNUSED,int clock_var)4240 c6x_sched_reorder (FILE *dump ATTRIBUTE_UNUSED,
4241 		   int sched_verbose ATTRIBUTE_UNUSED,
4242 		   rtx_insn **ready ATTRIBUTE_UNUSED,
4243 		   int *pn_ready ATTRIBUTE_UNUSED, int clock_var)
4244 {
4245   ss.curr_sched_clock = clock_var;
4246   ss.issued_this_cycle = 0;
4247   memset (ss.reg_n_accesses, 0, sizeof ss.reg_n_accesses);
4248   memset (ss.reg_n_xaccesses, 0, sizeof ss.reg_n_xaccesses);
4249 
4250   if (ready == NULL)
4251     return 0;
4252 
4253   return c6x_sched_reorder_1 (ready, pn_ready, clock_var);
4254 }
4255 
4256 /* Implement the TARGET_SCHED_REORDER2 hook.  We use this to record the clock
4257    cycle for every insn.  */
4258 
4259 static int
c6x_sched_reorder2(FILE * dump ATTRIBUTE_UNUSED,int sched_verbose ATTRIBUTE_UNUSED,rtx_insn ** ready ATTRIBUTE_UNUSED,int * pn_ready ATTRIBUTE_UNUSED,int clock_var)4260 c6x_sched_reorder2 (FILE *dump ATTRIBUTE_UNUSED,
4261 		    int sched_verbose ATTRIBUTE_UNUSED,
4262 		    rtx_insn **ready ATTRIBUTE_UNUSED,
4263 		    int *pn_ready ATTRIBUTE_UNUSED, int clock_var)
4264 {
4265   /* FIXME: the assembler rejects labels inside an execute packet.
4266      This can occur if prologue insns are scheduled in parallel with
4267      others, so we avoid this here.  Also make sure that nothing is
4268      scheduled in parallel with a TYPE_ATOMIC insn or after a jump.  */
4269   if (RTX_FRAME_RELATED_P (ss.last_scheduled_insn)
4270       || JUMP_P (ss.last_scheduled_insn)
4271       || (recog_memoized (ss.last_scheduled_insn) >= 0
4272 	  && get_attr_type (ss.last_scheduled_insn) == TYPE_ATOMIC))
4273     {
4274       int n_ready = *pn_ready;
4275       rtx_insn **e_ready = ready + n_ready;
4276       rtx_insn **insnp;
4277 
4278       for (insnp = ready; insnp < e_ready; insnp++)
4279 	{
4280 	  rtx_insn *insn = *insnp;
4281 	  if (!shadow_p (insn))
4282 	    {
4283 	      memmove (ready + 1, ready, (insnp - ready) * sizeof (rtx));
4284 	      *ready = insn;
4285 	      n_ready--;
4286 	      ready++;
4287 	    }
4288 	}
4289       return n_ready;
4290     }
4291 
4292   return c6x_sched_reorder_1 (ready, pn_ready, clock_var);
4293 }
4294 
4295 /* Subroutine of maybe_clobber_cond, called through note_stores.  */
4296 
4297 static void
clobber_cond_1(rtx x,const_rtx pat ATTRIBUTE_UNUSED,void * data1)4298 clobber_cond_1 (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data1)
4299 {
4300   rtx *cond = (rtx *)data1;
4301   if (*cond != NULL_RTX && reg_overlap_mentioned_p (x, *cond))
4302     *cond = NULL_RTX;
4303 }
4304 
4305 /* Examine INSN, and if it destroys the conditions have recorded for
4306    any of the jumps in flight, clear that condition so that we don't
4307    predicate any more insns.  CLOCK_VAR helps us limit the search to
4308    only those jumps which are still in flight.  */
4309 
4310 static void
maybe_clobber_cond(rtx_insn * insn,int clock_var)4311 maybe_clobber_cond (rtx_insn *insn, int clock_var)
4312 {
4313   int n, idx;
4314   idx = ss.jump_cycle_index;
4315   for (n = 0; n < 12; n++, idx++)
4316     {
4317       rtx cond, link;
4318       int cycle;
4319 
4320       if (idx >= 12)
4321 	idx -= 12;
4322       cycle = ss.jump_cycles[idx];
4323       if (cycle <= clock_var)
4324 	return;
4325 
4326       cond = ss.jump_cond[idx];
4327       if (cond == NULL_RTX)
4328 	continue;
4329 
4330       if (CALL_P (insn))
4331 	{
4332 	  ss.jump_cond[idx] = NULL_RTX;
4333 	  continue;
4334 	}
4335 
4336       note_stores (insn, clobber_cond_1, ss.jump_cond + idx);
4337       for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
4338 	if (REG_NOTE_KIND (link) == REG_INC)
4339 	  clobber_cond_1 (XEXP (link, 0), NULL_RTX, ss.jump_cond + idx);
4340     }
4341 }
4342 
4343 /* Implement the TARGET_SCHED_VARIABLE_ISSUE hook.  We are about to
4344    issue INSN.  Return the number of insns left on the ready queue
4345    that can be issued this cycle.
4346    We use this hook to record clock cycles and reservations for every insn.  */
4347 
4348 static int
c6x_variable_issue(FILE * dump ATTRIBUTE_UNUSED,int sched_verbose ATTRIBUTE_UNUSED,rtx_insn * insn,int can_issue_more ATTRIBUTE_UNUSED)4349 c6x_variable_issue (FILE *dump ATTRIBUTE_UNUSED,
4350 		    int sched_verbose ATTRIBUTE_UNUSED,
4351 		    rtx_insn *insn, int can_issue_more ATTRIBUTE_UNUSED)
4352 {
4353   ss.last_scheduled_insn = insn;
4354   if (INSN_UID (insn) < sploop_max_uid_iter0 && !JUMP_P (insn))
4355     ss.last_scheduled_iter0 = insn;
4356   if (GET_CODE (PATTERN (insn)) != USE && GET_CODE (PATTERN (insn)) != CLOBBER)
4357     ss.issued_this_cycle++;
4358   if (insn_info.exists ())
4359     {
4360       state_t st_after = alloca (dfa_state_size);
4361       int curr_clock = ss.curr_sched_clock;
4362       int uid = INSN_UID (insn);
4363       int icode = recog_memoized (insn);
4364       rtx first_cond;
4365       int first, first_cycle;
4366       unsigned int mask;
4367       int i;
4368 
4369       insn_set_clock (insn, curr_clock);
4370       INSN_INFO_ENTRY (uid).ebb_start
4371 	= curr_clock == 0 && ss.issued_this_cycle == 1;
4372 
4373       first = first_jump_index (ss.curr_sched_clock);
4374       if (first == -1)
4375 	{
4376 	  first_cycle = 0;
4377 	  first_cond = NULL_RTX;
4378 	}
4379       else
4380 	{
4381 	  first_cycle = get_jump_cycle (first);
4382 	  first_cond = get_jump_cond (first);
4383 	}
4384       if (icode >= 0
4385 	  && first_cycle > curr_clock
4386 	  && first_cond != NULL_RTX
4387 	  && (curr_clock + get_attr_cycles (insn) > first_cycle
4388 	      || get_attr_type (insn) == TYPE_BRANCH
4389 	      || get_attr_type (insn) == TYPE_CALL))
4390 	INSN_INFO_ENTRY (uid).new_cond = first_cond;
4391 
4392       memcpy (st_after, curr_state, dfa_state_size);
4393       state_transition (st_after, const0_rtx);
4394 
4395       mask = 0;
4396       for (i = 0; i < 2 * UNIT_QID_SIDE_OFFSET; i++)
4397 	if (cpu_unit_reservation_p (st_after, c6x_unit_codes[i])
4398 	    && !cpu_unit_reservation_p (prev_cycle_state, c6x_unit_codes[i]))
4399 	  mask |= 1 << i;
4400       INSN_INFO_ENTRY (uid).unit_mask = mask;
4401 
4402       maybe_clobber_cond (insn, curr_clock);
4403 
4404       if (icode >= 0)
4405 	{
4406 	  int i, cycles;
4407 
4408 	  c6x_registers_update (insn);
4409 	  memcpy (ss.reg_n_accesses, ss.tmp_reg_n_accesses,
4410 		  sizeof ss.reg_n_accesses);
4411 	  memcpy (ss.reg_n_xaccesses, ss.tmp_reg_n_accesses,
4412 		  sizeof ss.reg_n_xaccesses);
4413 
4414 	  cycles = get_attr_cycles (insn);
4415 	  if (ss.delays_finished_at < ss.curr_sched_clock + cycles)
4416 	    ss.delays_finished_at = ss.curr_sched_clock + cycles;
4417 	  if (get_attr_type (insn) == TYPE_BRANCH
4418 	      || get_attr_type (insn) == TYPE_CALL)
4419 	    {
4420 	      rtx opposite = condjump_opposite_condition (insn);
4421 	      record_jump (ss.curr_sched_clock + cycles, opposite);
4422 	    }
4423 
4424 	  /* Mark the cycles in which the destination registers are written.
4425 	     This is used for calculating stalls when using cross units.  */
4426 	  extract_insn (insn);
4427 	  /* Cross-path stalls don't apply to results of load insns.  */
4428 	  if (get_attr_type (insn) == TYPE_LOAD
4429 	      || get_attr_type (insn) == TYPE_LOADN
4430 	      || get_attr_type (insn) == TYPE_LOAD_SHADOW)
4431 	    cycles--;
4432 	  for (i = 0; i < recog_data.n_operands; i++)
4433 	    {
4434 	      rtx op = recog_data.operand[i];
4435 	      if (MEM_P (op))
4436 		{
4437 		  rtx addr = XEXP (op, 0);
4438 		  if (GET_RTX_CLASS (GET_CODE (addr)) == RTX_AUTOINC)
4439 		    c6x_mark_reg_written (XEXP (addr, 0),
4440 					  insn_uid_get_clock (uid) + 1);
4441 		}
4442 	      if (recog_data.operand_type[i] != OP_IN
4443 		  && REG_P (op))
4444 		{
4445 		  c6x_mark_reg_written (op,
4446 					insn_uid_get_clock (uid) + cycles);
4447 		}
4448 	    }
4449 	}
4450     }
4451   return can_issue_more;
4452 }
4453 
4454 /* Implement the TARGET_SCHED_ADJUST_COST hook.  We need special handling for
4455    anti- and output dependencies.  */
4456 
4457 static int
c6x_adjust_cost(rtx_insn * insn,int dep_type,rtx_insn * dep_insn,int cost,unsigned int)4458 c6x_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn, int cost,
4459 		 unsigned int)
4460 {
4461   enum attr_type insn_type = TYPE_UNKNOWN, dep_insn_type = TYPE_UNKNOWN;
4462   int dep_insn_code_number, insn_code_number;
4463   int shadow_bonus = 0;
4464   enum reg_note kind;
4465   dep_insn_code_number = recog_memoized (dep_insn);
4466   insn_code_number = recog_memoized (insn);
4467 
4468   if (dep_insn_code_number >= 0)
4469     dep_insn_type = get_attr_type (dep_insn);
4470 
4471   if (insn_code_number >= 0)
4472     insn_type = get_attr_type (insn);
4473 
4474   kind = (reg_note) dep_type;
4475   if (kind == 0)
4476     {
4477       /* If we have a dependency on a load, and it's not for the result of
4478 	 the load, it must be for an autoincrement.  Reduce the cost in that
4479 	 case.  */
4480       if (dep_insn_type == TYPE_LOAD)
4481 	{
4482 	  rtx set = PATTERN (dep_insn);
4483 	  if (GET_CODE (set) == COND_EXEC)
4484 	    set = COND_EXEC_CODE (set);
4485 	  if (GET_CODE (set) == UNSPEC)
4486 	    cost = 1;
4487 	  else
4488 	    {
4489 	      gcc_assert (GET_CODE (set) == SET);
4490 	      if (!reg_overlap_mentioned_p (SET_DEST (set), PATTERN (insn)))
4491 		cost = 1;
4492 	    }
4493 	}
4494     }
4495 
4496   /* A jump shadow needs to have its latency decreased by one.  Conceptually,
4497      it occurs in between two cycles, but we schedule it at the end of the
4498      first cycle.  */
4499   if (shadow_type_p (insn_type))
4500     shadow_bonus = 1;
4501 
4502   /* Anti and output dependencies usually have zero cost, but we want
4503      to insert a stall after a jump, and after certain floating point
4504      insns that take more than one cycle to read their inputs.  In the
4505      future, we should try to find a better algorithm for scheduling
4506      jumps.  */
4507   if (kind != 0)
4508     {
4509       /* We can get anti-dependencies against shadow insns.  Treat these
4510 	 like output dependencies, so that the insn is entirely finished
4511 	 before the branch takes place.  */
4512       if (kind == REG_DEP_ANTI && insn_type == TYPE_SHADOW)
4513 	kind = REG_DEP_OUTPUT;
4514       switch (dep_insn_type)
4515 	{
4516 	case TYPE_CALLP:
4517 	  return 1;
4518 	case TYPE_BRANCH:
4519 	case TYPE_CALL:
4520 	  if (get_attr_has_shadow (dep_insn) == HAS_SHADOW_Y)
4521 	    /* This is a real_jump/real_call insn.  These don't have
4522 	       outputs, and ensuring the validity of scheduling things
4523 	       in the delay slot is the job of
4524 	       c6x_sched_reorder_1.  */
4525 	    return 0;
4526 	  /* Unsplit calls can happen - e.g. for divide insns.  */
4527 	  return 6;
4528 	case TYPE_LOAD:
4529 	case TYPE_LOADN:
4530 	case TYPE_INTDP:
4531 	  if (kind == REG_DEP_OUTPUT)
4532 	    return 5 - shadow_bonus;
4533 	  return 0;
4534 	case TYPE_MPY4:
4535 	case TYPE_FP4:
4536 	  if (kind == REG_DEP_OUTPUT)
4537 	    return 4 - shadow_bonus;
4538 	  return 0;
4539 	case TYPE_MPY2:
4540 	  if (kind == REG_DEP_OUTPUT)
4541 	    return 2 - shadow_bonus;
4542 	  return 0;
4543 	case TYPE_CMPDP:
4544 	  if (kind == REG_DEP_OUTPUT)
4545 	    return 2 - shadow_bonus;
4546 	  return 2;
4547 	case TYPE_ADDDP:
4548 	case TYPE_MPYSPDP:
4549 	  if (kind == REG_DEP_OUTPUT)
4550 	    return 7 - shadow_bonus;
4551 	  return 2;
4552 	case TYPE_MPYSP2DP:
4553 	  if (kind == REG_DEP_OUTPUT)
4554 	    return 5 - shadow_bonus;
4555 	  return 2;
4556 	case TYPE_MPYI:
4557 	  if (kind == REG_DEP_OUTPUT)
4558 	    return 9 - shadow_bonus;
4559 	  return 4;
4560 	case TYPE_MPYID:
4561 	case TYPE_MPYDP:
4562 	  if (kind == REG_DEP_OUTPUT)
4563 	    return 10 - shadow_bonus;
4564 	  return 4;
4565 
4566 	default:
4567 	  if (insn_type == TYPE_SPKERNEL)
4568 	    return 0;
4569 	  if (kind == REG_DEP_OUTPUT)
4570 	    return 1 - shadow_bonus;
4571 
4572 	  return 0;
4573 	}
4574     }
4575 
4576   return cost - shadow_bonus;
4577 }
4578 
4579 /* Create a SEQUENCE rtx to replace the instructions in SLOT, of which there
4580    are N_FILLED.  REAL_FIRST identifies the slot if the insn that appears
4581    first in the original stream.  */
4582 
4583 static void
gen_one_bundle(rtx_insn ** slot,int n_filled,int real_first)4584 gen_one_bundle (rtx_insn **slot, int n_filled, int real_first)
4585 {
4586   rtx seq;
4587   rtx_insn *bundle;
4588   rtx_insn *t;
4589   int i;
4590 
4591   seq = gen_rtx_SEQUENCE (VOIDmode, gen_rtvec_v (n_filled, slot));
4592   bundle = make_insn_raw (seq);
4593   BLOCK_FOR_INSN (bundle) = BLOCK_FOR_INSN (slot[0]);
4594   INSN_LOCATION (bundle) = INSN_LOCATION (slot[0]);
4595   SET_PREV_INSN (bundle) = SET_PREV_INSN (slot[real_first]);
4596 
4597   t = NULL;
4598 
4599   for (i = 0; i < n_filled; i++)
4600     {
4601       rtx_insn *insn = slot[i];
4602       remove_insn (insn);
4603       SET_PREV_INSN (insn) = t ? t : PREV_INSN (bundle);
4604       if (t != NULL_RTX)
4605 	SET_NEXT_INSN (t) = insn;
4606       t = insn;
4607       if (i > 0)
4608 	INSN_LOCATION (slot[i]) = INSN_LOCATION (bundle);
4609     }
4610 
4611   SET_NEXT_INSN (bundle) = NEXT_INSN (PREV_INSN (bundle));
4612   SET_NEXT_INSN (t) = NEXT_INSN (bundle);
4613   SET_NEXT_INSN (PREV_INSN (bundle)) = bundle;
4614   SET_PREV_INSN (NEXT_INSN (bundle)) = bundle;
4615 }
4616 
4617 /* Move all parallel instructions into SEQUENCEs, so that no subsequent passes
4618    try to insert labels in the middle.  */
4619 
4620 static void
c6x_gen_bundles(void)4621 c6x_gen_bundles (void)
4622 {
4623   basic_block bb;
4624 
4625   FOR_EACH_BB_FN (bb, cfun)
4626     {
4627       rtx_insn *insn, *next;
4628       /* The machine is eight insns wide.  We can have up to six shadow
4629 	 insns, plus an extra slot for merging the jump shadow.  */
4630       rtx_insn *slot[15];
4631       int n_filled = 0;
4632       int first_slot = 0;
4633 
4634       for (insn = BB_HEAD (bb);; insn = next)
4635 	{
4636 	  int at_end;
4637 	  rtx delete_this = NULL_RTX;
4638 
4639 	  if (NONDEBUG_INSN_P (insn))
4640 	    {
4641 	      /* Put calls at the start of the sequence.  */
4642 	      if (CALL_P (insn))
4643 		{
4644 		  first_slot++;
4645 		  if (n_filled)
4646 		    {
4647 		      memmove (&slot[1], &slot[0],
4648 			       n_filled * sizeof (slot[0]));
4649 		    }
4650 		  if (!shadow_p (insn))
4651 		    {
4652 		      PUT_MODE (insn, TImode);
4653 		      if (n_filled)
4654 			PUT_MODE (slot[1], VOIDmode);
4655 		    }
4656 		  n_filled++;
4657 		  slot[0] = insn;
4658 		}
4659 	      else
4660 		{
4661 		  slot[n_filled++] = insn;
4662 		}
4663 	    }
4664 
4665 	  next = NEXT_INSN (insn);
4666 	  while (next && insn != BB_END (bb)
4667 		 && !(NONDEBUG_INSN_P (next)
4668 		      && GET_CODE (PATTERN (next)) != USE
4669 		      && GET_CODE (PATTERN (next)) != CLOBBER))
4670 	    {
4671 	      insn = next;
4672 	      next = NEXT_INSN (insn);
4673 	    }
4674 
4675 	  at_end = insn == BB_END (bb);
4676 	  if (delete_this == NULL_RTX
4677 	      && (at_end || (GET_MODE (next) == TImode
4678 			     && !(shadow_p (next) && CALL_P (next)))))
4679 	    {
4680 	      if (n_filled >= 2)
4681 		gen_one_bundle (slot, n_filled, first_slot);
4682 
4683 	      n_filled = 0;
4684 	      first_slot = 0;
4685 	    }
4686 	  if (at_end)
4687 	    break;
4688 	}
4689     }
4690 }
4691 
4692 /* Emit a NOP instruction for CYCLES cycles after insn AFTER.  Return it.  */
4693 
4694 static rtx_insn *
emit_nop_after(int cycles,rtx_insn * after)4695 emit_nop_after (int cycles, rtx_insn *after)
4696 {
4697   rtx_insn *insn;
4698 
4699   /* mpydp has 9 delay slots, and we may schedule a stall for a cross-path
4700      operation.  We don't need the extra NOP since in this case, the hardware
4701      will automatically insert the required stall.  */
4702   if (cycles == 10)
4703     cycles--;
4704 
4705   gcc_assert (cycles < 10);
4706 
4707   insn = emit_insn_after (gen_nop_count (GEN_INT (cycles)), after);
4708   PUT_MODE (insn, TImode);
4709 
4710   return insn;
4711 }
4712 
4713 /* Determine whether INSN is a call that needs to have a return label
4714    placed.  */
4715 
4716 static bool
returning_call_p(rtx_insn * insn)4717 returning_call_p (rtx_insn *insn)
4718 {
4719   if (CALL_P (insn))
4720     return (!SIBLING_CALL_P (insn)
4721 	    && get_attr_type (insn) != TYPE_CALLP
4722 	    && get_attr_type (insn) != TYPE_SHADOW);
4723   if (recog_memoized (insn) < 0)
4724     return false;
4725   if (get_attr_type (insn) == TYPE_CALL)
4726     return true;
4727   return false;
4728 }
4729 
4730 /* Determine whether INSN's pattern can be converted to use callp.  */
4731 static bool
can_use_callp(rtx_insn * insn)4732 can_use_callp (rtx_insn *insn)
4733 {
4734   int icode = recog_memoized (insn);
4735   if (!TARGET_INSNS_64PLUS
4736       || icode < 0
4737       || GET_CODE (PATTERN (insn)) == COND_EXEC)
4738     return false;
4739 
4740   return ((icode == CODE_FOR_real_call
4741 	   || icode == CODE_FOR_call_internal
4742 	   || icode == CODE_FOR_call_value_internal)
4743 	  && get_attr_dest_regfile (insn) == DEST_REGFILE_ANY);
4744 }
4745 
4746 /* Convert the pattern of INSN, which must be a CALL_INSN, into a callp.  */
4747 static void
convert_to_callp(rtx_insn * insn)4748 convert_to_callp (rtx_insn *insn)
4749 {
4750   rtx lab;
4751   extract_insn (insn);
4752   if (GET_CODE (PATTERN (insn)) == SET)
4753     {
4754       rtx dest = recog_data.operand[0];
4755       lab = recog_data.operand[1];
4756       PATTERN (insn) = gen_callp_value (dest, lab);
4757       INSN_CODE (insn) = CODE_FOR_callp_value;
4758     }
4759   else
4760     {
4761       lab = recog_data.operand[0];
4762       PATTERN (insn) = gen_callp (lab);
4763       INSN_CODE (insn) = CODE_FOR_callp;
4764     }
4765 }
4766 
4767 /* Scan forwards from INSN until we find the next insn that has mode TImode
4768    (indicating it starts a new cycle), and occurs in cycle CLOCK.
4769    Return it if we find such an insn, NULL_RTX otherwise.  */
4770 static rtx_insn *
find_next_cycle_insn(rtx_insn * insn,int clock)4771 find_next_cycle_insn (rtx_insn *insn, int clock)
4772 {
4773   rtx_insn *t = insn;
4774   if (GET_MODE (t) == TImode)
4775     t = next_real_insn (t);
4776   while (t && GET_MODE (t) != TImode)
4777     t = next_real_insn (t);
4778 
4779   if (t && insn_get_clock (t) == clock)
4780     return t;
4781   return NULL;
4782 }
4783 
4784 /* If COND_INSN has a COND_EXEC condition, wrap the same condition
4785    around PAT.  Return PAT either unchanged or modified in this
4786    way.  */
4787 static rtx
duplicate_cond(rtx pat,rtx cond_insn)4788 duplicate_cond (rtx pat, rtx cond_insn)
4789 {
4790   rtx cond_pat = PATTERN (cond_insn);
4791   if (GET_CODE (cond_pat) == COND_EXEC)
4792     pat = gen_rtx_COND_EXEC (VOIDmode, copy_rtx (COND_EXEC_TEST (cond_pat)),
4793 			     pat);
4794   return pat;
4795 }
4796 
4797 /* Walk forward from INSN to find the last insn that issues in the same clock
4798    cycle.  */
4799 static rtx_insn *
find_last_same_clock(rtx_insn * insn)4800 find_last_same_clock (rtx_insn *insn)
4801 {
4802   rtx_insn *retval = insn;
4803   rtx_insn *t = next_real_insn (insn);
4804 
4805   while (t && GET_MODE (t) != TImode)
4806     {
4807       if (!DEBUG_INSN_P (t) && recog_memoized (t) >= 0)
4808 	retval = t;
4809       t = next_real_insn (t);
4810     }
4811   return retval;
4812 }
4813 
4814 /* For every call insn in the function, emit code to load the return
4815    address.  For each call we create a return label and store it in
4816    CALL_LABELS.  If are not scheduling, we emit the labels here,
4817    otherwise the caller will do it later.
4818    This function is called after final insn scheduling, but before creating
4819    the SEQUENCEs that represent execute packets.  */
4820 
4821 static void
reorg_split_calls(rtx_code_label ** call_labels)4822 reorg_split_calls (rtx_code_label **call_labels)
4823 {
4824   unsigned int reservation_mask = 0;
4825   rtx_insn *insn = get_insns ();
4826   gcc_assert (NOTE_P (insn));
4827   insn = next_real_insn (insn);
4828   while (insn)
4829     {
4830       int uid;
4831       rtx_insn *next = next_real_insn (insn);
4832 
4833       if (DEBUG_INSN_P (insn))
4834 	goto done;
4835 
4836       if (GET_MODE (insn) == TImode)
4837 	reservation_mask = 0;
4838       uid = INSN_UID (insn);
4839       if (c6x_flag_schedule_insns2 && recog_memoized (insn) >= 0)
4840 	reservation_mask |= 1 << INSN_INFO_ENTRY (uid).reservation;
4841 
4842       if (returning_call_p (insn))
4843 	{
4844 	  rtx_code_label *label = gen_label_rtx ();
4845 	  rtx labelref = gen_rtx_LABEL_REF (Pmode, label);
4846 	  rtx reg = gen_rtx_REG (SImode, RETURN_ADDR_REGNO);
4847 
4848 	  LABEL_NUSES (label) = 2;
4849 	  if (!c6x_flag_schedule_insns2)
4850 	    {
4851 	      if (can_use_callp (insn))
4852 		convert_to_callp (insn);
4853 	      else
4854 		{
4855 		  rtx t;
4856 		  rtx_insn *slot[4];
4857 		  emit_label_after (label, insn);
4858 
4859 		  /* Bundle the call and its delay slots into a single
4860 		     SEQUENCE.  While these do not issue in parallel
4861 		     we need to group them into a single EH region.  */
4862 		  slot[0] = insn;
4863 		  PUT_MODE (insn, TImode);
4864 		  if (TARGET_INSNS_64)
4865 		    {
4866 		      t = gen_addkpc (reg, labelref, GEN_INT (4));
4867 		      slot[1] = emit_insn_after (duplicate_cond (t, insn),
4868 						 insn);
4869 		      PUT_MODE (slot[1], TImode);
4870 		      gen_one_bundle (slot, 2, 0);
4871 		    }
4872 		  else
4873 		    {
4874 		      slot[3] = emit_insn_after (gen_nop_count (GEN_INT (3)),
4875 						 insn);
4876 		      PUT_MODE (slot[3], TImode);
4877 		      t = gen_movsi_lo_sum (reg, reg, labelref);
4878 		      slot[2] = emit_insn_after (duplicate_cond (t, insn),
4879 						  insn);
4880 		      PUT_MODE (slot[2], TImode);
4881 		      t = gen_movsi_high (reg, labelref);
4882 		      slot[1] = emit_insn_after (duplicate_cond (t, insn),
4883 						 insn);
4884 		      PUT_MODE (slot[1], TImode);
4885 		      gen_one_bundle (slot, 4, 0);
4886 		    }
4887 		}
4888 	    }
4889 	  else
4890 	    {
4891 	      /* If we scheduled, we reserved the .S2 unit for one or two
4892 		 cycles after the call.  Emit the insns in these slots,
4893 		 unless it's possible to create a CALLP insn.
4894 		 Note that this works because the dependencies ensure that
4895 		 no insn setting/using B3 is scheduled in the delay slots of
4896 		 a call.  */
4897 	      int this_clock = insn_get_clock (insn);
4898 	      rtx_insn *after1;
4899 
4900 	      call_labels[INSN_UID (insn)] = label;
4901 
4902 	      rtx_insn *last_same_clock = find_last_same_clock (insn);
4903 
4904 	      if (can_use_callp (insn))
4905 		{
4906 		  /* Find the first insn of the next execute packet.  If it
4907 		     is the shadow insn corresponding to this call, we may
4908 		     use a CALLP insn.  */
4909 		  rtx_insn *shadow =
4910 		    next_nonnote_nondebug_insn (last_same_clock);
4911 
4912 		  if (CALL_P (shadow)
4913 		      && insn_get_clock (shadow) == this_clock + 5)
4914 		    {
4915 		      convert_to_callp (shadow);
4916 		      insn_set_clock (shadow, this_clock);
4917 		      INSN_INFO_ENTRY (INSN_UID (shadow)).reservation
4918 			= RESERVATION_S2;
4919 		      INSN_INFO_ENTRY (INSN_UID (shadow)).unit_mask
4920 			= INSN_INFO_ENTRY (INSN_UID (last_same_clock)).unit_mask;
4921 		      if (GET_MODE (insn) == TImode)
4922 			{
4923 			  rtx_insn *new_cycle_first = NEXT_INSN (insn);
4924 			  while (!NONDEBUG_INSN_P (new_cycle_first)
4925 				 || GET_CODE (PATTERN (new_cycle_first)) == USE
4926 				 || GET_CODE (PATTERN (new_cycle_first)) == CLOBBER)
4927 			    new_cycle_first = NEXT_INSN (new_cycle_first);
4928 			  PUT_MODE (new_cycle_first, TImode);
4929 			  if (new_cycle_first != shadow)
4930 			    PUT_MODE (shadow, VOIDmode);
4931 			  INSN_INFO_ENTRY (INSN_UID (new_cycle_first)).ebb_start
4932 			    = INSN_INFO_ENTRY (INSN_UID (insn)).ebb_start;
4933 			}
4934 		      else
4935 			PUT_MODE (shadow, VOIDmode);
4936 		      delete_insn (insn);
4937 		      goto done;
4938 		    }
4939 		}
4940 	      after1 = find_next_cycle_insn (last_same_clock, this_clock + 1);
4941 	      if (after1 == NULL_RTX)
4942 		after1 = last_same_clock;
4943 	      else
4944 		after1 = find_last_same_clock (after1);
4945 	      if (TARGET_INSNS_64)
4946 		{
4947 		  rtx x1 = gen_addkpc (reg, labelref, const0_rtx);
4948 		  x1 = emit_insn_after (duplicate_cond (x1, insn), after1);
4949 		  insn_set_clock (x1, this_clock + 1);
4950 		  INSN_INFO_ENTRY (INSN_UID (x1)).reservation = RESERVATION_S2;
4951 		  if (after1 == last_same_clock)
4952 		    PUT_MODE (x1, TImode);
4953 		  else
4954 		    INSN_INFO_ENTRY (INSN_UID (x1)).unit_mask
4955 		      = INSN_INFO_ENTRY (INSN_UID (after1)).unit_mask;
4956 		}
4957 	      else
4958 		{
4959 		  rtx x1, x2;
4960 		  rtx_insn *after2 = find_next_cycle_insn (after1,
4961 							   this_clock + 2);
4962 		  if (after2 == NULL_RTX)
4963 		    after2 = after1;
4964 		  x2 = gen_movsi_lo_sum (reg, reg, labelref);
4965 		  x2 = emit_insn_after (duplicate_cond (x2, insn), after2);
4966 		  x1 = gen_movsi_high (reg, labelref);
4967 		  x1 = emit_insn_after (duplicate_cond (x1, insn), after1);
4968 		  insn_set_clock (x1, this_clock + 1);
4969 		  insn_set_clock (x2, this_clock + 2);
4970 		  INSN_INFO_ENTRY (INSN_UID (x1)).reservation = RESERVATION_S2;
4971 		  INSN_INFO_ENTRY (INSN_UID (x2)).reservation = RESERVATION_S2;
4972 		  if (after1 == last_same_clock)
4973 		    PUT_MODE (x1, TImode);
4974 		  else
4975 		    INSN_INFO_ENTRY (INSN_UID (x1)).unit_mask
4976 		      = INSN_INFO_ENTRY (INSN_UID (after1)).unit_mask;
4977 		  if (after1 == after2)
4978 		    PUT_MODE (x2, TImode);
4979 		  else
4980 		    INSN_INFO_ENTRY (INSN_UID (x2)).unit_mask
4981 		      = INSN_INFO_ENTRY (INSN_UID (after2)).unit_mask;
4982 		}
4983 	    }
4984 	}
4985     done:
4986       insn = next;
4987     }
4988 }
4989 
4990 /* Called as part of c6x_reorg.  This function emits multi-cycle NOP
4991    insns as required for correctness.  CALL_LABELS is the array that
4992    holds the return labels for call insns; we emit these here if
4993    scheduling was run earlier.  */
4994 
4995 static void
reorg_emit_nops(rtx_code_label ** call_labels)4996 reorg_emit_nops (rtx_code_label **call_labels)
4997 {
4998   bool first;
4999   rtx last_call;
5000   rtx_insn *prev;
5001   int prev_clock, earliest_bb_end;
5002   int prev_implicit_nops;
5003   rtx_insn *insn = get_insns ();
5004 
5005   /* We look at one insn (or bundle inside a sequence) in each iteration, storing
5006      its issue time in PREV_CLOCK for the next iteration.  If there is a gap in
5007      clocks, we must insert a NOP.
5008      EARLIEST_BB_END tracks in which cycle all insns that have been issued in the
5009      current basic block will finish.  We must not allow the next basic block to
5010      begin before this cycle.
5011      PREV_IMPLICIT_NOPS tells us whether we've seen an insn that implicitly contains
5012      a multi-cycle nop.  The code is scheduled such that subsequent insns will
5013      show the cycle gap, but we needn't insert a real NOP instruction.  */
5014   insn = next_real_insn (insn);
5015   last_call = prev = NULL;
5016   prev_clock = -1;
5017   earliest_bb_end = 0;
5018   prev_implicit_nops = 0;
5019   first = true;
5020   while (insn)
5021     {
5022       int this_clock = -1;
5023       rtx_insn *next;
5024       int max_cycles = 0;
5025 
5026       next = next_real_insn (insn);
5027 
5028       if (DEBUG_INSN_P (insn)
5029 	  || GET_CODE (PATTERN (insn)) == USE
5030 	  || GET_CODE (PATTERN (insn)) == CLOBBER
5031 	  || shadow_or_blockage_p (insn)
5032 	  || JUMP_TABLE_DATA_P (insn))
5033 	goto next_insn;
5034 
5035       if (!c6x_flag_schedule_insns2)
5036 	/* No scheduling; ensure that no parallel issue happens.  */
5037 	PUT_MODE (insn, TImode);
5038       else
5039 	{
5040 	  int cycles;
5041 
5042 	  this_clock = insn_get_clock (insn);
5043 	  if (this_clock != prev_clock)
5044 	    {
5045 	      PUT_MODE (insn, TImode);
5046 
5047 	      if (!first)
5048 		{
5049 		  cycles = this_clock - prev_clock;
5050 
5051 		  cycles -= prev_implicit_nops;
5052 		  if (cycles > 1)
5053 		    {
5054 		      rtx nop = emit_nop_after (cycles - 1, prev);
5055 		      insn_set_clock (nop, prev_clock + prev_implicit_nops + 1);
5056 		    }
5057 		}
5058 	      prev_clock = this_clock;
5059 
5060 	      if (last_call
5061 		  && insn_get_clock (last_call) + 6 <= this_clock)
5062 		{
5063 		  emit_label_before (call_labels[INSN_UID (last_call)], insn);
5064 		  last_call = NULL_RTX;
5065 		}
5066 	      prev_implicit_nops = 0;
5067 	    }
5068 	}
5069 
5070       /* Examine how many cycles the current insn takes, and adjust
5071 	 LAST_CALL, EARLIEST_BB_END and PREV_IMPLICIT_NOPS.  */
5072       if (recog_memoized (insn) >= 0
5073 	  /* If not scheduling, we've emitted NOPs after calls already.  */
5074 	  && (c6x_flag_schedule_insns2 || !returning_call_p (insn)))
5075 	{
5076 	  max_cycles = get_attr_cycles (insn);
5077 	  if (get_attr_type (insn) == TYPE_CALLP)
5078 	    prev_implicit_nops = 5;
5079 	}
5080       else
5081 	max_cycles = 1;
5082       if (returning_call_p (insn))
5083 	last_call = insn;
5084 
5085       if (c6x_flag_schedule_insns2)
5086 	{
5087 	  gcc_assert (this_clock >= 0);
5088 	  if (earliest_bb_end < this_clock + max_cycles)
5089 	    earliest_bb_end = this_clock + max_cycles;
5090 	}
5091       else if (max_cycles > 1)
5092 	emit_nop_after (max_cycles - 1, insn);
5093 
5094       prev = insn;
5095       first = false;
5096 
5097     next_insn:
5098       if (c6x_flag_schedule_insns2
5099 	  && (next == NULL_RTX
5100 	      || (GET_MODE (next) == TImode
5101 		  && INSN_INFO_ENTRY (INSN_UID (next)).ebb_start))
5102 	  && earliest_bb_end > 0)
5103 	{
5104 	  int cycles = earliest_bb_end - prev_clock;
5105 	  if (cycles > 1)
5106 	    {
5107 	      prev = emit_nop_after (cycles - 1, prev);
5108 	      insn_set_clock (prev, prev_clock + prev_implicit_nops + 1);
5109 	    }
5110 	  earliest_bb_end = 0;
5111 	  prev_clock = -1;
5112 	  first = true;
5113 
5114 	  if (last_call)
5115 	    emit_label_after (call_labels[INSN_UID (last_call)], prev);
5116 	  last_call = NULL_RTX;
5117 	}
5118       insn = next;
5119     }
5120 }
5121 
5122 /* If possible, split INSN, which we know is either a jump or a call, into a real
5123    insn and its shadow.  */
5124 static void
split_delayed_branch(rtx_insn * insn)5125 split_delayed_branch (rtx_insn *insn)
5126 {
5127   int code = recog_memoized (insn);
5128   rtx_insn *i1;
5129   rtx newpat;
5130   rtx pat = PATTERN (insn);
5131 
5132   if (GET_CODE (pat) == COND_EXEC)
5133     pat = COND_EXEC_CODE (pat);
5134 
5135   if (CALL_P (insn))
5136     {
5137       rtx src = pat, dest = NULL_RTX;
5138       rtx callee;
5139       if (GET_CODE (pat) == SET)
5140 	{
5141 	  dest = SET_DEST (pat);
5142 	  src = SET_SRC (pat);
5143 	}
5144       callee = XEXP (XEXP (src, 0), 0);
5145       if (SIBLING_CALL_P (insn))
5146 	{
5147 	  if (REG_P (callee))
5148 	    newpat = gen_indirect_sibcall_shadow ();
5149 	  else
5150 	    newpat = gen_sibcall_shadow (callee);
5151 	  pat = gen_real_jump (callee);
5152 	}
5153       else if (dest != NULL_RTX)
5154 	{
5155 	  if (REG_P (callee))
5156 	    newpat = gen_indirect_call_value_shadow (dest);
5157 	  else
5158 	    newpat = gen_call_value_shadow (dest, callee);
5159 	  pat = gen_real_call (callee);
5160 	}
5161       else
5162 	{
5163 	  if (REG_P (callee))
5164 	    newpat = gen_indirect_call_shadow ();
5165 	  else
5166 	    newpat = gen_call_shadow (callee);
5167 	  pat = gen_real_call (callee);
5168 	}
5169       pat = duplicate_cond (pat, insn);
5170       newpat = duplicate_cond (newpat, insn);
5171     }
5172   else
5173     {
5174       rtx src, op;
5175       if (GET_CODE (pat) == PARALLEL
5176 	  && GET_CODE (XVECEXP (pat, 0, 0)) == RETURN)
5177 	{
5178 	  newpat = gen_return_shadow ();
5179 	  pat = gen_real_ret (XEXP (XVECEXP (pat, 0, 1), 0));
5180 	  newpat = duplicate_cond (newpat, insn);
5181 	}
5182       else
5183 	switch (code)
5184 	  {
5185 	  case CODE_FOR_br_true:
5186 	  case CODE_FOR_br_false:
5187 	    src = SET_SRC (pat);
5188 	    op = XEXP (src, code == CODE_FOR_br_true ? 1 : 2);
5189 	    newpat = gen_condjump_shadow (op);
5190 	    pat = gen_real_jump (op);
5191 	    if (code == CODE_FOR_br_true)
5192 	      pat = gen_rtx_COND_EXEC (VOIDmode, XEXP (src, 0), pat);
5193 	    else
5194 	      pat = gen_rtx_COND_EXEC (VOIDmode,
5195 				       reversed_comparison (XEXP (src, 0),
5196 							    VOIDmode),
5197 				       pat);
5198 	    break;
5199 
5200 	  case CODE_FOR_jump:
5201 	    op = SET_SRC (pat);
5202 	    newpat = gen_jump_shadow (op);
5203 	    break;
5204 
5205 	  case CODE_FOR_indirect_jump:
5206 	    newpat = gen_indirect_jump_shadow ();
5207 	    break;
5208 
5209 	  case CODE_FOR_return_internal:
5210 	    newpat = gen_return_shadow ();
5211 	    pat = gen_real_ret (XEXP (XVECEXP (pat, 0, 1), 0));
5212 	    break;
5213 
5214 	  default:
5215 	    return;
5216 	  }
5217     }
5218   i1 = emit_insn_before (pat, insn);
5219   PATTERN (insn) = newpat;
5220   INSN_CODE (insn) = -1;
5221   record_delay_slot_pair (i1, insn, 5, 0);
5222 }
5223 
5224 /* If INSN is a multi-cycle insn that should be handled properly in
5225    modulo-scheduling, split it into a real insn and a shadow.
5226    Return true if we made a change.
5227 
5228    It is valid for us to fail to split an insn; the caller has to deal
5229    with the possibility.  Currently we handle loads and most mpy2 and
5230    mpy4 insns.  */
5231 static bool
split_delayed_nonbranch(rtx_insn * insn)5232 split_delayed_nonbranch (rtx_insn *insn)
5233 {
5234   int code = recog_memoized (insn);
5235   enum attr_type type;
5236   rtx_insn *i1;
5237   rtx newpat, src, dest;
5238   rtx pat = PATTERN (insn);
5239   rtvec rtv;
5240   int delay;
5241 
5242   if (GET_CODE (pat) == COND_EXEC)
5243     pat = COND_EXEC_CODE (pat);
5244 
5245   if (code < 0 || GET_CODE (pat) != SET)
5246     return false;
5247   src = SET_SRC (pat);
5248   dest = SET_DEST (pat);
5249   if (!REG_P (dest))
5250     return false;
5251 
5252   type = get_attr_type (insn);
5253   if (code >= 0
5254       && (type == TYPE_LOAD
5255 	  || type == TYPE_LOADN))
5256     {
5257       if (!MEM_P (src)
5258 	  && (GET_CODE (src) != ZERO_EXTEND
5259 	      || !MEM_P (XEXP (src, 0))))
5260 	return false;
5261 
5262       if (GET_MODE_SIZE (GET_MODE (dest)) > 4
5263 	  && (GET_MODE_SIZE (GET_MODE (dest)) != 8 || !TARGET_LDDW))
5264 	return false;
5265 
5266       rtv = gen_rtvec (2, GEN_INT (REGNO (SET_DEST (pat))),
5267 		       SET_SRC (pat));
5268       newpat = gen_load_shadow (SET_DEST (pat));
5269       pat = gen_rtx_UNSPEC (VOIDmode, rtv, UNSPEC_REAL_LOAD);
5270       delay = 4;
5271     }
5272   else if (code >= 0
5273 	   && (type == TYPE_MPY2
5274 	       || type == TYPE_MPY4))
5275     {
5276       /* We don't handle floating point multiplies yet.  */
5277       if (GET_MODE (dest) == SFmode)
5278 	return false;
5279 
5280       rtv = gen_rtvec (2, GEN_INT (REGNO (SET_DEST (pat))),
5281 		       SET_SRC (pat));
5282       newpat = gen_mult_shadow (SET_DEST (pat));
5283       pat = gen_rtx_UNSPEC (VOIDmode, rtv, UNSPEC_REAL_MULT);
5284       delay = type == TYPE_MPY2 ? 1 : 3;
5285     }
5286   else
5287     return false;
5288 
5289   pat = duplicate_cond (pat, insn);
5290   newpat = duplicate_cond (newpat, insn);
5291   i1 = emit_insn_before (pat, insn);
5292   PATTERN (insn) = newpat;
5293   INSN_CODE (insn) = -1;
5294   recog_memoized (insn);
5295   recog_memoized (i1);
5296   record_delay_slot_pair (i1, insn, delay, 0);
5297   return true;
5298 }
5299 
5300 /* Examine if INSN is the result of splitting a load into a real load and a
5301    shadow, and if so, undo the transformation.  */
5302 static void
undo_split_delayed_nonbranch(rtx_insn * insn)5303 undo_split_delayed_nonbranch (rtx_insn *insn)
5304 {
5305   int icode = recog_memoized (insn);
5306   enum attr_type type;
5307   rtx prev_pat, insn_pat;
5308   rtx_insn *prev;
5309 
5310   if (icode < 0)
5311     return;
5312   type = get_attr_type (insn);
5313   if (type != TYPE_LOAD_SHADOW && type != TYPE_MULT_SHADOW)
5314     return;
5315   prev = PREV_INSN (insn);
5316   prev_pat = PATTERN (prev);
5317   insn_pat = PATTERN (insn);
5318   if (GET_CODE (prev_pat) == COND_EXEC)
5319     {
5320       prev_pat = COND_EXEC_CODE (prev_pat);
5321       insn_pat = COND_EXEC_CODE (insn_pat);
5322     }
5323 
5324   gcc_assert (GET_CODE (prev_pat) == UNSPEC
5325 	      && ((XINT (prev_pat, 1) == UNSPEC_REAL_LOAD
5326 		   && type == TYPE_LOAD_SHADOW)
5327 		  || (XINT (prev_pat, 1) == UNSPEC_REAL_MULT
5328 		      && type == TYPE_MULT_SHADOW)));
5329   insn_pat = gen_rtx_SET (SET_DEST (insn_pat),
5330 			  XVECEXP (prev_pat, 0, 1));
5331   insn_pat = duplicate_cond (insn_pat, prev);
5332   PATTERN (insn) = insn_pat;
5333   INSN_CODE (insn) = -1;
5334   delete_insn (prev);
5335 }
5336 
5337 /* Split every insn (i.e. jumps and calls) which can have delay slots into
5338    two parts: the first one is scheduled normally and emits the instruction,
5339    while the second one is a shadow insn which shows the side effect taking
5340    place. The second one is placed in the right cycle by the scheduler, but
5341    not emitted as an assembly instruction.  */
5342 
5343 static void
split_delayed_insns(void)5344 split_delayed_insns (void)
5345 {
5346   rtx_insn *insn;
5347   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5348     {
5349       if (JUMP_P (insn) || CALL_P (insn))
5350 	split_delayed_branch (insn);
5351     }
5352 }
5353 
5354 /* For every insn that has an entry in the new_conditions vector, give it
5355    the appropriate predicate.  */
5356 static void
conditionalize_after_sched(void)5357 conditionalize_after_sched (void)
5358 {
5359   basic_block bb;
5360   rtx_insn *insn;
5361   FOR_EACH_BB_FN (bb, cfun)
5362     FOR_BB_INSNS (bb, insn)
5363       {
5364 	unsigned uid = INSN_UID (insn);
5365 	rtx cond;
5366 	if (!NONDEBUG_INSN_P (insn) || uid >= INSN_INFO_LENGTH)
5367 	  continue;
5368 	cond = INSN_INFO_ENTRY (uid).new_cond;
5369 	if (cond == NULL_RTX)
5370 	  continue;
5371 	if (dump_file)
5372 	  fprintf (dump_file, "Conditionalizing insn %d\n", uid);
5373 	predicate_insn (insn, cond, true);
5374       }
5375 }
5376 
5377 /* A callback for the hw-doloop pass.  This function examines INSN; if
5378    it is a loop_end pattern we recognize, return the reg rtx for the
5379    loop counter.  Otherwise, return NULL_RTX.  */
5380 
5381 static rtx
hwloop_pattern_reg(rtx_insn * insn)5382 hwloop_pattern_reg (rtx_insn *insn)
5383 {
5384   rtx pat, reg;
5385 
5386   if (!JUMP_P (insn) || recog_memoized (insn) != CODE_FOR_loop_end)
5387     return NULL_RTX;
5388 
5389   pat = PATTERN (insn);
5390   reg = SET_DEST (XVECEXP (pat, 0, 1));
5391   if (!REG_P (reg))
5392     return NULL_RTX;
5393   return reg;
5394 }
5395 
5396 /* Return the number of cycles taken by BB, as computed by scheduling,
5397    including the latencies of all insns with delay slots.  IGNORE is
5398    an insn we should ignore in the calculation, usually the final
5399    branch.  */
5400 static int
bb_earliest_end_cycle(basic_block bb,rtx ignore)5401 bb_earliest_end_cycle (basic_block bb, rtx ignore)
5402 {
5403   int earliest = 0;
5404   rtx_insn *insn;
5405 
5406   FOR_BB_INSNS (bb, insn)
5407     {
5408       int cycles, this_clock;
5409 
5410       if (LABEL_P (insn) || NOTE_P (insn) || DEBUG_INSN_P (insn)
5411 	  || GET_CODE (PATTERN (insn)) == USE
5412 	  || GET_CODE (PATTERN (insn)) == CLOBBER
5413 	  || insn == ignore)
5414 	continue;
5415 
5416       this_clock = insn_get_clock (insn);
5417       cycles = get_attr_cycles (insn);
5418 
5419       if (earliest < this_clock + cycles)
5420 	earliest = this_clock + cycles;
5421     }
5422   return earliest;
5423 }
5424 
5425 /* Examine the insns in BB and remove all which have a uid greater or
5426    equal to MAX_UID.  */
5427 static void
filter_insns_above(basic_block bb,int max_uid)5428 filter_insns_above (basic_block bb, int max_uid)
5429 {
5430   rtx_insn *insn, *next;
5431   bool prev_ti = false;
5432   int prev_cycle = -1;
5433 
5434   FOR_BB_INSNS_SAFE (bb, insn, next)
5435     {
5436       int this_cycle;
5437       if (!NONDEBUG_INSN_P (insn))
5438 	continue;
5439       if (insn == BB_END (bb))
5440 	return;
5441       this_cycle = insn_get_clock (insn);
5442       if (prev_ti && this_cycle == prev_cycle)
5443 	{
5444 	  gcc_assert (GET_MODE (insn) != TImode);
5445 	  PUT_MODE (insn, TImode);
5446 	}
5447       prev_ti = false;
5448       if (INSN_UID (insn) >= max_uid)
5449 	{
5450 	  if (GET_MODE (insn) == TImode)
5451 	    {
5452 	      prev_ti = true;
5453 	      prev_cycle = this_cycle;
5454 	    }
5455 	  delete_insn (insn);
5456 	}
5457     }
5458 }
5459 
5460 /* Implement TARGET_ASM_EMIT_EXCEPT_PERSONALITY.  */
5461 
5462 static void
c6x_asm_emit_except_personality(rtx personality)5463 c6x_asm_emit_except_personality (rtx personality)
5464 {
5465   fputs ("\t.personality\t", asm_out_file);
5466   output_addr_const (asm_out_file, personality);
5467   fputc ('\n', asm_out_file);
5468 }
5469 
5470 /* Use a special assembly directive rather than a regular setion for
5471    unwind table data.  */
5472 
5473 static void
c6x_asm_init_sections(void)5474 c6x_asm_init_sections (void)
5475 {
5476   exception_section = get_unnamed_section (0, output_section_asm_op,
5477 					   "\t.handlerdata");
5478 }
5479 
5480 /* A callback for the hw-doloop pass.  Called to optimize LOOP in a
5481    machine-specific fashion; returns true if successful and false if
5482    the hwloop_fail function should be called.  */
5483 
5484 static bool
hwloop_optimize(hwloop_info loop)5485 hwloop_optimize (hwloop_info loop)
5486 {
5487   basic_block entry_bb, bb;
5488   rtx_insn *seq, *insn, *prev, *entry_after, *end_packet;
5489   rtx_insn *head_insn, *tail_insn, *new_insns, *last_insn;
5490   int loop_earliest;
5491   int n_execute_packets;
5492   edge entry_edge;
5493   unsigned ix;
5494   int max_uid_before, delayed_splits;
5495   int i, sp_ii, min_ii, max_ii, max_parallel, n_insns, n_real_insns, stages;
5496   rtx_insn **orig_vec;
5497   rtx_insn **copies;
5498   rtx_insn ***insn_copies;
5499 
5500   if (!c6x_flag_modulo_sched || !c6x_flag_schedule_insns2
5501       || !TARGET_INSNS_64PLUS)
5502     return false;
5503 
5504   if (loop->iter_reg_used || loop->depth > 1)
5505     return false;
5506   if (loop->has_call || loop->has_asm)
5507     return false;
5508 
5509   if (loop->head != loop->tail)
5510     return false;
5511 
5512   gcc_assert (loop->incoming_dest == loop->head);
5513 
5514   entry_edge = NULL;
5515   FOR_EACH_VEC_SAFE_ELT (loop->incoming, i, entry_edge)
5516     if (entry_edge->flags & EDGE_FALLTHRU)
5517       break;
5518   if (entry_edge == NULL)
5519     return false;
5520 
5521   reshuffle_units (loop->head);
5522 
5523   in_hwloop = true;
5524   schedule_ebbs_init ();
5525   schedule_ebb (BB_HEAD (loop->tail), loop->loop_end, true);
5526   schedule_ebbs_finish ();
5527   in_hwloop = false;
5528 
5529   bb = loop->head;
5530   loop_earliest = bb_earliest_end_cycle (bb, loop->loop_end) + 1;
5531 
5532   max_uid_before = get_max_uid ();
5533 
5534   /* Split all multi-cycle operations, such as loads.  For normal
5535      scheduling, we only do this for branches, as the generated code
5536      would otherwise not be interrupt-safe.  When using sploop, it is
5537      safe and beneficial to split them.  If any multi-cycle operations
5538      remain after splitting (because we don't handle them yet), we
5539      cannot pipeline the loop.  */
5540   delayed_splits = 0;
5541   FOR_BB_INSNS (bb, insn)
5542     {
5543       if (NONDEBUG_INSN_P (insn))
5544 	{
5545 	  recog_memoized (insn);
5546 	  if (split_delayed_nonbranch (insn))
5547 	    delayed_splits++;
5548 	  else if (INSN_CODE (insn) >= 0
5549 		   && get_attr_cycles (insn) > 1)
5550 	    goto undo_splits;
5551 	}
5552     }
5553 
5554   /* Count the number of insns as well as the number real insns, and save
5555      the original sequence of insns in case we must restore it later.  */
5556   n_insns = n_real_insns = 0;
5557   FOR_BB_INSNS (bb, insn)
5558     {
5559       n_insns++;
5560       if (NONDEBUG_INSN_P (insn) && insn != loop->loop_end)
5561 	n_real_insns++;
5562     }
5563   orig_vec = XNEWVEC (rtx_insn *, n_insns);
5564   n_insns = 0;
5565   FOR_BB_INSNS (bb, insn)
5566     orig_vec[n_insns++] = insn;
5567 
5568   /* Count the unit reservations, and compute a minimum II from that
5569      table.  */
5570   count_unit_reqs (unit_reqs, loop->start_label,
5571 		   PREV_INSN (loop->loop_end));
5572   merge_unit_reqs (unit_reqs);
5573 
5574   min_ii = res_mii (unit_reqs);
5575   max_ii = loop_earliest < 15 ? loop_earliest : 14;
5576 
5577   /* Make copies of the loop body, up to a maximum number of stages we want
5578      to handle.  */
5579   max_parallel = loop_earliest / min_ii + 1;
5580 
5581   copies = XCNEWVEC (rtx_insn *, (max_parallel + 1) * n_real_insns);
5582   insn_copies = XNEWVEC (rtx_insn **, max_parallel + 1);
5583   for (i = 0; i < max_parallel + 1; i++)
5584     insn_copies[i] = copies + i * n_real_insns;
5585 
5586   head_insn = next_nonnote_nondebug_insn (loop->start_label);
5587   tail_insn = prev_real_insn (BB_END (bb));
5588 
5589   i = 0;
5590   FOR_BB_INSNS (bb, insn)
5591     if (NONDEBUG_INSN_P (insn) && insn != loop->loop_end)
5592       insn_copies[0][i++] = insn;
5593 
5594   sploop_max_uid_iter0 = get_max_uid ();
5595 
5596   /* Generate the copies of the loop body, and save them in the
5597      INSN_COPIES array.  */
5598   start_sequence ();
5599   for (i = 0; i < max_parallel; i++)
5600     {
5601       int j;
5602       rtx_insn *this_iter;
5603 
5604       copy_bb_data id;
5605       this_iter = duplicate_insn_chain (head_insn, tail_insn, NULL, &id);
5606       j = 0;
5607       while (this_iter)
5608 	{
5609 	  rtx_insn *prev_stage_insn = insn_copies[i][j];
5610 	  gcc_assert (INSN_CODE (this_iter) == INSN_CODE (prev_stage_insn));
5611 
5612 	  if (INSN_CODE (this_iter) >= 0
5613 	      && (get_attr_type (this_iter) == TYPE_LOAD_SHADOW
5614 		  || get_attr_type (this_iter) == TYPE_MULT_SHADOW))
5615 	    {
5616 	      rtx_insn *prev = PREV_INSN (this_iter);
5617 	      record_delay_slot_pair (prev, this_iter,
5618 				      get_attr_cycles (prev) - 1, 0);
5619 	    }
5620 	  else
5621 	    record_delay_slot_pair (prev_stage_insn, this_iter, i, 1);
5622 
5623 	  insn_copies[i + 1][j] = this_iter;
5624 	  j++;
5625 	  this_iter = next_nonnote_nondebug_insn (this_iter);
5626 	}
5627     }
5628   new_insns = get_insns ();
5629   last_insn = insn_copies[max_parallel][n_real_insns - 1];
5630   end_sequence ();
5631   emit_insn_before (new_insns, BB_END (bb));
5632 
5633   /* Try to schedule the loop using varying initiation intervals,
5634      starting with the smallest possible and incrementing it
5635      on failure.  */
5636   for (sp_ii = min_ii; sp_ii <= max_ii; sp_ii++)
5637     {
5638       basic_block tmp_bb;
5639       if (dump_file)
5640 	fprintf (dump_file, "Trying to schedule for II %d\n", sp_ii);
5641 
5642       df_clear_flags (DF_LR_RUN_DCE);
5643 
5644       schedule_ebbs_init ();
5645       set_modulo_params (sp_ii, max_parallel, n_real_insns,
5646 			 sploop_max_uid_iter0);
5647       tmp_bb = schedule_ebb (BB_HEAD (bb), last_insn, true);
5648       schedule_ebbs_finish ();
5649 
5650       if (tmp_bb)
5651 	{
5652 	  if (dump_file)
5653 	    fprintf (dump_file, "Found schedule with II %d\n", sp_ii);
5654 	  break;
5655 	}
5656     }
5657 
5658   discard_delay_pairs_above (max_uid_before);
5659 
5660   if (sp_ii > max_ii)
5661     goto restore_loop;
5662 
5663   stages = insn_get_clock (ss.last_scheduled_iter0) / sp_ii + 1;
5664 
5665   if (stages == 1 && sp_ii > 5)
5666     goto restore_loop;
5667 
5668   /* At this point, we know we've been successful, unless we find later that
5669      there are too many execute packets for the loop buffer to hold.  */
5670 
5671   /* Assign reservations to the instructions in the loop.  We must find
5672      the stage that contains the full loop kernel, and transfer the
5673      reservations of the instructions contained in it to the corresponding
5674      instructions from iteration 0, which are the only ones we'll keep.  */
5675   assign_reservations (BB_HEAD (bb), ss.last_scheduled_insn);
5676   SET_PREV_INSN (BB_END (bb)) = ss.last_scheduled_iter0;
5677   SET_NEXT_INSN (ss.last_scheduled_iter0) = BB_END (bb);
5678   filter_insns_above (bb, sploop_max_uid_iter0);
5679 
5680   for (i = 0; i < n_real_insns; i++)
5681     {
5682       rtx insn = insn_copies[0][i];
5683       int uid = INSN_UID (insn);
5684       int stage = insn_uid_get_clock (uid) / sp_ii;
5685 
5686       if (stage + 1 < stages)
5687 	{
5688 	  int copy_uid;
5689 	  stage = stages - stage - 1;
5690 	  copy_uid = INSN_UID (insn_copies[stage][i]);
5691 	  INSN_INFO_ENTRY (uid).reservation
5692 	    = INSN_INFO_ENTRY (copy_uid).reservation;
5693 	}
5694     }
5695   if (stages == 1)
5696     stages++;
5697 
5698   /* Compute the number of execute packets the pipelined form of the loop will
5699      require.  */
5700   prev = NULL;
5701   n_execute_packets = 0;
5702   for (insn = loop->start_label;
5703        insn != loop->loop_end;
5704        insn = NEXT_INSN (insn))
5705     {
5706       if (NONDEBUG_INSN_P (insn) && GET_MODE (insn) == TImode
5707 	  && !shadow_p (insn))
5708 	{
5709 	  n_execute_packets++;
5710 	  if (prev && insn_get_clock (prev) + 1 != insn_get_clock (insn))
5711 	    /* We need an extra NOP instruction.  */
5712 	    n_execute_packets++;
5713 
5714 	  prev = insn;
5715 	}
5716     }
5717 
5718   end_packet = ss.last_scheduled_iter0;
5719   while (!NONDEBUG_INSN_P (end_packet) || GET_MODE (end_packet) != TImode)
5720     end_packet = PREV_INSN (end_packet);
5721 
5722   /* The earliest cycle in which we can emit the SPKERNEL instruction.  */
5723   loop_earliest = (stages - 1) * sp_ii;
5724   if (loop_earliest > insn_get_clock (end_packet))
5725     {
5726       n_execute_packets++;
5727       end_packet = loop->loop_end;
5728     }
5729   else
5730     loop_earliest = insn_get_clock (end_packet);
5731 
5732   if (n_execute_packets > 14)
5733     goto restore_loop;
5734 
5735   /* Generate the spkernel instruction, and place it at the appropriate
5736      spot.  */
5737   PUT_MODE (end_packet, VOIDmode);
5738 
5739   insn = emit_jump_insn_before (
5740 	   gen_spkernel (GEN_INT (stages - 1),
5741 			 const0_rtx, JUMP_LABEL (loop->loop_end)),
5742 	   end_packet);
5743   JUMP_LABEL (insn) = JUMP_LABEL (loop->loop_end);
5744   insn_set_clock (insn, loop_earliest);
5745   PUT_MODE (insn, TImode);
5746   INSN_INFO_ENTRY (INSN_UID (insn)).ebb_start = false;
5747   delete_insn (loop->loop_end);
5748 
5749   /* Place the mvc and sploop instructions before the loop.  */
5750   entry_bb = entry_edge->src;
5751 
5752   start_sequence ();
5753 
5754   insn = emit_insn (gen_mvilc (loop->iter_reg));
5755   if (loop->iter_reg_used_outside)
5756     insn = emit_move_insn (loop->iter_reg, const0_rtx);
5757   insn = emit_insn (gen_sploop (GEN_INT (sp_ii)));
5758   seq = get_insns ();
5759 
5760   if (!single_succ_p (entry_bb) || vec_safe_length (loop->incoming) > 1)
5761     {
5762       basic_block new_bb;
5763       edge e;
5764       edge_iterator ei;
5765 
5766       emit_insn_before (seq, BB_HEAD (loop->head));
5767       seq = emit_label_before (gen_label_rtx (), seq);
5768 
5769       new_bb = create_basic_block (seq, insn, entry_bb);
5770       FOR_EACH_EDGE (e, ei, loop->incoming)
5771 	{
5772 	  if (!(e->flags & EDGE_FALLTHRU))
5773 	    redirect_edge_and_branch_force (e, new_bb);
5774 	  else
5775 	    redirect_edge_succ (e, new_bb);
5776 	}
5777       make_edge (new_bb, loop->head, 0);
5778     }
5779   else
5780     {
5781       entry_after = BB_END (entry_bb);
5782       while (DEBUG_INSN_P (entry_after)
5783 	     || (NOTE_P (entry_after)
5784 		 && NOTE_KIND (entry_after) != NOTE_INSN_BASIC_BLOCK))
5785 	entry_after = PREV_INSN (entry_after);
5786       emit_insn_after (seq, entry_after);
5787     }
5788 
5789   end_sequence ();
5790 
5791   /* Make sure we don't try to schedule this loop again.  */
5792   for (ix = 0; loop->blocks.iterate (ix, &bb); ix++)
5793     bb->flags |= BB_DISABLE_SCHEDULE;
5794 
5795   return true;
5796 
5797  restore_loop:
5798   if (dump_file)
5799     fprintf (dump_file, "Unable to pipeline loop.\n");
5800 
5801   for (i = 1; i < n_insns; i++)
5802     {
5803       SET_NEXT_INSN (orig_vec[i - 1]) = orig_vec[i];
5804       SET_PREV_INSN (orig_vec[i]) = orig_vec[i - 1];
5805     }
5806   SET_PREV_INSN (orig_vec[0]) = PREV_INSN (BB_HEAD (bb));
5807   SET_NEXT_INSN (PREV_INSN (BB_HEAD (bb))) = orig_vec[0];
5808   SET_NEXT_INSN (orig_vec[n_insns - 1]) = NEXT_INSN (BB_END (bb));
5809   SET_PREV_INSN (NEXT_INSN (BB_END (bb))) = orig_vec[n_insns - 1];
5810   BB_HEAD (bb) = orig_vec[0];
5811   BB_END (bb) = orig_vec[n_insns - 1];
5812  undo_splits:
5813   free_delay_pairs ();
5814   FOR_BB_INSNS (bb, insn)
5815     if (NONDEBUG_INSN_P (insn))
5816       undo_split_delayed_nonbranch (insn);
5817   return false;
5818 }
5819 
5820 /* A callback for the hw-doloop pass.  Called when a loop we have discovered
5821    turns out not to be optimizable; we have to split the doloop_end pattern
5822    into a subtract and a test.  */
5823 static void
hwloop_fail(hwloop_info loop)5824 hwloop_fail (hwloop_info loop)
5825 {
5826   rtx insn, test, testreg;
5827 
5828   if (dump_file)
5829     fprintf (dump_file, "splitting doloop insn %d\n",
5830 	     INSN_UID (loop->loop_end));
5831   insn = gen_addsi3 (loop->iter_reg, loop->iter_reg, constm1_rtx);
5832   /* See if we can emit the add at the head of the loop rather than at the
5833      end.  */
5834   if (loop->head == NULL
5835       || loop->iter_reg_used_outside
5836       || loop->iter_reg_used
5837       || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REGNO (loop->iter_reg))
5838       || loop->incoming_dest != loop->head
5839       || EDGE_COUNT (loop->head->preds) != 2)
5840     emit_insn_before (insn, loop->loop_end);
5841   else
5842     {
5843       rtx_insn *t = loop->start_label;
5844       while (!NOTE_P (t) || NOTE_KIND (t) != NOTE_INSN_BASIC_BLOCK)
5845 	t = NEXT_INSN (t);
5846       emit_insn_after (insn, t);
5847     }
5848 
5849   testreg = SET_DEST (XVECEXP (PATTERN (loop->loop_end), 0, 2));
5850   if (GET_CODE (testreg) == SCRATCH)
5851     testreg = loop->iter_reg;
5852   else
5853     emit_insn_before (gen_movsi (testreg, loop->iter_reg), loop->loop_end);
5854 
5855   test = gen_rtx_NE (VOIDmode, testreg, const0_rtx);
5856   insn = emit_jump_insn_before (gen_cbranchsi4 (test, testreg, const0_rtx,
5857 						loop->start_label),
5858 				loop->loop_end);
5859 
5860   JUMP_LABEL (insn) = loop->start_label;
5861   LABEL_NUSES (loop->start_label)++;
5862   delete_insn (loop->loop_end);
5863 }
5864 
5865 static struct hw_doloop_hooks c6x_doloop_hooks =
5866 {
5867   hwloop_pattern_reg,
5868   hwloop_optimize,
5869   hwloop_fail
5870 };
5871 
5872 /* Run the hw-doloop pass to modulo-schedule hardware loops, or split the
5873    doloop_end patterns where such optimizations are impossible.  */
5874 static void
c6x_hwloops(void)5875 c6x_hwloops (void)
5876 {
5877   if (optimize)
5878     reorg_loops (true, &c6x_doloop_hooks);
5879 }
5880 
5881 /* Implement the TARGET_MACHINE_DEPENDENT_REORG pass.  We split call insns here
5882    into a sequence that loads the return register and performs the call,
5883    and emit the return label.
5884    If scheduling after reload is requested, it happens here.  */
5885 
5886 static void
c6x_reorg(void)5887 c6x_reorg (void)
5888 {
5889   basic_block bb;
5890   bool do_selsched = (c6x_flag_schedule_insns2 && flag_selective_scheduling2
5891 		      && !maybe_skip_selective_scheduling ());
5892 
5893   /* We are freeing block_for_insn in the toplev to keep compatibility
5894      with old MDEP_REORGS that are not CFG based.  Recompute it now.  */
5895   compute_bb_for_insn ();
5896 
5897   df_clear_flags (DF_LR_RUN_DCE);
5898   df_note_add_problem ();
5899 
5900   /* If optimizing, we'll have split before scheduling.  */
5901   if (optimize == 0)
5902     split_all_insns ();
5903 
5904   df_analyze ();
5905 
5906   if (c6x_flag_schedule_insns2)
5907     {
5908       int sz = get_max_uid () * 3 / 2 + 1;
5909 
5910       insn_info.create (sz);
5911     }
5912 
5913   /* Make sure the real-jump insns we create are not deleted.  When modulo-
5914      scheduling, situations where a reg is only stored in a loop can also
5915      cause dead code when doing the initial unrolling.  */
5916   sched_no_dce = true;
5917 
5918   c6x_hwloops ();
5919 
5920   if (c6x_flag_schedule_insns2)
5921     {
5922       split_delayed_insns ();
5923       timevar_push (TV_SCHED2);
5924       if (do_selsched)
5925 	run_selective_scheduling ();
5926       else
5927 	schedule_ebbs ();
5928       conditionalize_after_sched ();
5929       timevar_pop (TV_SCHED2);
5930 
5931       free_delay_pairs ();
5932     }
5933   sched_no_dce = false;
5934 
5935   rtx_code_label **call_labels = XCNEWVEC (rtx_code_label *, get_max_uid () + 1);
5936 
5937   reorg_split_calls (call_labels);
5938 
5939   if (c6x_flag_schedule_insns2)
5940     {
5941       FOR_EACH_BB_FN (bb, cfun)
5942 	if ((bb->flags & BB_DISABLE_SCHEDULE) == 0)
5943 	  assign_reservations (BB_HEAD (bb), BB_END (bb));
5944     }
5945 
5946   if (c6x_flag_var_tracking)
5947     {
5948       timevar_push (TV_VAR_TRACKING);
5949       variable_tracking_main ();
5950       timevar_pop (TV_VAR_TRACKING);
5951     }
5952 
5953   reorg_emit_nops (call_labels);
5954 
5955   /* Post-process the schedule to move parallel insns into SEQUENCEs.  */
5956   if (c6x_flag_schedule_insns2)
5957     {
5958       free_delay_pairs ();
5959       c6x_gen_bundles ();
5960     }
5961 
5962   df_finish_pass (false);
5963 }
5964 
5965 /* Called when a function has been assembled.  It should perform all the
5966    tasks of ASM_DECLARE_FUNCTION_SIZE in elfos.h, plus target-specific
5967    tasks.
5968    We free the reservation (and other scheduling) information here now that
5969    all insns have been output.  */
5970 void
c6x_function_end(FILE * file,const char * fname)5971 c6x_function_end (FILE *file, const char *fname)
5972 {
5973   c6x_output_fn_unwind (file);
5974 
5975   insn_info.release ();
5976 
5977   if (!flag_inhibit_size_directive)
5978     ASM_OUTPUT_MEASURED_SIZE (file, fname);
5979 }
5980 
5981 /* Determine whether X is a shift with code CODE and an integer amount
5982    AMOUNT.  */
5983 static bool
shift_p(rtx x,enum rtx_code code,int amount)5984 shift_p (rtx x, enum rtx_code code, int amount)
5985 {
5986   return (GET_CODE (x) == code && GET_CODE (XEXP (x, 1)) == CONST_INT
5987 	  && INTVAL (XEXP (x, 1)) == amount);
5988 }
5989 
5990 /* Compute a (partial) cost for rtx X.  Return true if the complete
5991    cost has been computed, and false if subexpressions should be
5992    scanned.  In either case, *TOTAL contains the cost result.  */
5993 
5994 static bool
c6x_rtx_costs(rtx x,machine_mode mode,int outer_code,int opno,int * total,bool speed)5995 c6x_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno, int *total,
5996 	       bool speed)
5997 {
5998   int cost2 = COSTS_N_INSNS (1);
5999   rtx op0, op1;
6000   int code = GET_CODE (x);
6001 
6002   switch (code)
6003     {
6004     case CONST_INT:
6005       if (outer_code == SET || outer_code == PLUS)
6006         *total = satisfies_constraint_IsB (x) ? 0 : cost2;
6007       else if (outer_code == AND || outer_code == IOR || outer_code == XOR
6008 	       || outer_code == MINUS)
6009 	*total = satisfies_constraint_Is5 (x) ? 0 : cost2;
6010       else if (GET_RTX_CLASS (outer_code) == RTX_COMPARE
6011 	       || GET_RTX_CLASS (outer_code) == RTX_COMM_COMPARE)
6012 	*total = satisfies_constraint_Iu4 (x) ? 0 : cost2;
6013       else if (outer_code == ASHIFT || outer_code == ASHIFTRT
6014 	       || outer_code == LSHIFTRT)
6015 	*total = satisfies_constraint_Iu5 (x) ? 0 : cost2;
6016       else
6017 	*total = cost2;
6018       return true;
6019 
6020     case CONST:
6021     case LABEL_REF:
6022     case SYMBOL_REF:
6023     case CONST_DOUBLE:
6024       *total = COSTS_N_INSNS (2);
6025       return true;
6026 
6027     case TRUNCATE:
6028       /* Recognize a mult_highpart operation.  */
6029       if ((mode == HImode || mode == SImode)
6030 	  && GET_CODE (XEXP (x, 0)) == LSHIFTRT
6031 	  && GET_MODE (XEXP (x, 0)) == GET_MODE_2XWIDER_MODE (mode).require ()
6032 	  && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
6033 	  && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
6034 	  && INTVAL (XEXP (XEXP (x, 0), 1)) == GET_MODE_BITSIZE (mode))
6035 	{
6036 	  rtx mul = XEXP (XEXP (x, 0), 0);
6037 	  rtx op0 = XEXP (mul, 0);
6038 	  rtx op1 = XEXP (mul, 1);
6039 	  enum rtx_code code0 = GET_CODE (op0);
6040 	  enum rtx_code code1 = GET_CODE (op1);
6041 
6042 	  if ((code0 == code1
6043 	       && (code0 == SIGN_EXTEND || code0 == ZERO_EXTEND))
6044 	      || (mode == HImode
6045 		  && code0 == ZERO_EXTEND && code1 == SIGN_EXTEND))
6046 	    {
6047 	      if (mode == HImode)
6048 		*total = COSTS_N_INSNS (2);
6049 	      else
6050 		*total = COSTS_N_INSNS (12);
6051 	      mode = GET_MODE (XEXP (op0, 0));
6052 	      *total += rtx_cost (XEXP (op0, 0), mode, code0, 0, speed);
6053 	      *total += rtx_cost (XEXP (op1, 0), mode, code1, 0, speed);
6054 	      return true;
6055 	    }
6056 	}
6057       return false;
6058 
6059     case ASHIFT:
6060     case ASHIFTRT:
6061     case LSHIFTRT:
6062       if (mode == DImode)
6063 	*total = COSTS_N_INSNS (CONSTANT_P (XEXP (x, 1)) ? 4 : 15);
6064       else
6065 	*total = COSTS_N_INSNS (1);
6066       return false;
6067 
6068     case PLUS:
6069     case MINUS:
6070       *total = COSTS_N_INSNS (1);
6071       op0 = code == PLUS ? XEXP (x, 0) : XEXP (x, 1);
6072       op1 = code == PLUS ? XEXP (x, 1) : XEXP (x, 0);
6073       if (GET_MODE_SIZE (mode) <= UNITS_PER_WORD
6074 	  && INTEGRAL_MODE_P (mode)
6075 	  && GET_CODE (op0) == MULT
6076 	  && GET_CODE (XEXP (op0, 1)) == CONST_INT
6077 	  && (INTVAL (XEXP (op0, 1)) == 2
6078 	      || INTVAL (XEXP (op0, 1)) == 4
6079 	      || (code == PLUS && INTVAL (XEXP (op0, 1)) == 8)))
6080 	{
6081 	  *total += rtx_cost (XEXP (op0, 0), mode, ASHIFT, 0, speed);
6082 	  *total += rtx_cost (op1, mode, (enum rtx_code) code, 1, speed);
6083 	  return true;
6084 	}
6085       return false;
6086 
6087     case MULT:
6088       op0 = XEXP (x, 0);
6089       op1 = XEXP (x, 1);
6090       if (mode == DFmode)
6091 	{
6092 	  if (TARGET_FP)
6093 	    *total = COSTS_N_INSNS (speed ? 10 : 1);
6094 	  else
6095 	    *total = COSTS_N_INSNS (speed ? 200 : 4);
6096 	}
6097       else if (mode == SFmode)
6098 	{
6099 	  if (TARGET_FP)
6100 	    *total = COSTS_N_INSNS (speed ? 4 : 1);
6101 	  else
6102 	    *total = COSTS_N_INSNS (speed ? 100 : 4);
6103 	}
6104       else if (mode == DImode)
6105 	{
6106 	  if (TARGET_MPY32
6107 	      && GET_CODE (op0) == GET_CODE (op1)
6108 	      && (GET_CODE (op0) == ZERO_EXTEND
6109 		  || GET_CODE (op0) == SIGN_EXTEND))
6110 	    {
6111 	      *total = COSTS_N_INSNS (speed ? 2 : 1);
6112 	      op0 = XEXP (op0, 0);
6113 	      op1 = XEXP (op1, 0);
6114 	    }
6115 	  else
6116 	    /* Maybe improve this laster.  */
6117 	    *total = COSTS_N_INSNS (20);
6118 	}
6119       else if (mode == SImode)
6120 	{
6121 	  if (((GET_CODE (op0) == ZERO_EXTEND
6122 		|| GET_CODE (op0) == SIGN_EXTEND
6123 		|| shift_p (op0, LSHIFTRT, 16))
6124 	       && (GET_CODE (op1) == SIGN_EXTEND
6125 		   || GET_CODE (op1) == ZERO_EXTEND
6126 		   || scst5_operand (op1, SImode)
6127 		   || shift_p (op1, ASHIFTRT, 16)
6128 		   || shift_p (op1, LSHIFTRT, 16)))
6129 	      || (shift_p (op0, ASHIFTRT, 16)
6130 		  && (GET_CODE (op1) == SIGN_EXTEND
6131 		      || shift_p (op1, ASHIFTRT, 16))))
6132 	    {
6133 	      *total = COSTS_N_INSNS (speed ? 2 : 1);
6134 	      op0 = XEXP (op0, 0);
6135 	      if (scst5_operand (op1, SImode))
6136 		op1 = NULL_RTX;
6137 	      else
6138 		op1 = XEXP (op1, 0);
6139 	    }
6140 	  else if (!speed)
6141 	    *total = COSTS_N_INSNS (1);
6142 	  else if (TARGET_MPY32)
6143 	    *total = COSTS_N_INSNS (4);
6144 	  else
6145 	    *total = COSTS_N_INSNS (6);
6146 	}
6147       else if (mode == HImode)
6148 	*total = COSTS_N_INSNS (speed ? 2 : 1);
6149 
6150       if (GET_CODE (op0) != REG
6151 	  && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
6152 	*total += rtx_cost (op0, mode, MULT, 0, speed);
6153       if (op1 && GET_CODE (op1) != REG
6154 	  && (GET_CODE (op1) != SUBREG || GET_CODE (SUBREG_REG (op1)) != REG))
6155 	*total += rtx_cost (op1, mode, MULT, 1, speed);
6156       return true;
6157 
6158     case UDIV:
6159     case DIV:
6160       /* This is a bit random; assuming on average there'll be 16 leading
6161 	 zeros.  FIXME: estimate better for constant dividends.  */
6162       *total = COSTS_N_INSNS (6 + 3 * 16);
6163       return false;
6164 
6165     case IF_THEN_ELSE:
6166       /* Recognize the cmp_and/ior patterns.  */
6167       op0 = XEXP (x, 0);
6168       if ((GET_CODE (op0) == EQ || GET_CODE (op0) == NE)
6169 	  && REG_P (XEXP (op0, 0))
6170 	  && XEXP (op0, 1) == const0_rtx
6171 	  && rtx_equal_p (XEXP (x, 1), XEXP (op0, 0)))
6172 	{
6173 	  *total = rtx_cost (XEXP (x, 1), VOIDmode, (enum rtx_code) outer_code,
6174 			     opno, speed);
6175 	  return false;
6176 	}
6177       return false;
6178 
6179     default:
6180       return false;
6181     }
6182 }
6183 
6184 /* Implements target hook vector_mode_supported_p.  */
6185 
6186 static bool
c6x_vector_mode_supported_p(machine_mode mode)6187 c6x_vector_mode_supported_p (machine_mode mode)
6188 {
6189   switch (mode)
6190     {
6191     case E_V2HImode:
6192     case E_V4QImode:
6193     case E_V2SImode:
6194     case E_V4HImode:
6195     case E_V8QImode:
6196       return true;
6197     default:
6198       return false;
6199     }
6200 }
6201 
6202 /* Implements TARGET_VECTORIZE_PREFERRED_SIMD_MODE.  */
6203 static machine_mode
c6x_preferred_simd_mode(scalar_mode mode)6204 c6x_preferred_simd_mode (scalar_mode mode)
6205 {
6206   switch (mode)
6207     {
6208     case E_HImode:
6209       return V2HImode;
6210     case E_QImode:
6211       return V4QImode;
6212 
6213     default:
6214       return word_mode;
6215     }
6216 }
6217 
6218 /* Implement TARGET_SCALAR_MODE_SUPPORTED_P.  */
6219 
6220 static bool
c6x_scalar_mode_supported_p(scalar_mode mode)6221 c6x_scalar_mode_supported_p (scalar_mode mode)
6222 {
6223   if (ALL_FIXED_POINT_MODE_P (mode)
6224       && GET_MODE_PRECISION (mode) <= 2 * BITS_PER_WORD)
6225     return true;
6226 
6227   return default_scalar_mode_supported_p (mode);
6228 }
6229 
6230 /* Output a reference from a function exception table to the type_info
6231    object X.  Output these via a special assembly directive.  */
6232 
6233 static bool
c6x_output_ttype(rtx x)6234 c6x_output_ttype (rtx x)
6235 {
6236   /* Use special relocations for symbol references.  */
6237   if (GET_CODE (x) != CONST_INT)
6238     fputs ("\t.ehtype\t", asm_out_file);
6239   else
6240     fputs ("\t.word\t", asm_out_file);
6241   output_addr_const (asm_out_file, x);
6242   fputc ('\n', asm_out_file);
6243 
6244   return TRUE;
6245 }
6246 
6247 /* Modify the return address of the current function.  */
6248 
6249 void
c6x_set_return_address(rtx source,rtx scratch)6250 c6x_set_return_address (rtx source, rtx scratch)
6251 {
6252   struct c6x_frame frame;
6253   rtx addr;
6254   HOST_WIDE_INT offset;
6255 
6256   c6x_compute_frame_layout (&frame);
6257   if (! c6x_save_reg (RETURN_ADDR_REGNO))
6258     emit_move_insn (gen_rtx_REG (Pmode, RETURN_ADDR_REGNO), source);
6259   else
6260     {
6261 
6262       if (frame_pointer_needed)
6263 	{
6264 	  addr = hard_frame_pointer_rtx;
6265 	  offset = frame.b3_offset;
6266 	}
6267       else
6268 	{
6269 	  addr = stack_pointer_rtx;
6270 	  offset = frame.to_allocate - frame.b3_offset;
6271 	}
6272 
6273       /* TODO: Use base+offset loads where possible.  */
6274       if (offset)
6275 	{
6276 	  HOST_WIDE_INT low = trunc_int_for_mode (offset, HImode);
6277 
6278 	  emit_insn (gen_movsi_high (scratch, GEN_INT (low)));
6279 	  if (low != offset)
6280 	    emit_insn (gen_movsi_lo_sum (scratch, scratch, GEN_INT(offset)));
6281 	  emit_insn (gen_addsi3 (scratch, addr, scratch));
6282 	  addr = scratch;
6283 	}
6284 
6285       emit_move_insn (gen_frame_mem (Pmode, addr), source);
6286     }
6287 }
6288 
6289 /* We save pairs of registers using a DImode store.  Describe the component
6290    registers for DWARF generation code.  */
6291 
6292 static rtx
c6x_dwarf_register_span(rtx rtl)6293 c6x_dwarf_register_span (rtx rtl)
6294 {
6295     unsigned regno;
6296     unsigned real_regno;
6297     int nregs;
6298     int i;
6299     rtx p;
6300 
6301     regno = REGNO (rtl);
6302     nregs = REG_NREGS (rtl);
6303     if (nregs == 1)
6304       return  NULL_RTX;
6305 
6306     p = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc(nregs));
6307     for (i = 0; i < nregs; i++)
6308       {
6309 	if (TARGET_BIG_ENDIAN)
6310 	  real_regno = regno + nregs - (i + 1);
6311 	else
6312 	  real_regno = regno + i;
6313 
6314 	XVECEXP (p, 0, i) = gen_rtx_REG (SImode, real_regno);
6315       }
6316 
6317     return p;
6318 }
6319 
6320 /* Codes for all the C6X builtins.  */
6321 enum c6x_builtins
6322 {
6323   C6X_BUILTIN_SADD,
6324   C6X_BUILTIN_SSUB,
6325   C6X_BUILTIN_ADD2,
6326   C6X_BUILTIN_SUB2,
6327   C6X_BUILTIN_ADD4,
6328   C6X_BUILTIN_SUB4,
6329   C6X_BUILTIN_SADD2,
6330   C6X_BUILTIN_SSUB2,
6331   C6X_BUILTIN_SADDU4,
6332 
6333   C6X_BUILTIN_SMPY,
6334   C6X_BUILTIN_SMPYH,
6335   C6X_BUILTIN_SMPYHL,
6336   C6X_BUILTIN_SMPYLH,
6337   C6X_BUILTIN_MPY2,
6338   C6X_BUILTIN_SMPY2,
6339 
6340   C6X_BUILTIN_CLRR,
6341   C6X_BUILTIN_EXTR,
6342   C6X_BUILTIN_EXTRU,
6343 
6344   C6X_BUILTIN_SSHL,
6345   C6X_BUILTIN_SUBC,
6346   C6X_BUILTIN_ABS,
6347   C6X_BUILTIN_ABS2,
6348   C6X_BUILTIN_AVG2,
6349   C6X_BUILTIN_AVGU4,
6350 
6351   C6X_BUILTIN_MAX
6352 };
6353 
6354 
6355 static GTY(()) tree c6x_builtin_decls[C6X_BUILTIN_MAX];
6356 
6357 /* Return the C6X builtin for CODE.  */
6358 static tree
c6x_builtin_decl(unsigned code,bool initialize_p ATTRIBUTE_UNUSED)6359 c6x_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
6360 {
6361   if (code >= C6X_BUILTIN_MAX)
6362     return error_mark_node;
6363 
6364   return c6x_builtin_decls[code];
6365 }
6366 
6367 #define def_builtin(NAME, TYPE, CODE)					\
6368 do {									\
6369   tree bdecl;								\
6370   bdecl = add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD,	\
6371 				NULL, NULL_TREE);			\
6372   c6x_builtin_decls[CODE] = bdecl;					\
6373 } while (0)
6374 
6375 /* Set up all builtin functions for this target.  */
6376 static void
c6x_init_builtins(void)6377 c6x_init_builtins (void)
6378 {
6379   tree V4QI_type_node = build_vector_type (unsigned_intQI_type_node, 4);
6380   tree V2HI_type_node = build_vector_type (intHI_type_node, 2);
6381   tree V2SI_type_node = build_vector_type (intSI_type_node, 2);
6382   tree int_ftype_int
6383     = build_function_type_list (integer_type_node, integer_type_node,
6384 				NULL_TREE);
6385   tree int_ftype_int_int
6386     = build_function_type_list (integer_type_node, integer_type_node,
6387 				integer_type_node, NULL_TREE);
6388   tree v2hi_ftype_v2hi
6389     = build_function_type_list (V2HI_type_node, V2HI_type_node, NULL_TREE);
6390   tree v4qi_ftype_v4qi_v4qi
6391     = build_function_type_list (V4QI_type_node, V4QI_type_node,
6392 				V4QI_type_node, NULL_TREE);
6393   tree v2hi_ftype_v2hi_v2hi
6394     = build_function_type_list (V2HI_type_node, V2HI_type_node,
6395 				V2HI_type_node, NULL_TREE);
6396   tree v2si_ftype_v2hi_v2hi
6397     = build_function_type_list (V2SI_type_node, V2HI_type_node,
6398 				V2HI_type_node, NULL_TREE);
6399 
6400   def_builtin ("__builtin_c6x_sadd", int_ftype_int_int,
6401 	       C6X_BUILTIN_SADD);
6402   def_builtin ("__builtin_c6x_ssub", int_ftype_int_int,
6403 	       C6X_BUILTIN_SSUB);
6404   def_builtin ("__builtin_c6x_add2", v2hi_ftype_v2hi_v2hi,
6405 	       C6X_BUILTIN_ADD2);
6406   def_builtin ("__builtin_c6x_sub2", v2hi_ftype_v2hi_v2hi,
6407 	       C6X_BUILTIN_SUB2);
6408   def_builtin ("__builtin_c6x_add4", v4qi_ftype_v4qi_v4qi,
6409 	       C6X_BUILTIN_ADD4);
6410   def_builtin ("__builtin_c6x_sub4", v4qi_ftype_v4qi_v4qi,
6411 	       C6X_BUILTIN_SUB4);
6412   def_builtin ("__builtin_c6x_mpy2", v2si_ftype_v2hi_v2hi,
6413 	       C6X_BUILTIN_MPY2);
6414   def_builtin ("__builtin_c6x_sadd2", v2hi_ftype_v2hi_v2hi,
6415 	       C6X_BUILTIN_SADD2);
6416   def_builtin ("__builtin_c6x_ssub2", v2hi_ftype_v2hi_v2hi,
6417 	       C6X_BUILTIN_SSUB2);
6418   def_builtin ("__builtin_c6x_saddu4", v4qi_ftype_v4qi_v4qi,
6419 	       C6X_BUILTIN_SADDU4);
6420   def_builtin ("__builtin_c6x_smpy2", v2si_ftype_v2hi_v2hi,
6421 	       C6X_BUILTIN_SMPY2);
6422 
6423   def_builtin ("__builtin_c6x_smpy", int_ftype_int_int,
6424 	       C6X_BUILTIN_SMPY);
6425   def_builtin ("__builtin_c6x_smpyh", int_ftype_int_int,
6426 	       C6X_BUILTIN_SMPYH);
6427   def_builtin ("__builtin_c6x_smpyhl", int_ftype_int_int,
6428 	       C6X_BUILTIN_SMPYHL);
6429   def_builtin ("__builtin_c6x_smpylh", int_ftype_int_int,
6430 	       C6X_BUILTIN_SMPYLH);
6431 
6432   def_builtin ("__builtin_c6x_sshl", int_ftype_int_int,
6433 	       C6X_BUILTIN_SSHL);
6434   def_builtin ("__builtin_c6x_subc", int_ftype_int_int,
6435 	       C6X_BUILTIN_SUBC);
6436 
6437   def_builtin ("__builtin_c6x_avg2", v2hi_ftype_v2hi_v2hi,
6438 	       C6X_BUILTIN_AVG2);
6439   def_builtin ("__builtin_c6x_avgu4", v4qi_ftype_v4qi_v4qi,
6440 	       C6X_BUILTIN_AVGU4);
6441 
6442   def_builtin ("__builtin_c6x_clrr", int_ftype_int_int,
6443 	       C6X_BUILTIN_CLRR);
6444   def_builtin ("__builtin_c6x_extr", int_ftype_int_int,
6445 	       C6X_BUILTIN_EXTR);
6446   def_builtin ("__builtin_c6x_extru", int_ftype_int_int,
6447 	       C6X_BUILTIN_EXTRU);
6448 
6449   def_builtin ("__builtin_c6x_abs", int_ftype_int, C6X_BUILTIN_ABS);
6450   def_builtin ("__builtin_c6x_abs2", v2hi_ftype_v2hi, C6X_BUILTIN_ABS2);
6451 }
6452 
6453 
6454 struct builtin_description
6455 {
6456   const enum insn_code icode;
6457   const char *const name;
6458   const enum c6x_builtins code;
6459 };
6460 
6461 static const struct builtin_description bdesc_2arg[] =
6462 {
6463   { CODE_FOR_saddsi3, "__builtin_c6x_sadd", C6X_BUILTIN_SADD },
6464   { CODE_FOR_ssubsi3, "__builtin_c6x_ssub", C6X_BUILTIN_SSUB },
6465   { CODE_FOR_addv2hi3, "__builtin_c6x_add2", C6X_BUILTIN_ADD2 },
6466   { CODE_FOR_subv2hi3, "__builtin_c6x_sub2", C6X_BUILTIN_SUB2 },
6467   { CODE_FOR_addv4qi3, "__builtin_c6x_add4", C6X_BUILTIN_ADD4 },
6468   { CODE_FOR_subv4qi3, "__builtin_c6x_sub4", C6X_BUILTIN_SUB4 },
6469   { CODE_FOR_ss_addv2hi3, "__builtin_c6x_sadd2", C6X_BUILTIN_SADD2 },
6470   { CODE_FOR_ss_subv2hi3, "__builtin_c6x_ssub2", C6X_BUILTIN_SSUB2 },
6471   { CODE_FOR_us_addv4qi3, "__builtin_c6x_saddu4", C6X_BUILTIN_SADDU4 },
6472 
6473   { CODE_FOR_subcsi3, "__builtin_c6x_subc", C6X_BUILTIN_SUBC },
6474   { CODE_FOR_ss_ashlsi3, "__builtin_c6x_sshl", C6X_BUILTIN_SSHL },
6475 
6476   { CODE_FOR_avgv2hi3, "__builtin_c6x_avg2", C6X_BUILTIN_AVG2 },
6477   { CODE_FOR_uavgv4qi3, "__builtin_c6x_avgu4", C6X_BUILTIN_AVGU4 },
6478 
6479   { CODE_FOR_mulhqsq3, "__builtin_c6x_smpy", C6X_BUILTIN_SMPY },
6480   { CODE_FOR_mulhqsq3_hh, "__builtin_c6x_smpyh", C6X_BUILTIN_SMPYH },
6481   { CODE_FOR_mulhqsq3_lh, "__builtin_c6x_smpylh", C6X_BUILTIN_SMPYLH },
6482   { CODE_FOR_mulhqsq3_hl, "__builtin_c6x_smpyhl", C6X_BUILTIN_SMPYHL },
6483 
6484   { CODE_FOR_mulv2hqv2sq3, "__builtin_c6x_smpy2", C6X_BUILTIN_SMPY2 },
6485 
6486   { CODE_FOR_clrr, "__builtin_c6x_clrr", C6X_BUILTIN_CLRR },
6487   { CODE_FOR_extr, "__builtin_c6x_extr", C6X_BUILTIN_EXTR },
6488   { CODE_FOR_extru, "__builtin_c6x_extru", C6X_BUILTIN_EXTRU }
6489 };
6490 
6491 static const struct builtin_description bdesc_1arg[] =
6492 {
6493   { CODE_FOR_ssabssi2, "__builtin_c6x_abs", C6X_BUILTIN_ABS },
6494   { CODE_FOR_ssabsv2hi2, "__builtin_c6x_abs2", C6X_BUILTIN_ABS2 }
6495 };
6496 
6497 /* Errors in the source file can cause expand_expr to return const0_rtx
6498    where we expect a vector.  To avoid crashing, use one of the vector
6499    clear instructions.  */
6500 static rtx
safe_vector_operand(rtx x,machine_mode mode)6501 safe_vector_operand (rtx x, machine_mode mode)
6502 {
6503   if (x != const0_rtx)
6504     return x;
6505   x = gen_reg_rtx (SImode);
6506 
6507   emit_insn (gen_movsi (x, CONST0_RTX (SImode)));
6508   return gen_lowpart (mode, x);
6509 }
6510 
6511 /* Subroutine of c6x_expand_builtin to take care of binop insns.  MACFLAG is -1
6512    if this is a normal binary op, or one of the MACFLAG_xxx constants.  */
6513 
6514 static rtx
c6x_expand_binop_builtin(enum insn_code icode,tree exp,rtx target,bool match_op)6515 c6x_expand_binop_builtin (enum insn_code icode, tree exp, rtx target,
6516 			  bool match_op)
6517 {
6518   int offs = match_op ? 1 : 0;
6519   rtx pat;
6520   tree arg0 = CALL_EXPR_ARG (exp, 0);
6521   tree arg1 = CALL_EXPR_ARG (exp, 1);
6522   rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
6523   rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, EXPAND_NORMAL);
6524   machine_mode op0mode = GET_MODE (op0);
6525   machine_mode op1mode = GET_MODE (op1);
6526   machine_mode tmode = insn_data[icode].operand[0].mode;
6527   machine_mode mode0 = insn_data[icode].operand[1 + offs].mode;
6528   machine_mode mode1 = insn_data[icode].operand[2 + offs].mode;
6529   rtx ret = target;
6530 
6531   if (VECTOR_MODE_P (mode0))
6532     op0 = safe_vector_operand (op0, mode0);
6533   if (VECTOR_MODE_P (mode1))
6534     op1 = safe_vector_operand (op1, mode1);
6535 
6536   if (! target
6537       || GET_MODE (target) != tmode
6538       || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
6539     {
6540       if (tmode == SQmode || tmode == V2SQmode)
6541 	{
6542 	  ret = gen_reg_rtx (tmode == SQmode ? SImode : V2SImode);
6543 	  target = gen_lowpart (tmode, ret);
6544 	}
6545       else
6546 	target = gen_reg_rtx (tmode);
6547     }
6548 
6549   if ((op0mode == V2HImode || op0mode == SImode || op0mode == VOIDmode)
6550       && (mode0 == V2HQmode || mode0 == HQmode || mode0 == SQmode))
6551     {
6552       op0mode = mode0;
6553       op0 = gen_lowpart (mode0, op0);
6554     }
6555   if ((op1mode == V2HImode || op1mode == SImode || op1mode == VOIDmode)
6556       && (mode1 == V2HQmode || mode1 == HQmode || mode1 == SQmode))
6557     {
6558       op1mode = mode1;
6559       op1 = gen_lowpart (mode1, op1);
6560     }
6561   /* In case the insn wants input operands in modes different from
6562      the result, abort.  */
6563   gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
6564 	      && (op1mode == mode1 || op1mode == VOIDmode));
6565 
6566   if (! (*insn_data[icode].operand[1 + offs].predicate) (op0, mode0))
6567     op0 = copy_to_mode_reg (mode0, op0);
6568   if (! (*insn_data[icode].operand[2 + offs].predicate) (op1, mode1))
6569     op1 = copy_to_mode_reg (mode1, op1);
6570 
6571   if (match_op)
6572     pat = GEN_FCN (icode) (target, target, op0, op1);
6573   else
6574     pat = GEN_FCN (icode) (target, op0, op1);
6575 
6576   if (! pat)
6577     return 0;
6578 
6579   emit_insn (pat);
6580 
6581   return ret;
6582 }
6583 
6584 /* Subroutine of c6x_expand_builtin to take care of unop insns.  */
6585 
6586 static rtx
c6x_expand_unop_builtin(enum insn_code icode,tree exp,rtx target)6587 c6x_expand_unop_builtin (enum insn_code icode, tree exp,
6588 			  rtx target)
6589 {
6590   rtx pat;
6591   tree arg0 = CALL_EXPR_ARG (exp, 0);
6592   rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
6593   machine_mode op0mode = GET_MODE (op0);
6594   machine_mode tmode = insn_data[icode].operand[0].mode;
6595   machine_mode mode0 = insn_data[icode].operand[1].mode;
6596 
6597   if (! target
6598       || GET_MODE (target) != tmode
6599       || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
6600     target = gen_reg_rtx (tmode);
6601 
6602   if (VECTOR_MODE_P (mode0))
6603     op0 = safe_vector_operand (op0, mode0);
6604 
6605   if (op0mode == SImode && mode0 == HImode)
6606     {
6607       op0mode = HImode;
6608       op0 = gen_lowpart (HImode, op0);
6609     }
6610   gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
6611 
6612   if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6613     op0 = copy_to_mode_reg (mode0, op0);
6614 
6615   pat = GEN_FCN (icode) (target, op0);
6616   if (! pat)
6617     return 0;
6618   emit_insn (pat);
6619   return target;
6620 }
6621 
6622 /* Expand an expression EXP that calls a built-in function,
6623    with result going to TARGET if that's convenient
6624    (and in mode MODE if that's convenient).
6625    SUBTARGET may be used as the target for computing one of EXP's operands.
6626    IGNORE is nonzero if the value is to be ignored.  */
6627 
6628 static rtx
c6x_expand_builtin(tree exp,rtx target ATTRIBUTE_UNUSED,rtx subtarget ATTRIBUTE_UNUSED,machine_mode mode ATTRIBUTE_UNUSED,int ignore ATTRIBUTE_UNUSED)6629 c6x_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
6630 		     rtx subtarget ATTRIBUTE_UNUSED,
6631 		     machine_mode mode ATTRIBUTE_UNUSED,
6632 		     int ignore ATTRIBUTE_UNUSED)
6633 {
6634   size_t i;
6635   const struct builtin_description *d;
6636   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
6637   unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
6638 
6639   for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
6640     if (d->code == fcode)
6641       return c6x_expand_binop_builtin (d->icode, exp, target,
6642 				       fcode == C6X_BUILTIN_CLRR);
6643 
6644   for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
6645     if (d->code == fcode)
6646       return c6x_expand_unop_builtin (d->icode, exp, target);
6647 
6648   gcc_unreachable ();
6649 }
6650 
6651 /* Target unwind frame info is generated from dwarf CFI directives, so
6652    always output dwarf2 unwind info.  */
6653 
6654 static enum unwind_info_type
c6x_debug_unwind_info(void)6655 c6x_debug_unwind_info (void)
6656 {
6657   if (flag_unwind_tables || flag_exceptions)
6658     return UI_DWARF2;
6659 
6660   return default_debug_unwind_info ();
6661 }
6662 
6663 /* Implement TARGET_HARD_REGNO_MODE_OK.  */
6664 
6665 static bool
c6x_hard_regno_mode_ok(unsigned int regno,machine_mode mode)6666 c6x_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
6667 {
6668   return GET_MODE_SIZE (mode) <= UNITS_PER_WORD || (regno & 1) == 0;
6669 }
6670 
6671 /* Implement TARGET_MODES_TIEABLE_P.  */
6672 
6673 static bool
c6x_modes_tieable_p(machine_mode mode1,machine_mode mode2)6674 c6x_modes_tieable_p (machine_mode mode1, machine_mode mode2)
6675 {
6676   return (mode1 == mode2
6677 	  || (GET_MODE_SIZE (mode1) <= UNITS_PER_WORD
6678 	      && GET_MODE_SIZE (mode2) <= UNITS_PER_WORD));
6679 }
6680 
6681 /* Implement REGNO_REG_CLASS.  */
6682 
6683 enum reg_class
c6x_regno_reg_class(int reg)6684 c6x_regno_reg_class (int reg)
6685 {
6686   if (reg >= REG_A1 && reg <= REG_A2)
6687     return PREDICATE_A_REGS;
6688 
6689   if (reg == REG_A0 && TARGET_INSNS_64)
6690     return PREDICATE_A_REGS;
6691 
6692   if (reg >= REG_B0 && reg <= REG_B2)
6693     return PREDICATE_B_REGS;
6694 
6695   if (A_REGNO_P (reg))
6696     return NONPREDICATE_A_REGS;
6697 
6698   if (call_used_or_fixed_reg_p (reg))
6699     return CALL_USED_B_REGS;
6700 
6701   return B_REGS;
6702 }
6703 
6704 /* Target Structure.  */
6705 
6706 /* Initialize the GCC target structure.  */
6707 #undef TARGET_FUNCTION_ARG
6708 #define TARGET_FUNCTION_ARG c6x_function_arg
6709 #undef TARGET_FUNCTION_ARG_ADVANCE
6710 #define TARGET_FUNCTION_ARG_ADVANCE c6x_function_arg_advance
6711 #undef TARGET_FUNCTION_ARG_BOUNDARY
6712 #define TARGET_FUNCTION_ARG_BOUNDARY c6x_function_arg_boundary
6713 #undef TARGET_FUNCTION_ARG_ROUND_BOUNDARY
6714 #define TARGET_FUNCTION_ARG_ROUND_BOUNDARY \
6715   c6x_function_arg_round_boundary
6716 #undef TARGET_FUNCTION_VALUE_REGNO_P
6717 #define TARGET_FUNCTION_VALUE_REGNO_P c6x_function_value_regno_p
6718 #undef TARGET_FUNCTION_VALUE
6719 #define TARGET_FUNCTION_VALUE c6x_function_value
6720 #undef TARGET_LIBCALL_VALUE
6721 #define TARGET_LIBCALL_VALUE c6x_libcall_value
6722 #undef TARGET_RETURN_IN_MEMORY
6723 #define TARGET_RETURN_IN_MEMORY c6x_return_in_memory
6724 #undef TARGET_RETURN_IN_MSB
6725 #define TARGET_RETURN_IN_MSB c6x_return_in_msb
6726 #undef TARGET_PASS_BY_REFERENCE
6727 #define TARGET_PASS_BY_REFERENCE c6x_pass_by_reference
6728 #undef TARGET_CALLEE_COPIES
6729 #define TARGET_CALLEE_COPIES hook_bool_CUMULATIVE_ARGS_arg_info_true
6730 #undef TARGET_STRUCT_VALUE_RTX
6731 #define TARGET_STRUCT_VALUE_RTX c6x_struct_value_rtx
6732 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
6733 #define TARGET_FUNCTION_OK_FOR_SIBCALL c6x_function_ok_for_sibcall
6734 
6735 #undef TARGET_ASM_OUTPUT_MI_THUNK
6736 #define TARGET_ASM_OUTPUT_MI_THUNK c6x_output_mi_thunk
6737 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
6738 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK c6x_can_output_mi_thunk
6739 
6740 #undef TARGET_BUILD_BUILTIN_VA_LIST
6741 #define TARGET_BUILD_BUILTIN_VA_LIST c6x_build_builtin_va_list
6742 
6743 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
6744 #define TARGET_ASM_TRAMPOLINE_TEMPLATE c6x_asm_trampoline_template
6745 #undef TARGET_TRAMPOLINE_INIT
6746 #define TARGET_TRAMPOLINE_INIT c6x_initialize_trampoline
6747 
6748 #undef TARGET_LEGITIMATE_CONSTANT_P
6749 #define TARGET_LEGITIMATE_CONSTANT_P c6x_legitimate_constant_p
6750 #undef TARGET_LEGITIMATE_ADDRESS_P
6751 #define TARGET_LEGITIMATE_ADDRESS_P c6x_legitimate_address_p
6752 
6753 #undef TARGET_LRA_P
6754 #define TARGET_LRA_P hook_bool_void_false
6755 
6756 #undef TARGET_IN_SMALL_DATA_P
6757 #define TARGET_IN_SMALL_DATA_P c6x_in_small_data_p
6758 #undef	TARGET_ASM_SELECT_RTX_SECTION
6759 #define TARGET_ASM_SELECT_RTX_SECTION  c6x_select_rtx_section
6760 #undef TARGET_ASM_SELECT_SECTION
6761 #define TARGET_ASM_SELECT_SECTION  c6x_elf_select_section
6762 #undef TARGET_ASM_UNIQUE_SECTION
6763 #define TARGET_ASM_UNIQUE_SECTION  c6x_elf_unique_section
6764 #undef TARGET_SECTION_TYPE_FLAGS
6765 #define TARGET_SECTION_TYPE_FLAGS  c6x_section_type_flags
6766 #undef TARGET_HAVE_SRODATA_SECTION
6767 #define TARGET_HAVE_SRODATA_SECTION true
6768 #undef TARGET_ASM_MERGEABLE_RODATA_PREFIX
6769 #define TARGET_ASM_MERGEABLE_RODATA_PREFIX ".const"
6770 
6771 #undef TARGET_OPTION_OVERRIDE
6772 #define TARGET_OPTION_OVERRIDE c6x_option_override
6773 #undef TARGET_CONDITIONAL_REGISTER_USAGE
6774 #define TARGET_CONDITIONAL_REGISTER_USAGE c6x_conditional_register_usage
6775 
6776 #undef TARGET_INIT_LIBFUNCS
6777 #define TARGET_INIT_LIBFUNCS c6x_init_libfuncs
6778 #undef TARGET_LIBFUNC_GNU_PREFIX
6779 #define TARGET_LIBFUNC_GNU_PREFIX true
6780 
6781 #undef TARGET_SCALAR_MODE_SUPPORTED_P
6782 #define TARGET_SCALAR_MODE_SUPPORTED_P c6x_scalar_mode_supported_p
6783 #undef TARGET_VECTOR_MODE_SUPPORTED_P
6784 #define TARGET_VECTOR_MODE_SUPPORTED_P c6x_vector_mode_supported_p
6785 #undef TARGET_VECTORIZE_PREFERRED_SIMD_MODE
6786 #define TARGET_VECTORIZE_PREFERRED_SIMD_MODE c6x_preferred_simd_mode
6787 
6788 #undef TARGET_RTX_COSTS
6789 #define TARGET_RTX_COSTS c6x_rtx_costs
6790 
6791 #undef TARGET_SCHED_INIT
6792 #define TARGET_SCHED_INIT c6x_sched_init
6793 #undef TARGET_SCHED_SET_SCHED_FLAGS
6794 #define TARGET_SCHED_SET_SCHED_FLAGS c6x_set_sched_flags
6795 #undef TARGET_SCHED_ADJUST_COST
6796 #define TARGET_SCHED_ADJUST_COST c6x_adjust_cost
6797 #undef TARGET_SCHED_ISSUE_RATE
6798 #define TARGET_SCHED_ISSUE_RATE c6x_issue_rate
6799 #undef TARGET_SCHED_VARIABLE_ISSUE
6800 #define TARGET_SCHED_VARIABLE_ISSUE c6x_variable_issue
6801 #undef TARGET_SCHED_REORDER
6802 #define TARGET_SCHED_REORDER c6x_sched_reorder
6803 #undef TARGET_SCHED_REORDER2
6804 #define TARGET_SCHED_REORDER2 c6x_sched_reorder2
6805 #undef TARGET_SCHED_DFA_NEW_CYCLE
6806 #define TARGET_SCHED_DFA_NEW_CYCLE c6x_dfa_new_cycle
6807 #undef TARGET_SCHED_DFA_PRE_CYCLE_INSN
6808 #define TARGET_SCHED_DFA_PRE_CYCLE_INSN c6x_sched_dfa_pre_cycle_insn
6809 #undef TARGET_SCHED_EXPOSED_PIPELINE
6810 #define TARGET_SCHED_EXPOSED_PIPELINE true
6811 
6812 #undef TARGET_SCHED_ALLOC_SCHED_CONTEXT
6813 #define TARGET_SCHED_ALLOC_SCHED_CONTEXT c6x_alloc_sched_context
6814 #undef TARGET_SCHED_INIT_SCHED_CONTEXT
6815 #define TARGET_SCHED_INIT_SCHED_CONTEXT c6x_init_sched_context
6816 #undef TARGET_SCHED_SET_SCHED_CONTEXT
6817 #define TARGET_SCHED_SET_SCHED_CONTEXT c6x_set_sched_context
6818 #undef TARGET_SCHED_CLEAR_SCHED_CONTEXT
6819 #define TARGET_SCHED_CLEAR_SCHED_CONTEXT c6x_clear_sched_context
6820 #undef TARGET_SCHED_FREE_SCHED_CONTEXT
6821 #define TARGET_SCHED_FREE_SCHED_CONTEXT c6x_free_sched_context
6822 
6823 #undef TARGET_CAN_ELIMINATE
6824 #define TARGET_CAN_ELIMINATE c6x_can_eliminate
6825 
6826 #undef TARGET_PREFERRED_RENAME_CLASS
6827 #define TARGET_PREFERRED_RENAME_CLASS c6x_preferred_rename_class
6828 
6829 #undef TARGET_MACHINE_DEPENDENT_REORG
6830 #define TARGET_MACHINE_DEPENDENT_REORG c6x_reorg
6831 
6832 #undef TARGET_ASM_FILE_START
6833 #define TARGET_ASM_FILE_START c6x_file_start
6834 
6835 #undef  TARGET_PRINT_OPERAND
6836 #define TARGET_PRINT_OPERAND c6x_print_operand
6837 #undef  TARGET_PRINT_OPERAND_ADDRESS
6838 #define TARGET_PRINT_OPERAND_ADDRESS c6x_print_operand_address
6839 #undef  TARGET_PRINT_OPERAND_PUNCT_VALID_P
6840 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P c6x_print_operand_punct_valid_p
6841 
6842 /* C6x unwinding tables use a different format for the typeinfo tables.  */
6843 #undef TARGET_ASM_TTYPE
6844 #define TARGET_ASM_TTYPE c6x_output_ttype
6845 
6846 /* The C6x ABI follows the ARM EABI exception handling rules.  */
6847 #undef TARGET_ARM_EABI_UNWINDER
6848 #define TARGET_ARM_EABI_UNWINDER true
6849 
6850 #undef TARGET_ASM_EMIT_EXCEPT_PERSONALITY
6851 #define TARGET_ASM_EMIT_EXCEPT_PERSONALITY c6x_asm_emit_except_personality
6852 
6853 #undef TARGET_ASM_INIT_SECTIONS
6854 #define TARGET_ASM_INIT_SECTIONS c6x_asm_init_sections
6855 
6856 #undef TARGET_DEBUG_UNWIND_INFO
6857 #define TARGET_DEBUG_UNWIND_INFO  c6x_debug_unwind_info
6858 
6859 #undef TARGET_DWARF_REGISTER_SPAN
6860 #define TARGET_DWARF_REGISTER_SPAN c6x_dwarf_register_span
6861 
6862 #undef TARGET_INIT_BUILTINS
6863 #define TARGET_INIT_BUILTINS c6x_init_builtins
6864 #undef TARGET_EXPAND_BUILTIN
6865 #define TARGET_EXPAND_BUILTIN c6x_expand_builtin
6866 #undef  TARGET_BUILTIN_DECL
6867 #define TARGET_BUILTIN_DECL c6x_builtin_decl
6868 
6869 #undef TARGET_HARD_REGNO_MODE_OK
6870 #define TARGET_HARD_REGNO_MODE_OK c6x_hard_regno_mode_ok
6871 #undef TARGET_MODES_TIEABLE_P
6872 #define TARGET_MODES_TIEABLE_P c6x_modes_tieable_p
6873 
6874 struct gcc_target targetm = TARGET_INITIALIZER;
6875 
6876 #include "gt-c6x.h"
6877