OSDN Git Service

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