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