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