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)
151 if (TARGET_ID_SHARED_LIBRARY)
152 unspec = UNSPEC_MOVE_PIC;
153 else if (GET_CODE (addr) == SYMBOL_REF
154 && SYMBOL_REF_FUNCTION_P (addr))
155 unspec = UNSPEC_FUNCDESC_GOT17M4;
157 unspec = UNSPEC_MOVE_FDPIC;
161 gcc_assert (!no_new_pseudos);
162 reg = gen_reg_rtx (Pmode);
165 tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), unspec);
166 new = gen_const_mem (Pmode, gen_rtx_PLUS (Pmode, picreg, tmp));
168 emit_move_insn (reg, new);
169 if (picreg == pic_offset_table_rtx)
170 current_function_uses_pic_offset_table = 1;
174 else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
178 if (GET_CODE (addr) == CONST)
180 addr = XEXP (addr, 0);
181 gcc_assert (GET_CODE (addr) == PLUS);
184 if (XEXP (addr, 0) == picreg)
189 gcc_assert (!no_new_pseudos);
190 reg = gen_reg_rtx (Pmode);
193 base = legitimize_pic_address (XEXP (addr, 0), reg, picreg);
194 addr = legitimize_pic_address (XEXP (addr, 1),
195 base == reg ? NULL_RTX : reg,
198 if (GET_CODE (addr) == CONST_INT)
200 gcc_assert (! reload_in_progress && ! reload_completed);
201 addr = force_reg (Pmode, addr);
204 if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
206 base = gen_rtx_PLUS (Pmode, base, XEXP (addr, 0));
207 addr = XEXP (addr, 1);
210 return gen_rtx_PLUS (Pmode, base, addr);
216 /* Stack frame layout. */
218 /* Compute the number of DREGS to save with a push_multiple operation.
219 This could include registers that aren't modified in the function,
220 since push_multiple only takes a range of registers.
221 If IS_INTHANDLER, then everything that is live must be saved, even
222 if normally call-clobbered. */
225 n_dregs_to_save (bool is_inthandler)
229 for (i = REG_R0; i <= REG_R7; i++)
231 if (regs_ever_live[i] && (is_inthandler || ! call_used_regs[i]))
232 return REG_R7 - i + 1;
234 if (current_function_calls_eh_return)
239 unsigned test = EH_RETURN_DATA_REGNO (j);
240 if (test == INVALID_REGNUM)
243 return REG_R7 - i + 1;
251 /* Like n_dregs_to_save, but compute number of PREGS to save. */
254 n_pregs_to_save (bool is_inthandler)
258 for (i = REG_P0; i <= REG_P5; i++)
259 if ((regs_ever_live[i] && (is_inthandler || ! call_used_regs[i]))
261 && i == PIC_OFFSET_TABLE_REGNUM
262 && (current_function_uses_pic_offset_table
263 || (TARGET_ID_SHARED_LIBRARY && ! current_function_is_leaf))))
264 return REG_P5 - i + 1;
268 /* Determine if we are going to save the frame pointer in the prologue. */
271 must_save_fp_p (void)
273 return frame_pointer_needed || regs_ever_live[REG_FP];
277 stack_frame_needed_p (void)
279 /* EH return puts a new return address into the frame using an
280 address relative to the frame pointer. */
281 if (current_function_calls_eh_return)
283 return frame_pointer_needed;
286 /* Emit code to save registers in the prologue. SAVEALL is nonzero if we
287 must save all registers; this is used for interrupt handlers.
288 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
289 this for an interrupt (or exception) handler. */
292 expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler)
294 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler);
295 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler);
296 int dregno = REG_R7 + 1 - ndregs;
297 int pregno = REG_P5 + 1 - npregs;
298 int total = ndregs + npregs;
305 val = GEN_INT (-total * 4);
306 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total + 2));
307 XVECEXP (pat, 0, 0) = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, val),
308 UNSPEC_PUSH_MULTIPLE);
309 XVECEXP (pat, 0, total + 1) = gen_rtx_SET (VOIDmode, spreg,
310 gen_rtx_PLUS (Pmode, spreg,
312 RTX_FRAME_RELATED_P (XVECEXP (pat, 0, total + 1)) = 1;
313 for (i = 0; i < total; i++)
315 rtx memref = gen_rtx_MEM (word_mode,
316 gen_rtx_PLUS (Pmode, spreg,
317 GEN_INT (- i * 4 - 4)));
321 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
327 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
331 XVECEXP (pat, 0, i + 1) = subpat;
332 RTX_FRAME_RELATED_P (subpat) = 1;
334 insn = emit_insn (pat);
335 RTX_FRAME_RELATED_P (insn) = 1;
338 /* Emit code to restore registers in the epilogue. SAVEALL is nonzero if we
339 must save all registers; this is used for interrupt handlers.
340 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
341 this for an interrupt (or exception) handler. */
344 expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler)
346 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler);
347 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler);
348 int total = ndregs + npregs;
355 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total + 1));
356 XVECEXP (pat, 0, 0) = gen_rtx_SET (VOIDmode, spreg,
357 gen_rtx_PLUS (Pmode, spreg,
358 GEN_INT (total * 4)));
365 for (i = 0; i < total; i++)
368 ? gen_rtx_PLUS (Pmode, spreg, GEN_INT (i * 4))
370 rtx memref = gen_rtx_MEM (word_mode, addr);
373 XVECEXP (pat, 0, i + 1)
374 = gen_rtx_SET (VOIDmode, gen_rtx_REG (word_mode, regno), memref);
383 insn = emit_insn (pat);
384 RTX_FRAME_RELATED_P (insn) = 1;
387 /* Perform any needed actions needed for a function that is receiving a
388 variable number of arguments.
392 MODE and TYPE are the mode and type of the current parameter.
394 PRETEND_SIZE is a variable that should be set to the amount of stack
395 that must be pushed by the prolog to pretend that our caller pushed
398 Normally, this macro will push all remaining incoming registers on the
399 stack and set PRETEND_SIZE to the length of the registers pushed.
402 - VDSP C compiler manual (our ABI) says that a variable args function
403 should save the R0, R1 and R2 registers in the stack.
404 - The caller will always leave space on the stack for the
405 arguments that are passed in registers, so we dont have
406 to leave any extra space.
407 - now, the vastart pointer can access all arguments from the stack. */
410 setup_incoming_varargs (CUMULATIVE_ARGS *cum,
411 enum machine_mode mode ATTRIBUTE_UNUSED,
412 tree type ATTRIBUTE_UNUSED, int *pretend_size,
421 /* The move for named arguments will be generated automatically by the
422 compiler. We need to generate the move rtx for the unnamed arguments
423 if they are in the first 3 words. We assume at least 1 named argument
424 exists, so we never generate [ARGP] = R0 here. */
426 for (i = cum->words + 1; i < max_arg_registers; i++)
428 mem = gen_rtx_MEM (Pmode,
429 plus_constant (arg_pointer_rtx, (i * UNITS_PER_WORD)));
430 emit_move_insn (mem, gen_rtx_REG (Pmode, i));
436 /* Value should be nonzero if functions must have frame pointers.
437 Zero means the frame pointer need not be set up (and parms may
438 be accessed via the stack pointer) in functions that seem suitable. */
441 bfin_frame_pointer_required (void)
443 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
445 if (fkind != SUBROUTINE)
448 /* We turn on -fomit-frame-pointer if -momit-leaf-frame-pointer is used,
449 so we have to override it for non-leaf functions. */
450 if (TARGET_OMIT_LEAF_FRAME_POINTER && ! current_function_is_leaf)
456 /* Return the number of registers pushed during the prologue. */
459 n_regs_saved_by_prologue (void)
461 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
462 bool is_inthandler = fkind != SUBROUTINE;
463 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
464 bool all = (lookup_attribute ("saveall", attrs) != NULL_TREE
465 || (is_inthandler && !current_function_is_leaf));
466 int ndregs = all ? 8 : n_dregs_to_save (is_inthandler);
467 int npregs = all ? 6 : n_pregs_to_save (is_inthandler);
468 int n = ndregs + npregs;
470 if (all || stack_frame_needed_p ())
471 /* We use a LINK instruction in this case. */
475 if (must_save_fp_p ())
477 if (! current_function_is_leaf)
481 if (fkind != SUBROUTINE)
485 /* Increment once for ASTAT. */
489 if (lookup_attribute ("nesting", attrs))
492 for (i = REG_P7 + 1; i < REG_CC; i++)
495 || (!leaf_function_p () && call_used_regs[i]))
496 n += i == REG_A0 || i == REG_A1 ? 2 : 1;
501 /* Return the offset between two registers, one to be eliminated, and the other
502 its replacement, at the start of a routine. */
505 bfin_initial_elimination_offset (int from, int to)
507 HOST_WIDE_INT offset = 0;
509 if (from == ARG_POINTER_REGNUM)
510 offset = n_regs_saved_by_prologue () * 4;
512 if (to == STACK_POINTER_REGNUM)
514 if (current_function_outgoing_args_size >= FIXED_STACK_AREA)
515 offset += current_function_outgoing_args_size;
516 else if (current_function_outgoing_args_size)
517 offset += FIXED_STACK_AREA;
519 offset += get_frame_size ();
525 /* Emit code to load a constant CONSTANT into register REG; setting
526 RTX_FRAME_RELATED_P on all insns we generate if RELATED is true.
527 Make sure that the insns we generate need not be split. */
530 frame_related_constant_load (rtx reg, HOST_WIDE_INT constant, bool related)
533 rtx cst = GEN_INT (constant);
535 if (constant >= -32768 && constant < 65536)
536 insn = emit_move_insn (reg, cst);
539 /* We don't call split_load_immediate here, since dwarf2out.c can get
540 confused about some of the more clever sequences it can generate. */
541 insn = emit_insn (gen_movsi_high (reg, cst));
543 RTX_FRAME_RELATED_P (insn) = 1;
544 insn = emit_insn (gen_movsi_low (reg, reg, cst));
547 RTX_FRAME_RELATED_P (insn) = 1;
550 /* Generate efficient code to add a value to a P register. We can use
551 P1 as a scratch register. Set RTX_FRAME_RELATED_P on the generated
552 insns if FRAME is nonzero. */
555 add_to_reg (rtx reg, HOST_WIDE_INT value, int frame)
560 /* Choose whether to use a sequence using a temporary register, or
561 a sequence with multiple adds. We can add a signed 7 bit value
562 in one instruction. */
563 if (value > 120 || value < -120)
565 rtx tmpreg = gen_rtx_REG (SImode, REG_P1);
569 frame_related_constant_load (tmpreg, value, TRUE);
571 insn = emit_move_insn (tmpreg, GEN_INT (value));
573 insn = emit_insn (gen_addsi3 (reg, reg, tmpreg));
575 RTX_FRAME_RELATED_P (insn) = 1;
586 /* We could use -62, but that would leave the stack unaligned, so
590 insn = emit_insn (gen_addsi3 (reg, reg, GEN_INT (size)));
592 RTX_FRAME_RELATED_P (insn) = 1;
598 /* Generate a LINK insn for a frame sized FRAME_SIZE. If this constant
599 is too large, generate a sequence of insns that has the same effect.
600 SPREG contains (reg:SI REG_SP). */
603 emit_link_insn (rtx spreg, HOST_WIDE_INT frame_size)
605 HOST_WIDE_INT link_size = frame_size;
609 if (link_size > 262140)
612 /* Use a LINK insn with as big a constant as possible, then subtract
613 any remaining size from the SP. */
614 insn = emit_insn (gen_link (GEN_INT (-8 - link_size)));
615 RTX_FRAME_RELATED_P (insn) = 1;
617 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
619 rtx set = XVECEXP (PATTERN (insn), 0, i);
620 gcc_assert (GET_CODE (set) == SET);
621 RTX_FRAME_RELATED_P (set) = 1;
624 frame_size -= link_size;
628 /* Must use a call-clobbered PREG that isn't the static chain. */
629 rtx tmpreg = gen_rtx_REG (Pmode, REG_P1);
631 frame_related_constant_load (tmpreg, -frame_size, TRUE);
632 insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg));
633 RTX_FRAME_RELATED_P (insn) = 1;
637 /* Return the number of bytes we must reserve for outgoing arguments
638 in the current function's stack frame. */
643 if (current_function_outgoing_args_size)
645 if (current_function_outgoing_args_size >= FIXED_STACK_AREA)
646 return current_function_outgoing_args_size;
648 return FIXED_STACK_AREA;
653 /* Save RETS and FP, and allocate a stack frame. ALL is true if the
654 function must save all its registers (true only for certain interrupt
658 do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all)
660 frame_size += arg_area_size ();
662 if (all || stack_frame_needed_p ()
663 || (must_save_fp_p () && ! current_function_is_leaf))
664 emit_link_insn (spreg, frame_size);
667 if (! current_function_is_leaf)
669 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
670 gen_rtx_PRE_DEC (Pmode, spreg)),
672 rtx insn = emit_insn (pat);
673 RTX_FRAME_RELATED_P (insn) = 1;
675 if (must_save_fp_p ())
677 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
678 gen_rtx_PRE_DEC (Pmode, spreg)),
679 gen_rtx_REG (Pmode, REG_FP));
680 rtx insn = emit_insn (pat);
681 RTX_FRAME_RELATED_P (insn) = 1;
683 add_to_reg (spreg, -frame_size, 1);
687 /* Like do_link, but used for epilogues to deallocate the stack frame. */
690 do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all)
692 frame_size += arg_area_size ();
694 if (all || stack_frame_needed_p ())
695 emit_insn (gen_unlink ());
698 rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg));
700 add_to_reg (spreg, frame_size, 0);
701 if (must_save_fp_p ())
703 rtx fpreg = gen_rtx_REG (Pmode, REG_FP);
704 emit_move_insn (fpreg, postinc);
705 emit_insn (gen_rtx_USE (VOIDmode, fpreg));
707 if (! current_function_is_leaf)
709 emit_move_insn (bfin_rets_rtx, postinc);
710 emit_insn (gen_rtx_USE (VOIDmode, bfin_rets_rtx));
715 /* Generate a prologue suitable for a function of kind FKIND. This is
716 called for interrupt and exception handler prologues.
717 SPREG contains (reg:SI REG_SP). */
720 expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind)
723 HOST_WIDE_INT frame_size = get_frame_size ();
724 rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
725 rtx predec = gen_rtx_MEM (SImode, predec1);
727 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
728 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
729 tree kspisusp = lookup_attribute ("kspisusp", attrs);
733 insn = emit_move_insn (spreg, gen_rtx_REG (Pmode, REG_USP));
734 RTX_FRAME_RELATED_P (insn) = 1;
737 /* We need space on the stack in case we need to save the argument
739 if (fkind == EXCPT_HANDLER)
741 insn = emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (-12)));
742 RTX_FRAME_RELATED_P (insn) = 1;
745 insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
746 RTX_FRAME_RELATED_P (insn) = 1;
748 /* If we're calling other functions, they won't save their call-clobbered
749 registers, so we must save everything here. */
750 if (!current_function_is_leaf)
752 expand_prologue_reg_save (spreg, all, true);
754 for (i = REG_P7 + 1; i < REG_CC; i++)
757 || (!leaf_function_p () && call_used_regs[i]))
759 if (i == REG_A0 || i == REG_A1)
760 insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1),
761 gen_rtx_REG (PDImode, i));
763 insn = emit_move_insn (predec, gen_rtx_REG (SImode, i));
764 RTX_FRAME_RELATED_P (insn) = 1;
767 if (lookup_attribute ("nesting", attrs))
769 rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
770 : fkind == NMI_HANDLER ? REG_RETN
772 insn = emit_move_insn (predec, srcreg);
773 RTX_FRAME_RELATED_P (insn) = 1;
776 do_link (spreg, frame_size, all);
778 if (fkind == EXCPT_HANDLER)
780 rtx r0reg = gen_rtx_REG (SImode, REG_R0);
781 rtx r1reg = gen_rtx_REG (SImode, REG_R1);
782 rtx r2reg = gen_rtx_REG (SImode, REG_R2);
785 insn = emit_move_insn (r0reg, gen_rtx_REG (SImode, REG_SEQSTAT));
786 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
788 insn = emit_insn (gen_ashrsi3 (r0reg, r0reg, GEN_INT (26)));
789 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
791 insn = emit_insn (gen_ashlsi3 (r0reg, r0reg, GEN_INT (26)));
792 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
794 insn = emit_move_insn (r1reg, spreg);
795 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
797 insn = emit_move_insn (r2reg, gen_rtx_REG (Pmode, REG_FP));
798 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
800 insn = emit_insn (gen_addsi3 (r2reg, r2reg, GEN_INT (8)));
801 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
806 /* Generate an epilogue suitable for a function of kind FKIND. This is
807 called for interrupt and exception handler epilogues.
808 SPREG contains (reg:SI REG_SP). */
811 expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind)
814 rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
815 rtx postinc = gen_rtx_MEM (SImode, postinc1);
816 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
817 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
819 /* A slightly crude technique to stop flow from trying to delete "dead"
821 MEM_VOLATILE_P (postinc) = 1;
823 do_unlink (spreg, get_frame_size (), all);
825 if (lookup_attribute ("nesting", attrs))
827 rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
828 : fkind == NMI_HANDLER ? REG_RETN
830 emit_move_insn (srcreg, postinc);
833 /* If we're calling other functions, they won't save their call-clobbered
834 registers, so we must save (and restore) everything here. */
835 if (!current_function_is_leaf)
838 for (i = REG_CC - 1; i > REG_P7; i--)
841 || (!leaf_function_p () && call_used_regs[i]))
843 if (i == REG_A0 || i == REG_A1)
845 rtx mem = gen_rtx_MEM (PDImode, postinc1);
846 MEM_VOLATILE_P (mem) = 1;
847 emit_move_insn (gen_rtx_REG (PDImode, i), mem);
850 emit_move_insn (gen_rtx_REG (SImode, i), postinc);
853 expand_epilogue_reg_restore (spreg, all, true);
855 emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
857 /* Deallocate any space we left on the stack in case we needed to save the
858 argument registers. */
859 if (fkind == EXCPT_HANDLER)
860 emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (12)));
862 emit_jump_insn (gen_return_internal (GEN_INT (fkind)));
865 /* Used while emitting the prologue to generate code to load the correct value
866 into the PIC register, which is passed in DEST. */
869 bfin_load_pic_reg (rtx dest)
871 struct cgraph_local_info *i = NULL;
874 if (flag_unit_at_a_time)
875 i = cgraph_local_info (current_function_decl);
877 /* Functions local to the translation unit don't need to reload the
878 pic reg, since the caller always passes a usable one. */
880 return pic_offset_table_rtx;
882 if (bfin_lib_id_given)
883 addr = plus_constant (pic_offset_table_rtx, -4 - bfin_library_id * 4);
885 addr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
886 gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
887 UNSPEC_LIBRARY_OFFSET));
888 insn = emit_insn (gen_movsi (dest, gen_rtx_MEM (Pmode, addr)));
889 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
893 /* Generate RTL for the prologue of the current function. */
896 bfin_expand_prologue (void)
899 HOST_WIDE_INT frame_size = get_frame_size ();
900 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
901 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
902 rtx pic_reg_loaded = NULL_RTX;
904 if (fkind != SUBROUTINE)
906 expand_interrupt_handler_prologue (spreg, fkind);
910 if (current_function_limit_stack
911 || TARGET_STACK_CHECK_L1)
914 = bfin_initial_elimination_offset (ARG_POINTER_REGNUM,
915 STACK_POINTER_REGNUM);
916 rtx lim = current_function_limit_stack ? stack_limit_rtx : NULL_RTX;
917 rtx p2reg = gen_rtx_REG (Pmode, REG_P2);
921 rtx p1reg = gen_rtx_REG (Pmode, REG_P1);
922 emit_move_insn (p2reg, gen_int_mode (0xFFB00000, SImode));
923 emit_move_insn (p2reg, gen_rtx_MEM (Pmode, p2reg));
926 if (GET_CODE (lim) == SYMBOL_REF)
928 if (TARGET_ID_SHARED_LIBRARY)
930 rtx p1reg = gen_rtx_REG (Pmode, REG_P1);
932 pic_reg_loaded = bfin_load_pic_reg (p2reg);
933 val = legitimize_pic_address (stack_limit_rtx, p1reg,
935 emit_move_insn (p1reg, val);
936 frame_related_constant_load (p2reg, offset, FALSE);
937 emit_insn (gen_addsi3 (p2reg, p2reg, p1reg));
942 rtx limit = plus_constant (lim, offset);
943 emit_move_insn (p2reg, limit);
950 emit_move_insn (p2reg, lim);
951 add_to_reg (p2reg, offset, 0);
954 emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim));
955 emit_insn (gen_trapifcc ());
957 expand_prologue_reg_save (spreg, 0, false);
959 do_link (spreg, frame_size, false);
961 if (TARGET_ID_SHARED_LIBRARY
963 && (current_function_uses_pic_offset_table
964 || !current_function_is_leaf))
965 bfin_load_pic_reg (pic_offset_table_rtx);
968 /* Generate RTL for the epilogue of the current function. NEED_RETURN is zero
969 if this is for a sibcall. EH_RETURN is nonzero if we're expanding an
970 eh_return pattern. */
973 bfin_expand_epilogue (int need_return, int eh_return)
975 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
976 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
978 if (fkind != SUBROUTINE)
980 expand_interrupt_handler_epilogue (spreg, fkind);
984 do_unlink (spreg, get_frame_size (), false);
986 expand_epilogue_reg_restore (spreg, false, false);
988 /* Omit the return insn if this is for a sibcall. */
993 emit_insn (gen_addsi3 (spreg, spreg, gen_rtx_REG (Pmode, REG_P2)));
995 emit_jump_insn (gen_return_internal (GEN_INT (SUBROUTINE)));
998 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
1001 bfin_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
1002 unsigned int new_reg)
1004 /* Interrupt functions can only use registers that have already been
1005 saved by the prologue, even if they would normally be
1008 if (funkind (TREE_TYPE (current_function_decl)) != SUBROUTINE
1009 && !regs_ever_live[new_reg])
1015 /* Return the value of the return address for the frame COUNT steps up
1016 from the current frame, after the prologue.
1017 We punt for everything but the current frame by returning const0_rtx. */
1020 bfin_return_addr_rtx (int count)
1025 return get_hard_reg_initial_val (Pmode, REG_RETS);
1028 /* Try machine-dependent ways of modifying an illegitimate address X
1029 to be legitimate. If we find one, return the new, valid address,
1030 otherwise return NULL_RTX.
1032 OLDX is the address as it was before break_out_memory_refs was called.
1033 In some cases it is useful to look at this to decide what needs to be done.
1035 MODE is the mode of the memory reference. */
1038 legitimize_address (rtx x ATTRIBUTE_UNUSED, rtx oldx ATTRIBUTE_UNUSED,
1039 enum machine_mode mode ATTRIBUTE_UNUSED)
1045 bfin_delegitimize_address (rtx orig_x)
1049 if (GET_CODE (x) != MEM)
1053 if (GET_CODE (x) == PLUS
1054 && GET_CODE (XEXP (x, 1)) == UNSPEC
1055 && XINT (XEXP (x, 1), 1) == UNSPEC_MOVE_PIC
1056 && GET_CODE (XEXP (x, 0)) == REG
1057 && REGNO (XEXP (x, 0)) == PIC_OFFSET_TABLE_REGNUM)
1058 return XVECEXP (XEXP (x, 1), 0, 0);
1063 /* This predicate is used to compute the length of a load/store insn.
1064 OP is a MEM rtx, we return nonzero if its addressing mode requires a
1065 32 bit instruction. */
1068 effective_address_32bit_p (rtx op, enum machine_mode mode)
1070 HOST_WIDE_INT offset;
1072 mode = GET_MODE (op);
1075 if (GET_CODE (op) != PLUS)
1077 gcc_assert (REG_P (op) || GET_CODE (op) == POST_INC
1078 || GET_CODE (op) == PRE_DEC || GET_CODE (op) == POST_DEC);
1082 offset = INTVAL (XEXP (op, 1));
1084 /* All byte loads use a 16 bit offset. */
1085 if (GET_MODE_SIZE (mode) == 1)
1088 if (GET_MODE_SIZE (mode) == 4)
1090 /* Frame pointer relative loads can use a negative offset, all others
1091 are restricted to a small positive one. */
1092 if (XEXP (op, 0) == frame_pointer_rtx)
1093 return offset < -128 || offset > 60;
1094 return offset < 0 || offset > 60;
1097 /* Must be HImode now. */
1098 return offset < 0 || offset > 30;
1101 /* Returns true if X is a memory reference using an I register. */
1103 bfin_dsp_memref_p (rtx x)
1108 if (GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_INC
1109 || GET_CODE (x) == POST_DEC || GET_CODE (x) == PRE_DEC)
1114 /* Return cost of the memory address ADDR.
1115 All addressing modes are equally cheap on the Blackfin. */
1118 bfin_address_cost (rtx addr ATTRIBUTE_UNUSED)
1123 /* Subroutine of print_operand; used to print a memory reference X to FILE. */
1126 print_address_operand (FILE *file, rtx x)
1128 switch (GET_CODE (x))
1131 output_address (XEXP (x, 0));
1132 fprintf (file, "+");
1133 output_address (XEXP (x, 1));
1137 fprintf (file, "--");
1138 output_address (XEXP (x, 0));
1141 output_address (XEXP (x, 0));
1142 fprintf (file, "++");
1145 output_address (XEXP (x, 0));
1146 fprintf (file, "--");
1150 gcc_assert (GET_CODE (x) != MEM);
1151 print_operand (file, x, 0);
1156 /* Adding intp DImode support by Tony
1162 print_operand (FILE *file, rtx x, char code)
1164 enum machine_mode mode = GET_MODE (x);
1169 switch (GET_CODE (x))
1172 fprintf (file, "e");
1175 fprintf (file, "ne");
1178 fprintf (file, "g");
1181 fprintf (file, "l");
1184 fprintf (file, "ge");
1187 fprintf (file, "le");
1190 fprintf (file, "g");
1193 fprintf (file, "l");
1196 fprintf (file, "ge");
1199 fprintf (file, "le");
1202 output_operand_lossage ("invalid %%j value");
1206 case 'J': /* reverse logic */
1207 switch (GET_CODE(x))
1210 fprintf (file, "ne");
1213 fprintf (file, "e");
1216 fprintf (file, "le");
1219 fprintf (file, "ge");
1222 fprintf (file, "l");
1225 fprintf (file, "g");
1228 fprintf (file, "le");
1231 fprintf (file, "ge");
1234 fprintf (file, "l");
1237 fprintf (file, "g");
1240 output_operand_lossage ("invalid %%J value");
1245 switch (GET_CODE (x))
1250 gcc_assert (REGNO (x) < 32);
1251 fprintf (file, "%s", short_reg_names[REGNO (x)]);
1252 /*fprintf (file, "\n%d\n ", REGNO (x));*/
1255 else if (code == 'd')
1257 gcc_assert (REGNO (x) < 32);
1258 fprintf (file, "%s", high_reg_names[REGNO (x)]);
1261 else if (code == 'w')
1263 gcc_assert (REGNO (x) == REG_A0 || REGNO (x) == REG_A1);
1264 fprintf (file, "%s.w", reg_names[REGNO (x)]);
1266 else if (code == 'x')
1268 gcc_assert (REGNO (x) == REG_A0 || REGNO (x) == REG_A1);
1269 fprintf (file, "%s.x", reg_names[REGNO (x)]);
1271 else if (code == 'D')
1273 fprintf (file, "%s", dregs_pair_names[REGNO (x)]);
1275 else if (code == 'H')
1277 gcc_assert (mode == DImode || mode == DFmode);
1278 gcc_assert (REG_P (x));
1279 fprintf (file, "%s", reg_names[REGNO (x) + 1]);
1281 else if (code == 'T')
1283 gcc_assert (D_REGNO_P (REGNO (x)));
1284 fprintf (file, "%s", byte_reg_names[REGNO (x)]);
1287 fprintf (file, "%s", reg_names[REGNO (x)]);
1293 print_address_operand (file, x);
1305 fputs ("(FU)", file);
1308 fputs ("(T)", file);
1311 fputs ("(TFU)", file);
1314 fputs ("(W32)", file);
1317 fputs ("(IS)", file);
1320 fputs ("(IU)", file);
1323 fputs ("(IH)", file);
1326 fputs ("(M)", file);
1329 fputs ("(ISS2)", file);
1332 fputs ("(S2RND)", file);
1339 else if (code == 'b')
1341 if (INTVAL (x) == 0)
1343 else if (INTVAL (x) == 1)
1349 /* Moves to half registers with d or h modifiers always use unsigned
1351 else if (code == 'd')
1352 x = GEN_INT ((INTVAL (x) >> 16) & 0xffff);
1353 else if (code == 'h')
1354 x = GEN_INT (INTVAL (x) & 0xffff);
1355 else if (code == 'X')
1356 x = GEN_INT (exact_log2 (0xffffffff & INTVAL (x)));
1357 else if (code == 'Y')
1358 x = GEN_INT (exact_log2 (0xffffffff & ~INTVAL (x)));
1359 else if (code == 'Z')
1360 /* Used for LINK insns. */
1361 x = GEN_INT (-8 - INTVAL (x));
1366 output_addr_const (file, x);
1370 output_operand_lossage ("invalid const_double operand");
1374 switch (XINT (x, 1))
1376 case UNSPEC_MOVE_PIC:
1377 output_addr_const (file, XVECEXP (x, 0, 0));
1378 fprintf (file, "@GOT");
1381 case UNSPEC_MOVE_FDPIC:
1382 output_addr_const (file, XVECEXP (x, 0, 0));
1383 fprintf (file, "@GOT17M4");
1386 case UNSPEC_FUNCDESC_GOT17M4:
1387 output_addr_const (file, XVECEXP (x, 0, 0));
1388 fprintf (file, "@FUNCDESC_GOT17M4");
1391 case UNSPEC_LIBRARY_OFFSET:
1392 fprintf (file, "_current_shared_library_p5_offset_");
1401 output_addr_const (file, x);
1406 /* Argument support functions. */
1408 /* Initialize a variable CUM of type CUMULATIVE_ARGS
1409 for a call to a function whose data type is FNTYPE.
1410 For a library call, FNTYPE is 0.
1411 VDSP C Compiler manual, our ABI says that
1412 first 3 words of arguments will use R0, R1 and R2.
1416 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
1417 rtx libname ATTRIBUTE_UNUSED)
1419 static CUMULATIVE_ARGS zero_cum;
1423 /* Set up the number of registers to use for passing arguments. */
1425 cum->nregs = max_arg_registers;
1426 cum->arg_regs = arg_regs;
1428 cum->call_cookie = CALL_NORMAL;
1429 /* Check for a longcall attribute. */
1430 if (fntype && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype)))
1431 cum->call_cookie |= CALL_SHORT;
1432 else if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)))
1433 cum->call_cookie |= CALL_LONG;
1438 /* Update the data in CUM to advance over an argument
1439 of mode MODE and data type TYPE.
1440 (TYPE is null for libcalls where that information may not be available.) */
1443 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1444 int named ATTRIBUTE_UNUSED)
1446 int count, bytes, words;
1448 bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1449 words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1451 cum->words += words;
1452 cum->nregs -= words;
1454 if (cum->nregs <= 0)
1457 cum->arg_regs = NULL;
1461 for (count = 1; count <= words; count++)
1468 /* Define where to put the arguments to a function.
1469 Value is zero to push the argument on the stack,
1470 or a hard register in which to store the argument.
1472 MODE is the argument's machine mode.
1473 TYPE is the data type of the argument (as a tree).
1474 This is null for libcalls where that information may
1476 CUM is a variable of type CUMULATIVE_ARGS which gives info about
1477 the preceding args and about the function being called.
1478 NAMED is nonzero if this argument is a named parameter
1479 (otherwise it is an extra parameter matching an ellipsis). */
1482 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1483 int named ATTRIBUTE_UNUSED)
1486 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1488 if (mode == VOIDmode)
1489 /* Compute operand 2 of the call insn. */
1490 return GEN_INT (cum->call_cookie);
1496 return gen_rtx_REG (mode, *(cum->arg_regs));
1501 /* For an arg passed partly in registers and partly in memory,
1502 this is the number of bytes passed in registers.
1503 For args passed entirely in registers or entirely in memory, zero.
1505 Refer VDSP C Compiler manual, our ABI.
1506 First 3 words are in registers. So, if a an argument is larger
1507 than the registers available, it will span the register and
1511 bfin_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1512 tree type ATTRIBUTE_UNUSED,
1513 bool named ATTRIBUTE_UNUSED)
1516 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1517 int bytes_left = cum->nregs * UNITS_PER_WORD;
1522 if (bytes_left == 0)
1524 if (bytes > bytes_left)
1529 /* Variable sized types are passed by reference. */
1532 bfin_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
1533 enum machine_mode mode ATTRIBUTE_UNUSED,
1534 tree type, bool named ATTRIBUTE_UNUSED)
1536 return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
1539 /* Decide whether a type should be returned in memory (true)
1540 or in a register (false). This is called by the macro
1541 RETURN_IN_MEMORY. */
1544 bfin_return_in_memory (tree type)
1546 int size = int_size_in_bytes (type);
1547 return size > 2 * UNITS_PER_WORD || size == -1;
1550 /* Register in which address to store a structure value
1551 is passed to a function. */
1553 bfin_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
1554 int incoming ATTRIBUTE_UNUSED)
1556 return gen_rtx_REG (Pmode, REG_P0);
1559 /* Return true when register may be used to pass function parameters. */
1562 function_arg_regno_p (int n)
1565 for (i = 0; arg_regs[i] != -1; i++)
1566 if (n == arg_regs[i])
1571 /* Returns 1 if OP contains a symbol reference */
1574 symbolic_reference_mentioned_p (rtx op)
1576 register const char *fmt;
1579 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
1582 fmt = GET_RTX_FORMAT (GET_CODE (op));
1583 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
1589 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
1590 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
1594 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
1601 /* Decide whether we can make a sibling call to a function. DECL is the
1602 declaration of the function being targeted by the call and EXP is the
1603 CALL_EXPR representing the call. */
1606 bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
1607 tree exp ATTRIBUTE_UNUSED)
1609 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1610 if (fkind != SUBROUTINE)
1612 if (!TARGET_ID_SHARED_LIBRARY || TARGET_SEP_DATA)
1615 /* When compiling for ID shared libraries, can't sibcall a local function
1616 from a non-local function, because the local function thinks it does
1617 not need to reload P5 in the prologue, but the sibcall wil pop P5 in the
1618 sibcall epilogue, and we end up with the wrong value in P5. */
1620 if (!flag_unit_at_a_time || decl == NULL)
1621 /* Not enough information. */
1625 struct cgraph_local_info *this_func, *called_func;
1628 this_func = cgraph_local_info (current_function_decl);
1629 called_func = cgraph_local_info (decl);
1630 return !called_func->local || this_func->local;
1634 /* Emit RTL insns to initialize the variable parts of a trampoline at
1635 TRAMP. FNADDR is an RTX for the address of the function's pure
1636 code. CXT is an RTX for the static chain value for the function. */
1639 initialize_trampoline (tramp, fnaddr, cxt)
1640 rtx tramp, fnaddr, cxt;
1642 rtx t1 = copy_to_reg (fnaddr);
1643 rtx t2 = copy_to_reg (cxt);
1649 rtx a = memory_address (Pmode, plus_constant (tramp, 8));
1650 addr = memory_address (Pmode, tramp);
1651 emit_move_insn (gen_rtx_MEM (SImode, addr), a);
1655 addr = memory_address (Pmode, plus_constant (tramp, i + 2));
1656 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
1657 emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16)));
1658 addr = memory_address (Pmode, plus_constant (tramp, i + 6));
1659 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
1661 addr = memory_address (Pmode, plus_constant (tramp, i + 10));
1662 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
1663 emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16)));
1664 addr = memory_address (Pmode, plus_constant (tramp, i + 14));
1665 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
1668 /* Emit insns to move operands[1] into operands[0]. */
1671 emit_pic_move (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
1673 rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
1675 gcc_assert (!TARGET_FDPIC || !(reload_in_progress || reload_completed));
1676 if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
1677 operands[1] = force_reg (SImode, operands[1]);
1679 operands[1] = legitimize_pic_address (operands[1], temp,
1680 TARGET_FDPIC ? OUR_FDPIC_REG
1681 : pic_offset_table_rtx);
1684 /* Expand a move operation in mode MODE. The operands are in OPERANDS.
1685 Returns true if no further code must be generated, false if the caller
1686 should generate an insn to move OPERANDS[1] to OPERANDS[0]. */
1689 expand_move (rtx *operands, enum machine_mode mode)
1691 rtx op = operands[1];
1692 if ((TARGET_ID_SHARED_LIBRARY || TARGET_FDPIC)
1693 && SYMBOLIC_CONST (op))
1694 emit_pic_move (operands, mode);
1695 else if (mode == SImode && GET_CODE (op) == CONST
1696 && GET_CODE (XEXP (op, 0)) == PLUS
1697 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
1698 && !bfin_legitimate_constant_p (op))
1700 rtx dest = operands[0];
1702 gcc_assert (!reload_in_progress && !reload_completed);
1704 op0 = force_reg (mode, XEXP (op, 0));
1706 if (!insn_data[CODE_FOR_addsi3].operand[2].predicate (op1, mode))
1707 op1 = force_reg (mode, op1);
1708 if (GET_CODE (dest) == MEM)
1709 dest = gen_reg_rtx (mode);
1710 emit_insn (gen_addsi3 (dest, op0, op1));
1711 if (dest == operands[0])
1715 /* Don't generate memory->memory or constant->memory moves, go through a
1717 else if ((reload_in_progress | reload_completed) == 0
1718 && GET_CODE (operands[0]) == MEM
1719 && GET_CODE (operands[1]) != REG)
1720 operands[1] = force_reg (mode, operands[1]);
1724 /* Split one or more DImode RTL references into pairs of SImode
1725 references. The RTL can be REG, offsettable MEM, integer constant, or
1726 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
1727 split and "num" is its length. lo_half and hi_half are output arrays
1728 that parallel "operands". */
1731 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
1735 rtx op = operands[num];
1737 /* simplify_subreg refuse to split volatile memory addresses,
1738 but we still have to handle it. */
1739 if (GET_CODE (op) == MEM)
1741 lo_half[num] = adjust_address (op, SImode, 0);
1742 hi_half[num] = adjust_address (op, SImode, 4);
1746 lo_half[num] = simplify_gen_subreg (SImode, op,
1747 GET_MODE (op) == VOIDmode
1748 ? DImode : GET_MODE (op), 0);
1749 hi_half[num] = simplify_gen_subreg (SImode, op,
1750 GET_MODE (op) == VOIDmode
1751 ? DImode : GET_MODE (op), 4);
1757 bfin_longcall_p (rtx op, int call_cookie)
1759 gcc_assert (GET_CODE (op) == SYMBOL_REF);
1760 if (call_cookie & CALL_SHORT)
1762 if (call_cookie & CALL_LONG)
1764 if (TARGET_LONG_CALLS)
1769 /* Expand a call instruction. FNADDR is the call target, RETVAL the return value.
1770 COOKIE is a CONST_INT holding the call_cookie prepared init_cumulative_args.
1771 SIBCALL is nonzero if this is a sibling call. */
1774 bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
1776 rtx use = NULL, call;
1777 rtx callee = XEXP (fnaddr, 0);
1778 int nelts = 2 + !!sibcall;
1780 rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REGNO);
1783 /* In an untyped call, we can get NULL for operand 2. */
1784 if (cookie == NULL_RTX)
1785 cookie = const0_rtx;
1787 /* Static functions and indirect calls don't need the pic register. */
1788 if (!TARGET_FDPIC && flag_pic
1789 && GET_CODE (callee) == SYMBOL_REF
1790 && !SYMBOL_REF_LOCAL_P (callee))
1791 use_reg (&use, pic_offset_table_rtx);
1795 if (GET_CODE (callee) != SYMBOL_REF
1796 || bfin_longcall_p (callee, INTVAL (cookie)))
1799 if (! address_operand (addr, Pmode))
1800 addr = force_reg (Pmode, addr);
1802 fnaddr = gen_reg_rtx (SImode);
1803 emit_insn (gen_load_funcdescsi (fnaddr, addr));
1804 fnaddr = gen_rtx_MEM (Pmode, fnaddr);
1806 picreg = gen_reg_rtx (SImode);
1807 emit_insn (gen_load_funcdescsi (picreg,
1808 plus_constant (addr, 4)));
1813 else if ((!register_no_elim_operand (callee, Pmode)
1814 && GET_CODE (callee) != SYMBOL_REF)
1815 || (GET_CODE (callee) == SYMBOL_REF
1816 && ((TARGET_ID_SHARED_LIBRARY && !TARGET_LEAF_ID_SHARED_LIBRARY)
1817 || bfin_longcall_p (callee, INTVAL (cookie)))))
1819 callee = copy_to_mode_reg (Pmode, callee);
1820 fnaddr = gen_rtx_MEM (Pmode, callee);
1822 call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
1825 call = gen_rtx_SET (VOIDmode, retval, call);
1827 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nelts));
1829 XVECEXP (pat, 0, n++) = call;
1831 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, picreg);
1832 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie);
1834 XVECEXP (pat, 0, n++) = gen_rtx_RETURN (VOIDmode);
1835 call = emit_call_insn (pat);
1837 CALL_INSN_FUNCTION_USAGE (call) = use;
1840 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
1843 hard_regno_mode_ok (int regno, enum machine_mode mode)
1845 /* Allow only dregs to store value of mode HI or QI */
1846 enum reg_class class = REGNO_REG_CLASS (regno);
1851 if (mode == V2HImode)
1852 return D_REGNO_P (regno);
1853 if (class == CCREGS)
1854 return mode == BImode;
1855 if (mode == PDImode || mode == V2PDImode)
1856 return regno == REG_A0 || regno == REG_A1;
1858 && TEST_HARD_REG_BIT (reg_class_contents[PROLOGUE_REGS], regno))
1861 return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno);
1864 /* Implements target hook vector_mode_supported_p. */
1867 bfin_vector_mode_supported_p (enum machine_mode mode)
1869 return mode == V2HImode;
1872 /* Return the cost of moving data from a register in class CLASS1 to
1873 one in class CLASS2. A cost of 2 is the default. */
1876 bfin_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
1877 enum reg_class class1, enum reg_class class2)
1879 /* These need secondary reloads, so they're more expensive. */
1880 if ((class1 == CCREGS && class2 != DREGS)
1881 || (class1 != DREGS && class2 == CCREGS))
1884 /* If optimizing for size, always prefer reg-reg over reg-memory moves. */
1888 /* There are some stalls involved when moving from a DREG to a different
1889 class reg, and using the value in one of the following instructions.
1890 Attempt to model this by slightly discouraging such moves. */
1891 if (class1 == DREGS && class2 != DREGS)
1897 /* Return the cost of moving data of mode M between a
1898 register and memory. A value of 2 is the default; this cost is
1899 relative to those in `REGISTER_MOVE_COST'.
1901 ??? In theory L1 memory has single-cycle latency. We should add a switch
1902 that tells the compiler whether we expect to use only L1 memory for the
1903 program; it'll make the costs more accurate. */
1906 bfin_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
1907 enum reg_class class,
1908 int in ATTRIBUTE_UNUSED)
1910 /* Make memory accesses slightly more expensive than any register-register
1911 move. Also, penalize non-DP registers, since they need secondary
1912 reloads to load and store. */
1913 if (! reg_class_subset_p (class, DPREGS))
1919 /* Inform reload about cases where moving X with a mode MODE to a register in
1920 CLASS requires an extra scratch register. Return the class needed for the
1921 scratch register. */
1923 static enum reg_class
1924 bfin_secondary_reload (bool in_p, rtx x, enum reg_class class,
1925 enum machine_mode mode, secondary_reload_info *sri)
1927 /* If we have HImode or QImode, we can only use DREGS as secondary registers;
1928 in most other cases we can also use PREGS. */
1929 enum reg_class default_class = GET_MODE_SIZE (mode) >= 4 ? DPREGS : DREGS;
1930 enum reg_class x_class = NO_REGS;
1931 enum rtx_code code = GET_CODE (x);
1934 x = SUBREG_REG (x), code = GET_CODE (x);
1937 int regno = REGNO (x);
1938 if (regno >= FIRST_PSEUDO_REGISTER)
1939 regno = reg_renumber[regno];
1944 x_class = REGNO_REG_CLASS (regno);
1947 /* We can be asked to reload (plus (FP) (large_constant)) into a DREG.
1948 This happens as a side effect of register elimination, and we need
1949 a scratch register to do it. */
1950 if (fp_plus_const_operand (x, mode))
1952 rtx op2 = XEXP (x, 1);
1953 int large_constant_p = ! CONST_7BIT_IMM_P (INTVAL (op2));
1955 if (class == PREGS || class == PREGS_CLOBBERED)
1957 /* If destination is a DREG, we can do this without a scratch register
1958 if the constant is valid for an add instruction. */
1959 if ((class == DREGS || class == DPREGS)
1960 && ! large_constant_p)
1962 /* Reloading to anything other than a DREG? Use a PREG scratch
1964 sri->icode = CODE_FOR_reload_insi;
1968 /* Data can usually be moved freely between registers of most classes.
1969 AREGS are an exception; they can only move to or from another register
1970 in AREGS or one in DREGS. They can also be assigned the constant 0. */
1971 if (x_class == AREGS)
1972 return class == DREGS || class == AREGS ? NO_REGS : DREGS;
1976 if (x != const0_rtx && x_class != DREGS)
1982 /* CCREGS can only be moved from/to DREGS. */
1983 if (class == CCREGS && x_class != DREGS)
1985 if (x_class == CCREGS && class != DREGS)
1988 /* All registers other than AREGS can load arbitrary constants. The only
1989 case that remains is MEM. */
1991 if (! reg_class_subset_p (class, default_class))
1992 return default_class;
1996 /* Implement TARGET_HANDLE_OPTION. */
1999 bfin_handle_option (size_t code, const char *arg, int value)
2003 case OPT_mshared_library_id_:
2004 if (value > MAX_LIBRARY_ID)
2005 error ("-mshared-library-id=%s is not between 0 and %d",
2006 arg, MAX_LIBRARY_ID);
2007 bfin_lib_id_given = 1;
2015 static struct machine_function *
2016 bfin_init_machine_status (void)
2018 struct machine_function *f;
2020 f = ggc_alloc_cleared (sizeof (struct machine_function));
2025 /* Implement the macro OVERRIDE_OPTIONS. */
2028 override_options (void)
2030 if (TARGET_OMIT_LEAF_FRAME_POINTER)
2031 flag_omit_frame_pointer = 1;
2033 /* Library identification */
2034 if (bfin_lib_id_given && ! TARGET_ID_SHARED_LIBRARY)
2035 error ("-mshared-library-id= specified without -mid-shared-library");
2037 if (TARGET_ID_SHARED_LIBRARY && flag_pic == 0)
2040 if (stack_limit_rtx && TARGET_STACK_CHECK_L1)
2041 error ("Can't use multiple stack checking methods together.");
2043 if (TARGET_ID_SHARED_LIBRARY && TARGET_FDPIC)
2044 error ("ID shared libraries and FD-PIC mode can't be used together.");
2046 /* Don't allow the user to specify -mid-shared-library and -msep-data
2047 together, as it makes little sense from a user's point of view... */
2048 if (TARGET_SEP_DATA && TARGET_ID_SHARED_LIBRARY)
2049 error ("cannot specify both -msep-data and -mid-shared-library");
2050 /* ... internally, however, it's nearly the same. */
2051 if (TARGET_SEP_DATA)
2052 target_flags |= MASK_ID_SHARED_LIBRARY | MASK_LEAF_ID_SHARED_LIBRARY;
2054 /* There is no single unaligned SI op for PIC code. Sometimes we
2055 need to use ".4byte" and sometimes we need to use ".picptr".
2056 See bfin_assemble_integer for details. */
2058 targetm.asm_out.unaligned_op.si = 0;
2060 /* Silently turn off flag_pic if not doing FDPIC or ID shared libraries,
2061 since we don't support it and it'll just break. */
2062 if (flag_pic && !TARGET_FDPIC && !TARGET_ID_SHARED_LIBRARY)
2065 flag_schedule_insns = 0;
2067 init_machine_status = bfin_init_machine_status;
2070 /* Return the destination address of BRANCH.
2071 We need to use this instead of get_attr_length, because the
2072 cbranch_with_nops pattern conservatively sets its length to 6, and
2073 we still prefer to use shorter sequences. */
2076 branch_dest (rtx branch)
2080 rtx pat = PATTERN (branch);
2081 if (GET_CODE (pat) == PARALLEL)
2082 pat = XVECEXP (pat, 0, 0);
2083 dest = SET_SRC (pat);
2084 if (GET_CODE (dest) == IF_THEN_ELSE)
2085 dest = XEXP (dest, 1);
2086 dest = XEXP (dest, 0);
2087 dest_uid = INSN_UID (dest);
2088 return INSN_ADDRESSES (dest_uid);
2091 /* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates
2092 it's a branch that's predicted taken. */
2095 cbranch_predicted_taken_p (rtx insn)
2097 rtx x = find_reg_note (insn, REG_BR_PROB, 0);
2101 int pred_val = INTVAL (XEXP (x, 0));
2103 return pred_val >= REG_BR_PROB_BASE / 2;
2109 /* Templates for use by asm_conditional_branch. */
2111 static const char *ccbranch_templates[][3] = {
2112 { "if !cc jump %3;", "if cc jump 4 (bp); jump.s %3;", "if cc jump 6 (bp); jump.l %3;" },
2113 { "if cc jump %3;", "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" },
2114 { "if !cc jump %3 (bp);", "if cc jump 4; jump.s %3;", "if cc jump 6; jump.l %3;" },
2115 { "if cc jump %3 (bp);", "if !cc jump 4; jump.s %3;", "if !cc jump 6; jump.l %3;" },
2118 /* Output INSN, which is a conditional branch instruction with operands
2121 We deal with the various forms of conditional branches that can be generated
2122 by bfin_reorg to prevent the hardware from doing speculative loads, by
2123 - emitting a sufficient number of nops, if N_NOPS is nonzero, or
2124 - always emitting the branch as predicted taken, if PREDICT_TAKEN is true.
2125 Either of these is only necessary if the branch is short, otherwise the
2126 template we use ends in an unconditional jump which flushes the pipeline
2130 asm_conditional_branch (rtx insn, rtx *operands, int n_nops, int predict_taken)
2132 int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
2133 /* Note : offset for instructions like if cc jmp; jump.[sl] offset
2134 is to be taken from start of if cc rather than jump.
2135 Range for jump.s is (-4094, 4096) instead of (-4096, 4094)
2137 int len = (offset >= -1024 && offset <= 1022 ? 0
2138 : offset >= -4094 && offset <= 4096 ? 1
2140 int bp = predict_taken && len == 0 ? 1 : cbranch_predicted_taken_p (insn);
2141 int idx = (bp << 1) | (GET_CODE (operands[0]) == EQ ? BRF : BRT);
2142 output_asm_insn (ccbranch_templates[idx][len], operands);
2143 gcc_assert (n_nops == 0 || !bp);
2145 while (n_nops-- > 0)
2146 output_asm_insn ("nop;", NULL);
2149 /* Emit rtl for a comparison operation CMP in mode MODE. Operands have been
2150 stored in bfin_compare_op0 and bfin_compare_op1 already. */
2153 bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED)
2155 enum rtx_code code1, code2;
2156 rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1;
2157 rtx tem = bfin_cc_rtx;
2158 enum rtx_code code = GET_CODE (cmp);
2160 /* If we have a BImode input, then we already have a compare result, and
2161 do not need to emit another comparison. */
2162 if (GET_MODE (op0) == BImode)
2164 gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
2165 tem = op0, code2 = code;
2170 /* bfin has these conditions */
2180 code1 = reverse_condition (code);
2184 emit_insn (gen_rtx_SET (BImode, tem,
2185 gen_rtx_fmt_ee (code1, BImode, op0, op1)));
2188 return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode));
2191 /* Return nonzero iff C has exactly one bit set if it is interpreted
2192 as a 32 bit constant. */
2195 log2constp (unsigned HOST_WIDE_INT c)
2198 return c != 0 && (c & (c-1)) == 0;
2201 /* Returns the number of consecutive least significant zeros in the binary
2202 representation of *V.
2203 We modify *V to contain the original value arithmetically shifted right by
2204 the number of zeroes. */
2207 shiftr_zero (HOST_WIDE_INT *v)
2209 unsigned HOST_WIDE_INT tmp = *v;
2210 unsigned HOST_WIDE_INT sgn;
2216 sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1));
2217 while ((tmp & 0x1) == 0 && n <= 32)
2219 tmp = (tmp >> 1) | sgn;
2226 /* After reload, split the load of an immediate constant. OPERANDS are the
2227 operands of the movsi_insn pattern which we are splitting. We return
2228 nonzero if we emitted a sequence to load the constant, zero if we emitted
2229 nothing because we want to use the splitter's default sequence. */
2232 split_load_immediate (rtx operands[])
2234 HOST_WIDE_INT val = INTVAL (operands[1]);
2236 HOST_WIDE_INT shifted = val;
2237 HOST_WIDE_INT shifted_compl = ~val;
2238 int num_zero = shiftr_zero (&shifted);
2239 int num_compl_zero = shiftr_zero (&shifted_compl);
2240 unsigned int regno = REGNO (operands[0]);
2241 enum reg_class class1 = REGNO_REG_CLASS (regno);
2243 /* This case takes care of single-bit set/clear constants, which we could
2244 also implement with BITSET/BITCLR. */
2246 && shifted >= -32768 && shifted < 65536
2247 && (D_REGNO_P (regno)
2248 || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))
2250 emit_insn (gen_movsi (operands[0], GEN_INT (shifted)));
2251 emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));
2256 tmp |= -(tmp & 0x8000);
2258 /* If high word has one bit set or clear, try to use a bit operation. */
2259 if (D_REGNO_P (regno))
2261 if (log2constp (val & 0xFFFF0000))
2263 emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));
2264 emit_insn (gen_iorsi3 (operands[0], operands[0], GEN_INT (val & 0xFFFF0000)));
2267 else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)
2269 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2270 emit_insn (gen_andsi3 (operands[0], operands[0], GEN_INT (val | 0xFFFF)));
2274 if (D_REGNO_P (regno))
2276 if (CONST_7BIT_IMM_P (tmp))
2278 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2279 emit_insn (gen_movstricthi_high (operands[0], GEN_INT (val & -65536)));
2283 if ((val & 0xFFFF0000) == 0)
2285 emit_insn (gen_movsi (operands[0], const0_rtx));
2286 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2290 if ((val & 0xFFFF0000) == 0xFFFF0000)
2292 emit_insn (gen_movsi (operands[0], constm1_rtx));
2293 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2298 /* Need DREGs for the remaining case. */
2303 && num_compl_zero && CONST_7BIT_IMM_P (shifted_compl))
2305 /* If optimizing for size, generate a sequence that has more instructions
2307 emit_insn (gen_movsi (operands[0], GEN_INT (shifted_compl)));
2308 emit_insn (gen_ashlsi3 (operands[0], operands[0],
2309 GEN_INT (num_compl_zero)));
2310 emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
2316 /* Return true if the legitimate memory address for a memory operand of mode
2317 MODE. Return false if not. */
2320 bfin_valid_add (enum machine_mode mode, HOST_WIDE_INT value)
2322 unsigned HOST_WIDE_INT v = value > 0 ? value : -value;
2323 int sz = GET_MODE_SIZE (mode);
2324 int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2;
2325 /* The usual offsettable_memref machinery doesn't work so well for this
2326 port, so we deal with the problem here. */
2327 unsigned HOST_WIDE_INT mask = sz == 8 ? 0x7ffe : 0x7fff;
2328 return (v & ~(mask << shift)) == 0;
2332 bfin_valid_reg_p (unsigned int regno, int strict, enum machine_mode mode,
2333 enum rtx_code outer_code)
2336 return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH);
2338 return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH);
2342 bfin_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
2344 switch (GET_CODE (x)) {
2346 if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM))
2350 if (REG_P (XEXP (x, 0))
2351 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS)
2352 && ((GET_CODE (XEXP (x, 1)) == UNSPEC && mode == SImode)
2353 || (GET_CODE (XEXP (x, 1)) == CONST_INT
2354 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
2359 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2360 && REG_P (XEXP (x, 0))
2361 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC))
2364 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2365 && XEXP (x, 0) == stack_pointer_rtx
2366 && REG_P (XEXP (x, 0))
2367 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC))
2376 /* Decide whether we can force certain constants to memory. If we
2377 decide we can't, the caller should be able to cope with it in
2381 bfin_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
2383 /* We have only one class of non-legitimate constants, and our movsi
2384 expander knows how to handle them. Dropping these constants into the
2385 data section would only shift the problem - we'd still get relocs
2386 outside the object, in the data section rather than the text section. */
2390 /* Ensure that for any constant of the form symbol + offset, the offset
2391 remains within the object. Any other constants are ok.
2392 This ensures that flat binaries never have to deal with relocations
2393 crossing section boundaries. */
2396 bfin_legitimate_constant_p (rtx x)
2399 HOST_WIDE_INT offset;
2401 if (GET_CODE (x) != CONST)
2405 gcc_assert (GET_CODE (x) == PLUS);
2409 if (GET_CODE (sym) != SYMBOL_REF
2410 || GET_CODE (x) != CONST_INT)
2412 offset = INTVAL (x);
2414 if (SYMBOL_REF_DECL (sym) == 0)
2417 || offset >= int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (sym))))
2424 bfin_rtx_costs (rtx x, int code, int outer_code, int *total)
2426 int cost2 = COSTS_N_INSNS (1);
2431 if (outer_code == SET || outer_code == PLUS)
2432 *total = CONST_7BIT_IMM_P (INTVAL (x)) ? 0 : cost2;
2433 else if (outer_code == AND)
2434 *total = log2constp (~INTVAL (x)) ? 0 : cost2;
2435 else if (outer_code == LE || outer_code == LT || outer_code == EQ)
2436 *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
2437 else if (outer_code == LEU || outer_code == LTU)
2438 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
2439 else if (outer_code == MULT)
2440 *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
2441 else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
2443 else if (outer_code == ASHIFT || outer_code == ASHIFTRT
2444 || outer_code == LSHIFTRT)
2445 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
2446 else if (outer_code == IOR || outer_code == XOR)
2447 *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
2456 *total = COSTS_N_INSNS (2);
2460 if (GET_MODE (x) == Pmode)
2462 if (GET_CODE (XEXP (x, 0)) == MULT
2463 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
2465 HOST_WIDE_INT val = INTVAL (XEXP (XEXP (x, 0), 1));
2466 if (val == 2 || val == 4)
2469 *total += rtx_cost (XEXP (XEXP (x, 0), 0), outer_code);
2470 *total += rtx_cost (XEXP (x, 1), outer_code);
2482 if (GET_MODE (x) == DImode)
2489 if (GET_MODE (x) == DImode)
2494 if (GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD)
2495 *total = COSTS_N_INSNS (3);
2500 *total = COSTS_N_INSNS (32);
2505 if (outer_code == SET)
2515 bfin_internal_label (FILE *stream, const char *prefix, unsigned long num)
2517 fprintf (stream, "%s%s$%ld:\n", LOCAL_LABEL_PREFIX, prefix, num);
2520 /* Used for communication between {push,pop}_multiple_operation (which
2521 we use not only as a predicate) and the corresponding output functions. */
2522 static int first_preg_to_save, first_dreg_to_save;
2525 push_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2527 int lastdreg = 8, lastpreg = 6;
2530 first_preg_to_save = lastpreg;
2531 first_dreg_to_save = lastdreg;
2532 for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
2534 rtx t = XVECEXP (op, 0, i);
2538 if (GET_CODE (t) != SET)
2542 dest = SET_DEST (t);
2543 if (GET_CODE (dest) != MEM || ! REG_P (src))
2545 dest = XEXP (dest, 0);
2546 if (GET_CODE (dest) != PLUS
2547 || ! REG_P (XEXP (dest, 0))
2548 || REGNO (XEXP (dest, 0)) != REG_SP
2549 || GET_CODE (XEXP (dest, 1)) != CONST_INT
2550 || INTVAL (XEXP (dest, 1)) != -i * 4)
2553 regno = REGNO (src);
2556 if (D_REGNO_P (regno))
2559 first_dreg_to_save = lastdreg = regno - REG_R0;
2561 else if (regno >= REG_P0 && regno <= REG_P7)
2564 first_preg_to_save = lastpreg = regno - REG_P0;
2574 if (regno >= REG_P0 && regno <= REG_P7)
2577 first_preg_to_save = lastpreg = regno - REG_P0;
2579 else if (regno != REG_R0 + lastdreg + 1)
2584 else if (group == 2)
2586 if (regno != REG_P0 + lastpreg + 1)
2595 pop_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2597 int lastdreg = 8, lastpreg = 6;
2600 for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
2602 rtx t = XVECEXP (op, 0, i);
2606 if (GET_CODE (t) != SET)
2610 dest = SET_DEST (t);
2611 if (GET_CODE (src) != MEM || ! REG_P (dest))
2613 src = XEXP (src, 0);
2617 if (! REG_P (src) || REGNO (src) != REG_SP)
2620 else if (GET_CODE (src) != PLUS
2621 || ! REG_P (XEXP (src, 0))
2622 || REGNO (XEXP (src, 0)) != REG_SP
2623 || GET_CODE (XEXP (src, 1)) != CONST_INT
2624 || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
2627 regno = REGNO (dest);
2630 if (regno == REG_R7)
2635 else if (regno != REG_P0 + lastpreg - 1)
2640 else if (group == 1)
2642 if (regno != REG_R0 + lastdreg - 1)
2648 first_dreg_to_save = lastdreg;
2649 first_preg_to_save = lastpreg;
2653 /* Emit assembly code for one multi-register push described by INSN, with
2654 operands in OPERANDS. */
2657 output_push_multiple (rtx insn, rtx *operands)
2662 /* Validate the insn again, and compute first_[dp]reg_to_save. */
2663 ok = push_multiple_operation (PATTERN (insn), VOIDmode);
2666 if (first_dreg_to_save == 8)
2667 sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
2668 else if (first_preg_to_save == 6)
2669 sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
2671 sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
2672 first_dreg_to_save, first_preg_to_save);
2674 output_asm_insn (buf, operands);
2677 /* Emit assembly code for one multi-register pop described by INSN, with
2678 operands in OPERANDS. */
2681 output_pop_multiple (rtx insn, rtx *operands)
2686 /* Validate the insn again, and compute first_[dp]reg_to_save. */
2687 ok = pop_multiple_operation (PATTERN (insn), VOIDmode);
2690 if (first_dreg_to_save == 8)
2691 sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
2692 else if (first_preg_to_save == 6)
2693 sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
2695 sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
2696 first_dreg_to_save, first_preg_to_save);
2698 output_asm_insn (buf, operands);
2701 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE. */
2704 single_move_for_movmem (rtx dst, rtx src, enum machine_mode mode, HOST_WIDE_INT offset)
2706 rtx scratch = gen_reg_rtx (mode);
2709 srcmem = adjust_address_nv (src, mode, offset);
2710 dstmem = adjust_address_nv (dst, mode, offset);
2711 emit_move_insn (scratch, srcmem);
2712 emit_move_insn (dstmem, scratch);
2715 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
2716 alignment ALIGN_EXP. Return true if successful, false if we should fall
2717 back on a different method. */
2720 bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
2722 rtx srcreg, destreg, countreg;
2723 HOST_WIDE_INT align = 0;
2724 unsigned HOST_WIDE_INT count = 0;
2726 if (GET_CODE (align_exp) == CONST_INT)
2727 align = INTVAL (align_exp);
2728 if (GET_CODE (count_exp) == CONST_INT)
2730 count = INTVAL (count_exp);
2732 if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
2737 /* If optimizing for size, only do single copies inline. */
2740 if (count == 2 && align < 2)
2742 if (count == 4 && align < 4)
2744 if (count != 1 && count != 2 && count != 4)
2747 if (align < 2 && count != 1)
2750 destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
2751 if (destreg != XEXP (dst, 0))
2752 dst = replace_equiv_address_nv (dst, destreg);
2753 srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
2754 if (srcreg != XEXP (src, 0))
2755 src = replace_equiv_address_nv (src, srcreg);
2757 if (count != 0 && align >= 2)
2759 unsigned HOST_WIDE_INT offset = 0;
2763 if ((count & ~3) == 4)
2765 single_move_for_movmem (dst, src, SImode, offset);
2768 else if (count & ~3)
2770 HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
2771 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
2773 emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
2777 single_move_for_movmem (dst, src, HImode, offset);
2783 if ((count & ~1) == 2)
2785 single_move_for_movmem (dst, src, HImode, offset);
2788 else if (count & ~1)
2790 HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
2791 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
2793 emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
2798 single_move_for_movmem (dst, src, QImode, offset);
2807 bfin_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
2809 enum attr_type insn_type, dep_insn_type;
2810 int dep_insn_code_number;
2812 /* Anti and output dependencies have zero cost. */
2813 if (REG_NOTE_KIND (link) != 0)
2816 dep_insn_code_number = recog_memoized (dep_insn);
2818 /* If we can't recognize the insns, we can't really do anything. */
2819 if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
2822 insn_type = get_attr_type (insn);
2823 dep_insn_type = get_attr_type (dep_insn);
2825 if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)
2827 rtx pat = PATTERN (dep_insn);
2828 rtx dest = SET_DEST (pat);
2829 rtx src = SET_SRC (pat);
2830 if (! ADDRESS_REGNO_P (REGNO (dest)) || ! D_REGNO_P (REGNO (src)))
2832 return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);
2839 /* Increment the counter for the number of loop instructions in the
2840 current function. */
2843 bfin_hardware_loop (void)
2845 cfun->machine->has_hardware_loops++;
2848 /* Maximum loop nesting depth. */
2849 #define MAX_LOOP_DEPTH 2
2851 /* Maximum size of a loop. */
2852 #define MAX_LOOP_LENGTH 2042
2854 /* We need to keep a vector of loops */
2855 typedef struct loop_info *loop_info;
2856 DEF_VEC_P (loop_info);
2857 DEF_VEC_ALLOC_P (loop_info,heap);
2859 /* Information about a loop we have found (or are in the process of
2861 struct loop_info GTY (())
2863 /* loop number, for dumps */
2866 /* Predecessor block of the loop. This is the one that falls into
2867 the loop and contains the initialization instruction. */
2868 basic_block predecessor;
2870 /* First block in the loop. This is the one branched to by the loop_end
2874 /* Last block in the loop (the one with the loop_end insn). */
2877 /* The successor block of the loop. This is the one the loop_end insn
2879 basic_block successor;
2881 /* The last instruction in the tail. */
2884 /* The loop_end insn. */
2887 /* The iteration register. */
2890 /* The new initialization insn. */
2893 /* The new initialization instruction. */
2896 /* The new label placed at the beginning of the loop. */
2899 /* The new label placed at the end of the loop. */
2902 /* The length of the loop. */
2905 /* The nesting depth of the loop. */
2908 /* Nonzero if we can't optimize this loop. */
2911 /* True if we have visited this loop. */
2914 /* True if this loop body clobbers any of LC0, LT0, or LB0. */
2917 /* True if this loop body clobbers any of LC1, LT1, or LB1. */
2920 /* Next loop in the graph. */
2921 struct loop_info *next;
2923 /* Immediate outer loop of this loop. */
2924 struct loop_info *outer;
2926 /* Vector of blocks only within the loop, including those within
2928 VEC (basic_block,heap) *blocks;
2930 /* Same information in a bitmap. */
2931 bitmap block_bitmap;
2933 /* Vector of inner loops within this loop */
2934 VEC (loop_info,heap) *loops;
2938 bfin_dump_loops (loop_info loops)
2942 for (loop = loops; loop; loop = loop->next)
2948 fprintf (dump_file, ";; loop %d: ", loop->loop_no);
2950 fprintf (dump_file, "(bad) ");
2951 fprintf (dump_file, "{head:%d, depth:%d}", loop->head->index, loop->depth);
2953 fprintf (dump_file, " blocks: [ ");
2954 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, b); ix++)
2955 fprintf (dump_file, "%d ", b->index);
2956 fprintf (dump_file, "] ");
2958 fprintf (dump_file, " inner loops: [ ");
2959 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, i); ix++)
2960 fprintf (dump_file, "%d ", i->loop_no);
2961 fprintf (dump_file, "]\n");
2963 fprintf (dump_file, "\n");
2966 /* Scan the blocks of LOOP (and its inferiors) looking for basic block
2967 BB. Return true, if we find it. */
2970 bfin_bb_in_loop (loop_info loop, basic_block bb)
2972 return bitmap_bit_p (loop->block_bitmap, bb->index);
2975 /* Scan the blocks of LOOP (and its inferiors) looking for uses of
2976 REG. Return true, if we find any. Don't count the loop's loop_end
2977 insn if it matches LOOP_END. */
2980 bfin_scan_loop (loop_info loop, rtx reg, rtx loop_end)
2985 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
2989 for (insn = BB_HEAD (bb);
2990 insn != NEXT_INSN (BB_END (bb));
2991 insn = NEXT_INSN (insn))
2995 if (insn == loop_end)
2997 if (reg_mentioned_p (reg, PATTERN (insn)))
3004 /* Optimize LOOP. */
3007 bfin_optimize_loop (loop_info loop)
3011 rtx insn, init_insn, last_insn, nop_insn;
3012 rtx loop_init, start_label, end_label;
3013 rtx reg_lc0, reg_lc1, reg_lt0, reg_lt1, reg_lb0, reg_lb1;
3015 rtx lc_reg, lt_reg, lb_reg;
3019 int inner_depth = 0;
3029 fprintf (dump_file, ";; loop %d bad when found\n", loop->loop_no);
3033 /* Every loop contains in its list of inner loops every loop nested inside
3034 it, even if there are intermediate loops. This works because we're doing
3035 a depth-first search here and never visit a loop more than once. */
3036 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, inner); ix++)
3038 bfin_optimize_loop (inner);
3040 if (!inner->bad && inner_depth < inner->depth)
3042 inner_depth = inner->depth;
3044 loop->clobber_loop0 |= inner->clobber_loop0;
3045 loop->clobber_loop1 |= inner->clobber_loop1;
3049 loop->depth = inner_depth + 1;
3050 if (loop->depth > MAX_LOOP_DEPTH)
3053 fprintf (dump_file, ";; loop %d too deep\n", loop->loop_no);
3057 /* Get the loop iteration register. */
3058 iter_reg = loop->iter_reg;
3060 if (!DPREG_P (iter_reg))
3063 fprintf (dump_file, ";; loop %d iteration count NOT in PREG or DREG\n",
3068 /* Check if start_label appears before loop_end and calculate the
3069 offset between them. We calculate the length of instructions
3072 for (insn = loop->start_label;
3073 insn && insn != loop->loop_end;
3074 insn = NEXT_INSN (insn))
3076 if (JUMP_P (insn) && any_condjump_p (insn) && !optimize_size)
3078 if (TARGET_CSYNC_ANOMALY)
3080 else if (TARGET_SPECLD_ANOMALY)
3083 else if (LABEL_P (insn))
3085 if (TARGET_CSYNC_ANOMALY)
3090 length += get_attr_length (insn);
3096 fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
3101 loop->length = length;
3102 if (loop->length > MAX_LOOP_LENGTH)
3105 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
3109 /* Scan all the blocks to make sure they don't use iter_reg. */
3110 if (bfin_scan_loop (loop, iter_reg, loop->loop_end))
3113 fprintf (dump_file, ";; loop %d uses iterator\n", loop->loop_no);
3117 /* Scan all the insns to see if the loop body clobber
3118 any hardware loop registers. */
3120 reg_lc0 = gen_rtx_REG (SImode, REG_LC0);
3121 reg_lc1 = gen_rtx_REG (SImode, REG_LC1);
3122 reg_lt0 = gen_rtx_REG (SImode, REG_LT0);
3123 reg_lt1 = gen_rtx_REG (SImode, REG_LT1);
3124 reg_lb0 = gen_rtx_REG (SImode, REG_LB0);
3125 reg_lb1 = gen_rtx_REG (SImode, REG_LB1);
3127 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
3131 for (insn = BB_HEAD (bb);
3132 insn != NEXT_INSN (BB_END (bb));
3133 insn = NEXT_INSN (insn))
3138 if (reg_set_p (reg_lc0, insn)
3139 || reg_set_p (reg_lt0, insn)
3140 || reg_set_p (reg_lb0, insn))
3141 loop->clobber_loop0 = 1;
3143 if (reg_set_p (reg_lc1, insn)
3144 || reg_set_p (reg_lt1, insn)
3145 || reg_set_p (reg_lb1, insn))
3146 loop->clobber_loop1 |= 1;
3150 if ((loop->clobber_loop0 && loop->clobber_loop1)
3151 || (loop->depth == MAX_LOOP_DEPTH && loop->clobber_loop0))
3153 loop->depth = MAX_LOOP_DEPTH + 1;
3155 fprintf (dump_file, ";; loop %d no loop reg available\n",
3160 /* There should be an instruction before the loop_end instruction
3161 in the same basic block. And the instruction must not be
3163 - CONDITIONAL BRANCH
3167 - Returns (RTS, RTN, etc.) */
3170 last_insn = PREV_INSN (loop->loop_end);
3174 for (; last_insn != PREV_INSN (BB_HEAD (bb));
3175 last_insn = PREV_INSN (last_insn))
3176 if (INSN_P (last_insn))
3179 if (last_insn != PREV_INSN (BB_HEAD (bb)))
3182 if (single_pred_p (bb)
3183 && single_pred (bb) != ENTRY_BLOCK_PTR)
3185 bb = single_pred (bb);
3186 last_insn = BB_END (bb);
3191 last_insn = NULL_RTX;
3199 fprintf (dump_file, ";; loop %d has no last instruction\n",
3204 if (JUMP_P (last_insn))
3206 loop_info inner = bb->aux;
3208 && inner->outer == loop
3209 && inner->loop_end == last_insn
3210 && inner->depth == 1)
3211 /* This jump_insn is the exact loop_end of an inner loop
3212 and to be optimized away. So use the inner's last_insn. */
3213 last_insn = inner->last_insn;
3217 fprintf (dump_file, ";; loop %d has bad last instruction\n",
3222 else if (CALL_P (last_insn)
3223 || get_attr_type (last_insn) == TYPE_SYNC
3224 || recog_memoized (last_insn) == CODE_FOR_return_internal)
3227 fprintf (dump_file, ";; loop %d has bad last instruction\n",
3232 if (GET_CODE (PATTERN (last_insn)) == ASM_INPUT
3233 || asm_noperands (PATTERN (last_insn)) >= 0
3234 || get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI)
3236 nop_insn = emit_insn_after (gen_nop (), last_insn);
3237 last_insn = nop_insn;
3240 loop->last_insn = last_insn;
3242 /* The loop is good for replacement. */
3243 start_label = loop->start_label;
3244 end_label = gen_label_rtx ();
3245 iter_reg = loop->iter_reg;
3247 if (loop->depth == 1 && !loop->clobber_loop1)
3252 loop->clobber_loop1 = 1;
3259 loop->clobber_loop0 = 1;
3262 /* If iter_reg is a DREG, we need generate an instruction to load
3263 the loop count into LC register. */
3264 if (D_REGNO_P (REGNO (iter_reg)))
3266 init_insn = gen_movsi (lc_reg, iter_reg);
3267 loop_init = gen_lsetup_without_autoinit (lt_reg, start_label,
3271 else if (P_REGNO_P (REGNO (iter_reg)))
3273 init_insn = NULL_RTX;
3274 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
3281 loop->init = init_insn;
3282 loop->end_label = end_label;
3283 loop->loop_init = loop_init;
3287 fprintf (dump_file, ";; replacing loop %d initializer with\n",
3289 print_rtl_single (dump_file, loop->loop_init);
3290 fprintf (dump_file, ";; replacing loop %d terminator with\n",
3292 print_rtl_single (dump_file, loop->loop_end);
3297 if (loop->init != NULL_RTX)
3298 emit_insn (loop->init);
3299 emit_insn(loop->loop_init);
3300 emit_label (loop->start_label);
3305 emit_insn_after (seq, BB_END (loop->predecessor));
3306 delete_insn (loop->loop_end);
3308 /* Insert the loop end label before the last instruction of the loop. */
3309 emit_label_before (loop->end_label, loop->last_insn);
3316 fprintf (dump_file, ";; loop %d is bad\n", loop->loop_no);
3320 if (DPREG_P (loop->iter_reg))
3322 /* If loop->iter_reg is a DREG or PREG, we can split it here
3323 without scratch register. */
3326 emit_insn_before (gen_addsi3 (loop->iter_reg,
3331 emit_insn_before (gen_cmpsi (loop->iter_reg, const0_rtx),
3334 insn = emit_jump_insn_before (gen_bne (loop->start_label),
3337 JUMP_LABEL (insn) = loop->start_label;
3338 LABEL_NUSES (loop->start_label)++;
3339 delete_insn (loop->loop_end);
3343 /* Called from bfin_reorg_loops when a potential loop end is found. LOOP is
3344 a newly set up structure describing the loop, it is this function's
3345 responsibility to fill most of it. TAIL_BB and TAIL_INSN point to the
3346 loop_end insn and its enclosing basic block. */
3349 bfin_discover_loop (loop_info loop, basic_block tail_bb, rtx tail_insn)
3353 VEC (basic_block,heap) *works = VEC_alloc (basic_block,heap,20);
3355 loop->tail = tail_bb;
3356 loop->head = BRANCH_EDGE (tail_bb)->dest;
3357 loop->successor = FALLTHRU_EDGE (tail_bb)->dest;
3358 loop->predecessor = NULL;
3359 loop->loop_end = tail_insn;
3360 loop->last_insn = NULL_RTX;
3361 loop->iter_reg = SET_DEST (XVECEXP (PATTERN (tail_insn), 0, 1));
3362 loop->depth = loop->length = 0;
3364 loop->clobber_loop0 = loop->clobber_loop1 = 0;
3368 loop->init = loop->loop_init = NULL_RTX;
3369 loop->start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (tail_insn), 0, 0)), 1), 0);
3370 loop->end_label = NULL_RTX;
3373 VEC_safe_push (basic_block, heap, works, loop->head);
3375 while (VEC_iterate (basic_block, works, dwork++, bb))
3379 if (bb == EXIT_BLOCK_PTR)
3381 /* We've reached the exit block. The loop must be bad. */
3384 ";; Loop is bad - reached exit block while scanning\n");
3389 if (bitmap_bit_p (loop->block_bitmap, bb->index))
3392 /* We've not seen this block before. Add it to the loop's
3393 list and then add each successor to the work list. */
3395 VEC_safe_push (basic_block, heap, loop->blocks, bb);
3396 bitmap_set_bit (loop->block_bitmap, bb->index);
3400 FOR_EACH_EDGE (e, ei, bb->succs)
3402 basic_block succ = EDGE_SUCC (bb, ei.index)->dest;
3403 if (!REGNO_REG_SET_P (succ->il.rtl->global_live_at_start,
3404 REGNO (loop->iter_reg)))
3406 if (!VEC_space (basic_block, works, 1))
3410 VEC_block_remove (basic_block, works, 0, dwork);
3414 VEC_reserve (basic_block, heap, works, 1);
3416 VEC_quick_push (basic_block, works, succ);
3423 /* Make sure we only have one entry point. */
3424 if (EDGE_COUNT (loop->head->preds) == 2)
3426 loop->predecessor = EDGE_PRED (loop->head, 0)->src;
3427 if (loop->predecessor == loop->tail)
3428 /* We wanted the other predecessor. */
3429 loop->predecessor = EDGE_PRED (loop->head, 1)->src;
3431 /* We can only place a loop insn on a fall through edge of a
3432 single exit block. */
3433 if (EDGE_COUNT (loop->predecessor->succs) != 1
3434 || !(EDGE_SUCC (loop->predecessor, 0)->flags & EDGE_FALLTHRU)
3435 /* If loop->predecessor is in loop, loop->head is not really
3436 the head of the loop. */
3437 || bfin_bb_in_loop (loop, loop->predecessor))
3438 loop->predecessor = NULL;
3441 if (loop->predecessor == NULL)
3444 fprintf (dump_file, ";; loop has bad predecessor\n");
3449 #ifdef ENABLE_CHECKING
3450 /* Make sure nothing jumps into this loop. This shouldn't happen as we
3451 wouldn't have generated the counted loop patterns in such a case.
3452 However, this test must be done after the test above to detect loops
3453 with invalid headers. */
3455 for (dwork = 0; VEC_iterate (basic_block, loop->blocks, dwork, bb); dwork++)
3459 if (bb == loop->head)
3461 FOR_EACH_EDGE (e, ei, bb->preds)
3463 basic_block pred = EDGE_PRED (bb, ei.index)->src;
3464 if (!bfin_bb_in_loop (loop, pred))
3469 VEC_free (basic_block, heap, works);
3473 bfin_reorg_loops (FILE *dump_file)
3475 bitmap_obstack stack;
3478 loop_info loops = NULL;
3482 bitmap_obstack_initialize (&stack);
3484 /* Find all the possible loop tails. This means searching for every
3485 loop_end instruction. For each one found, create a loop_info
3486 structure and add the head block to the work list. */
3489 rtx tail = BB_END (bb);
3491 while (GET_CODE (tail) == NOTE)
3492 tail = PREV_INSN (tail);
3496 if (INSN_P (tail) && recog_memoized (tail) == CODE_FOR_loop_end)
3498 /* A possible loop end */
3500 loop = XNEW (struct loop_info);
3503 loop->loop_no = nloops++;
3504 loop->blocks = VEC_alloc (basic_block, heap, 20);
3505 loop->block_bitmap = BITMAP_ALLOC (&stack);
3510 fprintf (dump_file, ";; potential loop %d ending at\n",
3512 print_rtl_single (dump_file, tail);
3515 bfin_discover_loop (loop, bb, tail);
3519 tmp_bitmap = BITMAP_ALLOC (&stack);
3520 /* Compute loop nestings. */
3521 for (loop = loops; loop; loop = loop->next)
3527 for (other = loop->next; other; other = other->next)
3532 bitmap_and (tmp_bitmap, other->block_bitmap, loop->block_bitmap);
3533 if (bitmap_empty_p (tmp_bitmap))
3535 if (bitmap_equal_p (tmp_bitmap, other->block_bitmap))
3537 other->outer = loop;
3538 VEC_safe_push (loop_info, heap, loop->loops, other);
3540 else if (bitmap_equal_p (tmp_bitmap, loop->block_bitmap))
3542 loop->outer = other;
3543 VEC_safe_push (loop_info, heap, other->loops, loop);
3547 loop->bad = other->bad = 1;
3551 BITMAP_FREE (tmp_bitmap);
3555 fprintf (dump_file, ";; All loops found:\n\n");
3556 bfin_dump_loops (loops);
3559 /* Now apply the optimizations. */
3560 for (loop = loops; loop; loop = loop->next)
3561 bfin_optimize_loop (loop);
3565 fprintf (dump_file, ";; After hardware loops optimization:\n\n");
3566 bfin_dump_loops (loops);
3569 /* Free up the loop structures */
3574 VEC_free (loop_info, heap, loop->loops);
3575 VEC_free (basic_block, heap, loop->blocks);
3576 BITMAP_FREE (loop->block_bitmap);
3581 print_rtl (dump_file, get_insns ());
3585 /* We use the machine specific reorg pass for emitting CSYNC instructions
3586 after conditional branches as needed.
3588 The Blackfin is unusual in that a code sequence like
3591 may speculatively perform the load even if the condition isn't true. This
3592 happens for a branch that is predicted not taken, because the pipeline
3593 isn't flushed or stalled, so the early stages of the following instructions,
3594 which perform the memory reference, are allowed to execute before the
3595 jump condition is evaluated.
3596 Therefore, we must insert additional instructions in all places where this
3597 could lead to incorrect behavior. The manual recommends CSYNC, while
3598 VDSP seems to use NOPs (even though its corresponding compiler option is
3601 When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
3602 When optimizing for size, we turn the branch into a predicted taken one.
3603 This may be slower due to mispredicts, but saves code size. */
3608 rtx insn, last_condjump = NULL_RTX;
3609 int cycles_since_jump = INT_MAX;
3611 /* Doloop optimization */
3612 if (cfun->machine->has_hardware_loops)
3613 bfin_reorg_loops (dump_file);
3615 if (! TARGET_SPECLD_ANOMALY && ! TARGET_CSYNC_ANOMALY)
3618 /* First pass: find predicted-false branches; if something after them
3619 needs nops, insert them or change the branch to predict true. */
3620 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
3624 if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
3627 pat = PATTERN (insn);
3628 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
3629 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
3630 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
3635 if (any_condjump_p (insn)
3636 && ! cbranch_predicted_taken_p (insn))
3638 last_condjump = insn;
3639 cycles_since_jump = 0;
3642 cycles_since_jump = INT_MAX;
3644 else if (INSN_P (insn))
3646 enum attr_type type = get_attr_type (insn);
3647 int delay_needed = 0;
3648 if (cycles_since_jump < INT_MAX)
3649 cycles_since_jump++;
3651 if (type == TYPE_MCLD && TARGET_SPECLD_ANOMALY)
3653 rtx pat = single_set (insn);
3654 if (may_trap_p (SET_SRC (pat)))
3657 else if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
3660 if (delay_needed > cycles_since_jump)
3664 rtx *op = recog_data.operand;
3666 delay_needed -= cycles_since_jump;
3668 extract_insn (last_condjump);
3671 pat = gen_cbranch_predicted_taken (op[0], op[1], op[2],
3673 cycles_since_jump = INT_MAX;
3676 /* Do not adjust cycles_since_jump in this case, so that
3677 we'll increase the number of NOPs for a subsequent insn
3679 pat = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
3680 GEN_INT (delay_needed));
3681 PATTERN (last_condjump) = pat;
3682 INSN_CODE (last_condjump) = recog (pat, insn, &num_clobbers);
3686 /* Second pass: for predicted-true branches, see if anything at the
3687 branch destination needs extra nops. */
3688 if (! TARGET_CSYNC_ANOMALY)
3691 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
3694 && any_condjump_p (insn)
3695 && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken
3696 || cbranch_predicted_taken_p (insn)))
3698 rtx target = JUMP_LABEL (insn);
3700 cycles_since_jump = 0;
3701 for (; target && cycles_since_jump < 3; target = NEXT_INSN (target))
3705 if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
3708 pat = PATTERN (target);
3709 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
3710 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
3711 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
3714 if (INSN_P (target))
3716 enum attr_type type = get_attr_type (target);
3717 int delay_needed = 0;
3718 if (cycles_since_jump < INT_MAX)
3719 cycles_since_jump++;
3721 if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
3724 if (delay_needed > cycles_since_jump)
3726 rtx prev = prev_real_insn (label);
3727 delay_needed -= cycles_since_jump;
3729 fprintf (dump_file, "Adding %d nops after %d\n",
3730 delay_needed, INSN_UID (label));
3732 && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops)
3739 "Reducing nops on insn %d.\n",
3742 x = XVECEXP (x, 0, 1);
3743 v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed;
3744 XVECEXP (x, 0, 0) = GEN_INT (v);
3746 while (delay_needed-- > 0)
3747 emit_insn_after (gen_nop (), label);
3756 /* Handle interrupt_handler, exception_handler and nmi_handler function
3757 attributes; arguments as in struct attribute_spec.handler. */
3760 handle_int_attribute (tree *node, tree name,
3761 tree args ATTRIBUTE_UNUSED,
3762 int flags ATTRIBUTE_UNUSED,
3766 if (TREE_CODE (x) == FUNCTION_DECL)
3769 if (TREE_CODE (x) != FUNCTION_TYPE)
3771 warning (OPT_Wattributes, "%qs attribute only applies to functions",
3772 IDENTIFIER_POINTER (name));
3773 *no_add_attrs = true;
3775 else if (funkind (x) != SUBROUTINE)
3776 error ("multiple function type attributes specified");
3781 /* Return 0 if the attributes for two types are incompatible, 1 if they
3782 are compatible, and 2 if they are nearly compatible (which causes a
3783 warning to be generated). */
3786 bfin_comp_type_attributes (tree type1, tree type2)
3788 e_funkind kind1, kind2;
3790 if (TREE_CODE (type1) != FUNCTION_TYPE)
3793 kind1 = funkind (type1);
3794 kind2 = funkind (type2);
3799 /* Check for mismatched modifiers */
3800 if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
3801 != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
3804 if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
3805 != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
3808 if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
3809 != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
3812 if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1))
3813 != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2)))
3819 /* Handle a "longcall" or "shortcall" attribute; arguments as in
3820 struct attribute_spec.handler. */
3823 bfin_handle_longcall_attribute (tree *node, tree name,
3824 tree args ATTRIBUTE_UNUSED,
3825 int flags ATTRIBUTE_UNUSED,
3828 if (TREE_CODE (*node) != FUNCTION_TYPE
3829 && TREE_CODE (*node) != FIELD_DECL
3830 && TREE_CODE (*node) != TYPE_DECL)
3832 warning (OPT_Wattributes, "`%s' attribute only applies to functions",
3833 IDENTIFIER_POINTER (name));
3834 *no_add_attrs = true;
3837 if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0
3838 && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node)))
3839 || (strcmp (IDENTIFIER_POINTER (name), "shortcall") == 0
3840 && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node))))
3842 warning (OPT_Wattributes,
3843 "can't apply both longcall and shortcall attributes to the same function");
3844 *no_add_attrs = true;
3850 /* Table of valid machine attributes. */
3851 const struct attribute_spec bfin_attribute_table[] =
3853 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
3854 { "interrupt_handler", 0, 0, false, true, true, handle_int_attribute },
3855 { "exception_handler", 0, 0, false, true, true, handle_int_attribute },
3856 { "nmi_handler", 0, 0, false, true, true, handle_int_attribute },
3857 { "nesting", 0, 0, false, true, true, NULL },
3858 { "kspisusp", 0, 0, false, true, true, NULL },
3859 { "saveall", 0, 0, false, true, true, NULL },
3860 { "longcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
3861 { "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
3862 { NULL, 0, 0, false, false, false, NULL }
3865 /* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to
3866 tell the assembler to generate pointers to function descriptors in
3870 bfin_assemble_integer (rtx value, unsigned int size, int aligned_p)
3872 if (TARGET_FDPIC && size == UNITS_PER_WORD)
3874 if (GET_CODE (value) == SYMBOL_REF
3875 && SYMBOL_REF_FUNCTION_P (value))
3877 fputs ("\t.picptr\tfuncdesc(", asm_out_file);
3878 output_addr_const (asm_out_file, value);
3879 fputs (")\n", asm_out_file);
3884 /* We've set the unaligned SI op to NULL, so we always have to
3885 handle the unaligned case here. */
3886 assemble_integer_with_op ("\t.4byte\t", value);
3890 return default_assemble_integer (value, size, aligned_p);
3893 /* Output the assembler code for a thunk function. THUNK_DECL is the
3894 declaration for the thunk function itself, FUNCTION is the decl for
3895 the target function. DELTA is an immediate constant offset to be
3896 added to THIS. If VCALL_OFFSET is nonzero, the word at
3897 *(*this + vcall_offset) should be added to THIS. */
3900 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
3901 tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
3902 HOST_WIDE_INT vcall_offset, tree function)
3905 /* The this parameter is passed as the first argument. */
3906 rtx this = gen_rtx_REG (Pmode, REG_R0);
3908 /* Adjust the this parameter by a fixed constant. */
3912 if (delta >= -64 && delta <= 63)
3914 xops[0] = GEN_INT (delta);
3915 output_asm_insn ("%1 += %0;", xops);
3917 else if (delta >= -128 && delta < -64)
3919 xops[0] = GEN_INT (delta + 64);
3920 output_asm_insn ("%1 += -64; %1 += %0;", xops);
3922 else if (delta > 63 && delta <= 126)
3924 xops[0] = GEN_INT (delta - 63);
3925 output_asm_insn ("%1 += 63; %1 += %0;", xops);
3929 xops[0] = GEN_INT (delta);
3930 output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
3934 /* Adjust the this parameter by a value stored in the vtable. */
3937 rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
3938 rtx tmp = gen_rtx_REG (Pmode, REG_R2);
3942 output_asm_insn ("%2 = r0; %2 = [%2];", xops);
3944 /* Adjust the this parameter. */
3945 xops[0] = gen_rtx_MEM (Pmode, plus_constant (p2tmp, vcall_offset));
3946 if (!memory_operand (xops[0], Pmode))
3948 rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
3949 xops[0] = GEN_INT (vcall_offset);
3951 output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
3952 xops[0] = gen_rtx_MEM (Pmode, p2tmp);
3955 output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
3958 xops[0] = XEXP (DECL_RTL (function), 0);
3959 if (1 || !flag_pic || (*targetm.binds_local_p) (function))
3960 output_asm_insn ("jump.l\t%P0", xops);
3963 /* Codes for all the Blackfin builtins. */
3968 BFIN_BUILTIN_COMPOSE_2X16,
3969 BFIN_BUILTIN_EXTRACTLO,
3970 BFIN_BUILTIN_EXTRACTHI,
3972 BFIN_BUILTIN_SSADD_2X16,
3973 BFIN_BUILTIN_SSSUB_2X16,
3974 BFIN_BUILTIN_SSADDSUB_2X16,
3975 BFIN_BUILTIN_SSSUBADD_2X16,
3976 BFIN_BUILTIN_MULT_2X16,
3977 BFIN_BUILTIN_MULTR_2X16,
3978 BFIN_BUILTIN_NEG_2X16,
3979 BFIN_BUILTIN_ABS_2X16,
3980 BFIN_BUILTIN_MIN_2X16,
3981 BFIN_BUILTIN_MAX_2X16,
3983 BFIN_BUILTIN_SSADD_1X16,
3984 BFIN_BUILTIN_SSSUB_1X16,
3985 BFIN_BUILTIN_MULT_1X16,
3986 BFIN_BUILTIN_MULTR_1X16,
3987 BFIN_BUILTIN_NORM_1X16,
3988 BFIN_BUILTIN_NEG_1X16,
3989 BFIN_BUILTIN_ABS_1X16,
3990 BFIN_BUILTIN_MIN_1X16,
3991 BFIN_BUILTIN_MAX_1X16,
3993 BFIN_BUILTIN_DIFFHL_2X16,
3994 BFIN_BUILTIN_DIFFLH_2X16,
3996 BFIN_BUILTIN_SSADD_1X32,
3997 BFIN_BUILTIN_SSSUB_1X32,
3998 BFIN_BUILTIN_NORM_1X32,
3999 BFIN_BUILTIN_NEG_1X32,
4000 BFIN_BUILTIN_MIN_1X32,
4001 BFIN_BUILTIN_MAX_1X32,
4002 BFIN_BUILTIN_MULT_1X32,
4004 BFIN_BUILTIN_MULHISILL,
4005 BFIN_BUILTIN_MULHISILH,
4006 BFIN_BUILTIN_MULHISIHL,
4007 BFIN_BUILTIN_MULHISIHH,
4009 BFIN_BUILTIN_LSHIFT_1X16,
4010 BFIN_BUILTIN_LSHIFT_2X16,
4011 BFIN_BUILTIN_SSASHIFT_1X16,
4012 BFIN_BUILTIN_SSASHIFT_2X16,
4014 BFIN_BUILTIN_CPLX_MUL_16,
4015 BFIN_BUILTIN_CPLX_MAC_16,
4016 BFIN_BUILTIN_CPLX_MSU_16,
4021 #define def_builtin(NAME, TYPE, CODE) \
4023 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
4027 /* Set up all builtin functions for this target. */
4029 bfin_init_builtins (void)
4031 tree V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
4032 tree void_ftype_void
4033 = build_function_type (void_type_node, void_list_node);
4034 tree short_ftype_short
4035 = build_function_type_list (short_integer_type_node, short_integer_type_node,
4037 tree short_ftype_int_int
4038 = build_function_type_list (short_integer_type_node, integer_type_node,
4039 integer_type_node, NULL_TREE);
4040 tree int_ftype_int_int
4041 = build_function_type_list (integer_type_node, integer_type_node,
4042 integer_type_node, NULL_TREE);
4044 = build_function_type_list (integer_type_node, integer_type_node,
4046 tree short_ftype_int
4047 = build_function_type_list (short_integer_type_node, integer_type_node,
4049 tree int_ftype_v2hi_v2hi
4050 = build_function_type_list (integer_type_node, V2HI_type_node,
4051 V2HI_type_node, NULL_TREE);
4052 tree v2hi_ftype_v2hi_v2hi
4053 = build_function_type_list (V2HI_type_node, V2HI_type_node,
4054 V2HI_type_node, NULL_TREE);
4055 tree v2hi_ftype_v2hi_v2hi_v2hi
4056 = build_function_type_list (V2HI_type_node, V2HI_type_node,
4057 V2HI_type_node, V2HI_type_node, NULL_TREE);
4058 tree v2hi_ftype_int_int
4059 = build_function_type_list (V2HI_type_node, integer_type_node,
4060 integer_type_node, NULL_TREE);
4061 tree v2hi_ftype_v2hi_int
4062 = build_function_type_list (V2HI_type_node, V2HI_type_node,
4063 integer_type_node, NULL_TREE);
4064 tree int_ftype_short_short
4065 = build_function_type_list (integer_type_node, short_integer_type_node,
4066 short_integer_type_node, NULL_TREE);
4067 tree v2hi_ftype_v2hi
4068 = build_function_type_list (V2HI_type_node, V2HI_type_node, NULL_TREE);
4069 tree short_ftype_v2hi
4070 = build_function_type_list (short_integer_type_node, V2HI_type_node,
4073 /* Add the remaining MMX insns with somewhat more complicated types. */
4074 def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC);
4075 def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC);
4077 def_builtin ("__builtin_bfin_compose_2x16", v2hi_ftype_int_int,
4078 BFIN_BUILTIN_COMPOSE_2X16);
4079 def_builtin ("__builtin_bfin_extract_hi", short_ftype_v2hi,
4080 BFIN_BUILTIN_EXTRACTHI);
4081 def_builtin ("__builtin_bfin_extract_lo", short_ftype_v2hi,
4082 BFIN_BUILTIN_EXTRACTLO);
4084 def_builtin ("__builtin_bfin_min_fr2x16", v2hi_ftype_v2hi_v2hi,
4085 BFIN_BUILTIN_MIN_2X16);
4086 def_builtin ("__builtin_bfin_max_fr2x16", v2hi_ftype_v2hi_v2hi,
4087 BFIN_BUILTIN_MAX_2X16);
4089 def_builtin ("__builtin_bfin_add_fr2x16", v2hi_ftype_v2hi_v2hi,
4090 BFIN_BUILTIN_SSADD_2X16);
4091 def_builtin ("__builtin_bfin_sub_fr2x16", v2hi_ftype_v2hi_v2hi,
4092 BFIN_BUILTIN_SSSUB_2X16);
4093 def_builtin ("__builtin_bfin_dspaddsubsat", v2hi_ftype_v2hi_v2hi,
4094 BFIN_BUILTIN_SSADDSUB_2X16);
4095 def_builtin ("__builtin_bfin_dspsubaddsat", v2hi_ftype_v2hi_v2hi,
4096 BFIN_BUILTIN_SSSUBADD_2X16);
4097 def_builtin ("__builtin_bfin_mult_fr2x16", v2hi_ftype_v2hi_v2hi,
4098 BFIN_BUILTIN_MULT_2X16);
4099 def_builtin ("__builtin_bfin_multr_fr2x16", v2hi_ftype_v2hi_v2hi,
4100 BFIN_BUILTIN_MULTR_2X16);
4101 def_builtin ("__builtin_bfin_negate_fr2x16", v2hi_ftype_v2hi,
4102 BFIN_BUILTIN_NEG_2X16);
4103 def_builtin ("__builtin_bfin_abs_fr2x16", v2hi_ftype_v2hi,
4104 BFIN_BUILTIN_ABS_2X16);
4106 def_builtin ("__builtin_bfin_add_fr1x16", short_ftype_int_int,
4107 BFIN_BUILTIN_SSADD_1X16);
4108 def_builtin ("__builtin_bfin_sub_fr1x16", short_ftype_int_int,
4109 BFIN_BUILTIN_SSSUB_1X16);
4110 def_builtin ("__builtin_bfin_mult_fr1x16", short_ftype_int_int,
4111 BFIN_BUILTIN_MULT_1X16);
4112 def_builtin ("__builtin_bfin_multr_fr1x16", short_ftype_int_int,
4113 BFIN_BUILTIN_MULTR_1X16);
4114 def_builtin ("__builtin_bfin_negate_fr1x16", short_ftype_short,
4115 BFIN_BUILTIN_NEG_1X16);
4116 def_builtin ("__builtin_bfin_abs_fr1x16", short_ftype_short,
4117 BFIN_BUILTIN_ABS_1X16);
4118 def_builtin ("__builtin_bfin_norm_fr1x16", short_ftype_int,
4119 BFIN_BUILTIN_NORM_1X16);
4121 def_builtin ("__builtin_bfin_diff_hl_fr2x16", short_ftype_v2hi,
4122 BFIN_BUILTIN_DIFFHL_2X16);
4123 def_builtin ("__builtin_bfin_diff_lh_fr2x16", short_ftype_v2hi,
4124 BFIN_BUILTIN_DIFFLH_2X16);
4126 def_builtin ("__builtin_bfin_mulhisill", int_ftype_v2hi_v2hi,
4127 BFIN_BUILTIN_MULHISILL);
4128 def_builtin ("__builtin_bfin_mulhisihl", int_ftype_v2hi_v2hi,
4129 BFIN_BUILTIN_MULHISIHL);
4130 def_builtin ("__builtin_bfin_mulhisilh", int_ftype_v2hi_v2hi,
4131 BFIN_BUILTIN_MULHISILH);
4132 def_builtin ("__builtin_bfin_mulhisihh", int_ftype_v2hi_v2hi,
4133 BFIN_BUILTIN_MULHISIHH);
4135 def_builtin ("__builtin_bfin_add_fr1x32", int_ftype_int_int,
4136 BFIN_BUILTIN_SSADD_1X32);
4137 def_builtin ("__builtin_bfin_sub_fr1x32", int_ftype_int_int,
4138 BFIN_BUILTIN_SSSUB_1X32);
4139 def_builtin ("__builtin_bfin_negate_fr1x32", int_ftype_int,
4140 BFIN_BUILTIN_NEG_1X32);
4141 def_builtin ("__builtin_bfin_norm_fr1x32", short_ftype_int,
4142 BFIN_BUILTIN_NORM_1X32);
4143 def_builtin ("__builtin_bfin_mult_fr1x32", int_ftype_short_short,
4144 BFIN_BUILTIN_MULT_1X32);
4147 def_builtin ("__builtin_bfin_shl_fr1x16", short_ftype_int_int,
4148 BFIN_BUILTIN_SSASHIFT_1X16);
4149 def_builtin ("__builtin_bfin_shl_fr2x16", v2hi_ftype_v2hi_int,
4150 BFIN_BUILTIN_SSASHIFT_2X16);
4151 def_builtin ("__builtin_bfin_lshl_fr1x16", short_ftype_int_int,
4152 BFIN_BUILTIN_LSHIFT_1X16);
4153 def_builtin ("__builtin_bfin_lshl_fr2x16", v2hi_ftype_v2hi_int,
4154 BFIN_BUILTIN_LSHIFT_2X16);
4156 /* Complex numbers. */
4157 def_builtin ("__builtin_bfin_cmplx_mul", v2hi_ftype_v2hi_v2hi,
4158 BFIN_BUILTIN_CPLX_MUL_16);
4159 def_builtin ("__builtin_bfin_cmplx_mac", v2hi_ftype_v2hi_v2hi_v2hi,
4160 BFIN_BUILTIN_CPLX_MAC_16);
4161 def_builtin ("__builtin_bfin_cmplx_msu", v2hi_ftype_v2hi_v2hi_v2hi,
4162 BFIN_BUILTIN_CPLX_MSU_16);
4166 struct builtin_description
4168 const enum insn_code icode;
4169 const char *const name;
4170 const enum bfin_builtins code;
4174 static const struct builtin_description bdesc_2arg[] =
4176 { CODE_FOR_composev2hi, "__builtin_bfin_compose_2x16", BFIN_BUILTIN_COMPOSE_2X16, -1 },
4178 { CODE_FOR_ssashiftv2hi3, "__builtin_bfin_shl_fr2x16", BFIN_BUILTIN_SSASHIFT_2X16, -1 },
4179 { CODE_FOR_ssashifthi3, "__builtin_bfin_shl_fr1x16", BFIN_BUILTIN_SSASHIFT_1X16, -1 },
4180 { CODE_FOR_lshiftv2hi3, "__builtin_bfin_lshl_fr2x16", BFIN_BUILTIN_LSHIFT_2X16, -1 },
4181 { CODE_FOR_lshifthi3, "__builtin_bfin_lshl_fr1x16", BFIN_BUILTIN_LSHIFT_1X16, -1 },
4183 { CODE_FOR_sminhi3, "__builtin_bfin_min_fr1x16", BFIN_BUILTIN_MIN_1X16, -1 },
4184 { CODE_FOR_smaxhi3, "__builtin_bfin_max_fr1x16", BFIN_BUILTIN_MAX_1X16, -1 },
4185 { CODE_FOR_ssaddhi3, "__builtin_bfin_add_fr1x16", BFIN_BUILTIN_SSADD_1X16, -1 },
4186 { CODE_FOR_sssubhi3, "__builtin_bfin_sub_fr1x16", BFIN_BUILTIN_SSSUB_1X16, -1 },
4188 { CODE_FOR_sminsi3, "__builtin_bfin_min_fr1x32", BFIN_BUILTIN_MIN_1X32, -1 },
4189 { CODE_FOR_smaxsi3, "__builtin_bfin_max_fr1x32", BFIN_BUILTIN_MAX_1X32, -1 },
4190 { CODE_FOR_ssaddsi3, "__builtin_bfin_add_fr1x32", BFIN_BUILTIN_SSADD_1X32, -1 },
4191 { CODE_FOR_sssubsi3, "__builtin_bfin_sub_fr1x32", BFIN_BUILTIN_SSSUB_1X32, -1 },
4193 { CODE_FOR_sminv2hi3, "__builtin_bfin_min_fr2x16", BFIN_BUILTIN_MIN_2X16, -1 },
4194 { CODE_FOR_smaxv2hi3, "__builtin_bfin_max_fr2x16", BFIN_BUILTIN_MAX_2X16, -1 },
4195 { CODE_FOR_ssaddv2hi3, "__builtin_bfin_add_fr2x16", BFIN_BUILTIN_SSADD_2X16, -1 },
4196 { CODE_FOR_sssubv2hi3, "__builtin_bfin_sub_fr2x16", BFIN_BUILTIN_SSSUB_2X16, -1 },
4197 { CODE_FOR_ssaddsubv2hi3, "__builtin_bfin_dspaddsubsat", BFIN_BUILTIN_SSADDSUB_2X16, -1 },
4198 { CODE_FOR_sssubaddv2hi3, "__builtin_bfin_dspsubaddsat", BFIN_BUILTIN_SSSUBADD_2X16, -1 },
4200 { CODE_FOR_flag_mulhisi, "__builtin_bfin_mult_fr1x32", BFIN_BUILTIN_MULT_1X32, MACFLAG_NONE },
4201 { CODE_FOR_flag_mulhi, "__builtin_bfin_mult_fr1x16", BFIN_BUILTIN_MULT_1X16, MACFLAG_T },
4202 { CODE_FOR_flag_mulhi, "__builtin_bfin_multr_fr1x16", BFIN_BUILTIN_MULTR_1X16, MACFLAG_NONE },
4203 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_mult_fr2x16", BFIN_BUILTIN_MULT_2X16, MACFLAG_T },
4204 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_multr_fr2x16", BFIN_BUILTIN_MULTR_2X16, MACFLAG_NONE }
4207 static const struct builtin_description bdesc_1arg[] =
4209 { CODE_FOR_signbitshi2, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16, 0 },
4210 { CODE_FOR_ssneghi2, "__builtin_bfin_negate_fr1x16", BFIN_BUILTIN_NEG_1X16, 0 },
4211 { CODE_FOR_abshi2, "__builtin_bfin_abs_fr1x16", BFIN_BUILTIN_ABS_1X16, 0 },
4213 { CODE_FOR_signbitssi2, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32, 0 },
4214 { CODE_FOR_ssnegsi2, "__builtin_bfin_negate_fr1x32", BFIN_BUILTIN_NEG_1X32, 0 },
4216 { CODE_FOR_movv2hi_hi_low, "__builtin_bfin_extract_lo", BFIN_BUILTIN_EXTRACTLO, 0 },
4217 { CODE_FOR_movv2hi_hi_high, "__builtin_bfin_extract_hi", BFIN_BUILTIN_EXTRACTHI, 0 },
4218 { CODE_FOR_ssnegv2hi2, "__builtin_bfin_negate_fr2x16", BFIN_BUILTIN_NEG_2X16, 0 },
4219 { CODE_FOR_absv2hi2, "__builtin_bfin_abs_fr2x16", BFIN_BUILTIN_ABS_2X16, 0 }
4222 /* Errors in the source file can cause expand_expr to return const0_rtx
4223 where we expect a vector. To avoid crashing, use one of the vector
4224 clear instructions. */
4226 safe_vector_operand (rtx x, enum machine_mode mode)
4228 if (x != const0_rtx)
4230 x = gen_reg_rtx (SImode);
4232 emit_insn (gen_movsi (x, CONST0_RTX (SImode)));
4233 return gen_lowpart (mode, x);
4236 /* Subroutine of bfin_expand_builtin to take care of binop insns. MACFLAG is -1
4237 if this is a normal binary op, or one of the MACFLAG_xxx constants. */
4240 bfin_expand_binop_builtin (enum insn_code icode, tree arglist, rtx target,
4244 tree arg0 = TREE_VALUE (arglist);
4245 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
4246 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4247 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
4248 enum machine_mode op0mode = GET_MODE (op0);
4249 enum machine_mode op1mode = GET_MODE (op1);
4250 enum machine_mode tmode = insn_data[icode].operand[0].mode;
4251 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
4252 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
4254 if (VECTOR_MODE_P (mode0))
4255 op0 = safe_vector_operand (op0, mode0);
4256 if (VECTOR_MODE_P (mode1))
4257 op1 = safe_vector_operand (op1, mode1);
4260 || GET_MODE (target) != tmode
4261 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
4262 target = gen_reg_rtx (tmode);
4264 if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode)
4267 op0 = gen_lowpart (HImode, op0);
4269 if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode)
4272 op1 = gen_lowpart (HImode, op1);
4274 /* In case the insn wants input operands in modes different from
4275 the result, abort. */
4276 gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
4277 && (op1mode == mode1 || op1mode == VOIDmode));
4279 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
4280 op0 = copy_to_mode_reg (mode0, op0);
4281 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
4282 op1 = copy_to_mode_reg (mode1, op1);
4285 pat = GEN_FCN (icode) (target, op0, op1);
4287 pat = GEN_FCN (icode) (target, op0, op1, GEN_INT (macflag));
4295 /* Subroutine of bfin_expand_builtin to take care of unop insns. */
4298 bfin_expand_unop_builtin (enum insn_code icode, tree arglist,
4302 tree arg0 = TREE_VALUE (arglist);
4303 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4304 enum machine_mode op0mode = GET_MODE (op0);
4305 enum machine_mode tmode = insn_data[icode].operand[0].mode;
4306 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
4309 || GET_MODE (target) != tmode
4310 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
4311 target = gen_reg_rtx (tmode);
4313 if (VECTOR_MODE_P (mode0))
4314 op0 = safe_vector_operand (op0, mode0);
4316 if (op0mode == SImode && mode0 == HImode)
4319 op0 = gen_lowpart (HImode, op0);
4321 gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
4323 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
4324 op0 = copy_to_mode_reg (mode0, op0);
4326 pat = GEN_FCN (icode) (target, op0);
4333 /* Expand an expression EXP that calls a built-in function,
4334 with result going to TARGET if that's convenient
4335 (and in mode MODE if that's convenient).
4336 SUBTARGET may be used as the target for computing one of EXP's operands.
4337 IGNORE is nonzero if the value is to be ignored. */
4340 bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
4341 rtx subtarget ATTRIBUTE_UNUSED,
4342 enum machine_mode mode ATTRIBUTE_UNUSED,
4343 int ignore ATTRIBUTE_UNUSED)
4346 enum insn_code icode;
4347 const struct builtin_description *d;
4348 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
4349 tree arglist = TREE_OPERAND (exp, 1);
4350 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
4351 tree arg0, arg1, arg2;
4352 rtx op0, op1, op2, accvec, pat, tmp1, tmp2;
4353 enum machine_mode tmode, mode0;
4357 case BFIN_BUILTIN_CSYNC:
4358 emit_insn (gen_csync ());
4360 case BFIN_BUILTIN_SSYNC:
4361 emit_insn (gen_ssync ());
4364 case BFIN_BUILTIN_DIFFHL_2X16:
4365 case BFIN_BUILTIN_DIFFLH_2X16:
4366 arg0 = TREE_VALUE (arglist);
4367 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4368 icode = (fcode == BFIN_BUILTIN_DIFFHL_2X16
4369 ? CODE_FOR_subhilov2hi3 : CODE_FOR_sublohiv2hi3);
4370 tmode = insn_data[icode].operand[0].mode;
4371 mode0 = insn_data[icode].operand[1].mode;
4374 || GET_MODE (target) != tmode
4375 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
4376 target = gen_reg_rtx (tmode);
4378 if (VECTOR_MODE_P (mode0))
4379 op0 = safe_vector_operand (op0, mode0);
4381 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
4382 op0 = copy_to_mode_reg (mode0, op0);
4384 pat = GEN_FCN (icode) (target, op0, op0);
4390 case BFIN_BUILTIN_CPLX_MUL_16:
4391 arg0 = TREE_VALUE (arglist);
4392 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
4393 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4394 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
4395 accvec = gen_reg_rtx (V2PDImode);
4398 || GET_MODE (target) != V2HImode
4399 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
4400 target = gen_reg_rtx (tmode);
4401 if (! register_operand (op0, GET_MODE (op0)))
4402 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
4403 if (! register_operand (op1, GET_MODE (op1)))
4404 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
4406 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
4407 const0_rtx, const0_rtx,
4408 const1_rtx, GEN_INT (MACFLAG_NONE)));
4409 emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
4410 const1_rtx, const1_rtx,
4411 const0_rtx, accvec, const1_rtx, const0_rtx,
4412 GEN_INT (MACFLAG_NONE), accvec));
4416 case BFIN_BUILTIN_CPLX_MAC_16:
4417 case BFIN_BUILTIN_CPLX_MSU_16:
4418 arg0 = TREE_VALUE (arglist);
4419 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
4420 arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
4421 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4422 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
4423 op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
4424 accvec = gen_reg_rtx (V2PDImode);
4427 || GET_MODE (target) != V2HImode
4428 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
4429 target = gen_reg_rtx (tmode);
4430 if (! register_operand (op0, GET_MODE (op0)))
4431 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
4432 if (! register_operand (op1, GET_MODE (op1)))
4433 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
4435 tmp1 = gen_reg_rtx (SImode);
4436 tmp2 = gen_reg_rtx (SImode);
4437 emit_insn (gen_ashlsi3 (tmp1, gen_lowpart (SImode, op2), GEN_INT (16)));
4438 emit_move_insn (tmp2, gen_lowpart (SImode, op2));
4439 emit_insn (gen_movstricthi_1 (gen_lowpart (HImode, tmp2), const0_rtx));
4440 emit_insn (gen_load_accumulator_pair (accvec, tmp1, tmp2));
4441 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op0, op1, const0_rtx,
4442 const0_rtx, const0_rtx,
4443 const1_rtx, accvec, const0_rtx,
4445 GEN_INT (MACFLAG_W32)));
4446 tmp1 = (fcode == BFIN_BUILTIN_CPLX_MAC_16 ? const1_rtx : const0_rtx);
4447 tmp2 = (fcode == BFIN_BUILTIN_CPLX_MAC_16 ? const0_rtx : const1_rtx);
4448 emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
4449 const1_rtx, const1_rtx,
4450 const0_rtx, accvec, tmp1, tmp2,
4451 GEN_INT (MACFLAG_NONE), accvec));
4459 for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
4460 if (d->code == fcode)
4461 return bfin_expand_binop_builtin (d->icode, arglist, target,
4464 for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
4465 if (d->code == fcode)
4466 return bfin_expand_unop_builtin (d->icode, arglist, target);
4471 #undef TARGET_INIT_BUILTINS
4472 #define TARGET_INIT_BUILTINS bfin_init_builtins
4474 #undef TARGET_EXPAND_BUILTIN
4475 #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
4477 #undef TARGET_ASM_GLOBALIZE_LABEL
4478 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label
4480 #undef TARGET_ASM_FILE_START
4481 #define TARGET_ASM_FILE_START output_file_start
4483 #undef TARGET_ATTRIBUTE_TABLE
4484 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
4486 #undef TARGET_COMP_TYPE_ATTRIBUTES
4487 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
4489 #undef TARGET_RTX_COSTS
4490 #define TARGET_RTX_COSTS bfin_rtx_costs
4492 #undef TARGET_ADDRESS_COST
4493 #define TARGET_ADDRESS_COST bfin_address_cost
4495 #undef TARGET_ASM_INTERNAL_LABEL
4496 #define TARGET_ASM_INTERNAL_LABEL bfin_internal_label
4498 #undef TARGET_ASM_INTEGER
4499 #define TARGET_ASM_INTEGER bfin_assemble_integer
4501 #undef TARGET_MACHINE_DEPENDENT_REORG
4502 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
4504 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
4505 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
4507 #undef TARGET_ASM_OUTPUT_MI_THUNK
4508 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
4509 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
4510 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
4512 #undef TARGET_SCHED_ADJUST_COST
4513 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
4515 #undef TARGET_PROMOTE_PROTOTYPES
4516 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
4517 #undef TARGET_PROMOTE_FUNCTION_ARGS
4518 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
4519 #undef TARGET_PROMOTE_FUNCTION_RETURN
4520 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
4522 #undef TARGET_ARG_PARTIAL_BYTES
4523 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
4525 #undef TARGET_PASS_BY_REFERENCE
4526 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
4528 #undef TARGET_SETUP_INCOMING_VARARGS
4529 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
4531 #undef TARGET_STRUCT_VALUE_RTX
4532 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
4534 #undef TARGET_VECTOR_MODE_SUPPORTED_P
4535 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
4537 #undef TARGET_HANDLE_OPTION
4538 #define TARGET_HANDLE_OPTION bfin_handle_option
4540 #undef TARGET_DEFAULT_TARGET_FLAGS
4541 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
4543 #undef TARGET_SECONDARY_RELOAD
4544 #define TARGET_SECONDARY_RELOAD bfin_secondary_reload
4546 #undef TARGET_DELEGITIMIZE_ADDRESS
4547 #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address
4549 #undef TARGET_CANNOT_FORCE_CONST_MEM
4550 #define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem
4552 struct gcc_target targetm = TARGET_INITIALIZER;