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"
55 #include "cfglayout.h"
58 /* A C structure for machine-specific, per-function data.
59 This is added to the cfun structure. */
60 struct machine_function GTY(())
62 int has_hardware_loops;
65 /* Test and compare insns in bfin.md store the information needed to
66 generate branch and scc insns here. */
67 rtx bfin_compare_op0, bfin_compare_op1;
69 /* RTX for condition code flag register and RETS register */
70 extern GTY(()) rtx bfin_cc_rtx;
71 extern GTY(()) rtx bfin_rets_rtx;
72 rtx bfin_cc_rtx, bfin_rets_rtx;
74 int max_arg_registers = 0;
76 /* Arrays used when emitting register names. */
77 const char *short_reg_names[] = SHORT_REGISTER_NAMES;
78 const char *high_reg_names[] = HIGH_REGISTER_NAMES;
79 const char *dregs_pair_names[] = DREGS_PAIR_NAMES;
80 const char *byte_reg_names[] = BYTE_REGISTER_NAMES;
82 static int arg_regs[] = FUNCTION_ARG_REGISTERS;
84 /* Nonzero if -mshared-library-id was given. */
85 static int bfin_lib_id_given;
87 /* Nonzero if -fschedule-insns2 was given. We override it and
88 call the scheduler ourselves during reorg. */
89 static int bfin_flag_schedule_insns2;
91 /* Determines whether we run variable tracking in machine dependent
93 static int bfin_flag_var_tracking;
96 bfin_cpu_t bfin_cpu_type = DEFAULT_CPU_TYPE;
98 int splitting_for_sched;
101 bfin_globalize_label (FILE *stream, const char *name)
103 fputs (".global ", stream);
104 assemble_name (stream, name);
110 output_file_start (void)
112 FILE *file = asm_out_file;
115 /* Variable tracking should be run after all optimizations which change order
116 of insns. It also needs a valid CFG. This can't be done in
117 override_options, because flag_var_tracking is finalized after
119 bfin_flag_var_tracking = flag_var_tracking;
120 flag_var_tracking = 0;
122 fprintf (file, ".file \"%s\";\n", input_filename);
124 for (i = 0; arg_regs[i] >= 0; i++)
126 max_arg_registers = i; /* how many arg reg used */
129 /* Called early in the compilation to conditionally modify
130 fixed_regs/call_used_regs. */
133 conditional_register_usage (void)
135 /* initialize condition code flag register rtx */
136 bfin_cc_rtx = gen_rtx_REG (BImode, REG_CC);
137 bfin_rets_rtx = gen_rtx_REG (Pmode, REG_RETS);
140 /* Examine machine-dependent attributes of function type FUNTYPE and return its
141 type. See the definition of E_FUNKIND. */
143 static e_funkind funkind (tree funtype)
145 tree attrs = TYPE_ATTRIBUTES (funtype);
146 if (lookup_attribute ("interrupt_handler", attrs))
147 return INTERRUPT_HANDLER;
148 else if (lookup_attribute ("exception_handler", attrs))
149 return EXCPT_HANDLER;
150 else if (lookup_attribute ("nmi_handler", attrs))
156 /* Legitimize PIC addresses. If the address is already position-independent,
157 we return ORIG. Newly generated position-independent addresses go into a
158 reg. This is REG if nonzero, otherwise we allocate register(s) as
159 necessary. PICREG is the register holding the pointer to the PIC offset
163 legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
168 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
173 if (TARGET_ID_SHARED_LIBRARY)
174 unspec = UNSPEC_MOVE_PIC;
175 else if (GET_CODE (addr) == SYMBOL_REF
176 && SYMBOL_REF_FUNCTION_P (addr))
177 unspec = UNSPEC_FUNCDESC_GOT17M4;
179 unspec = UNSPEC_MOVE_FDPIC;
183 gcc_assert (!no_new_pseudos);
184 reg = gen_reg_rtx (Pmode);
187 tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), unspec);
188 new = gen_const_mem (Pmode, gen_rtx_PLUS (Pmode, picreg, tmp));
190 emit_move_insn (reg, new);
191 if (picreg == pic_offset_table_rtx)
192 current_function_uses_pic_offset_table = 1;
196 else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
200 if (GET_CODE (addr) == CONST)
202 addr = XEXP (addr, 0);
203 gcc_assert (GET_CODE (addr) == PLUS);
206 if (XEXP (addr, 0) == picreg)
211 gcc_assert (!no_new_pseudos);
212 reg = gen_reg_rtx (Pmode);
215 base = legitimize_pic_address (XEXP (addr, 0), reg, picreg);
216 addr = legitimize_pic_address (XEXP (addr, 1),
217 base == reg ? NULL_RTX : reg,
220 if (GET_CODE (addr) == CONST_INT)
222 gcc_assert (! reload_in_progress && ! reload_completed);
223 addr = force_reg (Pmode, addr);
226 if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
228 base = gen_rtx_PLUS (Pmode, base, XEXP (addr, 0));
229 addr = XEXP (addr, 1);
232 return gen_rtx_PLUS (Pmode, base, addr);
238 /* Stack frame layout. */
240 /* Compute the number of DREGS to save with a push_multiple operation.
241 This could include registers that aren't modified in the function,
242 since push_multiple only takes a range of registers.
243 If IS_INTHANDLER, then everything that is live must be saved, even
244 if normally call-clobbered. */
247 n_dregs_to_save (bool is_inthandler)
251 for (i = REG_R0; i <= REG_R7; i++)
253 if (regs_ever_live[i] && (is_inthandler || ! call_used_regs[i]))
254 return REG_R7 - i + 1;
256 if (current_function_calls_eh_return)
261 unsigned test = EH_RETURN_DATA_REGNO (j);
262 if (test == INVALID_REGNUM)
265 return REG_R7 - i + 1;
273 /* Like n_dregs_to_save, but compute number of PREGS to save. */
276 n_pregs_to_save (bool is_inthandler)
280 for (i = REG_P0; i <= REG_P5; i++)
281 if ((regs_ever_live[i] && (is_inthandler || ! call_used_regs[i]))
283 && i == PIC_OFFSET_TABLE_REGNUM
284 && (current_function_uses_pic_offset_table
285 || (TARGET_ID_SHARED_LIBRARY && ! current_function_is_leaf))))
286 return REG_P5 - i + 1;
290 /* Determine if we are going to save the frame pointer in the prologue. */
293 must_save_fp_p (void)
295 return frame_pointer_needed || regs_ever_live[REG_FP];
299 stack_frame_needed_p (void)
301 /* EH return puts a new return address into the frame using an
302 address relative to the frame pointer. */
303 if (current_function_calls_eh_return)
305 return frame_pointer_needed;
308 /* Emit code to save registers in the prologue. SAVEALL is nonzero if we
309 must save all registers; this is used for interrupt handlers.
310 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
311 this for an interrupt (or exception) handler. */
314 expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler)
316 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler);
317 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler);
318 int dregno = REG_R7 + 1 - ndregs;
319 int pregno = REG_P5 + 1 - npregs;
320 int total = ndregs + npregs;
327 val = GEN_INT (-total * 4);
328 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total + 2));
329 XVECEXP (pat, 0, 0) = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, val),
330 UNSPEC_PUSH_MULTIPLE);
331 XVECEXP (pat, 0, total + 1) = gen_rtx_SET (VOIDmode, spreg,
332 gen_rtx_PLUS (Pmode, spreg,
334 RTX_FRAME_RELATED_P (XVECEXP (pat, 0, total + 1)) = 1;
335 for (i = 0; i < total; i++)
337 rtx memref = gen_rtx_MEM (word_mode,
338 gen_rtx_PLUS (Pmode, spreg,
339 GEN_INT (- i * 4 - 4)));
343 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
349 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
353 XVECEXP (pat, 0, i + 1) = subpat;
354 RTX_FRAME_RELATED_P (subpat) = 1;
356 insn = emit_insn (pat);
357 RTX_FRAME_RELATED_P (insn) = 1;
360 /* Emit code to restore registers in the epilogue. SAVEALL is nonzero if we
361 must save all registers; this is used for interrupt handlers.
362 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
363 this for an interrupt (or exception) handler. */
366 expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler)
368 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler);
369 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler);
370 int total = ndregs + npregs;
377 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total + 1));
378 XVECEXP (pat, 0, 0) = gen_rtx_SET (VOIDmode, spreg,
379 gen_rtx_PLUS (Pmode, spreg,
380 GEN_INT (total * 4)));
387 for (i = 0; i < total; i++)
390 ? gen_rtx_PLUS (Pmode, spreg, GEN_INT (i * 4))
392 rtx memref = gen_rtx_MEM (word_mode, addr);
395 XVECEXP (pat, 0, i + 1)
396 = gen_rtx_SET (VOIDmode, gen_rtx_REG (word_mode, regno), memref);
405 insn = emit_insn (pat);
406 RTX_FRAME_RELATED_P (insn) = 1;
409 /* Perform any needed actions needed for a function that is receiving a
410 variable number of arguments.
414 MODE and TYPE are the mode and type of the current parameter.
416 PRETEND_SIZE is a variable that should be set to the amount of stack
417 that must be pushed by the prolog to pretend that our caller pushed
420 Normally, this macro will push all remaining incoming registers on the
421 stack and set PRETEND_SIZE to the length of the registers pushed.
424 - VDSP C compiler manual (our ABI) says that a variable args function
425 should save the R0, R1 and R2 registers in the stack.
426 - The caller will always leave space on the stack for the
427 arguments that are passed in registers, so we dont have
428 to leave any extra space.
429 - now, the vastart pointer can access all arguments from the stack. */
432 setup_incoming_varargs (CUMULATIVE_ARGS *cum,
433 enum machine_mode mode ATTRIBUTE_UNUSED,
434 tree type ATTRIBUTE_UNUSED, int *pretend_size,
443 /* The move for named arguments will be generated automatically by the
444 compiler. We need to generate the move rtx for the unnamed arguments
445 if they are in the first 3 words. We assume at least 1 named argument
446 exists, so we never generate [ARGP] = R0 here. */
448 for (i = cum->words + 1; i < max_arg_registers; i++)
450 mem = gen_rtx_MEM (Pmode,
451 plus_constant (arg_pointer_rtx, (i * UNITS_PER_WORD)));
452 emit_move_insn (mem, gen_rtx_REG (Pmode, i));
458 /* Value should be nonzero if functions must have frame pointers.
459 Zero means the frame pointer need not be set up (and parms may
460 be accessed via the stack pointer) in functions that seem suitable. */
463 bfin_frame_pointer_required (void)
465 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
467 if (fkind != SUBROUTINE)
470 /* We turn on -fomit-frame-pointer if -momit-leaf-frame-pointer is used,
471 so we have to override it for non-leaf functions. */
472 if (TARGET_OMIT_LEAF_FRAME_POINTER && ! current_function_is_leaf)
478 /* Return the number of registers pushed during the prologue. */
481 n_regs_saved_by_prologue (void)
483 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
484 bool is_inthandler = fkind != SUBROUTINE;
485 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
486 bool all = (lookup_attribute ("saveall", attrs) != NULL_TREE
487 || (is_inthandler && !current_function_is_leaf));
488 int ndregs = all ? 8 : n_dregs_to_save (is_inthandler);
489 int npregs = all ? 6 : n_pregs_to_save (is_inthandler);
490 int n = ndregs + npregs;
492 if (all || stack_frame_needed_p ())
493 /* We use a LINK instruction in this case. */
497 if (must_save_fp_p ())
499 if (! current_function_is_leaf)
503 if (fkind != SUBROUTINE)
507 /* Increment once for ASTAT. */
511 if (lookup_attribute ("nesting", attrs))
514 for (i = REG_P7 + 1; i < REG_CC; i++)
517 || (!leaf_function_p () && call_used_regs[i]))
518 n += i == REG_A0 || i == REG_A1 ? 2 : 1;
523 /* Return the offset between two registers, one to be eliminated, and the other
524 its replacement, at the start of a routine. */
527 bfin_initial_elimination_offset (int from, int to)
529 HOST_WIDE_INT offset = 0;
531 if (from == ARG_POINTER_REGNUM)
532 offset = n_regs_saved_by_prologue () * 4;
534 if (to == STACK_POINTER_REGNUM)
536 if (current_function_outgoing_args_size >= FIXED_STACK_AREA)
537 offset += current_function_outgoing_args_size;
538 else if (current_function_outgoing_args_size)
539 offset += FIXED_STACK_AREA;
541 offset += get_frame_size ();
547 /* Emit code to load a constant CONSTANT into register REG; setting
548 RTX_FRAME_RELATED_P on all insns we generate if RELATED is true.
549 Make sure that the insns we generate need not be split. */
552 frame_related_constant_load (rtx reg, HOST_WIDE_INT constant, bool related)
555 rtx cst = GEN_INT (constant);
557 if (constant >= -32768 && constant < 65536)
558 insn = emit_move_insn (reg, cst);
561 /* We don't call split_load_immediate here, since dwarf2out.c can get
562 confused about some of the more clever sequences it can generate. */
563 insn = emit_insn (gen_movsi_high (reg, cst));
565 RTX_FRAME_RELATED_P (insn) = 1;
566 insn = emit_insn (gen_movsi_low (reg, reg, cst));
569 RTX_FRAME_RELATED_P (insn) = 1;
572 /* Generate efficient code to add a value to a P register. We can use
573 P1 as a scratch register. Set RTX_FRAME_RELATED_P on the generated
574 insns if FRAME is nonzero. */
577 add_to_reg (rtx reg, HOST_WIDE_INT value, int frame)
582 /* Choose whether to use a sequence using a temporary register, or
583 a sequence with multiple adds. We can add a signed 7-bit value
584 in one instruction. */
585 if (value > 120 || value < -120)
587 rtx tmpreg = gen_rtx_REG (SImode, REG_P1);
591 frame_related_constant_load (tmpreg, value, TRUE);
593 insn = emit_move_insn (tmpreg, GEN_INT (value));
595 insn = emit_insn (gen_addsi3 (reg, reg, tmpreg));
597 RTX_FRAME_RELATED_P (insn) = 1;
608 /* We could use -62, but that would leave the stack unaligned, so
612 insn = emit_insn (gen_addsi3 (reg, reg, GEN_INT (size)));
614 RTX_FRAME_RELATED_P (insn) = 1;
620 /* Generate a LINK insn for a frame sized FRAME_SIZE. If this constant
621 is too large, generate a sequence of insns that has the same effect.
622 SPREG contains (reg:SI REG_SP). */
625 emit_link_insn (rtx spreg, HOST_WIDE_INT frame_size)
627 HOST_WIDE_INT link_size = frame_size;
631 if (link_size > 262140)
634 /* Use a LINK insn with as big a constant as possible, then subtract
635 any remaining size from the SP. */
636 insn = emit_insn (gen_link (GEN_INT (-8 - link_size)));
637 RTX_FRAME_RELATED_P (insn) = 1;
639 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
641 rtx set = XVECEXP (PATTERN (insn), 0, i);
642 gcc_assert (GET_CODE (set) == SET);
643 RTX_FRAME_RELATED_P (set) = 1;
646 frame_size -= link_size;
650 /* Must use a call-clobbered PREG that isn't the static chain. */
651 rtx tmpreg = gen_rtx_REG (Pmode, REG_P1);
653 frame_related_constant_load (tmpreg, -frame_size, TRUE);
654 insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg));
655 RTX_FRAME_RELATED_P (insn) = 1;
659 /* Return the number of bytes we must reserve for outgoing arguments
660 in the current function's stack frame. */
665 if (current_function_outgoing_args_size)
667 if (current_function_outgoing_args_size >= FIXED_STACK_AREA)
668 return current_function_outgoing_args_size;
670 return FIXED_STACK_AREA;
675 /* Save RETS and FP, and allocate a stack frame. ALL is true if the
676 function must save all its registers (true only for certain interrupt
680 do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all)
682 frame_size += arg_area_size ();
684 if (all || stack_frame_needed_p ()
685 || (must_save_fp_p () && ! current_function_is_leaf))
686 emit_link_insn (spreg, frame_size);
689 if (! current_function_is_leaf)
691 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
692 gen_rtx_PRE_DEC (Pmode, spreg)),
694 rtx insn = emit_insn (pat);
695 RTX_FRAME_RELATED_P (insn) = 1;
697 if (must_save_fp_p ())
699 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
700 gen_rtx_PRE_DEC (Pmode, spreg)),
701 gen_rtx_REG (Pmode, REG_FP));
702 rtx insn = emit_insn (pat);
703 RTX_FRAME_RELATED_P (insn) = 1;
705 add_to_reg (spreg, -frame_size, 1);
709 /* Like do_link, but used for epilogues to deallocate the stack frame. */
712 do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all)
714 frame_size += arg_area_size ();
716 if (all || stack_frame_needed_p ())
717 emit_insn (gen_unlink ());
720 rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg));
722 add_to_reg (spreg, frame_size, 0);
723 if (must_save_fp_p ())
725 rtx fpreg = gen_rtx_REG (Pmode, REG_FP);
726 emit_move_insn (fpreg, postinc);
727 emit_insn (gen_rtx_USE (VOIDmode, fpreg));
729 if (! current_function_is_leaf)
731 emit_move_insn (bfin_rets_rtx, postinc);
732 emit_insn (gen_rtx_USE (VOIDmode, bfin_rets_rtx));
737 /* Generate a prologue suitable for a function of kind FKIND. This is
738 called for interrupt and exception handler prologues.
739 SPREG contains (reg:SI REG_SP). */
742 expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind)
745 HOST_WIDE_INT frame_size = get_frame_size ();
746 rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
747 rtx predec = gen_rtx_MEM (SImode, predec1);
749 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
750 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
751 tree kspisusp = lookup_attribute ("kspisusp", attrs);
755 insn = emit_move_insn (spreg, gen_rtx_REG (Pmode, REG_USP));
756 RTX_FRAME_RELATED_P (insn) = 1;
759 /* We need space on the stack in case we need to save the argument
761 if (fkind == EXCPT_HANDLER)
763 insn = emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (-12)));
764 RTX_FRAME_RELATED_P (insn) = 1;
767 insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
768 RTX_FRAME_RELATED_P (insn) = 1;
770 /* If we're calling other functions, they won't save their call-clobbered
771 registers, so we must save everything here. */
772 if (!current_function_is_leaf)
774 expand_prologue_reg_save (spreg, all, true);
776 for (i = REG_P7 + 1; i < REG_CC; i++)
779 || (!leaf_function_p () && call_used_regs[i]))
781 if (i == REG_A0 || i == REG_A1)
782 insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1),
783 gen_rtx_REG (PDImode, i));
785 insn = emit_move_insn (predec, gen_rtx_REG (SImode, i));
786 RTX_FRAME_RELATED_P (insn) = 1;
789 if (lookup_attribute ("nesting", attrs))
791 rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
792 : fkind == NMI_HANDLER ? REG_RETN
794 insn = emit_move_insn (predec, srcreg);
795 RTX_FRAME_RELATED_P (insn) = 1;
798 do_link (spreg, frame_size, all);
800 if (fkind == EXCPT_HANDLER)
802 rtx r0reg = gen_rtx_REG (SImode, REG_R0);
803 rtx r1reg = gen_rtx_REG (SImode, REG_R1);
804 rtx r2reg = gen_rtx_REG (SImode, REG_R2);
807 insn = emit_move_insn (r0reg, gen_rtx_REG (SImode, REG_SEQSTAT));
808 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
810 insn = emit_insn (gen_ashrsi3 (r0reg, r0reg, GEN_INT (26)));
811 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
813 insn = emit_insn (gen_ashlsi3 (r0reg, r0reg, GEN_INT (26)));
814 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
816 insn = emit_move_insn (r1reg, spreg);
817 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
819 insn = emit_move_insn (r2reg, gen_rtx_REG (Pmode, REG_FP));
820 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
822 insn = emit_insn (gen_addsi3 (r2reg, r2reg, GEN_INT (8)));
823 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
828 /* Generate an epilogue suitable for a function of kind FKIND. This is
829 called for interrupt and exception handler epilogues.
830 SPREG contains (reg:SI REG_SP). */
833 expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind)
836 rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
837 rtx postinc = gen_rtx_MEM (SImode, postinc1);
838 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
839 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
841 /* A slightly crude technique to stop flow from trying to delete "dead"
843 MEM_VOLATILE_P (postinc) = 1;
845 do_unlink (spreg, get_frame_size (), all);
847 if (lookup_attribute ("nesting", attrs))
849 rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
850 : fkind == NMI_HANDLER ? REG_RETN
852 emit_move_insn (srcreg, postinc);
855 /* If we're calling other functions, they won't save their call-clobbered
856 registers, so we must save (and restore) everything here. */
857 if (!current_function_is_leaf)
860 for (i = REG_CC - 1; i > REG_P7; i--)
863 || (!leaf_function_p () && call_used_regs[i]))
865 if (i == REG_A0 || i == REG_A1)
867 rtx mem = gen_rtx_MEM (PDImode, postinc1);
868 MEM_VOLATILE_P (mem) = 1;
869 emit_move_insn (gen_rtx_REG (PDImode, i), mem);
872 emit_move_insn (gen_rtx_REG (SImode, i), postinc);
875 expand_epilogue_reg_restore (spreg, all, true);
877 emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
879 /* Deallocate any space we left on the stack in case we needed to save the
880 argument registers. */
881 if (fkind == EXCPT_HANDLER)
882 emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (12)));
884 emit_jump_insn (gen_return_internal (GEN_INT (fkind)));
887 /* Used while emitting the prologue to generate code to load the correct value
888 into the PIC register, which is passed in DEST. */
891 bfin_load_pic_reg (rtx dest)
893 struct cgraph_local_info *i = NULL;
896 if (flag_unit_at_a_time)
897 i = cgraph_local_info (current_function_decl);
899 /* Functions local to the translation unit don't need to reload the
900 pic reg, since the caller always passes a usable one. */
902 return pic_offset_table_rtx;
904 if (bfin_lib_id_given)
905 addr = plus_constant (pic_offset_table_rtx, -4 - bfin_library_id * 4);
907 addr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
908 gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
909 UNSPEC_LIBRARY_OFFSET));
910 insn = emit_insn (gen_movsi (dest, gen_rtx_MEM (Pmode, addr)));
911 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
915 /* Generate RTL for the prologue of the current function. */
918 bfin_expand_prologue (void)
920 HOST_WIDE_INT frame_size = get_frame_size ();
921 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
922 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
923 rtx pic_reg_loaded = NULL_RTX;
925 if (fkind != SUBROUTINE)
927 expand_interrupt_handler_prologue (spreg, fkind);
931 if (current_function_limit_stack
932 || TARGET_STACK_CHECK_L1)
935 = bfin_initial_elimination_offset (ARG_POINTER_REGNUM,
936 STACK_POINTER_REGNUM);
937 rtx lim = current_function_limit_stack ? stack_limit_rtx : NULL_RTX;
938 rtx p2reg = gen_rtx_REG (Pmode, REG_P2);
942 emit_move_insn (p2reg, gen_int_mode (0xFFB00000, SImode));
943 emit_move_insn (p2reg, gen_rtx_MEM (Pmode, p2reg));
946 if (GET_CODE (lim) == SYMBOL_REF)
948 if (TARGET_ID_SHARED_LIBRARY)
950 rtx p1reg = gen_rtx_REG (Pmode, REG_P1);
952 pic_reg_loaded = bfin_load_pic_reg (p2reg);
953 val = legitimize_pic_address (stack_limit_rtx, p1reg,
955 emit_move_insn (p1reg, val);
956 frame_related_constant_load (p2reg, offset, FALSE);
957 emit_insn (gen_addsi3 (p2reg, p2reg, p1reg));
962 rtx limit = plus_constant (lim, offset);
963 emit_move_insn (p2reg, limit);
970 emit_move_insn (p2reg, lim);
971 add_to_reg (p2reg, offset, 0);
974 emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim));
975 emit_insn (gen_trapifcc ());
977 expand_prologue_reg_save (spreg, 0, false);
979 do_link (spreg, frame_size, false);
981 if (TARGET_ID_SHARED_LIBRARY
983 && (current_function_uses_pic_offset_table
984 || !current_function_is_leaf))
985 bfin_load_pic_reg (pic_offset_table_rtx);
988 /* Generate RTL for the epilogue of the current function. NEED_RETURN is zero
989 if this is for a sibcall. EH_RETURN is nonzero if we're expanding an
990 eh_return pattern. */
993 bfin_expand_epilogue (int need_return, int eh_return)
995 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
996 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
998 if (fkind != SUBROUTINE)
1000 expand_interrupt_handler_epilogue (spreg, fkind);
1004 do_unlink (spreg, get_frame_size (), false);
1006 expand_epilogue_reg_restore (spreg, false, false);
1008 /* Omit the return insn if this is for a sibcall. */
1013 emit_insn (gen_addsi3 (spreg, spreg, gen_rtx_REG (Pmode, REG_P2)));
1015 emit_jump_insn (gen_return_internal (GEN_INT (SUBROUTINE)));
1018 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
1021 bfin_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
1022 unsigned int new_reg)
1024 /* Interrupt functions can only use registers that have already been
1025 saved by the prologue, even if they would normally be
1028 if (funkind (TREE_TYPE (current_function_decl)) != SUBROUTINE
1029 && !regs_ever_live[new_reg])
1035 /* Return the value of the return address for the frame COUNT steps up
1036 from the current frame, after the prologue.
1037 We punt for everything but the current frame by returning const0_rtx. */
1040 bfin_return_addr_rtx (int count)
1045 return get_hard_reg_initial_val (Pmode, REG_RETS);
1048 /* Try machine-dependent ways of modifying an illegitimate address X
1049 to be legitimate. If we find one, return the new, valid address,
1050 otherwise return NULL_RTX.
1052 OLDX is the address as it was before break_out_memory_refs was called.
1053 In some cases it is useful to look at this to decide what needs to be done.
1055 MODE is the mode of the memory reference. */
1058 legitimize_address (rtx x ATTRIBUTE_UNUSED, rtx oldx ATTRIBUTE_UNUSED,
1059 enum machine_mode mode ATTRIBUTE_UNUSED)
1065 bfin_delegitimize_address (rtx orig_x)
1069 if (GET_CODE (x) != MEM)
1073 if (GET_CODE (x) == PLUS
1074 && GET_CODE (XEXP (x, 1)) == UNSPEC
1075 && XINT (XEXP (x, 1), 1) == UNSPEC_MOVE_PIC
1076 && GET_CODE (XEXP (x, 0)) == REG
1077 && REGNO (XEXP (x, 0)) == PIC_OFFSET_TABLE_REGNUM)
1078 return XVECEXP (XEXP (x, 1), 0, 0);
1083 /* This predicate is used to compute the length of a load/store insn.
1084 OP is a MEM rtx, we return nonzero if its addressing mode requires a
1085 32-bit instruction. */
1088 effective_address_32bit_p (rtx op, enum machine_mode mode)
1090 HOST_WIDE_INT offset;
1092 mode = GET_MODE (op);
1095 if (GET_CODE (op) != PLUS)
1097 gcc_assert (REG_P (op) || GET_CODE (op) == POST_INC
1098 || GET_CODE (op) == PRE_DEC || GET_CODE (op) == POST_DEC);
1102 if (GET_CODE (XEXP (op, 1)) == UNSPEC)
1105 offset = INTVAL (XEXP (op, 1));
1107 /* All byte loads use a 16-bit offset. */
1108 if (GET_MODE_SIZE (mode) == 1)
1111 if (GET_MODE_SIZE (mode) == 4)
1113 /* Frame pointer relative loads can use a negative offset, all others
1114 are restricted to a small positive one. */
1115 if (XEXP (op, 0) == frame_pointer_rtx)
1116 return offset < -128 || offset > 60;
1117 return offset < 0 || offset > 60;
1120 /* Must be HImode now. */
1121 return offset < 0 || offset > 30;
1124 /* Returns true if X is a memory reference using an I register. */
1126 bfin_dsp_memref_p (rtx x)
1131 if (GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_INC
1132 || GET_CODE (x) == POST_DEC || GET_CODE (x) == PRE_DEC)
1137 /* Return cost of the memory address ADDR.
1138 All addressing modes are equally cheap on the Blackfin. */
1141 bfin_address_cost (rtx addr ATTRIBUTE_UNUSED)
1146 /* Subroutine of print_operand; used to print a memory reference X to FILE. */
1149 print_address_operand (FILE *file, rtx x)
1151 switch (GET_CODE (x))
1154 output_address (XEXP (x, 0));
1155 fprintf (file, "+");
1156 output_address (XEXP (x, 1));
1160 fprintf (file, "--");
1161 output_address (XEXP (x, 0));
1164 output_address (XEXP (x, 0));
1165 fprintf (file, "++");
1168 output_address (XEXP (x, 0));
1169 fprintf (file, "--");
1173 gcc_assert (GET_CODE (x) != MEM);
1174 print_operand (file, x, 0);
1179 /* Adding intp DImode support by Tony
1185 print_operand (FILE *file, rtx x, char code)
1187 enum machine_mode mode;
1191 if (GET_MODE (current_output_insn) == SImode)
1192 fprintf (file, " ||");
1194 fprintf (file, ";");
1198 mode = GET_MODE (x);
1203 switch (GET_CODE (x))
1206 fprintf (file, "e");
1209 fprintf (file, "ne");
1212 fprintf (file, "g");
1215 fprintf (file, "l");
1218 fprintf (file, "ge");
1221 fprintf (file, "le");
1224 fprintf (file, "g");
1227 fprintf (file, "l");
1230 fprintf (file, "ge");
1233 fprintf (file, "le");
1236 output_operand_lossage ("invalid %%j value");
1240 case 'J': /* reverse logic */
1241 switch (GET_CODE(x))
1244 fprintf (file, "ne");
1247 fprintf (file, "e");
1250 fprintf (file, "le");
1253 fprintf (file, "ge");
1256 fprintf (file, "l");
1259 fprintf (file, "g");
1262 fprintf (file, "le");
1265 fprintf (file, "ge");
1268 fprintf (file, "l");
1271 fprintf (file, "g");
1274 output_operand_lossage ("invalid %%J value");
1279 switch (GET_CODE (x))
1284 gcc_assert (REGNO (x) < 32);
1285 fprintf (file, "%s", short_reg_names[REGNO (x)]);
1286 /*fprintf (file, "\n%d\n ", REGNO (x));*/
1289 else if (code == 'd')
1291 gcc_assert (REGNO (x) < 32);
1292 fprintf (file, "%s", high_reg_names[REGNO (x)]);
1295 else if (code == 'w')
1297 gcc_assert (REGNO (x) == REG_A0 || REGNO (x) == REG_A1);
1298 fprintf (file, "%s.w", reg_names[REGNO (x)]);
1300 else if (code == 'x')
1302 gcc_assert (REGNO (x) == REG_A0 || REGNO (x) == REG_A1);
1303 fprintf (file, "%s.x", reg_names[REGNO (x)]);
1305 else if (code == 'D')
1307 fprintf (file, "%s", dregs_pair_names[REGNO (x)]);
1309 else if (code == 'H')
1311 gcc_assert (mode == DImode || mode == DFmode);
1312 gcc_assert (REG_P (x));
1313 fprintf (file, "%s", reg_names[REGNO (x) + 1]);
1315 else if (code == 'T')
1317 gcc_assert (D_REGNO_P (REGNO (x)));
1318 fprintf (file, "%s", byte_reg_names[REGNO (x)]);
1321 fprintf (file, "%s", reg_names[REGNO (x)]);
1327 print_address_operand (file, x);
1339 fputs ("(FU)", file);
1342 fputs ("(T)", file);
1345 fputs ("(TFU)", file);
1348 fputs ("(W32)", file);
1351 fputs ("(IS)", file);
1354 fputs ("(IU)", file);
1357 fputs ("(IH)", file);
1360 fputs ("(M)", file);
1363 fputs ("(IS,M)", file);
1366 fputs ("(ISS2)", file);
1369 fputs ("(S2RND)", file);
1376 else if (code == 'b')
1378 if (INTVAL (x) == 0)
1380 else if (INTVAL (x) == 1)
1386 /* Moves to half registers with d or h modifiers always use unsigned
1388 else if (code == 'd')
1389 x = GEN_INT ((INTVAL (x) >> 16) & 0xffff);
1390 else if (code == 'h')
1391 x = GEN_INT (INTVAL (x) & 0xffff);
1392 else if (code == 'N')
1393 x = GEN_INT (-INTVAL (x));
1394 else if (code == 'X')
1395 x = GEN_INT (exact_log2 (0xffffffff & INTVAL (x)));
1396 else if (code == 'Y')
1397 x = GEN_INT (exact_log2 (0xffffffff & ~INTVAL (x)));
1398 else if (code == 'Z')
1399 /* Used for LINK insns. */
1400 x = GEN_INT (-8 - INTVAL (x));
1405 output_addr_const (file, x);
1409 output_operand_lossage ("invalid const_double operand");
1413 switch (XINT (x, 1))
1415 case UNSPEC_MOVE_PIC:
1416 output_addr_const (file, XVECEXP (x, 0, 0));
1417 fprintf (file, "@GOT");
1420 case UNSPEC_MOVE_FDPIC:
1421 output_addr_const (file, XVECEXP (x, 0, 0));
1422 fprintf (file, "@GOT17M4");
1425 case UNSPEC_FUNCDESC_GOT17M4:
1426 output_addr_const (file, XVECEXP (x, 0, 0));
1427 fprintf (file, "@FUNCDESC_GOT17M4");
1430 case UNSPEC_LIBRARY_OFFSET:
1431 fprintf (file, "_current_shared_library_p5_offset_");
1440 output_addr_const (file, x);
1445 /* Argument support functions. */
1447 /* Initialize a variable CUM of type CUMULATIVE_ARGS
1448 for a call to a function whose data type is FNTYPE.
1449 For a library call, FNTYPE is 0.
1450 VDSP C Compiler manual, our ABI says that
1451 first 3 words of arguments will use R0, R1 and R2.
1455 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
1456 rtx libname ATTRIBUTE_UNUSED)
1458 static CUMULATIVE_ARGS zero_cum;
1462 /* Set up the number of registers to use for passing arguments. */
1464 cum->nregs = max_arg_registers;
1465 cum->arg_regs = arg_regs;
1467 cum->call_cookie = CALL_NORMAL;
1468 /* Check for a longcall attribute. */
1469 if (fntype && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype)))
1470 cum->call_cookie |= CALL_SHORT;
1471 else if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)))
1472 cum->call_cookie |= CALL_LONG;
1477 /* Update the data in CUM to advance over an argument
1478 of mode MODE and data type TYPE.
1479 (TYPE is null for libcalls where that information may not be available.) */
1482 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1483 int named ATTRIBUTE_UNUSED)
1485 int count, bytes, words;
1487 bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1488 words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1490 cum->words += words;
1491 cum->nregs -= words;
1493 if (cum->nregs <= 0)
1496 cum->arg_regs = NULL;
1500 for (count = 1; count <= words; count++)
1507 /* Define where to put the arguments to a function.
1508 Value is zero to push the argument on the stack,
1509 or a hard register in which to store the argument.
1511 MODE is the argument's machine mode.
1512 TYPE is the data type of the argument (as a tree).
1513 This is null for libcalls where that information may
1515 CUM is a variable of type CUMULATIVE_ARGS which gives info about
1516 the preceding args and about the function being called.
1517 NAMED is nonzero if this argument is a named parameter
1518 (otherwise it is an extra parameter matching an ellipsis). */
1521 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1522 int named ATTRIBUTE_UNUSED)
1525 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1527 if (mode == VOIDmode)
1528 /* Compute operand 2 of the call insn. */
1529 return GEN_INT (cum->call_cookie);
1535 return gen_rtx_REG (mode, *(cum->arg_regs));
1540 /* For an arg passed partly in registers and partly in memory,
1541 this is the number of bytes passed in registers.
1542 For args passed entirely in registers or entirely in memory, zero.
1544 Refer VDSP C Compiler manual, our ABI.
1545 First 3 words are in registers. So, if an argument is larger
1546 than the registers available, it will span the register and
1550 bfin_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1551 tree type ATTRIBUTE_UNUSED,
1552 bool named ATTRIBUTE_UNUSED)
1555 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1556 int bytes_left = cum->nregs * UNITS_PER_WORD;
1561 if (bytes_left == 0)
1563 if (bytes > bytes_left)
1568 /* Variable sized types are passed by reference. */
1571 bfin_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
1572 enum machine_mode mode ATTRIBUTE_UNUSED,
1573 tree type, bool named ATTRIBUTE_UNUSED)
1575 return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
1578 /* Decide whether a type should be returned in memory (true)
1579 or in a register (false). This is called by the macro
1580 RETURN_IN_MEMORY. */
1583 bfin_return_in_memory (tree type)
1585 int size = int_size_in_bytes (type);
1586 return size > 2 * UNITS_PER_WORD || size == -1;
1589 /* Register in which address to store a structure value
1590 is passed to a function. */
1592 bfin_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
1593 int incoming ATTRIBUTE_UNUSED)
1595 return gen_rtx_REG (Pmode, REG_P0);
1598 /* Return true when register may be used to pass function parameters. */
1601 function_arg_regno_p (int n)
1604 for (i = 0; arg_regs[i] != -1; i++)
1605 if (n == arg_regs[i])
1610 /* Returns 1 if OP contains a symbol reference */
1613 symbolic_reference_mentioned_p (rtx op)
1615 register const char *fmt;
1618 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
1621 fmt = GET_RTX_FORMAT (GET_CODE (op));
1622 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
1628 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
1629 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
1633 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
1640 /* Decide whether we can make a sibling call to a function. DECL is the
1641 declaration of the function being targeted by the call and EXP is the
1642 CALL_EXPR representing the call. */
1645 bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
1646 tree exp ATTRIBUTE_UNUSED)
1648 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1649 if (fkind != SUBROUTINE)
1651 if (!TARGET_ID_SHARED_LIBRARY || TARGET_SEP_DATA)
1654 /* When compiling for ID shared libraries, can't sibcall a local function
1655 from a non-local function, because the local function thinks it does
1656 not need to reload P5 in the prologue, but the sibcall wil pop P5 in the
1657 sibcall epilogue, and we end up with the wrong value in P5. */
1659 if (!flag_unit_at_a_time || decl == NULL)
1660 /* Not enough information. */
1664 struct cgraph_local_info *this_func, *called_func;
1666 this_func = cgraph_local_info (current_function_decl);
1667 called_func = cgraph_local_info (decl);
1668 return !called_func->local || this_func->local;
1672 /* Emit RTL insns to initialize the variable parts of a trampoline at
1673 TRAMP. FNADDR is an RTX for the address of the function's pure
1674 code. CXT is an RTX for the static chain value for the function. */
1677 initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt)
1679 rtx t1 = copy_to_reg (fnaddr);
1680 rtx t2 = copy_to_reg (cxt);
1686 rtx a = memory_address (Pmode, plus_constant (tramp, 8));
1687 addr = memory_address (Pmode, tramp);
1688 emit_move_insn (gen_rtx_MEM (SImode, addr), a);
1692 addr = memory_address (Pmode, plus_constant (tramp, i + 2));
1693 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
1694 emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16)));
1695 addr = memory_address (Pmode, plus_constant (tramp, i + 6));
1696 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
1698 addr = memory_address (Pmode, plus_constant (tramp, i + 10));
1699 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
1700 emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16)));
1701 addr = memory_address (Pmode, plus_constant (tramp, i + 14));
1702 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
1705 /* Emit insns to move operands[1] into operands[0]. */
1708 emit_pic_move (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
1710 rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
1712 gcc_assert (!TARGET_FDPIC || !(reload_in_progress || reload_completed));
1713 if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
1714 operands[1] = force_reg (SImode, operands[1]);
1716 operands[1] = legitimize_pic_address (operands[1], temp,
1717 TARGET_FDPIC ? OUR_FDPIC_REG
1718 : pic_offset_table_rtx);
1721 /* Expand a move operation in mode MODE. The operands are in OPERANDS.
1722 Returns true if no further code must be generated, false if the caller
1723 should generate an insn to move OPERANDS[1] to OPERANDS[0]. */
1726 expand_move (rtx *operands, enum machine_mode mode)
1728 rtx op = operands[1];
1729 if ((TARGET_ID_SHARED_LIBRARY || TARGET_FDPIC)
1730 && SYMBOLIC_CONST (op))
1731 emit_pic_move (operands, mode);
1732 else if (mode == SImode && GET_CODE (op) == CONST
1733 && GET_CODE (XEXP (op, 0)) == PLUS
1734 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
1735 && !bfin_legitimate_constant_p (op))
1737 rtx dest = operands[0];
1739 gcc_assert (!reload_in_progress && !reload_completed);
1741 op0 = force_reg (mode, XEXP (op, 0));
1743 if (!insn_data[CODE_FOR_addsi3].operand[2].predicate (op1, mode))
1744 op1 = force_reg (mode, op1);
1745 if (GET_CODE (dest) == MEM)
1746 dest = gen_reg_rtx (mode);
1747 emit_insn (gen_addsi3 (dest, op0, op1));
1748 if (dest == operands[0])
1752 /* Don't generate memory->memory or constant->memory moves, go through a
1754 else if ((reload_in_progress | reload_completed) == 0
1755 && GET_CODE (operands[0]) == MEM
1756 && GET_CODE (operands[1]) != REG)
1757 operands[1] = force_reg (mode, operands[1]);
1761 /* Split one or more DImode RTL references into pairs of SImode
1762 references. The RTL can be REG, offsettable MEM, integer constant, or
1763 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
1764 split and "num" is its length. lo_half and hi_half are output arrays
1765 that parallel "operands". */
1768 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
1772 rtx op = operands[num];
1774 /* simplify_subreg refuse to split volatile memory addresses,
1775 but we still have to handle it. */
1776 if (GET_CODE (op) == MEM)
1778 lo_half[num] = adjust_address (op, SImode, 0);
1779 hi_half[num] = adjust_address (op, SImode, 4);
1783 lo_half[num] = simplify_gen_subreg (SImode, op,
1784 GET_MODE (op) == VOIDmode
1785 ? DImode : GET_MODE (op), 0);
1786 hi_half[num] = simplify_gen_subreg (SImode, op,
1787 GET_MODE (op) == VOIDmode
1788 ? DImode : GET_MODE (op), 4);
1794 bfin_longcall_p (rtx op, int call_cookie)
1796 gcc_assert (GET_CODE (op) == SYMBOL_REF);
1797 if (call_cookie & CALL_SHORT)
1799 if (call_cookie & CALL_LONG)
1801 if (TARGET_LONG_CALLS)
1806 /* Expand a call instruction. FNADDR is the call target, RETVAL the return value.
1807 COOKIE is a CONST_INT holding the call_cookie prepared init_cumulative_args.
1808 SIBCALL is nonzero if this is a sibling call. */
1811 bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
1813 rtx use = NULL, call;
1814 rtx callee = XEXP (fnaddr, 0);
1815 int nelts = 2 + !!sibcall;
1817 rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REGNO);
1820 /* In an untyped call, we can get NULL for operand 2. */
1821 if (cookie == NULL_RTX)
1822 cookie = const0_rtx;
1824 /* Static functions and indirect calls don't need the pic register. */
1825 if (!TARGET_FDPIC && flag_pic
1826 && GET_CODE (callee) == SYMBOL_REF
1827 && !SYMBOL_REF_LOCAL_P (callee))
1828 use_reg (&use, pic_offset_table_rtx);
1832 if (GET_CODE (callee) != SYMBOL_REF
1833 || bfin_longcall_p (callee, INTVAL (cookie)))
1836 if (! address_operand (addr, Pmode))
1837 addr = force_reg (Pmode, addr);
1839 fnaddr = gen_reg_rtx (SImode);
1840 emit_insn (gen_load_funcdescsi (fnaddr, addr));
1841 fnaddr = gen_rtx_MEM (Pmode, fnaddr);
1843 picreg = gen_reg_rtx (SImode);
1844 emit_insn (gen_load_funcdescsi (picreg,
1845 plus_constant (addr, 4)));
1850 else if ((!register_no_elim_operand (callee, Pmode)
1851 && GET_CODE (callee) != SYMBOL_REF)
1852 || (GET_CODE (callee) == SYMBOL_REF
1853 && ((TARGET_ID_SHARED_LIBRARY && !TARGET_LEAF_ID_SHARED_LIBRARY)
1854 || bfin_longcall_p (callee, INTVAL (cookie)))))
1856 callee = copy_to_mode_reg (Pmode, callee);
1857 fnaddr = gen_rtx_MEM (Pmode, callee);
1859 call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
1862 call = gen_rtx_SET (VOIDmode, retval, call);
1864 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nelts));
1866 XVECEXP (pat, 0, n++) = call;
1868 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, picreg);
1869 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie);
1871 XVECEXP (pat, 0, n++) = gen_rtx_RETURN (VOIDmode);
1872 call = emit_call_insn (pat);
1874 CALL_INSN_FUNCTION_USAGE (call) = use;
1877 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
1880 hard_regno_mode_ok (int regno, enum machine_mode mode)
1882 /* Allow only dregs to store value of mode HI or QI */
1883 enum reg_class class = REGNO_REG_CLASS (regno);
1888 if (mode == V2HImode)
1889 return D_REGNO_P (regno);
1890 if (class == CCREGS)
1891 return mode == BImode;
1892 if (mode == PDImode || mode == V2PDImode)
1893 return regno == REG_A0 || regno == REG_A1;
1895 /* Allow all normal 32-bit regs, except REG_M3, in case regclass ever comes
1896 up with a bad register class (such as ALL_REGS) for DImode. */
1898 return regno < REG_M3;
1901 && TEST_HARD_REG_BIT (reg_class_contents[PROLOGUE_REGS], regno))
1904 return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno);
1907 /* Implements target hook vector_mode_supported_p. */
1910 bfin_vector_mode_supported_p (enum machine_mode mode)
1912 return mode == V2HImode;
1915 /* Return the cost of moving data from a register in class CLASS1 to
1916 one in class CLASS2. A cost of 2 is the default. */
1919 bfin_register_move_cost (enum machine_mode mode,
1920 enum reg_class class1, enum reg_class class2)
1922 /* These need secondary reloads, so they're more expensive. */
1923 if ((class1 == CCREGS && class2 != DREGS)
1924 || (class1 != DREGS && class2 == CCREGS))
1927 /* If optimizing for size, always prefer reg-reg over reg-memory moves. */
1931 /* There are some stalls involved when moving from a DREG to a different
1932 class reg, and using the value in one of the following instructions.
1933 Attempt to model this by slightly discouraging such moves. */
1934 if (class1 == DREGS && class2 != DREGS)
1937 if (GET_MODE_CLASS (mode) == MODE_INT)
1939 /* Discourage trying to use the accumulators. */
1940 if (TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A0)
1941 || TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A1)
1942 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A0)
1943 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A1))
1949 /* Return the cost of moving data of mode M between a
1950 register and memory. A value of 2 is the default; this cost is
1951 relative to those in `REGISTER_MOVE_COST'.
1953 ??? In theory L1 memory has single-cycle latency. We should add a switch
1954 that tells the compiler whether we expect to use only L1 memory for the
1955 program; it'll make the costs more accurate. */
1958 bfin_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
1959 enum reg_class class,
1960 int in ATTRIBUTE_UNUSED)
1962 /* Make memory accesses slightly more expensive than any register-register
1963 move. Also, penalize non-DP registers, since they need secondary
1964 reloads to load and store. */
1965 if (! reg_class_subset_p (class, DPREGS))
1971 /* Inform reload about cases where moving X with a mode MODE to a register in
1972 CLASS requires an extra scratch register. Return the class needed for the
1973 scratch register. */
1975 static enum reg_class
1976 bfin_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x, enum reg_class class,
1977 enum machine_mode mode, secondary_reload_info *sri)
1979 /* If we have HImode or QImode, we can only use DREGS as secondary registers;
1980 in most other cases we can also use PREGS. */
1981 enum reg_class default_class = GET_MODE_SIZE (mode) >= 4 ? DPREGS : DREGS;
1982 enum reg_class x_class = NO_REGS;
1983 enum rtx_code code = GET_CODE (x);
1986 x = SUBREG_REG (x), code = GET_CODE (x);
1989 int regno = REGNO (x);
1990 if (regno >= FIRST_PSEUDO_REGISTER)
1991 regno = reg_renumber[regno];
1996 x_class = REGNO_REG_CLASS (regno);
1999 /* We can be asked to reload (plus (FP) (large_constant)) into a DREG.
2000 This happens as a side effect of register elimination, and we need
2001 a scratch register to do it. */
2002 if (fp_plus_const_operand (x, mode))
2004 rtx op2 = XEXP (x, 1);
2005 int large_constant_p = ! CONST_7BIT_IMM_P (INTVAL (op2));
2007 if (class == PREGS || class == PREGS_CLOBBERED)
2009 /* If destination is a DREG, we can do this without a scratch register
2010 if the constant is valid for an add instruction. */
2011 if ((class == DREGS || class == DPREGS)
2012 && ! large_constant_p)
2014 /* Reloading to anything other than a DREG? Use a PREG scratch
2016 sri->icode = CODE_FOR_reload_insi;
2020 /* Data can usually be moved freely between registers of most classes.
2021 AREGS are an exception; they can only move to or from another register
2022 in AREGS or one in DREGS. They can also be assigned the constant 0. */
2023 if (x_class == AREGS || x_class == EVEN_AREGS || x_class == ODD_AREGS)
2024 return (class == DREGS || class == AREGS || class == EVEN_AREGS
2025 || class == ODD_AREGS
2028 if (class == AREGS || class == EVEN_AREGS || class == ODD_AREGS)
2030 if (x != const0_rtx && x_class != DREGS)
2036 /* CCREGS can only be moved from/to DREGS. */
2037 if (class == CCREGS && x_class != DREGS)
2039 if (x_class == CCREGS && class != DREGS)
2042 /* All registers other than AREGS can load arbitrary constants. The only
2043 case that remains is MEM. */
2045 if (! reg_class_subset_p (class, default_class))
2046 return default_class;
2050 /* Implement TARGET_HANDLE_OPTION. */
2053 bfin_handle_option (size_t code, const char *arg, int value)
2057 case OPT_mshared_library_id_:
2058 if (value > MAX_LIBRARY_ID)
2059 error ("-mshared-library-id=%s is not between 0 and %d",
2060 arg, MAX_LIBRARY_ID);
2061 bfin_lib_id_given = 1;
2065 if (strcmp (arg, "bf531") == 0)
2066 bfin_cpu_type = BFIN_CPU_BF531;
2067 else if (strcmp (arg, "bf532") == 0)
2068 bfin_cpu_type = BFIN_CPU_BF532;
2069 else if (strcmp (arg, "bf533") == 0)
2070 bfin_cpu_type = BFIN_CPU_BF533;
2071 else if (strcmp (arg, "bf537") == 0)
2072 bfin_cpu_type = BFIN_CPU_BF537;
2082 static struct machine_function *
2083 bfin_init_machine_status (void)
2085 struct machine_function *f;
2087 f = ggc_alloc_cleared (sizeof (struct machine_function));
2092 /* Implement the macro OVERRIDE_OPTIONS. */
2095 override_options (void)
2097 if (TARGET_OMIT_LEAF_FRAME_POINTER)
2098 flag_omit_frame_pointer = 1;
2100 /* Library identification */
2101 if (bfin_lib_id_given && ! TARGET_ID_SHARED_LIBRARY)
2102 error ("-mshared-library-id= specified without -mid-shared-library");
2104 if (TARGET_ID_SHARED_LIBRARY && flag_pic == 0)
2107 if (stack_limit_rtx && TARGET_STACK_CHECK_L1)
2108 error ("Can't use multiple stack checking methods together.");
2110 if (TARGET_ID_SHARED_LIBRARY && TARGET_FDPIC)
2111 error ("ID shared libraries and FD-PIC mode can't be used together.");
2113 /* Don't allow the user to specify -mid-shared-library and -msep-data
2114 together, as it makes little sense from a user's point of view... */
2115 if (TARGET_SEP_DATA && TARGET_ID_SHARED_LIBRARY)
2116 error ("cannot specify both -msep-data and -mid-shared-library");
2117 /* ... internally, however, it's nearly the same. */
2118 if (TARGET_SEP_DATA)
2119 target_flags |= MASK_ID_SHARED_LIBRARY | MASK_LEAF_ID_SHARED_LIBRARY;
2121 /* There is no single unaligned SI op for PIC code. Sometimes we
2122 need to use ".4byte" and sometimes we need to use ".picptr".
2123 See bfin_assemble_integer for details. */
2125 targetm.asm_out.unaligned_op.si = 0;
2127 /* Silently turn off flag_pic if not doing FDPIC or ID shared libraries,
2128 since we don't support it and it'll just break. */
2129 if (flag_pic && !TARGET_FDPIC && !TARGET_ID_SHARED_LIBRARY)
2132 flag_schedule_insns = 0;
2134 /* Passes after sched2 can break the helpful TImode annotations that
2135 haifa-sched puts on every insn. Just do scheduling in reorg. */
2136 bfin_flag_schedule_insns2 = flag_schedule_insns_after_reload;
2137 flag_schedule_insns_after_reload = 0;
2139 init_machine_status = bfin_init_machine_status;
2142 /* Return the destination address of BRANCH.
2143 We need to use this instead of get_attr_length, because the
2144 cbranch_with_nops pattern conservatively sets its length to 6, and
2145 we still prefer to use shorter sequences. */
2148 branch_dest (rtx branch)
2152 rtx pat = PATTERN (branch);
2153 if (GET_CODE (pat) == PARALLEL)
2154 pat = XVECEXP (pat, 0, 0);
2155 dest = SET_SRC (pat);
2156 if (GET_CODE (dest) == IF_THEN_ELSE)
2157 dest = XEXP (dest, 1);
2158 dest = XEXP (dest, 0);
2159 dest_uid = INSN_UID (dest);
2160 return INSN_ADDRESSES (dest_uid);
2163 /* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates
2164 it's a branch that's predicted taken. */
2167 cbranch_predicted_taken_p (rtx insn)
2169 rtx x = find_reg_note (insn, REG_BR_PROB, 0);
2173 int pred_val = INTVAL (XEXP (x, 0));
2175 return pred_val >= REG_BR_PROB_BASE / 2;
2181 /* Templates for use by asm_conditional_branch. */
2183 static const char *ccbranch_templates[][3] = {
2184 { "if !cc jump %3;", "if cc jump 4 (bp); jump.s %3;", "if cc jump 6 (bp); jump.l %3;" },
2185 { "if cc jump %3;", "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" },
2186 { "if !cc jump %3 (bp);", "if cc jump 4; jump.s %3;", "if cc jump 6; jump.l %3;" },
2187 { "if cc jump %3 (bp);", "if !cc jump 4; jump.s %3;", "if !cc jump 6; jump.l %3;" },
2190 /* Output INSN, which is a conditional branch instruction with operands
2193 We deal with the various forms of conditional branches that can be generated
2194 by bfin_reorg to prevent the hardware from doing speculative loads, by
2195 - emitting a sufficient number of nops, if N_NOPS is nonzero, or
2196 - always emitting the branch as predicted taken, if PREDICT_TAKEN is true.
2197 Either of these is only necessary if the branch is short, otherwise the
2198 template we use ends in an unconditional jump which flushes the pipeline
2202 asm_conditional_branch (rtx insn, rtx *operands, int n_nops, int predict_taken)
2204 int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
2205 /* Note : offset for instructions like if cc jmp; jump.[sl] offset
2206 is to be taken from start of if cc rather than jump.
2207 Range for jump.s is (-4094, 4096) instead of (-4096, 4094)
2209 int len = (offset >= -1024 && offset <= 1022 ? 0
2210 : offset >= -4094 && offset <= 4096 ? 1
2212 int bp = predict_taken && len == 0 ? 1 : cbranch_predicted_taken_p (insn);
2213 int idx = (bp << 1) | (GET_CODE (operands[0]) == EQ ? BRF : BRT);
2214 output_asm_insn (ccbranch_templates[idx][len], operands);
2215 gcc_assert (n_nops == 0 || !bp);
2217 while (n_nops-- > 0)
2218 output_asm_insn ("nop;", NULL);
2221 /* Emit rtl for a comparison operation CMP in mode MODE. Operands have been
2222 stored in bfin_compare_op0 and bfin_compare_op1 already. */
2225 bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED)
2227 enum rtx_code code1, code2;
2228 rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1;
2229 rtx tem = bfin_cc_rtx;
2230 enum rtx_code code = GET_CODE (cmp);
2232 /* If we have a BImode input, then we already have a compare result, and
2233 do not need to emit another comparison. */
2234 if (GET_MODE (op0) == BImode)
2236 gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
2237 tem = op0, code2 = code;
2242 /* bfin has these conditions */
2252 code1 = reverse_condition (code);
2256 emit_insn (gen_rtx_SET (BImode, tem,
2257 gen_rtx_fmt_ee (code1, BImode, op0, op1)));
2260 return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode));
2263 /* Return nonzero iff C has exactly one bit set if it is interpreted
2264 as a 32-bit constant. */
2267 log2constp (unsigned HOST_WIDE_INT c)
2270 return c != 0 && (c & (c-1)) == 0;
2273 /* Returns the number of consecutive least significant zeros in the binary
2274 representation of *V.
2275 We modify *V to contain the original value arithmetically shifted right by
2276 the number of zeroes. */
2279 shiftr_zero (HOST_WIDE_INT *v)
2281 unsigned HOST_WIDE_INT tmp = *v;
2282 unsigned HOST_WIDE_INT sgn;
2288 sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1));
2289 while ((tmp & 0x1) == 0 && n <= 32)
2291 tmp = (tmp >> 1) | sgn;
2298 /* After reload, split the load of an immediate constant. OPERANDS are the
2299 operands of the movsi_insn pattern which we are splitting. We return
2300 nonzero if we emitted a sequence to load the constant, zero if we emitted
2301 nothing because we want to use the splitter's default sequence. */
2304 split_load_immediate (rtx operands[])
2306 HOST_WIDE_INT val = INTVAL (operands[1]);
2308 HOST_WIDE_INT shifted = val;
2309 HOST_WIDE_INT shifted_compl = ~val;
2310 int num_zero = shiftr_zero (&shifted);
2311 int num_compl_zero = shiftr_zero (&shifted_compl);
2312 unsigned int regno = REGNO (operands[0]);
2314 /* This case takes care of single-bit set/clear constants, which we could
2315 also implement with BITSET/BITCLR. */
2317 && shifted >= -32768 && shifted < 65536
2318 && (D_REGNO_P (regno)
2319 || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))
2321 emit_insn (gen_movsi (operands[0], GEN_INT (shifted)));
2322 emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));
2327 tmp |= -(tmp & 0x8000);
2329 /* If high word has one bit set or clear, try to use a bit operation. */
2330 if (D_REGNO_P (regno))
2332 if (log2constp (val & 0xFFFF0000))
2334 emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));
2335 emit_insn (gen_iorsi3 (operands[0], operands[0], GEN_INT (val & 0xFFFF0000)));
2338 else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)
2340 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2341 emit_insn (gen_andsi3 (operands[0], operands[0], GEN_INT (val | 0xFFFF)));
2345 if (D_REGNO_P (regno))
2347 if (CONST_7BIT_IMM_P (tmp))
2349 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2350 emit_insn (gen_movstricthi_high (operands[0], GEN_INT (val & -65536)));
2354 if ((val & 0xFFFF0000) == 0)
2356 emit_insn (gen_movsi (operands[0], const0_rtx));
2357 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2361 if ((val & 0xFFFF0000) == 0xFFFF0000)
2363 emit_insn (gen_movsi (operands[0], constm1_rtx));
2364 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2369 /* Need DREGs for the remaining case. */
2374 && num_compl_zero && CONST_7BIT_IMM_P (shifted_compl))
2376 /* If optimizing for size, generate a sequence that has more instructions
2378 emit_insn (gen_movsi (operands[0], GEN_INT (shifted_compl)));
2379 emit_insn (gen_ashlsi3 (operands[0], operands[0],
2380 GEN_INT (num_compl_zero)));
2381 emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
2387 /* Return true if the legitimate memory address for a memory operand of mode
2388 MODE. Return false if not. */
2391 bfin_valid_add (enum machine_mode mode, HOST_WIDE_INT value)
2393 unsigned HOST_WIDE_INT v = value > 0 ? value : -value;
2394 int sz = GET_MODE_SIZE (mode);
2395 int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2;
2396 /* The usual offsettable_memref machinery doesn't work so well for this
2397 port, so we deal with the problem here. */
2398 if (value > 0 && sz == 8)
2400 return (v & ~(0x7fff << shift)) == 0;
2404 bfin_valid_reg_p (unsigned int regno, int strict, enum machine_mode mode,
2405 enum rtx_code outer_code)
2408 return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH);
2410 return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH);
2414 bfin_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
2416 switch (GET_CODE (x)) {
2418 if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM))
2422 if (REG_P (XEXP (x, 0))
2423 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS)
2424 && ((GET_CODE (XEXP (x, 1)) == UNSPEC && mode == SImode)
2425 || (GET_CODE (XEXP (x, 1)) == CONST_INT
2426 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
2431 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2432 && REG_P (XEXP (x, 0))
2433 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC))
2436 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2437 && XEXP (x, 0) == stack_pointer_rtx
2438 && REG_P (XEXP (x, 0))
2439 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC))
2448 /* Decide whether we can force certain constants to memory. If we
2449 decide we can't, the caller should be able to cope with it in
2453 bfin_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
2455 /* We have only one class of non-legitimate constants, and our movsi
2456 expander knows how to handle them. Dropping these constants into the
2457 data section would only shift the problem - we'd still get relocs
2458 outside the object, in the data section rather than the text section. */
2462 /* Ensure that for any constant of the form symbol + offset, the offset
2463 remains within the object. Any other constants are ok.
2464 This ensures that flat binaries never have to deal with relocations
2465 crossing section boundaries. */
2468 bfin_legitimate_constant_p (rtx x)
2471 HOST_WIDE_INT offset;
2473 if (GET_CODE (x) != CONST)
2477 gcc_assert (GET_CODE (x) == PLUS);
2481 if (GET_CODE (sym) != SYMBOL_REF
2482 || GET_CODE (x) != CONST_INT)
2484 offset = INTVAL (x);
2486 if (SYMBOL_REF_DECL (sym) == 0)
2489 || offset >= int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (sym))))
2496 bfin_rtx_costs (rtx x, int code, int outer_code, int *total)
2498 int cost2 = COSTS_N_INSNS (1);
2504 if (outer_code == SET || outer_code == PLUS)
2505 *total = CONST_7BIT_IMM_P (INTVAL (x)) ? 0 : cost2;
2506 else if (outer_code == AND)
2507 *total = log2constp (~INTVAL (x)) ? 0 : cost2;
2508 else if (outer_code == LE || outer_code == LT || outer_code == EQ)
2509 *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
2510 else if (outer_code == LEU || outer_code == LTU)
2511 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
2512 else if (outer_code == MULT)
2513 *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
2514 else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
2516 else if (outer_code == ASHIFT || outer_code == ASHIFTRT
2517 || outer_code == LSHIFTRT)
2518 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
2519 else if (outer_code == IOR || outer_code == XOR)
2520 *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
2529 *total = COSTS_N_INSNS (2);
2535 if (GET_MODE (x) == SImode)
2537 if (GET_CODE (op0) == MULT
2538 && GET_CODE (XEXP (op0, 1)) == CONST_INT)
2540 HOST_WIDE_INT val = INTVAL (XEXP (op0, 1));
2541 if (val == 2 || val == 4)
2544 *total += rtx_cost (XEXP (op0, 0), outer_code);
2545 *total += rtx_cost (op1, outer_code);
2550 if (GET_CODE (op0) != REG
2551 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2552 *total += rtx_cost (op0, SET);
2553 #if 0 /* We'd like to do this for accuracy, but it biases the loop optimizer
2554 towards creating too many induction variables. */
2555 if (!reg_or_7bit_operand (op1, SImode))
2556 *total += rtx_cost (op1, SET);
2559 else if (GET_MODE (x) == DImode)
2562 if (GET_CODE (op1) != CONST_INT
2563 || !CONST_7BIT_IMM_P (INTVAL (op1)))
2564 *total += rtx_cost (op1, PLUS);
2565 if (GET_CODE (op0) != REG
2566 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2567 *total += rtx_cost (op0, PLUS);
2572 if (GET_MODE (x) == DImode)
2581 if (GET_MODE (x) == DImode)
2588 if (GET_CODE (op0) != REG
2589 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2590 *total += rtx_cost (op0, code);
2600 /* Handle special cases of IOR: rotates, ALIGN insns, movstricthi_high. */
2603 if ((GET_CODE (op0) == LSHIFTRT && GET_CODE (op1) == ASHIFT)
2604 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == ZERO_EXTEND)
2605 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT)
2606 || (GET_CODE (op0) == AND && GET_CODE (op1) == CONST_INT))
2613 if (GET_CODE (op0) != REG
2614 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2615 *total += rtx_cost (op0, code);
2617 if (GET_MODE (x) == DImode)
2623 if (GET_MODE (x) != SImode)
2628 if (! rhs_andsi3_operand (XEXP (x, 1), SImode))
2629 *total += rtx_cost (XEXP (x, 1), code);
2633 if (! regorlog2_operand (XEXP (x, 1), SImode))
2634 *total += rtx_cost (XEXP (x, 1), code);
2641 if (outer_code == SET
2642 && XEXP (x, 1) == const1_rtx
2643 && GET_CODE (XEXP (x, 2)) == CONST_INT)
2659 if (GET_CODE (op0) == GET_CODE (op1)
2660 && (GET_CODE (op0) == ZERO_EXTEND
2661 || GET_CODE (op0) == SIGN_EXTEND))
2663 *total = COSTS_N_INSNS (1);
2664 op0 = XEXP (op0, 0);
2665 op1 = XEXP (op1, 0);
2667 else if (optimize_size)
2668 *total = COSTS_N_INSNS (1);
2670 *total = COSTS_N_INSNS (3);
2672 if (GET_CODE (op0) != REG
2673 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2674 *total += rtx_cost (op0, MULT);
2675 if (GET_CODE (op1) != REG
2676 && (GET_CODE (op1) != SUBREG || GET_CODE (SUBREG_REG (op1)) != REG))
2677 *total += rtx_cost (op1, MULT);
2683 *total = COSTS_N_INSNS (32);
2688 if (outer_code == SET)
2698 bfin_internal_label (FILE *stream, const char *prefix, unsigned long num)
2700 fprintf (stream, "%s%s$%ld:\n", LOCAL_LABEL_PREFIX, prefix, num);
2703 /* Used for communication between {push,pop}_multiple_operation (which
2704 we use not only as a predicate) and the corresponding output functions. */
2705 static int first_preg_to_save, first_dreg_to_save;
2708 push_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2710 int lastdreg = 8, lastpreg = 6;
2713 first_preg_to_save = lastpreg;
2714 first_dreg_to_save = lastdreg;
2715 for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
2717 rtx t = XVECEXP (op, 0, i);
2721 if (GET_CODE (t) != SET)
2725 dest = SET_DEST (t);
2726 if (GET_CODE (dest) != MEM || ! REG_P (src))
2728 dest = XEXP (dest, 0);
2729 if (GET_CODE (dest) != PLUS
2730 || ! REG_P (XEXP (dest, 0))
2731 || REGNO (XEXP (dest, 0)) != REG_SP
2732 || GET_CODE (XEXP (dest, 1)) != CONST_INT
2733 || INTVAL (XEXP (dest, 1)) != -i * 4)
2736 regno = REGNO (src);
2739 if (D_REGNO_P (regno))
2742 first_dreg_to_save = lastdreg = regno - REG_R0;
2744 else if (regno >= REG_P0 && regno <= REG_P7)
2747 first_preg_to_save = lastpreg = regno - REG_P0;
2757 if (regno >= REG_P0 && regno <= REG_P7)
2760 first_preg_to_save = lastpreg = regno - REG_P0;
2762 else if (regno != REG_R0 + lastdreg + 1)
2767 else if (group == 2)
2769 if (regno != REG_P0 + lastpreg + 1)
2778 pop_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2780 int lastdreg = 8, lastpreg = 6;
2783 for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
2785 rtx t = XVECEXP (op, 0, i);
2789 if (GET_CODE (t) != SET)
2793 dest = SET_DEST (t);
2794 if (GET_CODE (src) != MEM || ! REG_P (dest))
2796 src = XEXP (src, 0);
2800 if (! REG_P (src) || REGNO (src) != REG_SP)
2803 else if (GET_CODE (src) != PLUS
2804 || ! REG_P (XEXP (src, 0))
2805 || REGNO (XEXP (src, 0)) != REG_SP
2806 || GET_CODE (XEXP (src, 1)) != CONST_INT
2807 || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
2810 regno = REGNO (dest);
2813 if (regno == REG_R7)
2818 else if (regno != REG_P0 + lastpreg - 1)
2823 else if (group == 1)
2825 if (regno != REG_R0 + lastdreg - 1)
2831 first_dreg_to_save = lastdreg;
2832 first_preg_to_save = lastpreg;
2836 /* Emit assembly code for one multi-register push described by INSN, with
2837 operands in OPERANDS. */
2840 output_push_multiple (rtx insn, rtx *operands)
2845 /* Validate the insn again, and compute first_[dp]reg_to_save. */
2846 ok = push_multiple_operation (PATTERN (insn), VOIDmode);
2849 if (first_dreg_to_save == 8)
2850 sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
2851 else if (first_preg_to_save == 6)
2852 sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
2854 sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
2855 first_dreg_to_save, first_preg_to_save);
2857 output_asm_insn (buf, operands);
2860 /* Emit assembly code for one multi-register pop described by INSN, with
2861 operands in OPERANDS. */
2864 output_pop_multiple (rtx insn, rtx *operands)
2869 /* Validate the insn again, and compute first_[dp]reg_to_save. */
2870 ok = pop_multiple_operation (PATTERN (insn), VOIDmode);
2873 if (first_dreg_to_save == 8)
2874 sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
2875 else if (first_preg_to_save == 6)
2876 sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
2878 sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
2879 first_dreg_to_save, first_preg_to_save);
2881 output_asm_insn (buf, operands);
2884 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE. */
2887 single_move_for_movmem (rtx dst, rtx src, enum machine_mode mode, HOST_WIDE_INT offset)
2889 rtx scratch = gen_reg_rtx (mode);
2892 srcmem = adjust_address_nv (src, mode, offset);
2893 dstmem = adjust_address_nv (dst, mode, offset);
2894 emit_move_insn (scratch, srcmem);
2895 emit_move_insn (dstmem, scratch);
2898 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
2899 alignment ALIGN_EXP. Return true if successful, false if we should fall
2900 back on a different method. */
2903 bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
2905 rtx srcreg, destreg, countreg;
2906 HOST_WIDE_INT align = 0;
2907 unsigned HOST_WIDE_INT count = 0;
2909 if (GET_CODE (align_exp) == CONST_INT)
2910 align = INTVAL (align_exp);
2911 if (GET_CODE (count_exp) == CONST_INT)
2913 count = INTVAL (count_exp);
2915 if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
2920 /* If optimizing for size, only do single copies inline. */
2923 if (count == 2 && align < 2)
2925 if (count == 4 && align < 4)
2927 if (count != 1 && count != 2 && count != 4)
2930 if (align < 2 && count != 1)
2933 destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
2934 if (destreg != XEXP (dst, 0))
2935 dst = replace_equiv_address_nv (dst, destreg);
2936 srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
2937 if (srcreg != XEXP (src, 0))
2938 src = replace_equiv_address_nv (src, srcreg);
2940 if (count != 0 && align >= 2)
2942 unsigned HOST_WIDE_INT offset = 0;
2946 if ((count & ~3) == 4)
2948 single_move_for_movmem (dst, src, SImode, offset);
2951 else if (count & ~3)
2953 HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
2954 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
2956 emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
2960 single_move_for_movmem (dst, src, HImode, offset);
2966 if ((count & ~1) == 2)
2968 single_move_for_movmem (dst, src, HImode, offset);
2971 else if (count & ~1)
2973 HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
2974 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
2976 emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
2981 single_move_for_movmem (dst, src, QImode, offset);
2988 /* Implement TARGET_SCHED_ISSUE_RATE. */
2991 bfin_issue_rate (void)
2997 bfin_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
2999 enum attr_type insn_type, dep_insn_type;
3000 int dep_insn_code_number;
3002 /* Anti and output dependencies have zero cost. */
3003 if (REG_NOTE_KIND (link) != 0)
3006 dep_insn_code_number = recog_memoized (dep_insn);
3008 /* If we can't recognize the insns, we can't really do anything. */
3009 if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
3012 insn_type = get_attr_type (insn);
3013 dep_insn_type = get_attr_type (dep_insn);
3015 if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)
3017 rtx pat = PATTERN (dep_insn);
3018 rtx dest = SET_DEST (pat);
3019 rtx src = SET_SRC (pat);
3020 if (! ADDRESS_REGNO_P (REGNO (dest))
3021 || ! (MEM_P (src) || D_REGNO_P (REGNO (src))))
3023 return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);
3030 /* Increment the counter for the number of loop instructions in the
3031 current function. */
3034 bfin_hardware_loop (void)
3036 cfun->machine->has_hardware_loops++;
3039 /* Maximum loop nesting depth. */
3040 #define MAX_LOOP_DEPTH 2
3042 /* Maximum size of a loop. */
3043 #define MAX_LOOP_LENGTH 2042
3045 /* Maximum distance of the LSETUP instruction from the loop start. */
3046 #define MAX_LSETUP_DISTANCE 30
3048 /* We need to keep a vector of loops */
3049 typedef struct loop_info *loop_info;
3050 DEF_VEC_P (loop_info);
3051 DEF_VEC_ALLOC_P (loop_info,heap);
3053 /* Information about a loop we have found (or are in the process of
3055 struct loop_info GTY (())
3057 /* loop number, for dumps */
3060 /* All edges that jump into and out of the loop. */
3061 VEC(edge,gc) *incoming;
3063 /* We can handle two cases: all incoming edges have the same destination
3064 block, or all incoming edges have the same source block. These two
3065 members are set to the common source or destination we found, or NULL
3066 if different blocks were found. If both are NULL the loop can't be
3068 basic_block incoming_src;
3069 basic_block incoming_dest;
3071 /* First block in the loop. This is the one branched to by the loop_end
3075 /* Last block in the loop (the one with the loop_end insn). */
3078 /* The successor block of the loop. This is the one the loop_end insn
3080 basic_block successor;
3082 /* The last instruction in the tail. */
3085 /* The loop_end insn. */
3088 /* The iteration register. */
3091 /* The new initialization insn. */
3094 /* The new initialization instruction. */
3097 /* The new label placed at the beginning of the loop. */
3100 /* The new label placed at the end of the loop. */
3103 /* The length of the loop. */
3106 /* The nesting depth of the loop. */
3109 /* Nonzero if we can't optimize this loop. */
3112 /* True if we have visited this loop. */
3115 /* True if this loop body clobbers any of LC0, LT0, or LB0. */
3118 /* True if this loop body clobbers any of LC1, LT1, or LB1. */
3121 /* Next loop in the graph. */
3122 struct loop_info *next;
3124 /* Immediate outer loop of this loop. */
3125 struct loop_info *outer;
3127 /* Vector of blocks only within the loop, including those within
3129 VEC (basic_block,heap) *blocks;
3131 /* Same information in a bitmap. */
3132 bitmap block_bitmap;
3134 /* Vector of inner loops within this loop */
3135 VEC (loop_info,heap) *loops;
3139 bfin_dump_loops (loop_info loops)
3143 for (loop = loops; loop; loop = loop->next)
3149 fprintf (dump_file, ";; loop %d: ", loop->loop_no);
3151 fprintf (dump_file, "(bad) ");
3152 fprintf (dump_file, "{head:%d, depth:%d}", loop->head->index, loop->depth);
3154 fprintf (dump_file, " blocks: [ ");
3155 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, b); ix++)
3156 fprintf (dump_file, "%d ", b->index);
3157 fprintf (dump_file, "] ");
3159 fprintf (dump_file, " inner loops: [ ");
3160 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, i); ix++)
3161 fprintf (dump_file, "%d ", i->loop_no);
3162 fprintf (dump_file, "]\n");
3164 fprintf (dump_file, "\n");
3167 /* Scan the blocks of LOOP (and its inferiors) looking for basic block
3168 BB. Return true, if we find it. */
3171 bfin_bb_in_loop (loop_info loop, basic_block bb)
3173 return bitmap_bit_p (loop->block_bitmap, bb->index);
3176 /* Scan the blocks of LOOP (and its inferiors) looking for uses of
3177 REG. Return true, if we find any. Don't count the loop's loop_end
3178 insn if it matches LOOP_END. */
3181 bfin_scan_loop (loop_info loop, rtx reg, rtx loop_end)
3186 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
3190 for (insn = BB_HEAD (bb);
3191 insn != NEXT_INSN (BB_END (bb));
3192 insn = NEXT_INSN (insn))
3196 if (insn == loop_end)
3198 if (reg_mentioned_p (reg, PATTERN (insn)))
3205 /* Estimate the length of INSN conservatively. */
3208 length_for_loop (rtx insn)
3211 if (JUMP_P (insn) && any_condjump_p (insn) && !optimize_size)
3213 if (TARGET_CSYNC_ANOMALY)
3215 else if (TARGET_SPECLD_ANOMALY)
3218 else if (LABEL_P (insn))
3220 if (TARGET_CSYNC_ANOMALY)
3225 length += get_attr_length (insn);
3230 /* Optimize LOOP. */
3233 bfin_optimize_loop (loop_info loop)
3237 rtx insn, init_insn, last_insn, nop_insn;
3238 rtx loop_init, start_label, end_label;
3239 rtx reg_lc0, reg_lc1, reg_lt0, reg_lt1, reg_lb0, reg_lb1;
3241 rtx lc_reg, lt_reg, lb_reg;
3245 int inner_depth = 0;
3255 fprintf (dump_file, ";; loop %d bad when found\n", loop->loop_no);
3259 /* Every loop contains in its list of inner loops every loop nested inside
3260 it, even if there are intermediate loops. This works because we're doing
3261 a depth-first search here and never visit a loop more than once. */
3262 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, inner); ix++)
3264 bfin_optimize_loop (inner);
3266 if (!inner->bad && inner_depth < inner->depth)
3268 inner_depth = inner->depth;
3270 loop->clobber_loop0 |= inner->clobber_loop0;
3271 loop->clobber_loop1 |= inner->clobber_loop1;
3275 loop->depth = inner_depth + 1;
3276 if (loop->depth > MAX_LOOP_DEPTH)
3279 fprintf (dump_file, ";; loop %d too deep\n", loop->loop_no);
3283 /* Get the loop iteration register. */
3284 iter_reg = loop->iter_reg;
3286 if (!DPREG_P (iter_reg))
3289 fprintf (dump_file, ";; loop %d iteration count NOT in PREG or DREG\n",
3294 if (loop->incoming_src)
3296 /* Make sure the predecessor is before the loop start label, as required by
3297 the LSETUP instruction. */
3299 for (insn = BB_END (loop->incoming_src);
3300 insn && insn != loop->start_label;
3301 insn = NEXT_INSN (insn))
3302 length += length_for_loop (insn);
3307 fprintf (dump_file, ";; loop %d lsetup not before loop_start\n",
3312 if (length > MAX_LSETUP_DISTANCE)
3315 fprintf (dump_file, ";; loop %d lsetup too far away\n", loop->loop_no);
3320 /* Check if start_label appears before loop_end and calculate the
3321 offset between them. We calculate the length of instructions
3324 for (insn = loop->start_label;
3325 insn && insn != loop->loop_end;
3326 insn = NEXT_INSN (insn))
3327 length += length_for_loop (insn);
3332 fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
3337 loop->length = length;
3338 if (loop->length > MAX_LOOP_LENGTH)
3341 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
3345 /* Scan all the blocks to make sure they don't use iter_reg. */
3346 if (bfin_scan_loop (loop, iter_reg, loop->loop_end))
3349 fprintf (dump_file, ";; loop %d uses iterator\n", loop->loop_no);
3353 /* Scan all the insns to see if the loop body clobber
3354 any hardware loop registers. */
3356 reg_lc0 = gen_rtx_REG (SImode, REG_LC0);
3357 reg_lc1 = gen_rtx_REG (SImode, REG_LC1);
3358 reg_lt0 = gen_rtx_REG (SImode, REG_LT0);
3359 reg_lt1 = gen_rtx_REG (SImode, REG_LT1);
3360 reg_lb0 = gen_rtx_REG (SImode, REG_LB0);
3361 reg_lb1 = gen_rtx_REG (SImode, REG_LB1);
3363 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
3367 for (insn = BB_HEAD (bb);
3368 insn != NEXT_INSN (BB_END (bb));
3369 insn = NEXT_INSN (insn))
3374 if (reg_set_p (reg_lc0, insn)
3375 || reg_set_p (reg_lt0, insn)
3376 || reg_set_p (reg_lb0, insn))
3377 loop->clobber_loop0 = 1;
3379 if (reg_set_p (reg_lc1, insn)
3380 || reg_set_p (reg_lt1, insn)
3381 || reg_set_p (reg_lb1, insn))
3382 loop->clobber_loop1 |= 1;
3386 if ((loop->clobber_loop0 && loop->clobber_loop1)
3387 || (loop->depth == MAX_LOOP_DEPTH && loop->clobber_loop0))
3389 loop->depth = MAX_LOOP_DEPTH + 1;
3391 fprintf (dump_file, ";; loop %d no loop reg available\n",
3396 /* There should be an instruction before the loop_end instruction
3397 in the same basic block. And the instruction must not be
3399 - CONDITIONAL BRANCH
3403 - Returns (RTS, RTN, etc.) */
3406 last_insn = PREV_INSN (loop->loop_end);
3410 for (; last_insn != PREV_INSN (BB_HEAD (bb));
3411 last_insn = PREV_INSN (last_insn))
3412 if (INSN_P (last_insn))
3415 if (last_insn != PREV_INSN (BB_HEAD (bb)))
3418 if (single_pred_p (bb)
3419 && single_pred (bb) != ENTRY_BLOCK_PTR)
3421 bb = single_pred (bb);
3422 last_insn = BB_END (bb);
3427 last_insn = NULL_RTX;
3435 fprintf (dump_file, ";; loop %d has no last instruction\n",
3440 if (JUMP_P (last_insn))
3442 loop_info inner = bb->aux;
3444 && inner->outer == loop
3445 && inner->loop_end == last_insn
3446 && inner->depth == 1)
3447 /* This jump_insn is the exact loop_end of an inner loop
3448 and to be optimized away. So use the inner's last_insn. */
3449 last_insn = inner->last_insn;
3453 fprintf (dump_file, ";; loop %d has bad last instruction\n",
3458 else if (CALL_P (last_insn)
3459 || (GET_CODE (PATTERN (last_insn)) != SEQUENCE
3460 && get_attr_type (last_insn) == TYPE_SYNC)
3461 || recog_memoized (last_insn) == CODE_FOR_return_internal)
3464 fprintf (dump_file, ";; loop %d has bad last instruction\n",
3469 if (GET_CODE (PATTERN (last_insn)) == ASM_INPUT
3470 || asm_noperands (PATTERN (last_insn)) >= 0
3471 || (GET_CODE (PATTERN (last_insn)) != SEQUENCE
3472 && get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI))
3474 nop_insn = emit_insn_after (gen_nop (), last_insn);
3475 last_insn = nop_insn;
3478 loop->last_insn = last_insn;
3480 /* The loop is good for replacement. */
3481 start_label = loop->start_label;
3482 end_label = gen_label_rtx ();
3483 iter_reg = loop->iter_reg;
3485 if (loop->depth == 1 && !loop->clobber_loop1)
3490 loop->clobber_loop1 = 1;
3497 loop->clobber_loop0 = 1;
3500 /* If iter_reg is a DREG, we need generate an instruction to load
3501 the loop count into LC register. */
3502 if (D_REGNO_P (REGNO (iter_reg)))
3504 init_insn = gen_movsi (lc_reg, iter_reg);
3505 loop_init = gen_lsetup_without_autoinit (lt_reg, start_label,
3509 else if (P_REGNO_P (REGNO (iter_reg)))
3511 init_insn = NULL_RTX;
3512 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
3519 loop->init = init_insn;
3520 loop->end_label = end_label;
3521 loop->loop_init = loop_init;
3525 fprintf (dump_file, ";; replacing loop %d initializer with\n",
3527 print_rtl_single (dump_file, loop->loop_init);
3528 fprintf (dump_file, ";; replacing loop %d terminator with\n",
3530 print_rtl_single (dump_file, loop->loop_end);
3535 if (loop->init != NULL_RTX)
3536 emit_insn (loop->init);
3537 seq_end = emit_insn (loop->loop_init);
3542 if (loop->incoming_src)
3544 rtx prev = BB_END (loop->incoming_src);
3545 if (VEC_length (edge, loop->incoming) > 1
3546 || !(VEC_last (edge, loop->incoming)->flags & EDGE_FALLTHRU))
3548 gcc_assert (JUMP_P (prev));
3549 prev = PREV_INSN (prev);
3551 emit_insn_after (seq, prev);
3559 if (loop->head != loop->incoming_dest)
3561 FOR_EACH_EDGE (e, ei, loop->head->preds)
3563 if (e->flags & EDGE_FALLTHRU)
3565 rtx newjump = gen_jump (loop->start_label);
3566 emit_insn_before (newjump, BB_HEAD (loop->head));
3567 new_bb = create_basic_block (newjump, newjump, loop->head->prev_bb);
3568 gcc_assert (new_bb = loop->head->prev_bb);
3574 emit_insn_before (seq, BB_HEAD (loop->head));
3575 seq = emit_label_before (gen_label_rtx (), seq);
3577 new_bb = create_basic_block (seq, seq_end, loop->head->prev_bb);
3578 FOR_EACH_EDGE (e, ei, loop->incoming)
3580 if (!(e->flags & EDGE_FALLTHRU)
3581 || e->dest != loop->head)
3582 redirect_edge_and_branch_force (e, new_bb);
3584 redirect_edge_succ (e, new_bb);
3588 delete_insn (loop->loop_end);
3589 /* Insert the loop end label before the last instruction of the loop. */
3590 emit_label_before (loop->end_label, loop->last_insn);
3597 fprintf (dump_file, ";; loop %d is bad\n", loop->loop_no);
3601 if (DPREG_P (loop->iter_reg))
3603 /* If loop->iter_reg is a DREG or PREG, we can split it here
3604 without scratch register. */
3607 emit_insn_before (gen_addsi3 (loop->iter_reg,
3612 emit_insn_before (gen_cmpsi (loop->iter_reg, const0_rtx),
3615 insn = emit_jump_insn_before (gen_bne (loop->start_label),
3618 JUMP_LABEL (insn) = loop->start_label;
3619 LABEL_NUSES (loop->start_label)++;
3620 delete_insn (loop->loop_end);
3624 /* Called from bfin_reorg_loops when a potential loop end is found. LOOP is
3625 a newly set up structure describing the loop, it is this function's
3626 responsibility to fill most of it. TAIL_BB and TAIL_INSN point to the
3627 loop_end insn and its enclosing basic block. */
3630 bfin_discover_loop (loop_info loop, basic_block tail_bb, rtx tail_insn)
3634 VEC (basic_block,heap) *works = VEC_alloc (basic_block,heap,20);
3636 loop->tail = tail_bb;
3637 loop->head = BRANCH_EDGE (tail_bb)->dest;
3638 loop->successor = FALLTHRU_EDGE (tail_bb)->dest;
3639 loop->loop_end = tail_insn;
3640 loop->last_insn = NULL_RTX;
3641 loop->iter_reg = SET_DEST (XVECEXP (PATTERN (tail_insn), 0, 1));
3642 loop->depth = loop->length = 0;
3644 loop->clobber_loop0 = loop->clobber_loop1 = 0;
3647 loop->incoming = VEC_alloc (edge, gc, 2);
3648 loop->init = loop->loop_init = NULL_RTX;
3649 loop->start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (tail_insn), 0, 0)), 1), 0);
3650 loop->end_label = NULL_RTX;
3653 VEC_safe_push (basic_block, heap, works, loop->head);
3655 while (VEC_iterate (basic_block, works, dwork++, bb))
3659 if (bb == EXIT_BLOCK_PTR)
3661 /* We've reached the exit block. The loop must be bad. */
3664 ";; Loop is bad - reached exit block while scanning\n");
3669 if (bitmap_bit_p (loop->block_bitmap, bb->index))
3672 /* We've not seen this block before. Add it to the loop's
3673 list and then add each successor to the work list. */
3675 VEC_safe_push (basic_block, heap, loop->blocks, bb);
3676 bitmap_set_bit (loop->block_bitmap, bb->index);
3680 FOR_EACH_EDGE (e, ei, bb->succs)
3682 basic_block succ = EDGE_SUCC (bb, ei.index)->dest;
3683 if (!REGNO_REG_SET_P (succ->il.rtl->global_live_at_start,
3684 REGNO (loop->iter_reg)))
3686 if (!VEC_space (basic_block, works, 1))
3690 VEC_block_remove (basic_block, works, 0, dwork);
3694 VEC_reserve (basic_block, heap, works, 1);
3696 VEC_quick_push (basic_block, works, succ);
3701 /* Find the predecessor, and make sure nothing else jumps into this loop. */
3705 for (dwork = 0; VEC_iterate (basic_block, loop->blocks, dwork, bb); dwork++)
3709 FOR_EACH_EDGE (e, ei, bb->preds)
3711 basic_block pred = e->src;
3713 if (!bfin_bb_in_loop (loop, pred))
3716 fprintf (dump_file, ";; Loop %d: incoming edge %d -> %d\n",
3717 loop->loop_no, pred->index,
3719 VEC_safe_push (edge, gc, loop->incoming, e);
3724 for (pass = 0, retry = 1; retry && pass < 2; pass++)
3731 FOR_EACH_EDGE (e, ei, loop->incoming)
3735 loop->incoming_src = e->src;
3736 loop->incoming_dest = e->dest;
3741 if (e->dest != loop->incoming_dest)
3742 loop->incoming_dest = NULL;
3743 if (e->src != loop->incoming_src)
3744 loop->incoming_src = NULL;
3746 if (loop->incoming_src == NULL && loop->incoming_dest == NULL)
3752 ";; retrying loop %d with forwarder blocks\n",
3760 ";; can't find suitable entry for loop %d\n",
3768 FOR_EACH_EDGE (e, ei, loop->incoming)
3770 if (forwarder_block_p (e->src))
3777 ";; Adding forwarder block %d to loop %d and retrying\n",
3778 e->src->index, loop->loop_no);
3779 VEC_safe_push (basic_block, heap, loop->blocks, e->src);
3780 bitmap_set_bit (loop->block_bitmap, e->src->index);
3781 FOR_EACH_EDGE (e2, ei2, e->src->preds)
3782 VEC_safe_push (edge, gc, loop->incoming, e2);
3783 VEC_unordered_remove (edge, loop->incoming, ei.index);
3793 VEC_free (basic_block, heap, works);
3796 /* Analyze the structure of the loops in the current function. Use STACK
3797 for bitmap allocations. Returns all the valid candidates for hardware
3798 loops found in this function. */
3800 bfin_discover_loops (bitmap_obstack *stack, FILE *dump_file)
3802 loop_info loops = NULL;
3808 /* Find all the possible loop tails. This means searching for every
3809 loop_end instruction. For each one found, create a loop_info
3810 structure and add the head block to the work list. */
3813 rtx tail = BB_END (bb);
3815 while (GET_CODE (tail) == NOTE)
3816 tail = PREV_INSN (tail);
3820 if (INSN_P (tail) && recog_memoized (tail) == CODE_FOR_loop_end)
3822 /* A possible loop end */
3824 loop = XNEW (struct loop_info);
3827 loop->loop_no = nloops++;
3828 loop->blocks = VEC_alloc (basic_block, heap, 20);
3829 loop->block_bitmap = BITMAP_ALLOC (stack);
3834 fprintf (dump_file, ";; potential loop %d ending at\n",
3836 print_rtl_single (dump_file, tail);
3839 bfin_discover_loop (loop, bb, tail);
3843 tmp_bitmap = BITMAP_ALLOC (stack);
3844 /* Compute loop nestings. */
3845 for (loop = loops; loop; loop = loop->next)
3851 for (other = loop->next; other; other = other->next)
3856 bitmap_and (tmp_bitmap, other->block_bitmap, loop->block_bitmap);
3857 if (bitmap_empty_p (tmp_bitmap))
3859 if (bitmap_equal_p (tmp_bitmap, other->block_bitmap))
3861 other->outer = loop;
3862 VEC_safe_push (loop_info, heap, loop->loops, other);
3864 else if (bitmap_equal_p (tmp_bitmap, loop->block_bitmap))
3866 loop->outer = other;
3867 VEC_safe_push (loop_info, heap, other->loops, loop);
3873 ";; can't find suitable nesting for loops %d and %d\n",
3874 loop->loop_no, other->loop_no);
3875 loop->bad = other->bad = 1;
3879 BITMAP_FREE (tmp_bitmap);
3884 /* Free up the loop structures in LOOPS. */
3886 free_loops (loop_info loops)
3890 loop_info loop = loops;
3892 VEC_free (loop_info, heap, loop->loops);
3893 VEC_free (basic_block, heap, loop->blocks);
3894 BITMAP_FREE (loop->block_bitmap);
3899 #define BB_AUX_INDEX(BB) ((unsigned)(BB)->aux)
3901 /* The taken-branch edge from the loop end can actually go forward. Since the
3902 Blackfin's LSETUP instruction requires that the loop end be after the loop
3903 start, try to reorder a loop's basic blocks when we find such a case. */
3905 bfin_reorder_loops (loop_info loops, FILE *dump_file)
3912 cfg_layout_initialize (CLEANUP_UPDATE_LIFE);
3914 for (loop = loops; loop; loop = loop->next)
3924 /* Recreate an index for basic blocks that represents their order. */
3925 for (bb = ENTRY_BLOCK_PTR->next_bb, index = 0;
3926 bb != EXIT_BLOCK_PTR;
3927 bb = bb->next_bb, index++)
3928 bb->aux = (PTR) index;
3930 if (BB_AUX_INDEX (loop->head) < BB_AUX_INDEX (loop->tail))
3933 FOR_EACH_EDGE (e, ei, loop->head->succs)
3935 if (bitmap_bit_p (loop->block_bitmap, e->dest->index)
3936 && BB_AUX_INDEX (e->dest) < BB_AUX_INDEX (loop->tail))
3938 basic_block start_bb = e->dest;
3939 basic_block start_prev_bb = start_bb->prev_bb;
3942 fprintf (dump_file, ";; Moving block %d before block %d\n",
3943 loop->head->index, start_bb->index);
3944 loop->head->prev_bb->next_bb = loop->head->next_bb;
3945 loop->head->next_bb->prev_bb = loop->head->prev_bb;
3947 loop->head->prev_bb = start_prev_bb;
3948 loop->head->next_bb = start_bb;
3949 start_prev_bb->next_bb = start_bb->prev_bb = loop->head;
3953 loops = loops->next;
3958 if (bb->next_bb != EXIT_BLOCK_PTR)
3959 bb->aux = bb->next_bb;
3963 cfg_layout_finalize ();
3966 /* Run from machine_dependent_reorg, this pass looks for doloop_end insns
3967 and tries to rewrite the RTL of these loops so that proper Blackfin
3968 hardware loops are generated. */
3971 bfin_reorg_loops (FILE *dump_file)
3973 loop_info loops = NULL;
3976 bitmap_obstack stack;
3978 bitmap_obstack_initialize (&stack);
3981 fprintf (dump_file, ";; Find loops, first pass\n\n");
3983 loops = bfin_discover_loops (&stack, dump_file);
3986 bfin_dump_loops (loops);
3988 bfin_reorder_loops (loops, dump_file);
3992 fprintf (dump_file, ";; Find loops, second pass\n\n");
3994 loops = bfin_discover_loops (&stack, dump_file);
3997 fprintf (dump_file, ";; All loops found:\n\n");
3998 bfin_dump_loops (loops);
4001 /* Now apply the optimizations. */
4002 for (loop = loops; loop; loop = loop->next)
4003 bfin_optimize_loop (loop);
4007 fprintf (dump_file, ";; After hardware loops optimization:\n\n");
4008 bfin_dump_loops (loops);
4014 print_rtl (dump_file, get_insns ());
4020 /* Possibly generate a SEQUENCE out of three insns found in SLOT.
4021 Returns true if we modified the insn chain, false otherwise. */
4023 gen_one_bundle (rtx slot[3])
4027 gcc_assert (slot[1] != NULL_RTX);
4029 /* Verify that we really can do the multi-issue. */
4032 rtx t = NEXT_INSN (slot[0]);
4033 while (t != slot[1])
4035 if (GET_CODE (t) != NOTE
4036 || NOTE_LINE_NUMBER (t) != NOTE_INSN_DELETED)
4043 rtx t = NEXT_INSN (slot[1]);
4044 while (t != slot[2])
4046 if (GET_CODE (t) != NOTE
4047 || NOTE_LINE_NUMBER (t) != NOTE_INSN_DELETED)
4053 if (slot[0] == NULL_RTX)
4054 slot[0] = emit_insn_before (gen_mnop (), slot[1]);
4055 if (slot[2] == NULL_RTX)
4056 slot[2] = emit_insn_after (gen_nop (), slot[1]);
4058 /* Avoid line number information being printed inside one bundle. */
4059 if (INSN_LOCATOR (slot[1])
4060 && INSN_LOCATOR (slot[1]) != INSN_LOCATOR (slot[0]))
4061 INSN_LOCATOR (slot[1]) = INSN_LOCATOR (slot[0]);
4062 if (INSN_LOCATOR (slot[2])
4063 && INSN_LOCATOR (slot[2]) != INSN_LOCATOR (slot[0]))
4064 INSN_LOCATOR (slot[2]) = INSN_LOCATOR (slot[0]);
4066 /* Terminate them with "|| " instead of ";" in the output. */
4067 PUT_MODE (slot[0], SImode);
4068 PUT_MODE (slot[1], SImode);
4070 /* This is a cheat to avoid emit_insn's special handling of SEQUENCEs.
4071 Generating a PARALLEL first and changing its code later is the
4072 easiest way to emit a SEQUENCE insn. */
4073 bundle = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (3, slot[0], slot[1], slot[2]));
4074 emit_insn_before (bundle, slot[0]);
4075 remove_insn (slot[0]);
4076 remove_insn (slot[1]);
4077 remove_insn (slot[2]);
4078 PUT_CODE (bundle, SEQUENCE);
4083 /* Go through all insns, and use the information generated during scheduling
4084 to generate SEQUENCEs to represent bundles of instructions issued
4088 bfin_gen_bundles (void)
4097 slot[0] = slot[1] = slot[2] = NULL_RTX;
4098 for (insn = BB_HEAD (bb);; insn = next)
4103 if (get_attr_type (insn) == TYPE_DSP32)
4105 else if (slot[1] == NULL_RTX)
4112 next = NEXT_INSN (insn);
4113 while (next && insn != BB_END (bb)
4115 && GET_CODE (PATTERN (next)) != USE
4116 && GET_CODE (PATTERN (next)) != CLOBBER))
4119 next = NEXT_INSN (insn);
4122 /* BB_END can change due to emitting extra NOPs, so check here. */
4123 at_end = insn == BB_END (bb);
4124 if (at_end || GET_MODE (next) == TImode)
4127 || !gen_one_bundle (slot))
4128 && slot[0] != NULL_RTX)
4130 rtx pat = PATTERN (slot[0]);
4131 if (GET_CODE (pat) == SET
4132 && GET_CODE (SET_SRC (pat)) == UNSPEC
4133 && XINT (SET_SRC (pat), 1) == UNSPEC_32BIT)
4135 SET_SRC (pat) = XVECEXP (SET_SRC (pat), 0, 0);
4136 INSN_CODE (slot[0]) = -1;
4140 slot[0] = slot[1] = slot[2] = NULL_RTX;
4148 /* Return an insn type for INSN that can be used by the caller for anomaly
4149 workarounds. This differs from plain get_attr_type in that it handles
4152 static enum attr_type
4153 type_for_anomaly (rtx insn)
4155 rtx pat = PATTERN (insn);
4156 if (GET_CODE (pat) == SEQUENCE)
4159 t = get_attr_type (XVECEXP (pat, 0, 1));
4162 t = get_attr_type (XVECEXP (pat, 0, 2));
4168 return get_attr_type (insn);
4171 /* Return nonzero if INSN contains any loads that may trap. It handles
4172 SEQUENCEs correctly. */
4175 trapping_loads_p (rtx insn)
4177 rtx pat = PATTERN (insn);
4178 if (GET_CODE (pat) == SEQUENCE)
4181 t = get_attr_type (XVECEXP (pat, 0, 1));
4183 && may_trap_p (SET_SRC (PATTERN (XVECEXP (pat, 0, 1)))))
4185 t = get_attr_type (XVECEXP (pat, 0, 2));
4187 && may_trap_p (SET_SRC (PATTERN (XVECEXP (pat, 0, 2)))))
4192 return may_trap_p (SET_SRC (single_set (insn)));
4195 /* We use the machine specific reorg pass for emitting CSYNC instructions
4196 after conditional branches as needed.
4198 The Blackfin is unusual in that a code sequence like
4201 may speculatively perform the load even if the condition isn't true. This
4202 happens for a branch that is predicted not taken, because the pipeline
4203 isn't flushed or stalled, so the early stages of the following instructions,
4204 which perform the memory reference, are allowed to execute before the
4205 jump condition is evaluated.
4206 Therefore, we must insert additional instructions in all places where this
4207 could lead to incorrect behavior. The manual recommends CSYNC, while
4208 VDSP seems to use NOPs (even though its corresponding compiler option is
4211 When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
4212 When optimizing for size, we turn the branch into a predicted taken one.
4213 This may be slower due to mispredicts, but saves code size. */
4218 rtx insn, last_condjump = NULL_RTX;
4219 int cycles_since_jump = INT_MAX;
4221 /* We are freeing block_for_insn in the toplev to keep compatibility
4222 with old MDEP_REORGS that are not CFG based. Recompute it now. */
4223 compute_bb_for_insn ();
4225 if (bfin_flag_schedule_insns2)
4227 splitting_for_sched = 1;
4228 split_all_insns (0);
4229 splitting_for_sched = 0;
4231 update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES, PROP_DEATH_NOTES);
4233 timevar_push (TV_SCHED2);
4235 timevar_pop (TV_SCHED2);
4237 /* Examine the schedule and insert nops as necessary for 64-bit parallel
4239 bfin_gen_bundles ();
4242 /* Doloop optimization */
4243 if (cfun->machine->has_hardware_loops)
4244 bfin_reorg_loops (dump_file);
4246 if (! TARGET_SPECLD_ANOMALY && ! TARGET_CSYNC_ANOMALY)
4249 /* First pass: find predicted-false branches; if something after them
4250 needs nops, insert them or change the branch to predict true. */
4251 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4255 if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
4258 pat = PATTERN (insn);
4259 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4260 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
4261 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
4266 if (any_condjump_p (insn)
4267 && ! cbranch_predicted_taken_p (insn))
4269 last_condjump = insn;
4270 cycles_since_jump = 0;
4273 cycles_since_jump = INT_MAX;
4275 else if (INSN_P (insn))
4277 enum attr_type type = type_for_anomaly (insn);
4278 int delay_needed = 0;
4279 if (cycles_since_jump < INT_MAX)
4280 cycles_since_jump++;
4282 if (type == TYPE_MCLD && TARGET_SPECLD_ANOMALY)
4284 if (trapping_loads_p (insn))
4287 else if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
4290 if (delay_needed > cycles_since_jump)
4294 rtx *op = recog_data.operand;
4296 delay_needed -= cycles_since_jump;
4298 extract_insn (last_condjump);
4301 pat = gen_cbranch_predicted_taken (op[0], op[1], op[2],
4303 cycles_since_jump = INT_MAX;
4306 /* Do not adjust cycles_since_jump in this case, so that
4307 we'll increase the number of NOPs for a subsequent insn
4309 pat = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
4310 GEN_INT (delay_needed));
4311 PATTERN (last_condjump) = pat;
4312 INSN_CODE (last_condjump) = recog (pat, insn, &num_clobbers);
4316 /* Second pass: for predicted-true branches, see if anything at the
4317 branch destination needs extra nops. */
4318 if (! TARGET_CSYNC_ANOMALY)
4321 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4324 && any_condjump_p (insn)
4325 && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken
4326 || cbranch_predicted_taken_p (insn)))
4328 rtx target = JUMP_LABEL (insn);
4330 cycles_since_jump = 0;
4331 for (; target && cycles_since_jump < 3; target = NEXT_INSN (target))
4335 if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
4338 pat = PATTERN (target);
4339 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4340 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
4341 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
4344 if (INSN_P (target))
4346 enum attr_type type = type_for_anomaly (target);
4347 int delay_needed = 0;
4348 if (cycles_since_jump < INT_MAX)
4349 cycles_since_jump++;
4351 if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
4354 if (delay_needed > cycles_since_jump)
4356 rtx prev = prev_real_insn (label);
4357 delay_needed -= cycles_since_jump;
4359 fprintf (dump_file, "Adding %d nops after %d\n",
4360 delay_needed, INSN_UID (label));
4362 && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops)
4369 "Reducing nops on insn %d.\n",
4372 x = XVECEXP (x, 0, 1);
4373 v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed;
4374 XVECEXP (x, 0, 0) = GEN_INT (v);
4376 while (delay_needed-- > 0)
4377 emit_insn_after (gen_nop (), label);
4385 if (bfin_flag_var_tracking)
4387 timevar_push (TV_VAR_TRACKING);
4388 variable_tracking_main ();
4389 timevar_pop (TV_VAR_TRACKING);
4393 /* Handle interrupt_handler, exception_handler and nmi_handler function
4394 attributes; arguments as in struct attribute_spec.handler. */
4397 handle_int_attribute (tree *node, tree name,
4398 tree args ATTRIBUTE_UNUSED,
4399 int flags ATTRIBUTE_UNUSED,
4403 if (TREE_CODE (x) == FUNCTION_DECL)
4406 if (TREE_CODE (x) != FUNCTION_TYPE)
4408 warning (OPT_Wattributes, "%qs attribute only applies to functions",
4409 IDENTIFIER_POINTER (name));
4410 *no_add_attrs = true;
4412 else if (funkind (x) != SUBROUTINE)
4413 error ("multiple function type attributes specified");
4418 /* Return 0 if the attributes for two types are incompatible, 1 if they
4419 are compatible, and 2 if they are nearly compatible (which causes a
4420 warning to be generated). */
4423 bfin_comp_type_attributes (tree type1, tree type2)
4425 e_funkind kind1, kind2;
4427 if (TREE_CODE (type1) != FUNCTION_TYPE)
4430 kind1 = funkind (type1);
4431 kind2 = funkind (type2);
4436 /* Check for mismatched modifiers */
4437 if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
4438 != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
4441 if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
4442 != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
4445 if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
4446 != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
4449 if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1))
4450 != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2)))
4456 /* Handle a "longcall" or "shortcall" attribute; arguments as in
4457 struct attribute_spec.handler. */
4460 bfin_handle_longcall_attribute (tree *node, tree name,
4461 tree args ATTRIBUTE_UNUSED,
4462 int flags ATTRIBUTE_UNUSED,
4465 if (TREE_CODE (*node) != FUNCTION_TYPE
4466 && TREE_CODE (*node) != FIELD_DECL
4467 && TREE_CODE (*node) != TYPE_DECL)
4469 warning (OPT_Wattributes, "`%s' attribute only applies to functions",
4470 IDENTIFIER_POINTER (name));
4471 *no_add_attrs = true;
4474 if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0
4475 && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node)))
4476 || (strcmp (IDENTIFIER_POINTER (name), "shortcall") == 0
4477 && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node))))
4479 warning (OPT_Wattributes,
4480 "can't apply both longcall and shortcall attributes to the same function");
4481 *no_add_attrs = true;
4487 /* Table of valid machine attributes. */
4488 const struct attribute_spec bfin_attribute_table[] =
4490 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4491 { "interrupt_handler", 0, 0, false, true, true, handle_int_attribute },
4492 { "exception_handler", 0, 0, false, true, true, handle_int_attribute },
4493 { "nmi_handler", 0, 0, false, true, true, handle_int_attribute },
4494 { "nesting", 0, 0, false, true, true, NULL },
4495 { "kspisusp", 0, 0, false, true, true, NULL },
4496 { "saveall", 0, 0, false, true, true, NULL },
4497 { "longcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
4498 { "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
4499 { NULL, 0, 0, false, false, false, NULL }
4502 /* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to
4503 tell the assembler to generate pointers to function descriptors in
4507 bfin_assemble_integer (rtx value, unsigned int size, int aligned_p)
4509 if (TARGET_FDPIC && size == UNITS_PER_WORD)
4511 if (GET_CODE (value) == SYMBOL_REF
4512 && SYMBOL_REF_FUNCTION_P (value))
4514 fputs ("\t.picptr\tfuncdesc(", asm_out_file);
4515 output_addr_const (asm_out_file, value);
4516 fputs (")\n", asm_out_file);
4521 /* We've set the unaligned SI op to NULL, so we always have to
4522 handle the unaligned case here. */
4523 assemble_integer_with_op ("\t.4byte\t", value);
4527 return default_assemble_integer (value, size, aligned_p);
4530 /* Output the assembler code for a thunk function. THUNK_DECL is the
4531 declaration for the thunk function itself, FUNCTION is the decl for
4532 the target function. DELTA is an immediate constant offset to be
4533 added to THIS. If VCALL_OFFSET is nonzero, the word at
4534 *(*this + vcall_offset) should be added to THIS. */
4537 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
4538 tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
4539 HOST_WIDE_INT vcall_offset, tree function)
4542 /* The this parameter is passed as the first argument. */
4543 rtx this = gen_rtx_REG (Pmode, REG_R0);
4545 /* Adjust the this parameter by a fixed constant. */
4549 if (delta >= -64 && delta <= 63)
4551 xops[0] = GEN_INT (delta);
4552 output_asm_insn ("%1 += %0;", xops);
4554 else if (delta >= -128 && delta < -64)
4556 xops[0] = GEN_INT (delta + 64);
4557 output_asm_insn ("%1 += -64; %1 += %0;", xops);
4559 else if (delta > 63 && delta <= 126)
4561 xops[0] = GEN_INT (delta - 63);
4562 output_asm_insn ("%1 += 63; %1 += %0;", xops);
4566 xops[0] = GEN_INT (delta);
4567 output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
4571 /* Adjust the this parameter by a value stored in the vtable. */
4574 rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
4575 rtx tmp = gen_rtx_REG (Pmode, REG_R3);
4579 output_asm_insn ("%2 = r0; %2 = [%2];", xops);
4581 /* Adjust the this parameter. */
4582 xops[0] = gen_rtx_MEM (Pmode, plus_constant (p2tmp, vcall_offset));
4583 if (!memory_operand (xops[0], Pmode))
4585 rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
4586 xops[0] = GEN_INT (vcall_offset);
4588 output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
4589 xops[0] = gen_rtx_MEM (Pmode, p2tmp);
4592 output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
4595 xops[0] = XEXP (DECL_RTL (function), 0);
4596 if (1 || !flag_pic || (*targetm.binds_local_p) (function))
4597 output_asm_insn ("jump.l\t%P0", xops);
4600 /* Codes for all the Blackfin builtins. */
4605 BFIN_BUILTIN_COMPOSE_2X16,
4606 BFIN_BUILTIN_EXTRACTLO,
4607 BFIN_BUILTIN_EXTRACTHI,
4609 BFIN_BUILTIN_SSADD_2X16,
4610 BFIN_BUILTIN_SSSUB_2X16,
4611 BFIN_BUILTIN_SSADDSUB_2X16,
4612 BFIN_BUILTIN_SSSUBADD_2X16,
4613 BFIN_BUILTIN_MULT_2X16,
4614 BFIN_BUILTIN_MULTR_2X16,
4615 BFIN_BUILTIN_NEG_2X16,
4616 BFIN_BUILTIN_ABS_2X16,
4617 BFIN_BUILTIN_MIN_2X16,
4618 BFIN_BUILTIN_MAX_2X16,
4620 BFIN_BUILTIN_SSADD_1X16,
4621 BFIN_BUILTIN_SSSUB_1X16,
4622 BFIN_BUILTIN_MULT_1X16,
4623 BFIN_BUILTIN_MULTR_1X16,
4624 BFIN_BUILTIN_NORM_1X16,
4625 BFIN_BUILTIN_NEG_1X16,
4626 BFIN_BUILTIN_ABS_1X16,
4627 BFIN_BUILTIN_MIN_1X16,
4628 BFIN_BUILTIN_MAX_1X16,
4630 BFIN_BUILTIN_DIFFHL_2X16,
4631 BFIN_BUILTIN_DIFFLH_2X16,
4633 BFIN_BUILTIN_SSADD_1X32,
4634 BFIN_BUILTIN_SSSUB_1X32,
4635 BFIN_BUILTIN_NORM_1X32,
4636 BFIN_BUILTIN_NEG_1X32,
4637 BFIN_BUILTIN_MIN_1X32,
4638 BFIN_BUILTIN_MAX_1X32,
4639 BFIN_BUILTIN_MULT_1X32,
4641 BFIN_BUILTIN_MULHISILL,
4642 BFIN_BUILTIN_MULHISILH,
4643 BFIN_BUILTIN_MULHISIHL,
4644 BFIN_BUILTIN_MULHISIHH,
4646 BFIN_BUILTIN_LSHIFT_1X16,
4647 BFIN_BUILTIN_LSHIFT_2X16,
4648 BFIN_BUILTIN_SSASHIFT_1X16,
4649 BFIN_BUILTIN_SSASHIFT_2X16,
4651 BFIN_BUILTIN_CPLX_MUL_16,
4652 BFIN_BUILTIN_CPLX_MAC_16,
4653 BFIN_BUILTIN_CPLX_MSU_16,
4658 #define def_builtin(NAME, TYPE, CODE) \
4660 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
4664 /* Set up all builtin functions for this target. */
4666 bfin_init_builtins (void)
4668 tree V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
4669 tree void_ftype_void
4670 = build_function_type (void_type_node, void_list_node);
4671 tree short_ftype_short
4672 = build_function_type_list (short_integer_type_node, short_integer_type_node,
4674 tree short_ftype_int_int
4675 = build_function_type_list (short_integer_type_node, integer_type_node,
4676 integer_type_node, NULL_TREE);
4677 tree int_ftype_int_int
4678 = build_function_type_list (integer_type_node, integer_type_node,
4679 integer_type_node, NULL_TREE);
4681 = build_function_type_list (integer_type_node, integer_type_node,
4683 tree short_ftype_int
4684 = build_function_type_list (short_integer_type_node, integer_type_node,
4686 tree int_ftype_v2hi_v2hi
4687 = build_function_type_list (integer_type_node, V2HI_type_node,
4688 V2HI_type_node, NULL_TREE);
4689 tree v2hi_ftype_v2hi_v2hi
4690 = build_function_type_list (V2HI_type_node, V2HI_type_node,
4691 V2HI_type_node, NULL_TREE);
4692 tree v2hi_ftype_v2hi_v2hi_v2hi
4693 = build_function_type_list (V2HI_type_node, V2HI_type_node,
4694 V2HI_type_node, V2HI_type_node, NULL_TREE);
4695 tree v2hi_ftype_int_int
4696 = build_function_type_list (V2HI_type_node, integer_type_node,
4697 integer_type_node, NULL_TREE);
4698 tree v2hi_ftype_v2hi_int
4699 = build_function_type_list (V2HI_type_node, V2HI_type_node,
4700 integer_type_node, NULL_TREE);
4701 tree int_ftype_short_short
4702 = build_function_type_list (integer_type_node, short_integer_type_node,
4703 short_integer_type_node, NULL_TREE);
4704 tree v2hi_ftype_v2hi
4705 = build_function_type_list (V2HI_type_node, V2HI_type_node, NULL_TREE);
4706 tree short_ftype_v2hi
4707 = build_function_type_list (short_integer_type_node, V2HI_type_node,
4710 /* Add the remaining MMX insns with somewhat more complicated types. */
4711 def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC);
4712 def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC);
4714 def_builtin ("__builtin_bfin_compose_2x16", v2hi_ftype_int_int,
4715 BFIN_BUILTIN_COMPOSE_2X16);
4716 def_builtin ("__builtin_bfin_extract_hi", short_ftype_v2hi,
4717 BFIN_BUILTIN_EXTRACTHI);
4718 def_builtin ("__builtin_bfin_extract_lo", short_ftype_v2hi,
4719 BFIN_BUILTIN_EXTRACTLO);
4721 def_builtin ("__builtin_bfin_min_fr2x16", v2hi_ftype_v2hi_v2hi,
4722 BFIN_BUILTIN_MIN_2X16);
4723 def_builtin ("__builtin_bfin_max_fr2x16", v2hi_ftype_v2hi_v2hi,
4724 BFIN_BUILTIN_MAX_2X16);
4726 def_builtin ("__builtin_bfin_add_fr2x16", v2hi_ftype_v2hi_v2hi,
4727 BFIN_BUILTIN_SSADD_2X16);
4728 def_builtin ("__builtin_bfin_sub_fr2x16", v2hi_ftype_v2hi_v2hi,
4729 BFIN_BUILTIN_SSSUB_2X16);
4730 def_builtin ("__builtin_bfin_dspaddsubsat", v2hi_ftype_v2hi_v2hi,
4731 BFIN_BUILTIN_SSADDSUB_2X16);
4732 def_builtin ("__builtin_bfin_dspsubaddsat", v2hi_ftype_v2hi_v2hi,
4733 BFIN_BUILTIN_SSSUBADD_2X16);
4734 def_builtin ("__builtin_bfin_mult_fr2x16", v2hi_ftype_v2hi_v2hi,
4735 BFIN_BUILTIN_MULT_2X16);
4736 def_builtin ("__builtin_bfin_multr_fr2x16", v2hi_ftype_v2hi_v2hi,
4737 BFIN_BUILTIN_MULTR_2X16);
4738 def_builtin ("__builtin_bfin_negate_fr2x16", v2hi_ftype_v2hi,
4739 BFIN_BUILTIN_NEG_2X16);
4740 def_builtin ("__builtin_bfin_abs_fr2x16", v2hi_ftype_v2hi,
4741 BFIN_BUILTIN_ABS_2X16);
4743 def_builtin ("__builtin_bfin_add_fr1x16", short_ftype_int_int,
4744 BFIN_BUILTIN_SSADD_1X16);
4745 def_builtin ("__builtin_bfin_sub_fr1x16", short_ftype_int_int,
4746 BFIN_BUILTIN_SSSUB_1X16);
4747 def_builtin ("__builtin_bfin_mult_fr1x16", short_ftype_int_int,
4748 BFIN_BUILTIN_MULT_1X16);
4749 def_builtin ("__builtin_bfin_multr_fr1x16", short_ftype_int_int,
4750 BFIN_BUILTIN_MULTR_1X16);
4751 def_builtin ("__builtin_bfin_negate_fr1x16", short_ftype_short,
4752 BFIN_BUILTIN_NEG_1X16);
4753 def_builtin ("__builtin_bfin_abs_fr1x16", short_ftype_short,
4754 BFIN_BUILTIN_ABS_1X16);
4755 def_builtin ("__builtin_bfin_norm_fr1x16", short_ftype_int,
4756 BFIN_BUILTIN_NORM_1X16);
4758 def_builtin ("__builtin_bfin_diff_hl_fr2x16", short_ftype_v2hi,
4759 BFIN_BUILTIN_DIFFHL_2X16);
4760 def_builtin ("__builtin_bfin_diff_lh_fr2x16", short_ftype_v2hi,
4761 BFIN_BUILTIN_DIFFLH_2X16);
4763 def_builtin ("__builtin_bfin_mulhisill", int_ftype_v2hi_v2hi,
4764 BFIN_BUILTIN_MULHISILL);
4765 def_builtin ("__builtin_bfin_mulhisihl", int_ftype_v2hi_v2hi,
4766 BFIN_BUILTIN_MULHISIHL);
4767 def_builtin ("__builtin_bfin_mulhisilh", int_ftype_v2hi_v2hi,
4768 BFIN_BUILTIN_MULHISILH);
4769 def_builtin ("__builtin_bfin_mulhisihh", int_ftype_v2hi_v2hi,
4770 BFIN_BUILTIN_MULHISIHH);
4772 def_builtin ("__builtin_bfin_add_fr1x32", int_ftype_int_int,
4773 BFIN_BUILTIN_SSADD_1X32);
4774 def_builtin ("__builtin_bfin_sub_fr1x32", int_ftype_int_int,
4775 BFIN_BUILTIN_SSSUB_1X32);
4776 def_builtin ("__builtin_bfin_negate_fr1x32", int_ftype_int,
4777 BFIN_BUILTIN_NEG_1X32);
4778 def_builtin ("__builtin_bfin_norm_fr1x32", short_ftype_int,
4779 BFIN_BUILTIN_NORM_1X32);
4780 def_builtin ("__builtin_bfin_mult_fr1x32", int_ftype_short_short,
4781 BFIN_BUILTIN_MULT_1X32);
4784 def_builtin ("__builtin_bfin_shl_fr1x16", short_ftype_int_int,
4785 BFIN_BUILTIN_SSASHIFT_1X16);
4786 def_builtin ("__builtin_bfin_shl_fr2x16", v2hi_ftype_v2hi_int,
4787 BFIN_BUILTIN_SSASHIFT_2X16);
4788 def_builtin ("__builtin_bfin_lshl_fr1x16", short_ftype_int_int,
4789 BFIN_BUILTIN_LSHIFT_1X16);
4790 def_builtin ("__builtin_bfin_lshl_fr2x16", v2hi_ftype_v2hi_int,
4791 BFIN_BUILTIN_LSHIFT_2X16);
4793 /* Complex numbers. */
4794 def_builtin ("__builtin_bfin_cmplx_mul", v2hi_ftype_v2hi_v2hi,
4795 BFIN_BUILTIN_CPLX_MUL_16);
4796 def_builtin ("__builtin_bfin_cmplx_mac", v2hi_ftype_v2hi_v2hi_v2hi,
4797 BFIN_BUILTIN_CPLX_MAC_16);
4798 def_builtin ("__builtin_bfin_cmplx_msu", v2hi_ftype_v2hi_v2hi_v2hi,
4799 BFIN_BUILTIN_CPLX_MSU_16);
4803 struct builtin_description
4805 const enum insn_code icode;
4806 const char *const name;
4807 const enum bfin_builtins code;
4811 static const struct builtin_description bdesc_2arg[] =
4813 { CODE_FOR_composev2hi, "__builtin_bfin_compose_2x16", BFIN_BUILTIN_COMPOSE_2X16, -1 },
4815 { CODE_FOR_ssashiftv2hi3, "__builtin_bfin_shl_fr2x16", BFIN_BUILTIN_SSASHIFT_2X16, -1 },
4816 { CODE_FOR_ssashifthi3, "__builtin_bfin_shl_fr1x16", BFIN_BUILTIN_SSASHIFT_1X16, -1 },
4817 { CODE_FOR_lshiftv2hi3, "__builtin_bfin_lshl_fr2x16", BFIN_BUILTIN_LSHIFT_2X16, -1 },
4818 { CODE_FOR_lshifthi3, "__builtin_bfin_lshl_fr1x16", BFIN_BUILTIN_LSHIFT_1X16, -1 },
4820 { CODE_FOR_sminhi3, "__builtin_bfin_min_fr1x16", BFIN_BUILTIN_MIN_1X16, -1 },
4821 { CODE_FOR_smaxhi3, "__builtin_bfin_max_fr1x16", BFIN_BUILTIN_MAX_1X16, -1 },
4822 { CODE_FOR_ssaddhi3, "__builtin_bfin_add_fr1x16", BFIN_BUILTIN_SSADD_1X16, -1 },
4823 { CODE_FOR_sssubhi3, "__builtin_bfin_sub_fr1x16", BFIN_BUILTIN_SSSUB_1X16, -1 },
4825 { CODE_FOR_sminsi3, "__builtin_bfin_min_fr1x32", BFIN_BUILTIN_MIN_1X32, -1 },
4826 { CODE_FOR_smaxsi3, "__builtin_bfin_max_fr1x32", BFIN_BUILTIN_MAX_1X32, -1 },
4827 { CODE_FOR_ssaddsi3, "__builtin_bfin_add_fr1x32", BFIN_BUILTIN_SSADD_1X32, -1 },
4828 { CODE_FOR_sssubsi3, "__builtin_bfin_sub_fr1x32", BFIN_BUILTIN_SSSUB_1X32, -1 },
4830 { CODE_FOR_sminv2hi3, "__builtin_bfin_min_fr2x16", BFIN_BUILTIN_MIN_2X16, -1 },
4831 { CODE_FOR_smaxv2hi3, "__builtin_bfin_max_fr2x16", BFIN_BUILTIN_MAX_2X16, -1 },
4832 { CODE_FOR_ssaddv2hi3, "__builtin_bfin_add_fr2x16", BFIN_BUILTIN_SSADD_2X16, -1 },
4833 { CODE_FOR_sssubv2hi3, "__builtin_bfin_sub_fr2x16", BFIN_BUILTIN_SSSUB_2X16, -1 },
4834 { CODE_FOR_ssaddsubv2hi3, "__builtin_bfin_dspaddsubsat", BFIN_BUILTIN_SSADDSUB_2X16, -1 },
4835 { CODE_FOR_sssubaddv2hi3, "__builtin_bfin_dspsubaddsat", BFIN_BUILTIN_SSSUBADD_2X16, -1 },
4837 { CODE_FOR_flag_mulhisi, "__builtin_bfin_mult_fr1x32", BFIN_BUILTIN_MULT_1X32, MACFLAG_NONE },
4838 { CODE_FOR_flag_mulhi, "__builtin_bfin_mult_fr1x16", BFIN_BUILTIN_MULT_1X16, MACFLAG_T },
4839 { CODE_FOR_flag_mulhi, "__builtin_bfin_multr_fr1x16", BFIN_BUILTIN_MULTR_1X16, MACFLAG_NONE },
4840 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_mult_fr2x16", BFIN_BUILTIN_MULT_2X16, MACFLAG_T },
4841 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_multr_fr2x16", BFIN_BUILTIN_MULTR_2X16, MACFLAG_NONE }
4844 static const struct builtin_description bdesc_1arg[] =
4846 { CODE_FOR_signbitshi2, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16, 0 },
4847 { CODE_FOR_ssneghi2, "__builtin_bfin_negate_fr1x16", BFIN_BUILTIN_NEG_1X16, 0 },
4848 { CODE_FOR_abshi2, "__builtin_bfin_abs_fr1x16", BFIN_BUILTIN_ABS_1X16, 0 },
4850 { CODE_FOR_signbitssi2, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32, 0 },
4851 { CODE_FOR_ssnegsi2, "__builtin_bfin_negate_fr1x32", BFIN_BUILTIN_NEG_1X32, 0 },
4853 { CODE_FOR_movv2hi_hi_low, "__builtin_bfin_extract_lo", BFIN_BUILTIN_EXTRACTLO, 0 },
4854 { CODE_FOR_movv2hi_hi_high, "__builtin_bfin_extract_hi", BFIN_BUILTIN_EXTRACTHI, 0 },
4855 { CODE_FOR_ssnegv2hi2, "__builtin_bfin_negate_fr2x16", BFIN_BUILTIN_NEG_2X16, 0 },
4856 { CODE_FOR_absv2hi2, "__builtin_bfin_abs_fr2x16", BFIN_BUILTIN_ABS_2X16, 0 }
4859 /* Errors in the source file can cause expand_expr to return const0_rtx
4860 where we expect a vector. To avoid crashing, use one of the vector
4861 clear instructions. */
4863 safe_vector_operand (rtx x, enum machine_mode mode)
4865 if (x != const0_rtx)
4867 x = gen_reg_rtx (SImode);
4869 emit_insn (gen_movsi (x, CONST0_RTX (SImode)));
4870 return gen_lowpart (mode, x);
4873 /* Subroutine of bfin_expand_builtin to take care of binop insns. MACFLAG is -1
4874 if this is a normal binary op, or one of the MACFLAG_xxx constants. */
4877 bfin_expand_binop_builtin (enum insn_code icode, tree exp, rtx target,
4881 tree arg0 = CALL_EXPR_ARG (exp, 0);
4882 tree arg1 = CALL_EXPR_ARG (exp, 1);
4883 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4884 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
4885 enum machine_mode op0mode = GET_MODE (op0);
4886 enum machine_mode op1mode = GET_MODE (op1);
4887 enum machine_mode tmode = insn_data[icode].operand[0].mode;
4888 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
4889 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
4891 if (VECTOR_MODE_P (mode0))
4892 op0 = safe_vector_operand (op0, mode0);
4893 if (VECTOR_MODE_P (mode1))
4894 op1 = safe_vector_operand (op1, mode1);
4897 || GET_MODE (target) != tmode
4898 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
4899 target = gen_reg_rtx (tmode);
4901 if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode)
4904 op0 = gen_lowpart (HImode, op0);
4906 if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode)
4909 op1 = gen_lowpart (HImode, op1);
4911 /* In case the insn wants input operands in modes different from
4912 the result, abort. */
4913 gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
4914 && (op1mode == mode1 || op1mode == VOIDmode));
4916 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
4917 op0 = copy_to_mode_reg (mode0, op0);
4918 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
4919 op1 = copy_to_mode_reg (mode1, op1);
4922 pat = GEN_FCN (icode) (target, op0, op1);
4924 pat = GEN_FCN (icode) (target, op0, op1, GEN_INT (macflag));
4932 /* Subroutine of bfin_expand_builtin to take care of unop insns. */
4935 bfin_expand_unop_builtin (enum insn_code icode, tree exp,
4939 tree arg0 = CALL_EXPR_ARG (exp, 0);
4940 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4941 enum machine_mode op0mode = GET_MODE (op0);
4942 enum machine_mode tmode = insn_data[icode].operand[0].mode;
4943 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
4946 || GET_MODE (target) != tmode
4947 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
4948 target = gen_reg_rtx (tmode);
4950 if (VECTOR_MODE_P (mode0))
4951 op0 = safe_vector_operand (op0, mode0);
4953 if (op0mode == SImode && mode0 == HImode)
4956 op0 = gen_lowpart (HImode, op0);
4958 gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
4960 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
4961 op0 = copy_to_mode_reg (mode0, op0);
4963 pat = GEN_FCN (icode) (target, op0);
4970 /* Expand an expression EXP that calls a built-in function,
4971 with result going to TARGET if that's convenient
4972 (and in mode MODE if that's convenient).
4973 SUBTARGET may be used as the target for computing one of EXP's operands.
4974 IGNORE is nonzero if the value is to be ignored. */
4977 bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
4978 rtx subtarget ATTRIBUTE_UNUSED,
4979 enum machine_mode mode ATTRIBUTE_UNUSED,
4980 int ignore ATTRIBUTE_UNUSED)
4983 enum insn_code icode;
4984 const struct builtin_description *d;
4985 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
4986 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
4987 tree arg0, arg1, arg2;
4988 rtx op0, op1, op2, accvec, pat, tmp1, tmp2;
4989 enum machine_mode tmode, mode0;
4993 case BFIN_BUILTIN_CSYNC:
4994 emit_insn (gen_csync ());
4996 case BFIN_BUILTIN_SSYNC:
4997 emit_insn (gen_ssync ());
5000 case BFIN_BUILTIN_DIFFHL_2X16:
5001 case BFIN_BUILTIN_DIFFLH_2X16:
5002 arg0 = CALL_EXPR_ARG (exp, 0);
5003 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5004 icode = (fcode == BFIN_BUILTIN_DIFFHL_2X16
5005 ? CODE_FOR_subhilov2hi3 : CODE_FOR_sublohiv2hi3);
5006 tmode = insn_data[icode].operand[0].mode;
5007 mode0 = insn_data[icode].operand[1].mode;
5010 || GET_MODE (target) != tmode
5011 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5012 target = gen_reg_rtx (tmode);
5014 if (VECTOR_MODE_P (mode0))
5015 op0 = safe_vector_operand (op0, mode0);
5017 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5018 op0 = copy_to_mode_reg (mode0, op0);
5020 pat = GEN_FCN (icode) (target, op0, op0);
5026 case BFIN_BUILTIN_CPLX_MUL_16:
5027 arg0 = CALL_EXPR_ARG (exp, 0);
5028 arg1 = CALL_EXPR_ARG (exp, 1);
5029 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5030 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
5031 accvec = gen_reg_rtx (V2PDImode);
5034 || GET_MODE (target) != V2HImode
5035 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5036 target = gen_reg_rtx (tmode);
5037 if (! register_operand (op0, GET_MODE (op0)))
5038 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
5039 if (! register_operand (op1, GET_MODE (op1)))
5040 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
5042 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
5043 const0_rtx, const0_rtx,
5044 const1_rtx, GEN_INT (MACFLAG_NONE)));
5045 emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
5046 const1_rtx, const1_rtx,
5047 const0_rtx, accvec, const1_rtx, const0_rtx,
5048 GEN_INT (MACFLAG_NONE), accvec));
5052 case BFIN_BUILTIN_CPLX_MAC_16:
5053 case BFIN_BUILTIN_CPLX_MSU_16:
5054 arg0 = CALL_EXPR_ARG (exp, 0);
5055 arg1 = CALL_EXPR_ARG (exp, 1);
5056 arg2 = CALL_EXPR_ARG (exp, 2);
5057 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5058 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
5059 op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
5060 accvec = gen_reg_rtx (V2PDImode);
5063 || GET_MODE (target) != V2HImode
5064 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5065 target = gen_reg_rtx (tmode);
5066 if (! register_operand (op0, GET_MODE (op0)))
5067 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
5068 if (! register_operand (op1, GET_MODE (op1)))
5069 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
5071 tmp1 = gen_reg_rtx (SImode);
5072 tmp2 = gen_reg_rtx (SImode);
5073 emit_insn (gen_ashlsi3 (tmp1, gen_lowpart (SImode, op2), GEN_INT (16)));
5074 emit_move_insn (tmp2, gen_lowpart (SImode, op2));
5075 emit_insn (gen_movstricthi_1 (gen_lowpart (HImode, tmp2), const0_rtx));
5076 emit_insn (gen_load_accumulator_pair (accvec, tmp1, tmp2));
5077 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op0, op1, const0_rtx,
5078 const0_rtx, const0_rtx,
5079 const1_rtx, accvec, const0_rtx,
5081 GEN_INT (MACFLAG_W32)));
5082 tmp1 = (fcode == BFIN_BUILTIN_CPLX_MAC_16 ? const1_rtx : const0_rtx);
5083 tmp2 = (fcode == BFIN_BUILTIN_CPLX_MAC_16 ? const0_rtx : const1_rtx);
5084 emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
5085 const1_rtx, const1_rtx,
5086 const0_rtx, accvec, tmp1, tmp2,
5087 GEN_INT (MACFLAG_NONE), accvec));
5095 for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
5096 if (d->code == fcode)
5097 return bfin_expand_binop_builtin (d->icode, exp, target,
5100 for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
5101 if (d->code == fcode)
5102 return bfin_expand_unop_builtin (d->icode, exp, target);
5107 #undef TARGET_INIT_BUILTINS
5108 #define TARGET_INIT_BUILTINS bfin_init_builtins
5110 #undef TARGET_EXPAND_BUILTIN
5111 #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
5113 #undef TARGET_ASM_GLOBALIZE_LABEL
5114 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label
5116 #undef TARGET_ASM_FILE_START
5117 #define TARGET_ASM_FILE_START output_file_start
5119 #undef TARGET_ATTRIBUTE_TABLE
5120 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
5122 #undef TARGET_COMP_TYPE_ATTRIBUTES
5123 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
5125 #undef TARGET_RTX_COSTS
5126 #define TARGET_RTX_COSTS bfin_rtx_costs
5128 #undef TARGET_ADDRESS_COST
5129 #define TARGET_ADDRESS_COST bfin_address_cost
5131 #undef TARGET_ASM_INTERNAL_LABEL
5132 #define TARGET_ASM_INTERNAL_LABEL bfin_internal_label
5134 #undef TARGET_ASM_INTEGER
5135 #define TARGET_ASM_INTEGER bfin_assemble_integer
5137 #undef TARGET_MACHINE_DEPENDENT_REORG
5138 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
5140 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
5141 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
5143 #undef TARGET_ASM_OUTPUT_MI_THUNK
5144 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
5145 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
5146 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
5148 #undef TARGET_SCHED_ADJUST_COST
5149 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
5151 #undef TARGET_SCHED_ISSUE_RATE
5152 #define TARGET_SCHED_ISSUE_RATE bfin_issue_rate
5154 #undef TARGET_PROMOTE_PROTOTYPES
5155 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
5156 #undef TARGET_PROMOTE_FUNCTION_ARGS
5157 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
5158 #undef TARGET_PROMOTE_FUNCTION_RETURN
5159 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
5161 #undef TARGET_ARG_PARTIAL_BYTES
5162 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
5164 #undef TARGET_PASS_BY_REFERENCE
5165 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
5167 #undef TARGET_SETUP_INCOMING_VARARGS
5168 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
5170 #undef TARGET_STRUCT_VALUE_RTX
5171 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
5173 #undef TARGET_VECTOR_MODE_SUPPORTED_P
5174 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
5176 #undef TARGET_HANDLE_OPTION
5177 #define TARGET_HANDLE_OPTION bfin_handle_option
5179 #undef TARGET_DEFAULT_TARGET_FLAGS
5180 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
5182 #undef TARGET_SECONDARY_RELOAD
5183 #define TARGET_SECONDARY_RELOAD bfin_secondary_reload
5185 #undef TARGET_DELEGITIMIZE_ADDRESS
5186 #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address
5188 #undef TARGET_CANNOT_FORCE_CONST_MEM
5189 #define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem
5191 struct gcc_target targetm = TARGET_INITIALIZER;