Merged with mainline at revision 128810.
[official-gcc.git] / gcc / config / bfin / bfin.c
blobc3b59880104da5bfafd8a9fd2ef234d6b31542f7
1 /* The Blackfin code generation auxiliary output file.
2 Copyright (C) 2005, 2006, 2007 Free Software Foundation, Inc.
3 Contributed by Analog Devices.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published
9 by the Free Software Foundation; either version 3, or (at your
10 option) any later version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "rtl.h"
26 #include "regs.h"
27 #include "hard-reg-set.h"
28 #include "real.h"
29 #include "insn-config.h"
30 #include "insn-codes.h"
31 #include "conditions.h"
32 #include "insn-flags.h"
33 #include "output.h"
34 #include "insn-attr.h"
35 #include "tree.h"
36 #include "flags.h"
37 #include "except.h"
38 #include "function.h"
39 #include "input.h"
40 #include "target.h"
41 #include "target-def.h"
42 #include "expr.h"
43 #include "toplev.h"
44 #include "recog.h"
45 #include "optabs.h"
46 #include "ggc.h"
47 #include "integrate.h"
48 #include "cgraph.h"
49 #include "langhooks.h"
50 #include "bfin-protos.h"
51 #include "tm-preds.h"
52 #include "gt-bfin.h"
53 #include "basic-block.h"
54 #include "cfglayout.h"
55 #include "timevar.h"
56 #include "df.h"
58 /* A C structure for machine-specific, per-function data.
59 This is added to the cfun structure. */
60 struct machine_function GTY(())
62 int has_hardware_loops;
65 /* Test and compare insns in bfin.md store the information needed to
66 generate branch and scc insns here. */
67 rtx bfin_compare_op0, bfin_compare_op1;
69 /* RTX for condition code flag register and RETS register */
70 extern GTY(()) rtx bfin_cc_rtx;
71 extern GTY(()) rtx bfin_rets_rtx;
72 rtx bfin_cc_rtx, bfin_rets_rtx;
74 int max_arg_registers = 0;
76 /* Arrays used when emitting register names. */
77 const char *short_reg_names[] = SHORT_REGISTER_NAMES;
78 const char *high_reg_names[] = HIGH_REGISTER_NAMES;
79 const char *dregs_pair_names[] = DREGS_PAIR_NAMES;
80 const char *byte_reg_names[] = BYTE_REGISTER_NAMES;
82 static int arg_regs[] = FUNCTION_ARG_REGISTERS;
84 /* Nonzero if -mshared-library-id was given. */
85 static int bfin_lib_id_given;
87 /* Nonzero if -fschedule-insns2 was given. We override it and
88 call the scheduler ourselves during reorg. */
89 static int bfin_flag_schedule_insns2;
91 /* Determines whether we run variable tracking in machine dependent
92 reorganization. */
93 static int bfin_flag_var_tracking;
95 /* -mcpu support */
96 bfin_cpu_t bfin_cpu_type = DEFAULT_CPU_TYPE;
98 /* -msi-revision support. There are three special values:
99 -1 -msi-revision=none.
100 0xffff -msi-revision=any. */
101 int bfin_si_revision;
103 /* The workarounds enabled */
104 unsigned int bfin_workarounds = 0;
106 struct bfin_cpu
108 const char *name;
109 bfin_cpu_t type;
110 int si_revision;
111 unsigned int workarounds;
114 struct bfin_cpu bfin_cpus[] =
116 {"bf522", BFIN_CPU_BF522, 0x0000,
117 WA_SPECULATIVE_LOADS},
119 {"bf525", BFIN_CPU_BF525, 0x0000,
120 WA_SPECULATIVE_LOADS},
122 {"bf527", BFIN_CPU_BF527, 0x0000,
123 WA_SPECULATIVE_LOADS},
125 {"bf531", BFIN_CPU_BF531, 0x0005,
126 WA_SPECULATIVE_LOADS},
127 {"bf531", BFIN_CPU_BF531, 0x0004,
128 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS},
129 {"bf531", BFIN_CPU_BF531, 0x0003,
130 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS},
132 {"bf532", BFIN_CPU_BF532, 0x0005,
133 WA_SPECULATIVE_LOADS},
134 {"bf532", BFIN_CPU_BF532, 0x0004,
135 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS},
136 {"bf532", BFIN_CPU_BF532, 0x0003,
137 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS},
139 {"bf533", BFIN_CPU_BF533, 0x0005,
140 WA_SPECULATIVE_LOADS},
141 {"bf533", BFIN_CPU_BF533, 0x0004,
142 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS},
143 {"bf533", BFIN_CPU_BF533, 0x0003,
144 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS},
146 {"bf534", BFIN_CPU_BF534, 0x0003,
147 WA_SPECULATIVE_LOADS},
148 {"bf534", BFIN_CPU_BF534, 0x0002,
149 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS},
150 {"bf534", BFIN_CPU_BF534, 0x0001,
151 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS},
153 {"bf536", BFIN_CPU_BF536, 0x0003,
154 WA_SPECULATIVE_LOADS},
155 {"bf536", BFIN_CPU_BF536, 0x0002,
156 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS},
157 {"bf536", BFIN_CPU_BF536, 0x0001,
158 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS},
160 {"bf537", BFIN_CPU_BF537, 0x0003,
161 WA_SPECULATIVE_LOADS},
162 {"bf537", BFIN_CPU_BF537, 0x0002,
163 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS},
164 {"bf537", BFIN_CPU_BF537, 0x0001,
165 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS},
167 {"bf538", BFIN_CPU_BF538, 0x0004,
168 WA_SPECULATIVE_LOADS},
169 {"bf538", BFIN_CPU_BF538, 0x0003,
170 WA_SPECULATIVE_LOADS},
172 {"bf539", BFIN_CPU_BF539, 0x0004,
173 WA_SPECULATIVE_LOADS},
174 {"bf539", BFIN_CPU_BF539, 0x0003,
175 WA_SPECULATIVE_LOADS},
176 {"bf539", BFIN_CPU_BF539, 0x0002,
177 WA_SPECULATIVE_LOADS},
179 {"bf542", BFIN_CPU_BF542, 0x0000,
180 WA_SPECULATIVE_LOADS},
182 {"bf544", BFIN_CPU_BF544, 0x0000,
183 WA_SPECULATIVE_LOADS},
185 {"bf548", BFIN_CPU_BF548, 0x0000,
186 WA_SPECULATIVE_LOADS},
188 {"bf549", BFIN_CPU_BF549, 0x0000,
189 WA_SPECULATIVE_LOADS},
191 {"bf561", BFIN_CPU_BF561, 0x0005, 0},
192 {"bf561", BFIN_CPU_BF561, 0x0003,
193 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS},
194 {"bf561", BFIN_CPU_BF561, 0x0002,
195 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS},
197 {NULL, 0, 0, 0}
200 int splitting_for_sched;
202 static void
203 bfin_globalize_label (FILE *stream, const char *name)
205 fputs (".global ", stream);
206 assemble_name (stream, name);
207 fputc (';',stream);
208 fputc ('\n',stream);
211 static void
212 output_file_start (void)
214 FILE *file = asm_out_file;
215 int i;
217 /* Variable tracking should be run after all optimizations which change order
218 of insns. It also needs a valid CFG. This can't be done in
219 override_options, because flag_var_tracking is finalized after
220 that. */
221 bfin_flag_var_tracking = flag_var_tracking;
222 flag_var_tracking = 0;
224 fprintf (file, ".file \"%s\";\n", input_filename);
226 for (i = 0; arg_regs[i] >= 0; i++)
228 max_arg_registers = i; /* how many arg reg used */
231 /* Called early in the compilation to conditionally modify
232 fixed_regs/call_used_regs. */
234 void
235 conditional_register_usage (void)
237 /* initialize condition code flag register rtx */
238 bfin_cc_rtx = gen_rtx_REG (BImode, REG_CC);
239 bfin_rets_rtx = gen_rtx_REG (Pmode, REG_RETS);
242 /* Examine machine-dependent attributes of function type FUNTYPE and return its
243 type. See the definition of E_FUNKIND. */
245 static e_funkind
246 funkind (const_tree funtype)
248 tree attrs = TYPE_ATTRIBUTES (funtype);
249 if (lookup_attribute ("interrupt_handler", attrs))
250 return INTERRUPT_HANDLER;
251 else if (lookup_attribute ("exception_handler", attrs))
252 return EXCPT_HANDLER;
253 else if (lookup_attribute ("nmi_handler", attrs))
254 return NMI_HANDLER;
255 else
256 return SUBROUTINE;
259 /* Legitimize PIC addresses. If the address is already position-independent,
260 we return ORIG. Newly generated position-independent addresses go into a
261 reg. This is REG if nonzero, otherwise we allocate register(s) as
262 necessary. PICREG is the register holding the pointer to the PIC offset
263 table. */
265 static rtx
266 legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
268 rtx addr = orig;
269 rtx new = orig;
271 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
273 int unspec;
274 rtx tmp;
276 if (TARGET_ID_SHARED_LIBRARY)
277 unspec = UNSPEC_MOVE_PIC;
278 else if (GET_CODE (addr) == SYMBOL_REF
279 && SYMBOL_REF_FUNCTION_P (addr))
280 unspec = UNSPEC_FUNCDESC_GOT17M4;
281 else
282 unspec = UNSPEC_MOVE_FDPIC;
284 if (reg == 0)
286 gcc_assert (can_create_pseudo_p ());
287 reg = gen_reg_rtx (Pmode);
290 tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), unspec);
291 new = gen_const_mem (Pmode, gen_rtx_PLUS (Pmode, picreg, tmp));
293 emit_move_insn (reg, new);
294 if (picreg == pic_offset_table_rtx)
295 current_function_uses_pic_offset_table = 1;
296 return reg;
299 else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
301 rtx base;
303 if (GET_CODE (addr) == CONST)
305 addr = XEXP (addr, 0);
306 gcc_assert (GET_CODE (addr) == PLUS);
309 if (XEXP (addr, 0) == picreg)
310 return orig;
312 if (reg == 0)
314 gcc_assert (can_create_pseudo_p ());
315 reg = gen_reg_rtx (Pmode);
318 base = legitimize_pic_address (XEXP (addr, 0), reg, picreg);
319 addr = legitimize_pic_address (XEXP (addr, 1),
320 base == reg ? NULL_RTX : reg,
321 picreg);
323 if (GET_CODE (addr) == CONST_INT)
325 gcc_assert (! reload_in_progress && ! reload_completed);
326 addr = force_reg (Pmode, addr);
329 if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
331 base = gen_rtx_PLUS (Pmode, base, XEXP (addr, 0));
332 addr = XEXP (addr, 1);
335 return gen_rtx_PLUS (Pmode, base, addr);
338 return new;
341 /* Stack frame layout. */
343 /* Compute the number of DREGS to save with a push_multiple operation.
344 This could include registers that aren't modified in the function,
345 since push_multiple only takes a range of registers.
346 If IS_INTHANDLER, then everything that is live must be saved, even
347 if normally call-clobbered. */
349 static int
350 n_dregs_to_save (bool is_inthandler)
352 unsigned i;
354 for (i = REG_R0; i <= REG_R7; i++)
356 if (df_regs_ever_live_p (i) && (is_inthandler || ! call_used_regs[i]))
357 return REG_R7 - i + 1;
359 if (current_function_calls_eh_return)
361 unsigned j;
362 for (j = 0; ; j++)
364 unsigned test = EH_RETURN_DATA_REGNO (j);
365 if (test == INVALID_REGNUM)
366 break;
367 if (test == i)
368 return REG_R7 - i + 1;
373 return 0;
376 /* Like n_dregs_to_save, but compute number of PREGS to save. */
378 static int
379 n_pregs_to_save (bool is_inthandler)
381 unsigned i;
383 for (i = REG_P0; i <= REG_P5; i++)
384 if ((df_regs_ever_live_p (i) && (is_inthandler || ! call_used_regs[i]))
385 || (!TARGET_FDPIC
386 && i == PIC_OFFSET_TABLE_REGNUM
387 && (current_function_uses_pic_offset_table
388 || (TARGET_ID_SHARED_LIBRARY && ! current_function_is_leaf))))
389 return REG_P5 - i + 1;
390 return 0;
393 /* Determine if we are going to save the frame pointer in the prologue. */
395 static bool
396 must_save_fp_p (void)
398 return frame_pointer_needed || df_regs_ever_live_p (REG_FP);
401 static bool
402 stack_frame_needed_p (void)
404 /* EH return puts a new return address into the frame using an
405 address relative to the frame pointer. */
406 if (current_function_calls_eh_return)
407 return true;
408 return frame_pointer_needed;
411 /* Emit code to save registers in the prologue. SAVEALL is nonzero if we
412 must save all registers; this is used for interrupt handlers.
413 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
414 this for an interrupt (or exception) handler. */
416 static void
417 expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler)
419 rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
420 rtx predec = gen_rtx_MEM (SImode, predec1);
421 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler);
422 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler);
423 int dregno = REG_R7 + 1 - ndregs;
424 int pregno = REG_P5 + 1 - npregs;
425 int total = ndregs + npregs;
426 int i;
427 rtx pat, insn, val;
429 if (saveall || is_inthandler)
431 insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
432 RTX_FRAME_RELATED_P (insn) = 1;
435 if (total == 0 && !saveall)
436 return;
438 val = GEN_INT (-total * 4);
439 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total + 2));
440 XVECEXP (pat, 0, 0) = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, val),
441 UNSPEC_PUSH_MULTIPLE);
442 XVECEXP (pat, 0, total + 1) = gen_rtx_SET (VOIDmode, spreg,
443 gen_rtx_PLUS (Pmode, spreg,
444 val));
445 RTX_FRAME_RELATED_P (XVECEXP (pat, 0, total + 1)) = 1;
446 for (i = 0; i < total; i++)
448 rtx memref = gen_rtx_MEM (word_mode,
449 gen_rtx_PLUS (Pmode, spreg,
450 GEN_INT (- i * 4 - 4)));
451 rtx subpat;
452 if (ndregs > 0)
454 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
455 dregno++));
456 ndregs--;
458 else
460 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
461 pregno++));
462 npregs++;
464 XVECEXP (pat, 0, i + 1) = subpat;
465 RTX_FRAME_RELATED_P (subpat) = 1;
467 insn = emit_insn (pat);
468 RTX_FRAME_RELATED_P (insn) = 1;
470 for (i = REG_P7 + 1; i < REG_CC; i++)
471 if (saveall
472 || (is_inthandler
473 && (df_regs_ever_live_p (i)
474 || (!leaf_function_p () && call_used_regs[i]))))
476 if (i == REG_A0 || i == REG_A1)
477 insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1),
478 gen_rtx_REG (PDImode, i));
479 else
480 insn = emit_move_insn (predec, gen_rtx_REG (SImode, i));
481 RTX_FRAME_RELATED_P (insn) = 1;
485 /* Emit code to restore registers in the epilogue. SAVEALL is nonzero if we
486 must save all registers; this is used for interrupt handlers.
487 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
488 this for an interrupt (or exception) handler. */
490 static void
491 expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler)
493 rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
494 rtx postinc = gen_rtx_MEM (SImode, postinc1);
496 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler);
497 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler);
498 int total = ndregs + npregs;
499 int i, regno;
500 rtx pat, insn;
502 /* A slightly crude technique to stop flow from trying to delete "dead"
503 insns. */
504 MEM_VOLATILE_P (postinc) = 1;
506 for (i = REG_CC - 1; i > REG_P7; i--)
507 if (saveall
508 || (is_inthandler
509 && (df_regs_ever_live_p (i)
510 || (!leaf_function_p () && call_used_regs[i]))))
512 if (i == REG_A0 || i == REG_A1)
514 rtx mem = gen_rtx_MEM (PDImode, postinc1);
515 MEM_VOLATILE_P (mem) = 1;
516 emit_move_insn (gen_rtx_REG (PDImode, i), mem);
518 else
519 emit_move_insn (gen_rtx_REG (SImode, i), postinc);
522 if (total == 0)
523 return;
525 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total + 1));
526 XVECEXP (pat, 0, 0) = gen_rtx_SET (VOIDmode, spreg,
527 gen_rtx_PLUS (Pmode, spreg,
528 GEN_INT (total * 4)));
530 if (npregs > 0)
531 regno = REG_P5 + 1;
532 else
533 regno = REG_R7 + 1;
535 for (i = 0; i < total; i++)
537 rtx addr = (i > 0
538 ? gen_rtx_PLUS (Pmode, spreg, GEN_INT (i * 4))
539 : spreg);
540 rtx memref = gen_rtx_MEM (word_mode, addr);
542 regno--;
543 XVECEXP (pat, 0, i + 1)
544 = gen_rtx_SET (VOIDmode, gen_rtx_REG (word_mode, regno), memref);
546 if (npregs > 0)
548 if (--npregs == 0)
549 regno = REG_R7 + 1;
553 insn = emit_insn (pat);
554 RTX_FRAME_RELATED_P (insn) = 1;
556 if (saveall || is_inthandler)
557 emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
560 /* Perform any needed actions needed for a function that is receiving a
561 variable number of arguments.
563 CUM is as above.
565 MODE and TYPE are the mode and type of the current parameter.
567 PRETEND_SIZE is a variable that should be set to the amount of stack
568 that must be pushed by the prolog to pretend that our caller pushed
571 Normally, this macro will push all remaining incoming registers on the
572 stack and set PRETEND_SIZE to the length of the registers pushed.
574 Blackfin specific :
575 - VDSP C compiler manual (our ABI) says that a variable args function
576 should save the R0, R1 and R2 registers in the stack.
577 - The caller will always leave space on the stack for the
578 arguments that are passed in registers, so we dont have
579 to leave any extra space.
580 - now, the vastart pointer can access all arguments from the stack. */
582 static void
583 setup_incoming_varargs (CUMULATIVE_ARGS *cum,
584 enum machine_mode mode ATTRIBUTE_UNUSED,
585 tree type ATTRIBUTE_UNUSED, int *pretend_size,
586 int no_rtl)
588 rtx mem;
589 int i;
591 if (no_rtl)
592 return;
594 /* The move for named arguments will be generated automatically by the
595 compiler. We need to generate the move rtx for the unnamed arguments
596 if they are in the first 3 words. We assume at least 1 named argument
597 exists, so we never generate [ARGP] = R0 here. */
599 for (i = cum->words + 1; i < max_arg_registers; i++)
601 mem = gen_rtx_MEM (Pmode,
602 plus_constant (arg_pointer_rtx, (i * UNITS_PER_WORD)));
603 emit_move_insn (mem, gen_rtx_REG (Pmode, i));
606 *pretend_size = 0;
609 /* Value should be nonzero if functions must have frame pointers.
610 Zero means the frame pointer need not be set up (and parms may
611 be accessed via the stack pointer) in functions that seem suitable. */
614 bfin_frame_pointer_required (void)
616 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
618 if (fkind != SUBROUTINE)
619 return 1;
621 /* We turn on -fomit-frame-pointer if -momit-leaf-frame-pointer is used,
622 so we have to override it for non-leaf functions. */
623 if (TARGET_OMIT_LEAF_FRAME_POINTER && ! current_function_is_leaf)
624 return 1;
626 return 0;
629 /* Return the number of registers pushed during the prologue. */
631 static int
632 n_regs_saved_by_prologue (void)
634 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
635 bool is_inthandler = fkind != SUBROUTINE;
636 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
637 bool all = (lookup_attribute ("saveall", attrs) != NULL_TREE
638 || (is_inthandler && !current_function_is_leaf));
639 int ndregs = all ? 8 : n_dregs_to_save (is_inthandler);
640 int npregs = all ? 6 : n_pregs_to_save (is_inthandler);
641 int n = ndregs + npregs;
642 int i;
644 if (all || stack_frame_needed_p ())
645 /* We use a LINK instruction in this case. */
646 n += 2;
647 else
649 if (must_save_fp_p ())
650 n++;
651 if (! current_function_is_leaf)
652 n++;
655 if (fkind != SUBROUTINE || all)
656 /* Increment once for ASTAT. */
657 n++;
659 if (fkind != SUBROUTINE)
661 /* RETE/X/N. */
662 if (lookup_attribute ("nesting", attrs))
663 n++;
666 for (i = REG_P7 + 1; i < REG_CC; i++)
667 if (all
668 || (fkind != SUBROUTINE
669 && (df_regs_ever_live_p (i)
670 || (!leaf_function_p () && call_used_regs[i]))))
671 n += i == REG_A0 || i == REG_A1 ? 2 : 1;
673 return n;
676 /* Return the offset between two registers, one to be eliminated, and the other
677 its replacement, at the start of a routine. */
679 HOST_WIDE_INT
680 bfin_initial_elimination_offset (int from, int to)
682 HOST_WIDE_INT offset = 0;
684 if (from == ARG_POINTER_REGNUM)
685 offset = n_regs_saved_by_prologue () * 4;
687 if (to == STACK_POINTER_REGNUM)
689 if (current_function_outgoing_args_size >= FIXED_STACK_AREA)
690 offset += current_function_outgoing_args_size;
691 else if (current_function_outgoing_args_size)
692 offset += FIXED_STACK_AREA;
694 offset += get_frame_size ();
697 return offset;
700 /* Emit code to load a constant CONSTANT into register REG; setting
701 RTX_FRAME_RELATED_P on all insns we generate if RELATED is true.
702 Make sure that the insns we generate need not be split. */
704 static void
705 frame_related_constant_load (rtx reg, HOST_WIDE_INT constant, bool related)
707 rtx insn;
708 rtx cst = GEN_INT (constant);
710 if (constant >= -32768 && constant < 65536)
711 insn = emit_move_insn (reg, cst);
712 else
714 /* We don't call split_load_immediate here, since dwarf2out.c can get
715 confused about some of the more clever sequences it can generate. */
716 insn = emit_insn (gen_movsi_high (reg, cst));
717 if (related)
718 RTX_FRAME_RELATED_P (insn) = 1;
719 insn = emit_insn (gen_movsi_low (reg, reg, cst));
721 if (related)
722 RTX_FRAME_RELATED_P (insn) = 1;
725 /* Generate efficient code to add a value to a P register.
726 Set RTX_FRAME_RELATED_P on the generated insns if FRAME is nonzero.
727 EPILOGUE_P is zero if this function is called for prologue,
728 otherwise it's nonzero. And it's less than zero if this is for
729 sibcall epilogue. */
731 static void
732 add_to_reg (rtx reg, HOST_WIDE_INT value, int frame, int epilogue_p)
734 if (value == 0)
735 return;
737 /* Choose whether to use a sequence using a temporary register, or
738 a sequence with multiple adds. We can add a signed 7-bit value
739 in one instruction. */
740 if (value > 120 || value < -120)
742 rtx tmpreg;
743 rtx tmpreg2;
744 rtx insn;
746 tmpreg2 = NULL_RTX;
748 /* For prologue or normal epilogue, P1 can be safely used
749 as the temporary register. For sibcall epilogue, we try to find
750 a call used P register, which will be restored in epilogue.
751 If we cannot find such a P register, we have to use one I register
752 to help us. */
754 if (epilogue_p >= 0)
755 tmpreg = gen_rtx_REG (SImode, REG_P1);
756 else
758 int i;
759 for (i = REG_P0; i <= REG_P5; i++)
760 if ((df_regs_ever_live_p (i) && ! call_used_regs[i])
761 || (!TARGET_FDPIC
762 && i == PIC_OFFSET_TABLE_REGNUM
763 && (current_function_uses_pic_offset_table
764 || (TARGET_ID_SHARED_LIBRARY
765 && ! current_function_is_leaf))))
766 break;
767 if (i <= REG_P5)
768 tmpreg = gen_rtx_REG (SImode, i);
769 else
771 tmpreg = gen_rtx_REG (SImode, REG_P1);
772 tmpreg2 = gen_rtx_REG (SImode, REG_I0);
773 emit_move_insn (tmpreg2, tmpreg);
777 if (frame)
778 frame_related_constant_load (tmpreg, value, TRUE);
779 else
780 insn = emit_move_insn (tmpreg, GEN_INT (value));
782 insn = emit_insn (gen_addsi3 (reg, reg, tmpreg));
783 if (frame)
784 RTX_FRAME_RELATED_P (insn) = 1;
786 if (tmpreg2 != NULL_RTX)
787 emit_move_insn (tmpreg, tmpreg2);
789 else
792 int size = value;
793 rtx insn;
795 if (size > 60)
796 size = 60;
797 else if (size < -60)
798 /* We could use -62, but that would leave the stack unaligned, so
799 it's no good. */
800 size = -60;
802 insn = emit_insn (gen_addsi3 (reg, reg, GEN_INT (size)));
803 if (frame)
804 RTX_FRAME_RELATED_P (insn) = 1;
805 value -= size;
807 while (value != 0);
810 /* Generate a LINK insn for a frame sized FRAME_SIZE. If this constant
811 is too large, generate a sequence of insns that has the same effect.
812 SPREG contains (reg:SI REG_SP). */
814 static void
815 emit_link_insn (rtx spreg, HOST_WIDE_INT frame_size)
817 HOST_WIDE_INT link_size = frame_size;
818 rtx insn;
819 int i;
821 if (link_size > 262140)
822 link_size = 262140;
824 /* Use a LINK insn with as big a constant as possible, then subtract
825 any remaining size from the SP. */
826 insn = emit_insn (gen_link (GEN_INT (-8 - link_size)));
827 RTX_FRAME_RELATED_P (insn) = 1;
829 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
831 rtx set = XVECEXP (PATTERN (insn), 0, i);
832 gcc_assert (GET_CODE (set) == SET);
833 RTX_FRAME_RELATED_P (set) = 1;
836 frame_size -= link_size;
838 if (frame_size > 0)
840 /* Must use a call-clobbered PREG that isn't the static chain. */
841 rtx tmpreg = gen_rtx_REG (Pmode, REG_P1);
843 frame_related_constant_load (tmpreg, -frame_size, TRUE);
844 insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg));
845 RTX_FRAME_RELATED_P (insn) = 1;
849 /* Return the number of bytes we must reserve for outgoing arguments
850 in the current function's stack frame. */
852 static HOST_WIDE_INT
853 arg_area_size (void)
855 if (current_function_outgoing_args_size)
857 if (current_function_outgoing_args_size >= FIXED_STACK_AREA)
858 return current_function_outgoing_args_size;
859 else
860 return FIXED_STACK_AREA;
862 return 0;
865 /* Save RETS and FP, and allocate a stack frame. ALL is true if the
866 function must save all its registers (true only for certain interrupt
867 handlers). */
869 static void
870 do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all)
872 frame_size += arg_area_size ();
874 if (all || stack_frame_needed_p ()
875 || (must_save_fp_p () && ! current_function_is_leaf))
876 emit_link_insn (spreg, frame_size);
877 else
879 if (! current_function_is_leaf)
881 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
882 gen_rtx_PRE_DEC (Pmode, spreg)),
883 bfin_rets_rtx);
884 rtx insn = emit_insn (pat);
885 RTX_FRAME_RELATED_P (insn) = 1;
887 if (must_save_fp_p ())
889 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
890 gen_rtx_PRE_DEC (Pmode, spreg)),
891 gen_rtx_REG (Pmode, REG_FP));
892 rtx insn = emit_insn (pat);
893 RTX_FRAME_RELATED_P (insn) = 1;
895 add_to_reg (spreg, -frame_size, 1, 0);
899 /* Like do_link, but used for epilogues to deallocate the stack frame.
900 EPILOGUE_P is zero if this function is called for prologue,
901 otherwise it's nonzero. And it's less than zero if this is for
902 sibcall epilogue. */
904 static void
905 do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all, int epilogue_p)
907 frame_size += arg_area_size ();
909 if (all || stack_frame_needed_p ())
910 emit_insn (gen_unlink ());
911 else
913 rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg));
915 add_to_reg (spreg, frame_size, 0, epilogue_p);
916 if (must_save_fp_p ())
918 rtx fpreg = gen_rtx_REG (Pmode, REG_FP);
919 emit_move_insn (fpreg, postinc);
920 emit_insn (gen_rtx_USE (VOIDmode, fpreg));
922 if (! current_function_is_leaf)
924 emit_move_insn (bfin_rets_rtx, postinc);
925 emit_insn (gen_rtx_USE (VOIDmode, bfin_rets_rtx));
930 /* Generate a prologue suitable for a function of kind FKIND. This is
931 called for interrupt and exception handler prologues.
932 SPREG contains (reg:SI REG_SP). */
934 static void
935 expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind, bool all)
937 HOST_WIDE_INT frame_size = get_frame_size ();
938 rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
939 rtx predec = gen_rtx_MEM (SImode, predec1);
940 rtx insn;
941 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
942 tree kspisusp = lookup_attribute ("kspisusp", attrs);
944 if (kspisusp)
946 insn = emit_move_insn (spreg, gen_rtx_REG (Pmode, REG_USP));
947 RTX_FRAME_RELATED_P (insn) = 1;
950 /* We need space on the stack in case we need to save the argument
951 registers. */
952 if (fkind == EXCPT_HANDLER)
954 insn = emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (-12)));
955 RTX_FRAME_RELATED_P (insn) = 1;
958 /* If we're calling other functions, they won't save their call-clobbered
959 registers, so we must save everything here. */
960 if (!current_function_is_leaf)
961 all = true;
962 expand_prologue_reg_save (spreg, all, true);
964 if (lookup_attribute ("nesting", attrs))
966 rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
967 : fkind == NMI_HANDLER ? REG_RETN
968 : REG_RETI));
969 insn = emit_move_insn (predec, srcreg);
970 RTX_FRAME_RELATED_P (insn) = 1;
973 do_link (spreg, frame_size, all);
975 if (fkind == EXCPT_HANDLER)
977 rtx r0reg = gen_rtx_REG (SImode, REG_R0);
978 rtx r1reg = gen_rtx_REG (SImode, REG_R1);
979 rtx r2reg = gen_rtx_REG (SImode, REG_R2);
980 rtx insn;
982 insn = emit_move_insn (r0reg, gen_rtx_REG (SImode, REG_SEQSTAT));
983 insn = emit_insn (gen_ashrsi3 (r0reg, r0reg, GEN_INT (26)));
984 insn = emit_insn (gen_ashlsi3 (r0reg, r0reg, GEN_INT (26)));
985 insn = emit_move_insn (r1reg, spreg);
986 insn = emit_move_insn (r2reg, gen_rtx_REG (Pmode, REG_FP));
987 insn = emit_insn (gen_addsi3 (r2reg, r2reg, GEN_INT (8)));
991 /* Generate an epilogue suitable for a function of kind FKIND. This is
992 called for interrupt and exception handler epilogues.
993 SPREG contains (reg:SI REG_SP). */
995 static void
996 expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind, bool all)
998 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
999 rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
1000 rtx postinc = gen_rtx_MEM (SImode, postinc1);
1002 /* A slightly crude technique to stop flow from trying to delete "dead"
1003 insns. */
1004 MEM_VOLATILE_P (postinc) = 1;
1006 do_unlink (spreg, get_frame_size (), all, 1);
1008 if (lookup_attribute ("nesting", attrs))
1010 rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
1011 : fkind == NMI_HANDLER ? REG_RETN
1012 : REG_RETI));
1013 emit_move_insn (srcreg, postinc);
1016 /* If we're calling other functions, they won't save their call-clobbered
1017 registers, so we must save (and restore) everything here. */
1018 if (!current_function_is_leaf)
1019 all = true;
1021 expand_epilogue_reg_restore (spreg, all, true);
1023 /* Deallocate any space we left on the stack in case we needed to save the
1024 argument registers. */
1025 if (fkind == EXCPT_HANDLER)
1026 emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (12)));
1028 emit_jump_insn (gen_return_internal (GEN_INT (fkind)));
1031 /* Used while emitting the prologue to generate code to load the correct value
1032 into the PIC register, which is passed in DEST. */
1034 static rtx
1035 bfin_load_pic_reg (rtx dest)
1037 struct cgraph_local_info *i = NULL;
1038 rtx addr, insn;
1040 if (flag_unit_at_a_time)
1041 i = cgraph_local_info (current_function_decl);
1043 /* Functions local to the translation unit don't need to reload the
1044 pic reg, since the caller always passes a usable one. */
1045 if (i && i->local)
1046 return pic_offset_table_rtx;
1048 if (bfin_lib_id_given)
1049 addr = plus_constant (pic_offset_table_rtx, -4 - bfin_library_id * 4);
1050 else
1051 addr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
1052 gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
1053 UNSPEC_LIBRARY_OFFSET));
1054 insn = emit_insn (gen_movsi (dest, gen_rtx_MEM (Pmode, addr)));
1055 return dest;
1058 /* Generate RTL for the prologue of the current function. */
1060 void
1061 bfin_expand_prologue (void)
1063 HOST_WIDE_INT frame_size = get_frame_size ();
1064 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
1065 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1066 rtx pic_reg_loaded = NULL_RTX;
1067 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1068 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
1070 if (fkind != SUBROUTINE)
1072 expand_interrupt_handler_prologue (spreg, fkind, all);
1073 return;
1076 if (current_function_limit_stack
1077 || TARGET_STACK_CHECK_L1)
1079 HOST_WIDE_INT offset
1080 = bfin_initial_elimination_offset (ARG_POINTER_REGNUM,
1081 STACK_POINTER_REGNUM);
1082 rtx lim = current_function_limit_stack ? stack_limit_rtx : NULL_RTX;
1083 rtx p2reg = gen_rtx_REG (Pmode, REG_P2);
1085 if (!lim)
1087 emit_move_insn (p2reg, gen_int_mode (0xFFB00000, SImode));
1088 emit_move_insn (p2reg, gen_rtx_MEM (Pmode, p2reg));
1089 lim = p2reg;
1091 if (GET_CODE (lim) == SYMBOL_REF)
1093 if (TARGET_ID_SHARED_LIBRARY)
1095 rtx p1reg = gen_rtx_REG (Pmode, REG_P1);
1096 rtx val;
1097 pic_reg_loaded = bfin_load_pic_reg (p2reg);
1098 val = legitimize_pic_address (stack_limit_rtx, p1reg,
1099 pic_reg_loaded);
1100 emit_move_insn (p1reg, val);
1101 frame_related_constant_load (p2reg, offset, FALSE);
1102 emit_insn (gen_addsi3 (p2reg, p2reg, p1reg));
1103 lim = p2reg;
1105 else
1107 rtx limit = plus_constant (lim, offset);
1108 emit_move_insn (p2reg, limit);
1109 lim = p2reg;
1112 else
1114 if (lim != p2reg)
1115 emit_move_insn (p2reg, lim);
1116 add_to_reg (p2reg, offset, 0, 0);
1117 lim = p2reg;
1119 emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim));
1120 emit_insn (gen_trapifcc ());
1122 expand_prologue_reg_save (spreg, all, false);
1124 do_link (spreg, frame_size, false);
1126 if (TARGET_ID_SHARED_LIBRARY
1127 && !TARGET_SEP_DATA
1128 && (current_function_uses_pic_offset_table
1129 || !current_function_is_leaf))
1130 bfin_load_pic_reg (pic_offset_table_rtx);
1133 /* Generate RTL for the epilogue of the current function. NEED_RETURN is zero
1134 if this is for a sibcall. EH_RETURN is nonzero if we're expanding an
1135 eh_return pattern. SIBCALL_P is true if this is a sibcall epilogue,
1136 false otherwise. */
1138 void
1139 bfin_expand_epilogue (int need_return, int eh_return, bool sibcall_p)
1141 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
1142 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1143 int e = sibcall_p ? -1 : 1;
1144 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1145 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
1147 if (fkind != SUBROUTINE)
1149 expand_interrupt_handler_epilogue (spreg, fkind, all);
1150 return;
1153 do_unlink (spreg, get_frame_size (), false, e);
1155 expand_epilogue_reg_restore (spreg, all, false);
1157 /* Omit the return insn if this is for a sibcall. */
1158 if (! need_return)
1159 return;
1161 if (eh_return)
1162 emit_insn (gen_addsi3 (spreg, spreg, gen_rtx_REG (Pmode, REG_P2)));
1164 emit_jump_insn (gen_return_internal (GEN_INT (SUBROUTINE)));
1167 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
1170 bfin_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
1171 unsigned int new_reg)
1173 /* Interrupt functions can only use registers that have already been
1174 saved by the prologue, even if they would normally be
1175 call-clobbered. */
1177 if (funkind (TREE_TYPE (current_function_decl)) != SUBROUTINE
1178 && !df_regs_ever_live_p (new_reg))
1179 return 0;
1181 return 1;
1184 /* Return the value of the return address for the frame COUNT steps up
1185 from the current frame, after the prologue.
1186 We punt for everything but the current frame by returning const0_rtx. */
1189 bfin_return_addr_rtx (int count)
1191 if (count != 0)
1192 return const0_rtx;
1194 return get_hard_reg_initial_val (Pmode, REG_RETS);
1197 /* Try machine-dependent ways of modifying an illegitimate address X
1198 to be legitimate. If we find one, return the new, valid address,
1199 otherwise return NULL_RTX.
1201 OLDX is the address as it was before break_out_memory_refs was called.
1202 In some cases it is useful to look at this to decide what needs to be done.
1204 MODE is the mode of the memory reference. */
1207 legitimize_address (rtx x ATTRIBUTE_UNUSED, rtx oldx ATTRIBUTE_UNUSED,
1208 enum machine_mode mode ATTRIBUTE_UNUSED)
1210 return NULL_RTX;
1213 static rtx
1214 bfin_delegitimize_address (rtx orig_x)
1216 rtx x = orig_x;
1218 if (GET_CODE (x) != MEM)
1219 return orig_x;
1221 x = XEXP (x, 0);
1222 if (GET_CODE (x) == PLUS
1223 && GET_CODE (XEXP (x, 1)) == UNSPEC
1224 && XINT (XEXP (x, 1), 1) == UNSPEC_MOVE_PIC
1225 && GET_CODE (XEXP (x, 0)) == REG
1226 && REGNO (XEXP (x, 0)) == PIC_OFFSET_TABLE_REGNUM)
1227 return XVECEXP (XEXP (x, 1), 0, 0);
1229 return orig_x;
1232 /* This predicate is used to compute the length of a load/store insn.
1233 OP is a MEM rtx, we return nonzero if its addressing mode requires a
1234 32-bit instruction. */
1237 effective_address_32bit_p (rtx op, enum machine_mode mode)
1239 HOST_WIDE_INT offset;
1241 mode = GET_MODE (op);
1242 op = XEXP (op, 0);
1244 if (GET_CODE (op) != PLUS)
1246 gcc_assert (REG_P (op) || GET_CODE (op) == POST_INC
1247 || GET_CODE (op) == PRE_DEC || GET_CODE (op) == POST_DEC);
1248 return 0;
1251 if (GET_CODE (XEXP (op, 1)) == UNSPEC)
1252 return 1;
1254 offset = INTVAL (XEXP (op, 1));
1256 /* All byte loads use a 16-bit offset. */
1257 if (GET_MODE_SIZE (mode) == 1)
1258 return 1;
1260 if (GET_MODE_SIZE (mode) == 4)
1262 /* Frame pointer relative loads can use a negative offset, all others
1263 are restricted to a small positive one. */
1264 if (XEXP (op, 0) == frame_pointer_rtx)
1265 return offset < -128 || offset > 60;
1266 return offset < 0 || offset > 60;
1269 /* Must be HImode now. */
1270 return offset < 0 || offset > 30;
1273 /* Returns true if X is a memory reference using an I register. */
1274 bool
1275 bfin_dsp_memref_p (rtx x)
1277 if (! MEM_P (x))
1278 return false;
1279 x = XEXP (x, 0);
1280 if (GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_INC
1281 || GET_CODE (x) == POST_DEC || GET_CODE (x) == PRE_DEC)
1282 x = XEXP (x, 0);
1283 return IREG_P (x);
1286 /* Return cost of the memory address ADDR.
1287 All addressing modes are equally cheap on the Blackfin. */
1289 static int
1290 bfin_address_cost (rtx addr ATTRIBUTE_UNUSED)
1292 return 1;
1295 /* Subroutine of print_operand; used to print a memory reference X to FILE. */
1297 void
1298 print_address_operand (FILE *file, rtx x)
1300 switch (GET_CODE (x))
1302 case PLUS:
1303 output_address (XEXP (x, 0));
1304 fprintf (file, "+");
1305 output_address (XEXP (x, 1));
1306 break;
1308 case PRE_DEC:
1309 fprintf (file, "--");
1310 output_address (XEXP (x, 0));
1311 break;
1312 case POST_INC:
1313 output_address (XEXP (x, 0));
1314 fprintf (file, "++");
1315 break;
1316 case POST_DEC:
1317 output_address (XEXP (x, 0));
1318 fprintf (file, "--");
1319 break;
1321 default:
1322 gcc_assert (GET_CODE (x) != MEM);
1323 print_operand (file, x, 0);
1324 break;
1328 /* Adding intp DImode support by Tony
1329 * -- Q: (low word)
1330 * -- R: (high word)
1333 void
1334 print_operand (FILE *file, rtx x, char code)
1336 enum machine_mode mode;
1338 if (code == '!')
1340 if (GET_MODE (current_output_insn) == SImode)
1341 fprintf (file, " ||");
1342 else
1343 fprintf (file, ";");
1344 return;
1347 mode = GET_MODE (x);
1349 switch (code)
1351 case 'j':
1352 switch (GET_CODE (x))
1354 case EQ:
1355 fprintf (file, "e");
1356 break;
1357 case NE:
1358 fprintf (file, "ne");
1359 break;
1360 case GT:
1361 fprintf (file, "g");
1362 break;
1363 case LT:
1364 fprintf (file, "l");
1365 break;
1366 case GE:
1367 fprintf (file, "ge");
1368 break;
1369 case LE:
1370 fprintf (file, "le");
1371 break;
1372 case GTU:
1373 fprintf (file, "g");
1374 break;
1375 case LTU:
1376 fprintf (file, "l");
1377 break;
1378 case GEU:
1379 fprintf (file, "ge");
1380 break;
1381 case LEU:
1382 fprintf (file, "le");
1383 break;
1384 default:
1385 output_operand_lossage ("invalid %%j value");
1387 break;
1389 case 'J': /* reverse logic */
1390 switch (GET_CODE(x))
1392 case EQ:
1393 fprintf (file, "ne");
1394 break;
1395 case NE:
1396 fprintf (file, "e");
1397 break;
1398 case GT:
1399 fprintf (file, "le");
1400 break;
1401 case LT:
1402 fprintf (file, "ge");
1403 break;
1404 case GE:
1405 fprintf (file, "l");
1406 break;
1407 case LE:
1408 fprintf (file, "g");
1409 break;
1410 case GTU:
1411 fprintf (file, "le");
1412 break;
1413 case LTU:
1414 fprintf (file, "ge");
1415 break;
1416 case GEU:
1417 fprintf (file, "l");
1418 break;
1419 case LEU:
1420 fprintf (file, "g");
1421 break;
1422 default:
1423 output_operand_lossage ("invalid %%J value");
1425 break;
1427 default:
1428 switch (GET_CODE (x))
1430 case REG:
1431 if (code == 'h')
1433 if (REGNO (x) < 32)
1434 fprintf (file, "%s", short_reg_names[REGNO (x)]);
1435 else
1436 output_operand_lossage ("invalid operand for code '%c'", code);
1438 else if (code == 'd')
1440 if (REGNO (x) < 32)
1441 fprintf (file, "%s", high_reg_names[REGNO (x)]);
1442 else
1443 output_operand_lossage ("invalid operand for code '%c'", code);
1445 else if (code == 'w')
1447 if (REGNO (x) == REG_A0 || REGNO (x) == REG_A1)
1448 fprintf (file, "%s.w", reg_names[REGNO (x)]);
1449 else
1450 output_operand_lossage ("invalid operand for code '%c'", code);
1452 else if (code == 'x')
1454 if (REGNO (x) == REG_A0 || REGNO (x) == REG_A1)
1455 fprintf (file, "%s.x", reg_names[REGNO (x)]);
1456 else
1457 output_operand_lossage ("invalid operand for code '%c'", code);
1459 else if (code == 'v')
1461 if (REGNO (x) == REG_A0)
1462 fprintf (file, "AV0");
1463 else if (REGNO (x) == REG_A1)
1464 fprintf (file, "AV1");
1465 else
1466 output_operand_lossage ("invalid operand for code '%c'", code);
1468 else if (code == 'D')
1470 if (D_REGNO_P (REGNO (x)))
1471 fprintf (file, "%s", dregs_pair_names[REGNO (x)]);
1472 else
1473 output_operand_lossage ("invalid operand for code '%c'", code);
1475 else if (code == 'H')
1477 if ((mode == DImode || mode == DFmode) && REG_P (x))
1478 fprintf (file, "%s", reg_names[REGNO (x) + 1]);
1479 else
1480 output_operand_lossage ("invalid operand for code '%c'", code);
1482 else if (code == 'T')
1484 if (D_REGNO_P (REGNO (x)))
1485 fprintf (file, "%s", byte_reg_names[REGNO (x)]);
1486 else
1487 output_operand_lossage ("invalid operand for code '%c'", code);
1489 else
1490 fprintf (file, "%s", reg_names[REGNO (x)]);
1491 break;
1493 case MEM:
1494 fputc ('[', file);
1495 x = XEXP (x,0);
1496 print_address_operand (file, x);
1497 fputc (']', file);
1498 break;
1500 case CONST_INT:
1501 if (code == 'M')
1503 switch (INTVAL (x))
1505 case MACFLAG_NONE:
1506 break;
1507 case MACFLAG_FU:
1508 fputs ("(FU)", file);
1509 break;
1510 case MACFLAG_T:
1511 fputs ("(T)", file);
1512 break;
1513 case MACFLAG_TFU:
1514 fputs ("(TFU)", file);
1515 break;
1516 case MACFLAG_W32:
1517 fputs ("(W32)", file);
1518 break;
1519 case MACFLAG_IS:
1520 fputs ("(IS)", file);
1521 break;
1522 case MACFLAG_IU:
1523 fputs ("(IU)", file);
1524 break;
1525 case MACFLAG_IH:
1526 fputs ("(IH)", file);
1527 break;
1528 case MACFLAG_M:
1529 fputs ("(M)", file);
1530 break;
1531 case MACFLAG_IS_M:
1532 fputs ("(IS,M)", file);
1533 break;
1534 case MACFLAG_ISS2:
1535 fputs ("(ISS2)", file);
1536 break;
1537 case MACFLAG_S2RND:
1538 fputs ("(S2RND)", file);
1539 break;
1540 default:
1541 gcc_unreachable ();
1543 break;
1545 else if (code == 'b')
1547 if (INTVAL (x) == 0)
1548 fputs ("+=", file);
1549 else if (INTVAL (x) == 1)
1550 fputs ("-=", file);
1551 else
1552 gcc_unreachable ();
1553 break;
1555 /* Moves to half registers with d or h modifiers always use unsigned
1556 constants. */
1557 else if (code == 'd')
1558 x = GEN_INT ((INTVAL (x) >> 16) & 0xffff);
1559 else if (code == 'h')
1560 x = GEN_INT (INTVAL (x) & 0xffff);
1561 else if (code == 'N')
1562 x = GEN_INT (-INTVAL (x));
1563 else if (code == 'X')
1564 x = GEN_INT (exact_log2 (0xffffffff & INTVAL (x)));
1565 else if (code == 'Y')
1566 x = GEN_INT (exact_log2 (0xffffffff & ~INTVAL (x)));
1567 else if (code == 'Z')
1568 /* Used for LINK insns. */
1569 x = GEN_INT (-8 - INTVAL (x));
1571 /* fall through */
1573 case SYMBOL_REF:
1574 output_addr_const (file, x);
1575 break;
1577 case CONST_DOUBLE:
1578 output_operand_lossage ("invalid const_double operand");
1579 break;
1581 case UNSPEC:
1582 switch (XINT (x, 1))
1584 case UNSPEC_MOVE_PIC:
1585 output_addr_const (file, XVECEXP (x, 0, 0));
1586 fprintf (file, "@GOT");
1587 break;
1589 case UNSPEC_MOVE_FDPIC:
1590 output_addr_const (file, XVECEXP (x, 0, 0));
1591 fprintf (file, "@GOT17M4");
1592 break;
1594 case UNSPEC_FUNCDESC_GOT17M4:
1595 output_addr_const (file, XVECEXP (x, 0, 0));
1596 fprintf (file, "@FUNCDESC_GOT17M4");
1597 break;
1599 case UNSPEC_LIBRARY_OFFSET:
1600 fprintf (file, "_current_shared_library_p5_offset_");
1601 break;
1603 default:
1604 gcc_unreachable ();
1606 break;
1608 default:
1609 output_addr_const (file, x);
1614 /* Argument support functions. */
1616 /* Initialize a variable CUM of type CUMULATIVE_ARGS
1617 for a call to a function whose data type is FNTYPE.
1618 For a library call, FNTYPE is 0.
1619 VDSP C Compiler manual, our ABI says that
1620 first 3 words of arguments will use R0, R1 and R2.
1623 void
1624 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
1625 rtx libname ATTRIBUTE_UNUSED)
1627 static CUMULATIVE_ARGS zero_cum;
1629 *cum = zero_cum;
1631 /* Set up the number of registers to use for passing arguments. */
1633 cum->nregs = max_arg_registers;
1634 cum->arg_regs = arg_regs;
1636 cum->call_cookie = CALL_NORMAL;
1637 /* Check for a longcall attribute. */
1638 if (fntype && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype)))
1639 cum->call_cookie |= CALL_SHORT;
1640 else if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)))
1641 cum->call_cookie |= CALL_LONG;
1643 return;
1646 /* Update the data in CUM to advance over an argument
1647 of mode MODE and data type TYPE.
1648 (TYPE is null for libcalls where that information may not be available.) */
1650 void
1651 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1652 int named ATTRIBUTE_UNUSED)
1654 int count, bytes, words;
1656 bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1657 words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1659 cum->words += words;
1660 cum->nregs -= words;
1662 if (cum->nregs <= 0)
1664 cum->nregs = 0;
1665 cum->arg_regs = NULL;
1667 else
1669 for (count = 1; count <= words; count++)
1670 cum->arg_regs++;
1673 return;
1676 /* Define where to put the arguments to a function.
1677 Value is zero to push the argument on the stack,
1678 or a hard register in which to store the argument.
1680 MODE is the argument's machine mode.
1681 TYPE is the data type of the argument (as a tree).
1682 This is null for libcalls where that information may
1683 not be available.
1684 CUM is a variable of type CUMULATIVE_ARGS which gives info about
1685 the preceding args and about the function being called.
1686 NAMED is nonzero if this argument is a named parameter
1687 (otherwise it is an extra parameter matching an ellipsis). */
1689 struct rtx_def *
1690 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1691 int named ATTRIBUTE_UNUSED)
1693 int bytes
1694 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1696 if (mode == VOIDmode)
1697 /* Compute operand 2 of the call insn. */
1698 return GEN_INT (cum->call_cookie);
1700 if (bytes == -1)
1701 return NULL_RTX;
1703 if (cum->nregs)
1704 return gen_rtx_REG (mode, *(cum->arg_regs));
1706 return NULL_RTX;
1709 /* For an arg passed partly in registers and partly in memory,
1710 this is the number of bytes passed in registers.
1711 For args passed entirely in registers or entirely in memory, zero.
1713 Refer VDSP C Compiler manual, our ABI.
1714 First 3 words are in registers. So, if an argument is larger
1715 than the registers available, it will span the register and
1716 stack. */
1718 static int
1719 bfin_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1720 tree type ATTRIBUTE_UNUSED,
1721 bool named ATTRIBUTE_UNUSED)
1723 int bytes
1724 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1725 int bytes_left = cum->nregs * UNITS_PER_WORD;
1727 if (bytes == -1)
1728 return 0;
1730 if (bytes_left == 0)
1731 return 0;
1732 if (bytes > bytes_left)
1733 return bytes_left;
1734 return 0;
1737 /* Variable sized types are passed by reference. */
1739 static bool
1740 bfin_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
1741 enum machine_mode mode ATTRIBUTE_UNUSED,
1742 const_tree type, bool named ATTRIBUTE_UNUSED)
1744 return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
1747 /* Decide whether a type should be returned in memory (true)
1748 or in a register (false). This is called by the macro
1749 RETURN_IN_MEMORY. */
1752 bfin_return_in_memory (const_tree type)
1754 int size = int_size_in_bytes (type);
1755 return size > 2 * UNITS_PER_WORD || size == -1;
1758 /* Register in which address to store a structure value
1759 is passed to a function. */
1760 static rtx
1761 bfin_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
1762 int incoming ATTRIBUTE_UNUSED)
1764 return gen_rtx_REG (Pmode, REG_P0);
1767 /* Return true when register may be used to pass function parameters. */
1769 bool
1770 function_arg_regno_p (int n)
1772 int i;
1773 for (i = 0; arg_regs[i] != -1; i++)
1774 if (n == arg_regs[i])
1775 return true;
1776 return false;
1779 /* Returns 1 if OP contains a symbol reference */
1782 symbolic_reference_mentioned_p (rtx op)
1784 register const char *fmt;
1785 register int i;
1787 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
1788 return 1;
1790 fmt = GET_RTX_FORMAT (GET_CODE (op));
1791 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
1793 if (fmt[i] == 'E')
1795 register int j;
1797 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
1798 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
1799 return 1;
1802 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
1803 return 1;
1806 return 0;
1809 /* Decide whether we can make a sibling call to a function. DECL is the
1810 declaration of the function being targeted by the call and EXP is the
1811 CALL_EXPR representing the call. */
1813 static bool
1814 bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
1815 tree exp ATTRIBUTE_UNUSED)
1817 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1818 if (fkind != SUBROUTINE)
1819 return false;
1820 if (!TARGET_ID_SHARED_LIBRARY || TARGET_SEP_DATA)
1821 return true;
1823 /* When compiling for ID shared libraries, can't sibcall a local function
1824 from a non-local function, because the local function thinks it does
1825 not need to reload P5 in the prologue, but the sibcall wil pop P5 in the
1826 sibcall epilogue, and we end up with the wrong value in P5. */
1828 if (!flag_unit_at_a_time || decl == NULL)
1829 /* Not enough information. */
1830 return false;
1833 struct cgraph_local_info *this_func, *called_func;
1835 this_func = cgraph_local_info (current_function_decl);
1836 called_func = cgraph_local_info (decl);
1837 return !called_func->local || this_func->local;
1841 /* Emit RTL insns to initialize the variable parts of a trampoline at
1842 TRAMP. FNADDR is an RTX for the address of the function's pure
1843 code. CXT is an RTX for the static chain value for the function. */
1845 void
1846 initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt)
1848 rtx t1 = copy_to_reg (fnaddr);
1849 rtx t2 = copy_to_reg (cxt);
1850 rtx addr;
1851 int i = 0;
1853 if (TARGET_FDPIC)
1855 rtx a = memory_address (Pmode, plus_constant (tramp, 8));
1856 addr = memory_address (Pmode, tramp);
1857 emit_move_insn (gen_rtx_MEM (SImode, addr), a);
1858 i = 8;
1861 addr = memory_address (Pmode, plus_constant (tramp, i + 2));
1862 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
1863 emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16)));
1864 addr = memory_address (Pmode, plus_constant (tramp, i + 6));
1865 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
1867 addr = memory_address (Pmode, plus_constant (tramp, i + 10));
1868 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
1869 emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16)));
1870 addr = memory_address (Pmode, plus_constant (tramp, i + 14));
1871 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
1874 /* Emit insns to move operands[1] into operands[0]. */
1876 void
1877 emit_pic_move (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
1879 rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
1881 gcc_assert (!TARGET_FDPIC || !(reload_in_progress || reload_completed));
1882 if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
1883 operands[1] = force_reg (SImode, operands[1]);
1884 else
1885 operands[1] = legitimize_pic_address (operands[1], temp,
1886 TARGET_FDPIC ? OUR_FDPIC_REG
1887 : pic_offset_table_rtx);
1890 /* Expand a move operation in mode MODE. The operands are in OPERANDS.
1891 Returns true if no further code must be generated, false if the caller
1892 should generate an insn to move OPERANDS[1] to OPERANDS[0]. */
1894 bool
1895 expand_move (rtx *operands, enum machine_mode mode)
1897 rtx op = operands[1];
1898 if ((TARGET_ID_SHARED_LIBRARY || TARGET_FDPIC)
1899 && SYMBOLIC_CONST (op))
1900 emit_pic_move (operands, mode);
1901 else if (mode == SImode && GET_CODE (op) == CONST
1902 && GET_CODE (XEXP (op, 0)) == PLUS
1903 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
1904 && !bfin_legitimate_constant_p (op))
1906 rtx dest = operands[0];
1907 rtx op0, op1;
1908 gcc_assert (!reload_in_progress && !reload_completed);
1909 op = XEXP (op, 0);
1910 op0 = force_reg (mode, XEXP (op, 0));
1911 op1 = XEXP (op, 1);
1912 if (!insn_data[CODE_FOR_addsi3].operand[2].predicate (op1, mode))
1913 op1 = force_reg (mode, op1);
1914 if (GET_CODE (dest) == MEM)
1915 dest = gen_reg_rtx (mode);
1916 emit_insn (gen_addsi3 (dest, op0, op1));
1917 if (dest == operands[0])
1918 return true;
1919 operands[1] = dest;
1921 /* Don't generate memory->memory or constant->memory moves, go through a
1922 register */
1923 else if ((reload_in_progress | reload_completed) == 0
1924 && GET_CODE (operands[0]) == MEM
1925 && GET_CODE (operands[1]) != REG)
1926 operands[1] = force_reg (mode, operands[1]);
1927 return false;
1930 /* Split one or more DImode RTL references into pairs of SImode
1931 references. The RTL can be REG, offsettable MEM, integer constant, or
1932 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
1933 split and "num" is its length. lo_half and hi_half are output arrays
1934 that parallel "operands". */
1936 void
1937 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
1939 while (num--)
1941 rtx op = operands[num];
1943 /* simplify_subreg refuse to split volatile memory addresses,
1944 but we still have to handle it. */
1945 if (GET_CODE (op) == MEM)
1947 lo_half[num] = adjust_address (op, SImode, 0);
1948 hi_half[num] = adjust_address (op, SImode, 4);
1950 else
1952 lo_half[num] = simplify_gen_subreg (SImode, op,
1953 GET_MODE (op) == VOIDmode
1954 ? DImode : GET_MODE (op), 0);
1955 hi_half[num] = simplify_gen_subreg (SImode, op,
1956 GET_MODE (op) == VOIDmode
1957 ? DImode : GET_MODE (op), 4);
1962 bool
1963 bfin_longcall_p (rtx op, int call_cookie)
1965 gcc_assert (GET_CODE (op) == SYMBOL_REF);
1966 if (call_cookie & CALL_SHORT)
1967 return 0;
1968 if (call_cookie & CALL_LONG)
1969 return 1;
1970 if (TARGET_LONG_CALLS)
1971 return 1;
1972 return 0;
1975 /* Expand a call instruction. FNADDR is the call target, RETVAL the return value.
1976 COOKIE is a CONST_INT holding the call_cookie prepared init_cumulative_args.
1977 SIBCALL is nonzero if this is a sibling call. */
1979 void
1980 bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
1982 rtx use = NULL, call;
1983 rtx callee = XEXP (fnaddr, 0);
1984 int nelts = 2 + !!sibcall;
1985 rtx pat;
1986 rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REGNO);
1987 int n;
1989 /* In an untyped call, we can get NULL for operand 2. */
1990 if (cookie == NULL_RTX)
1991 cookie = const0_rtx;
1993 /* Static functions and indirect calls don't need the pic register. */
1994 if (!TARGET_FDPIC && flag_pic
1995 && GET_CODE (callee) == SYMBOL_REF
1996 && !SYMBOL_REF_LOCAL_P (callee))
1997 use_reg (&use, pic_offset_table_rtx);
1999 if (TARGET_FDPIC)
2001 int caller_has_l1_text, callee_has_l1_text;
2003 caller_has_l1_text = callee_has_l1_text = 0;
2005 if (lookup_attribute ("l1_text",
2006 DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE)
2007 caller_has_l1_text = 1;
2009 if (GET_CODE (callee) == SYMBOL_REF
2010 && SYMBOL_REF_DECL (callee) && DECL_P (SYMBOL_REF_DECL (callee))
2011 && lookup_attribute
2012 ("l1_text",
2013 DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE)
2014 callee_has_l1_text = 1;
2016 if (GET_CODE (callee) != SYMBOL_REF
2017 || bfin_longcall_p (callee, INTVAL (cookie))
2018 || (GET_CODE (callee) == SYMBOL_REF
2019 && !SYMBOL_REF_LOCAL_P (callee)
2020 && TARGET_INLINE_PLT)
2021 || caller_has_l1_text != callee_has_l1_text
2022 || (caller_has_l1_text && callee_has_l1_text
2023 && (GET_CODE (callee) != SYMBOL_REF
2024 || !SYMBOL_REF_LOCAL_P (callee))))
2026 rtx addr = callee;
2027 if (! address_operand (addr, Pmode))
2028 addr = force_reg (Pmode, addr);
2030 fnaddr = gen_reg_rtx (SImode);
2031 emit_insn (gen_load_funcdescsi (fnaddr, addr));
2032 fnaddr = gen_rtx_MEM (Pmode, fnaddr);
2034 picreg = gen_reg_rtx (SImode);
2035 emit_insn (gen_load_funcdescsi (picreg,
2036 plus_constant (addr, 4)));
2039 nelts++;
2041 else if ((!register_no_elim_operand (callee, Pmode)
2042 && GET_CODE (callee) != SYMBOL_REF)
2043 || (GET_CODE (callee) == SYMBOL_REF
2044 && ((TARGET_ID_SHARED_LIBRARY && !TARGET_LEAF_ID_SHARED_LIBRARY)
2045 || bfin_longcall_p (callee, INTVAL (cookie)))))
2047 callee = copy_to_mode_reg (Pmode, callee);
2048 fnaddr = gen_rtx_MEM (Pmode, callee);
2050 call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
2052 if (retval)
2053 call = gen_rtx_SET (VOIDmode, retval, call);
2055 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nelts));
2056 n = 0;
2057 XVECEXP (pat, 0, n++) = call;
2058 if (TARGET_FDPIC)
2059 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, picreg);
2060 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie);
2061 if (sibcall)
2062 XVECEXP (pat, 0, n++) = gen_rtx_RETURN (VOIDmode);
2063 call = emit_call_insn (pat);
2064 if (use)
2065 CALL_INSN_FUNCTION_USAGE (call) = use;
2068 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
2071 hard_regno_mode_ok (int regno, enum machine_mode mode)
2073 /* Allow only dregs to store value of mode HI or QI */
2074 enum reg_class class = REGNO_REG_CLASS (regno);
2076 if (mode == CCmode)
2077 return 0;
2079 if (mode == V2HImode)
2080 return D_REGNO_P (regno);
2081 if (class == CCREGS)
2082 return mode == BImode;
2083 if (mode == PDImode || mode == V2PDImode)
2084 return regno == REG_A0 || regno == REG_A1;
2086 /* Allow all normal 32-bit regs, except REG_M3, in case regclass ever comes
2087 up with a bad register class (such as ALL_REGS) for DImode. */
2088 if (mode == DImode)
2089 return regno < REG_M3;
2091 if (mode == SImode
2092 && TEST_HARD_REG_BIT (reg_class_contents[PROLOGUE_REGS], regno))
2093 return 1;
2095 return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno);
2098 /* Implements target hook vector_mode_supported_p. */
2100 static bool
2101 bfin_vector_mode_supported_p (enum machine_mode mode)
2103 return mode == V2HImode;
2106 /* Return the cost of moving data from a register in class CLASS1 to
2107 one in class CLASS2. A cost of 2 is the default. */
2110 bfin_register_move_cost (enum machine_mode mode,
2111 enum reg_class class1, enum reg_class class2)
2113 /* These need secondary reloads, so they're more expensive. */
2114 if ((class1 == CCREGS && class2 != DREGS)
2115 || (class1 != DREGS && class2 == CCREGS))
2116 return 4;
2118 /* If optimizing for size, always prefer reg-reg over reg-memory moves. */
2119 if (optimize_size)
2120 return 2;
2122 /* There are some stalls involved when moving from a DREG to a different
2123 class reg, and using the value in one of the following instructions.
2124 Attempt to model this by slightly discouraging such moves. */
2125 if (class1 == DREGS && class2 != DREGS)
2126 return 2 * 2;
2128 if (GET_MODE_CLASS (mode) == MODE_INT)
2130 /* Discourage trying to use the accumulators. */
2131 if (TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A0)
2132 || TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A1)
2133 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A0)
2134 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A1))
2135 return 20;
2137 return 2;
2140 /* Return the cost of moving data of mode M between a
2141 register and memory. A value of 2 is the default; this cost is
2142 relative to those in `REGISTER_MOVE_COST'.
2144 ??? In theory L1 memory has single-cycle latency. We should add a switch
2145 that tells the compiler whether we expect to use only L1 memory for the
2146 program; it'll make the costs more accurate. */
2149 bfin_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
2150 enum reg_class class,
2151 int in ATTRIBUTE_UNUSED)
2153 /* Make memory accesses slightly more expensive than any register-register
2154 move. Also, penalize non-DP registers, since they need secondary
2155 reloads to load and store. */
2156 if (! reg_class_subset_p (class, DPREGS))
2157 return 10;
2159 return 8;
2162 /* Inform reload about cases where moving X with a mode MODE to a register in
2163 CLASS requires an extra scratch register. Return the class needed for the
2164 scratch register. */
2166 static enum reg_class
2167 bfin_secondary_reload (bool in_p, rtx x, enum reg_class class,
2168 enum machine_mode mode, secondary_reload_info *sri)
2170 /* If we have HImode or QImode, we can only use DREGS as secondary registers;
2171 in most other cases we can also use PREGS. */
2172 enum reg_class default_class = GET_MODE_SIZE (mode) >= 4 ? DPREGS : DREGS;
2173 enum reg_class x_class = NO_REGS;
2174 enum rtx_code code = GET_CODE (x);
2176 if (code == SUBREG)
2177 x = SUBREG_REG (x), code = GET_CODE (x);
2178 if (REG_P (x))
2180 int regno = REGNO (x);
2181 if (regno >= FIRST_PSEUDO_REGISTER)
2182 regno = reg_renumber[regno];
2184 if (regno == -1)
2185 code = MEM;
2186 else
2187 x_class = REGNO_REG_CLASS (regno);
2190 /* We can be asked to reload (plus (FP) (large_constant)) into a DREG.
2191 This happens as a side effect of register elimination, and we need
2192 a scratch register to do it. */
2193 if (fp_plus_const_operand (x, mode))
2195 rtx op2 = XEXP (x, 1);
2196 int large_constant_p = ! CONST_7BIT_IMM_P (INTVAL (op2));
2198 if (class == PREGS || class == PREGS_CLOBBERED)
2199 return NO_REGS;
2200 /* If destination is a DREG, we can do this without a scratch register
2201 if the constant is valid for an add instruction. */
2202 if ((class == DREGS || class == DPREGS)
2203 && ! large_constant_p)
2204 return NO_REGS;
2205 /* Reloading to anything other than a DREG? Use a PREG scratch
2206 register. */
2207 sri->icode = CODE_FOR_reload_insi;
2208 return NO_REGS;
2211 /* Data can usually be moved freely between registers of most classes.
2212 AREGS are an exception; they can only move to or from another register
2213 in AREGS or one in DREGS. They can also be assigned the constant 0. */
2214 if (x_class == AREGS || x_class == EVEN_AREGS || x_class == ODD_AREGS)
2215 return (class == DREGS || class == AREGS || class == EVEN_AREGS
2216 || class == ODD_AREGS
2217 ? NO_REGS : DREGS);
2219 if (class == AREGS || class == EVEN_AREGS || class == ODD_AREGS)
2221 if (code == MEM)
2223 sri->icode = in_p ? CODE_FOR_reload_inpdi : CODE_FOR_reload_outpdi;
2224 return NO_REGS;
2227 if (x != const0_rtx && x_class != DREGS)
2229 return DREGS;
2231 else
2232 return NO_REGS;
2235 /* CCREGS can only be moved from/to DREGS. */
2236 if (class == CCREGS && x_class != DREGS)
2237 return DREGS;
2238 if (x_class == CCREGS && class != DREGS)
2239 return DREGS;
2241 /* All registers other than AREGS can load arbitrary constants. The only
2242 case that remains is MEM. */
2243 if (code == MEM)
2244 if (! reg_class_subset_p (class, default_class))
2245 return default_class;
2247 return NO_REGS;
2250 /* Implement TARGET_HANDLE_OPTION. */
2252 static bool
2253 bfin_handle_option (size_t code, const char *arg, int value)
2255 switch (code)
2257 case OPT_mshared_library_id_:
2258 if (value > MAX_LIBRARY_ID)
2259 error ("-mshared-library-id=%s is not between 0 and %d",
2260 arg, MAX_LIBRARY_ID);
2261 bfin_lib_id_given = 1;
2262 return true;
2264 case OPT_mcpu_:
2266 const char *p, *q;
2267 int i;
2269 i = 0;
2270 while ((p = bfin_cpus[i].name) != NULL)
2272 if (strncmp (arg, p, strlen (p)) == 0)
2273 break;
2274 i++;
2277 if (p == NULL)
2279 error ("-mcpu=%s is not valid", arg);
2280 return false;
2283 bfin_cpu_type = bfin_cpus[i].type;
2285 q = arg + strlen (p);
2287 if (*q == '\0')
2289 bfin_si_revision = bfin_cpus[i].si_revision;
2290 bfin_workarounds |= bfin_cpus[i].workarounds;
2292 else if (strcmp (q, "-none") == 0)
2293 bfin_si_revision = -1;
2294 else if (strcmp (q, "-any") == 0)
2296 bfin_si_revision = 0xffff;
2297 while (bfin_cpus[i].type == bfin_cpu_type)
2299 bfin_workarounds |= bfin_cpus[i].workarounds;
2300 i++;
2303 else
2305 unsigned int si_major, si_minor;
2306 int rev_len, n;
2308 rev_len = strlen (q);
2310 if (sscanf (q, "-%u.%u%n", &si_major, &si_minor, &n) != 2
2311 || n != rev_len
2312 || si_major > 0xff || si_minor > 0xff)
2314 invalid_silicon_revision:
2315 error ("-mcpu=%s has invalid silicon revision", arg);
2316 return false;
2319 bfin_si_revision = (si_major << 8) | si_minor;
2321 while (bfin_cpus[i].type == bfin_cpu_type
2322 && bfin_cpus[i].si_revision != bfin_si_revision)
2323 i++;
2325 if (bfin_cpus[i].type != bfin_cpu_type)
2326 goto invalid_silicon_revision;
2328 bfin_workarounds |= bfin_cpus[i].workarounds;
2331 if (bfin_cpu_type == BFIN_CPU_BF561)
2332 warning (0, "bf561 support is incomplete yet.");
2334 return true;
2337 default:
2338 return true;
2342 static struct machine_function *
2343 bfin_init_machine_status (void)
2345 struct machine_function *f;
2347 f = ggc_alloc_cleared (sizeof (struct machine_function));
2349 return f;
2352 /* Implement the macro OVERRIDE_OPTIONS. */
2354 void
2355 override_options (void)
2357 if (bfin_csync_anomaly == 1)
2358 bfin_workarounds |= WA_SPECULATIVE_SYNCS;
2359 else if (bfin_csync_anomaly == 0)
2360 bfin_workarounds &= ~WA_SPECULATIVE_SYNCS;
2362 if (bfin_specld_anomaly == 1)
2363 bfin_workarounds |= WA_SPECULATIVE_LOADS;
2364 else if (bfin_specld_anomaly == 0)
2365 bfin_workarounds &= ~WA_SPECULATIVE_LOADS;
2367 if (TARGET_OMIT_LEAF_FRAME_POINTER)
2368 flag_omit_frame_pointer = 1;
2370 /* Library identification */
2371 if (bfin_lib_id_given && ! TARGET_ID_SHARED_LIBRARY)
2372 error ("-mshared-library-id= specified without -mid-shared-library");
2374 if (TARGET_ID_SHARED_LIBRARY && flag_pic == 0)
2375 flag_pic = 1;
2377 if (stack_limit_rtx && TARGET_STACK_CHECK_L1)
2378 error ("Can't use multiple stack checking methods together.");
2380 if (TARGET_ID_SHARED_LIBRARY && TARGET_FDPIC)
2381 error ("ID shared libraries and FD-PIC mode can't be used together.");
2383 /* Don't allow the user to specify -mid-shared-library and -msep-data
2384 together, as it makes little sense from a user's point of view... */
2385 if (TARGET_SEP_DATA && TARGET_ID_SHARED_LIBRARY)
2386 error ("cannot specify both -msep-data and -mid-shared-library");
2387 /* ... internally, however, it's nearly the same. */
2388 if (TARGET_SEP_DATA)
2389 target_flags |= MASK_ID_SHARED_LIBRARY | MASK_LEAF_ID_SHARED_LIBRARY;
2391 /* There is no single unaligned SI op for PIC code. Sometimes we
2392 need to use ".4byte" and sometimes we need to use ".picptr".
2393 See bfin_assemble_integer for details. */
2394 if (TARGET_FDPIC)
2395 targetm.asm_out.unaligned_op.si = 0;
2397 /* Silently turn off flag_pic if not doing FDPIC or ID shared libraries,
2398 since we don't support it and it'll just break. */
2399 if (flag_pic && !TARGET_FDPIC && !TARGET_ID_SHARED_LIBRARY)
2400 flag_pic = 0;
2402 flag_schedule_insns = 0;
2404 /* Passes after sched2 can break the helpful TImode annotations that
2405 haifa-sched puts on every insn. Just do scheduling in reorg. */
2406 bfin_flag_schedule_insns2 = flag_schedule_insns_after_reload;
2407 flag_schedule_insns_after_reload = 0;
2409 init_machine_status = bfin_init_machine_status;
2412 /* Return the destination address of BRANCH.
2413 We need to use this instead of get_attr_length, because the
2414 cbranch_with_nops pattern conservatively sets its length to 6, and
2415 we still prefer to use shorter sequences. */
2417 static int
2418 branch_dest (rtx branch)
2420 rtx dest;
2421 int dest_uid;
2422 rtx pat = PATTERN (branch);
2423 if (GET_CODE (pat) == PARALLEL)
2424 pat = XVECEXP (pat, 0, 0);
2425 dest = SET_SRC (pat);
2426 if (GET_CODE (dest) == IF_THEN_ELSE)
2427 dest = XEXP (dest, 1);
2428 dest = XEXP (dest, 0);
2429 dest_uid = INSN_UID (dest);
2430 return INSN_ADDRESSES (dest_uid);
2433 /* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates
2434 it's a branch that's predicted taken. */
2436 static int
2437 cbranch_predicted_taken_p (rtx insn)
2439 rtx x = find_reg_note (insn, REG_BR_PROB, 0);
2441 if (x)
2443 int pred_val = INTVAL (XEXP (x, 0));
2445 return pred_val >= REG_BR_PROB_BASE / 2;
2448 return 0;
2451 /* Templates for use by asm_conditional_branch. */
2453 static const char *ccbranch_templates[][3] = {
2454 { "if !cc jump %3;", "if cc jump 4 (bp); jump.s %3;", "if cc jump 6 (bp); jump.l %3;" },
2455 { "if cc jump %3;", "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" },
2456 { "if !cc jump %3 (bp);", "if cc jump 4; jump.s %3;", "if cc jump 6; jump.l %3;" },
2457 { "if cc jump %3 (bp);", "if !cc jump 4; jump.s %3;", "if !cc jump 6; jump.l %3;" },
2460 /* Output INSN, which is a conditional branch instruction with operands
2461 OPERANDS.
2463 We deal with the various forms of conditional branches that can be generated
2464 by bfin_reorg to prevent the hardware from doing speculative loads, by
2465 - emitting a sufficient number of nops, if N_NOPS is nonzero, or
2466 - always emitting the branch as predicted taken, if PREDICT_TAKEN is true.
2467 Either of these is only necessary if the branch is short, otherwise the
2468 template we use ends in an unconditional jump which flushes the pipeline
2469 anyway. */
2471 void
2472 asm_conditional_branch (rtx insn, rtx *operands, int n_nops, int predict_taken)
2474 int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
2475 /* Note : offset for instructions like if cc jmp; jump.[sl] offset
2476 is to be taken from start of if cc rather than jump.
2477 Range for jump.s is (-4094, 4096) instead of (-4096, 4094)
2479 int len = (offset >= -1024 && offset <= 1022 ? 0
2480 : offset >= -4094 && offset <= 4096 ? 1
2481 : 2);
2482 int bp = predict_taken && len == 0 ? 1 : cbranch_predicted_taken_p (insn);
2483 int idx = (bp << 1) | (GET_CODE (operands[0]) == EQ ? BRF : BRT);
2484 output_asm_insn (ccbranch_templates[idx][len], operands);
2485 gcc_assert (n_nops == 0 || !bp);
2486 if (len == 0)
2487 while (n_nops-- > 0)
2488 output_asm_insn ("nop;", NULL);
2491 /* Emit rtl for a comparison operation CMP in mode MODE. Operands have been
2492 stored in bfin_compare_op0 and bfin_compare_op1 already. */
2495 bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED)
2497 enum rtx_code code1, code2;
2498 rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1;
2499 rtx tem = bfin_cc_rtx;
2500 enum rtx_code code = GET_CODE (cmp);
2502 /* If we have a BImode input, then we already have a compare result, and
2503 do not need to emit another comparison. */
2504 if (GET_MODE (op0) == BImode)
2506 gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
2507 tem = op0, code2 = code;
2509 else
2511 switch (code) {
2512 /* bfin has these conditions */
2513 case EQ:
2514 case LT:
2515 case LE:
2516 case LEU:
2517 case LTU:
2518 code1 = code;
2519 code2 = NE;
2520 break;
2521 default:
2522 code1 = reverse_condition (code);
2523 code2 = EQ;
2524 break;
2526 emit_insn (gen_rtx_SET (BImode, tem,
2527 gen_rtx_fmt_ee (code1, BImode, op0, op1)));
2530 return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode));
2533 /* Return nonzero iff C has exactly one bit set if it is interpreted
2534 as a 32-bit constant. */
2537 log2constp (unsigned HOST_WIDE_INT c)
2539 c &= 0xFFFFFFFF;
2540 return c != 0 && (c & (c-1)) == 0;
2543 /* Returns the number of consecutive least significant zeros in the binary
2544 representation of *V.
2545 We modify *V to contain the original value arithmetically shifted right by
2546 the number of zeroes. */
2548 static int
2549 shiftr_zero (HOST_WIDE_INT *v)
2551 unsigned HOST_WIDE_INT tmp = *v;
2552 unsigned HOST_WIDE_INT sgn;
2553 int n = 0;
2555 if (tmp == 0)
2556 return 0;
2558 sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1));
2559 while ((tmp & 0x1) == 0 && n <= 32)
2561 tmp = (tmp >> 1) | sgn;
2562 n++;
2564 *v = tmp;
2565 return n;
2568 /* After reload, split the load of an immediate constant. OPERANDS are the
2569 operands of the movsi_insn pattern which we are splitting. We return
2570 nonzero if we emitted a sequence to load the constant, zero if we emitted
2571 nothing because we want to use the splitter's default sequence. */
2574 split_load_immediate (rtx operands[])
2576 HOST_WIDE_INT val = INTVAL (operands[1]);
2577 HOST_WIDE_INT tmp;
2578 HOST_WIDE_INT shifted = val;
2579 HOST_WIDE_INT shifted_compl = ~val;
2580 int num_zero = shiftr_zero (&shifted);
2581 int num_compl_zero = shiftr_zero (&shifted_compl);
2582 unsigned int regno = REGNO (operands[0]);
2584 /* This case takes care of single-bit set/clear constants, which we could
2585 also implement with BITSET/BITCLR. */
2586 if (num_zero
2587 && shifted >= -32768 && shifted < 65536
2588 && (D_REGNO_P (regno)
2589 || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))
2591 emit_insn (gen_movsi (operands[0], GEN_INT (shifted)));
2592 emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));
2593 return 1;
2596 tmp = val & 0xFFFF;
2597 tmp |= -(tmp & 0x8000);
2599 /* If high word has one bit set or clear, try to use a bit operation. */
2600 if (D_REGNO_P (regno))
2602 if (log2constp (val & 0xFFFF0000))
2604 emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));
2605 emit_insn (gen_iorsi3 (operands[0], operands[0], GEN_INT (val & 0xFFFF0000)));
2606 return 1;
2608 else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)
2610 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2611 emit_insn (gen_andsi3 (operands[0], operands[0], GEN_INT (val | 0xFFFF)));
2615 if (D_REGNO_P (regno))
2617 if (CONST_7BIT_IMM_P (tmp))
2619 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2620 emit_insn (gen_movstricthi_high (operands[0], GEN_INT (val & -65536)));
2621 return 1;
2624 if ((val & 0xFFFF0000) == 0)
2626 emit_insn (gen_movsi (operands[0], const0_rtx));
2627 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2628 return 1;
2631 if ((val & 0xFFFF0000) == 0xFFFF0000)
2633 emit_insn (gen_movsi (operands[0], constm1_rtx));
2634 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2635 return 1;
2639 /* Need DREGs for the remaining case. */
2640 if (regno > REG_R7)
2641 return 0;
2643 if (optimize_size
2644 && num_compl_zero && CONST_7BIT_IMM_P (shifted_compl))
2646 /* If optimizing for size, generate a sequence that has more instructions
2647 but is shorter. */
2648 emit_insn (gen_movsi (operands[0], GEN_INT (shifted_compl)));
2649 emit_insn (gen_ashlsi3 (operands[0], operands[0],
2650 GEN_INT (num_compl_zero)));
2651 emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
2652 return 1;
2654 return 0;
2657 /* Return true if the legitimate memory address for a memory operand of mode
2658 MODE. Return false if not. */
2660 static bool
2661 bfin_valid_add (enum machine_mode mode, HOST_WIDE_INT value)
2663 unsigned HOST_WIDE_INT v = value > 0 ? value : -value;
2664 int sz = GET_MODE_SIZE (mode);
2665 int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2;
2666 /* The usual offsettable_memref machinery doesn't work so well for this
2667 port, so we deal with the problem here. */
2668 if (value > 0 && sz == 8)
2669 v += 4;
2670 return (v & ~(0x7fff << shift)) == 0;
2673 static bool
2674 bfin_valid_reg_p (unsigned int regno, int strict, enum machine_mode mode,
2675 enum rtx_code outer_code)
2677 if (strict)
2678 return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH);
2679 else
2680 return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH);
2683 bool
2684 bfin_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
2686 switch (GET_CODE (x)) {
2687 case REG:
2688 if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM))
2689 return true;
2690 break;
2691 case PLUS:
2692 if (REG_P (XEXP (x, 0))
2693 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS)
2694 && ((GET_CODE (XEXP (x, 1)) == UNSPEC && mode == SImode)
2695 || (GET_CODE (XEXP (x, 1)) == CONST_INT
2696 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
2697 return true;
2698 break;
2699 case POST_INC:
2700 case POST_DEC:
2701 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2702 && REG_P (XEXP (x, 0))
2703 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC))
2704 return true;
2705 case PRE_DEC:
2706 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2707 && XEXP (x, 0) == stack_pointer_rtx
2708 && REG_P (XEXP (x, 0))
2709 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC))
2710 return true;
2711 break;
2712 default:
2713 break;
2715 return false;
2718 /* Decide whether we can force certain constants to memory. If we
2719 decide we can't, the caller should be able to cope with it in
2720 another way. */
2722 static bool
2723 bfin_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
2725 /* We have only one class of non-legitimate constants, and our movsi
2726 expander knows how to handle them. Dropping these constants into the
2727 data section would only shift the problem - we'd still get relocs
2728 outside the object, in the data section rather than the text section. */
2729 return true;
2732 /* Ensure that for any constant of the form symbol + offset, the offset
2733 remains within the object. Any other constants are ok.
2734 This ensures that flat binaries never have to deal with relocations
2735 crossing section boundaries. */
2737 bool
2738 bfin_legitimate_constant_p (rtx x)
2740 rtx sym;
2741 HOST_WIDE_INT offset;
2743 if (GET_CODE (x) != CONST)
2744 return true;
2746 x = XEXP (x, 0);
2747 gcc_assert (GET_CODE (x) == PLUS);
2749 sym = XEXP (x, 0);
2750 x = XEXP (x, 1);
2751 if (GET_CODE (sym) != SYMBOL_REF
2752 || GET_CODE (x) != CONST_INT)
2753 return true;
2754 offset = INTVAL (x);
2756 if (SYMBOL_REF_DECL (sym) == 0)
2757 return true;
2758 if (offset < 0
2759 || offset >= int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (sym))))
2760 return false;
2762 return true;
2765 static bool
2766 bfin_rtx_costs (rtx x, int code, int outer_code, int *total)
2768 int cost2 = COSTS_N_INSNS (1);
2769 rtx op0, op1;
2771 switch (code)
2773 case CONST_INT:
2774 if (outer_code == SET || outer_code == PLUS)
2775 *total = CONST_7BIT_IMM_P (INTVAL (x)) ? 0 : cost2;
2776 else if (outer_code == AND)
2777 *total = log2constp (~INTVAL (x)) ? 0 : cost2;
2778 else if (outer_code == LE || outer_code == LT || outer_code == EQ)
2779 *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
2780 else if (outer_code == LEU || outer_code == LTU)
2781 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
2782 else if (outer_code == MULT)
2783 *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
2784 else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
2785 *total = 0;
2786 else if (outer_code == ASHIFT || outer_code == ASHIFTRT
2787 || outer_code == LSHIFTRT)
2788 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
2789 else if (outer_code == IOR || outer_code == XOR)
2790 *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
2791 else
2792 *total = cost2;
2793 return true;
2795 case CONST:
2796 case LABEL_REF:
2797 case SYMBOL_REF:
2798 case CONST_DOUBLE:
2799 *total = COSTS_N_INSNS (2);
2800 return true;
2802 case PLUS:
2803 op0 = XEXP (x, 0);
2804 op1 = XEXP (x, 1);
2805 if (GET_MODE (x) == SImode)
2807 if (GET_CODE (op0) == MULT
2808 && GET_CODE (XEXP (op0, 1)) == CONST_INT)
2810 HOST_WIDE_INT val = INTVAL (XEXP (op0, 1));
2811 if (val == 2 || val == 4)
2813 *total = cost2;
2814 *total += rtx_cost (XEXP (op0, 0), outer_code);
2815 *total += rtx_cost (op1, outer_code);
2816 return true;
2819 *total = cost2;
2820 if (GET_CODE (op0) != REG
2821 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2822 *total += rtx_cost (op0, SET);
2823 #if 0 /* We'd like to do this for accuracy, but it biases the loop optimizer
2824 towards creating too many induction variables. */
2825 if (!reg_or_7bit_operand (op1, SImode))
2826 *total += rtx_cost (op1, SET);
2827 #endif
2829 else if (GET_MODE (x) == DImode)
2831 *total = 6 * cost2;
2832 if (GET_CODE (op1) != CONST_INT
2833 || !CONST_7BIT_IMM_P (INTVAL (op1)))
2834 *total += rtx_cost (op1, PLUS);
2835 if (GET_CODE (op0) != REG
2836 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2837 *total += rtx_cost (op0, PLUS);
2839 return true;
2841 case MINUS:
2842 if (GET_MODE (x) == DImode)
2843 *total = 6 * cost2;
2844 else
2845 *total = cost2;
2846 return true;
2848 case ASHIFT:
2849 case ASHIFTRT:
2850 case LSHIFTRT:
2851 if (GET_MODE (x) == DImode)
2852 *total = 6 * cost2;
2853 else
2854 *total = cost2;
2856 op0 = XEXP (x, 0);
2857 op1 = XEXP (x, 1);
2858 if (GET_CODE (op0) != REG
2859 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2860 *total += rtx_cost (op0, code);
2862 return true;
2864 case IOR:
2865 case AND:
2866 case XOR:
2867 op0 = XEXP (x, 0);
2868 op1 = XEXP (x, 1);
2870 /* Handle special cases of IOR: rotates, ALIGN insns, movstricthi_high. */
2871 if (code == IOR)
2873 if ((GET_CODE (op0) == LSHIFTRT && GET_CODE (op1) == ASHIFT)
2874 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == ZERO_EXTEND)
2875 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT)
2876 || (GET_CODE (op0) == AND && GET_CODE (op1) == CONST_INT))
2878 *total = cost2;
2879 return true;
2883 if (GET_CODE (op0) != REG
2884 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2885 *total += rtx_cost (op0, code);
2887 if (GET_MODE (x) == DImode)
2889 *total = 2 * cost2;
2890 return true;
2892 *total = cost2;
2893 if (GET_MODE (x) != SImode)
2894 return true;
2896 if (code == AND)
2898 if (! rhs_andsi3_operand (XEXP (x, 1), SImode))
2899 *total += rtx_cost (XEXP (x, 1), code);
2901 else
2903 if (! regorlog2_operand (XEXP (x, 1), SImode))
2904 *total += rtx_cost (XEXP (x, 1), code);
2907 return true;
2909 case ZERO_EXTRACT:
2910 case SIGN_EXTRACT:
2911 if (outer_code == SET
2912 && XEXP (x, 1) == const1_rtx
2913 && GET_CODE (XEXP (x, 2)) == CONST_INT)
2915 *total = 2 * cost2;
2916 return true;
2918 /* fall through */
2920 case SIGN_EXTEND:
2921 case ZERO_EXTEND:
2922 *total = cost2;
2923 return true;
2925 case MULT:
2927 op0 = XEXP (x, 0);
2928 op1 = XEXP (x, 1);
2929 if (GET_CODE (op0) == GET_CODE (op1)
2930 && (GET_CODE (op0) == ZERO_EXTEND
2931 || GET_CODE (op0) == SIGN_EXTEND))
2933 *total = COSTS_N_INSNS (1);
2934 op0 = XEXP (op0, 0);
2935 op1 = XEXP (op1, 0);
2937 else if (optimize_size)
2938 *total = COSTS_N_INSNS (1);
2939 else
2940 *total = COSTS_N_INSNS (3);
2942 if (GET_CODE (op0) != REG
2943 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2944 *total += rtx_cost (op0, MULT);
2945 if (GET_CODE (op1) != REG
2946 && (GET_CODE (op1) != SUBREG || GET_CODE (SUBREG_REG (op1)) != REG))
2947 *total += rtx_cost (op1, MULT);
2949 return true;
2951 case UDIV:
2952 case UMOD:
2953 *total = COSTS_N_INSNS (32);
2954 return true;
2956 case VEC_CONCAT:
2957 case VEC_SELECT:
2958 if (outer_code == SET)
2959 *total = cost2;
2960 return true;
2962 default:
2963 return false;
2967 /* Used for communication between {push,pop}_multiple_operation (which
2968 we use not only as a predicate) and the corresponding output functions. */
2969 static int first_preg_to_save, first_dreg_to_save;
2972 push_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2974 int lastdreg = 8, lastpreg = 6;
2975 int i, group;
2977 first_preg_to_save = lastpreg;
2978 first_dreg_to_save = lastdreg;
2979 for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
2981 rtx t = XVECEXP (op, 0, i);
2982 rtx src, dest;
2983 int regno;
2985 if (GET_CODE (t) != SET)
2986 return 0;
2988 src = SET_SRC (t);
2989 dest = SET_DEST (t);
2990 if (GET_CODE (dest) != MEM || ! REG_P (src))
2991 return 0;
2992 dest = XEXP (dest, 0);
2993 if (GET_CODE (dest) != PLUS
2994 || ! REG_P (XEXP (dest, 0))
2995 || REGNO (XEXP (dest, 0)) != REG_SP
2996 || GET_CODE (XEXP (dest, 1)) != CONST_INT
2997 || INTVAL (XEXP (dest, 1)) != -i * 4)
2998 return 0;
3000 regno = REGNO (src);
3001 if (group == 0)
3003 if (D_REGNO_P (regno))
3005 group = 1;
3006 first_dreg_to_save = lastdreg = regno - REG_R0;
3008 else if (regno >= REG_P0 && regno <= REG_P7)
3010 group = 2;
3011 first_preg_to_save = lastpreg = regno - REG_P0;
3013 else
3014 return 0;
3016 continue;
3019 if (group == 1)
3021 if (regno >= REG_P0 && regno <= REG_P7)
3023 group = 2;
3024 first_preg_to_save = lastpreg = regno - REG_P0;
3026 else if (regno != REG_R0 + lastdreg + 1)
3027 return 0;
3028 else
3029 lastdreg++;
3031 else if (group == 2)
3033 if (regno != REG_P0 + lastpreg + 1)
3034 return 0;
3035 lastpreg++;
3038 return 1;
3042 pop_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
3044 int lastdreg = 8, lastpreg = 6;
3045 int i, group;
3047 for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
3049 rtx t = XVECEXP (op, 0, i);
3050 rtx src, dest;
3051 int regno;
3053 if (GET_CODE (t) != SET)
3054 return 0;
3056 src = SET_SRC (t);
3057 dest = SET_DEST (t);
3058 if (GET_CODE (src) != MEM || ! REG_P (dest))
3059 return 0;
3060 src = XEXP (src, 0);
3062 if (i == 1)
3064 if (! REG_P (src) || REGNO (src) != REG_SP)
3065 return 0;
3067 else if (GET_CODE (src) != PLUS
3068 || ! REG_P (XEXP (src, 0))
3069 || REGNO (XEXP (src, 0)) != REG_SP
3070 || GET_CODE (XEXP (src, 1)) != CONST_INT
3071 || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
3072 return 0;
3074 regno = REGNO (dest);
3075 if (group == 0)
3077 if (regno == REG_R7)
3079 group = 1;
3080 lastdreg = 7;
3082 else if (regno != REG_P0 + lastpreg - 1)
3083 return 0;
3084 else
3085 lastpreg--;
3087 else if (group == 1)
3089 if (regno != REG_R0 + lastdreg - 1)
3090 return 0;
3091 else
3092 lastdreg--;
3095 first_dreg_to_save = lastdreg;
3096 first_preg_to_save = lastpreg;
3097 return 1;
3100 /* Emit assembly code for one multi-register push described by INSN, with
3101 operands in OPERANDS. */
3103 void
3104 output_push_multiple (rtx insn, rtx *operands)
3106 char buf[80];
3107 int ok;
3109 /* Validate the insn again, and compute first_[dp]reg_to_save. */
3110 ok = push_multiple_operation (PATTERN (insn), VOIDmode);
3111 gcc_assert (ok);
3113 if (first_dreg_to_save == 8)
3114 sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
3115 else if (first_preg_to_save == 6)
3116 sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
3117 else
3118 sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
3119 first_dreg_to_save, first_preg_to_save);
3121 output_asm_insn (buf, operands);
3124 /* Emit assembly code for one multi-register pop described by INSN, with
3125 operands in OPERANDS. */
3127 void
3128 output_pop_multiple (rtx insn, rtx *operands)
3130 char buf[80];
3131 int ok;
3133 /* Validate the insn again, and compute first_[dp]reg_to_save. */
3134 ok = pop_multiple_operation (PATTERN (insn), VOIDmode);
3135 gcc_assert (ok);
3137 if (first_dreg_to_save == 8)
3138 sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
3139 else if (first_preg_to_save == 6)
3140 sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
3141 else
3142 sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
3143 first_dreg_to_save, first_preg_to_save);
3145 output_asm_insn (buf, operands);
3148 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE. */
3150 static void
3151 single_move_for_movmem (rtx dst, rtx src, enum machine_mode mode, HOST_WIDE_INT offset)
3153 rtx scratch = gen_reg_rtx (mode);
3154 rtx srcmem, dstmem;
3156 srcmem = adjust_address_nv (src, mode, offset);
3157 dstmem = adjust_address_nv (dst, mode, offset);
3158 emit_move_insn (scratch, srcmem);
3159 emit_move_insn (dstmem, scratch);
3162 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
3163 alignment ALIGN_EXP. Return true if successful, false if we should fall
3164 back on a different method. */
3166 bool
3167 bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
3169 rtx srcreg, destreg, countreg;
3170 HOST_WIDE_INT align = 0;
3171 unsigned HOST_WIDE_INT count = 0;
3173 if (GET_CODE (align_exp) == CONST_INT)
3174 align = INTVAL (align_exp);
3175 if (GET_CODE (count_exp) == CONST_INT)
3177 count = INTVAL (count_exp);
3178 #if 0
3179 if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
3180 return false;
3181 #endif
3184 /* If optimizing for size, only do single copies inline. */
3185 if (optimize_size)
3187 if (count == 2 && align < 2)
3188 return false;
3189 if (count == 4 && align < 4)
3190 return false;
3191 if (count != 1 && count != 2 && count != 4)
3192 return false;
3194 if (align < 2 && count != 1)
3195 return false;
3197 destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
3198 if (destreg != XEXP (dst, 0))
3199 dst = replace_equiv_address_nv (dst, destreg);
3200 srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
3201 if (srcreg != XEXP (src, 0))
3202 src = replace_equiv_address_nv (src, srcreg);
3204 if (count != 0 && align >= 2)
3206 unsigned HOST_WIDE_INT offset = 0;
3208 if (align >= 4)
3210 if ((count & ~3) == 4)
3212 single_move_for_movmem (dst, src, SImode, offset);
3213 offset = 4;
3215 else if (count & ~3)
3217 HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
3218 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3220 emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
3222 if (count & 2)
3224 single_move_for_movmem (dst, src, HImode, offset);
3225 offset += 2;
3228 else
3230 if ((count & ~1) == 2)
3232 single_move_for_movmem (dst, src, HImode, offset);
3233 offset = 2;
3235 else if (count & ~1)
3237 HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
3238 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3240 emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
3243 if (count & 1)
3245 single_move_for_movmem (dst, src, QImode, offset);
3247 return true;
3249 return false;
3252 /* Compute the alignment for a local variable.
3253 TYPE is the data type, and ALIGN is the alignment that
3254 the object would ordinarily have. The value of this macro is used
3255 instead of that alignment to align the object. */
3258 bfin_local_alignment (tree type, int align)
3260 /* Increasing alignment for (relatively) big types allows the builtin
3261 memcpy can use 32 bit loads/stores. */
3262 if (TYPE_SIZE (type)
3263 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
3264 && (TREE_INT_CST_LOW (TYPE_SIZE (type)) > 8
3265 || TREE_INT_CST_HIGH (TYPE_SIZE (type))) && align < 32)
3266 return 32;
3267 return align;
3270 /* Implement TARGET_SCHED_ISSUE_RATE. */
3272 static int
3273 bfin_issue_rate (void)
3275 return 3;
3278 static int
3279 bfin_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
3281 enum attr_type insn_type, dep_insn_type;
3282 int dep_insn_code_number;
3284 /* Anti and output dependencies have zero cost. */
3285 if (REG_NOTE_KIND (link) != 0)
3286 return 0;
3288 dep_insn_code_number = recog_memoized (dep_insn);
3290 /* If we can't recognize the insns, we can't really do anything. */
3291 if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
3292 return cost;
3294 insn_type = get_attr_type (insn);
3295 dep_insn_type = get_attr_type (dep_insn);
3297 if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)
3299 rtx pat = PATTERN (dep_insn);
3300 rtx dest = SET_DEST (pat);
3301 rtx src = SET_SRC (pat);
3302 if (! ADDRESS_REGNO_P (REGNO (dest))
3303 || ! (MEM_P (src) || D_REGNO_P (REGNO (src))))
3304 return cost;
3305 return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);
3308 return cost;
3312 /* Increment the counter for the number of loop instructions in the
3313 current function. */
3315 void
3316 bfin_hardware_loop (void)
3318 cfun->machine->has_hardware_loops++;
3321 /* Maximum loop nesting depth. */
3322 #define MAX_LOOP_DEPTH 2
3324 /* Maximum size of a loop. */
3325 #define MAX_LOOP_LENGTH 2042
3327 /* Maximum distance of the LSETUP instruction from the loop start. */
3328 #define MAX_LSETUP_DISTANCE 30
3330 /* We need to keep a vector of loops */
3331 typedef struct loop_info *loop_info;
3332 DEF_VEC_P (loop_info);
3333 DEF_VEC_ALLOC_P (loop_info,heap);
3335 /* Information about a loop we have found (or are in the process of
3336 finding). */
3337 struct loop_info GTY (())
3339 /* loop number, for dumps */
3340 int loop_no;
3342 /* All edges that jump into and out of the loop. */
3343 VEC(edge,gc) *incoming;
3345 /* We can handle two cases: all incoming edges have the same destination
3346 block, or all incoming edges have the same source block. These two
3347 members are set to the common source or destination we found, or NULL
3348 if different blocks were found. If both are NULL the loop can't be
3349 optimized. */
3350 basic_block incoming_src;
3351 basic_block incoming_dest;
3353 /* First block in the loop. This is the one branched to by the loop_end
3354 insn. */
3355 basic_block head;
3357 /* Last block in the loop (the one with the loop_end insn). */
3358 basic_block tail;
3360 /* The successor block of the loop. This is the one the loop_end insn
3361 falls into. */
3362 basic_block successor;
3364 /* The last instruction in the tail. */
3365 rtx last_insn;
3367 /* The loop_end insn. */
3368 rtx loop_end;
3370 /* The iteration register. */
3371 rtx iter_reg;
3373 /* The new initialization insn. */
3374 rtx init;
3376 /* The new initialization instruction. */
3377 rtx loop_init;
3379 /* The new label placed at the beginning of the loop. */
3380 rtx start_label;
3382 /* The new label placed at the end of the loop. */
3383 rtx end_label;
3385 /* The length of the loop. */
3386 int length;
3388 /* The nesting depth of the loop. */
3389 int depth;
3391 /* Nonzero if we can't optimize this loop. */
3392 int bad;
3394 /* True if we have visited this loop. */
3395 int visited;
3397 /* True if this loop body clobbers any of LC0, LT0, or LB0. */
3398 int clobber_loop0;
3400 /* True if this loop body clobbers any of LC1, LT1, or LB1. */
3401 int clobber_loop1;
3403 /* Next loop in the graph. */
3404 struct loop_info *next;
3406 /* Immediate outer loop of this loop. */
3407 struct loop_info *outer;
3409 /* Vector of blocks only within the loop, including those within
3410 inner loops. */
3411 VEC (basic_block,heap) *blocks;
3413 /* Same information in a bitmap. */
3414 bitmap block_bitmap;
3416 /* Vector of inner loops within this loop */
3417 VEC (loop_info,heap) *loops;
3420 static void
3421 bfin_dump_loops (loop_info loops)
3423 loop_info loop;
3425 for (loop = loops; loop; loop = loop->next)
3427 loop_info i;
3428 basic_block b;
3429 unsigned ix;
3431 fprintf (dump_file, ";; loop %d: ", loop->loop_no);
3432 if (loop->bad)
3433 fprintf (dump_file, "(bad) ");
3434 fprintf (dump_file, "{head:%d, depth:%d}", loop->head->index, loop->depth);
3436 fprintf (dump_file, " blocks: [ ");
3437 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, b); ix++)
3438 fprintf (dump_file, "%d ", b->index);
3439 fprintf (dump_file, "] ");
3441 fprintf (dump_file, " inner loops: [ ");
3442 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, i); ix++)
3443 fprintf (dump_file, "%d ", i->loop_no);
3444 fprintf (dump_file, "]\n");
3446 fprintf (dump_file, "\n");
3449 /* Scan the blocks of LOOP (and its inferiors) looking for basic block
3450 BB. Return true, if we find it. */
3452 static bool
3453 bfin_bb_in_loop (loop_info loop, basic_block bb)
3455 return bitmap_bit_p (loop->block_bitmap, bb->index);
3458 /* Scan the blocks of LOOP (and its inferiors) looking for uses of
3459 REG. Return true, if we find any. Don't count the loop's loop_end
3460 insn if it matches LOOP_END. */
3462 static bool
3463 bfin_scan_loop (loop_info loop, rtx reg, rtx loop_end)
3465 unsigned ix;
3466 basic_block bb;
3468 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
3470 rtx insn;
3472 for (insn = BB_HEAD (bb);
3473 insn != NEXT_INSN (BB_END (bb));
3474 insn = NEXT_INSN (insn))
3476 if (!INSN_P (insn))
3477 continue;
3478 if (insn == loop_end)
3479 continue;
3480 if (reg_mentioned_p (reg, PATTERN (insn)))
3481 return true;
3484 return false;
3487 /* Estimate the length of INSN conservatively. */
3489 static int
3490 length_for_loop (rtx insn)
3492 int length = 0;
3493 if (JUMP_P (insn) && any_condjump_p (insn) && !optimize_size)
3495 if (ENABLE_WA_SPECULATIVE_SYNCS)
3496 length = 8;
3497 else if (ENABLE_WA_SPECULATIVE_LOADS)
3498 length = 6;
3500 else if (LABEL_P (insn))
3502 if (ENABLE_WA_SPECULATIVE_SYNCS)
3503 length = 4;
3506 if (INSN_P (insn))
3507 length += get_attr_length (insn);
3509 return length;
3512 /* Optimize LOOP. */
3514 static void
3515 bfin_optimize_loop (loop_info loop)
3517 basic_block bb;
3518 loop_info inner;
3519 rtx insn, init_insn, last_insn, nop_insn;
3520 rtx loop_init, start_label, end_label;
3521 rtx reg_lc0, reg_lc1, reg_lt0, reg_lt1, reg_lb0, reg_lb1;
3522 rtx iter_reg;
3523 rtx lc_reg, lt_reg, lb_reg;
3524 rtx seq, seq_end;
3525 int length;
3526 unsigned ix;
3527 int inner_depth = 0;
3529 if (loop->visited)
3530 return;
3532 loop->visited = 1;
3534 if (loop->bad)
3536 if (dump_file)
3537 fprintf (dump_file, ";; loop %d bad when found\n", loop->loop_no);
3538 goto bad_loop;
3541 /* Every loop contains in its list of inner loops every loop nested inside
3542 it, even if there are intermediate loops. This works because we're doing
3543 a depth-first search here and never visit a loop more than once. */
3544 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, inner); ix++)
3546 bfin_optimize_loop (inner);
3548 if (!inner->bad && inner_depth < inner->depth)
3550 inner_depth = inner->depth;
3552 loop->clobber_loop0 |= inner->clobber_loop0;
3553 loop->clobber_loop1 |= inner->clobber_loop1;
3557 loop->depth = inner_depth + 1;
3558 if (loop->depth > MAX_LOOP_DEPTH)
3560 if (dump_file)
3561 fprintf (dump_file, ";; loop %d too deep\n", loop->loop_no);
3562 goto bad_loop;
3565 /* Get the loop iteration register. */
3566 iter_reg = loop->iter_reg;
3568 if (!DPREG_P (iter_reg))
3570 if (dump_file)
3571 fprintf (dump_file, ";; loop %d iteration count NOT in PREG or DREG\n",
3572 loop->loop_no);
3573 goto bad_loop;
3576 if (loop->incoming_src)
3578 /* Make sure the predecessor is before the loop start label, as required by
3579 the LSETUP instruction. */
3580 length = 0;
3581 for (insn = BB_END (loop->incoming_src);
3582 insn && insn != loop->start_label;
3583 insn = NEXT_INSN (insn))
3584 length += length_for_loop (insn);
3586 if (!insn)
3588 if (dump_file)
3589 fprintf (dump_file, ";; loop %d lsetup not before loop_start\n",
3590 loop->loop_no);
3591 goto bad_loop;
3594 if (length > MAX_LSETUP_DISTANCE)
3596 if (dump_file)
3597 fprintf (dump_file, ";; loop %d lsetup too far away\n", loop->loop_no);
3598 goto bad_loop;
3602 /* Check if start_label appears before loop_end and calculate the
3603 offset between them. We calculate the length of instructions
3604 conservatively. */
3605 length = 0;
3606 for (insn = loop->start_label;
3607 insn && insn != loop->loop_end;
3608 insn = NEXT_INSN (insn))
3609 length += length_for_loop (insn);
3611 if (!insn)
3613 if (dump_file)
3614 fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
3615 loop->loop_no);
3616 goto bad_loop;
3619 loop->length = length;
3620 if (loop->length > MAX_LOOP_LENGTH)
3622 if (dump_file)
3623 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
3624 goto bad_loop;
3627 /* Scan all the blocks to make sure they don't use iter_reg. */
3628 if (bfin_scan_loop (loop, iter_reg, loop->loop_end))
3630 if (dump_file)
3631 fprintf (dump_file, ";; loop %d uses iterator\n", loop->loop_no);
3632 goto bad_loop;
3635 /* Scan all the insns to see if the loop body clobber
3636 any hardware loop registers. */
3638 reg_lc0 = gen_rtx_REG (SImode, REG_LC0);
3639 reg_lc1 = gen_rtx_REG (SImode, REG_LC1);
3640 reg_lt0 = gen_rtx_REG (SImode, REG_LT0);
3641 reg_lt1 = gen_rtx_REG (SImode, REG_LT1);
3642 reg_lb0 = gen_rtx_REG (SImode, REG_LB0);
3643 reg_lb1 = gen_rtx_REG (SImode, REG_LB1);
3645 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
3647 rtx insn;
3649 for (insn = BB_HEAD (bb);
3650 insn != NEXT_INSN (BB_END (bb));
3651 insn = NEXT_INSN (insn))
3653 if (!INSN_P (insn))
3654 continue;
3656 if (reg_set_p (reg_lc0, insn)
3657 || reg_set_p (reg_lt0, insn)
3658 || reg_set_p (reg_lb0, insn))
3659 loop->clobber_loop0 = 1;
3661 if (reg_set_p (reg_lc1, insn)
3662 || reg_set_p (reg_lt1, insn)
3663 || reg_set_p (reg_lb1, insn))
3664 loop->clobber_loop1 |= 1;
3668 if ((loop->clobber_loop0 && loop->clobber_loop1)
3669 || (loop->depth == MAX_LOOP_DEPTH && loop->clobber_loop0))
3671 loop->depth = MAX_LOOP_DEPTH + 1;
3672 if (dump_file)
3673 fprintf (dump_file, ";; loop %d no loop reg available\n",
3674 loop->loop_no);
3675 goto bad_loop;
3678 /* There should be an instruction before the loop_end instruction
3679 in the same basic block. And the instruction must not be
3680 - JUMP
3681 - CONDITIONAL BRANCH
3682 - CALL
3683 - CSYNC
3684 - SSYNC
3685 - Returns (RTS, RTN, etc.) */
3687 bb = loop->tail;
3688 last_insn = PREV_INSN (loop->loop_end);
3690 while (1)
3692 for (; last_insn != PREV_INSN (BB_HEAD (bb));
3693 last_insn = PREV_INSN (last_insn))
3694 if (INSN_P (last_insn))
3695 break;
3697 if (last_insn != PREV_INSN (BB_HEAD (bb)))
3698 break;
3700 if (single_pred_p (bb)
3701 && single_pred (bb) != ENTRY_BLOCK_PTR)
3703 bb = single_pred (bb);
3704 last_insn = BB_END (bb);
3705 continue;
3707 else
3709 last_insn = NULL_RTX;
3710 break;
3714 if (!last_insn)
3716 if (dump_file)
3717 fprintf (dump_file, ";; loop %d has no last instruction\n",
3718 loop->loop_no);
3719 goto bad_loop;
3722 if (JUMP_P (last_insn))
3724 loop_info inner = bb->aux;
3725 if (inner
3726 && inner->outer == loop
3727 && inner->loop_end == last_insn
3728 && inner->depth == 1)
3729 /* This jump_insn is the exact loop_end of an inner loop
3730 and to be optimized away. So use the inner's last_insn. */
3731 last_insn = inner->last_insn;
3732 else
3734 if (dump_file)
3735 fprintf (dump_file, ";; loop %d has bad last instruction\n",
3736 loop->loop_no);
3737 goto bad_loop;
3740 else if (CALL_P (last_insn)
3741 || (GET_CODE (PATTERN (last_insn)) != SEQUENCE
3742 && get_attr_type (last_insn) == TYPE_SYNC)
3743 || recog_memoized (last_insn) == CODE_FOR_return_internal)
3745 if (dump_file)
3746 fprintf (dump_file, ";; loop %d has bad last instruction\n",
3747 loop->loop_no);
3748 goto bad_loop;
3751 if (GET_CODE (PATTERN (last_insn)) == ASM_INPUT
3752 || asm_noperands (PATTERN (last_insn)) >= 0
3753 || (GET_CODE (PATTERN (last_insn)) != SEQUENCE
3754 && get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI))
3756 nop_insn = emit_insn_after (gen_nop (), last_insn);
3757 last_insn = nop_insn;
3760 loop->last_insn = last_insn;
3762 /* The loop is good for replacement. */
3763 start_label = loop->start_label;
3764 end_label = gen_label_rtx ();
3765 iter_reg = loop->iter_reg;
3767 if (loop->depth == 1 && !loop->clobber_loop1)
3769 lc_reg = reg_lc1;
3770 lt_reg = reg_lt1;
3771 lb_reg = reg_lb1;
3772 loop->clobber_loop1 = 1;
3774 else
3776 lc_reg = reg_lc0;
3777 lt_reg = reg_lt0;
3778 lb_reg = reg_lb0;
3779 loop->clobber_loop0 = 1;
3782 /* If iter_reg is a DREG, we need generate an instruction to load
3783 the loop count into LC register. */
3784 if (D_REGNO_P (REGNO (iter_reg)))
3786 init_insn = gen_movsi (lc_reg, iter_reg);
3787 loop_init = gen_lsetup_without_autoinit (lt_reg, start_label,
3788 lb_reg, end_label,
3789 lc_reg);
3791 else if (P_REGNO_P (REGNO (iter_reg)))
3793 init_insn = NULL_RTX;
3794 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
3795 lb_reg, end_label,
3796 lc_reg, iter_reg);
3798 else
3799 gcc_unreachable ();
3801 loop->init = init_insn;
3802 loop->end_label = end_label;
3803 loop->loop_init = loop_init;
3805 if (dump_file)
3807 fprintf (dump_file, ";; replacing loop %d initializer with\n",
3808 loop->loop_no);
3809 print_rtl_single (dump_file, loop->loop_init);
3810 fprintf (dump_file, ";; replacing loop %d terminator with\n",
3811 loop->loop_no);
3812 print_rtl_single (dump_file, loop->loop_end);
3815 start_sequence ();
3817 if (loop->init != NULL_RTX)
3818 emit_insn (loop->init);
3819 seq_end = emit_insn (loop->loop_init);
3821 seq = get_insns ();
3822 end_sequence ();
3824 if (loop->incoming_src)
3826 rtx prev = BB_END (loop->incoming_src);
3827 if (VEC_length (edge, loop->incoming) > 1
3828 || !(VEC_last (edge, loop->incoming)->flags & EDGE_FALLTHRU))
3830 gcc_assert (JUMP_P (prev));
3831 prev = PREV_INSN (prev);
3833 emit_insn_after (seq, prev);
3835 else
3837 basic_block new_bb;
3838 edge e;
3839 edge_iterator ei;
3841 if (loop->head != loop->incoming_dest)
3843 FOR_EACH_EDGE (e, ei, loop->head->preds)
3845 if (e->flags & EDGE_FALLTHRU)
3847 rtx newjump = gen_jump (loop->start_label);
3848 emit_insn_before (newjump, BB_HEAD (loop->head));
3849 new_bb = create_basic_block (newjump, newjump, loop->head->prev_bb);
3850 gcc_assert (new_bb = loop->head->prev_bb);
3851 break;
3856 emit_insn_before (seq, BB_HEAD (loop->head));
3857 seq = emit_label_before (gen_label_rtx (), seq);
3859 new_bb = create_basic_block (seq, seq_end, loop->head->prev_bb);
3860 FOR_EACH_EDGE (e, ei, loop->incoming)
3862 if (!(e->flags & EDGE_FALLTHRU)
3863 || e->dest != loop->head)
3864 redirect_edge_and_branch_force (e, new_bb);
3865 else
3866 redirect_edge_succ (e, new_bb);
3870 delete_insn (loop->loop_end);
3871 /* Insert the loop end label before the last instruction of the loop. */
3872 emit_label_before (loop->end_label, loop->last_insn);
3874 return;
3876 bad_loop:
3878 if (dump_file)
3879 fprintf (dump_file, ";; loop %d is bad\n", loop->loop_no);
3881 loop->bad = 1;
3883 if (DPREG_P (loop->iter_reg))
3885 /* If loop->iter_reg is a DREG or PREG, we can split it here
3886 without scratch register. */
3887 rtx insn;
3889 emit_insn_before (gen_addsi3 (loop->iter_reg,
3890 loop->iter_reg,
3891 constm1_rtx),
3892 loop->loop_end);
3894 emit_insn_before (gen_cmpsi (loop->iter_reg, const0_rtx),
3895 loop->loop_end);
3897 insn = emit_jump_insn_before (gen_bne (loop->start_label),
3898 loop->loop_end);
3900 JUMP_LABEL (insn) = loop->start_label;
3901 LABEL_NUSES (loop->start_label)++;
3902 delete_insn (loop->loop_end);
3906 /* Called from bfin_reorg_loops when a potential loop end is found. LOOP is
3907 a newly set up structure describing the loop, it is this function's
3908 responsibility to fill most of it. TAIL_BB and TAIL_INSN point to the
3909 loop_end insn and its enclosing basic block. */
3911 static void
3912 bfin_discover_loop (loop_info loop, basic_block tail_bb, rtx tail_insn)
3914 unsigned dwork = 0;
3915 basic_block bb;
3916 VEC (basic_block,heap) *works = VEC_alloc (basic_block,heap,20);
3918 loop->tail = tail_bb;
3919 loop->head = BRANCH_EDGE (tail_bb)->dest;
3920 loop->successor = FALLTHRU_EDGE (tail_bb)->dest;
3921 loop->loop_end = tail_insn;
3922 loop->last_insn = NULL_RTX;
3923 loop->iter_reg = SET_DEST (XVECEXP (PATTERN (tail_insn), 0, 1));
3924 loop->depth = loop->length = 0;
3925 loop->visited = 0;
3926 loop->clobber_loop0 = loop->clobber_loop1 = 0;
3927 loop->outer = NULL;
3928 loop->loops = NULL;
3929 loop->incoming = VEC_alloc (edge, gc, 2);
3930 loop->init = loop->loop_init = NULL_RTX;
3931 loop->start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (tail_insn), 0, 0)), 1), 0);
3932 loop->end_label = NULL_RTX;
3933 loop->bad = 0;
3935 VEC_safe_push (basic_block, heap, works, loop->head);
3937 while (VEC_iterate (basic_block, works, dwork++, bb))
3939 edge e;
3940 edge_iterator ei;
3941 if (bb == EXIT_BLOCK_PTR)
3943 /* We've reached the exit block. The loop must be bad. */
3944 if (dump_file)
3945 fprintf (dump_file,
3946 ";; Loop is bad - reached exit block while scanning\n");
3947 loop->bad = 1;
3948 break;
3951 if (bitmap_bit_p (loop->block_bitmap, bb->index))
3952 continue;
3954 /* We've not seen this block before. Add it to the loop's
3955 list and then add each successor to the work list. */
3957 VEC_safe_push (basic_block, heap, loop->blocks, bb);
3958 bitmap_set_bit (loop->block_bitmap, bb->index);
3960 if (bb != tail_bb)
3962 FOR_EACH_EDGE (e, ei, bb->succs)
3964 basic_block succ = EDGE_SUCC (bb, ei.index)->dest;
3965 if (!REGNO_REG_SET_P (df_get_live_in (succ),
3966 REGNO (loop->iter_reg)))
3967 continue;
3968 if (!VEC_space (basic_block, works, 1))
3970 if (dwork)
3972 VEC_block_remove (basic_block, works, 0, dwork);
3973 dwork = 0;
3975 else
3976 VEC_reserve (basic_block, heap, works, 1);
3978 VEC_quick_push (basic_block, works, succ);
3983 /* Find the predecessor, and make sure nothing else jumps into this loop. */
3984 if (!loop->bad)
3986 int pass, retry;
3987 for (dwork = 0; VEC_iterate (basic_block, loop->blocks, dwork, bb); dwork++)
3989 edge e;
3990 edge_iterator ei;
3991 FOR_EACH_EDGE (e, ei, bb->preds)
3993 basic_block pred = e->src;
3995 if (!bfin_bb_in_loop (loop, pred))
3997 if (dump_file)
3998 fprintf (dump_file, ";; Loop %d: incoming edge %d -> %d\n",
3999 loop->loop_no, pred->index,
4000 e->dest->index);
4001 VEC_safe_push (edge, gc, loop->incoming, e);
4006 for (pass = 0, retry = 1; retry && pass < 2; pass++)
4008 edge e;
4009 edge_iterator ei;
4010 bool first = true;
4011 retry = 0;
4013 FOR_EACH_EDGE (e, ei, loop->incoming)
4015 if (first)
4017 loop->incoming_src = e->src;
4018 loop->incoming_dest = e->dest;
4019 first = false;
4021 else
4023 if (e->dest != loop->incoming_dest)
4024 loop->incoming_dest = NULL;
4025 if (e->src != loop->incoming_src)
4026 loop->incoming_src = NULL;
4028 if (loop->incoming_src == NULL && loop->incoming_dest == NULL)
4030 if (pass == 0)
4032 if (dump_file)
4033 fprintf (dump_file,
4034 ";; retrying loop %d with forwarder blocks\n",
4035 loop->loop_no);
4036 retry = 1;
4037 break;
4039 loop->bad = 1;
4040 if (dump_file)
4041 fprintf (dump_file,
4042 ";; can't find suitable entry for loop %d\n",
4043 loop->loop_no);
4044 goto out;
4047 if (retry)
4049 retry = 0;
4050 FOR_EACH_EDGE (e, ei, loop->incoming)
4052 if (forwarder_block_p (e->src))
4054 edge e2;
4055 edge_iterator ei2;
4057 if (dump_file)
4058 fprintf (dump_file,
4059 ";; Adding forwarder block %d to loop %d and retrying\n",
4060 e->src->index, loop->loop_no);
4061 VEC_safe_push (basic_block, heap, loop->blocks, e->src);
4062 bitmap_set_bit (loop->block_bitmap, e->src->index);
4063 FOR_EACH_EDGE (e2, ei2, e->src->preds)
4064 VEC_safe_push (edge, gc, loop->incoming, e2);
4065 VEC_unordered_remove (edge, loop->incoming, ei.index);
4066 retry = 1;
4067 break;
4074 out:
4075 VEC_free (basic_block, heap, works);
4078 /* Analyze the structure of the loops in the current function. Use STACK
4079 for bitmap allocations. Returns all the valid candidates for hardware
4080 loops found in this function. */
4081 static loop_info
4082 bfin_discover_loops (bitmap_obstack *stack, FILE *dump_file)
4084 loop_info loops = NULL;
4085 loop_info loop;
4086 basic_block bb;
4087 bitmap tmp_bitmap;
4088 int nloops = 0;
4090 /* Find all the possible loop tails. This means searching for every
4091 loop_end instruction. For each one found, create a loop_info
4092 structure and add the head block to the work list. */
4093 FOR_EACH_BB (bb)
4095 rtx tail = BB_END (bb);
4097 while (GET_CODE (tail) == NOTE)
4098 tail = PREV_INSN (tail);
4100 bb->aux = NULL;
4102 if (INSN_P (tail) && recog_memoized (tail) == CODE_FOR_loop_end)
4104 /* A possible loop end */
4106 loop = XNEW (struct loop_info);
4107 loop->next = loops;
4108 loops = loop;
4109 loop->loop_no = nloops++;
4110 loop->blocks = VEC_alloc (basic_block, heap, 20);
4111 loop->block_bitmap = BITMAP_ALLOC (stack);
4112 bb->aux = loop;
4114 if (dump_file)
4116 fprintf (dump_file, ";; potential loop %d ending at\n",
4117 loop->loop_no);
4118 print_rtl_single (dump_file, tail);
4121 bfin_discover_loop (loop, bb, tail);
4125 tmp_bitmap = BITMAP_ALLOC (stack);
4126 /* Compute loop nestings. */
4127 for (loop = loops; loop; loop = loop->next)
4129 loop_info other;
4130 if (loop->bad)
4131 continue;
4133 for (other = loop->next; other; other = other->next)
4135 if (other->bad)
4136 continue;
4138 bitmap_and (tmp_bitmap, other->block_bitmap, loop->block_bitmap);
4139 if (bitmap_empty_p (tmp_bitmap))
4140 continue;
4141 if (bitmap_equal_p (tmp_bitmap, other->block_bitmap))
4143 other->outer = loop;
4144 VEC_safe_push (loop_info, heap, loop->loops, other);
4146 else if (bitmap_equal_p (tmp_bitmap, loop->block_bitmap))
4148 loop->outer = other;
4149 VEC_safe_push (loop_info, heap, other->loops, loop);
4151 else
4153 if (dump_file)
4154 fprintf (dump_file,
4155 ";; can't find suitable nesting for loops %d and %d\n",
4156 loop->loop_no, other->loop_no);
4157 loop->bad = other->bad = 1;
4161 BITMAP_FREE (tmp_bitmap);
4163 return loops;
4166 /* Free up the loop structures in LOOPS. */
4167 static void
4168 free_loops (loop_info loops)
4170 while (loops)
4172 loop_info loop = loops;
4173 loops = loop->next;
4174 VEC_free (loop_info, heap, loop->loops);
4175 VEC_free (basic_block, heap, loop->blocks);
4176 BITMAP_FREE (loop->block_bitmap);
4177 XDELETE (loop);
4181 #define BB_AUX_INDEX(BB) ((unsigned)(BB)->aux)
4183 /* The taken-branch edge from the loop end can actually go forward. Since the
4184 Blackfin's LSETUP instruction requires that the loop end be after the loop
4185 start, try to reorder a loop's basic blocks when we find such a case. */
4186 static void
4187 bfin_reorder_loops (loop_info loops, FILE *dump_file)
4189 basic_block bb;
4190 loop_info loop;
4192 FOR_EACH_BB (bb)
4193 bb->aux = NULL;
4194 cfg_layout_initialize (0);
4196 for (loop = loops; loop; loop = loop->next)
4198 unsigned index;
4199 basic_block bb;
4200 edge e;
4201 edge_iterator ei;
4203 if (loop->bad)
4204 continue;
4206 /* Recreate an index for basic blocks that represents their order. */
4207 for (bb = ENTRY_BLOCK_PTR->next_bb, index = 0;
4208 bb != EXIT_BLOCK_PTR;
4209 bb = bb->next_bb, index++)
4210 bb->aux = (PTR) index;
4212 if (BB_AUX_INDEX (loop->head) < BB_AUX_INDEX (loop->tail))
4213 continue;
4215 FOR_EACH_EDGE (e, ei, loop->head->succs)
4217 if (bitmap_bit_p (loop->block_bitmap, e->dest->index)
4218 && BB_AUX_INDEX (e->dest) < BB_AUX_INDEX (loop->tail))
4220 basic_block start_bb = e->dest;
4221 basic_block start_prev_bb = start_bb->prev_bb;
4223 if (dump_file)
4224 fprintf (dump_file, ";; Moving block %d before block %d\n",
4225 loop->head->index, start_bb->index);
4226 loop->head->prev_bb->next_bb = loop->head->next_bb;
4227 loop->head->next_bb->prev_bb = loop->head->prev_bb;
4229 loop->head->prev_bb = start_prev_bb;
4230 loop->head->next_bb = start_bb;
4231 start_prev_bb->next_bb = start_bb->prev_bb = loop->head;
4232 break;
4235 loops = loops->next;
4238 FOR_EACH_BB (bb)
4240 if (bb->next_bb != EXIT_BLOCK_PTR)
4241 bb->aux = bb->next_bb;
4242 else
4243 bb->aux = NULL;
4245 cfg_layout_finalize ();
4246 df_analyze ();
4249 /* Run from machine_dependent_reorg, this pass looks for doloop_end insns
4250 and tries to rewrite the RTL of these loops so that proper Blackfin
4251 hardware loops are generated. */
4253 static void
4254 bfin_reorg_loops (FILE *dump_file)
4256 loop_info loops = NULL;
4257 loop_info loop;
4258 basic_block bb;
4259 bitmap_obstack stack;
4261 bitmap_obstack_initialize (&stack);
4263 if (dump_file)
4264 fprintf (dump_file, ";; Find loops, first pass\n\n");
4266 loops = bfin_discover_loops (&stack, dump_file);
4268 if (dump_file)
4269 bfin_dump_loops (loops);
4271 bfin_reorder_loops (loops, dump_file);
4272 free_loops (loops);
4274 if (dump_file)
4275 fprintf (dump_file, ";; Find loops, second pass\n\n");
4277 loops = bfin_discover_loops (&stack, dump_file);
4278 if (dump_file)
4280 fprintf (dump_file, ";; All loops found:\n\n");
4281 bfin_dump_loops (loops);
4284 /* Now apply the optimizations. */
4285 for (loop = loops; loop; loop = loop->next)
4286 bfin_optimize_loop (loop);
4288 if (dump_file)
4290 fprintf (dump_file, ";; After hardware loops optimization:\n\n");
4291 bfin_dump_loops (loops);
4294 free_loops (loops);
4296 if (dump_file)
4297 print_rtl (dump_file, get_insns ());
4299 FOR_EACH_BB (bb)
4300 bb->aux = NULL;
4303 /* Possibly generate a SEQUENCE out of three insns found in SLOT.
4304 Returns true if we modified the insn chain, false otherwise. */
4305 static bool
4306 gen_one_bundle (rtx slot[3])
4308 gcc_assert (slot[1] != NULL_RTX);
4310 /* Verify that we really can do the multi-issue. */
4311 if (slot[0])
4313 rtx t = NEXT_INSN (slot[0]);
4314 while (t != slot[1])
4316 if (GET_CODE (t) != NOTE
4317 || NOTE_KIND (t) != NOTE_INSN_DELETED)
4318 return false;
4319 t = NEXT_INSN (t);
4322 if (slot[2])
4324 rtx t = NEXT_INSN (slot[1]);
4325 while (t != slot[2])
4327 if (GET_CODE (t) != NOTE
4328 || NOTE_KIND (t) != NOTE_INSN_DELETED)
4329 return false;
4330 t = NEXT_INSN (t);
4334 if (slot[0] == NULL_RTX)
4336 slot[0] = emit_insn_before (gen_mnop (), slot[1]);
4337 df_insn_rescan (slot[0]);
4339 if (slot[2] == NULL_RTX)
4341 slot[2] = emit_insn_after (gen_forced_nop (), slot[1]);
4342 df_insn_rescan (slot[2]);
4345 /* Avoid line number information being printed inside one bundle. */
4346 if (INSN_LOCATOR (slot[1])
4347 && INSN_LOCATOR (slot[1]) != INSN_LOCATOR (slot[0]))
4348 INSN_LOCATOR (slot[1]) = INSN_LOCATOR (slot[0]);
4349 if (INSN_LOCATOR (slot[2])
4350 && INSN_LOCATOR (slot[2]) != INSN_LOCATOR (slot[0]))
4351 INSN_LOCATOR (slot[2]) = INSN_LOCATOR (slot[0]);
4353 /* Terminate them with "|| " instead of ";" in the output. */
4354 PUT_MODE (slot[0], SImode);
4355 PUT_MODE (slot[1], SImode);
4356 /* Terminate the bundle, for the benefit of reorder_var_tracking_notes. */
4357 PUT_MODE (slot[2], QImode);
4358 return true;
4361 /* Go through all insns, and use the information generated during scheduling
4362 to generate SEQUENCEs to represent bundles of instructions issued
4363 simultaneously. */
4365 static void
4366 bfin_gen_bundles (void)
4368 basic_block bb;
4369 FOR_EACH_BB (bb)
4371 rtx insn, next;
4372 rtx slot[3];
4373 int n_filled = 0;
4375 slot[0] = slot[1] = slot[2] = NULL_RTX;
4376 for (insn = BB_HEAD (bb);; insn = next)
4378 int at_end;
4379 if (INSN_P (insn))
4381 if (get_attr_type (insn) == TYPE_DSP32)
4382 slot[0] = insn;
4383 else if (slot[1] == NULL_RTX)
4384 slot[1] = insn;
4385 else
4386 slot[2] = insn;
4387 n_filled++;
4390 next = NEXT_INSN (insn);
4391 while (next && insn != BB_END (bb)
4392 && !(INSN_P (next)
4393 && GET_CODE (PATTERN (next)) != USE
4394 && GET_CODE (PATTERN (next)) != CLOBBER))
4396 insn = next;
4397 next = NEXT_INSN (insn);
4400 /* BB_END can change due to emitting extra NOPs, so check here. */
4401 at_end = insn == BB_END (bb);
4402 if (at_end || GET_MODE (next) == TImode)
4404 if ((n_filled < 2
4405 || !gen_one_bundle (slot))
4406 && slot[0] != NULL_RTX)
4408 rtx pat = PATTERN (slot[0]);
4409 if (GET_CODE (pat) == SET
4410 && GET_CODE (SET_SRC (pat)) == UNSPEC
4411 && XINT (SET_SRC (pat), 1) == UNSPEC_32BIT)
4413 SET_SRC (pat) = XVECEXP (SET_SRC (pat), 0, 0);
4414 INSN_CODE (slot[0]) = -1;
4415 df_insn_rescan (slot[0]);
4418 n_filled = 0;
4419 slot[0] = slot[1] = slot[2] = NULL_RTX;
4421 if (at_end)
4422 break;
4427 /* Ensure that no var tracking notes are emitted in the middle of a
4428 three-instruction bundle. */
4430 static void
4431 reorder_var_tracking_notes (void)
4433 basic_block bb;
4434 FOR_EACH_BB (bb)
4436 rtx insn, next;
4437 rtx queue = NULL_RTX;
4438 bool in_bundle = false;
4440 for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = next)
4442 next = NEXT_INSN (insn);
4444 if (INSN_P (insn))
4446 /* Emit queued up notes at the last instruction of a bundle. */
4447 if (GET_MODE (insn) == QImode)
4449 while (queue)
4451 rtx next_queue = PREV_INSN (queue);
4452 PREV_INSN (NEXT_INSN (insn)) = queue;
4453 NEXT_INSN (queue) = NEXT_INSN (insn);
4454 NEXT_INSN (insn) = queue;
4455 PREV_INSN (queue) = insn;
4456 queue = next_queue;
4458 in_bundle = false;
4460 else if (GET_MODE (insn) == SImode)
4461 in_bundle = true;
4463 else if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION)
4465 if (in_bundle)
4467 rtx prev = PREV_INSN (insn);
4468 PREV_INSN (next) = prev;
4469 NEXT_INSN (prev) = next;
4471 PREV_INSN (insn) = queue;
4472 queue = insn;
4479 /* Return an insn type for INSN that can be used by the caller for anomaly
4480 workarounds. This differs from plain get_attr_type in that it handles
4481 SEQUENCEs. */
4483 static enum attr_type
4484 type_for_anomaly (rtx insn)
4486 rtx pat = PATTERN (insn);
4487 if (GET_CODE (pat) == SEQUENCE)
4489 enum attr_type t;
4490 t = get_attr_type (XVECEXP (pat, 0, 1));
4491 if (t == TYPE_MCLD)
4492 return t;
4493 t = get_attr_type (XVECEXP (pat, 0, 2));
4494 if (t == TYPE_MCLD)
4495 return t;
4496 return TYPE_MCST;
4498 else
4499 return get_attr_type (insn);
4502 /* Return nonzero if INSN contains any loads that may trap. It handles
4503 SEQUENCEs correctly. */
4505 static bool
4506 trapping_loads_p (rtx insn)
4508 rtx pat = PATTERN (insn);
4509 if (GET_CODE (pat) == SEQUENCE)
4511 enum attr_type t;
4512 t = get_attr_type (XVECEXP (pat, 0, 1));
4513 if (t == TYPE_MCLD
4514 && may_trap_p (SET_SRC (PATTERN (XVECEXP (pat, 0, 1)))))
4515 return true;
4516 t = get_attr_type (XVECEXP (pat, 0, 2));
4517 if (t == TYPE_MCLD
4518 && may_trap_p (SET_SRC (PATTERN (XVECEXP (pat, 0, 2)))))
4519 return true;
4520 return false;
4522 else
4523 return may_trap_p (SET_SRC (single_set (insn)));
4526 /* This function acts like NEXT_INSN, but is aware of three-insn bundles and
4527 skips all subsequent parallel instructions if INSN is the start of such
4528 a group. */
4529 static rtx
4530 find_next_insn_start (rtx insn)
4532 if (GET_MODE (insn) == SImode)
4534 while (GET_MODE (insn) != QImode)
4535 insn = NEXT_INSN (insn);
4537 return NEXT_INSN (insn);
4540 /* Return INSN if it is of TYPE_MCLD. Alternatively, if INSN is the start of
4541 a three-insn bundle, see if one of them is a load and return that if so.
4542 Return NULL_RTX if the insn does not contain loads. */
4543 static rtx
4544 find_load (rtx insn)
4546 if (get_attr_type (insn) == TYPE_MCLD)
4547 return insn;
4548 if (GET_MODE (insn) != SImode)
4549 return NULL_RTX;
4550 do {
4551 insn = NEXT_INSN (insn);
4552 if ((GET_MODE (insn) == SImode || GET_MODE (insn) == QImode)
4553 && get_attr_type (insn) == TYPE_MCLD)
4554 return insn;
4555 } while (GET_MODE (insn) != QImode);
4556 return NULL_RTX;
4559 /* We use the machine specific reorg pass for emitting CSYNC instructions
4560 after conditional branches as needed.
4562 The Blackfin is unusual in that a code sequence like
4563 if cc jump label
4564 r0 = (p0)
4565 may speculatively perform the load even if the condition isn't true. This
4566 happens for a branch that is predicted not taken, because the pipeline
4567 isn't flushed or stalled, so the early stages of the following instructions,
4568 which perform the memory reference, are allowed to execute before the
4569 jump condition is evaluated.
4570 Therefore, we must insert additional instructions in all places where this
4571 could lead to incorrect behavior. The manual recommends CSYNC, while
4572 VDSP seems to use NOPs (even though its corresponding compiler option is
4573 named CSYNC).
4575 When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
4576 When optimizing for size, we turn the branch into a predicted taken one.
4577 This may be slower due to mispredicts, but saves code size. */
4579 static void
4580 bfin_reorg (void)
4582 rtx insn, next;
4583 rtx last_condjump = NULL_RTX;
4584 int cycles_since_jump = INT_MAX;
4586 /* We are freeing block_for_insn in the toplev to keep compatibility
4587 with old MDEP_REORGS that are not CFG based. Recompute it now. */
4588 compute_bb_for_insn ();
4590 if (bfin_flag_schedule_insns2)
4592 splitting_for_sched = 1;
4593 split_all_insns ();
4594 splitting_for_sched = 0;
4596 timevar_push (TV_SCHED2);
4597 schedule_insns ();
4598 timevar_pop (TV_SCHED2);
4600 /* Examine the schedule and insert nops as necessary for 64-bit parallel
4601 instructions. */
4602 bfin_gen_bundles ();
4605 df_analyze ();
4607 /* Doloop optimization */
4608 if (cfun->machine->has_hardware_loops)
4609 bfin_reorg_loops (dump_file);
4611 if (! ENABLE_WA_SPECULATIVE_LOADS && ! ENABLE_WA_SPECULATIVE_SYNCS)
4612 return;
4614 /* First pass: find predicted-false branches; if something after them
4615 needs nops, insert them or change the branch to predict true. */
4616 for (insn = get_insns (); insn; insn = next)
4618 rtx pat;
4620 next = find_next_insn_start (insn);
4622 if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
4623 continue;
4625 pat = PATTERN (insn);
4626 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4627 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
4628 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
4629 continue;
4631 if (JUMP_P (insn))
4633 if (any_condjump_p (insn)
4634 && ! cbranch_predicted_taken_p (insn))
4636 last_condjump = insn;
4637 cycles_since_jump = 0;
4639 else
4640 cycles_since_jump = INT_MAX;
4642 else if (INSN_P (insn))
4644 rtx load_insn = find_load (insn);
4645 enum attr_type type = type_for_anomaly (insn);
4646 int delay_needed = 0;
4647 if (cycles_since_jump < INT_MAX)
4648 cycles_since_jump++;
4650 if (load_insn && ENABLE_WA_SPECULATIVE_LOADS)
4652 if (trapping_loads_p (load_insn))
4653 delay_needed = 3;
4655 else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS)
4656 delay_needed = 4;
4658 if (delay_needed > cycles_since_jump)
4660 rtx pat;
4661 int num_clobbers;
4662 rtx *op = recog_data.operand;
4664 delay_needed -= cycles_since_jump;
4666 extract_insn (last_condjump);
4667 if (optimize_size)
4669 pat = gen_cbranch_predicted_taken (op[0], op[1], op[2],
4670 op[3]);
4671 cycles_since_jump = INT_MAX;
4673 else
4674 /* Do not adjust cycles_since_jump in this case, so that
4675 we'll increase the number of NOPs for a subsequent insn
4676 if necessary. */
4677 pat = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
4678 GEN_INT (delay_needed));
4679 PATTERN (last_condjump) = pat;
4680 INSN_CODE (last_condjump) = recog (pat, insn, &num_clobbers);
4684 /* Second pass: for predicted-true branches, see if anything at the
4685 branch destination needs extra nops. */
4686 if (! ENABLE_WA_SPECULATIVE_SYNCS)
4687 return;
4689 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4691 if (JUMP_P (insn)
4692 && any_condjump_p (insn)
4693 && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken
4694 || cbranch_predicted_taken_p (insn)))
4696 rtx target = JUMP_LABEL (insn);
4697 rtx label = target;
4698 cycles_since_jump = 0;
4699 for (; target && cycles_since_jump < 3; target = NEXT_INSN (target))
4701 rtx pat;
4703 if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
4704 continue;
4706 pat = PATTERN (target);
4707 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4708 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
4709 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
4710 continue;
4712 if (INSN_P (target))
4714 enum attr_type type = type_for_anomaly (target);
4715 int delay_needed = 0;
4716 if (cycles_since_jump < INT_MAX)
4717 cycles_since_jump++;
4719 if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS)
4720 delay_needed = 2;
4722 if (delay_needed > cycles_since_jump)
4724 rtx prev = prev_real_insn (label);
4725 delay_needed -= cycles_since_jump;
4726 if (dump_file)
4727 fprintf (dump_file, "Adding %d nops after %d\n",
4728 delay_needed, INSN_UID (label));
4729 if (JUMP_P (prev)
4730 && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops)
4732 rtx x;
4733 HOST_WIDE_INT v;
4735 if (dump_file)
4736 fprintf (dump_file,
4737 "Reducing nops on insn %d.\n",
4738 INSN_UID (prev));
4739 x = PATTERN (prev);
4740 x = XVECEXP (x, 0, 1);
4741 v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed;
4742 XVECEXP (x, 0, 0) = GEN_INT (v);
4744 while (delay_needed-- > 0)
4745 emit_insn_after (gen_nop (), label);
4746 break;
4753 if (bfin_flag_var_tracking)
4755 timevar_push (TV_VAR_TRACKING);
4756 variable_tracking_main ();
4757 reorder_var_tracking_notes ();
4758 timevar_pop (TV_VAR_TRACKING);
4760 df_finish_pass (false);
4763 /* Handle interrupt_handler, exception_handler and nmi_handler function
4764 attributes; arguments as in struct attribute_spec.handler. */
4766 static tree
4767 handle_int_attribute (tree *node, tree name,
4768 tree args ATTRIBUTE_UNUSED,
4769 int flags ATTRIBUTE_UNUSED,
4770 bool *no_add_attrs)
4772 tree x = *node;
4773 if (TREE_CODE (x) == FUNCTION_DECL)
4774 x = TREE_TYPE (x);
4776 if (TREE_CODE (x) != FUNCTION_TYPE)
4778 warning (OPT_Wattributes, "%qs attribute only applies to functions",
4779 IDENTIFIER_POINTER (name));
4780 *no_add_attrs = true;
4782 else if (funkind (x) != SUBROUTINE)
4783 error ("multiple function type attributes specified");
4785 return NULL_TREE;
4788 /* Return 0 if the attributes for two types are incompatible, 1 if they
4789 are compatible, and 2 if they are nearly compatible (which causes a
4790 warning to be generated). */
4792 static int
4793 bfin_comp_type_attributes (const_tree type1, const_tree type2)
4795 e_funkind kind1, kind2;
4797 if (TREE_CODE (type1) != FUNCTION_TYPE)
4798 return 1;
4800 kind1 = funkind (type1);
4801 kind2 = funkind (type2);
4803 if (kind1 != kind2)
4804 return 0;
4806 /* Check for mismatched modifiers */
4807 if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
4808 != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
4809 return 0;
4811 if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
4812 != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
4813 return 0;
4815 if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
4816 != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
4817 return 0;
4819 if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1))
4820 != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2)))
4821 return 0;
4823 return 1;
4826 /* Handle a "longcall" or "shortcall" attribute; arguments as in
4827 struct attribute_spec.handler. */
4829 static tree
4830 bfin_handle_longcall_attribute (tree *node, tree name,
4831 tree args ATTRIBUTE_UNUSED,
4832 int flags ATTRIBUTE_UNUSED,
4833 bool *no_add_attrs)
4835 if (TREE_CODE (*node) != FUNCTION_TYPE
4836 && TREE_CODE (*node) != FIELD_DECL
4837 && TREE_CODE (*node) != TYPE_DECL)
4839 warning (OPT_Wattributes, "`%s' attribute only applies to functions",
4840 IDENTIFIER_POINTER (name));
4841 *no_add_attrs = true;
4844 if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0
4845 && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node)))
4846 || (strcmp (IDENTIFIER_POINTER (name), "shortcall") == 0
4847 && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node))))
4849 warning (OPT_Wattributes,
4850 "can't apply both longcall and shortcall attributes to the same function");
4851 *no_add_attrs = true;
4854 return NULL_TREE;
4857 /* Handle a "l1_text" attribute; arguments as in
4858 struct attribute_spec.handler. */
4860 static tree
4861 bfin_handle_l1_text_attribute (tree *node, tree name, tree ARG_UNUSED (args),
4862 int ARG_UNUSED (flags), bool *no_add_attrs)
4864 tree decl = *node;
4866 if (TREE_CODE (decl) != FUNCTION_DECL)
4868 error ("`%s' attribute only applies to functions",
4869 IDENTIFIER_POINTER (name));
4870 *no_add_attrs = true;
4873 /* The decl may have already been given a section attribute
4874 from a previous declaration. Ensure they match. */
4875 else if (DECL_SECTION_NAME (decl) != NULL_TREE
4876 && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
4877 ".l1.text") != 0)
4879 error ("section of %q+D conflicts with previous declaration",
4880 decl);
4881 *no_add_attrs = true;
4883 else
4884 DECL_SECTION_NAME (decl) = build_string (9, ".l1.text");
4886 return NULL_TREE;
4889 /* Handle a "l1_data", "l1_data_A" or "l1_data_B" attribute;
4890 arguments as in struct attribute_spec.handler. */
4892 static tree
4893 bfin_handle_l1_data_attribute (tree *node, tree name, tree ARG_UNUSED (args),
4894 int ARG_UNUSED (flags), bool *no_add_attrs)
4896 tree decl = *node;
4898 if (TREE_CODE (decl) != VAR_DECL)
4900 error ("`%s' attribute only applies to variables",
4901 IDENTIFIER_POINTER (name));
4902 *no_add_attrs = true;
4904 else if (current_function_decl != NULL_TREE
4905 && !TREE_STATIC (decl))
4907 error ("`%s' attribute cannot be specified for local variables",
4908 IDENTIFIER_POINTER (name));
4909 *no_add_attrs = true;
4911 else
4913 const char *section_name;
4915 if (strcmp (IDENTIFIER_POINTER (name), "l1_data") == 0)
4916 section_name = ".l1.data";
4917 else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_A") == 0)
4918 section_name = ".l1.data.A";
4919 else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_B") == 0)
4920 section_name = ".l1.data.B";
4921 else
4922 gcc_unreachable ();
4924 /* The decl may have already been given a section attribute
4925 from a previous declaration. Ensure they match. */
4926 if (DECL_SECTION_NAME (decl) != NULL_TREE
4927 && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
4928 section_name) != 0)
4930 error ("section of %q+D conflicts with previous declaration",
4931 decl);
4932 *no_add_attrs = true;
4934 else
4935 DECL_SECTION_NAME (decl)
4936 = build_string (strlen (section_name) + 1, section_name);
4939 return NULL_TREE;
4942 /* Table of valid machine attributes. */
4943 const struct attribute_spec bfin_attribute_table[] =
4945 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4946 { "interrupt_handler", 0, 0, false, true, true, handle_int_attribute },
4947 { "exception_handler", 0, 0, false, true, true, handle_int_attribute },
4948 { "nmi_handler", 0, 0, false, true, true, handle_int_attribute },
4949 { "nesting", 0, 0, false, true, true, NULL },
4950 { "kspisusp", 0, 0, false, true, true, NULL },
4951 { "saveall", 0, 0, false, true, true, NULL },
4952 { "longcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
4953 { "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
4954 { "l1_text", 0, 0, true, false, false, bfin_handle_l1_text_attribute },
4955 { "l1_data", 0, 0, true, false, false, bfin_handle_l1_data_attribute },
4956 { "l1_data_A", 0, 0, true, false, false, bfin_handle_l1_data_attribute },
4957 { "l1_data_B", 0, 0, true, false, false, bfin_handle_l1_data_attribute },
4958 { NULL, 0, 0, false, false, false, NULL }
4961 /* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to
4962 tell the assembler to generate pointers to function descriptors in
4963 some cases. */
4965 static bool
4966 bfin_assemble_integer (rtx value, unsigned int size, int aligned_p)
4968 if (TARGET_FDPIC && size == UNITS_PER_WORD)
4970 if (GET_CODE (value) == SYMBOL_REF
4971 && SYMBOL_REF_FUNCTION_P (value))
4973 fputs ("\t.picptr\tfuncdesc(", asm_out_file);
4974 output_addr_const (asm_out_file, value);
4975 fputs (")\n", asm_out_file);
4976 return true;
4978 if (!aligned_p)
4980 /* We've set the unaligned SI op to NULL, so we always have to
4981 handle the unaligned case here. */
4982 assemble_integer_with_op ("\t.4byte\t", value);
4983 return true;
4986 return default_assemble_integer (value, size, aligned_p);
4989 /* Output the assembler code for a thunk function. THUNK_DECL is the
4990 declaration for the thunk function itself, FUNCTION is the decl for
4991 the target function. DELTA is an immediate constant offset to be
4992 added to THIS. If VCALL_OFFSET is nonzero, the word at
4993 *(*this + vcall_offset) should be added to THIS. */
4995 static void
4996 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
4997 tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
4998 HOST_WIDE_INT vcall_offset, tree function)
5000 rtx xops[3];
5001 /* The this parameter is passed as the first argument. */
5002 rtx this = gen_rtx_REG (Pmode, REG_R0);
5004 /* Adjust the this parameter by a fixed constant. */
5005 if (delta)
5007 xops[1] = this;
5008 if (delta >= -64 && delta <= 63)
5010 xops[0] = GEN_INT (delta);
5011 output_asm_insn ("%1 += %0;", xops);
5013 else if (delta >= -128 && delta < -64)
5015 xops[0] = GEN_INT (delta + 64);
5016 output_asm_insn ("%1 += -64; %1 += %0;", xops);
5018 else if (delta > 63 && delta <= 126)
5020 xops[0] = GEN_INT (delta - 63);
5021 output_asm_insn ("%1 += 63; %1 += %0;", xops);
5023 else
5025 xops[0] = GEN_INT (delta);
5026 output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
5030 /* Adjust the this parameter by a value stored in the vtable. */
5031 if (vcall_offset)
5033 rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
5034 rtx tmp = gen_rtx_REG (Pmode, REG_R3);
5036 xops[1] = tmp;
5037 xops[2] = p2tmp;
5038 output_asm_insn ("%2 = r0; %2 = [%2];", xops);
5040 /* Adjust the this parameter. */
5041 xops[0] = gen_rtx_MEM (Pmode, plus_constant (p2tmp, vcall_offset));
5042 if (!memory_operand (xops[0], Pmode))
5044 rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
5045 xops[0] = GEN_INT (vcall_offset);
5046 xops[1] = tmp2;
5047 output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
5048 xops[0] = gen_rtx_MEM (Pmode, p2tmp);
5050 xops[2] = this;
5051 output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
5054 xops[0] = XEXP (DECL_RTL (function), 0);
5055 if (1 || !flag_pic || (*targetm.binds_local_p) (function))
5056 output_asm_insn ("jump.l\t%P0", xops);
5059 /* Codes for all the Blackfin builtins. */
5060 enum bfin_builtins
5062 BFIN_BUILTIN_CSYNC,
5063 BFIN_BUILTIN_SSYNC,
5064 BFIN_BUILTIN_ONES,
5065 BFIN_BUILTIN_COMPOSE_2X16,
5066 BFIN_BUILTIN_EXTRACTLO,
5067 BFIN_BUILTIN_EXTRACTHI,
5069 BFIN_BUILTIN_SSADD_2X16,
5070 BFIN_BUILTIN_SSSUB_2X16,
5071 BFIN_BUILTIN_SSADDSUB_2X16,
5072 BFIN_BUILTIN_SSSUBADD_2X16,
5073 BFIN_BUILTIN_MULT_2X16,
5074 BFIN_BUILTIN_MULTR_2X16,
5075 BFIN_BUILTIN_NEG_2X16,
5076 BFIN_BUILTIN_ABS_2X16,
5077 BFIN_BUILTIN_MIN_2X16,
5078 BFIN_BUILTIN_MAX_2X16,
5080 BFIN_BUILTIN_SSADD_1X16,
5081 BFIN_BUILTIN_SSSUB_1X16,
5082 BFIN_BUILTIN_MULT_1X16,
5083 BFIN_BUILTIN_MULTR_1X16,
5084 BFIN_BUILTIN_NORM_1X16,
5085 BFIN_BUILTIN_NEG_1X16,
5086 BFIN_BUILTIN_ABS_1X16,
5087 BFIN_BUILTIN_MIN_1X16,
5088 BFIN_BUILTIN_MAX_1X16,
5090 BFIN_BUILTIN_SUM_2X16,
5091 BFIN_BUILTIN_DIFFHL_2X16,
5092 BFIN_BUILTIN_DIFFLH_2X16,
5094 BFIN_BUILTIN_SSADD_1X32,
5095 BFIN_BUILTIN_SSSUB_1X32,
5096 BFIN_BUILTIN_NORM_1X32,
5097 BFIN_BUILTIN_ROUND_1X32,
5098 BFIN_BUILTIN_NEG_1X32,
5099 BFIN_BUILTIN_ABS_1X32,
5100 BFIN_BUILTIN_MIN_1X32,
5101 BFIN_BUILTIN_MAX_1X32,
5102 BFIN_BUILTIN_MULT_1X32,
5103 BFIN_BUILTIN_MULT_1X32X32,
5104 BFIN_BUILTIN_MULT_1X32X32NS,
5106 BFIN_BUILTIN_MULHISILL,
5107 BFIN_BUILTIN_MULHISILH,
5108 BFIN_BUILTIN_MULHISIHL,
5109 BFIN_BUILTIN_MULHISIHH,
5111 BFIN_BUILTIN_LSHIFT_1X16,
5112 BFIN_BUILTIN_LSHIFT_2X16,
5113 BFIN_BUILTIN_SSASHIFT_1X16,
5114 BFIN_BUILTIN_SSASHIFT_2X16,
5115 BFIN_BUILTIN_SSASHIFT_1X32,
5117 BFIN_BUILTIN_CPLX_MUL_16,
5118 BFIN_BUILTIN_CPLX_MAC_16,
5119 BFIN_BUILTIN_CPLX_MSU_16,
5121 BFIN_BUILTIN_CPLX_MUL_16_S40,
5122 BFIN_BUILTIN_CPLX_MAC_16_S40,
5123 BFIN_BUILTIN_CPLX_MSU_16_S40,
5125 BFIN_BUILTIN_CPLX_SQU,
5127 BFIN_BUILTIN_MAX
5130 #define def_builtin(NAME, TYPE, CODE) \
5131 do { \
5132 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
5133 NULL, NULL_TREE); \
5134 } while (0)
5136 /* Set up all builtin functions for this target. */
5137 static void
5138 bfin_init_builtins (void)
5140 tree V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
5141 tree void_ftype_void
5142 = build_function_type (void_type_node, void_list_node);
5143 tree short_ftype_short
5144 = build_function_type_list (short_integer_type_node, short_integer_type_node,
5145 NULL_TREE);
5146 tree short_ftype_int_int
5147 = build_function_type_list (short_integer_type_node, integer_type_node,
5148 integer_type_node, NULL_TREE);
5149 tree int_ftype_int_int
5150 = build_function_type_list (integer_type_node, integer_type_node,
5151 integer_type_node, NULL_TREE);
5152 tree int_ftype_int
5153 = build_function_type_list (integer_type_node, integer_type_node,
5154 NULL_TREE);
5155 tree short_ftype_int
5156 = build_function_type_list (short_integer_type_node, integer_type_node,
5157 NULL_TREE);
5158 tree int_ftype_v2hi_v2hi
5159 = build_function_type_list (integer_type_node, V2HI_type_node,
5160 V2HI_type_node, NULL_TREE);
5161 tree v2hi_ftype_v2hi_v2hi
5162 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5163 V2HI_type_node, NULL_TREE);
5164 tree v2hi_ftype_v2hi_v2hi_v2hi
5165 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5166 V2HI_type_node, V2HI_type_node, NULL_TREE);
5167 tree v2hi_ftype_int_int
5168 = build_function_type_list (V2HI_type_node, integer_type_node,
5169 integer_type_node, NULL_TREE);
5170 tree v2hi_ftype_v2hi_int
5171 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5172 integer_type_node, NULL_TREE);
5173 tree int_ftype_short_short
5174 = build_function_type_list (integer_type_node, short_integer_type_node,
5175 short_integer_type_node, NULL_TREE);
5176 tree v2hi_ftype_v2hi
5177 = build_function_type_list (V2HI_type_node, V2HI_type_node, NULL_TREE);
5178 tree short_ftype_v2hi
5179 = build_function_type_list (short_integer_type_node, V2HI_type_node,
5180 NULL_TREE);
5182 /* Add the remaining MMX insns with somewhat more complicated types. */
5183 def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC);
5184 def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC);
5186 def_builtin ("__builtin_bfin_ones", short_ftype_int, BFIN_BUILTIN_ONES);
5188 def_builtin ("__builtin_bfin_compose_2x16", v2hi_ftype_int_int,
5189 BFIN_BUILTIN_COMPOSE_2X16);
5190 def_builtin ("__builtin_bfin_extract_hi", short_ftype_v2hi,
5191 BFIN_BUILTIN_EXTRACTHI);
5192 def_builtin ("__builtin_bfin_extract_lo", short_ftype_v2hi,
5193 BFIN_BUILTIN_EXTRACTLO);
5195 def_builtin ("__builtin_bfin_min_fr2x16", v2hi_ftype_v2hi_v2hi,
5196 BFIN_BUILTIN_MIN_2X16);
5197 def_builtin ("__builtin_bfin_max_fr2x16", v2hi_ftype_v2hi_v2hi,
5198 BFIN_BUILTIN_MAX_2X16);
5200 def_builtin ("__builtin_bfin_add_fr2x16", v2hi_ftype_v2hi_v2hi,
5201 BFIN_BUILTIN_SSADD_2X16);
5202 def_builtin ("__builtin_bfin_sub_fr2x16", v2hi_ftype_v2hi_v2hi,
5203 BFIN_BUILTIN_SSSUB_2X16);
5204 def_builtin ("__builtin_bfin_dspaddsubsat", v2hi_ftype_v2hi_v2hi,
5205 BFIN_BUILTIN_SSADDSUB_2X16);
5206 def_builtin ("__builtin_bfin_dspsubaddsat", v2hi_ftype_v2hi_v2hi,
5207 BFIN_BUILTIN_SSSUBADD_2X16);
5208 def_builtin ("__builtin_bfin_mult_fr2x16", v2hi_ftype_v2hi_v2hi,
5209 BFIN_BUILTIN_MULT_2X16);
5210 def_builtin ("__builtin_bfin_multr_fr2x16", v2hi_ftype_v2hi_v2hi,
5211 BFIN_BUILTIN_MULTR_2X16);
5212 def_builtin ("__builtin_bfin_negate_fr2x16", v2hi_ftype_v2hi,
5213 BFIN_BUILTIN_NEG_2X16);
5214 def_builtin ("__builtin_bfin_abs_fr2x16", v2hi_ftype_v2hi,
5215 BFIN_BUILTIN_ABS_2X16);
5217 def_builtin ("__builtin_bfin_min_fr1x16", short_ftype_int_int,
5218 BFIN_BUILTIN_MIN_1X16);
5219 def_builtin ("__builtin_bfin_max_fr1x16", short_ftype_int_int,
5220 BFIN_BUILTIN_MAX_1X16);
5222 def_builtin ("__builtin_bfin_add_fr1x16", short_ftype_int_int,
5223 BFIN_BUILTIN_SSADD_1X16);
5224 def_builtin ("__builtin_bfin_sub_fr1x16", short_ftype_int_int,
5225 BFIN_BUILTIN_SSSUB_1X16);
5226 def_builtin ("__builtin_bfin_mult_fr1x16", short_ftype_int_int,
5227 BFIN_BUILTIN_MULT_1X16);
5228 def_builtin ("__builtin_bfin_multr_fr1x16", short_ftype_int_int,
5229 BFIN_BUILTIN_MULTR_1X16);
5230 def_builtin ("__builtin_bfin_negate_fr1x16", short_ftype_short,
5231 BFIN_BUILTIN_NEG_1X16);
5232 def_builtin ("__builtin_bfin_abs_fr1x16", short_ftype_short,
5233 BFIN_BUILTIN_ABS_1X16);
5234 def_builtin ("__builtin_bfin_norm_fr1x16", short_ftype_int,
5235 BFIN_BUILTIN_NORM_1X16);
5237 def_builtin ("__builtin_bfin_sum_fr2x16", short_ftype_v2hi,
5238 BFIN_BUILTIN_SUM_2X16);
5239 def_builtin ("__builtin_bfin_diff_hl_fr2x16", short_ftype_v2hi,
5240 BFIN_BUILTIN_DIFFHL_2X16);
5241 def_builtin ("__builtin_bfin_diff_lh_fr2x16", short_ftype_v2hi,
5242 BFIN_BUILTIN_DIFFLH_2X16);
5244 def_builtin ("__builtin_bfin_mulhisill", int_ftype_v2hi_v2hi,
5245 BFIN_BUILTIN_MULHISILL);
5246 def_builtin ("__builtin_bfin_mulhisihl", int_ftype_v2hi_v2hi,
5247 BFIN_BUILTIN_MULHISIHL);
5248 def_builtin ("__builtin_bfin_mulhisilh", int_ftype_v2hi_v2hi,
5249 BFIN_BUILTIN_MULHISILH);
5250 def_builtin ("__builtin_bfin_mulhisihh", int_ftype_v2hi_v2hi,
5251 BFIN_BUILTIN_MULHISIHH);
5253 def_builtin ("__builtin_bfin_min_fr1x32", int_ftype_int_int,
5254 BFIN_BUILTIN_MIN_1X32);
5255 def_builtin ("__builtin_bfin_max_fr1x32", int_ftype_int_int,
5256 BFIN_BUILTIN_MAX_1X32);
5258 def_builtin ("__builtin_bfin_add_fr1x32", int_ftype_int_int,
5259 BFIN_BUILTIN_SSADD_1X32);
5260 def_builtin ("__builtin_bfin_sub_fr1x32", int_ftype_int_int,
5261 BFIN_BUILTIN_SSSUB_1X32);
5262 def_builtin ("__builtin_bfin_negate_fr1x32", int_ftype_int,
5263 BFIN_BUILTIN_NEG_1X32);
5264 def_builtin ("__builtin_bfin_abs_fr1x32", int_ftype_int,
5265 BFIN_BUILTIN_ABS_1X32);
5266 def_builtin ("__builtin_bfin_norm_fr1x32", short_ftype_int,
5267 BFIN_BUILTIN_NORM_1X32);
5268 def_builtin ("__builtin_bfin_round_fr1x32", short_ftype_int,
5269 BFIN_BUILTIN_ROUND_1X32);
5270 def_builtin ("__builtin_bfin_mult_fr1x32", int_ftype_short_short,
5271 BFIN_BUILTIN_MULT_1X32);
5272 def_builtin ("__builtin_bfin_mult_fr1x32x32", int_ftype_int_int,
5273 BFIN_BUILTIN_MULT_1X32X32);
5274 def_builtin ("__builtin_bfin_mult_fr1x32x32NS", int_ftype_int_int,
5275 BFIN_BUILTIN_MULT_1X32X32NS);
5277 /* Shifts. */
5278 def_builtin ("__builtin_bfin_shl_fr1x16", short_ftype_int_int,
5279 BFIN_BUILTIN_SSASHIFT_1X16);
5280 def_builtin ("__builtin_bfin_shl_fr2x16", v2hi_ftype_v2hi_int,
5281 BFIN_BUILTIN_SSASHIFT_2X16);
5282 def_builtin ("__builtin_bfin_lshl_fr1x16", short_ftype_int_int,
5283 BFIN_BUILTIN_LSHIFT_1X16);
5284 def_builtin ("__builtin_bfin_lshl_fr2x16", v2hi_ftype_v2hi_int,
5285 BFIN_BUILTIN_LSHIFT_2X16);
5286 def_builtin ("__builtin_bfin_shl_fr1x32", int_ftype_int_int,
5287 BFIN_BUILTIN_SSASHIFT_1X32);
5289 /* Complex numbers. */
5290 def_builtin ("__builtin_bfin_cmplx_add", v2hi_ftype_v2hi_v2hi,
5291 BFIN_BUILTIN_SSADD_2X16);
5292 def_builtin ("__builtin_bfin_cmplx_sub", v2hi_ftype_v2hi_v2hi,
5293 BFIN_BUILTIN_SSSUB_2X16);
5294 def_builtin ("__builtin_bfin_cmplx_mul", v2hi_ftype_v2hi_v2hi,
5295 BFIN_BUILTIN_CPLX_MUL_16);
5296 def_builtin ("__builtin_bfin_cmplx_mac", v2hi_ftype_v2hi_v2hi_v2hi,
5297 BFIN_BUILTIN_CPLX_MAC_16);
5298 def_builtin ("__builtin_bfin_cmplx_msu", v2hi_ftype_v2hi_v2hi_v2hi,
5299 BFIN_BUILTIN_CPLX_MSU_16);
5300 def_builtin ("__builtin_bfin_cmplx_mul_s40", v2hi_ftype_v2hi_v2hi,
5301 BFIN_BUILTIN_CPLX_MUL_16_S40);
5302 def_builtin ("__builtin_bfin_cmplx_mac_s40", v2hi_ftype_v2hi_v2hi_v2hi,
5303 BFIN_BUILTIN_CPLX_MAC_16_S40);
5304 def_builtin ("__builtin_bfin_cmplx_msu_s40", v2hi_ftype_v2hi_v2hi_v2hi,
5305 BFIN_BUILTIN_CPLX_MSU_16_S40);
5306 def_builtin ("__builtin_bfin_csqu_fr16", v2hi_ftype_v2hi,
5307 BFIN_BUILTIN_CPLX_SQU);
5311 struct builtin_description
5313 const enum insn_code icode;
5314 const char *const name;
5315 const enum bfin_builtins code;
5316 int macflag;
5319 static const struct builtin_description bdesc_2arg[] =
5321 { CODE_FOR_composev2hi, "__builtin_bfin_compose_2x16", BFIN_BUILTIN_COMPOSE_2X16, -1 },
5323 { CODE_FOR_ssashiftv2hi3, "__builtin_bfin_shl_fr2x16", BFIN_BUILTIN_SSASHIFT_2X16, -1 },
5324 { CODE_FOR_ssashifthi3, "__builtin_bfin_shl_fr1x16", BFIN_BUILTIN_SSASHIFT_1X16, -1 },
5325 { CODE_FOR_lshiftv2hi3, "__builtin_bfin_lshl_fr2x16", BFIN_BUILTIN_LSHIFT_2X16, -1 },
5326 { CODE_FOR_lshifthi3, "__builtin_bfin_lshl_fr1x16", BFIN_BUILTIN_LSHIFT_1X16, -1 },
5327 { CODE_FOR_ssashiftsi3, "__builtin_bfin_shl_fr1x32", BFIN_BUILTIN_SSASHIFT_1X32, -1 },
5329 { CODE_FOR_sminhi3, "__builtin_bfin_min_fr1x16", BFIN_BUILTIN_MIN_1X16, -1 },
5330 { CODE_FOR_smaxhi3, "__builtin_bfin_max_fr1x16", BFIN_BUILTIN_MAX_1X16, -1 },
5331 { CODE_FOR_ssaddhi3, "__builtin_bfin_add_fr1x16", BFIN_BUILTIN_SSADD_1X16, -1 },
5332 { CODE_FOR_sssubhi3, "__builtin_bfin_sub_fr1x16", BFIN_BUILTIN_SSSUB_1X16, -1 },
5334 { CODE_FOR_sminsi3, "__builtin_bfin_min_fr1x32", BFIN_BUILTIN_MIN_1X32, -1 },
5335 { CODE_FOR_smaxsi3, "__builtin_bfin_max_fr1x32", BFIN_BUILTIN_MAX_1X32, -1 },
5336 { CODE_FOR_ssaddsi3, "__builtin_bfin_add_fr1x32", BFIN_BUILTIN_SSADD_1X32, -1 },
5337 { CODE_FOR_sssubsi3, "__builtin_bfin_sub_fr1x32", BFIN_BUILTIN_SSSUB_1X32, -1 },
5339 { CODE_FOR_sminv2hi3, "__builtin_bfin_min_fr2x16", BFIN_BUILTIN_MIN_2X16, -1 },
5340 { CODE_FOR_smaxv2hi3, "__builtin_bfin_max_fr2x16", BFIN_BUILTIN_MAX_2X16, -1 },
5341 { CODE_FOR_ssaddv2hi3, "__builtin_bfin_add_fr2x16", BFIN_BUILTIN_SSADD_2X16, -1 },
5342 { CODE_FOR_sssubv2hi3, "__builtin_bfin_sub_fr2x16", BFIN_BUILTIN_SSSUB_2X16, -1 },
5343 { CODE_FOR_ssaddsubv2hi3, "__builtin_bfin_dspaddsubsat", BFIN_BUILTIN_SSADDSUB_2X16, -1 },
5344 { CODE_FOR_sssubaddv2hi3, "__builtin_bfin_dspsubaddsat", BFIN_BUILTIN_SSSUBADD_2X16, -1 },
5346 { CODE_FOR_flag_mulhisi, "__builtin_bfin_mult_fr1x32", BFIN_BUILTIN_MULT_1X32, MACFLAG_NONE },
5347 { CODE_FOR_flag_mulhi, "__builtin_bfin_mult_fr1x16", BFIN_BUILTIN_MULT_1X16, MACFLAG_T },
5348 { CODE_FOR_flag_mulhi, "__builtin_bfin_multr_fr1x16", BFIN_BUILTIN_MULTR_1X16, MACFLAG_NONE },
5349 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_mult_fr2x16", BFIN_BUILTIN_MULT_2X16, MACFLAG_T },
5350 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_multr_fr2x16", BFIN_BUILTIN_MULTR_2X16, MACFLAG_NONE }
5353 static const struct builtin_description bdesc_1arg[] =
5355 { CODE_FOR_ones, "__builtin_bfin_ones", BFIN_BUILTIN_ONES, 0 },
5357 { CODE_FOR_signbitshi2, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16, 0 },
5358 { CODE_FOR_ssneghi2, "__builtin_bfin_negate_fr1x16", BFIN_BUILTIN_NEG_1X16, 0 },
5359 { CODE_FOR_abshi2, "__builtin_bfin_abs_fr1x16", BFIN_BUILTIN_ABS_1X16, 0 },
5361 { CODE_FOR_signbitssi2, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32, 0 },
5362 { CODE_FOR_ssroundsi2, "__builtin_bfin_round_fr1x32", BFIN_BUILTIN_ROUND_1X32, 0 },
5363 { CODE_FOR_ssnegsi2, "__builtin_bfin_negate_fr1x32", BFIN_BUILTIN_NEG_1X32, 0 },
5364 { CODE_FOR_ssabssi2, "__builtin_bfin_abs_fr1x32", BFIN_BUILTIN_ABS_1X32, 0 },
5366 { CODE_FOR_movv2hi_hi_low, "__builtin_bfin_extract_lo", BFIN_BUILTIN_EXTRACTLO, 0 },
5367 { CODE_FOR_movv2hi_hi_high, "__builtin_bfin_extract_hi", BFIN_BUILTIN_EXTRACTHI, 0 },
5368 { CODE_FOR_ssnegv2hi2, "__builtin_bfin_negate_fr2x16", BFIN_BUILTIN_NEG_2X16, 0 },
5369 { CODE_FOR_ssabsv2hi2, "__builtin_bfin_abs_fr2x16", BFIN_BUILTIN_ABS_2X16, 0 }
5372 /* Errors in the source file can cause expand_expr to return const0_rtx
5373 where we expect a vector. To avoid crashing, use one of the vector
5374 clear instructions. */
5375 static rtx
5376 safe_vector_operand (rtx x, enum machine_mode mode)
5378 if (x != const0_rtx)
5379 return x;
5380 x = gen_reg_rtx (SImode);
5382 emit_insn (gen_movsi (x, CONST0_RTX (SImode)));
5383 return gen_lowpart (mode, x);
5386 /* Subroutine of bfin_expand_builtin to take care of binop insns. MACFLAG is -1
5387 if this is a normal binary op, or one of the MACFLAG_xxx constants. */
5389 static rtx
5390 bfin_expand_binop_builtin (enum insn_code icode, tree exp, rtx target,
5391 int macflag)
5393 rtx pat;
5394 tree arg0 = CALL_EXPR_ARG (exp, 0);
5395 tree arg1 = CALL_EXPR_ARG (exp, 1);
5396 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5397 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
5398 enum machine_mode op0mode = GET_MODE (op0);
5399 enum machine_mode op1mode = GET_MODE (op1);
5400 enum machine_mode tmode = insn_data[icode].operand[0].mode;
5401 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
5402 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
5404 if (VECTOR_MODE_P (mode0))
5405 op0 = safe_vector_operand (op0, mode0);
5406 if (VECTOR_MODE_P (mode1))
5407 op1 = safe_vector_operand (op1, mode1);
5409 if (! target
5410 || GET_MODE (target) != tmode
5411 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5412 target = gen_reg_rtx (tmode);
5414 if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode)
5416 op0mode = HImode;
5417 op0 = gen_lowpart (HImode, op0);
5419 if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode)
5421 op1mode = HImode;
5422 op1 = gen_lowpart (HImode, op1);
5424 /* In case the insn wants input operands in modes different from
5425 the result, abort. */
5426 gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
5427 && (op1mode == mode1 || op1mode == VOIDmode));
5429 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5430 op0 = copy_to_mode_reg (mode0, op0);
5431 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
5432 op1 = copy_to_mode_reg (mode1, op1);
5434 if (macflag == -1)
5435 pat = GEN_FCN (icode) (target, op0, op1);
5436 else
5437 pat = GEN_FCN (icode) (target, op0, op1, GEN_INT (macflag));
5438 if (! pat)
5439 return 0;
5441 emit_insn (pat);
5442 return target;
5445 /* Subroutine of bfin_expand_builtin to take care of unop insns. */
5447 static rtx
5448 bfin_expand_unop_builtin (enum insn_code icode, tree exp,
5449 rtx target)
5451 rtx pat;
5452 tree arg0 = CALL_EXPR_ARG (exp, 0);
5453 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5454 enum machine_mode op0mode = GET_MODE (op0);
5455 enum machine_mode tmode = insn_data[icode].operand[0].mode;
5456 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
5458 if (! target
5459 || GET_MODE (target) != tmode
5460 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5461 target = gen_reg_rtx (tmode);
5463 if (VECTOR_MODE_P (mode0))
5464 op0 = safe_vector_operand (op0, mode0);
5466 if (op0mode == SImode && mode0 == HImode)
5468 op0mode = HImode;
5469 op0 = gen_lowpart (HImode, op0);
5471 gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
5473 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5474 op0 = copy_to_mode_reg (mode0, op0);
5476 pat = GEN_FCN (icode) (target, op0);
5477 if (! pat)
5478 return 0;
5479 emit_insn (pat);
5480 return target;
5483 /* Expand an expression EXP that calls a built-in function,
5484 with result going to TARGET if that's convenient
5485 (and in mode MODE if that's convenient).
5486 SUBTARGET may be used as the target for computing one of EXP's operands.
5487 IGNORE is nonzero if the value is to be ignored. */
5489 static rtx
5490 bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
5491 rtx subtarget ATTRIBUTE_UNUSED,
5492 enum machine_mode mode ATTRIBUTE_UNUSED,
5493 int ignore ATTRIBUTE_UNUSED)
5495 size_t i;
5496 enum insn_code icode;
5497 const struct builtin_description *d;
5498 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
5499 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
5500 tree arg0, arg1, arg2;
5501 rtx op0, op1, op2, accvec, pat, tmp1, tmp2, a0reg, a1reg;
5502 enum machine_mode tmode, mode0;
5504 switch (fcode)
5506 case BFIN_BUILTIN_CSYNC:
5507 emit_insn (gen_csync ());
5508 return 0;
5509 case BFIN_BUILTIN_SSYNC:
5510 emit_insn (gen_ssync ());
5511 return 0;
5513 case BFIN_BUILTIN_DIFFHL_2X16:
5514 case BFIN_BUILTIN_DIFFLH_2X16:
5515 case BFIN_BUILTIN_SUM_2X16:
5516 arg0 = CALL_EXPR_ARG (exp, 0);
5517 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5518 icode = (fcode == BFIN_BUILTIN_DIFFHL_2X16 ? CODE_FOR_subhilov2hi3
5519 : fcode == BFIN_BUILTIN_DIFFLH_2X16 ? CODE_FOR_sublohiv2hi3
5520 : CODE_FOR_ssaddhilov2hi3);
5521 tmode = insn_data[icode].operand[0].mode;
5522 mode0 = insn_data[icode].operand[1].mode;
5524 if (! target
5525 || GET_MODE (target) != tmode
5526 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5527 target = gen_reg_rtx (tmode);
5529 if (VECTOR_MODE_P (mode0))
5530 op0 = safe_vector_operand (op0, mode0);
5532 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5533 op0 = copy_to_mode_reg (mode0, op0);
5535 pat = GEN_FCN (icode) (target, op0, op0);
5536 if (! pat)
5537 return 0;
5538 emit_insn (pat);
5539 return target;
5541 case BFIN_BUILTIN_MULT_1X32X32:
5542 case BFIN_BUILTIN_MULT_1X32X32NS:
5543 arg0 = CALL_EXPR_ARG (exp, 0);
5544 arg1 = CALL_EXPR_ARG (exp, 1);
5545 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5546 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
5547 if (! target
5548 || !register_operand (target, SImode))
5549 target = gen_reg_rtx (SImode);
5551 a1reg = gen_rtx_REG (PDImode, REG_A1);
5552 a0reg = gen_rtx_REG (PDImode, REG_A0);
5553 tmp1 = gen_lowpart (V2HImode, op0);
5554 tmp2 = gen_lowpart (V2HImode, op1);
5555 emit_insn (gen_flag_macinit1hi (a1reg,
5556 gen_lowpart (HImode, op0),
5557 gen_lowpart (HImode, op1),
5558 GEN_INT (MACFLAG_FU)));
5559 emit_insn (gen_lshrpdi3 (a1reg, a1reg, GEN_INT (16)));
5561 if (fcode == BFIN_BUILTIN_MULT_1X32X32)
5562 emit_insn (gen_flag_mul_macv2hi_parts_acconly (a0reg, a1reg, tmp1, tmp2,
5563 const1_rtx, const1_rtx,
5564 const1_rtx, const0_rtx, a1reg,
5565 const0_rtx, GEN_INT (MACFLAG_NONE),
5566 GEN_INT (MACFLAG_M)));
5567 else
5569 /* For saturating multiplication, there's exactly one special case
5570 to be handled: multiplying the smallest negative value with
5571 itself. Due to shift correction in fractional multiplies, this
5572 can overflow. Iff this happens, OP2 will contain 1, which, when
5573 added in 32 bits to the smallest negative, wraps to the largest
5574 positive, which is the result we want. */
5575 op2 = gen_reg_rtx (V2HImode);
5576 emit_insn (gen_packv2hi (op2, tmp1, tmp2, const0_rtx, const0_rtx));
5577 emit_insn (gen_movsibi (gen_rtx_REG (BImode, REG_CC),
5578 gen_lowpart (SImode, op2)));
5579 emit_insn (gen_flag_mul_macv2hi_parts_acconly_andcc0 (a0reg, a1reg, tmp1, tmp2,
5580 const1_rtx, const1_rtx,
5581 const1_rtx, const0_rtx, a1reg,
5582 const0_rtx, GEN_INT (MACFLAG_NONE),
5583 GEN_INT (MACFLAG_M)));
5584 op2 = gen_reg_rtx (SImode);
5585 emit_insn (gen_movbisi (op2, gen_rtx_REG (BImode, REG_CC)));
5587 emit_insn (gen_flag_machi_parts_acconly (a1reg, tmp2, tmp1,
5588 const1_rtx, const0_rtx,
5589 a1reg, const0_rtx, GEN_INT (MACFLAG_M)));
5590 emit_insn (gen_ashrpdi3 (a1reg, a1reg, GEN_INT (15)));
5591 emit_insn (gen_sum_of_accumulators (target, a0reg, a0reg, a1reg));
5592 if (fcode == BFIN_BUILTIN_MULT_1X32X32NS)
5593 emit_insn (gen_addsi3 (target, target, op2));
5594 return target;
5596 case BFIN_BUILTIN_CPLX_MUL_16:
5597 case BFIN_BUILTIN_CPLX_MUL_16_S40:
5598 arg0 = CALL_EXPR_ARG (exp, 0);
5599 arg1 = CALL_EXPR_ARG (exp, 1);
5600 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5601 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
5602 accvec = gen_reg_rtx (V2PDImode);
5604 if (! target
5605 || GET_MODE (target) != V2HImode
5606 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5607 target = gen_reg_rtx (tmode);
5608 if (! register_operand (op0, GET_MODE (op0)))
5609 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
5610 if (! register_operand (op1, GET_MODE (op1)))
5611 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
5613 if (fcode == BFIN_BUILTIN_CPLX_MUL_16)
5614 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
5615 const0_rtx, const0_rtx,
5616 const1_rtx, GEN_INT (MACFLAG_W32)));
5617 else
5618 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
5619 const0_rtx, const0_rtx,
5620 const1_rtx, GEN_INT (MACFLAG_NONE)));
5621 emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
5622 const1_rtx, const1_rtx,
5623 const0_rtx, accvec, const1_rtx, const0_rtx,
5624 GEN_INT (MACFLAG_NONE), accvec));
5626 return target;
5628 case BFIN_BUILTIN_CPLX_MAC_16:
5629 case BFIN_BUILTIN_CPLX_MSU_16:
5630 case BFIN_BUILTIN_CPLX_MAC_16_S40:
5631 case BFIN_BUILTIN_CPLX_MSU_16_S40:
5632 arg0 = CALL_EXPR_ARG (exp, 0);
5633 arg1 = CALL_EXPR_ARG (exp, 1);
5634 arg2 = CALL_EXPR_ARG (exp, 2);
5635 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5636 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
5637 op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
5638 accvec = gen_reg_rtx (V2PDImode);
5640 if (! target
5641 || GET_MODE (target) != V2HImode
5642 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5643 target = gen_reg_rtx (tmode);
5644 if (! register_operand (op1, GET_MODE (op1)))
5645 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
5646 if (! register_operand (op2, GET_MODE (op2)))
5647 op2 = copy_to_mode_reg (GET_MODE (op2), op2);
5649 tmp1 = gen_reg_rtx (SImode);
5650 tmp2 = gen_reg_rtx (SImode);
5651 emit_insn (gen_ashlsi3 (tmp1, gen_lowpart (SImode, op0), GEN_INT (16)));
5652 emit_move_insn (tmp2, gen_lowpart (SImode, op0));
5653 emit_insn (gen_movstricthi_1 (gen_lowpart (HImode, tmp2), const0_rtx));
5654 emit_insn (gen_load_accumulator_pair (accvec, tmp1, tmp2));
5655 if (fcode == BFIN_BUILTIN_CPLX_MAC_16
5656 || fcode == BFIN_BUILTIN_CPLX_MSU_16)
5657 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx,
5658 const0_rtx, const0_rtx,
5659 const1_rtx, accvec, const0_rtx,
5660 const0_rtx,
5661 GEN_INT (MACFLAG_W32)));
5662 else
5663 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx,
5664 const0_rtx, const0_rtx,
5665 const1_rtx, accvec, const0_rtx,
5666 const0_rtx,
5667 GEN_INT (MACFLAG_NONE)));
5668 if (fcode == BFIN_BUILTIN_CPLX_MAC_16
5669 || fcode == BFIN_BUILTIN_CPLX_MAC_16_S40)
5671 tmp1 = const1_rtx;
5672 tmp2 = const0_rtx;
5674 else
5676 tmp1 = const0_rtx;
5677 tmp2 = const1_rtx;
5679 emit_insn (gen_flag_macv2hi_parts (target, op1, op2, const1_rtx,
5680 const1_rtx, const1_rtx,
5681 const0_rtx, accvec, tmp1, tmp2,
5682 GEN_INT (MACFLAG_NONE), accvec));
5684 return target;
5686 case BFIN_BUILTIN_CPLX_SQU:
5687 arg0 = CALL_EXPR_ARG (exp, 0);
5688 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5689 accvec = gen_reg_rtx (V2PDImode);
5690 icode = CODE_FOR_flag_mulv2hi;
5691 tmp1 = gen_reg_rtx (V2HImode);
5692 tmp2 = gen_reg_rtx (V2HImode);
5694 if (! target
5695 || GET_MODE (target) != V2HImode
5696 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5697 target = gen_reg_rtx (V2HImode);
5698 if (! register_operand (op0, GET_MODE (op0)))
5699 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
5701 emit_insn (gen_flag_mulv2hi (tmp1, op0, op0, GEN_INT (MACFLAG_NONE)));
5703 emit_insn (gen_flag_mulhi_parts (tmp2, op0, op0, const0_rtx,
5704 const0_rtx, const1_rtx,
5705 GEN_INT (MACFLAG_NONE)));
5707 emit_insn (gen_ssaddhi3_parts (target, tmp2, tmp2, const1_rtx,
5708 const0_rtx, const0_rtx));
5710 emit_insn (gen_sssubhi3_parts (target, tmp1, tmp1, const0_rtx,
5711 const0_rtx, const1_rtx));
5713 return target;
5715 default:
5716 break;
5719 for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
5720 if (d->code == fcode)
5721 return bfin_expand_binop_builtin (d->icode, exp, target,
5722 d->macflag);
5724 for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
5725 if (d->code == fcode)
5726 return bfin_expand_unop_builtin (d->icode, exp, target);
5728 gcc_unreachable ();
5731 #undef TARGET_INIT_BUILTINS
5732 #define TARGET_INIT_BUILTINS bfin_init_builtins
5734 #undef TARGET_EXPAND_BUILTIN
5735 #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
5737 #undef TARGET_ASM_GLOBALIZE_LABEL
5738 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label
5740 #undef TARGET_ASM_FILE_START
5741 #define TARGET_ASM_FILE_START output_file_start
5743 #undef TARGET_ATTRIBUTE_TABLE
5744 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
5746 #undef TARGET_COMP_TYPE_ATTRIBUTES
5747 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
5749 #undef TARGET_RTX_COSTS
5750 #define TARGET_RTX_COSTS bfin_rtx_costs
5752 #undef TARGET_ADDRESS_COST
5753 #define TARGET_ADDRESS_COST bfin_address_cost
5755 #undef TARGET_ASM_INTEGER
5756 #define TARGET_ASM_INTEGER bfin_assemble_integer
5758 #undef TARGET_MACHINE_DEPENDENT_REORG
5759 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
5761 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
5762 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
5764 #undef TARGET_ASM_OUTPUT_MI_THUNK
5765 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
5766 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
5767 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
5769 #undef TARGET_SCHED_ADJUST_COST
5770 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
5772 #undef TARGET_SCHED_ISSUE_RATE
5773 #define TARGET_SCHED_ISSUE_RATE bfin_issue_rate
5775 #undef TARGET_PROMOTE_PROTOTYPES
5776 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
5777 #undef TARGET_PROMOTE_FUNCTION_ARGS
5778 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
5779 #undef TARGET_PROMOTE_FUNCTION_RETURN
5780 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true
5782 #undef TARGET_ARG_PARTIAL_BYTES
5783 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
5785 #undef TARGET_PASS_BY_REFERENCE
5786 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
5788 #undef TARGET_SETUP_INCOMING_VARARGS
5789 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
5791 #undef TARGET_STRUCT_VALUE_RTX
5792 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
5794 #undef TARGET_VECTOR_MODE_SUPPORTED_P
5795 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
5797 #undef TARGET_HANDLE_OPTION
5798 #define TARGET_HANDLE_OPTION bfin_handle_option
5800 #undef TARGET_DEFAULT_TARGET_FLAGS
5801 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
5803 #undef TARGET_SECONDARY_RELOAD
5804 #define TARGET_SECONDARY_RELOAD bfin_secondary_reload
5806 #undef TARGET_DELEGITIMIZE_ADDRESS
5807 #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address
5809 #undef TARGET_CANNOT_FORCE_CONST_MEM
5810 #define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem
5812 struct gcc_target targetm = TARGET_INITIALIZER;