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