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