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