1 /* The Blackfin code generation auxiliary output file.
2 Copyright (C) 2005, 2006 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 2, 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 COPYING. If not, write to
19 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, USA. */
24 #include "coretypes.h"
28 #include "hard-reg-set.h"
30 #include "insn-config.h"
31 #include "insn-codes.h"
32 #include "conditions.h"
33 #include "insn-flags.h"
35 #include "insn-attr.h"
42 #include "target-def.h"
48 #include "integrate.h"
50 #include "langhooks.h"
51 #include "bfin-protos.h"
54 #include "basic-block.h"
56 /* A C structure for machine-specific, per-function data.
57 This is added to the cfun structure. */
58 struct machine_function GTY(())
60 int has_hardware_loops;
63 /* Test and compare insns in bfin.md store the information needed to
64 generate branch and scc insns here. */
65 rtx bfin_compare_op0, bfin_compare_op1;
67 /* RTX for condition code flag register and RETS register */
68 extern GTY(()) rtx bfin_cc_rtx;
69 extern GTY(()) rtx bfin_rets_rtx;
70 rtx bfin_cc_rtx, bfin_rets_rtx;
72 int max_arg_registers = 0;
74 /* Arrays used when emitting register names. */
75 const char *short_reg_names[] = SHORT_REGISTER_NAMES;
76 const char *high_reg_names[] = HIGH_REGISTER_NAMES;
77 const char *dregs_pair_names[] = DREGS_PAIR_NAMES;
78 const char *byte_reg_names[] = BYTE_REGISTER_NAMES;
80 static int arg_regs[] = FUNCTION_ARG_REGISTERS;
82 /* Nonzero if -mshared-library-id was given. */
83 static int bfin_lib_id_given;
86 bfin_globalize_label (FILE *stream, const char *name)
88 fputs (".global ", stream);
89 assemble_name (stream, name);
95 output_file_start (void)
97 FILE *file = asm_out_file;
100 fprintf (file, ".file \"%s\";\n", input_filename);
102 for (i = 0; arg_regs[i] >= 0; i++)
104 max_arg_registers = i; /* how many arg reg used */
107 /* Called early in the compilation to conditionally modify
108 fixed_regs/call_used_regs. */
111 conditional_register_usage (void)
113 /* initialize condition code flag register rtx */
114 bfin_cc_rtx = gen_rtx_REG (BImode, REG_CC);
115 bfin_rets_rtx = gen_rtx_REG (Pmode, REG_RETS);
118 /* Examine machine-dependent attributes of function type FUNTYPE and return its
119 type. See the definition of E_FUNKIND. */
121 static e_funkind funkind (tree funtype)
123 tree attrs = TYPE_ATTRIBUTES (funtype);
124 if (lookup_attribute ("interrupt_handler", attrs))
125 return INTERRUPT_HANDLER;
126 else if (lookup_attribute ("exception_handler", attrs))
127 return EXCPT_HANDLER;
128 else if (lookup_attribute ("nmi_handler", attrs))
134 /* Legitimize PIC addresses. If the address is already position-independent,
135 we return ORIG. Newly generated position-independent addresses go into a
136 reg. This is REG if nonzero, otherwise we allocate register(s) as
137 necessary. PICREG is the register holding the pointer to the PIC offset
141 legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
146 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
148 if (GET_CODE (addr) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (addr))
155 if (TARGET_ID_SHARED_LIBRARY)
156 unspec = UNSPEC_MOVE_PIC;
157 else if (GET_CODE (addr) == SYMBOL_REF
158 && SYMBOL_REF_FUNCTION_P (addr))
160 unspec = UNSPEC_FUNCDESC_GOT17M4;
164 unspec = UNSPEC_MOVE_FDPIC;
169 gcc_assert (!no_new_pseudos);
170 reg = gen_reg_rtx (Pmode);
173 tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), unspec);
174 new = gen_const_mem (Pmode, gen_rtx_PLUS (Pmode, picreg, tmp));
176 emit_move_insn (reg, new);
178 if (picreg == pic_offset_table_rtx)
179 current_function_uses_pic_offset_table = 1;
183 else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
187 if (GET_CODE (addr) == CONST)
189 addr = XEXP (addr, 0);
190 gcc_assert (GET_CODE (addr) == PLUS);
193 if (XEXP (addr, 0) == picreg)
198 gcc_assert (!no_new_pseudos);
199 reg = gen_reg_rtx (Pmode);
202 base = legitimize_pic_address (XEXP (addr, 0), reg, picreg);
203 addr = legitimize_pic_address (XEXP (addr, 1),
204 base == reg ? NULL_RTX : reg,
207 if (GET_CODE (addr) == CONST_INT)
209 gcc_assert (! reload_in_progress && ! reload_completed);
210 addr = force_reg (Pmode, addr);
213 if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
215 base = gen_rtx_PLUS (Pmode, base, XEXP (addr, 0));
216 addr = XEXP (addr, 1);
219 return gen_rtx_PLUS (Pmode, base, addr);
225 /* Stack frame layout. */
227 /* Compute the number of DREGS to save with a push_multiple operation.
228 This could include registers that aren't modified in the function,
229 since push_multiple only takes a range of registers.
230 If IS_INTHANDLER, then everything that is live must be saved, even
231 if normally call-clobbered. */
234 n_dregs_to_save (bool is_inthandler)
238 for (i = REG_R0; i <= REG_R7; i++)
240 if (regs_ever_live[i] && (is_inthandler || ! call_used_regs[i]))
241 return REG_R7 - i + 1;
243 if (current_function_calls_eh_return)
248 unsigned test = EH_RETURN_DATA_REGNO (j);
249 if (test == INVALID_REGNUM)
252 return REG_R7 - i + 1;
260 /* Like n_dregs_to_save, but compute number of PREGS to save. */
263 n_pregs_to_save (bool is_inthandler)
267 for (i = REG_P0; i <= REG_P5; i++)
268 if ((regs_ever_live[i] && (is_inthandler || ! call_used_regs[i]))
270 && i == PIC_OFFSET_TABLE_REGNUM
271 && (current_function_uses_pic_offset_table
272 || (TARGET_ID_SHARED_LIBRARY && ! current_function_is_leaf))))
273 return REG_P5 - i + 1;
277 /* Determine if we are going to save the frame pointer in the prologue. */
280 must_save_fp_p (void)
282 return frame_pointer_needed || regs_ever_live[REG_FP];
286 stack_frame_needed_p (void)
288 /* EH return puts a new return address into the frame using an
289 address relative to the frame pointer. */
290 if (current_function_calls_eh_return)
292 return frame_pointer_needed;
295 /* Emit code to save registers in the prologue. SAVEALL is nonzero if we
296 must save all registers; this is used for interrupt handlers.
297 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
298 this for an interrupt (or exception) handler. */
301 expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler)
303 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler);
304 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler);
305 int dregno = REG_R7 + 1 - ndregs;
306 int pregno = REG_P5 + 1 - npregs;
307 int total = ndregs + npregs;
314 val = GEN_INT (-total * 4);
315 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total + 2));
316 XVECEXP (pat, 0, 0) = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, val),
317 UNSPEC_PUSH_MULTIPLE);
318 XVECEXP (pat, 0, total + 1) = gen_rtx_SET (VOIDmode, spreg,
319 gen_rtx_PLUS (Pmode, spreg,
321 RTX_FRAME_RELATED_P (XVECEXP (pat, 0, total + 1)) = 1;
322 for (i = 0; i < total; i++)
324 rtx memref = gen_rtx_MEM (word_mode,
325 gen_rtx_PLUS (Pmode, spreg,
326 GEN_INT (- i * 4 - 4)));
330 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
336 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
340 XVECEXP (pat, 0, i + 1) = subpat;
341 RTX_FRAME_RELATED_P (subpat) = 1;
343 insn = emit_insn (pat);
344 RTX_FRAME_RELATED_P (insn) = 1;
347 /* Emit code to restore registers in the epilogue. SAVEALL is nonzero if we
348 must save all registers; this is used for interrupt handlers.
349 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
350 this for an interrupt (or exception) handler. */
353 expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler)
355 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler);
356 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler);
357 int total = ndregs + npregs;
364 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total + 1));
365 XVECEXP (pat, 0, 0) = gen_rtx_SET (VOIDmode, spreg,
366 gen_rtx_PLUS (Pmode, spreg,
367 GEN_INT (total * 4)));
374 for (i = 0; i < total; i++)
377 ? gen_rtx_PLUS (Pmode, spreg, GEN_INT (i * 4))
379 rtx memref = gen_rtx_MEM (word_mode, addr);
382 XVECEXP (pat, 0, i + 1)
383 = gen_rtx_SET (VOIDmode, gen_rtx_REG (word_mode, regno), memref);
392 insn = emit_insn (pat);
393 RTX_FRAME_RELATED_P (insn) = 1;
396 /* Perform any needed actions needed for a function that is receiving a
397 variable number of arguments.
401 MODE and TYPE are the mode and type of the current parameter.
403 PRETEND_SIZE is a variable that should be set to the amount of stack
404 that must be pushed by the prolog to pretend that our caller pushed
407 Normally, this macro will push all remaining incoming registers on the
408 stack and set PRETEND_SIZE to the length of the registers pushed.
411 - VDSP C compiler manual (our ABI) says that a variable args function
412 should save the R0, R1 and R2 registers in the stack.
413 - The caller will always leave space on the stack for the
414 arguments that are passed in registers, so we dont have
415 to leave any extra space.
416 - now, the vastart pointer can access all arguments from the stack. */
419 setup_incoming_varargs (CUMULATIVE_ARGS *cum,
420 enum machine_mode mode ATTRIBUTE_UNUSED,
421 tree type ATTRIBUTE_UNUSED, int *pretend_size,
430 /* The move for named arguments will be generated automatically by the
431 compiler. We need to generate the move rtx for the unnamed arguments
432 if they are in the first 3 words. We assume at least 1 named argument
433 exists, so we never generate [ARGP] = R0 here. */
435 for (i = cum->words + 1; i < max_arg_registers; i++)
437 mem = gen_rtx_MEM (Pmode,
438 plus_constant (arg_pointer_rtx, (i * UNITS_PER_WORD)));
439 emit_move_insn (mem, gen_rtx_REG (Pmode, i));
445 /* Value should be nonzero if functions must have frame pointers.
446 Zero means the frame pointer need not be set up (and parms may
447 be accessed via the stack pointer) in functions that seem suitable. */
450 bfin_frame_pointer_required (void)
452 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
454 if (fkind != SUBROUTINE)
457 /* We turn on -fomit-frame-pointer if -momit-leaf-frame-pointer is used,
458 so we have to override it for non-leaf functions. */
459 if (TARGET_OMIT_LEAF_FRAME_POINTER && ! current_function_is_leaf)
465 /* Return the number of registers pushed during the prologue. */
468 n_regs_saved_by_prologue (void)
470 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
471 bool is_inthandler = fkind != SUBROUTINE;
472 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
473 bool all = (lookup_attribute ("saveall", attrs) != NULL_TREE
474 || (is_inthandler && !current_function_is_leaf));
475 int ndregs = all ? 8 : n_dregs_to_save (is_inthandler);
476 int npregs = all ? 6 : n_pregs_to_save (is_inthandler);
477 int n = ndregs + npregs;
479 if (all || stack_frame_needed_p ())
480 /* We use a LINK instruction in this case. */
484 if (must_save_fp_p ())
486 if (! current_function_is_leaf)
490 if (fkind != SUBROUTINE)
494 /* Increment once for ASTAT. */
498 if (lookup_attribute ("nesting", attrs))
501 for (i = REG_P7 + 1; i < REG_CC; i++)
504 || (!leaf_function_p () && call_used_regs[i]))
505 n += i == REG_A0 || i == REG_A1 ? 2 : 1;
510 /* Return the offset between two registers, one to be eliminated, and the other
511 its replacement, at the start of a routine. */
514 bfin_initial_elimination_offset (int from, int to)
516 HOST_WIDE_INT offset = 0;
518 if (from == ARG_POINTER_REGNUM)
519 offset = n_regs_saved_by_prologue () * 4;
521 if (to == STACK_POINTER_REGNUM)
523 if (current_function_outgoing_args_size >= FIXED_STACK_AREA)
524 offset += current_function_outgoing_args_size;
525 else if (current_function_outgoing_args_size)
526 offset += FIXED_STACK_AREA;
528 offset += get_frame_size ();
534 /* Emit code to load a constant CONSTANT into register REG; setting
535 RTX_FRAME_RELATED_P on all insns we generate if RELATED is true.
536 Make sure that the insns we generate need not be split. */
539 frame_related_constant_load (rtx reg, HOST_WIDE_INT constant, bool related)
542 rtx cst = GEN_INT (constant);
544 if (constant >= -32768 && constant < 65536)
545 insn = emit_move_insn (reg, cst);
548 /* We don't call split_load_immediate here, since dwarf2out.c can get
549 confused about some of the more clever sequences it can generate. */
550 insn = emit_insn (gen_movsi_high (reg, cst));
552 RTX_FRAME_RELATED_P (insn) = 1;
553 insn = emit_insn (gen_movsi_low (reg, reg, cst));
556 RTX_FRAME_RELATED_P (insn) = 1;
559 /* Generate efficient code to add a value to the frame pointer. We
560 can use P1 as a scratch register. Set RTX_FRAME_RELATED_P on the
561 generated insns if FRAME is nonzero. */
564 add_to_sp (rtx spreg, HOST_WIDE_INT value, int frame)
569 /* Choose whether to use a sequence using a temporary register, or
570 a sequence with multiple adds. We can add a signed 7 bit value
571 in one instruction. */
572 if (value > 120 || value < -120)
574 rtx tmpreg = gen_rtx_REG (SImode, REG_P1);
578 frame_related_constant_load (tmpreg, value, TRUE);
581 insn = emit_move_insn (tmpreg, GEN_INT (value));
583 RTX_FRAME_RELATED_P (insn) = 1;
586 insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg));
588 RTX_FRAME_RELATED_P (insn) = 1;
599 /* We could use -62, but that would leave the stack unaligned, so
603 insn = emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (size)));
605 RTX_FRAME_RELATED_P (insn) = 1;
611 /* Generate a LINK insn for a frame sized FRAME_SIZE. If this constant
612 is too large, generate a sequence of insns that has the same effect.
613 SPREG contains (reg:SI REG_SP). */
616 emit_link_insn (rtx spreg, HOST_WIDE_INT frame_size)
618 HOST_WIDE_INT link_size = frame_size;
622 if (link_size > 262140)
625 /* Use a LINK insn with as big a constant as possible, then subtract
626 any remaining size from the SP. */
627 insn = emit_insn (gen_link (GEN_INT (-8 - link_size)));
628 RTX_FRAME_RELATED_P (insn) = 1;
630 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
632 rtx set = XVECEXP (PATTERN (insn), 0, i);
633 gcc_assert (GET_CODE (set) == SET);
634 RTX_FRAME_RELATED_P (set) = 1;
637 frame_size -= link_size;
641 /* Must use a call-clobbered PREG that isn't the static chain. */
642 rtx tmpreg = gen_rtx_REG (Pmode, REG_P1);
644 frame_related_constant_load (tmpreg, -frame_size, TRUE);
645 insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg));
646 RTX_FRAME_RELATED_P (insn) = 1;
650 /* Return the number of bytes we must reserve for outgoing arguments
651 in the current function's stack frame. */
656 if (current_function_outgoing_args_size)
658 if (current_function_outgoing_args_size >= FIXED_STACK_AREA)
659 return current_function_outgoing_args_size;
661 return FIXED_STACK_AREA;
666 /* Save RETS and FP, and allocate a stack frame. ALL is true if the
667 function must save all its registers (true only for certain interrupt
671 do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all)
673 frame_size += arg_area_size ();
675 if (all || stack_frame_needed_p ()
676 || (must_save_fp_p () && ! current_function_is_leaf))
677 emit_link_insn (spreg, frame_size);
680 if (! current_function_is_leaf)
682 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
683 gen_rtx_PRE_DEC (Pmode, spreg)),
685 rtx insn = emit_insn (pat);
686 RTX_FRAME_RELATED_P (insn) = 1;
688 if (must_save_fp_p ())
690 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
691 gen_rtx_PRE_DEC (Pmode, spreg)),
692 gen_rtx_REG (Pmode, REG_FP));
693 rtx insn = emit_insn (pat);
694 RTX_FRAME_RELATED_P (insn) = 1;
696 add_to_sp (spreg, -frame_size, 1);
700 /* Like do_link, but used for epilogues to deallocate the stack frame. */
703 do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all)
705 frame_size += arg_area_size ();
707 if (all || stack_frame_needed_p ())
708 emit_insn (gen_unlink ());
711 rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg));
713 add_to_sp (spreg, frame_size, 0);
714 if (must_save_fp_p ())
716 rtx fpreg = gen_rtx_REG (Pmode, REG_FP);
717 emit_move_insn (fpreg, postinc);
718 emit_insn (gen_rtx_USE (VOIDmode, fpreg));
720 if (! current_function_is_leaf)
722 emit_move_insn (bfin_rets_rtx, postinc);
723 emit_insn (gen_rtx_USE (VOIDmode, bfin_rets_rtx));
728 /* Generate a prologue suitable for a function of kind FKIND. This is
729 called for interrupt and exception handler prologues.
730 SPREG contains (reg:SI REG_SP). */
733 expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind)
736 HOST_WIDE_INT frame_size = get_frame_size ();
737 rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
738 rtx predec = gen_rtx_MEM (SImode, predec1);
740 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
741 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
742 tree kspisusp = lookup_attribute ("kspisusp", attrs);
746 insn = emit_move_insn (spreg, gen_rtx_REG (Pmode, REG_USP));
747 RTX_FRAME_RELATED_P (insn) = 1;
750 /* We need space on the stack in case we need to save the argument
752 if (fkind == EXCPT_HANDLER)
754 insn = emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (-12)));
755 RTX_FRAME_RELATED_P (insn) = 1;
758 insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
759 RTX_FRAME_RELATED_P (insn) = 1;
761 /* If we're calling other functions, they won't save their call-clobbered
762 registers, so we must save everything here. */
763 if (!current_function_is_leaf)
765 expand_prologue_reg_save (spreg, all, true);
767 for (i = REG_P7 + 1; i < REG_CC; i++)
770 || (!leaf_function_p () && call_used_regs[i]))
772 if (i == REG_A0 || i == REG_A1)
773 insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1),
774 gen_rtx_REG (PDImode, i));
776 insn = emit_move_insn (predec, gen_rtx_REG (SImode, i));
777 RTX_FRAME_RELATED_P (insn) = 1;
780 if (lookup_attribute ("nesting", attrs))
782 rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
783 : fkind == NMI_HANDLER ? REG_RETN
785 insn = emit_move_insn (predec, srcreg);
786 RTX_FRAME_RELATED_P (insn) = 1;
789 do_link (spreg, frame_size, all);
791 if (fkind == EXCPT_HANDLER)
793 rtx r0reg = gen_rtx_REG (SImode, REG_R0);
794 rtx r1reg = gen_rtx_REG (SImode, REG_R1);
795 rtx r2reg = gen_rtx_REG (SImode, REG_R2);
798 insn = emit_move_insn (r0reg, gen_rtx_REG (SImode, REG_SEQSTAT));
799 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
801 insn = emit_insn (gen_ashrsi3 (r0reg, r0reg, GEN_INT (26)));
802 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
804 insn = emit_insn (gen_ashlsi3 (r0reg, r0reg, GEN_INT (26)));
805 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
807 insn = emit_move_insn (r1reg, spreg);
808 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
810 insn = emit_move_insn (r2reg, gen_rtx_REG (Pmode, REG_FP));
811 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
813 insn = emit_insn (gen_addsi3 (r2reg, r2reg, GEN_INT (8)));
814 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
819 /* Generate an epilogue suitable for a function of kind FKIND. This is
820 called for interrupt and exception handler epilogues.
821 SPREG contains (reg:SI REG_SP). */
824 expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind)
827 rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
828 rtx postinc = gen_rtx_MEM (SImode, postinc1);
829 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
830 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
832 /* A slightly crude technique to stop flow from trying to delete "dead"
834 MEM_VOLATILE_P (postinc) = 1;
836 do_unlink (spreg, get_frame_size (), all);
838 if (lookup_attribute ("nesting", attrs))
840 rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
841 : fkind == NMI_HANDLER ? REG_RETN
843 emit_move_insn (srcreg, postinc);
846 /* If we're calling other functions, they won't save their call-clobbered
847 registers, so we must save (and restore) everything here. */
848 if (!current_function_is_leaf)
851 for (i = REG_CC - 1; i > REG_P7; i--)
854 || (!leaf_function_p () && call_used_regs[i]))
856 if (i == REG_A0 || i == REG_A1)
858 rtx mem = gen_rtx_MEM (PDImode, postinc1);
859 MEM_VOLATILE_P (mem) = 1;
860 emit_move_insn (gen_rtx_REG (PDImode, i), mem);
863 emit_move_insn (gen_rtx_REG (SImode, i), postinc);
866 expand_epilogue_reg_restore (spreg, all, true);
868 emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
870 /* Deallocate any space we left on the stack in case we needed to save the
871 argument registers. */
872 if (fkind == EXCPT_HANDLER)
873 emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (12)));
875 emit_jump_insn (gen_return_internal (GEN_INT (fkind)));
878 /* Used while emitting the prologue to generate code to load the correct value
879 into the PIC register, which is passed in DEST. */
882 bfin_load_pic_reg (rtx dest)
884 struct cgraph_local_info *i = NULL;
887 if (flag_unit_at_a_time)
888 i = cgraph_local_info (current_function_decl);
890 /* Functions local to the translation unit don't need to reload the
891 pic reg, since the caller always passes a usable one. */
893 return pic_offset_table_rtx;
895 if (bfin_lib_id_given)
896 addr = plus_constant (pic_offset_table_rtx, -4 - bfin_library_id * 4);
898 addr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
899 gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
900 UNSPEC_LIBRARY_OFFSET));
901 insn = emit_insn (gen_movsi (dest, gen_rtx_MEM (Pmode, addr)));
902 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
906 /* Generate RTL for the prologue of the current function. */
909 bfin_expand_prologue (void)
912 HOST_WIDE_INT frame_size = get_frame_size ();
913 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
914 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
915 rtx pic_reg_loaded = NULL_RTX;
917 if (fkind != SUBROUTINE)
919 expand_interrupt_handler_prologue (spreg, fkind);
923 if (current_function_limit_stack)
926 = bfin_initial_elimination_offset (ARG_POINTER_REGNUM,
927 STACK_POINTER_REGNUM);
928 rtx lim = stack_limit_rtx;
930 if (GET_CODE (lim) == SYMBOL_REF)
932 rtx p2reg = gen_rtx_REG (Pmode, REG_P2);
933 if (TARGET_ID_SHARED_LIBRARY)
935 rtx p1reg = gen_rtx_REG (Pmode, REG_P1);
937 pic_reg_loaded = bfin_load_pic_reg (p2reg);
938 val = legitimize_pic_address (stack_limit_rtx, p1reg,
940 emit_move_insn (p1reg, val);
941 frame_related_constant_load (p2reg, offset, FALSE);
942 emit_insn (gen_addsi3 (p2reg, p2reg, p1reg));
947 rtx limit = plus_constant (stack_limit_rtx, offset);
948 emit_move_insn (p2reg, limit);
952 emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim));
953 emit_insn (gen_trapifcc ());
955 expand_prologue_reg_save (spreg, 0, false);
957 do_link (spreg, frame_size, false);
959 if (TARGET_ID_SHARED_LIBRARY
960 && (current_function_uses_pic_offset_table
961 || !current_function_is_leaf))
962 bfin_load_pic_reg (pic_offset_table_rtx);
965 /* Generate RTL for the epilogue of the current function. NEED_RETURN is zero
966 if this is for a sibcall. EH_RETURN is nonzero if we're expanding an
967 eh_return pattern. */
970 bfin_expand_epilogue (int need_return, int eh_return)
972 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
973 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
975 if (fkind != SUBROUTINE)
977 expand_interrupt_handler_epilogue (spreg, fkind);
981 do_unlink (spreg, get_frame_size (), false);
983 expand_epilogue_reg_restore (spreg, false, false);
985 /* Omit the return insn if this is for a sibcall. */
990 emit_insn (gen_addsi3 (spreg, spreg, gen_rtx_REG (Pmode, REG_P2)));
992 emit_jump_insn (gen_return_internal (GEN_INT (SUBROUTINE)));
995 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
998 bfin_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
999 unsigned int new_reg)
1001 /* Interrupt functions can only use registers that have already been
1002 saved by the prologue, even if they would normally be
1005 if (funkind (TREE_TYPE (current_function_decl)) != SUBROUTINE
1006 && !regs_ever_live[new_reg])
1012 /* Return the value of the return address for the frame COUNT steps up
1013 from the current frame, after the prologue.
1014 We punt for everything but the current frame by returning const0_rtx. */
1017 bfin_return_addr_rtx (int count)
1022 return get_hard_reg_initial_val (Pmode, REG_RETS);
1025 /* Try machine-dependent ways of modifying an illegitimate address X
1026 to be legitimate. If we find one, return the new, valid address,
1027 otherwise return NULL_RTX.
1029 OLDX is the address as it was before break_out_memory_refs was called.
1030 In some cases it is useful to look at this to decide what needs to be done.
1032 MODE is the mode of the memory reference. */
1035 legitimize_address (rtx x ATTRIBUTE_UNUSED, rtx oldx ATTRIBUTE_UNUSED,
1036 enum machine_mode mode ATTRIBUTE_UNUSED)
1042 bfin_delegitimize_address (rtx orig_x)
1046 if (GET_CODE (x) != MEM)
1050 if (GET_CODE (x) == PLUS
1051 && GET_CODE (XEXP (x, 1)) == UNSPEC
1052 && XINT (XEXP (x, 1), 1) == UNSPEC_MOVE_PIC
1053 && GET_CODE (XEXP (x, 0)) == REG
1054 && REGNO (XEXP (x, 0)) == PIC_OFFSET_TABLE_REGNUM)
1055 return XVECEXP (XEXP (x, 1), 0, 0);
1060 /* This predicate is used to compute the length of a load/store insn.
1061 OP is a MEM rtx, we return nonzero if its addressing mode requires a
1062 32 bit instruction. */
1065 effective_address_32bit_p (rtx op, enum machine_mode mode)
1067 HOST_WIDE_INT offset;
1069 mode = GET_MODE (op);
1072 if (GET_CODE (op) != PLUS)
1074 gcc_assert (REG_P (op) || GET_CODE (op) == POST_INC
1075 || GET_CODE (op) == PRE_DEC || GET_CODE (op) == POST_DEC);
1079 offset = INTVAL (XEXP (op, 1));
1081 /* All byte loads use a 16 bit offset. */
1082 if (GET_MODE_SIZE (mode) == 1)
1085 if (GET_MODE_SIZE (mode) == 4)
1087 /* Frame pointer relative loads can use a negative offset, all others
1088 are restricted to a small positive one. */
1089 if (XEXP (op, 0) == frame_pointer_rtx)
1090 return offset < -128 || offset > 60;
1091 return offset < 0 || offset > 60;
1094 /* Must be HImode now. */
1095 return offset < 0 || offset > 30;
1098 /* Returns true if X is a memory reference using an I register. */
1100 bfin_dsp_memref_p (rtx x)
1105 if (GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_INC
1106 || GET_CODE (x) == POST_DEC || GET_CODE (x) == PRE_DEC)
1111 /* Return cost of the memory address ADDR.
1112 All addressing modes are equally cheap on the Blackfin. */
1115 bfin_address_cost (rtx addr ATTRIBUTE_UNUSED)
1120 /* Subroutine of print_operand; used to print a memory reference X to FILE. */
1123 print_address_operand (FILE *file, rtx x)
1125 switch (GET_CODE (x))
1128 output_address (XEXP (x, 0));
1129 fprintf (file, "+");
1130 output_address (XEXP (x, 1));
1134 fprintf (file, "--");
1135 output_address (XEXP (x, 0));
1138 output_address (XEXP (x, 0));
1139 fprintf (file, "++");
1142 output_address (XEXP (x, 0));
1143 fprintf (file, "--");
1147 gcc_assert (GET_CODE (x) != MEM);
1148 print_operand (file, x, 0);
1153 /* Adding intp DImode support by Tony
1159 print_operand (FILE *file, rtx x, char code)
1161 enum machine_mode mode = GET_MODE (x);
1166 switch (GET_CODE (x))
1169 fprintf (file, "e");
1172 fprintf (file, "ne");
1175 fprintf (file, "g");
1178 fprintf (file, "l");
1181 fprintf (file, "ge");
1184 fprintf (file, "le");
1187 fprintf (file, "g");
1190 fprintf (file, "l");
1193 fprintf (file, "ge");
1196 fprintf (file, "le");
1199 output_operand_lossage ("invalid %%j value");
1203 case 'J': /* reverse logic */
1204 switch (GET_CODE(x))
1207 fprintf (file, "ne");
1210 fprintf (file, "e");
1213 fprintf (file, "le");
1216 fprintf (file, "ge");
1219 fprintf (file, "l");
1222 fprintf (file, "g");
1225 fprintf (file, "le");
1228 fprintf (file, "ge");
1231 fprintf (file, "l");
1234 fprintf (file, "g");
1237 output_operand_lossage ("invalid %%J value");
1242 switch (GET_CODE (x))
1247 gcc_assert (REGNO (x) < 32);
1248 fprintf (file, "%s", short_reg_names[REGNO (x)]);
1249 /*fprintf (file, "\n%d\n ", REGNO (x));*/
1252 else if (code == 'd')
1254 gcc_assert (REGNO (x) < 32);
1255 fprintf (file, "%s", high_reg_names[REGNO (x)]);
1258 else if (code == 'w')
1260 gcc_assert (REGNO (x) == REG_A0 || REGNO (x) == REG_A1);
1261 fprintf (file, "%s.w", reg_names[REGNO (x)]);
1263 else if (code == 'x')
1265 gcc_assert (REGNO (x) == REG_A0 || REGNO (x) == REG_A1);
1266 fprintf (file, "%s.x", reg_names[REGNO (x)]);
1268 else if (code == 'D')
1270 fprintf (file, "%s", dregs_pair_names[REGNO (x)]);
1272 else if (code == 'H')
1274 gcc_assert (mode == DImode || mode == DFmode);
1275 gcc_assert (REG_P (x));
1276 fprintf (file, "%s", reg_names[REGNO (x) + 1]);
1278 else if (code == 'T')
1280 gcc_assert (D_REGNO_P (REGNO (x)));
1281 fprintf (file, "%s", byte_reg_names[REGNO (x)]);
1284 fprintf (file, "%s", reg_names[REGNO (x)]);
1290 print_address_operand (file, x);
1302 fputs ("(FU)", file);
1305 fputs ("(T)", file);
1308 fputs ("(TFU)", file);
1311 fputs ("(W32)", file);
1314 fputs ("(IS)", file);
1317 fputs ("(IU)", file);
1320 fputs ("(IH)", file);
1323 fputs ("(M)", file);
1326 fputs ("(ISS2)", file);
1329 fputs ("(S2RND)", file);
1336 else if (code == 'b')
1338 if (INTVAL (x) == 0)
1340 else if (INTVAL (x) == 1)
1346 /* Moves to half registers with d or h modifiers always use unsigned
1348 else if (code == 'd')
1349 x = GEN_INT ((INTVAL (x) >> 16) & 0xffff);
1350 else if (code == 'h')
1351 x = GEN_INT (INTVAL (x) & 0xffff);
1352 else if (code == 'X')
1353 x = GEN_INT (exact_log2 (0xffffffff & INTVAL (x)));
1354 else if (code == 'Y')
1355 x = GEN_INT (exact_log2 (0xffffffff & ~INTVAL (x)));
1356 else if (code == 'Z')
1357 /* Used for LINK insns. */
1358 x = GEN_INT (-8 - INTVAL (x));
1363 output_addr_const (file, x);
1367 output_operand_lossage ("invalid const_double operand");
1371 switch (XINT (x, 1))
1373 case UNSPEC_MOVE_PIC:
1374 output_addr_const (file, XVECEXP (x, 0, 0));
1375 fprintf (file, "@GOT");
1378 case UNSPEC_MOVE_FDPIC:
1379 output_addr_const (file, XVECEXP (x, 0, 0));
1380 fprintf (file, "@GOT17M4");
1383 case UNSPEC_FUNCDESC_GOT17M4:
1384 output_addr_const (file, XVECEXP (x, 0, 0));
1385 fprintf (file, "@FUNCDESC_GOT17M4");
1388 case UNSPEC_LIBRARY_OFFSET:
1389 fprintf (file, "_current_shared_library_p5_offset_");
1398 output_addr_const (file, x);
1403 /* Argument support functions. */
1405 /* Initialize a variable CUM of type CUMULATIVE_ARGS
1406 for a call to a function whose data type is FNTYPE.
1407 For a library call, FNTYPE is 0.
1408 VDSP C Compiler manual, our ABI says that
1409 first 3 words of arguments will use R0, R1 and R2.
1413 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
1414 rtx libname ATTRIBUTE_UNUSED)
1416 static CUMULATIVE_ARGS zero_cum;
1420 /* Set up the number of registers to use for passing arguments. */
1422 cum->nregs = max_arg_registers;
1423 cum->arg_regs = arg_regs;
1425 cum->call_cookie = CALL_NORMAL;
1426 /* Check for a longcall attribute. */
1427 if (fntype && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype)))
1428 cum->call_cookie |= CALL_SHORT;
1429 else if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)))
1430 cum->call_cookie |= CALL_LONG;
1435 /* Update the data in CUM to advance over an argument
1436 of mode MODE and data type TYPE.
1437 (TYPE is null for libcalls where that information may not be available.) */
1440 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1441 int named ATTRIBUTE_UNUSED)
1443 int count, bytes, words;
1445 bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1446 words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1448 cum->words += words;
1449 cum->nregs -= words;
1451 if (cum->nregs <= 0)
1454 cum->arg_regs = NULL;
1458 for (count = 1; count <= words; count++)
1465 /* Define where to put the arguments to a function.
1466 Value is zero to push the argument on the stack,
1467 or a hard register in which to store the argument.
1469 MODE is the argument's machine mode.
1470 TYPE is the data type of the argument (as a tree).
1471 This is null for libcalls where that information may
1473 CUM is a variable of type CUMULATIVE_ARGS which gives info about
1474 the preceding args and about the function being called.
1475 NAMED is nonzero if this argument is a named parameter
1476 (otherwise it is an extra parameter matching an ellipsis). */
1479 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1480 int named ATTRIBUTE_UNUSED)
1483 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1485 if (mode == VOIDmode)
1486 /* Compute operand 2 of the call insn. */
1487 return GEN_INT (cum->call_cookie);
1493 return gen_rtx_REG (mode, *(cum->arg_regs));
1498 /* For an arg passed partly in registers and partly in memory,
1499 this is the number of bytes passed in registers.
1500 For args passed entirely in registers or entirely in memory, zero.
1502 Refer VDSP C Compiler manual, our ABI.
1503 First 3 words are in registers. So, if a an argument is larger
1504 than the registers available, it will span the register and
1508 bfin_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1509 tree type ATTRIBUTE_UNUSED,
1510 bool named ATTRIBUTE_UNUSED)
1513 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1514 int bytes_left = cum->nregs * UNITS_PER_WORD;
1519 if (bytes_left == 0)
1521 if (bytes > bytes_left)
1526 /* Variable sized types are passed by reference. */
1529 bfin_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
1530 enum machine_mode mode ATTRIBUTE_UNUSED,
1531 tree type, bool named ATTRIBUTE_UNUSED)
1533 return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
1536 /* Decide whether a type should be returned in memory (true)
1537 or in a register (false). This is called by the macro
1538 RETURN_IN_MEMORY. */
1541 bfin_return_in_memory (tree type)
1543 int size = int_size_in_bytes (type);
1544 return size > 2 * UNITS_PER_WORD || size == -1;
1547 /* Register in which address to store a structure value
1548 is passed to a function. */
1550 bfin_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
1551 int incoming ATTRIBUTE_UNUSED)
1553 return gen_rtx_REG (Pmode, REG_P0);
1556 /* Return true when register may be used to pass function parameters. */
1559 function_arg_regno_p (int n)
1562 for (i = 0; arg_regs[i] != -1; i++)
1563 if (n == arg_regs[i])
1568 /* Returns 1 if OP contains a symbol reference */
1571 symbolic_reference_mentioned_p (rtx op)
1573 register const char *fmt;
1576 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
1579 fmt = GET_RTX_FORMAT (GET_CODE (op));
1580 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
1586 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
1587 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
1591 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
1598 /* Decide whether we can make a sibling call to a function. DECL is the
1599 declaration of the function being targeted by the call and EXP is the
1600 CALL_EXPR representing the call. */
1603 bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
1604 tree exp ATTRIBUTE_UNUSED)
1606 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1607 return fkind == SUBROUTINE;
1610 /* Emit RTL insns to initialize the variable parts of a trampoline at
1611 TRAMP. FNADDR is an RTX for the address of the function's pure
1612 code. CXT is an RTX for the static chain value for the function. */
1615 initialize_trampoline (tramp, fnaddr, cxt)
1616 rtx tramp, fnaddr, cxt;
1618 rtx t1 = copy_to_reg (fnaddr);
1619 rtx t2 = copy_to_reg (cxt);
1625 rtx a = memory_address (Pmode, plus_constant (tramp, 8));
1626 addr = memory_address (Pmode, tramp);
1627 emit_move_insn (gen_rtx_MEM (SImode, addr), a);
1631 addr = memory_address (Pmode, plus_constant (tramp, i + 2));
1632 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
1633 emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16)));
1634 addr = memory_address (Pmode, plus_constant (tramp, i + 6));
1635 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
1637 addr = memory_address (Pmode, plus_constant (tramp, i + 10));
1638 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
1639 emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16)));
1640 addr = memory_address (Pmode, plus_constant (tramp, i + 14));
1641 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
1644 /* Emit insns to move operands[1] into operands[0]. */
1647 emit_pic_move (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
1649 rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
1651 gcc_assert (!TARGET_FDPIC || !(reload_in_progress || reload_completed));
1652 if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
1653 operands[1] = force_reg (SImode, operands[1]);
1655 operands[1] = legitimize_pic_address (operands[1], temp,
1656 TARGET_FDPIC ? OUR_FDPIC_REG
1657 : pic_offset_table_rtx);
1660 /* Expand a move operation in mode MODE. The operands are in OPERANDS. */
1663 expand_move (rtx *operands, enum machine_mode mode)
1665 rtx op = operands[1];
1666 if ((TARGET_ID_SHARED_LIBRARY || TARGET_FDPIC)
1667 && SYMBOLIC_CONST (op))
1668 emit_pic_move (operands, mode);
1669 /* Don't generate memory->memory or constant->memory moves, go through a
1671 else if ((reload_in_progress | reload_completed) == 0
1672 && GET_CODE (operands[0]) == MEM
1673 && GET_CODE (operands[1]) != REG)
1674 operands[1] = force_reg (mode, operands[1]);
1677 /* Split one or more DImode RTL references into pairs of SImode
1678 references. The RTL can be REG, offsettable MEM, integer constant, or
1679 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
1680 split and "num" is its length. lo_half and hi_half are output arrays
1681 that parallel "operands". */
1684 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
1688 rtx op = operands[num];
1690 /* simplify_subreg refuse to split volatile memory addresses,
1691 but we still have to handle it. */
1692 if (GET_CODE (op) == MEM)
1694 lo_half[num] = adjust_address (op, SImode, 0);
1695 hi_half[num] = adjust_address (op, SImode, 4);
1699 lo_half[num] = simplify_gen_subreg (SImode, op,
1700 GET_MODE (op) == VOIDmode
1701 ? DImode : GET_MODE (op), 0);
1702 hi_half[num] = simplify_gen_subreg (SImode, op,
1703 GET_MODE (op) == VOIDmode
1704 ? DImode : GET_MODE (op), 4);
1710 bfin_longcall_p (rtx op, int call_cookie)
1712 gcc_assert (GET_CODE (op) == SYMBOL_REF);
1713 if (call_cookie & CALL_SHORT)
1715 if (call_cookie & CALL_LONG)
1717 if (TARGET_LONG_CALLS)
1722 /* Expand a call instruction. FNADDR is the call target, RETVAL the return value.
1723 COOKIE is a CONST_INT holding the call_cookie prepared init_cumulative_args.
1724 SIBCALL is nonzero if this is a sibling call. */
1727 bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
1729 rtx use = NULL, call;
1730 rtx callee = XEXP (fnaddr, 0);
1731 int nelts = 2 + !!sibcall;
1733 rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REGNO);
1736 /* In an untyped call, we can get NULL for operand 2. */
1737 if (cookie == NULL_RTX)
1738 cookie = const0_rtx;
1740 /* Static functions and indirect calls don't need the pic register. */
1741 if (!TARGET_FDPIC && flag_pic
1742 && GET_CODE (callee) == SYMBOL_REF
1743 && !SYMBOL_REF_LOCAL_P (callee))
1744 use_reg (&use, pic_offset_table_rtx);
1748 if (GET_CODE (callee) != SYMBOL_REF
1749 || bfin_longcall_p (callee, INTVAL (cookie)))
1752 if (! address_operand (addr, Pmode))
1753 addr = force_reg (Pmode, addr);
1755 fnaddr = gen_reg_rtx (SImode);
1756 emit_insn (gen_load_funcdescsi (fnaddr, addr));
1757 fnaddr = gen_rtx_MEM (Pmode, fnaddr);
1759 picreg = gen_reg_rtx (SImode);
1760 emit_insn (gen_load_funcdescsi (picreg,
1761 plus_constant (addr, 4)));
1766 else if ((!register_no_elim_operand (callee, Pmode)
1767 && GET_CODE (callee) != SYMBOL_REF)
1768 || (GET_CODE (callee) == SYMBOL_REF
1770 || bfin_longcall_p (callee, INTVAL (cookie)))))
1772 callee = copy_to_mode_reg (Pmode, callee);
1773 fnaddr = gen_rtx_MEM (Pmode, callee);
1775 call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
1778 call = gen_rtx_SET (VOIDmode, retval, call);
1780 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nelts));
1782 XVECEXP (pat, 0, n++) = call;
1784 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, picreg);
1785 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie);
1787 XVECEXP (pat, 0, n++) = gen_rtx_RETURN (VOIDmode);
1788 call = emit_call_insn (pat);
1790 CALL_INSN_FUNCTION_USAGE (call) = use;
1793 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
1796 hard_regno_mode_ok (int regno, enum machine_mode mode)
1798 /* Allow only dregs to store value of mode HI or QI */
1799 enum reg_class class = REGNO_REG_CLASS (regno);
1804 if (mode == V2HImode)
1805 return D_REGNO_P (regno);
1806 if (class == CCREGS)
1807 return mode == BImode;
1808 if (mode == PDImode || mode == V2PDImode)
1809 return regno == REG_A0 || regno == REG_A1;
1811 && TEST_HARD_REG_BIT (reg_class_contents[PROLOGUE_REGS], regno))
1814 return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno);
1817 /* Implements target hook vector_mode_supported_p. */
1820 bfin_vector_mode_supported_p (enum machine_mode mode)
1822 return mode == V2HImode;
1825 /* Return the cost of moving data from a register in class CLASS1 to
1826 one in class CLASS2. A cost of 2 is the default. */
1829 bfin_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
1830 enum reg_class class1, enum reg_class class2)
1832 /* These need secondary reloads, so they're more expensive. */
1833 if ((class1 == CCREGS && class2 != DREGS)
1834 || (class1 != DREGS && class2 == CCREGS))
1837 /* If optimizing for size, always prefer reg-reg over reg-memory moves. */
1841 /* There are some stalls involved when moving from a DREG to a different
1842 class reg, and using the value in one of the following instructions.
1843 Attempt to model this by slightly discouraging such moves. */
1844 if (class1 == DREGS && class2 != DREGS)
1850 /* Return the cost of moving data of mode M between a
1851 register and memory. A value of 2 is the default; this cost is
1852 relative to those in `REGISTER_MOVE_COST'.
1854 ??? In theory L1 memory has single-cycle latency. We should add a switch
1855 that tells the compiler whether we expect to use only L1 memory for the
1856 program; it'll make the costs more accurate. */
1859 bfin_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
1860 enum reg_class class,
1861 int in ATTRIBUTE_UNUSED)
1863 /* Make memory accesses slightly more expensive than any register-register
1864 move. Also, penalize non-DP registers, since they need secondary
1865 reloads to load and store. */
1866 if (! reg_class_subset_p (class, DPREGS))
1872 /* Inform reload about cases where moving X with a mode MODE to a register in
1873 CLASS requires an extra scratch register. Return the class needed for the
1874 scratch register. */
1876 static enum reg_class
1877 bfin_secondary_reload (bool in_p, rtx x, enum reg_class class,
1878 enum machine_mode mode, secondary_reload_info *sri)
1880 /* If we have HImode or QImode, we can only use DREGS as secondary registers;
1881 in most other cases we can also use PREGS. */
1882 enum reg_class default_class = GET_MODE_SIZE (mode) >= 4 ? DPREGS : DREGS;
1883 enum reg_class x_class = NO_REGS;
1884 enum rtx_code code = GET_CODE (x);
1887 x = SUBREG_REG (x), code = GET_CODE (x);
1890 int regno = REGNO (x);
1891 if (regno >= FIRST_PSEUDO_REGISTER)
1892 regno = reg_renumber[regno];
1897 x_class = REGNO_REG_CLASS (regno);
1900 /* We can be asked to reload (plus (FP) (large_constant)) into a DREG.
1901 This happens as a side effect of register elimination, and we need
1902 a scratch register to do it. */
1903 if (fp_plus_const_operand (x, mode))
1905 rtx op2 = XEXP (x, 1);
1906 int large_constant_p = ! CONST_7BIT_IMM_P (INTVAL (op2));
1908 if (class == PREGS || class == PREGS_CLOBBERED)
1910 /* If destination is a DREG, we can do this without a scratch register
1911 if the constant is valid for an add instruction. */
1912 if ((class == DREGS || class == DPREGS)
1913 && ! large_constant_p)
1915 /* Reloading to anything other than a DREG? Use a PREG scratch
1917 sri->icode = CODE_FOR_reload_insi;
1921 /* Data can usually be moved freely between registers of most classes.
1922 AREGS are an exception; they can only move to or from another register
1923 in AREGS or one in DREGS. They can also be assigned the constant 0. */
1924 if (x_class == AREGS)
1925 return class == DREGS || class == AREGS ? NO_REGS : DREGS;
1929 if (x != const0_rtx && x_class != DREGS)
1935 /* CCREGS can only be moved from/to DREGS. */
1936 if (class == CCREGS && x_class != DREGS)
1938 if (x_class == CCREGS && class != DREGS)
1941 /* All registers other than AREGS can load arbitrary constants. The only
1942 case that remains is MEM. */
1944 if (! reg_class_subset_p (class, default_class))
1945 return default_class;
1949 /* Implement TARGET_HANDLE_OPTION. */
1952 bfin_handle_option (size_t code, const char *arg, int value)
1956 case OPT_mshared_library_id_:
1957 if (value > MAX_LIBRARY_ID)
1958 error ("-mshared-library-id=%s is not between 0 and %d",
1959 arg, MAX_LIBRARY_ID);
1960 bfin_lib_id_given = 1;
1968 static struct machine_function *
1969 bfin_init_machine_status (void)
1971 struct machine_function *f;
1973 f = ggc_alloc_cleared (sizeof (struct machine_function));
1978 /* Implement the macro OVERRIDE_OPTIONS. */
1981 override_options (void)
1983 if (TARGET_OMIT_LEAF_FRAME_POINTER)
1984 flag_omit_frame_pointer = 1;
1986 /* Library identification */
1987 if (bfin_lib_id_given && ! TARGET_ID_SHARED_LIBRARY)
1988 error ("-mshared-library-id= specified without -mid-shared-library");
1990 if (TARGET_ID_SHARED_LIBRARY && flag_pic == 0)
1993 if (TARGET_ID_SHARED_LIBRARY && TARGET_FDPIC)
1994 error ("ID shared libraries and FD-PIC mode can't be used together.");
1996 /* There is no single unaligned SI op for PIC code. Sometimes we
1997 need to use ".4byte" and sometimes we need to use ".picptr".
1998 See bfin_assemble_integer for details. */
2000 targetm.asm_out.unaligned_op.si = 0;
2002 /* Silently turn off flag_pic if not doing FDPIC or ID shared libraries,
2003 since we don't support it and it'll just break. */
2004 if (flag_pic && !TARGET_FDPIC && !TARGET_ID_SHARED_LIBRARY)
2007 flag_schedule_insns = 0;
2009 init_machine_status = bfin_init_machine_status;
2012 /* Return the destination address of BRANCH.
2013 We need to use this instead of get_attr_length, because the
2014 cbranch_with_nops pattern conservatively sets its length to 6, and
2015 we still prefer to use shorter sequences. */
2018 branch_dest (rtx branch)
2022 rtx pat = PATTERN (branch);
2023 if (GET_CODE (pat) == PARALLEL)
2024 pat = XVECEXP (pat, 0, 0);
2025 dest = SET_SRC (pat);
2026 if (GET_CODE (dest) == IF_THEN_ELSE)
2027 dest = XEXP (dest, 1);
2028 dest = XEXP (dest, 0);
2029 dest_uid = INSN_UID (dest);
2030 return INSN_ADDRESSES (dest_uid);
2033 /* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates
2034 it's a branch that's predicted taken. */
2037 cbranch_predicted_taken_p (rtx insn)
2039 rtx x = find_reg_note (insn, REG_BR_PROB, 0);
2043 int pred_val = INTVAL (XEXP (x, 0));
2045 return pred_val >= REG_BR_PROB_BASE / 2;
2051 /* Templates for use by asm_conditional_branch. */
2053 static const char *ccbranch_templates[][3] = {
2054 { "if !cc jump %3;", "if cc jump 4 (bp); jump.s %3;", "if cc jump 6 (bp); jump.l %3;" },
2055 { "if cc jump %3;", "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" },
2056 { "if !cc jump %3 (bp);", "if cc jump 4; jump.s %3;", "if cc jump 6; jump.l %3;" },
2057 { "if cc jump %3 (bp);", "if !cc jump 4; jump.s %3;", "if !cc jump 6; jump.l %3;" },
2060 /* Output INSN, which is a conditional branch instruction with operands
2063 We deal with the various forms of conditional branches that can be generated
2064 by bfin_reorg to prevent the hardware from doing speculative loads, by
2065 - emitting a sufficient number of nops, if N_NOPS is nonzero, or
2066 - always emitting the branch as predicted taken, if PREDICT_TAKEN is true.
2067 Either of these is only necessary if the branch is short, otherwise the
2068 template we use ends in an unconditional jump which flushes the pipeline
2072 asm_conditional_branch (rtx insn, rtx *operands, int n_nops, int predict_taken)
2074 int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
2075 /* Note : offset for instructions like if cc jmp; jump.[sl] offset
2076 is to be taken from start of if cc rather than jump.
2077 Range for jump.s is (-4094, 4096) instead of (-4096, 4094)
2079 int len = (offset >= -1024 && offset <= 1022 ? 0
2080 : offset >= -4094 && offset <= 4096 ? 1
2082 int bp = predict_taken && len == 0 ? 1 : cbranch_predicted_taken_p (insn);
2083 int idx = (bp << 1) | (GET_CODE (operands[0]) == EQ ? BRF : BRT);
2084 output_asm_insn (ccbranch_templates[idx][len], operands);
2085 gcc_assert (n_nops == 0 || !bp);
2087 while (n_nops-- > 0)
2088 output_asm_insn ("nop;", NULL);
2091 /* Emit rtl for a comparison operation CMP in mode MODE. Operands have been
2092 stored in bfin_compare_op0 and bfin_compare_op1 already. */
2095 bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED)
2097 enum rtx_code code1, code2;
2098 rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1;
2099 rtx tem = bfin_cc_rtx;
2100 enum rtx_code code = GET_CODE (cmp);
2102 /* If we have a BImode input, then we already have a compare result, and
2103 do not need to emit another comparison. */
2104 if (GET_MODE (op0) == BImode)
2106 gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
2107 tem = op0, code2 = code;
2112 /* bfin has these conditions */
2122 code1 = reverse_condition (code);
2126 emit_insn (gen_rtx_SET (BImode, tem,
2127 gen_rtx_fmt_ee (code1, BImode, op0, op1)));
2130 return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode));
2133 /* Return nonzero iff C has exactly one bit set if it is interpreted
2134 as a 32 bit constant. */
2137 log2constp (unsigned HOST_WIDE_INT c)
2140 return c != 0 && (c & (c-1)) == 0;
2143 /* Returns the number of consecutive least significant zeros in the binary
2144 representation of *V.
2145 We modify *V to contain the original value arithmetically shifted right by
2146 the number of zeroes. */
2149 shiftr_zero (HOST_WIDE_INT *v)
2151 unsigned HOST_WIDE_INT tmp = *v;
2152 unsigned HOST_WIDE_INT sgn;
2158 sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1));
2159 while ((tmp & 0x1) == 0 && n <= 32)
2161 tmp = (tmp >> 1) | sgn;
2168 /* After reload, split the load of an immediate constant. OPERANDS are the
2169 operands of the movsi_insn pattern which we are splitting. We return
2170 nonzero if we emitted a sequence to load the constant, zero if we emitted
2171 nothing because we want to use the splitter's default sequence. */
2174 split_load_immediate (rtx operands[])
2176 HOST_WIDE_INT val = INTVAL (operands[1]);
2178 HOST_WIDE_INT shifted = val;
2179 HOST_WIDE_INT shifted_compl = ~val;
2180 int num_zero = shiftr_zero (&shifted);
2181 int num_compl_zero = shiftr_zero (&shifted_compl);
2182 unsigned int regno = REGNO (operands[0]);
2183 enum reg_class class1 = REGNO_REG_CLASS (regno);
2185 /* This case takes care of single-bit set/clear constants, which we could
2186 also implement with BITSET/BITCLR. */
2188 && shifted >= -32768 && shifted < 65536
2189 && (D_REGNO_P (regno)
2190 || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))
2192 emit_insn (gen_movsi (operands[0], GEN_INT (shifted)));
2193 emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));
2198 tmp |= -(tmp & 0x8000);
2200 /* If high word has one bit set or clear, try to use a bit operation. */
2201 if (D_REGNO_P (regno))
2203 if (log2constp (val & 0xFFFF0000))
2205 emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));
2206 emit_insn (gen_iorsi3 (operands[0], operands[0], GEN_INT (val & 0xFFFF0000)));
2209 else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)
2211 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2212 emit_insn (gen_andsi3 (operands[0], operands[0], GEN_INT (val | 0xFFFF)));
2216 if (D_REGNO_P (regno))
2218 if (CONST_7BIT_IMM_P (tmp))
2220 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2221 emit_insn (gen_movstricthi_high (operands[0], GEN_INT (val & -65536)));
2225 if ((val & 0xFFFF0000) == 0)
2227 emit_insn (gen_movsi (operands[0], const0_rtx));
2228 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2232 if ((val & 0xFFFF0000) == 0xFFFF0000)
2234 emit_insn (gen_movsi (operands[0], constm1_rtx));
2235 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2240 /* Need DREGs for the remaining case. */
2245 && num_compl_zero && CONST_7BIT_IMM_P (shifted_compl))
2247 /* If optimizing for size, generate a sequence that has more instructions
2249 emit_insn (gen_movsi (operands[0], GEN_INT (shifted_compl)));
2250 emit_insn (gen_ashlsi3 (operands[0], operands[0],
2251 GEN_INT (num_compl_zero)));
2252 emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
2258 /* Return true if the legitimate memory address for a memory operand of mode
2259 MODE. Return false if not. */
2262 bfin_valid_add (enum machine_mode mode, HOST_WIDE_INT value)
2264 unsigned HOST_WIDE_INT v = value > 0 ? value : -value;
2265 int sz = GET_MODE_SIZE (mode);
2266 int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2;
2267 /* The usual offsettable_memref machinery doesn't work so well for this
2268 port, so we deal with the problem here. */
2269 unsigned HOST_WIDE_INT mask = sz == 8 ? 0x7ffe : 0x7fff;
2270 return (v & ~(mask << shift)) == 0;
2274 bfin_valid_reg_p (unsigned int regno, int strict, enum machine_mode mode,
2275 enum rtx_code outer_code)
2278 return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH);
2280 return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH);
2284 bfin_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
2286 switch (GET_CODE (x)) {
2288 if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM))
2292 if (REG_P (XEXP (x, 0))
2293 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS)
2294 && ((GET_CODE (XEXP (x, 1)) == UNSPEC && mode == SImode)
2295 || (GET_CODE (XEXP (x, 1)) == CONST_INT
2296 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
2301 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2302 && REG_P (XEXP (x, 0))
2303 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC))
2306 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2307 && XEXP (x, 0) == stack_pointer_rtx
2308 && REG_P (XEXP (x, 0))
2309 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC))
2319 bfin_rtx_costs (rtx x, int code, int outer_code, int *total)
2321 int cost2 = COSTS_N_INSNS (1);
2326 if (outer_code == SET || outer_code == PLUS)
2327 *total = CONST_7BIT_IMM_P (INTVAL (x)) ? 0 : cost2;
2328 else if (outer_code == AND)
2329 *total = log2constp (~INTVAL (x)) ? 0 : cost2;
2330 else if (outer_code == LE || outer_code == LT || outer_code == EQ)
2331 *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
2332 else if (outer_code == LEU || outer_code == LTU)
2333 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
2334 else if (outer_code == MULT)
2335 *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
2336 else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
2338 else if (outer_code == ASHIFT || outer_code == ASHIFTRT
2339 || outer_code == LSHIFTRT)
2340 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
2341 else if (outer_code == IOR || outer_code == XOR)
2342 *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
2351 *total = COSTS_N_INSNS (2);
2355 if (GET_MODE (x) == Pmode)
2357 if (GET_CODE (XEXP (x, 0)) == MULT
2358 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
2360 HOST_WIDE_INT val = INTVAL (XEXP (XEXP (x, 0), 1));
2361 if (val == 2 || val == 4)
2364 *total += rtx_cost (XEXP (XEXP (x, 0), 0), outer_code);
2365 *total += rtx_cost (XEXP (x, 1), outer_code);
2377 if (GET_MODE (x) == DImode)
2384 if (GET_MODE (x) == DImode)
2389 if (GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD)
2390 *total = COSTS_N_INSNS (3);
2395 *total = COSTS_N_INSNS (32);
2400 if (outer_code == SET)
2410 bfin_internal_label (FILE *stream, const char *prefix, unsigned long num)
2412 fprintf (stream, "%s%s$%ld:\n", LOCAL_LABEL_PREFIX, prefix, num);
2415 /* Used for communication between {push,pop}_multiple_operation (which
2416 we use not only as a predicate) and the corresponding output functions. */
2417 static int first_preg_to_save, first_dreg_to_save;
2420 push_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2422 int lastdreg = 8, lastpreg = 6;
2425 first_preg_to_save = lastpreg;
2426 first_dreg_to_save = lastdreg;
2427 for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
2429 rtx t = XVECEXP (op, 0, i);
2433 if (GET_CODE (t) != SET)
2437 dest = SET_DEST (t);
2438 if (GET_CODE (dest) != MEM || ! REG_P (src))
2440 dest = XEXP (dest, 0);
2441 if (GET_CODE (dest) != PLUS
2442 || ! REG_P (XEXP (dest, 0))
2443 || REGNO (XEXP (dest, 0)) != REG_SP
2444 || GET_CODE (XEXP (dest, 1)) != CONST_INT
2445 || INTVAL (XEXP (dest, 1)) != -i * 4)
2448 regno = REGNO (src);
2451 if (D_REGNO_P (regno))
2454 first_dreg_to_save = lastdreg = regno - REG_R0;
2456 else if (regno >= REG_P0 && regno <= REG_P7)
2459 first_preg_to_save = lastpreg = regno - REG_P0;
2469 if (regno >= REG_P0 && regno <= REG_P7)
2472 first_preg_to_save = lastpreg = regno - REG_P0;
2474 else if (regno != REG_R0 + lastdreg + 1)
2479 else if (group == 2)
2481 if (regno != REG_P0 + lastpreg + 1)
2490 pop_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2492 int lastdreg = 8, lastpreg = 6;
2495 for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
2497 rtx t = XVECEXP (op, 0, i);
2501 if (GET_CODE (t) != SET)
2505 dest = SET_DEST (t);
2506 if (GET_CODE (src) != MEM || ! REG_P (dest))
2508 src = XEXP (src, 0);
2512 if (! REG_P (src) || REGNO (src) != REG_SP)
2515 else if (GET_CODE (src) != PLUS
2516 || ! REG_P (XEXP (src, 0))
2517 || REGNO (XEXP (src, 0)) != REG_SP
2518 || GET_CODE (XEXP (src, 1)) != CONST_INT
2519 || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
2522 regno = REGNO (dest);
2525 if (regno == REG_R7)
2530 else if (regno != REG_P0 + lastpreg - 1)
2535 else if (group == 1)
2537 if (regno != REG_R0 + lastdreg - 1)
2543 first_dreg_to_save = lastdreg;
2544 first_preg_to_save = lastpreg;
2548 /* Emit assembly code for one multi-register push described by INSN, with
2549 operands in OPERANDS. */
2552 output_push_multiple (rtx insn, rtx *operands)
2557 /* Validate the insn again, and compute first_[dp]reg_to_save. */
2558 ok = push_multiple_operation (PATTERN (insn), VOIDmode);
2561 if (first_dreg_to_save == 8)
2562 sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
2563 else if (first_preg_to_save == 6)
2564 sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
2566 sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
2567 first_dreg_to_save, first_preg_to_save);
2569 output_asm_insn (buf, operands);
2572 /* Emit assembly code for one multi-register pop described by INSN, with
2573 operands in OPERANDS. */
2576 output_pop_multiple (rtx insn, rtx *operands)
2581 /* Validate the insn again, and compute first_[dp]reg_to_save. */
2582 ok = pop_multiple_operation (PATTERN (insn), VOIDmode);
2585 if (first_dreg_to_save == 8)
2586 sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
2587 else if (first_preg_to_save == 6)
2588 sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
2590 sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
2591 first_dreg_to_save, first_preg_to_save);
2593 output_asm_insn (buf, operands);
2596 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE. */
2599 single_move_for_movmem (rtx dst, rtx src, enum machine_mode mode, HOST_WIDE_INT offset)
2601 rtx scratch = gen_reg_rtx (mode);
2604 srcmem = adjust_address_nv (src, mode, offset);
2605 dstmem = adjust_address_nv (dst, mode, offset);
2606 emit_move_insn (scratch, srcmem);
2607 emit_move_insn (dstmem, scratch);
2610 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
2611 alignment ALIGN_EXP. Return true if successful, false if we should fall
2612 back on a different method. */
2615 bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
2617 rtx srcreg, destreg, countreg;
2618 HOST_WIDE_INT align = 0;
2619 unsigned HOST_WIDE_INT count = 0;
2621 if (GET_CODE (align_exp) == CONST_INT)
2622 align = INTVAL (align_exp);
2623 if (GET_CODE (count_exp) == CONST_INT)
2625 count = INTVAL (count_exp);
2627 if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
2632 /* If optimizing for size, only do single copies inline. */
2635 if (count == 2 && align < 2)
2637 if (count == 4 && align < 4)
2639 if (count != 1 && count != 2 && count != 4)
2642 if (align < 2 && count != 1)
2645 destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
2646 if (destreg != XEXP (dst, 0))
2647 dst = replace_equiv_address_nv (dst, destreg);
2648 srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
2649 if (srcreg != XEXP (src, 0))
2650 src = replace_equiv_address_nv (src, srcreg);
2652 if (count != 0 && align >= 2)
2654 unsigned HOST_WIDE_INT offset = 0;
2658 if ((count & ~3) == 4)
2660 single_move_for_movmem (dst, src, SImode, offset);
2663 else if (count & ~3)
2665 HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
2666 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
2668 emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
2672 single_move_for_movmem (dst, src, HImode, offset);
2678 if ((count & ~1) == 2)
2680 single_move_for_movmem (dst, src, HImode, offset);
2683 else if (count & ~1)
2685 HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
2686 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
2688 emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
2693 single_move_for_movmem (dst, src, QImode, offset);
2702 bfin_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
2704 enum attr_type insn_type, dep_insn_type;
2705 int dep_insn_code_number;
2707 /* Anti and output dependencies have zero cost. */
2708 if (REG_NOTE_KIND (link) != 0)
2711 dep_insn_code_number = recog_memoized (dep_insn);
2713 /* If we can't recognize the insns, we can't really do anything. */
2714 if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
2717 insn_type = get_attr_type (insn);
2718 dep_insn_type = get_attr_type (dep_insn);
2720 if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)
2722 rtx pat = PATTERN (dep_insn);
2723 rtx dest = SET_DEST (pat);
2724 rtx src = SET_SRC (pat);
2725 if (! ADDRESS_REGNO_P (REGNO (dest)) || ! D_REGNO_P (REGNO (src)))
2727 return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);
2734 /* Increment the counter for the number of loop instructions in the
2735 current function. */
2738 bfin_hardware_loop (void)
2740 cfun->machine->has_hardware_loops++;
2743 /* Maximum loop nesting depth. */
2744 #define MAX_LOOP_DEPTH 2
2746 /* Maximum size of a loop. */
2747 #define MAX_LOOP_LENGTH 2042
2749 /* We need to keep a vector of loops */
2750 typedef struct loop_info *loop_info;
2751 DEF_VEC_P (loop_info);
2752 DEF_VEC_ALLOC_P (loop_info,heap);
2754 /* Information about a loop we have found (or are in the process of
2756 struct loop_info GTY (())
2758 /* loop number, for dumps */
2761 /* Predecessor block of the loop. This is the one that falls into
2762 the loop and contains the initialization instruction. */
2763 basic_block predecessor;
2765 /* First block in the loop. This is the one branched to by the loop_end
2769 /* Last block in the loop (the one with the loop_end insn). */
2772 /* The successor block of the loop. This is the one the loop_end insn
2774 basic_block successor;
2776 /* The last instruction in the tail. */
2779 /* The loop_end insn. */
2782 /* The iteration register. */
2785 /* The new initialization insn. */
2788 /* The new initialization instruction. */
2791 /* The new label placed at the beginning of the loop. */
2794 /* The new label placed at the end of the loop. */
2797 /* The length of the loop. */
2800 /* The nesting depth of the loop. Set to -1 for a bad loop. */
2803 /* True if we have visited this loop. */
2806 /* True if this loop body clobbers any of LC0, LT0, or LB0. */
2809 /* True if this loop body clobbers any of LC1, LT1, or LB1. */
2812 /* Next loop in the graph. */
2813 struct loop_info *next;
2815 /* Immediate outer loop of this loop. */
2816 struct loop_info *outer;
2818 /* Vector of blocks only within the loop, (excluding those within
2820 VEC (basic_block,heap) *blocks;
2822 /* Vector of inner loops within this loop */
2823 VEC (loop_info,heap) *loops;
2826 /* Information used during loop detection. */
2827 typedef struct loop_work GTY(())
2829 /* Basic block to be scanned. */
2832 /* Loop it will be within. */
2837 DEF_VEC_O (loop_work);
2838 DEF_VEC_ALLOC_O (loop_work,heap);
2841 bfin_dump_loops (loop_info loops)
2845 for (loop = loops; loop; loop = loop->next)
2851 fprintf (dump_file, ";; loop %d: ", loop->loop_no);
2852 fprintf (dump_file, "{head:%d, depth:%d}", loop->head->index, loop->depth);
2854 fprintf (dump_file, " blocks: [ ");
2855 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, b); ix++)
2856 fprintf (dump_file, "%d ", b->index);
2857 fprintf (dump_file, "] ");
2859 fprintf (dump_file, " inner loops: [ ");
2860 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, i); ix++)
2861 fprintf (dump_file, "%d ", i->loop_no);
2862 fprintf (dump_file, "]\n");
2864 fprintf (dump_file, "\n");
2867 /* Scan the blocks of LOOP (and its inferiors) looking for basic block
2868 BB. Return true, if we find it. */
2871 bfin_bb_in_loop (loop_info loop, basic_block bb)
2877 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, b); ix++)
2881 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, inner); ix++)
2882 if (bfin_bb_in_loop (inner, bb))
2888 /* Scan the blocks of LOOP (and its inferiors) looking for uses of
2889 REG. Return true, if we find any. Don't count the loop's loop_end
2890 insn if it matches LOOP_END. */
2893 bfin_scan_loop (loop_info loop, rtx reg, rtx loop_end)
2899 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
2903 for (insn = BB_HEAD (bb);
2904 insn != NEXT_INSN (BB_END (bb));
2905 insn = NEXT_INSN (insn))
2909 if (insn == loop_end)
2911 if (reg_mentioned_p (reg, PATTERN (insn)))
2915 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, inner); ix++)
2916 if (bfin_scan_loop (inner, reg, NULL_RTX))
2922 /* Optimize LOOP. */
2925 bfin_optimize_loop (loop_info loop)
2928 loop_info inner, outer;
2929 rtx insn, init_insn, last_insn, nop_insn;
2930 rtx loop_init, start_label, end_label;
2931 rtx reg_lc0, reg_lc1, reg_lt0, reg_lt1, reg_lb0, reg_lb1;
2933 rtx lc_reg, lt_reg, lb_reg;
2937 int inner_depth = 0;
2946 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, inner); ix++)
2948 if (inner->loop_no == loop->loop_no)
2951 bfin_optimize_loop (inner);
2953 if (inner->depth < 0 || inner->depth > MAX_LOOP_DEPTH)
2955 inner->outer = NULL;
2956 VEC_ordered_remove (loop_info, loop->loops, ix);
2959 if (inner_depth < inner->depth)
2960 inner_depth = inner->depth;
2962 loop->clobber_loop0 |= inner->clobber_loop0;
2963 loop->clobber_loop1 |= inner->clobber_loop1;
2966 if (loop->depth < 0)
2969 fprintf (dump_file, ";; loop %d bad when found\n", loop->loop_no);
2973 loop->depth = inner_depth + 1;
2974 if (loop->depth > MAX_LOOP_DEPTH)
2977 fprintf (dump_file, ";; loop %d too deep\n", loop->loop_no);
2981 /* Make sure we only have one entry point. */
2982 if (EDGE_COUNT (loop->head->preds) == 2)
2984 loop->predecessor = EDGE_PRED (loop->head, 0)->src;
2985 if (loop->predecessor == loop->tail)
2986 /* We wanted the other predecessor. */
2987 loop->predecessor = EDGE_PRED (loop->head, 1)->src;
2989 /* We can only place a loop insn on a fall through edge of a
2990 single exit block. */
2991 if (EDGE_COUNT (loop->predecessor->succs) != 1
2992 || !(EDGE_SUCC (loop->predecessor, 0)->flags & EDGE_FALLTHRU)
2993 /* If loop->predecessor is in loop, loop->head is not really
2994 the head of the loop. */
2995 || bfin_bb_in_loop (loop, loop->predecessor))
2996 loop->predecessor = NULL;
2999 if (loop->predecessor == NULL)
3002 fprintf (dump_file, ";; loop %d has bad predecessor\n", loop->loop_no);
3006 /* Get the loop iteration register. */
3007 iter_reg = loop->iter_reg;
3009 if (!DPREG_P (iter_reg))
3012 fprintf (dump_file, ";; loop %d iteration count NOT in PREG or DREG\n",
3017 /* Check if start_label appears before loop_end and calculate the
3018 offset between them. We calculate the length of instructions
3021 for (insn = loop->start_label;
3022 insn && insn != loop->loop_end;
3023 insn = NEXT_INSN (insn))
3025 if (JUMP_P (insn) && any_condjump_p (insn) && !optimize_size)
3027 if (TARGET_CSYNC_ANOMALY)
3029 else if (TARGET_SPECLD_ANOMALY)
3032 else if (LABEL_P (insn))
3034 if (TARGET_CSYNC_ANOMALY)
3039 length += get_attr_length (insn);
3045 fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
3050 loop->length = length;
3051 if (loop->length > MAX_LOOP_LENGTH)
3054 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
3058 /* Scan all the blocks to make sure they don't use iter_reg. */
3059 if (bfin_scan_loop (loop, iter_reg, loop->loop_end))
3062 fprintf (dump_file, ";; loop %d uses iterator\n", loop->loop_no);
3066 /* Scan all the insns to see if the loop body clobber
3067 any hardware loop registers. */
3069 reg_lc0 = gen_rtx_REG (SImode, REG_LC0);
3070 reg_lc1 = gen_rtx_REG (SImode, REG_LC1);
3071 reg_lt0 = gen_rtx_REG (SImode, REG_LT0);
3072 reg_lt1 = gen_rtx_REG (SImode, REG_LT1);
3073 reg_lb0 = gen_rtx_REG (SImode, REG_LB0);
3074 reg_lb1 = gen_rtx_REG (SImode, REG_LB1);
3076 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
3080 for (insn = BB_HEAD (bb);
3081 insn != NEXT_INSN (BB_END (bb));
3082 insn = NEXT_INSN (insn))
3087 if (reg_set_p (reg_lc0, insn)
3088 || reg_set_p (reg_lt0, insn)
3089 || reg_set_p (reg_lb0, insn))
3090 loop->clobber_loop0 = 1;
3092 if (reg_set_p (reg_lc1, insn)
3093 || reg_set_p (reg_lt1, insn)
3094 || reg_set_p (reg_lb1, insn))
3095 loop->clobber_loop1 |= 1;
3099 if ((loop->clobber_loop0 && loop->clobber_loop1)
3100 || (loop->depth == MAX_LOOP_DEPTH && loop->clobber_loop0))
3102 loop->depth = MAX_LOOP_DEPTH + 1;
3104 fprintf (dump_file, ";; loop %d no loop reg available\n",
3109 /* There should be an instruction before the loop_end instruction
3110 in the same basic block. And the instruction must not be
3112 - CONDITIONAL BRANCH
3116 - Returns (RTS, RTN, etc.) */
3119 last_insn = PREV_INSN (loop->loop_end);
3123 for (; last_insn != PREV_INSN (BB_HEAD (bb));
3124 last_insn = PREV_INSN (last_insn))
3125 if (INSN_P (last_insn))
3128 if (last_insn != PREV_INSN (BB_HEAD (bb)))
3131 if (single_pred_p (bb)
3132 && single_pred (bb) != ENTRY_BLOCK_PTR)
3134 bb = single_pred (bb);
3135 last_insn = BB_END (bb);
3140 last_insn = NULL_RTX;
3148 fprintf (dump_file, ";; loop %d has no last instruction\n",
3153 if (JUMP_P (last_insn))
3155 loop_info inner = bb->aux;
3157 && inner->outer == loop
3158 && inner->loop_end == last_insn
3159 && inner->depth == 1)
3160 /* This jump_insn is the exact loop_end of an inner loop
3161 and to be optimized away. So use the inner's last_insn. */
3162 last_insn = inner->last_insn;
3166 fprintf (dump_file, ";; loop %d has bad last instruction\n",
3171 else if (CALL_P (last_insn)
3172 || get_attr_type (last_insn) == TYPE_SYNC
3173 || recog_memoized (last_insn) == CODE_FOR_return_internal)
3176 fprintf (dump_file, ";; loop %d has bad last instruction\n",
3181 if (GET_CODE (PATTERN (last_insn)) == ASM_INPUT
3182 || asm_noperands (PATTERN (last_insn)) >= 0
3183 || get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI)
3185 nop_insn = emit_insn_after (gen_nop (), last_insn);
3186 last_insn = nop_insn;
3189 loop->last_insn = last_insn;
3191 /* The loop is good for replacement. */
3192 start_label = loop->start_label;
3193 end_label = gen_label_rtx ();
3194 iter_reg = loop->iter_reg;
3196 if (loop->depth == 1 && !loop->clobber_loop1)
3201 loop->clobber_loop1 = 1;
3208 loop->clobber_loop0 = 1;
3211 /* If iter_reg is a DREG, we need generate an instruction to load
3212 the loop count into LC register. */
3213 if (D_REGNO_P (REGNO (iter_reg)))
3215 init_insn = gen_movsi (lc_reg, iter_reg);
3216 loop_init = gen_lsetup_without_autoinit (lt_reg, start_label,
3220 else if (P_REGNO_P (REGNO (iter_reg)))
3222 init_insn = NULL_RTX;
3223 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
3230 loop->init = init_insn;
3231 loop->end_label = end_label;
3232 loop->loop_init = loop_init;
3236 fprintf (dump_file, ";; replacing loop %d initializer with\n",
3238 print_rtl_single (dump_file, loop->loop_init);
3239 fprintf (dump_file, ";; replacing loop %d terminator with\n",
3241 print_rtl_single (dump_file, loop->loop_end);
3246 if (loop->init != NULL_RTX)
3247 emit_insn (loop->init);
3248 emit_insn(loop->loop_init);
3249 emit_label (loop->start_label);
3254 emit_insn_after (seq, BB_END (loop->predecessor));
3255 delete_insn (loop->loop_end);
3257 /* Insert the loop end label before the last instruction of the loop. */
3258 emit_label_before (loop->end_label, loop->last_insn);
3265 fprintf (dump_file, ";; loop %d is bad\n", loop->loop_no);
3267 /* Mark this loop bad. */
3268 if (loop->depth <= MAX_LOOP_DEPTH)
3271 outer = loop->outer;
3273 /* Move all inner loops to loop's outer loop. */
3274 inner_num = VEC_length (loop_info, loop->loops);
3280 VEC_reserve (loop_info, heap, outer->loops, inner_num);
3282 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, l); ix++)
3286 VEC_quick_push (loop_info, outer->loops, l);
3289 VEC_free (loop_info, heap, loop->loops);
3292 /* Move all blocks to loop's outer loop. */
3293 bb_num = VEC_length (basic_block, loop->blocks);
3299 VEC_reserve (basic_block, heap, outer->blocks, bb_num);
3301 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, b); ix++)
3305 VEC_quick_push (basic_block, outer->blocks, b);
3308 VEC_free (basic_block, heap, loop->blocks);
3311 if (DPREG_P (loop->iter_reg))
3313 /* If loop->iter_reg is a DREG or PREG, we can split it here
3314 without scratch register. */
3317 emit_insn_before (gen_addsi3 (loop->iter_reg,
3322 emit_insn_before (gen_cmpsi (loop->iter_reg, const0_rtx),
3325 insn = emit_jump_insn_before (gen_bne (loop->start_label),
3328 JUMP_LABEL (insn) = loop->start_label;
3329 LABEL_NUSES (loop->start_label)++;
3330 delete_insn (loop->loop_end);
3335 bfin_reorg_loops (FILE *dump_file)
3338 loop_info loops = NULL;
3342 VEC (loop_work,heap) *works = VEC_alloc (loop_work,heap,20);
3347 /* Find all the possible loop tails. This means searching for every
3348 loop_end instruction. For each one found, create a loop_info
3349 structure and add the head block to the work list. */
3352 rtx tail = BB_END (bb);
3354 while (GET_CODE (tail) == NOTE)
3355 tail = PREV_INSN (tail);
3358 if (INSN_P (tail) && recog_memoized (tail) == CODE_FOR_loop_end)
3360 /* A possible loop end */
3362 loop = XNEW (struct loop_info);
3366 loop->head = BRANCH_EDGE (bb)->dest;
3367 loop->successor = FALLTHRU_EDGE (bb)->dest;
3368 loop->predecessor = NULL;
3369 loop->loop_end = tail;
3370 loop->last_insn = NULL_RTX;
3371 loop->iter_reg = SET_DEST (XVECEXP (PATTERN (tail), 0, 1));
3372 loop->depth = loop->length = 0;
3374 loop->clobber_loop0 = loop->clobber_loop1 = 0;
3375 loop->blocks = VEC_alloc (basic_block, heap, 20);
3376 VEC_quick_push (basic_block, loop->blocks, bb);
3379 loop->loop_no = nloops++;
3381 loop->init = loop->loop_init = NULL_RTX;
3382 loop->start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (tail), 0, 0)), 1), 0);
3383 loop->end_label = NULL_RTX;
3385 work = VEC_safe_push (loop_work, heap, works, NULL);
3386 work->block = loop->head;
3393 fprintf (dump_file, ";; potential loop %d ending at\n",
3395 print_rtl_single (dump_file, tail);
3400 /* Now find all the closed loops.
3401 until work list empty,
3402 if block's auxptr is set
3404 if block's loop's start != block
3407 append block's loop's fallthrough block to worklist
3408 increment this loop's depth
3409 else if block is exit block
3413 for each target of block
3415 while (VEC_iterate (loop_work, works, dwork++, work))
3419 if (bb == EXIT_BLOCK_PTR)
3420 /* We've reached the exit block. The loop must be bad. */
3424 /* We've not seen this block before. Add it to the loop's
3425 list and then add each successor to the work list. */
3427 VEC_safe_push (basic_block, heap, loop->blocks, bb);
3428 FOR_EACH_EDGE (e, ei, bb->succs)
3430 if (!VEC_space (loop_work, works, 1))
3434 VEC_block_remove (loop_work, works, 0, dwork);
3438 VEC_reserve (loop_work, heap, works, 1);
3440 work = VEC_quick_push (loop_work, works, NULL);
3441 work->block = EDGE_SUCC (bb, ei.index)->dest;
3445 else if (bb->aux != loop)
3447 /* We've seen this block in a different loop. If it's not
3448 the other loop's head, then this loop must be bad.
3449 Otherwise, the other loop might be a nested loop, so
3450 continue from that loop's successor. */
3451 loop_info other = bb->aux;
3453 if (other->head != bb)
3457 other->outer = loop;
3458 VEC_safe_push (loop_info, heap, loop->loops, other);
3459 work = VEC_safe_push (loop_work, heap, works, NULL);
3461 work->block = other->successor;
3465 VEC_free (loop_work, heap, works);
3469 fprintf (dump_file, ";; All loops found:\n\n");
3470 bfin_dump_loops (loops);
3473 /* Now apply the optimizations. */
3474 for (loop = loops; loop; loop = loop->next)
3475 bfin_optimize_loop (loop);
3479 fprintf (dump_file, ";; After hardware loops optimization:\n\n");
3480 bfin_dump_loops (loops);
3483 /* Free up the loop structures */
3488 VEC_free (loop_info, heap, loop->loops);
3489 VEC_free (basic_block, heap, loop->blocks);
3494 print_rtl (dump_file, get_insns ());
3498 /* We use the machine specific reorg pass for emitting CSYNC instructions
3499 after conditional branches as needed.
3501 The Blackfin is unusual in that a code sequence like
3504 may speculatively perform the load even if the condition isn't true. This
3505 happens for a branch that is predicted not taken, because the pipeline
3506 isn't flushed or stalled, so the early stages of the following instructions,
3507 which perform the memory reference, are allowed to execute before the
3508 jump condition is evaluated.
3509 Therefore, we must insert additional instructions in all places where this
3510 could lead to incorrect behavior. The manual recommends CSYNC, while
3511 VDSP seems to use NOPs (even though its corresponding compiler option is
3514 When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
3515 When optimizing for size, we turn the branch into a predicted taken one.
3516 This may be slower due to mispredicts, but saves code size. */
3521 rtx insn, last_condjump = NULL_RTX;
3522 int cycles_since_jump = INT_MAX;
3524 /* Doloop optimization */
3525 if (cfun->machine->has_hardware_loops)
3526 bfin_reorg_loops (dump_file);
3528 if (! TARGET_SPECLD_ANOMALY && ! TARGET_CSYNC_ANOMALY)
3531 /* First pass: find predicted-false branches; if something after them
3532 needs nops, insert them or change the branch to predict true. */
3533 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
3537 if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
3540 pat = PATTERN (insn);
3541 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
3542 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
3543 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
3548 if (any_condjump_p (insn)
3549 && ! cbranch_predicted_taken_p (insn))
3551 last_condjump = insn;
3552 cycles_since_jump = 0;
3555 cycles_since_jump = INT_MAX;
3557 else if (INSN_P (insn))
3559 enum attr_type type = get_attr_type (insn);
3560 int delay_needed = 0;
3561 if (cycles_since_jump < INT_MAX)
3562 cycles_since_jump++;
3564 if (type == TYPE_MCLD && TARGET_SPECLD_ANOMALY)
3566 rtx pat = single_set (insn);
3567 if (may_trap_p (SET_SRC (pat)))
3570 else if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
3573 if (delay_needed > cycles_since_jump)
3577 rtx *op = recog_data.operand;
3579 delay_needed -= cycles_since_jump;
3581 extract_insn (last_condjump);
3584 pat = gen_cbranch_predicted_taken (op[0], op[1], op[2],
3586 cycles_since_jump = INT_MAX;
3589 /* Do not adjust cycles_since_jump in this case, so that
3590 we'll increase the number of NOPs for a subsequent insn
3592 pat = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
3593 GEN_INT (delay_needed));
3594 PATTERN (last_condjump) = pat;
3595 INSN_CODE (last_condjump) = recog (pat, insn, &num_clobbers);
3599 /* Second pass: for predicted-true branches, see if anything at the
3600 branch destination needs extra nops. */
3601 if (! TARGET_CSYNC_ANOMALY)
3604 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
3607 && any_condjump_p (insn)
3608 && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken
3609 || cbranch_predicted_taken_p (insn)))
3611 rtx target = JUMP_LABEL (insn);
3613 cycles_since_jump = 0;
3614 for (; target && cycles_since_jump < 3; target = NEXT_INSN (target))
3618 if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
3621 pat = PATTERN (target);
3622 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
3623 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
3624 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
3627 if (INSN_P (target))
3629 enum attr_type type = get_attr_type (target);
3630 int delay_needed = 0;
3631 if (cycles_since_jump < INT_MAX)
3632 cycles_since_jump++;
3634 if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
3637 if (delay_needed > cycles_since_jump)
3639 rtx prev = prev_real_insn (label);
3640 delay_needed -= cycles_since_jump;
3642 fprintf (dump_file, "Adding %d nops after %d\n",
3643 delay_needed, INSN_UID (label));
3645 && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops)
3652 "Reducing nops on insn %d.\n",
3655 x = XVECEXP (x, 0, 1);
3656 v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed;
3657 XVECEXP (x, 0, 0) = GEN_INT (v);
3659 while (delay_needed-- > 0)
3660 emit_insn_after (gen_nop (), label);
3669 /* Handle interrupt_handler, exception_handler and nmi_handler function
3670 attributes; arguments as in struct attribute_spec.handler. */
3673 handle_int_attribute (tree *node, tree name,
3674 tree args ATTRIBUTE_UNUSED,
3675 int flags ATTRIBUTE_UNUSED,
3679 if (TREE_CODE (x) == FUNCTION_DECL)
3682 if (TREE_CODE (x) != FUNCTION_TYPE)
3684 warning (OPT_Wattributes, "%qs attribute only applies to functions",
3685 IDENTIFIER_POINTER (name));
3686 *no_add_attrs = true;
3688 else if (funkind (x) != SUBROUTINE)
3689 error ("multiple function type attributes specified");
3694 /* Return 0 if the attributes for two types are incompatible, 1 if they
3695 are compatible, and 2 if they are nearly compatible (which causes a
3696 warning to be generated). */
3699 bfin_comp_type_attributes (tree type1, tree type2)
3701 e_funkind kind1, kind2;
3703 if (TREE_CODE (type1) != FUNCTION_TYPE)
3706 kind1 = funkind (type1);
3707 kind2 = funkind (type2);
3712 /* Check for mismatched modifiers */
3713 if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
3714 != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
3717 if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
3718 != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
3721 if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
3722 != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
3725 if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1))
3726 != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2)))
3732 /* Handle a "longcall" or "shortcall" attribute; arguments as in
3733 struct attribute_spec.handler. */
3736 bfin_handle_longcall_attribute (tree *node, tree name,
3737 tree args ATTRIBUTE_UNUSED,
3738 int flags ATTRIBUTE_UNUSED,
3741 if (TREE_CODE (*node) != FUNCTION_TYPE
3742 && TREE_CODE (*node) != FIELD_DECL
3743 && TREE_CODE (*node) != TYPE_DECL)
3745 warning (OPT_Wattributes, "`%s' attribute only applies to functions",
3746 IDENTIFIER_POINTER (name));
3747 *no_add_attrs = true;
3750 if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0
3751 && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node)))
3752 || (strcmp (IDENTIFIER_POINTER (name), "shortcall") == 0
3753 && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node))))
3755 warning (OPT_Wattributes,
3756 "can't apply both longcall and shortcall attributes to the same function");
3757 *no_add_attrs = true;
3763 /* Table of valid machine attributes. */
3764 const struct attribute_spec bfin_attribute_table[] =
3766 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
3767 { "interrupt_handler", 0, 0, false, true, true, handle_int_attribute },
3768 { "exception_handler", 0, 0, false, true, true, handle_int_attribute },
3769 { "nmi_handler", 0, 0, false, true, true, handle_int_attribute },
3770 { "nesting", 0, 0, false, true, true, NULL },
3771 { "kspisusp", 0, 0, false, true, true, NULL },
3772 { "saveall", 0, 0, false, true, true, NULL },
3773 { "longcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
3774 { "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
3775 { NULL, 0, 0, false, false, false, NULL }
3778 /* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to
3779 tell the assembler to generate pointers to function descriptors in
3783 bfin_assemble_integer (rtx value, unsigned int size, int aligned_p)
3785 if (TARGET_FDPIC && size == UNITS_PER_WORD)
3787 if (GET_CODE (value) == SYMBOL_REF
3788 && SYMBOL_REF_FUNCTION_P (value))
3790 fputs ("\t.picptr\tfuncdesc(", asm_out_file);
3791 output_addr_const (asm_out_file, value);
3792 fputs (")\n", asm_out_file);
3797 /* We've set the unaligned SI op to NULL, so we always have to
3798 handle the unaligned case here. */
3799 assemble_integer_with_op ("\t.4byte\t", value);
3803 return default_assemble_integer (value, size, aligned_p);
3806 /* Output the assembler code for a thunk function. THUNK_DECL is the
3807 declaration for the thunk function itself, FUNCTION is the decl for
3808 the target function. DELTA is an immediate constant offset to be
3809 added to THIS. If VCALL_OFFSET is nonzero, the word at
3810 *(*this + vcall_offset) should be added to THIS. */
3813 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
3814 tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
3815 HOST_WIDE_INT vcall_offset, tree function)
3818 /* The this parameter is passed as the first argument. */
3819 rtx this = gen_rtx_REG (Pmode, REG_R0);
3821 /* Adjust the this parameter by a fixed constant. */
3825 if (delta >= -64 && delta <= 63)
3827 xops[0] = GEN_INT (delta);
3828 output_asm_insn ("%1 += %0;", xops);
3830 else if (delta >= -128 && delta < -64)
3832 xops[0] = GEN_INT (delta + 64);
3833 output_asm_insn ("%1 += -64; %1 += %0;", xops);
3835 else if (delta > 63 && delta <= 126)
3837 xops[0] = GEN_INT (delta - 63);
3838 output_asm_insn ("%1 += 63; %1 += %0;", xops);
3842 xops[0] = GEN_INT (delta);
3843 output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
3847 /* Adjust the this parameter by a value stored in the vtable. */
3850 rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
3851 rtx tmp = gen_rtx_REG (Pmode, REG_R2);
3855 output_asm_insn ("%2 = r0; %2 = [%2];", xops);
3857 /* Adjust the this parameter. */
3858 xops[0] = gen_rtx_MEM (Pmode, plus_constant (p2tmp, vcall_offset));
3859 if (!memory_operand (xops[0], Pmode))
3861 rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
3862 xops[0] = GEN_INT (vcall_offset);
3864 output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
3865 xops[0] = gen_rtx_MEM (Pmode, p2tmp);
3868 output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
3871 xops[0] = XEXP (DECL_RTL (function), 0);
3872 if (1 || !flag_pic || (*targetm.binds_local_p) (function))
3873 output_asm_insn ("jump.l\t%P0", xops);
3876 /* Codes for all the Blackfin builtins. */
3881 BFIN_BUILTIN_COMPOSE_2X16,
3882 BFIN_BUILTIN_EXTRACTLO,
3883 BFIN_BUILTIN_EXTRACTHI,
3885 BFIN_BUILTIN_SSADD_2X16,
3886 BFIN_BUILTIN_SSSUB_2X16,
3887 BFIN_BUILTIN_SSADDSUB_2X16,
3888 BFIN_BUILTIN_SSSUBADD_2X16,
3889 BFIN_BUILTIN_MULT_2X16,
3890 BFIN_BUILTIN_MULTR_2X16,
3891 BFIN_BUILTIN_NEG_2X16,
3892 BFIN_BUILTIN_ABS_2X16,
3893 BFIN_BUILTIN_MIN_2X16,
3894 BFIN_BUILTIN_MAX_2X16,
3896 BFIN_BUILTIN_SSADD_1X16,
3897 BFIN_BUILTIN_SSSUB_1X16,
3898 BFIN_BUILTIN_MULT_1X16,
3899 BFIN_BUILTIN_MULTR_1X16,
3900 BFIN_BUILTIN_NORM_1X16,
3901 BFIN_BUILTIN_NEG_1X16,
3902 BFIN_BUILTIN_ABS_1X16,
3903 BFIN_BUILTIN_MIN_1X16,
3904 BFIN_BUILTIN_MAX_1X16,
3906 BFIN_BUILTIN_DIFFHL_2X16,
3907 BFIN_BUILTIN_DIFFLH_2X16,
3909 BFIN_BUILTIN_SSADD_1X32,
3910 BFIN_BUILTIN_SSSUB_1X32,
3911 BFIN_BUILTIN_NORM_1X32,
3912 BFIN_BUILTIN_NEG_1X32,
3913 BFIN_BUILTIN_MIN_1X32,
3914 BFIN_BUILTIN_MAX_1X32,
3915 BFIN_BUILTIN_MULT_1X32,
3917 BFIN_BUILTIN_MULHISILL,
3918 BFIN_BUILTIN_MULHISILH,
3919 BFIN_BUILTIN_MULHISIHL,
3920 BFIN_BUILTIN_MULHISIHH,
3922 BFIN_BUILTIN_LSHIFT_1X16,
3923 BFIN_BUILTIN_LSHIFT_2X16,
3924 BFIN_BUILTIN_SSASHIFT_1X16,
3925 BFIN_BUILTIN_SSASHIFT_2X16,
3927 BFIN_BUILTIN_CPLX_MUL_16,
3928 BFIN_BUILTIN_CPLX_MAC_16,
3929 BFIN_BUILTIN_CPLX_MSU_16,
3934 #define def_builtin(NAME, TYPE, CODE) \
3936 lang_hooks.builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
3940 /* Set up all builtin functions for this target. */
3942 bfin_init_builtins (void)
3944 tree V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
3945 tree void_ftype_void
3946 = build_function_type (void_type_node, void_list_node);
3947 tree short_ftype_short
3948 = build_function_type_list (short_integer_type_node, short_integer_type_node,
3950 tree short_ftype_int_int
3951 = build_function_type_list (short_integer_type_node, integer_type_node,
3952 integer_type_node, NULL_TREE);
3953 tree int_ftype_int_int
3954 = build_function_type_list (integer_type_node, integer_type_node,
3955 integer_type_node, NULL_TREE);
3957 = build_function_type_list (integer_type_node, integer_type_node,
3959 tree short_ftype_int
3960 = build_function_type_list (short_integer_type_node, integer_type_node,
3962 tree int_ftype_v2hi_v2hi
3963 = build_function_type_list (integer_type_node, V2HI_type_node,
3964 V2HI_type_node, NULL_TREE);
3965 tree v2hi_ftype_v2hi_v2hi
3966 = build_function_type_list (V2HI_type_node, V2HI_type_node,
3967 V2HI_type_node, NULL_TREE);
3968 tree v2hi_ftype_v2hi_v2hi_v2hi
3969 = build_function_type_list (V2HI_type_node, V2HI_type_node,
3970 V2HI_type_node, V2HI_type_node, NULL_TREE);
3971 tree v2hi_ftype_int_int
3972 = build_function_type_list (V2HI_type_node, integer_type_node,
3973 integer_type_node, NULL_TREE);
3974 tree v2hi_ftype_v2hi_int
3975 = build_function_type_list (V2HI_type_node, V2HI_type_node,
3976 integer_type_node, NULL_TREE);
3977 tree int_ftype_short_short
3978 = build_function_type_list (integer_type_node, short_integer_type_node,
3979 short_integer_type_node, NULL_TREE);
3980 tree v2hi_ftype_v2hi
3981 = build_function_type_list (V2HI_type_node, V2HI_type_node, NULL_TREE);
3982 tree short_ftype_v2hi
3983 = build_function_type_list (short_integer_type_node, V2HI_type_node,
3986 /* Add the remaining MMX insns with somewhat more complicated types. */
3987 def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC);
3988 def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC);
3990 def_builtin ("__builtin_bfin_compose_2x16", v2hi_ftype_int_int,
3991 BFIN_BUILTIN_COMPOSE_2X16);
3992 def_builtin ("__builtin_bfin_extract_hi", short_ftype_v2hi,
3993 BFIN_BUILTIN_EXTRACTHI);
3994 def_builtin ("__builtin_bfin_extract_lo", short_ftype_v2hi,
3995 BFIN_BUILTIN_EXTRACTLO);
3997 def_builtin ("__builtin_bfin_min_fr2x16", v2hi_ftype_v2hi_v2hi,
3998 BFIN_BUILTIN_MIN_2X16);
3999 def_builtin ("__builtin_bfin_max_fr2x16", v2hi_ftype_v2hi_v2hi,
4000 BFIN_BUILTIN_MAX_2X16);
4002 def_builtin ("__builtin_bfin_add_fr2x16", v2hi_ftype_v2hi_v2hi,
4003 BFIN_BUILTIN_SSADD_2X16);
4004 def_builtin ("__builtin_bfin_sub_fr2x16", v2hi_ftype_v2hi_v2hi,
4005 BFIN_BUILTIN_SSSUB_2X16);
4006 def_builtin ("__builtin_bfin_dspaddsubsat", v2hi_ftype_v2hi_v2hi,
4007 BFIN_BUILTIN_SSADDSUB_2X16);
4008 def_builtin ("__builtin_bfin_dspsubaddsat", v2hi_ftype_v2hi_v2hi,
4009 BFIN_BUILTIN_SSSUBADD_2X16);
4010 def_builtin ("__builtin_bfin_mult_fr2x16", v2hi_ftype_v2hi_v2hi,
4011 BFIN_BUILTIN_MULT_2X16);
4012 def_builtin ("__builtin_bfin_multr_fr2x16", v2hi_ftype_v2hi_v2hi,
4013 BFIN_BUILTIN_MULTR_2X16);
4014 def_builtin ("__builtin_bfin_negate_fr2x16", v2hi_ftype_v2hi,
4015 BFIN_BUILTIN_NEG_2X16);
4016 def_builtin ("__builtin_bfin_abs_fr2x16", v2hi_ftype_v2hi,
4017 BFIN_BUILTIN_ABS_2X16);
4019 def_builtin ("__builtin_bfin_add_fr1x16", short_ftype_int_int,
4020 BFIN_BUILTIN_SSADD_1X16);
4021 def_builtin ("__builtin_bfin_sub_fr1x16", short_ftype_int_int,
4022 BFIN_BUILTIN_SSSUB_1X16);
4023 def_builtin ("__builtin_bfin_mult_fr1x16", short_ftype_int_int,
4024 BFIN_BUILTIN_MULT_1X16);
4025 def_builtin ("__builtin_bfin_multr_fr1x16", short_ftype_int_int,
4026 BFIN_BUILTIN_MULTR_1X16);
4027 def_builtin ("__builtin_bfin_negate_fr1x16", short_ftype_short,
4028 BFIN_BUILTIN_NEG_1X16);
4029 def_builtin ("__builtin_bfin_abs_fr1x16", short_ftype_short,
4030 BFIN_BUILTIN_ABS_1X16);
4031 def_builtin ("__builtin_bfin_norm_fr1x16", short_ftype_int,
4032 BFIN_BUILTIN_NORM_1X16);
4034 def_builtin ("__builtin_bfin_diff_hl_fr2x16", short_ftype_v2hi,
4035 BFIN_BUILTIN_DIFFHL_2X16);
4036 def_builtin ("__builtin_bfin_diff_lh_fr2x16", short_ftype_v2hi,
4037 BFIN_BUILTIN_DIFFLH_2X16);
4039 def_builtin ("__builtin_bfin_mulhisill", int_ftype_v2hi_v2hi,
4040 BFIN_BUILTIN_MULHISILL);
4041 def_builtin ("__builtin_bfin_mulhisihl", int_ftype_v2hi_v2hi,
4042 BFIN_BUILTIN_MULHISIHL);
4043 def_builtin ("__builtin_bfin_mulhisilh", int_ftype_v2hi_v2hi,
4044 BFIN_BUILTIN_MULHISILH);
4045 def_builtin ("__builtin_bfin_mulhisihh", int_ftype_v2hi_v2hi,
4046 BFIN_BUILTIN_MULHISIHH);
4048 def_builtin ("__builtin_bfin_add_fr1x32", int_ftype_int_int,
4049 BFIN_BUILTIN_SSADD_1X32);
4050 def_builtin ("__builtin_bfin_sub_fr1x32", int_ftype_int_int,
4051 BFIN_BUILTIN_SSSUB_1X32);
4052 def_builtin ("__builtin_bfin_negate_fr1x32", int_ftype_int,
4053 BFIN_BUILTIN_NEG_1X32);
4054 def_builtin ("__builtin_bfin_norm_fr1x32", short_ftype_int,
4055 BFIN_BUILTIN_NORM_1X32);
4056 def_builtin ("__builtin_bfin_mult_fr1x32", int_ftype_short_short,
4057 BFIN_BUILTIN_MULT_1X32);
4060 def_builtin ("__builtin_bfin_shl_fr1x16", short_ftype_int_int,
4061 BFIN_BUILTIN_SSASHIFT_1X16);
4062 def_builtin ("__builtin_bfin_shl_fr2x16", v2hi_ftype_v2hi_int,
4063 BFIN_BUILTIN_SSASHIFT_2X16);
4064 def_builtin ("__builtin_bfin_lshl_fr1x16", short_ftype_int_int,
4065 BFIN_BUILTIN_LSHIFT_1X16);
4066 def_builtin ("__builtin_bfin_lshl_fr2x16", v2hi_ftype_v2hi_int,
4067 BFIN_BUILTIN_LSHIFT_2X16);
4069 /* Complex numbers. */
4070 def_builtin ("__builtin_bfin_cmplx_mul", v2hi_ftype_v2hi_v2hi,
4071 BFIN_BUILTIN_CPLX_MUL_16);
4072 def_builtin ("__builtin_bfin_cmplx_mac", v2hi_ftype_v2hi_v2hi_v2hi,
4073 BFIN_BUILTIN_CPLX_MAC_16);
4074 def_builtin ("__builtin_bfin_cmplx_msu", v2hi_ftype_v2hi_v2hi_v2hi,
4075 BFIN_BUILTIN_CPLX_MSU_16);
4079 struct builtin_description
4081 const enum insn_code icode;
4082 const char *const name;
4083 const enum bfin_builtins code;
4087 static const struct builtin_description bdesc_2arg[] =
4089 { CODE_FOR_composev2hi, "__builtin_bfin_compose_2x16", BFIN_BUILTIN_COMPOSE_2X16, -1 },
4091 { CODE_FOR_ssashiftv2hi3, "__builtin_bfin_shl_fr2x16", BFIN_BUILTIN_SSASHIFT_2X16, -1 },
4092 { CODE_FOR_ssashifthi3, "__builtin_bfin_shl_fr1x16", BFIN_BUILTIN_SSASHIFT_1X16, -1 },
4093 { CODE_FOR_lshiftv2hi3, "__builtin_bfin_lshl_fr2x16", BFIN_BUILTIN_LSHIFT_2X16, -1 },
4094 { CODE_FOR_lshifthi3, "__builtin_bfin_lshl_fr1x16", BFIN_BUILTIN_LSHIFT_1X16, -1 },
4096 { CODE_FOR_sminhi3, "__builtin_bfin_min_fr1x16", BFIN_BUILTIN_MIN_1X16, -1 },
4097 { CODE_FOR_smaxhi3, "__builtin_bfin_max_fr1x16", BFIN_BUILTIN_MAX_1X16, -1 },
4098 { CODE_FOR_ssaddhi3, "__builtin_bfin_add_fr1x16", BFIN_BUILTIN_SSADD_1X16, -1 },
4099 { CODE_FOR_sssubhi3, "__builtin_bfin_sub_fr1x16", BFIN_BUILTIN_SSSUB_1X16, -1 },
4101 { CODE_FOR_sminsi3, "__builtin_bfin_min_fr1x32", BFIN_BUILTIN_MIN_1X32, -1 },
4102 { CODE_FOR_smaxsi3, "__builtin_bfin_max_fr1x32", BFIN_BUILTIN_MAX_1X32, -1 },
4103 { CODE_FOR_ssaddsi3, "__builtin_bfin_add_fr1x32", BFIN_BUILTIN_SSADD_1X32, -1 },
4104 { CODE_FOR_sssubsi3, "__builtin_bfin_sub_fr1x32", BFIN_BUILTIN_SSSUB_1X32, -1 },
4106 { CODE_FOR_sminv2hi3, "__builtin_bfin_min_fr2x16", BFIN_BUILTIN_MIN_2X16, -1 },
4107 { CODE_FOR_smaxv2hi3, "__builtin_bfin_max_fr2x16", BFIN_BUILTIN_MAX_2X16, -1 },
4108 { CODE_FOR_ssaddv2hi3, "__builtin_bfin_add_fr2x16", BFIN_BUILTIN_SSADD_2X16, -1 },
4109 { CODE_FOR_sssubv2hi3, "__builtin_bfin_sub_fr2x16", BFIN_BUILTIN_SSSUB_2X16, -1 },
4110 { CODE_FOR_ssaddsubv2hi3, "__builtin_bfin_dspaddsubsat", BFIN_BUILTIN_SSADDSUB_2X16, -1 },
4111 { CODE_FOR_sssubaddv2hi3, "__builtin_bfin_dspsubaddsat", BFIN_BUILTIN_SSSUBADD_2X16, -1 },
4113 { CODE_FOR_flag_mulhisi, "__builtin_bfin_mult_fr1x32", BFIN_BUILTIN_MULT_1X32, MACFLAG_NONE },
4114 { CODE_FOR_flag_mulhi, "__builtin_bfin_mult_fr1x16", BFIN_BUILTIN_MULT_1X16, MACFLAG_T },
4115 { CODE_FOR_flag_mulhi, "__builtin_bfin_multr_fr1x16", BFIN_BUILTIN_MULTR_1X16, MACFLAG_NONE },
4116 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_mult_fr2x16", BFIN_BUILTIN_MULT_2X16, MACFLAG_T },
4117 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_multr_fr2x16", BFIN_BUILTIN_MULTR_2X16, MACFLAG_NONE }
4120 static const struct builtin_description bdesc_1arg[] =
4122 { CODE_FOR_signbitshi2, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16, 0 },
4123 { CODE_FOR_ssneghi2, "__builtin_bfin_negate_fr1x16", BFIN_BUILTIN_NEG_1X16, 0 },
4124 { CODE_FOR_abshi2, "__builtin_bfin_abs_fr1x16", BFIN_BUILTIN_ABS_1X16, 0 },
4126 { CODE_FOR_signbitssi2, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32, 0 },
4127 { CODE_FOR_ssnegsi2, "__builtin_bfin_negate_fr1x32", BFIN_BUILTIN_NEG_1X32, 0 },
4129 { CODE_FOR_movv2hi_hi_low, "__builtin_bfin_extract_lo", BFIN_BUILTIN_EXTRACTLO, 0 },
4130 { CODE_FOR_movv2hi_hi_high, "__builtin_bfin_extract_hi", BFIN_BUILTIN_EXTRACTHI, 0 },
4131 { CODE_FOR_ssnegv2hi2, "__builtin_bfin_negate_fr2x16", BFIN_BUILTIN_NEG_2X16, 0 },
4132 { CODE_FOR_absv2hi2, "__builtin_bfin_abs_fr2x16", BFIN_BUILTIN_ABS_2X16, 0 }
4135 /* Errors in the source file can cause expand_expr to return const0_rtx
4136 where we expect a vector. To avoid crashing, use one of the vector
4137 clear instructions. */
4139 safe_vector_operand (rtx x, enum machine_mode mode)
4141 if (x != const0_rtx)
4143 x = gen_reg_rtx (SImode);
4145 emit_insn (gen_movsi (x, CONST0_RTX (SImode)));
4146 return gen_lowpart (mode, x);
4149 /* Subroutine of bfin_expand_builtin to take care of binop insns. MACFLAG is -1
4150 if this is a normal binary op, or one of the MACFLAG_xxx constants. */
4153 bfin_expand_binop_builtin (enum insn_code icode, tree arglist, rtx target,
4157 tree arg0 = TREE_VALUE (arglist);
4158 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
4159 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4160 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
4161 enum machine_mode op0mode = GET_MODE (op0);
4162 enum machine_mode op1mode = GET_MODE (op1);
4163 enum machine_mode tmode = insn_data[icode].operand[0].mode;
4164 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
4165 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
4167 if (VECTOR_MODE_P (mode0))
4168 op0 = safe_vector_operand (op0, mode0);
4169 if (VECTOR_MODE_P (mode1))
4170 op1 = safe_vector_operand (op1, mode1);
4173 || GET_MODE (target) != tmode
4174 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
4175 target = gen_reg_rtx (tmode);
4177 if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode)
4180 op0 = gen_lowpart (HImode, op0);
4182 if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode)
4185 op1 = gen_lowpart (HImode, op1);
4187 /* In case the insn wants input operands in modes different from
4188 the result, abort. */
4189 gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
4190 && (op1mode == mode1 || op1mode == VOIDmode));
4192 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
4193 op0 = copy_to_mode_reg (mode0, op0);
4194 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
4195 op1 = copy_to_mode_reg (mode1, op1);
4198 pat = GEN_FCN (icode) (target, op0, op1);
4200 pat = GEN_FCN (icode) (target, op0, op1, GEN_INT (macflag));
4208 /* Subroutine of bfin_expand_builtin to take care of unop insns. */
4211 bfin_expand_unop_builtin (enum insn_code icode, tree arglist,
4215 tree arg0 = TREE_VALUE (arglist);
4216 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4217 enum machine_mode op0mode = GET_MODE (op0);
4218 enum machine_mode tmode = insn_data[icode].operand[0].mode;
4219 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
4222 || GET_MODE (target) != tmode
4223 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
4224 target = gen_reg_rtx (tmode);
4226 if (VECTOR_MODE_P (mode0))
4227 op0 = safe_vector_operand (op0, mode0);
4229 if (op0mode == SImode && mode0 == HImode)
4232 op0 = gen_lowpart (HImode, op0);
4234 gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
4236 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
4237 op0 = copy_to_mode_reg (mode0, op0);
4239 pat = GEN_FCN (icode) (target, op0);
4246 /* Expand an expression EXP that calls a built-in function,
4247 with result going to TARGET if that's convenient
4248 (and in mode MODE if that's convenient).
4249 SUBTARGET may be used as the target for computing one of EXP's operands.
4250 IGNORE is nonzero if the value is to be ignored. */
4253 bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
4254 rtx subtarget ATTRIBUTE_UNUSED,
4255 enum machine_mode mode ATTRIBUTE_UNUSED,
4256 int ignore ATTRIBUTE_UNUSED)
4259 enum insn_code icode;
4260 const struct builtin_description *d;
4261 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
4262 tree arglist = TREE_OPERAND (exp, 1);
4263 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
4264 tree arg0, arg1, arg2;
4265 rtx op0, op1, op2, accvec, pat, tmp1, tmp2;
4266 enum machine_mode tmode, mode0;
4270 case BFIN_BUILTIN_CSYNC:
4271 emit_insn (gen_csync ());
4273 case BFIN_BUILTIN_SSYNC:
4274 emit_insn (gen_ssync ());
4277 case BFIN_BUILTIN_DIFFHL_2X16:
4278 case BFIN_BUILTIN_DIFFLH_2X16:
4279 arg0 = TREE_VALUE (arglist);
4280 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4281 icode = (fcode == BFIN_BUILTIN_DIFFHL_2X16
4282 ? CODE_FOR_subhilov2hi3 : CODE_FOR_sublohiv2hi3);
4283 tmode = insn_data[icode].operand[0].mode;
4284 mode0 = insn_data[icode].operand[1].mode;
4287 || GET_MODE (target) != tmode
4288 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
4289 target = gen_reg_rtx (tmode);
4291 if (VECTOR_MODE_P (mode0))
4292 op0 = safe_vector_operand (op0, mode0);
4294 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
4295 op0 = copy_to_mode_reg (mode0, op0);
4297 pat = GEN_FCN (icode) (target, op0, op0);
4303 case BFIN_BUILTIN_CPLX_MUL_16:
4304 arg0 = TREE_VALUE (arglist);
4305 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
4306 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4307 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
4308 accvec = gen_reg_rtx (V2PDImode);
4311 || GET_MODE (target) != V2HImode
4312 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
4313 target = gen_reg_rtx (tmode);
4314 if (! register_operand (op0, GET_MODE (op0)))
4315 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
4316 if (! register_operand (op1, GET_MODE (op1)))
4317 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
4319 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
4320 const0_rtx, const0_rtx,
4321 const1_rtx, GEN_INT (MACFLAG_NONE)));
4322 emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
4323 const1_rtx, const1_rtx,
4324 const0_rtx, accvec, const1_rtx, const0_rtx,
4325 GEN_INT (MACFLAG_NONE), accvec));
4329 case BFIN_BUILTIN_CPLX_MAC_16:
4330 case BFIN_BUILTIN_CPLX_MSU_16:
4331 arg0 = TREE_VALUE (arglist);
4332 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
4333 arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
4334 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4335 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
4336 op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
4337 accvec = gen_reg_rtx (V2PDImode);
4340 || GET_MODE (target) != V2HImode
4341 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
4342 target = gen_reg_rtx (tmode);
4343 if (! register_operand (op0, GET_MODE (op0)))
4344 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
4345 if (! register_operand (op1, GET_MODE (op1)))
4346 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
4348 tmp1 = gen_reg_rtx (SImode);
4349 tmp2 = gen_reg_rtx (SImode);
4350 emit_insn (gen_ashlsi3 (tmp1, gen_lowpart (SImode, op2), GEN_INT (16)));
4351 emit_move_insn (tmp2, gen_lowpart (SImode, op2));
4352 emit_insn (gen_movstricthi_1 (gen_lowpart (HImode, tmp2), const0_rtx));
4353 emit_insn (gen_load_accumulator_pair (accvec, tmp1, tmp2));
4354 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op0, op1, const0_rtx,
4355 const0_rtx, const0_rtx,
4356 const1_rtx, accvec, const0_rtx,
4358 GEN_INT (MACFLAG_W32)));
4359 tmp1 = (fcode == BFIN_BUILTIN_CPLX_MAC_16 ? const1_rtx : const0_rtx);
4360 tmp2 = (fcode == BFIN_BUILTIN_CPLX_MAC_16 ? const0_rtx : const1_rtx);
4361 emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
4362 const1_rtx, const1_rtx,
4363 const0_rtx, accvec, tmp1, tmp2,
4364 GEN_INT (MACFLAG_NONE), accvec));
4372 for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
4373 if (d->code == fcode)
4374 return bfin_expand_binop_builtin (d->icode, arglist, target,
4377 for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
4378 if (d->code == fcode)
4379 return bfin_expand_unop_builtin (d->icode, arglist, target);
4384 #undef TARGET_INIT_BUILTINS
4385 #define TARGET_INIT_BUILTINS bfin_init_builtins
4387 #undef TARGET_EXPAND_BUILTIN
4388 #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
4390 #undef TARGET_ASM_GLOBALIZE_LABEL
4391 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label
4393 #undef TARGET_ASM_FILE_START
4394 #define TARGET_ASM_FILE_START output_file_start
4396 #undef TARGET_ATTRIBUTE_TABLE
4397 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
4399 #undef TARGET_COMP_TYPE_ATTRIBUTES
4400 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
4402 #undef TARGET_RTX_COSTS
4403 #define TARGET_RTX_COSTS bfin_rtx_costs
4405 #undef TARGET_ADDRESS_COST
4406 #define TARGET_ADDRESS_COST bfin_address_cost
4408 #undef TARGET_ASM_INTERNAL_LABEL
4409 #define TARGET_ASM_INTERNAL_LABEL bfin_internal_label
4411 #undef TARGET_ASM_INTEGER
4412 #define TARGET_ASM_INTEGER bfin_assemble_integer
4414 #undef TARGET_MACHINE_DEPENDENT_REORG
4415 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
4417 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
4418 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
4420 #undef TARGET_ASM_OUTPUT_MI_THUNK
4421 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
4422 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
4423 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
4425 #undef TARGET_SCHED_ADJUST_COST
4426 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
4428 #undef TARGET_PROMOTE_PROTOTYPES
4429 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
4430 #undef TARGET_PROMOTE_FUNCTION_ARGS
4431 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
4432 #undef TARGET_PROMOTE_FUNCTION_RETURN
4433 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
4435 #undef TARGET_ARG_PARTIAL_BYTES
4436 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
4438 #undef TARGET_PASS_BY_REFERENCE
4439 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
4441 #undef TARGET_SETUP_INCOMING_VARARGS
4442 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
4444 #undef TARGET_STRUCT_VALUE_RTX
4445 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
4447 #undef TARGET_VECTOR_MODE_SUPPORTED_P
4448 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
4450 #undef TARGET_HANDLE_OPTION
4451 #define TARGET_HANDLE_OPTION bfin_handle_option
4453 #undef TARGET_DEFAULT_TARGET_FLAGS
4454 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
4456 #undef TARGET_SECONDARY_RELOAD
4457 #define TARGET_SECONDARY_RELOAD bfin_secondary_reload
4459 #undef TARGET_DELEGITIMIZE_ADDRESS
4460 #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address
4462 struct gcc_target targetm = TARGET_INITIALIZER;