* config/bfin/bfin.opt (minline-plt): Add.
[official-gcc/alias-decl.git] / gcc / config / bfin / bfin.c
blobb34e130628422420441b24d1878786f19d551c27
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 int splitting_for_sched;
100 static void
101 bfin_globalize_label (FILE *stream, const char *name)
103 fputs (".global ", stream);
104 assemble_name (stream, name);
105 fputc (';',stream);
106 fputc ('\n',stream);
109 static void
110 output_file_start (void)
112 FILE *file = asm_out_file;
113 int i;
115 /* Variable tracking should be run after all optimizations which change order
116 of insns. It also needs a valid CFG. This can't be done in
117 override_options, because flag_var_tracking is finalized after
118 that. */
119 bfin_flag_var_tracking = flag_var_tracking;
120 flag_var_tracking = 0;
122 fprintf (file, ".file \"%s\";\n", input_filename);
124 for (i = 0; arg_regs[i] >= 0; i++)
126 max_arg_registers = i; /* how many arg reg used */
129 /* Called early in the compilation to conditionally modify
130 fixed_regs/call_used_regs. */
132 void
133 conditional_register_usage (void)
135 /* initialize condition code flag register rtx */
136 bfin_cc_rtx = gen_rtx_REG (BImode, REG_CC);
137 bfin_rets_rtx = gen_rtx_REG (Pmode, REG_RETS);
140 /* Examine machine-dependent attributes of function type FUNTYPE and return its
141 type. See the definition of E_FUNKIND. */
143 static e_funkind
144 funkind (const_tree funtype)
146 tree attrs = TYPE_ATTRIBUTES (funtype);
147 if (lookup_attribute ("interrupt_handler", attrs))
148 return INTERRUPT_HANDLER;
149 else if (lookup_attribute ("exception_handler", attrs))
150 return EXCPT_HANDLER;
151 else if (lookup_attribute ("nmi_handler", attrs))
152 return NMI_HANDLER;
153 else
154 return SUBROUTINE;
157 /* Legitimize PIC addresses. If the address is already position-independent,
158 we return ORIG. Newly generated position-independent addresses go into a
159 reg. This is REG if nonzero, otherwise we allocate register(s) as
160 necessary. PICREG is the register holding the pointer to the PIC offset
161 table. */
163 static rtx
164 legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
166 rtx addr = orig;
167 rtx new = orig;
169 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
171 int unspec;
172 rtx tmp;
174 if (TARGET_ID_SHARED_LIBRARY)
175 unspec = UNSPEC_MOVE_PIC;
176 else if (GET_CODE (addr) == SYMBOL_REF
177 && SYMBOL_REF_FUNCTION_P (addr))
178 unspec = UNSPEC_FUNCDESC_GOT17M4;
179 else
180 unspec = UNSPEC_MOVE_FDPIC;
182 if (reg == 0)
184 gcc_assert (can_create_pseudo_p ());
185 reg = gen_reg_rtx (Pmode);
188 tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), unspec);
189 new = gen_const_mem (Pmode, gen_rtx_PLUS (Pmode, picreg, tmp));
191 emit_move_insn (reg, new);
192 if (picreg == pic_offset_table_rtx)
193 current_function_uses_pic_offset_table = 1;
194 return reg;
197 else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
199 rtx base;
201 if (GET_CODE (addr) == CONST)
203 addr = XEXP (addr, 0);
204 gcc_assert (GET_CODE (addr) == PLUS);
207 if (XEXP (addr, 0) == picreg)
208 return orig;
210 if (reg == 0)
212 gcc_assert (can_create_pseudo_p ());
213 reg = gen_reg_rtx (Pmode);
216 base = legitimize_pic_address (XEXP (addr, 0), reg, picreg);
217 addr = legitimize_pic_address (XEXP (addr, 1),
218 base == reg ? NULL_RTX : reg,
219 picreg);
221 if (GET_CODE (addr) == CONST_INT)
223 gcc_assert (! reload_in_progress && ! reload_completed);
224 addr = force_reg (Pmode, addr);
227 if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
229 base = gen_rtx_PLUS (Pmode, base, XEXP (addr, 0));
230 addr = XEXP (addr, 1);
233 return gen_rtx_PLUS (Pmode, base, addr);
236 return new;
239 /* Stack frame layout. */
241 /* Compute the number of DREGS to save with a push_multiple operation.
242 This could include registers that aren't modified in the function,
243 since push_multiple only takes a range of registers.
244 If IS_INTHANDLER, then everything that is live must be saved, even
245 if normally call-clobbered. */
247 static int
248 n_dregs_to_save (bool is_inthandler)
250 unsigned i;
252 for (i = REG_R0; i <= REG_R7; i++)
254 if (df_regs_ever_live_p (i) && (is_inthandler || ! call_used_regs[i]))
255 return REG_R7 - i + 1;
257 if (current_function_calls_eh_return)
259 unsigned j;
260 for (j = 0; ; j++)
262 unsigned test = EH_RETURN_DATA_REGNO (j);
263 if (test == INVALID_REGNUM)
264 break;
265 if (test == i)
266 return REG_R7 - i + 1;
271 return 0;
274 /* Like n_dregs_to_save, but compute number of PREGS to save. */
276 static int
277 n_pregs_to_save (bool is_inthandler)
279 unsigned i;
281 for (i = REG_P0; i <= REG_P5; i++)
282 if ((df_regs_ever_live_p (i) && (is_inthandler || ! call_used_regs[i]))
283 || (!TARGET_FDPIC
284 && i == PIC_OFFSET_TABLE_REGNUM
285 && (current_function_uses_pic_offset_table
286 || (TARGET_ID_SHARED_LIBRARY && ! current_function_is_leaf))))
287 return REG_P5 - i + 1;
288 return 0;
291 /* Determine if we are going to save the frame pointer in the prologue. */
293 static bool
294 must_save_fp_p (void)
296 return frame_pointer_needed || df_regs_ever_live_p (REG_FP);
299 static bool
300 stack_frame_needed_p (void)
302 /* EH return puts a new return address into the frame using an
303 address relative to the frame pointer. */
304 if (current_function_calls_eh_return)
305 return true;
306 return frame_pointer_needed;
309 /* Emit code to save registers in the prologue. SAVEALL is nonzero if we
310 must save all registers; this is used for interrupt handlers.
311 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
312 this for an interrupt (or exception) handler. */
314 static void
315 expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler)
317 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler);
318 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler);
319 int dregno = REG_R7 + 1 - ndregs;
320 int pregno = REG_P5 + 1 - npregs;
321 int total = ndregs + npregs;
322 int i;
323 rtx pat, insn, val;
325 if (total == 0)
326 return;
328 val = GEN_INT (-total * 4);
329 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total + 2));
330 XVECEXP (pat, 0, 0) = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, val),
331 UNSPEC_PUSH_MULTIPLE);
332 XVECEXP (pat, 0, total + 1) = gen_rtx_SET (VOIDmode, spreg,
333 gen_rtx_PLUS (Pmode, spreg,
334 val));
335 RTX_FRAME_RELATED_P (XVECEXP (pat, 0, total + 1)) = 1;
336 for (i = 0; i < total; i++)
338 rtx memref = gen_rtx_MEM (word_mode,
339 gen_rtx_PLUS (Pmode, spreg,
340 GEN_INT (- i * 4 - 4)));
341 rtx subpat;
342 if (ndregs > 0)
344 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
345 dregno++));
346 ndregs--;
348 else
350 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
351 pregno++));
352 npregs++;
354 XVECEXP (pat, 0, i + 1) = subpat;
355 RTX_FRAME_RELATED_P (subpat) = 1;
357 insn = emit_insn (pat);
358 RTX_FRAME_RELATED_P (insn) = 1;
361 /* Emit code to restore registers in the epilogue. SAVEALL is nonzero if we
362 must save all registers; this is used for interrupt handlers.
363 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
364 this for an interrupt (or exception) handler. */
366 static void
367 expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler)
369 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler);
370 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler);
371 int total = ndregs + npregs;
372 int i, regno;
373 rtx pat, insn;
375 if (total == 0)
376 return;
378 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total + 1));
379 XVECEXP (pat, 0, 0) = gen_rtx_SET (VOIDmode, spreg,
380 gen_rtx_PLUS (Pmode, spreg,
381 GEN_INT (total * 4)));
383 if (npregs > 0)
384 regno = REG_P5 + 1;
385 else
386 regno = REG_R7 + 1;
388 for (i = 0; i < total; i++)
390 rtx addr = (i > 0
391 ? gen_rtx_PLUS (Pmode, spreg, GEN_INT (i * 4))
392 : spreg);
393 rtx memref = gen_rtx_MEM (word_mode, addr);
395 regno--;
396 XVECEXP (pat, 0, i + 1)
397 = gen_rtx_SET (VOIDmode, gen_rtx_REG (word_mode, regno), memref);
399 if (npregs > 0)
401 if (--npregs == 0)
402 regno = REG_R7 + 1;
406 insn = emit_insn (pat);
407 RTX_FRAME_RELATED_P (insn) = 1;
410 /* Perform any needed actions needed for a function that is receiving a
411 variable number of arguments.
413 CUM is as above.
415 MODE and TYPE are the mode and type of the current parameter.
417 PRETEND_SIZE is a variable that should be set to the amount of stack
418 that must be pushed by the prolog to pretend that our caller pushed
421 Normally, this macro will push all remaining incoming registers on the
422 stack and set PRETEND_SIZE to the length of the registers pushed.
424 Blackfin specific :
425 - VDSP C compiler manual (our ABI) says that a variable args function
426 should save the R0, R1 and R2 registers in the stack.
427 - The caller will always leave space on the stack for the
428 arguments that are passed in registers, so we dont have
429 to leave any extra space.
430 - now, the vastart pointer can access all arguments from the stack. */
432 static void
433 setup_incoming_varargs (CUMULATIVE_ARGS *cum,
434 enum machine_mode mode ATTRIBUTE_UNUSED,
435 tree type ATTRIBUTE_UNUSED, int *pretend_size,
436 int no_rtl)
438 rtx mem;
439 int i;
441 if (no_rtl)
442 return;
444 /* The move for named arguments will be generated automatically by the
445 compiler. We need to generate the move rtx for the unnamed arguments
446 if they are in the first 3 words. We assume at least 1 named argument
447 exists, so we never generate [ARGP] = R0 here. */
449 for (i = cum->words + 1; i < max_arg_registers; i++)
451 mem = gen_rtx_MEM (Pmode,
452 plus_constant (arg_pointer_rtx, (i * UNITS_PER_WORD)));
453 emit_move_insn (mem, gen_rtx_REG (Pmode, i));
456 *pretend_size = 0;
459 /* Value should be nonzero if functions must have frame pointers.
460 Zero means the frame pointer need not be set up (and parms may
461 be accessed via the stack pointer) in functions that seem suitable. */
464 bfin_frame_pointer_required (void)
466 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
468 if (fkind != SUBROUTINE)
469 return 1;
471 /* We turn on -fomit-frame-pointer if -momit-leaf-frame-pointer is used,
472 so we have to override it for non-leaf functions. */
473 if (TARGET_OMIT_LEAF_FRAME_POINTER && ! current_function_is_leaf)
474 return 1;
476 return 0;
479 /* Return the number of registers pushed during the prologue. */
481 static int
482 n_regs_saved_by_prologue (void)
484 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
485 bool is_inthandler = fkind != SUBROUTINE;
486 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
487 bool all = (lookup_attribute ("saveall", attrs) != NULL_TREE
488 || (is_inthandler && !current_function_is_leaf));
489 int ndregs = all ? 8 : n_dregs_to_save (is_inthandler);
490 int npregs = all ? 6 : n_pregs_to_save (is_inthandler);
491 int n = ndregs + npregs;
493 if (all || stack_frame_needed_p ())
494 /* We use a LINK instruction in this case. */
495 n += 2;
496 else
498 if (must_save_fp_p ())
499 n++;
500 if (! current_function_is_leaf)
501 n++;
504 if (fkind != SUBROUTINE)
506 int i;
508 /* Increment once for ASTAT. */
509 n++;
511 /* RETE/X/N. */
512 if (lookup_attribute ("nesting", attrs))
513 n++;
515 for (i = REG_P7 + 1; i < REG_CC; i++)
516 if (all
517 || df_regs_ever_live_p (i)
518 || (!leaf_function_p () && call_used_regs[i]))
519 n += i == REG_A0 || i == REG_A1 ? 2 : 1;
521 return n;
524 /* Return the offset between two registers, one to be eliminated, and the other
525 its replacement, at the start of a routine. */
527 HOST_WIDE_INT
528 bfin_initial_elimination_offset (int from, int to)
530 HOST_WIDE_INT offset = 0;
532 if (from == ARG_POINTER_REGNUM)
533 offset = n_regs_saved_by_prologue () * 4;
535 if (to == STACK_POINTER_REGNUM)
537 if (current_function_outgoing_args_size >= FIXED_STACK_AREA)
538 offset += current_function_outgoing_args_size;
539 else if (current_function_outgoing_args_size)
540 offset += FIXED_STACK_AREA;
542 offset += get_frame_size ();
545 return offset;
548 /* Emit code to load a constant CONSTANT into register REG; setting
549 RTX_FRAME_RELATED_P on all insns we generate if RELATED is true.
550 Make sure that the insns we generate need not be split. */
552 static void
553 frame_related_constant_load (rtx reg, HOST_WIDE_INT constant, bool related)
555 rtx insn;
556 rtx cst = GEN_INT (constant);
558 if (constant >= -32768 && constant < 65536)
559 insn = emit_move_insn (reg, cst);
560 else
562 /* We don't call split_load_immediate here, since dwarf2out.c can get
563 confused about some of the more clever sequences it can generate. */
564 insn = emit_insn (gen_movsi_high (reg, cst));
565 if (related)
566 RTX_FRAME_RELATED_P (insn) = 1;
567 insn = emit_insn (gen_movsi_low (reg, reg, cst));
569 if (related)
570 RTX_FRAME_RELATED_P (insn) = 1;
573 /* Generate efficient code to add a value to a P register.
574 Set RTX_FRAME_RELATED_P on the generated insns if FRAME is nonzero.
575 EPILOGUE_P is zero if this function is called for prologue,
576 otherwise it's nonzero. And it's less than zero if this is for
577 sibcall epilogue. */
579 static void
580 add_to_reg (rtx reg, HOST_WIDE_INT value, int frame, int epilogue_p)
582 if (value == 0)
583 return;
585 /* Choose whether to use a sequence using a temporary register, or
586 a sequence with multiple adds. We can add a signed 7-bit value
587 in one instruction. */
588 if (value > 120 || value < -120)
590 rtx tmpreg;
591 rtx tmpreg2;
592 rtx insn;
594 tmpreg2 = NULL_RTX;
596 /* For prologue or normal epilogue, P1 can be safely used
597 as the temporary register. For sibcall epilogue, we try to find
598 a call used P register, which will be restored in epilogue.
599 If we cannot find such a P register, we have to use one I register
600 to help us. */
602 if (epilogue_p >= 0)
603 tmpreg = gen_rtx_REG (SImode, REG_P1);
604 else
606 int i;
607 for (i = REG_P0; i <= REG_P5; i++)
608 if ((df_regs_ever_live_p (i) && ! call_used_regs[i])
609 || (!TARGET_FDPIC
610 && i == PIC_OFFSET_TABLE_REGNUM
611 && (current_function_uses_pic_offset_table
612 || (TARGET_ID_SHARED_LIBRARY
613 && ! current_function_is_leaf))))
614 break;
615 if (i <= REG_P5)
616 tmpreg = gen_rtx_REG (SImode, i);
617 else
619 tmpreg = gen_rtx_REG (SImode, REG_P1);
620 tmpreg2 = gen_rtx_REG (SImode, REG_I0);
621 emit_move_insn (tmpreg2, tmpreg);
625 if (frame)
626 frame_related_constant_load (tmpreg, value, TRUE);
627 else
628 insn = emit_move_insn (tmpreg, GEN_INT (value));
630 insn = emit_insn (gen_addsi3 (reg, reg, tmpreg));
631 if (frame)
632 RTX_FRAME_RELATED_P (insn) = 1;
634 if (tmpreg2 != NULL_RTX)
635 emit_move_insn (tmpreg, tmpreg2);
637 else
640 int size = value;
641 rtx insn;
643 if (size > 60)
644 size = 60;
645 else if (size < -60)
646 /* We could use -62, but that would leave the stack unaligned, so
647 it's no good. */
648 size = -60;
650 insn = emit_insn (gen_addsi3 (reg, reg, GEN_INT (size)));
651 if (frame)
652 RTX_FRAME_RELATED_P (insn) = 1;
653 value -= size;
655 while (value != 0);
658 /* Generate a LINK insn for a frame sized FRAME_SIZE. If this constant
659 is too large, generate a sequence of insns that has the same effect.
660 SPREG contains (reg:SI REG_SP). */
662 static void
663 emit_link_insn (rtx spreg, HOST_WIDE_INT frame_size)
665 HOST_WIDE_INT link_size = frame_size;
666 rtx insn;
667 int i;
669 if (link_size > 262140)
670 link_size = 262140;
672 /* Use a LINK insn with as big a constant as possible, then subtract
673 any remaining size from the SP. */
674 insn = emit_insn (gen_link (GEN_INT (-8 - link_size)));
675 RTX_FRAME_RELATED_P (insn) = 1;
677 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
679 rtx set = XVECEXP (PATTERN (insn), 0, i);
680 gcc_assert (GET_CODE (set) == SET);
681 RTX_FRAME_RELATED_P (set) = 1;
684 frame_size -= link_size;
686 if (frame_size > 0)
688 /* Must use a call-clobbered PREG that isn't the static chain. */
689 rtx tmpreg = gen_rtx_REG (Pmode, REG_P1);
691 frame_related_constant_load (tmpreg, -frame_size, TRUE);
692 insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg));
693 RTX_FRAME_RELATED_P (insn) = 1;
697 /* Return the number of bytes we must reserve for outgoing arguments
698 in the current function's stack frame. */
700 static HOST_WIDE_INT
701 arg_area_size (void)
703 if (current_function_outgoing_args_size)
705 if (current_function_outgoing_args_size >= FIXED_STACK_AREA)
706 return current_function_outgoing_args_size;
707 else
708 return FIXED_STACK_AREA;
710 return 0;
713 /* Save RETS and FP, and allocate a stack frame. ALL is true if the
714 function must save all its registers (true only for certain interrupt
715 handlers). */
717 static void
718 do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all)
720 frame_size += arg_area_size ();
722 if (all || stack_frame_needed_p ()
723 || (must_save_fp_p () && ! current_function_is_leaf))
724 emit_link_insn (spreg, frame_size);
725 else
727 if (! current_function_is_leaf)
729 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
730 gen_rtx_PRE_DEC (Pmode, spreg)),
731 bfin_rets_rtx);
732 rtx insn = emit_insn (pat);
733 RTX_FRAME_RELATED_P (insn) = 1;
735 if (must_save_fp_p ())
737 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
738 gen_rtx_PRE_DEC (Pmode, spreg)),
739 gen_rtx_REG (Pmode, REG_FP));
740 rtx insn = emit_insn (pat);
741 RTX_FRAME_RELATED_P (insn) = 1;
743 add_to_reg (spreg, -frame_size, 1, 0);
747 /* Like do_link, but used for epilogues to deallocate the stack frame.
748 EPILOGUE_P is zero if this function is called for prologue,
749 otherwise it's nonzero. And it's less than zero if this is for
750 sibcall epilogue. */
752 static void
753 do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all, int epilogue_p)
755 frame_size += arg_area_size ();
757 if (all || stack_frame_needed_p ())
758 emit_insn (gen_unlink ());
759 else
761 rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg));
763 add_to_reg (spreg, frame_size, 0, epilogue_p);
764 if (must_save_fp_p ())
766 rtx fpreg = gen_rtx_REG (Pmode, REG_FP);
767 emit_move_insn (fpreg, postinc);
768 emit_insn (gen_rtx_USE (VOIDmode, fpreg));
770 if (! current_function_is_leaf)
772 emit_move_insn (bfin_rets_rtx, postinc);
773 emit_insn (gen_rtx_USE (VOIDmode, bfin_rets_rtx));
778 /* Generate a prologue suitable for a function of kind FKIND. This is
779 called for interrupt and exception handler prologues.
780 SPREG contains (reg:SI REG_SP). */
782 static void
783 expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind)
785 int i;
786 HOST_WIDE_INT frame_size = get_frame_size ();
787 rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
788 rtx predec = gen_rtx_MEM (SImode, predec1);
789 rtx insn;
790 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
791 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
792 tree kspisusp = lookup_attribute ("kspisusp", attrs);
794 if (kspisusp)
796 insn = emit_move_insn (spreg, gen_rtx_REG (Pmode, REG_USP));
797 RTX_FRAME_RELATED_P (insn) = 1;
800 /* We need space on the stack in case we need to save the argument
801 registers. */
802 if (fkind == EXCPT_HANDLER)
804 insn = emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (-12)));
805 RTX_FRAME_RELATED_P (insn) = 1;
808 insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
809 RTX_FRAME_RELATED_P (insn) = 1;
811 /* If we're calling other functions, they won't save their call-clobbered
812 registers, so we must save everything here. */
813 if (!current_function_is_leaf)
814 all = true;
815 expand_prologue_reg_save (spreg, all, true);
817 for (i = REG_P7 + 1; i < REG_CC; i++)
818 if (all
819 || df_regs_ever_live_p (i)
820 || (!leaf_function_p () && call_used_regs[i]))
822 if (i == REG_A0 || i == REG_A1)
823 insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1),
824 gen_rtx_REG (PDImode, i));
825 else
826 insn = emit_move_insn (predec, gen_rtx_REG (SImode, i));
827 RTX_FRAME_RELATED_P (insn) = 1;
830 if (lookup_attribute ("nesting", attrs))
832 rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
833 : fkind == NMI_HANDLER ? REG_RETN
834 : REG_RETI));
835 insn = emit_move_insn (predec, srcreg);
836 RTX_FRAME_RELATED_P (insn) = 1;
839 do_link (spreg, frame_size, all);
841 if (fkind == EXCPT_HANDLER)
843 rtx r0reg = gen_rtx_REG (SImode, REG_R0);
844 rtx r1reg = gen_rtx_REG (SImode, REG_R1);
845 rtx r2reg = gen_rtx_REG (SImode, REG_R2);
846 rtx insn;
848 insn = emit_move_insn (r0reg, gen_rtx_REG (SImode, REG_SEQSTAT));
849 insn = emit_insn (gen_ashrsi3 (r0reg, r0reg, GEN_INT (26)));
850 insn = emit_insn (gen_ashlsi3 (r0reg, r0reg, GEN_INT (26)));
851 insn = emit_move_insn (r1reg, spreg);
852 insn = emit_move_insn (r2reg, gen_rtx_REG (Pmode, REG_FP));
853 insn = emit_insn (gen_addsi3 (r2reg, r2reg, GEN_INT (8)));
857 /* Generate an epilogue suitable for a function of kind FKIND. This is
858 called for interrupt and exception handler epilogues.
859 SPREG contains (reg:SI REG_SP). */
861 static void
862 expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind)
864 int i;
865 rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
866 rtx postinc = gen_rtx_MEM (SImode, postinc1);
867 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
868 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
870 /* A slightly crude technique to stop flow from trying to delete "dead"
871 insns. */
872 MEM_VOLATILE_P (postinc) = 1;
874 do_unlink (spreg, get_frame_size (), all, 1);
876 if (lookup_attribute ("nesting", attrs))
878 rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
879 : fkind == NMI_HANDLER ? REG_RETN
880 : REG_RETI));
881 emit_move_insn (srcreg, postinc);
884 /* If we're calling other functions, they won't save their call-clobbered
885 registers, so we must save (and restore) everything here. */
886 if (!current_function_is_leaf)
887 all = true;
889 for (i = REG_CC - 1; i > REG_P7; i--)
890 if (all
891 || df_regs_ever_live_p (i)
892 || (!leaf_function_p () && call_used_regs[i]))
894 if (i == REG_A0 || i == REG_A1)
896 rtx mem = gen_rtx_MEM (PDImode, postinc1);
897 MEM_VOLATILE_P (mem) = 1;
898 emit_move_insn (gen_rtx_REG (PDImode, i), mem);
900 else
901 emit_move_insn (gen_rtx_REG (SImode, i), postinc);
904 expand_epilogue_reg_restore (spreg, all, true);
906 emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
908 /* Deallocate any space we left on the stack in case we needed to save the
909 argument registers. */
910 if (fkind == EXCPT_HANDLER)
911 emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (12)));
913 emit_jump_insn (gen_return_internal (GEN_INT (fkind)));
916 /* Used while emitting the prologue to generate code to load the correct value
917 into the PIC register, which is passed in DEST. */
919 static rtx
920 bfin_load_pic_reg (rtx dest)
922 struct cgraph_local_info *i = NULL;
923 rtx addr, insn;
925 if (flag_unit_at_a_time)
926 i = cgraph_local_info (current_function_decl);
928 /* Functions local to the translation unit don't need to reload the
929 pic reg, since the caller always passes a usable one. */
930 if (i && i->local)
931 return pic_offset_table_rtx;
933 if (bfin_lib_id_given)
934 addr = plus_constant (pic_offset_table_rtx, -4 - bfin_library_id * 4);
935 else
936 addr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
937 gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
938 UNSPEC_LIBRARY_OFFSET));
939 insn = emit_insn (gen_movsi (dest, gen_rtx_MEM (Pmode, addr)));
940 return dest;
943 /* Generate RTL for the prologue of the current function. */
945 void
946 bfin_expand_prologue (void)
948 HOST_WIDE_INT frame_size = get_frame_size ();
949 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
950 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
951 rtx pic_reg_loaded = NULL_RTX;
953 if (fkind != SUBROUTINE)
955 expand_interrupt_handler_prologue (spreg, fkind);
956 return;
959 if (current_function_limit_stack
960 || TARGET_STACK_CHECK_L1)
962 HOST_WIDE_INT offset
963 = bfin_initial_elimination_offset (ARG_POINTER_REGNUM,
964 STACK_POINTER_REGNUM);
965 rtx lim = current_function_limit_stack ? stack_limit_rtx : NULL_RTX;
966 rtx p2reg = gen_rtx_REG (Pmode, REG_P2);
968 if (!lim)
970 emit_move_insn (p2reg, gen_int_mode (0xFFB00000, SImode));
971 emit_move_insn (p2reg, gen_rtx_MEM (Pmode, p2reg));
972 lim = p2reg;
974 if (GET_CODE (lim) == SYMBOL_REF)
976 if (TARGET_ID_SHARED_LIBRARY)
978 rtx p1reg = gen_rtx_REG (Pmode, REG_P1);
979 rtx val;
980 pic_reg_loaded = bfin_load_pic_reg (p2reg);
981 val = legitimize_pic_address (stack_limit_rtx, p1reg,
982 pic_reg_loaded);
983 emit_move_insn (p1reg, val);
984 frame_related_constant_load (p2reg, offset, FALSE);
985 emit_insn (gen_addsi3 (p2reg, p2reg, p1reg));
986 lim = p2reg;
988 else
990 rtx limit = plus_constant (lim, offset);
991 emit_move_insn (p2reg, limit);
992 lim = p2reg;
995 else
997 if (lim != p2reg)
998 emit_move_insn (p2reg, lim);
999 add_to_reg (p2reg, offset, 0, 0);
1000 lim = p2reg;
1002 emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim));
1003 emit_insn (gen_trapifcc ());
1005 expand_prologue_reg_save (spreg, 0, false);
1007 do_link (spreg, frame_size, false);
1009 if (TARGET_ID_SHARED_LIBRARY
1010 && !TARGET_SEP_DATA
1011 && (current_function_uses_pic_offset_table
1012 || !current_function_is_leaf))
1013 bfin_load_pic_reg (pic_offset_table_rtx);
1016 /* Generate RTL for the epilogue of the current function. NEED_RETURN is zero
1017 if this is for a sibcall. EH_RETURN is nonzero if we're expanding an
1018 eh_return pattern. SIBCALL_P is true if this is a sibcall epilogue,
1019 false otherwise. */
1021 void
1022 bfin_expand_epilogue (int need_return, int eh_return, bool sibcall_p)
1024 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
1025 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1026 int e = sibcall_p ? -1 : 1;
1028 if (fkind != SUBROUTINE)
1030 expand_interrupt_handler_epilogue (spreg, fkind);
1031 return;
1034 do_unlink (spreg, get_frame_size (), false, e);
1036 expand_epilogue_reg_restore (spreg, false, false);
1038 /* Omit the return insn if this is for a sibcall. */
1039 if (! need_return)
1040 return;
1042 if (eh_return)
1043 emit_insn (gen_addsi3 (spreg, spreg, gen_rtx_REG (Pmode, REG_P2)));
1045 emit_jump_insn (gen_return_internal (GEN_INT (SUBROUTINE)));
1048 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
1051 bfin_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
1052 unsigned int new_reg)
1054 /* Interrupt functions can only use registers that have already been
1055 saved by the prologue, even if they would normally be
1056 call-clobbered. */
1058 if (funkind (TREE_TYPE (current_function_decl)) != SUBROUTINE
1059 && !df_regs_ever_live_p (new_reg))
1060 return 0;
1062 return 1;
1065 /* Return the value of the return address for the frame COUNT steps up
1066 from the current frame, after the prologue.
1067 We punt for everything but the current frame by returning const0_rtx. */
1070 bfin_return_addr_rtx (int count)
1072 if (count != 0)
1073 return const0_rtx;
1075 return get_hard_reg_initial_val (Pmode, REG_RETS);
1078 /* Try machine-dependent ways of modifying an illegitimate address X
1079 to be legitimate. If we find one, return the new, valid address,
1080 otherwise return NULL_RTX.
1082 OLDX is the address as it was before break_out_memory_refs was called.
1083 In some cases it is useful to look at this to decide what needs to be done.
1085 MODE is the mode of the memory reference. */
1088 legitimize_address (rtx x ATTRIBUTE_UNUSED, rtx oldx ATTRIBUTE_UNUSED,
1089 enum machine_mode mode ATTRIBUTE_UNUSED)
1091 return NULL_RTX;
1094 static rtx
1095 bfin_delegitimize_address (rtx orig_x)
1097 rtx x = orig_x;
1099 if (GET_CODE (x) != MEM)
1100 return orig_x;
1102 x = XEXP (x, 0);
1103 if (GET_CODE (x) == PLUS
1104 && GET_CODE (XEXP (x, 1)) == UNSPEC
1105 && XINT (XEXP (x, 1), 1) == UNSPEC_MOVE_PIC
1106 && GET_CODE (XEXP (x, 0)) == REG
1107 && REGNO (XEXP (x, 0)) == PIC_OFFSET_TABLE_REGNUM)
1108 return XVECEXP (XEXP (x, 1), 0, 0);
1110 return orig_x;
1113 /* This predicate is used to compute the length of a load/store insn.
1114 OP is a MEM rtx, we return nonzero if its addressing mode requires a
1115 32-bit instruction. */
1118 effective_address_32bit_p (rtx op, enum machine_mode mode)
1120 HOST_WIDE_INT offset;
1122 mode = GET_MODE (op);
1123 op = XEXP (op, 0);
1125 if (GET_CODE (op) != PLUS)
1127 gcc_assert (REG_P (op) || GET_CODE (op) == POST_INC
1128 || GET_CODE (op) == PRE_DEC || GET_CODE (op) == POST_DEC);
1129 return 0;
1132 if (GET_CODE (XEXP (op, 1)) == UNSPEC)
1133 return 1;
1135 offset = INTVAL (XEXP (op, 1));
1137 /* All byte loads use a 16-bit offset. */
1138 if (GET_MODE_SIZE (mode) == 1)
1139 return 1;
1141 if (GET_MODE_SIZE (mode) == 4)
1143 /* Frame pointer relative loads can use a negative offset, all others
1144 are restricted to a small positive one. */
1145 if (XEXP (op, 0) == frame_pointer_rtx)
1146 return offset < -128 || offset > 60;
1147 return offset < 0 || offset > 60;
1150 /* Must be HImode now. */
1151 return offset < 0 || offset > 30;
1154 /* Returns true if X is a memory reference using an I register. */
1155 bool
1156 bfin_dsp_memref_p (rtx x)
1158 if (! MEM_P (x))
1159 return false;
1160 x = XEXP (x, 0);
1161 if (GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_INC
1162 || GET_CODE (x) == POST_DEC || GET_CODE (x) == PRE_DEC)
1163 x = XEXP (x, 0);
1164 return IREG_P (x);
1167 /* Return cost of the memory address ADDR.
1168 All addressing modes are equally cheap on the Blackfin. */
1170 static int
1171 bfin_address_cost (rtx addr ATTRIBUTE_UNUSED)
1173 return 1;
1176 /* Subroutine of print_operand; used to print a memory reference X to FILE. */
1178 void
1179 print_address_operand (FILE *file, rtx x)
1181 switch (GET_CODE (x))
1183 case PLUS:
1184 output_address (XEXP (x, 0));
1185 fprintf (file, "+");
1186 output_address (XEXP (x, 1));
1187 break;
1189 case PRE_DEC:
1190 fprintf (file, "--");
1191 output_address (XEXP (x, 0));
1192 break;
1193 case POST_INC:
1194 output_address (XEXP (x, 0));
1195 fprintf (file, "++");
1196 break;
1197 case POST_DEC:
1198 output_address (XEXP (x, 0));
1199 fprintf (file, "--");
1200 break;
1202 default:
1203 gcc_assert (GET_CODE (x) != MEM);
1204 print_operand (file, x, 0);
1205 break;
1209 /* Adding intp DImode support by Tony
1210 * -- Q: (low word)
1211 * -- R: (high word)
1214 void
1215 print_operand (FILE *file, rtx x, char code)
1217 enum machine_mode mode;
1219 if (code == '!')
1221 if (GET_MODE (current_output_insn) == SImode)
1222 fprintf (file, " ||");
1223 else
1224 fprintf (file, ";");
1225 return;
1228 mode = GET_MODE (x);
1230 switch (code)
1232 case 'j':
1233 switch (GET_CODE (x))
1235 case EQ:
1236 fprintf (file, "e");
1237 break;
1238 case NE:
1239 fprintf (file, "ne");
1240 break;
1241 case GT:
1242 fprintf (file, "g");
1243 break;
1244 case LT:
1245 fprintf (file, "l");
1246 break;
1247 case GE:
1248 fprintf (file, "ge");
1249 break;
1250 case LE:
1251 fprintf (file, "le");
1252 break;
1253 case GTU:
1254 fprintf (file, "g");
1255 break;
1256 case LTU:
1257 fprintf (file, "l");
1258 break;
1259 case GEU:
1260 fprintf (file, "ge");
1261 break;
1262 case LEU:
1263 fprintf (file, "le");
1264 break;
1265 default:
1266 output_operand_lossage ("invalid %%j value");
1268 break;
1270 case 'J': /* reverse logic */
1271 switch (GET_CODE(x))
1273 case EQ:
1274 fprintf (file, "ne");
1275 break;
1276 case NE:
1277 fprintf (file, "e");
1278 break;
1279 case GT:
1280 fprintf (file, "le");
1281 break;
1282 case LT:
1283 fprintf (file, "ge");
1284 break;
1285 case GE:
1286 fprintf (file, "l");
1287 break;
1288 case LE:
1289 fprintf (file, "g");
1290 break;
1291 case GTU:
1292 fprintf (file, "le");
1293 break;
1294 case LTU:
1295 fprintf (file, "ge");
1296 break;
1297 case GEU:
1298 fprintf (file, "l");
1299 break;
1300 case LEU:
1301 fprintf (file, "g");
1302 break;
1303 default:
1304 output_operand_lossage ("invalid %%J value");
1306 break;
1308 default:
1309 switch (GET_CODE (x))
1311 case REG:
1312 if (code == 'h')
1314 if (REGNO (x) < 32)
1315 fprintf (file, "%s", short_reg_names[REGNO (x)]);
1316 else
1317 output_operand_lossage ("invalid operand for code '%c'", code);
1319 else if (code == 'd')
1321 if (REGNO (x) < 32)
1322 fprintf (file, "%s", high_reg_names[REGNO (x)]);
1323 else
1324 output_operand_lossage ("invalid operand for code '%c'", code);
1326 else if (code == 'w')
1328 if (REGNO (x) == REG_A0 || REGNO (x) == REG_A1)
1329 fprintf (file, "%s.w", reg_names[REGNO (x)]);
1330 else
1331 output_operand_lossage ("invalid operand for code '%c'", code);
1333 else if (code == 'x')
1335 if (REGNO (x) == REG_A0 || REGNO (x) == REG_A1)
1336 fprintf (file, "%s.x", reg_names[REGNO (x)]);
1337 else
1338 output_operand_lossage ("invalid operand for code '%c'", code);
1340 else if (code == 'v')
1342 if (REGNO (x) == REG_A0)
1343 fprintf (file, "AV0");
1344 else if (REGNO (x) == REG_A1)
1345 fprintf (file, "AV1");
1346 else
1347 output_operand_lossage ("invalid operand for code '%c'", code);
1349 else if (code == 'D')
1351 if (D_REGNO_P (REGNO (x)))
1352 fprintf (file, "%s", dregs_pair_names[REGNO (x)]);
1353 else
1354 output_operand_lossage ("invalid operand for code '%c'", code);
1356 else if (code == 'H')
1358 if ((mode == DImode || mode == DFmode) && REG_P (x))
1359 fprintf (file, "%s", reg_names[REGNO (x) + 1]);
1360 else
1361 output_operand_lossage ("invalid operand for code '%c'", code);
1363 else if (code == 'T')
1365 if (D_REGNO_P (REGNO (x)))
1366 fprintf (file, "%s", byte_reg_names[REGNO (x)]);
1367 else
1368 output_operand_lossage ("invalid operand for code '%c'", code);
1370 else
1371 fprintf (file, "%s", reg_names[REGNO (x)]);
1372 break;
1374 case MEM:
1375 fputc ('[', file);
1376 x = XEXP (x,0);
1377 print_address_operand (file, x);
1378 fputc (']', file);
1379 break;
1381 case CONST_INT:
1382 if (code == 'M')
1384 switch (INTVAL (x))
1386 case MACFLAG_NONE:
1387 break;
1388 case MACFLAG_FU:
1389 fputs ("(FU)", file);
1390 break;
1391 case MACFLAG_T:
1392 fputs ("(T)", file);
1393 break;
1394 case MACFLAG_TFU:
1395 fputs ("(TFU)", file);
1396 break;
1397 case MACFLAG_W32:
1398 fputs ("(W32)", file);
1399 break;
1400 case MACFLAG_IS:
1401 fputs ("(IS)", file);
1402 break;
1403 case MACFLAG_IU:
1404 fputs ("(IU)", file);
1405 break;
1406 case MACFLAG_IH:
1407 fputs ("(IH)", file);
1408 break;
1409 case MACFLAG_M:
1410 fputs ("(M)", file);
1411 break;
1412 case MACFLAG_IS_M:
1413 fputs ("(IS,M)", file);
1414 break;
1415 case MACFLAG_ISS2:
1416 fputs ("(ISS2)", file);
1417 break;
1418 case MACFLAG_S2RND:
1419 fputs ("(S2RND)", file);
1420 break;
1421 default:
1422 gcc_unreachable ();
1424 break;
1426 else if (code == 'b')
1428 if (INTVAL (x) == 0)
1429 fputs ("+=", file);
1430 else if (INTVAL (x) == 1)
1431 fputs ("-=", file);
1432 else
1433 gcc_unreachable ();
1434 break;
1436 /* Moves to half registers with d or h modifiers always use unsigned
1437 constants. */
1438 else if (code == 'd')
1439 x = GEN_INT ((INTVAL (x) >> 16) & 0xffff);
1440 else if (code == 'h')
1441 x = GEN_INT (INTVAL (x) & 0xffff);
1442 else if (code == 'N')
1443 x = GEN_INT (-INTVAL (x));
1444 else if (code == 'X')
1445 x = GEN_INT (exact_log2 (0xffffffff & INTVAL (x)));
1446 else if (code == 'Y')
1447 x = GEN_INT (exact_log2 (0xffffffff & ~INTVAL (x)));
1448 else if (code == 'Z')
1449 /* Used for LINK insns. */
1450 x = GEN_INT (-8 - INTVAL (x));
1452 /* fall through */
1454 case SYMBOL_REF:
1455 output_addr_const (file, x);
1456 break;
1458 case CONST_DOUBLE:
1459 output_operand_lossage ("invalid const_double operand");
1460 break;
1462 case UNSPEC:
1463 switch (XINT (x, 1))
1465 case UNSPEC_MOVE_PIC:
1466 output_addr_const (file, XVECEXP (x, 0, 0));
1467 fprintf (file, "@GOT");
1468 break;
1470 case UNSPEC_MOVE_FDPIC:
1471 output_addr_const (file, XVECEXP (x, 0, 0));
1472 fprintf (file, "@GOT17M4");
1473 break;
1475 case UNSPEC_FUNCDESC_GOT17M4:
1476 output_addr_const (file, XVECEXP (x, 0, 0));
1477 fprintf (file, "@FUNCDESC_GOT17M4");
1478 break;
1480 case UNSPEC_LIBRARY_OFFSET:
1481 fprintf (file, "_current_shared_library_p5_offset_");
1482 break;
1484 default:
1485 gcc_unreachable ();
1487 break;
1489 default:
1490 output_addr_const (file, x);
1495 /* Argument support functions. */
1497 /* Initialize a variable CUM of type CUMULATIVE_ARGS
1498 for a call to a function whose data type is FNTYPE.
1499 For a library call, FNTYPE is 0.
1500 VDSP C Compiler manual, our ABI says that
1501 first 3 words of arguments will use R0, R1 and R2.
1504 void
1505 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
1506 rtx libname ATTRIBUTE_UNUSED)
1508 static CUMULATIVE_ARGS zero_cum;
1510 *cum = zero_cum;
1512 /* Set up the number of registers to use for passing arguments. */
1514 cum->nregs = max_arg_registers;
1515 cum->arg_regs = arg_regs;
1517 cum->call_cookie = CALL_NORMAL;
1518 /* Check for a longcall attribute. */
1519 if (fntype && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype)))
1520 cum->call_cookie |= CALL_SHORT;
1521 else if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)))
1522 cum->call_cookie |= CALL_LONG;
1524 return;
1527 /* Update the data in CUM to advance over an argument
1528 of mode MODE and data type TYPE.
1529 (TYPE is null for libcalls where that information may not be available.) */
1531 void
1532 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1533 int named ATTRIBUTE_UNUSED)
1535 int count, bytes, words;
1537 bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1538 words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1540 cum->words += words;
1541 cum->nregs -= words;
1543 if (cum->nregs <= 0)
1545 cum->nregs = 0;
1546 cum->arg_regs = NULL;
1548 else
1550 for (count = 1; count <= words; count++)
1551 cum->arg_regs++;
1554 return;
1557 /* Define where to put the arguments to a function.
1558 Value is zero to push the argument on the stack,
1559 or a hard register in which to store the argument.
1561 MODE is the argument's machine mode.
1562 TYPE is the data type of the argument (as a tree).
1563 This is null for libcalls where that information may
1564 not be available.
1565 CUM is a variable of type CUMULATIVE_ARGS which gives info about
1566 the preceding args and about the function being called.
1567 NAMED is nonzero if this argument is a named parameter
1568 (otherwise it is an extra parameter matching an ellipsis). */
1570 struct rtx_def *
1571 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1572 int named ATTRIBUTE_UNUSED)
1574 int bytes
1575 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1577 if (mode == VOIDmode)
1578 /* Compute operand 2 of the call insn. */
1579 return GEN_INT (cum->call_cookie);
1581 if (bytes == -1)
1582 return NULL_RTX;
1584 if (cum->nregs)
1585 return gen_rtx_REG (mode, *(cum->arg_regs));
1587 return NULL_RTX;
1590 /* For an arg passed partly in registers and partly in memory,
1591 this is the number of bytes passed in registers.
1592 For args passed entirely in registers or entirely in memory, zero.
1594 Refer VDSP C Compiler manual, our ABI.
1595 First 3 words are in registers. So, if an argument is larger
1596 than the registers available, it will span the register and
1597 stack. */
1599 static int
1600 bfin_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1601 tree type ATTRIBUTE_UNUSED,
1602 bool named ATTRIBUTE_UNUSED)
1604 int bytes
1605 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1606 int bytes_left = cum->nregs * UNITS_PER_WORD;
1608 if (bytes == -1)
1609 return 0;
1611 if (bytes_left == 0)
1612 return 0;
1613 if (bytes > bytes_left)
1614 return bytes_left;
1615 return 0;
1618 /* Variable sized types are passed by reference. */
1620 static bool
1621 bfin_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
1622 enum machine_mode mode ATTRIBUTE_UNUSED,
1623 const_tree type, bool named ATTRIBUTE_UNUSED)
1625 return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
1628 /* Decide whether a type should be returned in memory (true)
1629 or in a register (false). This is called by the macro
1630 RETURN_IN_MEMORY. */
1633 bfin_return_in_memory (const_tree type)
1635 int size = int_size_in_bytes (type);
1636 return size > 2 * UNITS_PER_WORD || size == -1;
1639 /* Register in which address to store a structure value
1640 is passed to a function. */
1641 static rtx
1642 bfin_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
1643 int incoming ATTRIBUTE_UNUSED)
1645 return gen_rtx_REG (Pmode, REG_P0);
1648 /* Return true when register may be used to pass function parameters. */
1650 bool
1651 function_arg_regno_p (int n)
1653 int i;
1654 for (i = 0; arg_regs[i] != -1; i++)
1655 if (n == arg_regs[i])
1656 return true;
1657 return false;
1660 /* Returns 1 if OP contains a symbol reference */
1663 symbolic_reference_mentioned_p (rtx op)
1665 register const char *fmt;
1666 register int i;
1668 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
1669 return 1;
1671 fmt = GET_RTX_FORMAT (GET_CODE (op));
1672 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
1674 if (fmt[i] == 'E')
1676 register int j;
1678 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
1679 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
1680 return 1;
1683 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
1684 return 1;
1687 return 0;
1690 /* Decide whether we can make a sibling call to a function. DECL is the
1691 declaration of the function being targeted by the call and EXP is the
1692 CALL_EXPR representing the call. */
1694 static bool
1695 bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
1696 tree exp ATTRIBUTE_UNUSED)
1698 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1699 if (fkind != SUBROUTINE)
1700 return false;
1701 if (!TARGET_ID_SHARED_LIBRARY || TARGET_SEP_DATA)
1702 return true;
1704 /* When compiling for ID shared libraries, can't sibcall a local function
1705 from a non-local function, because the local function thinks it does
1706 not need to reload P5 in the prologue, but the sibcall wil pop P5 in the
1707 sibcall epilogue, and we end up with the wrong value in P5. */
1709 if (!flag_unit_at_a_time || decl == NULL)
1710 /* Not enough information. */
1711 return false;
1714 struct cgraph_local_info *this_func, *called_func;
1716 this_func = cgraph_local_info (current_function_decl);
1717 called_func = cgraph_local_info (decl);
1718 return !called_func->local || this_func->local;
1722 /* Emit RTL insns to initialize the variable parts of a trampoline at
1723 TRAMP. FNADDR is an RTX for the address of the function's pure
1724 code. CXT is an RTX for the static chain value for the function. */
1726 void
1727 initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt)
1729 rtx t1 = copy_to_reg (fnaddr);
1730 rtx t2 = copy_to_reg (cxt);
1731 rtx addr;
1732 int i = 0;
1734 if (TARGET_FDPIC)
1736 rtx a = memory_address (Pmode, plus_constant (tramp, 8));
1737 addr = memory_address (Pmode, tramp);
1738 emit_move_insn (gen_rtx_MEM (SImode, addr), a);
1739 i = 8;
1742 addr = memory_address (Pmode, plus_constant (tramp, i + 2));
1743 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
1744 emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16)));
1745 addr = memory_address (Pmode, plus_constant (tramp, i + 6));
1746 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
1748 addr = memory_address (Pmode, plus_constant (tramp, i + 10));
1749 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
1750 emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16)));
1751 addr = memory_address (Pmode, plus_constant (tramp, i + 14));
1752 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
1755 /* Emit insns to move operands[1] into operands[0]. */
1757 void
1758 emit_pic_move (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
1760 rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
1762 gcc_assert (!TARGET_FDPIC || !(reload_in_progress || reload_completed));
1763 if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
1764 operands[1] = force_reg (SImode, operands[1]);
1765 else
1766 operands[1] = legitimize_pic_address (operands[1], temp,
1767 TARGET_FDPIC ? OUR_FDPIC_REG
1768 : pic_offset_table_rtx);
1771 /* Expand a move operation in mode MODE. The operands are in OPERANDS.
1772 Returns true if no further code must be generated, false if the caller
1773 should generate an insn to move OPERANDS[1] to OPERANDS[0]. */
1775 bool
1776 expand_move (rtx *operands, enum machine_mode mode)
1778 rtx op = operands[1];
1779 if ((TARGET_ID_SHARED_LIBRARY || TARGET_FDPIC)
1780 && SYMBOLIC_CONST (op))
1781 emit_pic_move (operands, mode);
1782 else if (mode == SImode && GET_CODE (op) == CONST
1783 && GET_CODE (XEXP (op, 0)) == PLUS
1784 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
1785 && !bfin_legitimate_constant_p (op))
1787 rtx dest = operands[0];
1788 rtx op0, op1;
1789 gcc_assert (!reload_in_progress && !reload_completed);
1790 op = XEXP (op, 0);
1791 op0 = force_reg (mode, XEXP (op, 0));
1792 op1 = XEXP (op, 1);
1793 if (!insn_data[CODE_FOR_addsi3].operand[2].predicate (op1, mode))
1794 op1 = force_reg (mode, op1);
1795 if (GET_CODE (dest) == MEM)
1796 dest = gen_reg_rtx (mode);
1797 emit_insn (gen_addsi3 (dest, op0, op1));
1798 if (dest == operands[0])
1799 return true;
1800 operands[1] = dest;
1802 /* Don't generate memory->memory or constant->memory moves, go through a
1803 register */
1804 else if ((reload_in_progress | reload_completed) == 0
1805 && GET_CODE (operands[0]) == MEM
1806 && GET_CODE (operands[1]) != REG)
1807 operands[1] = force_reg (mode, operands[1]);
1808 return false;
1811 /* Split one or more DImode RTL references into pairs of SImode
1812 references. The RTL can be REG, offsettable MEM, integer constant, or
1813 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
1814 split and "num" is its length. lo_half and hi_half are output arrays
1815 that parallel "operands". */
1817 void
1818 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
1820 while (num--)
1822 rtx op = operands[num];
1824 /* simplify_subreg refuse to split volatile memory addresses,
1825 but we still have to handle it. */
1826 if (GET_CODE (op) == MEM)
1828 lo_half[num] = adjust_address (op, SImode, 0);
1829 hi_half[num] = adjust_address (op, SImode, 4);
1831 else
1833 lo_half[num] = simplify_gen_subreg (SImode, op,
1834 GET_MODE (op) == VOIDmode
1835 ? DImode : GET_MODE (op), 0);
1836 hi_half[num] = simplify_gen_subreg (SImode, op,
1837 GET_MODE (op) == VOIDmode
1838 ? DImode : GET_MODE (op), 4);
1843 bool
1844 bfin_longcall_p (rtx op, int call_cookie)
1846 gcc_assert (GET_CODE (op) == SYMBOL_REF);
1847 if (call_cookie & CALL_SHORT)
1848 return 0;
1849 if (call_cookie & CALL_LONG)
1850 return 1;
1851 if (TARGET_LONG_CALLS)
1852 return 1;
1853 return 0;
1856 /* Expand a call instruction. FNADDR is the call target, RETVAL the return value.
1857 COOKIE is a CONST_INT holding the call_cookie prepared init_cumulative_args.
1858 SIBCALL is nonzero if this is a sibling call. */
1860 void
1861 bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
1863 rtx use = NULL, call;
1864 rtx callee = XEXP (fnaddr, 0);
1865 int nelts = 2 + !!sibcall;
1866 rtx pat;
1867 rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REGNO);
1868 int n;
1870 /* In an untyped call, we can get NULL for operand 2. */
1871 if (cookie == NULL_RTX)
1872 cookie = const0_rtx;
1874 /* Static functions and indirect calls don't need the pic register. */
1875 if (!TARGET_FDPIC && flag_pic
1876 && GET_CODE (callee) == SYMBOL_REF
1877 && !SYMBOL_REF_LOCAL_P (callee))
1878 use_reg (&use, pic_offset_table_rtx);
1880 if (TARGET_FDPIC)
1882 if (GET_CODE (callee) != SYMBOL_REF
1883 || bfin_longcall_p (callee, INTVAL (cookie))
1884 || (GET_CODE (callee) == SYMBOL_REF
1885 && !SYMBOL_REF_LOCAL_P (callee)
1886 && TARGET_INLINE_PLT))
1888 rtx addr = callee;
1889 if (! address_operand (addr, Pmode))
1890 addr = force_reg (Pmode, addr);
1892 fnaddr = gen_reg_rtx (SImode);
1893 emit_insn (gen_load_funcdescsi (fnaddr, addr));
1894 fnaddr = gen_rtx_MEM (Pmode, fnaddr);
1896 picreg = gen_reg_rtx (SImode);
1897 emit_insn (gen_load_funcdescsi (picreg,
1898 plus_constant (addr, 4)));
1901 nelts++;
1903 else if ((!register_no_elim_operand (callee, Pmode)
1904 && GET_CODE (callee) != SYMBOL_REF)
1905 || (GET_CODE (callee) == SYMBOL_REF
1906 && ((TARGET_ID_SHARED_LIBRARY && !TARGET_LEAF_ID_SHARED_LIBRARY)
1907 || bfin_longcall_p (callee, INTVAL (cookie)))))
1909 callee = copy_to_mode_reg (Pmode, callee);
1910 fnaddr = gen_rtx_MEM (Pmode, callee);
1912 call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
1914 if (retval)
1915 call = gen_rtx_SET (VOIDmode, retval, call);
1917 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nelts));
1918 n = 0;
1919 XVECEXP (pat, 0, n++) = call;
1920 if (TARGET_FDPIC)
1921 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, picreg);
1922 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie);
1923 if (sibcall)
1924 XVECEXP (pat, 0, n++) = gen_rtx_RETURN (VOIDmode);
1925 call = emit_call_insn (pat);
1926 if (use)
1927 CALL_INSN_FUNCTION_USAGE (call) = use;
1930 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
1933 hard_regno_mode_ok (int regno, enum machine_mode mode)
1935 /* Allow only dregs to store value of mode HI or QI */
1936 enum reg_class class = REGNO_REG_CLASS (regno);
1938 if (mode == CCmode)
1939 return 0;
1941 if (mode == V2HImode)
1942 return D_REGNO_P (regno);
1943 if (class == CCREGS)
1944 return mode == BImode;
1945 if (mode == PDImode || mode == V2PDImode)
1946 return regno == REG_A0 || regno == REG_A1;
1948 /* Allow all normal 32-bit regs, except REG_M3, in case regclass ever comes
1949 up with a bad register class (such as ALL_REGS) for DImode. */
1950 if (mode == DImode)
1951 return regno < REG_M3;
1953 if (mode == SImode
1954 && TEST_HARD_REG_BIT (reg_class_contents[PROLOGUE_REGS], regno))
1955 return 1;
1957 return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno);
1960 /* Implements target hook vector_mode_supported_p. */
1962 static bool
1963 bfin_vector_mode_supported_p (enum machine_mode mode)
1965 return mode == V2HImode;
1968 /* Return the cost of moving data from a register in class CLASS1 to
1969 one in class CLASS2. A cost of 2 is the default. */
1972 bfin_register_move_cost (enum machine_mode mode,
1973 enum reg_class class1, enum reg_class class2)
1975 /* These need secondary reloads, so they're more expensive. */
1976 if ((class1 == CCREGS && class2 != DREGS)
1977 || (class1 != DREGS && class2 == CCREGS))
1978 return 4;
1980 /* If optimizing for size, always prefer reg-reg over reg-memory moves. */
1981 if (optimize_size)
1982 return 2;
1984 /* There are some stalls involved when moving from a DREG to a different
1985 class reg, and using the value in one of the following instructions.
1986 Attempt to model this by slightly discouraging such moves. */
1987 if (class1 == DREGS && class2 != DREGS)
1988 return 2 * 2;
1990 if (GET_MODE_CLASS (mode) == MODE_INT)
1992 /* Discourage trying to use the accumulators. */
1993 if (TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A0)
1994 || TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A1)
1995 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A0)
1996 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A1))
1997 return 20;
1999 return 2;
2002 /* Return the cost of moving data of mode M between a
2003 register and memory. A value of 2 is the default; this cost is
2004 relative to those in `REGISTER_MOVE_COST'.
2006 ??? In theory L1 memory has single-cycle latency. We should add a switch
2007 that tells the compiler whether we expect to use only L1 memory for the
2008 program; it'll make the costs more accurate. */
2011 bfin_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
2012 enum reg_class class,
2013 int in ATTRIBUTE_UNUSED)
2015 /* Make memory accesses slightly more expensive than any register-register
2016 move. Also, penalize non-DP registers, since they need secondary
2017 reloads to load and store. */
2018 if (! reg_class_subset_p (class, DPREGS))
2019 return 10;
2021 return 8;
2024 /* Inform reload about cases where moving X with a mode MODE to a register in
2025 CLASS requires an extra scratch register. Return the class needed for the
2026 scratch register. */
2028 static enum reg_class
2029 bfin_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x, enum reg_class class,
2030 enum machine_mode mode, secondary_reload_info *sri)
2032 /* If we have HImode or QImode, we can only use DREGS as secondary registers;
2033 in most other cases we can also use PREGS. */
2034 enum reg_class default_class = GET_MODE_SIZE (mode) >= 4 ? DPREGS : DREGS;
2035 enum reg_class x_class = NO_REGS;
2036 enum rtx_code code = GET_CODE (x);
2038 if (code == SUBREG)
2039 x = SUBREG_REG (x), code = GET_CODE (x);
2040 if (REG_P (x))
2042 int regno = REGNO (x);
2043 if (regno >= FIRST_PSEUDO_REGISTER)
2044 regno = reg_renumber[regno];
2046 if (regno == -1)
2047 code = MEM;
2048 else
2049 x_class = REGNO_REG_CLASS (regno);
2052 /* We can be asked to reload (plus (FP) (large_constant)) into a DREG.
2053 This happens as a side effect of register elimination, and we need
2054 a scratch register to do it. */
2055 if (fp_plus_const_operand (x, mode))
2057 rtx op2 = XEXP (x, 1);
2058 int large_constant_p = ! CONST_7BIT_IMM_P (INTVAL (op2));
2060 if (class == PREGS || class == PREGS_CLOBBERED)
2061 return NO_REGS;
2062 /* If destination is a DREG, we can do this without a scratch register
2063 if the constant is valid for an add instruction. */
2064 if ((class == DREGS || class == DPREGS)
2065 && ! large_constant_p)
2066 return NO_REGS;
2067 /* Reloading to anything other than a DREG? Use a PREG scratch
2068 register. */
2069 sri->icode = CODE_FOR_reload_insi;
2070 return NO_REGS;
2073 /* Data can usually be moved freely between registers of most classes.
2074 AREGS are an exception; they can only move to or from another register
2075 in AREGS or one in DREGS. They can also be assigned the constant 0. */
2076 if (x_class == AREGS || x_class == EVEN_AREGS || x_class == ODD_AREGS)
2077 return (class == DREGS || class == AREGS || class == EVEN_AREGS
2078 || class == ODD_AREGS
2079 ? NO_REGS : DREGS);
2081 if (class == AREGS || class == EVEN_AREGS || class == ODD_AREGS)
2083 if (x != const0_rtx && x_class != DREGS)
2084 return DREGS;
2085 else
2086 return NO_REGS;
2089 /* CCREGS can only be moved from/to DREGS. */
2090 if (class == CCREGS && x_class != DREGS)
2091 return DREGS;
2092 if (x_class == CCREGS && class != DREGS)
2093 return DREGS;
2095 /* All registers other than AREGS can load arbitrary constants. The only
2096 case that remains is MEM. */
2097 if (code == MEM)
2098 if (! reg_class_subset_p (class, default_class))
2099 return default_class;
2100 return NO_REGS;
2103 /* Implement TARGET_HANDLE_OPTION. */
2105 static bool
2106 bfin_handle_option (size_t code, const char *arg, int value)
2108 switch (code)
2110 case OPT_mshared_library_id_:
2111 if (value > MAX_LIBRARY_ID)
2112 error ("-mshared-library-id=%s is not between 0 and %d",
2113 arg, MAX_LIBRARY_ID);
2114 bfin_lib_id_given = 1;
2115 return true;
2117 case OPT_mcpu_:
2118 if (strcmp (arg, "bf531") == 0)
2119 bfin_cpu_type = BFIN_CPU_BF531;
2120 else if (strcmp (arg, "bf532") == 0)
2121 bfin_cpu_type = BFIN_CPU_BF532;
2122 else if (strcmp (arg, "bf533") == 0)
2123 bfin_cpu_type = BFIN_CPU_BF533;
2124 else if (strcmp (arg, "bf534") == 0)
2125 bfin_cpu_type = BFIN_CPU_BF534;
2126 else if (strcmp (arg, "bf536") == 0)
2127 bfin_cpu_type = BFIN_CPU_BF536;
2128 else if (strcmp (arg, "bf537") == 0)
2129 bfin_cpu_type = BFIN_CPU_BF537;
2130 else if (strcmp (arg, "bf561") == 0)
2132 warning (0, "bf561 support is incomplete yet.");
2133 bfin_cpu_type = BFIN_CPU_BF561;
2135 else
2136 return false;
2137 return true;
2139 default:
2140 return true;
2144 static struct machine_function *
2145 bfin_init_machine_status (void)
2147 struct machine_function *f;
2149 f = ggc_alloc_cleared (sizeof (struct machine_function));
2151 return f;
2154 /* Implement the macro OVERRIDE_OPTIONS. */
2156 void
2157 override_options (void)
2159 if (TARGET_OMIT_LEAF_FRAME_POINTER)
2160 flag_omit_frame_pointer = 1;
2162 /* Library identification */
2163 if (bfin_lib_id_given && ! TARGET_ID_SHARED_LIBRARY)
2164 error ("-mshared-library-id= specified without -mid-shared-library");
2166 if (TARGET_ID_SHARED_LIBRARY && flag_pic == 0)
2167 flag_pic = 1;
2169 if (stack_limit_rtx && TARGET_STACK_CHECK_L1)
2170 error ("Can't use multiple stack checking methods together.");
2172 if (TARGET_ID_SHARED_LIBRARY && TARGET_FDPIC)
2173 error ("ID shared libraries and FD-PIC mode can't be used together.");
2175 /* Don't allow the user to specify -mid-shared-library and -msep-data
2176 together, as it makes little sense from a user's point of view... */
2177 if (TARGET_SEP_DATA && TARGET_ID_SHARED_LIBRARY)
2178 error ("cannot specify both -msep-data and -mid-shared-library");
2179 /* ... internally, however, it's nearly the same. */
2180 if (TARGET_SEP_DATA)
2181 target_flags |= MASK_ID_SHARED_LIBRARY | MASK_LEAF_ID_SHARED_LIBRARY;
2183 /* There is no single unaligned SI op for PIC code. Sometimes we
2184 need to use ".4byte" and sometimes we need to use ".picptr".
2185 See bfin_assemble_integer for details. */
2186 if (TARGET_FDPIC)
2187 targetm.asm_out.unaligned_op.si = 0;
2189 /* Silently turn off flag_pic if not doing FDPIC or ID shared libraries,
2190 since we don't support it and it'll just break. */
2191 if (flag_pic && !TARGET_FDPIC && !TARGET_ID_SHARED_LIBRARY)
2192 flag_pic = 0;
2194 flag_schedule_insns = 0;
2196 /* Passes after sched2 can break the helpful TImode annotations that
2197 haifa-sched puts on every insn. Just do scheduling in reorg. */
2198 bfin_flag_schedule_insns2 = flag_schedule_insns_after_reload;
2199 flag_schedule_insns_after_reload = 0;
2201 init_machine_status = bfin_init_machine_status;
2204 /* Return the destination address of BRANCH.
2205 We need to use this instead of get_attr_length, because the
2206 cbranch_with_nops pattern conservatively sets its length to 6, and
2207 we still prefer to use shorter sequences. */
2209 static int
2210 branch_dest (rtx branch)
2212 rtx dest;
2213 int dest_uid;
2214 rtx pat = PATTERN (branch);
2215 if (GET_CODE (pat) == PARALLEL)
2216 pat = XVECEXP (pat, 0, 0);
2217 dest = SET_SRC (pat);
2218 if (GET_CODE (dest) == IF_THEN_ELSE)
2219 dest = XEXP (dest, 1);
2220 dest = XEXP (dest, 0);
2221 dest_uid = INSN_UID (dest);
2222 return INSN_ADDRESSES (dest_uid);
2225 /* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates
2226 it's a branch that's predicted taken. */
2228 static int
2229 cbranch_predicted_taken_p (rtx insn)
2231 rtx x = find_reg_note (insn, REG_BR_PROB, 0);
2233 if (x)
2235 int pred_val = INTVAL (XEXP (x, 0));
2237 return pred_val >= REG_BR_PROB_BASE / 2;
2240 return 0;
2243 /* Templates for use by asm_conditional_branch. */
2245 static const char *ccbranch_templates[][3] = {
2246 { "if !cc jump %3;", "if cc jump 4 (bp); jump.s %3;", "if cc jump 6 (bp); jump.l %3;" },
2247 { "if cc jump %3;", "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" },
2248 { "if !cc jump %3 (bp);", "if cc jump 4; jump.s %3;", "if cc jump 6; jump.l %3;" },
2249 { "if cc jump %3 (bp);", "if !cc jump 4; jump.s %3;", "if !cc jump 6; jump.l %3;" },
2252 /* Output INSN, which is a conditional branch instruction with operands
2253 OPERANDS.
2255 We deal with the various forms of conditional branches that can be generated
2256 by bfin_reorg to prevent the hardware from doing speculative loads, by
2257 - emitting a sufficient number of nops, if N_NOPS is nonzero, or
2258 - always emitting the branch as predicted taken, if PREDICT_TAKEN is true.
2259 Either of these is only necessary if the branch is short, otherwise the
2260 template we use ends in an unconditional jump which flushes the pipeline
2261 anyway. */
2263 void
2264 asm_conditional_branch (rtx insn, rtx *operands, int n_nops, int predict_taken)
2266 int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
2267 /* Note : offset for instructions like if cc jmp; jump.[sl] offset
2268 is to be taken from start of if cc rather than jump.
2269 Range for jump.s is (-4094, 4096) instead of (-4096, 4094)
2271 int len = (offset >= -1024 && offset <= 1022 ? 0
2272 : offset >= -4094 && offset <= 4096 ? 1
2273 : 2);
2274 int bp = predict_taken && len == 0 ? 1 : cbranch_predicted_taken_p (insn);
2275 int idx = (bp << 1) | (GET_CODE (operands[0]) == EQ ? BRF : BRT);
2276 output_asm_insn (ccbranch_templates[idx][len], operands);
2277 gcc_assert (n_nops == 0 || !bp);
2278 if (len == 0)
2279 while (n_nops-- > 0)
2280 output_asm_insn ("nop;", NULL);
2283 /* Emit rtl for a comparison operation CMP in mode MODE. Operands have been
2284 stored in bfin_compare_op0 and bfin_compare_op1 already. */
2287 bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED)
2289 enum rtx_code code1, code2;
2290 rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1;
2291 rtx tem = bfin_cc_rtx;
2292 enum rtx_code code = GET_CODE (cmp);
2294 /* If we have a BImode input, then we already have a compare result, and
2295 do not need to emit another comparison. */
2296 if (GET_MODE (op0) == BImode)
2298 gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
2299 tem = op0, code2 = code;
2301 else
2303 switch (code) {
2304 /* bfin has these conditions */
2305 case EQ:
2306 case LT:
2307 case LE:
2308 case LEU:
2309 case LTU:
2310 code1 = code;
2311 code2 = NE;
2312 break;
2313 default:
2314 code1 = reverse_condition (code);
2315 code2 = EQ;
2316 break;
2318 emit_insn (gen_rtx_SET (BImode, tem,
2319 gen_rtx_fmt_ee (code1, BImode, op0, op1)));
2322 return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode));
2325 /* Return nonzero iff C has exactly one bit set if it is interpreted
2326 as a 32-bit constant. */
2329 log2constp (unsigned HOST_WIDE_INT c)
2331 c &= 0xFFFFFFFF;
2332 return c != 0 && (c & (c-1)) == 0;
2335 /* Returns the number of consecutive least significant zeros in the binary
2336 representation of *V.
2337 We modify *V to contain the original value arithmetically shifted right by
2338 the number of zeroes. */
2340 static int
2341 shiftr_zero (HOST_WIDE_INT *v)
2343 unsigned HOST_WIDE_INT tmp = *v;
2344 unsigned HOST_WIDE_INT sgn;
2345 int n = 0;
2347 if (tmp == 0)
2348 return 0;
2350 sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1));
2351 while ((tmp & 0x1) == 0 && n <= 32)
2353 tmp = (tmp >> 1) | sgn;
2354 n++;
2356 *v = tmp;
2357 return n;
2360 /* After reload, split the load of an immediate constant. OPERANDS are the
2361 operands of the movsi_insn pattern which we are splitting. We return
2362 nonzero if we emitted a sequence to load the constant, zero if we emitted
2363 nothing because we want to use the splitter's default sequence. */
2366 split_load_immediate (rtx operands[])
2368 HOST_WIDE_INT val = INTVAL (operands[1]);
2369 HOST_WIDE_INT tmp;
2370 HOST_WIDE_INT shifted = val;
2371 HOST_WIDE_INT shifted_compl = ~val;
2372 int num_zero = shiftr_zero (&shifted);
2373 int num_compl_zero = shiftr_zero (&shifted_compl);
2374 unsigned int regno = REGNO (operands[0]);
2376 /* This case takes care of single-bit set/clear constants, which we could
2377 also implement with BITSET/BITCLR. */
2378 if (num_zero
2379 && shifted >= -32768 && shifted < 65536
2380 && (D_REGNO_P (regno)
2381 || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))
2383 emit_insn (gen_movsi (operands[0], GEN_INT (shifted)));
2384 emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));
2385 return 1;
2388 tmp = val & 0xFFFF;
2389 tmp |= -(tmp & 0x8000);
2391 /* If high word has one bit set or clear, try to use a bit operation. */
2392 if (D_REGNO_P (regno))
2394 if (log2constp (val & 0xFFFF0000))
2396 emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));
2397 emit_insn (gen_iorsi3 (operands[0], operands[0], GEN_INT (val & 0xFFFF0000)));
2398 return 1;
2400 else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)
2402 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2403 emit_insn (gen_andsi3 (operands[0], operands[0], GEN_INT (val | 0xFFFF)));
2407 if (D_REGNO_P (regno))
2409 if (CONST_7BIT_IMM_P (tmp))
2411 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2412 emit_insn (gen_movstricthi_high (operands[0], GEN_INT (val & -65536)));
2413 return 1;
2416 if ((val & 0xFFFF0000) == 0)
2418 emit_insn (gen_movsi (operands[0], const0_rtx));
2419 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2420 return 1;
2423 if ((val & 0xFFFF0000) == 0xFFFF0000)
2425 emit_insn (gen_movsi (operands[0], constm1_rtx));
2426 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2427 return 1;
2431 /* Need DREGs for the remaining case. */
2432 if (regno > REG_R7)
2433 return 0;
2435 if (optimize_size
2436 && num_compl_zero && CONST_7BIT_IMM_P (shifted_compl))
2438 /* If optimizing for size, generate a sequence that has more instructions
2439 but is shorter. */
2440 emit_insn (gen_movsi (operands[0], GEN_INT (shifted_compl)));
2441 emit_insn (gen_ashlsi3 (operands[0], operands[0],
2442 GEN_INT (num_compl_zero)));
2443 emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
2444 return 1;
2446 return 0;
2449 /* Return true if the legitimate memory address for a memory operand of mode
2450 MODE. Return false if not. */
2452 static bool
2453 bfin_valid_add (enum machine_mode mode, HOST_WIDE_INT value)
2455 unsigned HOST_WIDE_INT v = value > 0 ? value : -value;
2456 int sz = GET_MODE_SIZE (mode);
2457 int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2;
2458 /* The usual offsettable_memref machinery doesn't work so well for this
2459 port, so we deal with the problem here. */
2460 if (value > 0 && sz == 8)
2461 v += 4;
2462 return (v & ~(0x7fff << shift)) == 0;
2465 static bool
2466 bfin_valid_reg_p (unsigned int regno, int strict, enum machine_mode mode,
2467 enum rtx_code outer_code)
2469 if (strict)
2470 return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH);
2471 else
2472 return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH);
2475 bool
2476 bfin_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
2478 switch (GET_CODE (x)) {
2479 case REG:
2480 if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM))
2481 return true;
2482 break;
2483 case PLUS:
2484 if (REG_P (XEXP (x, 0))
2485 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS)
2486 && ((GET_CODE (XEXP (x, 1)) == UNSPEC && mode == SImode)
2487 || (GET_CODE (XEXP (x, 1)) == CONST_INT
2488 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
2489 return true;
2490 break;
2491 case POST_INC:
2492 case POST_DEC:
2493 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2494 && REG_P (XEXP (x, 0))
2495 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC))
2496 return true;
2497 case PRE_DEC:
2498 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2499 && XEXP (x, 0) == stack_pointer_rtx
2500 && REG_P (XEXP (x, 0))
2501 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC))
2502 return true;
2503 break;
2504 default:
2505 break;
2507 return false;
2510 /* Decide whether we can force certain constants to memory. If we
2511 decide we can't, the caller should be able to cope with it in
2512 another way. */
2514 static bool
2515 bfin_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
2517 /* We have only one class of non-legitimate constants, and our movsi
2518 expander knows how to handle them. Dropping these constants into the
2519 data section would only shift the problem - we'd still get relocs
2520 outside the object, in the data section rather than the text section. */
2521 return true;
2524 /* Ensure that for any constant of the form symbol + offset, the offset
2525 remains within the object. Any other constants are ok.
2526 This ensures that flat binaries never have to deal with relocations
2527 crossing section boundaries. */
2529 bool
2530 bfin_legitimate_constant_p (rtx x)
2532 rtx sym;
2533 HOST_WIDE_INT offset;
2535 if (GET_CODE (x) != CONST)
2536 return true;
2538 x = XEXP (x, 0);
2539 gcc_assert (GET_CODE (x) == PLUS);
2541 sym = XEXP (x, 0);
2542 x = XEXP (x, 1);
2543 if (GET_CODE (sym) != SYMBOL_REF
2544 || GET_CODE (x) != CONST_INT)
2545 return true;
2546 offset = INTVAL (x);
2548 if (SYMBOL_REF_DECL (sym) == 0)
2549 return true;
2550 if (offset < 0
2551 || offset >= int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (sym))))
2552 return false;
2554 return true;
2557 static bool
2558 bfin_rtx_costs (rtx x, int code, int outer_code, int *total)
2560 int cost2 = COSTS_N_INSNS (1);
2561 rtx op0, op1;
2563 switch (code)
2565 case CONST_INT:
2566 if (outer_code == SET || outer_code == PLUS)
2567 *total = CONST_7BIT_IMM_P (INTVAL (x)) ? 0 : cost2;
2568 else if (outer_code == AND)
2569 *total = log2constp (~INTVAL (x)) ? 0 : cost2;
2570 else if (outer_code == LE || outer_code == LT || outer_code == EQ)
2571 *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
2572 else if (outer_code == LEU || outer_code == LTU)
2573 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
2574 else if (outer_code == MULT)
2575 *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
2576 else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
2577 *total = 0;
2578 else if (outer_code == ASHIFT || outer_code == ASHIFTRT
2579 || outer_code == LSHIFTRT)
2580 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
2581 else if (outer_code == IOR || outer_code == XOR)
2582 *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
2583 else
2584 *total = cost2;
2585 return true;
2587 case CONST:
2588 case LABEL_REF:
2589 case SYMBOL_REF:
2590 case CONST_DOUBLE:
2591 *total = COSTS_N_INSNS (2);
2592 return true;
2594 case PLUS:
2595 op0 = XEXP (x, 0);
2596 op1 = XEXP (x, 1);
2597 if (GET_MODE (x) == SImode)
2599 if (GET_CODE (op0) == MULT
2600 && GET_CODE (XEXP (op0, 1)) == CONST_INT)
2602 HOST_WIDE_INT val = INTVAL (XEXP (op0, 1));
2603 if (val == 2 || val == 4)
2605 *total = cost2;
2606 *total += rtx_cost (XEXP (op0, 0), outer_code);
2607 *total += rtx_cost (op1, outer_code);
2608 return true;
2611 *total = cost2;
2612 if (GET_CODE (op0) != REG
2613 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2614 *total += rtx_cost (op0, SET);
2615 #if 0 /* We'd like to do this for accuracy, but it biases the loop optimizer
2616 towards creating too many induction variables. */
2617 if (!reg_or_7bit_operand (op1, SImode))
2618 *total += rtx_cost (op1, SET);
2619 #endif
2621 else if (GET_MODE (x) == DImode)
2623 *total = 6 * cost2;
2624 if (GET_CODE (op1) != CONST_INT
2625 || !CONST_7BIT_IMM_P (INTVAL (op1)))
2626 *total += rtx_cost (op1, PLUS);
2627 if (GET_CODE (op0) != REG
2628 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2629 *total += rtx_cost (op0, PLUS);
2631 return true;
2633 case MINUS:
2634 if (GET_MODE (x) == DImode)
2635 *total = 6 * cost2;
2636 else
2637 *total = cost2;
2638 return true;
2640 case ASHIFT:
2641 case ASHIFTRT:
2642 case LSHIFTRT:
2643 if (GET_MODE (x) == DImode)
2644 *total = 6 * cost2;
2645 else
2646 *total = cost2;
2648 op0 = XEXP (x, 0);
2649 op1 = XEXP (x, 1);
2650 if (GET_CODE (op0) != REG
2651 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2652 *total += rtx_cost (op0, code);
2654 return true;
2656 case IOR:
2657 case AND:
2658 case XOR:
2659 op0 = XEXP (x, 0);
2660 op1 = XEXP (x, 1);
2662 /* Handle special cases of IOR: rotates, ALIGN insns, movstricthi_high. */
2663 if (code == IOR)
2665 if ((GET_CODE (op0) == LSHIFTRT && GET_CODE (op1) == ASHIFT)
2666 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == ZERO_EXTEND)
2667 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT)
2668 || (GET_CODE (op0) == AND && GET_CODE (op1) == CONST_INT))
2670 *total = cost2;
2671 return true;
2675 if (GET_CODE (op0) != REG
2676 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2677 *total += rtx_cost (op0, code);
2679 if (GET_MODE (x) == DImode)
2681 *total = 2 * cost2;
2682 return true;
2684 *total = cost2;
2685 if (GET_MODE (x) != SImode)
2686 return true;
2688 if (code == AND)
2690 if (! rhs_andsi3_operand (XEXP (x, 1), SImode))
2691 *total += rtx_cost (XEXP (x, 1), code);
2693 else
2695 if (! regorlog2_operand (XEXP (x, 1), SImode))
2696 *total += rtx_cost (XEXP (x, 1), code);
2699 return true;
2701 case ZERO_EXTRACT:
2702 case SIGN_EXTRACT:
2703 if (outer_code == SET
2704 && XEXP (x, 1) == const1_rtx
2705 && GET_CODE (XEXP (x, 2)) == CONST_INT)
2707 *total = 2 * cost2;
2708 return true;
2710 /* fall through */
2712 case SIGN_EXTEND:
2713 case ZERO_EXTEND:
2714 *total = cost2;
2715 return true;
2717 case MULT:
2719 op0 = XEXP (x, 0);
2720 op1 = XEXP (x, 1);
2721 if (GET_CODE (op0) == GET_CODE (op1)
2722 && (GET_CODE (op0) == ZERO_EXTEND
2723 || GET_CODE (op0) == SIGN_EXTEND))
2725 *total = COSTS_N_INSNS (1);
2726 op0 = XEXP (op0, 0);
2727 op1 = XEXP (op1, 0);
2729 else if (optimize_size)
2730 *total = COSTS_N_INSNS (1);
2731 else
2732 *total = COSTS_N_INSNS (3);
2734 if (GET_CODE (op0) != REG
2735 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2736 *total += rtx_cost (op0, MULT);
2737 if (GET_CODE (op1) != REG
2738 && (GET_CODE (op1) != SUBREG || GET_CODE (SUBREG_REG (op1)) != REG))
2739 *total += rtx_cost (op1, MULT);
2741 return true;
2743 case UDIV:
2744 case UMOD:
2745 *total = COSTS_N_INSNS (32);
2746 return true;
2748 case VEC_CONCAT:
2749 case VEC_SELECT:
2750 if (outer_code == SET)
2751 *total = cost2;
2752 return true;
2754 default:
2755 return false;
2759 /* Used for communication between {push,pop}_multiple_operation (which
2760 we use not only as a predicate) and the corresponding output functions. */
2761 static int first_preg_to_save, first_dreg_to_save;
2764 push_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2766 int lastdreg = 8, lastpreg = 6;
2767 int i, group;
2769 first_preg_to_save = lastpreg;
2770 first_dreg_to_save = lastdreg;
2771 for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
2773 rtx t = XVECEXP (op, 0, i);
2774 rtx src, dest;
2775 int regno;
2777 if (GET_CODE (t) != SET)
2778 return 0;
2780 src = SET_SRC (t);
2781 dest = SET_DEST (t);
2782 if (GET_CODE (dest) != MEM || ! REG_P (src))
2783 return 0;
2784 dest = XEXP (dest, 0);
2785 if (GET_CODE (dest) != PLUS
2786 || ! REG_P (XEXP (dest, 0))
2787 || REGNO (XEXP (dest, 0)) != REG_SP
2788 || GET_CODE (XEXP (dest, 1)) != CONST_INT
2789 || INTVAL (XEXP (dest, 1)) != -i * 4)
2790 return 0;
2792 regno = REGNO (src);
2793 if (group == 0)
2795 if (D_REGNO_P (regno))
2797 group = 1;
2798 first_dreg_to_save = lastdreg = regno - REG_R0;
2800 else if (regno >= REG_P0 && regno <= REG_P7)
2802 group = 2;
2803 first_preg_to_save = lastpreg = regno - REG_P0;
2805 else
2806 return 0;
2808 continue;
2811 if (group == 1)
2813 if (regno >= REG_P0 && regno <= REG_P7)
2815 group = 2;
2816 first_preg_to_save = lastpreg = regno - REG_P0;
2818 else if (regno != REG_R0 + lastdreg + 1)
2819 return 0;
2820 else
2821 lastdreg++;
2823 else if (group == 2)
2825 if (regno != REG_P0 + lastpreg + 1)
2826 return 0;
2827 lastpreg++;
2830 return 1;
2834 pop_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2836 int lastdreg = 8, lastpreg = 6;
2837 int i, group;
2839 for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
2841 rtx t = XVECEXP (op, 0, i);
2842 rtx src, dest;
2843 int regno;
2845 if (GET_CODE (t) != SET)
2846 return 0;
2848 src = SET_SRC (t);
2849 dest = SET_DEST (t);
2850 if (GET_CODE (src) != MEM || ! REG_P (dest))
2851 return 0;
2852 src = XEXP (src, 0);
2854 if (i == 1)
2856 if (! REG_P (src) || REGNO (src) != REG_SP)
2857 return 0;
2859 else if (GET_CODE (src) != PLUS
2860 || ! REG_P (XEXP (src, 0))
2861 || REGNO (XEXP (src, 0)) != REG_SP
2862 || GET_CODE (XEXP (src, 1)) != CONST_INT
2863 || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
2864 return 0;
2866 regno = REGNO (dest);
2867 if (group == 0)
2869 if (regno == REG_R7)
2871 group = 1;
2872 lastdreg = 7;
2874 else if (regno != REG_P0 + lastpreg - 1)
2875 return 0;
2876 else
2877 lastpreg--;
2879 else if (group == 1)
2881 if (regno != REG_R0 + lastdreg - 1)
2882 return 0;
2883 else
2884 lastdreg--;
2887 first_dreg_to_save = lastdreg;
2888 first_preg_to_save = lastpreg;
2889 return 1;
2892 /* Emit assembly code for one multi-register push described by INSN, with
2893 operands in OPERANDS. */
2895 void
2896 output_push_multiple (rtx insn, rtx *operands)
2898 char buf[80];
2899 int ok;
2901 /* Validate the insn again, and compute first_[dp]reg_to_save. */
2902 ok = push_multiple_operation (PATTERN (insn), VOIDmode);
2903 gcc_assert (ok);
2905 if (first_dreg_to_save == 8)
2906 sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
2907 else if (first_preg_to_save == 6)
2908 sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
2909 else
2910 sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
2911 first_dreg_to_save, first_preg_to_save);
2913 output_asm_insn (buf, operands);
2916 /* Emit assembly code for one multi-register pop described by INSN, with
2917 operands in OPERANDS. */
2919 void
2920 output_pop_multiple (rtx insn, rtx *operands)
2922 char buf[80];
2923 int ok;
2925 /* Validate the insn again, and compute first_[dp]reg_to_save. */
2926 ok = pop_multiple_operation (PATTERN (insn), VOIDmode);
2927 gcc_assert (ok);
2929 if (first_dreg_to_save == 8)
2930 sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
2931 else if (first_preg_to_save == 6)
2932 sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
2933 else
2934 sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
2935 first_dreg_to_save, first_preg_to_save);
2937 output_asm_insn (buf, operands);
2940 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE. */
2942 static void
2943 single_move_for_movmem (rtx dst, rtx src, enum machine_mode mode, HOST_WIDE_INT offset)
2945 rtx scratch = gen_reg_rtx (mode);
2946 rtx srcmem, dstmem;
2948 srcmem = adjust_address_nv (src, mode, offset);
2949 dstmem = adjust_address_nv (dst, mode, offset);
2950 emit_move_insn (scratch, srcmem);
2951 emit_move_insn (dstmem, scratch);
2954 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
2955 alignment ALIGN_EXP. Return true if successful, false if we should fall
2956 back on a different method. */
2958 bool
2959 bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
2961 rtx srcreg, destreg, countreg;
2962 HOST_WIDE_INT align = 0;
2963 unsigned HOST_WIDE_INT count = 0;
2965 if (GET_CODE (align_exp) == CONST_INT)
2966 align = INTVAL (align_exp);
2967 if (GET_CODE (count_exp) == CONST_INT)
2969 count = INTVAL (count_exp);
2970 #if 0
2971 if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
2972 return false;
2973 #endif
2976 /* If optimizing for size, only do single copies inline. */
2977 if (optimize_size)
2979 if (count == 2 && align < 2)
2980 return false;
2981 if (count == 4 && align < 4)
2982 return false;
2983 if (count != 1 && count != 2 && count != 4)
2984 return false;
2986 if (align < 2 && count != 1)
2987 return false;
2989 destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
2990 if (destreg != XEXP (dst, 0))
2991 dst = replace_equiv_address_nv (dst, destreg);
2992 srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
2993 if (srcreg != XEXP (src, 0))
2994 src = replace_equiv_address_nv (src, srcreg);
2996 if (count != 0 && align >= 2)
2998 unsigned HOST_WIDE_INT offset = 0;
3000 if (align >= 4)
3002 if ((count & ~3) == 4)
3004 single_move_for_movmem (dst, src, SImode, offset);
3005 offset = 4;
3007 else if (count & ~3)
3009 HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
3010 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3012 emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
3014 if (count & 2)
3016 single_move_for_movmem (dst, src, HImode, offset);
3017 offset += 2;
3020 else
3022 if ((count & ~1) == 2)
3024 single_move_for_movmem (dst, src, HImode, offset);
3025 offset = 2;
3027 else if (count & ~1)
3029 HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
3030 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3032 emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
3035 if (count & 1)
3037 single_move_for_movmem (dst, src, QImode, offset);
3039 return true;
3041 return false;
3044 /* Compute the alignment for a local variable.
3045 TYPE is the data type, and ALIGN is the alignment that
3046 the object would ordinarily have. The value of this macro is used
3047 instead of that alignment to align the object. */
3050 bfin_local_alignment (tree type, int align)
3052 /* Increasing alignment for (relatively) big types allows the builtin
3053 memcpy can use 32 bit loads/stores. */
3054 if (TYPE_SIZE (type)
3055 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
3056 && (TREE_INT_CST_LOW (TYPE_SIZE (type)) > 8
3057 || TREE_INT_CST_HIGH (TYPE_SIZE (type))) && align < 32)
3058 return 32;
3059 return align;
3062 /* Implement TARGET_SCHED_ISSUE_RATE. */
3064 static int
3065 bfin_issue_rate (void)
3067 return 3;
3070 static int
3071 bfin_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
3073 enum attr_type insn_type, dep_insn_type;
3074 int dep_insn_code_number;
3076 /* Anti and output dependencies have zero cost. */
3077 if (REG_NOTE_KIND (link) != 0)
3078 return 0;
3080 dep_insn_code_number = recog_memoized (dep_insn);
3082 /* If we can't recognize the insns, we can't really do anything. */
3083 if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
3084 return cost;
3086 insn_type = get_attr_type (insn);
3087 dep_insn_type = get_attr_type (dep_insn);
3089 if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)
3091 rtx pat = PATTERN (dep_insn);
3092 rtx dest = SET_DEST (pat);
3093 rtx src = SET_SRC (pat);
3094 if (! ADDRESS_REGNO_P (REGNO (dest))
3095 || ! (MEM_P (src) || D_REGNO_P (REGNO (src))))
3096 return cost;
3097 return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);
3100 return cost;
3104 /* Increment the counter for the number of loop instructions in the
3105 current function. */
3107 void
3108 bfin_hardware_loop (void)
3110 cfun->machine->has_hardware_loops++;
3113 /* Maximum loop nesting depth. */
3114 #define MAX_LOOP_DEPTH 2
3116 /* Maximum size of a loop. */
3117 #define MAX_LOOP_LENGTH 2042
3119 /* Maximum distance of the LSETUP instruction from the loop start. */
3120 #define MAX_LSETUP_DISTANCE 30
3122 /* We need to keep a vector of loops */
3123 typedef struct loop_info *loop_info;
3124 DEF_VEC_P (loop_info);
3125 DEF_VEC_ALLOC_P (loop_info,heap);
3127 /* Information about a loop we have found (or are in the process of
3128 finding). */
3129 struct loop_info GTY (())
3131 /* loop number, for dumps */
3132 int loop_no;
3134 /* All edges that jump into and out of the loop. */
3135 VEC(edge,gc) *incoming;
3137 /* We can handle two cases: all incoming edges have the same destination
3138 block, or all incoming edges have the same source block. These two
3139 members are set to the common source or destination we found, or NULL
3140 if different blocks were found. If both are NULL the loop can't be
3141 optimized. */
3142 basic_block incoming_src;
3143 basic_block incoming_dest;
3145 /* First block in the loop. This is the one branched to by the loop_end
3146 insn. */
3147 basic_block head;
3149 /* Last block in the loop (the one with the loop_end insn). */
3150 basic_block tail;
3152 /* The successor block of the loop. This is the one the loop_end insn
3153 falls into. */
3154 basic_block successor;
3156 /* The last instruction in the tail. */
3157 rtx last_insn;
3159 /* The loop_end insn. */
3160 rtx loop_end;
3162 /* The iteration register. */
3163 rtx iter_reg;
3165 /* The new initialization insn. */
3166 rtx init;
3168 /* The new initialization instruction. */
3169 rtx loop_init;
3171 /* The new label placed at the beginning of the loop. */
3172 rtx start_label;
3174 /* The new label placed at the end of the loop. */
3175 rtx end_label;
3177 /* The length of the loop. */
3178 int length;
3180 /* The nesting depth of the loop. */
3181 int depth;
3183 /* Nonzero if we can't optimize this loop. */
3184 int bad;
3186 /* True if we have visited this loop. */
3187 int visited;
3189 /* True if this loop body clobbers any of LC0, LT0, or LB0. */
3190 int clobber_loop0;
3192 /* True if this loop body clobbers any of LC1, LT1, or LB1. */
3193 int clobber_loop1;
3195 /* Next loop in the graph. */
3196 struct loop_info *next;
3198 /* Immediate outer loop of this loop. */
3199 struct loop_info *outer;
3201 /* Vector of blocks only within the loop, including those within
3202 inner loops. */
3203 VEC (basic_block,heap) *blocks;
3205 /* Same information in a bitmap. */
3206 bitmap block_bitmap;
3208 /* Vector of inner loops within this loop */
3209 VEC (loop_info,heap) *loops;
3212 static void
3213 bfin_dump_loops (loop_info loops)
3215 loop_info loop;
3217 for (loop = loops; loop; loop = loop->next)
3219 loop_info i;
3220 basic_block b;
3221 unsigned ix;
3223 fprintf (dump_file, ";; loop %d: ", loop->loop_no);
3224 if (loop->bad)
3225 fprintf (dump_file, "(bad) ");
3226 fprintf (dump_file, "{head:%d, depth:%d}", loop->head->index, loop->depth);
3228 fprintf (dump_file, " blocks: [ ");
3229 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, b); ix++)
3230 fprintf (dump_file, "%d ", b->index);
3231 fprintf (dump_file, "] ");
3233 fprintf (dump_file, " inner loops: [ ");
3234 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, i); ix++)
3235 fprintf (dump_file, "%d ", i->loop_no);
3236 fprintf (dump_file, "]\n");
3238 fprintf (dump_file, "\n");
3241 /* Scan the blocks of LOOP (and its inferiors) looking for basic block
3242 BB. Return true, if we find it. */
3244 static bool
3245 bfin_bb_in_loop (loop_info loop, basic_block bb)
3247 return bitmap_bit_p (loop->block_bitmap, bb->index);
3250 /* Scan the blocks of LOOP (and its inferiors) looking for uses of
3251 REG. Return true, if we find any. Don't count the loop's loop_end
3252 insn if it matches LOOP_END. */
3254 static bool
3255 bfin_scan_loop (loop_info loop, rtx reg, rtx loop_end)
3257 unsigned ix;
3258 basic_block bb;
3260 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
3262 rtx insn;
3264 for (insn = BB_HEAD (bb);
3265 insn != NEXT_INSN (BB_END (bb));
3266 insn = NEXT_INSN (insn))
3268 if (!INSN_P (insn))
3269 continue;
3270 if (insn == loop_end)
3271 continue;
3272 if (reg_mentioned_p (reg, PATTERN (insn)))
3273 return true;
3276 return false;
3279 /* Estimate the length of INSN conservatively. */
3281 static int
3282 length_for_loop (rtx insn)
3284 int length = 0;
3285 if (JUMP_P (insn) && any_condjump_p (insn) && !optimize_size)
3287 if (TARGET_CSYNC_ANOMALY)
3288 length = 8;
3289 else if (TARGET_SPECLD_ANOMALY)
3290 length = 6;
3292 else if (LABEL_P (insn))
3294 if (TARGET_CSYNC_ANOMALY)
3295 length = 4;
3298 if (INSN_P (insn))
3299 length += get_attr_length (insn);
3301 return length;
3304 /* Optimize LOOP. */
3306 static void
3307 bfin_optimize_loop (loop_info loop)
3309 basic_block bb;
3310 loop_info inner;
3311 rtx insn, init_insn, last_insn, nop_insn;
3312 rtx loop_init, start_label, end_label;
3313 rtx reg_lc0, reg_lc1, reg_lt0, reg_lt1, reg_lb0, reg_lb1;
3314 rtx iter_reg;
3315 rtx lc_reg, lt_reg, lb_reg;
3316 rtx seq, seq_end;
3317 int length;
3318 unsigned ix;
3319 int inner_depth = 0;
3321 if (loop->visited)
3322 return;
3324 loop->visited = 1;
3326 if (loop->bad)
3328 if (dump_file)
3329 fprintf (dump_file, ";; loop %d bad when found\n", loop->loop_no);
3330 goto bad_loop;
3333 /* Every loop contains in its list of inner loops every loop nested inside
3334 it, even if there are intermediate loops. This works because we're doing
3335 a depth-first search here and never visit a loop more than once. */
3336 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, inner); ix++)
3338 bfin_optimize_loop (inner);
3340 if (!inner->bad && inner_depth < inner->depth)
3342 inner_depth = inner->depth;
3344 loop->clobber_loop0 |= inner->clobber_loop0;
3345 loop->clobber_loop1 |= inner->clobber_loop1;
3349 loop->depth = inner_depth + 1;
3350 if (loop->depth > MAX_LOOP_DEPTH)
3352 if (dump_file)
3353 fprintf (dump_file, ";; loop %d too deep\n", loop->loop_no);
3354 goto bad_loop;
3357 /* Get the loop iteration register. */
3358 iter_reg = loop->iter_reg;
3360 if (!DPREG_P (iter_reg))
3362 if (dump_file)
3363 fprintf (dump_file, ";; loop %d iteration count NOT in PREG or DREG\n",
3364 loop->loop_no);
3365 goto bad_loop;
3368 if (loop->incoming_src)
3370 /* Make sure the predecessor is before the loop start label, as required by
3371 the LSETUP instruction. */
3372 length = 0;
3373 for (insn = BB_END (loop->incoming_src);
3374 insn && insn != loop->start_label;
3375 insn = NEXT_INSN (insn))
3376 length += length_for_loop (insn);
3378 if (!insn)
3380 if (dump_file)
3381 fprintf (dump_file, ";; loop %d lsetup not before loop_start\n",
3382 loop->loop_no);
3383 goto bad_loop;
3386 if (length > MAX_LSETUP_DISTANCE)
3388 if (dump_file)
3389 fprintf (dump_file, ";; loop %d lsetup too far away\n", loop->loop_no);
3390 goto bad_loop;
3394 /* Check if start_label appears before loop_end and calculate the
3395 offset between them. We calculate the length of instructions
3396 conservatively. */
3397 length = 0;
3398 for (insn = loop->start_label;
3399 insn && insn != loop->loop_end;
3400 insn = NEXT_INSN (insn))
3401 length += length_for_loop (insn);
3403 if (!insn)
3405 if (dump_file)
3406 fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
3407 loop->loop_no);
3408 goto bad_loop;
3411 loop->length = length;
3412 if (loop->length > MAX_LOOP_LENGTH)
3414 if (dump_file)
3415 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
3416 goto bad_loop;
3419 /* Scan all the blocks to make sure they don't use iter_reg. */
3420 if (bfin_scan_loop (loop, iter_reg, loop->loop_end))
3422 if (dump_file)
3423 fprintf (dump_file, ";; loop %d uses iterator\n", loop->loop_no);
3424 goto bad_loop;
3427 /* Scan all the insns to see if the loop body clobber
3428 any hardware loop registers. */
3430 reg_lc0 = gen_rtx_REG (SImode, REG_LC0);
3431 reg_lc1 = gen_rtx_REG (SImode, REG_LC1);
3432 reg_lt0 = gen_rtx_REG (SImode, REG_LT0);
3433 reg_lt1 = gen_rtx_REG (SImode, REG_LT1);
3434 reg_lb0 = gen_rtx_REG (SImode, REG_LB0);
3435 reg_lb1 = gen_rtx_REG (SImode, REG_LB1);
3437 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
3439 rtx insn;
3441 for (insn = BB_HEAD (bb);
3442 insn != NEXT_INSN (BB_END (bb));
3443 insn = NEXT_INSN (insn))
3445 if (!INSN_P (insn))
3446 continue;
3448 if (reg_set_p (reg_lc0, insn)
3449 || reg_set_p (reg_lt0, insn)
3450 || reg_set_p (reg_lb0, insn))
3451 loop->clobber_loop0 = 1;
3453 if (reg_set_p (reg_lc1, insn)
3454 || reg_set_p (reg_lt1, insn)
3455 || reg_set_p (reg_lb1, insn))
3456 loop->clobber_loop1 |= 1;
3460 if ((loop->clobber_loop0 && loop->clobber_loop1)
3461 || (loop->depth == MAX_LOOP_DEPTH && loop->clobber_loop0))
3463 loop->depth = MAX_LOOP_DEPTH + 1;
3464 if (dump_file)
3465 fprintf (dump_file, ";; loop %d no loop reg available\n",
3466 loop->loop_no);
3467 goto bad_loop;
3470 /* There should be an instruction before the loop_end instruction
3471 in the same basic block. And the instruction must not be
3472 - JUMP
3473 - CONDITIONAL BRANCH
3474 - CALL
3475 - CSYNC
3476 - SSYNC
3477 - Returns (RTS, RTN, etc.) */
3479 bb = loop->tail;
3480 last_insn = PREV_INSN (loop->loop_end);
3482 while (1)
3484 for (; last_insn != PREV_INSN (BB_HEAD (bb));
3485 last_insn = PREV_INSN (last_insn))
3486 if (INSN_P (last_insn))
3487 break;
3489 if (last_insn != PREV_INSN (BB_HEAD (bb)))
3490 break;
3492 if (single_pred_p (bb)
3493 && single_pred (bb) != ENTRY_BLOCK_PTR)
3495 bb = single_pred (bb);
3496 last_insn = BB_END (bb);
3497 continue;
3499 else
3501 last_insn = NULL_RTX;
3502 break;
3506 if (!last_insn)
3508 if (dump_file)
3509 fprintf (dump_file, ";; loop %d has no last instruction\n",
3510 loop->loop_no);
3511 goto bad_loop;
3514 if (JUMP_P (last_insn))
3516 loop_info inner = bb->aux;
3517 if (inner
3518 && inner->outer == loop
3519 && inner->loop_end == last_insn
3520 && inner->depth == 1)
3521 /* This jump_insn is the exact loop_end of an inner loop
3522 and to be optimized away. So use the inner's last_insn. */
3523 last_insn = inner->last_insn;
3524 else
3526 if (dump_file)
3527 fprintf (dump_file, ";; loop %d has bad last instruction\n",
3528 loop->loop_no);
3529 goto bad_loop;
3532 else if (CALL_P (last_insn)
3533 || (GET_CODE (PATTERN (last_insn)) != SEQUENCE
3534 && get_attr_type (last_insn) == TYPE_SYNC)
3535 || recog_memoized (last_insn) == CODE_FOR_return_internal)
3537 if (dump_file)
3538 fprintf (dump_file, ";; loop %d has bad last instruction\n",
3539 loop->loop_no);
3540 goto bad_loop;
3543 if (GET_CODE (PATTERN (last_insn)) == ASM_INPUT
3544 || asm_noperands (PATTERN (last_insn)) >= 0
3545 || (GET_CODE (PATTERN (last_insn)) != SEQUENCE
3546 && get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI))
3548 nop_insn = emit_insn_after (gen_nop (), last_insn);
3549 last_insn = nop_insn;
3552 loop->last_insn = last_insn;
3554 /* The loop is good for replacement. */
3555 start_label = loop->start_label;
3556 end_label = gen_label_rtx ();
3557 iter_reg = loop->iter_reg;
3559 if (loop->depth == 1 && !loop->clobber_loop1)
3561 lc_reg = reg_lc1;
3562 lt_reg = reg_lt1;
3563 lb_reg = reg_lb1;
3564 loop->clobber_loop1 = 1;
3566 else
3568 lc_reg = reg_lc0;
3569 lt_reg = reg_lt0;
3570 lb_reg = reg_lb0;
3571 loop->clobber_loop0 = 1;
3574 /* If iter_reg is a DREG, we need generate an instruction to load
3575 the loop count into LC register. */
3576 if (D_REGNO_P (REGNO (iter_reg)))
3578 init_insn = gen_movsi (lc_reg, iter_reg);
3579 loop_init = gen_lsetup_without_autoinit (lt_reg, start_label,
3580 lb_reg, end_label,
3581 lc_reg);
3583 else if (P_REGNO_P (REGNO (iter_reg)))
3585 init_insn = NULL_RTX;
3586 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
3587 lb_reg, end_label,
3588 lc_reg, iter_reg);
3590 else
3591 gcc_unreachable ();
3593 loop->init = init_insn;
3594 loop->end_label = end_label;
3595 loop->loop_init = loop_init;
3597 if (dump_file)
3599 fprintf (dump_file, ";; replacing loop %d initializer with\n",
3600 loop->loop_no);
3601 print_rtl_single (dump_file, loop->loop_init);
3602 fprintf (dump_file, ";; replacing loop %d terminator with\n",
3603 loop->loop_no);
3604 print_rtl_single (dump_file, loop->loop_end);
3607 start_sequence ();
3609 if (loop->init != NULL_RTX)
3610 emit_insn (loop->init);
3611 seq_end = emit_insn (loop->loop_init);
3613 seq = get_insns ();
3614 end_sequence ();
3616 if (loop->incoming_src)
3618 rtx prev = BB_END (loop->incoming_src);
3619 if (VEC_length (edge, loop->incoming) > 1
3620 || !(VEC_last (edge, loop->incoming)->flags & EDGE_FALLTHRU))
3622 gcc_assert (JUMP_P (prev));
3623 prev = PREV_INSN (prev);
3625 emit_insn_after (seq, prev);
3627 else
3629 basic_block new_bb;
3630 edge e;
3631 edge_iterator ei;
3633 if (loop->head != loop->incoming_dest)
3635 FOR_EACH_EDGE (e, ei, loop->head->preds)
3637 if (e->flags & EDGE_FALLTHRU)
3639 rtx newjump = gen_jump (loop->start_label);
3640 emit_insn_before (newjump, BB_HEAD (loop->head));
3641 new_bb = create_basic_block (newjump, newjump, loop->head->prev_bb);
3642 gcc_assert (new_bb = loop->head->prev_bb);
3643 break;
3648 emit_insn_before (seq, BB_HEAD (loop->head));
3649 seq = emit_label_before (gen_label_rtx (), seq);
3651 new_bb = create_basic_block (seq, seq_end, loop->head->prev_bb);
3652 FOR_EACH_EDGE (e, ei, loop->incoming)
3654 if (!(e->flags & EDGE_FALLTHRU)
3655 || e->dest != loop->head)
3656 redirect_edge_and_branch_force (e, new_bb);
3657 else
3658 redirect_edge_succ (e, new_bb);
3662 delete_insn (loop->loop_end);
3663 /* Insert the loop end label before the last instruction of the loop. */
3664 emit_label_before (loop->end_label, loop->last_insn);
3666 return;
3668 bad_loop:
3670 if (dump_file)
3671 fprintf (dump_file, ";; loop %d is bad\n", loop->loop_no);
3673 loop->bad = 1;
3675 if (DPREG_P (loop->iter_reg))
3677 /* If loop->iter_reg is a DREG or PREG, we can split it here
3678 without scratch register. */
3679 rtx insn;
3681 emit_insn_before (gen_addsi3 (loop->iter_reg,
3682 loop->iter_reg,
3683 constm1_rtx),
3684 loop->loop_end);
3686 emit_insn_before (gen_cmpsi (loop->iter_reg, const0_rtx),
3687 loop->loop_end);
3689 insn = emit_jump_insn_before (gen_bne (loop->start_label),
3690 loop->loop_end);
3692 JUMP_LABEL (insn) = loop->start_label;
3693 LABEL_NUSES (loop->start_label)++;
3694 delete_insn (loop->loop_end);
3698 /* Called from bfin_reorg_loops when a potential loop end is found. LOOP is
3699 a newly set up structure describing the loop, it is this function's
3700 responsibility to fill most of it. TAIL_BB and TAIL_INSN point to the
3701 loop_end insn and its enclosing basic block. */
3703 static void
3704 bfin_discover_loop (loop_info loop, basic_block tail_bb, rtx tail_insn)
3706 unsigned dwork = 0;
3707 basic_block bb;
3708 VEC (basic_block,heap) *works = VEC_alloc (basic_block,heap,20);
3710 loop->tail = tail_bb;
3711 loop->head = BRANCH_EDGE (tail_bb)->dest;
3712 loop->successor = FALLTHRU_EDGE (tail_bb)->dest;
3713 loop->loop_end = tail_insn;
3714 loop->last_insn = NULL_RTX;
3715 loop->iter_reg = SET_DEST (XVECEXP (PATTERN (tail_insn), 0, 1));
3716 loop->depth = loop->length = 0;
3717 loop->visited = 0;
3718 loop->clobber_loop0 = loop->clobber_loop1 = 0;
3719 loop->outer = NULL;
3720 loop->loops = NULL;
3721 loop->incoming = VEC_alloc (edge, gc, 2);
3722 loop->init = loop->loop_init = NULL_RTX;
3723 loop->start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (tail_insn), 0, 0)), 1), 0);
3724 loop->end_label = NULL_RTX;
3725 loop->bad = 0;
3727 VEC_safe_push (basic_block, heap, works, loop->head);
3729 while (VEC_iterate (basic_block, works, dwork++, bb))
3731 edge e;
3732 edge_iterator ei;
3733 if (bb == EXIT_BLOCK_PTR)
3735 /* We've reached the exit block. The loop must be bad. */
3736 if (dump_file)
3737 fprintf (dump_file,
3738 ";; Loop is bad - reached exit block while scanning\n");
3739 loop->bad = 1;
3740 break;
3743 if (bitmap_bit_p (loop->block_bitmap, bb->index))
3744 continue;
3746 /* We've not seen this block before. Add it to the loop's
3747 list and then add each successor to the work list. */
3749 VEC_safe_push (basic_block, heap, loop->blocks, bb);
3750 bitmap_set_bit (loop->block_bitmap, bb->index);
3752 if (bb != tail_bb)
3754 FOR_EACH_EDGE (e, ei, bb->succs)
3756 basic_block succ = EDGE_SUCC (bb, ei.index)->dest;
3757 if (!REGNO_REG_SET_P (df_get_live_in (succ),
3758 REGNO (loop->iter_reg)))
3759 continue;
3760 if (!VEC_space (basic_block, works, 1))
3762 if (dwork)
3764 VEC_block_remove (basic_block, works, 0, dwork);
3765 dwork = 0;
3767 else
3768 VEC_reserve (basic_block, heap, works, 1);
3770 VEC_quick_push (basic_block, works, succ);
3775 /* Find the predecessor, and make sure nothing else jumps into this loop. */
3776 if (!loop->bad)
3778 int pass, retry;
3779 for (dwork = 0; VEC_iterate (basic_block, loop->blocks, dwork, bb); dwork++)
3781 edge e;
3782 edge_iterator ei;
3783 FOR_EACH_EDGE (e, ei, bb->preds)
3785 basic_block pred = e->src;
3787 if (!bfin_bb_in_loop (loop, pred))
3789 if (dump_file)
3790 fprintf (dump_file, ";; Loop %d: incoming edge %d -> %d\n",
3791 loop->loop_no, pred->index,
3792 e->dest->index);
3793 VEC_safe_push (edge, gc, loop->incoming, e);
3798 for (pass = 0, retry = 1; retry && pass < 2; pass++)
3800 edge e;
3801 edge_iterator ei;
3802 bool first = true;
3803 retry = 0;
3805 FOR_EACH_EDGE (e, ei, loop->incoming)
3807 if (first)
3809 loop->incoming_src = e->src;
3810 loop->incoming_dest = e->dest;
3811 first = false;
3813 else
3815 if (e->dest != loop->incoming_dest)
3816 loop->incoming_dest = NULL;
3817 if (e->src != loop->incoming_src)
3818 loop->incoming_src = NULL;
3820 if (loop->incoming_src == NULL && loop->incoming_dest == NULL)
3822 if (pass == 0)
3824 if (dump_file)
3825 fprintf (dump_file,
3826 ";; retrying loop %d with forwarder blocks\n",
3827 loop->loop_no);
3828 retry = 1;
3829 break;
3831 loop->bad = 1;
3832 if (dump_file)
3833 fprintf (dump_file,
3834 ";; can't find suitable entry for loop %d\n",
3835 loop->loop_no);
3836 goto out;
3839 if (retry)
3841 retry = 0;
3842 FOR_EACH_EDGE (e, ei, loop->incoming)
3844 if (forwarder_block_p (e->src))
3846 edge e2;
3847 edge_iterator ei2;
3849 if (dump_file)
3850 fprintf (dump_file,
3851 ";; Adding forwarder block %d to loop %d and retrying\n",
3852 e->src->index, loop->loop_no);
3853 VEC_safe_push (basic_block, heap, loop->blocks, e->src);
3854 bitmap_set_bit (loop->block_bitmap, e->src->index);
3855 FOR_EACH_EDGE (e2, ei2, e->src->preds)
3856 VEC_safe_push (edge, gc, loop->incoming, e2);
3857 VEC_unordered_remove (edge, loop->incoming, ei.index);
3858 retry = 1;
3859 break;
3866 out:
3867 VEC_free (basic_block, heap, works);
3870 /* Analyze the structure of the loops in the current function. Use STACK
3871 for bitmap allocations. Returns all the valid candidates for hardware
3872 loops found in this function. */
3873 static loop_info
3874 bfin_discover_loops (bitmap_obstack *stack, FILE *dump_file)
3876 loop_info loops = NULL;
3877 loop_info loop;
3878 basic_block bb;
3879 bitmap tmp_bitmap;
3880 int nloops = 0;
3882 /* Find all the possible loop tails. This means searching for every
3883 loop_end instruction. For each one found, create a loop_info
3884 structure and add the head block to the work list. */
3885 FOR_EACH_BB (bb)
3887 rtx tail = BB_END (bb);
3889 while (GET_CODE (tail) == NOTE)
3890 tail = PREV_INSN (tail);
3892 bb->aux = NULL;
3894 if (INSN_P (tail) && recog_memoized (tail) == CODE_FOR_loop_end)
3896 /* A possible loop end */
3898 loop = XNEW (struct loop_info);
3899 loop->next = loops;
3900 loops = loop;
3901 loop->loop_no = nloops++;
3902 loop->blocks = VEC_alloc (basic_block, heap, 20);
3903 loop->block_bitmap = BITMAP_ALLOC (stack);
3904 bb->aux = loop;
3906 if (dump_file)
3908 fprintf (dump_file, ";; potential loop %d ending at\n",
3909 loop->loop_no);
3910 print_rtl_single (dump_file, tail);
3913 bfin_discover_loop (loop, bb, tail);
3917 tmp_bitmap = BITMAP_ALLOC (stack);
3918 /* Compute loop nestings. */
3919 for (loop = loops; loop; loop = loop->next)
3921 loop_info other;
3922 if (loop->bad)
3923 continue;
3925 for (other = loop->next; other; other = other->next)
3927 if (other->bad)
3928 continue;
3930 bitmap_and (tmp_bitmap, other->block_bitmap, loop->block_bitmap);
3931 if (bitmap_empty_p (tmp_bitmap))
3932 continue;
3933 if (bitmap_equal_p (tmp_bitmap, other->block_bitmap))
3935 other->outer = loop;
3936 VEC_safe_push (loop_info, heap, loop->loops, other);
3938 else if (bitmap_equal_p (tmp_bitmap, loop->block_bitmap))
3940 loop->outer = other;
3941 VEC_safe_push (loop_info, heap, other->loops, loop);
3943 else
3945 if (dump_file)
3946 fprintf (dump_file,
3947 ";; can't find suitable nesting for loops %d and %d\n",
3948 loop->loop_no, other->loop_no);
3949 loop->bad = other->bad = 1;
3953 BITMAP_FREE (tmp_bitmap);
3955 return loops;
3958 /* Free up the loop structures in LOOPS. */
3959 static void
3960 free_loops (loop_info loops)
3962 while (loops)
3964 loop_info loop = loops;
3965 loops = loop->next;
3966 VEC_free (loop_info, heap, loop->loops);
3967 VEC_free (basic_block, heap, loop->blocks);
3968 BITMAP_FREE (loop->block_bitmap);
3969 XDELETE (loop);
3973 #define BB_AUX_INDEX(BB) ((unsigned)(BB)->aux)
3975 /* The taken-branch edge from the loop end can actually go forward. Since the
3976 Blackfin's LSETUP instruction requires that the loop end be after the loop
3977 start, try to reorder a loop's basic blocks when we find such a case. */
3978 static void
3979 bfin_reorder_loops (loop_info loops, FILE *dump_file)
3981 basic_block bb;
3982 loop_info loop;
3984 FOR_EACH_BB (bb)
3985 bb->aux = NULL;
3986 cfg_layout_initialize (0);
3988 for (loop = loops; loop; loop = loop->next)
3990 unsigned index;
3991 basic_block bb;
3992 edge e;
3993 edge_iterator ei;
3995 if (loop->bad)
3996 continue;
3998 /* Recreate an index for basic blocks that represents their order. */
3999 for (bb = ENTRY_BLOCK_PTR->next_bb, index = 0;
4000 bb != EXIT_BLOCK_PTR;
4001 bb = bb->next_bb, index++)
4002 bb->aux = (PTR) index;
4004 if (BB_AUX_INDEX (loop->head) < BB_AUX_INDEX (loop->tail))
4005 continue;
4007 FOR_EACH_EDGE (e, ei, loop->head->succs)
4009 if (bitmap_bit_p (loop->block_bitmap, e->dest->index)
4010 && BB_AUX_INDEX (e->dest) < BB_AUX_INDEX (loop->tail))
4012 basic_block start_bb = e->dest;
4013 basic_block start_prev_bb = start_bb->prev_bb;
4015 if (dump_file)
4016 fprintf (dump_file, ";; Moving block %d before block %d\n",
4017 loop->head->index, start_bb->index);
4018 loop->head->prev_bb->next_bb = loop->head->next_bb;
4019 loop->head->next_bb->prev_bb = loop->head->prev_bb;
4021 loop->head->prev_bb = start_prev_bb;
4022 loop->head->next_bb = start_bb;
4023 start_prev_bb->next_bb = start_bb->prev_bb = loop->head;
4024 break;
4027 loops = loops->next;
4030 FOR_EACH_BB (bb)
4032 if (bb->next_bb != EXIT_BLOCK_PTR)
4033 bb->aux = bb->next_bb;
4034 else
4035 bb->aux = NULL;
4037 cfg_layout_finalize ();
4038 df_analyze ();
4041 /* Run from machine_dependent_reorg, this pass looks for doloop_end insns
4042 and tries to rewrite the RTL of these loops so that proper Blackfin
4043 hardware loops are generated. */
4045 static void
4046 bfin_reorg_loops (FILE *dump_file)
4048 loop_info loops = NULL;
4049 loop_info loop;
4050 basic_block bb;
4051 bitmap_obstack stack;
4053 bitmap_obstack_initialize (&stack);
4055 if (dump_file)
4056 fprintf (dump_file, ";; Find loops, first pass\n\n");
4058 loops = bfin_discover_loops (&stack, dump_file);
4060 if (dump_file)
4061 bfin_dump_loops (loops);
4063 bfin_reorder_loops (loops, dump_file);
4064 free_loops (loops);
4066 if (dump_file)
4067 fprintf (dump_file, ";; Find loops, second pass\n\n");
4069 loops = bfin_discover_loops (&stack, dump_file);
4070 if (dump_file)
4072 fprintf (dump_file, ";; All loops found:\n\n");
4073 bfin_dump_loops (loops);
4076 /* Now apply the optimizations. */
4077 for (loop = loops; loop; loop = loop->next)
4078 bfin_optimize_loop (loop);
4080 if (dump_file)
4082 fprintf (dump_file, ";; After hardware loops optimization:\n\n");
4083 bfin_dump_loops (loops);
4086 free_loops (loops);
4088 if (dump_file)
4089 print_rtl (dump_file, get_insns ());
4091 FOR_EACH_BB (bb)
4092 bb->aux = NULL;
4095 /* Possibly generate a SEQUENCE out of three insns found in SLOT.
4096 Returns true if we modified the insn chain, false otherwise. */
4097 static bool
4098 gen_one_bundle (rtx slot[3])
4100 gcc_assert (slot[1] != NULL_RTX);
4102 /* Verify that we really can do the multi-issue. */
4103 if (slot[0])
4105 rtx t = NEXT_INSN (slot[0]);
4106 while (t != slot[1])
4108 if (GET_CODE (t) != NOTE
4109 || NOTE_KIND (t) != NOTE_INSN_DELETED)
4110 return false;
4111 t = NEXT_INSN (t);
4114 if (slot[2])
4116 rtx t = NEXT_INSN (slot[1]);
4117 while (t != slot[2])
4119 if (GET_CODE (t) != NOTE
4120 || NOTE_KIND (t) != NOTE_INSN_DELETED)
4121 return false;
4122 t = NEXT_INSN (t);
4126 if (slot[0] == NULL_RTX)
4128 slot[0] = emit_insn_before (gen_mnop (), slot[1]);
4129 df_insn_rescan (slot[0]);
4131 if (slot[2] == NULL_RTX)
4133 slot[2] = emit_insn_after (gen_forced_nop (), slot[1]);
4134 df_insn_rescan (slot[2]);
4137 /* Avoid line number information being printed inside one bundle. */
4138 if (INSN_LOCATOR (slot[1])
4139 && INSN_LOCATOR (slot[1]) != INSN_LOCATOR (slot[0]))
4140 INSN_LOCATOR (slot[1]) = INSN_LOCATOR (slot[0]);
4141 if (INSN_LOCATOR (slot[2])
4142 && INSN_LOCATOR (slot[2]) != INSN_LOCATOR (slot[0]))
4143 INSN_LOCATOR (slot[2]) = INSN_LOCATOR (slot[0]);
4145 /* Terminate them with "|| " instead of ";" in the output. */
4146 PUT_MODE (slot[0], SImode);
4147 PUT_MODE (slot[1], SImode);
4148 /* Terminate the bundle, for the benefit of reorder_var_tracking_notes. */
4149 PUT_MODE (slot[2], QImode);
4150 return true;
4153 /* Go through all insns, and use the information generated during scheduling
4154 to generate SEQUENCEs to represent bundles of instructions issued
4155 simultaneously. */
4157 static void
4158 bfin_gen_bundles (void)
4160 basic_block bb;
4161 FOR_EACH_BB (bb)
4163 rtx insn, next;
4164 rtx slot[3];
4165 int n_filled = 0;
4167 slot[0] = slot[1] = slot[2] = NULL_RTX;
4168 for (insn = BB_HEAD (bb);; insn = next)
4170 int at_end;
4171 if (INSN_P (insn))
4173 if (get_attr_type (insn) == TYPE_DSP32)
4174 slot[0] = insn;
4175 else if (slot[1] == NULL_RTX)
4176 slot[1] = insn;
4177 else
4178 slot[2] = insn;
4179 n_filled++;
4182 next = NEXT_INSN (insn);
4183 while (next && insn != BB_END (bb)
4184 && !(INSN_P (next)
4185 && GET_CODE (PATTERN (next)) != USE
4186 && GET_CODE (PATTERN (next)) != CLOBBER))
4188 insn = next;
4189 next = NEXT_INSN (insn);
4192 /* BB_END can change due to emitting extra NOPs, so check here. */
4193 at_end = insn == BB_END (bb);
4194 if (at_end || GET_MODE (next) == TImode)
4196 if ((n_filled < 2
4197 || !gen_one_bundle (slot))
4198 && slot[0] != NULL_RTX)
4200 rtx pat = PATTERN (slot[0]);
4201 if (GET_CODE (pat) == SET
4202 && GET_CODE (SET_SRC (pat)) == UNSPEC
4203 && XINT (SET_SRC (pat), 1) == UNSPEC_32BIT)
4205 SET_SRC (pat) = XVECEXP (SET_SRC (pat), 0, 0);
4206 INSN_CODE (slot[0]) = -1;
4207 df_insn_rescan (slot[0]);
4210 n_filled = 0;
4211 slot[0] = slot[1] = slot[2] = NULL_RTX;
4213 if (at_end)
4214 break;
4219 /* Ensure that no var tracking notes are emitted in the middle of a
4220 three-instruction bundle. */
4222 static void
4223 reorder_var_tracking_notes (void)
4225 basic_block bb;
4226 FOR_EACH_BB (bb)
4228 rtx insn, next;
4229 rtx queue = NULL_RTX;
4230 bool in_bundle = false;
4232 for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = next)
4234 next = NEXT_INSN (insn);
4236 if (INSN_P (insn))
4238 /* Emit queued up notes at the last instruction of a bundle. */
4239 if (GET_MODE (insn) == QImode)
4241 while (queue)
4243 rtx next_queue = PREV_INSN (queue);
4244 PREV_INSN (NEXT_INSN (insn)) = queue;
4245 NEXT_INSN (queue) = NEXT_INSN (insn);
4246 NEXT_INSN (insn) = queue;
4247 PREV_INSN (queue) = insn;
4248 queue = next_queue;
4250 in_bundle = false;
4252 else if (GET_MODE (insn) == SImode)
4253 in_bundle = true;
4255 else if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION)
4257 if (in_bundle)
4259 rtx prev = PREV_INSN (insn);
4260 PREV_INSN (next) = prev;
4261 NEXT_INSN (prev) = next;
4263 PREV_INSN (insn) = queue;
4264 queue = insn;
4271 /* Return an insn type for INSN that can be used by the caller for anomaly
4272 workarounds. This differs from plain get_attr_type in that it handles
4273 SEQUENCEs. */
4275 static enum attr_type
4276 type_for_anomaly (rtx insn)
4278 rtx pat = PATTERN (insn);
4279 if (GET_CODE (pat) == SEQUENCE)
4281 enum attr_type t;
4282 t = get_attr_type (XVECEXP (pat, 0, 1));
4283 if (t == TYPE_MCLD)
4284 return t;
4285 t = get_attr_type (XVECEXP (pat, 0, 2));
4286 if (t == TYPE_MCLD)
4287 return t;
4288 return TYPE_MCST;
4290 else
4291 return get_attr_type (insn);
4294 /* Return nonzero if INSN contains any loads that may trap. It handles
4295 SEQUENCEs correctly. */
4297 static bool
4298 trapping_loads_p (rtx insn)
4300 rtx pat = PATTERN (insn);
4301 if (GET_CODE (pat) == SEQUENCE)
4303 enum attr_type t;
4304 t = get_attr_type (XVECEXP (pat, 0, 1));
4305 if (t == TYPE_MCLD
4306 && may_trap_p (SET_SRC (PATTERN (XVECEXP (pat, 0, 1)))))
4307 return true;
4308 t = get_attr_type (XVECEXP (pat, 0, 2));
4309 if (t == TYPE_MCLD
4310 && may_trap_p (SET_SRC (PATTERN (XVECEXP (pat, 0, 2)))))
4311 return true;
4312 return false;
4314 else
4315 return may_trap_p (SET_SRC (single_set (insn)));
4318 /* This function acts like NEXT_INSN, but is aware of three-insn bundles and
4319 skips all subsequent parallel instructions if INSN is the start of such
4320 a group. */
4321 static rtx
4322 find_next_insn_start (rtx insn)
4324 if (GET_MODE (insn) == SImode)
4326 while (GET_MODE (insn) != QImode)
4327 insn = NEXT_INSN (insn);
4329 return NEXT_INSN (insn);
4332 /* Return INSN if it is of TYPE_MCLD. Alternatively, if INSN is the start of
4333 a three-insn bundle, see if one of them is a load and return that if so.
4334 Return NULL_RTX if the insn does not contain loads. */
4335 static rtx
4336 find_load (rtx insn)
4338 if (get_attr_type (insn) == TYPE_MCLD)
4339 return insn;
4340 if (GET_MODE (insn) != SImode)
4341 return NULL_RTX;
4342 do {
4343 insn = NEXT_INSN (insn);
4344 if ((GET_MODE (insn) == SImode || GET_MODE (insn) == QImode)
4345 && get_attr_type (insn) == TYPE_MCLD)
4346 return insn;
4347 } while (GET_MODE (insn) != QImode);
4348 return NULL_RTX;
4351 /* We use the machine specific reorg pass for emitting CSYNC instructions
4352 after conditional branches as needed.
4354 The Blackfin is unusual in that a code sequence like
4355 if cc jump label
4356 r0 = (p0)
4357 may speculatively perform the load even if the condition isn't true. This
4358 happens for a branch that is predicted not taken, because the pipeline
4359 isn't flushed or stalled, so the early stages of the following instructions,
4360 which perform the memory reference, are allowed to execute before the
4361 jump condition is evaluated.
4362 Therefore, we must insert additional instructions in all places where this
4363 could lead to incorrect behavior. The manual recommends CSYNC, while
4364 VDSP seems to use NOPs (even though its corresponding compiler option is
4365 named CSYNC).
4367 When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
4368 When optimizing for size, we turn the branch into a predicted taken one.
4369 This may be slower due to mispredicts, but saves code size. */
4371 static void
4372 bfin_reorg (void)
4374 rtx insn, next;
4375 rtx last_condjump = NULL_RTX;
4376 int cycles_since_jump = INT_MAX;
4378 /* We are freeing block_for_insn in the toplev to keep compatibility
4379 with old MDEP_REORGS that are not CFG based. Recompute it now. */
4380 compute_bb_for_insn ();
4382 if (bfin_flag_schedule_insns2)
4384 splitting_for_sched = 1;
4385 split_all_insns ();
4386 splitting_for_sched = 0;
4388 timevar_push (TV_SCHED2);
4389 schedule_insns ();
4390 timevar_pop (TV_SCHED2);
4392 /* Examine the schedule and insert nops as necessary for 64-bit parallel
4393 instructions. */
4394 bfin_gen_bundles ();
4397 df_analyze ();
4399 /* Doloop optimization */
4400 if (cfun->machine->has_hardware_loops)
4401 bfin_reorg_loops (dump_file);
4403 if (! TARGET_SPECLD_ANOMALY && ! TARGET_CSYNC_ANOMALY)
4404 return;
4406 /* First pass: find predicted-false branches; if something after them
4407 needs nops, insert them or change the branch to predict true. */
4408 for (insn = get_insns (); insn; insn = next)
4410 rtx pat;
4412 next = find_next_insn_start (insn);
4414 if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
4415 continue;
4417 pat = PATTERN (insn);
4418 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4419 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
4420 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
4421 continue;
4423 if (JUMP_P (insn))
4425 if (any_condjump_p (insn)
4426 && ! cbranch_predicted_taken_p (insn))
4428 last_condjump = insn;
4429 cycles_since_jump = 0;
4431 else
4432 cycles_since_jump = INT_MAX;
4434 else if (INSN_P (insn))
4436 rtx load_insn = find_load (insn);
4437 enum attr_type type = type_for_anomaly (insn);
4438 int delay_needed = 0;
4439 if (cycles_since_jump < INT_MAX)
4440 cycles_since_jump++;
4442 if (load_insn && TARGET_SPECLD_ANOMALY)
4444 if (trapping_loads_p (load_insn))
4445 delay_needed = 3;
4447 else if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
4448 delay_needed = 4;
4450 if (delay_needed > cycles_since_jump)
4452 rtx pat;
4453 int num_clobbers;
4454 rtx *op = recog_data.operand;
4456 delay_needed -= cycles_since_jump;
4458 extract_insn (last_condjump);
4459 if (optimize_size)
4461 pat = gen_cbranch_predicted_taken (op[0], op[1], op[2],
4462 op[3]);
4463 cycles_since_jump = INT_MAX;
4465 else
4466 /* Do not adjust cycles_since_jump in this case, so that
4467 we'll increase the number of NOPs for a subsequent insn
4468 if necessary. */
4469 pat = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
4470 GEN_INT (delay_needed));
4471 PATTERN (last_condjump) = pat;
4472 INSN_CODE (last_condjump) = recog (pat, insn, &num_clobbers);
4476 /* Second pass: for predicted-true branches, see if anything at the
4477 branch destination needs extra nops. */
4478 if (! TARGET_CSYNC_ANOMALY)
4479 return;
4481 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4483 if (JUMP_P (insn)
4484 && any_condjump_p (insn)
4485 && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken
4486 || cbranch_predicted_taken_p (insn)))
4488 rtx target = JUMP_LABEL (insn);
4489 rtx label = target;
4490 cycles_since_jump = 0;
4491 for (; target && cycles_since_jump < 3; target = NEXT_INSN (target))
4493 rtx pat;
4495 if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
4496 continue;
4498 pat = PATTERN (target);
4499 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4500 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
4501 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
4502 continue;
4504 if (INSN_P (target))
4506 enum attr_type type = type_for_anomaly (target);
4507 int delay_needed = 0;
4508 if (cycles_since_jump < INT_MAX)
4509 cycles_since_jump++;
4511 if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
4512 delay_needed = 2;
4514 if (delay_needed > cycles_since_jump)
4516 rtx prev = prev_real_insn (label);
4517 delay_needed -= cycles_since_jump;
4518 if (dump_file)
4519 fprintf (dump_file, "Adding %d nops after %d\n",
4520 delay_needed, INSN_UID (label));
4521 if (JUMP_P (prev)
4522 && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops)
4524 rtx x;
4525 HOST_WIDE_INT v;
4527 if (dump_file)
4528 fprintf (dump_file,
4529 "Reducing nops on insn %d.\n",
4530 INSN_UID (prev));
4531 x = PATTERN (prev);
4532 x = XVECEXP (x, 0, 1);
4533 v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed;
4534 XVECEXP (x, 0, 0) = GEN_INT (v);
4536 while (delay_needed-- > 0)
4537 emit_insn_after (gen_nop (), label);
4538 break;
4545 if (bfin_flag_var_tracking)
4547 timevar_push (TV_VAR_TRACKING);
4548 variable_tracking_main ();
4549 reorder_var_tracking_notes ();
4550 timevar_pop (TV_VAR_TRACKING);
4552 df_finish_pass (false);
4555 /* Handle interrupt_handler, exception_handler and nmi_handler function
4556 attributes; arguments as in struct attribute_spec.handler. */
4558 static tree
4559 handle_int_attribute (tree *node, tree name,
4560 tree args ATTRIBUTE_UNUSED,
4561 int flags ATTRIBUTE_UNUSED,
4562 bool *no_add_attrs)
4564 tree x = *node;
4565 if (TREE_CODE (x) == FUNCTION_DECL)
4566 x = TREE_TYPE (x);
4568 if (TREE_CODE (x) != FUNCTION_TYPE)
4570 warning (OPT_Wattributes, "%qs attribute only applies to functions",
4571 IDENTIFIER_POINTER (name));
4572 *no_add_attrs = true;
4574 else if (funkind (x) != SUBROUTINE)
4575 error ("multiple function type attributes specified");
4577 return NULL_TREE;
4580 /* Return 0 if the attributes for two types are incompatible, 1 if they
4581 are compatible, and 2 if they are nearly compatible (which causes a
4582 warning to be generated). */
4584 static int
4585 bfin_comp_type_attributes (const_tree type1, const_tree type2)
4587 e_funkind kind1, kind2;
4589 if (TREE_CODE (type1) != FUNCTION_TYPE)
4590 return 1;
4592 kind1 = funkind (type1);
4593 kind2 = funkind (type2);
4595 if (kind1 != kind2)
4596 return 0;
4598 /* Check for mismatched modifiers */
4599 if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
4600 != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
4601 return 0;
4603 if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
4604 != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
4605 return 0;
4607 if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
4608 != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
4609 return 0;
4611 if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1))
4612 != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2)))
4613 return 0;
4615 return 1;
4618 /* Handle a "longcall" or "shortcall" attribute; arguments as in
4619 struct attribute_spec.handler. */
4621 static tree
4622 bfin_handle_longcall_attribute (tree *node, tree name,
4623 tree args ATTRIBUTE_UNUSED,
4624 int flags ATTRIBUTE_UNUSED,
4625 bool *no_add_attrs)
4627 if (TREE_CODE (*node) != FUNCTION_TYPE
4628 && TREE_CODE (*node) != FIELD_DECL
4629 && TREE_CODE (*node) != TYPE_DECL)
4631 warning (OPT_Wattributes, "`%s' attribute only applies to functions",
4632 IDENTIFIER_POINTER (name));
4633 *no_add_attrs = true;
4636 if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0
4637 && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node)))
4638 || (strcmp (IDENTIFIER_POINTER (name), "shortcall") == 0
4639 && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node))))
4641 warning (OPT_Wattributes,
4642 "can't apply both longcall and shortcall attributes to the same function");
4643 *no_add_attrs = true;
4646 return NULL_TREE;
4649 /* Table of valid machine attributes. */
4650 const struct attribute_spec bfin_attribute_table[] =
4652 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4653 { "interrupt_handler", 0, 0, false, true, true, handle_int_attribute },
4654 { "exception_handler", 0, 0, false, true, true, handle_int_attribute },
4655 { "nmi_handler", 0, 0, false, true, true, handle_int_attribute },
4656 { "nesting", 0, 0, false, true, true, NULL },
4657 { "kspisusp", 0, 0, false, true, true, NULL },
4658 { "saveall", 0, 0, false, true, true, NULL },
4659 { "longcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
4660 { "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
4661 { NULL, 0, 0, false, false, false, NULL }
4664 /* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to
4665 tell the assembler to generate pointers to function descriptors in
4666 some cases. */
4668 static bool
4669 bfin_assemble_integer (rtx value, unsigned int size, int aligned_p)
4671 if (TARGET_FDPIC && size == UNITS_PER_WORD)
4673 if (GET_CODE (value) == SYMBOL_REF
4674 && SYMBOL_REF_FUNCTION_P (value))
4676 fputs ("\t.picptr\tfuncdesc(", asm_out_file);
4677 output_addr_const (asm_out_file, value);
4678 fputs (")\n", asm_out_file);
4679 return true;
4681 if (!aligned_p)
4683 /* We've set the unaligned SI op to NULL, so we always have to
4684 handle the unaligned case here. */
4685 assemble_integer_with_op ("\t.4byte\t", value);
4686 return true;
4689 return default_assemble_integer (value, size, aligned_p);
4692 /* Output the assembler code for a thunk function. THUNK_DECL is the
4693 declaration for the thunk function itself, FUNCTION is the decl for
4694 the target function. DELTA is an immediate constant offset to be
4695 added to THIS. If VCALL_OFFSET is nonzero, the word at
4696 *(*this + vcall_offset) should be added to THIS. */
4698 static void
4699 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
4700 tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
4701 HOST_WIDE_INT vcall_offset, tree function)
4703 rtx xops[3];
4704 /* The this parameter is passed as the first argument. */
4705 rtx this = gen_rtx_REG (Pmode, REG_R0);
4707 /* Adjust the this parameter by a fixed constant. */
4708 if (delta)
4710 xops[1] = this;
4711 if (delta >= -64 && delta <= 63)
4713 xops[0] = GEN_INT (delta);
4714 output_asm_insn ("%1 += %0;", xops);
4716 else if (delta >= -128 && delta < -64)
4718 xops[0] = GEN_INT (delta + 64);
4719 output_asm_insn ("%1 += -64; %1 += %0;", xops);
4721 else if (delta > 63 && delta <= 126)
4723 xops[0] = GEN_INT (delta - 63);
4724 output_asm_insn ("%1 += 63; %1 += %0;", xops);
4726 else
4728 xops[0] = GEN_INT (delta);
4729 output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
4733 /* Adjust the this parameter by a value stored in the vtable. */
4734 if (vcall_offset)
4736 rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
4737 rtx tmp = gen_rtx_REG (Pmode, REG_R3);
4739 xops[1] = tmp;
4740 xops[2] = p2tmp;
4741 output_asm_insn ("%2 = r0; %2 = [%2];", xops);
4743 /* Adjust the this parameter. */
4744 xops[0] = gen_rtx_MEM (Pmode, plus_constant (p2tmp, vcall_offset));
4745 if (!memory_operand (xops[0], Pmode))
4747 rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
4748 xops[0] = GEN_INT (vcall_offset);
4749 xops[1] = tmp2;
4750 output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
4751 xops[0] = gen_rtx_MEM (Pmode, p2tmp);
4753 xops[2] = this;
4754 output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
4757 xops[0] = XEXP (DECL_RTL (function), 0);
4758 if (1 || !flag_pic || (*targetm.binds_local_p) (function))
4759 output_asm_insn ("jump.l\t%P0", xops);
4762 /* Codes for all the Blackfin builtins. */
4763 enum bfin_builtins
4765 BFIN_BUILTIN_CSYNC,
4766 BFIN_BUILTIN_SSYNC,
4767 BFIN_BUILTIN_COMPOSE_2X16,
4768 BFIN_BUILTIN_EXTRACTLO,
4769 BFIN_BUILTIN_EXTRACTHI,
4771 BFIN_BUILTIN_SSADD_2X16,
4772 BFIN_BUILTIN_SSSUB_2X16,
4773 BFIN_BUILTIN_SSADDSUB_2X16,
4774 BFIN_BUILTIN_SSSUBADD_2X16,
4775 BFIN_BUILTIN_MULT_2X16,
4776 BFIN_BUILTIN_MULTR_2X16,
4777 BFIN_BUILTIN_NEG_2X16,
4778 BFIN_BUILTIN_ABS_2X16,
4779 BFIN_BUILTIN_MIN_2X16,
4780 BFIN_BUILTIN_MAX_2X16,
4782 BFIN_BUILTIN_SSADD_1X16,
4783 BFIN_BUILTIN_SSSUB_1X16,
4784 BFIN_BUILTIN_MULT_1X16,
4785 BFIN_BUILTIN_MULTR_1X16,
4786 BFIN_BUILTIN_NORM_1X16,
4787 BFIN_BUILTIN_NEG_1X16,
4788 BFIN_BUILTIN_ABS_1X16,
4789 BFIN_BUILTIN_MIN_1X16,
4790 BFIN_BUILTIN_MAX_1X16,
4792 BFIN_BUILTIN_SUM_2X16,
4793 BFIN_BUILTIN_DIFFHL_2X16,
4794 BFIN_BUILTIN_DIFFLH_2X16,
4796 BFIN_BUILTIN_SSADD_1X32,
4797 BFIN_BUILTIN_SSSUB_1X32,
4798 BFIN_BUILTIN_NORM_1X32,
4799 BFIN_BUILTIN_ROUND_1X32,
4800 BFIN_BUILTIN_NEG_1X32,
4801 BFIN_BUILTIN_ABS_1X32,
4802 BFIN_BUILTIN_MIN_1X32,
4803 BFIN_BUILTIN_MAX_1X32,
4804 BFIN_BUILTIN_MULT_1X32,
4805 BFIN_BUILTIN_MULT_1X32X32,
4806 BFIN_BUILTIN_MULT_1X32X32NS,
4808 BFIN_BUILTIN_MULHISILL,
4809 BFIN_BUILTIN_MULHISILH,
4810 BFIN_BUILTIN_MULHISIHL,
4811 BFIN_BUILTIN_MULHISIHH,
4813 BFIN_BUILTIN_LSHIFT_1X16,
4814 BFIN_BUILTIN_LSHIFT_2X16,
4815 BFIN_BUILTIN_SSASHIFT_1X16,
4816 BFIN_BUILTIN_SSASHIFT_2X16,
4817 BFIN_BUILTIN_SSASHIFT_1X32,
4819 BFIN_BUILTIN_CPLX_MUL_16,
4820 BFIN_BUILTIN_CPLX_MAC_16,
4821 BFIN_BUILTIN_CPLX_MSU_16,
4823 BFIN_BUILTIN_MAX
4826 #define def_builtin(NAME, TYPE, CODE) \
4827 do { \
4828 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
4829 NULL, NULL_TREE); \
4830 } while (0)
4832 /* Set up all builtin functions for this target. */
4833 static void
4834 bfin_init_builtins (void)
4836 tree V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
4837 tree void_ftype_void
4838 = build_function_type (void_type_node, void_list_node);
4839 tree short_ftype_short
4840 = build_function_type_list (short_integer_type_node, short_integer_type_node,
4841 NULL_TREE);
4842 tree short_ftype_int_int
4843 = build_function_type_list (short_integer_type_node, integer_type_node,
4844 integer_type_node, NULL_TREE);
4845 tree int_ftype_int_int
4846 = build_function_type_list (integer_type_node, integer_type_node,
4847 integer_type_node, NULL_TREE);
4848 tree int_ftype_int
4849 = build_function_type_list (integer_type_node, integer_type_node,
4850 NULL_TREE);
4851 tree short_ftype_int
4852 = build_function_type_list (short_integer_type_node, integer_type_node,
4853 NULL_TREE);
4854 tree int_ftype_v2hi_v2hi
4855 = build_function_type_list (integer_type_node, V2HI_type_node,
4856 V2HI_type_node, NULL_TREE);
4857 tree v2hi_ftype_v2hi_v2hi
4858 = build_function_type_list (V2HI_type_node, V2HI_type_node,
4859 V2HI_type_node, NULL_TREE);
4860 tree v2hi_ftype_v2hi_v2hi_v2hi
4861 = build_function_type_list (V2HI_type_node, V2HI_type_node,
4862 V2HI_type_node, V2HI_type_node, NULL_TREE);
4863 tree v2hi_ftype_int_int
4864 = build_function_type_list (V2HI_type_node, integer_type_node,
4865 integer_type_node, NULL_TREE);
4866 tree v2hi_ftype_v2hi_int
4867 = build_function_type_list (V2HI_type_node, V2HI_type_node,
4868 integer_type_node, NULL_TREE);
4869 tree int_ftype_short_short
4870 = build_function_type_list (integer_type_node, short_integer_type_node,
4871 short_integer_type_node, NULL_TREE);
4872 tree v2hi_ftype_v2hi
4873 = build_function_type_list (V2HI_type_node, V2HI_type_node, NULL_TREE);
4874 tree short_ftype_v2hi
4875 = build_function_type_list (short_integer_type_node, V2HI_type_node,
4876 NULL_TREE);
4878 /* Add the remaining MMX insns with somewhat more complicated types. */
4879 def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC);
4880 def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC);
4882 def_builtin ("__builtin_bfin_compose_2x16", v2hi_ftype_int_int,
4883 BFIN_BUILTIN_COMPOSE_2X16);
4884 def_builtin ("__builtin_bfin_extract_hi", short_ftype_v2hi,
4885 BFIN_BUILTIN_EXTRACTHI);
4886 def_builtin ("__builtin_bfin_extract_lo", short_ftype_v2hi,
4887 BFIN_BUILTIN_EXTRACTLO);
4889 def_builtin ("__builtin_bfin_min_fr2x16", v2hi_ftype_v2hi_v2hi,
4890 BFIN_BUILTIN_MIN_2X16);
4891 def_builtin ("__builtin_bfin_max_fr2x16", v2hi_ftype_v2hi_v2hi,
4892 BFIN_BUILTIN_MAX_2X16);
4894 def_builtin ("__builtin_bfin_add_fr2x16", v2hi_ftype_v2hi_v2hi,
4895 BFIN_BUILTIN_SSADD_2X16);
4896 def_builtin ("__builtin_bfin_sub_fr2x16", v2hi_ftype_v2hi_v2hi,
4897 BFIN_BUILTIN_SSSUB_2X16);
4898 def_builtin ("__builtin_bfin_dspaddsubsat", v2hi_ftype_v2hi_v2hi,
4899 BFIN_BUILTIN_SSADDSUB_2X16);
4900 def_builtin ("__builtin_bfin_dspsubaddsat", v2hi_ftype_v2hi_v2hi,
4901 BFIN_BUILTIN_SSSUBADD_2X16);
4902 def_builtin ("__builtin_bfin_mult_fr2x16", v2hi_ftype_v2hi_v2hi,
4903 BFIN_BUILTIN_MULT_2X16);
4904 def_builtin ("__builtin_bfin_multr_fr2x16", v2hi_ftype_v2hi_v2hi,
4905 BFIN_BUILTIN_MULTR_2X16);
4906 def_builtin ("__builtin_bfin_negate_fr2x16", v2hi_ftype_v2hi,
4907 BFIN_BUILTIN_NEG_2X16);
4908 def_builtin ("__builtin_bfin_abs_fr2x16", v2hi_ftype_v2hi,
4909 BFIN_BUILTIN_ABS_2X16);
4911 def_builtin ("__builtin_bfin_add_fr1x16", short_ftype_int_int,
4912 BFIN_BUILTIN_SSADD_1X16);
4913 def_builtin ("__builtin_bfin_sub_fr1x16", short_ftype_int_int,
4914 BFIN_BUILTIN_SSSUB_1X16);
4915 def_builtin ("__builtin_bfin_mult_fr1x16", short_ftype_int_int,
4916 BFIN_BUILTIN_MULT_1X16);
4917 def_builtin ("__builtin_bfin_multr_fr1x16", short_ftype_int_int,
4918 BFIN_BUILTIN_MULTR_1X16);
4919 def_builtin ("__builtin_bfin_negate_fr1x16", short_ftype_short,
4920 BFIN_BUILTIN_NEG_1X16);
4921 def_builtin ("__builtin_bfin_abs_fr1x16", short_ftype_short,
4922 BFIN_BUILTIN_ABS_1X16);
4923 def_builtin ("__builtin_bfin_norm_fr1x16", short_ftype_int,
4924 BFIN_BUILTIN_NORM_1X16);
4926 def_builtin ("__builtin_bfin_sum_fr2x16", short_ftype_v2hi,
4927 BFIN_BUILTIN_SUM_2X16);
4928 def_builtin ("__builtin_bfin_diff_hl_fr2x16", short_ftype_v2hi,
4929 BFIN_BUILTIN_DIFFHL_2X16);
4930 def_builtin ("__builtin_bfin_diff_lh_fr2x16", short_ftype_v2hi,
4931 BFIN_BUILTIN_DIFFLH_2X16);
4933 def_builtin ("__builtin_bfin_mulhisill", int_ftype_v2hi_v2hi,
4934 BFIN_BUILTIN_MULHISILL);
4935 def_builtin ("__builtin_bfin_mulhisihl", int_ftype_v2hi_v2hi,
4936 BFIN_BUILTIN_MULHISIHL);
4937 def_builtin ("__builtin_bfin_mulhisilh", int_ftype_v2hi_v2hi,
4938 BFIN_BUILTIN_MULHISILH);
4939 def_builtin ("__builtin_bfin_mulhisihh", int_ftype_v2hi_v2hi,
4940 BFIN_BUILTIN_MULHISIHH);
4942 def_builtin ("__builtin_bfin_add_fr1x32", int_ftype_int_int,
4943 BFIN_BUILTIN_SSADD_1X32);
4944 def_builtin ("__builtin_bfin_sub_fr1x32", int_ftype_int_int,
4945 BFIN_BUILTIN_SSSUB_1X32);
4946 def_builtin ("__builtin_bfin_negate_fr1x32", int_ftype_int,
4947 BFIN_BUILTIN_NEG_1X32);
4948 def_builtin ("__builtin_bfin_abs_fr1x32", int_ftype_int,
4949 BFIN_BUILTIN_ABS_1X32);
4950 def_builtin ("__builtin_bfin_norm_fr1x32", short_ftype_int,
4951 BFIN_BUILTIN_NORM_1X32);
4952 def_builtin ("__builtin_bfin_round_fr1x32", short_ftype_int,
4953 BFIN_BUILTIN_ROUND_1X32);
4954 def_builtin ("__builtin_bfin_mult_fr1x32", int_ftype_short_short,
4955 BFIN_BUILTIN_MULT_1X32);
4956 def_builtin ("__builtin_bfin_mult_fr1x32x32", int_ftype_int_int,
4957 BFIN_BUILTIN_MULT_1X32X32);
4958 def_builtin ("__builtin_bfin_mult_fr1x32x32NS", int_ftype_int_int,
4959 BFIN_BUILTIN_MULT_1X32X32NS);
4961 /* Shifts. */
4962 def_builtin ("__builtin_bfin_shl_fr1x16", short_ftype_int_int,
4963 BFIN_BUILTIN_SSASHIFT_1X16);
4964 def_builtin ("__builtin_bfin_shl_fr2x16", v2hi_ftype_v2hi_int,
4965 BFIN_BUILTIN_SSASHIFT_2X16);
4966 def_builtin ("__builtin_bfin_lshl_fr1x16", short_ftype_int_int,
4967 BFIN_BUILTIN_LSHIFT_1X16);
4968 def_builtin ("__builtin_bfin_lshl_fr2x16", v2hi_ftype_v2hi_int,
4969 BFIN_BUILTIN_LSHIFT_2X16);
4970 def_builtin ("__builtin_bfin_shl_fr1x32", int_ftype_int_int,
4971 BFIN_BUILTIN_SSASHIFT_1X32);
4973 /* Complex numbers. */
4974 def_builtin ("__builtin_bfin_cmplx_mul", v2hi_ftype_v2hi_v2hi,
4975 BFIN_BUILTIN_CPLX_MUL_16);
4976 def_builtin ("__builtin_bfin_cmplx_mac", v2hi_ftype_v2hi_v2hi_v2hi,
4977 BFIN_BUILTIN_CPLX_MAC_16);
4978 def_builtin ("__builtin_bfin_cmplx_msu", v2hi_ftype_v2hi_v2hi_v2hi,
4979 BFIN_BUILTIN_CPLX_MSU_16);
4983 struct builtin_description
4985 const enum insn_code icode;
4986 const char *const name;
4987 const enum bfin_builtins code;
4988 int macflag;
4991 static const struct builtin_description bdesc_2arg[] =
4993 { CODE_FOR_composev2hi, "__builtin_bfin_compose_2x16", BFIN_BUILTIN_COMPOSE_2X16, -1 },
4995 { CODE_FOR_ssashiftv2hi3, "__builtin_bfin_shl_fr2x16", BFIN_BUILTIN_SSASHIFT_2X16, -1 },
4996 { CODE_FOR_ssashifthi3, "__builtin_bfin_shl_fr1x16", BFIN_BUILTIN_SSASHIFT_1X16, -1 },
4997 { CODE_FOR_lshiftv2hi3, "__builtin_bfin_lshl_fr2x16", BFIN_BUILTIN_LSHIFT_2X16, -1 },
4998 { CODE_FOR_lshifthi3, "__builtin_bfin_lshl_fr1x16", BFIN_BUILTIN_LSHIFT_1X16, -1 },
4999 { CODE_FOR_ssashiftsi3, "__builtin_bfin_shl_fr1x32", BFIN_BUILTIN_SSASHIFT_1X32, -1 },
5001 { CODE_FOR_sminhi3, "__builtin_bfin_min_fr1x16", BFIN_BUILTIN_MIN_1X16, -1 },
5002 { CODE_FOR_smaxhi3, "__builtin_bfin_max_fr1x16", BFIN_BUILTIN_MAX_1X16, -1 },
5003 { CODE_FOR_ssaddhi3, "__builtin_bfin_add_fr1x16", BFIN_BUILTIN_SSADD_1X16, -1 },
5004 { CODE_FOR_sssubhi3, "__builtin_bfin_sub_fr1x16", BFIN_BUILTIN_SSSUB_1X16, -1 },
5006 { CODE_FOR_sminsi3, "__builtin_bfin_min_fr1x32", BFIN_BUILTIN_MIN_1X32, -1 },
5007 { CODE_FOR_smaxsi3, "__builtin_bfin_max_fr1x32", BFIN_BUILTIN_MAX_1X32, -1 },
5008 { CODE_FOR_ssaddsi3, "__builtin_bfin_add_fr1x32", BFIN_BUILTIN_SSADD_1X32, -1 },
5009 { CODE_FOR_sssubsi3, "__builtin_bfin_sub_fr1x32", BFIN_BUILTIN_SSSUB_1X32, -1 },
5011 { CODE_FOR_sminv2hi3, "__builtin_bfin_min_fr2x16", BFIN_BUILTIN_MIN_2X16, -1 },
5012 { CODE_FOR_smaxv2hi3, "__builtin_bfin_max_fr2x16", BFIN_BUILTIN_MAX_2X16, -1 },
5013 { CODE_FOR_ssaddv2hi3, "__builtin_bfin_add_fr2x16", BFIN_BUILTIN_SSADD_2X16, -1 },
5014 { CODE_FOR_sssubv2hi3, "__builtin_bfin_sub_fr2x16", BFIN_BUILTIN_SSSUB_2X16, -1 },
5015 { CODE_FOR_ssaddsubv2hi3, "__builtin_bfin_dspaddsubsat", BFIN_BUILTIN_SSADDSUB_2X16, -1 },
5016 { CODE_FOR_sssubaddv2hi3, "__builtin_bfin_dspsubaddsat", BFIN_BUILTIN_SSSUBADD_2X16, -1 },
5018 { CODE_FOR_flag_mulhisi, "__builtin_bfin_mult_fr1x32", BFIN_BUILTIN_MULT_1X32, MACFLAG_NONE },
5019 { CODE_FOR_flag_mulhi, "__builtin_bfin_mult_fr1x16", BFIN_BUILTIN_MULT_1X16, MACFLAG_T },
5020 { CODE_FOR_flag_mulhi, "__builtin_bfin_multr_fr1x16", BFIN_BUILTIN_MULTR_1X16, MACFLAG_NONE },
5021 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_mult_fr2x16", BFIN_BUILTIN_MULT_2X16, MACFLAG_T },
5022 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_multr_fr2x16", BFIN_BUILTIN_MULTR_2X16, MACFLAG_NONE }
5025 static const struct builtin_description bdesc_1arg[] =
5027 { CODE_FOR_signbitshi2, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16, 0 },
5028 { CODE_FOR_ssneghi2, "__builtin_bfin_negate_fr1x16", BFIN_BUILTIN_NEG_1X16, 0 },
5029 { CODE_FOR_abshi2, "__builtin_bfin_abs_fr1x16", BFIN_BUILTIN_ABS_1X16, 0 },
5031 { CODE_FOR_signbitssi2, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32, 0 },
5032 { CODE_FOR_ssroundsi2, "__builtin_bfin_round_fr1x32", BFIN_BUILTIN_ROUND_1X32, 0 },
5033 { CODE_FOR_ssnegsi2, "__builtin_bfin_negate_fr1x32", BFIN_BUILTIN_NEG_1X32, 0 },
5034 { CODE_FOR_ssabssi2, "__builtin_bfin_abs_fr1x32", BFIN_BUILTIN_ABS_1X32, 0 },
5036 { CODE_FOR_movv2hi_hi_low, "__builtin_bfin_extract_lo", BFIN_BUILTIN_EXTRACTLO, 0 },
5037 { CODE_FOR_movv2hi_hi_high, "__builtin_bfin_extract_hi", BFIN_BUILTIN_EXTRACTHI, 0 },
5038 { CODE_FOR_ssnegv2hi2, "__builtin_bfin_negate_fr2x16", BFIN_BUILTIN_NEG_2X16, 0 },
5039 { CODE_FOR_ssabsv2hi2, "__builtin_bfin_abs_fr2x16", BFIN_BUILTIN_ABS_2X16, 0 }
5042 /* Errors in the source file can cause expand_expr to return const0_rtx
5043 where we expect a vector. To avoid crashing, use one of the vector
5044 clear instructions. */
5045 static rtx
5046 safe_vector_operand (rtx x, enum machine_mode mode)
5048 if (x != const0_rtx)
5049 return x;
5050 x = gen_reg_rtx (SImode);
5052 emit_insn (gen_movsi (x, CONST0_RTX (SImode)));
5053 return gen_lowpart (mode, x);
5056 /* Subroutine of bfin_expand_builtin to take care of binop insns. MACFLAG is -1
5057 if this is a normal binary op, or one of the MACFLAG_xxx constants. */
5059 static rtx
5060 bfin_expand_binop_builtin (enum insn_code icode, tree exp, rtx target,
5061 int macflag)
5063 rtx pat;
5064 tree arg0 = CALL_EXPR_ARG (exp, 0);
5065 tree arg1 = CALL_EXPR_ARG (exp, 1);
5066 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5067 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
5068 enum machine_mode op0mode = GET_MODE (op0);
5069 enum machine_mode op1mode = GET_MODE (op1);
5070 enum machine_mode tmode = insn_data[icode].operand[0].mode;
5071 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
5072 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
5074 if (VECTOR_MODE_P (mode0))
5075 op0 = safe_vector_operand (op0, mode0);
5076 if (VECTOR_MODE_P (mode1))
5077 op1 = safe_vector_operand (op1, mode1);
5079 if (! target
5080 || GET_MODE (target) != tmode
5081 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5082 target = gen_reg_rtx (tmode);
5084 if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode)
5086 op0mode = HImode;
5087 op0 = gen_lowpart (HImode, op0);
5089 if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode)
5091 op1mode = HImode;
5092 op1 = gen_lowpart (HImode, op1);
5094 /* In case the insn wants input operands in modes different from
5095 the result, abort. */
5096 gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
5097 && (op1mode == mode1 || op1mode == VOIDmode));
5099 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5100 op0 = copy_to_mode_reg (mode0, op0);
5101 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
5102 op1 = copy_to_mode_reg (mode1, op1);
5104 if (macflag == -1)
5105 pat = GEN_FCN (icode) (target, op0, op1);
5106 else
5107 pat = GEN_FCN (icode) (target, op0, op1, GEN_INT (macflag));
5108 if (! pat)
5109 return 0;
5111 emit_insn (pat);
5112 return target;
5115 /* Subroutine of bfin_expand_builtin to take care of unop insns. */
5117 static rtx
5118 bfin_expand_unop_builtin (enum insn_code icode, tree exp,
5119 rtx target)
5121 rtx pat;
5122 tree arg0 = CALL_EXPR_ARG (exp, 0);
5123 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5124 enum machine_mode op0mode = GET_MODE (op0);
5125 enum machine_mode tmode = insn_data[icode].operand[0].mode;
5126 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
5128 if (! target
5129 || GET_MODE (target) != tmode
5130 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5131 target = gen_reg_rtx (tmode);
5133 if (VECTOR_MODE_P (mode0))
5134 op0 = safe_vector_operand (op0, mode0);
5136 if (op0mode == SImode && mode0 == HImode)
5138 op0mode = HImode;
5139 op0 = gen_lowpart (HImode, op0);
5141 gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
5143 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5144 op0 = copy_to_mode_reg (mode0, op0);
5146 pat = GEN_FCN (icode) (target, op0);
5147 if (! pat)
5148 return 0;
5149 emit_insn (pat);
5150 return target;
5153 /* Expand an expression EXP that calls a built-in function,
5154 with result going to TARGET if that's convenient
5155 (and in mode MODE if that's convenient).
5156 SUBTARGET may be used as the target for computing one of EXP's operands.
5157 IGNORE is nonzero if the value is to be ignored. */
5159 static rtx
5160 bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
5161 rtx subtarget ATTRIBUTE_UNUSED,
5162 enum machine_mode mode ATTRIBUTE_UNUSED,
5163 int ignore ATTRIBUTE_UNUSED)
5165 size_t i;
5166 enum insn_code icode;
5167 const struct builtin_description *d;
5168 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
5169 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
5170 tree arg0, arg1, arg2;
5171 rtx op0, op1, op2, accvec, pat, tmp1, tmp2, a0reg, a1reg;
5172 enum machine_mode tmode, mode0;
5174 switch (fcode)
5176 case BFIN_BUILTIN_CSYNC:
5177 emit_insn (gen_csync ());
5178 return 0;
5179 case BFIN_BUILTIN_SSYNC:
5180 emit_insn (gen_ssync ());
5181 return 0;
5183 case BFIN_BUILTIN_DIFFHL_2X16:
5184 case BFIN_BUILTIN_DIFFLH_2X16:
5185 case BFIN_BUILTIN_SUM_2X16:
5186 arg0 = CALL_EXPR_ARG (exp, 0);
5187 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5188 icode = (fcode == BFIN_BUILTIN_DIFFHL_2X16 ? CODE_FOR_subhilov2hi3
5189 : fcode == BFIN_BUILTIN_DIFFLH_2X16 ? CODE_FOR_sublohiv2hi3
5190 : CODE_FOR_ssaddhilov2hi3);
5191 tmode = insn_data[icode].operand[0].mode;
5192 mode0 = insn_data[icode].operand[1].mode;
5194 if (! target
5195 || GET_MODE (target) != tmode
5196 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5197 target = gen_reg_rtx (tmode);
5199 if (VECTOR_MODE_P (mode0))
5200 op0 = safe_vector_operand (op0, mode0);
5202 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5203 op0 = copy_to_mode_reg (mode0, op0);
5205 pat = GEN_FCN (icode) (target, op0, op0);
5206 if (! pat)
5207 return 0;
5208 emit_insn (pat);
5209 return target;
5211 case BFIN_BUILTIN_MULT_1X32X32:
5212 case BFIN_BUILTIN_MULT_1X32X32NS:
5213 arg0 = CALL_EXPR_ARG (exp, 0);
5214 arg1 = CALL_EXPR_ARG (exp, 1);
5215 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5216 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
5217 if (! target
5218 || !register_operand (target, SImode))
5219 target = gen_reg_rtx (SImode);
5221 a1reg = gen_rtx_REG (PDImode, REG_A1);
5222 a0reg = gen_rtx_REG (PDImode, REG_A0);
5223 tmp1 = gen_lowpart (V2HImode, op0);
5224 tmp2 = gen_lowpart (V2HImode, op1);
5225 emit_insn (gen_flag_macinit1hi (a1reg,
5226 gen_lowpart (HImode, op0),
5227 gen_lowpart (HImode, op1),
5228 GEN_INT (MACFLAG_FU)));
5229 emit_insn (gen_lshrpdi3 (a1reg, a1reg, GEN_INT (16)));
5231 if (fcode == BFIN_BUILTIN_MULT_1X32X32)
5232 emit_insn (gen_flag_mul_macv2hi_parts_acconly (a0reg, a1reg, tmp1, tmp2,
5233 const1_rtx, const1_rtx,
5234 const1_rtx, const0_rtx, a1reg,
5235 const0_rtx, GEN_INT (MACFLAG_NONE),
5236 GEN_INT (MACFLAG_M)));
5237 else
5239 /* For saturating multiplication, there's exactly one special case
5240 to be handled: multiplying the smallest negative value with
5241 itself. Due to shift correction in fractional multiplies, this
5242 can overflow. Iff this happens, OP2 will contain 1, which, when
5243 added in 32 bits to the smallest negative, wraps to the largest
5244 positive, which is the result we want. */
5245 op2 = gen_reg_rtx (V2HImode);
5246 emit_insn (gen_packv2hi (op2, tmp1, tmp2, const0_rtx, const0_rtx));
5247 emit_insn (gen_movsibi (gen_rtx_REG (BImode, REG_CC),
5248 gen_lowpart (SImode, op2)));
5249 emit_insn (gen_flag_mul_macv2hi_parts_acconly_andcc0 (a0reg, a1reg, tmp1, tmp2,
5250 const1_rtx, const1_rtx,
5251 const1_rtx, const0_rtx, a1reg,
5252 const0_rtx, GEN_INT (MACFLAG_NONE),
5253 GEN_INT (MACFLAG_M)));
5254 op2 = gen_reg_rtx (SImode);
5255 emit_insn (gen_movbisi (op2, gen_rtx_REG (BImode, REG_CC)));
5257 emit_insn (gen_flag_machi_parts_acconly (a1reg, tmp2, tmp1,
5258 const1_rtx, const0_rtx,
5259 a1reg, const0_rtx, GEN_INT (MACFLAG_M)));
5260 emit_insn (gen_ashrpdi3 (a1reg, a1reg, GEN_INT (15)));
5261 emit_insn (gen_sum_of_accumulators (target, a0reg, a0reg, a1reg));
5262 if (fcode == BFIN_BUILTIN_MULT_1X32X32NS)
5263 emit_insn (gen_addsi3 (target, target, op2));
5264 return target;
5266 case BFIN_BUILTIN_CPLX_MUL_16:
5267 arg0 = CALL_EXPR_ARG (exp, 0);
5268 arg1 = CALL_EXPR_ARG (exp, 1);
5269 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5270 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
5271 accvec = gen_reg_rtx (V2PDImode);
5273 if (! target
5274 || GET_MODE (target) != V2HImode
5275 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5276 target = gen_reg_rtx (tmode);
5277 if (! register_operand (op0, GET_MODE (op0)))
5278 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
5279 if (! register_operand (op1, GET_MODE (op1)))
5280 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
5282 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
5283 const0_rtx, const0_rtx,
5284 const1_rtx, GEN_INT (MACFLAG_NONE)));
5285 emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
5286 const1_rtx, const1_rtx,
5287 const0_rtx, accvec, const1_rtx, const0_rtx,
5288 GEN_INT (MACFLAG_NONE), accvec));
5290 return target;
5292 case BFIN_BUILTIN_CPLX_MAC_16:
5293 case BFIN_BUILTIN_CPLX_MSU_16:
5294 arg0 = CALL_EXPR_ARG (exp, 0);
5295 arg1 = CALL_EXPR_ARG (exp, 1);
5296 arg2 = CALL_EXPR_ARG (exp, 2);
5297 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5298 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
5299 op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
5300 accvec = gen_reg_rtx (V2PDImode);
5302 if (! target
5303 || GET_MODE (target) != V2HImode
5304 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5305 target = gen_reg_rtx (tmode);
5306 if (! register_operand (op0, GET_MODE (op0)))
5307 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
5308 if (! register_operand (op1, GET_MODE (op1)))
5309 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
5311 tmp1 = gen_reg_rtx (SImode);
5312 tmp2 = gen_reg_rtx (SImode);
5313 emit_insn (gen_ashlsi3 (tmp1, gen_lowpart (SImode, op2), GEN_INT (16)));
5314 emit_move_insn (tmp2, gen_lowpart (SImode, op2));
5315 emit_insn (gen_movstricthi_1 (gen_lowpart (HImode, tmp2), const0_rtx));
5316 emit_insn (gen_load_accumulator_pair (accvec, tmp1, tmp2));
5317 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op0, op1, const0_rtx,
5318 const0_rtx, const0_rtx,
5319 const1_rtx, accvec, const0_rtx,
5320 const0_rtx,
5321 GEN_INT (MACFLAG_W32)));
5322 tmp1 = (fcode == BFIN_BUILTIN_CPLX_MAC_16 ? const1_rtx : const0_rtx);
5323 tmp2 = (fcode == BFIN_BUILTIN_CPLX_MAC_16 ? const0_rtx : const1_rtx);
5324 emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
5325 const1_rtx, const1_rtx,
5326 const0_rtx, accvec, tmp1, tmp2,
5327 GEN_INT (MACFLAG_NONE), accvec));
5329 return target;
5331 default:
5332 break;
5335 for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
5336 if (d->code == fcode)
5337 return bfin_expand_binop_builtin (d->icode, exp, target,
5338 d->macflag);
5340 for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
5341 if (d->code == fcode)
5342 return bfin_expand_unop_builtin (d->icode, exp, target);
5344 gcc_unreachable ();
5347 #undef TARGET_INIT_BUILTINS
5348 #define TARGET_INIT_BUILTINS bfin_init_builtins
5350 #undef TARGET_EXPAND_BUILTIN
5351 #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
5353 #undef TARGET_ASM_GLOBALIZE_LABEL
5354 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label
5356 #undef TARGET_ASM_FILE_START
5357 #define TARGET_ASM_FILE_START output_file_start
5359 #undef TARGET_ATTRIBUTE_TABLE
5360 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
5362 #undef TARGET_COMP_TYPE_ATTRIBUTES
5363 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
5365 #undef TARGET_RTX_COSTS
5366 #define TARGET_RTX_COSTS bfin_rtx_costs
5368 #undef TARGET_ADDRESS_COST
5369 #define TARGET_ADDRESS_COST bfin_address_cost
5371 #undef TARGET_ASM_INTEGER
5372 #define TARGET_ASM_INTEGER bfin_assemble_integer
5374 #undef TARGET_MACHINE_DEPENDENT_REORG
5375 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
5377 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
5378 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
5380 #undef TARGET_ASM_OUTPUT_MI_THUNK
5381 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
5382 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
5383 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
5385 #undef TARGET_SCHED_ADJUST_COST
5386 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
5388 #undef TARGET_SCHED_ISSUE_RATE
5389 #define TARGET_SCHED_ISSUE_RATE bfin_issue_rate
5391 #undef TARGET_PROMOTE_PROTOTYPES
5392 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
5393 #undef TARGET_PROMOTE_FUNCTION_ARGS
5394 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
5395 #undef TARGET_PROMOTE_FUNCTION_RETURN
5396 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true
5398 #undef TARGET_ARG_PARTIAL_BYTES
5399 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
5401 #undef TARGET_PASS_BY_REFERENCE
5402 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
5404 #undef TARGET_SETUP_INCOMING_VARARGS
5405 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
5407 #undef TARGET_STRUCT_VALUE_RTX
5408 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
5410 #undef TARGET_VECTOR_MODE_SUPPORTED_P
5411 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
5413 #undef TARGET_HANDLE_OPTION
5414 #define TARGET_HANDLE_OPTION bfin_handle_option
5416 #undef TARGET_DEFAULT_TARGET_FLAGS
5417 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
5419 #undef TARGET_SECONDARY_RELOAD
5420 #define TARGET_SECONDARY_RELOAD bfin_secondary_reload
5422 #undef TARGET_DELEGITIMIZE_ADDRESS
5423 #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address
5425 #undef TARGET_CANNOT_FORCE_CONST_MEM
5426 #define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem
5428 struct gcc_target targetm = TARGET_INITIALIZER;