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 /* Allow all normal 32 bit regs, except REG_M3, in case regclass ever comes
1859 up with a bad register class (such as ALL_REGS) for DImode. */
1861 return regno < REG_M3;
1864 && TEST_HARD_REG_BIT (reg_class_contents[PROLOGUE_REGS], regno))
1867 return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno);
1870 /* Implements target hook vector_mode_supported_p. */
1873 bfin_vector_mode_supported_p (enum machine_mode mode)
1875 return mode == V2HImode;
1878 /* Return the cost of moving data from a register in class CLASS1 to
1879 one in class CLASS2. A cost of 2 is the default. */
1882 bfin_register_move_cost (enum machine_mode mode,
1883 enum reg_class class1, enum reg_class class2)
1885 /* These need secondary reloads, so they're more expensive. */
1886 if ((class1 == CCREGS && class2 != DREGS)
1887 || (class1 != DREGS && class2 == CCREGS))
1890 /* If optimizing for size, always prefer reg-reg over reg-memory moves. */
1894 /* There are some stalls involved when moving from a DREG to a different
1895 class reg, and using the value in one of the following instructions.
1896 Attempt to model this by slightly discouraging such moves. */
1897 if (class1 == DREGS && class2 != DREGS)
1900 if (GET_MODE_CLASS (mode) == MODE_INT)
1902 /* Discourage trying to use the accumulators. */
1903 if (TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A0)
1904 || TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A1)
1905 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A0)
1906 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A1))
1912 /* Return the cost of moving data of mode M between a
1913 register and memory. A value of 2 is the default; this cost is
1914 relative to those in `REGISTER_MOVE_COST'.
1916 ??? In theory L1 memory has single-cycle latency. We should add a switch
1917 that tells the compiler whether we expect to use only L1 memory for the
1918 program; it'll make the costs more accurate. */
1921 bfin_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
1922 enum reg_class class,
1923 int in ATTRIBUTE_UNUSED)
1925 /* Make memory accesses slightly more expensive than any register-register
1926 move. Also, penalize non-DP registers, since they need secondary
1927 reloads to load and store. */
1928 if (! reg_class_subset_p (class, DPREGS))
1934 /* Inform reload about cases where moving X with a mode MODE to a register in
1935 CLASS requires an extra scratch register. Return the class needed for the
1936 scratch register. */
1938 static enum reg_class
1939 bfin_secondary_reload (bool in_p, rtx x, enum reg_class class,
1940 enum machine_mode mode, secondary_reload_info *sri)
1942 /* If we have HImode or QImode, we can only use DREGS as secondary registers;
1943 in most other cases we can also use PREGS. */
1944 enum reg_class default_class = GET_MODE_SIZE (mode) >= 4 ? DPREGS : DREGS;
1945 enum reg_class x_class = NO_REGS;
1946 enum rtx_code code = GET_CODE (x);
1949 x = SUBREG_REG (x), code = GET_CODE (x);
1952 int regno = REGNO (x);
1953 if (regno >= FIRST_PSEUDO_REGISTER)
1954 regno = reg_renumber[regno];
1959 x_class = REGNO_REG_CLASS (regno);
1962 /* We can be asked to reload (plus (FP) (large_constant)) into a DREG.
1963 This happens as a side effect of register elimination, and we need
1964 a scratch register to do it. */
1965 if (fp_plus_const_operand (x, mode))
1967 rtx op2 = XEXP (x, 1);
1968 int large_constant_p = ! CONST_7BIT_IMM_P (INTVAL (op2));
1970 if (class == PREGS || class == PREGS_CLOBBERED)
1972 /* If destination is a DREG, we can do this without a scratch register
1973 if the constant is valid for an add instruction. */
1974 if ((class == DREGS || class == DPREGS)
1975 && ! large_constant_p)
1977 /* Reloading to anything other than a DREG? Use a PREG scratch
1979 sri->icode = CODE_FOR_reload_insi;
1983 /* Data can usually be moved freely between registers of most classes.
1984 AREGS are an exception; they can only move to or from another register
1985 in AREGS or one in DREGS. They can also be assigned the constant 0. */
1986 if (x_class == AREGS)
1987 return class == DREGS || class == AREGS ? NO_REGS : DREGS;
1991 if (x != const0_rtx && x_class != DREGS)
1997 /* CCREGS can only be moved from/to DREGS. */
1998 if (class == CCREGS && x_class != DREGS)
2000 if (x_class == CCREGS && class != DREGS)
2003 /* All registers other than AREGS can load arbitrary constants. The only
2004 case that remains is MEM. */
2006 if (! reg_class_subset_p (class, default_class))
2007 return default_class;
2011 /* Implement TARGET_HANDLE_OPTION. */
2014 bfin_handle_option (size_t code, const char *arg, int value)
2018 case OPT_mshared_library_id_:
2019 if (value > MAX_LIBRARY_ID)
2020 error ("-mshared-library-id=%s is not between 0 and %d",
2021 arg, MAX_LIBRARY_ID);
2022 bfin_lib_id_given = 1;
2030 static struct machine_function *
2031 bfin_init_machine_status (void)
2033 struct machine_function *f;
2035 f = ggc_alloc_cleared (sizeof (struct machine_function));
2040 /* Implement the macro OVERRIDE_OPTIONS. */
2043 override_options (void)
2045 if (TARGET_OMIT_LEAF_FRAME_POINTER)
2046 flag_omit_frame_pointer = 1;
2048 /* Library identification */
2049 if (bfin_lib_id_given && ! TARGET_ID_SHARED_LIBRARY)
2050 error ("-mshared-library-id= specified without -mid-shared-library");
2052 if (TARGET_ID_SHARED_LIBRARY && flag_pic == 0)
2055 if (stack_limit_rtx && TARGET_STACK_CHECK_L1)
2056 error ("Can't use multiple stack checking methods together.");
2058 if (TARGET_ID_SHARED_LIBRARY && TARGET_FDPIC)
2059 error ("ID shared libraries and FD-PIC mode can't be used together.");
2061 /* Don't allow the user to specify -mid-shared-library and -msep-data
2062 together, as it makes little sense from a user's point of view... */
2063 if (TARGET_SEP_DATA && TARGET_ID_SHARED_LIBRARY)
2064 error ("cannot specify both -msep-data and -mid-shared-library");
2065 /* ... internally, however, it's nearly the same. */
2066 if (TARGET_SEP_DATA)
2067 target_flags |= MASK_ID_SHARED_LIBRARY | MASK_LEAF_ID_SHARED_LIBRARY;
2069 /* There is no single unaligned SI op for PIC code. Sometimes we
2070 need to use ".4byte" and sometimes we need to use ".picptr".
2071 See bfin_assemble_integer for details. */
2073 targetm.asm_out.unaligned_op.si = 0;
2075 /* Silently turn off flag_pic if not doing FDPIC or ID shared libraries,
2076 since we don't support it and it'll just break. */
2077 if (flag_pic && !TARGET_FDPIC && !TARGET_ID_SHARED_LIBRARY)
2080 flag_schedule_insns = 0;
2082 init_machine_status = bfin_init_machine_status;
2085 /* Return the destination address of BRANCH.
2086 We need to use this instead of get_attr_length, because the
2087 cbranch_with_nops pattern conservatively sets its length to 6, and
2088 we still prefer to use shorter sequences. */
2091 branch_dest (rtx branch)
2095 rtx pat = PATTERN (branch);
2096 if (GET_CODE (pat) == PARALLEL)
2097 pat = XVECEXP (pat, 0, 0);
2098 dest = SET_SRC (pat);
2099 if (GET_CODE (dest) == IF_THEN_ELSE)
2100 dest = XEXP (dest, 1);
2101 dest = XEXP (dest, 0);
2102 dest_uid = INSN_UID (dest);
2103 return INSN_ADDRESSES (dest_uid);
2106 /* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates
2107 it's a branch that's predicted taken. */
2110 cbranch_predicted_taken_p (rtx insn)
2112 rtx x = find_reg_note (insn, REG_BR_PROB, 0);
2116 int pred_val = INTVAL (XEXP (x, 0));
2118 return pred_val >= REG_BR_PROB_BASE / 2;
2124 /* Templates for use by asm_conditional_branch. */
2126 static const char *ccbranch_templates[][3] = {
2127 { "if !cc jump %3;", "if cc jump 4 (bp); jump.s %3;", "if cc jump 6 (bp); jump.l %3;" },
2128 { "if cc jump %3;", "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" },
2129 { "if !cc jump %3 (bp);", "if cc jump 4; jump.s %3;", "if cc jump 6; jump.l %3;" },
2130 { "if cc jump %3 (bp);", "if !cc jump 4; jump.s %3;", "if !cc jump 6; jump.l %3;" },
2133 /* Output INSN, which is a conditional branch instruction with operands
2136 We deal with the various forms of conditional branches that can be generated
2137 by bfin_reorg to prevent the hardware from doing speculative loads, by
2138 - emitting a sufficient number of nops, if N_NOPS is nonzero, or
2139 - always emitting the branch as predicted taken, if PREDICT_TAKEN is true.
2140 Either of these is only necessary if the branch is short, otherwise the
2141 template we use ends in an unconditional jump which flushes the pipeline
2145 asm_conditional_branch (rtx insn, rtx *operands, int n_nops, int predict_taken)
2147 int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
2148 /* Note : offset for instructions like if cc jmp; jump.[sl] offset
2149 is to be taken from start of if cc rather than jump.
2150 Range for jump.s is (-4094, 4096) instead of (-4096, 4094)
2152 int len = (offset >= -1024 && offset <= 1022 ? 0
2153 : offset >= -4094 && offset <= 4096 ? 1
2155 int bp = predict_taken && len == 0 ? 1 : cbranch_predicted_taken_p (insn);
2156 int idx = (bp << 1) | (GET_CODE (operands[0]) == EQ ? BRF : BRT);
2157 output_asm_insn (ccbranch_templates[idx][len], operands);
2158 gcc_assert (n_nops == 0 || !bp);
2160 while (n_nops-- > 0)
2161 output_asm_insn ("nop;", NULL);
2164 /* Emit rtl for a comparison operation CMP in mode MODE. Operands have been
2165 stored in bfin_compare_op0 and bfin_compare_op1 already. */
2168 bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED)
2170 enum rtx_code code1, code2;
2171 rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1;
2172 rtx tem = bfin_cc_rtx;
2173 enum rtx_code code = GET_CODE (cmp);
2175 /* If we have a BImode input, then we already have a compare result, and
2176 do not need to emit another comparison. */
2177 if (GET_MODE (op0) == BImode)
2179 gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
2180 tem = op0, code2 = code;
2185 /* bfin has these conditions */
2195 code1 = reverse_condition (code);
2199 emit_insn (gen_rtx_SET (BImode, tem,
2200 gen_rtx_fmt_ee (code1, BImode, op0, op1)));
2203 return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode));
2206 /* Return nonzero iff C has exactly one bit set if it is interpreted
2207 as a 32 bit constant. */
2210 log2constp (unsigned HOST_WIDE_INT c)
2213 return c != 0 && (c & (c-1)) == 0;
2216 /* Returns the number of consecutive least significant zeros in the binary
2217 representation of *V.
2218 We modify *V to contain the original value arithmetically shifted right by
2219 the number of zeroes. */
2222 shiftr_zero (HOST_WIDE_INT *v)
2224 unsigned HOST_WIDE_INT tmp = *v;
2225 unsigned HOST_WIDE_INT sgn;
2231 sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1));
2232 while ((tmp & 0x1) == 0 && n <= 32)
2234 tmp = (tmp >> 1) | sgn;
2241 /* After reload, split the load of an immediate constant. OPERANDS are the
2242 operands of the movsi_insn pattern which we are splitting. We return
2243 nonzero if we emitted a sequence to load the constant, zero if we emitted
2244 nothing because we want to use the splitter's default sequence. */
2247 split_load_immediate (rtx operands[])
2249 HOST_WIDE_INT val = INTVAL (operands[1]);
2251 HOST_WIDE_INT shifted = val;
2252 HOST_WIDE_INT shifted_compl = ~val;
2253 int num_zero = shiftr_zero (&shifted);
2254 int num_compl_zero = shiftr_zero (&shifted_compl);
2255 unsigned int regno = REGNO (operands[0]);
2256 enum reg_class class1 = REGNO_REG_CLASS (regno);
2258 /* This case takes care of single-bit set/clear constants, which we could
2259 also implement with BITSET/BITCLR. */
2261 && shifted >= -32768 && shifted < 65536
2262 && (D_REGNO_P (regno)
2263 || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))
2265 emit_insn (gen_movsi (operands[0], GEN_INT (shifted)));
2266 emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));
2271 tmp |= -(tmp & 0x8000);
2273 /* If high word has one bit set or clear, try to use a bit operation. */
2274 if (D_REGNO_P (regno))
2276 if (log2constp (val & 0xFFFF0000))
2278 emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));
2279 emit_insn (gen_iorsi3 (operands[0], operands[0], GEN_INT (val & 0xFFFF0000)));
2282 else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)
2284 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2285 emit_insn (gen_andsi3 (operands[0], operands[0], GEN_INT (val | 0xFFFF)));
2289 if (D_REGNO_P (regno))
2291 if (CONST_7BIT_IMM_P (tmp))
2293 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2294 emit_insn (gen_movstricthi_high (operands[0], GEN_INT (val & -65536)));
2298 if ((val & 0xFFFF0000) == 0)
2300 emit_insn (gen_movsi (operands[0], const0_rtx));
2301 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2305 if ((val & 0xFFFF0000) == 0xFFFF0000)
2307 emit_insn (gen_movsi (operands[0], constm1_rtx));
2308 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2313 /* Need DREGs for the remaining case. */
2318 && num_compl_zero && CONST_7BIT_IMM_P (shifted_compl))
2320 /* If optimizing for size, generate a sequence that has more instructions
2322 emit_insn (gen_movsi (operands[0], GEN_INT (shifted_compl)));
2323 emit_insn (gen_ashlsi3 (operands[0], operands[0],
2324 GEN_INT (num_compl_zero)));
2325 emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
2331 /* Return true if the legitimate memory address for a memory operand of mode
2332 MODE. Return false if not. */
2335 bfin_valid_add (enum machine_mode mode, HOST_WIDE_INT value)
2337 unsigned HOST_WIDE_INT v = value > 0 ? value : -value;
2338 int sz = GET_MODE_SIZE (mode);
2339 int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2;
2340 /* The usual offsettable_memref machinery doesn't work so well for this
2341 port, so we deal with the problem here. */
2342 unsigned HOST_WIDE_INT mask = sz == 8 ? 0x7ffe : 0x7fff;
2343 return (v & ~(mask << shift)) == 0;
2347 bfin_valid_reg_p (unsigned int regno, int strict, enum machine_mode mode,
2348 enum rtx_code outer_code)
2351 return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH);
2353 return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH);
2357 bfin_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
2359 switch (GET_CODE (x)) {
2361 if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM))
2365 if (REG_P (XEXP (x, 0))
2366 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS)
2367 && ((GET_CODE (XEXP (x, 1)) == UNSPEC && mode == SImode)
2368 || (GET_CODE (XEXP (x, 1)) == CONST_INT
2369 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
2374 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2375 && REG_P (XEXP (x, 0))
2376 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC))
2379 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2380 && XEXP (x, 0) == stack_pointer_rtx
2381 && REG_P (XEXP (x, 0))
2382 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC))
2391 /* Decide whether we can force certain constants to memory. If we
2392 decide we can't, the caller should be able to cope with it in
2396 bfin_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
2398 /* We have only one class of non-legitimate constants, and our movsi
2399 expander knows how to handle them. Dropping these constants into the
2400 data section would only shift the problem - we'd still get relocs
2401 outside the object, in the data section rather than the text section. */
2405 /* Ensure that for any constant of the form symbol + offset, the offset
2406 remains within the object. Any other constants are ok.
2407 This ensures that flat binaries never have to deal with relocations
2408 crossing section boundaries. */
2411 bfin_legitimate_constant_p (rtx x)
2414 HOST_WIDE_INT offset;
2416 if (GET_CODE (x) != CONST)
2420 gcc_assert (GET_CODE (x) == PLUS);
2424 if (GET_CODE (sym) != SYMBOL_REF
2425 || GET_CODE (x) != CONST_INT)
2427 offset = INTVAL (x);
2429 if (SYMBOL_REF_DECL (sym) == 0)
2432 || offset >= int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (sym))))
2439 bfin_rtx_costs (rtx x, int code, int outer_code, int *total)
2441 int cost2 = COSTS_N_INSNS (1);
2446 if (outer_code == SET || outer_code == PLUS)
2447 *total = CONST_7BIT_IMM_P (INTVAL (x)) ? 0 : cost2;
2448 else if (outer_code == AND)
2449 *total = log2constp (~INTVAL (x)) ? 0 : cost2;
2450 else if (outer_code == LE || outer_code == LT || outer_code == EQ)
2451 *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
2452 else if (outer_code == LEU || outer_code == LTU)
2453 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
2454 else if (outer_code == MULT)
2455 *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
2456 else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
2458 else if (outer_code == ASHIFT || outer_code == ASHIFTRT
2459 || outer_code == LSHIFTRT)
2460 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
2461 else if (outer_code == IOR || outer_code == XOR)
2462 *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
2471 *total = COSTS_N_INSNS (2);
2475 if (GET_MODE (x) == Pmode)
2477 if (GET_CODE (XEXP (x, 0)) == MULT
2478 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
2480 HOST_WIDE_INT val = INTVAL (XEXP (XEXP (x, 0), 1));
2481 if (val == 2 || val == 4)
2484 *total += rtx_cost (XEXP (XEXP (x, 0), 0), outer_code);
2485 *total += rtx_cost (XEXP (x, 1), outer_code);
2497 if (GET_MODE (x) == DImode)
2504 if (GET_MODE (x) == DImode)
2509 if (GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD)
2510 *total = COSTS_N_INSNS (3);
2515 *total = COSTS_N_INSNS (32);
2520 if (outer_code == SET)
2530 bfin_internal_label (FILE *stream, const char *prefix, unsigned long num)
2532 fprintf (stream, "%s%s$%ld:\n", LOCAL_LABEL_PREFIX, prefix, num);
2535 /* Used for communication between {push,pop}_multiple_operation (which
2536 we use not only as a predicate) and the corresponding output functions. */
2537 static int first_preg_to_save, first_dreg_to_save;
2540 push_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2542 int lastdreg = 8, lastpreg = 6;
2545 first_preg_to_save = lastpreg;
2546 first_dreg_to_save = lastdreg;
2547 for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
2549 rtx t = XVECEXP (op, 0, i);
2553 if (GET_CODE (t) != SET)
2557 dest = SET_DEST (t);
2558 if (GET_CODE (dest) != MEM || ! REG_P (src))
2560 dest = XEXP (dest, 0);
2561 if (GET_CODE (dest) != PLUS
2562 || ! REG_P (XEXP (dest, 0))
2563 || REGNO (XEXP (dest, 0)) != REG_SP
2564 || GET_CODE (XEXP (dest, 1)) != CONST_INT
2565 || INTVAL (XEXP (dest, 1)) != -i * 4)
2568 regno = REGNO (src);
2571 if (D_REGNO_P (regno))
2574 first_dreg_to_save = lastdreg = regno - REG_R0;
2576 else if (regno >= REG_P0 && regno <= REG_P7)
2579 first_preg_to_save = lastpreg = regno - REG_P0;
2589 if (regno >= REG_P0 && regno <= REG_P7)
2592 first_preg_to_save = lastpreg = regno - REG_P0;
2594 else if (regno != REG_R0 + lastdreg + 1)
2599 else if (group == 2)
2601 if (regno != REG_P0 + lastpreg + 1)
2610 pop_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2612 int lastdreg = 8, lastpreg = 6;
2615 for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
2617 rtx t = XVECEXP (op, 0, i);
2621 if (GET_CODE (t) != SET)
2625 dest = SET_DEST (t);
2626 if (GET_CODE (src) != MEM || ! REG_P (dest))
2628 src = XEXP (src, 0);
2632 if (! REG_P (src) || REGNO (src) != REG_SP)
2635 else if (GET_CODE (src) != PLUS
2636 || ! REG_P (XEXP (src, 0))
2637 || REGNO (XEXP (src, 0)) != REG_SP
2638 || GET_CODE (XEXP (src, 1)) != CONST_INT
2639 || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
2642 regno = REGNO (dest);
2645 if (regno == REG_R7)
2650 else if (regno != REG_P0 + lastpreg - 1)
2655 else if (group == 1)
2657 if (regno != REG_R0 + lastdreg - 1)
2663 first_dreg_to_save = lastdreg;
2664 first_preg_to_save = lastpreg;
2668 /* Emit assembly code for one multi-register push described by INSN, with
2669 operands in OPERANDS. */
2672 output_push_multiple (rtx insn, rtx *operands)
2677 /* Validate the insn again, and compute first_[dp]reg_to_save. */
2678 ok = push_multiple_operation (PATTERN (insn), VOIDmode);
2681 if (first_dreg_to_save == 8)
2682 sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
2683 else if (first_preg_to_save == 6)
2684 sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
2686 sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
2687 first_dreg_to_save, first_preg_to_save);
2689 output_asm_insn (buf, operands);
2692 /* Emit assembly code for one multi-register pop described by INSN, with
2693 operands in OPERANDS. */
2696 output_pop_multiple (rtx insn, rtx *operands)
2701 /* Validate the insn again, and compute first_[dp]reg_to_save. */
2702 ok = pop_multiple_operation (PATTERN (insn), VOIDmode);
2705 if (first_dreg_to_save == 8)
2706 sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
2707 else if (first_preg_to_save == 6)
2708 sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
2710 sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
2711 first_dreg_to_save, first_preg_to_save);
2713 output_asm_insn (buf, operands);
2716 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE. */
2719 single_move_for_movmem (rtx dst, rtx src, enum machine_mode mode, HOST_WIDE_INT offset)
2721 rtx scratch = gen_reg_rtx (mode);
2724 srcmem = adjust_address_nv (src, mode, offset);
2725 dstmem = adjust_address_nv (dst, mode, offset);
2726 emit_move_insn (scratch, srcmem);
2727 emit_move_insn (dstmem, scratch);
2730 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
2731 alignment ALIGN_EXP. Return true if successful, false if we should fall
2732 back on a different method. */
2735 bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
2737 rtx srcreg, destreg, countreg;
2738 HOST_WIDE_INT align = 0;
2739 unsigned HOST_WIDE_INT count = 0;
2741 if (GET_CODE (align_exp) == CONST_INT)
2742 align = INTVAL (align_exp);
2743 if (GET_CODE (count_exp) == CONST_INT)
2745 count = INTVAL (count_exp);
2747 if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
2752 /* If optimizing for size, only do single copies inline. */
2755 if (count == 2 && align < 2)
2757 if (count == 4 && align < 4)
2759 if (count != 1 && count != 2 && count != 4)
2762 if (align < 2 && count != 1)
2765 destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
2766 if (destreg != XEXP (dst, 0))
2767 dst = replace_equiv_address_nv (dst, destreg);
2768 srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
2769 if (srcreg != XEXP (src, 0))
2770 src = replace_equiv_address_nv (src, srcreg);
2772 if (count != 0 && align >= 2)
2774 unsigned HOST_WIDE_INT offset = 0;
2778 if ((count & ~3) == 4)
2780 single_move_for_movmem (dst, src, SImode, offset);
2783 else if (count & ~3)
2785 HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
2786 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
2788 emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
2792 single_move_for_movmem (dst, src, HImode, offset);
2798 if ((count & ~1) == 2)
2800 single_move_for_movmem (dst, src, HImode, offset);
2803 else if (count & ~1)
2805 HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
2806 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
2808 emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
2813 single_move_for_movmem (dst, src, QImode, offset);
2820 /* Implement TARGET_SCHED_ISSUE_RATE. */
2823 bfin_issue_rate (void)
2829 bfin_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
2831 enum attr_type insn_type, dep_insn_type;
2832 int dep_insn_code_number;
2834 /* Anti and output dependencies have zero cost. */
2835 if (REG_NOTE_KIND (link) != 0)
2838 dep_insn_code_number = recog_memoized (dep_insn);
2840 /* If we can't recognize the insns, we can't really do anything. */
2841 if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
2844 insn_type = get_attr_type (insn);
2845 dep_insn_type = get_attr_type (dep_insn);
2847 if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)
2849 rtx pat = PATTERN (dep_insn);
2850 rtx dest = SET_DEST (pat);
2851 rtx src = SET_SRC (pat);
2852 if (! ADDRESS_REGNO_P (REGNO (dest)) || ! D_REGNO_P (REGNO (src)))
2854 return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);
2861 /* Increment the counter for the number of loop instructions in the
2862 current function. */
2865 bfin_hardware_loop (void)
2867 cfun->machine->has_hardware_loops++;
2870 /* Maximum loop nesting depth. */
2871 #define MAX_LOOP_DEPTH 2
2873 /* Maximum size of a loop. */
2874 #define MAX_LOOP_LENGTH 2042
2876 /* We need to keep a vector of loops */
2877 typedef struct loop_info *loop_info;
2878 DEF_VEC_P (loop_info);
2879 DEF_VEC_ALLOC_P (loop_info,heap);
2881 /* Information about a loop we have found (or are in the process of
2883 struct loop_info GTY (())
2885 /* loop number, for dumps */
2888 /* Predecessor block of the loop. This is the one that falls into
2889 the loop and contains the initialization instruction. */
2890 basic_block predecessor;
2892 /* First block in the loop. This is the one branched to by the loop_end
2896 /* Last block in the loop (the one with the loop_end insn). */
2899 /* The successor block of the loop. This is the one the loop_end insn
2901 basic_block successor;
2903 /* The last instruction in the tail. */
2906 /* The loop_end insn. */
2909 /* The iteration register. */
2912 /* The new initialization insn. */
2915 /* The new initialization instruction. */
2918 /* The new label placed at the beginning of the loop. */
2921 /* The new label placed at the end of the loop. */
2924 /* The length of the loop. */
2927 /* The nesting depth of the loop. */
2930 /* Nonzero if we can't optimize this loop. */
2933 /* True if we have visited this loop. */
2936 /* True if this loop body clobbers any of LC0, LT0, or LB0. */
2939 /* True if this loop body clobbers any of LC1, LT1, or LB1. */
2942 /* Next loop in the graph. */
2943 struct loop_info *next;
2945 /* Immediate outer loop of this loop. */
2946 struct loop_info *outer;
2948 /* Vector of blocks only within the loop, including those within
2950 VEC (basic_block,heap) *blocks;
2952 /* Same information in a bitmap. */
2953 bitmap block_bitmap;
2955 /* Vector of inner loops within this loop */
2956 VEC (loop_info,heap) *loops;
2960 bfin_dump_loops (loop_info loops)
2964 for (loop = loops; loop; loop = loop->next)
2970 fprintf (dump_file, ";; loop %d: ", loop->loop_no);
2972 fprintf (dump_file, "(bad) ");
2973 fprintf (dump_file, "{head:%d, depth:%d}", loop->head->index, loop->depth);
2975 fprintf (dump_file, " blocks: [ ");
2976 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, b); ix++)
2977 fprintf (dump_file, "%d ", b->index);
2978 fprintf (dump_file, "] ");
2980 fprintf (dump_file, " inner loops: [ ");
2981 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, i); ix++)
2982 fprintf (dump_file, "%d ", i->loop_no);
2983 fprintf (dump_file, "]\n");
2985 fprintf (dump_file, "\n");
2988 /* Scan the blocks of LOOP (and its inferiors) looking for basic block
2989 BB. Return true, if we find it. */
2992 bfin_bb_in_loop (loop_info loop, basic_block bb)
2994 return bitmap_bit_p (loop->block_bitmap, bb->index);
2997 /* Scan the blocks of LOOP (and its inferiors) looking for uses of
2998 REG. Return true, if we find any. Don't count the loop's loop_end
2999 insn if it matches LOOP_END. */
3002 bfin_scan_loop (loop_info loop, rtx reg, rtx loop_end)
3007 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
3011 for (insn = BB_HEAD (bb);
3012 insn != NEXT_INSN (BB_END (bb));
3013 insn = NEXT_INSN (insn))
3017 if (insn == loop_end)
3019 if (reg_mentioned_p (reg, PATTERN (insn)))
3026 /* Optimize LOOP. */
3029 bfin_optimize_loop (loop_info loop)
3033 rtx insn, init_insn, last_insn, nop_insn;
3034 rtx loop_init, start_label, end_label;
3035 rtx reg_lc0, reg_lc1, reg_lt0, reg_lt1, reg_lb0, reg_lb1;
3037 rtx lc_reg, lt_reg, lb_reg;
3041 int inner_depth = 0;
3051 fprintf (dump_file, ";; loop %d bad when found\n", loop->loop_no);
3055 /* Every loop contains in its list of inner loops every loop nested inside
3056 it, even if there are intermediate loops. This works because we're doing
3057 a depth-first search here and never visit a loop more than once. */
3058 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, inner); ix++)
3060 bfin_optimize_loop (inner);
3062 if (!inner->bad && inner_depth < inner->depth)
3064 inner_depth = inner->depth;
3066 loop->clobber_loop0 |= inner->clobber_loop0;
3067 loop->clobber_loop1 |= inner->clobber_loop1;
3071 loop->depth = inner_depth + 1;
3072 if (loop->depth > MAX_LOOP_DEPTH)
3075 fprintf (dump_file, ";; loop %d too deep\n", loop->loop_no);
3079 /* Get the loop iteration register. */
3080 iter_reg = loop->iter_reg;
3082 if (!DPREG_P (iter_reg))
3085 fprintf (dump_file, ";; loop %d iteration count NOT in PREG or DREG\n",
3090 /* Check if start_label appears before loop_end and calculate the
3091 offset between them. We calculate the length of instructions
3094 for (insn = loop->start_label;
3095 insn && insn != loop->loop_end;
3096 insn = NEXT_INSN (insn))
3098 if (JUMP_P (insn) && any_condjump_p (insn) && !optimize_size)
3100 if (TARGET_CSYNC_ANOMALY)
3102 else if (TARGET_SPECLD_ANOMALY)
3105 else if (LABEL_P (insn))
3107 if (TARGET_CSYNC_ANOMALY)
3112 length += get_attr_length (insn);
3118 fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
3123 loop->length = length;
3124 if (loop->length > MAX_LOOP_LENGTH)
3127 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
3131 /* Scan all the blocks to make sure they don't use iter_reg. */
3132 if (bfin_scan_loop (loop, iter_reg, loop->loop_end))
3135 fprintf (dump_file, ";; loop %d uses iterator\n", loop->loop_no);
3139 /* Scan all the insns to see if the loop body clobber
3140 any hardware loop registers. */
3142 reg_lc0 = gen_rtx_REG (SImode, REG_LC0);
3143 reg_lc1 = gen_rtx_REG (SImode, REG_LC1);
3144 reg_lt0 = gen_rtx_REG (SImode, REG_LT0);
3145 reg_lt1 = gen_rtx_REG (SImode, REG_LT1);
3146 reg_lb0 = gen_rtx_REG (SImode, REG_LB0);
3147 reg_lb1 = gen_rtx_REG (SImode, REG_LB1);
3149 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
3153 for (insn = BB_HEAD (bb);
3154 insn != NEXT_INSN (BB_END (bb));
3155 insn = NEXT_INSN (insn))
3160 if (reg_set_p (reg_lc0, insn)
3161 || reg_set_p (reg_lt0, insn)
3162 || reg_set_p (reg_lb0, insn))
3163 loop->clobber_loop0 = 1;
3165 if (reg_set_p (reg_lc1, insn)
3166 || reg_set_p (reg_lt1, insn)
3167 || reg_set_p (reg_lb1, insn))
3168 loop->clobber_loop1 |= 1;
3172 if ((loop->clobber_loop0 && loop->clobber_loop1)
3173 || (loop->depth == MAX_LOOP_DEPTH && loop->clobber_loop0))
3175 loop->depth = MAX_LOOP_DEPTH + 1;
3177 fprintf (dump_file, ";; loop %d no loop reg available\n",
3182 /* There should be an instruction before the loop_end instruction
3183 in the same basic block. And the instruction must not be
3185 - CONDITIONAL BRANCH
3189 - Returns (RTS, RTN, etc.) */
3192 last_insn = PREV_INSN (loop->loop_end);
3196 for (; last_insn != PREV_INSN (BB_HEAD (bb));
3197 last_insn = PREV_INSN (last_insn))
3198 if (INSN_P (last_insn))
3201 if (last_insn != PREV_INSN (BB_HEAD (bb)))
3204 if (single_pred_p (bb)
3205 && single_pred (bb) != ENTRY_BLOCK_PTR)
3207 bb = single_pred (bb);
3208 last_insn = BB_END (bb);
3213 last_insn = NULL_RTX;
3221 fprintf (dump_file, ";; loop %d has no last instruction\n",
3226 if (JUMP_P (last_insn))
3228 loop_info inner = bb->aux;
3230 && inner->outer == loop
3231 && inner->loop_end == last_insn
3232 && inner->depth == 1)
3233 /* This jump_insn is the exact loop_end of an inner loop
3234 and to be optimized away. So use the inner's last_insn. */
3235 last_insn = inner->last_insn;
3239 fprintf (dump_file, ";; loop %d has bad last instruction\n",
3244 else if (CALL_P (last_insn)
3245 || get_attr_type (last_insn) == TYPE_SYNC
3246 || recog_memoized (last_insn) == CODE_FOR_return_internal)
3249 fprintf (dump_file, ";; loop %d has bad last instruction\n",
3254 if (GET_CODE (PATTERN (last_insn)) == ASM_INPUT
3255 || asm_noperands (PATTERN (last_insn)) >= 0
3256 || get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI)
3258 nop_insn = emit_insn_after (gen_nop (), last_insn);
3259 last_insn = nop_insn;
3262 loop->last_insn = last_insn;
3264 /* The loop is good for replacement. */
3265 start_label = loop->start_label;
3266 end_label = gen_label_rtx ();
3267 iter_reg = loop->iter_reg;
3269 if (loop->depth == 1 && !loop->clobber_loop1)
3274 loop->clobber_loop1 = 1;
3281 loop->clobber_loop0 = 1;
3284 /* If iter_reg is a DREG, we need generate an instruction to load
3285 the loop count into LC register. */
3286 if (D_REGNO_P (REGNO (iter_reg)))
3288 init_insn = gen_movsi (lc_reg, iter_reg);
3289 loop_init = gen_lsetup_without_autoinit (lt_reg, start_label,
3293 else if (P_REGNO_P (REGNO (iter_reg)))
3295 init_insn = NULL_RTX;
3296 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
3303 loop->init = init_insn;
3304 loop->end_label = end_label;
3305 loop->loop_init = loop_init;
3309 fprintf (dump_file, ";; replacing loop %d initializer with\n",
3311 print_rtl_single (dump_file, loop->loop_init);
3312 fprintf (dump_file, ";; replacing loop %d terminator with\n",
3314 print_rtl_single (dump_file, loop->loop_end);
3319 if (loop->init != NULL_RTX)
3320 emit_insn (loop->init);
3321 emit_insn(loop->loop_init);
3322 emit_label (loop->start_label);
3327 emit_insn_after (seq, BB_END (loop->predecessor));
3328 delete_insn (loop->loop_end);
3330 /* Insert the loop end label before the last instruction of the loop. */
3331 emit_label_before (loop->end_label, loop->last_insn);
3338 fprintf (dump_file, ";; loop %d is bad\n", loop->loop_no);
3342 if (DPREG_P (loop->iter_reg))
3344 /* If loop->iter_reg is a DREG or PREG, we can split it here
3345 without scratch register. */
3348 emit_insn_before (gen_addsi3 (loop->iter_reg,
3353 emit_insn_before (gen_cmpsi (loop->iter_reg, const0_rtx),
3356 insn = emit_jump_insn_before (gen_bne (loop->start_label),
3359 JUMP_LABEL (insn) = loop->start_label;
3360 LABEL_NUSES (loop->start_label)++;
3361 delete_insn (loop->loop_end);
3365 /* Called from bfin_reorg_loops when a potential loop end is found. LOOP is
3366 a newly set up structure describing the loop, it is this function's
3367 responsibility to fill most of it. TAIL_BB and TAIL_INSN point to the
3368 loop_end insn and its enclosing basic block. */
3371 bfin_discover_loop (loop_info loop, basic_block tail_bb, rtx tail_insn)
3375 VEC (basic_block,heap) *works = VEC_alloc (basic_block,heap,20);
3377 loop->tail = tail_bb;
3378 loop->head = BRANCH_EDGE (tail_bb)->dest;
3379 loop->successor = FALLTHRU_EDGE (tail_bb)->dest;
3380 loop->predecessor = NULL;
3381 loop->loop_end = tail_insn;
3382 loop->last_insn = NULL_RTX;
3383 loop->iter_reg = SET_DEST (XVECEXP (PATTERN (tail_insn), 0, 1));
3384 loop->depth = loop->length = 0;
3386 loop->clobber_loop0 = loop->clobber_loop1 = 0;
3390 loop->init = loop->loop_init = NULL_RTX;
3391 loop->start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (tail_insn), 0, 0)), 1), 0);
3392 loop->end_label = NULL_RTX;
3395 VEC_safe_push (basic_block, heap, works, loop->head);
3397 while (VEC_iterate (basic_block, works, dwork++, bb))
3401 if (bb == EXIT_BLOCK_PTR)
3403 /* We've reached the exit block. The loop must be bad. */
3406 ";; Loop is bad - reached exit block while scanning\n");
3411 if (bitmap_bit_p (loop->block_bitmap, bb->index))
3414 /* We've not seen this block before. Add it to the loop's
3415 list and then add each successor to the work list. */
3417 VEC_safe_push (basic_block, heap, loop->blocks, bb);
3418 bitmap_set_bit (loop->block_bitmap, bb->index);
3422 FOR_EACH_EDGE (e, ei, bb->succs)
3424 basic_block succ = EDGE_SUCC (bb, ei.index)->dest;
3425 if (!REGNO_REG_SET_P (succ->il.rtl->global_live_at_start,
3426 REGNO (loop->iter_reg)))
3428 if (!VEC_space (basic_block, works, 1))
3432 VEC_block_remove (basic_block, works, 0, dwork);
3436 VEC_reserve (basic_block, heap, works, 1);
3438 VEC_quick_push (basic_block, works, succ);
3445 /* Make sure we only have one entry point. */
3446 if (EDGE_COUNT (loop->head->preds) == 2)
3448 loop->predecessor = EDGE_PRED (loop->head, 0)->src;
3449 if (loop->predecessor == loop->tail)
3450 /* We wanted the other predecessor. */
3451 loop->predecessor = EDGE_PRED (loop->head, 1)->src;
3453 /* We can only place a loop insn on a fall through edge of a
3454 single exit block. */
3455 if (EDGE_COUNT (loop->predecessor->succs) != 1
3456 || !(EDGE_SUCC (loop->predecessor, 0)->flags & EDGE_FALLTHRU)
3457 /* If loop->predecessor is in loop, loop->head is not really
3458 the head of the loop. */
3459 || bfin_bb_in_loop (loop, loop->predecessor))
3460 loop->predecessor = NULL;
3463 if (loop->predecessor == NULL)
3466 fprintf (dump_file, ";; loop has bad predecessor\n");
3471 #ifdef ENABLE_CHECKING
3472 /* Make sure nothing jumps into this loop. This shouldn't happen as we
3473 wouldn't have generated the counted loop patterns in such a case.
3474 However, this test must be done after the test above to detect loops
3475 with invalid headers. */
3477 for (dwork = 0; VEC_iterate (basic_block, loop->blocks, dwork, bb); dwork++)
3481 if (bb == loop->head)
3483 FOR_EACH_EDGE (e, ei, bb->preds)
3485 basic_block pred = EDGE_PRED (bb, ei.index)->src;
3486 if (!bfin_bb_in_loop (loop, pred))
3491 VEC_free (basic_block, heap, works);
3495 bfin_reorg_loops (FILE *dump_file)
3497 bitmap_obstack stack;
3500 loop_info loops = NULL;
3504 bitmap_obstack_initialize (&stack);
3506 /* Find all the possible loop tails. This means searching for every
3507 loop_end instruction. For each one found, create a loop_info
3508 structure and add the head block to the work list. */
3511 rtx tail = BB_END (bb);
3513 while (GET_CODE (tail) == NOTE)
3514 tail = PREV_INSN (tail);
3518 if (INSN_P (tail) && recog_memoized (tail) == CODE_FOR_loop_end)
3520 /* A possible loop end */
3522 loop = XNEW (struct loop_info);
3525 loop->loop_no = nloops++;
3526 loop->blocks = VEC_alloc (basic_block, heap, 20);
3527 loop->block_bitmap = BITMAP_ALLOC (&stack);
3532 fprintf (dump_file, ";; potential loop %d ending at\n",
3534 print_rtl_single (dump_file, tail);
3537 bfin_discover_loop (loop, bb, tail);
3541 tmp_bitmap = BITMAP_ALLOC (&stack);
3542 /* Compute loop nestings. */
3543 for (loop = loops; loop; loop = loop->next)
3549 for (other = loop->next; other; other = other->next)
3554 bitmap_and (tmp_bitmap, other->block_bitmap, loop->block_bitmap);
3555 if (bitmap_empty_p (tmp_bitmap))
3557 if (bitmap_equal_p (tmp_bitmap, other->block_bitmap))
3559 other->outer = loop;
3560 VEC_safe_push (loop_info, heap, loop->loops, other);
3562 else if (bitmap_equal_p (tmp_bitmap, loop->block_bitmap))
3564 loop->outer = other;
3565 VEC_safe_push (loop_info, heap, other->loops, loop);
3569 loop->bad = other->bad = 1;
3573 BITMAP_FREE (tmp_bitmap);
3577 fprintf (dump_file, ";; All loops found:\n\n");
3578 bfin_dump_loops (loops);
3581 /* Now apply the optimizations. */
3582 for (loop = loops; loop; loop = loop->next)
3583 bfin_optimize_loop (loop);
3587 fprintf (dump_file, ";; After hardware loops optimization:\n\n");
3588 bfin_dump_loops (loops);
3591 /* Free up the loop structures */
3596 VEC_free (loop_info, heap, loop->loops);
3597 VEC_free (basic_block, heap, loop->blocks);
3598 BITMAP_FREE (loop->block_bitmap);
3603 print_rtl (dump_file, get_insns ());
3607 /* We use the machine specific reorg pass for emitting CSYNC instructions
3608 after conditional branches as needed.
3610 The Blackfin is unusual in that a code sequence like
3613 may speculatively perform the load even if the condition isn't true. This
3614 happens for a branch that is predicted not taken, because the pipeline
3615 isn't flushed or stalled, so the early stages of the following instructions,
3616 which perform the memory reference, are allowed to execute before the
3617 jump condition is evaluated.
3618 Therefore, we must insert additional instructions in all places where this
3619 could lead to incorrect behavior. The manual recommends CSYNC, while
3620 VDSP seems to use NOPs (even though its corresponding compiler option is
3623 When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
3624 When optimizing for size, we turn the branch into a predicted taken one.
3625 This may be slower due to mispredicts, but saves code size. */
3630 rtx insn, last_condjump = NULL_RTX;
3631 int cycles_since_jump = INT_MAX;
3633 /* Doloop optimization */
3634 if (cfun->machine->has_hardware_loops)
3635 bfin_reorg_loops (dump_file);
3637 if (! TARGET_SPECLD_ANOMALY && ! TARGET_CSYNC_ANOMALY)
3640 /* First pass: find predicted-false branches; if something after them
3641 needs nops, insert them or change the branch to predict true. */
3642 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
3646 if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
3649 pat = PATTERN (insn);
3650 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
3651 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
3652 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
3657 if (any_condjump_p (insn)
3658 && ! cbranch_predicted_taken_p (insn))
3660 last_condjump = insn;
3661 cycles_since_jump = 0;
3664 cycles_since_jump = INT_MAX;
3666 else if (INSN_P (insn))
3668 enum attr_type type = get_attr_type (insn);
3669 int delay_needed = 0;
3670 if (cycles_since_jump < INT_MAX)
3671 cycles_since_jump++;
3673 if (type == TYPE_MCLD && TARGET_SPECLD_ANOMALY)
3675 rtx pat = single_set (insn);
3676 if (may_trap_p (SET_SRC (pat)))
3679 else if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
3682 if (delay_needed > cycles_since_jump)
3686 rtx *op = recog_data.operand;
3688 delay_needed -= cycles_since_jump;
3690 extract_insn (last_condjump);
3693 pat = gen_cbranch_predicted_taken (op[0], op[1], op[2],
3695 cycles_since_jump = INT_MAX;
3698 /* Do not adjust cycles_since_jump in this case, so that
3699 we'll increase the number of NOPs for a subsequent insn
3701 pat = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
3702 GEN_INT (delay_needed));
3703 PATTERN (last_condjump) = pat;
3704 INSN_CODE (last_condjump) = recog (pat, insn, &num_clobbers);
3708 /* Second pass: for predicted-true branches, see if anything at the
3709 branch destination needs extra nops. */
3710 if (! TARGET_CSYNC_ANOMALY)
3713 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
3716 && any_condjump_p (insn)
3717 && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken
3718 || cbranch_predicted_taken_p (insn)))
3720 rtx target = JUMP_LABEL (insn);
3722 cycles_since_jump = 0;
3723 for (; target && cycles_since_jump < 3; target = NEXT_INSN (target))
3727 if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
3730 pat = PATTERN (target);
3731 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
3732 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
3733 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
3736 if (INSN_P (target))
3738 enum attr_type type = get_attr_type (target);
3739 int delay_needed = 0;
3740 if (cycles_since_jump < INT_MAX)
3741 cycles_since_jump++;
3743 if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
3746 if (delay_needed > cycles_since_jump)
3748 rtx prev = prev_real_insn (label);
3749 delay_needed -= cycles_since_jump;
3751 fprintf (dump_file, "Adding %d nops after %d\n",
3752 delay_needed, INSN_UID (label));
3754 && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops)
3761 "Reducing nops on insn %d.\n",
3764 x = XVECEXP (x, 0, 1);
3765 v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed;
3766 XVECEXP (x, 0, 0) = GEN_INT (v);
3768 while (delay_needed-- > 0)
3769 emit_insn_after (gen_nop (), label);
3778 /* Handle interrupt_handler, exception_handler and nmi_handler function
3779 attributes; arguments as in struct attribute_spec.handler. */
3782 handle_int_attribute (tree *node, tree name,
3783 tree args ATTRIBUTE_UNUSED,
3784 int flags ATTRIBUTE_UNUSED,
3788 if (TREE_CODE (x) == FUNCTION_DECL)
3791 if (TREE_CODE (x) != FUNCTION_TYPE)
3793 warning (OPT_Wattributes, "%qs attribute only applies to functions",
3794 IDENTIFIER_POINTER (name));
3795 *no_add_attrs = true;
3797 else if (funkind (x) != SUBROUTINE)
3798 error ("multiple function type attributes specified");
3803 /* Return 0 if the attributes for two types are incompatible, 1 if they
3804 are compatible, and 2 if they are nearly compatible (which causes a
3805 warning to be generated). */
3808 bfin_comp_type_attributes (tree type1, tree type2)
3810 e_funkind kind1, kind2;
3812 if (TREE_CODE (type1) != FUNCTION_TYPE)
3815 kind1 = funkind (type1);
3816 kind2 = funkind (type2);
3821 /* Check for mismatched modifiers */
3822 if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
3823 != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
3826 if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
3827 != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
3830 if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
3831 != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
3834 if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1))
3835 != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2)))
3841 /* Handle a "longcall" or "shortcall" attribute; arguments as in
3842 struct attribute_spec.handler. */
3845 bfin_handle_longcall_attribute (tree *node, tree name,
3846 tree args ATTRIBUTE_UNUSED,
3847 int flags ATTRIBUTE_UNUSED,
3850 if (TREE_CODE (*node) != FUNCTION_TYPE
3851 && TREE_CODE (*node) != FIELD_DECL
3852 && TREE_CODE (*node) != TYPE_DECL)
3854 warning (OPT_Wattributes, "`%s' attribute only applies to functions",
3855 IDENTIFIER_POINTER (name));
3856 *no_add_attrs = true;
3859 if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0
3860 && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node)))
3861 || (strcmp (IDENTIFIER_POINTER (name), "shortcall") == 0
3862 && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node))))
3864 warning (OPT_Wattributes,
3865 "can't apply both longcall and shortcall attributes to the same function");
3866 *no_add_attrs = true;
3872 /* Table of valid machine attributes. */
3873 const struct attribute_spec bfin_attribute_table[] =
3875 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
3876 { "interrupt_handler", 0, 0, false, true, true, handle_int_attribute },
3877 { "exception_handler", 0, 0, false, true, true, handle_int_attribute },
3878 { "nmi_handler", 0, 0, false, true, true, handle_int_attribute },
3879 { "nesting", 0, 0, false, true, true, NULL },
3880 { "kspisusp", 0, 0, false, true, true, NULL },
3881 { "saveall", 0, 0, false, true, true, NULL },
3882 { "longcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
3883 { "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
3884 { NULL, 0, 0, false, false, false, NULL }
3887 /* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to
3888 tell the assembler to generate pointers to function descriptors in
3892 bfin_assemble_integer (rtx value, unsigned int size, int aligned_p)
3894 if (TARGET_FDPIC && size == UNITS_PER_WORD)
3896 if (GET_CODE (value) == SYMBOL_REF
3897 && SYMBOL_REF_FUNCTION_P (value))
3899 fputs ("\t.picptr\tfuncdesc(", asm_out_file);
3900 output_addr_const (asm_out_file, value);
3901 fputs (")\n", asm_out_file);
3906 /* We've set the unaligned SI op to NULL, so we always have to
3907 handle the unaligned case here. */
3908 assemble_integer_with_op ("\t.4byte\t", value);
3912 return default_assemble_integer (value, size, aligned_p);
3915 /* Output the assembler code for a thunk function. THUNK_DECL is the
3916 declaration for the thunk function itself, FUNCTION is the decl for
3917 the target function. DELTA is an immediate constant offset to be
3918 added to THIS. If VCALL_OFFSET is nonzero, the word at
3919 *(*this + vcall_offset) should be added to THIS. */
3922 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
3923 tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
3924 HOST_WIDE_INT vcall_offset, tree function)
3927 /* The this parameter is passed as the first argument. */
3928 rtx this = gen_rtx_REG (Pmode, REG_R0);
3930 /* Adjust the this parameter by a fixed constant. */
3934 if (delta >= -64 && delta <= 63)
3936 xops[0] = GEN_INT (delta);
3937 output_asm_insn ("%1 += %0;", xops);
3939 else if (delta >= -128 && delta < -64)
3941 xops[0] = GEN_INT (delta + 64);
3942 output_asm_insn ("%1 += -64; %1 += %0;", xops);
3944 else if (delta > 63 && delta <= 126)
3946 xops[0] = GEN_INT (delta - 63);
3947 output_asm_insn ("%1 += 63; %1 += %0;", xops);
3951 xops[0] = GEN_INT (delta);
3952 output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
3956 /* Adjust the this parameter by a value stored in the vtable. */
3959 rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
3960 rtx tmp = gen_rtx_REG (Pmode, REG_R2);
3964 output_asm_insn ("%2 = r0; %2 = [%2];", xops);
3966 /* Adjust the this parameter. */
3967 xops[0] = gen_rtx_MEM (Pmode, plus_constant (p2tmp, vcall_offset));
3968 if (!memory_operand (xops[0], Pmode))
3970 rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
3971 xops[0] = GEN_INT (vcall_offset);
3973 output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
3974 xops[0] = gen_rtx_MEM (Pmode, p2tmp);
3977 output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
3980 xops[0] = XEXP (DECL_RTL (function), 0);
3981 if (1 || !flag_pic || (*targetm.binds_local_p) (function))
3982 output_asm_insn ("jump.l\t%P0", xops);
3985 /* Codes for all the Blackfin builtins. */
3990 BFIN_BUILTIN_COMPOSE_2X16,
3991 BFIN_BUILTIN_EXTRACTLO,
3992 BFIN_BUILTIN_EXTRACTHI,
3994 BFIN_BUILTIN_SSADD_2X16,
3995 BFIN_BUILTIN_SSSUB_2X16,
3996 BFIN_BUILTIN_SSADDSUB_2X16,
3997 BFIN_BUILTIN_SSSUBADD_2X16,
3998 BFIN_BUILTIN_MULT_2X16,
3999 BFIN_BUILTIN_MULTR_2X16,
4000 BFIN_BUILTIN_NEG_2X16,
4001 BFIN_BUILTIN_ABS_2X16,
4002 BFIN_BUILTIN_MIN_2X16,
4003 BFIN_BUILTIN_MAX_2X16,
4005 BFIN_BUILTIN_SSADD_1X16,
4006 BFIN_BUILTIN_SSSUB_1X16,
4007 BFIN_BUILTIN_MULT_1X16,
4008 BFIN_BUILTIN_MULTR_1X16,
4009 BFIN_BUILTIN_NORM_1X16,
4010 BFIN_BUILTIN_NEG_1X16,
4011 BFIN_BUILTIN_ABS_1X16,
4012 BFIN_BUILTIN_MIN_1X16,
4013 BFIN_BUILTIN_MAX_1X16,
4015 BFIN_BUILTIN_DIFFHL_2X16,
4016 BFIN_BUILTIN_DIFFLH_2X16,
4018 BFIN_BUILTIN_SSADD_1X32,
4019 BFIN_BUILTIN_SSSUB_1X32,
4020 BFIN_BUILTIN_NORM_1X32,
4021 BFIN_BUILTIN_NEG_1X32,
4022 BFIN_BUILTIN_MIN_1X32,
4023 BFIN_BUILTIN_MAX_1X32,
4024 BFIN_BUILTIN_MULT_1X32,
4026 BFIN_BUILTIN_MULHISILL,
4027 BFIN_BUILTIN_MULHISILH,
4028 BFIN_BUILTIN_MULHISIHL,
4029 BFIN_BUILTIN_MULHISIHH,
4031 BFIN_BUILTIN_LSHIFT_1X16,
4032 BFIN_BUILTIN_LSHIFT_2X16,
4033 BFIN_BUILTIN_SSASHIFT_1X16,
4034 BFIN_BUILTIN_SSASHIFT_2X16,
4036 BFIN_BUILTIN_CPLX_MUL_16,
4037 BFIN_BUILTIN_CPLX_MAC_16,
4038 BFIN_BUILTIN_CPLX_MSU_16,
4043 #define def_builtin(NAME, TYPE, CODE) \
4045 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
4049 /* Set up all builtin functions for this target. */
4051 bfin_init_builtins (void)
4053 tree V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
4054 tree void_ftype_void
4055 = build_function_type (void_type_node, void_list_node);
4056 tree short_ftype_short
4057 = build_function_type_list (short_integer_type_node, short_integer_type_node,
4059 tree short_ftype_int_int
4060 = build_function_type_list (short_integer_type_node, integer_type_node,
4061 integer_type_node, NULL_TREE);
4062 tree int_ftype_int_int
4063 = build_function_type_list (integer_type_node, integer_type_node,
4064 integer_type_node, NULL_TREE);
4066 = build_function_type_list (integer_type_node, integer_type_node,
4068 tree short_ftype_int
4069 = build_function_type_list (short_integer_type_node, integer_type_node,
4071 tree int_ftype_v2hi_v2hi
4072 = build_function_type_list (integer_type_node, V2HI_type_node,
4073 V2HI_type_node, NULL_TREE);
4074 tree v2hi_ftype_v2hi_v2hi
4075 = build_function_type_list (V2HI_type_node, V2HI_type_node,
4076 V2HI_type_node, NULL_TREE);
4077 tree v2hi_ftype_v2hi_v2hi_v2hi
4078 = build_function_type_list (V2HI_type_node, V2HI_type_node,
4079 V2HI_type_node, V2HI_type_node, NULL_TREE);
4080 tree v2hi_ftype_int_int
4081 = build_function_type_list (V2HI_type_node, integer_type_node,
4082 integer_type_node, NULL_TREE);
4083 tree v2hi_ftype_v2hi_int
4084 = build_function_type_list (V2HI_type_node, V2HI_type_node,
4085 integer_type_node, NULL_TREE);
4086 tree int_ftype_short_short
4087 = build_function_type_list (integer_type_node, short_integer_type_node,
4088 short_integer_type_node, NULL_TREE);
4089 tree v2hi_ftype_v2hi
4090 = build_function_type_list (V2HI_type_node, V2HI_type_node, NULL_TREE);
4091 tree short_ftype_v2hi
4092 = build_function_type_list (short_integer_type_node, V2HI_type_node,
4095 /* Add the remaining MMX insns with somewhat more complicated types. */
4096 def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC);
4097 def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC);
4099 def_builtin ("__builtin_bfin_compose_2x16", v2hi_ftype_int_int,
4100 BFIN_BUILTIN_COMPOSE_2X16);
4101 def_builtin ("__builtin_bfin_extract_hi", short_ftype_v2hi,
4102 BFIN_BUILTIN_EXTRACTHI);
4103 def_builtin ("__builtin_bfin_extract_lo", short_ftype_v2hi,
4104 BFIN_BUILTIN_EXTRACTLO);
4106 def_builtin ("__builtin_bfin_min_fr2x16", v2hi_ftype_v2hi_v2hi,
4107 BFIN_BUILTIN_MIN_2X16);
4108 def_builtin ("__builtin_bfin_max_fr2x16", v2hi_ftype_v2hi_v2hi,
4109 BFIN_BUILTIN_MAX_2X16);
4111 def_builtin ("__builtin_bfin_add_fr2x16", v2hi_ftype_v2hi_v2hi,
4112 BFIN_BUILTIN_SSADD_2X16);
4113 def_builtin ("__builtin_bfin_sub_fr2x16", v2hi_ftype_v2hi_v2hi,
4114 BFIN_BUILTIN_SSSUB_2X16);
4115 def_builtin ("__builtin_bfin_dspaddsubsat", v2hi_ftype_v2hi_v2hi,
4116 BFIN_BUILTIN_SSADDSUB_2X16);
4117 def_builtin ("__builtin_bfin_dspsubaddsat", v2hi_ftype_v2hi_v2hi,
4118 BFIN_BUILTIN_SSSUBADD_2X16);
4119 def_builtin ("__builtin_bfin_mult_fr2x16", v2hi_ftype_v2hi_v2hi,
4120 BFIN_BUILTIN_MULT_2X16);
4121 def_builtin ("__builtin_bfin_multr_fr2x16", v2hi_ftype_v2hi_v2hi,
4122 BFIN_BUILTIN_MULTR_2X16);
4123 def_builtin ("__builtin_bfin_negate_fr2x16", v2hi_ftype_v2hi,
4124 BFIN_BUILTIN_NEG_2X16);
4125 def_builtin ("__builtin_bfin_abs_fr2x16", v2hi_ftype_v2hi,
4126 BFIN_BUILTIN_ABS_2X16);
4128 def_builtin ("__builtin_bfin_add_fr1x16", short_ftype_int_int,
4129 BFIN_BUILTIN_SSADD_1X16);
4130 def_builtin ("__builtin_bfin_sub_fr1x16", short_ftype_int_int,
4131 BFIN_BUILTIN_SSSUB_1X16);
4132 def_builtin ("__builtin_bfin_mult_fr1x16", short_ftype_int_int,
4133 BFIN_BUILTIN_MULT_1X16);
4134 def_builtin ("__builtin_bfin_multr_fr1x16", short_ftype_int_int,
4135 BFIN_BUILTIN_MULTR_1X16);
4136 def_builtin ("__builtin_bfin_negate_fr1x16", short_ftype_short,
4137 BFIN_BUILTIN_NEG_1X16);
4138 def_builtin ("__builtin_bfin_abs_fr1x16", short_ftype_short,
4139 BFIN_BUILTIN_ABS_1X16);
4140 def_builtin ("__builtin_bfin_norm_fr1x16", short_ftype_int,
4141 BFIN_BUILTIN_NORM_1X16);
4143 def_builtin ("__builtin_bfin_diff_hl_fr2x16", short_ftype_v2hi,
4144 BFIN_BUILTIN_DIFFHL_2X16);
4145 def_builtin ("__builtin_bfin_diff_lh_fr2x16", short_ftype_v2hi,
4146 BFIN_BUILTIN_DIFFLH_2X16);
4148 def_builtin ("__builtin_bfin_mulhisill", int_ftype_v2hi_v2hi,
4149 BFIN_BUILTIN_MULHISILL);
4150 def_builtin ("__builtin_bfin_mulhisihl", int_ftype_v2hi_v2hi,
4151 BFIN_BUILTIN_MULHISIHL);
4152 def_builtin ("__builtin_bfin_mulhisilh", int_ftype_v2hi_v2hi,
4153 BFIN_BUILTIN_MULHISILH);
4154 def_builtin ("__builtin_bfin_mulhisihh", int_ftype_v2hi_v2hi,
4155 BFIN_BUILTIN_MULHISIHH);
4157 def_builtin ("__builtin_bfin_add_fr1x32", int_ftype_int_int,
4158 BFIN_BUILTIN_SSADD_1X32);
4159 def_builtin ("__builtin_bfin_sub_fr1x32", int_ftype_int_int,
4160 BFIN_BUILTIN_SSSUB_1X32);
4161 def_builtin ("__builtin_bfin_negate_fr1x32", int_ftype_int,
4162 BFIN_BUILTIN_NEG_1X32);
4163 def_builtin ("__builtin_bfin_norm_fr1x32", short_ftype_int,
4164 BFIN_BUILTIN_NORM_1X32);
4165 def_builtin ("__builtin_bfin_mult_fr1x32", int_ftype_short_short,
4166 BFIN_BUILTIN_MULT_1X32);
4169 def_builtin ("__builtin_bfin_shl_fr1x16", short_ftype_int_int,
4170 BFIN_BUILTIN_SSASHIFT_1X16);
4171 def_builtin ("__builtin_bfin_shl_fr2x16", v2hi_ftype_v2hi_int,
4172 BFIN_BUILTIN_SSASHIFT_2X16);
4173 def_builtin ("__builtin_bfin_lshl_fr1x16", short_ftype_int_int,
4174 BFIN_BUILTIN_LSHIFT_1X16);
4175 def_builtin ("__builtin_bfin_lshl_fr2x16", v2hi_ftype_v2hi_int,
4176 BFIN_BUILTIN_LSHIFT_2X16);
4178 /* Complex numbers. */
4179 def_builtin ("__builtin_bfin_cmplx_mul", v2hi_ftype_v2hi_v2hi,
4180 BFIN_BUILTIN_CPLX_MUL_16);
4181 def_builtin ("__builtin_bfin_cmplx_mac", v2hi_ftype_v2hi_v2hi_v2hi,
4182 BFIN_BUILTIN_CPLX_MAC_16);
4183 def_builtin ("__builtin_bfin_cmplx_msu", v2hi_ftype_v2hi_v2hi_v2hi,
4184 BFIN_BUILTIN_CPLX_MSU_16);
4188 struct builtin_description
4190 const enum insn_code icode;
4191 const char *const name;
4192 const enum bfin_builtins code;
4196 static const struct builtin_description bdesc_2arg[] =
4198 { CODE_FOR_composev2hi, "__builtin_bfin_compose_2x16", BFIN_BUILTIN_COMPOSE_2X16, -1 },
4200 { CODE_FOR_ssashiftv2hi3, "__builtin_bfin_shl_fr2x16", BFIN_BUILTIN_SSASHIFT_2X16, -1 },
4201 { CODE_FOR_ssashifthi3, "__builtin_bfin_shl_fr1x16", BFIN_BUILTIN_SSASHIFT_1X16, -1 },
4202 { CODE_FOR_lshiftv2hi3, "__builtin_bfin_lshl_fr2x16", BFIN_BUILTIN_LSHIFT_2X16, -1 },
4203 { CODE_FOR_lshifthi3, "__builtin_bfin_lshl_fr1x16", BFIN_BUILTIN_LSHIFT_1X16, -1 },
4205 { CODE_FOR_sminhi3, "__builtin_bfin_min_fr1x16", BFIN_BUILTIN_MIN_1X16, -1 },
4206 { CODE_FOR_smaxhi3, "__builtin_bfin_max_fr1x16", BFIN_BUILTIN_MAX_1X16, -1 },
4207 { CODE_FOR_ssaddhi3, "__builtin_bfin_add_fr1x16", BFIN_BUILTIN_SSADD_1X16, -1 },
4208 { CODE_FOR_sssubhi3, "__builtin_bfin_sub_fr1x16", BFIN_BUILTIN_SSSUB_1X16, -1 },
4210 { CODE_FOR_sminsi3, "__builtin_bfin_min_fr1x32", BFIN_BUILTIN_MIN_1X32, -1 },
4211 { CODE_FOR_smaxsi3, "__builtin_bfin_max_fr1x32", BFIN_BUILTIN_MAX_1X32, -1 },
4212 { CODE_FOR_ssaddsi3, "__builtin_bfin_add_fr1x32", BFIN_BUILTIN_SSADD_1X32, -1 },
4213 { CODE_FOR_sssubsi3, "__builtin_bfin_sub_fr1x32", BFIN_BUILTIN_SSSUB_1X32, -1 },
4215 { CODE_FOR_sminv2hi3, "__builtin_bfin_min_fr2x16", BFIN_BUILTIN_MIN_2X16, -1 },
4216 { CODE_FOR_smaxv2hi3, "__builtin_bfin_max_fr2x16", BFIN_BUILTIN_MAX_2X16, -1 },
4217 { CODE_FOR_ssaddv2hi3, "__builtin_bfin_add_fr2x16", BFIN_BUILTIN_SSADD_2X16, -1 },
4218 { CODE_FOR_sssubv2hi3, "__builtin_bfin_sub_fr2x16", BFIN_BUILTIN_SSSUB_2X16, -1 },
4219 { CODE_FOR_ssaddsubv2hi3, "__builtin_bfin_dspaddsubsat", BFIN_BUILTIN_SSADDSUB_2X16, -1 },
4220 { CODE_FOR_sssubaddv2hi3, "__builtin_bfin_dspsubaddsat", BFIN_BUILTIN_SSSUBADD_2X16, -1 },
4222 { CODE_FOR_flag_mulhisi, "__builtin_bfin_mult_fr1x32", BFIN_BUILTIN_MULT_1X32, MACFLAG_NONE },
4223 { CODE_FOR_flag_mulhi, "__builtin_bfin_mult_fr1x16", BFIN_BUILTIN_MULT_1X16, MACFLAG_T },
4224 { CODE_FOR_flag_mulhi, "__builtin_bfin_multr_fr1x16", BFIN_BUILTIN_MULTR_1X16, MACFLAG_NONE },
4225 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_mult_fr2x16", BFIN_BUILTIN_MULT_2X16, MACFLAG_T },
4226 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_multr_fr2x16", BFIN_BUILTIN_MULTR_2X16, MACFLAG_NONE }
4229 static const struct builtin_description bdesc_1arg[] =
4231 { CODE_FOR_signbitshi2, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16, 0 },
4232 { CODE_FOR_ssneghi2, "__builtin_bfin_negate_fr1x16", BFIN_BUILTIN_NEG_1X16, 0 },
4233 { CODE_FOR_abshi2, "__builtin_bfin_abs_fr1x16", BFIN_BUILTIN_ABS_1X16, 0 },
4235 { CODE_FOR_signbitssi2, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32, 0 },
4236 { CODE_FOR_ssnegsi2, "__builtin_bfin_negate_fr1x32", BFIN_BUILTIN_NEG_1X32, 0 },
4238 { CODE_FOR_movv2hi_hi_low, "__builtin_bfin_extract_lo", BFIN_BUILTIN_EXTRACTLO, 0 },
4239 { CODE_FOR_movv2hi_hi_high, "__builtin_bfin_extract_hi", BFIN_BUILTIN_EXTRACTHI, 0 },
4240 { CODE_FOR_ssnegv2hi2, "__builtin_bfin_negate_fr2x16", BFIN_BUILTIN_NEG_2X16, 0 },
4241 { CODE_FOR_absv2hi2, "__builtin_bfin_abs_fr2x16", BFIN_BUILTIN_ABS_2X16, 0 }
4244 /* Errors in the source file can cause expand_expr to return const0_rtx
4245 where we expect a vector. To avoid crashing, use one of the vector
4246 clear instructions. */
4248 safe_vector_operand (rtx x, enum machine_mode mode)
4250 if (x != const0_rtx)
4252 x = gen_reg_rtx (SImode);
4254 emit_insn (gen_movsi (x, CONST0_RTX (SImode)));
4255 return gen_lowpart (mode, x);
4258 /* Subroutine of bfin_expand_builtin to take care of binop insns. MACFLAG is -1
4259 if this is a normal binary op, or one of the MACFLAG_xxx constants. */
4262 bfin_expand_binop_builtin (enum insn_code icode, tree arglist, rtx target,
4266 tree arg0 = TREE_VALUE (arglist);
4267 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
4268 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4269 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
4270 enum machine_mode op0mode = GET_MODE (op0);
4271 enum machine_mode op1mode = GET_MODE (op1);
4272 enum machine_mode tmode = insn_data[icode].operand[0].mode;
4273 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
4274 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
4276 if (VECTOR_MODE_P (mode0))
4277 op0 = safe_vector_operand (op0, mode0);
4278 if (VECTOR_MODE_P (mode1))
4279 op1 = safe_vector_operand (op1, mode1);
4282 || GET_MODE (target) != tmode
4283 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
4284 target = gen_reg_rtx (tmode);
4286 if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode)
4289 op0 = gen_lowpart (HImode, op0);
4291 if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode)
4294 op1 = gen_lowpart (HImode, op1);
4296 /* In case the insn wants input operands in modes different from
4297 the result, abort. */
4298 gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
4299 && (op1mode == mode1 || op1mode == VOIDmode));
4301 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
4302 op0 = copy_to_mode_reg (mode0, op0);
4303 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
4304 op1 = copy_to_mode_reg (mode1, op1);
4307 pat = GEN_FCN (icode) (target, op0, op1);
4309 pat = GEN_FCN (icode) (target, op0, op1, GEN_INT (macflag));
4317 /* Subroutine of bfin_expand_builtin to take care of unop insns. */
4320 bfin_expand_unop_builtin (enum insn_code icode, tree arglist,
4324 tree arg0 = TREE_VALUE (arglist);
4325 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4326 enum machine_mode op0mode = GET_MODE (op0);
4327 enum machine_mode tmode = insn_data[icode].operand[0].mode;
4328 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
4331 || GET_MODE (target) != tmode
4332 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
4333 target = gen_reg_rtx (tmode);
4335 if (VECTOR_MODE_P (mode0))
4336 op0 = safe_vector_operand (op0, mode0);
4338 if (op0mode == SImode && mode0 == HImode)
4341 op0 = gen_lowpart (HImode, op0);
4343 gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
4345 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
4346 op0 = copy_to_mode_reg (mode0, op0);
4348 pat = GEN_FCN (icode) (target, op0);
4355 /* Expand an expression EXP that calls a built-in function,
4356 with result going to TARGET if that's convenient
4357 (and in mode MODE if that's convenient).
4358 SUBTARGET may be used as the target for computing one of EXP's operands.
4359 IGNORE is nonzero if the value is to be ignored. */
4362 bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
4363 rtx subtarget ATTRIBUTE_UNUSED,
4364 enum machine_mode mode ATTRIBUTE_UNUSED,
4365 int ignore ATTRIBUTE_UNUSED)
4368 enum insn_code icode;
4369 const struct builtin_description *d;
4370 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
4371 tree arglist = TREE_OPERAND (exp, 1);
4372 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
4373 tree arg0, arg1, arg2;
4374 rtx op0, op1, op2, accvec, pat, tmp1, tmp2;
4375 enum machine_mode tmode, mode0;
4379 case BFIN_BUILTIN_CSYNC:
4380 emit_insn (gen_csync ());
4382 case BFIN_BUILTIN_SSYNC:
4383 emit_insn (gen_ssync ());
4386 case BFIN_BUILTIN_DIFFHL_2X16:
4387 case BFIN_BUILTIN_DIFFLH_2X16:
4388 arg0 = TREE_VALUE (arglist);
4389 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4390 icode = (fcode == BFIN_BUILTIN_DIFFHL_2X16
4391 ? CODE_FOR_subhilov2hi3 : CODE_FOR_sublohiv2hi3);
4392 tmode = insn_data[icode].operand[0].mode;
4393 mode0 = insn_data[icode].operand[1].mode;
4396 || GET_MODE (target) != tmode
4397 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
4398 target = gen_reg_rtx (tmode);
4400 if (VECTOR_MODE_P (mode0))
4401 op0 = safe_vector_operand (op0, mode0);
4403 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
4404 op0 = copy_to_mode_reg (mode0, op0);
4406 pat = GEN_FCN (icode) (target, op0, op0);
4412 case BFIN_BUILTIN_CPLX_MUL_16:
4413 arg0 = TREE_VALUE (arglist);
4414 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
4415 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4416 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
4417 accvec = gen_reg_rtx (V2PDImode);
4420 || GET_MODE (target) != V2HImode
4421 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
4422 target = gen_reg_rtx (tmode);
4423 if (! register_operand (op0, GET_MODE (op0)))
4424 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
4425 if (! register_operand (op1, GET_MODE (op1)))
4426 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
4428 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
4429 const0_rtx, const0_rtx,
4430 const1_rtx, GEN_INT (MACFLAG_NONE)));
4431 emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
4432 const1_rtx, const1_rtx,
4433 const0_rtx, accvec, const1_rtx, const0_rtx,
4434 GEN_INT (MACFLAG_NONE), accvec));
4438 case BFIN_BUILTIN_CPLX_MAC_16:
4439 case BFIN_BUILTIN_CPLX_MSU_16:
4440 arg0 = TREE_VALUE (arglist);
4441 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
4442 arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
4443 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4444 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
4445 op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
4446 accvec = gen_reg_rtx (V2PDImode);
4449 || GET_MODE (target) != V2HImode
4450 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
4451 target = gen_reg_rtx (tmode);
4452 if (! register_operand (op0, GET_MODE (op0)))
4453 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
4454 if (! register_operand (op1, GET_MODE (op1)))
4455 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
4457 tmp1 = gen_reg_rtx (SImode);
4458 tmp2 = gen_reg_rtx (SImode);
4459 emit_insn (gen_ashlsi3 (tmp1, gen_lowpart (SImode, op2), GEN_INT (16)));
4460 emit_move_insn (tmp2, gen_lowpart (SImode, op2));
4461 emit_insn (gen_movstricthi_1 (gen_lowpart (HImode, tmp2), const0_rtx));
4462 emit_insn (gen_load_accumulator_pair (accvec, tmp1, tmp2));
4463 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op0, op1, const0_rtx,
4464 const0_rtx, const0_rtx,
4465 const1_rtx, accvec, const0_rtx,
4467 GEN_INT (MACFLAG_W32)));
4468 tmp1 = (fcode == BFIN_BUILTIN_CPLX_MAC_16 ? const1_rtx : const0_rtx);
4469 tmp2 = (fcode == BFIN_BUILTIN_CPLX_MAC_16 ? const0_rtx : const1_rtx);
4470 emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
4471 const1_rtx, const1_rtx,
4472 const0_rtx, accvec, tmp1, tmp2,
4473 GEN_INT (MACFLAG_NONE), accvec));
4481 for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
4482 if (d->code == fcode)
4483 return bfin_expand_binop_builtin (d->icode, arglist, target,
4486 for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
4487 if (d->code == fcode)
4488 return bfin_expand_unop_builtin (d->icode, arglist, target);
4493 #undef TARGET_INIT_BUILTINS
4494 #define TARGET_INIT_BUILTINS bfin_init_builtins
4496 #undef TARGET_EXPAND_BUILTIN
4497 #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
4499 #undef TARGET_ASM_GLOBALIZE_LABEL
4500 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label
4502 #undef TARGET_ASM_FILE_START
4503 #define TARGET_ASM_FILE_START output_file_start
4505 #undef TARGET_ATTRIBUTE_TABLE
4506 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
4508 #undef TARGET_COMP_TYPE_ATTRIBUTES
4509 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
4511 #undef TARGET_RTX_COSTS
4512 #define TARGET_RTX_COSTS bfin_rtx_costs
4514 #undef TARGET_ADDRESS_COST
4515 #define TARGET_ADDRESS_COST bfin_address_cost
4517 #undef TARGET_ASM_INTERNAL_LABEL
4518 #define TARGET_ASM_INTERNAL_LABEL bfin_internal_label
4520 #undef TARGET_ASM_INTEGER
4521 #define TARGET_ASM_INTEGER bfin_assemble_integer
4523 #undef TARGET_MACHINE_DEPENDENT_REORG
4524 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
4526 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
4527 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
4529 #undef TARGET_ASM_OUTPUT_MI_THUNK
4530 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
4531 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
4532 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
4534 #undef TARGET_SCHED_ADJUST_COST
4535 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
4537 #undef TARGET_SCHED_ISSUE_RATE
4538 #define TARGET_SCHED_ISSUE_RATE bfin_issue_rate
4540 #undef TARGET_PROMOTE_PROTOTYPES
4541 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
4542 #undef TARGET_PROMOTE_FUNCTION_ARGS
4543 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
4544 #undef TARGET_PROMOTE_FUNCTION_RETURN
4545 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
4547 #undef TARGET_ARG_PARTIAL_BYTES
4548 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
4550 #undef TARGET_PASS_BY_REFERENCE
4551 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
4553 #undef TARGET_SETUP_INCOMING_VARARGS
4554 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
4556 #undef TARGET_STRUCT_VALUE_RTX
4557 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
4559 #undef TARGET_VECTOR_MODE_SUPPORTED_P
4560 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
4562 #undef TARGET_HANDLE_OPTION
4563 #define TARGET_HANDLE_OPTION bfin_handle_option
4565 #undef TARGET_DEFAULT_TARGET_FLAGS
4566 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
4568 #undef TARGET_SECONDARY_RELOAD
4569 #define TARGET_SECONDARY_RELOAD bfin_secondary_reload
4571 #undef TARGET_DELEGITIMIZE_ADDRESS
4572 #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address
4574 #undef TARGET_CANNOT_FORCE_CONST_MEM
4575 #define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem
4577 struct gcc_target targetm = TARGET_INITIALIZER;