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