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/>. */
23 #include "coretypes.h"
27 #include "hard-reg-set.h"
29 #include "insn-config.h"
30 #include "insn-codes.h"
31 #include "conditions.h"
32 #include "insn-flags.h"
34 #include "insn-attr.h"
41 #include "target-def.h"
47 #include "integrate.h"
49 #include "langhooks.h"
50 #include "bfin-protos.h"
53 #include "basic-block.h"
54 #include "cfglayout.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
93 static int bfin_flag_var_tracking;
96 bfin_cpu_t bfin_cpu_type = DEFAULT_CPU_TYPE;
98 int splitting_for_sched;
101 bfin_globalize_label (FILE *stream, const char *name)
103 fputs (".global ", stream);
104 assemble_name (stream, name);
110 output_file_start (void)
112 FILE *file = asm_out_file;
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
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. */
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. */
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))
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
164 legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
169 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
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;
180 unspec = UNSPEC_MOVE_FDPIC;
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;
197 else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
201 if (GET_CODE (addr) == CONST)
203 addr = XEXP (addr, 0);
204 gcc_assert (GET_CODE (addr) == PLUS);
207 if (XEXP (addr, 0) == picreg)
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,
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);
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. */
248 n_dregs_to_save (bool is_inthandler)
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)
262 unsigned test = EH_RETURN_DATA_REGNO (j);
263 if (test == INVALID_REGNUM)
266 return REG_R7 - i + 1;
274 /* Like n_dregs_to_save, but compute number of PREGS to save. */
277 n_pregs_to_save (bool is_inthandler)
281 for (i = REG_P0; i <= REG_P5; i++)
282 if ((df_regs_ever_live_p (i) && (is_inthandler || ! call_used_regs[i]))
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;
291 /* Determine if we are going to save the frame pointer in the prologue. */
294 must_save_fp_p (void)
296 return frame_pointer_needed || df_regs_ever_live_p (REG_FP);
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)
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. */
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;
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,
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)));
344 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
350 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
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. */
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;
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)));
388 for (i = 0; i < total; i++)
391 ? gen_rtx_PLUS (Pmode, spreg, GEN_INT (i * 4))
393 rtx memref = gen_rtx_MEM (word_mode, addr);
396 XVECEXP (pat, 0, i + 1)
397 = gen_rtx_SET (VOIDmode, gen_rtx_REG (word_mode, regno), memref);
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.
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.
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. */
433 setup_incoming_varargs (CUMULATIVE_ARGS *cum,
434 enum machine_mode mode ATTRIBUTE_UNUSED,
435 tree type ATTRIBUTE_UNUSED, int *pretend_size,
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));
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)
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)
479 /* Return the number of registers pushed during the prologue. */
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. */
498 if (must_save_fp_p ())
500 if (! current_function_is_leaf)
504 if (fkind != SUBROUTINE)
508 /* Increment once for ASTAT. */
512 if (lookup_attribute ("nesting", attrs))
515 for (i = REG_P7 + 1; i < REG_CC; i++)
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;
524 /* Return the offset between two registers, one to be eliminated, and the other
525 its replacement, at the start of a routine. */
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 ();
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. */
553 frame_related_constant_load (rtx reg, HOST_WIDE_INT constant, bool related)
556 rtx cst = GEN_INT (constant);
558 if (constant >= -32768 && constant < 65536)
559 insn = emit_move_insn (reg, cst);
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));
566 RTX_FRAME_RELATED_P (insn) = 1;
567 insn = emit_insn (gen_movsi_low (reg, reg, cst));
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
580 add_to_reg (rtx reg, HOST_WIDE_INT value, int frame, int epilogue_p)
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)
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
603 tmpreg = gen_rtx_REG (SImode, REG_P1);
607 for (i = REG_P0; i <= REG_P5; i++)
608 if ((df_regs_ever_live_p (i) && ! call_used_regs[i])
610 && i == PIC_OFFSET_TABLE_REGNUM
611 && (current_function_uses_pic_offset_table
612 || (TARGET_ID_SHARED_LIBRARY
613 && ! current_function_is_leaf))))
616 tmpreg = gen_rtx_REG (SImode, i);
619 tmpreg = gen_rtx_REG (SImode, REG_P1);
620 tmpreg2 = gen_rtx_REG (SImode, REG_I0);
621 emit_move_insn (tmpreg2, tmpreg);
626 frame_related_constant_load (tmpreg, value, TRUE);
628 insn = emit_move_insn (tmpreg, GEN_INT (value));
630 insn = emit_insn (gen_addsi3 (reg, reg, tmpreg));
632 RTX_FRAME_RELATED_P (insn) = 1;
634 if (tmpreg2 != NULL_RTX)
635 emit_move_insn (tmpreg, tmpreg2);
646 /* We could use -62, but that would leave the stack unaligned, so
650 insn = emit_insn (gen_addsi3 (reg, reg, GEN_INT (size)));
652 RTX_FRAME_RELATED_P (insn) = 1;
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). */
663 emit_link_insn (rtx spreg, HOST_WIDE_INT frame_size)
665 HOST_WIDE_INT link_size = frame_size;
669 if (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;
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. */
703 if (current_function_outgoing_args_size)
705 if (current_function_outgoing_args_size >= FIXED_STACK_AREA)
706 return current_function_outgoing_args_size;
708 return FIXED_STACK_AREA;
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
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);
727 if (! current_function_is_leaf)
729 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
730 gen_rtx_PRE_DEC (Pmode, spreg)),
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
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 ());
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). */
783 expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind)
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);
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);
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
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)
815 expand_prologue_reg_save (spreg, all, true);
817 for (i = REG_P7 + 1; i < REG_CC; i++)
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));
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
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);
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). */
862 expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind)
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"
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
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)
889 for (i = REG_CC - 1; i > REG_P7; i--)
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);
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. */
920 bfin_load_pic_reg (rtx dest)
922 struct cgraph_local_info *i = NULL;
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. */
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);
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)));
943 /* Generate RTL for the prologue of the current function. */
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);
959 if (current_function_limit_stack
960 || TARGET_STACK_CHECK_L1)
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);
970 emit_move_insn (p2reg, gen_int_mode (0xFFB00000, SImode));
971 emit_move_insn (p2reg, gen_rtx_MEM (Pmode, p2reg));
974 if (GET_CODE (lim) == SYMBOL_REF)
976 if (TARGET_ID_SHARED_LIBRARY)
978 rtx p1reg = gen_rtx_REG (Pmode, REG_P1);
980 pic_reg_loaded = bfin_load_pic_reg (p2reg);
981 val = legitimize_pic_address (stack_limit_rtx, p1reg,
983 emit_move_insn (p1reg, val);
984 frame_related_constant_load (p2reg, offset, FALSE);
985 emit_insn (gen_addsi3 (p2reg, p2reg, p1reg));
990 rtx limit = plus_constant (lim, offset);
991 emit_move_insn (p2reg, limit);
998 emit_move_insn (p2reg, lim);
999 add_to_reg (p2reg, offset, 0, 0);
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
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,
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);
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. */
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
1058 if (funkind (TREE_TYPE (current_function_decl)) != SUBROUTINE
1059 && !df_regs_ever_live_p (new_reg))
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)
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)
1095 bfin_delegitimize_address (rtx orig_x)
1099 if (GET_CODE (x) != MEM)
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);
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);
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);
1132 if (GET_CODE (XEXP (op, 1)) == UNSPEC)
1135 offset = INTVAL (XEXP (op, 1));
1137 /* All byte loads use a 16-bit offset. */
1138 if (GET_MODE_SIZE (mode) == 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. */
1156 bfin_dsp_memref_p (rtx x)
1161 if (GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_INC
1162 || GET_CODE (x) == POST_DEC || GET_CODE (x) == PRE_DEC)
1167 /* Return cost of the memory address ADDR.
1168 All addressing modes are equally cheap on the Blackfin. */
1171 bfin_address_cost (rtx addr ATTRIBUTE_UNUSED)
1176 /* Subroutine of print_operand; used to print a memory reference X to FILE. */
1179 print_address_operand (FILE *file, rtx x)
1181 switch (GET_CODE (x))
1184 output_address (XEXP (x, 0));
1185 fprintf (file, "+");
1186 output_address (XEXP (x, 1));
1190 fprintf (file, "--");
1191 output_address (XEXP (x, 0));
1194 output_address (XEXP (x, 0));
1195 fprintf (file, "++");
1198 output_address (XEXP (x, 0));
1199 fprintf (file, "--");
1203 gcc_assert (GET_CODE (x) != MEM);
1204 print_operand (file, x, 0);
1209 /* Adding intp DImode support by Tony
1215 print_operand (FILE *file, rtx x, char code)
1217 enum machine_mode mode;
1221 if (GET_MODE (current_output_insn) == SImode)
1222 fprintf (file, " ||");
1224 fprintf (file, ";");
1228 mode = GET_MODE (x);
1233 switch (GET_CODE (x))
1236 fprintf (file, "e");
1239 fprintf (file, "ne");
1242 fprintf (file, "g");
1245 fprintf (file, "l");
1248 fprintf (file, "ge");
1251 fprintf (file, "le");
1254 fprintf (file, "g");
1257 fprintf (file, "l");
1260 fprintf (file, "ge");
1263 fprintf (file, "le");
1266 output_operand_lossage ("invalid %%j value");
1270 case 'J': /* reverse logic */
1271 switch (GET_CODE(x))
1274 fprintf (file, "ne");
1277 fprintf (file, "e");
1280 fprintf (file, "le");
1283 fprintf (file, "ge");
1286 fprintf (file, "l");
1289 fprintf (file, "g");
1292 fprintf (file, "le");
1295 fprintf (file, "ge");
1298 fprintf (file, "l");
1301 fprintf (file, "g");
1304 output_operand_lossage ("invalid %%J value");
1309 switch (GET_CODE (x))
1315 fprintf (file, "%s", short_reg_names[REGNO (x)]);
1317 output_operand_lossage ("invalid operand for code '%c'", code);
1319 else if (code == 'd')
1322 fprintf (file, "%s", high_reg_names[REGNO (x)]);
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)]);
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)]);
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");
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)]);
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]);
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)]);
1368 output_operand_lossage ("invalid operand for code '%c'", code);
1371 fprintf (file, "%s", reg_names[REGNO (x)]);
1377 print_address_operand (file, x);
1389 fputs ("(FU)", file);
1392 fputs ("(T)", file);
1395 fputs ("(TFU)", file);
1398 fputs ("(W32)", file);
1401 fputs ("(IS)", file);
1404 fputs ("(IU)", file);
1407 fputs ("(IH)", file);
1410 fputs ("(M)", file);
1413 fputs ("(IS,M)", file);
1416 fputs ("(ISS2)", file);
1419 fputs ("(S2RND)", file);
1426 else if (code == 'b')
1428 if (INTVAL (x) == 0)
1430 else if (INTVAL (x) == 1)
1436 /* Moves to half registers with d or h modifiers always use unsigned
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));
1455 output_addr_const (file, x);
1459 output_operand_lossage ("invalid const_double operand");
1463 switch (XINT (x, 1))
1465 case UNSPEC_MOVE_PIC:
1466 output_addr_const (file, XVECEXP (x, 0, 0));
1467 fprintf (file, "@GOT");
1470 case UNSPEC_MOVE_FDPIC:
1471 output_addr_const (file, XVECEXP (x, 0, 0));
1472 fprintf (file, "@GOT17M4");
1475 case UNSPEC_FUNCDESC_GOT17M4:
1476 output_addr_const (file, XVECEXP (x, 0, 0));
1477 fprintf (file, "@FUNCDESC_GOT17M4");
1480 case UNSPEC_LIBRARY_OFFSET:
1481 fprintf (file, "_current_shared_library_p5_offset_");
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.
1505 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
1506 rtx libname ATTRIBUTE_UNUSED)
1508 static CUMULATIVE_ARGS 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;
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.) */
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)
1546 cum->arg_regs = NULL;
1550 for (count = 1; count <= words; count++)
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
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). */
1571 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1572 int named ATTRIBUTE_UNUSED)
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);
1585 return gen_rtx_REG (mode, *(cum->arg_regs));
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
1600 bfin_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1601 tree type ATTRIBUTE_UNUSED,
1602 bool named ATTRIBUTE_UNUSED)
1605 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1606 int bytes_left = cum->nregs * UNITS_PER_WORD;
1611 if (bytes_left == 0)
1613 if (bytes > bytes_left)
1618 /* Variable sized types are passed by reference. */
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. */
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. */
1651 function_arg_regno_p (int n)
1654 for (i = 0; arg_regs[i] != -1; i++)
1655 if (n == arg_regs[i])
1660 /* Returns 1 if OP contains a symbol reference */
1663 symbolic_reference_mentioned_p (rtx op)
1665 register const char *fmt;
1668 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
1671 fmt = GET_RTX_FORMAT (GET_CODE (op));
1672 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
1678 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
1679 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
1683 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
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. */
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)
1701 if (!TARGET_ID_SHARED_LIBRARY || TARGET_SEP_DATA)
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. */
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. */
1727 initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt)
1729 rtx t1 = copy_to_reg (fnaddr);
1730 rtx t2 = copy_to_reg (cxt);
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);
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]. */
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]);
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]. */
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];
1789 gcc_assert (!reload_in_progress && !reload_completed);
1791 op0 = force_reg (mode, XEXP (op, 0));
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])
1802 /* Don't generate memory->memory or constant->memory moves, go through a
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]);
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". */
1818 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
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);
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);
1844 bfin_longcall_p (rtx op, int call_cookie)
1846 gcc_assert (GET_CODE (op) == SYMBOL_REF);
1847 if (call_cookie & CALL_SHORT)
1849 if (call_cookie & CALL_LONG)
1851 if (TARGET_LONG_CALLS)
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. */
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;
1867 rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REGNO);
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);
1882 int caller_has_l1_text, callee_has_l1_text;
1884 caller_has_l1_text = callee_has_l1_text = 0;
1886 if (lookup_attribute ("l1_text",
1887 DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE)
1888 caller_has_l1_text = 1;
1890 if (GET_CODE (callee) == SYMBOL_REF
1891 && SYMBOL_REF_DECL (callee) && DECL_P (SYMBOL_REF_DECL (callee))
1894 DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE)
1895 callee_has_l1_text = 1;
1897 if (GET_CODE (callee) != SYMBOL_REF
1898 || bfin_longcall_p (callee, INTVAL (cookie))
1899 || (GET_CODE (callee) == SYMBOL_REF
1900 && !SYMBOL_REF_LOCAL_P (callee)
1901 && TARGET_INLINE_PLT)
1902 || caller_has_l1_text != callee_has_l1_text
1903 || (caller_has_l1_text && callee_has_l1_text
1904 && (GET_CODE (callee) != SYMBOL_REF
1905 || !SYMBOL_REF_LOCAL_P (callee))))
1908 if (! address_operand (addr, Pmode))
1909 addr = force_reg (Pmode, addr);
1911 fnaddr = gen_reg_rtx (SImode);
1912 emit_insn (gen_load_funcdescsi (fnaddr, addr));
1913 fnaddr = gen_rtx_MEM (Pmode, fnaddr);
1915 picreg = gen_reg_rtx (SImode);
1916 emit_insn (gen_load_funcdescsi (picreg,
1917 plus_constant (addr, 4)));
1922 else if ((!register_no_elim_operand (callee, Pmode)
1923 && GET_CODE (callee) != SYMBOL_REF)
1924 || (GET_CODE (callee) == SYMBOL_REF
1925 && ((TARGET_ID_SHARED_LIBRARY && !TARGET_LEAF_ID_SHARED_LIBRARY)
1926 || bfin_longcall_p (callee, INTVAL (cookie)))))
1928 callee = copy_to_mode_reg (Pmode, callee);
1929 fnaddr = gen_rtx_MEM (Pmode, callee);
1931 call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
1934 call = gen_rtx_SET (VOIDmode, retval, call);
1936 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nelts));
1938 XVECEXP (pat, 0, n++) = call;
1940 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, picreg);
1941 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie);
1943 XVECEXP (pat, 0, n++) = gen_rtx_RETURN (VOIDmode);
1944 call = emit_call_insn (pat);
1946 CALL_INSN_FUNCTION_USAGE (call) = use;
1949 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
1952 hard_regno_mode_ok (int regno, enum machine_mode mode)
1954 /* Allow only dregs to store value of mode HI or QI */
1955 enum reg_class class = REGNO_REG_CLASS (regno);
1960 if (mode == V2HImode)
1961 return D_REGNO_P (regno);
1962 if (class == CCREGS)
1963 return mode == BImode;
1964 if (mode == PDImode || mode == V2PDImode)
1965 return regno == REG_A0 || regno == REG_A1;
1967 /* Allow all normal 32-bit regs, except REG_M3, in case regclass ever comes
1968 up with a bad register class (such as ALL_REGS) for DImode. */
1970 return regno < REG_M3;
1973 && TEST_HARD_REG_BIT (reg_class_contents[PROLOGUE_REGS], regno))
1976 return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno);
1979 /* Implements target hook vector_mode_supported_p. */
1982 bfin_vector_mode_supported_p (enum machine_mode mode)
1984 return mode == V2HImode;
1987 /* Return the cost of moving data from a register in class CLASS1 to
1988 one in class CLASS2. A cost of 2 is the default. */
1991 bfin_register_move_cost (enum machine_mode mode,
1992 enum reg_class class1, enum reg_class class2)
1994 /* These need secondary reloads, so they're more expensive. */
1995 if ((class1 == CCREGS && class2 != DREGS)
1996 || (class1 != DREGS && class2 == CCREGS))
1999 /* If optimizing for size, always prefer reg-reg over reg-memory moves. */
2003 /* There are some stalls involved when moving from a DREG to a different
2004 class reg, and using the value in one of the following instructions.
2005 Attempt to model this by slightly discouraging such moves. */
2006 if (class1 == DREGS && class2 != DREGS)
2009 if (GET_MODE_CLASS (mode) == MODE_INT)
2011 /* Discourage trying to use the accumulators. */
2012 if (TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A0)
2013 || TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A1)
2014 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A0)
2015 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A1))
2021 /* Return the cost of moving data of mode M between a
2022 register and memory. A value of 2 is the default; this cost is
2023 relative to those in `REGISTER_MOVE_COST'.
2025 ??? In theory L1 memory has single-cycle latency. We should add a switch
2026 that tells the compiler whether we expect to use only L1 memory for the
2027 program; it'll make the costs more accurate. */
2030 bfin_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
2031 enum reg_class class,
2032 int in ATTRIBUTE_UNUSED)
2034 /* Make memory accesses slightly more expensive than any register-register
2035 move. Also, penalize non-DP registers, since they need secondary
2036 reloads to load and store. */
2037 if (! reg_class_subset_p (class, DPREGS))
2043 /* Inform reload about cases where moving X with a mode MODE to a register in
2044 CLASS requires an extra scratch register. Return the class needed for the
2045 scratch register. */
2047 static enum reg_class
2048 bfin_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x, enum reg_class class,
2049 enum machine_mode mode, secondary_reload_info *sri)
2051 /* If we have HImode or QImode, we can only use DREGS as secondary registers;
2052 in most other cases we can also use PREGS. */
2053 enum reg_class default_class = GET_MODE_SIZE (mode) >= 4 ? DPREGS : DREGS;
2054 enum reg_class x_class = NO_REGS;
2055 enum rtx_code code = GET_CODE (x);
2058 x = SUBREG_REG (x), code = GET_CODE (x);
2061 int regno = REGNO (x);
2062 if (regno >= FIRST_PSEUDO_REGISTER)
2063 regno = reg_renumber[regno];
2068 x_class = REGNO_REG_CLASS (regno);
2071 /* We can be asked to reload (plus (FP) (large_constant)) into a DREG.
2072 This happens as a side effect of register elimination, and we need
2073 a scratch register to do it. */
2074 if (fp_plus_const_operand (x, mode))
2076 rtx op2 = XEXP (x, 1);
2077 int large_constant_p = ! CONST_7BIT_IMM_P (INTVAL (op2));
2079 if (class == PREGS || class == PREGS_CLOBBERED)
2081 /* If destination is a DREG, we can do this without a scratch register
2082 if the constant is valid for an add instruction. */
2083 if ((class == DREGS || class == DPREGS)
2084 && ! large_constant_p)
2086 /* Reloading to anything other than a DREG? Use a PREG scratch
2088 sri->icode = CODE_FOR_reload_insi;
2092 /* Data can usually be moved freely between registers of most classes.
2093 AREGS are an exception; they can only move to or from another register
2094 in AREGS or one in DREGS. They can also be assigned the constant 0. */
2095 if (x_class == AREGS || x_class == EVEN_AREGS || x_class == ODD_AREGS)
2096 return (class == DREGS || class == AREGS || class == EVEN_AREGS
2097 || class == ODD_AREGS
2100 if (class == AREGS || class == EVEN_AREGS || class == ODD_AREGS)
2102 if (x != const0_rtx && x_class != DREGS)
2108 /* CCREGS can only be moved from/to DREGS. */
2109 if (class == CCREGS && x_class != DREGS)
2111 if (x_class == CCREGS && class != DREGS)
2114 /* All registers other than AREGS can load arbitrary constants. The only
2115 case that remains is MEM. */
2117 if (! reg_class_subset_p (class, default_class))
2118 return default_class;
2122 /* Implement TARGET_HANDLE_OPTION. */
2125 bfin_handle_option (size_t code, const char *arg, int value)
2129 case OPT_mshared_library_id_:
2130 if (value > MAX_LIBRARY_ID)
2131 error ("-mshared-library-id=%s is not between 0 and %d",
2132 arg, MAX_LIBRARY_ID);
2133 bfin_lib_id_given = 1;
2137 if (strcmp (arg, "bf531") == 0)
2138 bfin_cpu_type = BFIN_CPU_BF531;
2139 else if (strcmp (arg, "bf532") == 0)
2140 bfin_cpu_type = BFIN_CPU_BF532;
2141 else if (strcmp (arg, "bf533") == 0)
2142 bfin_cpu_type = BFIN_CPU_BF533;
2143 else if (strcmp (arg, "bf534") == 0)
2144 bfin_cpu_type = BFIN_CPU_BF534;
2145 else if (strcmp (arg, "bf536") == 0)
2146 bfin_cpu_type = BFIN_CPU_BF536;
2147 else if (strcmp (arg, "bf537") == 0)
2148 bfin_cpu_type = BFIN_CPU_BF537;
2149 else if (strcmp (arg, "bf561") == 0)
2151 warning (0, "bf561 support is incomplete yet.");
2152 bfin_cpu_type = BFIN_CPU_BF561;
2163 static struct machine_function *
2164 bfin_init_machine_status (void)
2166 struct machine_function *f;
2168 f = ggc_alloc_cleared (sizeof (struct machine_function));
2173 /* Implement the macro OVERRIDE_OPTIONS. */
2176 override_options (void)
2178 if (TARGET_OMIT_LEAF_FRAME_POINTER)
2179 flag_omit_frame_pointer = 1;
2181 /* Library identification */
2182 if (bfin_lib_id_given && ! TARGET_ID_SHARED_LIBRARY)
2183 error ("-mshared-library-id= specified without -mid-shared-library");
2185 if (TARGET_ID_SHARED_LIBRARY && flag_pic == 0)
2188 if (stack_limit_rtx && TARGET_STACK_CHECK_L1)
2189 error ("Can't use multiple stack checking methods together.");
2191 if (TARGET_ID_SHARED_LIBRARY && TARGET_FDPIC)
2192 error ("ID shared libraries and FD-PIC mode can't be used together.");
2194 /* Don't allow the user to specify -mid-shared-library and -msep-data
2195 together, as it makes little sense from a user's point of view... */
2196 if (TARGET_SEP_DATA && TARGET_ID_SHARED_LIBRARY)
2197 error ("cannot specify both -msep-data and -mid-shared-library");
2198 /* ... internally, however, it's nearly the same. */
2199 if (TARGET_SEP_DATA)
2200 target_flags |= MASK_ID_SHARED_LIBRARY | MASK_LEAF_ID_SHARED_LIBRARY;
2202 /* There is no single unaligned SI op for PIC code. Sometimes we
2203 need to use ".4byte" and sometimes we need to use ".picptr".
2204 See bfin_assemble_integer for details. */
2206 targetm.asm_out.unaligned_op.si = 0;
2208 /* Silently turn off flag_pic if not doing FDPIC or ID shared libraries,
2209 since we don't support it and it'll just break. */
2210 if (flag_pic && !TARGET_FDPIC && !TARGET_ID_SHARED_LIBRARY)
2213 flag_schedule_insns = 0;
2215 /* Passes after sched2 can break the helpful TImode annotations that
2216 haifa-sched puts on every insn. Just do scheduling in reorg. */
2217 bfin_flag_schedule_insns2 = flag_schedule_insns_after_reload;
2218 flag_schedule_insns_after_reload = 0;
2220 init_machine_status = bfin_init_machine_status;
2223 /* Return the destination address of BRANCH.
2224 We need to use this instead of get_attr_length, because the
2225 cbranch_with_nops pattern conservatively sets its length to 6, and
2226 we still prefer to use shorter sequences. */
2229 branch_dest (rtx branch)
2233 rtx pat = PATTERN (branch);
2234 if (GET_CODE (pat) == PARALLEL)
2235 pat = XVECEXP (pat, 0, 0);
2236 dest = SET_SRC (pat);
2237 if (GET_CODE (dest) == IF_THEN_ELSE)
2238 dest = XEXP (dest, 1);
2239 dest = XEXP (dest, 0);
2240 dest_uid = INSN_UID (dest);
2241 return INSN_ADDRESSES (dest_uid);
2244 /* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates
2245 it's a branch that's predicted taken. */
2248 cbranch_predicted_taken_p (rtx insn)
2250 rtx x = find_reg_note (insn, REG_BR_PROB, 0);
2254 int pred_val = INTVAL (XEXP (x, 0));
2256 return pred_val >= REG_BR_PROB_BASE / 2;
2262 /* Templates for use by asm_conditional_branch. */
2264 static const char *ccbranch_templates[][3] = {
2265 { "if !cc jump %3;", "if cc jump 4 (bp); jump.s %3;", "if cc jump 6 (bp); jump.l %3;" },
2266 { "if cc jump %3;", "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" },
2267 { "if !cc jump %3 (bp);", "if cc jump 4; jump.s %3;", "if cc jump 6; jump.l %3;" },
2268 { "if cc jump %3 (bp);", "if !cc jump 4; jump.s %3;", "if !cc jump 6; jump.l %3;" },
2271 /* Output INSN, which is a conditional branch instruction with operands
2274 We deal with the various forms of conditional branches that can be generated
2275 by bfin_reorg to prevent the hardware from doing speculative loads, by
2276 - emitting a sufficient number of nops, if N_NOPS is nonzero, or
2277 - always emitting the branch as predicted taken, if PREDICT_TAKEN is true.
2278 Either of these is only necessary if the branch is short, otherwise the
2279 template we use ends in an unconditional jump which flushes the pipeline
2283 asm_conditional_branch (rtx insn, rtx *operands, int n_nops, int predict_taken)
2285 int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
2286 /* Note : offset for instructions like if cc jmp; jump.[sl] offset
2287 is to be taken from start of if cc rather than jump.
2288 Range for jump.s is (-4094, 4096) instead of (-4096, 4094)
2290 int len = (offset >= -1024 && offset <= 1022 ? 0
2291 : offset >= -4094 && offset <= 4096 ? 1
2293 int bp = predict_taken && len == 0 ? 1 : cbranch_predicted_taken_p (insn);
2294 int idx = (bp << 1) | (GET_CODE (operands[0]) == EQ ? BRF : BRT);
2295 output_asm_insn (ccbranch_templates[idx][len], operands);
2296 gcc_assert (n_nops == 0 || !bp);
2298 while (n_nops-- > 0)
2299 output_asm_insn ("nop;", NULL);
2302 /* Emit rtl for a comparison operation CMP in mode MODE. Operands have been
2303 stored in bfin_compare_op0 and bfin_compare_op1 already. */
2306 bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED)
2308 enum rtx_code code1, code2;
2309 rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1;
2310 rtx tem = bfin_cc_rtx;
2311 enum rtx_code code = GET_CODE (cmp);
2313 /* If we have a BImode input, then we already have a compare result, and
2314 do not need to emit another comparison. */
2315 if (GET_MODE (op0) == BImode)
2317 gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
2318 tem = op0, code2 = code;
2323 /* bfin has these conditions */
2333 code1 = reverse_condition (code);
2337 emit_insn (gen_rtx_SET (BImode, tem,
2338 gen_rtx_fmt_ee (code1, BImode, op0, op1)));
2341 return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode));
2344 /* Return nonzero iff C has exactly one bit set if it is interpreted
2345 as a 32-bit constant. */
2348 log2constp (unsigned HOST_WIDE_INT c)
2351 return c != 0 && (c & (c-1)) == 0;
2354 /* Returns the number of consecutive least significant zeros in the binary
2355 representation of *V.
2356 We modify *V to contain the original value arithmetically shifted right by
2357 the number of zeroes. */
2360 shiftr_zero (HOST_WIDE_INT *v)
2362 unsigned HOST_WIDE_INT tmp = *v;
2363 unsigned HOST_WIDE_INT sgn;
2369 sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1));
2370 while ((tmp & 0x1) == 0 && n <= 32)
2372 tmp = (tmp >> 1) | sgn;
2379 /* After reload, split the load of an immediate constant. OPERANDS are the
2380 operands of the movsi_insn pattern which we are splitting. We return
2381 nonzero if we emitted a sequence to load the constant, zero if we emitted
2382 nothing because we want to use the splitter's default sequence. */
2385 split_load_immediate (rtx operands[])
2387 HOST_WIDE_INT val = INTVAL (operands[1]);
2389 HOST_WIDE_INT shifted = val;
2390 HOST_WIDE_INT shifted_compl = ~val;
2391 int num_zero = shiftr_zero (&shifted);
2392 int num_compl_zero = shiftr_zero (&shifted_compl);
2393 unsigned int regno = REGNO (operands[0]);
2395 /* This case takes care of single-bit set/clear constants, which we could
2396 also implement with BITSET/BITCLR. */
2398 && shifted >= -32768 && shifted < 65536
2399 && (D_REGNO_P (regno)
2400 || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))
2402 emit_insn (gen_movsi (operands[0], GEN_INT (shifted)));
2403 emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));
2408 tmp |= -(tmp & 0x8000);
2410 /* If high word has one bit set or clear, try to use a bit operation. */
2411 if (D_REGNO_P (regno))
2413 if (log2constp (val & 0xFFFF0000))
2415 emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));
2416 emit_insn (gen_iorsi3 (operands[0], operands[0], GEN_INT (val & 0xFFFF0000)));
2419 else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)
2421 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2422 emit_insn (gen_andsi3 (operands[0], operands[0], GEN_INT (val | 0xFFFF)));
2426 if (D_REGNO_P (regno))
2428 if (CONST_7BIT_IMM_P (tmp))
2430 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2431 emit_insn (gen_movstricthi_high (operands[0], GEN_INT (val & -65536)));
2435 if ((val & 0xFFFF0000) == 0)
2437 emit_insn (gen_movsi (operands[0], const0_rtx));
2438 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2442 if ((val & 0xFFFF0000) == 0xFFFF0000)
2444 emit_insn (gen_movsi (operands[0], constm1_rtx));
2445 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2450 /* Need DREGs for the remaining case. */
2455 && num_compl_zero && CONST_7BIT_IMM_P (shifted_compl))
2457 /* If optimizing for size, generate a sequence that has more instructions
2459 emit_insn (gen_movsi (operands[0], GEN_INT (shifted_compl)));
2460 emit_insn (gen_ashlsi3 (operands[0], operands[0],
2461 GEN_INT (num_compl_zero)));
2462 emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
2468 /* Return true if the legitimate memory address for a memory operand of mode
2469 MODE. Return false if not. */
2472 bfin_valid_add (enum machine_mode mode, HOST_WIDE_INT value)
2474 unsigned HOST_WIDE_INT v = value > 0 ? value : -value;
2475 int sz = GET_MODE_SIZE (mode);
2476 int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2;
2477 /* The usual offsettable_memref machinery doesn't work so well for this
2478 port, so we deal with the problem here. */
2479 if (value > 0 && sz == 8)
2481 return (v & ~(0x7fff << shift)) == 0;
2485 bfin_valid_reg_p (unsigned int regno, int strict, enum machine_mode mode,
2486 enum rtx_code outer_code)
2489 return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH);
2491 return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH);
2495 bfin_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
2497 switch (GET_CODE (x)) {
2499 if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM))
2503 if (REG_P (XEXP (x, 0))
2504 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS)
2505 && ((GET_CODE (XEXP (x, 1)) == UNSPEC && mode == SImode)
2506 || (GET_CODE (XEXP (x, 1)) == CONST_INT
2507 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
2512 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2513 && REG_P (XEXP (x, 0))
2514 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC))
2517 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2518 && XEXP (x, 0) == stack_pointer_rtx
2519 && REG_P (XEXP (x, 0))
2520 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC))
2529 /* Decide whether we can force certain constants to memory. If we
2530 decide we can't, the caller should be able to cope with it in
2534 bfin_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
2536 /* We have only one class of non-legitimate constants, and our movsi
2537 expander knows how to handle them. Dropping these constants into the
2538 data section would only shift the problem - we'd still get relocs
2539 outside the object, in the data section rather than the text section. */
2543 /* Ensure that for any constant of the form symbol + offset, the offset
2544 remains within the object. Any other constants are ok.
2545 This ensures that flat binaries never have to deal with relocations
2546 crossing section boundaries. */
2549 bfin_legitimate_constant_p (rtx x)
2552 HOST_WIDE_INT offset;
2554 if (GET_CODE (x) != CONST)
2558 gcc_assert (GET_CODE (x) == PLUS);
2562 if (GET_CODE (sym) != SYMBOL_REF
2563 || GET_CODE (x) != CONST_INT)
2565 offset = INTVAL (x);
2567 if (SYMBOL_REF_DECL (sym) == 0)
2570 || offset >= int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (sym))))
2577 bfin_rtx_costs (rtx x, int code, int outer_code, int *total)
2579 int cost2 = COSTS_N_INSNS (1);
2585 if (outer_code == SET || outer_code == PLUS)
2586 *total = CONST_7BIT_IMM_P (INTVAL (x)) ? 0 : cost2;
2587 else if (outer_code == AND)
2588 *total = log2constp (~INTVAL (x)) ? 0 : cost2;
2589 else if (outer_code == LE || outer_code == LT || outer_code == EQ)
2590 *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
2591 else if (outer_code == LEU || outer_code == LTU)
2592 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
2593 else if (outer_code == MULT)
2594 *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
2595 else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
2597 else if (outer_code == ASHIFT || outer_code == ASHIFTRT
2598 || outer_code == LSHIFTRT)
2599 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
2600 else if (outer_code == IOR || outer_code == XOR)
2601 *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
2610 *total = COSTS_N_INSNS (2);
2616 if (GET_MODE (x) == SImode)
2618 if (GET_CODE (op0) == MULT
2619 && GET_CODE (XEXP (op0, 1)) == CONST_INT)
2621 HOST_WIDE_INT val = INTVAL (XEXP (op0, 1));
2622 if (val == 2 || val == 4)
2625 *total += rtx_cost (XEXP (op0, 0), outer_code);
2626 *total += rtx_cost (op1, outer_code);
2631 if (GET_CODE (op0) != REG
2632 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2633 *total += rtx_cost (op0, SET);
2634 #if 0 /* We'd like to do this for accuracy, but it biases the loop optimizer
2635 towards creating too many induction variables. */
2636 if (!reg_or_7bit_operand (op1, SImode))
2637 *total += rtx_cost (op1, SET);
2640 else if (GET_MODE (x) == DImode)
2643 if (GET_CODE (op1) != CONST_INT
2644 || !CONST_7BIT_IMM_P (INTVAL (op1)))
2645 *total += rtx_cost (op1, PLUS);
2646 if (GET_CODE (op0) != REG
2647 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2648 *total += rtx_cost (op0, PLUS);
2653 if (GET_MODE (x) == DImode)
2662 if (GET_MODE (x) == DImode)
2669 if (GET_CODE (op0) != REG
2670 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2671 *total += rtx_cost (op0, code);
2681 /* Handle special cases of IOR: rotates, ALIGN insns, movstricthi_high. */
2684 if ((GET_CODE (op0) == LSHIFTRT && GET_CODE (op1) == ASHIFT)
2685 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == ZERO_EXTEND)
2686 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT)
2687 || (GET_CODE (op0) == AND && GET_CODE (op1) == CONST_INT))
2694 if (GET_CODE (op0) != REG
2695 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2696 *total += rtx_cost (op0, code);
2698 if (GET_MODE (x) == DImode)
2704 if (GET_MODE (x) != SImode)
2709 if (! rhs_andsi3_operand (XEXP (x, 1), SImode))
2710 *total += rtx_cost (XEXP (x, 1), code);
2714 if (! regorlog2_operand (XEXP (x, 1), SImode))
2715 *total += rtx_cost (XEXP (x, 1), code);
2722 if (outer_code == SET
2723 && XEXP (x, 1) == const1_rtx
2724 && GET_CODE (XEXP (x, 2)) == CONST_INT)
2740 if (GET_CODE (op0) == GET_CODE (op1)
2741 && (GET_CODE (op0) == ZERO_EXTEND
2742 || GET_CODE (op0) == SIGN_EXTEND))
2744 *total = COSTS_N_INSNS (1);
2745 op0 = XEXP (op0, 0);
2746 op1 = XEXP (op1, 0);
2748 else if (optimize_size)
2749 *total = COSTS_N_INSNS (1);
2751 *total = COSTS_N_INSNS (3);
2753 if (GET_CODE (op0) != REG
2754 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2755 *total += rtx_cost (op0, MULT);
2756 if (GET_CODE (op1) != REG
2757 && (GET_CODE (op1) != SUBREG || GET_CODE (SUBREG_REG (op1)) != REG))
2758 *total += rtx_cost (op1, MULT);
2764 *total = COSTS_N_INSNS (32);
2769 if (outer_code == SET)
2778 /* Used for communication between {push,pop}_multiple_operation (which
2779 we use not only as a predicate) and the corresponding output functions. */
2780 static int first_preg_to_save, first_dreg_to_save;
2783 push_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2785 int lastdreg = 8, lastpreg = 6;
2788 first_preg_to_save = lastpreg;
2789 first_dreg_to_save = lastdreg;
2790 for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
2792 rtx t = XVECEXP (op, 0, i);
2796 if (GET_CODE (t) != SET)
2800 dest = SET_DEST (t);
2801 if (GET_CODE (dest) != MEM || ! REG_P (src))
2803 dest = XEXP (dest, 0);
2804 if (GET_CODE (dest) != PLUS
2805 || ! REG_P (XEXP (dest, 0))
2806 || REGNO (XEXP (dest, 0)) != REG_SP
2807 || GET_CODE (XEXP (dest, 1)) != CONST_INT
2808 || INTVAL (XEXP (dest, 1)) != -i * 4)
2811 regno = REGNO (src);
2814 if (D_REGNO_P (regno))
2817 first_dreg_to_save = lastdreg = regno - REG_R0;
2819 else if (regno >= REG_P0 && regno <= REG_P7)
2822 first_preg_to_save = lastpreg = regno - REG_P0;
2832 if (regno >= REG_P0 && regno <= REG_P7)
2835 first_preg_to_save = lastpreg = regno - REG_P0;
2837 else if (regno != REG_R0 + lastdreg + 1)
2842 else if (group == 2)
2844 if (regno != REG_P0 + lastpreg + 1)
2853 pop_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2855 int lastdreg = 8, lastpreg = 6;
2858 for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
2860 rtx t = XVECEXP (op, 0, i);
2864 if (GET_CODE (t) != SET)
2868 dest = SET_DEST (t);
2869 if (GET_CODE (src) != MEM || ! REG_P (dest))
2871 src = XEXP (src, 0);
2875 if (! REG_P (src) || REGNO (src) != REG_SP)
2878 else if (GET_CODE (src) != PLUS
2879 || ! REG_P (XEXP (src, 0))
2880 || REGNO (XEXP (src, 0)) != REG_SP
2881 || GET_CODE (XEXP (src, 1)) != CONST_INT
2882 || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
2885 regno = REGNO (dest);
2888 if (regno == REG_R7)
2893 else if (regno != REG_P0 + lastpreg - 1)
2898 else if (group == 1)
2900 if (regno != REG_R0 + lastdreg - 1)
2906 first_dreg_to_save = lastdreg;
2907 first_preg_to_save = lastpreg;
2911 /* Emit assembly code for one multi-register push described by INSN, with
2912 operands in OPERANDS. */
2915 output_push_multiple (rtx insn, rtx *operands)
2920 /* Validate the insn again, and compute first_[dp]reg_to_save. */
2921 ok = push_multiple_operation (PATTERN (insn), VOIDmode);
2924 if (first_dreg_to_save == 8)
2925 sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
2926 else if (first_preg_to_save == 6)
2927 sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
2929 sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
2930 first_dreg_to_save, first_preg_to_save);
2932 output_asm_insn (buf, operands);
2935 /* Emit assembly code for one multi-register pop described by INSN, with
2936 operands in OPERANDS. */
2939 output_pop_multiple (rtx insn, rtx *operands)
2944 /* Validate the insn again, and compute first_[dp]reg_to_save. */
2945 ok = pop_multiple_operation (PATTERN (insn), VOIDmode);
2948 if (first_dreg_to_save == 8)
2949 sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
2950 else if (first_preg_to_save == 6)
2951 sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
2953 sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
2954 first_dreg_to_save, first_preg_to_save);
2956 output_asm_insn (buf, operands);
2959 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE. */
2962 single_move_for_movmem (rtx dst, rtx src, enum machine_mode mode, HOST_WIDE_INT offset)
2964 rtx scratch = gen_reg_rtx (mode);
2967 srcmem = adjust_address_nv (src, mode, offset);
2968 dstmem = adjust_address_nv (dst, mode, offset);
2969 emit_move_insn (scratch, srcmem);
2970 emit_move_insn (dstmem, scratch);
2973 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
2974 alignment ALIGN_EXP. Return true if successful, false if we should fall
2975 back on a different method. */
2978 bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
2980 rtx srcreg, destreg, countreg;
2981 HOST_WIDE_INT align = 0;
2982 unsigned HOST_WIDE_INT count = 0;
2984 if (GET_CODE (align_exp) == CONST_INT)
2985 align = INTVAL (align_exp);
2986 if (GET_CODE (count_exp) == CONST_INT)
2988 count = INTVAL (count_exp);
2990 if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
2995 /* If optimizing for size, only do single copies inline. */
2998 if (count == 2 && align < 2)
3000 if (count == 4 && align < 4)
3002 if (count != 1 && count != 2 && count != 4)
3005 if (align < 2 && count != 1)
3008 destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
3009 if (destreg != XEXP (dst, 0))
3010 dst = replace_equiv_address_nv (dst, destreg);
3011 srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
3012 if (srcreg != XEXP (src, 0))
3013 src = replace_equiv_address_nv (src, srcreg);
3015 if (count != 0 && align >= 2)
3017 unsigned HOST_WIDE_INT offset = 0;
3021 if ((count & ~3) == 4)
3023 single_move_for_movmem (dst, src, SImode, offset);
3026 else if (count & ~3)
3028 HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
3029 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3031 emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
3035 single_move_for_movmem (dst, src, HImode, offset);
3041 if ((count & ~1) == 2)
3043 single_move_for_movmem (dst, src, HImode, offset);
3046 else if (count & ~1)
3048 HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
3049 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3051 emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
3056 single_move_for_movmem (dst, src, QImode, offset);
3063 /* Compute the alignment for a local variable.
3064 TYPE is the data type, and ALIGN is the alignment that
3065 the object would ordinarily have. The value of this macro is used
3066 instead of that alignment to align the object. */
3069 bfin_local_alignment (tree type, int align)
3071 /* Increasing alignment for (relatively) big types allows the builtin
3072 memcpy can use 32 bit loads/stores. */
3073 if (TYPE_SIZE (type)
3074 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
3075 && (TREE_INT_CST_LOW (TYPE_SIZE (type)) > 8
3076 || TREE_INT_CST_HIGH (TYPE_SIZE (type))) && align < 32)
3081 /* Implement TARGET_SCHED_ISSUE_RATE. */
3084 bfin_issue_rate (void)
3090 bfin_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
3092 enum attr_type insn_type, dep_insn_type;
3093 int dep_insn_code_number;
3095 /* Anti and output dependencies have zero cost. */
3096 if (REG_NOTE_KIND (link) != 0)
3099 dep_insn_code_number = recog_memoized (dep_insn);
3101 /* If we can't recognize the insns, we can't really do anything. */
3102 if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
3105 insn_type = get_attr_type (insn);
3106 dep_insn_type = get_attr_type (dep_insn);
3108 if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)
3110 rtx pat = PATTERN (dep_insn);
3111 rtx dest = SET_DEST (pat);
3112 rtx src = SET_SRC (pat);
3113 if (! ADDRESS_REGNO_P (REGNO (dest))
3114 || ! (MEM_P (src) || D_REGNO_P (REGNO (src))))
3116 return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);
3123 /* Increment the counter for the number of loop instructions in the
3124 current function. */
3127 bfin_hardware_loop (void)
3129 cfun->machine->has_hardware_loops++;
3132 /* Maximum loop nesting depth. */
3133 #define MAX_LOOP_DEPTH 2
3135 /* Maximum size of a loop. */
3136 #define MAX_LOOP_LENGTH 2042
3138 /* Maximum distance of the LSETUP instruction from the loop start. */
3139 #define MAX_LSETUP_DISTANCE 30
3141 /* We need to keep a vector of loops */
3142 typedef struct loop_info *loop_info;
3143 DEF_VEC_P (loop_info);
3144 DEF_VEC_ALLOC_P (loop_info,heap);
3146 /* Information about a loop we have found (or are in the process of
3148 struct loop_info GTY (())
3150 /* loop number, for dumps */
3153 /* All edges that jump into and out of the loop. */
3154 VEC(edge,gc) *incoming;
3156 /* We can handle two cases: all incoming edges have the same destination
3157 block, or all incoming edges have the same source block. These two
3158 members are set to the common source or destination we found, or NULL
3159 if different blocks were found. If both are NULL the loop can't be
3161 basic_block incoming_src;
3162 basic_block incoming_dest;
3164 /* First block in the loop. This is the one branched to by the loop_end
3168 /* Last block in the loop (the one with the loop_end insn). */
3171 /* The successor block of the loop. This is the one the loop_end insn
3173 basic_block successor;
3175 /* The last instruction in the tail. */
3178 /* The loop_end insn. */
3181 /* The iteration register. */
3184 /* The new initialization insn. */
3187 /* The new initialization instruction. */
3190 /* The new label placed at the beginning of the loop. */
3193 /* The new label placed at the end of the loop. */
3196 /* The length of the loop. */
3199 /* The nesting depth of the loop. */
3202 /* Nonzero if we can't optimize this loop. */
3205 /* True if we have visited this loop. */
3208 /* True if this loop body clobbers any of LC0, LT0, or LB0. */
3211 /* True if this loop body clobbers any of LC1, LT1, or LB1. */
3214 /* Next loop in the graph. */
3215 struct loop_info *next;
3217 /* Immediate outer loop of this loop. */
3218 struct loop_info *outer;
3220 /* Vector of blocks only within the loop, including those within
3222 VEC (basic_block,heap) *blocks;
3224 /* Same information in a bitmap. */
3225 bitmap block_bitmap;
3227 /* Vector of inner loops within this loop */
3228 VEC (loop_info,heap) *loops;
3232 bfin_dump_loops (loop_info loops)
3236 for (loop = loops; loop; loop = loop->next)
3242 fprintf (dump_file, ";; loop %d: ", loop->loop_no);
3244 fprintf (dump_file, "(bad) ");
3245 fprintf (dump_file, "{head:%d, depth:%d}", loop->head->index, loop->depth);
3247 fprintf (dump_file, " blocks: [ ");
3248 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, b); ix++)
3249 fprintf (dump_file, "%d ", b->index);
3250 fprintf (dump_file, "] ");
3252 fprintf (dump_file, " inner loops: [ ");
3253 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, i); ix++)
3254 fprintf (dump_file, "%d ", i->loop_no);
3255 fprintf (dump_file, "]\n");
3257 fprintf (dump_file, "\n");
3260 /* Scan the blocks of LOOP (and its inferiors) looking for basic block
3261 BB. Return true, if we find it. */
3264 bfin_bb_in_loop (loop_info loop, basic_block bb)
3266 return bitmap_bit_p (loop->block_bitmap, bb->index);
3269 /* Scan the blocks of LOOP (and its inferiors) looking for uses of
3270 REG. Return true, if we find any. Don't count the loop's loop_end
3271 insn if it matches LOOP_END. */
3274 bfin_scan_loop (loop_info loop, rtx reg, rtx loop_end)
3279 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
3283 for (insn = BB_HEAD (bb);
3284 insn != NEXT_INSN (BB_END (bb));
3285 insn = NEXT_INSN (insn))
3289 if (insn == loop_end)
3291 if (reg_mentioned_p (reg, PATTERN (insn)))
3298 /* Estimate the length of INSN conservatively. */
3301 length_for_loop (rtx insn)
3304 if (JUMP_P (insn) && any_condjump_p (insn) && !optimize_size)
3306 if (TARGET_CSYNC_ANOMALY)
3308 else if (TARGET_SPECLD_ANOMALY)
3311 else if (LABEL_P (insn))
3313 if (TARGET_CSYNC_ANOMALY)
3318 length += get_attr_length (insn);
3323 /* Optimize LOOP. */
3326 bfin_optimize_loop (loop_info loop)
3330 rtx insn, init_insn, last_insn, nop_insn;
3331 rtx loop_init, start_label, end_label;
3332 rtx reg_lc0, reg_lc1, reg_lt0, reg_lt1, reg_lb0, reg_lb1;
3334 rtx lc_reg, lt_reg, lb_reg;
3338 int inner_depth = 0;
3348 fprintf (dump_file, ";; loop %d bad when found\n", loop->loop_no);
3352 /* Every loop contains in its list of inner loops every loop nested inside
3353 it, even if there are intermediate loops. This works because we're doing
3354 a depth-first search here and never visit a loop more than once. */
3355 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, inner); ix++)
3357 bfin_optimize_loop (inner);
3359 if (!inner->bad && inner_depth < inner->depth)
3361 inner_depth = inner->depth;
3363 loop->clobber_loop0 |= inner->clobber_loop0;
3364 loop->clobber_loop1 |= inner->clobber_loop1;
3368 loop->depth = inner_depth + 1;
3369 if (loop->depth > MAX_LOOP_DEPTH)
3372 fprintf (dump_file, ";; loop %d too deep\n", loop->loop_no);
3376 /* Get the loop iteration register. */
3377 iter_reg = loop->iter_reg;
3379 if (!DPREG_P (iter_reg))
3382 fprintf (dump_file, ";; loop %d iteration count NOT in PREG or DREG\n",
3387 if (loop->incoming_src)
3389 /* Make sure the predecessor is before the loop start label, as required by
3390 the LSETUP instruction. */
3392 for (insn = BB_END (loop->incoming_src);
3393 insn && insn != loop->start_label;
3394 insn = NEXT_INSN (insn))
3395 length += length_for_loop (insn);
3400 fprintf (dump_file, ";; loop %d lsetup not before loop_start\n",
3405 if (length > MAX_LSETUP_DISTANCE)
3408 fprintf (dump_file, ";; loop %d lsetup too far away\n", loop->loop_no);
3413 /* Check if start_label appears before loop_end and calculate the
3414 offset between them. We calculate the length of instructions
3417 for (insn = loop->start_label;
3418 insn && insn != loop->loop_end;
3419 insn = NEXT_INSN (insn))
3420 length += length_for_loop (insn);
3425 fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
3430 loop->length = length;
3431 if (loop->length > MAX_LOOP_LENGTH)
3434 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
3438 /* Scan all the blocks to make sure they don't use iter_reg. */
3439 if (bfin_scan_loop (loop, iter_reg, loop->loop_end))
3442 fprintf (dump_file, ";; loop %d uses iterator\n", loop->loop_no);
3446 /* Scan all the insns to see if the loop body clobber
3447 any hardware loop registers. */
3449 reg_lc0 = gen_rtx_REG (SImode, REG_LC0);
3450 reg_lc1 = gen_rtx_REG (SImode, REG_LC1);
3451 reg_lt0 = gen_rtx_REG (SImode, REG_LT0);
3452 reg_lt1 = gen_rtx_REG (SImode, REG_LT1);
3453 reg_lb0 = gen_rtx_REG (SImode, REG_LB0);
3454 reg_lb1 = gen_rtx_REG (SImode, REG_LB1);
3456 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
3460 for (insn = BB_HEAD (bb);
3461 insn != NEXT_INSN (BB_END (bb));
3462 insn = NEXT_INSN (insn))
3467 if (reg_set_p (reg_lc0, insn)
3468 || reg_set_p (reg_lt0, insn)
3469 || reg_set_p (reg_lb0, insn))
3470 loop->clobber_loop0 = 1;
3472 if (reg_set_p (reg_lc1, insn)
3473 || reg_set_p (reg_lt1, insn)
3474 || reg_set_p (reg_lb1, insn))
3475 loop->clobber_loop1 |= 1;
3479 if ((loop->clobber_loop0 && loop->clobber_loop1)
3480 || (loop->depth == MAX_LOOP_DEPTH && loop->clobber_loop0))
3482 loop->depth = MAX_LOOP_DEPTH + 1;
3484 fprintf (dump_file, ";; loop %d no loop reg available\n",
3489 /* There should be an instruction before the loop_end instruction
3490 in the same basic block. And the instruction must not be
3492 - CONDITIONAL BRANCH
3496 - Returns (RTS, RTN, etc.) */
3499 last_insn = PREV_INSN (loop->loop_end);
3503 for (; last_insn != PREV_INSN (BB_HEAD (bb));
3504 last_insn = PREV_INSN (last_insn))
3505 if (INSN_P (last_insn))
3508 if (last_insn != PREV_INSN (BB_HEAD (bb)))
3511 if (single_pred_p (bb)
3512 && single_pred (bb) != ENTRY_BLOCK_PTR)
3514 bb = single_pred (bb);
3515 last_insn = BB_END (bb);
3520 last_insn = NULL_RTX;
3528 fprintf (dump_file, ";; loop %d has no last instruction\n",
3533 if (JUMP_P (last_insn))
3535 loop_info inner = bb->aux;
3537 && inner->outer == loop
3538 && inner->loop_end == last_insn
3539 && inner->depth == 1)
3540 /* This jump_insn is the exact loop_end of an inner loop
3541 and to be optimized away. So use the inner's last_insn. */
3542 last_insn = inner->last_insn;
3546 fprintf (dump_file, ";; loop %d has bad last instruction\n",
3551 else if (CALL_P (last_insn)
3552 || (GET_CODE (PATTERN (last_insn)) != SEQUENCE
3553 && get_attr_type (last_insn) == TYPE_SYNC)
3554 || recog_memoized (last_insn) == CODE_FOR_return_internal)
3557 fprintf (dump_file, ";; loop %d has bad last instruction\n",
3562 if (GET_CODE (PATTERN (last_insn)) == ASM_INPUT
3563 || asm_noperands (PATTERN (last_insn)) >= 0
3564 || (GET_CODE (PATTERN (last_insn)) != SEQUENCE
3565 && get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI))
3567 nop_insn = emit_insn_after (gen_nop (), last_insn);
3568 last_insn = nop_insn;
3571 loop->last_insn = last_insn;
3573 /* The loop is good for replacement. */
3574 start_label = loop->start_label;
3575 end_label = gen_label_rtx ();
3576 iter_reg = loop->iter_reg;
3578 if (loop->depth == 1 && !loop->clobber_loop1)
3583 loop->clobber_loop1 = 1;
3590 loop->clobber_loop0 = 1;
3593 /* If iter_reg is a DREG, we need generate an instruction to load
3594 the loop count into LC register. */
3595 if (D_REGNO_P (REGNO (iter_reg)))
3597 init_insn = gen_movsi (lc_reg, iter_reg);
3598 loop_init = gen_lsetup_without_autoinit (lt_reg, start_label,
3602 else if (P_REGNO_P (REGNO (iter_reg)))
3604 init_insn = NULL_RTX;
3605 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
3612 loop->init = init_insn;
3613 loop->end_label = end_label;
3614 loop->loop_init = loop_init;
3618 fprintf (dump_file, ";; replacing loop %d initializer with\n",
3620 print_rtl_single (dump_file, loop->loop_init);
3621 fprintf (dump_file, ";; replacing loop %d terminator with\n",
3623 print_rtl_single (dump_file, loop->loop_end);
3628 if (loop->init != NULL_RTX)
3629 emit_insn (loop->init);
3630 seq_end = emit_insn (loop->loop_init);
3635 if (loop->incoming_src)
3637 rtx prev = BB_END (loop->incoming_src);
3638 if (VEC_length (edge, loop->incoming) > 1
3639 || !(VEC_last (edge, loop->incoming)->flags & EDGE_FALLTHRU))
3641 gcc_assert (JUMP_P (prev));
3642 prev = PREV_INSN (prev);
3644 emit_insn_after (seq, prev);
3652 if (loop->head != loop->incoming_dest)
3654 FOR_EACH_EDGE (e, ei, loop->head->preds)
3656 if (e->flags & EDGE_FALLTHRU)
3658 rtx newjump = gen_jump (loop->start_label);
3659 emit_insn_before (newjump, BB_HEAD (loop->head));
3660 new_bb = create_basic_block (newjump, newjump, loop->head->prev_bb);
3661 gcc_assert (new_bb = loop->head->prev_bb);
3667 emit_insn_before (seq, BB_HEAD (loop->head));
3668 seq = emit_label_before (gen_label_rtx (), seq);
3670 new_bb = create_basic_block (seq, seq_end, loop->head->prev_bb);
3671 FOR_EACH_EDGE (e, ei, loop->incoming)
3673 if (!(e->flags & EDGE_FALLTHRU)
3674 || e->dest != loop->head)
3675 redirect_edge_and_branch_force (e, new_bb);
3677 redirect_edge_succ (e, new_bb);
3681 delete_insn (loop->loop_end);
3682 /* Insert the loop end label before the last instruction of the loop. */
3683 emit_label_before (loop->end_label, loop->last_insn);
3690 fprintf (dump_file, ";; loop %d is bad\n", loop->loop_no);
3694 if (DPREG_P (loop->iter_reg))
3696 /* If loop->iter_reg is a DREG or PREG, we can split it here
3697 without scratch register. */
3700 emit_insn_before (gen_addsi3 (loop->iter_reg,
3705 emit_insn_before (gen_cmpsi (loop->iter_reg, const0_rtx),
3708 insn = emit_jump_insn_before (gen_bne (loop->start_label),
3711 JUMP_LABEL (insn) = loop->start_label;
3712 LABEL_NUSES (loop->start_label)++;
3713 delete_insn (loop->loop_end);
3717 /* Called from bfin_reorg_loops when a potential loop end is found. LOOP is
3718 a newly set up structure describing the loop, it is this function's
3719 responsibility to fill most of it. TAIL_BB and TAIL_INSN point to the
3720 loop_end insn and its enclosing basic block. */
3723 bfin_discover_loop (loop_info loop, basic_block tail_bb, rtx tail_insn)
3727 VEC (basic_block,heap) *works = VEC_alloc (basic_block,heap,20);
3729 loop->tail = tail_bb;
3730 loop->head = BRANCH_EDGE (tail_bb)->dest;
3731 loop->successor = FALLTHRU_EDGE (tail_bb)->dest;
3732 loop->loop_end = tail_insn;
3733 loop->last_insn = NULL_RTX;
3734 loop->iter_reg = SET_DEST (XVECEXP (PATTERN (tail_insn), 0, 1));
3735 loop->depth = loop->length = 0;
3737 loop->clobber_loop0 = loop->clobber_loop1 = 0;
3740 loop->incoming = VEC_alloc (edge, gc, 2);
3741 loop->init = loop->loop_init = NULL_RTX;
3742 loop->start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (tail_insn), 0, 0)), 1), 0);
3743 loop->end_label = NULL_RTX;
3746 VEC_safe_push (basic_block, heap, works, loop->head);
3748 while (VEC_iterate (basic_block, works, dwork++, bb))
3752 if (bb == EXIT_BLOCK_PTR)
3754 /* We've reached the exit block. The loop must be bad. */
3757 ";; Loop is bad - reached exit block while scanning\n");
3762 if (bitmap_bit_p (loop->block_bitmap, bb->index))
3765 /* We've not seen this block before. Add it to the loop's
3766 list and then add each successor to the work list. */
3768 VEC_safe_push (basic_block, heap, loop->blocks, bb);
3769 bitmap_set_bit (loop->block_bitmap, bb->index);
3773 FOR_EACH_EDGE (e, ei, bb->succs)
3775 basic_block succ = EDGE_SUCC (bb, ei.index)->dest;
3776 if (!REGNO_REG_SET_P (df_get_live_in (succ),
3777 REGNO (loop->iter_reg)))
3779 if (!VEC_space (basic_block, works, 1))
3783 VEC_block_remove (basic_block, works, 0, dwork);
3787 VEC_reserve (basic_block, heap, works, 1);
3789 VEC_quick_push (basic_block, works, succ);
3794 /* Find the predecessor, and make sure nothing else jumps into this loop. */
3798 for (dwork = 0; VEC_iterate (basic_block, loop->blocks, dwork, bb); dwork++)
3802 FOR_EACH_EDGE (e, ei, bb->preds)
3804 basic_block pred = e->src;
3806 if (!bfin_bb_in_loop (loop, pred))
3809 fprintf (dump_file, ";; Loop %d: incoming edge %d -> %d\n",
3810 loop->loop_no, pred->index,
3812 VEC_safe_push (edge, gc, loop->incoming, e);
3817 for (pass = 0, retry = 1; retry && pass < 2; pass++)
3824 FOR_EACH_EDGE (e, ei, loop->incoming)
3828 loop->incoming_src = e->src;
3829 loop->incoming_dest = e->dest;
3834 if (e->dest != loop->incoming_dest)
3835 loop->incoming_dest = NULL;
3836 if (e->src != loop->incoming_src)
3837 loop->incoming_src = NULL;
3839 if (loop->incoming_src == NULL && loop->incoming_dest == NULL)
3845 ";; retrying loop %d with forwarder blocks\n",
3853 ";; can't find suitable entry for loop %d\n",
3861 FOR_EACH_EDGE (e, ei, loop->incoming)
3863 if (forwarder_block_p (e->src))
3870 ";; Adding forwarder block %d to loop %d and retrying\n",
3871 e->src->index, loop->loop_no);
3872 VEC_safe_push (basic_block, heap, loop->blocks, e->src);
3873 bitmap_set_bit (loop->block_bitmap, e->src->index);
3874 FOR_EACH_EDGE (e2, ei2, e->src->preds)
3875 VEC_safe_push (edge, gc, loop->incoming, e2);
3876 VEC_unordered_remove (edge, loop->incoming, ei.index);
3886 VEC_free (basic_block, heap, works);
3889 /* Analyze the structure of the loops in the current function. Use STACK
3890 for bitmap allocations. Returns all the valid candidates for hardware
3891 loops found in this function. */
3893 bfin_discover_loops (bitmap_obstack *stack, FILE *dump_file)
3895 loop_info loops = NULL;
3901 /* Find all the possible loop tails. This means searching for every
3902 loop_end instruction. For each one found, create a loop_info
3903 structure and add the head block to the work list. */
3906 rtx tail = BB_END (bb);
3908 while (GET_CODE (tail) == NOTE)
3909 tail = PREV_INSN (tail);
3913 if (INSN_P (tail) && recog_memoized (tail) == CODE_FOR_loop_end)
3915 /* A possible loop end */
3917 loop = XNEW (struct loop_info);
3920 loop->loop_no = nloops++;
3921 loop->blocks = VEC_alloc (basic_block, heap, 20);
3922 loop->block_bitmap = BITMAP_ALLOC (stack);
3927 fprintf (dump_file, ";; potential loop %d ending at\n",
3929 print_rtl_single (dump_file, tail);
3932 bfin_discover_loop (loop, bb, tail);
3936 tmp_bitmap = BITMAP_ALLOC (stack);
3937 /* Compute loop nestings. */
3938 for (loop = loops; loop; loop = loop->next)
3944 for (other = loop->next; other; other = other->next)
3949 bitmap_and (tmp_bitmap, other->block_bitmap, loop->block_bitmap);
3950 if (bitmap_empty_p (tmp_bitmap))
3952 if (bitmap_equal_p (tmp_bitmap, other->block_bitmap))
3954 other->outer = loop;
3955 VEC_safe_push (loop_info, heap, loop->loops, other);
3957 else if (bitmap_equal_p (tmp_bitmap, loop->block_bitmap))
3959 loop->outer = other;
3960 VEC_safe_push (loop_info, heap, other->loops, loop);
3966 ";; can't find suitable nesting for loops %d and %d\n",
3967 loop->loop_no, other->loop_no);
3968 loop->bad = other->bad = 1;
3972 BITMAP_FREE (tmp_bitmap);
3977 /* Free up the loop structures in LOOPS. */
3979 free_loops (loop_info loops)
3983 loop_info loop = loops;
3985 VEC_free (loop_info, heap, loop->loops);
3986 VEC_free (basic_block, heap, loop->blocks);
3987 BITMAP_FREE (loop->block_bitmap);
3992 #define BB_AUX_INDEX(BB) ((unsigned)(BB)->aux)
3994 /* The taken-branch edge from the loop end can actually go forward. Since the
3995 Blackfin's LSETUP instruction requires that the loop end be after the loop
3996 start, try to reorder a loop's basic blocks when we find such a case. */
3998 bfin_reorder_loops (loop_info loops, FILE *dump_file)
4005 cfg_layout_initialize (0);
4007 for (loop = loops; loop; loop = loop->next)
4017 /* Recreate an index for basic blocks that represents their order. */
4018 for (bb = ENTRY_BLOCK_PTR->next_bb, index = 0;
4019 bb != EXIT_BLOCK_PTR;
4020 bb = bb->next_bb, index++)
4021 bb->aux = (PTR) index;
4023 if (BB_AUX_INDEX (loop->head) < BB_AUX_INDEX (loop->tail))
4026 FOR_EACH_EDGE (e, ei, loop->head->succs)
4028 if (bitmap_bit_p (loop->block_bitmap, e->dest->index)
4029 && BB_AUX_INDEX (e->dest) < BB_AUX_INDEX (loop->tail))
4031 basic_block start_bb = e->dest;
4032 basic_block start_prev_bb = start_bb->prev_bb;
4035 fprintf (dump_file, ";; Moving block %d before block %d\n",
4036 loop->head->index, start_bb->index);
4037 loop->head->prev_bb->next_bb = loop->head->next_bb;
4038 loop->head->next_bb->prev_bb = loop->head->prev_bb;
4040 loop->head->prev_bb = start_prev_bb;
4041 loop->head->next_bb = start_bb;
4042 start_prev_bb->next_bb = start_bb->prev_bb = loop->head;
4046 loops = loops->next;
4051 if (bb->next_bb != EXIT_BLOCK_PTR)
4052 bb->aux = bb->next_bb;
4056 cfg_layout_finalize ();
4060 /* Run from machine_dependent_reorg, this pass looks for doloop_end insns
4061 and tries to rewrite the RTL of these loops so that proper Blackfin
4062 hardware loops are generated. */
4065 bfin_reorg_loops (FILE *dump_file)
4067 loop_info loops = NULL;
4070 bitmap_obstack stack;
4072 bitmap_obstack_initialize (&stack);
4075 fprintf (dump_file, ";; Find loops, first pass\n\n");
4077 loops = bfin_discover_loops (&stack, dump_file);
4080 bfin_dump_loops (loops);
4082 bfin_reorder_loops (loops, dump_file);
4086 fprintf (dump_file, ";; Find loops, second pass\n\n");
4088 loops = bfin_discover_loops (&stack, dump_file);
4091 fprintf (dump_file, ";; All loops found:\n\n");
4092 bfin_dump_loops (loops);
4095 /* Now apply the optimizations. */
4096 for (loop = loops; loop; loop = loop->next)
4097 bfin_optimize_loop (loop);
4101 fprintf (dump_file, ";; After hardware loops optimization:\n\n");
4102 bfin_dump_loops (loops);
4108 print_rtl (dump_file, get_insns ());
4114 /* Possibly generate a SEQUENCE out of three insns found in SLOT.
4115 Returns true if we modified the insn chain, false otherwise. */
4117 gen_one_bundle (rtx slot[3])
4119 gcc_assert (slot[1] != NULL_RTX);
4121 /* Verify that we really can do the multi-issue. */
4124 rtx t = NEXT_INSN (slot[0]);
4125 while (t != slot[1])
4127 if (GET_CODE (t) != NOTE
4128 || NOTE_KIND (t) != NOTE_INSN_DELETED)
4135 rtx t = NEXT_INSN (slot[1]);
4136 while (t != slot[2])
4138 if (GET_CODE (t) != NOTE
4139 || NOTE_KIND (t) != NOTE_INSN_DELETED)
4145 if (slot[0] == NULL_RTX)
4147 slot[0] = emit_insn_before (gen_mnop (), slot[1]);
4148 df_insn_rescan (slot[0]);
4150 if (slot[2] == NULL_RTX)
4152 slot[2] = emit_insn_after (gen_forced_nop (), slot[1]);
4153 df_insn_rescan (slot[2]);
4156 /* Avoid line number information being printed inside one bundle. */
4157 if (INSN_LOCATOR (slot[1])
4158 && INSN_LOCATOR (slot[1]) != INSN_LOCATOR (slot[0]))
4159 INSN_LOCATOR (slot[1]) = INSN_LOCATOR (slot[0]);
4160 if (INSN_LOCATOR (slot[2])
4161 && INSN_LOCATOR (slot[2]) != INSN_LOCATOR (slot[0]))
4162 INSN_LOCATOR (slot[2]) = INSN_LOCATOR (slot[0]);
4164 /* Terminate them with "|| " instead of ";" in the output. */
4165 PUT_MODE (slot[0], SImode);
4166 PUT_MODE (slot[1], SImode);
4167 /* Terminate the bundle, for the benefit of reorder_var_tracking_notes. */
4168 PUT_MODE (slot[2], QImode);
4172 /* Go through all insns, and use the information generated during scheduling
4173 to generate SEQUENCEs to represent bundles of instructions issued
4177 bfin_gen_bundles (void)
4186 slot[0] = slot[1] = slot[2] = NULL_RTX;
4187 for (insn = BB_HEAD (bb);; insn = next)
4192 if (get_attr_type (insn) == TYPE_DSP32)
4194 else if (slot[1] == NULL_RTX)
4201 next = NEXT_INSN (insn);
4202 while (next && insn != BB_END (bb)
4204 && GET_CODE (PATTERN (next)) != USE
4205 && GET_CODE (PATTERN (next)) != CLOBBER))
4208 next = NEXT_INSN (insn);
4211 /* BB_END can change due to emitting extra NOPs, so check here. */
4212 at_end = insn == BB_END (bb);
4213 if (at_end || GET_MODE (next) == TImode)
4216 || !gen_one_bundle (slot))
4217 && slot[0] != NULL_RTX)
4219 rtx pat = PATTERN (slot[0]);
4220 if (GET_CODE (pat) == SET
4221 && GET_CODE (SET_SRC (pat)) == UNSPEC
4222 && XINT (SET_SRC (pat), 1) == UNSPEC_32BIT)
4224 SET_SRC (pat) = XVECEXP (SET_SRC (pat), 0, 0);
4225 INSN_CODE (slot[0]) = -1;
4226 df_insn_rescan (slot[0]);
4230 slot[0] = slot[1] = slot[2] = NULL_RTX;
4238 /* Ensure that no var tracking notes are emitted in the middle of a
4239 three-instruction bundle. */
4242 reorder_var_tracking_notes (void)
4248 rtx queue = NULL_RTX;
4249 bool in_bundle = false;
4251 for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = next)
4253 next = NEXT_INSN (insn);
4257 /* Emit queued up notes at the last instruction of a bundle. */
4258 if (GET_MODE (insn) == QImode)
4262 rtx next_queue = PREV_INSN (queue);
4263 PREV_INSN (NEXT_INSN (insn)) = queue;
4264 NEXT_INSN (queue) = NEXT_INSN (insn);
4265 NEXT_INSN (insn) = queue;
4266 PREV_INSN (queue) = insn;
4271 else if (GET_MODE (insn) == SImode)
4274 else if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION)
4278 rtx prev = PREV_INSN (insn);
4279 PREV_INSN (next) = prev;
4280 NEXT_INSN (prev) = next;
4282 PREV_INSN (insn) = queue;
4290 /* Return an insn type for INSN that can be used by the caller for anomaly
4291 workarounds. This differs from plain get_attr_type in that it handles
4294 static enum attr_type
4295 type_for_anomaly (rtx insn)
4297 rtx pat = PATTERN (insn);
4298 if (GET_CODE (pat) == SEQUENCE)
4301 t = get_attr_type (XVECEXP (pat, 0, 1));
4304 t = get_attr_type (XVECEXP (pat, 0, 2));
4310 return get_attr_type (insn);
4313 /* Return nonzero if INSN contains any loads that may trap. It handles
4314 SEQUENCEs correctly. */
4317 trapping_loads_p (rtx insn)
4319 rtx pat = PATTERN (insn);
4320 if (GET_CODE (pat) == SEQUENCE)
4323 t = get_attr_type (XVECEXP (pat, 0, 1));
4325 && may_trap_p (SET_SRC (PATTERN (XVECEXP (pat, 0, 1)))))
4327 t = get_attr_type (XVECEXP (pat, 0, 2));
4329 && may_trap_p (SET_SRC (PATTERN (XVECEXP (pat, 0, 2)))))
4334 return may_trap_p (SET_SRC (single_set (insn)));
4337 /* This function acts like NEXT_INSN, but is aware of three-insn bundles and
4338 skips all subsequent parallel instructions if INSN is the start of such
4341 find_next_insn_start (rtx insn)
4343 if (GET_MODE (insn) == SImode)
4345 while (GET_MODE (insn) != QImode)
4346 insn = NEXT_INSN (insn);
4348 return NEXT_INSN (insn);
4351 /* Return INSN if it is of TYPE_MCLD. Alternatively, if INSN is the start of
4352 a three-insn bundle, see if one of them is a load and return that if so.
4353 Return NULL_RTX if the insn does not contain loads. */
4355 find_load (rtx insn)
4357 if (get_attr_type (insn) == TYPE_MCLD)
4359 if (GET_MODE (insn) != SImode)
4362 insn = NEXT_INSN (insn);
4363 if ((GET_MODE (insn) == SImode || GET_MODE (insn) == QImode)
4364 && get_attr_type (insn) == TYPE_MCLD)
4366 } while (GET_MODE (insn) != QImode);
4370 /* We use the machine specific reorg pass for emitting CSYNC instructions
4371 after conditional branches as needed.
4373 The Blackfin is unusual in that a code sequence like
4376 may speculatively perform the load even if the condition isn't true. This
4377 happens for a branch that is predicted not taken, because the pipeline
4378 isn't flushed or stalled, so the early stages of the following instructions,
4379 which perform the memory reference, are allowed to execute before the
4380 jump condition is evaluated.
4381 Therefore, we must insert additional instructions in all places where this
4382 could lead to incorrect behavior. The manual recommends CSYNC, while
4383 VDSP seems to use NOPs (even though its corresponding compiler option is
4386 When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
4387 When optimizing for size, we turn the branch into a predicted taken one.
4388 This may be slower due to mispredicts, but saves code size. */
4394 rtx last_condjump = NULL_RTX;
4395 int cycles_since_jump = INT_MAX;
4397 /* We are freeing block_for_insn in the toplev to keep compatibility
4398 with old MDEP_REORGS that are not CFG based. Recompute it now. */
4399 compute_bb_for_insn ();
4401 if (bfin_flag_schedule_insns2)
4403 splitting_for_sched = 1;
4405 splitting_for_sched = 0;
4407 timevar_push (TV_SCHED2);
4409 timevar_pop (TV_SCHED2);
4411 /* Examine the schedule and insert nops as necessary for 64-bit parallel
4413 bfin_gen_bundles ();
4418 /* Doloop optimization */
4419 if (cfun->machine->has_hardware_loops)
4420 bfin_reorg_loops (dump_file);
4422 if (! TARGET_SPECLD_ANOMALY && ! TARGET_CSYNC_ANOMALY)
4425 /* First pass: find predicted-false branches; if something after them
4426 needs nops, insert them or change the branch to predict true. */
4427 for (insn = get_insns (); insn; insn = next)
4431 next = find_next_insn_start (insn);
4433 if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
4436 pat = PATTERN (insn);
4437 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4438 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
4439 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
4444 if (any_condjump_p (insn)
4445 && ! cbranch_predicted_taken_p (insn))
4447 last_condjump = insn;
4448 cycles_since_jump = 0;
4451 cycles_since_jump = INT_MAX;
4453 else if (INSN_P (insn))
4455 rtx load_insn = find_load (insn);
4456 enum attr_type type = type_for_anomaly (insn);
4457 int delay_needed = 0;
4458 if (cycles_since_jump < INT_MAX)
4459 cycles_since_jump++;
4461 if (load_insn && TARGET_SPECLD_ANOMALY)
4463 if (trapping_loads_p (load_insn))
4466 else if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
4469 if (delay_needed > cycles_since_jump)
4473 rtx *op = recog_data.operand;
4475 delay_needed -= cycles_since_jump;
4477 extract_insn (last_condjump);
4480 pat = gen_cbranch_predicted_taken (op[0], op[1], op[2],
4482 cycles_since_jump = INT_MAX;
4485 /* Do not adjust cycles_since_jump in this case, so that
4486 we'll increase the number of NOPs for a subsequent insn
4488 pat = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
4489 GEN_INT (delay_needed));
4490 PATTERN (last_condjump) = pat;
4491 INSN_CODE (last_condjump) = recog (pat, insn, &num_clobbers);
4495 /* Second pass: for predicted-true branches, see if anything at the
4496 branch destination needs extra nops. */
4497 if (! TARGET_CSYNC_ANOMALY)
4500 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4503 && any_condjump_p (insn)
4504 && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken
4505 || cbranch_predicted_taken_p (insn)))
4507 rtx target = JUMP_LABEL (insn);
4509 cycles_since_jump = 0;
4510 for (; target && cycles_since_jump < 3; target = NEXT_INSN (target))
4514 if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
4517 pat = PATTERN (target);
4518 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4519 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
4520 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
4523 if (INSN_P (target))
4525 enum attr_type type = type_for_anomaly (target);
4526 int delay_needed = 0;
4527 if (cycles_since_jump < INT_MAX)
4528 cycles_since_jump++;
4530 if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
4533 if (delay_needed > cycles_since_jump)
4535 rtx prev = prev_real_insn (label);
4536 delay_needed -= cycles_since_jump;
4538 fprintf (dump_file, "Adding %d nops after %d\n",
4539 delay_needed, INSN_UID (label));
4541 && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops)
4548 "Reducing nops on insn %d.\n",
4551 x = XVECEXP (x, 0, 1);
4552 v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed;
4553 XVECEXP (x, 0, 0) = GEN_INT (v);
4555 while (delay_needed-- > 0)
4556 emit_insn_after (gen_nop (), label);
4564 if (bfin_flag_var_tracking)
4566 timevar_push (TV_VAR_TRACKING);
4567 variable_tracking_main ();
4568 reorder_var_tracking_notes ();
4569 timevar_pop (TV_VAR_TRACKING);
4571 df_finish_pass (false);
4574 /* Handle interrupt_handler, exception_handler and nmi_handler function
4575 attributes; arguments as in struct attribute_spec.handler. */
4578 handle_int_attribute (tree *node, tree name,
4579 tree args ATTRIBUTE_UNUSED,
4580 int flags ATTRIBUTE_UNUSED,
4584 if (TREE_CODE (x) == FUNCTION_DECL)
4587 if (TREE_CODE (x) != FUNCTION_TYPE)
4589 warning (OPT_Wattributes, "%qs attribute only applies to functions",
4590 IDENTIFIER_POINTER (name));
4591 *no_add_attrs = true;
4593 else if (funkind (x) != SUBROUTINE)
4594 error ("multiple function type attributes specified");
4599 /* Return 0 if the attributes for two types are incompatible, 1 if they
4600 are compatible, and 2 if they are nearly compatible (which causes a
4601 warning to be generated). */
4604 bfin_comp_type_attributes (const_tree type1, const_tree type2)
4606 e_funkind kind1, kind2;
4608 if (TREE_CODE (type1) != FUNCTION_TYPE)
4611 kind1 = funkind (type1);
4612 kind2 = funkind (type2);
4617 /* Check for mismatched modifiers */
4618 if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
4619 != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
4622 if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
4623 != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
4626 if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
4627 != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
4630 if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1))
4631 != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2)))
4637 /* Handle a "longcall" or "shortcall" attribute; arguments as in
4638 struct attribute_spec.handler. */
4641 bfin_handle_longcall_attribute (tree *node, tree name,
4642 tree args ATTRIBUTE_UNUSED,
4643 int flags ATTRIBUTE_UNUSED,
4646 if (TREE_CODE (*node) != FUNCTION_TYPE
4647 && TREE_CODE (*node) != FIELD_DECL
4648 && TREE_CODE (*node) != TYPE_DECL)
4650 warning (OPT_Wattributes, "`%s' attribute only applies to functions",
4651 IDENTIFIER_POINTER (name));
4652 *no_add_attrs = true;
4655 if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0
4656 && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node)))
4657 || (strcmp (IDENTIFIER_POINTER (name), "shortcall") == 0
4658 && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node))))
4660 warning (OPT_Wattributes,
4661 "can't apply both longcall and shortcall attributes to the same function");
4662 *no_add_attrs = true;
4668 /* Handle a "l1_text" attribute; arguments as in
4669 struct attribute_spec.handler. */
4672 bfin_handle_l1_text_attribute (tree *node, tree name, tree ARG_UNUSED (args),
4673 int ARG_UNUSED (flags), bool *no_add_attrs)
4677 if (TREE_CODE (decl) != FUNCTION_DECL)
4679 error ("`%s' attribute only applies to functions",
4680 IDENTIFIER_POINTER (name));
4681 *no_add_attrs = true;
4684 /* The decl may have already been given a section attribute
4685 from a previous declaration. Ensure they match. */
4686 else if (DECL_SECTION_NAME (decl) != NULL_TREE
4687 && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
4690 error ("section of %q+D conflicts with previous declaration",
4692 *no_add_attrs = true;
4695 DECL_SECTION_NAME (decl) = build_string (9, ".l1.text");
4700 /* Handle a "l1_data", "l1_data_A" or "l1_data_B" attribute;
4701 arguments as in struct attribute_spec.handler. */
4704 bfin_handle_l1_data_attribute (tree *node, tree name, tree ARG_UNUSED (args),
4705 int ARG_UNUSED (flags), bool *no_add_attrs)
4709 if (TREE_CODE (decl) != VAR_DECL)
4711 error ("`%s' attribute only applies to variables",
4712 IDENTIFIER_POINTER (name));
4713 *no_add_attrs = true;
4715 else if (current_function_decl != NULL_TREE
4716 && !TREE_STATIC (decl))
4718 error ("`%s' attribute cannot be specified for local variables",
4719 IDENTIFIER_POINTER (name));
4720 *no_add_attrs = true;
4724 const char *section_name;
4726 if (strcmp (IDENTIFIER_POINTER (name), "l1_data") == 0)
4727 section_name = ".l1.data";
4728 else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_A") == 0)
4729 section_name = ".l1.data.A";
4730 else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_B") == 0)
4731 section_name = ".l1.data.B";
4735 /* The decl may have already been given a section attribute
4736 from a previous declaration. Ensure they match. */
4737 if (DECL_SECTION_NAME (decl) != NULL_TREE
4738 && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
4741 error ("section of %q+D conflicts with previous declaration",
4743 *no_add_attrs = true;
4746 DECL_SECTION_NAME (decl)
4747 = build_string (strlen (section_name) + 1, section_name);
4753 /* Table of valid machine attributes. */
4754 const struct attribute_spec bfin_attribute_table[] =
4756 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4757 { "interrupt_handler", 0, 0, false, true, true, handle_int_attribute },
4758 { "exception_handler", 0, 0, false, true, true, handle_int_attribute },
4759 { "nmi_handler", 0, 0, false, true, true, handle_int_attribute },
4760 { "nesting", 0, 0, false, true, true, NULL },
4761 { "kspisusp", 0, 0, false, true, true, NULL },
4762 { "saveall", 0, 0, false, true, true, NULL },
4763 { "longcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
4764 { "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
4765 { "l1_text", 0, 0, true, false, false, bfin_handle_l1_text_attribute },
4766 { "l1_data", 0, 0, true, false, false, bfin_handle_l1_data_attribute },
4767 { "l1_data_A", 0, 0, true, false, false, bfin_handle_l1_data_attribute },
4768 { "l1_data_B", 0, 0, true, false, false, bfin_handle_l1_data_attribute },
4769 { NULL, 0, 0, false, false, false, NULL }
4772 /* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to
4773 tell the assembler to generate pointers to function descriptors in
4777 bfin_assemble_integer (rtx value, unsigned int size, int aligned_p)
4779 if (TARGET_FDPIC && size == UNITS_PER_WORD)
4781 if (GET_CODE (value) == SYMBOL_REF
4782 && SYMBOL_REF_FUNCTION_P (value))
4784 fputs ("\t.picptr\tfuncdesc(", asm_out_file);
4785 output_addr_const (asm_out_file, value);
4786 fputs (")\n", asm_out_file);
4791 /* We've set the unaligned SI op to NULL, so we always have to
4792 handle the unaligned case here. */
4793 assemble_integer_with_op ("\t.4byte\t", value);
4797 return default_assemble_integer (value, size, aligned_p);
4800 /* Output the assembler code for a thunk function. THUNK_DECL is the
4801 declaration for the thunk function itself, FUNCTION is the decl for
4802 the target function. DELTA is an immediate constant offset to be
4803 added to THIS. If VCALL_OFFSET is nonzero, the word at
4804 *(*this + vcall_offset) should be added to THIS. */
4807 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
4808 tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
4809 HOST_WIDE_INT vcall_offset, tree function)
4812 /* The this parameter is passed as the first argument. */
4813 rtx this = gen_rtx_REG (Pmode, REG_R0);
4815 /* Adjust the this parameter by a fixed constant. */
4819 if (delta >= -64 && delta <= 63)
4821 xops[0] = GEN_INT (delta);
4822 output_asm_insn ("%1 += %0;", xops);
4824 else if (delta >= -128 && delta < -64)
4826 xops[0] = GEN_INT (delta + 64);
4827 output_asm_insn ("%1 += -64; %1 += %0;", xops);
4829 else if (delta > 63 && delta <= 126)
4831 xops[0] = GEN_INT (delta - 63);
4832 output_asm_insn ("%1 += 63; %1 += %0;", xops);
4836 xops[0] = GEN_INT (delta);
4837 output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
4841 /* Adjust the this parameter by a value stored in the vtable. */
4844 rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
4845 rtx tmp = gen_rtx_REG (Pmode, REG_R3);
4849 output_asm_insn ("%2 = r0; %2 = [%2];", xops);
4851 /* Adjust the this parameter. */
4852 xops[0] = gen_rtx_MEM (Pmode, plus_constant (p2tmp, vcall_offset));
4853 if (!memory_operand (xops[0], Pmode))
4855 rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
4856 xops[0] = GEN_INT (vcall_offset);
4858 output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
4859 xops[0] = gen_rtx_MEM (Pmode, p2tmp);
4862 output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
4865 xops[0] = XEXP (DECL_RTL (function), 0);
4866 if (1 || !flag_pic || (*targetm.binds_local_p) (function))
4867 output_asm_insn ("jump.l\t%P0", xops);
4870 /* Codes for all the Blackfin builtins. */
4875 BFIN_BUILTIN_COMPOSE_2X16,
4876 BFIN_BUILTIN_EXTRACTLO,
4877 BFIN_BUILTIN_EXTRACTHI,
4879 BFIN_BUILTIN_SSADD_2X16,
4880 BFIN_BUILTIN_SSSUB_2X16,
4881 BFIN_BUILTIN_SSADDSUB_2X16,
4882 BFIN_BUILTIN_SSSUBADD_2X16,
4883 BFIN_BUILTIN_MULT_2X16,
4884 BFIN_BUILTIN_MULTR_2X16,
4885 BFIN_BUILTIN_NEG_2X16,
4886 BFIN_BUILTIN_ABS_2X16,
4887 BFIN_BUILTIN_MIN_2X16,
4888 BFIN_BUILTIN_MAX_2X16,
4890 BFIN_BUILTIN_SSADD_1X16,
4891 BFIN_BUILTIN_SSSUB_1X16,
4892 BFIN_BUILTIN_MULT_1X16,
4893 BFIN_BUILTIN_MULTR_1X16,
4894 BFIN_BUILTIN_NORM_1X16,
4895 BFIN_BUILTIN_NEG_1X16,
4896 BFIN_BUILTIN_ABS_1X16,
4897 BFIN_BUILTIN_MIN_1X16,
4898 BFIN_BUILTIN_MAX_1X16,
4900 BFIN_BUILTIN_SUM_2X16,
4901 BFIN_BUILTIN_DIFFHL_2X16,
4902 BFIN_BUILTIN_DIFFLH_2X16,
4904 BFIN_BUILTIN_SSADD_1X32,
4905 BFIN_BUILTIN_SSSUB_1X32,
4906 BFIN_BUILTIN_NORM_1X32,
4907 BFIN_BUILTIN_ROUND_1X32,
4908 BFIN_BUILTIN_NEG_1X32,
4909 BFIN_BUILTIN_ABS_1X32,
4910 BFIN_BUILTIN_MIN_1X32,
4911 BFIN_BUILTIN_MAX_1X32,
4912 BFIN_BUILTIN_MULT_1X32,
4913 BFIN_BUILTIN_MULT_1X32X32,
4914 BFIN_BUILTIN_MULT_1X32X32NS,
4916 BFIN_BUILTIN_MULHISILL,
4917 BFIN_BUILTIN_MULHISILH,
4918 BFIN_BUILTIN_MULHISIHL,
4919 BFIN_BUILTIN_MULHISIHH,
4921 BFIN_BUILTIN_LSHIFT_1X16,
4922 BFIN_BUILTIN_LSHIFT_2X16,
4923 BFIN_BUILTIN_SSASHIFT_1X16,
4924 BFIN_BUILTIN_SSASHIFT_2X16,
4925 BFIN_BUILTIN_SSASHIFT_1X32,
4927 BFIN_BUILTIN_CPLX_MUL_16,
4928 BFIN_BUILTIN_CPLX_MAC_16,
4929 BFIN_BUILTIN_CPLX_MSU_16,
4934 #define def_builtin(NAME, TYPE, CODE) \
4936 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
4940 /* Set up all builtin functions for this target. */
4942 bfin_init_builtins (void)
4944 tree V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
4945 tree void_ftype_void
4946 = build_function_type (void_type_node, void_list_node);
4947 tree short_ftype_short
4948 = build_function_type_list (short_integer_type_node, short_integer_type_node,
4950 tree short_ftype_int_int
4951 = build_function_type_list (short_integer_type_node, integer_type_node,
4952 integer_type_node, NULL_TREE);
4953 tree int_ftype_int_int
4954 = build_function_type_list (integer_type_node, integer_type_node,
4955 integer_type_node, NULL_TREE);
4957 = build_function_type_list (integer_type_node, integer_type_node,
4959 tree short_ftype_int
4960 = build_function_type_list (short_integer_type_node, integer_type_node,
4962 tree int_ftype_v2hi_v2hi
4963 = build_function_type_list (integer_type_node, V2HI_type_node,
4964 V2HI_type_node, NULL_TREE);
4965 tree v2hi_ftype_v2hi_v2hi
4966 = build_function_type_list (V2HI_type_node, V2HI_type_node,
4967 V2HI_type_node, NULL_TREE);
4968 tree v2hi_ftype_v2hi_v2hi_v2hi
4969 = build_function_type_list (V2HI_type_node, V2HI_type_node,
4970 V2HI_type_node, V2HI_type_node, NULL_TREE);
4971 tree v2hi_ftype_int_int
4972 = build_function_type_list (V2HI_type_node, integer_type_node,
4973 integer_type_node, NULL_TREE);
4974 tree v2hi_ftype_v2hi_int
4975 = build_function_type_list (V2HI_type_node, V2HI_type_node,
4976 integer_type_node, NULL_TREE);
4977 tree int_ftype_short_short
4978 = build_function_type_list (integer_type_node, short_integer_type_node,
4979 short_integer_type_node, NULL_TREE);
4980 tree v2hi_ftype_v2hi
4981 = build_function_type_list (V2HI_type_node, V2HI_type_node, NULL_TREE);
4982 tree short_ftype_v2hi
4983 = build_function_type_list (short_integer_type_node, V2HI_type_node,
4986 /* Add the remaining MMX insns with somewhat more complicated types. */
4987 def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC);
4988 def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC);
4990 def_builtin ("__builtin_bfin_compose_2x16", v2hi_ftype_int_int,
4991 BFIN_BUILTIN_COMPOSE_2X16);
4992 def_builtin ("__builtin_bfin_extract_hi", short_ftype_v2hi,
4993 BFIN_BUILTIN_EXTRACTHI);
4994 def_builtin ("__builtin_bfin_extract_lo", short_ftype_v2hi,
4995 BFIN_BUILTIN_EXTRACTLO);
4997 def_builtin ("__builtin_bfin_min_fr2x16", v2hi_ftype_v2hi_v2hi,
4998 BFIN_BUILTIN_MIN_2X16);
4999 def_builtin ("__builtin_bfin_max_fr2x16", v2hi_ftype_v2hi_v2hi,
5000 BFIN_BUILTIN_MAX_2X16);
5002 def_builtin ("__builtin_bfin_add_fr2x16", v2hi_ftype_v2hi_v2hi,
5003 BFIN_BUILTIN_SSADD_2X16);
5004 def_builtin ("__builtin_bfin_sub_fr2x16", v2hi_ftype_v2hi_v2hi,
5005 BFIN_BUILTIN_SSSUB_2X16);
5006 def_builtin ("__builtin_bfin_dspaddsubsat", v2hi_ftype_v2hi_v2hi,
5007 BFIN_BUILTIN_SSADDSUB_2X16);
5008 def_builtin ("__builtin_bfin_dspsubaddsat", v2hi_ftype_v2hi_v2hi,
5009 BFIN_BUILTIN_SSSUBADD_2X16);
5010 def_builtin ("__builtin_bfin_mult_fr2x16", v2hi_ftype_v2hi_v2hi,
5011 BFIN_BUILTIN_MULT_2X16);
5012 def_builtin ("__builtin_bfin_multr_fr2x16", v2hi_ftype_v2hi_v2hi,
5013 BFIN_BUILTIN_MULTR_2X16);
5014 def_builtin ("__builtin_bfin_negate_fr2x16", v2hi_ftype_v2hi,
5015 BFIN_BUILTIN_NEG_2X16);
5016 def_builtin ("__builtin_bfin_abs_fr2x16", v2hi_ftype_v2hi,
5017 BFIN_BUILTIN_ABS_2X16);
5019 def_builtin ("__builtin_bfin_add_fr1x16", short_ftype_int_int,
5020 BFIN_BUILTIN_SSADD_1X16);
5021 def_builtin ("__builtin_bfin_sub_fr1x16", short_ftype_int_int,
5022 BFIN_BUILTIN_SSSUB_1X16);
5023 def_builtin ("__builtin_bfin_mult_fr1x16", short_ftype_int_int,
5024 BFIN_BUILTIN_MULT_1X16);
5025 def_builtin ("__builtin_bfin_multr_fr1x16", short_ftype_int_int,
5026 BFIN_BUILTIN_MULTR_1X16);
5027 def_builtin ("__builtin_bfin_negate_fr1x16", short_ftype_short,
5028 BFIN_BUILTIN_NEG_1X16);
5029 def_builtin ("__builtin_bfin_abs_fr1x16", short_ftype_short,
5030 BFIN_BUILTIN_ABS_1X16);
5031 def_builtin ("__builtin_bfin_norm_fr1x16", short_ftype_int,
5032 BFIN_BUILTIN_NORM_1X16);
5034 def_builtin ("__builtin_bfin_sum_fr2x16", short_ftype_v2hi,
5035 BFIN_BUILTIN_SUM_2X16);
5036 def_builtin ("__builtin_bfin_diff_hl_fr2x16", short_ftype_v2hi,
5037 BFIN_BUILTIN_DIFFHL_2X16);
5038 def_builtin ("__builtin_bfin_diff_lh_fr2x16", short_ftype_v2hi,
5039 BFIN_BUILTIN_DIFFLH_2X16);
5041 def_builtin ("__builtin_bfin_mulhisill", int_ftype_v2hi_v2hi,
5042 BFIN_BUILTIN_MULHISILL);
5043 def_builtin ("__builtin_bfin_mulhisihl", int_ftype_v2hi_v2hi,
5044 BFIN_BUILTIN_MULHISIHL);
5045 def_builtin ("__builtin_bfin_mulhisilh", int_ftype_v2hi_v2hi,
5046 BFIN_BUILTIN_MULHISILH);
5047 def_builtin ("__builtin_bfin_mulhisihh", int_ftype_v2hi_v2hi,
5048 BFIN_BUILTIN_MULHISIHH);
5050 def_builtin ("__builtin_bfin_add_fr1x32", int_ftype_int_int,
5051 BFIN_BUILTIN_SSADD_1X32);
5052 def_builtin ("__builtin_bfin_sub_fr1x32", int_ftype_int_int,
5053 BFIN_BUILTIN_SSSUB_1X32);
5054 def_builtin ("__builtin_bfin_negate_fr1x32", int_ftype_int,
5055 BFIN_BUILTIN_NEG_1X32);
5056 def_builtin ("__builtin_bfin_abs_fr1x32", int_ftype_int,
5057 BFIN_BUILTIN_ABS_1X32);
5058 def_builtin ("__builtin_bfin_norm_fr1x32", short_ftype_int,
5059 BFIN_BUILTIN_NORM_1X32);
5060 def_builtin ("__builtin_bfin_round_fr1x32", short_ftype_int,
5061 BFIN_BUILTIN_ROUND_1X32);
5062 def_builtin ("__builtin_bfin_mult_fr1x32", int_ftype_short_short,
5063 BFIN_BUILTIN_MULT_1X32);
5064 def_builtin ("__builtin_bfin_mult_fr1x32x32", int_ftype_int_int,
5065 BFIN_BUILTIN_MULT_1X32X32);
5066 def_builtin ("__builtin_bfin_mult_fr1x32x32NS", int_ftype_int_int,
5067 BFIN_BUILTIN_MULT_1X32X32NS);
5070 def_builtin ("__builtin_bfin_shl_fr1x16", short_ftype_int_int,
5071 BFIN_BUILTIN_SSASHIFT_1X16);
5072 def_builtin ("__builtin_bfin_shl_fr2x16", v2hi_ftype_v2hi_int,
5073 BFIN_BUILTIN_SSASHIFT_2X16);
5074 def_builtin ("__builtin_bfin_lshl_fr1x16", short_ftype_int_int,
5075 BFIN_BUILTIN_LSHIFT_1X16);
5076 def_builtin ("__builtin_bfin_lshl_fr2x16", v2hi_ftype_v2hi_int,
5077 BFIN_BUILTIN_LSHIFT_2X16);
5078 def_builtin ("__builtin_bfin_shl_fr1x32", int_ftype_int_int,
5079 BFIN_BUILTIN_SSASHIFT_1X32);
5081 /* Complex numbers. */
5082 def_builtin ("__builtin_bfin_cmplx_mul", v2hi_ftype_v2hi_v2hi,
5083 BFIN_BUILTIN_CPLX_MUL_16);
5084 def_builtin ("__builtin_bfin_cmplx_mac", v2hi_ftype_v2hi_v2hi_v2hi,
5085 BFIN_BUILTIN_CPLX_MAC_16);
5086 def_builtin ("__builtin_bfin_cmplx_msu", v2hi_ftype_v2hi_v2hi_v2hi,
5087 BFIN_BUILTIN_CPLX_MSU_16);
5091 struct builtin_description
5093 const enum insn_code icode;
5094 const char *const name;
5095 const enum bfin_builtins code;
5099 static const struct builtin_description bdesc_2arg[] =
5101 { CODE_FOR_composev2hi, "__builtin_bfin_compose_2x16", BFIN_BUILTIN_COMPOSE_2X16, -1 },
5103 { CODE_FOR_ssashiftv2hi3, "__builtin_bfin_shl_fr2x16", BFIN_BUILTIN_SSASHIFT_2X16, -1 },
5104 { CODE_FOR_ssashifthi3, "__builtin_bfin_shl_fr1x16", BFIN_BUILTIN_SSASHIFT_1X16, -1 },
5105 { CODE_FOR_lshiftv2hi3, "__builtin_bfin_lshl_fr2x16", BFIN_BUILTIN_LSHIFT_2X16, -1 },
5106 { CODE_FOR_lshifthi3, "__builtin_bfin_lshl_fr1x16", BFIN_BUILTIN_LSHIFT_1X16, -1 },
5107 { CODE_FOR_ssashiftsi3, "__builtin_bfin_shl_fr1x32", BFIN_BUILTIN_SSASHIFT_1X32, -1 },
5109 { CODE_FOR_sminhi3, "__builtin_bfin_min_fr1x16", BFIN_BUILTIN_MIN_1X16, -1 },
5110 { CODE_FOR_smaxhi3, "__builtin_bfin_max_fr1x16", BFIN_BUILTIN_MAX_1X16, -1 },
5111 { CODE_FOR_ssaddhi3, "__builtin_bfin_add_fr1x16", BFIN_BUILTIN_SSADD_1X16, -1 },
5112 { CODE_FOR_sssubhi3, "__builtin_bfin_sub_fr1x16", BFIN_BUILTIN_SSSUB_1X16, -1 },
5114 { CODE_FOR_sminsi3, "__builtin_bfin_min_fr1x32", BFIN_BUILTIN_MIN_1X32, -1 },
5115 { CODE_FOR_smaxsi3, "__builtin_bfin_max_fr1x32", BFIN_BUILTIN_MAX_1X32, -1 },
5116 { CODE_FOR_ssaddsi3, "__builtin_bfin_add_fr1x32", BFIN_BUILTIN_SSADD_1X32, -1 },
5117 { CODE_FOR_sssubsi3, "__builtin_bfin_sub_fr1x32", BFIN_BUILTIN_SSSUB_1X32, -1 },
5119 { CODE_FOR_sminv2hi3, "__builtin_bfin_min_fr2x16", BFIN_BUILTIN_MIN_2X16, -1 },
5120 { CODE_FOR_smaxv2hi3, "__builtin_bfin_max_fr2x16", BFIN_BUILTIN_MAX_2X16, -1 },
5121 { CODE_FOR_ssaddv2hi3, "__builtin_bfin_add_fr2x16", BFIN_BUILTIN_SSADD_2X16, -1 },
5122 { CODE_FOR_sssubv2hi3, "__builtin_bfin_sub_fr2x16", BFIN_BUILTIN_SSSUB_2X16, -1 },
5123 { CODE_FOR_ssaddsubv2hi3, "__builtin_bfin_dspaddsubsat", BFIN_BUILTIN_SSADDSUB_2X16, -1 },
5124 { CODE_FOR_sssubaddv2hi3, "__builtin_bfin_dspsubaddsat", BFIN_BUILTIN_SSSUBADD_2X16, -1 },
5126 { CODE_FOR_flag_mulhisi, "__builtin_bfin_mult_fr1x32", BFIN_BUILTIN_MULT_1X32, MACFLAG_NONE },
5127 { CODE_FOR_flag_mulhi, "__builtin_bfin_mult_fr1x16", BFIN_BUILTIN_MULT_1X16, MACFLAG_T },
5128 { CODE_FOR_flag_mulhi, "__builtin_bfin_multr_fr1x16", BFIN_BUILTIN_MULTR_1X16, MACFLAG_NONE },
5129 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_mult_fr2x16", BFIN_BUILTIN_MULT_2X16, MACFLAG_T },
5130 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_multr_fr2x16", BFIN_BUILTIN_MULTR_2X16, MACFLAG_NONE }
5133 static const struct builtin_description bdesc_1arg[] =
5135 { CODE_FOR_signbitshi2, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16, 0 },
5136 { CODE_FOR_ssneghi2, "__builtin_bfin_negate_fr1x16", BFIN_BUILTIN_NEG_1X16, 0 },
5137 { CODE_FOR_abshi2, "__builtin_bfin_abs_fr1x16", BFIN_BUILTIN_ABS_1X16, 0 },
5139 { CODE_FOR_signbitssi2, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32, 0 },
5140 { CODE_FOR_ssroundsi2, "__builtin_bfin_round_fr1x32", BFIN_BUILTIN_ROUND_1X32, 0 },
5141 { CODE_FOR_ssnegsi2, "__builtin_bfin_negate_fr1x32", BFIN_BUILTIN_NEG_1X32, 0 },
5142 { CODE_FOR_ssabssi2, "__builtin_bfin_abs_fr1x32", BFIN_BUILTIN_ABS_1X32, 0 },
5144 { CODE_FOR_movv2hi_hi_low, "__builtin_bfin_extract_lo", BFIN_BUILTIN_EXTRACTLO, 0 },
5145 { CODE_FOR_movv2hi_hi_high, "__builtin_bfin_extract_hi", BFIN_BUILTIN_EXTRACTHI, 0 },
5146 { CODE_FOR_ssnegv2hi2, "__builtin_bfin_negate_fr2x16", BFIN_BUILTIN_NEG_2X16, 0 },
5147 { CODE_FOR_ssabsv2hi2, "__builtin_bfin_abs_fr2x16", BFIN_BUILTIN_ABS_2X16, 0 }
5150 /* Errors in the source file can cause expand_expr to return const0_rtx
5151 where we expect a vector. To avoid crashing, use one of the vector
5152 clear instructions. */
5154 safe_vector_operand (rtx x, enum machine_mode mode)
5156 if (x != const0_rtx)
5158 x = gen_reg_rtx (SImode);
5160 emit_insn (gen_movsi (x, CONST0_RTX (SImode)));
5161 return gen_lowpart (mode, x);
5164 /* Subroutine of bfin_expand_builtin to take care of binop insns. MACFLAG is -1
5165 if this is a normal binary op, or one of the MACFLAG_xxx constants. */
5168 bfin_expand_binop_builtin (enum insn_code icode, tree exp, rtx target,
5172 tree arg0 = CALL_EXPR_ARG (exp, 0);
5173 tree arg1 = CALL_EXPR_ARG (exp, 1);
5174 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5175 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
5176 enum machine_mode op0mode = GET_MODE (op0);
5177 enum machine_mode op1mode = GET_MODE (op1);
5178 enum machine_mode tmode = insn_data[icode].operand[0].mode;
5179 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
5180 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
5182 if (VECTOR_MODE_P (mode0))
5183 op0 = safe_vector_operand (op0, mode0);
5184 if (VECTOR_MODE_P (mode1))
5185 op1 = safe_vector_operand (op1, mode1);
5188 || GET_MODE (target) != tmode
5189 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5190 target = gen_reg_rtx (tmode);
5192 if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode)
5195 op0 = gen_lowpart (HImode, op0);
5197 if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode)
5200 op1 = gen_lowpart (HImode, op1);
5202 /* In case the insn wants input operands in modes different from
5203 the result, abort. */
5204 gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
5205 && (op1mode == mode1 || op1mode == VOIDmode));
5207 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5208 op0 = copy_to_mode_reg (mode0, op0);
5209 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
5210 op1 = copy_to_mode_reg (mode1, op1);
5213 pat = GEN_FCN (icode) (target, op0, op1);
5215 pat = GEN_FCN (icode) (target, op0, op1, GEN_INT (macflag));
5223 /* Subroutine of bfin_expand_builtin to take care of unop insns. */
5226 bfin_expand_unop_builtin (enum insn_code icode, tree exp,
5230 tree arg0 = CALL_EXPR_ARG (exp, 0);
5231 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5232 enum machine_mode op0mode = GET_MODE (op0);
5233 enum machine_mode tmode = insn_data[icode].operand[0].mode;
5234 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
5237 || GET_MODE (target) != tmode
5238 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5239 target = gen_reg_rtx (tmode);
5241 if (VECTOR_MODE_P (mode0))
5242 op0 = safe_vector_operand (op0, mode0);
5244 if (op0mode == SImode && mode0 == HImode)
5247 op0 = gen_lowpart (HImode, op0);
5249 gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
5251 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5252 op0 = copy_to_mode_reg (mode0, op0);
5254 pat = GEN_FCN (icode) (target, op0);
5261 /* Expand an expression EXP that calls a built-in function,
5262 with result going to TARGET if that's convenient
5263 (and in mode MODE if that's convenient).
5264 SUBTARGET may be used as the target for computing one of EXP's operands.
5265 IGNORE is nonzero if the value is to be ignored. */
5268 bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
5269 rtx subtarget ATTRIBUTE_UNUSED,
5270 enum machine_mode mode ATTRIBUTE_UNUSED,
5271 int ignore ATTRIBUTE_UNUSED)
5274 enum insn_code icode;
5275 const struct builtin_description *d;
5276 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
5277 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
5278 tree arg0, arg1, arg2;
5279 rtx op0, op1, op2, accvec, pat, tmp1, tmp2, a0reg, a1reg;
5280 enum machine_mode tmode, mode0;
5284 case BFIN_BUILTIN_CSYNC:
5285 emit_insn (gen_csync ());
5287 case BFIN_BUILTIN_SSYNC:
5288 emit_insn (gen_ssync ());
5291 case BFIN_BUILTIN_DIFFHL_2X16:
5292 case BFIN_BUILTIN_DIFFLH_2X16:
5293 case BFIN_BUILTIN_SUM_2X16:
5294 arg0 = CALL_EXPR_ARG (exp, 0);
5295 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5296 icode = (fcode == BFIN_BUILTIN_DIFFHL_2X16 ? CODE_FOR_subhilov2hi3
5297 : fcode == BFIN_BUILTIN_DIFFLH_2X16 ? CODE_FOR_sublohiv2hi3
5298 : CODE_FOR_ssaddhilov2hi3);
5299 tmode = insn_data[icode].operand[0].mode;
5300 mode0 = insn_data[icode].operand[1].mode;
5303 || GET_MODE (target) != tmode
5304 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5305 target = gen_reg_rtx (tmode);
5307 if (VECTOR_MODE_P (mode0))
5308 op0 = safe_vector_operand (op0, mode0);
5310 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5311 op0 = copy_to_mode_reg (mode0, op0);
5313 pat = GEN_FCN (icode) (target, op0, op0);
5319 case BFIN_BUILTIN_MULT_1X32X32:
5320 case BFIN_BUILTIN_MULT_1X32X32NS:
5321 arg0 = CALL_EXPR_ARG (exp, 0);
5322 arg1 = CALL_EXPR_ARG (exp, 1);
5323 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5324 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
5326 || !register_operand (target, SImode))
5327 target = gen_reg_rtx (SImode);
5329 a1reg = gen_rtx_REG (PDImode, REG_A1);
5330 a0reg = gen_rtx_REG (PDImode, REG_A0);
5331 tmp1 = gen_lowpart (V2HImode, op0);
5332 tmp2 = gen_lowpart (V2HImode, op1);
5333 emit_insn (gen_flag_macinit1hi (a1reg,
5334 gen_lowpart (HImode, op0),
5335 gen_lowpart (HImode, op1),
5336 GEN_INT (MACFLAG_FU)));
5337 emit_insn (gen_lshrpdi3 (a1reg, a1reg, GEN_INT (16)));
5339 if (fcode == BFIN_BUILTIN_MULT_1X32X32)
5340 emit_insn (gen_flag_mul_macv2hi_parts_acconly (a0reg, a1reg, tmp1, tmp2,
5341 const1_rtx, const1_rtx,
5342 const1_rtx, const0_rtx, a1reg,
5343 const0_rtx, GEN_INT (MACFLAG_NONE),
5344 GEN_INT (MACFLAG_M)));
5347 /* For saturating multiplication, there's exactly one special case
5348 to be handled: multiplying the smallest negative value with
5349 itself. Due to shift correction in fractional multiplies, this
5350 can overflow. Iff this happens, OP2 will contain 1, which, when
5351 added in 32 bits to the smallest negative, wraps to the largest
5352 positive, which is the result we want. */
5353 op2 = gen_reg_rtx (V2HImode);
5354 emit_insn (gen_packv2hi (op2, tmp1, tmp2, const0_rtx, const0_rtx));
5355 emit_insn (gen_movsibi (gen_rtx_REG (BImode, REG_CC),
5356 gen_lowpart (SImode, op2)));
5357 emit_insn (gen_flag_mul_macv2hi_parts_acconly_andcc0 (a0reg, a1reg, tmp1, tmp2,
5358 const1_rtx, const1_rtx,
5359 const1_rtx, const0_rtx, a1reg,
5360 const0_rtx, GEN_INT (MACFLAG_NONE),
5361 GEN_INT (MACFLAG_M)));
5362 op2 = gen_reg_rtx (SImode);
5363 emit_insn (gen_movbisi (op2, gen_rtx_REG (BImode, REG_CC)));
5365 emit_insn (gen_flag_machi_parts_acconly (a1reg, tmp2, tmp1,
5366 const1_rtx, const0_rtx,
5367 a1reg, const0_rtx, GEN_INT (MACFLAG_M)));
5368 emit_insn (gen_ashrpdi3 (a1reg, a1reg, GEN_INT (15)));
5369 emit_insn (gen_sum_of_accumulators (target, a0reg, a0reg, a1reg));
5370 if (fcode == BFIN_BUILTIN_MULT_1X32X32NS)
5371 emit_insn (gen_addsi3 (target, target, op2));
5374 case BFIN_BUILTIN_CPLX_MUL_16:
5375 arg0 = CALL_EXPR_ARG (exp, 0);
5376 arg1 = CALL_EXPR_ARG (exp, 1);
5377 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5378 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
5379 accvec = gen_reg_rtx (V2PDImode);
5382 || GET_MODE (target) != V2HImode
5383 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5384 target = gen_reg_rtx (tmode);
5385 if (! register_operand (op0, GET_MODE (op0)))
5386 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
5387 if (! register_operand (op1, GET_MODE (op1)))
5388 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
5390 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
5391 const0_rtx, const0_rtx,
5392 const1_rtx, GEN_INT (MACFLAG_NONE)));
5393 emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
5394 const1_rtx, const1_rtx,
5395 const0_rtx, accvec, const1_rtx, const0_rtx,
5396 GEN_INT (MACFLAG_NONE), accvec));
5400 case BFIN_BUILTIN_CPLX_MAC_16:
5401 case BFIN_BUILTIN_CPLX_MSU_16:
5402 arg0 = CALL_EXPR_ARG (exp, 0);
5403 arg1 = CALL_EXPR_ARG (exp, 1);
5404 arg2 = CALL_EXPR_ARG (exp, 2);
5405 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5406 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
5407 op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
5408 accvec = gen_reg_rtx (V2PDImode);
5411 || GET_MODE (target) != V2HImode
5412 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5413 target = gen_reg_rtx (tmode);
5414 if (! register_operand (op1, GET_MODE (op1)))
5415 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
5416 if (! register_operand (op2, GET_MODE (op2)))
5417 op2 = copy_to_mode_reg (GET_MODE (op2), op2);
5419 tmp1 = gen_reg_rtx (SImode);
5420 tmp2 = gen_reg_rtx (SImode);
5421 emit_insn (gen_ashlsi3 (tmp1, gen_lowpart (SImode, op0), GEN_INT (16)));
5422 emit_move_insn (tmp2, gen_lowpart (SImode, op0));
5423 emit_insn (gen_movstricthi_1 (gen_lowpart (HImode, tmp2), const0_rtx));
5424 emit_insn (gen_load_accumulator_pair (accvec, tmp1, tmp2));
5425 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx,
5426 const0_rtx, const0_rtx,
5427 const1_rtx, accvec, const0_rtx,
5429 GEN_INT (MACFLAG_W32)));
5430 tmp1 = (fcode == BFIN_BUILTIN_CPLX_MAC_16 ? const1_rtx : const0_rtx);
5431 tmp2 = (fcode == BFIN_BUILTIN_CPLX_MAC_16 ? const0_rtx : const1_rtx);
5432 emit_insn (gen_flag_macv2hi_parts (target, op1, op2, const1_rtx,
5433 const1_rtx, const1_rtx,
5434 const0_rtx, accvec, tmp1, tmp2,
5435 GEN_INT (MACFLAG_NONE), accvec));
5443 for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
5444 if (d->code == fcode)
5445 return bfin_expand_binop_builtin (d->icode, exp, target,
5448 for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
5449 if (d->code == fcode)
5450 return bfin_expand_unop_builtin (d->icode, exp, target);
5455 #undef TARGET_INIT_BUILTINS
5456 #define TARGET_INIT_BUILTINS bfin_init_builtins
5458 #undef TARGET_EXPAND_BUILTIN
5459 #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
5461 #undef TARGET_ASM_GLOBALIZE_LABEL
5462 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label
5464 #undef TARGET_ASM_FILE_START
5465 #define TARGET_ASM_FILE_START output_file_start
5467 #undef TARGET_ATTRIBUTE_TABLE
5468 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
5470 #undef TARGET_COMP_TYPE_ATTRIBUTES
5471 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
5473 #undef TARGET_RTX_COSTS
5474 #define TARGET_RTX_COSTS bfin_rtx_costs
5476 #undef TARGET_ADDRESS_COST
5477 #define TARGET_ADDRESS_COST bfin_address_cost
5479 #undef TARGET_ASM_INTEGER
5480 #define TARGET_ASM_INTEGER bfin_assemble_integer
5482 #undef TARGET_MACHINE_DEPENDENT_REORG
5483 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
5485 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
5486 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
5488 #undef TARGET_ASM_OUTPUT_MI_THUNK
5489 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
5490 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
5491 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
5493 #undef TARGET_SCHED_ADJUST_COST
5494 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
5496 #undef TARGET_SCHED_ISSUE_RATE
5497 #define TARGET_SCHED_ISSUE_RATE bfin_issue_rate
5499 #undef TARGET_PROMOTE_PROTOTYPES
5500 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
5501 #undef TARGET_PROMOTE_FUNCTION_ARGS
5502 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
5503 #undef TARGET_PROMOTE_FUNCTION_RETURN
5504 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true
5506 #undef TARGET_ARG_PARTIAL_BYTES
5507 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
5509 #undef TARGET_PASS_BY_REFERENCE
5510 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
5512 #undef TARGET_SETUP_INCOMING_VARARGS
5513 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
5515 #undef TARGET_STRUCT_VALUE_RTX
5516 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
5518 #undef TARGET_VECTOR_MODE_SUPPORTED_P
5519 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
5521 #undef TARGET_HANDLE_OPTION
5522 #define TARGET_HANDLE_OPTION bfin_handle_option
5524 #undef TARGET_DEFAULT_TARGET_FLAGS
5525 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
5527 #undef TARGET_SECONDARY_RELOAD
5528 #define TARGET_SECONDARY_RELOAD bfin_secondary_reload
5530 #undef TARGET_DELEGITIMIZE_ADDRESS
5531 #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address
5533 #undef TARGET_CANNOT_FORCE_CONST_MEM
5534 #define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem
5536 struct gcc_target targetm = TARGET_INITIALIZER;