1 /* The Blackfin code generation auxiliary output file.
2 Copyright (C) 2005 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"
48 #include "langhooks.h"
49 #include "bfin-protos.h"
53 /* Test and compare insns in bfin.md store the information needed to
54 generate branch and scc insns here. */
55 rtx bfin_compare_op0, bfin_compare_op1;
57 /* RTX for condition code flag register and RETS register */
58 extern GTY(()) rtx bfin_cc_rtx;
59 extern GTY(()) rtx bfin_rets_rtx;
60 rtx bfin_cc_rtx, bfin_rets_rtx;
62 int max_arg_registers = 0;
64 /* Arrays used when emitting register names. */
65 const char *short_reg_names[] = SHORT_REGISTER_NAMES;
66 const char *high_reg_names[] = HIGH_REGISTER_NAMES;
67 const char *dregs_pair_names[] = DREGS_PAIR_NAMES;
68 const char *byte_reg_names[] = BYTE_REGISTER_NAMES;
70 static int arg_regs[] = FUNCTION_ARG_REGISTERS;
72 /* Nonzero if -mshared-library-id was given. */
73 static int bfin_lib_id_given;
76 bfin_globalize_label (FILE *stream, const char *name)
78 fputs (".global ", stream);
79 assemble_name (stream, name);
85 output_file_start (void)
87 FILE *file = asm_out_file;
90 fprintf (file, ".file \"%s\";\n", input_filename);
92 for (i = 0; arg_regs[i] >= 0; i++)
94 max_arg_registers = i; /* how many arg reg used */
97 /* Called early in the compilation to conditionally modify
98 fixed_regs/call_used_regs. */
101 conditional_register_usage (void)
103 /* initialize condition code flag register rtx */
104 bfin_cc_rtx = gen_rtx_REG (BImode, REG_CC);
105 bfin_rets_rtx = gen_rtx_REG (Pmode, REG_RETS);
108 /* Examine machine-dependent attributes of function type FUNTYPE and return its
109 type. See the definition of E_FUNKIND. */
111 static e_funkind funkind (tree funtype)
113 tree attrs = TYPE_ATTRIBUTES (funtype);
114 if (lookup_attribute ("interrupt_handler", attrs))
115 return INTERRUPT_HANDLER;
116 else if (lookup_attribute ("exception_handler", attrs))
117 return EXCPT_HANDLER;
118 else if (lookup_attribute ("nmi_handler", attrs))
124 /* Legitimize PIC addresses. If the address is already position-independent,
125 we return ORIG. Newly generated position-independent addresses go into a
126 reg. This is REG if nonzero, otherwise we allocate register(s) as
127 necessary. PICREG is the register holding the pointer to the PIC offset
131 legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
136 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
138 if (GET_CODE (addr) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (addr))
144 gcc_assert (!no_new_pseudos);
145 reg = gen_reg_rtx (Pmode);
150 emit_insn (gen_movsi_high_pic (reg, addr));
151 emit_insn (gen_movsi_low_pic (reg, reg, addr));
152 emit_insn (gen_addsi3 (reg, reg, picreg));
153 new = gen_rtx_MEM (Pmode, reg);
157 rtx tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
159 new = gen_rtx_MEM (Pmode,
160 gen_rtx_PLUS (Pmode, picreg, tmp));
162 emit_move_insn (reg, new);
164 if (picreg == pic_offset_table_rtx)
165 current_function_uses_pic_offset_table = 1;
169 else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
173 if (GET_CODE (addr) == CONST)
175 addr = XEXP (addr, 0);
176 gcc_assert (GET_CODE (addr) == PLUS);
179 if (XEXP (addr, 0) == picreg)
184 gcc_assert (!no_new_pseudos);
185 reg = gen_reg_rtx (Pmode);
188 base = legitimize_pic_address (XEXP (addr, 0), reg, picreg);
189 addr = legitimize_pic_address (XEXP (addr, 1),
190 base == reg ? NULL_RTX : reg,
193 if (GET_CODE (addr) == CONST_INT)
195 gcc_assert (! reload_in_progress && ! reload_completed);
196 addr = force_reg (Pmode, addr);
199 if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
201 base = gen_rtx_PLUS (Pmode, base, XEXP (addr, 0));
202 addr = XEXP (addr, 1);
205 return gen_rtx_PLUS (Pmode, base, addr);
211 /* Stack frame layout. */
213 /* Compute the number of DREGS to save with a push_multiple operation.
214 This could include registers that aren't modified in the function,
215 since push_multiple only takes a range of registers. */
218 n_dregs_to_save (void)
222 for (i = REG_R0; i <= REG_R7; i++)
224 if (regs_ever_live[i] && ! call_used_regs[i])
225 return REG_R7 - i + 1;
227 if (current_function_calls_eh_return)
232 unsigned test = EH_RETURN_DATA_REGNO (j);
233 if (test == INVALID_REGNUM)
236 return REG_R7 - i + 1;
244 /* Like n_dregs_to_save, but compute number of PREGS to save. */
247 n_pregs_to_save (void)
251 for (i = REG_P0; i <= REG_P5; i++)
252 if ((regs_ever_live[i] && ! call_used_regs[i])
253 || (i == PIC_OFFSET_TABLE_REGNUM
254 && (current_function_uses_pic_offset_table
255 || (TARGET_ID_SHARED_LIBRARY && ! current_function_is_leaf))))
256 return REG_P5 - i + 1;
260 /* Determine if we are going to save the frame pointer in the prologue. */
263 must_save_fp_p (void)
265 return (frame_pointer_needed || regs_ever_live[REG_FP]);
269 stack_frame_needed_p (void)
271 /* EH return puts a new return address into the frame using an
272 address relative to the frame pointer. */
273 if (current_function_calls_eh_return)
275 return frame_pointer_needed;
278 /* Emit code to save registers in the prologue. SAVEALL is nonzero if we
279 must save all registers; this is used for interrupt handlers.
280 SPREG contains (reg:SI REG_SP). */
283 expand_prologue_reg_save (rtx spreg, int saveall)
285 int ndregs = saveall ? 8 : n_dregs_to_save ();
286 int npregs = saveall ? 6 : n_pregs_to_save ();
287 int dregno = REG_R7 + 1 - ndregs;
288 int pregno = REG_P5 + 1 - npregs;
289 int total = ndregs + npregs;
296 val = GEN_INT (-total * 4);
297 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total + 2));
298 XVECEXP (pat, 0, 0) = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, val),
299 UNSPEC_PUSH_MULTIPLE);
300 XVECEXP (pat, 0, total + 1) = gen_rtx_SET (VOIDmode, spreg,
301 gen_rtx_PLUS (Pmode, spreg,
303 RTX_FRAME_RELATED_P (XVECEXP (pat, 0, total + 1)) = 1;
304 for (i = 0; i < total; i++)
306 rtx memref = gen_rtx_MEM (word_mode,
307 gen_rtx_PLUS (Pmode, spreg,
308 GEN_INT (- i * 4 - 4)));
312 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
318 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
322 XVECEXP (pat, 0, i + 1) = subpat;
323 RTX_FRAME_RELATED_P (subpat) = 1;
325 insn = emit_insn (pat);
326 RTX_FRAME_RELATED_P (insn) = 1;
329 /* Emit code to restore registers in the epilogue. SAVEALL is nonzero if we
330 must save all registers; this is used for interrupt handlers.
331 SPREG contains (reg:SI REG_SP). */
334 expand_epilogue_reg_restore (rtx spreg, int saveall)
336 int ndregs = saveall ? 8 : n_dregs_to_save ();
337 int npregs = saveall ? 6 : n_pregs_to_save ();
338 int total = ndregs + npregs;
345 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total + 1));
346 XVECEXP (pat, 0, 0) = gen_rtx_SET (VOIDmode, spreg,
347 gen_rtx_PLUS (Pmode, spreg,
348 GEN_INT (total * 4)));
355 for (i = 0; i < total; i++)
358 ? gen_rtx_PLUS (Pmode, spreg, GEN_INT (i * 4))
360 rtx memref = gen_rtx_MEM (word_mode, addr);
363 XVECEXP (pat, 0, i + 1)
364 = gen_rtx_SET (VOIDmode, gen_rtx_REG (word_mode, regno), memref);
373 insn = emit_insn (pat);
374 RTX_FRAME_RELATED_P (insn) = 1;
377 /* Perform any needed actions needed for a function that is receiving a
378 variable number of arguments.
382 MODE and TYPE are the mode and type of the current parameter.
384 PRETEND_SIZE is a variable that should be set to the amount of stack
385 that must be pushed by the prolog to pretend that our caller pushed
388 Normally, this macro will push all remaining incoming registers on the
389 stack and set PRETEND_SIZE to the length of the registers pushed.
392 - VDSP C compiler manual (our ABI) says that a variable args function
393 should save the R0, R1 and R2 registers in the stack.
394 - The caller will always leave space on the stack for the
395 arguments that are passed in registers, so we dont have
396 to leave any extra space.
397 - now, the vastart pointer can access all arguments from the stack. */
400 setup_incoming_varargs (CUMULATIVE_ARGS *cum,
401 enum machine_mode mode ATTRIBUTE_UNUSED,
402 tree type ATTRIBUTE_UNUSED, int *pretend_size,
411 /* The move for named arguments will be generated automatically by the
412 compiler. We need to generate the move rtx for the unnamed arguments
413 if they are in the first 3 words. We assume at least 1 named argument
414 exists, so we never generate [ARGP] = R0 here. */
416 for (i = cum->words + 1; i < max_arg_registers; i++)
418 mem = gen_rtx_MEM (Pmode,
419 plus_constant (arg_pointer_rtx, (i * UNITS_PER_WORD)));
420 emit_move_insn (mem, gen_rtx_REG (Pmode, i));
426 /* Value should be nonzero if functions must have frame pointers.
427 Zero means the frame pointer need not be set up (and parms may
428 be accessed via the stack pointer) in functions that seem suitable. */
431 bfin_frame_pointer_required (void)
433 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
435 if (fkind != SUBROUTINE)
438 /* We turn on -fomit-frame-pointer if -momit-leaf-frame-pointer is used,
439 so we have to override it for non-leaf functions. */
440 if (TARGET_OMIT_LEAF_FRAME_POINTER && ! current_function_is_leaf)
446 /* Return the number of registers pushed during the prologue. */
449 n_regs_saved_by_prologue (void)
451 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
452 int n = n_dregs_to_save () + n_pregs_to_save ();
454 if (stack_frame_needed_p ())
455 /* We use a LINK instruction in this case. */
459 if (must_save_fp_p ())
461 if (! current_function_is_leaf)
465 if (fkind != SUBROUTINE)
467 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
468 tree all = lookup_attribute ("saveall", attrs);
471 /* Increment once for ASTAT. */
475 if (lookup_attribute ("nesting", attrs))
478 for (i = REG_P7 + 1; i < REG_CC; i++)
481 || (!leaf_function_p () && call_used_regs[i]))
482 n += i == REG_A0 || i == REG_A1 ? 2 : 1;
487 /* Return the offset between two registers, one to be eliminated, and the other
488 its replacement, at the start of a routine. */
491 bfin_initial_elimination_offset (int from, int to)
493 HOST_WIDE_INT offset = 0;
495 if (from == ARG_POINTER_REGNUM)
496 offset = n_regs_saved_by_prologue () * 4;
498 if (to == STACK_POINTER_REGNUM)
500 if (current_function_outgoing_args_size >= FIXED_STACK_AREA)
501 offset += current_function_outgoing_args_size;
502 else if (current_function_outgoing_args_size)
503 offset += FIXED_STACK_AREA;
505 offset += get_frame_size ();
511 /* Emit code to load a constant CONSTANT into register REG; setting
512 RTX_FRAME_RELATED_P on all insns we generate if RELATED is true.
513 Make sure that the insns we generate need not be split. */
516 frame_related_constant_load (rtx reg, HOST_WIDE_INT constant, bool related)
519 rtx cst = GEN_INT (constant);
521 if (constant >= -32768 && constant < 65536)
522 insn = emit_move_insn (reg, cst);
525 /* We don't call split_load_immediate here, since dwarf2out.c can get
526 confused about some of the more clever sequences it can generate. */
527 insn = emit_insn (gen_movsi_high (reg, cst));
529 RTX_FRAME_RELATED_P (insn) = 1;
530 insn = emit_insn (gen_movsi_low (reg, reg, cst));
533 RTX_FRAME_RELATED_P (insn) = 1;
536 /* Generate efficient code to add a value to the frame pointer. We
537 can use P1 as a scratch register. Set RTX_FRAME_RELATED_P on the
538 generated insns if FRAME is nonzero. */
541 add_to_sp (rtx spreg, HOST_WIDE_INT value, int frame)
546 /* Choose whether to use a sequence using a temporary register, or
547 a sequence with multiple adds. We can add a signed 7 bit value
548 in one instruction. */
549 if (value > 120 || value < -120)
551 rtx tmpreg = gen_rtx_REG (SImode, REG_P1);
555 frame_related_constant_load (tmpreg, value, TRUE);
558 insn = emit_move_insn (tmpreg, GEN_INT (value));
560 RTX_FRAME_RELATED_P (insn) = 1;
563 insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg));
565 RTX_FRAME_RELATED_P (insn) = 1;
576 /* We could use -62, but that would leave the stack unaligned, so
580 insn = emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (size)));
582 RTX_FRAME_RELATED_P (insn) = 1;
588 /* Generate a LINK insn for a frame sized FRAME_SIZE. If this constant
589 is too large, generate a sequence of insns that has the same effect.
590 SPREG contains (reg:SI REG_SP). */
593 emit_link_insn (rtx spreg, HOST_WIDE_INT frame_size)
595 HOST_WIDE_INT link_size = frame_size;
599 if (link_size > 262140)
602 /* Use a LINK insn with as big a constant as possible, then subtract
603 any remaining size from the SP. */
604 insn = emit_insn (gen_link (GEN_INT (-8 - link_size)));
605 RTX_FRAME_RELATED_P (insn) = 1;
607 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
609 rtx set = XVECEXP (PATTERN (insn), 0, i);
610 gcc_assert (GET_CODE (set) == SET);
611 RTX_FRAME_RELATED_P (set) = 1;
614 frame_size -= link_size;
618 /* Must use a call-clobbered PREG that isn't the static chain. */
619 rtx tmpreg = gen_rtx_REG (Pmode, REG_P1);
621 frame_related_constant_load (tmpreg, -frame_size, TRUE);
622 insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg));
623 RTX_FRAME_RELATED_P (insn) = 1;
627 /* Return the number of bytes we must reserve for outgoing arguments
628 in the current function's stack frame. */
633 if (current_function_outgoing_args_size)
635 if (current_function_outgoing_args_size >= FIXED_STACK_AREA)
636 return current_function_outgoing_args_size;
638 return FIXED_STACK_AREA;
643 /* Save RETS and FP, and allocate a stack frame. */
646 do_link (rtx spreg, HOST_WIDE_INT frame_size)
648 frame_size += arg_area_size ();
650 if (stack_frame_needed_p ()
651 || (must_save_fp_p () && ! current_function_is_leaf))
652 emit_link_insn (spreg, frame_size);
655 if (! current_function_is_leaf)
657 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
658 gen_rtx_PRE_DEC (Pmode, spreg)),
660 rtx insn = emit_insn (pat);
661 RTX_FRAME_RELATED_P (insn) = 1;
663 if (must_save_fp_p ())
665 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
666 gen_rtx_PRE_DEC (Pmode, spreg)),
667 gen_rtx_REG (Pmode, REG_FP));
668 rtx insn = emit_insn (pat);
669 RTX_FRAME_RELATED_P (insn) = 1;
671 add_to_sp (spreg, -frame_size, 1);
675 /* Like do_link, but used for epilogues to deallocate the stack frame. */
678 do_unlink (rtx spreg, HOST_WIDE_INT frame_size)
680 frame_size += arg_area_size ();
682 if (stack_frame_needed_p ())
683 emit_insn (gen_unlink ());
686 rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg));
688 add_to_sp (spreg, frame_size, 0);
689 if (must_save_fp_p ())
691 rtx fpreg = gen_rtx_REG (Pmode, REG_FP);
692 emit_move_insn (fpreg, postinc);
693 emit_insn (gen_rtx_USE (VOIDmode, fpreg));
695 if (! current_function_is_leaf)
697 emit_move_insn (bfin_rets_rtx, postinc);
698 emit_insn (gen_rtx_USE (VOIDmode, bfin_rets_rtx));
703 /* Generate a prologue suitable for a function of kind FKIND. This is
704 called for interrupt and exception handler prologues.
705 SPREG contains (reg:SI REG_SP). */
708 expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind)
711 HOST_WIDE_INT frame_size = get_frame_size ();
712 rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
713 rtx predec = gen_rtx_MEM (SImode, predec1);
715 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
716 tree all = lookup_attribute ("saveall", attrs);
717 tree kspisusp = lookup_attribute ("kspisusp", attrs);
721 insn = emit_move_insn (spreg, gen_rtx_REG (Pmode, REG_USP));
722 RTX_FRAME_RELATED_P (insn) = 1;
725 /* We need space on the stack in case we need to save the argument
727 if (fkind == EXCPT_HANDLER)
729 insn = emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (-12)));
730 RTX_FRAME_RELATED_P (insn) = 1;
733 insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
734 RTX_FRAME_RELATED_P (insn) = 1;
736 expand_prologue_reg_save (spreg, all != NULL_TREE);
738 for (i = REG_P7 + 1; i < REG_CC; i++)
741 || (!leaf_function_p () && call_used_regs[i]))
743 if (i == REG_A0 || i == REG_A1)
744 insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1),
745 gen_rtx_REG (PDImode, i));
747 insn = emit_move_insn (predec, gen_rtx_REG (SImode, i));
748 RTX_FRAME_RELATED_P (insn) = 1;
751 if (lookup_attribute ("nesting", attrs))
753 rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
754 : fkind == NMI_HANDLER ? REG_RETN
756 insn = emit_move_insn (predec, srcreg);
757 RTX_FRAME_RELATED_P (insn) = 1;
760 do_link (spreg, frame_size);
762 if (fkind == EXCPT_HANDLER)
764 rtx r0reg = gen_rtx_REG (SImode, REG_R0);
765 rtx r1reg = gen_rtx_REG (SImode, REG_R1);
766 rtx r2reg = gen_rtx_REG (SImode, REG_R2);
769 insn = emit_move_insn (r0reg, gen_rtx_REG (SImode, REG_SEQSTAT));
770 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
772 insn = emit_insn (gen_ashrsi3 (r0reg, r0reg, GEN_INT (26)));
773 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
775 insn = emit_insn (gen_ashlsi3 (r0reg, r0reg, GEN_INT (26)));
776 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
778 insn = emit_move_insn (r1reg, spreg);
779 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
781 insn = emit_move_insn (r2reg, gen_rtx_REG (Pmode, REG_FP));
782 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
784 insn = emit_insn (gen_addsi3 (r2reg, r2reg, GEN_INT (8)));
785 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
790 /* Generate an epilogue suitable for a function of kind FKIND. This is
791 called for interrupt and exception handler epilogues.
792 SPREG contains (reg:SI REG_SP). */
795 expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind)
798 rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
799 rtx postinc = gen_rtx_MEM (SImode, postinc1);
800 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
801 tree all = lookup_attribute ("saveall", attrs);
803 /* A slightly crude technique to stop flow from trying to delete "dead"
805 MEM_VOLATILE_P (postinc) = 1;
807 do_unlink (spreg, get_frame_size ());
809 if (lookup_attribute ("nesting", attrs))
811 rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
812 : fkind == NMI_HANDLER ? REG_RETN
814 emit_move_insn (srcreg, postinc);
817 for (i = REG_CC - 1; i > REG_P7; i--)
820 || (!leaf_function_p () && call_used_regs[i]))
822 if (i == REG_A0 || i == REG_A1)
824 rtx mem = gen_rtx_MEM (PDImode, postinc1);
825 MEM_VOLATILE_P (mem) = 1;
826 emit_move_insn (gen_rtx_REG (PDImode, i), mem);
829 emit_move_insn (gen_rtx_REG (SImode, i), postinc);
832 expand_epilogue_reg_restore (spreg, all != NULL_TREE);
834 emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
836 /* Deallocate any space we left on the stack in case we needed to save the
837 argument registers. */
838 if (fkind == EXCPT_HANDLER)
839 emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (12)));
841 emit_jump_insn (gen_return_internal (GEN_INT (fkind)));
844 /* Used while emitting the prologue to generate code to load the correct value
845 into the PIC register, which is passed in DEST. */
848 bfin_load_pic_reg (rtx dest)
852 if (bfin_lib_id_given)
853 addr = plus_constant (pic_offset_table_rtx, -4 - bfin_library_id * 4);
855 addr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
856 gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
857 UNSPEC_LIBRARY_OFFSET));
858 insn = emit_insn (gen_movsi (dest, gen_rtx_MEM (Pmode, addr)));
859 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
862 /* Generate RTL for the prologue of the current function. */
865 bfin_expand_prologue (void)
868 HOST_WIDE_INT frame_size = get_frame_size ();
869 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
870 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
871 rtx pic_reg_loaded = NULL_RTX;
873 if (fkind != SUBROUTINE)
875 expand_interrupt_handler_prologue (spreg, fkind);
879 if (current_function_limit_stack)
882 = bfin_initial_elimination_offset (ARG_POINTER_REGNUM,
883 STACK_POINTER_REGNUM);
884 rtx lim = stack_limit_rtx;
886 if (GET_CODE (lim) == SYMBOL_REF)
888 rtx p2reg = gen_rtx_REG (Pmode, REG_P2);
889 if (TARGET_ID_SHARED_LIBRARY)
891 rtx p1reg = gen_rtx_REG (Pmode, REG_P1);
892 rtx r3reg = gen_rtx_REG (Pmode, REG_R3);
894 pic_reg_loaded = p2reg;
895 bfin_load_pic_reg (pic_reg_loaded);
896 val = legitimize_pic_address (stack_limit_rtx, p1reg, p2reg);
897 emit_move_insn (p1reg, val);
898 frame_related_constant_load (p2reg, offset, FALSE);
899 emit_insn (gen_addsi3 (p2reg, p2reg, p1reg));
904 rtx limit = plus_constant (stack_limit_rtx, offset);
905 emit_move_insn (p2reg, limit);
909 emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim));
910 emit_insn (gen_trapifcc ());
912 expand_prologue_reg_save (spreg, 0);
914 do_link (spreg, frame_size);
916 if (TARGET_ID_SHARED_LIBRARY
917 && (current_function_uses_pic_offset_table
918 || !current_function_is_leaf))
919 bfin_load_pic_reg (pic_offset_table_rtx);
922 /* Generate RTL for the epilogue of the current function. NEED_RETURN is zero
923 if this is for a sibcall. EH_RETURN is nonzero if we're expanding an
924 eh_return pattern. */
927 bfin_expand_epilogue (int need_return, int eh_return)
929 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
930 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
932 if (fkind != SUBROUTINE)
934 expand_interrupt_handler_epilogue (spreg, fkind);
938 do_unlink (spreg, get_frame_size ());
940 expand_epilogue_reg_restore (spreg, 0);
942 /* Omit the return insn if this is for a sibcall. */
947 emit_insn (gen_addsi3 (spreg, spreg, gen_rtx_REG (Pmode, REG_P2)));
949 emit_jump_insn (gen_return_internal (GEN_INT (SUBROUTINE)));
952 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
955 bfin_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
956 unsigned int new_reg)
958 /* Interrupt functions can only use registers that have already been
959 saved by the prologue, even if they would normally be
962 if (funkind (TREE_TYPE (current_function_decl)) != SUBROUTINE
963 && !regs_ever_live[new_reg])
969 /* Return the value of the return address for the frame COUNT steps up
970 from the current frame, after the prologue.
971 We punt for everything but the current frame by returning const0_rtx. */
974 bfin_return_addr_rtx (int count)
979 return get_hard_reg_initial_val (Pmode, REG_RETS);
982 /* Try machine-dependent ways of modifying an illegitimate address X
983 to be legitimate. If we find one, return the new, valid address,
984 otherwise return NULL_RTX.
986 OLDX is the address as it was before break_out_memory_refs was called.
987 In some cases it is useful to look at this to decide what needs to be done.
989 MODE is the mode of the memory reference. */
992 legitimize_address (rtx x ATTRIBUTE_UNUSED, rtx oldx ATTRIBUTE_UNUSED,
993 enum machine_mode mode ATTRIBUTE_UNUSED)
998 /* This predicate is used to compute the length of a load/store insn.
999 OP is a MEM rtx, we return nonzero if its addressing mode requires a
1000 32 bit instruction. */
1003 effective_address_32bit_p (rtx op, enum machine_mode mode)
1005 HOST_WIDE_INT offset;
1007 mode = GET_MODE (op);
1010 if (GET_CODE (op) != PLUS)
1012 gcc_assert (REG_P (op) || GET_CODE (op) == POST_INC
1013 || GET_CODE (op) == PRE_DEC || GET_CODE (op) == POST_DEC);
1017 offset = INTVAL (XEXP (op, 1));
1019 /* All byte loads use a 16 bit offset. */
1020 if (GET_MODE_SIZE (mode) == 1)
1023 if (GET_MODE_SIZE (mode) == 4)
1025 /* Frame pointer relative loads can use a negative offset, all others
1026 are restricted to a small positive one. */
1027 if (XEXP (op, 0) == frame_pointer_rtx)
1028 return offset < -128 || offset > 60;
1029 return offset < 0 || offset > 60;
1032 /* Must be HImode now. */
1033 return offset < 0 || offset > 30;
1036 /* Return cost of the memory address ADDR.
1037 All addressing modes are equally cheap on the Blackfin. */
1040 bfin_address_cost (rtx addr ATTRIBUTE_UNUSED)
1045 /* Subroutine of print_operand; used to print a memory reference X to FILE. */
1048 print_address_operand (FILE *file, rtx x)
1050 switch (GET_CODE (x))
1053 output_address (XEXP (x, 0));
1054 fprintf (file, "+");
1055 output_address (XEXP (x, 1));
1059 fprintf (file, "--");
1060 output_address (XEXP (x, 0));
1063 output_address (XEXP (x, 0));
1064 fprintf (file, "++");
1067 output_address (XEXP (x, 0));
1068 fprintf (file, "--");
1072 gcc_assert (GET_CODE (x) != MEM);
1073 print_operand (file, x, 0);
1078 /* Adding intp DImode support by Tony
1084 print_operand (FILE *file, rtx x, char code)
1086 enum machine_mode mode = GET_MODE (x);
1091 switch (GET_CODE (x))
1094 fprintf (file, "e");
1097 fprintf (file, "ne");
1100 fprintf (file, "g");
1103 fprintf (file, "l");
1106 fprintf (file, "ge");
1109 fprintf (file, "le");
1112 fprintf (file, "g");
1115 fprintf (file, "l");
1118 fprintf (file, "ge");
1121 fprintf (file, "le");
1124 output_operand_lossage ("invalid %%j value");
1128 case 'J': /* reverse logic */
1129 switch (GET_CODE(x))
1132 fprintf (file, "ne");
1135 fprintf (file, "e");
1138 fprintf (file, "le");
1141 fprintf (file, "ge");
1144 fprintf (file, "l");
1147 fprintf (file, "g");
1150 fprintf (file, "le");
1153 fprintf (file, "ge");
1156 fprintf (file, "l");
1159 fprintf (file, "g");
1162 output_operand_lossage ("invalid %%J value");
1167 switch (GET_CODE (x))
1172 gcc_assert (REGNO (x) < 32);
1173 fprintf (file, "%s", short_reg_names[REGNO (x)]);
1174 /*fprintf (file, "\n%d\n ", REGNO (x));*/
1177 else if (code == 'd')
1179 gcc_assert (REGNO (x) < 32);
1180 fprintf (file, "%s", high_reg_names[REGNO (x)]);
1183 else if (code == 'w')
1185 gcc_assert (REGNO (x) == REG_A0 || REGNO (x) == REG_A1);
1186 fprintf (file, "%s.w", reg_names[REGNO (x)]);
1188 else if (code == 'x')
1190 gcc_assert (REGNO (x) == REG_A0 || REGNO (x) == REG_A1);
1191 fprintf (file, "%s.x", reg_names[REGNO (x)]);
1193 else if (code == 'D')
1195 fprintf (file, "%s", dregs_pair_names[REGNO (x)]);
1197 else if (code == 'H')
1199 gcc_assert (mode == DImode || mode == DFmode);
1200 gcc_assert (REG_P (x));
1201 fprintf (file, "%s", reg_names[REGNO (x) + 1]);
1203 else if (code == 'T')
1205 gcc_assert (D_REGNO_P (REGNO (x)));
1206 fprintf (file, "%s", byte_reg_names[REGNO (x)]);
1209 fprintf (file, "%s", reg_names[REGNO (x)]);
1215 print_address_operand (file, x);
1220 /* Moves to half registers with d or h modifiers always use unsigned
1223 x = GEN_INT ((INTVAL (x) >> 16) & 0xffff);
1224 else if (code == 'h')
1225 x = GEN_INT (INTVAL (x) & 0xffff);
1226 else if (code == 'X')
1227 x = GEN_INT (exact_log2 (0xffffffff & INTVAL (x)));
1228 else if (code == 'Y')
1229 x = GEN_INT (exact_log2 (0xffffffff & ~INTVAL (x)));
1230 else if (code == 'Z')
1231 /* Used for LINK insns. */
1232 x = GEN_INT (-8 - INTVAL (x));
1237 output_addr_const (file, x);
1238 if (code == 'G' && flag_pic)
1239 fprintf (file, "@GOT");
1243 output_operand_lossage ("invalid const_double operand");
1247 switch (XINT (x, 1))
1249 case UNSPEC_MOVE_PIC:
1250 output_addr_const (file, XVECEXP (x, 0, 0));
1251 fprintf (file, "@GOT");
1254 case UNSPEC_LIBRARY_OFFSET:
1255 fprintf (file, "_current_shared_library_p5_offset_");
1264 output_addr_const (file, x);
1269 /* Argument support functions. */
1271 /* Initialize a variable CUM of type CUMULATIVE_ARGS
1272 for a call to a function whose data type is FNTYPE.
1273 For a library call, FNTYPE is 0.
1274 VDSP C Compiler manual, our ABI says that
1275 first 3 words of arguments will use R0, R1 and R2.
1279 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
1280 rtx libname ATTRIBUTE_UNUSED)
1282 static CUMULATIVE_ARGS zero_cum;
1286 /* Set up the number of registers to use for passing arguments. */
1288 cum->nregs = max_arg_registers;
1289 cum->arg_regs = arg_regs;
1291 cum->call_cookie = CALL_NORMAL;
1292 /* Check for a longcall attribute. */
1293 if (fntype && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype)))
1294 cum->call_cookie |= CALL_SHORT;
1295 else if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)))
1296 cum->call_cookie |= CALL_LONG;
1301 /* Update the data in CUM to advance over an argument
1302 of mode MODE and data type TYPE.
1303 (TYPE is null for libcalls where that information may not be available.) */
1306 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1307 int named ATTRIBUTE_UNUSED)
1309 int count, bytes, words;
1311 bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1312 words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1314 cum->words += words;
1315 cum->nregs -= words;
1317 if (cum->nregs <= 0)
1320 cum->arg_regs = NULL;
1324 for (count = 1; count <= words; count++)
1331 /* Define where to put the arguments to a function.
1332 Value is zero to push the argument on the stack,
1333 or a hard register in which to store the argument.
1335 MODE is the argument's machine mode.
1336 TYPE is the data type of the argument (as a tree).
1337 This is null for libcalls where that information may
1339 CUM is a variable of type CUMULATIVE_ARGS which gives info about
1340 the preceding args and about the function being called.
1341 NAMED is nonzero if this argument is a named parameter
1342 (otherwise it is an extra parameter matching an ellipsis). */
1345 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1346 int named ATTRIBUTE_UNUSED)
1349 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1351 if (mode == VOIDmode)
1352 /* Compute operand 2 of the call insn. */
1353 return GEN_INT (cum->call_cookie);
1359 return gen_rtx_REG (mode, *(cum->arg_regs));
1364 /* For an arg passed partly in registers and partly in memory,
1365 this is the number of bytes passed in registers.
1366 For args passed entirely in registers or entirely in memory, zero.
1368 Refer VDSP C Compiler manual, our ABI.
1369 First 3 words are in registers. So, if a an argument is larger
1370 than the registers available, it will span the register and
1374 bfin_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1375 tree type ATTRIBUTE_UNUSED,
1376 bool named ATTRIBUTE_UNUSED)
1379 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1380 int bytes_left = cum->nregs * UNITS_PER_WORD;
1385 if (bytes_left == 0)
1387 if (bytes > bytes_left)
1392 /* Variable sized types are passed by reference. */
1395 bfin_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
1396 enum machine_mode mode ATTRIBUTE_UNUSED,
1397 tree type, bool named ATTRIBUTE_UNUSED)
1399 return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
1402 /* Decide whether a type should be returned in memory (true)
1403 or in a register (false). This is called by the macro
1404 RETURN_IN_MEMORY. */
1407 bfin_return_in_memory (tree type)
1409 int size = int_size_in_bytes (type);
1410 return size > 2 * UNITS_PER_WORD || size == -1;
1413 /* Register in which address to store a structure value
1414 is passed to a function. */
1416 bfin_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
1417 int incoming ATTRIBUTE_UNUSED)
1419 return gen_rtx_REG (Pmode, REG_P0);
1422 /* Return true when register may be used to pass function parameters. */
1425 function_arg_regno_p (int n)
1428 for (i = 0; arg_regs[i] != -1; i++)
1429 if (n == arg_regs[i])
1434 /* Returns 1 if OP contains a symbol reference */
1437 symbolic_reference_mentioned_p (rtx op)
1439 register const char *fmt;
1442 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
1445 fmt = GET_RTX_FORMAT (GET_CODE (op));
1446 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
1452 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
1453 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
1457 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
1464 /* Decide whether we can make a sibling call to a function. DECL is the
1465 declaration of the function being targeted by the call and EXP is the
1466 CALL_EXPR representing the call. */
1469 bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
1470 tree exp ATTRIBUTE_UNUSED)
1475 /* Emit RTL insns to initialize the variable parts of a trampoline at
1476 TRAMP. FNADDR is an RTX for the address of the function's pure
1477 code. CXT is an RTX for the static chain value for the function. */
1480 initialize_trampoline (tramp, fnaddr, cxt)
1481 rtx tramp, fnaddr, cxt;
1483 rtx t1 = copy_to_reg (fnaddr);
1484 rtx t2 = copy_to_reg (cxt);
1487 addr = memory_address (Pmode, plus_constant (tramp, 2));
1488 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
1489 emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16)));
1490 addr = memory_address (Pmode, plus_constant (tramp, 6));
1491 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
1493 addr = memory_address (Pmode, plus_constant (tramp, 10));
1494 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
1495 emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16)));
1496 addr = memory_address (Pmode, plus_constant (tramp, 14));
1497 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
1500 /* Emit insns to move operands[1] into operands[0]. */
1503 emit_pic_move (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
1505 rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
1507 if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
1508 operands[1] = force_reg (SImode, operands[1]);
1510 operands[1] = legitimize_pic_address (operands[1], temp,
1511 pic_offset_table_rtx);
1514 /* Expand a move operation in mode MODE. The operands are in OPERANDS. */
1517 expand_move (rtx *operands, enum machine_mode mode)
1519 if (flag_pic && SYMBOLIC_CONST (operands[1]))
1520 emit_pic_move (operands, mode);
1522 /* Don't generate memory->memory or constant->memory moves, go through a
1524 else if ((reload_in_progress | reload_completed) == 0
1525 && GET_CODE (operands[0]) == MEM
1526 && GET_CODE (operands[1]) != REG)
1527 operands[1] = force_reg (mode, operands[1]);
1530 /* Split one or more DImode RTL references into pairs of SImode
1531 references. The RTL can be REG, offsettable MEM, integer constant, or
1532 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
1533 split and "num" is its length. lo_half and hi_half are output arrays
1534 that parallel "operands". */
1537 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
1541 rtx op = operands[num];
1543 /* simplify_subreg refuse to split volatile memory addresses,
1544 but we still have to handle it. */
1545 if (GET_CODE (op) == MEM)
1547 lo_half[num] = adjust_address (op, SImode, 0);
1548 hi_half[num] = adjust_address (op, SImode, 4);
1552 lo_half[num] = simplify_gen_subreg (SImode, op,
1553 GET_MODE (op) == VOIDmode
1554 ? DImode : GET_MODE (op), 0);
1555 hi_half[num] = simplify_gen_subreg (SImode, op,
1556 GET_MODE (op) == VOIDmode
1557 ? DImode : GET_MODE (op), 4);
1563 bfin_longcall_p (rtx op, int call_cookie)
1565 gcc_assert (GET_CODE (op) == SYMBOL_REF);
1566 if (call_cookie & CALL_SHORT)
1568 if (call_cookie & CALL_LONG)
1570 if (TARGET_LONG_CALLS)
1575 /* Expand a call instruction. FNADDR is the call target, RETVAL the return value.
1576 COOKIE is a CONST_INT holding the call_cookie prepared init_cumulative_args.
1577 SIBCALL is nonzero if this is a sibling call. */
1580 bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
1582 rtx use = NULL, call;
1583 rtx callee = XEXP (fnaddr, 0);
1584 rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (sibcall ? 3 : 2));
1586 /* In an untyped call, we can get NULL for operand 2. */
1587 if (cookie == NULL_RTX)
1588 cookie = const0_rtx;
1590 /* Static functions and indirect calls don't need the pic register. */
1592 && GET_CODE (callee) == SYMBOL_REF
1593 && !SYMBOL_REF_LOCAL_P (callee))
1594 use_reg (&use, pic_offset_table_rtx);
1596 if ((!register_no_elim_operand (callee, Pmode)
1597 && GET_CODE (callee) != SYMBOL_REF)
1598 || (GET_CODE (callee) == SYMBOL_REF
1600 || bfin_longcall_p (callee, INTVAL (cookie)))))
1602 callee = copy_to_mode_reg (Pmode, callee);
1603 fnaddr = gen_rtx_MEM (Pmode, callee);
1605 call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
1608 call = gen_rtx_SET (VOIDmode, retval, call);
1610 XVECEXP (pat, 0, 0) = call;
1611 XVECEXP (pat, 0, 1) = gen_rtx_USE (VOIDmode, cookie);
1613 XVECEXP (pat, 0, 2) = gen_rtx_RETURN (VOIDmode);
1614 call = emit_call_insn (pat);
1616 CALL_INSN_FUNCTION_USAGE (call) = use;
1619 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
1622 hard_regno_mode_ok (int regno, enum machine_mode mode)
1624 /* Allow only dregs to store value of mode HI or QI */
1625 enum reg_class class = REGNO_REG_CLASS (regno);
1630 if (mode == V2HImode)
1631 return D_REGNO_P (regno);
1632 if (class == CCREGS)
1633 return mode == BImode;
1634 if (mode == PDImode)
1635 return regno == REG_A0 || regno == REG_A1;
1637 && TEST_HARD_REG_BIT (reg_class_contents[PROLOGUE_REGS], regno))
1640 return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno);
1643 /* Implements target hook vector_mode_supported_p. */
1646 bfin_vector_mode_supported_p (enum machine_mode mode)
1648 return mode == V2HImode;
1651 /* Return the cost of moving data from a register in class CLASS1 to
1652 one in class CLASS2. A cost of 2 is the default. */
1655 bfin_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
1656 enum reg_class class1, enum reg_class class2)
1658 /* If optimizing for size, always prefer reg-reg over reg-memory moves. */
1662 /* There are some stalls involved when moving from a DREG to a different
1663 class reg, and using the value in one of the following instructions.
1664 Attempt to model this by slightly discouraging such moves. */
1665 if (class1 == DREGS && class2 != DREGS)
1671 /* Return the cost of moving data of mode M between a
1672 register and memory. A value of 2 is the default; this cost is
1673 relative to those in `REGISTER_MOVE_COST'.
1675 ??? In theory L1 memory has single-cycle latency. We should add a switch
1676 that tells the compiler whether we expect to use only L1 memory for the
1677 program; it'll make the costs more accurate. */
1680 bfin_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
1681 enum reg_class class,
1682 int in ATTRIBUTE_UNUSED)
1684 /* Make memory accesses slightly more expensive than any register-register
1685 move. Also, penalize non-DP registers, since they need secondary
1686 reloads to load and store. */
1687 if (! reg_class_subset_p (class, DPREGS))
1693 /* Inform reload about cases where moving X with a mode MODE to a register in
1694 CLASS requires an extra scratch register. Return the class needed for the
1695 scratch register. */
1698 secondary_input_reload_class (enum reg_class class, enum machine_mode mode,
1701 /* If we have HImode or QImode, we can only use DREGS as secondary registers;
1702 in most other cases we can also use PREGS. */
1703 enum reg_class default_class = GET_MODE_SIZE (mode) >= 4 ? DPREGS : DREGS;
1704 enum reg_class x_class = NO_REGS;
1705 enum rtx_code code = GET_CODE (x);
1708 x = SUBREG_REG (x), code = GET_CODE (x);
1711 int regno = REGNO (x);
1712 if (regno >= FIRST_PSEUDO_REGISTER)
1713 regno = reg_renumber[regno];
1718 x_class = REGNO_REG_CLASS (regno);
1721 /* We can be asked to reload (plus (FP) (large_constant)) into a DREG.
1722 This happens as a side effect of register elimination, and we need
1723 a scratch register to do it. */
1724 if (fp_plus_const_operand (x, mode))
1726 rtx op2 = XEXP (x, 1);
1727 int large_constant_p = ! CONST_7BIT_IMM_P (INTVAL (op2));
1729 if (class == PREGS || class == PREGS_CLOBBERED)
1731 /* If destination is a DREG, we can do this without a scratch register
1732 if the constant is valid for an add instruction. */
1733 if (class == DREGS || class == DPREGS)
1734 return large_constant_p ? PREGS : NO_REGS;
1735 /* Reloading to anything other than a DREG? Use a PREG scratch
1740 /* Data can usually be moved freely between registers of most classes.
1741 AREGS are an exception; they can only move to or from another register
1742 in AREGS or one in DREGS. They can also be assigned the constant 0. */
1743 if (x_class == AREGS)
1744 return class == DREGS || class == AREGS ? NO_REGS : DREGS;
1748 if (x != const0_rtx && x_class != DREGS)
1754 /* CCREGS can only be moved from/to DREGS. */
1755 if (class == CCREGS && x_class != DREGS)
1757 if (x_class == CCREGS && class != DREGS)
1759 /* All registers other than AREGS can load arbitrary constants. The only
1760 case that remains is MEM. */
1762 if (! reg_class_subset_p (class, default_class))
1763 return default_class;
1767 /* Like secondary_input_reload_class; and all we do is call that function. */
1770 secondary_output_reload_class (enum reg_class class, enum machine_mode mode,
1773 return secondary_input_reload_class (class, mode, x);
1776 /* Implement TARGET_HANDLE_OPTION. */
1779 bfin_handle_option (size_t code, const char *arg, int value)
1783 case OPT_mshared_library_id_:
1784 if (value > MAX_LIBRARY_ID)
1785 error ("-mshared-library-id=%s is not between 0 and %d",
1786 arg, MAX_LIBRARY_ID);
1787 bfin_lib_id_given = 1;
1795 /* Implement the macro OVERRIDE_OPTIONS. */
1798 override_options (void)
1800 if (TARGET_OMIT_LEAF_FRAME_POINTER)
1801 flag_omit_frame_pointer = 1;
1803 /* Library identification */
1804 if (bfin_lib_id_given && ! TARGET_ID_SHARED_LIBRARY)
1805 error ("-mshared-library-id= specified without -mid-shared-library");
1807 if (TARGET_ID_SHARED_LIBRARY)
1808 /* ??? Provide a way to use a bigger GOT. */
1811 flag_schedule_insns = 0;
1814 /* Return the destination address of BRANCH.
1815 We need to use this instead of get_attr_length, because the
1816 cbranch_with_nops pattern conservatively sets its length to 6, and
1817 we still prefer to use shorter sequences. */
1820 branch_dest (rtx branch)
1824 rtx pat = PATTERN (branch);
1825 if (GET_CODE (pat) == PARALLEL)
1826 pat = XVECEXP (pat, 0, 0);
1827 dest = SET_SRC (pat);
1828 if (GET_CODE (dest) == IF_THEN_ELSE)
1829 dest = XEXP (dest, 1);
1830 dest = XEXP (dest, 0);
1831 dest_uid = INSN_UID (dest);
1832 return INSN_ADDRESSES (dest_uid);
1835 /* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates
1836 it's a branch that's predicted taken. */
1839 cbranch_predicted_taken_p (rtx insn)
1841 rtx x = find_reg_note (insn, REG_BR_PROB, 0);
1845 int pred_val = INTVAL (XEXP (x, 0));
1847 return pred_val >= REG_BR_PROB_BASE / 2;
1853 /* Templates for use by asm_conditional_branch. */
1855 static const char *ccbranch_templates[][3] = {
1856 { "if !cc jump %3;", "if cc jump 4 (bp); jump.s %3;", "if cc jump 6 (bp); jump.l %3;" },
1857 { "if cc jump %3;", "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" },
1858 { "if !cc jump %3 (bp);", "if cc jump 4; jump.s %3;", "if cc jump 6; jump.l %3;" },
1859 { "if cc jump %3 (bp);", "if !cc jump 4; jump.s %3;", "if !cc jump 6; jump.l %3;" },
1862 /* Output INSN, which is a conditional branch instruction with operands
1865 We deal with the various forms of conditional branches that can be generated
1866 by bfin_reorg to prevent the hardware from doing speculative loads, by
1867 - emitting a sufficient number of nops, if N_NOPS is nonzero, or
1868 - always emitting the branch as predicted taken, if PREDICT_TAKEN is true.
1869 Either of these is only necessary if the branch is short, otherwise the
1870 template we use ends in an unconditional jump which flushes the pipeline
1874 asm_conditional_branch (rtx insn, rtx *operands, int n_nops, int predict_taken)
1876 int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
1877 /* Note : offset for instructions like if cc jmp; jump.[sl] offset
1878 is to be taken from start of if cc rather than jump.
1879 Range for jump.s is (-4094, 4096) instead of (-4096, 4094)
1881 int len = (offset >= -1024 && offset <= 1022 ? 0
1882 : offset >= -4094 && offset <= 4096 ? 1
1884 int bp = predict_taken && len == 0 ? 1 : cbranch_predicted_taken_p (insn);
1885 int idx = (bp << 1) | (GET_CODE (operands[0]) == EQ ? BRF : BRT);
1886 output_asm_insn (ccbranch_templates[idx][len], operands);
1887 gcc_assert (n_nops == 0 || !bp);
1889 while (n_nops-- > 0)
1890 output_asm_insn ("nop;", NULL);
1893 /* Emit rtl for a comparison operation CMP in mode MODE. Operands have been
1894 stored in bfin_compare_op0 and bfin_compare_op1 already. */
1897 bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED)
1899 enum rtx_code code1, code2;
1900 rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1;
1901 rtx tem = bfin_cc_rtx;
1902 enum rtx_code code = GET_CODE (cmp);
1904 /* If we have a BImode input, then we already have a compare result, and
1905 do not need to emit another comparison. */
1906 if (GET_MODE (op0) == BImode)
1908 gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
1909 tem = op0, code2 = code;
1914 /* bfin has these conditions */
1924 code1 = reverse_condition (code);
1928 emit_insn (gen_rtx_SET (BImode, tem,
1929 gen_rtx_fmt_ee (code1, BImode, op0, op1)));
1932 return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode));
1935 /* Return nonzero iff C has exactly one bit set if it is interpreted
1936 as a 32 bit constant. */
1939 log2constp (unsigned HOST_WIDE_INT c)
1942 return c != 0 && (c & (c-1)) == 0;
1945 /* Returns the number of consecutive least significant zeros in the binary
1946 representation of *V.
1947 We modify *V to contain the original value arithmetically shifted right by
1948 the number of zeroes. */
1951 shiftr_zero (HOST_WIDE_INT *v)
1953 unsigned HOST_WIDE_INT tmp = *v;
1954 unsigned HOST_WIDE_INT sgn;
1960 sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1));
1961 while ((tmp & 0x1) == 0 && n <= 32)
1963 tmp = (tmp >> 1) | sgn;
1970 /* After reload, split the load of an immediate constant. OPERANDS are the
1971 operands of the movsi_insn pattern which we are splitting. We return
1972 nonzero if we emitted a sequence to load the constant, zero if we emitted
1973 nothing because we want to use the splitter's default sequence. */
1976 split_load_immediate (rtx operands[])
1978 HOST_WIDE_INT val = INTVAL (operands[1]);
1980 HOST_WIDE_INT shifted = val;
1981 HOST_WIDE_INT shifted_compl = ~val;
1982 int num_zero = shiftr_zero (&shifted);
1983 int num_compl_zero = shiftr_zero (&shifted_compl);
1984 unsigned int regno = REGNO (operands[0]);
1985 enum reg_class class1 = REGNO_REG_CLASS (regno);
1987 /* This case takes care of single-bit set/clear constants, which we could
1988 also implement with BITSET/BITCLR. */
1990 && shifted >= -32768 && shifted < 65536
1991 && (D_REGNO_P (regno)
1992 || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))
1994 emit_insn (gen_movsi (operands[0], GEN_INT (shifted)));
1995 emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));
2000 tmp |= -(tmp & 0x8000);
2002 /* If high word has one bit set or clear, try to use a bit operation. */
2003 if (D_REGNO_P (regno))
2005 if (log2constp (val & 0xFFFF0000))
2007 emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));
2008 emit_insn (gen_iorsi3 (operands[0], operands[0], GEN_INT (val & 0xFFFF0000)));
2011 else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)
2013 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2014 emit_insn (gen_andsi3 (operands[0], operands[0], GEN_INT (val | 0xFFFF)));
2018 if (D_REGNO_P (regno))
2020 if (CONST_7BIT_IMM_P (tmp))
2022 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2023 emit_insn (gen_movstricthi_high (operands[0], GEN_INT (val & -65536)));
2027 if ((val & 0xFFFF0000) == 0)
2029 emit_insn (gen_movsi (operands[0], const0_rtx));
2030 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2034 if ((val & 0xFFFF0000) == 0xFFFF0000)
2036 emit_insn (gen_movsi (operands[0], constm1_rtx));
2037 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2042 /* Need DREGs for the remaining case. */
2047 && num_compl_zero && CONST_7BIT_IMM_P (shifted_compl))
2049 /* If optimizing for size, generate a sequence that has more instructions
2051 emit_insn (gen_movsi (operands[0], GEN_INT (shifted_compl)));
2052 emit_insn (gen_ashlsi3 (operands[0], operands[0],
2053 GEN_INT (num_compl_zero)));
2054 emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
2060 /* Return true if the legitimate memory address for a memory operand of mode
2061 MODE. Return false if not. */
2064 bfin_valid_add (enum machine_mode mode, HOST_WIDE_INT value)
2066 unsigned HOST_WIDE_INT v = value > 0 ? value : -value;
2067 int sz = GET_MODE_SIZE (mode);
2068 int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2;
2069 /* The usual offsettable_memref machinery doesn't work so well for this
2070 port, so we deal with the problem here. */
2071 unsigned HOST_WIDE_INT mask = sz == 8 ? 0x7ffe : 0x7fff;
2072 return (v & ~(mask << shift)) == 0;
2076 bfin_valid_reg_p (unsigned int regno, int strict)
2078 return ((strict && REGNO_OK_FOR_BASE_STRICT_P (regno))
2079 || (!strict && REGNO_OK_FOR_BASE_NONSTRICT_P (regno)));
2083 bfin_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
2085 switch (GET_CODE (x)) {
2087 if (bfin_valid_reg_p (REGNO (x), strict))
2091 if (REG_P (XEXP (x, 0))
2092 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict)
2093 && (GET_CODE (XEXP (x, 1)) == UNSPEC
2094 || (GET_CODE (XEXP (x, 1)) == CONST_INT
2095 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
2100 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2101 && REG_P (XEXP (x, 0))
2102 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict))
2105 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2106 && XEXP (x, 0) == stack_pointer_rtx
2107 && REG_P (XEXP (x, 0))
2108 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict))
2118 bfin_rtx_costs (rtx x, int code, int outer_code, int *total)
2120 int cost2 = COSTS_N_INSNS (1);
2125 if (outer_code == SET || outer_code == PLUS)
2126 *total = CONST_7BIT_IMM_P (INTVAL (x)) ? 0 : cost2;
2127 else if (outer_code == AND)
2128 *total = log2constp (~INTVAL (x)) ? 0 : cost2;
2129 else if (outer_code == LE || outer_code == LT || outer_code == EQ)
2130 *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
2131 else if (outer_code == LEU || outer_code == LTU)
2132 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
2133 else if (outer_code == MULT)
2134 *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
2135 else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
2137 else if (outer_code == ASHIFT || outer_code == ASHIFTRT
2138 || outer_code == LSHIFTRT)
2139 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
2140 else if (outer_code == IOR || outer_code == XOR)
2141 *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
2150 *total = COSTS_N_INSNS (2);
2154 if (GET_MODE (x) == Pmode)
2156 if (GET_CODE (XEXP (x, 0)) == MULT
2157 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
2159 HOST_WIDE_INT val = INTVAL (XEXP (XEXP (x, 0), 1));
2160 if (val == 2 || val == 4)
2163 *total += rtx_cost (XEXP (XEXP (x, 0), 0), outer_code);
2164 *total += rtx_cost (XEXP (x, 1), outer_code);
2176 if (GET_MODE (x) == DImode)
2183 if (GET_MODE (x) == DImode)
2188 if (GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD)
2189 *total = COSTS_N_INSNS (3);
2198 bfin_internal_label (FILE *stream, const char *prefix, unsigned long num)
2200 fprintf (stream, "%s%s$%ld:\n", LOCAL_LABEL_PREFIX, prefix, num);
2203 /* Used for communication between {push,pop}_multiple_operation (which
2204 we use not only as a predicate) and the corresponding output functions. */
2205 static int first_preg_to_save, first_dreg_to_save;
2208 push_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2210 int lastdreg = 8, lastpreg = 6;
2213 first_preg_to_save = lastpreg;
2214 first_dreg_to_save = lastdreg;
2215 for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
2217 rtx t = XVECEXP (op, 0, i);
2221 if (GET_CODE (t) != SET)
2225 dest = SET_DEST (t);
2226 if (GET_CODE (dest) != MEM || ! REG_P (src))
2228 dest = XEXP (dest, 0);
2229 if (GET_CODE (dest) != PLUS
2230 || ! REG_P (XEXP (dest, 0))
2231 || REGNO (XEXP (dest, 0)) != REG_SP
2232 || GET_CODE (XEXP (dest, 1)) != CONST_INT
2233 || INTVAL (XEXP (dest, 1)) != -i * 4)
2236 regno = REGNO (src);
2239 if (D_REGNO_P (regno))
2242 first_dreg_to_save = lastdreg = regno - REG_R0;
2244 else if (regno >= REG_P0 && regno <= REG_P7)
2247 first_preg_to_save = lastpreg = regno - REG_P0;
2257 if (regno >= REG_P0 && regno <= REG_P7)
2260 first_preg_to_save = lastpreg = regno - REG_P0;
2262 else if (regno != REG_R0 + lastdreg + 1)
2267 else if (group == 2)
2269 if (regno != REG_P0 + lastpreg + 1)
2278 pop_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2280 int lastdreg = 8, lastpreg = 6;
2283 for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
2285 rtx t = XVECEXP (op, 0, i);
2289 if (GET_CODE (t) != SET)
2293 dest = SET_DEST (t);
2294 if (GET_CODE (src) != MEM || ! REG_P (dest))
2296 src = XEXP (src, 0);
2300 if (! REG_P (src) || REGNO (src) != REG_SP)
2303 else if (GET_CODE (src) != PLUS
2304 || ! REG_P (XEXP (src, 0))
2305 || REGNO (XEXP (src, 0)) != REG_SP
2306 || GET_CODE (XEXP (src, 1)) != CONST_INT
2307 || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
2310 regno = REGNO (dest);
2313 if (regno == REG_R7)
2318 else if (regno != REG_P0 + lastpreg - 1)
2323 else if (group == 1)
2325 if (regno != REG_R0 + lastdreg - 1)
2331 first_dreg_to_save = lastdreg;
2332 first_preg_to_save = lastpreg;
2336 /* Emit assembly code for one multi-register push described by INSN, with
2337 operands in OPERANDS. */
2340 output_push_multiple (rtx insn, rtx *operands)
2345 /* Validate the insn again, and compute first_[dp]reg_to_save. */
2346 ok = push_multiple_operation (PATTERN (insn), VOIDmode);
2349 if (first_dreg_to_save == 8)
2350 sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
2351 else if (first_preg_to_save == 6)
2352 sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
2354 sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
2355 first_dreg_to_save, first_preg_to_save);
2357 output_asm_insn (buf, operands);
2360 /* Emit assembly code for one multi-register pop described by INSN, with
2361 operands in OPERANDS. */
2364 output_pop_multiple (rtx insn, rtx *operands)
2369 /* Validate the insn again, and compute first_[dp]reg_to_save. */
2370 ok = pop_multiple_operation (PATTERN (insn), VOIDmode);
2373 if (first_dreg_to_save == 8)
2374 sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
2375 else if (first_preg_to_save == 6)
2376 sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
2378 sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
2379 first_dreg_to_save, first_preg_to_save);
2381 output_asm_insn (buf, operands);
2384 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE. */
2387 single_move_for_strmov (rtx dst, rtx src, enum machine_mode mode, HOST_WIDE_INT offset)
2389 rtx scratch = gen_reg_rtx (mode);
2392 srcmem = adjust_address_nv (src, mode, offset);
2393 dstmem = adjust_address_nv (dst, mode, offset);
2394 emit_move_insn (scratch, srcmem);
2395 emit_move_insn (dstmem, scratch);
2398 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
2399 alignment ALIGN_EXP. Return true if successful, false if we should fall
2400 back on a different method. */
2403 bfin_expand_strmov (rtx dst, rtx src, rtx count_exp, rtx align_exp)
2405 rtx srcreg, destreg, countreg;
2406 HOST_WIDE_INT align = 0;
2407 unsigned HOST_WIDE_INT count = 0;
2409 if (GET_CODE (align_exp) == CONST_INT)
2410 align = INTVAL (align_exp);
2411 if (GET_CODE (count_exp) == CONST_INT)
2413 count = INTVAL (count_exp);
2415 if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
2420 /* If optimizing for size, only do single copies inline. */
2423 if (count == 2 && align < 2)
2425 if (count == 4 && align < 4)
2427 if (count != 1 && count != 2 && count != 4)
2430 if (align < 2 && count != 1)
2433 destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
2434 if (destreg != XEXP (dst, 0))
2435 dst = replace_equiv_address_nv (dst, destreg);
2436 srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
2437 if (srcreg != XEXP (src, 0))
2438 src = replace_equiv_address_nv (src, srcreg);
2440 if (count != 0 && align >= 2)
2442 unsigned HOST_WIDE_INT offset = 0;
2446 if ((count & ~3) == 4)
2448 single_move_for_strmov (dst, src, SImode, offset);
2451 else if (count & ~3)
2453 HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
2454 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
2456 emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
2461 if ((count & ~1) == 2)
2463 single_move_for_strmov (dst, src, HImode, offset);
2466 else if (count & ~1)
2468 HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
2469 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
2471 emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
2476 single_move_for_strmov (dst, src, HImode, offset);
2481 single_move_for_strmov (dst, src, QImode, offset);
2490 bfin_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
2492 enum attr_type insn_type, dep_insn_type;
2493 int dep_insn_code_number;
2495 /* Anti and output dependencies have zero cost. */
2496 if (REG_NOTE_KIND (link) != 0)
2499 dep_insn_code_number = recog_memoized (dep_insn);
2501 /* If we can't recognize the insns, we can't really do anything. */
2502 if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
2505 insn_type = get_attr_type (insn);
2506 dep_insn_type = get_attr_type (dep_insn);
2508 if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)
2510 rtx pat = PATTERN (dep_insn);
2511 rtx dest = SET_DEST (pat);
2512 rtx src = SET_SRC (pat);
2513 if (! ADDRESS_REGNO_P (REGNO (dest)) || ! D_REGNO_P (REGNO (src)))
2515 return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);
2521 /* We use the machine specific reorg pass for emitting CSYNC instructions
2522 after conditional branches as needed.
2524 The Blackfin is unusual in that a code sequence like
2527 may speculatively perform the load even if the condition isn't true. This
2528 happens for a branch that is predicted not taken, because the pipeline
2529 isn't flushed or stalled, so the early stages of the following instructions,
2530 which perform the memory reference, are allowed to execute before the
2531 jump condition is evaluated.
2532 Therefore, we must insert additional instructions in all places where this
2533 could lead to incorrect behavior. The manual recommends CSYNC, while
2534 VDSP seems to use NOPs (even though its corresponding compiler option is
2537 When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
2538 When optimizing for size, we turn the branch into a predicted taken one.
2539 This may be slower due to mispredicts, but saves code size. */
2544 rtx insn, last_condjump = NULL_RTX;
2545 int cycles_since_jump = INT_MAX;
2547 if (! TARGET_SPECLD_ANOMALY || ! TARGET_CSYNC_ANOMALY)
2550 /* First pass: find predicted-false branches; if something after them
2551 needs nops, insert them or change the branch to predict true. */
2552 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2556 if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
2559 pat = PATTERN (insn);
2560 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
2561 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
2562 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
2567 if (any_condjump_p (insn)
2568 && ! cbranch_predicted_taken_p (insn))
2570 last_condjump = insn;
2571 cycles_since_jump = 0;
2574 cycles_since_jump = INT_MAX;
2576 else if (INSN_P (insn))
2578 enum attr_type type = get_attr_type (insn);
2579 int delay_needed = 0;
2580 if (cycles_since_jump < INT_MAX)
2581 cycles_since_jump++;
2583 if (type == TYPE_MCLD && TARGET_SPECLD_ANOMALY)
2585 rtx pat = single_set (insn);
2586 if (may_trap_p (SET_SRC (pat)))
2589 else if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
2592 if (delay_needed > cycles_since_jump)
2596 rtx *op = recog_data.operand;
2598 delay_needed -= cycles_since_jump;
2600 extract_insn (last_condjump);
2603 pat = gen_cbranch_predicted_taken (op[0], op[1], op[2],
2605 cycles_since_jump = INT_MAX;
2608 /* Do not adjust cycles_since_jump in this case, so that
2609 we'll increase the number of NOPs for a subsequent insn
2611 pat = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
2612 GEN_INT (delay_needed));
2613 PATTERN (last_condjump) = pat;
2614 INSN_CODE (last_condjump) = recog (pat, insn, &num_clobbers);
2618 /* Second pass: for predicted-true branches, see if anything at the
2619 branch destination needs extra nops. */
2620 if (! TARGET_CSYNC_ANOMALY)
2623 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2626 && any_condjump_p (insn)
2627 && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken
2628 || cbranch_predicted_taken_p (insn)))
2630 rtx target = JUMP_LABEL (insn);
2632 cycles_since_jump = 0;
2633 for (; target && cycles_since_jump < 3; target = NEXT_INSN (target))
2637 if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
2640 pat = PATTERN (target);
2641 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
2642 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
2643 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
2646 if (INSN_P (target))
2648 enum attr_type type = get_attr_type (target);
2649 int delay_needed = 0;
2650 if (cycles_since_jump < INT_MAX)
2651 cycles_since_jump++;
2653 if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
2656 if (delay_needed > cycles_since_jump)
2658 rtx prev = prev_real_insn (label);
2659 delay_needed -= cycles_since_jump;
2661 fprintf (dump_file, "Adding %d nops after %d\n",
2662 delay_needed, INSN_UID (label));
2664 && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops)
2671 "Reducing nops on insn %d.\n",
2674 x = XVECEXP (x, 0, 1);
2675 v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed;
2676 XVECEXP (x, 0, 0) = GEN_INT (v);
2678 while (delay_needed-- > 0)
2679 emit_insn_after (gen_nop (), label);
2688 /* Handle interrupt_handler, exception_handler and nmi_handler function
2689 attributes; arguments as in struct attribute_spec.handler. */
2692 handle_int_attribute (tree *node, tree name,
2693 tree args ATTRIBUTE_UNUSED,
2694 int flags ATTRIBUTE_UNUSED,
2698 if (TREE_CODE (x) == FUNCTION_DECL)
2701 if (TREE_CODE (x) != FUNCTION_TYPE)
2703 warning (OPT_Wattributes, "%qs attribute only applies to functions",
2704 IDENTIFIER_POINTER (name));
2705 *no_add_attrs = true;
2707 else if (funkind (x) != SUBROUTINE)
2708 error ("multiple function type attributes specified");
2713 /* Return 0 if the attributes for two types are incompatible, 1 if they
2714 are compatible, and 2 if they are nearly compatible (which causes a
2715 warning to be generated). */
2718 bfin_comp_type_attributes (tree type1, tree type2)
2720 e_funkind kind1, kind2;
2722 if (TREE_CODE (type1) != FUNCTION_TYPE)
2725 kind1 = funkind (type1);
2726 kind2 = funkind (type2);
2731 /* Check for mismatched modifiers */
2732 if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
2733 != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
2736 if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
2737 != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
2740 if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
2741 != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
2744 if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1))
2745 != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2)))
2751 /* Handle a "longcall" or "shortcall" attribute; arguments as in
2752 struct attribute_spec.handler. */
2755 bfin_handle_longcall_attribute (tree *node, tree name,
2756 tree args ATTRIBUTE_UNUSED,
2757 int flags ATTRIBUTE_UNUSED,
2760 if (TREE_CODE (*node) != FUNCTION_TYPE
2761 && TREE_CODE (*node) != FIELD_DECL
2762 && TREE_CODE (*node) != TYPE_DECL)
2764 warning (OPT_Wattributes, "`%s' attribute only applies to functions",
2765 IDENTIFIER_POINTER (name));
2766 *no_add_attrs = true;
2769 if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0
2770 && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node)))
2771 || (strcmp (IDENTIFIER_POINTER (name), "shortcall") == 0
2772 && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node))))
2774 warning (OPT_Wattributes,
2775 "can't apply both longcall and shortcall attributes to the same function");
2776 *no_add_attrs = true;
2782 /* Table of valid machine attributes. */
2783 const struct attribute_spec bfin_attribute_table[] =
2785 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
2786 { "interrupt_handler", 0, 0, false, true, true, handle_int_attribute },
2787 { "exception_handler", 0, 0, false, true, true, handle_int_attribute },
2788 { "nmi_handler", 0, 0, false, true, true, handle_int_attribute },
2789 { "nesting", 0, 0, false, true, true, NULL },
2790 { "kspisusp", 0, 0, false, true, true, NULL },
2791 { "saveall", 0, 0, false, true, true, NULL },
2792 { "longcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
2793 { "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
2794 { NULL, 0, 0, false, false, false, NULL }
2797 /* Output the assembler code for a thunk function. THUNK_DECL is the
2798 declaration for the thunk function itself, FUNCTION is the decl for
2799 the target function. DELTA is an immediate constant offset to be
2800 added to THIS. If VCALL_OFFSET is nonzero, the word at
2801 *(*this + vcall_offset) should be added to THIS. */
2804 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
2805 tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
2806 HOST_WIDE_INT vcall_offset, tree function)
2809 /* The this parameter is passed as the first argument. */
2810 rtx this = gen_rtx_REG (Pmode, REG_R0);
2812 /* Adjust the this parameter by a fixed constant. */
2816 if (delta >= -64 && delta <= 63)
2818 xops[0] = GEN_INT (delta);
2819 output_asm_insn ("%1 += %0;", xops);
2821 else if (delta >= -128 && delta < -64)
2823 xops[0] = GEN_INT (delta + 64);
2824 output_asm_insn ("%1 += -64; %1 += %0;", xops);
2826 else if (delta > 63 && delta <= 126)
2828 xops[0] = GEN_INT (delta - 63);
2829 output_asm_insn ("%1 += 63; %1 += %0;", xops);
2833 xops[0] = GEN_INT (delta);
2834 output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
2838 /* Adjust the this parameter by a value stored in the vtable. */
2841 rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
2842 rtx tmp = gen_rtx_REG (Pmode, REG_R2);
2846 output_asm_insn ("%2 = r0; %2 = [%2];", xops);
2848 /* Adjust the this parameter. */
2849 xops[0] = gen_rtx_MEM (Pmode, plus_constant (p2tmp, vcall_offset));
2850 if (!memory_operand (xops[0], Pmode))
2852 rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
2853 xops[0] = GEN_INT (vcall_offset);
2855 output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
2856 xops[0] = gen_rtx_MEM (Pmode, p2tmp);
2859 output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
2862 xops[0] = XEXP (DECL_RTL (function), 0);
2863 if (1 || !flag_pic || (*targetm.binds_local_p) (function))
2864 output_asm_insn ("jump.l\t%P0", xops);
2867 /* Codes for all the Blackfin builtins. */
2875 #define def_builtin(NAME, TYPE, CODE) \
2877 lang_hooks.builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
2881 /* Set up all builtin functions for this target. */
2883 bfin_init_builtins (void)
2885 tree void_ftype_void
2886 = build_function_type (void_type_node, void_list_node);
2888 /* Add the remaining MMX insns with somewhat more complicated types. */
2889 def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC);
2890 def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC);
2893 /* Expand an expression EXP that calls a built-in function,
2894 with result going to TARGET if that's convenient
2895 (and in mode MODE if that's convenient).
2896 SUBTARGET may be used as the target for computing one of EXP's operands.
2897 IGNORE is nonzero if the value is to be ignored. */
2900 bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
2901 rtx subtarget ATTRIBUTE_UNUSED,
2902 enum machine_mode mode ATTRIBUTE_UNUSED,
2903 int ignore ATTRIBUTE_UNUSED)
2905 tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
2906 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
2910 case BFIN_BUILTIN_CSYNC:
2911 emit_insn (gen_csync ());
2913 case BFIN_BUILTIN_SSYNC:
2914 emit_insn (gen_ssync ());
2922 #undef TARGET_INIT_BUILTINS
2923 #define TARGET_INIT_BUILTINS bfin_init_builtins
2925 #undef TARGET_EXPAND_BUILTIN
2926 #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
2928 #undef TARGET_ASM_GLOBALIZE_LABEL
2929 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label
2931 #undef TARGET_ASM_FILE_START
2932 #define TARGET_ASM_FILE_START output_file_start
2934 #undef TARGET_ATTRIBUTE_TABLE
2935 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
2937 #undef TARGET_COMP_TYPE_ATTRIBUTES
2938 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
2940 #undef TARGET_RTX_COSTS
2941 #define TARGET_RTX_COSTS bfin_rtx_costs
2943 #undef TARGET_ADDRESS_COST
2944 #define TARGET_ADDRESS_COST bfin_address_cost
2946 #undef TARGET_ASM_INTERNAL_LABEL
2947 #define TARGET_ASM_INTERNAL_LABEL bfin_internal_label
2949 #undef TARGET_MACHINE_DEPENDENT_REORG
2950 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
2952 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
2953 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
2955 #undef TARGET_ASM_OUTPUT_MI_THUNK
2956 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
2957 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
2958 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
2960 #undef TARGET_SCHED_ADJUST_COST
2961 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
2963 #undef TARGET_PROMOTE_PROTOTYPES
2964 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
2965 #undef TARGET_PROMOTE_FUNCTION_ARGS
2966 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
2967 #undef TARGET_PROMOTE_FUNCTION_RETURN
2968 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
2970 #undef TARGET_ARG_PARTIAL_BYTES
2971 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
2973 #undef TARGET_PASS_BY_REFERENCE
2974 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
2976 #undef TARGET_SETUP_INCOMING_VARARGS
2977 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
2979 #undef TARGET_STRUCT_VALUE_RTX
2980 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
2982 #undef TARGET_VECTOR_MODE_SUPPORTED_P
2983 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
2985 #undef TARGET_HANDLE_OPTION
2986 #define TARGET_HANDLE_OPTION bfin_handle_option
2988 #undef TARGET_DEFAULT_TARGET_FLAGS
2989 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
2991 struct gcc_target targetm = TARGET_INITIALIZER;