2013-11-13 Jan-Benedict Glaw <jbglaw@lug-owl.de>
[official-gcc.git] / gcc / config / c6x / c6x.c
bloba37e02ff8341c79fb592e08d43df0c00f9b09412
1 /* Target Code for TI C6X
2 Copyright (C) 2010-2013 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 "insn-flags.h"
29 #include "output.h"
30 #include "insn-attr.h"
31 #include "insn-codes.h"
32 #include "expr.h"
33 #include "regs.h"
34 #include "optabs.h"
35 #include "recog.h"
36 #include "ggc.h"
37 #include "sched-int.h"
38 #include "timevar.h"
39 #include "tm_p.h"
40 #include "tm-preds.h"
41 #include "tm-constrs.h"
42 #include "df.h"
43 #include "function.h"
44 #include "diagnostic-core.h"
45 #include "cgraph.h"
46 #include "langhooks.h"
47 #include "target.h"
48 #include "target-def.h"
49 #include "sel-sched.h"
50 #include "debug.h"
51 #include "opts.h"
52 #include "hw-doloop.h"
53 #include "regrename.h"
54 #include "dumpfile.h"
55 #include "gimple-expr.h"
57 /* Table of supported architecture variants. */
58 typedef struct
60 const char *arch;
61 enum c6x_cpu_type type;
62 unsigned short features;
63 } c6x_arch_table;
65 /* A list of all ISAs, mapping each one to a representative device.
66 Used for -march selection. */
67 static const c6x_arch_table all_isas[] =
69 #define C6X_ISA(NAME,DEVICE,FLAGS) \
70 { NAME, DEVICE, FLAGS },
71 #include "c6x-isas.def"
72 #undef C6X_ISA
73 { NULL, C6X_CPU_C62X, 0 }
76 /* This is the parsed result of the "-march=" option, if given. */
77 enum c6x_cpu_type c6x_arch = C6X_DEFAULT_ARCH;
79 /* A mask of insn types that are allowed by the architecture selected by
80 the -march option. */
81 unsigned long c6x_insn_mask = C6X_DEFAULT_INSN_MASK;
83 /* The instruction that is being output (as obtained from FINAL_PRESCAN_INSN).
85 static rtx c6x_current_insn = NULL_RTX;
87 /* A decl we build to access __c6xabi_DSBT_base. */
88 static GTY(()) tree dsbt_decl;
90 /* Determines whether we run our final scheduling pass or not. We always
91 avoid the normal second scheduling pass. */
92 static int c6x_flag_schedule_insns2;
94 /* Determines whether we run variable tracking in machine dependent
95 reorganization. */
96 static int c6x_flag_var_tracking;
98 /* Determines whether we use modulo scheduling. */
99 static int c6x_flag_modulo_sched;
101 /* Record the state of flag_pic before we set it to 1 for DSBT. */
102 int c6x_initial_flag_pic;
104 typedef struct
106 /* We record the clock cycle for every insn during scheduling. */
107 int clock;
108 /* After scheduling, we run assign_reservations to choose unit
109 reservations for all insns. These are recorded here. */
110 int reservation;
111 /* Records the new condition for insns which must be made
112 conditional after scheduling. An entry of NULL_RTX means no such
113 change is necessary. */
114 rtx new_cond;
115 /* True for the first insn that was scheduled in an ebb. */
116 bool ebb_start;
117 /* The scheduler state after the insn, transformed into a mask of UNIT_QID
118 bits rather than storing the state. Meaningful only for the last
119 insn in a cycle. */
120 unsigned int unit_mask;
121 } c6x_sched_insn_info;
124 /* Record a c6x_sched_insn_info structure for every insn in the function. */
125 static vec<c6x_sched_insn_info> insn_info;
127 #define INSN_INFO_LENGTH (insn_info).length ()
128 #define INSN_INFO_ENTRY(N) (insn_info[(N)])
130 static bool done_cfi_sections;
132 #define RESERVATION_FLAG_D 1
133 #define RESERVATION_FLAG_L 2
134 #define RESERVATION_FLAG_S 4
135 #define RESERVATION_FLAG_M 8
136 #define RESERVATION_FLAG_DL (RESERVATION_FLAG_D | RESERVATION_FLAG_L)
137 #define RESERVATION_FLAG_DS (RESERVATION_FLAG_D | RESERVATION_FLAG_S)
138 #define RESERVATION_FLAG_LS (RESERVATION_FLAG_L | RESERVATION_FLAG_S)
139 #define RESERVATION_FLAG_DLS (RESERVATION_FLAG_D | RESERVATION_FLAG_LS)
141 /* The DFA names of the units. */
142 static const char *const c6x_unit_names[] =
144 "d1", "l1", "s1", "m1", "fps1", "fpl1", "adddps1", "adddpl1",
145 "d2", "l2", "s2", "m2", "fps2", "fpl2", "adddps2", "adddpl2"
148 /* The DFA unit number for each unit in c6x_unit_names[]. */
149 static int c6x_unit_codes[ARRAY_SIZE (c6x_unit_names)];
151 /* Unit query IDs. */
152 #define UNIT_QID_D1 0
153 #define UNIT_QID_L1 1
154 #define UNIT_QID_S1 2
155 #define UNIT_QID_M1 3
156 #define UNIT_QID_FPS1 4
157 #define UNIT_QID_FPL1 5
158 #define UNIT_QID_ADDDPS1 6
159 #define UNIT_QID_ADDDPL1 7
160 #define UNIT_QID_SIDE_OFFSET 8
162 #define RESERVATION_S1 2
163 #define RESERVATION_S2 10
165 /* An enum for the unit requirements we count in the UNIT_REQS table. */
166 enum unitreqs
168 UNIT_REQ_D,
169 UNIT_REQ_L,
170 UNIT_REQ_S,
171 UNIT_REQ_M,
172 UNIT_REQ_DL,
173 UNIT_REQ_DS,
174 UNIT_REQ_LS,
175 UNIT_REQ_DLS,
176 UNIT_REQ_T,
177 UNIT_REQ_X,
178 UNIT_REQ_MAX
181 /* A table used to count unit requirements. Used when computing minimum
182 iteration intervals. */
183 typedef int unit_req_table[2][UNIT_REQ_MAX];
184 static unit_req_table unit_reqs;
186 /* Register map for debugging. */
187 unsigned const dbx_register_map[FIRST_PSEUDO_REGISTER] =
189 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, /* A0 - A15. */
190 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, /* A16 - A32. */
191 50, 51, 52,
192 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, /* B0 - B15. */
193 29, 30, 31,
194 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, /* B16 - B32. */
195 66, 67, 68,
196 -1, -1, -1 /* FP, ARGP, ILC. */
199 /* Allocate a new, cleared machine_function structure. */
201 static struct machine_function *
202 c6x_init_machine_status (void)
204 return ggc_alloc_cleared_machine_function ();
207 /* Implement TARGET_OPTION_OVERRIDE. */
209 static void
210 c6x_option_override (void)
212 unsigned i;
214 if (global_options_set.x_c6x_arch_option)
216 c6x_arch = all_isas[c6x_arch_option].type;
217 c6x_insn_mask &= ~C6X_INSNS_ALL_CPU_BITS;
218 c6x_insn_mask |= all_isas[c6x_arch_option].features;
221 c6x_flag_schedule_insns2 = flag_schedule_insns_after_reload;
222 flag_schedule_insns_after_reload = 0;
224 c6x_flag_modulo_sched = flag_modulo_sched;
225 flag_modulo_sched = 0;
227 init_machine_status = c6x_init_machine_status;
229 for (i = 0; i < ARRAY_SIZE (c6x_unit_names); i++)
230 c6x_unit_codes[i] = get_cpu_unit_code (c6x_unit_names[i]);
232 if (flag_pic && !TARGET_DSBT)
234 error ("-fpic and -fPIC not supported without -mdsbt on this target");
235 flag_pic = 0;
237 c6x_initial_flag_pic = flag_pic;
238 if (TARGET_DSBT && !flag_pic)
239 flag_pic = 1;
243 /* Implement the TARGET_CONDITIONAL_REGISTER_USAGE hook. */
245 static void
246 c6x_conditional_register_usage (void)
248 int i;
249 if (c6x_arch == C6X_CPU_C62X || c6x_arch == C6X_CPU_C67X)
250 for (i = 16; i < 32; i++)
252 fixed_regs[i] = 1;
253 fixed_regs[32 + i] = 1;
255 if (TARGET_INSNS_64)
257 SET_HARD_REG_BIT (reg_class_contents[(int)PREDICATE_A_REGS],
258 REG_A0);
259 SET_HARD_REG_BIT (reg_class_contents[(int)PREDICATE_REGS],
260 REG_A0);
261 CLEAR_HARD_REG_BIT (reg_class_contents[(int)NONPREDICATE_A_REGS],
262 REG_A0);
263 CLEAR_HARD_REG_BIT (reg_class_contents[(int)NONPREDICATE_REGS],
264 REG_A0);
268 static GTY(()) rtx eqdf_libfunc;
269 static GTY(()) rtx nedf_libfunc;
270 static GTY(()) rtx ledf_libfunc;
271 static GTY(()) rtx ltdf_libfunc;
272 static GTY(()) rtx gedf_libfunc;
273 static GTY(()) rtx gtdf_libfunc;
274 static GTY(()) rtx eqsf_libfunc;
275 static GTY(()) rtx nesf_libfunc;
276 static GTY(()) rtx lesf_libfunc;
277 static GTY(()) rtx ltsf_libfunc;
278 static GTY(()) rtx gesf_libfunc;
279 static GTY(()) rtx gtsf_libfunc;
280 static GTY(()) rtx strasgi_libfunc;
281 static GTY(()) rtx strasgi64p_libfunc;
283 /* Implement the TARGET_INIT_LIBFUNCS macro. We use this to rename library
284 functions to match the C6x ABI. */
286 static void
287 c6x_init_libfuncs (void)
289 /* Double-precision floating-point arithmetic. */
290 set_optab_libfunc (add_optab, DFmode, "__c6xabi_addd");
291 set_optab_libfunc (sdiv_optab, DFmode, "__c6xabi_divd");
292 set_optab_libfunc (smul_optab, DFmode, "__c6xabi_mpyd");
293 set_optab_libfunc (neg_optab, DFmode, "__c6xabi_negd");
294 set_optab_libfunc (sub_optab, DFmode, "__c6xabi_subd");
296 /* Single-precision floating-point arithmetic. */
297 set_optab_libfunc (add_optab, SFmode, "__c6xabi_addf");
298 set_optab_libfunc (sdiv_optab, SFmode, "__c6xabi_divf");
299 set_optab_libfunc (smul_optab, SFmode, "__c6xabi_mpyf");
300 set_optab_libfunc (neg_optab, SFmode, "__c6xabi_negf");
301 set_optab_libfunc (sub_optab, SFmode, "__c6xabi_subf");
303 /* Floating-point comparisons. */
304 eqsf_libfunc = init_one_libfunc ("__c6xabi_eqf");
305 nesf_libfunc = init_one_libfunc ("__c6xabi_neqf");
306 lesf_libfunc = init_one_libfunc ("__c6xabi_lef");
307 ltsf_libfunc = init_one_libfunc ("__c6xabi_ltf");
308 gesf_libfunc = init_one_libfunc ("__c6xabi_gef");
309 gtsf_libfunc = init_one_libfunc ("__c6xabi_gtf");
310 eqdf_libfunc = init_one_libfunc ("__c6xabi_eqd");
311 nedf_libfunc = init_one_libfunc ("__c6xabi_neqd");
312 ledf_libfunc = init_one_libfunc ("__c6xabi_led");
313 ltdf_libfunc = init_one_libfunc ("__c6xabi_ltd");
314 gedf_libfunc = init_one_libfunc ("__c6xabi_ged");
315 gtdf_libfunc = init_one_libfunc ("__c6xabi_gtd");
317 set_optab_libfunc (eq_optab, SFmode, NULL);
318 set_optab_libfunc (ne_optab, SFmode, "__c6xabi_neqf");
319 set_optab_libfunc (gt_optab, SFmode, NULL);
320 set_optab_libfunc (ge_optab, SFmode, NULL);
321 set_optab_libfunc (lt_optab, SFmode, NULL);
322 set_optab_libfunc (le_optab, SFmode, NULL);
323 set_optab_libfunc (unord_optab, SFmode, "__c6xabi_unordf");
324 set_optab_libfunc (eq_optab, DFmode, NULL);
325 set_optab_libfunc (ne_optab, DFmode, "__c6xabi_neqd");
326 set_optab_libfunc (gt_optab, DFmode, NULL);
327 set_optab_libfunc (ge_optab, DFmode, NULL);
328 set_optab_libfunc (lt_optab, DFmode, NULL);
329 set_optab_libfunc (le_optab, DFmode, NULL);
330 set_optab_libfunc (unord_optab, DFmode, "__c6xabi_unordd");
332 /* Floating-point to integer conversions. */
333 set_conv_libfunc (sfix_optab, SImode, DFmode, "__c6xabi_fixdi");
334 set_conv_libfunc (ufix_optab, SImode, DFmode, "__c6xabi_fixdu");
335 set_conv_libfunc (sfix_optab, DImode, DFmode, "__c6xabi_fixdlli");
336 set_conv_libfunc (ufix_optab, DImode, DFmode, "__c6xabi_fixdull");
337 set_conv_libfunc (sfix_optab, SImode, SFmode, "__c6xabi_fixfi");
338 set_conv_libfunc (ufix_optab, SImode, SFmode, "__c6xabi_fixfu");
339 set_conv_libfunc (sfix_optab, DImode, SFmode, "__c6xabi_fixflli");
340 set_conv_libfunc (ufix_optab, DImode, SFmode, "__c6xabi_fixfull");
342 /* Conversions between floating types. */
343 set_conv_libfunc (trunc_optab, SFmode, DFmode, "__c6xabi_cvtdf");
344 set_conv_libfunc (sext_optab, DFmode, SFmode, "__c6xabi_cvtfd");
346 /* Integer to floating-point conversions. */
347 set_conv_libfunc (sfloat_optab, DFmode, SImode, "__c6xabi_fltid");
348 set_conv_libfunc (ufloat_optab, DFmode, SImode, "__c6xabi_fltud");
349 set_conv_libfunc (sfloat_optab, DFmode, DImode, "__c6xabi_fltllid");
350 set_conv_libfunc (ufloat_optab, DFmode, DImode, "__c6xabi_fltulld");
351 set_conv_libfunc (sfloat_optab, SFmode, SImode, "__c6xabi_fltif");
352 set_conv_libfunc (ufloat_optab, SFmode, SImode, "__c6xabi_fltuf");
353 set_conv_libfunc (sfloat_optab, SFmode, DImode, "__c6xabi_fltllif");
354 set_conv_libfunc (ufloat_optab, SFmode, DImode, "__c6xabi_fltullf");
356 /* Long long. */
357 set_optab_libfunc (smul_optab, DImode, "__c6xabi_mpyll");
358 set_optab_libfunc (ashl_optab, DImode, "__c6xabi_llshl");
359 set_optab_libfunc (lshr_optab, DImode, "__c6xabi_llshru");
360 set_optab_libfunc (ashr_optab, DImode, "__c6xabi_llshr");
362 set_optab_libfunc (sdiv_optab, SImode, "__c6xabi_divi");
363 set_optab_libfunc (udiv_optab, SImode, "__c6xabi_divu");
364 set_optab_libfunc (smod_optab, SImode, "__c6xabi_remi");
365 set_optab_libfunc (umod_optab, SImode, "__c6xabi_remu");
366 set_optab_libfunc (sdivmod_optab, SImode, "__c6xabi_divremi");
367 set_optab_libfunc (udivmod_optab, SImode, "__c6xabi_divremu");
368 set_optab_libfunc (sdiv_optab, DImode, "__c6xabi_divlli");
369 set_optab_libfunc (udiv_optab, DImode, "__c6xabi_divull");
370 set_optab_libfunc (smod_optab, DImode, "__c6xabi_remlli");
371 set_optab_libfunc (umod_optab, DImode, "__c6xabi_remull");
372 set_optab_libfunc (udivmod_optab, DImode, "__c6xabi_divremull");
374 /* Block move. */
375 strasgi_libfunc = init_one_libfunc ("__c6xabi_strasgi");
376 strasgi64p_libfunc = init_one_libfunc ("__c6xabi_strasgi_64plus");
379 /* Begin the assembly file. */
381 static void
382 c6x_file_start (void)
384 /* Variable tracking should be run after all optimizations which change order
385 of insns. It also needs a valid CFG. This can't be done in
386 c6x_override_options, because flag_var_tracking is finalized after
387 that. */
388 c6x_flag_var_tracking = flag_var_tracking;
389 flag_var_tracking = 0;
391 done_cfi_sections = false;
392 default_file_start ();
394 /* Arrays are aligned to 8-byte boundaries. */
395 asm_fprintf (asm_out_file,
396 "\t.c6xabi_attribute Tag_ABI_array_object_alignment, 0\n");
397 asm_fprintf (asm_out_file,
398 "\t.c6xabi_attribute Tag_ABI_array_object_align_expected, 0\n");
400 /* Stack alignment is 8 bytes. */
401 asm_fprintf (asm_out_file,
402 "\t.c6xabi_attribute Tag_ABI_stack_align_needed, 0\n");
403 asm_fprintf (asm_out_file,
404 "\t.c6xabi_attribute Tag_ABI_stack_align_preserved, 0\n");
406 #if 0 /* FIXME: Reenable when TI's tools are fixed. */
407 /* ??? Ideally we'd check flag_short_wchar somehow. */
408 asm_fprintf (asm_out_file, "\t.c6xabi_attribute Tag_ABI_wchar_t, %d\n", 2);
409 #endif
411 /* We conform to version 1.0 of the ABI. */
412 asm_fprintf (asm_out_file,
413 "\t.c6xabi_attribute Tag_ABI_conformance, \"1.0\"\n");
417 /* The LTO frontend only enables exceptions when it sees a function that
418 uses it. This changes the return value of dwarf2out_do_frame, so we
419 have to check before every function. */
421 void
422 c6x_output_file_unwind (FILE * f)
424 if (done_cfi_sections)
425 return;
427 /* Output a .cfi_sections directive. */
428 if (dwarf2out_do_frame ())
430 if (flag_unwind_tables || flag_exceptions)
432 if (write_symbols == DWARF2_DEBUG
433 || write_symbols == VMS_AND_DWARF2_DEBUG)
434 asm_fprintf (f, "\t.cfi_sections .debug_frame, .c6xabi.exidx\n");
435 else
436 asm_fprintf (f, "\t.cfi_sections .c6xabi.exidx\n");
438 else
439 asm_fprintf (f, "\t.cfi_sections .debug_frame\n");
440 done_cfi_sections = true;
444 /* Output unwind directives at the end of a function. */
446 static void
447 c6x_output_fn_unwind (FILE * f)
449 /* Return immediately if we are not generating unwinding tables. */
450 if (! (flag_unwind_tables || flag_exceptions))
451 return;
453 /* If this function will never be unwound, then mark it as such. */
454 if (!(flag_unwind_tables || crtl->uses_eh_lsda)
455 && (TREE_NOTHROW (current_function_decl)
456 || crtl->all_throwers_are_sibcalls))
457 fputs("\t.cantunwind\n", f);
459 fputs ("\t.endp\n", f);
463 /* Stack and Calling. */
465 int argument_registers[10] =
467 REG_A4, REG_B4,
468 REG_A6, REG_B6,
469 REG_A8, REG_B8,
470 REG_A10, REG_B10,
471 REG_A12, REG_B12
474 /* Implements the macro INIT_CUMULATIVE_ARGS defined in c6x.h. */
476 void
477 c6x_init_cumulative_args (CUMULATIVE_ARGS *cum, const_tree fntype, rtx libname,
478 int n_named_args ATTRIBUTE_UNUSED)
480 cum->count = 0;
481 cum->nregs = 10;
482 if (!libname && fntype)
484 /* We need to find out the number of named arguments. Unfortunately,
485 for incoming arguments, N_NAMED_ARGS is set to -1. */
486 if (stdarg_p (fntype))
487 cum->nregs = type_num_arguments (fntype) - 1;
488 if (cum->nregs > 10)
489 cum->nregs = 10;
493 /* Implements the macro FUNCTION_ARG defined in c6x.h. */
495 static rtx
496 c6x_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
497 const_tree type, bool named ATTRIBUTE_UNUSED)
499 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
500 if (cum->count >= cum->nregs)
501 return NULL_RTX;
502 if (type)
504 HOST_WIDE_INT size = int_size_in_bytes (type);
505 if (TARGET_BIG_ENDIAN && AGGREGATE_TYPE_P (type))
507 if (size > 4)
509 rtx reg1 = gen_rtx_REG (SImode, argument_registers[cum->count] + 1);
510 rtx reg2 = gen_rtx_REG (SImode, argument_registers[cum->count]);
511 rtvec vec = gen_rtvec (2, gen_rtx_EXPR_LIST (VOIDmode, reg1, const0_rtx),
512 gen_rtx_EXPR_LIST (VOIDmode, reg2, GEN_INT (4)));
513 return gen_rtx_PARALLEL (mode, vec);
517 return gen_rtx_REG (mode, argument_registers[cum->count]);
520 static void
521 c6x_function_arg_advance (cumulative_args_t cum_v,
522 enum machine_mode mode ATTRIBUTE_UNUSED,
523 const_tree type ATTRIBUTE_UNUSED,
524 bool named ATTRIBUTE_UNUSED)
526 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
527 cum->count++;
531 /* Return true if BLOCK_REG_PADDING (MODE, TYPE, FIRST) should return
532 upward rather than downward. */
534 bool
535 c6x_block_reg_pad_upward (enum machine_mode mode ATTRIBUTE_UNUSED,
536 const_tree type, bool first)
538 HOST_WIDE_INT size;
540 if (!TARGET_BIG_ENDIAN)
541 return true;
542 if (!first)
543 return true;
544 if (!type)
545 return true;
546 size = int_size_in_bytes (type);
547 return size == 3;
550 /* Implement TARGET_FUNCTION_ARG_BOUNDARY. */
552 static unsigned int
553 c6x_function_arg_boundary (enum machine_mode mode, const_tree type)
555 unsigned int boundary = type ? TYPE_ALIGN (type) : GET_MODE_BITSIZE (mode);
557 if (boundary > BITS_PER_WORD)
558 return 2 * BITS_PER_WORD;
560 if (mode == BLKmode)
562 HOST_WIDE_INT size = int_size_in_bytes (type);
563 if (size > 4)
564 return 2 * BITS_PER_WORD;
565 if (boundary < BITS_PER_WORD)
567 if (size >= 3)
568 return BITS_PER_WORD;
569 if (size >= 2)
570 return 2 * BITS_PER_UNIT;
573 return boundary;
576 /* Implement TARGET_FUNCTION_ARG_ROUND_BOUNDARY. */
577 static unsigned int
578 c6x_function_arg_round_boundary (enum machine_mode mode, const_tree type)
580 return c6x_function_arg_boundary (mode, type);
583 /* TARGET_FUNCTION_VALUE implementation. Returns an RTX representing the place
584 where function FUNC returns or receives a value of data type TYPE. */
586 static rtx
587 c6x_function_value (const_tree type, const_tree func ATTRIBUTE_UNUSED,
588 bool outgoing ATTRIBUTE_UNUSED)
590 /* Functions return values in register A4. When returning aggregates, we may
591 have to adjust for endianness. */
592 if (TARGET_BIG_ENDIAN && type && AGGREGATE_TYPE_P (type))
594 HOST_WIDE_INT size = int_size_in_bytes (type);
595 if (size > 4)
598 rtx reg1 = gen_rtx_REG (SImode, REG_A4 + 1);
599 rtx reg2 = gen_rtx_REG (SImode, REG_A4);
600 rtvec vec = gen_rtvec (2, gen_rtx_EXPR_LIST (VOIDmode, reg1, const0_rtx),
601 gen_rtx_EXPR_LIST (VOIDmode, reg2, GEN_INT (4)));
602 return gen_rtx_PARALLEL (TYPE_MODE (type), vec);
605 return gen_rtx_REG (TYPE_MODE (type), REG_A4);
608 /* Implement TARGET_LIBCALL_VALUE. */
610 static rtx
611 c6x_libcall_value (enum machine_mode mode, const_rtx fun ATTRIBUTE_UNUSED)
613 return gen_rtx_REG (mode, REG_A4);
616 /* TARGET_STRUCT_VALUE_RTX implementation. */
618 static rtx
619 c6x_struct_value_rtx (tree type ATTRIBUTE_UNUSED, int incoming ATTRIBUTE_UNUSED)
621 return gen_rtx_REG (Pmode, REG_A3);
624 /* Implement TARGET_FUNCTION_VALUE_REGNO_P. */
626 static bool
627 c6x_function_value_regno_p (const unsigned int regno)
629 return regno == REG_A4;
632 /* Types larger than 64 bit, and variable sized types, are passed by
633 reference. The callee must copy them; see c6x_callee_copies. */
635 static bool
636 c6x_pass_by_reference (cumulative_args_t cum_v ATTRIBUTE_UNUSED,
637 enum machine_mode mode, const_tree type,
638 bool named ATTRIBUTE_UNUSED)
640 int size = -1;
641 if (type)
642 size = int_size_in_bytes (type);
643 else if (mode != VOIDmode)
644 size = GET_MODE_SIZE (mode);
645 return size > 2 * UNITS_PER_WORD || size == -1;
648 /* Decide whether a type should be returned in memory (true)
649 or in a register (false). This is called by the macro
650 TARGET_RETURN_IN_MEMORY. */
652 static bool
653 c6x_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
655 int size = int_size_in_bytes (type);
656 return size > 2 * UNITS_PER_WORD || size == -1;
659 /* Values which must be returned in the most-significant end of the return
660 register. */
662 static bool
663 c6x_return_in_msb (const_tree valtype)
665 HOST_WIDE_INT size = int_size_in_bytes (valtype);
666 return TARGET_BIG_ENDIAN && AGGREGATE_TYPE_P (valtype) && size == 3;
669 /* Implement TARGET_CALLEE_COPIES. */
671 static bool
672 c6x_callee_copies (cumulative_args_t cum_v ATTRIBUTE_UNUSED,
673 enum machine_mode mode ATTRIBUTE_UNUSED,
674 const_tree type ATTRIBUTE_UNUSED,
675 bool named ATTRIBUTE_UNUSED)
677 return true;
680 /* Return the type to use as __builtin_va_list. */
681 static tree
682 c6x_build_builtin_va_list (void)
684 return build_pointer_type (char_type_node);
687 static void
688 c6x_asm_trampoline_template (FILE *f)
690 fprintf (f, "\t.long\t0x0000002b\n"); /* mvkl .s2 fnlow,B0 */
691 fprintf (f, "\t.long\t0x01000028\n"); /* || mvkl .s1 sclow,A2 */
692 fprintf (f, "\t.long\t0x0000006b\n"); /* mvkh .s2 fnhigh,B0 */
693 fprintf (f, "\t.long\t0x01000068\n"); /* || mvkh .s1 schigh,A2 */
694 fprintf (f, "\t.long\t0x00000362\n"); /* b .s2 B0 */
695 fprintf (f, "\t.long\t0x00008000\n"); /* nop 5 */
696 fprintf (f, "\t.long\t0x00000000\n"); /* nop */
697 fprintf (f, "\t.long\t0x00000000\n"); /* nop */
700 /* Emit RTL insns to initialize the variable parts of a trampoline at
701 TRAMP. FNADDR is an RTX for the address of the function's pure
702 code. CXT is an RTX for the static chain value for the function. */
704 static void
705 c6x_initialize_trampoline (rtx tramp, tree fndecl, rtx cxt)
707 rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
708 rtx t1 = copy_to_reg (fnaddr);
709 rtx t2 = copy_to_reg (cxt);
710 rtx mask = gen_reg_rtx (SImode);
711 int i;
713 emit_block_move (tramp, assemble_trampoline_template (),
714 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
716 emit_move_insn (mask, GEN_INT (0xffff << 7));
718 for (i = 0; i < 4; i++)
720 rtx mem = adjust_address (tramp, SImode, i * 4);
721 rtx t = (i & 1) ? t2 : t1;
722 rtx v1 = gen_reg_rtx (SImode);
723 rtx v2 = gen_reg_rtx (SImode);
724 emit_move_insn (v1, mem);
725 if (i < 2)
726 emit_insn (gen_ashlsi3 (v2, t, GEN_INT (7)));
727 else
728 emit_insn (gen_lshrsi3 (v2, t, GEN_INT (9)));
729 emit_insn (gen_andsi3 (v2, v2, mask));
730 emit_insn (gen_iorsi3 (v2, v2, v1));
731 emit_move_insn (mem, v2);
733 #ifdef CLEAR_INSN_CACHE
734 tramp = XEXP (tramp, 0);
735 emit_library_call (gen_rtx_SYMBOL_REF (Pmode, "__gnu_clear_cache"),
736 LCT_NORMAL, VOIDmode, 2, tramp, Pmode,
737 plus_constant (Pmode, tramp, TRAMPOLINE_SIZE),
738 Pmode);
739 #endif
742 /* Determine whether c6x_output_mi_thunk can succeed. */
744 static bool
745 c6x_can_output_mi_thunk (const_tree thunk ATTRIBUTE_UNUSED,
746 HOST_WIDE_INT delta ATTRIBUTE_UNUSED,
747 HOST_WIDE_INT vcall_offset ATTRIBUTE_UNUSED,
748 const_tree function ATTRIBUTE_UNUSED)
750 return !TARGET_LONG_CALLS;
753 /* Output the assembler code for a thunk function. THUNK is the
754 declaration for the thunk function itself, FUNCTION is the decl for
755 the target function. DELTA is an immediate constant offset to be
756 added to THIS. If VCALL_OFFSET is nonzero, the word at
757 *(*this + vcall_offset) should be added to THIS. */
759 static void
760 c6x_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
761 tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
762 HOST_WIDE_INT vcall_offset, tree function)
764 rtx xops[5];
765 /* The this parameter is passed as the first argument. */
766 rtx this_rtx = gen_rtx_REG (Pmode, REG_A4);
768 c6x_current_insn = NULL_RTX;
770 xops[4] = XEXP (DECL_RTL (function), 0);
771 if (!vcall_offset)
773 output_asm_insn ("b .s2 \t%4", xops);
774 if (!delta)
775 output_asm_insn ("nop 5", xops);
778 /* Adjust the this parameter by a fixed constant. */
779 if (delta)
781 xops[0] = GEN_INT (delta);
782 xops[1] = this_rtx;
783 if (delta >= -16 && delta <= 15)
785 output_asm_insn ("add .s1 %0, %1, %1", xops);
786 if (!vcall_offset)
787 output_asm_insn ("nop 4", xops);
789 else if (delta >= 16 && delta < 32)
791 output_asm_insn ("add .d1 %0, %1, %1", xops);
792 if (!vcall_offset)
793 output_asm_insn ("nop 4", xops);
795 else if (delta >= -32768 && delta < 32768)
797 output_asm_insn ("mvk .s1 %0, A0", xops);
798 output_asm_insn ("add .d1 %1, A0, %1", xops);
799 if (!vcall_offset)
800 output_asm_insn ("nop 3", xops);
802 else
804 output_asm_insn ("mvkl .s1 %0, A0", xops);
805 output_asm_insn ("mvkh .s1 %0, A0", xops);
806 output_asm_insn ("add .d1 %1, A0, %1", xops);
807 if (!vcall_offset)
808 output_asm_insn ("nop 3", xops);
812 /* Adjust the this parameter by a value stored in the vtable. */
813 if (vcall_offset)
815 rtx a0tmp = gen_rtx_REG (Pmode, REG_A0);
816 rtx a3tmp = gen_rtx_REG (Pmode, REG_A3);
818 xops[1] = a3tmp;
819 xops[2] = a0tmp;
820 xops[3] = gen_rtx_MEM (Pmode, a0tmp);
821 output_asm_insn ("mv .s1 a4, %2", xops);
822 output_asm_insn ("ldw .d1t1 %3, %2", xops);
824 /* Adjust the this parameter. */
825 xops[0] = gen_rtx_MEM (Pmode, plus_constant (Pmode, a0tmp,
826 vcall_offset));
827 if (!memory_operand (xops[0], Pmode))
829 rtx tmp2 = gen_rtx_REG (Pmode, REG_A1);
830 xops[0] = GEN_INT (vcall_offset);
831 xops[1] = tmp2;
832 output_asm_insn ("mvkl .s1 %0, %1", xops);
833 output_asm_insn ("mvkh .s1 %0, %1", xops);
834 output_asm_insn ("nop 2", xops);
835 output_asm_insn ("add .d1 %2, %1, %2", xops);
836 xops[0] = gen_rtx_MEM (Pmode, a0tmp);
838 else
839 output_asm_insn ("nop 4", xops);
840 xops[2] = this_rtx;
841 output_asm_insn ("ldw .d1t1 %0, %1", xops);
842 output_asm_insn ("|| b .s2 \t%4", xops);
843 output_asm_insn ("nop 4", xops);
844 output_asm_insn ("add .d1 %2, %1, %2", xops);
848 /* Return true if EXP goes in small data/bss. */
850 static bool
851 c6x_in_small_data_p (const_tree exp)
853 /* We want to merge strings, so we never consider them small data. */
854 if (TREE_CODE (exp) == STRING_CST)
855 return false;
857 /* Functions are never small data. */
858 if (TREE_CODE (exp) == FUNCTION_DECL)
859 return false;
861 if (TREE_CODE (exp) == VAR_DECL && DECL_WEAK (exp))
862 return false;
864 if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp))
866 const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp));
868 if (strcmp (section, ".neardata") == 0
869 || strncmp (section, ".neardata.", 10) == 0
870 || strncmp (section, ".gnu.linkonce.s.", 16) == 0
871 || strcmp (section, ".bss") == 0
872 || strncmp (section, ".bss.", 5) == 0
873 || strncmp (section, ".gnu.linkonce.sb.", 17) == 0
874 || strcmp (section, ".rodata") == 0
875 || strncmp (section, ".rodata.", 8) == 0
876 || strncmp (section, ".gnu.linkonce.s2.", 17) == 0)
877 return true;
879 else
880 return PLACE_IN_SDATA_P (exp);
882 return false;
885 /* Return a section for X. The only special thing we do here is to
886 honor small data. We don't have a tree type, so we can't use the
887 PLACE_IN_SDATA_P macro we use everywhere else; we choose to place
888 everything sized 8 bytes or smaller into small data. */
890 static section *
891 c6x_select_rtx_section (enum machine_mode mode, rtx x,
892 unsigned HOST_WIDE_INT align)
894 if (c6x_sdata_mode == C6X_SDATA_ALL
895 || (c6x_sdata_mode != C6X_SDATA_NONE && GET_MODE_SIZE (mode) <= 8))
896 /* ??? Consider using mergeable sdata sections. */
897 return sdata_section;
898 else
899 return default_elf_select_rtx_section (mode, x, align);
902 static section *
903 c6x_elf_select_section (tree decl, int reloc,
904 unsigned HOST_WIDE_INT align)
906 const char *sname = NULL;
907 unsigned int flags = SECTION_WRITE;
908 if (c6x_in_small_data_p (decl))
910 switch (categorize_decl_for_section (decl, reloc))
912 case SECCAT_SRODATA:
913 sname = ".rodata";
914 flags = 0;
915 break;
916 case SECCAT_SDATA:
917 sname = ".neardata";
918 break;
919 case SECCAT_SBSS:
920 sname = ".bss";
921 flags |= SECTION_BSS;
922 default:
923 break;
926 else
928 switch (categorize_decl_for_section (decl, reloc))
930 case SECCAT_DATA:
931 sname = ".fardata";
932 break;
933 case SECCAT_DATA_REL:
934 sname = ".fardata.rel";
935 break;
936 case SECCAT_DATA_REL_LOCAL:
937 sname = ".fardata.rel.local";
938 break;
939 case SECCAT_DATA_REL_RO:
940 sname = ".fardata.rel.ro";
941 break;
942 case SECCAT_DATA_REL_RO_LOCAL:
943 sname = ".fardata.rel.ro.local";
944 break;
945 case SECCAT_BSS:
946 sname = ".far";
947 flags |= SECTION_BSS;
948 break;
949 case SECCAT_RODATA:
950 sname = ".const";
951 flags = 0;
952 break;
953 case SECCAT_SRODATA:
954 case SECCAT_SDATA:
955 case SECCAT_SBSS:
956 gcc_unreachable ();
957 default:
958 break;
961 if (sname)
963 /* We might get called with string constants, but get_named_section
964 doesn't like them as they are not DECLs. Also, we need to set
965 flags in that case. */
966 if (!DECL_P (decl))
967 return get_section (sname, flags, NULL);
968 return get_named_section (decl, sname, reloc);
971 return default_elf_select_section (decl, reloc, align);
974 /* Build up a unique section name, expressed as a
975 STRING_CST node, and assign it to DECL_SECTION_NAME (decl).
976 RELOC indicates whether the initial value of EXP requires
977 link-time relocations. */
979 static void ATTRIBUTE_UNUSED
980 c6x_elf_unique_section (tree decl, int reloc)
982 const char *prefix = NULL;
983 /* We only need to use .gnu.linkonce if we don't have COMDAT groups. */
984 bool one_only = DECL_ONE_ONLY (decl) && !HAVE_COMDAT_GROUP;
986 if (c6x_in_small_data_p (decl))
988 switch (categorize_decl_for_section (decl, reloc))
990 case SECCAT_SDATA:
991 prefix = one_only ? ".s" : ".neardata";
992 break;
993 case SECCAT_SBSS:
994 prefix = one_only ? ".sb" : ".bss";
995 break;
996 case SECCAT_SRODATA:
997 prefix = one_only ? ".s2" : ".rodata";
998 break;
999 case SECCAT_RODATA_MERGE_STR:
1000 case SECCAT_RODATA_MERGE_STR_INIT:
1001 case SECCAT_RODATA_MERGE_CONST:
1002 case SECCAT_RODATA:
1003 case SECCAT_DATA:
1004 case SECCAT_DATA_REL:
1005 case SECCAT_DATA_REL_LOCAL:
1006 case SECCAT_DATA_REL_RO:
1007 case SECCAT_DATA_REL_RO_LOCAL:
1008 gcc_unreachable ();
1009 default:
1010 /* Everything else we place into default sections and hope for the
1011 best. */
1012 break;
1015 else
1017 switch (categorize_decl_for_section (decl, reloc))
1019 case SECCAT_DATA:
1020 case SECCAT_DATA_REL:
1021 case SECCAT_DATA_REL_LOCAL:
1022 case SECCAT_DATA_REL_RO:
1023 case SECCAT_DATA_REL_RO_LOCAL:
1024 prefix = one_only ? ".fd" : ".fardata";
1025 break;
1026 case SECCAT_BSS:
1027 prefix = one_only ? ".fb" : ".far";
1028 break;
1029 case SECCAT_RODATA:
1030 case SECCAT_RODATA_MERGE_STR:
1031 case SECCAT_RODATA_MERGE_STR_INIT:
1032 case SECCAT_RODATA_MERGE_CONST:
1033 prefix = one_only ? ".fr" : ".const";
1034 break;
1035 case SECCAT_SRODATA:
1036 case SECCAT_SDATA:
1037 case SECCAT_SBSS:
1038 gcc_unreachable ();
1039 default:
1040 break;
1044 if (prefix)
1046 const char *name, *linkonce;
1047 char *string;
1049 name = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
1050 name = targetm.strip_name_encoding (name);
1052 /* If we're using one_only, then there needs to be a .gnu.linkonce
1053 prefix to the section name. */
1054 linkonce = one_only ? ".gnu.linkonce" : "";
1056 string = ACONCAT ((linkonce, prefix, ".", name, NULL));
1058 DECL_SECTION_NAME (decl) = build_string (strlen (string), string);
1059 return;
1061 default_unique_section (decl, reloc);
1064 static unsigned int
1065 c6x_section_type_flags (tree decl, const char *name, int reloc)
1067 unsigned int flags = 0;
1069 if (strcmp (name, ".far") == 0
1070 || strncmp (name, ".far.", 5) == 0)
1071 flags |= SECTION_BSS;
1073 flags |= default_section_type_flags (decl, name, reloc);
1075 return flags;
1078 /* Checks whether the given CALL_EXPR would use a caller saved
1079 register. This is used to decide whether sibling call optimization
1080 could be performed on the respective function call. */
1082 static bool
1083 c6x_call_saved_register_used (tree call_expr)
1085 CUMULATIVE_ARGS cum_v;
1086 cumulative_args_t cum;
1087 HARD_REG_SET call_saved_regset;
1088 tree parameter;
1089 enum machine_mode mode;
1090 tree type;
1091 rtx parm_rtx;
1092 int i;
1094 INIT_CUMULATIVE_ARGS (cum_v, NULL, NULL, 0, 0);
1095 cum = pack_cumulative_args (&cum_v);
1097 COMPL_HARD_REG_SET (call_saved_regset, call_used_reg_set);
1098 for (i = 0; i < call_expr_nargs (call_expr); i++)
1100 parameter = CALL_EXPR_ARG (call_expr, i);
1101 gcc_assert (parameter);
1103 /* For an undeclared variable passed as parameter we will get
1104 an ERROR_MARK node here. */
1105 if (TREE_CODE (parameter) == ERROR_MARK)
1106 return true;
1108 type = TREE_TYPE (parameter);
1109 gcc_assert (type);
1111 mode = TYPE_MODE (type);
1112 gcc_assert (mode);
1114 if (pass_by_reference (&cum_v, mode, type, true))
1116 mode = Pmode;
1117 type = build_pointer_type (type);
1120 parm_rtx = c6x_function_arg (cum, mode, type, 0);
1122 c6x_function_arg_advance (cum, mode, type, 0);
1124 if (!parm_rtx)
1125 continue;
1127 if (REG_P (parm_rtx)
1128 && overlaps_hard_reg_set_p (call_saved_regset, GET_MODE (parm_rtx),
1129 REGNO (parm_rtx)))
1130 return true;
1131 if (GET_CODE (parm_rtx) == PARALLEL)
1133 int n = XVECLEN (parm_rtx, 0);
1134 while (n-- > 0)
1136 rtx x = XEXP (XVECEXP (parm_rtx, 0, n), 0);
1137 if (REG_P (x)
1138 && overlaps_hard_reg_set_p (call_saved_regset,
1139 GET_MODE (x), REGNO (x)))
1140 return true;
1144 return false;
1147 /* Decide whether we can make a sibling call to a function. DECL is the
1148 declaration of the function being targeted by the call and EXP is the
1149 CALL_EXPR representing the call. */
1151 static bool
1152 c6x_function_ok_for_sibcall (tree decl, tree exp)
1154 /* Registers A10, A12, B10 and B12 are available as arguments
1155 register but unfortunately caller saved. This makes functions
1156 needing these registers for arguments not suitable for
1157 sibcalls. */
1158 if (c6x_call_saved_register_used (exp))
1159 return false;
1161 if (!flag_pic)
1162 return true;
1164 if (TARGET_DSBT)
1166 /* When compiling for DSBT, the calling function must be local,
1167 so that when we reload B14 in the sibcall epilogue, it will
1168 not change its value. */
1169 struct cgraph_local_info *this_func;
1171 if (!decl)
1172 /* Not enough information. */
1173 return false;
1175 this_func = cgraph_local_info (current_function_decl);
1176 return this_func->local;
1179 return true;
1182 /* Return true if DECL is known to be linked into section SECTION. */
1184 static bool
1185 c6x_function_in_section_p (tree decl, section *section)
1187 /* We can only be certain about functions defined in the same
1188 compilation unit. */
1189 if (!TREE_STATIC (decl))
1190 return false;
1192 /* Make sure that SYMBOL always binds to the definition in this
1193 compilation unit. */
1194 if (!targetm.binds_local_p (decl))
1195 return false;
1197 /* If DECL_SECTION_NAME is set, assume it is trustworthy. */
1198 if (!DECL_SECTION_NAME (decl))
1200 /* Make sure that we will not create a unique section for DECL. */
1201 if (flag_function_sections || DECL_ONE_ONLY (decl))
1202 return false;
1205 return function_section (decl) == section;
1208 /* Return true if a call to OP, which is a SYMBOL_REF, must be expanded
1209 as a long call. */
1210 bool
1211 c6x_long_call_p (rtx op)
1213 tree decl;
1215 if (!TARGET_LONG_CALLS)
1216 return false;
1218 decl = SYMBOL_REF_DECL (op);
1220 /* Try to determine whether the symbol is in the same section as the current
1221 function. Be conservative, and only cater for cases in which the
1222 whole of the current function is placed in the same section. */
1223 if (decl != NULL_TREE
1224 && !flag_reorder_blocks_and_partition
1225 && TREE_CODE (decl) == FUNCTION_DECL
1226 && c6x_function_in_section_p (decl, current_function_section ()))
1227 return false;
1229 return true;
1232 /* Emit the sequence for a call. */
1233 void
1234 c6x_expand_call (rtx retval, rtx address, bool sibcall)
1236 rtx callee = XEXP (address, 0);
1237 rtx call_insn;
1239 if (!c6x_call_operand (callee, Pmode))
1241 callee = force_reg (Pmode, callee);
1242 address = change_address (address, Pmode, callee);
1244 call_insn = gen_rtx_CALL (VOIDmode, address, const0_rtx);
1245 if (sibcall)
1247 call_insn = emit_call_insn (call_insn);
1248 use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn),
1249 gen_rtx_REG (Pmode, REG_B3));
1251 else
1253 if (retval == NULL_RTX)
1254 call_insn = emit_call_insn (call_insn);
1255 else
1256 call_insn = emit_call_insn (gen_rtx_SET (GET_MODE (retval), retval,
1257 call_insn));
1259 if (flag_pic)
1260 use_reg (&CALL_INSN_FUNCTION_USAGE (call_insn), pic_offset_table_rtx);
1263 /* Legitimize PIC addresses. If the address is already position-independent,
1264 we return ORIG. Newly generated position-independent addresses go into a
1265 reg. This is REG if nonzero, otherwise we allocate register(s) as
1266 necessary. PICREG is the register holding the pointer to the PIC offset
1267 table. */
1269 static rtx
1270 legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
1272 rtx addr = orig;
1273 rtx new_rtx = orig;
1275 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
1277 int unspec = UNSPEC_LOAD_GOT;
1278 rtx tmp;
1280 if (reg == 0)
1282 gcc_assert (can_create_pseudo_p ());
1283 reg = gen_reg_rtx (Pmode);
1285 if (flag_pic == 2)
1287 if (can_create_pseudo_p ())
1288 tmp = gen_reg_rtx (Pmode);
1289 else
1290 tmp = reg;
1291 emit_insn (gen_movsi_gotoff_high (tmp, addr));
1292 emit_insn (gen_movsi_gotoff_lo_sum (tmp, tmp, addr));
1293 emit_insn (gen_load_got_gotoff (reg, picreg, tmp));
1295 else
1297 tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), unspec);
1298 new_rtx = gen_const_mem (Pmode, gen_rtx_PLUS (Pmode, picreg, tmp));
1300 emit_move_insn (reg, new_rtx);
1302 if (picreg == pic_offset_table_rtx)
1303 crtl->uses_pic_offset_table = 1;
1304 return reg;
1307 else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
1309 rtx base;
1311 if (GET_CODE (addr) == CONST)
1313 addr = XEXP (addr, 0);
1314 gcc_assert (GET_CODE (addr) == PLUS);
1317 if (XEXP (addr, 0) == picreg)
1318 return orig;
1320 if (reg == 0)
1322 gcc_assert (can_create_pseudo_p ());
1323 reg = gen_reg_rtx (Pmode);
1326 base = legitimize_pic_address (XEXP (addr, 0), reg, picreg);
1327 addr = legitimize_pic_address (XEXP (addr, 1),
1328 base == reg ? NULL_RTX : reg,
1329 picreg);
1331 if (GET_CODE (addr) == CONST_INT)
1333 gcc_assert (! reload_in_progress && ! reload_completed);
1334 addr = force_reg (Pmode, addr);
1337 if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
1339 base = gen_rtx_PLUS (Pmode, base, XEXP (addr, 0));
1340 addr = XEXP (addr, 1);
1343 return gen_rtx_PLUS (Pmode, base, addr);
1346 return new_rtx;
1349 /* Expand a move operation in mode MODE. The operands are in OPERANDS.
1350 Returns true if no further code must be generated, false if the caller
1351 should generate an insn to move OPERANDS[1] to OPERANDS[0]. */
1353 bool
1354 expand_move (rtx *operands, enum machine_mode mode)
1356 rtx dest = operands[0];
1357 rtx op = operands[1];
1359 if ((reload_in_progress | reload_completed) == 0
1360 && GET_CODE (dest) == MEM && GET_CODE (op) != REG)
1361 operands[1] = force_reg (mode, op);
1362 else if (mode == SImode && symbolic_operand (op, SImode))
1364 if (flag_pic)
1366 if (sdata_symbolic_operand (op, SImode))
1368 emit_insn (gen_load_sdata_pic (dest, pic_offset_table_rtx, op));
1369 crtl->uses_pic_offset_table = 1;
1370 return true;
1372 else
1374 rtx temp = (reload_completed || reload_in_progress
1375 ? dest : gen_reg_rtx (Pmode));
1377 operands[1] = legitimize_pic_address (op, temp,
1378 pic_offset_table_rtx);
1381 else if (reload_completed
1382 && !sdata_symbolic_operand (op, SImode))
1384 emit_insn (gen_movsi_high (dest, op));
1385 emit_insn (gen_movsi_lo_sum (dest, dest, op));
1386 return true;
1389 return false;
1392 /* This function is called when we're about to expand an integer compare
1393 operation which performs COMPARISON. It examines the second operand,
1394 and if it is an integer constant that cannot be used directly on the
1395 current machine in a comparison insn, it returns true. */
1396 bool
1397 c6x_force_op_for_comparison_p (enum rtx_code code, rtx op)
1399 if (!CONST_INT_P (op) || satisfies_constraint_Iu4 (op))
1400 return false;
1402 if ((code == EQ || code == LT || code == GT)
1403 && !satisfies_constraint_Is5 (op))
1404 return true;
1405 if ((code == GTU || code == LTU)
1406 && (!TARGET_INSNS_64 || !satisfies_constraint_Iu5 (op)))
1407 return true;
1409 return false;
1412 /* Emit comparison instruction if necessary, returning the expression
1413 that holds the compare result in the proper mode. Return the comparison
1414 that should be used in the jump insn. */
1417 c6x_expand_compare (rtx comparison, enum machine_mode mode)
1419 enum rtx_code code = GET_CODE (comparison);
1420 rtx op0 = XEXP (comparison, 0);
1421 rtx op1 = XEXP (comparison, 1);
1422 rtx cmp;
1423 enum rtx_code jump_code = code;
1424 enum machine_mode op_mode = GET_MODE (op0);
1426 if (op_mode == DImode && (code == NE || code == EQ) && op1 == const0_rtx)
1428 rtx t = gen_reg_rtx (SImode);
1429 emit_insn (gen_iorsi3 (t, gen_lowpart (SImode, op0),
1430 gen_highpart (SImode, op0)));
1431 op_mode = SImode;
1432 cmp = t;
1434 else if (op_mode == DImode)
1436 rtx lo[2], high[2];
1437 rtx cmp1, cmp2;
1439 if (code == NE || code == GEU || code == LEU || code == GE || code == LE)
1441 code = reverse_condition (code);
1442 jump_code = EQ;
1444 else
1445 jump_code = NE;
1447 split_di (&op0, 1, lo, high);
1448 split_di (&op1, 1, lo + 1, high + 1);
1450 if (c6x_force_op_for_comparison_p (code, high[1])
1451 || c6x_force_op_for_comparison_p (EQ, high[1]))
1452 high[1] = force_reg (SImode, high[1]);
1454 cmp1 = gen_reg_rtx (SImode);
1455 cmp2 = gen_reg_rtx (SImode);
1456 emit_insn (gen_rtx_SET (VOIDmode, cmp1,
1457 gen_rtx_fmt_ee (code, SImode, high[0], high[1])));
1458 if (code == EQ)
1460 if (c6x_force_op_for_comparison_p (code, lo[1]))
1461 lo[1] = force_reg (SImode, lo[1]);
1462 emit_insn (gen_rtx_SET (VOIDmode, cmp2,
1463 gen_rtx_fmt_ee (code, SImode, lo[0], lo[1])));
1464 emit_insn (gen_andsi3 (cmp1, cmp1, cmp2));
1466 else
1468 emit_insn (gen_rtx_SET (VOIDmode, cmp2,
1469 gen_rtx_EQ (SImode, high[0], high[1])));
1470 if (code == GT)
1471 code = GTU;
1472 else if (code == LT)
1473 code = LTU;
1474 if (c6x_force_op_for_comparison_p (code, lo[1]))
1475 lo[1] = force_reg (SImode, lo[1]);
1476 emit_insn (gen_cmpsi_and (cmp2, gen_rtx_fmt_ee (code, SImode,
1477 lo[0], lo[1]),
1478 lo[0], lo[1], cmp2));
1479 emit_insn (gen_iorsi3 (cmp1, cmp1, cmp2));
1481 cmp = cmp1;
1483 else if (TARGET_FP && !flag_finite_math_only
1484 && (op_mode == DFmode || op_mode == SFmode)
1485 && code != EQ && code != NE && code != LT && code != GT
1486 && code != UNLE && code != UNGE)
1488 enum rtx_code code1, code2, code3;
1489 rtx (*fn) (rtx, rtx, rtx, rtx, rtx);
1491 jump_code = NE;
1492 code3 = UNKNOWN;
1493 switch (code)
1495 case UNLT:
1496 case UNGT:
1497 jump_code = EQ;
1498 /* fall through */
1499 case LE:
1500 case GE:
1501 code1 = code == LE || code == UNGT ? LT : GT;
1502 code2 = EQ;
1503 break;
1505 case UNORDERED:
1506 jump_code = EQ;
1507 /* fall through */
1508 case ORDERED:
1509 code3 = EQ;
1510 /* fall through */
1511 case LTGT:
1512 code1 = LT;
1513 code2 = GT;
1514 break;
1516 case UNEQ:
1517 code1 = LT;
1518 code2 = GT;
1519 jump_code = EQ;
1520 break;
1522 default:
1523 gcc_unreachable ();
1526 cmp = gen_reg_rtx (SImode);
1527 emit_insn (gen_rtx_SET (VOIDmode, cmp,
1528 gen_rtx_fmt_ee (code1, SImode, op0, op1)));
1529 fn = op_mode == DFmode ? gen_cmpdf_ior : gen_cmpsf_ior;
1530 emit_insn (fn (cmp, gen_rtx_fmt_ee (code2, SImode, op0, op1),
1531 op0, op1, cmp));
1532 if (code3 != UNKNOWN)
1533 emit_insn (fn (cmp, gen_rtx_fmt_ee (code3, SImode, op0, op1),
1534 op0, op1, cmp));
1536 else if (op_mode == SImode && (code == NE || code == EQ) && op1 == const0_rtx)
1537 cmp = op0;
1538 else
1540 bool is_fp_libfunc;
1541 is_fp_libfunc = !TARGET_FP && (op_mode == DFmode || op_mode == SFmode);
1543 if ((code == NE || code == GEU || code == LEU || code == GE || code == LE)
1544 && !is_fp_libfunc)
1546 code = reverse_condition (code);
1547 jump_code = EQ;
1549 else if (code == UNGE)
1551 code = LT;
1552 jump_code = EQ;
1554 else if (code == UNLE)
1556 code = GT;
1557 jump_code = EQ;
1559 else
1560 jump_code = NE;
1562 if (is_fp_libfunc)
1564 rtx insns;
1565 rtx libfunc;
1566 switch (code)
1568 case EQ:
1569 libfunc = op_mode == DFmode ? eqdf_libfunc : eqsf_libfunc;
1570 break;
1571 case NE:
1572 libfunc = op_mode == DFmode ? nedf_libfunc : nesf_libfunc;
1573 break;
1574 case GT:
1575 libfunc = op_mode == DFmode ? gtdf_libfunc : gtsf_libfunc;
1576 break;
1577 case GE:
1578 libfunc = op_mode == DFmode ? gedf_libfunc : gesf_libfunc;
1579 break;
1580 case LT:
1581 libfunc = op_mode == DFmode ? ltdf_libfunc : ltsf_libfunc;
1582 break;
1583 case LE:
1584 libfunc = op_mode == DFmode ? ledf_libfunc : lesf_libfunc;
1585 break;
1586 default:
1587 gcc_unreachable ();
1589 start_sequence ();
1591 cmp = emit_library_call_value (libfunc, 0, LCT_CONST, SImode, 2,
1592 op0, op_mode, op1, op_mode);
1593 insns = get_insns ();
1594 end_sequence ();
1596 emit_libcall_block (insns, cmp, cmp,
1597 gen_rtx_fmt_ee (code, SImode, op0, op1));
1599 else
1601 cmp = gen_reg_rtx (SImode);
1602 if (c6x_force_op_for_comparison_p (code, op1))
1603 op1 = force_reg (SImode, op1);
1604 emit_insn (gen_rtx_SET (VOIDmode, cmp,
1605 gen_rtx_fmt_ee (code, SImode, op0, op1)));
1609 return gen_rtx_fmt_ee (jump_code, mode, cmp, const0_rtx);
1612 /* Return one word of double-word value OP. HIGH_P is true to select the
1613 high part, false to select the low part. When encountering auto-increment
1614 addressing, we make the assumption that the low part is going to be accessed
1615 first. */
1618 c6x_subword (rtx op, bool high_p)
1620 unsigned int byte;
1621 enum machine_mode mode;
1623 mode = GET_MODE (op);
1624 if (mode == VOIDmode)
1625 mode = DImode;
1627 if (TARGET_BIG_ENDIAN ? !high_p : high_p)
1628 byte = UNITS_PER_WORD;
1629 else
1630 byte = 0;
1632 if (MEM_P (op))
1634 rtx addr = XEXP (op, 0);
1635 if (GET_CODE (addr) == PLUS || REG_P (addr))
1636 return adjust_address (op, word_mode, byte);
1637 /* FIXME: should really support autoincrement addressing for
1638 multi-word modes. */
1639 gcc_unreachable ();
1642 return simplify_gen_subreg (word_mode, op, mode, byte);
1645 /* Split one or more DImode RTL references into pairs of SImode
1646 references. The RTL can be REG, offsettable MEM, integer constant, or
1647 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
1648 split and "num" is its length. lo_half and hi_half are output arrays
1649 that parallel "operands". */
1651 void
1652 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
1654 while (num--)
1656 rtx op = operands[num];
1658 lo_half[num] = c6x_subword (op, false);
1659 hi_half[num] = c6x_subword (op, true);
1663 /* Return true if VAL is a mask valid for a clr instruction. */
1664 bool
1665 c6x_valid_mask_p (HOST_WIDE_INT val)
1667 int i;
1668 for (i = 0; i < 32; i++)
1669 if (!(val & ((unsigned HOST_WIDE_INT)1 << i)))
1670 break;
1671 for (; i < 32; i++)
1672 if (val & ((unsigned HOST_WIDE_INT)1 << i))
1673 break;
1674 for (; i < 32; i++)
1675 if (!(val & ((unsigned HOST_WIDE_INT)1 << i)))
1676 return false;
1677 return true;
1680 /* Expand a block move for a movmemM pattern. */
1682 bool
1683 c6x_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp,
1684 rtx expected_align_exp ATTRIBUTE_UNUSED,
1685 rtx expected_size_exp ATTRIBUTE_UNUSED)
1687 unsigned HOST_WIDE_INT align = 1;
1688 unsigned HOST_WIDE_INT src_mem_align, dst_mem_align, min_mem_align;
1689 unsigned HOST_WIDE_INT count = 0, offset = 0;
1690 unsigned int biggest_move = TARGET_STDW ? 8 : 4;
1692 if (CONST_INT_P (align_exp))
1693 align = INTVAL (align_exp);
1695 src_mem_align = MEM_ALIGN (src) / BITS_PER_UNIT;
1696 dst_mem_align = MEM_ALIGN (dst) / BITS_PER_UNIT;
1697 min_mem_align = MIN (src_mem_align, dst_mem_align);
1699 if (min_mem_align > align)
1700 align = min_mem_align / BITS_PER_UNIT;
1701 if (src_mem_align < align)
1702 src_mem_align = align;
1703 if (dst_mem_align < align)
1704 dst_mem_align = align;
1706 if (CONST_INT_P (count_exp))
1707 count = INTVAL (count_exp);
1708 else
1709 return false;
1711 /* Make sure we don't need to care about overflow later on. */
1712 if (count > ((unsigned HOST_WIDE_INT) 1 << 30))
1713 return false;
1715 if (count >= 28 && (count & 3) == 0 && align >= 4)
1717 tree dst_expr = MEM_EXPR (dst);
1718 tree src_expr = MEM_EXPR (src);
1719 rtx fn = TARGET_INSNS_64PLUS ? strasgi64p_libfunc : strasgi_libfunc;
1720 rtx srcreg = force_reg (Pmode, XEXP (src, 0));
1721 rtx dstreg = force_reg (Pmode, XEXP (dst, 0));
1723 if (src_expr)
1724 mark_addressable (src_expr);
1725 if (dst_expr)
1726 mark_addressable (dst_expr);
1727 emit_library_call (fn, LCT_NORMAL, VOIDmode, 3,
1728 dstreg, Pmode, srcreg, Pmode, count_exp, SImode);
1729 return true;
1732 if (biggest_move > align && !TARGET_INSNS_64)
1733 biggest_move = align;
1735 if (count / biggest_move > 7)
1736 return false;
1738 while (count > 0)
1740 rtx reg, reg_lowpart;
1741 enum machine_mode srcmode, dstmode;
1742 unsigned HOST_WIDE_INT src_size, dst_size, src_left;
1743 int shift;
1744 rtx srcmem, dstmem;
1746 while (biggest_move > count)
1747 biggest_move /= 2;
1749 src_size = dst_size = biggest_move;
1750 if (src_size > src_mem_align && src_size == 2)
1751 src_size = 1;
1752 if (dst_size > dst_mem_align && dst_size == 2)
1753 dst_size = 1;
1755 if (dst_size > src_size)
1756 dst_size = src_size;
1758 srcmode = mode_for_size (src_size * BITS_PER_UNIT, MODE_INT, 0);
1759 dstmode = mode_for_size (dst_size * BITS_PER_UNIT, MODE_INT, 0);
1760 if (src_size >= 4)
1761 reg_lowpart = reg = gen_reg_rtx (srcmode);
1762 else
1764 reg = gen_reg_rtx (SImode);
1765 reg_lowpart = gen_lowpart (srcmode, reg);
1768 srcmem = adjust_address (copy_rtx (src), srcmode, offset);
1770 if (src_size > src_mem_align)
1772 enum insn_code icode = (srcmode == SImode ? CODE_FOR_movmisalignsi
1773 : CODE_FOR_movmisaligndi);
1774 emit_insn (GEN_FCN (icode) (reg_lowpart, srcmem));
1776 else
1777 emit_move_insn (reg_lowpart, srcmem);
1779 src_left = src_size;
1780 shift = TARGET_BIG_ENDIAN ? (src_size - dst_size) * BITS_PER_UNIT : 0;
1781 while (src_left > 0)
1783 rtx dstreg = reg_lowpart;
1785 if (src_size > dst_size)
1787 rtx srcword = reg;
1788 int shift_amount = shift & (BITS_PER_WORD - 1);
1789 if (src_size > 4)
1790 srcword = operand_subword_force (srcword, src_left >= 4 ? 0 : 4,
1791 SImode);
1792 if (shift_amount > 0)
1794 dstreg = gen_reg_rtx (SImode);
1795 emit_insn (gen_lshrsi3 (dstreg, srcword,
1796 GEN_INT (shift_amount)));
1798 else
1799 dstreg = srcword;
1800 dstreg = gen_lowpart (dstmode, dstreg);
1803 dstmem = adjust_address (copy_rtx (dst), dstmode, offset);
1804 if (dst_size > dst_mem_align)
1806 enum insn_code icode = (dstmode == SImode ? CODE_FOR_movmisalignsi
1807 : CODE_FOR_movmisaligndi);
1808 emit_insn (GEN_FCN (icode) (dstmem, dstreg));
1810 else
1811 emit_move_insn (dstmem, dstreg);
1813 if (TARGET_BIG_ENDIAN)
1814 shift -= dst_size * BITS_PER_UNIT;
1815 else
1816 shift += dst_size * BITS_PER_UNIT;
1817 offset += dst_size;
1818 src_left -= dst_size;
1820 count -= src_size;
1822 return true;
1825 /* Subroutine of print_address_operand, print a single address offset OFF for
1826 a memory access of mode MEM_MODE, choosing between normal form and scaled
1827 form depending on the type of the insn. Misaligned memory references must
1828 use the scaled form. */
1830 static void
1831 print_address_offset (FILE *file, rtx off, enum machine_mode mem_mode)
1833 rtx pat;
1835 if (c6x_current_insn != NULL_RTX)
1837 pat = PATTERN (c6x_current_insn);
1838 if (GET_CODE (pat) == COND_EXEC)
1839 pat = COND_EXEC_CODE (pat);
1840 if (GET_CODE (pat) == PARALLEL)
1841 pat = XVECEXP (pat, 0, 0);
1843 if (GET_CODE (pat) == SET
1844 && GET_CODE (SET_SRC (pat)) == UNSPEC
1845 && XINT (SET_SRC (pat), 1) == UNSPEC_MISALIGNED_ACCESS)
1847 gcc_assert (CONST_INT_P (off)
1848 && (INTVAL (off) & (GET_MODE_SIZE (mem_mode) - 1)) == 0);
1849 fprintf (file, "[" HOST_WIDE_INT_PRINT_DEC "]",
1850 INTVAL (off) / GET_MODE_SIZE (mem_mode));
1851 return;
1854 fputs ("(", file);
1855 output_address (off);
1856 fputs (")", file);
1859 static bool
1860 c6x_print_operand_punct_valid_p (unsigned char c)
1862 return c == '$' || c == '.' || c == '|';
1865 static void c6x_print_operand (FILE *, rtx, int);
1867 /* Subroutine of c6x_print_operand; used to print a memory reference X to FILE. */
1869 static void
1870 c6x_print_address_operand (FILE *file, rtx x, enum machine_mode mem_mode)
1872 rtx off;
1873 switch (GET_CODE (x))
1875 case PRE_MODIFY:
1876 case POST_MODIFY:
1877 if (GET_CODE (x) == POST_MODIFY)
1878 output_address (XEXP (x, 0));
1879 off = XEXP (XEXP (x, 1), 1);
1880 if (XEXP (x, 0) == stack_pointer_rtx)
1882 if (GET_CODE (x) == PRE_MODIFY)
1883 gcc_assert (INTVAL (off) > 0);
1884 else
1885 gcc_assert (INTVAL (off) < 0);
1887 if (CONST_INT_P (off) && INTVAL (off) < 0)
1889 fprintf (file, "--");
1890 off = GEN_INT (-INTVAL (off));
1892 else
1893 fprintf (file, "++");
1894 if (GET_CODE (x) == PRE_MODIFY)
1895 output_address (XEXP (x, 0));
1896 print_address_offset (file, off, mem_mode);
1897 break;
1899 case PLUS:
1900 off = XEXP (x, 1);
1901 if (CONST_INT_P (off) && INTVAL (off) < 0)
1903 fprintf (file, "-");
1904 off = GEN_INT (-INTVAL (off));
1906 else
1907 fprintf (file, "+");
1908 output_address (XEXP (x, 0));
1909 print_address_offset (file, off, mem_mode);
1910 break;
1912 case PRE_DEC:
1913 gcc_assert (XEXP (x, 0) != stack_pointer_rtx);
1914 fprintf (file, "--");
1915 output_address (XEXP (x, 0));
1916 fprintf (file, "[1]");
1917 break;
1918 case PRE_INC:
1919 fprintf (file, "++");
1920 output_address (XEXP (x, 0));
1921 fprintf (file, "[1]");
1922 break;
1923 case POST_INC:
1924 gcc_assert (XEXP (x, 0) != stack_pointer_rtx);
1925 output_address (XEXP (x, 0));
1926 fprintf (file, "++[1]");
1927 break;
1928 case POST_DEC:
1929 output_address (XEXP (x, 0));
1930 fprintf (file, "--[1]");
1931 break;
1933 case SYMBOL_REF:
1934 case CONST:
1935 case LABEL_REF:
1936 gcc_assert (sdata_symbolic_operand (x, Pmode));
1937 fprintf (file, "+B14(");
1938 output_addr_const (file, x);
1939 fprintf (file, ")");
1940 break;
1942 case UNSPEC:
1943 switch (XINT (x, 1))
1945 case UNSPEC_LOAD_GOT:
1946 fputs ("$GOT(", file);
1947 output_addr_const (file, XVECEXP (x, 0, 0));
1948 fputs (")", file);
1949 break;
1950 case UNSPEC_LOAD_SDATA:
1951 output_addr_const (file, XVECEXP (x, 0, 0));
1952 break;
1953 default:
1954 gcc_unreachable ();
1956 break;
1958 default:
1959 gcc_assert (GET_CODE (x) != MEM);
1960 c6x_print_operand (file, x, 0);
1961 break;
1965 /* Return a single character, which is either 'l', 's', 'd' or 'm', which
1966 specifies the functional unit used by INSN. */
1968 char
1969 c6x_get_unit_specifier (rtx insn)
1971 enum attr_units units;
1973 if (insn_info.exists ())
1975 int unit = INSN_INFO_ENTRY (INSN_UID (insn)).reservation;
1976 return c6x_unit_names[unit][0];
1979 units = get_attr_units (insn);
1980 switch (units)
1982 case UNITS_D:
1983 case UNITS_DL:
1984 case UNITS_DS:
1985 case UNITS_DLS:
1986 case UNITS_D_ADDR:
1987 return 'd';
1988 break;
1989 case UNITS_L:
1990 case UNITS_LS:
1991 return 'l';
1992 break;
1993 case UNITS_S:
1994 return 's';
1995 break;
1996 case UNITS_M:
1997 return 'm';
1998 break;
1999 default:
2000 gcc_unreachable ();
2004 /* Prints the unit specifier field. */
2005 static void
2006 c6x_print_unit_specifier_field (FILE *file, rtx insn)
2008 enum attr_units units = get_attr_units (insn);
2009 enum attr_cross cross = get_attr_cross (insn);
2010 enum attr_dest_regfile rf = get_attr_dest_regfile (insn);
2011 int half;
2012 char unitspec;
2014 if (units == UNITS_D_ADDR)
2016 enum attr_addr_regfile arf = get_attr_addr_regfile (insn);
2017 int t_half;
2018 gcc_assert (arf != ADDR_REGFILE_UNKNOWN);
2019 half = arf == ADDR_REGFILE_A ? 1 : 2;
2020 t_half = rf == DEST_REGFILE_A ? 1 : 2;
2021 fprintf (file, ".d%dt%d", half, t_half);
2022 return;
2025 if (insn_info.exists ())
2027 int unit = INSN_INFO_ENTRY (INSN_UID (insn)).reservation;
2028 fputs (".", file);
2029 fputs (c6x_unit_names[unit], file);
2030 if (cross == CROSS_Y)
2031 fputs ("x", file);
2032 return;
2035 gcc_assert (rf != DEST_REGFILE_UNKNOWN);
2036 unitspec = c6x_get_unit_specifier (insn);
2037 half = rf == DEST_REGFILE_A ? 1 : 2;
2038 fprintf (file, ".%c%d%s", unitspec, half, cross == CROSS_Y ? "x" : "");
2041 /* Output assembly language output for the address ADDR to FILE. */
2042 static void
2043 c6x_print_operand_address (FILE *file, rtx addr)
2045 c6x_print_address_operand (file, addr, VOIDmode);
2048 /* Print an operand, X, to FILE, with an optional modifier in CODE.
2050 Meaning of CODE:
2051 $ -- print the unit specifier field for the instruction.
2052 . -- print the predicate for the instruction or an emptry string for an
2053 unconditional one.
2054 | -- print "||" if the insn should be issued in parallel with the previous
2055 one.
2057 C -- print an opcode suffix for a reversed condition
2058 d -- H, W or D as a suffix for ADDA, based on the factor given by the
2059 operand
2060 D -- print either B, H, W or D as a suffix for ADDA, based on the size of
2061 the operand
2062 J -- print a predicate
2063 j -- like J, but use reverse predicate
2064 k -- treat a CONST_INT as a register number and print it as a register
2065 k -- like k, but print out a doubleword register
2066 n -- print an integer operand, negated
2067 p -- print the low part of a DImode register
2068 P -- print the high part of a DImode register
2069 r -- print the absolute value of an integer operand, shifted right by 1
2070 R -- print the absolute value of an integer operand, shifted right by 2
2071 f -- the first clear bit in an integer operand assumed to be a mask for
2072 a clr instruction
2073 F -- the last clear bit in such a mask
2074 s -- the first set bit in an integer operand assumed to be a mask for
2075 a set instruction
2076 S -- the last set bit in such a mask
2077 U -- print either 1 or 2, depending on the side of the machine used by
2078 the operand */
2080 static void
2081 c6x_print_operand (FILE *file, rtx x, int code)
2083 int i;
2084 HOST_WIDE_INT v;
2085 tree t;
2086 enum machine_mode mode;
2088 if (code == '|')
2090 if (GET_MODE (c6x_current_insn) != TImode)
2091 fputs ("||", file);
2092 return;
2094 if (code == '$')
2096 c6x_print_unit_specifier_field (file, c6x_current_insn);
2097 return;
2100 if (code == '.')
2102 x = current_insn_predicate;
2103 if (x)
2105 unsigned int regno = REGNO (XEXP (x, 0));
2106 fputs ("[", file);
2107 if (GET_CODE (x) == EQ)
2108 fputs ("!", file);
2109 fputs (reg_names [regno], file);
2110 fputs ("]", file);
2112 return;
2115 mode = GET_MODE (x);
2117 switch (code)
2119 case 'C':
2120 case 'c':
2122 enum rtx_code c = GET_CODE (x);
2123 if (code == 'C')
2124 c = swap_condition (c);
2125 fputs (GET_RTX_NAME (c), file);
2127 return;
2129 case 'J':
2130 case 'j':
2132 unsigned int regno = REGNO (XEXP (x, 0));
2133 if ((GET_CODE (x) == EQ) == (code == 'J'))
2134 fputs ("!", file);
2135 fputs (reg_names [regno], file);
2137 return;
2139 case 'k':
2140 gcc_assert (GET_CODE (x) == CONST_INT);
2141 v = INTVAL (x);
2142 fprintf (file, "%s", reg_names[v]);
2143 return;
2144 case 'K':
2145 gcc_assert (GET_CODE (x) == CONST_INT);
2146 v = INTVAL (x);
2147 gcc_assert ((v & 1) == 0);
2148 fprintf (file, "%s:%s", reg_names[v + 1], reg_names[v]);
2149 return;
2151 case 's':
2152 case 'S':
2153 case 'f':
2154 case 'F':
2155 gcc_assert (GET_CODE (x) == CONST_INT);
2156 v = INTVAL (x);
2157 for (i = 0; i < 32; i++)
2159 HOST_WIDE_INT tst = v & 1;
2160 if (((code == 'f' || code == 'F') && !tst)
2161 || ((code == 's' || code == 'S') && tst))
2162 break;
2163 v >>= 1;
2165 if (code == 'f' || code == 's')
2167 fprintf (file, "%d", i);
2168 return;
2170 for (;i < 32; i++)
2172 HOST_WIDE_INT tst = v & 1;
2173 if ((code == 'F' && tst) || (code == 'S' && !tst))
2174 break;
2175 v >>= 1;
2177 fprintf (file, "%d", i - 1);
2178 return;
2180 case 'n':
2181 gcc_assert (GET_CODE (x) == CONST_INT);
2182 output_addr_const (file, GEN_INT (-INTVAL (x)));
2183 return;
2185 case 'r':
2186 gcc_assert (GET_CODE (x) == CONST_INT);
2187 v = INTVAL (x);
2188 if (v < 0)
2189 v = -v;
2190 output_addr_const (file, GEN_INT (v >> 1));
2191 return;
2193 case 'R':
2194 gcc_assert (GET_CODE (x) == CONST_INT);
2195 v = INTVAL (x);
2196 if (v < 0)
2197 v = -v;
2198 output_addr_const (file, GEN_INT (v >> 2));
2199 return;
2201 case 'd':
2202 gcc_assert (GET_CODE (x) == CONST_INT);
2203 v = INTVAL (x);
2204 fputs (v == 2 ? "h" : v == 4 ? "w" : "d", file);
2205 return;
2207 case 'p':
2208 case 'P':
2209 gcc_assert (GET_CODE (x) == REG);
2210 v = REGNO (x);
2211 if (code == 'P')
2212 v++;
2213 fputs (reg_names[v], file);
2214 return;
2216 case 'D':
2217 v = 0;
2218 if (GET_CODE (x) == CONST)
2220 x = XEXP (x, 0);
2221 gcc_assert (GET_CODE (x) == PLUS);
2222 gcc_assert (GET_CODE (XEXP (x, 1)) == CONST_INT);
2223 v = INTVAL (XEXP (x, 1));
2224 x = XEXP (x, 0);
2227 gcc_assert (GET_CODE (x) == SYMBOL_REF);
2229 t = SYMBOL_REF_DECL (x);
2230 if (DECL_P (t))
2231 v |= DECL_ALIGN_UNIT (t);
2232 else
2233 v |= TYPE_ALIGN_UNIT (TREE_TYPE (t));
2234 if (v & 1)
2235 fputs ("b", file);
2236 else if (v & 2)
2237 fputs ("h", file);
2238 else
2239 fputs ("w", file);
2240 return;
2242 case 'U':
2243 if (MEM_P (x))
2245 x = XEXP (x, 0);
2246 if (GET_CODE (x) == PLUS
2247 || GET_RTX_CLASS (GET_CODE (x)) == RTX_AUTOINC)
2248 x = XEXP (x, 0);
2249 if (GET_CODE (x) == CONST || GET_CODE (x) == SYMBOL_REF)
2251 gcc_assert (sdata_symbolic_operand (x, Pmode));
2252 fputs ("2", file);
2253 return;
2256 gcc_assert (REG_P (x));
2257 if (A_REGNO_P (REGNO (x)))
2258 fputs ("1", file);
2259 if (B_REGNO_P (REGNO (x)))
2260 fputs ("2", file);
2261 return;
2263 default:
2264 switch (GET_CODE (x))
2266 case REG:
2267 if (GET_MODE_SIZE (mode) == 8)
2268 fprintf (file, "%s:%s", reg_names[REGNO (x) + 1],
2269 reg_names[REGNO (x)]);
2270 else
2271 fprintf (file, "%s", reg_names[REGNO (x)]);
2272 break;
2274 case MEM:
2275 fputc ('*', file);
2276 gcc_assert (XEXP (x, 0) != stack_pointer_rtx);
2277 c6x_print_address_operand (file, XEXP (x, 0), GET_MODE (x));
2278 break;
2280 case SYMBOL_REF:
2281 fputc ('(', file);
2282 output_addr_const (file, x);
2283 fputc (')', file);
2284 break;
2286 case CONST_INT:
2287 output_addr_const (file, x);
2288 break;
2290 case CONST_DOUBLE:
2291 output_operand_lossage ("invalid const_double operand");
2292 break;
2294 default:
2295 output_addr_const (file, x);
2300 /* Return TRUE if OP is a valid memory address with a base register of
2301 class C. If SMALL_OFFSET is true, we disallow memory references which would
2302 require a long offset with B14/B15. */
2304 bool
2305 c6x_mem_operand (rtx op, enum reg_class c, bool small_offset)
2307 enum machine_mode mode = GET_MODE (op);
2308 rtx base = XEXP (op, 0);
2309 switch (GET_CODE (base))
2311 case REG:
2312 break;
2313 case PLUS:
2314 if (small_offset
2315 && (XEXP (base, 0) == stack_pointer_rtx
2316 || XEXP (base, 0) == pic_offset_table_rtx))
2318 if (!c6x_legitimate_address_p_1 (mode, base, true, true))
2319 return false;
2322 /* fall through */
2323 case PRE_INC:
2324 case PRE_DEC:
2325 case PRE_MODIFY:
2326 case POST_INC:
2327 case POST_DEC:
2328 case POST_MODIFY:
2329 base = XEXP (base, 0);
2330 break;
2332 case CONST:
2333 case LABEL_REF:
2334 case SYMBOL_REF:
2335 gcc_assert (sdata_symbolic_operand (base, Pmode));
2336 return !small_offset && c == B_REGS;
2338 default:
2339 return false;
2341 return TEST_HARD_REG_BIT (reg_class_contents[ (int) (c)], REGNO (base));
2344 /* Returns true if X is a valid address for use in a memory reference
2345 of mode MODE. If STRICT is true, we do not allow pseudo registers
2346 in the address. NO_LARGE_OFFSET is true if we are examining an
2347 address for use in a load or store misaligned instruction, or
2348 recursively examining an operand inside a PRE/POST_MODIFY. */
2350 bool
2351 c6x_legitimate_address_p_1 (enum machine_mode mode, rtx x, bool strict,
2352 bool no_large_offset)
2354 int size, size1;
2355 HOST_WIDE_INT off;
2356 enum rtx_code code = GET_CODE (x);
2358 switch (code)
2360 case PRE_MODIFY:
2361 case POST_MODIFY:
2362 /* We can't split these into word-sized pieces yet. */
2363 if (!TARGET_STDW && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
2364 return false;
2365 if (GET_CODE (XEXP (x, 1)) != PLUS)
2366 return false;
2367 if (!c6x_legitimate_address_p_1 (mode, XEXP (x, 1), strict, true))
2368 return false;
2369 if (!rtx_equal_p (XEXP (x, 0), XEXP (XEXP (x, 1), 0)))
2370 return false;
2372 /* fall through */
2373 case PRE_INC:
2374 case PRE_DEC:
2375 case POST_INC:
2376 case POST_DEC:
2377 /* We can't split these into word-sized pieces yet. */
2378 if (!TARGET_STDW && GET_MODE_SIZE (mode) > UNITS_PER_WORD)
2379 return false;
2380 x = XEXP (x, 0);
2381 if (!REG_P (x))
2382 return false;
2384 /* fall through */
2385 case REG:
2386 if (strict)
2387 return REGNO_OK_FOR_BASE_STRICT_P (REGNO (x));
2388 else
2389 return REGNO_OK_FOR_BASE_NONSTRICT_P (REGNO (x));
2391 case PLUS:
2392 if (!REG_P (XEXP (x, 0))
2393 || !c6x_legitimate_address_p_1 (mode, XEXP (x, 0), strict, false))
2394 return false;
2395 /* We cannot ensure currently that both registers end up in the
2396 same register file. */
2397 if (REG_P (XEXP (x, 1)))
2398 return false;
2400 if (mode == BLKmode)
2401 size = 4;
2402 else if (mode == VOIDmode)
2403 /* ??? This can happen during ivopts. */
2404 size = 1;
2405 else
2406 size = GET_MODE_SIZE (mode);
2408 if (flag_pic
2409 && GET_CODE (XEXP (x, 1)) == UNSPEC
2410 && XINT (XEXP (x, 1), 1) == UNSPEC_LOAD_SDATA
2411 && XEXP (x, 0) == pic_offset_table_rtx
2412 && sdata_symbolic_operand (XVECEXP (XEXP (x, 1), 0, 0), SImode))
2413 return !no_large_offset && size <= 4;
2414 if (flag_pic == 1
2415 && mode == Pmode
2416 && GET_CODE (XEXP (x, 1)) == UNSPEC
2417 && XINT (XEXP (x, 1), 1) == UNSPEC_LOAD_GOT
2418 && XEXP (x, 0) == pic_offset_table_rtx
2419 && (GET_CODE (XVECEXP (XEXP (x, 1), 0, 0)) == SYMBOL_REF
2420 || GET_CODE (XVECEXP (XEXP (x, 1), 0, 0)) == LABEL_REF))
2421 return !no_large_offset;
2422 if (GET_CODE (XEXP (x, 1)) != CONST_INT)
2423 return false;
2425 off = INTVAL (XEXP (x, 1));
2427 /* If the machine does not have doubleword load/stores, we'll use
2428 word size accesses. */
2429 size1 = size;
2430 if (size == 2 * UNITS_PER_WORD && !TARGET_STDW)
2431 size = UNITS_PER_WORD;
2433 if (((HOST_WIDE_INT)size1 - 1) & off)
2434 return false;
2435 off /= size;
2436 if (off > -32 && off < (size1 == size ? 32 : 28))
2437 return true;
2438 if (no_large_offset || code != PLUS || XEXP (x, 0) != stack_pointer_rtx
2439 || size1 > UNITS_PER_WORD)
2440 return false;
2441 return off >= 0 && off < 32768;
2443 case CONST:
2444 case SYMBOL_REF:
2445 case LABEL_REF:
2446 return (!no_large_offset
2447 /* With -fpic, we must wrap it in an unspec to show the B14
2448 dependency. */
2449 && !flag_pic
2450 && GET_MODE_SIZE (mode) <= UNITS_PER_WORD
2451 && sdata_symbolic_operand (x, Pmode));
2453 default:
2454 return false;
2458 static bool
2459 c6x_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
2461 return c6x_legitimate_address_p_1 (mode, x, strict, false);
2464 static bool
2465 c6x_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED,
2466 rtx x ATTRIBUTE_UNUSED)
2468 return true;
2471 /* Implements TARGET_PREFERRED_RENAME_CLASS. */
2472 static reg_class_t
2473 c6x_preferred_rename_class (reg_class_t cl)
2475 if (cl == A_REGS)
2476 return NONPREDICATE_A_REGS;
2477 if (cl == B_REGS)
2478 return NONPREDICATE_B_REGS;
2479 if (cl == ALL_REGS || cl == GENERAL_REGS)
2480 return NONPREDICATE_REGS;
2481 return NO_REGS;
2484 /* Implements FINAL_PRESCAN_INSN. */
2485 void
2486 c6x_final_prescan_insn (rtx insn, rtx *opvec ATTRIBUTE_UNUSED,
2487 int noperands ATTRIBUTE_UNUSED)
2489 c6x_current_insn = insn;
2492 /* A structure to describe the stack layout of a function. The layout is
2493 as follows:
2495 [saved frame pointer (or possibly padding0)]
2496 --> incoming stack pointer, new hard frame pointer
2497 [saved call-used regs]
2498 [optional padding1]
2499 --> soft frame pointer
2500 [frame]
2501 [outgoing arguments]
2502 [optional padding2]
2504 The structure members are laid out in this order. */
2506 struct c6x_frame
2508 int padding0;
2509 /* Number of registers to save. */
2510 int nregs;
2511 int padding1;
2512 HOST_WIDE_INT frame;
2513 int outgoing_arguments_size;
2514 int padding2;
2516 HOST_WIDE_INT to_allocate;
2517 /* The offsets relative to the incoming stack pointer (which
2518 becomes HARD_FRAME_POINTER). */
2519 HOST_WIDE_INT frame_pointer_offset;
2520 HOST_WIDE_INT b3_offset;
2522 /* True if we should call push_rts/pop_rts to save and restore
2523 registers. */
2524 bool push_rts;
2527 /* Return true if we need to save and modify the PIC register in the
2528 prologue. */
2530 static bool
2531 must_reload_pic_reg_p (void)
2533 struct cgraph_local_info *i = NULL;
2535 if (!TARGET_DSBT)
2536 return false;
2538 i = cgraph_local_info (current_function_decl);
2540 if ((crtl->uses_pic_offset_table || !crtl->is_leaf) && !i->local)
2541 return true;
2542 return false;
2545 /* Return 1 if we need to save REGNO. */
2546 static int
2547 c6x_save_reg (unsigned int regno)
2549 return ((df_regs_ever_live_p (regno)
2550 && !call_used_regs[regno]
2551 && !fixed_regs[regno])
2552 || (regno == RETURN_ADDR_REGNO
2553 && (df_regs_ever_live_p (regno)
2554 || !crtl->is_leaf))
2555 || (regno == PIC_OFFSET_TABLE_REGNUM && must_reload_pic_reg_p ()));
2558 /* Examine the number of regs NREGS we've determined we must save.
2559 Return true if we should use __c6xabi_push_rts/__c6xabi_pop_rts for
2560 prologue and epilogue. */
2562 static bool
2563 use_push_rts_p (int nregs)
2565 if (TARGET_INSNS_64PLUS && optimize_function_for_size_p (cfun)
2566 && !cfun->machine->contains_sibcall
2567 && !cfun->returns_struct
2568 && !TARGET_LONG_CALLS
2569 && nregs >= 6 && !frame_pointer_needed)
2570 return true;
2571 return false;
2574 /* Return number of saved general prupose registers. */
2577 c6x_nsaved_regs (void)
2579 int nregs = 0;
2580 int regno;
2582 for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
2583 if (c6x_save_reg (regno))
2584 nregs++;
2585 return nregs;
2588 /* The safe debug order mandated by the ABI. */
2589 static unsigned reg_save_order[] =
2591 REG_A10, REG_A11, REG_A12, REG_A13,
2592 REG_A14, REG_B3,
2593 REG_B10, REG_B11, REG_B12, REG_B13,
2594 REG_B14, REG_A15
2597 #define N_SAVE_ORDER (sizeof reg_save_order / sizeof *reg_save_order)
2599 /* Compute the layout of the stack frame and store it in FRAME. */
2601 static void
2602 c6x_compute_frame_layout (struct c6x_frame *frame)
2604 HOST_WIDE_INT size = get_frame_size ();
2605 HOST_WIDE_INT offset;
2606 int nregs;
2608 /* We use the four bytes which are technically inside the caller's frame,
2609 usually to save the frame pointer. */
2610 offset = -4;
2611 frame->padding0 = 0;
2612 nregs = c6x_nsaved_regs ();
2613 frame->push_rts = false;
2614 frame->b3_offset = 0;
2615 if (use_push_rts_p (nregs))
2617 frame->push_rts = true;
2618 frame->b3_offset = (TARGET_BIG_ENDIAN ? -12 : -13) * 4;
2619 nregs = 14;
2621 else if (c6x_save_reg (REG_B3))
2623 int idx;
2624 for (idx = N_SAVE_ORDER - 1; reg_save_order[idx] != REG_B3; idx--)
2626 if (c6x_save_reg (reg_save_order[idx]))
2627 frame->b3_offset -= 4;
2630 frame->nregs = nregs;
2632 if (size == 0 && nregs == 0)
2634 frame->padding0 = 4;
2635 frame->padding1 = frame->padding2 = 0;
2636 frame->frame_pointer_offset = frame->to_allocate = 0;
2637 frame->outgoing_arguments_size = 0;
2638 return;
2641 if (!frame->push_rts)
2642 offset += frame->nregs * 4;
2644 if (offset == 0 && size == 0 && crtl->outgoing_args_size == 0
2645 && !crtl->is_leaf)
2646 /* Don't use the bottom of the caller's frame if we have no
2647 allocation of our own and call other functions. */
2648 frame->padding0 = frame->padding1 = 4;
2649 else if (offset & 4)
2650 frame->padding1 = 4;
2651 else
2652 frame->padding1 = 0;
2654 offset += frame->padding0 + frame->padding1;
2655 frame->frame_pointer_offset = offset;
2656 offset += size;
2658 frame->outgoing_arguments_size = crtl->outgoing_args_size;
2659 offset += frame->outgoing_arguments_size;
2661 if ((offset & 4) == 0)
2662 frame->padding2 = 8;
2663 else
2664 frame->padding2 = 4;
2665 frame->to_allocate = offset + frame->padding2;
2668 /* Return the offset between two registers, one to be eliminated, and the other
2669 its replacement, at the start of a routine. */
2671 HOST_WIDE_INT
2672 c6x_initial_elimination_offset (int from, int to)
2674 struct c6x_frame frame;
2675 c6x_compute_frame_layout (&frame);
2677 if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
2678 return 0;
2679 else if (from == FRAME_POINTER_REGNUM
2680 && to == HARD_FRAME_POINTER_REGNUM)
2681 return -frame.frame_pointer_offset;
2682 else
2684 gcc_assert (to == STACK_POINTER_REGNUM);
2686 if (from == ARG_POINTER_REGNUM)
2687 return frame.to_allocate + (frame.push_rts ? 56 : 0);
2689 gcc_assert (from == FRAME_POINTER_REGNUM);
2690 return frame.to_allocate - frame.frame_pointer_offset;
2694 /* Given FROM and TO register numbers, say whether this elimination is
2695 allowed. Frame pointer elimination is automatically handled. */
2697 static bool
2698 c6x_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
2700 if (to == STACK_POINTER_REGNUM)
2701 return !frame_pointer_needed;
2702 return true;
2705 /* Emit insns to increment the stack pointer by OFFSET. If
2706 FRAME_RELATED_P, set the RTX_FRAME_RELATED_P flag on the insns.
2707 Does nothing if the offset is zero. */
2709 static void
2710 emit_add_sp_const (HOST_WIDE_INT offset, bool frame_related_p)
2712 rtx to_add = GEN_INT (offset);
2713 rtx orig_to_add = to_add;
2714 rtx insn;
2716 if (offset == 0)
2717 return;
2719 if (offset < -32768 || offset > 32767)
2721 rtx reg = gen_rtx_REG (SImode, REG_A0);
2722 rtx low = GEN_INT (trunc_int_for_mode (offset, HImode));
2724 insn = emit_insn (gen_movsi_high (reg, low));
2725 if (frame_related_p)
2726 RTX_FRAME_RELATED_P (insn) = 1;
2727 insn = emit_insn (gen_movsi_lo_sum (reg, reg, to_add));
2728 if (frame_related_p)
2729 RTX_FRAME_RELATED_P (insn) = 1;
2730 to_add = reg;
2732 insn = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
2733 to_add));
2734 if (frame_related_p)
2736 if (REG_P (to_add))
2737 add_reg_note (insn, REG_FRAME_RELATED_EXPR,
2738 gen_rtx_SET (VOIDmode, stack_pointer_rtx,
2739 gen_rtx_PLUS (Pmode, stack_pointer_rtx,
2740 orig_to_add)));
2742 RTX_FRAME_RELATED_P (insn) = 1;
2746 /* Prologue and epilogue. */
2747 void
2748 c6x_expand_prologue (void)
2750 struct c6x_frame frame;
2751 rtx insn, mem;
2752 int nsaved = 0;
2753 HOST_WIDE_INT initial_offset, off, added_already;
2755 c6x_compute_frame_layout (&frame);
2757 if (flag_stack_usage_info)
2758 current_function_static_stack_size = frame.to_allocate;
2760 initial_offset = -frame.to_allocate;
2761 if (frame.push_rts)
2763 emit_insn (gen_push_rts ());
2764 nsaved = frame.nregs;
2767 /* If the offsets would be too large for the memory references we will
2768 create to save registers, do the stack allocation in two parts.
2769 Ensure by subtracting 8 that we don't store to the word pointed to
2770 by the stack pointer. */
2771 if (initial_offset < -32768)
2772 initial_offset = -frame.frame_pointer_offset - 8;
2774 if (frame.to_allocate > 0)
2775 gcc_assert (initial_offset != 0);
2777 off = -initial_offset + 4 - frame.padding0;
2779 mem = gen_frame_mem (Pmode, stack_pointer_rtx);
2781 added_already = 0;
2782 if (frame_pointer_needed)
2784 rtx fp_reg = gen_rtx_REG (SImode, REG_A15);
2785 /* We go through some contortions here to both follow the ABI's
2786 recommendation that FP == incoming SP, and to avoid writing or
2787 reading the word pointed to by the stack pointer. */
2788 rtx addr = gen_rtx_POST_MODIFY (Pmode, stack_pointer_rtx,
2789 gen_rtx_PLUS (Pmode, stack_pointer_rtx,
2790 GEN_INT (-8)));
2791 insn = emit_move_insn (gen_frame_mem (Pmode, addr), fp_reg);
2792 RTX_FRAME_RELATED_P (insn) = 1;
2793 nsaved++;
2794 insn = emit_insn (gen_addsi3 (hard_frame_pointer_rtx, stack_pointer_rtx,
2795 GEN_INT (8)));
2796 RTX_FRAME_RELATED_P (insn) = 1;
2797 off -= 4;
2798 added_already = -8;
2801 emit_add_sp_const (initial_offset - added_already, true);
2803 if (nsaved < frame.nregs)
2805 unsigned i;
2807 for (i = 0; i < N_SAVE_ORDER; i++)
2809 int idx = N_SAVE_ORDER - i - 1;
2810 unsigned regno = reg_save_order[idx];
2811 rtx reg;
2812 enum machine_mode save_mode = SImode;
2814 if (regno == REG_A15 && frame_pointer_needed)
2815 /* Already saved. */
2816 continue;
2817 if (!c6x_save_reg (regno))
2818 continue;
2820 if (TARGET_STDW && (off & 4) == 0 && off <= 256
2821 && (regno & 1) == 1
2822 && i + 1 < N_SAVE_ORDER
2823 && reg_save_order[idx - 1] == regno - 1
2824 && c6x_save_reg (regno - 1))
2826 save_mode = DImode;
2827 regno--;
2828 i++;
2830 reg = gen_rtx_REG (save_mode, regno);
2831 off -= GET_MODE_SIZE (save_mode);
2833 insn = emit_move_insn (adjust_address (mem, save_mode, off),
2834 reg);
2835 RTX_FRAME_RELATED_P (insn) = 1;
2837 nsaved += HARD_REGNO_NREGS (regno, save_mode);
2840 gcc_assert (nsaved == frame.nregs);
2841 emit_add_sp_const (-frame.to_allocate - initial_offset, true);
2842 if (must_reload_pic_reg_p ())
2844 if (dsbt_decl == NULL)
2846 tree t;
2848 t = build_index_type (integer_one_node);
2849 t = build_array_type (integer_type_node, t);
2850 t = build_decl (BUILTINS_LOCATION, VAR_DECL,
2851 get_identifier ("__c6xabi_DSBT_BASE"), t);
2852 DECL_ARTIFICIAL (t) = 1;
2853 DECL_IGNORED_P (t) = 1;
2854 DECL_EXTERNAL (t) = 1;
2855 TREE_STATIC (t) = 1;
2856 TREE_PUBLIC (t) = 1;
2857 TREE_USED (t) = 1;
2859 dsbt_decl = t;
2861 emit_insn (gen_setup_dsbt (pic_offset_table_rtx,
2862 XEXP (DECL_RTL (dsbt_decl), 0)));
2866 void
2867 c6x_expand_epilogue (bool sibcall)
2869 unsigned i;
2870 struct c6x_frame frame;
2871 rtx mem;
2872 HOST_WIDE_INT off;
2873 int nsaved = 0;
2875 c6x_compute_frame_layout (&frame);
2877 mem = gen_frame_mem (Pmode, stack_pointer_rtx);
2879 /* Insert a dummy set/use of the stack pointer. This creates a
2880 scheduler barrier between the prologue saves and epilogue restores. */
2881 emit_insn (gen_epilogue_barrier (stack_pointer_rtx, stack_pointer_rtx));
2883 /* If the offsets would be too large for the memory references we will
2884 create to restore registers, do a preliminary stack adjustment here. */
2885 off = frame.to_allocate - frame.frame_pointer_offset + frame.padding1;
2886 if (frame.push_rts)
2888 nsaved = frame.nregs;
2890 else
2892 if (frame.to_allocate > 32768)
2894 /* Don't add the entire offset so that we leave an unused word
2895 above the stack pointer. */
2896 emit_add_sp_const ((off - 16) & ~7, false);
2897 off &= 7;
2898 off += 16;
2900 for (i = 0; i < N_SAVE_ORDER; i++)
2902 unsigned regno = reg_save_order[i];
2903 rtx reg;
2904 enum machine_mode save_mode = SImode;
2906 if (!c6x_save_reg (regno))
2907 continue;
2908 if (regno == REG_A15 && frame_pointer_needed)
2909 continue;
2911 if (TARGET_STDW && (off & 4) == 0 && off < 256
2912 && (regno & 1) == 0
2913 && i + 1 < N_SAVE_ORDER
2914 && reg_save_order[i + 1] == regno + 1
2915 && c6x_save_reg (regno + 1))
2917 save_mode = DImode;
2918 i++;
2920 reg = gen_rtx_REG (save_mode, regno);
2922 emit_move_insn (reg, adjust_address (mem, save_mode, off));
2924 off += GET_MODE_SIZE (save_mode);
2925 nsaved += HARD_REGNO_NREGS (regno, save_mode);
2928 if (!frame_pointer_needed)
2929 emit_add_sp_const (off + frame.padding0 - 4, false);
2930 else
2932 rtx fp_reg = gen_rtx_REG (SImode, REG_A15);
2933 rtx addr = gen_rtx_PRE_MODIFY (Pmode, stack_pointer_rtx,
2934 gen_rtx_PLUS (Pmode, stack_pointer_rtx,
2935 GEN_INT (8)));
2936 emit_insn (gen_addsi3 (stack_pointer_rtx, hard_frame_pointer_rtx,
2937 GEN_INT (-8)));
2938 emit_move_insn (fp_reg, gen_frame_mem (Pmode, addr));
2939 nsaved++;
2941 gcc_assert (nsaved == frame.nregs);
2942 if (!sibcall)
2944 if (frame.push_rts)
2945 emit_jump_insn (gen_pop_rts ());
2946 else
2947 emit_jump_insn (gen_return_internal (gen_rtx_REG (SImode,
2948 RETURN_ADDR_REGNO)));
2952 /* Return the value of the return address for the frame COUNT steps up
2953 from the current frame, after the prologue.
2954 We punt for everything but the current frame by returning const0_rtx. */
2957 c6x_return_addr_rtx (int count)
2959 if (count != 0)
2960 return const0_rtx;
2962 return get_hard_reg_initial_val (Pmode, RETURN_ADDR_REGNO);
2965 /* Return true iff TYPE is one of the shadow types. */
2966 static bool
2967 shadow_type_p (enum attr_type type)
2969 return (type == TYPE_SHADOW || type == TYPE_LOAD_SHADOW
2970 || type == TYPE_MULT_SHADOW);
2973 /* Return true iff INSN is a shadow pattern. */
2974 static bool
2975 shadow_p (rtx insn)
2977 if (!NONDEBUG_INSN_P (insn) || recog_memoized (insn) < 0)
2978 return false;
2979 return shadow_type_p (get_attr_type (insn));
2982 /* Return true iff INSN is a shadow or blockage pattern. */
2983 static bool
2984 shadow_or_blockage_p (rtx insn)
2986 enum attr_type type;
2987 if (!NONDEBUG_INSN_P (insn) || recog_memoized (insn) < 0)
2988 return false;
2989 type = get_attr_type (insn);
2990 return shadow_type_p (type) || type == TYPE_BLOCKAGE;
2993 /* Translate UNITS into a bitmask of units we can reserve for this
2994 insn. */
2995 static int
2996 get_reservation_flags (enum attr_units units)
2998 switch (units)
3000 case UNITS_D:
3001 case UNITS_D_ADDR:
3002 return RESERVATION_FLAG_D;
3003 case UNITS_L:
3004 return RESERVATION_FLAG_L;
3005 case UNITS_S:
3006 return RESERVATION_FLAG_S;
3007 case UNITS_M:
3008 return RESERVATION_FLAG_M;
3009 case UNITS_LS:
3010 return RESERVATION_FLAG_LS;
3011 case UNITS_DL:
3012 return RESERVATION_FLAG_DL;
3013 case UNITS_DS:
3014 return RESERVATION_FLAG_DS;
3015 case UNITS_DLS:
3016 return RESERVATION_FLAG_DLS;
3017 default:
3018 return 0;
3022 /* Compute the side of the machine used by INSN, which reserves UNITS.
3023 This must match the reservations in the scheduling description. */
3024 static int
3025 get_insn_side (rtx insn, enum attr_units units)
3027 if (units == UNITS_D_ADDR)
3028 return (get_attr_addr_regfile (insn) == ADDR_REGFILE_A ? 0 : 1);
3029 else
3031 enum attr_dest_regfile rf = get_attr_dest_regfile (insn);
3032 if (rf == DEST_REGFILE_ANY)
3033 return get_attr_type (insn) == TYPE_BRANCH ? 0 : 1;
3034 else
3035 return rf == DEST_REGFILE_A ? 0 : 1;
3039 /* After scheduling, walk the insns between HEAD and END and assign unit
3040 reservations. */
3041 static void
3042 assign_reservations (rtx head, rtx end)
3044 rtx insn;
3045 for (insn = head; insn != NEXT_INSN (end); insn = NEXT_INSN (insn))
3047 unsigned int sched_mask, reserved;
3048 rtx within, last;
3049 int pass;
3050 int rsrv[2];
3051 int rsrv_count[2][4];
3052 int i;
3054 if (GET_MODE (insn) != TImode)
3055 continue;
3057 reserved = 0;
3058 last = NULL_RTX;
3059 /* Find the last insn in the packet. It has a state recorded for it,
3060 which we can use to determine the units we should be using. */
3061 for (within = insn;
3062 (within != NEXT_INSN (end)
3063 && (within == insn || GET_MODE (within) != TImode));
3064 within = NEXT_INSN (within))
3066 int icode;
3067 if (!NONDEBUG_INSN_P (within))
3068 continue;
3069 icode = recog_memoized (within);
3070 if (icode < 0)
3071 continue;
3072 if (shadow_p (within))
3073 continue;
3074 if (INSN_INFO_ENTRY (INSN_UID (within)).reservation != 0)
3075 reserved |= 1 << INSN_INFO_ENTRY (INSN_UID (within)).reservation;
3076 last = within;
3078 if (last == NULL_RTX)
3079 continue;
3081 sched_mask = INSN_INFO_ENTRY (INSN_UID (last)).unit_mask;
3082 sched_mask &= ~reserved;
3084 memset (rsrv_count, 0, sizeof rsrv_count);
3085 rsrv[0] = rsrv[1] = ~0;
3086 for (i = 0; i < 8; i++)
3088 int side = i / 4;
3089 int unit = i & 3;
3090 unsigned unit_bit = 1 << (unit + side * UNIT_QID_SIDE_OFFSET);
3091 /* Clear the bits which we expect to reserve in the following loop,
3092 leaving the ones set which aren't present in the scheduler's
3093 state and shouldn't be reserved. */
3094 if (sched_mask & unit_bit)
3095 rsrv[i / 4] &= ~(1 << unit);
3098 /* Walk through the insns that occur in the same cycle. We use multiple
3099 passes to assign units, assigning for insns with the most specific
3100 requirements first. */
3101 for (pass = 0; pass < 4; pass++)
3102 for (within = insn;
3103 (within != NEXT_INSN (end)
3104 && (within == insn || GET_MODE (within) != TImode));
3105 within = NEXT_INSN (within))
3107 int uid = INSN_UID (within);
3108 int this_rsrv, side;
3109 int icode;
3110 enum attr_units units;
3111 enum attr_type type;
3112 int j;
3114 if (!NONDEBUG_INSN_P (within))
3115 continue;
3116 icode = recog_memoized (within);
3117 if (icode < 0)
3118 continue;
3119 if (INSN_INFO_ENTRY (uid).reservation != 0)
3120 continue;
3121 units = get_attr_units (within);
3122 type = get_attr_type (within);
3123 this_rsrv = get_reservation_flags (units);
3124 if (this_rsrv == 0)
3125 continue;
3126 side = get_insn_side (within, units);
3128 /* Certain floating point instructions are treated specially. If
3129 an insn can choose between units it can reserve, and its
3130 reservation spans more than one cycle, the reservation contains
3131 special markers in the first cycle to help us reconstruct what
3132 the automaton chose. */
3133 if ((type == TYPE_ADDDP || type == TYPE_FP4)
3134 && units == UNITS_LS)
3136 int test1_code = ((type == TYPE_FP4 ? UNIT_QID_FPL1 : UNIT_QID_ADDDPL1)
3137 + side * UNIT_QID_SIDE_OFFSET);
3138 int test2_code = ((type == TYPE_FP4 ? UNIT_QID_FPS1 : UNIT_QID_ADDDPS1)
3139 + side * UNIT_QID_SIDE_OFFSET);
3140 if ((sched_mask & (1 << test1_code)) != 0)
3142 this_rsrv = RESERVATION_FLAG_L;
3143 sched_mask &= ~(1 << test1_code);
3145 else if ((sched_mask & (1 << test2_code)) != 0)
3147 this_rsrv = RESERVATION_FLAG_S;
3148 sched_mask &= ~(1 << test2_code);
3152 if ((this_rsrv & (this_rsrv - 1)) == 0)
3154 int t = exact_log2 (this_rsrv) + side * UNIT_QID_SIDE_OFFSET;
3155 rsrv[side] |= this_rsrv;
3156 INSN_INFO_ENTRY (uid).reservation = t;
3157 continue;
3160 if (pass == 1)
3162 for (j = 0; j < 4; j++)
3163 if (this_rsrv & (1 << j))
3164 rsrv_count[side][j]++;
3165 continue;
3167 if ((pass == 2 && this_rsrv != RESERVATION_FLAG_DLS)
3168 || (pass == 3 && this_rsrv == RESERVATION_FLAG_DLS))
3170 int best = -1, best_cost = INT_MAX;
3171 for (j = 0; j < 4; j++)
3172 if ((this_rsrv & (1 << j))
3173 && !(rsrv[side] & (1 << j))
3174 && rsrv_count[side][j] < best_cost)
3176 best_cost = rsrv_count[side][j];
3177 best = j;
3179 gcc_assert (best != -1);
3180 rsrv[side] |= 1 << best;
3181 for (j = 0; j < 4; j++)
3182 if ((this_rsrv & (1 << j)) && j != best)
3183 rsrv_count[side][j]--;
3185 INSN_INFO_ENTRY (uid).reservation
3186 = best + side * UNIT_QID_SIDE_OFFSET;
3192 /* Return a factor by which to weight unit imbalances for a reservation
3193 R. */
3194 static int
3195 unit_req_factor (enum unitreqs r)
3197 switch (r)
3199 case UNIT_REQ_D:
3200 case UNIT_REQ_L:
3201 case UNIT_REQ_S:
3202 case UNIT_REQ_M:
3203 case UNIT_REQ_X:
3204 case UNIT_REQ_T:
3205 return 1;
3206 case UNIT_REQ_DL:
3207 case UNIT_REQ_LS:
3208 case UNIT_REQ_DS:
3209 return 2;
3210 case UNIT_REQ_DLS:
3211 return 3;
3212 default:
3213 gcc_unreachable ();
3217 /* Examine INSN, and store in REQ1/SIDE1 and REQ2/SIDE2 the unit
3218 requirements. Returns zero if INSN can't be handled, otherwise
3219 either one or two to show how many of the two pairs are in use.
3220 REQ1 is always used, it holds what is normally thought of as the
3221 instructions reservation, e.g. UNIT_REQ_DL. REQ2 is used to either
3222 describe a cross path, or for loads/stores, the T unit. */
3223 static int
3224 get_unit_reqs (rtx insn, int *req1, int *side1, int *req2, int *side2)
3226 enum attr_units units;
3227 enum attr_cross cross;
3228 int side, req;
3230 if (!NONDEBUG_INSN_P (insn) || recog_memoized (insn) < 0)
3231 return 0;
3232 units = get_attr_units (insn);
3233 if (units == UNITS_UNKNOWN)
3234 return 0;
3235 side = get_insn_side (insn, units);
3236 cross = get_attr_cross (insn);
3238 req = (units == UNITS_D ? UNIT_REQ_D
3239 : units == UNITS_D_ADDR ? UNIT_REQ_D
3240 : units == UNITS_DL ? UNIT_REQ_DL
3241 : units == UNITS_DS ? UNIT_REQ_DS
3242 : units == UNITS_L ? UNIT_REQ_L
3243 : units == UNITS_LS ? UNIT_REQ_LS
3244 : units == UNITS_S ? UNIT_REQ_S
3245 : units == UNITS_M ? UNIT_REQ_M
3246 : units == UNITS_DLS ? UNIT_REQ_DLS
3247 : -1);
3248 gcc_assert (req != -1);
3249 *req1 = req;
3250 *side1 = side;
3251 if (units == UNITS_D_ADDR)
3253 *req2 = UNIT_REQ_T;
3254 *side2 = side ^ (cross == CROSS_Y ? 1 : 0);
3255 return 2;
3257 else if (cross == CROSS_Y)
3259 *req2 = UNIT_REQ_X;
3260 *side2 = side;
3261 return 2;
3263 return 1;
3266 /* Walk the insns between and including HEAD and TAIL, and mark the
3267 resource requirements in the unit_reqs table. */
3268 static void
3269 count_unit_reqs (unit_req_table reqs, rtx head, rtx tail)
3271 rtx insn;
3273 memset (reqs, 0, sizeof (unit_req_table));
3275 for (insn = head; insn != NEXT_INSN (tail); insn = NEXT_INSN (insn))
3277 int side1, side2, req1, req2;
3279 switch (get_unit_reqs (insn, &req1, &side1, &req2, &side2))
3281 case 2:
3282 reqs[side2][req2]++;
3283 /* fall through */
3284 case 1:
3285 reqs[side1][req1]++;
3286 break;
3291 /* Update the table REQS by merging more specific unit reservations into
3292 more general ones, i.e. counting (for example) UNIT_REQ_D also in
3293 UNIT_REQ_DL, DS, and DLS. */
3294 static void
3295 merge_unit_reqs (unit_req_table reqs)
3297 int side;
3298 for (side = 0; side < 2; side++)
3300 int d = reqs[side][UNIT_REQ_D];
3301 int l = reqs[side][UNIT_REQ_L];
3302 int s = reqs[side][UNIT_REQ_S];
3303 int dl = reqs[side][UNIT_REQ_DL];
3304 int ls = reqs[side][UNIT_REQ_LS];
3305 int ds = reqs[side][UNIT_REQ_DS];
3307 reqs[side][UNIT_REQ_DL] += d;
3308 reqs[side][UNIT_REQ_DL] += l;
3309 reqs[side][UNIT_REQ_DS] += d;
3310 reqs[side][UNIT_REQ_DS] += s;
3311 reqs[side][UNIT_REQ_LS] += l;
3312 reqs[side][UNIT_REQ_LS] += s;
3313 reqs[side][UNIT_REQ_DLS] += ds + dl + ls + d + l + s;
3317 /* Examine the table REQS and return a measure of unit imbalance by comparing
3318 the two sides of the machine. If, for example, D1 is used twice and D2
3319 used not at all, the return value should be 1 in the absence of other
3320 imbalances. */
3321 static int
3322 unit_req_imbalance (unit_req_table reqs)
3324 int val = 0;
3325 int i;
3327 for (i = 0; i < UNIT_REQ_MAX; i++)
3329 int factor = unit_req_factor ((enum unitreqs) i);
3330 int diff = abs (reqs[0][i] - reqs[1][i]);
3331 val += (diff + factor - 1) / factor / 2;
3333 return val;
3336 /* Return the resource-constrained minimum iteration interval given the
3337 data in the REQS table. This must have been processed with
3338 merge_unit_reqs already. */
3339 static int
3340 res_mii (unit_req_table reqs)
3342 int side, req;
3343 int worst = 1;
3344 for (side = 0; side < 2; side++)
3345 for (req = 0; req < UNIT_REQ_MAX; req++)
3347 int factor = unit_req_factor ((enum unitreqs) req);
3348 worst = MAX ((reqs[side][UNIT_REQ_D] + factor - 1) / factor, worst);
3351 return worst;
3354 /* Examine INSN, and store in PMASK1 and PMASK2 bitmasks that represent
3355 the operands that are involved in the (up to) two reservations, as
3356 found by get_unit_reqs. Return true if we did this successfully, false
3357 if we couldn't identify what to do with INSN. */
3358 static bool
3359 get_unit_operand_masks (rtx insn, unsigned int *pmask1, unsigned int *pmask2)
3361 enum attr_op_pattern op_pat;
3363 if (recog_memoized (insn) < 0)
3364 return 0;
3365 if (GET_CODE (PATTERN (insn)) == COND_EXEC)
3366 return false;
3367 extract_insn (insn);
3368 op_pat = get_attr_op_pattern (insn);
3369 if (op_pat == OP_PATTERN_DT)
3371 gcc_assert (recog_data.n_operands == 2);
3372 *pmask1 = 1 << 0;
3373 *pmask2 = 1 << 1;
3374 return true;
3376 else if (op_pat == OP_PATTERN_TD)
3378 gcc_assert (recog_data.n_operands == 2);
3379 *pmask1 = 1 << 1;
3380 *pmask2 = 1 << 0;
3381 return true;
3383 else if (op_pat == OP_PATTERN_SXS)
3385 gcc_assert (recog_data.n_operands == 3);
3386 *pmask1 = (1 << 0) | (1 << 2);
3387 *pmask2 = 1 << 1;
3388 return true;
3390 else if (op_pat == OP_PATTERN_SX)
3392 gcc_assert (recog_data.n_operands == 2);
3393 *pmask1 = 1 << 0;
3394 *pmask2 = 1 << 1;
3395 return true;
3397 else if (op_pat == OP_PATTERN_SSX)
3399 gcc_assert (recog_data.n_operands == 3);
3400 *pmask1 = (1 << 0) | (1 << 1);
3401 *pmask2 = 1 << 2;
3402 return true;
3404 return false;
3407 /* Try to replace a register in INSN, which has corresponding rename info
3408 from regrename_analyze in INFO. OP_MASK and ORIG_SIDE provide information
3409 about the operands that must be renamed and the side they are on.
3410 REQS is the table of unit reservations in the loop between HEAD and TAIL.
3411 We recompute this information locally after our transformation, and keep
3412 it only if we managed to improve the balance. */
3413 static void
3414 try_rename_operands (rtx head, rtx tail, unit_req_table reqs, rtx insn,
3415 insn_rr_info *info, unsigned int op_mask, int orig_side)
3417 enum reg_class super_class = orig_side == 0 ? B_REGS : A_REGS;
3418 HARD_REG_SET unavailable;
3419 du_head_p this_head;
3420 struct du_chain *chain;
3421 int i;
3422 unsigned tmp_mask;
3423 int best_reg, old_reg;
3424 vec<du_head_p> involved_chains = vNULL;
3425 unit_req_table new_reqs;
3427 for (i = 0, tmp_mask = op_mask; tmp_mask; i++)
3429 du_head_p op_chain;
3430 if ((tmp_mask & (1 << i)) == 0)
3431 continue;
3432 if (info->op_info[i].n_chains != 1)
3433 goto out_fail;
3434 op_chain = regrename_chain_from_id (info->op_info[i].heads[0]->id);
3435 involved_chains.safe_push (op_chain);
3436 tmp_mask &= ~(1 << i);
3439 if (involved_chains.length () > 1)
3440 goto out_fail;
3442 this_head = involved_chains[0];
3443 if (this_head->cannot_rename)
3444 goto out_fail;
3446 for (chain = this_head->first; chain; chain = chain->next_use)
3448 unsigned int mask1, mask2, mask_changed;
3449 int count, side1, side2, req1, req2;
3450 insn_rr_info *this_rr = &insn_rr[INSN_UID (chain->insn)];
3452 count = get_unit_reqs (chain->insn, &req1, &side1, &req2, &side2);
3454 if (count == 0)
3455 goto out_fail;
3457 if (!get_unit_operand_masks (chain->insn, &mask1, &mask2))
3458 goto out_fail;
3460 extract_insn (chain->insn);
3462 mask_changed = 0;
3463 for (i = 0; i < recog_data.n_operands; i++)
3465 int j;
3466 int n_this_op = this_rr->op_info[i].n_chains;
3467 for (j = 0; j < n_this_op; j++)
3469 du_head_p other = this_rr->op_info[i].heads[j];
3470 if (regrename_chain_from_id (other->id) == this_head)
3471 break;
3473 if (j == n_this_op)
3474 continue;
3476 if (n_this_op != 1)
3477 goto out_fail;
3478 mask_changed |= 1 << i;
3480 gcc_assert (mask_changed != 0);
3481 if (mask_changed != mask1 && mask_changed != mask2)
3482 goto out_fail;
3485 /* If we get here, we can do the renaming. */
3486 COMPL_HARD_REG_SET (unavailable, reg_class_contents[(int) super_class]);
3488 old_reg = this_head->regno;
3489 best_reg = find_best_rename_reg (this_head, super_class, &unavailable, old_reg);
3491 regrename_do_replace (this_head, best_reg);
3493 count_unit_reqs (new_reqs, head, PREV_INSN (tail));
3494 merge_unit_reqs (new_reqs);
3495 if (dump_file)
3497 fprintf (dump_file, "reshuffle for insn %d, op_mask %x, "
3498 "original side %d, new reg %d\n",
3499 INSN_UID (insn), op_mask, orig_side, best_reg);
3500 fprintf (dump_file, " imbalance %d -> %d\n",
3501 unit_req_imbalance (reqs), unit_req_imbalance (new_reqs));
3503 if (unit_req_imbalance (new_reqs) > unit_req_imbalance (reqs))
3504 regrename_do_replace (this_head, old_reg);
3505 else
3506 memcpy (reqs, new_reqs, sizeof (unit_req_table));
3508 out_fail:
3509 involved_chains.release ();
3512 /* Find insns in LOOP which would, if shifted to the other side
3513 of the machine, reduce an imbalance in the unit reservations. */
3514 static void
3515 reshuffle_units (basic_block loop)
3517 rtx head = BB_HEAD (loop);
3518 rtx tail = BB_END (loop);
3519 rtx insn;
3520 unit_req_table reqs;
3521 edge e;
3522 edge_iterator ei;
3523 bitmap_head bbs;
3525 count_unit_reqs (reqs, head, PREV_INSN (tail));
3526 merge_unit_reqs (reqs);
3528 regrename_init (true);
3530 bitmap_initialize (&bbs, &bitmap_default_obstack);
3532 FOR_EACH_EDGE (e, ei, loop->preds)
3533 bitmap_set_bit (&bbs, e->src->index);
3535 bitmap_set_bit (&bbs, loop->index);
3536 regrename_analyze (&bbs);
3538 for (insn = head; insn != NEXT_INSN (tail); insn = NEXT_INSN (insn))
3540 enum attr_units units;
3541 int count, side1, side2, req1, req2;
3542 unsigned int mask1, mask2;
3543 insn_rr_info *info;
3545 if (!NONDEBUG_INSN_P (insn))
3546 continue;
3548 count = get_unit_reqs (insn, &req1, &side1, &req2, &side2);
3550 if (count == 0)
3551 continue;
3553 if (!get_unit_operand_masks (insn, &mask1, &mask2))
3554 continue;
3556 info = &insn_rr[INSN_UID (insn)];
3557 if (info->op_info == NULL)
3558 continue;
3560 if (reqs[side1][req1] > 1
3561 && reqs[side1][req1] > 2 * reqs[side1 ^ 1][req1])
3563 try_rename_operands (head, tail, reqs, insn, info, mask1, side1);
3566 units = get_attr_units (insn);
3567 if (units == UNITS_D_ADDR)
3569 gcc_assert (count == 2);
3570 if (reqs[side2][req2] > 1
3571 && reqs[side2][req2] > 2 * reqs[side2 ^ 1][req2])
3573 try_rename_operands (head, tail, reqs, insn, info, mask2, side2);
3577 regrename_finish ();
3580 /* Backend scheduling state. */
3581 typedef struct c6x_sched_context
3583 /* The current scheduler clock, saved in the sched_reorder hook. */
3584 int curr_sched_clock;
3586 /* Number of insns issued so far in this cycle. */
3587 int issued_this_cycle;
3589 /* We record the time at which each jump occurs in JUMP_CYCLES. The
3590 theoretical maximum for number of jumps in flight is 12: 2 every
3591 cycle, with a latency of 6 cycles each. This is a circular
3592 buffer; JUMP_CYCLE_INDEX is the pointer to the start. Earlier
3593 jumps have a higher index. This array should be accessed through
3594 the jump_cycle function. */
3595 int jump_cycles[12];
3596 int jump_cycle_index;
3598 /* In parallel with jump_cycles, this array records the opposite of
3599 the condition used in each pending jump. This is used to
3600 predicate insns that are scheduled in the jump's delay slots. If
3601 this is NULL_RTX no such predication happens. */
3602 rtx jump_cond[12];
3604 /* Similar to the jump_cycles mechanism, but here we take into
3605 account all insns with delay slots, to avoid scheduling asms into
3606 the delay slots. */
3607 int delays_finished_at;
3609 /* The following variable value is the last issued insn. */
3610 rtx last_scheduled_insn;
3611 /* The last issued insn that isn't a shadow of another. */
3612 rtx last_scheduled_iter0;
3614 /* The following variable value is DFA state before issuing the
3615 first insn in the current clock cycle. We do not use this member
3616 of the structure directly; we copy the data in and out of
3617 prev_cycle_state. */
3618 state_t prev_cycle_state_ctx;
3620 int reg_n_accesses[FIRST_PSEUDO_REGISTER];
3621 int reg_n_xaccesses[FIRST_PSEUDO_REGISTER];
3622 int reg_set_in_cycle[FIRST_PSEUDO_REGISTER];
3624 int tmp_reg_n_accesses[FIRST_PSEUDO_REGISTER];
3625 int tmp_reg_n_xaccesses[FIRST_PSEUDO_REGISTER];
3626 } *c6x_sched_context_t;
3628 /* The current scheduling state. */
3629 static struct c6x_sched_context ss;
3631 /* The following variable value is DFA state before issuing the first insn
3632 in the current clock cycle. This is used in c6x_variable_issue for
3633 comparison with the state after issuing the last insn in a cycle. */
3634 static state_t prev_cycle_state;
3636 /* Set when we discover while processing an insn that it would lead to too
3637 many accesses of the same register. */
3638 static bool reg_access_stall;
3640 /* The highest insn uid after delayed insns were split, but before loop bodies
3641 were copied by the modulo scheduling code. */
3642 static int sploop_max_uid_iter0;
3644 /* Look up the jump cycle with index N. For an out-of-bounds N, we return 0,
3645 so the caller does not specifically have to test for it. */
3646 static int
3647 get_jump_cycle (int n)
3649 if (n >= 12)
3650 return 0;
3651 n += ss.jump_cycle_index;
3652 if (n >= 12)
3653 n -= 12;
3654 return ss.jump_cycles[n];
3657 /* Look up the jump condition with index N. */
3658 static rtx
3659 get_jump_cond (int n)
3661 if (n >= 12)
3662 return NULL_RTX;
3663 n += ss.jump_cycle_index;
3664 if (n >= 12)
3665 n -= 12;
3666 return ss.jump_cond[n];
3669 /* Return the index of the first jump that occurs after CLOCK_VAR. If no jump
3670 has delay slots beyond CLOCK_VAR, return -1. */
3671 static int
3672 first_jump_index (int clock_var)
3674 int retval = -1;
3675 int n = 0;
3676 for (;;)
3678 int t = get_jump_cycle (n);
3679 if (t <= clock_var)
3680 break;
3681 retval = n;
3682 n++;
3684 return retval;
3687 /* Add a new entry in our scheduling state for a jump that occurs in CYCLE
3688 and has the opposite condition of COND. */
3689 static void
3690 record_jump (int cycle, rtx cond)
3692 if (ss.jump_cycle_index == 0)
3693 ss.jump_cycle_index = 11;
3694 else
3695 ss.jump_cycle_index--;
3696 ss.jump_cycles[ss.jump_cycle_index] = cycle;
3697 ss.jump_cond[ss.jump_cycle_index] = cond;
3700 /* Set the clock cycle of INSN to CYCLE. Also clears the insn's entry in
3701 new_conditions. */
3702 static void
3703 insn_set_clock (rtx insn, int cycle)
3705 unsigned uid = INSN_UID (insn);
3707 if (uid >= INSN_INFO_LENGTH)
3708 insn_info.safe_grow (uid * 5 / 4 + 10);
3710 INSN_INFO_ENTRY (uid).clock = cycle;
3711 INSN_INFO_ENTRY (uid).new_cond = NULL;
3712 INSN_INFO_ENTRY (uid).reservation = 0;
3713 INSN_INFO_ENTRY (uid).ebb_start = false;
3716 /* Return the clock cycle we set for the insn with uid UID. */
3717 static int
3718 insn_uid_get_clock (int uid)
3720 return INSN_INFO_ENTRY (uid).clock;
3723 /* Return the clock cycle we set for INSN. */
3724 static int
3725 insn_get_clock (rtx insn)
3727 return insn_uid_get_clock (INSN_UID (insn));
3730 /* Examine INSN, and if it is a conditional jump of any kind, return
3731 the opposite of the condition in which it branches. Otherwise,
3732 return NULL_RTX. */
3733 static rtx
3734 condjump_opposite_condition (rtx insn)
3736 rtx pat = PATTERN (insn);
3737 int icode = INSN_CODE (insn);
3738 rtx x = NULL;
3740 if (icode == CODE_FOR_br_true || icode == CODE_FOR_br_false)
3742 x = XEXP (SET_SRC (pat), 0);
3743 if (icode == CODE_FOR_br_false)
3744 return x;
3746 if (GET_CODE (pat) == COND_EXEC)
3748 rtx t = COND_EXEC_CODE (pat);
3749 if ((GET_CODE (t) == PARALLEL
3750 && GET_CODE (XVECEXP (t, 0, 0)) == RETURN)
3751 || (GET_CODE (t) == UNSPEC && XINT (t, 1) == UNSPEC_REAL_JUMP)
3752 || (GET_CODE (t) == SET && SET_DEST (t) == pc_rtx))
3753 x = COND_EXEC_TEST (pat);
3756 if (x != NULL_RTX)
3758 enum rtx_code code = GET_CODE (x);
3759 x = gen_rtx_fmt_ee (code == EQ ? NE : EQ,
3760 GET_MODE (x), XEXP (x, 0),
3761 XEXP (x, 1));
3763 return x;
3766 /* Return true iff COND1 and COND2 are exactly opposite conditions
3767 one of them NE and the other EQ. */
3768 static bool
3769 conditions_opposite_p (rtx cond1, rtx cond2)
3771 return (rtx_equal_p (XEXP (cond1, 0), XEXP (cond2, 0))
3772 && rtx_equal_p (XEXP (cond1, 1), XEXP (cond2, 1))
3773 && GET_CODE (cond1) == reverse_condition (GET_CODE (cond2)));
3776 /* Return true if we can add a predicate COND to INSN, or if INSN
3777 already has that predicate. If DOIT is true, also perform the
3778 modification. */
3779 static bool
3780 predicate_insn (rtx insn, rtx cond, bool doit)
3782 int icode;
3783 if (cond == NULL_RTX)
3785 gcc_assert (!doit);
3786 return false;
3789 if (get_attr_predicable (insn) == PREDICABLE_YES
3790 && GET_CODE (PATTERN (insn)) != COND_EXEC)
3792 if (doit)
3794 rtx newpat = gen_rtx_COND_EXEC (VOIDmode, cond, PATTERN (insn));
3795 PATTERN (insn) = newpat;
3796 INSN_CODE (insn) = -1;
3798 return true;
3800 if (GET_CODE (PATTERN (insn)) == COND_EXEC
3801 && rtx_equal_p (COND_EXEC_TEST (PATTERN (insn)), cond))
3802 return true;
3803 icode = INSN_CODE (insn);
3804 if (icode == CODE_FOR_real_jump
3805 || icode == CODE_FOR_jump
3806 || icode == CODE_FOR_indirect_jump)
3808 rtx pat = PATTERN (insn);
3809 rtx dest = (icode == CODE_FOR_real_jump ? XVECEXP (pat, 0, 0)
3810 : icode == CODE_FOR_jump ? XEXP (SET_SRC (pat), 0)
3811 : SET_SRC (pat));
3812 if (doit)
3814 rtx newpat;
3815 if (REG_P (dest))
3816 newpat = gen_rtx_COND_EXEC (VOIDmode, cond, PATTERN (insn));
3817 else
3818 newpat = gen_br_true (cond, XEXP (cond, 0), dest);
3819 PATTERN (insn) = newpat;
3820 INSN_CODE (insn) = -1;
3822 return true;
3824 if (INSN_CODE (insn) == CODE_FOR_br_true)
3826 rtx br_cond = XEXP (SET_SRC (PATTERN (insn)), 0);
3827 return rtx_equal_p (br_cond, cond);
3829 if (INSN_CODE (insn) == CODE_FOR_br_false)
3831 rtx br_cond = XEXP (SET_SRC (PATTERN (insn)), 0);
3832 return conditions_opposite_p (br_cond, cond);
3834 return false;
3837 /* Initialize SC. Used by c6x_init_sched_context and c6x_sched_init. */
3838 static void
3839 init_sched_state (c6x_sched_context_t sc)
3841 sc->last_scheduled_insn = NULL_RTX;
3842 sc->last_scheduled_iter0 = NULL_RTX;
3843 sc->issued_this_cycle = 0;
3844 memset (sc->jump_cycles, 0, sizeof sc->jump_cycles);
3845 memset (sc->jump_cond, 0, sizeof sc->jump_cond);
3846 sc->jump_cycle_index = 0;
3847 sc->delays_finished_at = 0;
3848 sc->curr_sched_clock = 0;
3850 sc->prev_cycle_state_ctx = xmalloc (dfa_state_size);
3852 memset (sc->reg_n_accesses, 0, sizeof sc->reg_n_accesses);
3853 memset (sc->reg_n_xaccesses, 0, sizeof sc->reg_n_xaccesses);
3854 memset (sc->reg_set_in_cycle, 0, sizeof sc->reg_set_in_cycle);
3856 state_reset (sc->prev_cycle_state_ctx);
3859 /* Allocate store for new scheduling context. */
3860 static void *
3861 c6x_alloc_sched_context (void)
3863 return xmalloc (sizeof (struct c6x_sched_context));
3866 /* If CLEAN_P is true then initializes _SC with clean data,
3867 and from the global context otherwise. */
3868 static void
3869 c6x_init_sched_context (void *_sc, bool clean_p)
3871 c6x_sched_context_t sc = (c6x_sched_context_t) _sc;
3873 if (clean_p)
3875 init_sched_state (sc);
3877 else
3879 *sc = ss;
3880 sc->prev_cycle_state_ctx = xmalloc (dfa_state_size);
3881 memcpy (sc->prev_cycle_state_ctx, prev_cycle_state, dfa_state_size);
3885 /* Sets the global scheduling context to the one pointed to by _SC. */
3886 static void
3887 c6x_set_sched_context (void *_sc)
3889 c6x_sched_context_t sc = (c6x_sched_context_t) _sc;
3891 gcc_assert (sc != NULL);
3892 ss = *sc;
3893 memcpy (prev_cycle_state, sc->prev_cycle_state_ctx, dfa_state_size);
3896 /* Clear data in _SC. */
3897 static void
3898 c6x_clear_sched_context (void *_sc)
3900 c6x_sched_context_t sc = (c6x_sched_context_t) _sc;
3901 gcc_assert (_sc != NULL);
3903 free (sc->prev_cycle_state_ctx);
3906 /* Free _SC. */
3907 static void
3908 c6x_free_sched_context (void *_sc)
3910 free (_sc);
3913 /* True if we are currently performing a preliminary scheduling
3914 pass before modulo scheduling; we can't allow the scheduler to
3915 modify instruction patterns using packetization assumptions,
3916 since there will be another scheduling pass later if modulo
3917 scheduling fails. */
3918 static bool in_hwloop;
3920 /* Provide information about speculation capabilities, and set the
3921 DO_BACKTRACKING flag. */
3922 static void
3923 c6x_set_sched_flags (spec_info_t spec_info)
3925 unsigned int *flags = &(current_sched_info->flags);
3927 if (*flags & SCHED_EBB)
3929 *flags |= DO_BACKTRACKING | DO_PREDICATION;
3931 if (in_hwloop)
3932 *flags |= DONT_BREAK_DEPENDENCIES;
3934 spec_info->mask = 0;
3937 /* Implement the TARGET_SCHED_ISSUE_RATE hook. */
3939 static int
3940 c6x_issue_rate (void)
3942 return 8;
3945 /* Used together with the collapse_ndfa option, this ensures that we reach a
3946 deterministic automaton state before trying to advance a cycle.
3947 With collapse_ndfa, genautomata creates advance cycle arcs only for
3948 such deterministic states. */
3950 static rtx
3951 c6x_sched_dfa_pre_cycle_insn (void)
3953 return const0_rtx;
3956 /* We're beginning a new block. Initialize data structures as necessary. */
3958 static void
3959 c6x_sched_init (FILE *dump ATTRIBUTE_UNUSED,
3960 int sched_verbose ATTRIBUTE_UNUSED,
3961 int max_ready ATTRIBUTE_UNUSED)
3963 if (prev_cycle_state == NULL)
3965 prev_cycle_state = xmalloc (dfa_state_size);
3967 init_sched_state (&ss);
3968 state_reset (prev_cycle_state);
3971 /* We are about to being issuing INSN. Return nonzero if we cannot
3972 issue it on given cycle CLOCK and return zero if we should not sort
3973 the ready queue on the next clock start.
3974 For C6X, we use this function just to copy the previous DFA state
3975 for comparison purposes. */
3977 static int
3978 c6x_dfa_new_cycle (FILE *dump ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED,
3979 rtx insn ATTRIBUTE_UNUSED, int last_clock ATTRIBUTE_UNUSED,
3980 int clock ATTRIBUTE_UNUSED, int *sort_p ATTRIBUTE_UNUSED)
3982 if (clock != last_clock)
3983 memcpy (prev_cycle_state, curr_state, dfa_state_size);
3984 return 0;
3987 static void
3988 c6x_mark_regno_read (int regno, bool cross)
3990 int t = ++ss.tmp_reg_n_accesses[regno];
3992 if (t > 4)
3993 reg_access_stall = true;
3995 if (cross)
3997 int set_cycle = ss.reg_set_in_cycle[regno];
3998 /* This must be done in this way rather than by tweaking things in
3999 adjust_cost, since the stall occurs even for insns with opposite
4000 predicates, and the scheduler may not even see a dependency. */
4001 if (set_cycle > 0 && set_cycle == ss.curr_sched_clock)
4002 reg_access_stall = true;
4003 /* This doesn't quite do anything yet as we're only modeling one
4004 x unit. */
4005 ++ss.tmp_reg_n_xaccesses[regno];
4009 /* Note that REG is read in the insn being examined. If CROSS, it
4010 means the access is through a cross path. Update the temporary reg
4011 access arrays, and set REG_ACCESS_STALL if the insn can't be issued
4012 in the current cycle. */
4014 static void
4015 c6x_mark_reg_read (rtx reg, bool cross)
4017 unsigned regno = REGNO (reg);
4018 unsigned nregs = hard_regno_nregs[regno][GET_MODE (reg)];
4020 while (nregs-- > 0)
4021 c6x_mark_regno_read (regno + nregs, cross);
4024 /* Note that register REG is written in cycle CYCLES. */
4026 static void
4027 c6x_mark_reg_written (rtx reg, int cycles)
4029 unsigned regno = REGNO (reg);
4030 unsigned nregs = hard_regno_nregs[regno][GET_MODE (reg)];
4032 while (nregs-- > 0)
4033 ss.reg_set_in_cycle[regno + nregs] = cycles;
4036 /* Update the register state information for an instruction whose
4037 body is X. Return true if the instruction has to be delayed until the
4038 next cycle. */
4040 static bool
4041 c6x_registers_update (rtx insn)
4043 enum attr_cross cross;
4044 enum attr_dest_regfile destrf;
4045 int i, nops;
4046 rtx x;
4048 if (!reload_completed || recog_memoized (insn) < 0)
4049 return false;
4051 reg_access_stall = false;
4052 memcpy (ss.tmp_reg_n_accesses, ss.reg_n_accesses,
4053 sizeof ss.tmp_reg_n_accesses);
4054 memcpy (ss.tmp_reg_n_xaccesses, ss.reg_n_xaccesses,
4055 sizeof ss.tmp_reg_n_xaccesses);
4057 extract_insn (insn);
4059 cross = get_attr_cross (insn);
4060 destrf = get_attr_dest_regfile (insn);
4062 nops = recog_data.n_operands;
4063 x = PATTERN (insn);
4064 if (GET_CODE (x) == COND_EXEC)
4066 c6x_mark_reg_read (XEXP (XEXP (x, 0), 0), false);
4067 nops -= 2;
4070 for (i = 0; i < nops; i++)
4072 rtx op = recog_data.operand[i];
4073 if (recog_data.operand_type[i] == OP_OUT)
4074 continue;
4075 if (REG_P (op))
4077 bool this_cross = cross;
4078 if (destrf == DEST_REGFILE_A && A_REGNO_P (REGNO (op)))
4079 this_cross = false;
4080 if (destrf == DEST_REGFILE_B && B_REGNO_P (REGNO (op)))
4081 this_cross = false;
4082 c6x_mark_reg_read (op, this_cross);
4084 else if (MEM_P (op))
4086 op = XEXP (op, 0);
4087 switch (GET_CODE (op))
4089 case POST_INC:
4090 case PRE_INC:
4091 case POST_DEC:
4092 case PRE_DEC:
4093 op = XEXP (op, 0);
4094 /* fall through */
4095 case REG:
4096 c6x_mark_reg_read (op, false);
4097 break;
4098 case POST_MODIFY:
4099 case PRE_MODIFY:
4100 op = XEXP (op, 1);
4101 gcc_assert (GET_CODE (op) == PLUS);
4102 /* fall through */
4103 case PLUS:
4104 c6x_mark_reg_read (XEXP (op, 0), false);
4105 if (REG_P (XEXP (op, 1)))
4106 c6x_mark_reg_read (XEXP (op, 1), false);
4107 break;
4108 case SYMBOL_REF:
4109 case LABEL_REF:
4110 case CONST:
4111 c6x_mark_regno_read (REG_B14, false);
4112 break;
4113 default:
4114 gcc_unreachable ();
4117 else if (!CONSTANT_P (op) && strlen (recog_data.constraints[i]) > 0)
4118 gcc_unreachable ();
4120 return reg_access_stall;
4123 /* Helper function for the TARGET_SCHED_REORDER and
4124 TARGET_SCHED_REORDER2 hooks. If scheduling an insn would be unsafe
4125 in the current cycle, move it down in the ready list and return the
4126 number of non-unsafe insns. */
4128 static int
4129 c6x_sched_reorder_1 (rtx *ready, int *pn_ready, int clock_var)
4131 int n_ready = *pn_ready;
4132 rtx *e_ready = ready + n_ready;
4133 rtx *insnp;
4134 int first_jump;
4136 /* Keep track of conflicts due to a limit number of register accesses,
4137 and due to stalls incurred by too early accesses of registers using
4138 cross paths. */
4140 for (insnp = ready; insnp < e_ready; insnp++)
4142 rtx insn = *insnp;
4143 int icode = recog_memoized (insn);
4144 bool is_asm = (icode < 0
4145 && (GET_CODE (PATTERN (insn)) == ASM_INPUT
4146 || asm_noperands (PATTERN (insn)) >= 0));
4147 bool no_parallel = (is_asm || icode == CODE_FOR_sploop
4148 || (icode >= 0
4149 && get_attr_type (insn) == TYPE_ATOMIC));
4151 /* We delay asm insns until all delay slots are exhausted. We can't
4152 accurately tell how many cycles an asm takes, and the main scheduling
4153 code always assumes at least 1 cycle, which may be wrong. */
4154 if ((no_parallel
4155 && (ss.issued_this_cycle > 0 || clock_var < ss.delays_finished_at))
4156 || c6x_registers_update (insn)
4157 || (ss.issued_this_cycle > 0 && icode == CODE_FOR_sploop))
4159 memmove (ready + 1, ready, (insnp - ready) * sizeof (rtx));
4160 *ready = insn;
4161 n_ready--;
4162 ready++;
4164 else if (shadow_p (insn))
4166 memmove (ready + 1, ready, (insnp - ready) * sizeof (rtx));
4167 *ready = insn;
4171 /* Ensure that no other jump is scheduled in jump delay slots, since
4172 it would put the machine into the wrong state. Also, we must
4173 avoid scheduling insns that have a latency longer than the
4174 remaining jump delay slots, as the code at the jump destination
4175 won't be prepared for it.
4177 However, we can relax this condition somewhat. The rest of the
4178 scheduler will automatically avoid scheduling an insn on which
4179 the jump shadow depends so late that its side effect happens
4180 after the jump. This means that if we see an insn with a longer
4181 latency here, it can safely be scheduled if we can ensure that it
4182 has a predicate opposite of the previous jump: the side effect
4183 will happen in what we think of as the same basic block. In
4184 c6x_variable_issue, we will record the necessary predicate in
4185 new_conditions, and after scheduling is finished, we will modify
4186 the insn.
4188 Special care must be taken whenever there is more than one jump
4189 in flight. */
4191 first_jump = first_jump_index (clock_var);
4192 if (first_jump != -1)
4194 int first_cycle = get_jump_cycle (first_jump);
4195 rtx first_cond = get_jump_cond (first_jump);
4196 int second_cycle = 0;
4198 if (first_jump > 0)
4199 second_cycle = get_jump_cycle (first_jump - 1);
4201 for (insnp = ready; insnp < e_ready; insnp++)
4203 rtx insn = *insnp;
4204 int icode = recog_memoized (insn);
4205 bool is_asm = (icode < 0
4206 && (GET_CODE (PATTERN (insn)) == ASM_INPUT
4207 || asm_noperands (PATTERN (insn)) >= 0));
4208 int this_cycles, rsrv_cycles;
4209 enum attr_type type;
4211 gcc_assert (!is_asm);
4212 if (icode < 0)
4213 continue;
4214 this_cycles = get_attr_cycles (insn);
4215 rsrv_cycles = get_attr_reserve_cycles (insn);
4216 type = get_attr_type (insn);
4217 /* Treat branches specially; there is also a hazard if two jumps
4218 end at the same cycle. */
4219 if (type == TYPE_BRANCH || type == TYPE_CALL)
4220 this_cycles++;
4221 if (clock_var + this_cycles <= first_cycle)
4222 continue;
4223 if ((first_jump > 0 && clock_var + this_cycles > second_cycle)
4224 || clock_var + rsrv_cycles > first_cycle
4225 || !predicate_insn (insn, first_cond, false))
4227 memmove (ready + 1, ready, (insnp - ready) * sizeof (rtx));
4228 *ready = insn;
4229 n_ready--;
4230 ready++;
4235 return n_ready;
4238 /* Implement the TARGET_SCHED_REORDER hook. We save the current clock
4239 for later and clear the register access information for the new
4240 cycle. We also move asm statements out of the way if they would be
4241 scheduled in a delay slot. */
4243 static int
4244 c6x_sched_reorder (FILE *dump ATTRIBUTE_UNUSED,
4245 int sched_verbose ATTRIBUTE_UNUSED,
4246 rtx *ready ATTRIBUTE_UNUSED,
4247 int *pn_ready ATTRIBUTE_UNUSED, int clock_var)
4249 ss.curr_sched_clock = clock_var;
4250 ss.issued_this_cycle = 0;
4251 memset (ss.reg_n_accesses, 0, sizeof ss.reg_n_accesses);
4252 memset (ss.reg_n_xaccesses, 0, sizeof ss.reg_n_xaccesses);
4254 if (ready == NULL)
4255 return 0;
4257 return c6x_sched_reorder_1 (ready, pn_ready, clock_var);
4260 /* Implement the TARGET_SCHED_REORDER2 hook. We use this to record the clock
4261 cycle for every insn. */
4263 static int
4264 c6x_sched_reorder2 (FILE *dump ATTRIBUTE_UNUSED,
4265 int sched_verbose ATTRIBUTE_UNUSED,
4266 rtx *ready ATTRIBUTE_UNUSED,
4267 int *pn_ready ATTRIBUTE_UNUSED, int clock_var)
4269 /* FIXME: the assembler rejects labels inside an execute packet.
4270 This can occur if prologue insns are scheduled in parallel with
4271 others, so we avoid this here. Also make sure that nothing is
4272 scheduled in parallel with a TYPE_ATOMIC insn or after a jump. */
4273 if (RTX_FRAME_RELATED_P (ss.last_scheduled_insn)
4274 || JUMP_P (ss.last_scheduled_insn)
4275 || (recog_memoized (ss.last_scheduled_insn) >= 0
4276 && get_attr_type (ss.last_scheduled_insn) == TYPE_ATOMIC))
4278 int n_ready = *pn_ready;
4279 rtx *e_ready = ready + n_ready;
4280 rtx *insnp;
4282 for (insnp = ready; insnp < e_ready; insnp++)
4284 rtx insn = *insnp;
4285 if (!shadow_p (insn))
4287 memmove (ready + 1, ready, (insnp - ready) * sizeof (rtx));
4288 *ready = insn;
4289 n_ready--;
4290 ready++;
4293 return n_ready;
4296 return c6x_sched_reorder_1 (ready, pn_ready, clock_var);
4299 /* Subroutine of maybe_clobber_cond, called through note_stores. */
4301 static void
4302 clobber_cond_1 (rtx x, const_rtx pat ATTRIBUTE_UNUSED, void *data1)
4304 rtx *cond = (rtx *)data1;
4305 if (*cond != NULL_RTX && reg_overlap_mentioned_p (x, *cond))
4306 *cond = NULL_RTX;
4309 /* Examine INSN, and if it destroys the conditions have recorded for
4310 any of the jumps in flight, clear that condition so that we don't
4311 predicate any more insns. CLOCK_VAR helps us limit the search to
4312 only those jumps which are still in flight. */
4314 static void
4315 maybe_clobber_cond (rtx insn, int clock_var)
4317 int n, idx;
4318 idx = ss.jump_cycle_index;
4319 for (n = 0; n < 12; n++, idx++)
4321 rtx cond, link;
4322 int cycle;
4324 if (idx >= 12)
4325 idx -= 12;
4326 cycle = ss.jump_cycles[idx];
4327 if (cycle <= clock_var)
4328 return;
4330 cond = ss.jump_cond[idx];
4331 if (cond == NULL_RTX)
4332 continue;
4334 if (CALL_P (insn))
4336 ss.jump_cond[idx] = NULL_RTX;
4337 continue;
4340 note_stores (PATTERN (insn), clobber_cond_1, ss.jump_cond + idx);
4341 for (link = REG_NOTES (insn); link; link = XEXP (link, 1))
4342 if (REG_NOTE_KIND (link) == REG_INC)
4343 clobber_cond_1 (XEXP (link, 0), NULL_RTX, ss.jump_cond + idx);
4347 /* Implement the TARGET_SCHED_VARIABLE_ISSUE hook. We are about to
4348 issue INSN. Return the number of insns left on the ready queue
4349 that can be issued this cycle.
4350 We use this hook to record clock cycles and reservations for every insn. */
4352 static int
4353 c6x_variable_issue (FILE *dump ATTRIBUTE_UNUSED,
4354 int sched_verbose ATTRIBUTE_UNUSED,
4355 rtx insn, int can_issue_more ATTRIBUTE_UNUSED)
4357 ss.last_scheduled_insn = insn;
4358 if (INSN_UID (insn) < sploop_max_uid_iter0 && !JUMP_P (insn))
4359 ss.last_scheduled_iter0 = insn;
4360 if (GET_CODE (PATTERN (insn)) != USE && GET_CODE (PATTERN (insn)) != CLOBBER)
4361 ss.issued_this_cycle++;
4362 if (insn_info.exists ())
4364 state_t st_after = alloca (dfa_state_size);
4365 int curr_clock = ss.curr_sched_clock;
4366 int uid = INSN_UID (insn);
4367 int icode = recog_memoized (insn);
4368 rtx first_cond;
4369 int first, first_cycle;
4370 unsigned int mask;
4371 int i;
4373 insn_set_clock (insn, curr_clock);
4374 INSN_INFO_ENTRY (uid).ebb_start
4375 = curr_clock == 0 && ss.issued_this_cycle == 1;
4377 first = first_jump_index (ss.curr_sched_clock);
4378 if (first == -1)
4380 first_cycle = 0;
4381 first_cond = NULL_RTX;
4383 else
4385 first_cycle = get_jump_cycle (first);
4386 first_cond = get_jump_cond (first);
4388 if (icode >= 0
4389 && first_cycle > curr_clock
4390 && first_cond != NULL_RTX
4391 && (curr_clock + get_attr_cycles (insn) > first_cycle
4392 || get_attr_type (insn) == TYPE_BRANCH
4393 || get_attr_type (insn) == TYPE_CALL))
4394 INSN_INFO_ENTRY (uid).new_cond = first_cond;
4396 memcpy (st_after, curr_state, dfa_state_size);
4397 state_transition (st_after, const0_rtx);
4399 mask = 0;
4400 for (i = 0; i < 2 * UNIT_QID_SIDE_OFFSET; i++)
4401 if (cpu_unit_reservation_p (st_after, c6x_unit_codes[i])
4402 && !cpu_unit_reservation_p (prev_cycle_state, c6x_unit_codes[i]))
4403 mask |= 1 << i;
4404 INSN_INFO_ENTRY (uid).unit_mask = mask;
4406 maybe_clobber_cond (insn, curr_clock);
4408 if (icode >= 0)
4410 int i, cycles;
4412 c6x_registers_update (insn);
4413 memcpy (ss.reg_n_accesses, ss.tmp_reg_n_accesses,
4414 sizeof ss.reg_n_accesses);
4415 memcpy (ss.reg_n_xaccesses, ss.tmp_reg_n_accesses,
4416 sizeof ss.reg_n_xaccesses);
4418 cycles = get_attr_cycles (insn);
4419 if (ss.delays_finished_at < ss.curr_sched_clock + cycles)
4420 ss.delays_finished_at = ss.curr_sched_clock + cycles;
4421 if (get_attr_type (insn) == TYPE_BRANCH
4422 || get_attr_type (insn) == TYPE_CALL)
4424 rtx opposite = condjump_opposite_condition (insn);
4425 record_jump (ss.curr_sched_clock + cycles, opposite);
4428 /* Mark the cycles in which the destination registers are written.
4429 This is used for calculating stalls when using cross units. */
4430 extract_insn (insn);
4431 /* Cross-path stalls don't apply to results of load insns. */
4432 if (get_attr_type (insn) == TYPE_LOAD
4433 || get_attr_type (insn) == TYPE_LOADN
4434 || get_attr_type (insn) == TYPE_LOAD_SHADOW)
4435 cycles--;
4436 for (i = 0; i < recog_data.n_operands; i++)
4438 rtx op = recog_data.operand[i];
4439 if (MEM_P (op))
4441 rtx addr = XEXP (op, 0);
4442 if (GET_RTX_CLASS (GET_CODE (addr)) == RTX_AUTOINC)
4443 c6x_mark_reg_written (XEXP (addr, 0),
4444 insn_uid_get_clock (uid) + 1);
4446 if (recog_data.operand_type[i] != OP_IN
4447 && REG_P (op))
4449 c6x_mark_reg_written (op,
4450 insn_uid_get_clock (uid) + cycles);
4455 return can_issue_more;
4458 /* Implement the TARGET_SCHED_ADJUST_COST hook. We need special handling for
4459 anti- and output dependencies. */
4461 static int
4462 c6x_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
4464 enum attr_type insn_type = TYPE_UNKNOWN, dep_insn_type = TYPE_UNKNOWN;
4465 int dep_insn_code_number, insn_code_number;
4466 int shadow_bonus = 0;
4467 enum reg_note kind;
4468 dep_insn_code_number = recog_memoized (dep_insn);
4469 insn_code_number = recog_memoized (insn);
4471 if (dep_insn_code_number >= 0)
4472 dep_insn_type = get_attr_type (dep_insn);
4474 if (insn_code_number >= 0)
4475 insn_type = get_attr_type (insn);
4477 kind = REG_NOTE_KIND (link);
4478 if (kind == 0)
4480 /* If we have a dependency on a load, and it's not for the result of
4481 the load, it must be for an autoincrement. Reduce the cost in that
4482 case. */
4483 if (dep_insn_type == TYPE_LOAD)
4485 rtx set = PATTERN (dep_insn);
4486 if (GET_CODE (set) == COND_EXEC)
4487 set = COND_EXEC_CODE (set);
4488 if (GET_CODE (set) == UNSPEC)
4489 cost = 1;
4490 else
4492 gcc_assert (GET_CODE (set) == SET);
4493 if (!reg_overlap_mentioned_p (SET_DEST (set), PATTERN (insn)))
4494 cost = 1;
4499 /* A jump shadow needs to have its latency decreased by one. Conceptually,
4500 it occurs in between two cycles, but we schedule it at the end of the
4501 first cycle. */
4502 if (shadow_type_p (insn_type))
4503 shadow_bonus = 1;
4505 /* Anti and output dependencies usually have zero cost, but we want
4506 to insert a stall after a jump, and after certain floating point
4507 insns that take more than one cycle to read their inputs. In the
4508 future, we should try to find a better algorithm for scheduling
4509 jumps. */
4510 if (kind != 0)
4512 /* We can get anti-dependencies against shadow insns. Treat these
4513 like output dependencies, so that the insn is entirely finished
4514 before the branch takes place. */
4515 if (kind == REG_DEP_ANTI && insn_type == TYPE_SHADOW)
4516 kind = REG_DEP_OUTPUT;
4517 switch (dep_insn_type)
4519 case TYPE_CALLP:
4520 return 1;
4521 case TYPE_BRANCH:
4522 case TYPE_CALL:
4523 if (get_attr_has_shadow (dep_insn) == HAS_SHADOW_Y)
4524 /* This is a real_jump/real_call insn. These don't have
4525 outputs, and ensuring the validity of scheduling things
4526 in the delay slot is the job of
4527 c6x_sched_reorder_1. */
4528 return 0;
4529 /* Unsplit calls can happen - e.g. for divide insns. */
4530 return 6;
4531 case TYPE_LOAD:
4532 case TYPE_LOADN:
4533 case TYPE_INTDP:
4534 if (kind == REG_DEP_OUTPUT)
4535 return 5 - shadow_bonus;
4536 return 0;
4537 case TYPE_MPY4:
4538 case TYPE_FP4:
4539 if (kind == REG_DEP_OUTPUT)
4540 return 4 - shadow_bonus;
4541 return 0;
4542 case TYPE_MPY2:
4543 if (kind == REG_DEP_OUTPUT)
4544 return 2 - shadow_bonus;
4545 return 0;
4546 case TYPE_CMPDP:
4547 if (kind == REG_DEP_OUTPUT)
4548 return 2 - shadow_bonus;
4549 return 2;
4550 case TYPE_ADDDP:
4551 case TYPE_MPYSPDP:
4552 if (kind == REG_DEP_OUTPUT)
4553 return 7 - shadow_bonus;
4554 return 2;
4555 case TYPE_MPYSP2DP:
4556 if (kind == REG_DEP_OUTPUT)
4557 return 5 - shadow_bonus;
4558 return 2;
4559 case TYPE_MPYI:
4560 if (kind == REG_DEP_OUTPUT)
4561 return 9 - shadow_bonus;
4562 return 4;
4563 case TYPE_MPYID:
4564 case TYPE_MPYDP:
4565 if (kind == REG_DEP_OUTPUT)
4566 return 10 - shadow_bonus;
4567 return 4;
4569 default:
4570 if (insn_type == TYPE_SPKERNEL)
4571 return 0;
4572 if (kind == REG_DEP_OUTPUT)
4573 return 1 - shadow_bonus;
4575 return 0;
4579 return cost - shadow_bonus;
4582 /* Create a SEQUENCE rtx to replace the instructions in SLOT, of which there
4583 are N_FILLED. REAL_FIRST identifies the slot if the insn that appears
4584 first in the original stream. */
4586 static void
4587 gen_one_bundle (rtx *slot, int n_filled, int real_first)
4589 rtx bundle;
4590 rtx t;
4591 int i;
4593 bundle = gen_rtx_SEQUENCE (VOIDmode, gen_rtvec_v (n_filled, slot));
4594 bundle = make_insn_raw (bundle);
4595 BLOCK_FOR_INSN (bundle) = BLOCK_FOR_INSN (slot[0]);
4596 INSN_LOCATION (bundle) = INSN_LOCATION (slot[0]);
4597 PREV_INSN (bundle) = PREV_INSN (slot[real_first]);
4599 t = NULL_RTX;
4601 for (i = 0; i < n_filled; i++)
4603 rtx insn = slot[i];
4604 remove_insn (insn);
4605 PREV_INSN (insn) = t ? t : PREV_INSN (bundle);
4606 if (t != NULL_RTX)
4607 NEXT_INSN (t) = insn;
4608 t = insn;
4609 if (i > 0)
4610 INSN_LOCATION (slot[i]) = INSN_LOCATION (bundle);
4613 NEXT_INSN (bundle) = NEXT_INSN (PREV_INSN (bundle));
4614 NEXT_INSN (t) = NEXT_INSN (bundle);
4615 NEXT_INSN (PREV_INSN (bundle)) = bundle;
4616 PREV_INSN (NEXT_INSN (bundle)) = bundle;
4619 /* Move all parallel instructions into SEQUENCEs, so that no subsequent passes
4620 try to insert labels in the middle. */
4622 static void
4623 c6x_gen_bundles (void)
4625 basic_block bb;
4626 rtx insn, next, last_call;
4628 FOR_EACH_BB (bb)
4630 rtx insn, next;
4631 /* The machine is eight insns wide. We can have up to six shadow
4632 insns, plus an extra slot for merging the jump shadow. */
4633 rtx slot[15];
4634 int n_filled = 0;
4635 int first_slot = 0;
4637 for (insn = BB_HEAD (bb);; insn = next)
4639 int at_end;
4640 rtx delete_this = NULL_RTX;
4642 if (NONDEBUG_INSN_P (insn))
4644 /* Put calls at the start of the sequence. */
4645 if (CALL_P (insn))
4647 first_slot++;
4648 if (n_filled)
4650 memmove (&slot[1], &slot[0],
4651 n_filled * sizeof (slot[0]));
4653 if (!shadow_p (insn))
4655 PUT_MODE (insn, TImode);
4656 if (n_filled)
4657 PUT_MODE (slot[1], VOIDmode);
4659 n_filled++;
4660 slot[0] = insn;
4662 else
4664 slot[n_filled++] = insn;
4668 next = NEXT_INSN (insn);
4669 while (next && insn != BB_END (bb)
4670 && !(NONDEBUG_INSN_P (next)
4671 && GET_CODE (PATTERN (next)) != USE
4672 && GET_CODE (PATTERN (next)) != CLOBBER))
4674 insn = next;
4675 next = NEXT_INSN (insn);
4678 at_end = insn == BB_END (bb);
4679 if (delete_this == NULL_RTX
4680 && (at_end || (GET_MODE (next) == TImode
4681 && !(shadow_p (next) && CALL_P (next)))))
4683 if (n_filled >= 2)
4684 gen_one_bundle (slot, n_filled, first_slot);
4686 n_filled = 0;
4687 first_slot = 0;
4689 if (at_end)
4690 break;
4693 /* Bundling, and emitting nops, can separate
4694 NOTE_INSN_CALL_ARG_LOCATION from the corresponding calls. Fix
4695 that up here. */
4696 last_call = NULL_RTX;
4697 for (insn = get_insns (); insn; insn = next)
4699 next = NEXT_INSN (insn);
4700 if (CALL_P (insn)
4701 || (INSN_P (insn) && GET_CODE (PATTERN (insn)) == SEQUENCE
4702 && CALL_P (XVECEXP (PATTERN (insn), 0, 0))))
4703 last_call = insn;
4704 if (!NOTE_P (insn) || NOTE_KIND (insn) != NOTE_INSN_CALL_ARG_LOCATION)
4705 continue;
4706 if (NEXT_INSN (last_call) == insn)
4707 continue;
4708 NEXT_INSN (PREV_INSN (insn)) = NEXT_INSN (insn);
4709 PREV_INSN (NEXT_INSN (insn)) = PREV_INSN (insn);
4710 PREV_INSN (insn) = last_call;
4711 NEXT_INSN (insn) = NEXT_INSN (last_call);
4712 PREV_INSN (NEXT_INSN (insn)) = insn;
4713 NEXT_INSN (PREV_INSN (insn)) = insn;
4714 last_call = insn;
4718 /* Emit a NOP instruction for CYCLES cycles after insn AFTER. Return it. */
4720 static rtx
4721 emit_nop_after (int cycles, rtx after)
4723 rtx insn;
4725 /* mpydp has 9 delay slots, and we may schedule a stall for a cross-path
4726 operation. We don't need the extra NOP since in this case, the hardware
4727 will automatically insert the required stall. */
4728 if (cycles == 10)
4729 cycles--;
4731 gcc_assert (cycles < 10);
4733 insn = emit_insn_after (gen_nop_count (GEN_INT (cycles)), after);
4734 PUT_MODE (insn, TImode);
4736 return insn;
4739 /* Determine whether INSN is a call that needs to have a return label
4740 placed. */
4742 static bool
4743 returning_call_p (rtx insn)
4745 if (CALL_P (insn))
4746 return (!SIBLING_CALL_P (insn)
4747 && get_attr_type (insn) != TYPE_CALLP
4748 && get_attr_type (insn) != TYPE_SHADOW);
4749 if (recog_memoized (insn) < 0)
4750 return false;
4751 if (get_attr_type (insn) == TYPE_CALL)
4752 return true;
4753 return false;
4756 /* Determine whether INSN's pattern can be converted to use callp. */
4757 static bool
4758 can_use_callp (rtx insn)
4760 int icode = recog_memoized (insn);
4761 if (!TARGET_INSNS_64PLUS
4762 || icode < 0
4763 || GET_CODE (PATTERN (insn)) == COND_EXEC)
4764 return false;
4766 return ((icode == CODE_FOR_real_call
4767 || icode == CODE_FOR_call_internal
4768 || icode == CODE_FOR_call_value_internal)
4769 && get_attr_dest_regfile (insn) == DEST_REGFILE_ANY);
4772 /* Convert the pattern of INSN, which must be a CALL_INSN, into a callp. */
4773 static void
4774 convert_to_callp (rtx insn)
4776 rtx lab;
4777 extract_insn (insn);
4778 if (GET_CODE (PATTERN (insn)) == SET)
4780 rtx dest = recog_data.operand[0];
4781 lab = recog_data.operand[1];
4782 PATTERN (insn) = gen_callp_value (dest, lab);
4783 INSN_CODE (insn) = CODE_FOR_callp_value;
4785 else
4787 lab = recog_data.operand[0];
4788 PATTERN (insn) = gen_callp (lab);
4789 INSN_CODE (insn) = CODE_FOR_callp;
4793 /* Scan forwards from INSN until we find the next insn that has mode TImode
4794 (indicating it starts a new cycle), and occurs in cycle CLOCK.
4795 Return it if we find such an insn, NULL_RTX otherwise. */
4796 static rtx
4797 find_next_cycle_insn (rtx insn, int clock)
4799 rtx t = insn;
4800 if (GET_MODE (t) == TImode)
4801 t = next_real_insn (t);
4802 while (t && GET_MODE (t) != TImode)
4803 t = next_real_insn (t);
4805 if (t && insn_get_clock (t) == clock)
4806 return t;
4807 return NULL_RTX;
4810 /* If COND_INSN has a COND_EXEC condition, wrap the same condition
4811 around PAT. Return PAT either unchanged or modified in this
4812 way. */
4813 static rtx
4814 duplicate_cond (rtx pat, rtx cond_insn)
4816 rtx cond_pat = PATTERN (cond_insn);
4817 if (GET_CODE (cond_pat) == COND_EXEC)
4818 pat = gen_rtx_COND_EXEC (VOIDmode, copy_rtx (COND_EXEC_TEST (cond_pat)),
4819 pat);
4820 return pat;
4823 /* Walk forward from INSN to find the last insn that issues in the same clock
4824 cycle. */
4825 static rtx
4826 find_last_same_clock (rtx insn)
4828 rtx retval = insn;
4829 rtx t = next_real_insn (insn);
4831 while (t && GET_MODE (t) != TImode)
4833 if (!DEBUG_INSN_P (t) && recog_memoized (t) >= 0)
4834 retval = t;
4835 t = next_real_insn (t);
4837 return retval;
4840 /* For every call insn in the function, emit code to load the return
4841 address. For each call we create a return label and store it in
4842 CALL_LABELS. If are not scheduling, we emit the labels here,
4843 otherwise the caller will do it later.
4844 This function is called after final insn scheduling, but before creating
4845 the SEQUENCEs that represent execute packets. */
4847 static void
4848 reorg_split_calls (rtx *call_labels)
4850 unsigned int reservation_mask = 0;
4851 rtx insn = get_insns ();
4852 gcc_assert (NOTE_P (insn));
4853 insn = next_real_insn (insn);
4854 while (insn)
4856 int uid;
4857 rtx next = next_real_insn (insn);
4859 if (DEBUG_INSN_P (insn))
4860 goto done;
4862 if (GET_MODE (insn) == TImode)
4863 reservation_mask = 0;
4864 uid = INSN_UID (insn);
4865 if (c6x_flag_schedule_insns2 && recog_memoized (insn) >= 0)
4866 reservation_mask |= 1 << INSN_INFO_ENTRY (uid).reservation;
4868 if (returning_call_p (insn))
4870 rtx label = gen_label_rtx ();
4871 rtx labelref = gen_rtx_LABEL_REF (Pmode, label);
4872 rtx reg = gen_rtx_REG (SImode, RETURN_ADDR_REGNO);
4874 LABEL_NUSES (label) = 2;
4875 if (!c6x_flag_schedule_insns2)
4877 if (can_use_callp (insn))
4878 convert_to_callp (insn);
4879 else
4881 rtx t;
4882 rtx slot[4];
4883 emit_label_after (label, insn);
4885 /* Bundle the call and its delay slots into a single
4886 SEQUENCE. While these do not issue in parallel
4887 we need to group them into a single EH region. */
4888 slot[0] = insn;
4889 PUT_MODE (insn, TImode);
4890 if (TARGET_INSNS_64)
4892 t = gen_addkpc (reg, labelref, GEN_INT (4));
4893 slot[1] = emit_insn_after (duplicate_cond (t, insn),
4894 insn);
4895 PUT_MODE (slot[1], TImode);
4896 gen_one_bundle (slot, 2, 0);
4898 else
4900 slot[3] = emit_insn_after (gen_nop_count (GEN_INT (3)),
4901 insn);
4902 PUT_MODE (slot[3], TImode);
4903 t = gen_movsi_lo_sum (reg, reg, labelref);
4904 slot[2] = emit_insn_after (duplicate_cond (t, insn),
4905 insn);
4906 PUT_MODE (slot[2], TImode);
4907 t = gen_movsi_high (reg, labelref);
4908 slot[1] = emit_insn_after (duplicate_cond (t, insn),
4909 insn);
4910 PUT_MODE (slot[1], TImode);
4911 gen_one_bundle (slot, 4, 0);
4915 else
4917 /* If we scheduled, we reserved the .S2 unit for one or two
4918 cycles after the call. Emit the insns in these slots,
4919 unless it's possible to create a CALLP insn.
4920 Note that this works because the dependencies ensure that
4921 no insn setting/using B3 is scheduled in the delay slots of
4922 a call. */
4923 int this_clock = insn_get_clock (insn);
4924 rtx last_same_clock;
4925 rtx after1;
4927 call_labels[INSN_UID (insn)] = label;
4929 last_same_clock = find_last_same_clock (insn);
4931 if (can_use_callp (insn))
4933 /* Find the first insn of the next execute packet. If it
4934 is the shadow insn corresponding to this call, we may
4935 use a CALLP insn. */
4936 rtx shadow = next_nonnote_nondebug_insn (last_same_clock);
4938 if (CALL_P (shadow)
4939 && insn_get_clock (shadow) == this_clock + 5)
4941 convert_to_callp (shadow);
4942 insn_set_clock (shadow, this_clock);
4943 INSN_INFO_ENTRY (INSN_UID (shadow)).reservation
4944 = RESERVATION_S2;
4945 INSN_INFO_ENTRY (INSN_UID (shadow)).unit_mask
4946 = INSN_INFO_ENTRY (INSN_UID (last_same_clock)).unit_mask;
4947 if (GET_MODE (insn) == TImode)
4949 rtx new_cycle_first = NEXT_INSN (insn);
4950 while (!NONDEBUG_INSN_P (new_cycle_first)
4951 || GET_CODE (PATTERN (new_cycle_first)) == USE
4952 || GET_CODE (PATTERN (new_cycle_first)) == CLOBBER)
4953 new_cycle_first = NEXT_INSN (new_cycle_first);
4954 PUT_MODE (new_cycle_first, TImode);
4955 if (new_cycle_first != shadow)
4956 PUT_MODE (shadow, VOIDmode);
4957 INSN_INFO_ENTRY (INSN_UID (new_cycle_first)).ebb_start
4958 = INSN_INFO_ENTRY (INSN_UID (insn)).ebb_start;
4960 else
4961 PUT_MODE (shadow, VOIDmode);
4962 delete_insn (insn);
4963 goto done;
4966 after1 = find_next_cycle_insn (last_same_clock, this_clock + 1);
4967 if (after1 == NULL_RTX)
4968 after1 = last_same_clock;
4969 else
4970 after1 = find_last_same_clock (after1);
4971 if (TARGET_INSNS_64)
4973 rtx x1 = gen_addkpc (reg, labelref, const0_rtx);
4974 x1 = emit_insn_after (duplicate_cond (x1, insn), after1);
4975 insn_set_clock (x1, this_clock + 1);
4976 INSN_INFO_ENTRY (INSN_UID (x1)).reservation = RESERVATION_S2;
4977 if (after1 == last_same_clock)
4978 PUT_MODE (x1, TImode);
4979 else
4980 INSN_INFO_ENTRY (INSN_UID (x1)).unit_mask
4981 = INSN_INFO_ENTRY (INSN_UID (after1)).unit_mask;
4983 else
4985 rtx x1, x2;
4986 rtx after2 = find_next_cycle_insn (after1, this_clock + 2);
4987 if (after2 == NULL_RTX)
4988 after2 = after1;
4989 x2 = gen_movsi_lo_sum (reg, reg, labelref);
4990 x2 = emit_insn_after (duplicate_cond (x2, insn), after2);
4991 x1 = gen_movsi_high (reg, labelref);
4992 x1 = emit_insn_after (duplicate_cond (x1, insn), after1);
4993 insn_set_clock (x1, this_clock + 1);
4994 insn_set_clock (x2, this_clock + 2);
4995 INSN_INFO_ENTRY (INSN_UID (x1)).reservation = RESERVATION_S2;
4996 INSN_INFO_ENTRY (INSN_UID (x2)).reservation = RESERVATION_S2;
4997 if (after1 == last_same_clock)
4998 PUT_MODE (x1, TImode);
4999 else
5000 INSN_INFO_ENTRY (INSN_UID (x1)).unit_mask
5001 = INSN_INFO_ENTRY (INSN_UID (after1)).unit_mask;
5002 if (after1 == after2)
5003 PUT_MODE (x2, TImode);
5004 else
5005 INSN_INFO_ENTRY (INSN_UID (x2)).unit_mask
5006 = INSN_INFO_ENTRY (INSN_UID (after2)).unit_mask;
5010 done:
5011 insn = next;
5015 /* Called as part of c6x_reorg. This function emits multi-cycle NOP
5016 insns as required for correctness. CALL_LABELS is the array that
5017 holds the return labels for call insns; we emit these here if
5018 scheduling was run earlier. */
5020 static void
5021 reorg_emit_nops (rtx *call_labels)
5023 bool first;
5024 rtx prev, last_call;
5025 int prev_clock, earliest_bb_end;
5026 int prev_implicit_nops;
5027 rtx insn = get_insns ();
5029 /* We look at one insn (or bundle inside a sequence) in each iteration, storing
5030 its issue time in PREV_CLOCK for the next iteration. If there is a gap in
5031 clocks, we must insert a NOP.
5032 EARLIEST_BB_END tracks in which cycle all insns that have been issued in the
5033 current basic block will finish. We must not allow the next basic block to
5034 begin before this cycle.
5035 PREV_IMPLICIT_NOPS tells us whether we've seen an insn that implicitly contains
5036 a multi-cycle nop. The code is scheduled such that subsequent insns will
5037 show the cycle gap, but we needn't insert a real NOP instruction. */
5038 insn = next_real_insn (insn);
5039 last_call = prev = NULL_RTX;
5040 prev_clock = -1;
5041 earliest_bb_end = 0;
5042 prev_implicit_nops = 0;
5043 first = true;
5044 while (insn)
5046 int this_clock = -1;
5047 rtx next;
5048 int max_cycles = 0;
5050 next = next_real_insn (insn);
5052 if (DEBUG_INSN_P (insn)
5053 || GET_CODE (PATTERN (insn)) == USE
5054 || GET_CODE (PATTERN (insn)) == CLOBBER
5055 || shadow_or_blockage_p (insn)
5056 || JUMP_TABLE_DATA_P (insn))
5057 goto next_insn;
5059 if (!c6x_flag_schedule_insns2)
5060 /* No scheduling; ensure that no parallel issue happens. */
5061 PUT_MODE (insn, TImode);
5062 else
5064 int cycles;
5066 this_clock = insn_get_clock (insn);
5067 if (this_clock != prev_clock)
5069 PUT_MODE (insn, TImode);
5071 if (!first)
5073 cycles = this_clock - prev_clock;
5075 cycles -= prev_implicit_nops;
5076 if (cycles > 1)
5078 rtx nop = emit_nop_after (cycles - 1, prev);
5079 insn_set_clock (nop, prev_clock + prev_implicit_nops + 1);
5082 prev_clock = this_clock;
5084 if (last_call
5085 && insn_get_clock (last_call) + 6 <= this_clock)
5087 emit_label_before (call_labels[INSN_UID (last_call)], insn);
5088 last_call = NULL_RTX;
5090 prev_implicit_nops = 0;
5094 /* Examine how many cycles the current insn takes, and adjust
5095 LAST_CALL, EARLIEST_BB_END and PREV_IMPLICIT_NOPS. */
5096 if (recog_memoized (insn) >= 0
5097 /* If not scheduling, we've emitted NOPs after calls already. */
5098 && (c6x_flag_schedule_insns2 || !returning_call_p (insn)))
5100 max_cycles = get_attr_cycles (insn);
5101 if (get_attr_type (insn) == TYPE_CALLP)
5102 prev_implicit_nops = 5;
5104 else
5105 max_cycles = 1;
5106 if (returning_call_p (insn))
5107 last_call = insn;
5109 if (c6x_flag_schedule_insns2)
5111 gcc_assert (this_clock >= 0);
5112 if (earliest_bb_end < this_clock + max_cycles)
5113 earliest_bb_end = this_clock + max_cycles;
5115 else if (max_cycles > 1)
5116 emit_nop_after (max_cycles - 1, insn);
5118 prev = insn;
5119 first = false;
5121 next_insn:
5122 if (c6x_flag_schedule_insns2
5123 && (next == NULL_RTX
5124 || (GET_MODE (next) == TImode
5125 && INSN_INFO_ENTRY (INSN_UID (next)).ebb_start))
5126 && earliest_bb_end > 0)
5128 int cycles = earliest_bb_end - prev_clock;
5129 if (cycles > 1)
5131 prev = emit_nop_after (cycles - 1, prev);
5132 insn_set_clock (prev, prev_clock + prev_implicit_nops + 1);
5134 earliest_bb_end = 0;
5135 prev_clock = -1;
5136 first = true;
5138 if (last_call)
5139 emit_label_after (call_labels[INSN_UID (last_call)], prev);
5140 last_call = NULL_RTX;
5142 insn = next;
5146 /* If possible, split INSN, which we know is either a jump or a call, into a real
5147 insn and its shadow. */
5148 static void
5149 split_delayed_branch (rtx insn)
5151 int code = recog_memoized (insn);
5152 rtx i1, newpat;
5153 rtx pat = PATTERN (insn);
5155 if (GET_CODE (pat) == COND_EXEC)
5156 pat = COND_EXEC_CODE (pat);
5158 if (CALL_P (insn))
5160 rtx src = pat, dest = NULL_RTX;
5161 rtx callee;
5162 if (GET_CODE (pat) == SET)
5164 dest = SET_DEST (pat);
5165 src = SET_SRC (pat);
5167 callee = XEXP (XEXP (src, 0), 0);
5168 if (SIBLING_CALL_P (insn))
5170 if (REG_P (callee))
5171 newpat = gen_indirect_sibcall_shadow ();
5172 else
5173 newpat = gen_sibcall_shadow (callee);
5174 pat = gen_real_jump (callee);
5176 else if (dest != NULL_RTX)
5178 if (REG_P (callee))
5179 newpat = gen_indirect_call_value_shadow (dest);
5180 else
5181 newpat = gen_call_value_shadow (dest, callee);
5182 pat = gen_real_call (callee);
5184 else
5186 if (REG_P (callee))
5187 newpat = gen_indirect_call_shadow ();
5188 else
5189 newpat = gen_call_shadow (callee);
5190 pat = gen_real_call (callee);
5192 pat = duplicate_cond (pat, insn);
5193 newpat = duplicate_cond (newpat, insn);
5195 else
5197 rtx src, op;
5198 if (GET_CODE (pat) == PARALLEL
5199 && GET_CODE (XVECEXP (pat, 0, 0)) == RETURN)
5201 newpat = gen_return_shadow ();
5202 pat = gen_real_ret (XEXP (XVECEXP (pat, 0, 1), 0));
5203 newpat = duplicate_cond (newpat, insn);
5205 else
5206 switch (code)
5208 case CODE_FOR_br_true:
5209 case CODE_FOR_br_false:
5210 src = SET_SRC (pat);
5211 op = XEXP (src, code == CODE_FOR_br_true ? 1 : 2);
5212 newpat = gen_condjump_shadow (op);
5213 pat = gen_real_jump (op);
5214 if (code == CODE_FOR_br_true)
5215 pat = gen_rtx_COND_EXEC (VOIDmode, XEXP (src, 0), pat);
5216 else
5217 pat = gen_rtx_COND_EXEC (VOIDmode,
5218 reversed_comparison (XEXP (src, 0),
5219 VOIDmode),
5220 pat);
5221 break;
5223 case CODE_FOR_jump:
5224 op = SET_SRC (pat);
5225 newpat = gen_jump_shadow (op);
5226 break;
5228 case CODE_FOR_indirect_jump:
5229 newpat = gen_indirect_jump_shadow ();
5230 break;
5232 case CODE_FOR_return_internal:
5233 newpat = gen_return_shadow ();
5234 pat = gen_real_ret (XEXP (XVECEXP (pat, 0, 1), 0));
5235 break;
5237 default:
5238 return;
5241 i1 = emit_insn_before (pat, insn);
5242 PATTERN (insn) = newpat;
5243 INSN_CODE (insn) = -1;
5244 record_delay_slot_pair (i1, insn, 5, 0);
5247 /* If INSN is a multi-cycle insn that should be handled properly in
5248 modulo-scheduling, split it into a real insn and a shadow.
5249 Return true if we made a change.
5251 It is valid for us to fail to split an insn; the caller has to deal
5252 with the possibility. Currently we handle loads and most mpy2 and
5253 mpy4 insns. */
5254 static bool
5255 split_delayed_nonbranch (rtx insn)
5257 int code = recog_memoized (insn);
5258 enum attr_type type;
5259 rtx i1, newpat, src, dest;
5260 rtx pat = PATTERN (insn);
5261 rtvec rtv;
5262 int delay;
5264 if (GET_CODE (pat) == COND_EXEC)
5265 pat = COND_EXEC_CODE (pat);
5267 if (code < 0 || GET_CODE (pat) != SET)
5268 return false;
5269 src = SET_SRC (pat);
5270 dest = SET_DEST (pat);
5271 if (!REG_P (dest))
5272 return false;
5274 type = get_attr_type (insn);
5275 if (code >= 0
5276 && (type == TYPE_LOAD
5277 || type == TYPE_LOADN))
5279 if (!MEM_P (src)
5280 && (GET_CODE (src) != ZERO_EXTEND
5281 || !MEM_P (XEXP (src, 0))))
5282 return false;
5284 if (GET_MODE_SIZE (GET_MODE (dest)) > 4
5285 && (GET_MODE_SIZE (GET_MODE (dest)) != 8 || !TARGET_LDDW))
5286 return false;
5288 rtv = gen_rtvec (2, GEN_INT (REGNO (SET_DEST (pat))),
5289 SET_SRC (pat));
5290 newpat = gen_load_shadow (SET_DEST (pat));
5291 pat = gen_rtx_UNSPEC (VOIDmode, rtv, UNSPEC_REAL_LOAD);
5292 delay = 4;
5294 else if (code >= 0
5295 && (type == TYPE_MPY2
5296 || type == TYPE_MPY4))
5298 /* We don't handle floating point multiplies yet. */
5299 if (GET_MODE (dest) == SFmode)
5300 return false;
5302 rtv = gen_rtvec (2, GEN_INT (REGNO (SET_DEST (pat))),
5303 SET_SRC (pat));
5304 newpat = gen_mult_shadow (SET_DEST (pat));
5305 pat = gen_rtx_UNSPEC (VOIDmode, rtv, UNSPEC_REAL_MULT);
5306 delay = type == TYPE_MPY2 ? 1 : 3;
5308 else
5309 return false;
5311 pat = duplicate_cond (pat, insn);
5312 newpat = duplicate_cond (newpat, insn);
5313 i1 = emit_insn_before (pat, insn);
5314 PATTERN (insn) = newpat;
5315 INSN_CODE (insn) = -1;
5316 recog_memoized (insn);
5317 recog_memoized (i1);
5318 record_delay_slot_pair (i1, insn, delay, 0);
5319 return true;
5322 /* Examine if INSN is the result of splitting a load into a real load and a
5323 shadow, and if so, undo the transformation. */
5324 static void
5325 undo_split_delayed_nonbranch (rtx insn)
5327 int icode = recog_memoized (insn);
5328 enum attr_type type;
5329 rtx prev_pat, insn_pat, prev;
5331 if (icode < 0)
5332 return;
5333 type = get_attr_type (insn);
5334 if (type != TYPE_LOAD_SHADOW && type != TYPE_MULT_SHADOW)
5335 return;
5336 prev = PREV_INSN (insn);
5337 prev_pat = PATTERN (prev);
5338 insn_pat = PATTERN (insn);
5339 if (GET_CODE (prev_pat) == COND_EXEC)
5341 prev_pat = COND_EXEC_CODE (prev_pat);
5342 insn_pat = COND_EXEC_CODE (insn_pat);
5345 gcc_assert (GET_CODE (prev_pat) == UNSPEC
5346 && ((XINT (prev_pat, 1) == UNSPEC_REAL_LOAD
5347 && type == TYPE_LOAD_SHADOW)
5348 || (XINT (prev_pat, 1) == UNSPEC_REAL_MULT
5349 && type == TYPE_MULT_SHADOW)));
5350 insn_pat = gen_rtx_SET (VOIDmode, SET_DEST (insn_pat),
5351 XVECEXP (prev_pat, 0, 1));
5352 insn_pat = duplicate_cond (insn_pat, prev);
5353 PATTERN (insn) = insn_pat;
5354 INSN_CODE (insn) = -1;
5355 delete_insn (prev);
5358 /* Split every insn (i.e. jumps and calls) which can have delay slots into
5359 two parts: the first one is scheduled normally and emits the instruction,
5360 while the second one is a shadow insn which shows the side effect taking
5361 place. The second one is placed in the right cycle by the scheduler, but
5362 not emitted as an assembly instruction. */
5364 static void
5365 split_delayed_insns (void)
5367 rtx insn;
5368 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5370 if (JUMP_P (insn) || CALL_P (insn))
5371 split_delayed_branch (insn);
5375 /* For every insn that has an entry in the new_conditions vector, give it
5376 the appropriate predicate. */
5377 static void
5378 conditionalize_after_sched (void)
5380 basic_block bb;
5381 rtx insn;
5382 FOR_EACH_BB (bb)
5383 FOR_BB_INSNS (bb, insn)
5385 unsigned uid = INSN_UID (insn);
5386 rtx cond;
5387 if (!NONDEBUG_INSN_P (insn) || uid >= INSN_INFO_LENGTH)
5388 continue;
5389 cond = INSN_INFO_ENTRY (uid).new_cond;
5390 if (cond == NULL_RTX)
5391 continue;
5392 if (dump_file)
5393 fprintf (dump_file, "Conditionalizing insn %d\n", uid);
5394 predicate_insn (insn, cond, true);
5398 /* A callback for the hw-doloop pass. This function examines INSN; if
5399 it is a loop_end pattern we recognize, return the reg rtx for the
5400 loop counter. Otherwise, return NULL_RTX. */
5402 static rtx
5403 hwloop_pattern_reg (rtx insn)
5405 rtx pat, reg;
5407 if (!JUMP_P (insn) || recog_memoized (insn) != CODE_FOR_loop_end)
5408 return NULL_RTX;
5410 pat = PATTERN (insn);
5411 reg = SET_DEST (XVECEXP (pat, 0, 1));
5412 if (!REG_P (reg))
5413 return NULL_RTX;
5414 return reg;
5417 /* Return the number of cycles taken by BB, as computed by scheduling,
5418 including the latencies of all insns with delay slots. IGNORE is
5419 an insn we should ignore in the calculation, usually the final
5420 branch. */
5421 static int
5422 bb_earliest_end_cycle (basic_block bb, rtx ignore)
5424 int earliest = 0;
5425 rtx insn;
5427 FOR_BB_INSNS (bb, insn)
5429 int cycles, this_clock;
5431 if (LABEL_P (insn) || NOTE_P (insn) || DEBUG_INSN_P (insn)
5432 || GET_CODE (PATTERN (insn)) == USE
5433 || GET_CODE (PATTERN (insn)) == CLOBBER
5434 || insn == ignore)
5435 continue;
5437 this_clock = insn_get_clock (insn);
5438 cycles = get_attr_cycles (insn);
5440 if (earliest < this_clock + cycles)
5441 earliest = this_clock + cycles;
5443 return earliest;
5446 /* Examine the insns in BB and remove all which have a uid greater or
5447 equal to MAX_UID. */
5448 static void
5449 filter_insns_above (basic_block bb, int max_uid)
5451 rtx insn, next;
5452 bool prev_ti = false;
5453 int prev_cycle = -1;
5455 FOR_BB_INSNS_SAFE (bb, insn, next)
5457 int this_cycle;
5458 if (!NONDEBUG_INSN_P (insn))
5459 continue;
5460 if (insn == BB_END (bb))
5461 return;
5462 this_cycle = insn_get_clock (insn);
5463 if (prev_ti && this_cycle == prev_cycle)
5465 gcc_assert (GET_MODE (insn) != TImode);
5466 PUT_MODE (insn, TImode);
5468 prev_ti = false;
5469 if (INSN_UID (insn) >= max_uid)
5471 if (GET_MODE (insn) == TImode)
5473 prev_ti = true;
5474 prev_cycle = this_cycle;
5476 delete_insn (insn);
5481 /* Implement TARGET_ASM_EMIT_EXCEPT_PERSONALITY. */
5483 static void
5484 c6x_asm_emit_except_personality (rtx personality)
5486 fputs ("\t.personality\t", asm_out_file);
5487 output_addr_const (asm_out_file, personality);
5488 fputc ('\n', asm_out_file);
5491 /* Use a special assembly directive rather than a regular setion for
5492 unwind table data. */
5494 static void
5495 c6x_asm_init_sections (void)
5497 exception_section = get_unnamed_section (0, output_section_asm_op,
5498 "\t.handlerdata");
5501 /* A callback for the hw-doloop pass. Called to optimize LOOP in a
5502 machine-specific fashion; returns true if successful and false if
5503 the hwloop_fail function should be called. */
5505 static bool
5506 hwloop_optimize (hwloop_info loop)
5508 basic_block entry_bb, bb;
5509 rtx seq, insn, prev, entry_after, end_packet;
5510 rtx head_insn, tail_insn, new_insns, last_insn;
5511 int loop_earliest;
5512 int n_execute_packets;
5513 edge entry_edge;
5514 unsigned ix;
5515 int max_uid_before, delayed_splits;
5516 int i, sp_ii, min_ii, max_ii, max_parallel, n_insns, n_real_insns, stages;
5517 rtx *orig_vec;
5518 rtx *copies;
5519 rtx **insn_copies;
5521 if (!c6x_flag_modulo_sched || !c6x_flag_schedule_insns2
5522 || !TARGET_INSNS_64PLUS)
5523 return false;
5525 if (loop->iter_reg_used || loop->depth > 1)
5526 return false;
5527 if (loop->has_call || loop->has_asm)
5528 return false;
5530 if (loop->head != loop->tail)
5531 return false;
5533 gcc_assert (loop->incoming_dest == loop->head);
5535 entry_edge = NULL;
5536 FOR_EACH_VEC_SAFE_ELT (loop->incoming, i, entry_edge)
5537 if (entry_edge->flags & EDGE_FALLTHRU)
5538 break;
5539 if (entry_edge == NULL)
5540 return false;
5542 reshuffle_units (loop->head);
5544 in_hwloop = true;
5545 schedule_ebbs_init ();
5546 schedule_ebb (BB_HEAD (loop->tail), loop->loop_end, true);
5547 schedule_ebbs_finish ();
5548 in_hwloop = false;
5550 bb = loop->head;
5551 loop_earliest = bb_earliest_end_cycle (bb, loop->loop_end) + 1;
5553 max_uid_before = get_max_uid ();
5555 /* Split all multi-cycle operations, such as loads. For normal
5556 scheduling, we only do this for branches, as the generated code
5557 would otherwise not be interrupt-safe. When using sploop, it is
5558 safe and beneficial to split them. If any multi-cycle operations
5559 remain after splitting (because we don't handle them yet), we
5560 cannot pipeline the loop. */
5561 delayed_splits = 0;
5562 FOR_BB_INSNS (bb, insn)
5564 if (NONDEBUG_INSN_P (insn))
5566 recog_memoized (insn);
5567 if (split_delayed_nonbranch (insn))
5568 delayed_splits++;
5569 else if (INSN_CODE (insn) >= 0
5570 && get_attr_cycles (insn) > 1)
5571 goto undo_splits;
5575 /* Count the number of insns as well as the number real insns, and save
5576 the original sequence of insns in case we must restore it later. */
5577 n_insns = n_real_insns = 0;
5578 FOR_BB_INSNS (bb, insn)
5580 n_insns++;
5581 if (NONDEBUG_INSN_P (insn) && insn != loop->loop_end)
5582 n_real_insns++;
5584 orig_vec = XNEWVEC (rtx, n_insns);
5585 n_insns = 0;
5586 FOR_BB_INSNS (bb, insn)
5587 orig_vec[n_insns++] = insn;
5589 /* Count the unit reservations, and compute a minimum II from that
5590 table. */
5591 count_unit_reqs (unit_reqs, loop->start_label,
5592 PREV_INSN (loop->loop_end));
5593 merge_unit_reqs (unit_reqs);
5595 min_ii = res_mii (unit_reqs);
5596 max_ii = loop_earliest < 15 ? loop_earliest : 14;
5598 /* Make copies of the loop body, up to a maximum number of stages we want
5599 to handle. */
5600 max_parallel = loop_earliest / min_ii + 1;
5602 copies = XCNEWVEC (rtx, (max_parallel + 1) * n_real_insns);
5603 insn_copies = XNEWVEC (rtx *, max_parallel + 1);
5604 for (i = 0; i < max_parallel + 1; i++)
5605 insn_copies[i] = copies + i * n_real_insns;
5607 head_insn = next_nonnote_nondebug_insn (loop->start_label);
5608 tail_insn = prev_real_insn (BB_END (bb));
5610 i = 0;
5611 FOR_BB_INSNS (bb, insn)
5612 if (NONDEBUG_INSN_P (insn) && insn != loop->loop_end)
5613 insn_copies[0][i++] = insn;
5615 sploop_max_uid_iter0 = get_max_uid ();
5617 /* Generate the copies of the loop body, and save them in the
5618 INSN_COPIES array. */
5619 start_sequence ();
5620 for (i = 0; i < max_parallel; i++)
5622 int j;
5623 rtx this_iter;
5625 this_iter = duplicate_insn_chain (head_insn, tail_insn);
5626 j = 0;
5627 while (this_iter)
5629 rtx prev_stage_insn = insn_copies[i][j];
5630 gcc_assert (INSN_CODE (this_iter) == INSN_CODE (prev_stage_insn));
5632 if (INSN_CODE (this_iter) >= 0
5633 && (get_attr_type (this_iter) == TYPE_LOAD_SHADOW
5634 || get_attr_type (this_iter) == TYPE_MULT_SHADOW))
5636 rtx prev = PREV_INSN (this_iter);
5637 record_delay_slot_pair (prev, this_iter,
5638 get_attr_cycles (prev) - 1, 0);
5640 else
5641 record_delay_slot_pair (prev_stage_insn, this_iter, i, 1);
5643 insn_copies[i + 1][j] = this_iter;
5644 j++;
5645 this_iter = next_nonnote_nondebug_insn (this_iter);
5648 new_insns = get_insns ();
5649 last_insn = insn_copies[max_parallel][n_real_insns - 1];
5650 end_sequence ();
5651 emit_insn_before (new_insns, BB_END (bb));
5653 /* Try to schedule the loop using varying initiation intervals,
5654 starting with the smallest possible and incrementing it
5655 on failure. */
5656 for (sp_ii = min_ii; sp_ii <= max_ii; sp_ii++)
5658 basic_block tmp_bb;
5659 if (dump_file)
5660 fprintf (dump_file, "Trying to schedule for II %d\n", sp_ii);
5662 df_clear_flags (DF_LR_RUN_DCE);
5664 schedule_ebbs_init ();
5665 set_modulo_params (sp_ii, max_parallel, n_real_insns,
5666 sploop_max_uid_iter0);
5667 tmp_bb = schedule_ebb (BB_HEAD (bb), last_insn, true);
5668 schedule_ebbs_finish ();
5670 if (tmp_bb)
5672 if (dump_file)
5673 fprintf (dump_file, "Found schedule with II %d\n", sp_ii);
5674 break;
5678 discard_delay_pairs_above (max_uid_before);
5680 if (sp_ii > max_ii)
5681 goto restore_loop;
5683 stages = insn_get_clock (ss.last_scheduled_iter0) / sp_ii + 1;
5685 if (stages == 1 && sp_ii > 5)
5686 goto restore_loop;
5688 /* At this point, we know we've been successful, unless we find later that
5689 there are too many execute packets for the loop buffer to hold. */
5691 /* Assign reservations to the instructions in the loop. We must find
5692 the stage that contains the full loop kernel, and transfer the
5693 reservations of the instructions contained in it to the corresponding
5694 instructions from iteration 0, which are the only ones we'll keep. */
5695 assign_reservations (BB_HEAD (bb), ss.last_scheduled_insn);
5696 PREV_INSN (BB_END (bb)) = ss.last_scheduled_iter0;
5697 NEXT_INSN (ss.last_scheduled_iter0) = BB_END (bb);
5698 filter_insns_above (bb, sploop_max_uid_iter0);
5700 for (i = 0; i < n_real_insns; i++)
5702 rtx insn = insn_copies[0][i];
5703 int uid = INSN_UID (insn);
5704 int stage = insn_uid_get_clock (uid) / sp_ii;
5706 if (stage + 1 < stages)
5708 int copy_uid;
5709 stage = stages - stage - 1;
5710 copy_uid = INSN_UID (insn_copies[stage][i]);
5711 INSN_INFO_ENTRY (uid).reservation
5712 = INSN_INFO_ENTRY (copy_uid).reservation;
5715 if (stages == 1)
5716 stages++;
5718 /* Compute the number of execute packets the pipelined form of the loop will
5719 require. */
5720 prev = NULL_RTX;
5721 n_execute_packets = 0;
5722 for (insn = loop->start_label; insn != loop->loop_end; insn = NEXT_INSN (insn))
5724 if (NONDEBUG_INSN_P (insn) && GET_MODE (insn) == TImode
5725 && !shadow_p (insn))
5727 n_execute_packets++;
5728 if (prev && insn_get_clock (prev) + 1 != insn_get_clock (insn))
5729 /* We need an extra NOP instruction. */
5730 n_execute_packets++;
5732 prev = insn;
5736 end_packet = ss.last_scheduled_iter0;
5737 while (!NONDEBUG_INSN_P (end_packet) || GET_MODE (end_packet) != TImode)
5738 end_packet = PREV_INSN (end_packet);
5740 /* The earliest cycle in which we can emit the SPKERNEL instruction. */
5741 loop_earliest = (stages - 1) * sp_ii;
5742 if (loop_earliest > insn_get_clock (end_packet))
5744 n_execute_packets++;
5745 end_packet = loop->loop_end;
5747 else
5748 loop_earliest = insn_get_clock (end_packet);
5750 if (n_execute_packets > 14)
5751 goto restore_loop;
5753 /* Generate the spkernel instruction, and place it at the appropriate
5754 spot. */
5755 PUT_MODE (end_packet, VOIDmode);
5757 insn = gen_spkernel (GEN_INT (stages - 1),
5758 const0_rtx, JUMP_LABEL (loop->loop_end));
5759 insn = emit_jump_insn_before (insn, end_packet);
5760 JUMP_LABEL (insn) = JUMP_LABEL (loop->loop_end);
5761 insn_set_clock (insn, loop_earliest);
5762 PUT_MODE (insn, TImode);
5763 INSN_INFO_ENTRY (INSN_UID (insn)).ebb_start = false;
5764 delete_insn (loop->loop_end);
5766 /* Place the mvc and sploop instructions before the loop. */
5767 entry_bb = entry_edge->src;
5769 start_sequence ();
5771 insn = emit_insn (gen_mvilc (loop->iter_reg));
5772 insn = emit_insn (gen_sploop (GEN_INT (sp_ii)));
5774 seq = get_insns ();
5776 if (!single_succ_p (entry_bb) || vec_safe_length (loop->incoming) > 1)
5778 basic_block new_bb;
5779 edge e;
5780 edge_iterator ei;
5782 emit_insn_before (seq, BB_HEAD (loop->head));
5783 seq = emit_label_before (gen_label_rtx (), seq);
5785 new_bb = create_basic_block (seq, insn, entry_bb);
5786 FOR_EACH_EDGE (e, ei, loop->incoming)
5788 if (!(e->flags & EDGE_FALLTHRU))
5789 redirect_edge_and_branch_force (e, new_bb);
5790 else
5791 redirect_edge_succ (e, new_bb);
5793 make_edge (new_bb, loop->head, 0);
5795 else
5797 entry_after = BB_END (entry_bb);
5798 while (DEBUG_INSN_P (entry_after)
5799 || (NOTE_P (entry_after)
5800 && NOTE_KIND (entry_after) != NOTE_INSN_BASIC_BLOCK))
5801 entry_after = PREV_INSN (entry_after);
5802 emit_insn_after (seq, entry_after);
5805 end_sequence ();
5807 /* Make sure we don't try to schedule this loop again. */
5808 for (ix = 0; loop->blocks.iterate (ix, &bb); ix++)
5809 bb->flags |= BB_DISABLE_SCHEDULE;
5811 return true;
5813 restore_loop:
5814 if (dump_file)
5815 fprintf (dump_file, "Unable to pipeline loop.\n");
5817 for (i = 1; i < n_insns; i++)
5819 NEXT_INSN (orig_vec[i - 1]) = orig_vec[i];
5820 PREV_INSN (orig_vec[i]) = orig_vec[i - 1];
5822 PREV_INSN (orig_vec[0]) = PREV_INSN (BB_HEAD (bb));
5823 NEXT_INSN (PREV_INSN (BB_HEAD (bb))) = orig_vec[0];
5824 NEXT_INSN (orig_vec[n_insns - 1]) = NEXT_INSN (BB_END (bb));
5825 PREV_INSN (NEXT_INSN (BB_END (bb))) = orig_vec[n_insns - 1];
5826 BB_HEAD (bb) = orig_vec[0];
5827 BB_END (bb) = orig_vec[n_insns - 1];
5828 undo_splits:
5829 free_delay_pairs ();
5830 FOR_BB_INSNS (bb, insn)
5831 if (NONDEBUG_INSN_P (insn))
5832 undo_split_delayed_nonbranch (insn);
5833 return false;
5836 /* A callback for the hw-doloop pass. Called when a loop we have discovered
5837 turns out not to be optimizable; we have to split the doloop_end pattern
5838 into a subtract and a test. */
5839 static void
5840 hwloop_fail (hwloop_info loop)
5842 rtx insn, test, testreg;
5844 if (dump_file)
5845 fprintf (dump_file, "splitting doloop insn %d\n",
5846 INSN_UID (loop->loop_end));
5847 insn = gen_addsi3 (loop->iter_reg, loop->iter_reg, constm1_rtx);
5848 /* See if we can emit the add at the head of the loop rather than at the
5849 end. */
5850 if (loop->head == NULL
5851 || loop->iter_reg_used_outside
5852 || loop->iter_reg_used
5853 || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REGNO (loop->iter_reg))
5854 || loop->incoming_dest != loop->head
5855 || EDGE_COUNT (loop->head->preds) != 2)
5856 emit_insn_before (insn, loop->loop_end);
5857 else
5859 rtx t = loop->start_label;
5860 while (!NOTE_P (t) || NOTE_KIND (t) != NOTE_INSN_BASIC_BLOCK)
5861 t = NEXT_INSN (t);
5862 emit_insn_after (insn, t);
5865 testreg = SET_DEST (XVECEXP (PATTERN (loop->loop_end), 0, 2));
5866 if (GET_CODE (testreg) == SCRATCH)
5867 testreg = loop->iter_reg;
5868 else
5869 emit_insn_before (gen_movsi (testreg, loop->iter_reg), loop->loop_end);
5871 test = gen_rtx_NE (VOIDmode, testreg, const0_rtx);
5872 insn = emit_jump_insn_before (gen_cbranchsi4 (test, testreg, const0_rtx,
5873 loop->start_label),
5874 loop->loop_end);
5876 JUMP_LABEL (insn) = loop->start_label;
5877 LABEL_NUSES (loop->start_label)++;
5878 delete_insn (loop->loop_end);
5881 static struct hw_doloop_hooks c6x_doloop_hooks =
5883 hwloop_pattern_reg,
5884 hwloop_optimize,
5885 hwloop_fail
5888 /* Run the hw-doloop pass to modulo-schedule hardware loops, or split the
5889 doloop_end patterns where such optimizations are impossible. */
5890 static void
5891 c6x_hwloops (void)
5893 if (optimize)
5894 reorg_loops (true, &c6x_doloop_hooks);
5897 /* Implement the TARGET_MACHINE_DEPENDENT_REORG pass. We split call insns here
5898 into a sequence that loads the return register and performs the call,
5899 and emit the return label.
5900 If scheduling after reload is requested, it happens here. */
5902 static void
5903 c6x_reorg (void)
5905 basic_block bb;
5906 rtx *call_labels;
5907 bool do_selsched = (c6x_flag_schedule_insns2 && flag_selective_scheduling2
5908 && !maybe_skip_selective_scheduling ());
5910 /* We are freeing block_for_insn in the toplev to keep compatibility
5911 with old MDEP_REORGS that are not CFG based. Recompute it now. */
5912 compute_bb_for_insn ();
5914 df_clear_flags (DF_LR_RUN_DCE);
5915 df_note_add_problem ();
5917 /* If optimizing, we'll have split before scheduling. */
5918 if (optimize == 0)
5919 split_all_insns ();
5921 df_analyze ();
5923 if (c6x_flag_schedule_insns2)
5925 int sz = get_max_uid () * 3 / 2 + 1;
5927 insn_info.create (sz);
5930 /* Make sure the real-jump insns we create are not deleted. When modulo-
5931 scheduling, situations where a reg is only stored in a loop can also
5932 cause dead code when doing the initial unrolling. */
5933 sched_no_dce = true;
5935 c6x_hwloops ();
5937 if (c6x_flag_schedule_insns2)
5939 split_delayed_insns ();
5940 timevar_push (TV_SCHED2);
5941 if (do_selsched)
5942 run_selective_scheduling ();
5943 else
5944 schedule_ebbs ();
5945 conditionalize_after_sched ();
5946 timevar_pop (TV_SCHED2);
5948 free_delay_pairs ();
5950 sched_no_dce = false;
5952 call_labels = XCNEWVEC (rtx, get_max_uid () + 1);
5954 reorg_split_calls (call_labels);
5956 if (c6x_flag_schedule_insns2)
5958 FOR_EACH_BB (bb)
5959 if ((bb->flags & BB_DISABLE_SCHEDULE) == 0)
5960 assign_reservations (BB_HEAD (bb), BB_END (bb));
5963 if (c6x_flag_var_tracking)
5965 timevar_push (TV_VAR_TRACKING);
5966 variable_tracking_main ();
5967 timevar_pop (TV_VAR_TRACKING);
5970 reorg_emit_nops (call_labels);
5972 /* Post-process the schedule to move parallel insns into SEQUENCEs. */
5973 if (c6x_flag_schedule_insns2)
5975 free_delay_pairs ();
5976 c6x_gen_bundles ();
5979 df_finish_pass (false);
5982 /* Called when a function has been assembled. It should perform all the
5983 tasks of ASM_DECLARE_FUNCTION_SIZE in elfos.h, plus target-specific
5984 tasks.
5985 We free the reservation (and other scheduling) information here now that
5986 all insns have been output. */
5987 void
5988 c6x_function_end (FILE *file, const char *fname)
5990 c6x_output_fn_unwind (file);
5992 insn_info.release ();
5994 if (!flag_inhibit_size_directive)
5995 ASM_OUTPUT_MEASURED_SIZE (file, fname);
5998 /* Determine whether X is a shift with code CODE and an integer amount
5999 AMOUNT. */
6000 static bool
6001 shift_p (rtx x, enum rtx_code code, int amount)
6003 return (GET_CODE (x) == code && GET_CODE (XEXP (x, 1)) == CONST_INT
6004 && INTVAL (XEXP (x, 1)) == amount);
6007 /* Compute a (partial) cost for rtx X. Return true if the complete
6008 cost has been computed, and false if subexpressions should be
6009 scanned. In either case, *TOTAL contains the cost result. */
6011 static bool
6012 c6x_rtx_costs (rtx x, int code, int outer_code, int opno, int *total,
6013 bool speed)
6015 int cost2 = COSTS_N_INSNS (1);
6016 rtx op0, op1;
6018 switch (code)
6020 case CONST_INT:
6021 if (outer_code == SET || outer_code == PLUS)
6022 *total = satisfies_constraint_IsB (x) ? 0 : cost2;
6023 else if (outer_code == AND || outer_code == IOR || outer_code == XOR
6024 || outer_code == MINUS)
6025 *total = satisfies_constraint_Is5 (x) ? 0 : cost2;
6026 else if (GET_RTX_CLASS (outer_code) == RTX_COMPARE
6027 || GET_RTX_CLASS (outer_code) == RTX_COMM_COMPARE)
6028 *total = satisfies_constraint_Iu4 (x) ? 0 : cost2;
6029 else if (outer_code == ASHIFT || outer_code == ASHIFTRT
6030 || outer_code == LSHIFTRT)
6031 *total = satisfies_constraint_Iu5 (x) ? 0 : cost2;
6032 else
6033 *total = cost2;
6034 return true;
6036 case CONST:
6037 case LABEL_REF:
6038 case SYMBOL_REF:
6039 case CONST_DOUBLE:
6040 *total = COSTS_N_INSNS (2);
6041 return true;
6043 case TRUNCATE:
6044 /* Recognize a mult_highpart operation. */
6045 if ((GET_MODE (x) == HImode || GET_MODE (x) == SImode)
6046 && GET_CODE (XEXP (x, 0)) == LSHIFTRT
6047 && GET_MODE (XEXP (x, 0)) == GET_MODE_2XWIDER_MODE (GET_MODE (x))
6048 && GET_CODE (XEXP (XEXP (x, 0), 0)) == MULT
6049 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT
6050 && INTVAL (XEXP (XEXP (x, 0), 1)) == GET_MODE_BITSIZE (GET_MODE (x)))
6052 rtx mul = XEXP (XEXP (x, 0), 0);
6053 rtx op0 = XEXP (mul, 0);
6054 rtx op1 = XEXP (mul, 1);
6055 enum rtx_code code0 = GET_CODE (op0);
6056 enum rtx_code code1 = GET_CODE (op1);
6058 if ((code0 == code1
6059 && (code0 == SIGN_EXTEND || code0 == ZERO_EXTEND))
6060 || (GET_MODE (x) == HImode
6061 && code0 == ZERO_EXTEND && code1 == SIGN_EXTEND))
6063 if (GET_MODE (x) == HImode)
6064 *total = COSTS_N_INSNS (2);
6065 else
6066 *total = COSTS_N_INSNS (12);
6067 *total += rtx_cost (XEXP (op0, 0), code0, 0, speed);
6068 *total += rtx_cost (XEXP (op1, 0), code1, 0, speed);
6069 return true;
6072 return false;
6074 case ASHIFT:
6075 case ASHIFTRT:
6076 case LSHIFTRT:
6077 if (GET_MODE (x) == DImode)
6078 *total = COSTS_N_INSNS (CONSTANT_P (XEXP (x, 1)) ? 4 : 15);
6079 else
6080 *total = COSTS_N_INSNS (1);
6081 return false;
6083 case PLUS:
6084 case MINUS:
6085 *total = COSTS_N_INSNS (1);
6086 op0 = code == PLUS ? XEXP (x, 0) : XEXP (x, 1);
6087 op1 = code == PLUS ? XEXP (x, 1) : XEXP (x, 0);
6088 if (GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD
6089 && INTEGRAL_MODE_P (GET_MODE (x))
6090 && GET_CODE (op0) == MULT
6091 && GET_CODE (XEXP (op0, 1)) == CONST_INT
6092 && (INTVAL (XEXP (op0, 1)) == 2
6093 || INTVAL (XEXP (op0, 1)) == 4
6094 || (code == PLUS && INTVAL (XEXP (op0, 1)) == 8)))
6096 *total += rtx_cost (XEXP (op0, 0), ASHIFT, 0, speed);
6097 *total += rtx_cost (op1, (enum rtx_code) code, 1, speed);
6098 return true;
6100 return false;
6102 case MULT:
6103 op0 = XEXP (x, 0);
6104 op1 = XEXP (x, 1);
6105 if (GET_MODE (x) == DFmode)
6107 if (TARGET_FP)
6108 *total = COSTS_N_INSNS (speed ? 10 : 1);
6109 else
6110 *total = COSTS_N_INSNS (speed ? 200 : 4);
6112 else if (GET_MODE (x) == SFmode)
6114 if (TARGET_FP)
6115 *total = COSTS_N_INSNS (speed ? 4 : 1);
6116 else
6117 *total = COSTS_N_INSNS (speed ? 100 : 4);
6119 else if (GET_MODE (x) == DImode)
6121 if (TARGET_MPY32
6122 && GET_CODE (op0) == GET_CODE (op1)
6123 && (GET_CODE (op0) == ZERO_EXTEND
6124 || GET_CODE (op0) == SIGN_EXTEND))
6126 *total = COSTS_N_INSNS (speed ? 2 : 1);
6127 op0 = XEXP (op0, 0);
6128 op1 = XEXP (op1, 0);
6130 else
6131 /* Maybe improve this laster. */
6132 *total = COSTS_N_INSNS (20);
6134 else if (GET_MODE (x) == SImode)
6136 if (((GET_CODE (op0) == ZERO_EXTEND
6137 || GET_CODE (op0) == SIGN_EXTEND
6138 || shift_p (op0, LSHIFTRT, 16))
6139 && (GET_CODE (op1) == SIGN_EXTEND
6140 || GET_CODE (op1) == ZERO_EXTEND
6141 || scst5_operand (op1, SImode)
6142 || shift_p (op1, ASHIFTRT, 16)
6143 || shift_p (op1, LSHIFTRT, 16)))
6144 || (shift_p (op0, ASHIFTRT, 16)
6145 && (GET_CODE (op1) == SIGN_EXTEND
6146 || shift_p (op1, ASHIFTRT, 16))))
6148 *total = COSTS_N_INSNS (speed ? 2 : 1);
6149 op0 = XEXP (op0, 0);
6150 if (scst5_operand (op1, SImode))
6151 op1 = NULL_RTX;
6152 else
6153 op1 = XEXP (op1, 0);
6155 else if (!speed)
6156 *total = COSTS_N_INSNS (1);
6157 else if (TARGET_MPY32)
6158 *total = COSTS_N_INSNS (4);
6159 else
6160 *total = COSTS_N_INSNS (6);
6162 else if (GET_MODE (x) == HImode)
6163 *total = COSTS_N_INSNS (speed ? 2 : 1);
6165 if (GET_CODE (op0) != REG
6166 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
6167 *total += rtx_cost (op0, MULT, 0, speed);
6168 if (op1 && GET_CODE (op1) != REG
6169 && (GET_CODE (op1) != SUBREG || GET_CODE (SUBREG_REG (op1)) != REG))
6170 *total += rtx_cost (op1, MULT, 1, speed);
6171 return true;
6173 case UDIV:
6174 case DIV:
6175 /* This is a bit random; assuming on average there'll be 16 leading
6176 zeros. FIXME: estimate better for constant dividends. */
6177 *total = COSTS_N_INSNS (6 + 3 * 16);
6178 return false;
6180 case IF_THEN_ELSE:
6181 /* Recognize the cmp_and/ior patterns. */
6182 op0 = XEXP (x, 0);
6183 if ((GET_CODE (op0) == EQ || GET_CODE (op0) == NE)
6184 && REG_P (XEXP (op0, 0))
6185 && XEXP (op0, 1) == const0_rtx
6186 && rtx_equal_p (XEXP (x, 1), XEXP (op0, 0)))
6188 *total = rtx_cost (XEXP (x, 1), (enum rtx_code) outer_code,
6189 opno, speed);
6190 return false;
6192 return false;
6194 default:
6195 return false;
6199 /* Implements target hook vector_mode_supported_p. */
6201 static bool
6202 c6x_vector_mode_supported_p (enum machine_mode mode)
6204 switch (mode)
6206 case V2HImode:
6207 case V4QImode:
6208 case V2SImode:
6209 case V4HImode:
6210 case V8QImode:
6211 return true;
6212 default:
6213 return false;
6217 /* Implements TARGET_VECTORIZE_PREFERRED_SIMD_MODE. */
6218 static enum machine_mode
6219 c6x_preferred_simd_mode (enum machine_mode mode)
6221 switch (mode)
6223 case HImode:
6224 return V2HImode;
6225 case QImode:
6226 return V4QImode;
6228 default:
6229 return word_mode;
6233 /* Implement TARGET_SCALAR_MODE_SUPPORTED_P. */
6235 static bool
6236 c6x_scalar_mode_supported_p (enum machine_mode mode)
6238 if (ALL_FIXED_POINT_MODE_P (mode)
6239 && GET_MODE_PRECISION (mode) <= 2 * BITS_PER_WORD)
6240 return true;
6242 return default_scalar_mode_supported_p (mode);
6245 /* Output a reference from a function exception table to the type_info
6246 object X. Output these via a special assembly directive. */
6248 static bool
6249 c6x_output_ttype (rtx x)
6251 /* Use special relocations for symbol references. */
6252 if (GET_CODE (x) != CONST_INT)
6253 fputs ("\t.ehtype\t", asm_out_file);
6254 else
6255 fputs ("\t.word\t", asm_out_file);
6256 output_addr_const (asm_out_file, x);
6257 fputc ('\n', asm_out_file);
6259 return TRUE;
6262 /* Modify the return address of the current function. */
6264 void
6265 c6x_set_return_address (rtx source, rtx scratch)
6267 struct c6x_frame frame;
6268 rtx addr;
6269 HOST_WIDE_INT offset;
6271 c6x_compute_frame_layout (&frame);
6272 if (! c6x_save_reg (RETURN_ADDR_REGNO))
6273 emit_move_insn (gen_rtx_REG (Pmode, RETURN_ADDR_REGNO), source);
6274 else
6277 if (frame_pointer_needed)
6279 addr = hard_frame_pointer_rtx;
6280 offset = frame.b3_offset;
6282 else
6284 addr = stack_pointer_rtx;
6285 offset = frame.to_allocate - frame.b3_offset;
6288 /* TODO: Use base+offset loads where possible. */
6289 if (offset)
6291 HOST_WIDE_INT low = trunc_int_for_mode (offset, HImode);
6293 emit_insn (gen_movsi_high (scratch, GEN_INT (low)));
6294 if (low != offset)
6295 emit_insn (gen_movsi_lo_sum (scratch, scratch, GEN_INT(offset)));
6296 emit_insn (gen_addsi3 (scratch, addr, scratch));
6297 addr = scratch;
6300 emit_move_insn (gen_frame_mem (Pmode, addr), source);
6304 /* We save pairs of registers using a DImode store. Describe the component
6305 registers for DWARF generation code. */
6307 static rtx
6308 c6x_dwarf_register_span (rtx rtl)
6310 unsigned regno;
6311 unsigned real_regno;
6312 int nregs;
6313 int i;
6314 rtx p;
6316 regno = REGNO (rtl);
6317 nregs = HARD_REGNO_NREGS (regno, GET_MODE (rtl));
6318 if (nregs == 1)
6319 return NULL_RTX;
6321 p = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc(nregs));
6322 for (i = 0; i < nregs; i++)
6324 if (TARGET_BIG_ENDIAN)
6325 real_regno = regno + nregs - (i + 1);
6326 else
6327 real_regno = regno + i;
6329 XVECEXP (p, 0, i) = gen_rtx_REG (SImode, real_regno);
6332 return p;
6335 /* Codes for all the C6X builtins. */
6336 enum c6x_builtins
6338 C6X_BUILTIN_SADD,
6339 C6X_BUILTIN_SSUB,
6340 C6X_BUILTIN_ADD2,
6341 C6X_BUILTIN_SUB2,
6342 C6X_BUILTIN_ADD4,
6343 C6X_BUILTIN_SUB4,
6344 C6X_BUILTIN_SADD2,
6345 C6X_BUILTIN_SSUB2,
6346 C6X_BUILTIN_SADDU4,
6348 C6X_BUILTIN_SMPY,
6349 C6X_BUILTIN_SMPYH,
6350 C6X_BUILTIN_SMPYHL,
6351 C6X_BUILTIN_SMPYLH,
6352 C6X_BUILTIN_MPY2,
6353 C6X_BUILTIN_SMPY2,
6355 C6X_BUILTIN_CLRR,
6356 C6X_BUILTIN_EXTR,
6357 C6X_BUILTIN_EXTRU,
6359 C6X_BUILTIN_SSHL,
6360 C6X_BUILTIN_SUBC,
6361 C6X_BUILTIN_ABS,
6362 C6X_BUILTIN_ABS2,
6363 C6X_BUILTIN_AVG2,
6364 C6X_BUILTIN_AVGU4,
6366 C6X_BUILTIN_MAX
6370 static GTY(()) tree c6x_builtin_decls[C6X_BUILTIN_MAX];
6372 /* Return the C6X builtin for CODE. */
6373 static tree
6374 c6x_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
6376 if (code >= C6X_BUILTIN_MAX)
6377 return error_mark_node;
6379 return c6x_builtin_decls[code];
6382 #define def_builtin(NAME, TYPE, CODE) \
6383 do { \
6384 tree bdecl; \
6385 bdecl = add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
6386 NULL, NULL_TREE); \
6387 c6x_builtin_decls[CODE] = bdecl; \
6388 } while (0)
6390 /* Set up all builtin functions for this target. */
6391 static void
6392 c6x_init_builtins (void)
6394 tree V4QI_type_node = build_vector_type (unsigned_intQI_type_node, 4);
6395 tree V2HI_type_node = build_vector_type (intHI_type_node, 2);
6396 tree V2SI_type_node = build_vector_type (intSI_type_node, 2);
6397 tree int_ftype_int
6398 = build_function_type_list (integer_type_node, integer_type_node,
6399 NULL_TREE);
6400 tree int_ftype_int_int
6401 = build_function_type_list (integer_type_node, integer_type_node,
6402 integer_type_node, NULL_TREE);
6403 tree v2hi_ftype_v2hi
6404 = build_function_type_list (V2HI_type_node, V2HI_type_node, NULL_TREE);
6405 tree v4qi_ftype_v4qi_v4qi
6406 = build_function_type_list (V4QI_type_node, V4QI_type_node,
6407 V4QI_type_node, NULL_TREE);
6408 tree v2hi_ftype_v2hi_v2hi
6409 = build_function_type_list (V2HI_type_node, V2HI_type_node,
6410 V2HI_type_node, NULL_TREE);
6411 tree v2si_ftype_v2hi_v2hi
6412 = build_function_type_list (V2SI_type_node, V2HI_type_node,
6413 V2HI_type_node, NULL_TREE);
6415 def_builtin ("__builtin_c6x_sadd", int_ftype_int_int,
6416 C6X_BUILTIN_SADD);
6417 def_builtin ("__builtin_c6x_ssub", int_ftype_int_int,
6418 C6X_BUILTIN_SSUB);
6419 def_builtin ("__builtin_c6x_add2", v2hi_ftype_v2hi_v2hi,
6420 C6X_BUILTIN_ADD2);
6421 def_builtin ("__builtin_c6x_sub2", v2hi_ftype_v2hi_v2hi,
6422 C6X_BUILTIN_SUB2);
6423 def_builtin ("__builtin_c6x_add4", v4qi_ftype_v4qi_v4qi,
6424 C6X_BUILTIN_ADD4);
6425 def_builtin ("__builtin_c6x_sub4", v4qi_ftype_v4qi_v4qi,
6426 C6X_BUILTIN_SUB4);
6427 def_builtin ("__builtin_c6x_mpy2", v2si_ftype_v2hi_v2hi,
6428 C6X_BUILTIN_MPY2);
6429 def_builtin ("__builtin_c6x_sadd2", v2hi_ftype_v2hi_v2hi,
6430 C6X_BUILTIN_SADD2);
6431 def_builtin ("__builtin_c6x_ssub2", v2hi_ftype_v2hi_v2hi,
6432 C6X_BUILTIN_SSUB2);
6433 def_builtin ("__builtin_c6x_saddu4", v4qi_ftype_v4qi_v4qi,
6434 C6X_BUILTIN_SADDU4);
6435 def_builtin ("__builtin_c6x_smpy2", v2si_ftype_v2hi_v2hi,
6436 C6X_BUILTIN_SMPY2);
6438 def_builtin ("__builtin_c6x_smpy", int_ftype_int_int,
6439 C6X_BUILTIN_SMPY);
6440 def_builtin ("__builtin_c6x_smpyh", int_ftype_int_int,
6441 C6X_BUILTIN_SMPYH);
6442 def_builtin ("__builtin_c6x_smpyhl", int_ftype_int_int,
6443 C6X_BUILTIN_SMPYHL);
6444 def_builtin ("__builtin_c6x_smpylh", int_ftype_int_int,
6445 C6X_BUILTIN_SMPYLH);
6447 def_builtin ("__builtin_c6x_sshl", int_ftype_int_int,
6448 C6X_BUILTIN_SSHL);
6449 def_builtin ("__builtin_c6x_subc", int_ftype_int_int,
6450 C6X_BUILTIN_SUBC);
6452 def_builtin ("__builtin_c6x_avg2", v2hi_ftype_v2hi_v2hi,
6453 C6X_BUILTIN_AVG2);
6454 def_builtin ("__builtin_c6x_avgu4", v4qi_ftype_v4qi_v4qi,
6455 C6X_BUILTIN_AVGU4);
6457 def_builtin ("__builtin_c6x_clrr", int_ftype_int_int,
6458 C6X_BUILTIN_CLRR);
6459 def_builtin ("__builtin_c6x_extr", int_ftype_int_int,
6460 C6X_BUILTIN_EXTR);
6461 def_builtin ("__builtin_c6x_extru", int_ftype_int_int,
6462 C6X_BUILTIN_EXTRU);
6464 def_builtin ("__builtin_c6x_abs", int_ftype_int, C6X_BUILTIN_ABS);
6465 def_builtin ("__builtin_c6x_abs2", v2hi_ftype_v2hi, C6X_BUILTIN_ABS2);
6469 struct builtin_description
6471 const enum insn_code icode;
6472 const char *const name;
6473 const enum c6x_builtins code;
6476 static const struct builtin_description bdesc_2arg[] =
6478 { CODE_FOR_saddsi3, "__builtin_c6x_sadd", C6X_BUILTIN_SADD },
6479 { CODE_FOR_ssubsi3, "__builtin_c6x_ssub", C6X_BUILTIN_SSUB },
6480 { CODE_FOR_addv2hi3, "__builtin_c6x_add2", C6X_BUILTIN_ADD2 },
6481 { CODE_FOR_subv2hi3, "__builtin_c6x_sub2", C6X_BUILTIN_SUB2 },
6482 { CODE_FOR_addv4qi3, "__builtin_c6x_add4", C6X_BUILTIN_ADD4 },
6483 { CODE_FOR_subv4qi3, "__builtin_c6x_sub4", C6X_BUILTIN_SUB4 },
6484 { CODE_FOR_ss_addv2hi3, "__builtin_c6x_sadd2", C6X_BUILTIN_SADD2 },
6485 { CODE_FOR_ss_subv2hi3, "__builtin_c6x_ssub2", C6X_BUILTIN_SSUB2 },
6486 { CODE_FOR_us_addv4qi3, "__builtin_c6x_saddu4", C6X_BUILTIN_SADDU4 },
6488 { CODE_FOR_subcsi3, "__builtin_c6x_subc", C6X_BUILTIN_SUBC },
6489 { CODE_FOR_ss_ashlsi3, "__builtin_c6x_sshl", C6X_BUILTIN_SSHL },
6491 { CODE_FOR_avgv2hi3, "__builtin_c6x_avg2", C6X_BUILTIN_AVG2 },
6492 { CODE_FOR_uavgv4qi3, "__builtin_c6x_avgu4", C6X_BUILTIN_AVGU4 },
6494 { CODE_FOR_mulhqsq3, "__builtin_c6x_smpy", C6X_BUILTIN_SMPY },
6495 { CODE_FOR_mulhqsq3_hh, "__builtin_c6x_smpyh", C6X_BUILTIN_SMPYH },
6496 { CODE_FOR_mulhqsq3_lh, "__builtin_c6x_smpylh", C6X_BUILTIN_SMPYLH },
6497 { CODE_FOR_mulhqsq3_hl, "__builtin_c6x_smpyhl", C6X_BUILTIN_SMPYHL },
6499 { CODE_FOR_mulv2hqv2sq3, "__builtin_c6x_smpy2", C6X_BUILTIN_SMPY2 },
6501 { CODE_FOR_clrr, "__builtin_c6x_clrr", C6X_BUILTIN_CLRR },
6502 { CODE_FOR_extr, "__builtin_c6x_extr", C6X_BUILTIN_EXTR },
6503 { CODE_FOR_extru, "__builtin_c6x_extru", C6X_BUILTIN_EXTRU }
6506 static const struct builtin_description bdesc_1arg[] =
6508 { CODE_FOR_ssabssi2, "__builtin_c6x_abs", C6X_BUILTIN_ABS },
6509 { CODE_FOR_ssabsv2hi2, "__builtin_c6x_abs2", C6X_BUILTIN_ABS2 }
6512 /* Errors in the source file can cause expand_expr to return const0_rtx
6513 where we expect a vector. To avoid crashing, use one of the vector
6514 clear instructions. */
6515 static rtx
6516 safe_vector_operand (rtx x, enum machine_mode mode)
6518 if (x != const0_rtx)
6519 return x;
6520 x = gen_reg_rtx (SImode);
6522 emit_insn (gen_movsi (x, CONST0_RTX (SImode)));
6523 return gen_lowpart (mode, x);
6526 /* Subroutine of c6x_expand_builtin to take care of binop insns. MACFLAG is -1
6527 if this is a normal binary op, or one of the MACFLAG_xxx constants. */
6529 static rtx
6530 c6x_expand_binop_builtin (enum insn_code icode, tree exp, rtx target,
6531 bool match_op)
6533 int offs = match_op ? 1 : 0;
6534 rtx pat;
6535 tree arg0 = CALL_EXPR_ARG (exp, 0);
6536 tree arg1 = CALL_EXPR_ARG (exp, 1);
6537 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
6538 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, EXPAND_NORMAL);
6539 enum machine_mode op0mode = GET_MODE (op0);
6540 enum machine_mode op1mode = GET_MODE (op1);
6541 enum machine_mode tmode = insn_data[icode].operand[0].mode;
6542 enum machine_mode mode0 = insn_data[icode].operand[1 + offs].mode;
6543 enum machine_mode mode1 = insn_data[icode].operand[2 + offs].mode;
6544 rtx ret = target;
6546 if (VECTOR_MODE_P (mode0))
6547 op0 = safe_vector_operand (op0, mode0);
6548 if (VECTOR_MODE_P (mode1))
6549 op1 = safe_vector_operand (op1, mode1);
6551 if (! target
6552 || GET_MODE (target) != tmode
6553 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
6555 if (tmode == SQmode || tmode == V2SQmode)
6557 ret = gen_reg_rtx (tmode == SQmode ? SImode : V2SImode);
6558 target = gen_lowpart (tmode, ret);
6560 else
6561 target = gen_reg_rtx (tmode);
6564 if ((op0mode == V2HImode || op0mode == SImode || op0mode == VOIDmode)
6565 && (mode0 == V2HQmode || mode0 == HQmode || mode0 == SQmode))
6567 op0mode = mode0;
6568 op0 = gen_lowpart (mode0, op0);
6570 if ((op1mode == V2HImode || op1mode == SImode || op1mode == VOIDmode)
6571 && (mode1 == V2HQmode || mode1 == HQmode || mode1 == SQmode))
6573 op1mode = mode1;
6574 op1 = gen_lowpart (mode1, op1);
6576 /* In case the insn wants input operands in modes different from
6577 the result, abort. */
6578 gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
6579 && (op1mode == mode1 || op1mode == VOIDmode));
6581 if (! (*insn_data[icode].operand[1 + offs].predicate) (op0, mode0))
6582 op0 = copy_to_mode_reg (mode0, op0);
6583 if (! (*insn_data[icode].operand[2 + offs].predicate) (op1, mode1))
6584 op1 = copy_to_mode_reg (mode1, op1);
6586 if (match_op)
6587 pat = GEN_FCN (icode) (target, target, op0, op1);
6588 else
6589 pat = GEN_FCN (icode) (target, op0, op1);
6591 if (! pat)
6592 return 0;
6594 emit_insn (pat);
6596 return ret;
6599 /* Subroutine of c6x_expand_builtin to take care of unop insns. */
6601 static rtx
6602 c6x_expand_unop_builtin (enum insn_code icode, tree exp,
6603 rtx target)
6605 rtx pat;
6606 tree arg0 = CALL_EXPR_ARG (exp, 0);
6607 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, EXPAND_NORMAL);
6608 enum machine_mode op0mode = GET_MODE (op0);
6609 enum machine_mode tmode = insn_data[icode].operand[0].mode;
6610 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
6612 if (! target
6613 || GET_MODE (target) != tmode
6614 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
6615 target = gen_reg_rtx (tmode);
6617 if (VECTOR_MODE_P (mode0))
6618 op0 = safe_vector_operand (op0, mode0);
6620 if (op0mode == SImode && mode0 == HImode)
6622 op0mode = HImode;
6623 op0 = gen_lowpart (HImode, op0);
6625 gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
6627 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6628 op0 = copy_to_mode_reg (mode0, op0);
6630 pat = GEN_FCN (icode) (target, op0);
6631 if (! pat)
6632 return 0;
6633 emit_insn (pat);
6634 return target;
6637 /* Expand an expression EXP that calls a built-in function,
6638 with result going to TARGET if that's convenient
6639 (and in mode MODE if that's convenient).
6640 SUBTARGET may be used as the target for computing one of EXP's operands.
6641 IGNORE is nonzero if the value is to be ignored. */
6643 static rtx
6644 c6x_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
6645 rtx subtarget ATTRIBUTE_UNUSED,
6646 enum machine_mode mode ATTRIBUTE_UNUSED,
6647 int ignore ATTRIBUTE_UNUSED)
6649 size_t i;
6650 const struct builtin_description *d;
6651 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
6652 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
6654 for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
6655 if (d->code == fcode)
6656 return c6x_expand_binop_builtin (d->icode, exp, target,
6657 fcode == C6X_BUILTIN_CLRR);
6659 for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
6660 if (d->code == fcode)
6661 return c6x_expand_unop_builtin (d->icode, exp, target);
6663 gcc_unreachable ();
6666 /* Target unwind frame info is generated from dwarf CFI directives, so
6667 always output dwarf2 unwind info. */
6669 static enum unwind_info_type
6670 c6x_debug_unwind_info (void)
6672 if (flag_unwind_tables || flag_exceptions)
6673 return UI_DWARF2;
6675 return default_debug_unwind_info ();
6678 /* Target Structure. */
6680 /* Initialize the GCC target structure. */
6681 #undef TARGET_FUNCTION_ARG
6682 #define TARGET_FUNCTION_ARG c6x_function_arg
6683 #undef TARGET_FUNCTION_ARG_ADVANCE
6684 #define TARGET_FUNCTION_ARG_ADVANCE c6x_function_arg_advance
6685 #undef TARGET_FUNCTION_ARG_BOUNDARY
6686 #define TARGET_FUNCTION_ARG_BOUNDARY c6x_function_arg_boundary
6687 #undef TARGET_FUNCTION_ARG_ROUND_BOUNDARY
6688 #define TARGET_FUNCTION_ARG_ROUND_BOUNDARY \
6689 c6x_function_arg_round_boundary
6690 #undef TARGET_FUNCTION_VALUE_REGNO_P
6691 #define TARGET_FUNCTION_VALUE_REGNO_P c6x_function_value_regno_p
6692 #undef TARGET_FUNCTION_VALUE
6693 #define TARGET_FUNCTION_VALUE c6x_function_value
6694 #undef TARGET_LIBCALL_VALUE
6695 #define TARGET_LIBCALL_VALUE c6x_libcall_value
6696 #undef TARGET_RETURN_IN_MEMORY
6697 #define TARGET_RETURN_IN_MEMORY c6x_return_in_memory
6698 #undef TARGET_RETURN_IN_MSB
6699 #define TARGET_RETURN_IN_MSB c6x_return_in_msb
6700 #undef TARGET_PASS_BY_REFERENCE
6701 #define TARGET_PASS_BY_REFERENCE c6x_pass_by_reference
6702 #undef TARGET_CALLEE_COPIES
6703 #define TARGET_CALLEE_COPIES c6x_callee_copies
6704 #undef TARGET_STRUCT_VALUE_RTX
6705 #define TARGET_STRUCT_VALUE_RTX c6x_struct_value_rtx
6706 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
6707 #define TARGET_FUNCTION_OK_FOR_SIBCALL c6x_function_ok_for_sibcall
6709 #undef TARGET_ASM_OUTPUT_MI_THUNK
6710 #define TARGET_ASM_OUTPUT_MI_THUNK c6x_output_mi_thunk
6711 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
6712 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK c6x_can_output_mi_thunk
6714 #undef TARGET_BUILD_BUILTIN_VA_LIST
6715 #define TARGET_BUILD_BUILTIN_VA_LIST c6x_build_builtin_va_list
6717 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
6718 #define TARGET_ASM_TRAMPOLINE_TEMPLATE c6x_asm_trampoline_template
6719 #undef TARGET_TRAMPOLINE_INIT
6720 #define TARGET_TRAMPOLINE_INIT c6x_initialize_trampoline
6722 #undef TARGET_LEGITIMATE_CONSTANT_P
6723 #define TARGET_LEGITIMATE_CONSTANT_P c6x_legitimate_constant_p
6724 #undef TARGET_LEGITIMATE_ADDRESS_P
6725 #define TARGET_LEGITIMATE_ADDRESS_P c6x_legitimate_address_p
6727 #undef TARGET_IN_SMALL_DATA_P
6728 #define TARGET_IN_SMALL_DATA_P c6x_in_small_data_p
6729 #undef TARGET_ASM_SELECT_RTX_SECTION
6730 #define TARGET_ASM_SELECT_RTX_SECTION c6x_select_rtx_section
6731 #undef TARGET_ASM_SELECT_SECTION
6732 #define TARGET_ASM_SELECT_SECTION c6x_elf_select_section
6733 #undef TARGET_ASM_UNIQUE_SECTION
6734 #define TARGET_ASM_UNIQUE_SECTION c6x_elf_unique_section
6735 #undef TARGET_SECTION_TYPE_FLAGS
6736 #define TARGET_SECTION_TYPE_FLAGS c6x_section_type_flags
6737 #undef TARGET_HAVE_SRODATA_SECTION
6738 #define TARGET_HAVE_SRODATA_SECTION true
6739 #undef TARGET_ASM_MERGEABLE_RODATA_PREFIX
6740 #define TARGET_ASM_MERGEABLE_RODATA_PREFIX ".const"
6742 #undef TARGET_OPTION_OVERRIDE
6743 #define TARGET_OPTION_OVERRIDE c6x_option_override
6744 #undef TARGET_CONDITIONAL_REGISTER_USAGE
6745 #define TARGET_CONDITIONAL_REGISTER_USAGE c6x_conditional_register_usage
6747 #undef TARGET_INIT_LIBFUNCS
6748 #define TARGET_INIT_LIBFUNCS c6x_init_libfuncs
6749 #undef TARGET_LIBFUNC_GNU_PREFIX
6750 #define TARGET_LIBFUNC_GNU_PREFIX true
6752 #undef TARGET_SCALAR_MODE_SUPPORTED_P
6753 #define TARGET_SCALAR_MODE_SUPPORTED_P c6x_scalar_mode_supported_p
6754 #undef TARGET_VECTOR_MODE_SUPPORTED_P
6755 #define TARGET_VECTOR_MODE_SUPPORTED_P c6x_vector_mode_supported_p
6756 #undef TARGET_VECTORIZE_PREFERRED_SIMD_MODE
6757 #define TARGET_VECTORIZE_PREFERRED_SIMD_MODE c6x_preferred_simd_mode
6759 #undef TARGET_RTX_COSTS
6760 #define TARGET_RTX_COSTS c6x_rtx_costs
6762 #undef TARGET_SCHED_INIT
6763 #define TARGET_SCHED_INIT c6x_sched_init
6764 #undef TARGET_SCHED_SET_SCHED_FLAGS
6765 #define TARGET_SCHED_SET_SCHED_FLAGS c6x_set_sched_flags
6766 #undef TARGET_SCHED_ADJUST_COST
6767 #define TARGET_SCHED_ADJUST_COST c6x_adjust_cost
6768 #undef TARGET_SCHED_ISSUE_RATE
6769 #define TARGET_SCHED_ISSUE_RATE c6x_issue_rate
6770 #undef TARGET_SCHED_VARIABLE_ISSUE
6771 #define TARGET_SCHED_VARIABLE_ISSUE c6x_variable_issue
6772 #undef TARGET_SCHED_REORDER
6773 #define TARGET_SCHED_REORDER c6x_sched_reorder
6774 #undef TARGET_SCHED_REORDER2
6775 #define TARGET_SCHED_REORDER2 c6x_sched_reorder2
6776 #undef TARGET_SCHED_DFA_NEW_CYCLE
6777 #define TARGET_SCHED_DFA_NEW_CYCLE c6x_dfa_new_cycle
6778 #undef TARGET_SCHED_DFA_PRE_CYCLE_INSN
6779 #define TARGET_SCHED_DFA_PRE_CYCLE_INSN c6x_sched_dfa_pre_cycle_insn
6780 #undef TARGET_SCHED_EXPOSED_PIPELINE
6781 #define TARGET_SCHED_EXPOSED_PIPELINE true
6783 #undef TARGET_SCHED_ALLOC_SCHED_CONTEXT
6784 #define TARGET_SCHED_ALLOC_SCHED_CONTEXT c6x_alloc_sched_context
6785 #undef TARGET_SCHED_INIT_SCHED_CONTEXT
6786 #define TARGET_SCHED_INIT_SCHED_CONTEXT c6x_init_sched_context
6787 #undef TARGET_SCHED_SET_SCHED_CONTEXT
6788 #define TARGET_SCHED_SET_SCHED_CONTEXT c6x_set_sched_context
6789 #undef TARGET_SCHED_CLEAR_SCHED_CONTEXT
6790 #define TARGET_SCHED_CLEAR_SCHED_CONTEXT c6x_clear_sched_context
6791 #undef TARGET_SCHED_FREE_SCHED_CONTEXT
6792 #define TARGET_SCHED_FREE_SCHED_CONTEXT c6x_free_sched_context
6794 #undef TARGET_CAN_ELIMINATE
6795 #define TARGET_CAN_ELIMINATE c6x_can_eliminate
6797 #undef TARGET_PREFERRED_RENAME_CLASS
6798 #define TARGET_PREFERRED_RENAME_CLASS c6x_preferred_rename_class
6800 #undef TARGET_MACHINE_DEPENDENT_REORG
6801 #define TARGET_MACHINE_DEPENDENT_REORG c6x_reorg
6803 #undef TARGET_ASM_FILE_START
6804 #define TARGET_ASM_FILE_START c6x_file_start
6806 #undef TARGET_PRINT_OPERAND
6807 #define TARGET_PRINT_OPERAND c6x_print_operand
6808 #undef TARGET_PRINT_OPERAND_ADDRESS
6809 #define TARGET_PRINT_OPERAND_ADDRESS c6x_print_operand_address
6810 #undef TARGET_PRINT_OPERAND_PUNCT_VALID_P
6811 #define TARGET_PRINT_OPERAND_PUNCT_VALID_P c6x_print_operand_punct_valid_p
6813 /* C6x unwinding tables use a different format for the typeinfo tables. */
6814 #undef TARGET_ASM_TTYPE
6815 #define TARGET_ASM_TTYPE c6x_output_ttype
6817 /* The C6x ABI follows the ARM EABI exception handling rules. */
6818 #undef TARGET_ARM_EABI_UNWINDER
6819 #define TARGET_ARM_EABI_UNWINDER true
6821 #undef TARGET_ASM_EMIT_EXCEPT_PERSONALITY
6822 #define TARGET_ASM_EMIT_EXCEPT_PERSONALITY c6x_asm_emit_except_personality
6824 #undef TARGET_ASM_INIT_SECTIONS
6825 #define TARGET_ASM_INIT_SECTIONS c6x_asm_init_sections
6827 #undef TARGET_DEBUG_UNWIND_INFO
6828 #define TARGET_DEBUG_UNWIND_INFO c6x_debug_unwind_info
6830 #undef TARGET_DWARF_REGISTER_SPAN
6831 #define TARGET_DWARF_REGISTER_SPAN c6x_dwarf_register_span
6833 #undef TARGET_INIT_BUILTINS
6834 #define TARGET_INIT_BUILTINS c6x_init_builtins
6835 #undef TARGET_EXPAND_BUILTIN
6836 #define TARGET_EXPAND_BUILTIN c6x_expand_builtin
6837 #undef TARGET_BUILTIN_DECL
6838 #define TARGET_BUILTIN_DECL c6x_builtin_decl
6840 struct gcc_target targetm = TARGET_INITIALIZER;
6842 #include "gt-c6x.h"