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 if (value > 0 && sz == 8)
2344 return (v & ~(0x7fff << shift)) == 0;
2348 bfin_valid_reg_p (unsigned int regno, int strict, enum machine_mode mode,
2349 enum rtx_code outer_code)
2352 return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH);
2354 return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH);
2358 bfin_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
2360 switch (GET_CODE (x)) {
2362 if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM))
2366 if (REG_P (XEXP (x, 0))
2367 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS)
2368 && ((GET_CODE (XEXP (x, 1)) == UNSPEC && mode == SImode)
2369 || (GET_CODE (XEXP (x, 1)) == CONST_INT
2370 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
2375 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2376 && REG_P (XEXP (x, 0))
2377 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC))
2380 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2381 && XEXP (x, 0) == stack_pointer_rtx
2382 && REG_P (XEXP (x, 0))
2383 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC))
2392 /* Decide whether we can force certain constants to memory. If we
2393 decide we can't, the caller should be able to cope with it in
2397 bfin_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
2399 /* We have only one class of non-legitimate constants, and our movsi
2400 expander knows how to handle them. Dropping these constants into the
2401 data section would only shift the problem - we'd still get relocs
2402 outside the object, in the data section rather than the text section. */
2406 /* Ensure that for any constant of the form symbol + offset, the offset
2407 remains within the object. Any other constants are ok.
2408 This ensures that flat binaries never have to deal with relocations
2409 crossing section boundaries. */
2412 bfin_legitimate_constant_p (rtx x)
2415 HOST_WIDE_INT offset;
2417 if (GET_CODE (x) != CONST)
2421 gcc_assert (GET_CODE (x) == PLUS);
2425 if (GET_CODE (sym) != SYMBOL_REF
2426 || GET_CODE (x) != CONST_INT)
2428 offset = INTVAL (x);
2430 if (SYMBOL_REF_DECL (sym) == 0)
2433 || offset >= int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (sym))))
2440 bfin_rtx_costs (rtx x, int code, int outer_code, int *total)
2442 int cost2 = COSTS_N_INSNS (1);
2447 if (outer_code == SET || outer_code == PLUS)
2448 *total = CONST_7BIT_IMM_P (INTVAL (x)) ? 0 : cost2;
2449 else if (outer_code == AND)
2450 *total = log2constp (~INTVAL (x)) ? 0 : cost2;
2451 else if (outer_code == LE || outer_code == LT || outer_code == EQ)
2452 *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
2453 else if (outer_code == LEU || outer_code == LTU)
2454 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
2455 else if (outer_code == MULT)
2456 *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
2457 else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
2459 else if (outer_code == ASHIFT || outer_code == ASHIFTRT
2460 || outer_code == LSHIFTRT)
2461 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
2462 else if (outer_code == IOR || outer_code == XOR)
2463 *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
2472 *total = COSTS_N_INSNS (2);
2476 if (GET_MODE (x) == Pmode)
2478 if (GET_CODE (XEXP (x, 0)) == MULT
2479 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
2481 HOST_WIDE_INT val = INTVAL (XEXP (XEXP (x, 0), 1));
2482 if (val == 2 || val == 4)
2485 *total += rtx_cost (XEXP (XEXP (x, 0), 0), outer_code);
2486 *total += rtx_cost (XEXP (x, 1), outer_code);
2498 if (GET_MODE (x) == DImode)
2505 if (GET_MODE (x) == DImode)
2510 if (GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD)
2511 *total = COSTS_N_INSNS (3);
2516 *total = COSTS_N_INSNS (32);
2521 if (outer_code == SET)
2531 bfin_internal_label (FILE *stream, const char *prefix, unsigned long num)
2533 fprintf (stream, "%s%s$%ld:\n", LOCAL_LABEL_PREFIX, prefix, num);
2536 /* Used for communication between {push,pop}_multiple_operation (which
2537 we use not only as a predicate) and the corresponding output functions. */
2538 static int first_preg_to_save, first_dreg_to_save;
2541 push_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2543 int lastdreg = 8, lastpreg = 6;
2546 first_preg_to_save = lastpreg;
2547 first_dreg_to_save = lastdreg;
2548 for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
2550 rtx t = XVECEXP (op, 0, i);
2554 if (GET_CODE (t) != SET)
2558 dest = SET_DEST (t);
2559 if (GET_CODE (dest) != MEM || ! REG_P (src))
2561 dest = XEXP (dest, 0);
2562 if (GET_CODE (dest) != PLUS
2563 || ! REG_P (XEXP (dest, 0))
2564 || REGNO (XEXP (dest, 0)) != REG_SP
2565 || GET_CODE (XEXP (dest, 1)) != CONST_INT
2566 || INTVAL (XEXP (dest, 1)) != -i * 4)
2569 regno = REGNO (src);
2572 if (D_REGNO_P (regno))
2575 first_dreg_to_save = lastdreg = regno - REG_R0;
2577 else if (regno >= REG_P0 && regno <= REG_P7)
2580 first_preg_to_save = lastpreg = regno - REG_P0;
2590 if (regno >= REG_P0 && regno <= REG_P7)
2593 first_preg_to_save = lastpreg = regno - REG_P0;
2595 else if (regno != REG_R0 + lastdreg + 1)
2600 else if (group == 2)
2602 if (regno != REG_P0 + lastpreg + 1)
2611 pop_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2613 int lastdreg = 8, lastpreg = 6;
2616 for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
2618 rtx t = XVECEXP (op, 0, i);
2622 if (GET_CODE (t) != SET)
2626 dest = SET_DEST (t);
2627 if (GET_CODE (src) != MEM || ! REG_P (dest))
2629 src = XEXP (src, 0);
2633 if (! REG_P (src) || REGNO (src) != REG_SP)
2636 else if (GET_CODE (src) != PLUS
2637 || ! REG_P (XEXP (src, 0))
2638 || REGNO (XEXP (src, 0)) != REG_SP
2639 || GET_CODE (XEXP (src, 1)) != CONST_INT
2640 || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
2643 regno = REGNO (dest);
2646 if (regno == REG_R7)
2651 else if (regno != REG_P0 + lastpreg - 1)
2656 else if (group == 1)
2658 if (regno != REG_R0 + lastdreg - 1)
2664 first_dreg_to_save = lastdreg;
2665 first_preg_to_save = lastpreg;
2669 /* Emit assembly code for one multi-register push described by INSN, with
2670 operands in OPERANDS. */
2673 output_push_multiple (rtx insn, rtx *operands)
2678 /* Validate the insn again, and compute first_[dp]reg_to_save. */
2679 ok = push_multiple_operation (PATTERN (insn), VOIDmode);
2682 if (first_dreg_to_save == 8)
2683 sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
2684 else if (first_preg_to_save == 6)
2685 sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
2687 sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
2688 first_dreg_to_save, first_preg_to_save);
2690 output_asm_insn (buf, operands);
2693 /* Emit assembly code for one multi-register pop described by INSN, with
2694 operands in OPERANDS. */
2697 output_pop_multiple (rtx insn, rtx *operands)
2702 /* Validate the insn again, and compute first_[dp]reg_to_save. */
2703 ok = pop_multiple_operation (PATTERN (insn), VOIDmode);
2706 if (first_dreg_to_save == 8)
2707 sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
2708 else if (first_preg_to_save == 6)
2709 sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
2711 sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
2712 first_dreg_to_save, first_preg_to_save);
2714 output_asm_insn (buf, operands);
2717 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE. */
2720 single_move_for_movmem (rtx dst, rtx src, enum machine_mode mode, HOST_WIDE_INT offset)
2722 rtx scratch = gen_reg_rtx (mode);
2725 srcmem = adjust_address_nv (src, mode, offset);
2726 dstmem = adjust_address_nv (dst, mode, offset);
2727 emit_move_insn (scratch, srcmem);
2728 emit_move_insn (dstmem, scratch);
2731 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
2732 alignment ALIGN_EXP. Return true if successful, false if we should fall
2733 back on a different method. */
2736 bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
2738 rtx srcreg, destreg, countreg;
2739 HOST_WIDE_INT align = 0;
2740 unsigned HOST_WIDE_INT count = 0;
2742 if (GET_CODE (align_exp) == CONST_INT)
2743 align = INTVAL (align_exp);
2744 if (GET_CODE (count_exp) == CONST_INT)
2746 count = INTVAL (count_exp);
2748 if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
2753 /* If optimizing for size, only do single copies inline. */
2756 if (count == 2 && align < 2)
2758 if (count == 4 && align < 4)
2760 if (count != 1 && count != 2 && count != 4)
2763 if (align < 2 && count != 1)
2766 destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
2767 if (destreg != XEXP (dst, 0))
2768 dst = replace_equiv_address_nv (dst, destreg);
2769 srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
2770 if (srcreg != XEXP (src, 0))
2771 src = replace_equiv_address_nv (src, srcreg);
2773 if (count != 0 && align >= 2)
2775 unsigned HOST_WIDE_INT offset = 0;
2779 if ((count & ~3) == 4)
2781 single_move_for_movmem (dst, src, SImode, offset);
2784 else if (count & ~3)
2786 HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
2787 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
2789 emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
2793 single_move_for_movmem (dst, src, HImode, offset);
2799 if ((count & ~1) == 2)
2801 single_move_for_movmem (dst, src, HImode, offset);
2804 else if (count & ~1)
2806 HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
2807 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
2809 emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
2814 single_move_for_movmem (dst, src, QImode, offset);
2821 /* Implement TARGET_SCHED_ISSUE_RATE. */
2824 bfin_issue_rate (void)
2830 bfin_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
2832 enum attr_type insn_type, dep_insn_type;
2833 int dep_insn_code_number;
2835 /* Anti and output dependencies have zero cost. */
2836 if (REG_NOTE_KIND (link) != 0)
2839 dep_insn_code_number = recog_memoized (dep_insn);
2841 /* If we can't recognize the insns, we can't really do anything. */
2842 if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
2845 insn_type = get_attr_type (insn);
2846 dep_insn_type = get_attr_type (dep_insn);
2848 if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)
2850 rtx pat = PATTERN (dep_insn);
2851 rtx dest = SET_DEST (pat);
2852 rtx src = SET_SRC (pat);
2853 if (! ADDRESS_REGNO_P (REGNO (dest)) || ! D_REGNO_P (REGNO (src)))
2855 return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);
2862 /* Increment the counter for the number of loop instructions in the
2863 current function. */
2866 bfin_hardware_loop (void)
2868 cfun->machine->has_hardware_loops++;
2871 /* Maximum loop nesting depth. */
2872 #define MAX_LOOP_DEPTH 2
2874 /* Maximum size of a loop. */
2875 #define MAX_LOOP_LENGTH 2042
2877 /* We need to keep a vector of loops */
2878 typedef struct loop_info *loop_info;
2879 DEF_VEC_P (loop_info);
2880 DEF_VEC_ALLOC_P (loop_info,heap);
2882 /* Information about a loop we have found (or are in the process of
2884 struct loop_info GTY (())
2886 /* loop number, for dumps */
2889 /* Predecessor block of the loop. This is the one that falls into
2890 the loop and contains the initialization instruction. */
2891 basic_block predecessor;
2893 /* First block in the loop. This is the one branched to by the loop_end
2897 /* Last block in the loop (the one with the loop_end insn). */
2900 /* The successor block of the loop. This is the one the loop_end insn
2902 basic_block successor;
2904 /* The last instruction in the tail. */
2907 /* The loop_end insn. */
2910 /* The iteration register. */
2913 /* The new initialization insn. */
2916 /* The new initialization instruction. */
2919 /* The new label placed at the beginning of the loop. */
2922 /* The new label placed at the end of the loop. */
2925 /* The length of the loop. */
2928 /* The nesting depth of the loop. */
2931 /* Nonzero if we can't optimize this loop. */
2934 /* True if we have visited this loop. */
2937 /* True if this loop body clobbers any of LC0, LT0, or LB0. */
2940 /* True if this loop body clobbers any of LC1, LT1, or LB1. */
2943 /* Next loop in the graph. */
2944 struct loop_info *next;
2946 /* Immediate outer loop of this loop. */
2947 struct loop_info *outer;
2949 /* Vector of blocks only within the loop, including those within
2951 VEC (basic_block,heap) *blocks;
2953 /* Same information in a bitmap. */
2954 bitmap block_bitmap;
2956 /* Vector of inner loops within this loop */
2957 VEC (loop_info,heap) *loops;
2961 bfin_dump_loops (loop_info loops)
2965 for (loop = loops; loop; loop = loop->next)
2971 fprintf (dump_file, ";; loop %d: ", loop->loop_no);
2973 fprintf (dump_file, "(bad) ");
2974 fprintf (dump_file, "{head:%d, depth:%d}", loop->head->index, loop->depth);
2976 fprintf (dump_file, " blocks: [ ");
2977 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, b); ix++)
2978 fprintf (dump_file, "%d ", b->index);
2979 fprintf (dump_file, "] ");
2981 fprintf (dump_file, " inner loops: [ ");
2982 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, i); ix++)
2983 fprintf (dump_file, "%d ", i->loop_no);
2984 fprintf (dump_file, "]\n");
2986 fprintf (dump_file, "\n");
2989 /* Scan the blocks of LOOP (and its inferiors) looking for basic block
2990 BB. Return true, if we find it. */
2993 bfin_bb_in_loop (loop_info loop, basic_block bb)
2995 return bitmap_bit_p (loop->block_bitmap, bb->index);
2998 /* Scan the blocks of LOOP (and its inferiors) looking for uses of
2999 REG. Return true, if we find any. Don't count the loop's loop_end
3000 insn if it matches LOOP_END. */
3003 bfin_scan_loop (loop_info loop, rtx reg, rtx loop_end)
3008 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
3012 for (insn = BB_HEAD (bb);
3013 insn != NEXT_INSN (BB_END (bb));
3014 insn = NEXT_INSN (insn))
3018 if (insn == loop_end)
3020 if (reg_mentioned_p (reg, PATTERN (insn)))
3027 /* Optimize LOOP. */
3030 bfin_optimize_loop (loop_info loop)
3034 rtx insn, init_insn, last_insn, nop_insn;
3035 rtx loop_init, start_label, end_label;
3036 rtx reg_lc0, reg_lc1, reg_lt0, reg_lt1, reg_lb0, reg_lb1;
3038 rtx lc_reg, lt_reg, lb_reg;
3042 int inner_depth = 0;
3052 fprintf (dump_file, ";; loop %d bad when found\n", loop->loop_no);
3056 /* Every loop contains in its list of inner loops every loop nested inside
3057 it, even if there are intermediate loops. This works because we're doing
3058 a depth-first search here and never visit a loop more than once. */
3059 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, inner); ix++)
3061 bfin_optimize_loop (inner);
3063 if (!inner->bad && inner_depth < inner->depth)
3065 inner_depth = inner->depth;
3067 loop->clobber_loop0 |= inner->clobber_loop0;
3068 loop->clobber_loop1 |= inner->clobber_loop1;
3072 loop->depth = inner_depth + 1;
3073 if (loop->depth > MAX_LOOP_DEPTH)
3076 fprintf (dump_file, ";; loop %d too deep\n", loop->loop_no);
3080 /* Get the loop iteration register. */
3081 iter_reg = loop->iter_reg;
3083 if (!DPREG_P (iter_reg))
3086 fprintf (dump_file, ";; loop %d iteration count NOT in PREG or DREG\n",
3091 /* Check if start_label appears before loop_end and calculate the
3092 offset between them. We calculate the length of instructions
3095 for (insn = loop->start_label;
3096 insn && insn != loop->loop_end;
3097 insn = NEXT_INSN (insn))
3099 if (JUMP_P (insn) && any_condjump_p (insn) && !optimize_size)
3101 if (TARGET_CSYNC_ANOMALY)
3103 else if (TARGET_SPECLD_ANOMALY)
3106 else if (LABEL_P (insn))
3108 if (TARGET_CSYNC_ANOMALY)
3113 length += get_attr_length (insn);
3119 fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
3124 loop->length = length;
3125 if (loop->length > MAX_LOOP_LENGTH)
3128 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
3132 /* Scan all the blocks to make sure they don't use iter_reg. */
3133 if (bfin_scan_loop (loop, iter_reg, loop->loop_end))
3136 fprintf (dump_file, ";; loop %d uses iterator\n", loop->loop_no);
3140 /* Scan all the insns to see if the loop body clobber
3141 any hardware loop registers. */
3143 reg_lc0 = gen_rtx_REG (SImode, REG_LC0);
3144 reg_lc1 = gen_rtx_REG (SImode, REG_LC1);
3145 reg_lt0 = gen_rtx_REG (SImode, REG_LT0);
3146 reg_lt1 = gen_rtx_REG (SImode, REG_LT1);
3147 reg_lb0 = gen_rtx_REG (SImode, REG_LB0);
3148 reg_lb1 = gen_rtx_REG (SImode, REG_LB1);
3150 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
3154 for (insn = BB_HEAD (bb);
3155 insn != NEXT_INSN (BB_END (bb));
3156 insn = NEXT_INSN (insn))
3161 if (reg_set_p (reg_lc0, insn)
3162 || reg_set_p (reg_lt0, insn)
3163 || reg_set_p (reg_lb0, insn))
3164 loop->clobber_loop0 = 1;
3166 if (reg_set_p (reg_lc1, insn)
3167 || reg_set_p (reg_lt1, insn)
3168 || reg_set_p (reg_lb1, insn))
3169 loop->clobber_loop1 |= 1;
3173 if ((loop->clobber_loop0 && loop->clobber_loop1)
3174 || (loop->depth == MAX_LOOP_DEPTH && loop->clobber_loop0))
3176 loop->depth = MAX_LOOP_DEPTH + 1;
3178 fprintf (dump_file, ";; loop %d no loop reg available\n",
3183 /* There should be an instruction before the loop_end instruction
3184 in the same basic block. And the instruction must not be
3186 - CONDITIONAL BRANCH
3190 - Returns (RTS, RTN, etc.) */
3193 last_insn = PREV_INSN (loop->loop_end);
3197 for (; last_insn != PREV_INSN (BB_HEAD (bb));
3198 last_insn = PREV_INSN (last_insn))
3199 if (INSN_P (last_insn))
3202 if (last_insn != PREV_INSN (BB_HEAD (bb)))
3205 if (single_pred_p (bb)
3206 && single_pred (bb) != ENTRY_BLOCK_PTR)
3208 bb = single_pred (bb);
3209 last_insn = BB_END (bb);
3214 last_insn = NULL_RTX;
3222 fprintf (dump_file, ";; loop %d has no last instruction\n",
3227 if (JUMP_P (last_insn))
3229 loop_info inner = bb->aux;
3231 && inner->outer == loop
3232 && inner->loop_end == last_insn
3233 && inner->depth == 1)
3234 /* This jump_insn is the exact loop_end of an inner loop
3235 and to be optimized away. So use the inner's last_insn. */
3236 last_insn = inner->last_insn;
3240 fprintf (dump_file, ";; loop %d has bad last instruction\n",
3245 else if (CALL_P (last_insn)
3246 || get_attr_type (last_insn) == TYPE_SYNC
3247 || recog_memoized (last_insn) == CODE_FOR_return_internal)
3250 fprintf (dump_file, ";; loop %d has bad last instruction\n",
3255 if (GET_CODE (PATTERN (last_insn)) == ASM_INPUT
3256 || asm_noperands (PATTERN (last_insn)) >= 0
3257 || get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI)
3259 nop_insn = emit_insn_after (gen_nop (), last_insn);
3260 last_insn = nop_insn;
3263 loop->last_insn = last_insn;
3265 /* The loop is good for replacement. */
3266 start_label = loop->start_label;
3267 end_label = gen_label_rtx ();
3268 iter_reg = loop->iter_reg;
3270 if (loop->depth == 1 && !loop->clobber_loop1)
3275 loop->clobber_loop1 = 1;
3282 loop->clobber_loop0 = 1;
3285 /* If iter_reg is a DREG, we need generate an instruction to load
3286 the loop count into LC register. */
3287 if (D_REGNO_P (REGNO (iter_reg)))
3289 init_insn = gen_movsi (lc_reg, iter_reg);
3290 loop_init = gen_lsetup_without_autoinit (lt_reg, start_label,
3294 else if (P_REGNO_P (REGNO (iter_reg)))
3296 init_insn = NULL_RTX;
3297 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
3304 loop->init = init_insn;
3305 loop->end_label = end_label;
3306 loop->loop_init = loop_init;
3310 fprintf (dump_file, ";; replacing loop %d initializer with\n",
3312 print_rtl_single (dump_file, loop->loop_init);
3313 fprintf (dump_file, ";; replacing loop %d terminator with\n",
3315 print_rtl_single (dump_file, loop->loop_end);
3320 if (loop->init != NULL_RTX)
3321 emit_insn (loop->init);
3322 emit_insn(loop->loop_init);
3323 emit_label (loop->start_label);
3328 emit_insn_after (seq, BB_END (loop->predecessor));
3329 delete_insn (loop->loop_end);
3331 /* Insert the loop end label before the last instruction of the loop. */
3332 emit_label_before (loop->end_label, loop->last_insn);
3339 fprintf (dump_file, ";; loop %d is bad\n", loop->loop_no);
3343 if (DPREG_P (loop->iter_reg))
3345 /* If loop->iter_reg is a DREG or PREG, we can split it here
3346 without scratch register. */
3349 emit_insn_before (gen_addsi3 (loop->iter_reg,
3354 emit_insn_before (gen_cmpsi (loop->iter_reg, const0_rtx),
3357 insn = emit_jump_insn_before (gen_bne (loop->start_label),
3360 JUMP_LABEL (insn) = loop->start_label;
3361 LABEL_NUSES (loop->start_label)++;
3362 delete_insn (loop->loop_end);
3366 /* Called from bfin_reorg_loops when a potential loop end is found. LOOP is
3367 a newly set up structure describing the loop, it is this function's
3368 responsibility to fill most of it. TAIL_BB and TAIL_INSN point to the
3369 loop_end insn and its enclosing basic block. */
3372 bfin_discover_loop (loop_info loop, basic_block tail_bb, rtx tail_insn)
3376 VEC (basic_block,heap) *works = VEC_alloc (basic_block,heap,20);
3378 loop->tail = tail_bb;
3379 loop->head = BRANCH_EDGE (tail_bb)->dest;
3380 loop->successor = FALLTHRU_EDGE (tail_bb)->dest;
3381 loop->predecessor = NULL;
3382 loop->loop_end = tail_insn;
3383 loop->last_insn = NULL_RTX;
3384 loop->iter_reg = SET_DEST (XVECEXP (PATTERN (tail_insn), 0, 1));
3385 loop->depth = loop->length = 0;
3387 loop->clobber_loop0 = loop->clobber_loop1 = 0;
3391 loop->init = loop->loop_init = NULL_RTX;
3392 loop->start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (tail_insn), 0, 0)), 1), 0);
3393 loop->end_label = NULL_RTX;
3396 VEC_safe_push (basic_block, heap, works, loop->head);
3398 while (VEC_iterate (basic_block, works, dwork++, bb))
3402 if (bb == EXIT_BLOCK_PTR)
3404 /* We've reached the exit block. The loop must be bad. */
3407 ";; Loop is bad - reached exit block while scanning\n");
3412 if (bitmap_bit_p (loop->block_bitmap, bb->index))
3415 /* We've not seen this block before. Add it to the loop's
3416 list and then add each successor to the work list. */
3418 VEC_safe_push (basic_block, heap, loop->blocks, bb);
3419 bitmap_set_bit (loop->block_bitmap, bb->index);
3423 FOR_EACH_EDGE (e, ei, bb->succs)
3425 basic_block succ = EDGE_SUCC (bb, ei.index)->dest;
3426 if (!REGNO_REG_SET_P (succ->il.rtl->global_live_at_start,
3427 REGNO (loop->iter_reg)))
3429 if (!VEC_space (basic_block, works, 1))
3433 VEC_block_remove (basic_block, works, 0, dwork);
3437 VEC_reserve (basic_block, heap, works, 1);
3439 VEC_quick_push (basic_block, works, succ);
3446 /* Make sure we only have one entry point. */
3447 if (EDGE_COUNT (loop->head->preds) == 2)
3449 loop->predecessor = EDGE_PRED (loop->head, 0)->src;
3450 if (loop->predecessor == loop->tail)
3451 /* We wanted the other predecessor. */
3452 loop->predecessor = EDGE_PRED (loop->head, 1)->src;
3454 /* We can only place a loop insn on a fall through edge of a
3455 single exit block. */
3456 if (EDGE_COUNT (loop->predecessor->succs) != 1
3457 || !(EDGE_SUCC (loop->predecessor, 0)->flags & EDGE_FALLTHRU)
3458 /* If loop->predecessor is in loop, loop->head is not really
3459 the head of the loop. */
3460 || bfin_bb_in_loop (loop, loop->predecessor))
3461 loop->predecessor = NULL;
3464 if (loop->predecessor == NULL)
3467 fprintf (dump_file, ";; loop has bad predecessor\n");
3472 #ifdef ENABLE_CHECKING
3473 /* Make sure nothing jumps into this loop. This shouldn't happen as we
3474 wouldn't have generated the counted loop patterns in such a case.
3475 However, this test must be done after the test above to detect loops
3476 with invalid headers. */
3478 for (dwork = 0; VEC_iterate (basic_block, loop->blocks, dwork, bb); dwork++)
3482 if (bb == loop->head)
3484 FOR_EACH_EDGE (e, ei, bb->preds)
3486 basic_block pred = EDGE_PRED (bb, ei.index)->src;
3487 if (!bfin_bb_in_loop (loop, pred))
3492 VEC_free (basic_block, heap, works);
3496 bfin_reorg_loops (FILE *dump_file)
3498 bitmap_obstack stack;
3501 loop_info loops = NULL;
3505 bitmap_obstack_initialize (&stack);
3507 /* Find all the possible loop tails. This means searching for every
3508 loop_end instruction. For each one found, create a loop_info
3509 structure and add the head block to the work list. */
3512 rtx tail = BB_END (bb);
3514 while (GET_CODE (tail) == NOTE)
3515 tail = PREV_INSN (tail);
3519 if (INSN_P (tail) && recog_memoized (tail) == CODE_FOR_loop_end)
3521 /* A possible loop end */
3523 loop = XNEW (struct loop_info);
3526 loop->loop_no = nloops++;
3527 loop->blocks = VEC_alloc (basic_block, heap, 20);
3528 loop->block_bitmap = BITMAP_ALLOC (&stack);
3533 fprintf (dump_file, ";; potential loop %d ending at\n",
3535 print_rtl_single (dump_file, tail);
3538 bfin_discover_loop (loop, bb, tail);
3542 tmp_bitmap = BITMAP_ALLOC (&stack);
3543 /* Compute loop nestings. */
3544 for (loop = loops; loop; loop = loop->next)
3550 for (other = loop->next; other; other = other->next)
3555 bitmap_and (tmp_bitmap, other->block_bitmap, loop->block_bitmap);
3556 if (bitmap_empty_p (tmp_bitmap))
3558 if (bitmap_equal_p (tmp_bitmap, other->block_bitmap))
3560 other->outer = loop;
3561 VEC_safe_push (loop_info, heap, loop->loops, other);
3563 else if (bitmap_equal_p (tmp_bitmap, loop->block_bitmap))
3565 loop->outer = other;
3566 VEC_safe_push (loop_info, heap, other->loops, loop);
3570 loop->bad = other->bad = 1;
3574 BITMAP_FREE (tmp_bitmap);
3578 fprintf (dump_file, ";; All loops found:\n\n");
3579 bfin_dump_loops (loops);
3582 /* Now apply the optimizations. */
3583 for (loop = loops; loop; loop = loop->next)
3584 bfin_optimize_loop (loop);
3588 fprintf (dump_file, ";; After hardware loops optimization:\n\n");
3589 bfin_dump_loops (loops);
3592 /* Free up the loop structures */
3597 VEC_free (loop_info, heap, loop->loops);
3598 VEC_free (basic_block, heap, loop->blocks);
3599 BITMAP_FREE (loop->block_bitmap);
3604 print_rtl (dump_file, get_insns ());
3608 /* We use the machine specific reorg pass for emitting CSYNC instructions
3609 after conditional branches as needed.
3611 The Blackfin is unusual in that a code sequence like
3614 may speculatively perform the load even if the condition isn't true. This
3615 happens for a branch that is predicted not taken, because the pipeline
3616 isn't flushed or stalled, so the early stages of the following instructions,
3617 which perform the memory reference, are allowed to execute before the
3618 jump condition is evaluated.
3619 Therefore, we must insert additional instructions in all places where this
3620 could lead to incorrect behavior. The manual recommends CSYNC, while
3621 VDSP seems to use NOPs (even though its corresponding compiler option is
3624 When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
3625 When optimizing for size, we turn the branch into a predicted taken one.
3626 This may be slower due to mispredicts, but saves code size. */
3631 rtx insn, last_condjump = NULL_RTX;
3632 int cycles_since_jump = INT_MAX;
3634 /* Doloop optimization */
3635 if (cfun->machine->has_hardware_loops)
3636 bfin_reorg_loops (dump_file);
3638 if (! TARGET_SPECLD_ANOMALY && ! TARGET_CSYNC_ANOMALY)
3641 /* First pass: find predicted-false branches; if something after them
3642 needs nops, insert them or change the branch to predict true. */
3643 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
3647 if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
3650 pat = PATTERN (insn);
3651 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
3652 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
3653 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
3658 if (any_condjump_p (insn)
3659 && ! cbranch_predicted_taken_p (insn))
3661 last_condjump = insn;
3662 cycles_since_jump = 0;
3665 cycles_since_jump = INT_MAX;
3667 else if (INSN_P (insn))
3669 enum attr_type type = get_attr_type (insn);
3670 int delay_needed = 0;
3671 if (cycles_since_jump < INT_MAX)
3672 cycles_since_jump++;
3674 if (type == TYPE_MCLD && TARGET_SPECLD_ANOMALY)
3676 rtx pat = single_set (insn);
3677 if (may_trap_p (SET_SRC (pat)))
3680 else if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
3683 if (delay_needed > cycles_since_jump)
3687 rtx *op = recog_data.operand;
3689 delay_needed -= cycles_since_jump;
3691 extract_insn (last_condjump);
3694 pat = gen_cbranch_predicted_taken (op[0], op[1], op[2],
3696 cycles_since_jump = INT_MAX;
3699 /* Do not adjust cycles_since_jump in this case, so that
3700 we'll increase the number of NOPs for a subsequent insn
3702 pat = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
3703 GEN_INT (delay_needed));
3704 PATTERN (last_condjump) = pat;
3705 INSN_CODE (last_condjump) = recog (pat, insn, &num_clobbers);
3709 /* Second pass: for predicted-true branches, see if anything at the
3710 branch destination needs extra nops. */
3711 if (! TARGET_CSYNC_ANOMALY)
3714 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
3717 && any_condjump_p (insn)
3718 && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken
3719 || cbranch_predicted_taken_p (insn)))
3721 rtx target = JUMP_LABEL (insn);
3723 cycles_since_jump = 0;
3724 for (; target && cycles_since_jump < 3; target = NEXT_INSN (target))
3728 if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
3731 pat = PATTERN (target);
3732 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
3733 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
3734 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
3737 if (INSN_P (target))
3739 enum attr_type type = get_attr_type (target);
3740 int delay_needed = 0;
3741 if (cycles_since_jump < INT_MAX)
3742 cycles_since_jump++;
3744 if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
3747 if (delay_needed > cycles_since_jump)
3749 rtx prev = prev_real_insn (label);
3750 delay_needed -= cycles_since_jump;
3752 fprintf (dump_file, "Adding %d nops after %d\n",
3753 delay_needed, INSN_UID (label));
3755 && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops)
3762 "Reducing nops on insn %d.\n",
3765 x = XVECEXP (x, 0, 1);
3766 v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed;
3767 XVECEXP (x, 0, 0) = GEN_INT (v);
3769 while (delay_needed-- > 0)
3770 emit_insn_after (gen_nop (), label);
3779 /* Handle interrupt_handler, exception_handler and nmi_handler function
3780 attributes; arguments as in struct attribute_spec.handler. */
3783 handle_int_attribute (tree *node, tree name,
3784 tree args ATTRIBUTE_UNUSED,
3785 int flags ATTRIBUTE_UNUSED,
3789 if (TREE_CODE (x) == FUNCTION_DECL)
3792 if (TREE_CODE (x) != FUNCTION_TYPE)
3794 warning (OPT_Wattributes, "%qs attribute only applies to functions",
3795 IDENTIFIER_POINTER (name));
3796 *no_add_attrs = true;
3798 else if (funkind (x) != SUBROUTINE)
3799 error ("multiple function type attributes specified");
3804 /* Return 0 if the attributes for two types are incompatible, 1 if they
3805 are compatible, and 2 if they are nearly compatible (which causes a
3806 warning to be generated). */
3809 bfin_comp_type_attributes (tree type1, tree type2)
3811 e_funkind kind1, kind2;
3813 if (TREE_CODE (type1) != FUNCTION_TYPE)
3816 kind1 = funkind (type1);
3817 kind2 = funkind (type2);
3822 /* Check for mismatched modifiers */
3823 if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
3824 != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
3827 if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
3828 != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
3831 if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
3832 != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
3835 if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1))
3836 != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2)))
3842 /* Handle a "longcall" or "shortcall" attribute; arguments as in
3843 struct attribute_spec.handler. */
3846 bfin_handle_longcall_attribute (tree *node, tree name,
3847 tree args ATTRIBUTE_UNUSED,
3848 int flags ATTRIBUTE_UNUSED,
3851 if (TREE_CODE (*node) != FUNCTION_TYPE
3852 && TREE_CODE (*node) != FIELD_DECL
3853 && TREE_CODE (*node) != TYPE_DECL)
3855 warning (OPT_Wattributes, "`%s' attribute only applies to functions",
3856 IDENTIFIER_POINTER (name));
3857 *no_add_attrs = true;
3860 if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0
3861 && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node)))
3862 || (strcmp (IDENTIFIER_POINTER (name), "shortcall") == 0
3863 && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node))))
3865 warning (OPT_Wattributes,
3866 "can't apply both longcall and shortcall attributes to the same function");
3867 *no_add_attrs = true;
3873 /* Table of valid machine attributes. */
3874 const struct attribute_spec bfin_attribute_table[] =
3876 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
3877 { "interrupt_handler", 0, 0, false, true, true, handle_int_attribute },
3878 { "exception_handler", 0, 0, false, true, true, handle_int_attribute },
3879 { "nmi_handler", 0, 0, false, true, true, handle_int_attribute },
3880 { "nesting", 0, 0, false, true, true, NULL },
3881 { "kspisusp", 0, 0, false, true, true, NULL },
3882 { "saveall", 0, 0, false, true, true, NULL },
3883 { "longcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
3884 { "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
3885 { NULL, 0, 0, false, false, false, NULL }
3888 /* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to
3889 tell the assembler to generate pointers to function descriptors in
3893 bfin_assemble_integer (rtx value, unsigned int size, int aligned_p)
3895 if (TARGET_FDPIC && size == UNITS_PER_WORD)
3897 if (GET_CODE (value) == SYMBOL_REF
3898 && SYMBOL_REF_FUNCTION_P (value))
3900 fputs ("\t.picptr\tfuncdesc(", asm_out_file);
3901 output_addr_const (asm_out_file, value);
3902 fputs (")\n", asm_out_file);
3907 /* We've set the unaligned SI op to NULL, so we always have to
3908 handle the unaligned case here. */
3909 assemble_integer_with_op ("\t.4byte\t", value);
3913 return default_assemble_integer (value, size, aligned_p);
3916 /* Output the assembler code for a thunk function. THUNK_DECL is the
3917 declaration for the thunk function itself, FUNCTION is the decl for
3918 the target function. DELTA is an immediate constant offset to be
3919 added to THIS. If VCALL_OFFSET is nonzero, the word at
3920 *(*this + vcall_offset) should be added to THIS. */
3923 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
3924 tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
3925 HOST_WIDE_INT vcall_offset, tree function)
3928 /* The this parameter is passed as the first argument. */
3929 rtx this = gen_rtx_REG (Pmode, REG_R0);
3931 /* Adjust the this parameter by a fixed constant. */
3935 if (delta >= -64 && delta <= 63)
3937 xops[0] = GEN_INT (delta);
3938 output_asm_insn ("%1 += %0;", xops);
3940 else if (delta >= -128 && delta < -64)
3942 xops[0] = GEN_INT (delta + 64);
3943 output_asm_insn ("%1 += -64; %1 += %0;", xops);
3945 else if (delta > 63 && delta <= 126)
3947 xops[0] = GEN_INT (delta - 63);
3948 output_asm_insn ("%1 += 63; %1 += %0;", xops);
3952 xops[0] = GEN_INT (delta);
3953 output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
3957 /* Adjust the this parameter by a value stored in the vtable. */
3960 rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
3961 rtx tmp = gen_rtx_REG (Pmode, REG_R2);
3965 output_asm_insn ("%2 = r0; %2 = [%2];", xops);
3967 /* Adjust the this parameter. */
3968 xops[0] = gen_rtx_MEM (Pmode, plus_constant (p2tmp, vcall_offset));
3969 if (!memory_operand (xops[0], Pmode))
3971 rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
3972 xops[0] = GEN_INT (vcall_offset);
3974 output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
3975 xops[0] = gen_rtx_MEM (Pmode, p2tmp);
3978 output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
3981 xops[0] = XEXP (DECL_RTL (function), 0);
3982 if (1 || !flag_pic || (*targetm.binds_local_p) (function))
3983 output_asm_insn ("jump.l\t%P0", xops);
3986 /* Codes for all the Blackfin builtins. */
3991 BFIN_BUILTIN_COMPOSE_2X16,
3992 BFIN_BUILTIN_EXTRACTLO,
3993 BFIN_BUILTIN_EXTRACTHI,
3995 BFIN_BUILTIN_SSADD_2X16,
3996 BFIN_BUILTIN_SSSUB_2X16,
3997 BFIN_BUILTIN_SSADDSUB_2X16,
3998 BFIN_BUILTIN_SSSUBADD_2X16,
3999 BFIN_BUILTIN_MULT_2X16,
4000 BFIN_BUILTIN_MULTR_2X16,
4001 BFIN_BUILTIN_NEG_2X16,
4002 BFIN_BUILTIN_ABS_2X16,
4003 BFIN_BUILTIN_MIN_2X16,
4004 BFIN_BUILTIN_MAX_2X16,
4006 BFIN_BUILTIN_SSADD_1X16,
4007 BFIN_BUILTIN_SSSUB_1X16,
4008 BFIN_BUILTIN_MULT_1X16,
4009 BFIN_BUILTIN_MULTR_1X16,
4010 BFIN_BUILTIN_NORM_1X16,
4011 BFIN_BUILTIN_NEG_1X16,
4012 BFIN_BUILTIN_ABS_1X16,
4013 BFIN_BUILTIN_MIN_1X16,
4014 BFIN_BUILTIN_MAX_1X16,
4016 BFIN_BUILTIN_DIFFHL_2X16,
4017 BFIN_BUILTIN_DIFFLH_2X16,
4019 BFIN_BUILTIN_SSADD_1X32,
4020 BFIN_BUILTIN_SSSUB_1X32,
4021 BFIN_BUILTIN_NORM_1X32,
4022 BFIN_BUILTIN_NEG_1X32,
4023 BFIN_BUILTIN_MIN_1X32,
4024 BFIN_BUILTIN_MAX_1X32,
4025 BFIN_BUILTIN_MULT_1X32,
4027 BFIN_BUILTIN_MULHISILL,
4028 BFIN_BUILTIN_MULHISILH,
4029 BFIN_BUILTIN_MULHISIHL,
4030 BFIN_BUILTIN_MULHISIHH,
4032 BFIN_BUILTIN_LSHIFT_1X16,
4033 BFIN_BUILTIN_LSHIFT_2X16,
4034 BFIN_BUILTIN_SSASHIFT_1X16,
4035 BFIN_BUILTIN_SSASHIFT_2X16,
4037 BFIN_BUILTIN_CPLX_MUL_16,
4038 BFIN_BUILTIN_CPLX_MAC_16,
4039 BFIN_BUILTIN_CPLX_MSU_16,
4044 #define def_builtin(NAME, TYPE, CODE) \
4046 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
4050 /* Set up all builtin functions for this target. */
4052 bfin_init_builtins (void)
4054 tree V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
4055 tree void_ftype_void
4056 = build_function_type (void_type_node, void_list_node);
4057 tree short_ftype_short
4058 = build_function_type_list (short_integer_type_node, short_integer_type_node,
4060 tree short_ftype_int_int
4061 = build_function_type_list (short_integer_type_node, integer_type_node,
4062 integer_type_node, NULL_TREE);
4063 tree int_ftype_int_int
4064 = build_function_type_list (integer_type_node, integer_type_node,
4065 integer_type_node, NULL_TREE);
4067 = build_function_type_list (integer_type_node, integer_type_node,
4069 tree short_ftype_int
4070 = build_function_type_list (short_integer_type_node, integer_type_node,
4072 tree int_ftype_v2hi_v2hi
4073 = build_function_type_list (integer_type_node, V2HI_type_node,
4074 V2HI_type_node, NULL_TREE);
4075 tree v2hi_ftype_v2hi_v2hi
4076 = build_function_type_list (V2HI_type_node, V2HI_type_node,
4077 V2HI_type_node, NULL_TREE);
4078 tree v2hi_ftype_v2hi_v2hi_v2hi
4079 = build_function_type_list (V2HI_type_node, V2HI_type_node,
4080 V2HI_type_node, V2HI_type_node, NULL_TREE);
4081 tree v2hi_ftype_int_int
4082 = build_function_type_list (V2HI_type_node, integer_type_node,
4083 integer_type_node, NULL_TREE);
4084 tree v2hi_ftype_v2hi_int
4085 = build_function_type_list (V2HI_type_node, V2HI_type_node,
4086 integer_type_node, NULL_TREE);
4087 tree int_ftype_short_short
4088 = build_function_type_list (integer_type_node, short_integer_type_node,
4089 short_integer_type_node, NULL_TREE);
4090 tree v2hi_ftype_v2hi
4091 = build_function_type_list (V2HI_type_node, V2HI_type_node, NULL_TREE);
4092 tree short_ftype_v2hi
4093 = build_function_type_list (short_integer_type_node, V2HI_type_node,
4096 /* Add the remaining MMX insns with somewhat more complicated types. */
4097 def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC);
4098 def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC);
4100 def_builtin ("__builtin_bfin_compose_2x16", v2hi_ftype_int_int,
4101 BFIN_BUILTIN_COMPOSE_2X16);
4102 def_builtin ("__builtin_bfin_extract_hi", short_ftype_v2hi,
4103 BFIN_BUILTIN_EXTRACTHI);
4104 def_builtin ("__builtin_bfin_extract_lo", short_ftype_v2hi,
4105 BFIN_BUILTIN_EXTRACTLO);
4107 def_builtin ("__builtin_bfin_min_fr2x16", v2hi_ftype_v2hi_v2hi,
4108 BFIN_BUILTIN_MIN_2X16);
4109 def_builtin ("__builtin_bfin_max_fr2x16", v2hi_ftype_v2hi_v2hi,
4110 BFIN_BUILTIN_MAX_2X16);
4112 def_builtin ("__builtin_bfin_add_fr2x16", v2hi_ftype_v2hi_v2hi,
4113 BFIN_BUILTIN_SSADD_2X16);
4114 def_builtin ("__builtin_bfin_sub_fr2x16", v2hi_ftype_v2hi_v2hi,
4115 BFIN_BUILTIN_SSSUB_2X16);
4116 def_builtin ("__builtin_bfin_dspaddsubsat", v2hi_ftype_v2hi_v2hi,
4117 BFIN_BUILTIN_SSADDSUB_2X16);
4118 def_builtin ("__builtin_bfin_dspsubaddsat", v2hi_ftype_v2hi_v2hi,
4119 BFIN_BUILTIN_SSSUBADD_2X16);
4120 def_builtin ("__builtin_bfin_mult_fr2x16", v2hi_ftype_v2hi_v2hi,
4121 BFIN_BUILTIN_MULT_2X16);
4122 def_builtin ("__builtin_bfin_multr_fr2x16", v2hi_ftype_v2hi_v2hi,
4123 BFIN_BUILTIN_MULTR_2X16);
4124 def_builtin ("__builtin_bfin_negate_fr2x16", v2hi_ftype_v2hi,
4125 BFIN_BUILTIN_NEG_2X16);
4126 def_builtin ("__builtin_bfin_abs_fr2x16", v2hi_ftype_v2hi,
4127 BFIN_BUILTIN_ABS_2X16);
4129 def_builtin ("__builtin_bfin_add_fr1x16", short_ftype_int_int,
4130 BFIN_BUILTIN_SSADD_1X16);
4131 def_builtin ("__builtin_bfin_sub_fr1x16", short_ftype_int_int,
4132 BFIN_BUILTIN_SSSUB_1X16);
4133 def_builtin ("__builtin_bfin_mult_fr1x16", short_ftype_int_int,
4134 BFIN_BUILTIN_MULT_1X16);
4135 def_builtin ("__builtin_bfin_multr_fr1x16", short_ftype_int_int,
4136 BFIN_BUILTIN_MULTR_1X16);
4137 def_builtin ("__builtin_bfin_negate_fr1x16", short_ftype_short,
4138 BFIN_BUILTIN_NEG_1X16);
4139 def_builtin ("__builtin_bfin_abs_fr1x16", short_ftype_short,
4140 BFIN_BUILTIN_ABS_1X16);
4141 def_builtin ("__builtin_bfin_norm_fr1x16", short_ftype_int,
4142 BFIN_BUILTIN_NORM_1X16);
4144 def_builtin ("__builtin_bfin_diff_hl_fr2x16", short_ftype_v2hi,
4145 BFIN_BUILTIN_DIFFHL_2X16);
4146 def_builtin ("__builtin_bfin_diff_lh_fr2x16", short_ftype_v2hi,
4147 BFIN_BUILTIN_DIFFLH_2X16);
4149 def_builtin ("__builtin_bfin_mulhisill", int_ftype_v2hi_v2hi,
4150 BFIN_BUILTIN_MULHISILL);
4151 def_builtin ("__builtin_bfin_mulhisihl", int_ftype_v2hi_v2hi,
4152 BFIN_BUILTIN_MULHISIHL);
4153 def_builtin ("__builtin_bfin_mulhisilh", int_ftype_v2hi_v2hi,
4154 BFIN_BUILTIN_MULHISILH);
4155 def_builtin ("__builtin_bfin_mulhisihh", int_ftype_v2hi_v2hi,
4156 BFIN_BUILTIN_MULHISIHH);
4158 def_builtin ("__builtin_bfin_add_fr1x32", int_ftype_int_int,
4159 BFIN_BUILTIN_SSADD_1X32);
4160 def_builtin ("__builtin_bfin_sub_fr1x32", int_ftype_int_int,
4161 BFIN_BUILTIN_SSSUB_1X32);
4162 def_builtin ("__builtin_bfin_negate_fr1x32", int_ftype_int,
4163 BFIN_BUILTIN_NEG_1X32);
4164 def_builtin ("__builtin_bfin_norm_fr1x32", short_ftype_int,
4165 BFIN_BUILTIN_NORM_1X32);
4166 def_builtin ("__builtin_bfin_mult_fr1x32", int_ftype_short_short,
4167 BFIN_BUILTIN_MULT_1X32);
4170 def_builtin ("__builtin_bfin_shl_fr1x16", short_ftype_int_int,
4171 BFIN_BUILTIN_SSASHIFT_1X16);
4172 def_builtin ("__builtin_bfin_shl_fr2x16", v2hi_ftype_v2hi_int,
4173 BFIN_BUILTIN_SSASHIFT_2X16);
4174 def_builtin ("__builtin_bfin_lshl_fr1x16", short_ftype_int_int,
4175 BFIN_BUILTIN_LSHIFT_1X16);
4176 def_builtin ("__builtin_bfin_lshl_fr2x16", v2hi_ftype_v2hi_int,
4177 BFIN_BUILTIN_LSHIFT_2X16);
4179 /* Complex numbers. */
4180 def_builtin ("__builtin_bfin_cmplx_mul", v2hi_ftype_v2hi_v2hi,
4181 BFIN_BUILTIN_CPLX_MUL_16);
4182 def_builtin ("__builtin_bfin_cmplx_mac", v2hi_ftype_v2hi_v2hi_v2hi,
4183 BFIN_BUILTIN_CPLX_MAC_16);
4184 def_builtin ("__builtin_bfin_cmplx_msu", v2hi_ftype_v2hi_v2hi_v2hi,
4185 BFIN_BUILTIN_CPLX_MSU_16);
4189 struct builtin_description
4191 const enum insn_code icode;
4192 const char *const name;
4193 const enum bfin_builtins code;
4197 static const struct builtin_description bdesc_2arg[] =
4199 { CODE_FOR_composev2hi, "__builtin_bfin_compose_2x16", BFIN_BUILTIN_COMPOSE_2X16, -1 },
4201 { CODE_FOR_ssashiftv2hi3, "__builtin_bfin_shl_fr2x16", BFIN_BUILTIN_SSASHIFT_2X16, -1 },
4202 { CODE_FOR_ssashifthi3, "__builtin_bfin_shl_fr1x16", BFIN_BUILTIN_SSASHIFT_1X16, -1 },
4203 { CODE_FOR_lshiftv2hi3, "__builtin_bfin_lshl_fr2x16", BFIN_BUILTIN_LSHIFT_2X16, -1 },
4204 { CODE_FOR_lshifthi3, "__builtin_bfin_lshl_fr1x16", BFIN_BUILTIN_LSHIFT_1X16, -1 },
4206 { CODE_FOR_sminhi3, "__builtin_bfin_min_fr1x16", BFIN_BUILTIN_MIN_1X16, -1 },
4207 { CODE_FOR_smaxhi3, "__builtin_bfin_max_fr1x16", BFIN_BUILTIN_MAX_1X16, -1 },
4208 { CODE_FOR_ssaddhi3, "__builtin_bfin_add_fr1x16", BFIN_BUILTIN_SSADD_1X16, -1 },
4209 { CODE_FOR_sssubhi3, "__builtin_bfin_sub_fr1x16", BFIN_BUILTIN_SSSUB_1X16, -1 },
4211 { CODE_FOR_sminsi3, "__builtin_bfin_min_fr1x32", BFIN_BUILTIN_MIN_1X32, -1 },
4212 { CODE_FOR_smaxsi3, "__builtin_bfin_max_fr1x32", BFIN_BUILTIN_MAX_1X32, -1 },
4213 { CODE_FOR_ssaddsi3, "__builtin_bfin_add_fr1x32", BFIN_BUILTIN_SSADD_1X32, -1 },
4214 { CODE_FOR_sssubsi3, "__builtin_bfin_sub_fr1x32", BFIN_BUILTIN_SSSUB_1X32, -1 },
4216 { CODE_FOR_sminv2hi3, "__builtin_bfin_min_fr2x16", BFIN_BUILTIN_MIN_2X16, -1 },
4217 { CODE_FOR_smaxv2hi3, "__builtin_bfin_max_fr2x16", BFIN_BUILTIN_MAX_2X16, -1 },
4218 { CODE_FOR_ssaddv2hi3, "__builtin_bfin_add_fr2x16", BFIN_BUILTIN_SSADD_2X16, -1 },
4219 { CODE_FOR_sssubv2hi3, "__builtin_bfin_sub_fr2x16", BFIN_BUILTIN_SSSUB_2X16, -1 },
4220 { CODE_FOR_ssaddsubv2hi3, "__builtin_bfin_dspaddsubsat", BFIN_BUILTIN_SSADDSUB_2X16, -1 },
4221 { CODE_FOR_sssubaddv2hi3, "__builtin_bfin_dspsubaddsat", BFIN_BUILTIN_SSSUBADD_2X16, -1 },
4223 { CODE_FOR_flag_mulhisi, "__builtin_bfin_mult_fr1x32", BFIN_BUILTIN_MULT_1X32, MACFLAG_NONE },
4224 { CODE_FOR_flag_mulhi, "__builtin_bfin_mult_fr1x16", BFIN_BUILTIN_MULT_1X16, MACFLAG_T },
4225 { CODE_FOR_flag_mulhi, "__builtin_bfin_multr_fr1x16", BFIN_BUILTIN_MULTR_1X16, MACFLAG_NONE },
4226 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_mult_fr2x16", BFIN_BUILTIN_MULT_2X16, MACFLAG_T },
4227 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_multr_fr2x16", BFIN_BUILTIN_MULTR_2X16, MACFLAG_NONE }
4230 static const struct builtin_description bdesc_1arg[] =
4232 { CODE_FOR_signbitshi2, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16, 0 },
4233 { CODE_FOR_ssneghi2, "__builtin_bfin_negate_fr1x16", BFIN_BUILTIN_NEG_1X16, 0 },
4234 { CODE_FOR_abshi2, "__builtin_bfin_abs_fr1x16", BFIN_BUILTIN_ABS_1X16, 0 },
4236 { CODE_FOR_signbitssi2, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32, 0 },
4237 { CODE_FOR_ssnegsi2, "__builtin_bfin_negate_fr1x32", BFIN_BUILTIN_NEG_1X32, 0 },
4239 { CODE_FOR_movv2hi_hi_low, "__builtin_bfin_extract_lo", BFIN_BUILTIN_EXTRACTLO, 0 },
4240 { CODE_FOR_movv2hi_hi_high, "__builtin_bfin_extract_hi", BFIN_BUILTIN_EXTRACTHI, 0 },
4241 { CODE_FOR_ssnegv2hi2, "__builtin_bfin_negate_fr2x16", BFIN_BUILTIN_NEG_2X16, 0 },
4242 { CODE_FOR_absv2hi2, "__builtin_bfin_abs_fr2x16", BFIN_BUILTIN_ABS_2X16, 0 }
4245 /* Errors in the source file can cause expand_expr to return const0_rtx
4246 where we expect a vector. To avoid crashing, use one of the vector
4247 clear instructions. */
4249 safe_vector_operand (rtx x, enum machine_mode mode)
4251 if (x != const0_rtx)
4253 x = gen_reg_rtx (SImode);
4255 emit_insn (gen_movsi (x, CONST0_RTX (SImode)));
4256 return gen_lowpart (mode, x);
4259 /* Subroutine of bfin_expand_builtin to take care of binop insns. MACFLAG is -1
4260 if this is a normal binary op, or one of the MACFLAG_xxx constants. */
4263 bfin_expand_binop_builtin (enum insn_code icode, tree arglist, rtx target,
4267 tree arg0 = TREE_VALUE (arglist);
4268 tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
4269 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4270 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
4271 enum machine_mode op0mode = GET_MODE (op0);
4272 enum machine_mode op1mode = GET_MODE (op1);
4273 enum machine_mode tmode = insn_data[icode].operand[0].mode;
4274 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
4275 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
4277 if (VECTOR_MODE_P (mode0))
4278 op0 = safe_vector_operand (op0, mode0);
4279 if (VECTOR_MODE_P (mode1))
4280 op1 = safe_vector_operand (op1, mode1);
4283 || GET_MODE (target) != tmode
4284 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
4285 target = gen_reg_rtx (tmode);
4287 if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode)
4290 op0 = gen_lowpart (HImode, op0);
4292 if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode)
4295 op1 = gen_lowpart (HImode, op1);
4297 /* In case the insn wants input operands in modes different from
4298 the result, abort. */
4299 gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
4300 && (op1mode == mode1 || op1mode == VOIDmode));
4302 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
4303 op0 = copy_to_mode_reg (mode0, op0);
4304 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
4305 op1 = copy_to_mode_reg (mode1, op1);
4308 pat = GEN_FCN (icode) (target, op0, op1);
4310 pat = GEN_FCN (icode) (target, op0, op1, GEN_INT (macflag));
4318 /* Subroutine of bfin_expand_builtin to take care of unop insns. */
4321 bfin_expand_unop_builtin (enum insn_code icode, tree arglist,
4325 tree arg0 = TREE_VALUE (arglist);
4326 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4327 enum machine_mode op0mode = GET_MODE (op0);
4328 enum machine_mode tmode = insn_data[icode].operand[0].mode;
4329 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
4332 || GET_MODE (target) != tmode
4333 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
4334 target = gen_reg_rtx (tmode);
4336 if (VECTOR_MODE_P (mode0))
4337 op0 = safe_vector_operand (op0, mode0);
4339 if (op0mode == SImode && mode0 == HImode)
4342 op0 = gen_lowpart (HImode, op0);
4344 gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
4346 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
4347 op0 = copy_to_mode_reg (mode0, op0);
4349 pat = GEN_FCN (icode) (target, op0);
4356 /* Expand an expression EXP that calls a built-in function,
4357 with result going to TARGET if that's convenient
4358 (and in mode MODE if that's convenient).
4359 SUBTARGET may be used as the target for computing one of EXP's operands.
4360 IGNORE is nonzero if the value is to be ignored. */
4363 bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
4364 rtx subtarget ATTRIBUTE_UNUSED,
4365 enum machine_mode mode ATTRIBUTE_UNUSED,
4366 int ignore ATTRIBUTE_UNUSED)
4369 enum insn_code icode;
4370 const struct builtin_description *d;
4371 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
4372 tree arglist = TREE_OPERAND (exp, 1);
4373 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
4374 tree arg0, arg1, arg2;
4375 rtx op0, op1, op2, accvec, pat, tmp1, tmp2;
4376 enum machine_mode tmode, mode0;
4380 case BFIN_BUILTIN_CSYNC:
4381 emit_insn (gen_csync ());
4383 case BFIN_BUILTIN_SSYNC:
4384 emit_insn (gen_ssync ());
4387 case BFIN_BUILTIN_DIFFHL_2X16:
4388 case BFIN_BUILTIN_DIFFLH_2X16:
4389 arg0 = TREE_VALUE (arglist);
4390 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4391 icode = (fcode == BFIN_BUILTIN_DIFFHL_2X16
4392 ? CODE_FOR_subhilov2hi3 : CODE_FOR_sublohiv2hi3);
4393 tmode = insn_data[icode].operand[0].mode;
4394 mode0 = insn_data[icode].operand[1].mode;
4397 || GET_MODE (target) != tmode
4398 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
4399 target = gen_reg_rtx (tmode);
4401 if (VECTOR_MODE_P (mode0))
4402 op0 = safe_vector_operand (op0, mode0);
4404 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
4405 op0 = copy_to_mode_reg (mode0, op0);
4407 pat = GEN_FCN (icode) (target, op0, op0);
4413 case BFIN_BUILTIN_CPLX_MUL_16:
4414 arg0 = TREE_VALUE (arglist);
4415 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
4416 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4417 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
4418 accvec = gen_reg_rtx (V2PDImode);
4421 || GET_MODE (target) != V2HImode
4422 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
4423 target = gen_reg_rtx (tmode);
4424 if (! register_operand (op0, GET_MODE (op0)))
4425 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
4426 if (! register_operand (op1, GET_MODE (op1)))
4427 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
4429 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
4430 const0_rtx, const0_rtx,
4431 const1_rtx, GEN_INT (MACFLAG_NONE)));
4432 emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
4433 const1_rtx, const1_rtx,
4434 const0_rtx, accvec, const1_rtx, const0_rtx,
4435 GEN_INT (MACFLAG_NONE), accvec));
4439 case BFIN_BUILTIN_CPLX_MAC_16:
4440 case BFIN_BUILTIN_CPLX_MSU_16:
4441 arg0 = TREE_VALUE (arglist);
4442 arg1 = TREE_VALUE (TREE_CHAIN (arglist));
4443 arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
4444 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4445 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
4446 op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
4447 accvec = gen_reg_rtx (V2PDImode);
4450 || GET_MODE (target) != V2HImode
4451 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
4452 target = gen_reg_rtx (tmode);
4453 if (! register_operand (op0, GET_MODE (op0)))
4454 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
4455 if (! register_operand (op1, GET_MODE (op1)))
4456 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
4458 tmp1 = gen_reg_rtx (SImode);
4459 tmp2 = gen_reg_rtx (SImode);
4460 emit_insn (gen_ashlsi3 (tmp1, gen_lowpart (SImode, op2), GEN_INT (16)));
4461 emit_move_insn (tmp2, gen_lowpart (SImode, op2));
4462 emit_insn (gen_movstricthi_1 (gen_lowpart (HImode, tmp2), const0_rtx));
4463 emit_insn (gen_load_accumulator_pair (accvec, tmp1, tmp2));
4464 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op0, op1, const0_rtx,
4465 const0_rtx, const0_rtx,
4466 const1_rtx, accvec, const0_rtx,
4468 GEN_INT (MACFLAG_W32)));
4469 tmp1 = (fcode == BFIN_BUILTIN_CPLX_MAC_16 ? const1_rtx : const0_rtx);
4470 tmp2 = (fcode == BFIN_BUILTIN_CPLX_MAC_16 ? const0_rtx : const1_rtx);
4471 emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
4472 const1_rtx, const1_rtx,
4473 const0_rtx, accvec, tmp1, tmp2,
4474 GEN_INT (MACFLAG_NONE), accvec));
4482 for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
4483 if (d->code == fcode)
4484 return bfin_expand_binop_builtin (d->icode, arglist, target,
4487 for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
4488 if (d->code == fcode)
4489 return bfin_expand_unop_builtin (d->icode, arglist, target);
4494 #undef TARGET_INIT_BUILTINS
4495 #define TARGET_INIT_BUILTINS bfin_init_builtins
4497 #undef TARGET_EXPAND_BUILTIN
4498 #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
4500 #undef TARGET_ASM_GLOBALIZE_LABEL
4501 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label
4503 #undef TARGET_ASM_FILE_START
4504 #define TARGET_ASM_FILE_START output_file_start
4506 #undef TARGET_ATTRIBUTE_TABLE
4507 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
4509 #undef TARGET_COMP_TYPE_ATTRIBUTES
4510 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
4512 #undef TARGET_RTX_COSTS
4513 #define TARGET_RTX_COSTS bfin_rtx_costs
4515 #undef TARGET_ADDRESS_COST
4516 #define TARGET_ADDRESS_COST bfin_address_cost
4518 #undef TARGET_ASM_INTERNAL_LABEL
4519 #define TARGET_ASM_INTERNAL_LABEL bfin_internal_label
4521 #undef TARGET_ASM_INTEGER
4522 #define TARGET_ASM_INTEGER bfin_assemble_integer
4524 #undef TARGET_MACHINE_DEPENDENT_REORG
4525 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
4527 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
4528 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
4530 #undef TARGET_ASM_OUTPUT_MI_THUNK
4531 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
4532 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
4533 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
4535 #undef TARGET_SCHED_ADJUST_COST
4536 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
4538 #undef TARGET_SCHED_ISSUE_RATE
4539 #define TARGET_SCHED_ISSUE_RATE bfin_issue_rate
4541 #undef TARGET_PROMOTE_PROTOTYPES
4542 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
4543 #undef TARGET_PROMOTE_FUNCTION_ARGS
4544 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
4545 #undef TARGET_PROMOTE_FUNCTION_RETURN
4546 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
4548 #undef TARGET_ARG_PARTIAL_BYTES
4549 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
4551 #undef TARGET_PASS_BY_REFERENCE
4552 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
4554 #undef TARGET_SETUP_INCOMING_VARARGS
4555 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
4557 #undef TARGET_STRUCT_VALUE_RTX
4558 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
4560 #undef TARGET_VECTOR_MODE_SUPPORTED_P
4561 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
4563 #undef TARGET_HANDLE_OPTION
4564 #define TARGET_HANDLE_OPTION bfin_handle_option
4566 #undef TARGET_DEFAULT_TARGET_FLAGS
4567 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
4569 #undef TARGET_SECONDARY_RELOAD
4570 #define TARGET_SECONDARY_RELOAD bfin_secondary_reload
4572 #undef TARGET_DELEGITIMIZE_ADDRESS
4573 #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address
4575 #undef TARGET_CANNOT_FORCE_CONST_MEM
4576 #define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem
4578 struct gcc_target targetm = TARGET_INITIALIZER;