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"
47 #include "integrate.h"
49 #include "langhooks.h"
50 #include "bfin-protos.h"
54 /* Test and compare insns in bfin.md store the information needed to
55 generate branch and scc insns here. */
56 rtx bfin_compare_op0, bfin_compare_op1;
58 /* RTX for condition code flag register and RETS register */
59 extern GTY(()) rtx bfin_cc_rtx;
60 extern GTY(()) rtx bfin_rets_rtx;
61 rtx bfin_cc_rtx, bfin_rets_rtx;
63 int max_arg_registers = 0;
65 /* Arrays used when emitting register names. */
66 const char *short_reg_names[] = SHORT_REGISTER_NAMES;
67 const char *high_reg_names[] = HIGH_REGISTER_NAMES;
68 const char *dregs_pair_names[] = DREGS_PAIR_NAMES;
69 const char *byte_reg_names[] = BYTE_REGISTER_NAMES;
71 static int arg_regs[] = FUNCTION_ARG_REGISTERS;
73 /* Nonzero if -mshared-library-id was given. */
74 static int bfin_lib_id_given;
77 bfin_globalize_label (FILE *stream, const char *name)
79 fputs (".global ", stream);
80 assemble_name (stream, name);
86 output_file_start (void)
88 FILE *file = asm_out_file;
91 fprintf (file, ".file \"%s\";\n", input_filename);
93 for (i = 0; arg_regs[i] >= 0; i++)
95 max_arg_registers = i; /* how many arg reg used */
98 /* Called early in the compilation to conditionally modify
99 fixed_regs/call_used_regs. */
102 conditional_register_usage (void)
104 /* initialize condition code flag register rtx */
105 bfin_cc_rtx = gen_rtx_REG (BImode, REG_CC);
106 bfin_rets_rtx = gen_rtx_REG (Pmode, REG_RETS);
109 /* Examine machine-dependent attributes of function type FUNTYPE and return its
110 type. See the definition of E_FUNKIND. */
112 static e_funkind funkind (tree funtype)
114 tree attrs = TYPE_ATTRIBUTES (funtype);
115 if (lookup_attribute ("interrupt_handler", attrs))
116 return INTERRUPT_HANDLER;
117 else if (lookup_attribute ("exception_handler", attrs))
118 return EXCPT_HANDLER;
119 else if (lookup_attribute ("nmi_handler", attrs))
125 /* Legitimize PIC addresses. If the address is already position-independent,
126 we return ORIG. Newly generated position-independent addresses go into a
127 reg. This is REG if nonzero, otherwise we allocate register(s) as
128 necessary. PICREG is the register holding the pointer to the PIC offset
132 legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
137 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
139 if (GET_CODE (addr) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (addr))
145 gcc_assert (!no_new_pseudos);
146 reg = gen_reg_rtx (Pmode);
151 emit_insn (gen_movsi_high_pic (reg, addr));
152 emit_insn (gen_movsi_low_pic (reg, reg, addr));
153 emit_insn (gen_addsi3 (reg, reg, picreg));
154 new = gen_const_mem (Pmode, reg);
158 rtx tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
160 new = gen_const_mem (Pmode,
161 gen_rtx_PLUS (Pmode, picreg, tmp));
163 emit_move_insn (reg, new);
165 if (picreg == pic_offset_table_rtx)
166 current_function_uses_pic_offset_table = 1;
170 else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
174 if (GET_CODE (addr) == CONST)
176 addr = XEXP (addr, 0);
177 gcc_assert (GET_CODE (addr) == PLUS);
180 if (XEXP (addr, 0) == picreg)
185 gcc_assert (!no_new_pseudos);
186 reg = gen_reg_rtx (Pmode);
189 base = legitimize_pic_address (XEXP (addr, 0), reg, picreg);
190 addr = legitimize_pic_address (XEXP (addr, 1),
191 base == reg ? NULL_RTX : reg,
194 if (GET_CODE (addr) == CONST_INT)
196 gcc_assert (! reload_in_progress && ! reload_completed);
197 addr = force_reg (Pmode, addr);
200 if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
202 base = gen_rtx_PLUS (Pmode, base, XEXP (addr, 0));
203 addr = XEXP (addr, 1);
206 return gen_rtx_PLUS (Pmode, base, addr);
212 /* Stack frame layout. */
214 /* Compute the number of DREGS to save with a push_multiple operation.
215 This could include registers that aren't modified in the function,
216 since push_multiple only takes a range of registers.
217 If IS_INTHANDLER, then everything that is live must be saved, even
218 if normally call-clobbered. */
221 n_dregs_to_save (bool is_inthandler)
225 for (i = REG_R0; i <= REG_R7; i++)
227 if (regs_ever_live[i] && (is_inthandler || ! call_used_regs[i]))
228 return REG_R7 - i + 1;
230 if (current_function_calls_eh_return)
235 unsigned test = EH_RETURN_DATA_REGNO (j);
236 if (test == INVALID_REGNUM)
239 return REG_R7 - i + 1;
247 /* Like n_dregs_to_save, but compute number of PREGS to save. */
250 n_pregs_to_save (bool is_inthandler)
254 for (i = REG_P0; i <= REG_P5; i++)
255 if ((regs_ever_live[i] && (is_inthandler || ! call_used_regs[i]))
256 || (i == PIC_OFFSET_TABLE_REGNUM
257 && (current_function_uses_pic_offset_table
258 || (TARGET_ID_SHARED_LIBRARY && ! current_function_is_leaf))))
259 return REG_P5 - i + 1;
263 /* Determine if we are going to save the frame pointer in the prologue. */
266 must_save_fp_p (void)
268 return frame_pointer_needed || regs_ever_live[REG_FP];
272 stack_frame_needed_p (void)
274 /* EH return puts a new return address into the frame using an
275 address relative to the frame pointer. */
276 if (current_function_calls_eh_return)
278 return frame_pointer_needed;
281 /* Emit code to save registers in the prologue. SAVEALL is nonzero if we
282 must save all registers; this is used for interrupt handlers.
283 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
284 this for an interrupt (or exception) handler. */
287 expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler)
289 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler);
290 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler);
291 int dregno = REG_R7 + 1 - ndregs;
292 int pregno = REG_P5 + 1 - npregs;
293 int total = ndregs + npregs;
300 val = GEN_INT (-total * 4);
301 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total + 2));
302 XVECEXP (pat, 0, 0) = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, val),
303 UNSPEC_PUSH_MULTIPLE);
304 XVECEXP (pat, 0, total + 1) = gen_rtx_SET (VOIDmode, spreg,
305 gen_rtx_PLUS (Pmode, spreg,
307 RTX_FRAME_RELATED_P (XVECEXP (pat, 0, total + 1)) = 1;
308 for (i = 0; i < total; i++)
310 rtx memref = gen_rtx_MEM (word_mode,
311 gen_rtx_PLUS (Pmode, spreg,
312 GEN_INT (- i * 4 - 4)));
316 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
322 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
326 XVECEXP (pat, 0, i + 1) = subpat;
327 RTX_FRAME_RELATED_P (subpat) = 1;
329 insn = emit_insn (pat);
330 RTX_FRAME_RELATED_P (insn) = 1;
333 /* Emit code to restore registers in the epilogue. SAVEALL is nonzero if we
334 must save all registers; this is used for interrupt handlers.
335 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
336 this for an interrupt (or exception) handler. */
339 expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler)
341 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler);
342 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler);
343 int total = ndregs + npregs;
350 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total + 1));
351 XVECEXP (pat, 0, 0) = gen_rtx_SET (VOIDmode, spreg,
352 gen_rtx_PLUS (Pmode, spreg,
353 GEN_INT (total * 4)));
360 for (i = 0; i < total; i++)
363 ? gen_rtx_PLUS (Pmode, spreg, GEN_INT (i * 4))
365 rtx memref = gen_rtx_MEM (word_mode, addr);
368 XVECEXP (pat, 0, i + 1)
369 = gen_rtx_SET (VOIDmode, gen_rtx_REG (word_mode, regno), memref);
378 insn = emit_insn (pat);
379 RTX_FRAME_RELATED_P (insn) = 1;
382 /* Perform any needed actions needed for a function that is receiving a
383 variable number of arguments.
387 MODE and TYPE are the mode and type of the current parameter.
389 PRETEND_SIZE is a variable that should be set to the amount of stack
390 that must be pushed by the prolog to pretend that our caller pushed
393 Normally, this macro will push all remaining incoming registers on the
394 stack and set PRETEND_SIZE to the length of the registers pushed.
397 - VDSP C compiler manual (our ABI) says that a variable args function
398 should save the R0, R1 and R2 registers in the stack.
399 - The caller will always leave space on the stack for the
400 arguments that are passed in registers, so we dont have
401 to leave any extra space.
402 - now, the vastart pointer can access all arguments from the stack. */
405 setup_incoming_varargs (CUMULATIVE_ARGS *cum,
406 enum machine_mode mode ATTRIBUTE_UNUSED,
407 tree type ATTRIBUTE_UNUSED, int *pretend_size,
416 /* The move for named arguments will be generated automatically by the
417 compiler. We need to generate the move rtx for the unnamed arguments
418 if they are in the first 3 words. We assume at least 1 named argument
419 exists, so we never generate [ARGP] = R0 here. */
421 for (i = cum->words + 1; i < max_arg_registers; i++)
423 mem = gen_rtx_MEM (Pmode,
424 plus_constant (arg_pointer_rtx, (i * UNITS_PER_WORD)));
425 emit_move_insn (mem, gen_rtx_REG (Pmode, i));
431 /* Value should be nonzero if functions must have frame pointers.
432 Zero means the frame pointer need not be set up (and parms may
433 be accessed via the stack pointer) in functions that seem suitable. */
436 bfin_frame_pointer_required (void)
438 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
440 if (fkind != SUBROUTINE)
443 /* We turn on -fomit-frame-pointer if -momit-leaf-frame-pointer is used,
444 so we have to override it for non-leaf functions. */
445 if (TARGET_OMIT_LEAF_FRAME_POINTER && ! current_function_is_leaf)
451 /* Return the number of registers pushed during the prologue. */
454 n_regs_saved_by_prologue (void)
456 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
457 bool is_inthandler = fkind != SUBROUTINE;
458 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
459 bool all = (lookup_attribute ("saveall", attrs) != NULL_TREE
460 || (is_inthandler && !current_function_is_leaf));
461 int ndregs = all ? 8 : n_dregs_to_save (is_inthandler);
462 int npregs = all ? 6 : n_pregs_to_save (is_inthandler);
463 int n = ndregs + npregs;
465 if (all || stack_frame_needed_p ())
466 /* We use a LINK instruction in this case. */
470 if (must_save_fp_p ())
472 if (! current_function_is_leaf)
476 if (fkind != SUBROUTINE)
480 /* Increment once for ASTAT. */
484 if (lookup_attribute ("nesting", attrs))
487 for (i = REG_P7 + 1; i < REG_CC; i++)
490 || (!leaf_function_p () && call_used_regs[i]))
491 n += i == REG_A0 || i == REG_A1 ? 2 : 1;
496 /* Return the offset between two registers, one to be eliminated, and the other
497 its replacement, at the start of a routine. */
500 bfin_initial_elimination_offset (int from, int to)
502 HOST_WIDE_INT offset = 0;
504 if (from == ARG_POINTER_REGNUM)
505 offset = n_regs_saved_by_prologue () * 4;
507 if (to == STACK_POINTER_REGNUM)
509 if (current_function_outgoing_args_size >= FIXED_STACK_AREA)
510 offset += current_function_outgoing_args_size;
511 else if (current_function_outgoing_args_size)
512 offset += FIXED_STACK_AREA;
514 offset += get_frame_size ();
520 /* Emit code to load a constant CONSTANT into register REG; setting
521 RTX_FRAME_RELATED_P on all insns we generate if RELATED is true.
522 Make sure that the insns we generate need not be split. */
525 frame_related_constant_load (rtx reg, HOST_WIDE_INT constant, bool related)
528 rtx cst = GEN_INT (constant);
530 if (constant >= -32768 && constant < 65536)
531 insn = emit_move_insn (reg, cst);
534 /* We don't call split_load_immediate here, since dwarf2out.c can get
535 confused about some of the more clever sequences it can generate. */
536 insn = emit_insn (gen_movsi_high (reg, cst));
538 RTX_FRAME_RELATED_P (insn) = 1;
539 insn = emit_insn (gen_movsi_low (reg, reg, cst));
542 RTX_FRAME_RELATED_P (insn) = 1;
545 /* Generate efficient code to add a value to the frame pointer. We
546 can use P1 as a scratch register. Set RTX_FRAME_RELATED_P on the
547 generated insns if FRAME is nonzero. */
550 add_to_sp (rtx spreg, HOST_WIDE_INT value, int frame)
555 /* Choose whether to use a sequence using a temporary register, or
556 a sequence with multiple adds. We can add a signed 7 bit value
557 in one instruction. */
558 if (value > 120 || value < -120)
560 rtx tmpreg = gen_rtx_REG (SImode, REG_P1);
564 frame_related_constant_load (tmpreg, value, TRUE);
567 insn = emit_move_insn (tmpreg, GEN_INT (value));
569 RTX_FRAME_RELATED_P (insn) = 1;
572 insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg));
574 RTX_FRAME_RELATED_P (insn) = 1;
585 /* We could use -62, but that would leave the stack unaligned, so
589 insn = emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (size)));
591 RTX_FRAME_RELATED_P (insn) = 1;
597 /* Generate a LINK insn for a frame sized FRAME_SIZE. If this constant
598 is too large, generate a sequence of insns that has the same effect.
599 SPREG contains (reg:SI REG_SP). */
602 emit_link_insn (rtx spreg, HOST_WIDE_INT frame_size)
604 HOST_WIDE_INT link_size = frame_size;
608 if (link_size > 262140)
611 /* Use a LINK insn with as big a constant as possible, then subtract
612 any remaining size from the SP. */
613 insn = emit_insn (gen_link (GEN_INT (-8 - link_size)));
614 RTX_FRAME_RELATED_P (insn) = 1;
616 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
618 rtx set = XVECEXP (PATTERN (insn), 0, i);
619 gcc_assert (GET_CODE (set) == SET);
620 RTX_FRAME_RELATED_P (set) = 1;
623 frame_size -= link_size;
627 /* Must use a call-clobbered PREG that isn't the static chain. */
628 rtx tmpreg = gen_rtx_REG (Pmode, REG_P1);
630 frame_related_constant_load (tmpreg, -frame_size, TRUE);
631 insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg));
632 RTX_FRAME_RELATED_P (insn) = 1;
636 /* Return the number of bytes we must reserve for outgoing arguments
637 in the current function's stack frame. */
642 if (current_function_outgoing_args_size)
644 if (current_function_outgoing_args_size >= FIXED_STACK_AREA)
645 return current_function_outgoing_args_size;
647 return FIXED_STACK_AREA;
652 /* Save RETS and FP, and allocate a stack frame. ALL is true if the
653 function must save all its registers (true only for certain interrupt
657 do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all)
659 frame_size += arg_area_size ();
661 if (all || stack_frame_needed_p ()
662 || (must_save_fp_p () && ! current_function_is_leaf))
663 emit_link_insn (spreg, frame_size);
666 if (! current_function_is_leaf)
668 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
669 gen_rtx_PRE_DEC (Pmode, spreg)),
671 rtx insn = emit_insn (pat);
672 RTX_FRAME_RELATED_P (insn) = 1;
674 if (must_save_fp_p ())
676 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
677 gen_rtx_PRE_DEC (Pmode, spreg)),
678 gen_rtx_REG (Pmode, REG_FP));
679 rtx insn = emit_insn (pat);
680 RTX_FRAME_RELATED_P (insn) = 1;
682 add_to_sp (spreg, -frame_size, 1);
686 /* Like do_link, but used for epilogues to deallocate the stack frame. */
689 do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all)
691 frame_size += arg_area_size ();
693 if (all || stack_frame_needed_p ())
694 emit_insn (gen_unlink ());
697 rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg));
699 add_to_sp (spreg, frame_size, 0);
700 if (must_save_fp_p ())
702 rtx fpreg = gen_rtx_REG (Pmode, REG_FP);
703 emit_move_insn (fpreg, postinc);
704 emit_insn (gen_rtx_USE (VOIDmode, fpreg));
706 if (! current_function_is_leaf)
708 emit_move_insn (bfin_rets_rtx, postinc);
709 emit_insn (gen_rtx_USE (VOIDmode, bfin_rets_rtx));
714 /* Generate a prologue suitable for a function of kind FKIND. This is
715 called for interrupt and exception handler prologues.
716 SPREG contains (reg:SI REG_SP). */
719 expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind)
722 HOST_WIDE_INT frame_size = get_frame_size ();
723 rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
724 rtx predec = gen_rtx_MEM (SImode, predec1);
726 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
727 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
728 tree kspisusp = lookup_attribute ("kspisusp", attrs);
732 insn = emit_move_insn (spreg, gen_rtx_REG (Pmode, REG_USP));
733 RTX_FRAME_RELATED_P (insn) = 1;
736 /* We need space on the stack in case we need to save the argument
738 if (fkind == EXCPT_HANDLER)
740 insn = emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (-12)));
741 RTX_FRAME_RELATED_P (insn) = 1;
744 insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
745 RTX_FRAME_RELATED_P (insn) = 1;
747 /* If we're calling other functions, they won't save their call-clobbered
748 registers, so we must save everything here. */
749 if (!current_function_is_leaf)
751 expand_prologue_reg_save (spreg, all, true);
753 for (i = REG_P7 + 1; i < REG_CC; i++)
756 || (!leaf_function_p () && call_used_regs[i]))
758 if (i == REG_A0 || i == REG_A1)
759 insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1),
760 gen_rtx_REG (PDImode, i));
762 insn = emit_move_insn (predec, gen_rtx_REG (SImode, i));
763 RTX_FRAME_RELATED_P (insn) = 1;
766 if (lookup_attribute ("nesting", attrs))
768 rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
769 : fkind == NMI_HANDLER ? REG_RETN
771 insn = emit_move_insn (predec, srcreg);
772 RTX_FRAME_RELATED_P (insn) = 1;
775 do_link (spreg, frame_size, all);
777 if (fkind == EXCPT_HANDLER)
779 rtx r0reg = gen_rtx_REG (SImode, REG_R0);
780 rtx r1reg = gen_rtx_REG (SImode, REG_R1);
781 rtx r2reg = gen_rtx_REG (SImode, REG_R2);
784 insn = emit_move_insn (r0reg, gen_rtx_REG (SImode, REG_SEQSTAT));
785 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
787 insn = emit_insn (gen_ashrsi3 (r0reg, r0reg, GEN_INT (26)));
788 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
790 insn = emit_insn (gen_ashlsi3 (r0reg, r0reg, GEN_INT (26)));
791 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
793 insn = emit_move_insn (r1reg, spreg);
794 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
796 insn = emit_move_insn (r2reg, gen_rtx_REG (Pmode, REG_FP));
797 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
799 insn = emit_insn (gen_addsi3 (r2reg, r2reg, GEN_INT (8)));
800 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
805 /* Generate an epilogue suitable for a function of kind FKIND. This is
806 called for interrupt and exception handler epilogues.
807 SPREG contains (reg:SI REG_SP). */
810 expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind)
813 rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
814 rtx postinc = gen_rtx_MEM (SImode, postinc1);
815 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
816 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
818 /* A slightly crude technique to stop flow from trying to delete "dead"
820 MEM_VOLATILE_P (postinc) = 1;
822 do_unlink (spreg, get_frame_size (), all);
824 if (lookup_attribute ("nesting", attrs))
826 rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
827 : fkind == NMI_HANDLER ? REG_RETN
829 emit_move_insn (srcreg, postinc);
832 /* If we're calling other functions, they won't save their call-clobbered
833 registers, so we must save (and restore) everything here. */
834 if (!current_function_is_leaf)
837 for (i = REG_CC - 1; i > REG_P7; i--)
840 || (!leaf_function_p () && call_used_regs[i]))
842 if (i == REG_A0 || i == REG_A1)
844 rtx mem = gen_rtx_MEM (PDImode, postinc1);
845 MEM_VOLATILE_P (mem) = 1;
846 emit_move_insn (gen_rtx_REG (PDImode, i), mem);
849 emit_move_insn (gen_rtx_REG (SImode, i), postinc);
852 expand_epilogue_reg_restore (spreg, all, true);
854 emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
856 /* Deallocate any space we left on the stack in case we needed to save the
857 argument registers. */
858 if (fkind == EXCPT_HANDLER)
859 emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (12)));
861 emit_jump_insn (gen_return_internal (GEN_INT (fkind)));
864 /* Used while emitting the prologue to generate code to load the correct value
865 into the PIC register, which is passed in DEST. */
868 bfin_load_pic_reg (rtx dest)
870 struct cgraph_local_info *i = NULL;
873 if (flag_unit_at_a_time)
874 i = cgraph_local_info (current_function_decl);
876 /* Functions local to the translation unit don't need to reload the
877 pic reg, since the caller always passes a usable one. */
879 return pic_offset_table_rtx;
881 if (bfin_lib_id_given)
882 addr = plus_constant (pic_offset_table_rtx, -4 - bfin_library_id * 4);
884 addr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
885 gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
886 UNSPEC_LIBRARY_OFFSET));
887 insn = emit_insn (gen_movsi (dest, gen_rtx_MEM (Pmode, addr)));
888 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
892 /* Generate RTL for the prologue of the current function. */
895 bfin_expand_prologue (void)
898 HOST_WIDE_INT frame_size = get_frame_size ();
899 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
900 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
901 rtx pic_reg_loaded = NULL_RTX;
903 if (fkind != SUBROUTINE)
905 expand_interrupt_handler_prologue (spreg, fkind);
909 if (current_function_limit_stack)
912 = bfin_initial_elimination_offset (ARG_POINTER_REGNUM,
913 STACK_POINTER_REGNUM);
914 rtx lim = stack_limit_rtx;
916 if (GET_CODE (lim) == SYMBOL_REF)
918 rtx p2reg = gen_rtx_REG (Pmode, REG_P2);
919 if (TARGET_ID_SHARED_LIBRARY)
921 rtx p1reg = gen_rtx_REG (Pmode, REG_P1);
923 pic_reg_loaded = bfin_load_pic_reg (p2reg);
924 val = legitimize_pic_address (stack_limit_rtx, p1reg,
926 emit_move_insn (p1reg, val);
927 frame_related_constant_load (p2reg, offset, FALSE);
928 emit_insn (gen_addsi3 (p2reg, p2reg, p1reg));
933 rtx limit = plus_constant (stack_limit_rtx, offset);
934 emit_move_insn (p2reg, limit);
938 emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim));
939 emit_insn (gen_trapifcc ());
941 expand_prologue_reg_save (spreg, 0, false);
943 do_link (spreg, frame_size, false);
945 if (TARGET_ID_SHARED_LIBRARY
946 && (current_function_uses_pic_offset_table
947 || !current_function_is_leaf))
948 bfin_load_pic_reg (pic_offset_table_rtx);
951 /* Generate RTL for the epilogue of the current function. NEED_RETURN is zero
952 if this is for a sibcall. EH_RETURN is nonzero if we're expanding an
953 eh_return pattern. */
956 bfin_expand_epilogue (int need_return, int eh_return)
958 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
959 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
961 if (fkind != SUBROUTINE)
963 expand_interrupt_handler_epilogue (spreg, fkind);
967 do_unlink (spreg, get_frame_size (), false);
969 expand_epilogue_reg_restore (spreg, false, false);
971 /* Omit the return insn if this is for a sibcall. */
976 emit_insn (gen_addsi3 (spreg, spreg, gen_rtx_REG (Pmode, REG_P2)));
978 emit_jump_insn (gen_return_internal (GEN_INT (SUBROUTINE)));
981 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
984 bfin_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
985 unsigned int new_reg)
987 /* Interrupt functions can only use registers that have already been
988 saved by the prologue, even if they would normally be
991 if (funkind (TREE_TYPE (current_function_decl)) != SUBROUTINE
992 && !regs_ever_live[new_reg])
998 /* Return the value of the return address for the frame COUNT steps up
999 from the current frame, after the prologue.
1000 We punt for everything but the current frame by returning const0_rtx. */
1003 bfin_return_addr_rtx (int count)
1008 return get_hard_reg_initial_val (Pmode, REG_RETS);
1011 /* Try machine-dependent ways of modifying an illegitimate address X
1012 to be legitimate. If we find one, return the new, valid address,
1013 otherwise return NULL_RTX.
1015 OLDX is the address as it was before break_out_memory_refs was called.
1016 In some cases it is useful to look at this to decide what needs to be done.
1018 MODE is the mode of the memory reference. */
1021 legitimize_address (rtx x ATTRIBUTE_UNUSED, rtx oldx ATTRIBUTE_UNUSED,
1022 enum machine_mode mode ATTRIBUTE_UNUSED)
1027 /* This predicate is used to compute the length of a load/store insn.
1028 OP is a MEM rtx, we return nonzero if its addressing mode requires a
1029 32 bit instruction. */
1032 effective_address_32bit_p (rtx op, enum machine_mode mode)
1034 HOST_WIDE_INT offset;
1036 mode = GET_MODE (op);
1039 if (GET_CODE (op) != PLUS)
1041 gcc_assert (REG_P (op) || GET_CODE (op) == POST_INC
1042 || GET_CODE (op) == PRE_DEC || GET_CODE (op) == POST_DEC);
1046 offset = INTVAL (XEXP (op, 1));
1048 /* All byte loads use a 16 bit offset. */
1049 if (GET_MODE_SIZE (mode) == 1)
1052 if (GET_MODE_SIZE (mode) == 4)
1054 /* Frame pointer relative loads can use a negative offset, all others
1055 are restricted to a small positive one. */
1056 if (XEXP (op, 0) == frame_pointer_rtx)
1057 return offset < -128 || offset > 60;
1058 return offset < 0 || offset > 60;
1061 /* Must be HImode now. */
1062 return offset < 0 || offset > 30;
1065 /* Returns true if X is a memory reference using an I register. */
1067 bfin_dsp_memref_p (rtx x)
1072 if (GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_INC
1073 || GET_CODE (x) == POST_DEC || GET_CODE (x) == PRE_DEC)
1078 /* Return cost of the memory address ADDR.
1079 All addressing modes are equally cheap on the Blackfin. */
1082 bfin_address_cost (rtx addr ATTRIBUTE_UNUSED)
1087 /* Subroutine of print_operand; used to print a memory reference X to FILE. */
1090 print_address_operand (FILE *file, rtx x)
1092 switch (GET_CODE (x))
1095 output_address (XEXP (x, 0));
1096 fprintf (file, "+");
1097 output_address (XEXP (x, 1));
1101 fprintf (file, "--");
1102 output_address (XEXP (x, 0));
1105 output_address (XEXP (x, 0));
1106 fprintf (file, "++");
1109 output_address (XEXP (x, 0));
1110 fprintf (file, "--");
1114 gcc_assert (GET_CODE (x) != MEM);
1115 print_operand (file, x, 0);
1120 /* Adding intp DImode support by Tony
1126 print_operand (FILE *file, rtx x, char code)
1128 enum machine_mode mode = GET_MODE (x);
1133 switch (GET_CODE (x))
1136 fprintf (file, "e");
1139 fprintf (file, "ne");
1142 fprintf (file, "g");
1145 fprintf (file, "l");
1148 fprintf (file, "ge");
1151 fprintf (file, "le");
1154 fprintf (file, "g");
1157 fprintf (file, "l");
1160 fprintf (file, "ge");
1163 fprintf (file, "le");
1166 output_operand_lossage ("invalid %%j value");
1170 case 'J': /* reverse logic */
1171 switch (GET_CODE(x))
1174 fprintf (file, "ne");
1177 fprintf (file, "e");
1180 fprintf (file, "le");
1183 fprintf (file, "ge");
1186 fprintf (file, "l");
1189 fprintf (file, "g");
1192 fprintf (file, "le");
1195 fprintf (file, "ge");
1198 fprintf (file, "l");
1201 fprintf (file, "g");
1204 output_operand_lossage ("invalid %%J value");
1209 switch (GET_CODE (x))
1214 gcc_assert (REGNO (x) < 32);
1215 fprintf (file, "%s", short_reg_names[REGNO (x)]);
1216 /*fprintf (file, "\n%d\n ", REGNO (x));*/
1219 else if (code == 'd')
1221 gcc_assert (REGNO (x) < 32);
1222 fprintf (file, "%s", high_reg_names[REGNO (x)]);
1225 else if (code == 'w')
1227 gcc_assert (REGNO (x) == REG_A0 || REGNO (x) == REG_A1);
1228 fprintf (file, "%s.w", reg_names[REGNO (x)]);
1230 else if (code == 'x')
1232 gcc_assert (REGNO (x) == REG_A0 || REGNO (x) == REG_A1);
1233 fprintf (file, "%s.x", reg_names[REGNO (x)]);
1235 else if (code == 'D')
1237 fprintf (file, "%s", dregs_pair_names[REGNO (x)]);
1239 else if (code == 'H')
1241 gcc_assert (mode == DImode || mode == DFmode);
1242 gcc_assert (REG_P (x));
1243 fprintf (file, "%s", reg_names[REGNO (x) + 1]);
1245 else if (code == 'T')
1247 gcc_assert (D_REGNO_P (REGNO (x)));
1248 fprintf (file, "%s", byte_reg_names[REGNO (x)]);
1251 fprintf (file, "%s", reg_names[REGNO (x)]);
1257 print_address_operand (file, x);
1269 fputs ("(FU)", file);
1272 fputs ("(T)", file);
1275 fputs ("(TFU)", file);
1278 fputs ("(W32)", file);
1281 fputs ("(IS)", file);
1284 fputs ("(IU)", file);
1287 fputs ("(IH)", file);
1290 fputs ("(M)", file);
1293 fputs ("(ISS2)", file);
1296 fputs ("(S2RND)", file);
1303 else if (code == 'b')
1305 if (INTVAL (x) == 0)
1307 else if (INTVAL (x) == 1)
1313 /* Moves to half registers with d or h modifiers always use unsigned
1315 else if (code == 'd')
1316 x = GEN_INT ((INTVAL (x) >> 16) & 0xffff);
1317 else if (code == 'h')
1318 x = GEN_INT (INTVAL (x) & 0xffff);
1319 else if (code == 'X')
1320 x = GEN_INT (exact_log2 (0xffffffff & INTVAL (x)));
1321 else if (code == 'Y')
1322 x = GEN_INT (exact_log2 (0xffffffff & ~INTVAL (x)));
1323 else if (code == 'Z')
1324 /* Used for LINK insns. */
1325 x = GEN_INT (-8 - INTVAL (x));
1330 output_addr_const (file, x);
1334 output_operand_lossage ("invalid const_double operand");
1338 switch (XINT (x, 1))
1340 case UNSPEC_MOVE_PIC:
1341 output_addr_const (file, XVECEXP (x, 0, 0));
1342 fprintf (file, "@GOT");
1345 case UNSPEC_LIBRARY_OFFSET:
1346 fprintf (file, "_current_shared_library_p5_offset_");
1355 output_addr_const (file, x);
1360 /* Argument support functions. */
1362 /* Initialize a variable CUM of type CUMULATIVE_ARGS
1363 for a call to a function whose data type is FNTYPE.
1364 For a library call, FNTYPE is 0.
1365 VDSP C Compiler manual, our ABI says that
1366 first 3 words of arguments will use R0, R1 and R2.
1370 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
1371 rtx libname ATTRIBUTE_UNUSED)
1373 static CUMULATIVE_ARGS zero_cum;
1377 /* Set up the number of registers to use for passing arguments. */
1379 cum->nregs = max_arg_registers;
1380 cum->arg_regs = arg_regs;
1382 cum->call_cookie = CALL_NORMAL;
1383 /* Check for a longcall attribute. */
1384 if (fntype && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype)))
1385 cum->call_cookie |= CALL_SHORT;
1386 else if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)))
1387 cum->call_cookie |= CALL_LONG;
1392 /* Update the data in CUM to advance over an argument
1393 of mode MODE and data type TYPE.
1394 (TYPE is null for libcalls where that information may not be available.) */
1397 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1398 int named ATTRIBUTE_UNUSED)
1400 int count, bytes, words;
1402 bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1403 words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1405 cum->words += words;
1406 cum->nregs -= words;
1408 if (cum->nregs <= 0)
1411 cum->arg_regs = NULL;
1415 for (count = 1; count <= words; count++)
1422 /* Define where to put the arguments to a function.
1423 Value is zero to push the argument on the stack,
1424 or a hard register in which to store the argument.
1426 MODE is the argument's machine mode.
1427 TYPE is the data type of the argument (as a tree).
1428 This is null for libcalls where that information may
1430 CUM is a variable of type CUMULATIVE_ARGS which gives info about
1431 the preceding args and about the function being called.
1432 NAMED is nonzero if this argument is a named parameter
1433 (otherwise it is an extra parameter matching an ellipsis). */
1436 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1437 int named ATTRIBUTE_UNUSED)
1440 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1442 if (mode == VOIDmode)
1443 /* Compute operand 2 of the call insn. */
1444 return GEN_INT (cum->call_cookie);
1450 return gen_rtx_REG (mode, *(cum->arg_regs));
1455 /* For an arg passed partly in registers and partly in memory,
1456 this is the number of bytes passed in registers.
1457 For args passed entirely in registers or entirely in memory, zero.
1459 Refer VDSP C Compiler manual, our ABI.
1460 First 3 words are in registers. So, if a an argument is larger
1461 than the registers available, it will span the register and
1465 bfin_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1466 tree type ATTRIBUTE_UNUSED,
1467 bool named ATTRIBUTE_UNUSED)
1470 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1471 int bytes_left = cum->nregs * UNITS_PER_WORD;
1476 if (bytes_left == 0)
1478 if (bytes > bytes_left)
1483 /* Variable sized types are passed by reference. */
1486 bfin_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
1487 enum machine_mode mode ATTRIBUTE_UNUSED,
1488 tree type, bool named ATTRIBUTE_UNUSED)
1490 return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
1493 /* Decide whether a type should be returned in memory (true)
1494 or in a register (false). This is called by the macro
1495 RETURN_IN_MEMORY. */
1498 bfin_return_in_memory (tree type)
1500 int size = int_size_in_bytes (type);
1501 return size > 2 * UNITS_PER_WORD || size == -1;
1504 /* Register in which address to store a structure value
1505 is passed to a function. */
1507 bfin_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
1508 int incoming ATTRIBUTE_UNUSED)
1510 return gen_rtx_REG (Pmode, REG_P0);
1513 /* Return true when register may be used to pass function parameters. */
1516 function_arg_regno_p (int n)
1519 for (i = 0; arg_regs[i] != -1; i++)
1520 if (n == arg_regs[i])
1525 /* Returns 1 if OP contains a symbol reference */
1528 symbolic_reference_mentioned_p (rtx op)
1530 register const char *fmt;
1533 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
1536 fmt = GET_RTX_FORMAT (GET_CODE (op));
1537 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
1543 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
1544 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
1548 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
1555 /* Decide whether we can make a sibling call to a function. DECL is the
1556 declaration of the function being targeted by the call and EXP is the
1557 CALL_EXPR representing the call. */
1560 bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
1561 tree exp ATTRIBUTE_UNUSED)
1563 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1564 return fkind == SUBROUTINE;
1567 /* Emit RTL insns to initialize the variable parts of a trampoline at
1568 TRAMP. FNADDR is an RTX for the address of the function's pure
1569 code. CXT is an RTX for the static chain value for the function. */
1572 initialize_trampoline (tramp, fnaddr, cxt)
1573 rtx tramp, fnaddr, cxt;
1575 rtx t1 = copy_to_reg (fnaddr);
1576 rtx t2 = copy_to_reg (cxt);
1579 addr = memory_address (Pmode, plus_constant (tramp, 2));
1580 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
1581 emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16)));
1582 addr = memory_address (Pmode, plus_constant (tramp, 6));
1583 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
1585 addr = memory_address (Pmode, plus_constant (tramp, 10));
1586 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
1587 emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16)));
1588 addr = memory_address (Pmode, plus_constant (tramp, 14));
1589 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
1592 /* Emit insns to move operands[1] into operands[0]. */
1595 emit_pic_move (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
1597 rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
1599 if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
1600 operands[1] = force_reg (SImode, operands[1]);
1602 operands[1] = legitimize_pic_address (operands[1], temp,
1603 pic_offset_table_rtx);
1606 /* Expand a move operation in mode MODE. The operands are in OPERANDS. */
1609 expand_move (rtx *operands, enum machine_mode mode)
1611 if (flag_pic && SYMBOLIC_CONST (operands[1]))
1612 emit_pic_move (operands, mode);
1614 /* Don't generate memory->memory or constant->memory moves, go through a
1616 else if ((reload_in_progress | reload_completed) == 0
1617 && GET_CODE (operands[0]) == MEM
1618 && GET_CODE (operands[1]) != REG)
1619 operands[1] = force_reg (mode, operands[1]);
1622 /* Split one or more DImode RTL references into pairs of SImode
1623 references. The RTL can be REG, offsettable MEM, integer constant, or
1624 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
1625 split and "num" is its length. lo_half and hi_half are output arrays
1626 that parallel "operands". */
1629 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
1633 rtx op = operands[num];
1635 /* simplify_subreg refuse to split volatile memory addresses,
1636 but we still have to handle it. */
1637 if (GET_CODE (op) == MEM)
1639 lo_half[num] = adjust_address (op, SImode, 0);
1640 hi_half[num] = adjust_address (op, SImode, 4);
1644 lo_half[num] = simplify_gen_subreg (SImode, op,
1645 GET_MODE (op) == VOIDmode
1646 ? DImode : GET_MODE (op), 0);
1647 hi_half[num] = simplify_gen_subreg (SImode, op,
1648 GET_MODE (op) == VOIDmode
1649 ? DImode : GET_MODE (op), 4);
1655 bfin_longcall_p (rtx op, int call_cookie)
1657 gcc_assert (GET_CODE (op) == SYMBOL_REF);
1658 if (call_cookie & CALL_SHORT)
1660 if (call_cookie & CALL_LONG)
1662 if (TARGET_LONG_CALLS)
1667 /* Expand a call instruction. FNADDR is the call target, RETVAL the return value.
1668 COOKIE is a CONST_INT holding the call_cookie prepared init_cumulative_args.
1669 SIBCALL is nonzero if this is a sibling call. */
1672 bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
1674 rtx use = NULL, call;
1675 rtx callee = XEXP (fnaddr, 0);
1676 rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (sibcall ? 3 : 2));
1678 /* In an untyped call, we can get NULL for operand 2. */
1679 if (cookie == NULL_RTX)
1680 cookie = const0_rtx;
1682 /* Static functions and indirect calls don't need the pic register. */
1684 && GET_CODE (callee) == SYMBOL_REF
1685 && !SYMBOL_REF_LOCAL_P (callee))
1686 use_reg (&use, pic_offset_table_rtx);
1688 if ((!register_no_elim_operand (callee, Pmode)
1689 && GET_CODE (callee) != SYMBOL_REF)
1690 || (GET_CODE (callee) == SYMBOL_REF
1692 || bfin_longcall_p (callee, INTVAL (cookie)))))
1694 callee = copy_to_mode_reg (Pmode, callee);
1695 fnaddr = gen_rtx_MEM (Pmode, callee);
1697 call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
1700 call = gen_rtx_SET (VOIDmode, retval, call);
1702 XVECEXP (pat, 0, 0) = call;
1703 XVECEXP (pat, 0, 1) = gen_rtx_USE (VOIDmode, cookie);
1705 XVECEXP (pat, 0, 2) = gen_rtx_RETURN (VOIDmode);
1706 call = emit_call_insn (pat);
1708 CALL_INSN_FUNCTION_USAGE (call) = use;
1711 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
1714 hard_regno_mode_ok (int regno, enum machine_mode mode)
1716 /* Allow only dregs to store value of mode HI or QI */
1717 enum reg_class class = REGNO_REG_CLASS (regno);
1722 if (mode == V2HImode)
1723 return D_REGNO_P (regno);
1724 if (class == CCREGS)
1725 return mode == BImode;
1726 if (mode == PDImode || mode == V2PDImode)
1727 return regno == REG_A0 || regno == REG_A1;
1729 && TEST_HARD_REG_BIT (reg_class_contents[PROLOGUE_REGS], regno))
1732 return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno);
1735 /* Implements target hook vector_mode_supported_p. */
1738 bfin_vector_mode_supported_p (enum machine_mode mode)
1740 return mode == V2HImode;
1743 /* Return the cost of moving data from a register in class CLASS1 to
1744 one in class CLASS2. A cost of 2 is the default. */
1747 bfin_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
1748 enum reg_class class1, enum reg_class class2)
1750 /* These need secondary reloads, so they're more expensive. */
1751 if ((class1 == CCREGS && class2 != DREGS)
1752 || (class1 != DREGS && class2 == CCREGS))
1755 /* If optimizing for size, always prefer reg-reg over reg-memory moves. */
1759 /* There are some stalls involved when moving from a DREG to a different
1760 class reg, and using the value in one of the following instructions.
1761 Attempt to model this by slightly discouraging such moves. */
1762 if (class1 == DREGS && class2 != DREGS)
1768 /* Return the cost of moving data of mode M between a
1769 register and memory. A value of 2 is the default; this cost is
1770 relative to those in `REGISTER_MOVE_COST'.
1772 ??? In theory L1 memory has single-cycle latency. We should add a switch
1773 that tells the compiler whether we expect to use only L1 memory for the
1774 program; it'll make the costs more accurate. */
1777 bfin_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
1778 enum reg_class class,
1779 int in ATTRIBUTE_UNUSED)
1781 /* Make memory accesses slightly more expensive than any register-register
1782 move. Also, penalize non-DP registers, since they need secondary
1783 reloads to load and store. */
1784 if (! reg_class_subset_p (class, DPREGS))
1790 /* Inform reload about cases where moving X with a mode MODE to a register in
1791 CLASS requires an extra scratch register. Return the class needed for the
1792 scratch register. */
1794 static enum reg_class
1795 bfin_secondary_reload (bool in_p, rtx x, enum reg_class class,
1796 enum machine_mode mode, secondary_reload_info *sri)
1798 /* If we have HImode or QImode, we can only use DREGS as secondary registers;
1799 in most other cases we can also use PREGS. */
1800 enum reg_class default_class = GET_MODE_SIZE (mode) >= 4 ? DPREGS : DREGS;
1801 enum reg_class x_class = NO_REGS;
1802 enum rtx_code code = GET_CODE (x);
1805 x = SUBREG_REG (x), code = GET_CODE (x);
1808 int regno = REGNO (x);
1809 if (regno >= FIRST_PSEUDO_REGISTER)
1810 regno = reg_renumber[regno];
1815 x_class = REGNO_REG_CLASS (regno);
1818 /* We can be asked to reload (plus (FP) (large_constant)) into a DREG.
1819 This happens as a side effect of register elimination, and we need
1820 a scratch register to do it. */
1821 if (fp_plus_const_operand (x, mode))
1823 rtx op2 = XEXP (x, 1);
1824 int large_constant_p = ! CONST_7BIT_IMM_P (INTVAL (op2));
1826 if (class == PREGS || class == PREGS_CLOBBERED)
1828 /* If destination is a DREG, we can do this without a scratch register
1829 if the constant is valid for an add instruction. */
1830 if ((class == DREGS || class == DPREGS)
1831 && ! large_constant_p)
1833 /* Reloading to anything other than a DREG? Use a PREG scratch
1835 sri->icode = CODE_FOR_reload_insi;
1839 /* Data can usually be moved freely between registers of most classes.
1840 AREGS are an exception; they can only move to or from another register
1841 in AREGS or one in DREGS. They can also be assigned the constant 0. */
1842 if (x_class == AREGS)
1843 return class == DREGS || class == AREGS ? NO_REGS : DREGS;
1847 if (x != const0_rtx && x_class != DREGS)
1853 /* CCREGS can only be moved from/to DREGS. */
1854 if (class == CCREGS && x_class != DREGS)
1856 if (x_class == CCREGS && class != DREGS)
1859 /* All registers other than AREGS can load arbitrary constants. The only
1860 case that remains is MEM. */
1862 if (! reg_class_subset_p (class, default_class))
1863 return default_class;
1867 /* Implement TARGET_HANDLE_OPTION. */
1870 bfin_handle_option (size_t code, const char *arg, int value)
1874 case OPT_mshared_library_id_:
1875 if (value > MAX_LIBRARY_ID)
1876 error ("-mshared-library-id=%s is not between 0 and %d",
1877 arg, MAX_LIBRARY_ID);
1878 bfin_lib_id_given = 1;
1886 /* Implement the macro OVERRIDE_OPTIONS. */
1889 override_options (void)
1891 if (TARGET_OMIT_LEAF_FRAME_POINTER)
1892 flag_omit_frame_pointer = 1;
1894 /* Library identification */
1895 if (bfin_lib_id_given && ! TARGET_ID_SHARED_LIBRARY)
1896 error ("-mshared-library-id= specified without -mid-shared-library");
1898 if (TARGET_ID_SHARED_LIBRARY)
1899 /* ??? Provide a way to use a bigger GOT. */
1902 flag_schedule_insns = 0;
1905 /* Return the destination address of BRANCH.
1906 We need to use this instead of get_attr_length, because the
1907 cbranch_with_nops pattern conservatively sets its length to 6, and
1908 we still prefer to use shorter sequences. */
1911 branch_dest (rtx branch)
1915 rtx pat = PATTERN (branch);
1916 if (GET_CODE (pat) == PARALLEL)
1917 pat = XVECEXP (pat, 0, 0);
1918 dest = SET_SRC (pat);
1919 if (GET_CODE (dest) == IF_THEN_ELSE)
1920 dest = XEXP (dest, 1);
1921 dest = XEXP (dest, 0);
1922 dest_uid = INSN_UID (dest);
1923 return INSN_ADDRESSES (dest_uid);
1926 /* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates
1927 it's a branch that's predicted taken. */
1930 cbranch_predicted_taken_p (rtx insn)
1932 rtx x = find_reg_note (insn, REG_BR_PROB, 0);
1936 int pred_val = INTVAL (XEXP (x, 0));
1938 return pred_val >= REG_BR_PROB_BASE / 2;
1944 /* Templates for use by asm_conditional_branch. */
1946 static const char *ccbranch_templates[][3] = {
1947 { "if !cc jump %3;", "if cc jump 4 (bp); jump.s %3;", "if cc jump 6 (bp); jump.l %3;" },
1948 { "if cc jump %3;", "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" },
1949 { "if !cc jump %3 (bp);", "if cc jump 4; jump.s %3;", "if cc jump 6; jump.l %3;" },
1950 { "if cc jump %3 (bp);", "if !cc jump 4; jump.s %3;", "if !cc jump 6; jump.l %3;" },
1953 /* Output INSN, which is a conditional branch instruction with operands
1956 We deal with the various forms of conditional branches that can be generated
1957 by bfin_reorg to prevent the hardware from doing speculative loads, by
1958 - emitting a sufficient number of nops, if N_NOPS is nonzero, or
1959 - always emitting the branch as predicted taken, if PREDICT_TAKEN is true.
1960 Either of these is only necessary if the branch is short, otherwise the
1961 template we use ends in an unconditional jump which flushes the pipeline
1965 asm_conditional_branch (rtx insn, rtx *operands, int n_nops, int predict_taken)
1967 int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
1968 /* Note : offset for instructions like if cc jmp; jump.[sl] offset
1969 is to be taken from start of if cc rather than jump.
1970 Range for jump.s is (-4094, 4096) instead of (-4096, 4094)
1972 int len = (offset >= -1024 && offset <= 1022 ? 0
1973 : offset >= -4094 && offset <= 4096 ? 1
1975 int bp = predict_taken && len == 0 ? 1 : cbranch_predicted_taken_p (insn);
1976 int idx = (bp << 1) | (GET_CODE (operands[0]) == EQ ? BRF : BRT);
1977 output_asm_insn (ccbranch_templates[idx][len], operands);
1978 gcc_assert (n_nops == 0 || !bp);
1980 while (n_nops-- > 0)
1981 output_asm_insn ("nop;", NULL);
1984 /* Emit rtl for a comparison operation CMP in mode MODE. Operands have been
1985 stored in bfin_compare_op0 and bfin_compare_op1 already. */
1988 bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED)
1990 enum rtx_code code1, code2;
1991 rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1;
1992 rtx tem = bfin_cc_rtx;
1993 enum rtx_code code = GET_CODE (cmp);
1995 /* If we have a BImode input, then we already have a compare result, and
1996 do not need to emit another comparison. */
1997 if (GET_MODE (op0) == BImode)
1999 gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
2000 tem = op0, code2 = code;
2005 /* bfin has these conditions */
2015 code1 = reverse_condition (code);
2019 emit_insn (gen_rtx_SET (BImode, tem,
2020 gen_rtx_fmt_ee (code1, BImode, op0, op1)));
2023 return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode));
2026 /* Return nonzero iff C has exactly one bit set if it is interpreted
2027 as a 32 bit constant. */
2030 log2constp (unsigned HOST_WIDE_INT c)
2033 return c != 0 && (c & (c-1)) == 0;
2036 /* Returns the number of consecutive least significant zeros in the binary
2037 representation of *V.
2038 We modify *V to contain the original value arithmetically shifted right by
2039 the number of zeroes. */
2042 shiftr_zero (HOST_WIDE_INT *v)
2044 unsigned HOST_WIDE_INT tmp = *v;
2045 unsigned HOST_WIDE_INT sgn;
2051 sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1));
2052 while ((tmp & 0x1) == 0 && n <= 32)
2054 tmp = (tmp >> 1) | sgn;
2061 /* After reload, split the load of an immediate constant. OPERANDS are the
2062 operands of the movsi_insn pattern which we are splitting. We return
2063 nonzero if we emitted a sequence to load the constant, zero if we emitted
2064 nothing because we want to use the splitter's default sequence. */
2067 split_load_immediate (rtx operands[])
2069 HOST_WIDE_INT val = INTVAL (operands[1]);
2071 HOST_WIDE_INT shifted = val;
2072 HOST_WIDE_INT shifted_compl = ~val;
2073 int num_zero = shiftr_zero (&shifted);
2074 int num_compl_zero = shiftr_zero (&shifted_compl);
2075 unsigned int regno = REGNO (operands[0]);
2076 enum reg_class class1 = REGNO_REG_CLASS (regno);
2078 /* This case takes care of single-bit set/clear constants, which we could
2079 also implement with BITSET/BITCLR. */
2081 && shifted >= -32768 && shifted < 65536
2082 && (D_REGNO_P (regno)
2083 || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))
2085 emit_insn (gen_movsi (operands[0], GEN_INT (shifted)));
2086 emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));
2091 tmp |= -(tmp & 0x8000);
2093 /* If high word has one bit set or clear, try to use a bit operation. */
2094 if (D_REGNO_P (regno))
2096 if (log2constp (val & 0xFFFF0000))
2098 emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));
2099 emit_insn (gen_iorsi3 (operands[0], operands[0], GEN_INT (val & 0xFFFF0000)));
2102 else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)
2104 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2105 emit_insn (gen_andsi3 (operands[0], operands[0], GEN_INT (val | 0xFFFF)));
2109 if (D_REGNO_P (regno))
2111 if (CONST_7BIT_IMM_P (tmp))
2113 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2114 emit_insn (gen_movstricthi_high (operands[0], GEN_INT (val & -65536)));
2118 if ((val & 0xFFFF0000) == 0)
2120 emit_insn (gen_movsi (operands[0], const0_rtx));
2121 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2125 if ((val & 0xFFFF0000) == 0xFFFF0000)
2127 emit_insn (gen_movsi (operands[0], constm1_rtx));
2128 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2133 /* Need DREGs for the remaining case. */
2138 && num_compl_zero && CONST_7BIT_IMM_P (shifted_compl))
2140 /* If optimizing for size, generate a sequence that has more instructions
2142 emit_insn (gen_movsi (operands[0], GEN_INT (shifted_compl)));
2143 emit_insn (gen_ashlsi3 (operands[0], operands[0],
2144 GEN_INT (num_compl_zero)));
2145 emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
2151 /* Return true if the legitimate memory address for a memory operand of mode
2152 MODE. Return false if not. */
2155 bfin_valid_add (enum machine_mode mode, HOST_WIDE_INT value)
2157 unsigned HOST_WIDE_INT v = value > 0 ? value : -value;
2158 int sz = GET_MODE_SIZE (mode);
2159 int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2;
2160 /* The usual offsettable_memref machinery doesn't work so well for this
2161 port, so we deal with the problem here. */
2162 unsigned HOST_WIDE_INT mask = sz == 8 ? 0x7ffe : 0x7fff;
2163 return (v & ~(mask << shift)) == 0;
2167 bfin_valid_reg_p (unsigned int regno, int strict, enum machine_mode mode,
2168 enum rtx_code outer_code)
2171 return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH);
2173 return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH);
2177 bfin_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
2179 switch (GET_CODE (x)) {
2181 if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM))
2185 if (REG_P (XEXP (x, 0))
2186 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS)
2187 && ((GET_CODE (XEXP (x, 1)) == UNSPEC && mode == SImode)
2188 || (GET_CODE (XEXP (x, 1)) == CONST_INT
2189 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
2194 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2195 && REG_P (XEXP (x, 0))
2196 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC))
2199 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2200 && XEXP (x, 0) == stack_pointer_rtx
2201 && REG_P (XEXP (x, 0))
2202 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC))
2212 bfin_rtx_costs (rtx x, int code, int outer_code, int *total)
2214 int cost2 = COSTS_N_INSNS (1);
2219 if (outer_code == SET || outer_code == PLUS)
2220 *total = CONST_7BIT_IMM_P (INTVAL (x)) ? 0 : cost2;
2221 else if (outer_code == AND)
2222 *total = log2constp (~INTVAL (x)) ? 0 : cost2;
2223 else if (outer_code == LE || outer_code == LT || outer_code == EQ)
2224 *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
2225 else if (outer_code == LEU || outer_code == LTU)
2226 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
2227 else if (outer_code == MULT)
2228 *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
2229 else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
2231 else if (outer_code == ASHIFT || outer_code == ASHIFTRT
2232 || outer_code == LSHIFTRT)
2233 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
2234 else if (outer_code == IOR || outer_code == XOR)
2235 *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
2244 *total = COSTS_N_INSNS (2);
2248 if (GET_MODE (x) == Pmode)
2250 if (GET_CODE (XEXP (x, 0)) == MULT
2251 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
2253 HOST_WIDE_INT val = INTVAL (XEXP (XEXP (x, 0), 1));
2254 if (val == 2 || val == 4)
2257 *total += rtx_cost (XEXP (XEXP (x, 0), 0), outer_code);
2258 *total += rtx_cost (XEXP (x, 1), outer_code);
2270 if (GET_MODE (x) == DImode)
2277 if (GET_MODE (x) == DImode)
2282 if (GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD)
2283 *total = COSTS_N_INSNS (3);
2292 bfin_internal_label (FILE *stream, const char *prefix, unsigned long num)
2294 fprintf (stream, "%s%s$%ld:\n", LOCAL_LABEL_PREFIX, prefix, num);
2297 /* Used for communication between {push,pop}_multiple_operation (which
2298 we use not only as a predicate) and the corresponding output functions. */
2299 static int first_preg_to_save, first_dreg_to_save;
2302 push_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2304 int lastdreg = 8, lastpreg = 6;
2307 first_preg_to_save = lastpreg;
2308 first_dreg_to_save = lastdreg;
2309 for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
2311 rtx t = XVECEXP (op, 0, i);
2315 if (GET_CODE (t) != SET)
2319 dest = SET_DEST (t);
2320 if (GET_CODE (dest) != MEM || ! REG_P (src))
2322 dest = XEXP (dest, 0);
2323 if (GET_CODE (dest) != PLUS
2324 || ! REG_P (XEXP (dest, 0))
2325 || REGNO (XEXP (dest, 0)) != REG_SP
2326 || GET_CODE (XEXP (dest, 1)) != CONST_INT
2327 || INTVAL (XEXP (dest, 1)) != -i * 4)
2330 regno = REGNO (src);
2333 if (D_REGNO_P (regno))
2336 first_dreg_to_save = lastdreg = regno - REG_R0;
2338 else if (regno >= REG_P0 && regno <= REG_P7)
2341 first_preg_to_save = lastpreg = regno - REG_P0;
2351 if (regno >= REG_P0 && regno <= REG_P7)
2354 first_preg_to_save = lastpreg = regno - REG_P0;
2356 else if (regno != REG_R0 + lastdreg + 1)
2361 else if (group == 2)
2363 if (regno != REG_P0 + lastpreg + 1)
2372 pop_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2374 int lastdreg = 8, lastpreg = 6;
2377 for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
2379 rtx t = XVECEXP (op, 0, i);
2383 if (GET_CODE (t) != SET)
2387 dest = SET_DEST (t);
2388 if (GET_CODE (src) != MEM || ! REG_P (dest))
2390 src = XEXP (src, 0);
2394 if (! REG_P (src) || REGNO (src) != REG_SP)
2397 else if (GET_CODE (src) != PLUS
2398 || ! REG_P (XEXP (src, 0))
2399 || REGNO (XEXP (src, 0)) != REG_SP
2400 || GET_CODE (XEXP (src, 1)) != CONST_INT
2401 || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
2404 regno = REGNO (dest);
2407 if (regno == REG_R7)
2412 else if (regno != REG_P0 + lastpreg - 1)
2417 else if (group == 1)
2419 if (regno != REG_R0 + lastdreg - 1)
2425 first_dreg_to_save = lastdreg;
2426 first_preg_to_save = lastpreg;
2430 /* Emit assembly code for one multi-register push described by INSN, with
2431 operands in OPERANDS. */
2434 output_push_multiple (rtx insn, rtx *operands)
2439 /* Validate the insn again, and compute first_[dp]reg_to_save. */
2440 ok = push_multiple_operation (PATTERN (insn), VOIDmode);
2443 if (first_dreg_to_save == 8)
2444 sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
2445 else if (first_preg_to_save == 6)
2446 sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
2448 sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
2449 first_dreg_to_save, first_preg_to_save);
2451 output_asm_insn (buf, operands);
2454 /* Emit assembly code for one multi-register pop described by INSN, with
2455 operands in OPERANDS. */
2458 output_pop_multiple (rtx insn, rtx *operands)
2463 /* Validate the insn again, and compute first_[dp]reg_to_save. */
2464 ok = pop_multiple_operation (PATTERN (insn), VOIDmode);
2467 if (first_dreg_to_save == 8)
2468 sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
2469 else if (first_preg_to_save == 6)
2470 sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
2472 sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
2473 first_dreg_to_save, first_preg_to_save);
2475 output_asm_insn (buf, operands);
2478 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE. */
2481 single_move_for_movmem (rtx dst, rtx src, enum machine_mode mode, HOST_WIDE_INT offset)
2483 rtx scratch = gen_reg_rtx (mode);
2486 srcmem = adjust_address_nv (src, mode, offset);
2487 dstmem = adjust_address_nv (dst, mode, offset);
2488 emit_move_insn (scratch, srcmem);
2489 emit_move_insn (dstmem, scratch);
2492 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
2493 alignment ALIGN_EXP. Return true if successful, false if we should fall
2494 back on a different method. */
2497 bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
2499 rtx srcreg, destreg, countreg;
2500 HOST_WIDE_INT align = 0;
2501 unsigned HOST_WIDE_INT count = 0;
2503 if (GET_CODE (align_exp) == CONST_INT)
2504 align = INTVAL (align_exp);
2505 if (GET_CODE (count_exp) == CONST_INT)
2507 count = INTVAL (count_exp);
2509 if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
2514 /* If optimizing for size, only do single copies inline. */
2517 if (count == 2 && align < 2)
2519 if (count == 4 && align < 4)
2521 if (count != 1 && count != 2 && count != 4)
2524 if (align < 2 && count != 1)
2527 destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
2528 if (destreg != XEXP (dst, 0))
2529 dst = replace_equiv_address_nv (dst, destreg);
2530 srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
2531 if (srcreg != XEXP (src, 0))
2532 src = replace_equiv_address_nv (src, srcreg);
2534 if (count != 0 && align >= 2)
2536 unsigned HOST_WIDE_INT offset = 0;
2540 if ((count & ~3) == 4)
2542 single_move_for_movmem (dst, src, SImode, offset);
2545 else if (count & ~3)
2547 HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
2548 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
2550 emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
2554 single_move_for_movmem (dst, src, HImode, offset);
2560 if ((count & ~1) == 2)
2562 single_move_for_movmem (dst, src, HImode, offset);
2565 else if (count & ~1)
2567 HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
2568 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
2570 emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
2575 single_move_for_movmem (dst, src, QImode, offset);
2584 bfin_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
2586 enum attr_type insn_type, dep_insn_type;
2587 int dep_insn_code_number;
2589 /* Anti and output dependencies have zero cost. */
2590 if (REG_NOTE_KIND (link) != 0)
2593 dep_insn_code_number = recog_memoized (dep_insn);
2595 /* If we can't recognize the insns, we can't really do anything. */
2596 if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
2599 insn_type = get_attr_type (insn);
2600 dep_insn_type = get_attr_type (dep_insn);
2602 if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)
2604 rtx pat = PATTERN (dep_insn);
2605 rtx dest = SET_DEST (pat);
2606 rtx src = SET_SRC (pat);
2607 if (! ADDRESS_REGNO_P (REGNO (dest)) || ! D_REGNO_P (REGNO (src)))
2609 return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);
2615 /* We use the machine specific reorg pass for emitting CSYNC instructions
2616 after conditional branches as needed.
2618 The Blackfin is unusual in that a code sequence like
2621 may speculatively perform the load even if the condition isn't true. This
2622 happens for a branch that is predicted not taken, because the pipeline
2623 isn't flushed or stalled, so the early stages of the following instructions,
2624 which perform the memory reference, are allowed to execute before the
2625 jump condition is evaluated.
2626 Therefore, we must insert additional instructions in all places where this
2627 could lead to incorrect behavior. The manual recommends CSYNC, while
2628 VDSP seems to use NOPs (even though its corresponding compiler option is
2631 When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
2632 When optimizing for size, we turn the branch into a predicted taken one.
2633 This may be slower due to mispredicts, but saves code size. */
2638 rtx insn, last_condjump = NULL_RTX;
2639 int cycles_since_jump = INT_MAX;
2641 if (! TARGET_SPECLD_ANOMALY || ! TARGET_CSYNC_ANOMALY)
2644 /* First pass: find predicted-false branches; if something after them
2645 needs nops, insert them or change the branch to predict true. */
2646 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2650 if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
2653 pat = PATTERN (insn);
2654 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
2655 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
2656 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
2661 if (any_condjump_p (insn)
2662 && ! cbranch_predicted_taken_p (insn))
2664 last_condjump = insn;
2665 cycles_since_jump = 0;
2668 cycles_since_jump = INT_MAX;
2670 else if (INSN_P (insn))
2672 enum attr_type type = get_attr_type (insn);
2673 int delay_needed = 0;
2674 if (cycles_since_jump < INT_MAX)
2675 cycles_since_jump++;
2677 if (type == TYPE_MCLD && TARGET_SPECLD_ANOMALY)
2679 rtx pat = single_set (insn);
2680 if (may_trap_p (SET_SRC (pat)))
2683 else if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
2686 if (delay_needed > cycles_since_jump)
2690 rtx *op = recog_data.operand;
2692 delay_needed -= cycles_since_jump;
2694 extract_insn (last_condjump);
2697 pat = gen_cbranch_predicted_taken (op[0], op[1], op[2],
2699 cycles_since_jump = INT_MAX;
2702 /* Do not adjust cycles_since_jump in this case, so that
2703 we'll increase the number of NOPs for a subsequent insn
2705 pat = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
2706 GEN_INT (delay_needed));
2707 PATTERN (last_condjump) = pat;
2708 INSN_CODE (last_condjump) = recog (pat, insn, &num_clobbers);
2712 /* Second pass: for predicted-true branches, see if anything at the
2713 branch destination needs extra nops. */
2714 if (! TARGET_CSYNC_ANOMALY)
2717 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2720 && any_condjump_p (insn)
2721 && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken
2722 || cbranch_predicted_taken_p (insn)))
2724 rtx target = JUMP_LABEL (insn);
2726 cycles_since_jump = 0;
2727 for (; target && cycles_since_jump < 3; target = NEXT_INSN (target))
2731 if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
2734 pat = PATTERN (target);
2735 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
2736 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
2737 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
2740 if (INSN_P (target))
2742 enum attr_type type = get_attr_type (target);
2743 int delay_needed = 0;
2744 if (cycles_since_jump < INT_MAX)
2745 cycles_since_jump++;
2747 if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
2750 if (delay_needed > cycles_since_jump)
2752 rtx prev = prev_real_insn (label);
2753 delay_needed -= cycles_since_jump;
2755 fprintf (dump_file, "Adding %d nops after %d\n",
2756 delay_needed, INSN_UID (label));
2758 && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops)
2765 "Reducing nops on insn %d.\n",
2768 x = XVECEXP (x, 0, 1);
2769 v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed;
2770 XVECEXP (x, 0, 0) = GEN_INT (v);
2772 while (delay_needed-- > 0)
2773 emit_insn_after (gen_nop (), label);
2782 /* Handle interrupt_handler, exception_handler and nmi_handler function
2783 attributes; arguments as in struct attribute_spec.handler. */
2786 handle_int_attribute (tree *node, tree name,
2787 tree args ATTRIBUTE_UNUSED,
2788 int flags ATTRIBUTE_UNUSED,
2792 if (TREE_CODE (x) == FUNCTION_DECL)
2795 if (TREE_CODE (x) != FUNCTION_TYPE)
2797 warning (OPT_Wattributes, "%qs attribute only applies to functions",
2798 IDENTIFIER_POINTER (name));
2799 *no_add_attrs = true;
2801 else if (funkind (x) != SUBROUTINE)
2802 error ("multiple function type attributes specified");
2807 /* Return 0 if the attributes for two types are incompatible, 1 if they
2808 are compatible, and 2 if they are nearly compatible (which causes a
2809 warning to be generated). */
2812 bfin_comp_type_attributes (tree type1, tree type2)
2814 e_funkind kind1, kind2;
2816 if (TREE_CODE (type1) != FUNCTION_TYPE)
2819 kind1 = funkind (type1);
2820 kind2 = funkind (type2);
2825 /* Check for mismatched modifiers */
2826 if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
2827 != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
2830 if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
2831 != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
2834 if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
2835 != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
2838 if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1))
2839 != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2)))
2845 /* Handle a "longcall" or "shortcall" attribute; arguments as in
2846 struct attribute_spec.handler. */
2849 bfin_handle_longcall_attribute (tree *node, tree name,
2850 tree args ATTRIBUTE_UNUSED,
2851 int flags ATTRIBUTE_UNUSED,
2854 if (TREE_CODE (*node) != FUNCTION_TYPE
2855 && TREE_CODE (*node) != FIELD_DECL
2856 && TREE_CODE (*node) != TYPE_DECL)
2858 warning (OPT_Wattributes, "`%s' attribute only applies to functions",
2859 IDENTIFIER_POINTER (name));
2860 *no_add_attrs = true;
2863 if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0
2864 && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node)))
2865 || (strcmp (IDENTIFIER_POINTER (name), "shortcall") == 0
2866 && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node))))
2868 warning (OPT_Wattributes,
2869 "can't apply both longcall and shortcall attributes to the same function");
2870 *no_add_attrs = true;
2876 /* Table of valid machine attributes. */
2877 const struct attribute_spec bfin_attribute_table[] =
2879 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
2880 { "interrupt_handler", 0, 0, false, true, true, handle_int_attribute },
2881 { "exception_handler", 0, 0, false, true, true, handle_int_attribute },
2882 { "nmi_handler", 0, 0, false, true, true, handle_int_attribute },
2883 { "nesting", 0, 0, false, true, true, NULL },
2884 { "kspisusp", 0, 0, false, true, true, NULL },
2885 { "saveall", 0, 0, false, true, true, NULL },
2886 { "longcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
2887 { "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
2888 { NULL, 0, 0, false, false, false, NULL }
2891 /* Output the assembler code for a thunk function. THUNK_DECL is the
2892 declaration for the thunk function itself, FUNCTION is the decl for
2893 the target function. DELTA is an immediate constant offset to be
2894 added to THIS. If VCALL_OFFSET is nonzero, the word at
2895 *(*this + vcall_offset) should be added to THIS. */
2898 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
2899 tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
2900 HOST_WIDE_INT vcall_offset, tree function)
2903 /* The this parameter is passed as the first argument. */
2904 rtx this = gen_rtx_REG (Pmode, REG_R0);
2906 /* Adjust the this parameter by a fixed constant. */
2910 if (delta >= -64 && delta <= 63)
2912 xops[0] = GEN_INT (delta);
2913 output_asm_insn ("%1 += %0;", xops);
2915 else if (delta >= -128 && delta < -64)
2917 xops[0] = GEN_INT (delta + 64);
2918 output_asm_insn ("%1 += -64; %1 += %0;", xops);
2920 else if (delta > 63 && delta <= 126)
2922 xops[0] = GEN_INT (delta - 63);
2923 output_asm_insn ("%1 += 63; %1 += %0;", xops);
2927 xops[0] = GEN_INT (delta);
2928 output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
2932 /* Adjust the this parameter by a value stored in the vtable. */
2935 rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
2936 rtx tmp = gen_rtx_REG (Pmode, REG_R2);
2940 output_asm_insn ("%2 = r0; %2 = [%2];", xops);
2942 /* Adjust the this parameter. */
2943 xops[0] = gen_rtx_MEM (Pmode, plus_constant (p2tmp, vcall_offset));
2944 if (!memory_operand (xops[0], Pmode))
2946 rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
2947 xops[0] = GEN_INT (vcall_offset);
2949 output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
2950 xops[0] = gen_rtx_MEM (Pmode, p2tmp);
2953 output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
2956 xops[0] = XEXP (DECL_RTL (function), 0);
2957 if (1 || !flag_pic || (*targetm.binds_local_p) (function))
2958 output_asm_insn ("jump.l\t%P0", xops);
2961 /* Codes for all the Blackfin builtins. */
2969 #define def_builtin(NAME, TYPE, CODE) \
2971 lang_hooks.builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
2975 /* Set up all builtin functions for this target. */
2977 bfin_init_builtins (void)
2979 tree void_ftype_void
2980 = build_function_type (void_type_node, void_list_node);
2982 /* Add the remaining MMX insns with somewhat more complicated types. */
2983 def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC);
2984 def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC);
2987 /* Expand an expression EXP that calls a built-in function,
2988 with result going to TARGET if that's convenient
2989 (and in mode MODE if that's convenient).
2990 SUBTARGET may be used as the target for computing one of EXP's operands.
2991 IGNORE is nonzero if the value is to be ignored. */
2994 bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
2995 rtx subtarget ATTRIBUTE_UNUSED,
2996 enum machine_mode mode ATTRIBUTE_UNUSED,
2997 int ignore ATTRIBUTE_UNUSED)
2999 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
3000 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
3004 case BFIN_BUILTIN_CSYNC:
3005 emit_insn (gen_csync ());
3007 case BFIN_BUILTIN_SSYNC:
3008 emit_insn (gen_ssync ());
3016 #undef TARGET_INIT_BUILTINS
3017 #define TARGET_INIT_BUILTINS bfin_init_builtins
3019 #undef TARGET_EXPAND_BUILTIN
3020 #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
3022 #undef TARGET_ASM_GLOBALIZE_LABEL
3023 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label
3025 #undef TARGET_ASM_FILE_START
3026 #define TARGET_ASM_FILE_START output_file_start
3028 #undef TARGET_ATTRIBUTE_TABLE
3029 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
3031 #undef TARGET_COMP_TYPE_ATTRIBUTES
3032 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
3034 #undef TARGET_RTX_COSTS
3035 #define TARGET_RTX_COSTS bfin_rtx_costs
3037 #undef TARGET_ADDRESS_COST
3038 #define TARGET_ADDRESS_COST bfin_address_cost
3040 #undef TARGET_ASM_INTERNAL_LABEL
3041 #define TARGET_ASM_INTERNAL_LABEL bfin_internal_label
3043 #undef TARGET_MACHINE_DEPENDENT_REORG
3044 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
3046 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
3047 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
3049 #undef TARGET_ASM_OUTPUT_MI_THUNK
3050 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
3051 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
3052 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
3054 #undef TARGET_SCHED_ADJUST_COST
3055 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
3057 #undef TARGET_PROMOTE_PROTOTYPES
3058 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
3059 #undef TARGET_PROMOTE_FUNCTION_ARGS
3060 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
3061 #undef TARGET_PROMOTE_FUNCTION_RETURN
3062 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
3064 #undef TARGET_ARG_PARTIAL_BYTES
3065 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
3067 #undef TARGET_PASS_BY_REFERENCE
3068 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
3070 #undef TARGET_SETUP_INCOMING_VARARGS
3071 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
3073 #undef TARGET_STRUCT_VALUE_RTX
3074 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
3076 #undef TARGET_VECTOR_MODE_SUPPORTED_P
3077 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
3079 #undef TARGET_HANDLE_OPTION
3080 #define TARGET_HANDLE_OPTION bfin_handle_option
3082 #undef TARGET_DEFAULT_TARGET_FLAGS
3083 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
3085 #undef TARGET_SECONDARY_RELOAD
3086 #define TARGET_SECONDARY_RELOAD bfin_secondary_reload
3088 struct gcc_target targetm = TARGET_INITIALIZER;