1 /* The Blackfin code generation auxiliary output file.
2 Copyright (C) 2005-2015 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 3, 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 COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
27 #include "hard-reg-set.h"
28 #include "insn-config.h"
29 #include "insn-codes.h"
30 #include "conditions.h"
31 #include "insn-flags.h"
33 #include "insn-attr.h"
37 #include "double-int.h"
44 #include "fold-const.h"
51 #include "target-def.h"
53 #include "statistics.h"
55 #include "fixed-value.h"
62 #include "diagnostic-core.h"
67 #include "dominance.h"
73 #include "cfgcleanup.h"
74 #include "basic-block.h"
77 #include "plugin-api.h"
80 #include "langhooks.h"
81 #include "bfin-protos.h"
84 #include "tm-constrs.h"
88 #include "sel-sched.h"
89 #include "hw-doloop.h"
94 /* A C structure for machine-specific, per-function data.
95 This is added to the cfun structure. */
96 struct GTY(()) machine_function
98 /* Set if we are notified by the doloop pass that a hardware loop
100 int has_hardware_loops
;
102 /* Set if we create a memcpy pattern that uses loop registers. */
103 int has_loopreg_clobber
;
106 /* RTX for condition code flag register and RETS register */
107 extern GTY(()) rtx bfin_cc_rtx
;
108 extern GTY(()) rtx bfin_rets_rtx
;
109 rtx bfin_cc_rtx
, bfin_rets_rtx
;
111 int max_arg_registers
= 0;
113 /* Arrays used when emitting register names. */
114 const char *short_reg_names
[] = SHORT_REGISTER_NAMES
;
115 const char *high_reg_names
[] = HIGH_REGISTER_NAMES
;
116 const char *dregs_pair_names
[] = DREGS_PAIR_NAMES
;
117 const char *byte_reg_names
[] = BYTE_REGISTER_NAMES
;
119 static int arg_regs
[] = FUNCTION_ARG_REGISTERS
;
120 static int ret_regs
[] = FUNCTION_RETURN_REGISTERS
;
122 int splitting_for_sched
, splitting_loops
;
125 bfin_globalize_label (FILE *stream
, const char *name
)
127 fputs (".global ", stream
);
128 assemble_name (stream
, name
);
134 output_file_start (void)
136 FILE *file
= asm_out_file
;
139 fprintf (file
, ".file \"%s\";\n", LOCATION_FILE (input_location
));
141 for (i
= 0; arg_regs
[i
] >= 0; i
++)
143 max_arg_registers
= i
; /* how many arg reg used */
146 /* Examine machine-dependent attributes of function type FUNTYPE and return its
147 type. See the definition of E_FUNKIND. */
150 funkind (const_tree funtype
)
152 tree attrs
= TYPE_ATTRIBUTES (funtype
);
153 if (lookup_attribute ("interrupt_handler", attrs
))
154 return INTERRUPT_HANDLER
;
155 else if (lookup_attribute ("exception_handler", attrs
))
156 return EXCPT_HANDLER
;
157 else if (lookup_attribute ("nmi_handler", attrs
))
163 /* Legitimize PIC addresses. If the address is already position-independent,
164 we return ORIG. Newly generated position-independent addresses go into a
165 reg. This is REG if nonzero, otherwise we allocate register(s) as
166 necessary. PICREG is the register holding the pointer to the PIC offset
170 legitimize_pic_address (rtx orig
, rtx reg
, rtx picreg
)
175 if (GET_CODE (addr
) == SYMBOL_REF
|| GET_CODE (addr
) == LABEL_REF
)
180 if (TARGET_ID_SHARED_LIBRARY
)
181 unspec
= UNSPEC_MOVE_PIC
;
182 else if (GET_CODE (addr
) == SYMBOL_REF
183 && SYMBOL_REF_FUNCTION_P (addr
))
184 unspec
= UNSPEC_FUNCDESC_GOT17M4
;
186 unspec
= UNSPEC_MOVE_FDPIC
;
190 gcc_assert (can_create_pseudo_p ());
191 reg
= gen_reg_rtx (Pmode
);
194 tmp
= gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, addr
), unspec
);
195 new_rtx
= gen_const_mem (Pmode
, gen_rtx_PLUS (Pmode
, picreg
, tmp
));
197 emit_move_insn (reg
, new_rtx
);
198 if (picreg
== pic_offset_table_rtx
)
199 crtl
->uses_pic_offset_table
= 1;
203 else if (GET_CODE (addr
) == CONST
|| GET_CODE (addr
) == PLUS
)
207 if (GET_CODE (addr
) == CONST
)
209 addr
= XEXP (addr
, 0);
210 gcc_assert (GET_CODE (addr
) == PLUS
);
213 if (XEXP (addr
, 0) == picreg
)
218 gcc_assert (can_create_pseudo_p ());
219 reg
= gen_reg_rtx (Pmode
);
222 base
= legitimize_pic_address (XEXP (addr
, 0), reg
, picreg
);
223 addr
= legitimize_pic_address (XEXP (addr
, 1),
224 base
== reg
? NULL_RTX
: reg
,
227 if (GET_CODE (addr
) == CONST_INT
)
229 gcc_assert (! reload_in_progress
&& ! reload_completed
);
230 addr
= force_reg (Pmode
, addr
);
233 if (GET_CODE (addr
) == PLUS
&& CONSTANT_P (XEXP (addr
, 1)))
235 base
= gen_rtx_PLUS (Pmode
, base
, XEXP (addr
, 0));
236 addr
= XEXP (addr
, 1);
239 return gen_rtx_PLUS (Pmode
, base
, addr
);
245 /* Stack frame layout. */
247 /* For a given REGNO, determine whether it must be saved in the function
248 prologue. IS_INTHANDLER specifies whether we're generating a normal
249 prologue or an interrupt/exception one. */
251 must_save_p (bool is_inthandler
, unsigned regno
)
253 if (D_REGNO_P (regno
))
255 bool is_eh_return_reg
= false;
256 if (crtl
->calls_eh_return
)
261 unsigned test
= EH_RETURN_DATA_REGNO (j
);
262 if (test
== INVALID_REGNUM
)
265 is_eh_return_reg
= true;
269 return (is_eh_return_reg
270 || (df_regs_ever_live_p (regno
)
271 && !fixed_regs
[regno
]
272 && (is_inthandler
|| !call_used_regs
[regno
])));
274 else if (P_REGNO_P (regno
))
276 return ((df_regs_ever_live_p (regno
)
277 && !fixed_regs
[regno
]
278 && (is_inthandler
|| !call_used_regs
[regno
]))
280 && (ENABLE_WA_05000283
|| ENABLE_WA_05000315
)
283 && regno
== PIC_OFFSET_TABLE_REGNUM
284 && (crtl
->uses_pic_offset_table
285 || (TARGET_ID_SHARED_LIBRARY
&& !crtl
->is_leaf
))));
288 return ((is_inthandler
|| !call_used_regs
[regno
])
289 && (df_regs_ever_live_p (regno
)
290 || (!leaf_function_p () && call_used_regs
[regno
])));
294 /* Compute the number of DREGS to save with a push_multiple operation.
295 This could include registers that aren't modified in the function,
296 since push_multiple only takes a range of registers.
297 If IS_INTHANDLER, then everything that is live must be saved, even
298 if normally call-clobbered.
299 If CONSECUTIVE, return the number of registers we can save in one
300 instruction with a push/pop multiple instruction. */
303 n_dregs_to_save (bool is_inthandler
, bool consecutive
)
308 for (i
= REG_R7
+ 1; i
-- != REG_R0
;)
310 if (must_save_p (is_inthandler
, i
))
312 else if (consecutive
)
318 /* Like n_dregs_to_save, but compute number of PREGS to save. */
321 n_pregs_to_save (bool is_inthandler
, bool consecutive
)
326 for (i
= REG_P5
+ 1; i
-- != REG_P0
;)
327 if (must_save_p (is_inthandler
, i
))
329 else if (consecutive
)
334 /* Determine if we are going to save the frame pointer in the prologue. */
337 must_save_fp_p (void)
339 return df_regs_ever_live_p (REG_FP
);
342 /* Determine if we are going to save the RETS register. */
344 must_save_rets_p (void)
346 return df_regs_ever_live_p (REG_RETS
);
350 stack_frame_needed_p (void)
352 /* EH return puts a new return address into the frame using an
353 address relative to the frame pointer. */
354 if (crtl
->calls_eh_return
)
356 return frame_pointer_needed
;
359 /* Emit code to save registers in the prologue. SAVEALL is nonzero if we
360 must save all registers; this is used for interrupt handlers.
361 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
362 this for an interrupt (or exception) handler. */
365 expand_prologue_reg_save (rtx spreg
, int saveall
, bool is_inthandler
)
367 rtx predec1
= gen_rtx_PRE_DEC (SImode
, spreg
);
368 rtx predec
= gen_rtx_MEM (SImode
, predec1
);
369 int ndregs
= saveall
? 8 : n_dregs_to_save (is_inthandler
, false);
370 int npregs
= saveall
? 6 : n_pregs_to_save (is_inthandler
, false);
371 int ndregs_consec
= saveall
? 8 : n_dregs_to_save (is_inthandler
, true);
372 int npregs_consec
= saveall
? 6 : n_pregs_to_save (is_inthandler
, true);
374 int total_consec
= ndregs_consec
+ npregs_consec
;
377 if (saveall
|| is_inthandler
)
379 rtx_insn
*insn
= emit_move_insn (predec
, gen_rtx_REG (SImode
, REG_ASTAT
));
381 RTX_FRAME_RELATED_P (insn
) = 1;
382 for (dregno
= REG_LT0
; dregno
<= REG_LB1
; dregno
++)
384 || cfun
->machine
->has_hardware_loops
385 || cfun
->machine
->has_loopreg_clobber
386 || (ENABLE_WA_05000257
387 && (dregno
== REG_LC0
|| dregno
== REG_LC1
)))
389 insn
= emit_move_insn (predec
, gen_rtx_REG (SImode
, dregno
));
390 RTX_FRAME_RELATED_P (insn
) = 1;
394 if (total_consec
!= 0)
397 rtx val
= GEN_INT (-total_consec
* 4);
398 rtx pat
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (total_consec
+ 2));
400 XVECEXP (pat
, 0, 0) = gen_rtx_UNSPEC (VOIDmode
, gen_rtvec (1, val
),
401 UNSPEC_PUSH_MULTIPLE
);
402 XVECEXP (pat
, 0, total_consec
+ 1) = gen_rtx_SET (spreg
,
406 RTX_FRAME_RELATED_P (XVECEXP (pat
, 0, total_consec
+ 1)) = 1;
407 d_to_save
= ndregs_consec
;
408 dregno
= REG_R7
+ 1 - ndregs_consec
;
409 pregno
= REG_P5
+ 1 - npregs_consec
;
410 for (i
= 0; i
< total_consec
; i
++)
412 rtx memref
= gen_rtx_MEM (word_mode
,
413 gen_rtx_PLUS (Pmode
, spreg
,
414 GEN_INT (- i
* 4 - 4)));
418 subpat
= gen_rtx_SET (memref
, gen_rtx_REG (word_mode
, dregno
++));
423 subpat
= gen_rtx_SET (memref
, gen_rtx_REG (word_mode
, pregno
++));
425 XVECEXP (pat
, 0, i
+ 1) = subpat
;
426 RTX_FRAME_RELATED_P (subpat
) = 1;
428 insn
= emit_insn (pat
);
429 RTX_FRAME_RELATED_P (insn
) = 1;
432 for (dregno
= REG_R0
; ndregs
!= ndregs_consec
; dregno
++)
434 if (must_save_p (is_inthandler
, dregno
))
437 emit_move_insn (predec
, gen_rtx_REG (word_mode
, dregno
));
438 RTX_FRAME_RELATED_P (insn
) = 1;
442 for (pregno
= REG_P0
; npregs
!= npregs_consec
; pregno
++)
444 if (must_save_p (is_inthandler
, pregno
))
447 emit_move_insn (predec
, gen_rtx_REG (word_mode
, pregno
));
448 RTX_FRAME_RELATED_P (insn
) = 1;
452 for (i
= REG_P7
+ 1; i
< REG_CC
; i
++)
455 && (df_regs_ever_live_p (i
)
456 || (!leaf_function_p () && call_used_regs
[i
]))))
459 if (i
== REG_A0
|| i
== REG_A1
)
460 insn
= emit_move_insn (gen_rtx_MEM (PDImode
, predec1
),
461 gen_rtx_REG (PDImode
, i
));
463 insn
= emit_move_insn (predec
, gen_rtx_REG (SImode
, i
));
464 RTX_FRAME_RELATED_P (insn
) = 1;
468 /* Emit code to restore registers in the epilogue. SAVEALL is nonzero if we
469 must save all registers; this is used for interrupt handlers.
470 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
471 this for an interrupt (or exception) handler. */
474 expand_epilogue_reg_restore (rtx spreg
, bool saveall
, bool is_inthandler
)
476 rtx postinc1
= gen_rtx_POST_INC (SImode
, spreg
);
477 rtx postinc
= gen_rtx_MEM (SImode
, postinc1
);
479 int ndregs
= saveall
? 8 : n_dregs_to_save (is_inthandler
, false);
480 int npregs
= saveall
? 6 : n_pregs_to_save (is_inthandler
, false);
481 int ndregs_consec
= saveall
? 8 : n_dregs_to_save (is_inthandler
, true);
482 int npregs_consec
= saveall
? 6 : n_pregs_to_save (is_inthandler
, true);
483 int total_consec
= ndregs_consec
+ npregs_consec
;
487 /* A slightly crude technique to stop flow from trying to delete "dead"
489 MEM_VOLATILE_P (postinc
) = 1;
491 for (i
= REG_CC
- 1; i
> REG_P7
; i
--)
494 && (df_regs_ever_live_p (i
)
495 || (!leaf_function_p () && call_used_regs
[i
]))))
497 if (i
== REG_A0
|| i
== REG_A1
)
499 rtx mem
= gen_rtx_MEM (PDImode
, postinc1
);
500 MEM_VOLATILE_P (mem
) = 1;
501 emit_move_insn (gen_rtx_REG (PDImode
, i
), mem
);
504 emit_move_insn (gen_rtx_REG (SImode
, i
), postinc
);
507 regno
= REG_P5
- npregs_consec
;
508 for (; npregs
!= npregs_consec
; regno
--)
510 if (must_save_p (is_inthandler
, regno
))
512 emit_move_insn (gen_rtx_REG (word_mode
, regno
), postinc
);
516 regno
= REG_R7
- ndregs_consec
;
517 for (; ndregs
!= ndregs_consec
; regno
--)
519 if (must_save_p (is_inthandler
, regno
))
521 emit_move_insn (gen_rtx_REG (word_mode
, regno
), postinc
);
526 if (total_consec
!= 0)
528 rtx pat
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (total_consec
+ 1));
530 = gen_rtx_SET (spreg
, gen_rtx_PLUS (Pmode
, spreg
,
531 GEN_INT (total_consec
* 4)));
533 if (npregs_consec
> 0)
538 for (i
= 0; i
< total_consec
; i
++)
541 ? gen_rtx_PLUS (Pmode
, spreg
, GEN_INT (i
* 4))
543 rtx memref
= gen_rtx_MEM (word_mode
, addr
);
546 XVECEXP (pat
, 0, i
+ 1)
547 = gen_rtx_SET (gen_rtx_REG (word_mode
, regno
), memref
);
549 if (npregs_consec
> 0)
551 if (--npregs_consec
== 0)
556 insn
= emit_insn (pat
);
557 RTX_FRAME_RELATED_P (insn
) = 1;
559 if (saveall
|| is_inthandler
)
561 for (regno
= REG_LB1
; regno
>= REG_LT0
; regno
--)
563 || cfun
->machine
->has_hardware_loops
564 || cfun
->machine
->has_loopreg_clobber
565 || (ENABLE_WA_05000257
&& (regno
== REG_LC0
|| regno
== REG_LC1
)))
566 emit_move_insn (gen_rtx_REG (SImode
, regno
), postinc
);
568 emit_move_insn (gen_rtx_REG (SImode
, REG_ASTAT
), postinc
);
572 /* Perform any needed actions needed for a function that is receiving a
573 variable number of arguments.
577 MODE and TYPE are the mode and type of the current parameter.
579 PRETEND_SIZE is a variable that should be set to the amount of stack
580 that must be pushed by the prolog to pretend that our caller pushed
583 Normally, this macro will push all remaining incoming registers on the
584 stack and set PRETEND_SIZE to the length of the registers pushed.
587 - VDSP C compiler manual (our ABI) says that a variable args function
588 should save the R0, R1 and R2 registers in the stack.
589 - The caller will always leave space on the stack for the
590 arguments that are passed in registers, so we dont have
591 to leave any extra space.
592 - now, the vastart pointer can access all arguments from the stack. */
595 setup_incoming_varargs (cumulative_args_t cum
,
596 machine_mode mode ATTRIBUTE_UNUSED
,
597 tree type ATTRIBUTE_UNUSED
, int *pretend_size
,
606 /* The move for named arguments will be generated automatically by the
607 compiler. We need to generate the move rtx for the unnamed arguments
608 if they are in the first 3 words. We assume at least 1 named argument
609 exists, so we never generate [ARGP] = R0 here. */
611 for (i
= get_cumulative_args (cum
)->words
+ 1; i
< max_arg_registers
; i
++)
613 mem
= gen_rtx_MEM (Pmode
,
614 plus_constant (Pmode
, arg_pointer_rtx
,
615 (i
* UNITS_PER_WORD
)));
616 emit_move_insn (mem
, gen_rtx_REG (Pmode
, i
));
622 /* Value should be nonzero if functions must have frame pointers.
623 Zero means the frame pointer need not be set up (and parms may
624 be accessed via the stack pointer) in functions that seem suitable. */
627 bfin_frame_pointer_required (void)
629 e_funkind fkind
= funkind (TREE_TYPE (current_function_decl
));
631 if (fkind
!= SUBROUTINE
)
634 /* We turn on -fomit-frame-pointer if -momit-leaf-frame-pointer is used,
635 so we have to override it for non-leaf functions. */
636 if (TARGET_OMIT_LEAF_FRAME_POINTER
&& ! crtl
->is_leaf
)
642 /* Return the number of registers pushed during the prologue. */
645 n_regs_saved_by_prologue (void)
647 e_funkind fkind
= funkind (TREE_TYPE (current_function_decl
));
648 bool is_inthandler
= fkind
!= SUBROUTINE
;
649 tree attrs
= TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl
));
650 bool all
= (lookup_attribute ("saveall", attrs
) != NULL_TREE
651 || (is_inthandler
&& !crtl
->is_leaf
));
652 int ndregs
= all
? 8 : n_dregs_to_save (is_inthandler
, false);
653 int npregs
= all
? 6 : n_pregs_to_save (is_inthandler
, false);
654 int n
= ndregs
+ npregs
;
657 if (all
|| stack_frame_needed_p ())
661 if (must_save_fp_p ())
663 if (must_save_rets_p ())
667 if (fkind
!= SUBROUTINE
|| all
)
669 /* Increment once for ASTAT. */
672 || cfun
->machine
->has_hardware_loops
673 || cfun
->machine
->has_loopreg_clobber
)
679 if (fkind
!= SUBROUTINE
)
682 if (lookup_attribute ("nesting", attrs
))
686 for (i
= REG_P7
+ 1; i
< REG_CC
; i
++)
688 || (fkind
!= SUBROUTINE
689 && (df_regs_ever_live_p (i
)
690 || (!leaf_function_p () && call_used_regs
[i
]))))
691 n
+= i
== REG_A0
|| i
== REG_A1
? 2 : 1;
696 /* Given FROM and TO register numbers, say whether this elimination is
697 allowed. Frame pointer elimination is automatically handled.
699 All other eliminations are valid. */
702 bfin_can_eliminate (const int from ATTRIBUTE_UNUSED
, const int to
)
704 return (to
== STACK_POINTER_REGNUM
? ! frame_pointer_needed
: true);
707 /* Return the offset between two registers, one to be eliminated, and the other
708 its replacement, at the start of a routine. */
711 bfin_initial_elimination_offset (int from
, int to
)
713 HOST_WIDE_INT offset
= 0;
715 if (from
== ARG_POINTER_REGNUM
)
716 offset
= n_regs_saved_by_prologue () * 4;
718 if (to
== STACK_POINTER_REGNUM
)
720 if (crtl
->outgoing_args_size
>= FIXED_STACK_AREA
)
721 offset
+= crtl
->outgoing_args_size
;
722 else if (crtl
->outgoing_args_size
)
723 offset
+= FIXED_STACK_AREA
;
725 offset
+= get_frame_size ();
731 /* Emit code to load a constant CONSTANT into register REG; setting
732 RTX_FRAME_RELATED_P on all insns we generate if RELATED is true.
733 Make sure that the insns we generate need not be split. */
736 frame_related_constant_load (rtx reg
, HOST_WIDE_INT constant
, bool related
)
739 rtx cst
= GEN_INT (constant
);
741 if (constant
>= -32768 && constant
< 65536)
742 insn
= emit_move_insn (reg
, cst
);
745 /* We don't call split_load_immediate here, since dwarf2out.c can get
746 confused about some of the more clever sequences it can generate. */
747 insn
= emit_insn (gen_movsi_high (reg
, cst
));
749 RTX_FRAME_RELATED_P (insn
) = 1;
750 insn
= emit_insn (gen_movsi_low (reg
, reg
, cst
));
753 RTX_FRAME_RELATED_P (insn
) = 1;
756 /* Generate efficient code to add a value to a P register.
757 Set RTX_FRAME_RELATED_P on the generated insns if FRAME is nonzero.
758 EPILOGUE_P is zero if this function is called for prologue,
759 otherwise it's nonzero. And it's less than zero if this is for
763 add_to_reg (rtx reg
, HOST_WIDE_INT value
, int frame
, int epilogue_p
)
768 /* Choose whether to use a sequence using a temporary register, or
769 a sequence with multiple adds. We can add a signed 7-bit value
770 in one instruction. */
771 if (value
> 120 || value
< -120)
779 /* For prologue or normal epilogue, P1 can be safely used
780 as the temporary register. For sibcall epilogue, we try to find
781 a call used P register, which will be restored in epilogue.
782 If we cannot find such a P register, we have to use one I register
786 tmpreg
= gen_rtx_REG (SImode
, REG_P1
);
790 for (i
= REG_P0
; i
<= REG_P5
; i
++)
791 if ((df_regs_ever_live_p (i
) && ! call_used_regs
[i
])
793 && i
== PIC_OFFSET_TABLE_REGNUM
794 && (crtl
->uses_pic_offset_table
795 || (TARGET_ID_SHARED_LIBRARY
796 && ! crtl
->is_leaf
))))
799 tmpreg
= gen_rtx_REG (SImode
, i
);
802 tmpreg
= gen_rtx_REG (SImode
, REG_P1
);
803 tmpreg2
= gen_rtx_REG (SImode
, REG_I0
);
804 emit_move_insn (tmpreg2
, tmpreg
);
809 frame_related_constant_load (tmpreg
, value
, TRUE
);
811 insn
= emit_move_insn (tmpreg
, GEN_INT (value
));
813 insn
= emit_insn (gen_addsi3 (reg
, reg
, tmpreg
));
815 RTX_FRAME_RELATED_P (insn
) = 1;
817 if (tmpreg2
!= NULL_RTX
)
818 emit_move_insn (tmpreg
, tmpreg2
);
829 /* We could use -62, but that would leave the stack unaligned, so
833 insn
= emit_insn (gen_addsi3 (reg
, reg
, GEN_INT (size
)));
835 RTX_FRAME_RELATED_P (insn
) = 1;
841 /* Generate a LINK insn for a frame sized FRAME_SIZE. If this constant
842 is too large, generate a sequence of insns that has the same effect.
843 SPREG contains (reg:SI REG_SP). */
846 emit_link_insn (rtx spreg
, HOST_WIDE_INT frame_size
)
848 HOST_WIDE_INT link_size
= frame_size
;
852 if (link_size
> 262140)
855 /* Use a LINK insn with as big a constant as possible, then subtract
856 any remaining size from the SP. */
857 insn
= emit_insn (gen_link (GEN_INT (-8 - link_size
)));
858 RTX_FRAME_RELATED_P (insn
) = 1;
860 for (i
= 0; i
< XVECLEN (PATTERN (insn
), 0); i
++)
862 rtx set
= XVECEXP (PATTERN (insn
), 0, i
);
863 gcc_assert (GET_CODE (set
) == SET
);
864 RTX_FRAME_RELATED_P (set
) = 1;
867 frame_size
-= link_size
;
871 /* Must use a call-clobbered PREG that isn't the static chain. */
872 rtx tmpreg
= gen_rtx_REG (Pmode
, REG_P1
);
874 frame_related_constant_load (tmpreg
, -frame_size
, TRUE
);
875 insn
= emit_insn (gen_addsi3 (spreg
, spreg
, tmpreg
));
876 RTX_FRAME_RELATED_P (insn
) = 1;
880 /* Return the number of bytes we must reserve for outgoing arguments
881 in the current function's stack frame. */
886 if (crtl
->outgoing_args_size
)
888 if (crtl
->outgoing_args_size
>= FIXED_STACK_AREA
)
889 return crtl
->outgoing_args_size
;
891 return FIXED_STACK_AREA
;
896 /* Save RETS and FP, and allocate a stack frame. ALL is true if the
897 function must save all its registers (true only for certain interrupt
901 do_link (rtx spreg
, HOST_WIDE_INT frame_size
, bool all
)
903 frame_size
+= arg_area_size ();
906 || stack_frame_needed_p ()
907 || (must_save_rets_p () && must_save_fp_p ()))
908 emit_link_insn (spreg
, frame_size
);
911 if (must_save_rets_p ())
913 rtx pat
= gen_movsi (gen_rtx_MEM (Pmode
,
914 gen_rtx_PRE_DEC (Pmode
, spreg
)),
916 rtx_insn
*insn
= emit_insn (pat
);
917 RTX_FRAME_RELATED_P (insn
) = 1;
919 if (must_save_fp_p ())
921 rtx pat
= gen_movsi (gen_rtx_MEM (Pmode
,
922 gen_rtx_PRE_DEC (Pmode
, spreg
)),
923 gen_rtx_REG (Pmode
, REG_FP
));
924 rtx_insn
*insn
= emit_insn (pat
);
925 RTX_FRAME_RELATED_P (insn
) = 1;
927 add_to_reg (spreg
, -frame_size
, 1, 0);
931 /* Like do_link, but used for epilogues to deallocate the stack frame.
932 EPILOGUE_P is zero if this function is called for prologue,
933 otherwise it's nonzero. And it's less than zero if this is for
937 do_unlink (rtx spreg
, HOST_WIDE_INT frame_size
, bool all
, int epilogue_p
)
939 frame_size
+= arg_area_size ();
941 if (stack_frame_needed_p ())
942 emit_insn (gen_unlink ());
945 rtx postinc
= gen_rtx_MEM (Pmode
, gen_rtx_POST_INC (Pmode
, spreg
));
947 add_to_reg (spreg
, frame_size
, 0, epilogue_p
);
948 if (all
|| must_save_fp_p ())
950 rtx fpreg
= gen_rtx_REG (Pmode
, REG_FP
);
951 emit_move_insn (fpreg
, postinc
);
954 if (all
|| must_save_rets_p ())
956 emit_move_insn (bfin_rets_rtx
, postinc
);
957 emit_use (bfin_rets_rtx
);
962 /* Generate a prologue suitable for a function of kind FKIND. This is
963 called for interrupt and exception handler prologues.
964 SPREG contains (reg:SI REG_SP). */
967 expand_interrupt_handler_prologue (rtx spreg
, e_funkind fkind
, bool all
)
969 HOST_WIDE_INT frame_size
= get_frame_size ();
970 rtx predec1
= gen_rtx_PRE_DEC (SImode
, spreg
);
971 rtx predec
= gen_rtx_MEM (SImode
, predec1
);
973 tree attrs
= TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl
));
974 tree kspisusp
= lookup_attribute ("kspisusp", attrs
);
978 insn
= emit_move_insn (spreg
, gen_rtx_REG (Pmode
, REG_USP
));
979 RTX_FRAME_RELATED_P (insn
) = 1;
982 /* We need space on the stack in case we need to save the argument
984 if (fkind
== EXCPT_HANDLER
)
986 insn
= emit_insn (gen_addsi3 (spreg
, spreg
, GEN_INT (-12)));
987 RTX_FRAME_RELATED_P (insn
) = 1;
990 /* If we're calling other functions, they won't save their call-clobbered
991 registers, so we must save everything here. */
994 expand_prologue_reg_save (spreg
, all
, true);
996 if (ENABLE_WA_05000283
|| ENABLE_WA_05000315
)
998 rtx chipid
= GEN_INT (trunc_int_for_mode (0xFFC00014, SImode
));
999 rtx p5reg
= gen_rtx_REG (Pmode
, REG_P5
);
1000 emit_insn (gen_movbi (bfin_cc_rtx
, const1_rtx
));
1001 emit_insn (gen_movsi_high (p5reg
, chipid
));
1002 emit_insn (gen_movsi_low (p5reg
, p5reg
, chipid
));
1003 emit_insn (gen_dummy_load (p5reg
, bfin_cc_rtx
));
1006 if (lookup_attribute ("nesting", attrs
))
1008 rtx srcreg
= gen_rtx_REG (Pmode
, ret_regs
[fkind
]);
1009 insn
= emit_move_insn (predec
, srcreg
);
1010 RTX_FRAME_RELATED_P (insn
) = 1;
1013 do_link (spreg
, frame_size
, all
);
1015 if (fkind
== EXCPT_HANDLER
)
1017 rtx r0reg
= gen_rtx_REG (SImode
, REG_R0
);
1018 rtx r1reg
= gen_rtx_REG (SImode
, REG_R1
);
1019 rtx r2reg
= gen_rtx_REG (SImode
, REG_R2
);
1021 emit_move_insn (r0reg
, gen_rtx_REG (SImode
, REG_SEQSTAT
));
1022 emit_insn (gen_ashrsi3 (r0reg
, r0reg
, GEN_INT (26)));
1023 emit_insn (gen_ashlsi3 (r0reg
, r0reg
, GEN_INT (26)));
1024 emit_move_insn (r1reg
, spreg
);
1025 emit_move_insn (r2reg
, gen_rtx_REG (Pmode
, REG_FP
));
1026 emit_insn (gen_addsi3 (r2reg
, r2reg
, GEN_INT (8)));
1030 /* Generate an epilogue suitable for a function of kind FKIND. This is
1031 called for interrupt and exception handler epilogues.
1032 SPREG contains (reg:SI REG_SP). */
1035 expand_interrupt_handler_epilogue (rtx spreg
, e_funkind fkind
, bool all
)
1037 tree attrs
= TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl
));
1038 rtx postinc1
= gen_rtx_POST_INC (SImode
, spreg
);
1039 rtx postinc
= gen_rtx_MEM (SImode
, postinc1
);
1041 /* A slightly crude technique to stop flow from trying to delete "dead"
1043 MEM_VOLATILE_P (postinc
) = 1;
1045 do_unlink (spreg
, get_frame_size (), all
, 1);
1047 if (lookup_attribute ("nesting", attrs
))
1049 rtx srcreg
= gen_rtx_REG (Pmode
, ret_regs
[fkind
]);
1050 emit_move_insn (srcreg
, postinc
);
1053 /* If we're calling other functions, they won't save their call-clobbered
1054 registers, so we must save (and restore) everything here. */
1058 expand_epilogue_reg_restore (spreg
, all
, true);
1060 /* Deallocate any space we left on the stack in case we needed to save the
1061 argument registers. */
1062 if (fkind
== EXCPT_HANDLER
)
1063 emit_insn (gen_addsi3 (spreg
, spreg
, GEN_INT (12)));
1065 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode
, ret_regs
[fkind
])));
1068 /* Used while emitting the prologue to generate code to load the correct value
1069 into the PIC register, which is passed in DEST. */
1072 bfin_load_pic_reg (rtx dest
)
1074 struct cgraph_local_info
*i
= NULL
;
1077 i
= cgraph_node::local_info (current_function_decl
);
1079 /* Functions local to the translation unit don't need to reload the
1080 pic reg, since the caller always passes a usable one. */
1082 return pic_offset_table_rtx
;
1084 if (global_options_set
.x_bfin_library_id
)
1085 addr
= plus_constant (Pmode
, pic_offset_table_rtx
,
1086 -4 - bfin_library_id
* 4);
1088 addr
= gen_rtx_PLUS (Pmode
, pic_offset_table_rtx
,
1089 gen_rtx_UNSPEC (Pmode
, gen_rtvec (1, const0_rtx
),
1090 UNSPEC_LIBRARY_OFFSET
));
1091 emit_insn (gen_movsi (dest
, gen_rtx_MEM (Pmode
, addr
)));
1095 /* Generate RTL for the prologue of the current function. */
1098 bfin_expand_prologue (void)
1100 HOST_WIDE_INT frame_size
= get_frame_size ();
1101 rtx spreg
= gen_rtx_REG (Pmode
, REG_SP
);
1102 e_funkind fkind
= funkind (TREE_TYPE (current_function_decl
));
1103 rtx pic_reg_loaded
= NULL_RTX
;
1104 tree attrs
= TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl
));
1105 bool all
= lookup_attribute ("saveall", attrs
) != NULL_TREE
;
1107 if (fkind
!= SUBROUTINE
)
1109 expand_interrupt_handler_prologue (spreg
, fkind
, all
);
1113 if (crtl
->limit_stack
1114 || (TARGET_STACK_CHECK_L1
1115 && !DECL_NO_LIMIT_STACK (current_function_decl
)))
1117 HOST_WIDE_INT offset
1118 = bfin_initial_elimination_offset (ARG_POINTER_REGNUM
,
1119 STACK_POINTER_REGNUM
);
1120 rtx lim
= crtl
->limit_stack
? stack_limit_rtx
: NULL_RTX
;
1121 rtx tmp
= gen_rtx_REG (Pmode
, REG_R3
);
1122 rtx p2reg
= gen_rtx_REG (Pmode
, REG_P2
);
1124 emit_move_insn (tmp
, p2reg
);
1127 emit_move_insn (p2reg
, gen_int_mode (0xFFB00000, SImode
));
1128 emit_move_insn (p2reg
, gen_rtx_MEM (Pmode
, p2reg
));
1131 if (GET_CODE (lim
) == SYMBOL_REF
)
1133 if (TARGET_ID_SHARED_LIBRARY
)
1135 rtx p1reg
= gen_rtx_REG (Pmode
, REG_P1
);
1137 pic_reg_loaded
= bfin_load_pic_reg (p2reg
);
1138 val
= legitimize_pic_address (stack_limit_rtx
, p1reg
,
1140 emit_move_insn (p1reg
, val
);
1141 frame_related_constant_load (p2reg
, offset
, FALSE
);
1142 emit_insn (gen_addsi3 (p2reg
, p2reg
, p1reg
));
1147 rtx limit
= plus_constant (Pmode
, lim
, offset
);
1148 emit_move_insn (p2reg
, limit
);
1155 emit_move_insn (p2reg
, lim
);
1156 add_to_reg (p2reg
, offset
, 0, 0);
1159 emit_insn (gen_compare_lt (bfin_cc_rtx
, spreg
, lim
));
1160 emit_insn (gen_trapifcc ());
1161 emit_move_insn (p2reg
, tmp
);
1163 expand_prologue_reg_save (spreg
, all
, false);
1165 do_link (spreg
, frame_size
, all
);
1167 if (TARGET_ID_SHARED_LIBRARY
1169 && (crtl
->uses_pic_offset_table
1171 bfin_load_pic_reg (pic_offset_table_rtx
);
1174 /* Generate RTL for the epilogue of the current function. NEED_RETURN is zero
1175 if this is for a sibcall. EH_RETURN is nonzero if we're expanding an
1176 eh_return pattern. SIBCALL_P is true if this is a sibcall epilogue,
1180 bfin_expand_epilogue (int need_return
, int eh_return
, bool sibcall_p
)
1182 rtx spreg
= gen_rtx_REG (Pmode
, REG_SP
);
1183 e_funkind fkind
= funkind (TREE_TYPE (current_function_decl
));
1184 int e
= sibcall_p
? -1 : 1;
1185 tree attrs
= TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl
));
1186 bool all
= lookup_attribute ("saveall", attrs
) != NULL_TREE
;
1188 if (fkind
!= SUBROUTINE
)
1190 expand_interrupt_handler_epilogue (spreg
, fkind
, all
);
1194 do_unlink (spreg
, get_frame_size (), all
, e
);
1196 expand_epilogue_reg_restore (spreg
, all
, false);
1198 /* Omit the return insn if this is for a sibcall. */
1203 emit_insn (gen_addsi3 (spreg
, spreg
, gen_rtx_REG (Pmode
, REG_P2
)));
1205 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode
, REG_RETS
)));
1208 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
1211 bfin_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED
,
1212 unsigned int new_reg
)
1214 /* Interrupt functions can only use registers that have already been
1215 saved by the prologue, even if they would normally be
1218 if (funkind (TREE_TYPE (current_function_decl
)) != SUBROUTINE
1219 && !df_regs_ever_live_p (new_reg
))
1225 /* Implement TARGET_EXTRA_LIVE_ON_ENTRY. */
1227 bfin_extra_live_on_entry (bitmap regs
)
1230 bitmap_set_bit (regs
, FDPIC_REGNO
);
1233 /* Return the value of the return address for the frame COUNT steps up
1234 from the current frame, after the prologue.
1235 We punt for everything but the current frame by returning const0_rtx. */
1238 bfin_return_addr_rtx (int count
)
1243 return get_hard_reg_initial_val (Pmode
, REG_RETS
);
1247 bfin_delegitimize_address (rtx orig_x
)
1251 if (GET_CODE (x
) != MEM
)
1255 if (GET_CODE (x
) == PLUS
1256 && GET_CODE (XEXP (x
, 1)) == UNSPEC
1257 && XINT (XEXP (x
, 1), 1) == UNSPEC_MOVE_PIC
1258 && GET_CODE (XEXP (x
, 0)) == REG
1259 && REGNO (XEXP (x
, 0)) == PIC_OFFSET_TABLE_REGNUM
)
1260 return XVECEXP (XEXP (x
, 1), 0, 0);
1265 /* This predicate is used to compute the length of a load/store insn.
1266 OP is a MEM rtx, we return nonzero if its addressing mode requires a
1267 32-bit instruction. */
1270 effective_address_32bit_p (rtx op
, machine_mode mode
)
1272 HOST_WIDE_INT offset
;
1274 mode
= GET_MODE (op
);
1277 if (GET_CODE (op
) != PLUS
)
1279 gcc_assert (REG_P (op
) || GET_CODE (op
) == POST_INC
1280 || GET_CODE (op
) == PRE_DEC
|| GET_CODE (op
) == POST_DEC
);
1284 if (GET_CODE (XEXP (op
, 1)) == UNSPEC
)
1287 offset
= INTVAL (XEXP (op
, 1));
1289 /* All byte loads use a 16-bit offset. */
1290 if (GET_MODE_SIZE (mode
) == 1)
1293 if (GET_MODE_SIZE (mode
) == 4)
1295 /* Frame pointer relative loads can use a negative offset, all others
1296 are restricted to a small positive one. */
1297 if (XEXP (op
, 0) == frame_pointer_rtx
)
1298 return offset
< -128 || offset
> 60;
1299 return offset
< 0 || offset
> 60;
1302 /* Must be HImode now. */
1303 return offset
< 0 || offset
> 30;
1306 /* Returns true if X is a memory reference using an I register. */
1308 bfin_dsp_memref_p (rtx x
)
1313 if (GET_CODE (x
) == POST_INC
|| GET_CODE (x
) == PRE_INC
1314 || GET_CODE (x
) == POST_DEC
|| GET_CODE (x
) == PRE_DEC
)
1319 /* Return cost of the memory address ADDR.
1320 All addressing modes are equally cheap on the Blackfin. */
1323 bfin_address_cost (rtx addr ATTRIBUTE_UNUSED
,
1324 machine_mode mode ATTRIBUTE_UNUSED
,
1325 addr_space_t as ATTRIBUTE_UNUSED
,
1326 bool speed ATTRIBUTE_UNUSED
)
1331 /* Subroutine of print_operand; used to print a memory reference X to FILE. */
1334 print_address_operand (FILE *file
, rtx x
)
1336 switch (GET_CODE (x
))
1339 output_address (XEXP (x
, 0));
1340 fprintf (file
, "+");
1341 output_address (XEXP (x
, 1));
1345 fprintf (file
, "--");
1346 output_address (XEXP (x
, 0));
1349 output_address (XEXP (x
, 0));
1350 fprintf (file
, "++");
1353 output_address (XEXP (x
, 0));
1354 fprintf (file
, "--");
1358 gcc_assert (GET_CODE (x
) != MEM
);
1359 print_operand (file
, x
, 0);
1364 /* Adding intp DImode support by Tony
1370 print_operand (FILE *file
, rtx x
, char code
)
1376 if (GET_MODE (current_output_insn
) == SImode
)
1377 fprintf (file
, " ||");
1379 fprintf (file
, ";");
1383 mode
= GET_MODE (x
);
1388 switch (GET_CODE (x
))
1391 fprintf (file
, "e");
1394 fprintf (file
, "ne");
1397 fprintf (file
, "g");
1400 fprintf (file
, "l");
1403 fprintf (file
, "ge");
1406 fprintf (file
, "le");
1409 fprintf (file
, "g");
1412 fprintf (file
, "l");
1415 fprintf (file
, "ge");
1418 fprintf (file
, "le");
1421 output_operand_lossage ("invalid %%j value");
1425 case 'J': /* reverse logic */
1426 switch (GET_CODE(x
))
1429 fprintf (file
, "ne");
1432 fprintf (file
, "e");
1435 fprintf (file
, "le");
1438 fprintf (file
, "ge");
1441 fprintf (file
, "l");
1444 fprintf (file
, "g");
1447 fprintf (file
, "le");
1450 fprintf (file
, "ge");
1453 fprintf (file
, "l");
1456 fprintf (file
, "g");
1459 output_operand_lossage ("invalid %%J value");
1464 switch (GET_CODE (x
))
1470 fprintf (file
, "%s", short_reg_names
[REGNO (x
)]);
1472 output_operand_lossage ("invalid operand for code '%c'", code
);
1474 else if (code
== 'd')
1477 fprintf (file
, "%s", high_reg_names
[REGNO (x
)]);
1479 output_operand_lossage ("invalid operand for code '%c'", code
);
1481 else if (code
== 'w')
1483 if (REGNO (x
) == REG_A0
|| REGNO (x
) == REG_A1
)
1484 fprintf (file
, "%s.w", reg_names
[REGNO (x
)]);
1486 output_operand_lossage ("invalid operand for code '%c'", code
);
1488 else if (code
== 'x')
1490 if (REGNO (x
) == REG_A0
|| REGNO (x
) == REG_A1
)
1491 fprintf (file
, "%s.x", reg_names
[REGNO (x
)]);
1493 output_operand_lossage ("invalid operand for code '%c'", code
);
1495 else if (code
== 'v')
1497 if (REGNO (x
) == REG_A0
)
1498 fprintf (file
, "AV0");
1499 else if (REGNO (x
) == REG_A1
)
1500 fprintf (file
, "AV1");
1502 output_operand_lossage ("invalid operand for code '%c'", code
);
1504 else if (code
== 'D')
1506 if (D_REGNO_P (REGNO (x
)))
1507 fprintf (file
, "%s", dregs_pair_names
[REGNO (x
)]);
1509 output_operand_lossage ("invalid operand for code '%c'", code
);
1511 else if (code
== 'H')
1513 if ((mode
== DImode
|| mode
== DFmode
) && REG_P (x
))
1514 fprintf (file
, "%s", reg_names
[REGNO (x
) + 1]);
1516 output_operand_lossage ("invalid operand for code '%c'", code
);
1518 else if (code
== 'T')
1520 if (D_REGNO_P (REGNO (x
)))
1521 fprintf (file
, "%s", byte_reg_names
[REGNO (x
)]);
1523 output_operand_lossage ("invalid operand for code '%c'", code
);
1526 fprintf (file
, "%s", reg_names
[REGNO (x
)]);
1532 print_address_operand (file
, x
);
1544 fputs ("(FU)", file
);
1547 fputs ("(T)", file
);
1550 fputs ("(TFU)", file
);
1553 fputs ("(W32)", file
);
1556 fputs ("(IS)", file
);
1559 fputs ("(IU)", file
);
1562 fputs ("(IH)", file
);
1565 fputs ("(M)", file
);
1568 fputs ("(IS,M)", file
);
1571 fputs ("(ISS2)", file
);
1574 fputs ("(S2RND)", file
);
1581 else if (code
== 'b')
1583 if (INTVAL (x
) == 0)
1585 else if (INTVAL (x
) == 1)
1591 /* Moves to half registers with d or h modifiers always use unsigned
1593 else if (code
== 'd')
1594 x
= GEN_INT ((INTVAL (x
) >> 16) & 0xffff);
1595 else if (code
== 'h')
1596 x
= GEN_INT (INTVAL (x
) & 0xffff);
1597 else if (code
== 'N')
1598 x
= GEN_INT (-INTVAL (x
));
1599 else if (code
== 'X')
1600 x
= GEN_INT (exact_log2 (0xffffffff & INTVAL (x
)));
1601 else if (code
== 'Y')
1602 x
= GEN_INT (exact_log2 (0xffffffff & ~INTVAL (x
)));
1603 else if (code
== 'Z')
1604 /* Used for LINK insns. */
1605 x
= GEN_INT (-8 - INTVAL (x
));
1610 output_addr_const (file
, x
);
1614 output_operand_lossage ("invalid const_double operand");
1618 switch (XINT (x
, 1))
1620 case UNSPEC_MOVE_PIC
:
1621 output_addr_const (file
, XVECEXP (x
, 0, 0));
1622 fprintf (file
, "@GOT");
1625 case UNSPEC_MOVE_FDPIC
:
1626 output_addr_const (file
, XVECEXP (x
, 0, 0));
1627 fprintf (file
, "@GOT17M4");
1630 case UNSPEC_FUNCDESC_GOT17M4
:
1631 output_addr_const (file
, XVECEXP (x
, 0, 0));
1632 fprintf (file
, "@FUNCDESC_GOT17M4");
1635 case UNSPEC_LIBRARY_OFFSET
:
1636 fprintf (file
, "_current_shared_library_p5_offset_");
1645 output_addr_const (file
, x
);
1650 /* Argument support functions. */
1652 /* Initialize a variable CUM of type CUMULATIVE_ARGS
1653 for a call to a function whose data type is FNTYPE.
1654 For a library call, FNTYPE is 0.
1655 VDSP C Compiler manual, our ABI says that
1656 first 3 words of arguments will use R0, R1 and R2.
1660 init_cumulative_args (CUMULATIVE_ARGS
*cum
, tree fntype
,
1661 rtx libname ATTRIBUTE_UNUSED
)
1663 static CUMULATIVE_ARGS zero_cum
;
1667 /* Set up the number of registers to use for passing arguments. */
1669 cum
->nregs
= max_arg_registers
;
1670 cum
->arg_regs
= arg_regs
;
1672 cum
->call_cookie
= CALL_NORMAL
;
1673 /* Check for a longcall attribute. */
1674 if (fntype
&& lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype
)))
1675 cum
->call_cookie
|= CALL_SHORT
;
1676 else if (fntype
&& lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype
)))
1677 cum
->call_cookie
|= CALL_LONG
;
1682 /* Update the data in CUM to advance over an argument
1683 of mode MODE and data type TYPE.
1684 (TYPE is null for libcalls where that information may not be available.) */
1687 bfin_function_arg_advance (cumulative_args_t cum_v
, machine_mode mode
,
1688 const_tree type
, bool named ATTRIBUTE_UNUSED
)
1690 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
1691 int count
, bytes
, words
;
1693 bytes
= (mode
== BLKmode
) ? int_size_in_bytes (type
) : GET_MODE_SIZE (mode
);
1694 words
= (bytes
+ UNITS_PER_WORD
- 1) / UNITS_PER_WORD
;
1696 cum
->words
+= words
;
1697 cum
->nregs
-= words
;
1699 if (cum
->nregs
<= 0)
1702 cum
->arg_regs
= NULL
;
1706 for (count
= 1; count
<= words
; count
++)
1713 /* Define where to put the arguments to a function.
1714 Value is zero to push the argument on the stack,
1715 or a hard register in which to store the argument.
1717 MODE is the argument's machine mode.
1718 TYPE is the data type of the argument (as a tree).
1719 This is null for libcalls where that information may
1721 CUM is a variable of type CUMULATIVE_ARGS which gives info about
1722 the preceding args and about the function being called.
1723 NAMED is nonzero if this argument is a named parameter
1724 (otherwise it is an extra parameter matching an ellipsis). */
1727 bfin_function_arg (cumulative_args_t cum_v
, machine_mode mode
,
1728 const_tree type
, bool named ATTRIBUTE_UNUSED
)
1730 CUMULATIVE_ARGS
*cum
= get_cumulative_args (cum_v
);
1732 = (mode
== BLKmode
) ? int_size_in_bytes (type
) : GET_MODE_SIZE (mode
);
1734 if (mode
== VOIDmode
)
1735 /* Compute operand 2 of the call insn. */
1736 return GEN_INT (cum
->call_cookie
);
1742 return gen_rtx_REG (mode
, *(cum
->arg_regs
));
1747 /* For an arg passed partly in registers and partly in memory,
1748 this is the number of bytes passed in registers.
1749 For args passed entirely in registers or entirely in memory, zero.
1751 Refer VDSP C Compiler manual, our ABI.
1752 First 3 words are in registers. So, if an argument is larger
1753 than the registers available, it will span the register and
1757 bfin_arg_partial_bytes (cumulative_args_t cum
, machine_mode mode
,
1758 tree type ATTRIBUTE_UNUSED
,
1759 bool named ATTRIBUTE_UNUSED
)
1762 = (mode
== BLKmode
) ? int_size_in_bytes (type
) : GET_MODE_SIZE (mode
);
1763 int bytes_left
= get_cumulative_args (cum
)->nregs
* UNITS_PER_WORD
;
1768 if (bytes_left
== 0)
1770 if (bytes
> bytes_left
)
1775 /* Variable sized types are passed by reference. */
1778 bfin_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED
,
1779 machine_mode mode ATTRIBUTE_UNUSED
,
1780 const_tree type
, bool named ATTRIBUTE_UNUSED
)
1782 return type
&& TREE_CODE (TYPE_SIZE (type
)) != INTEGER_CST
;
1785 /* Decide whether a type should be returned in memory (true)
1786 or in a register (false). This is called by the macro
1787 TARGET_RETURN_IN_MEMORY. */
1790 bfin_return_in_memory (const_tree type
, const_tree fntype ATTRIBUTE_UNUSED
)
1792 int size
= int_size_in_bytes (type
);
1793 return size
> 2 * UNITS_PER_WORD
|| size
== -1;
1796 /* Register in which address to store a structure value
1797 is passed to a function. */
1799 bfin_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED
,
1800 int incoming ATTRIBUTE_UNUSED
)
1802 return gen_rtx_REG (Pmode
, REG_P0
);
1805 /* Return true when register may be used to pass function parameters. */
1808 function_arg_regno_p (int n
)
1811 for (i
= 0; arg_regs
[i
] != -1; i
++)
1812 if (n
== arg_regs
[i
])
1817 /* Returns 1 if OP contains a symbol reference */
1820 symbolic_reference_mentioned_p (rtx op
)
1822 register const char *fmt
;
1825 if (GET_CODE (op
) == SYMBOL_REF
|| GET_CODE (op
) == LABEL_REF
)
1828 fmt
= GET_RTX_FORMAT (GET_CODE (op
));
1829 for (i
= GET_RTX_LENGTH (GET_CODE (op
)) - 1; i
>= 0; i
--)
1835 for (j
= XVECLEN (op
, i
) - 1; j
>= 0; j
--)
1836 if (symbolic_reference_mentioned_p (XVECEXP (op
, i
, j
)))
1840 else if (fmt
[i
] == 'e' && symbolic_reference_mentioned_p (XEXP (op
, i
)))
1847 /* Decide whether we can make a sibling call to a function. DECL is the
1848 declaration of the function being targeted by the call and EXP is the
1849 CALL_EXPR representing the call. */
1852 bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED
,
1853 tree exp ATTRIBUTE_UNUSED
)
1855 struct cgraph_local_info
*this_func
, *called_func
;
1856 e_funkind fkind
= funkind (TREE_TYPE (current_function_decl
));
1857 if (fkind
!= SUBROUTINE
)
1859 if (!TARGET_ID_SHARED_LIBRARY
|| TARGET_SEP_DATA
)
1862 /* When compiling for ID shared libraries, can't sibcall a local function
1863 from a non-local function, because the local function thinks it does
1864 not need to reload P5 in the prologue, but the sibcall wil pop P5 in the
1865 sibcall epilogue, and we end up with the wrong value in P5. */
1868 /* Not enough information. */
1871 this_func
= cgraph_node::local_info (current_function_decl
);
1872 called_func
= cgraph_node::local_info (decl
);
1875 return !called_func
->local
|| this_func
->local
;
1878 /* Write a template for a trampoline to F. */
1881 bfin_asm_trampoline_template (FILE *f
)
1885 fprintf (f
, "\t.dd\t0x00000000\n"); /* 0 */
1886 fprintf (f
, "\t.dd\t0x00000000\n"); /* 0 */
1887 fprintf (f
, "\t.dd\t0x0000e109\n"); /* p1.l = fn low */
1888 fprintf (f
, "\t.dd\t0x0000e149\n"); /* p1.h = fn high */
1889 fprintf (f
, "\t.dd\t0x0000e10a\n"); /* p2.l = sc low */
1890 fprintf (f
, "\t.dd\t0x0000e14a\n"); /* p2.h = sc high */
1891 fprintf (f
, "\t.dw\t0xac4b\n"); /* p3 = [p1 + 4] */
1892 fprintf (f
, "\t.dw\t0x9149\n"); /* p1 = [p1] */
1893 fprintf (f
, "\t.dw\t0x0051\n"); /* jump (p1)*/
1897 fprintf (f
, "\t.dd\t0x0000e109\n"); /* p1.l = fn low */
1898 fprintf (f
, "\t.dd\t0x0000e149\n"); /* p1.h = fn high */
1899 fprintf (f
, "\t.dd\t0x0000e10a\n"); /* p2.l = sc low */
1900 fprintf (f
, "\t.dd\t0x0000e14a\n"); /* p2.h = sc high */
1901 fprintf (f
, "\t.dw\t0x0051\n"); /* jump (p1)*/
1905 /* Emit RTL insns to initialize the variable parts of a trampoline at
1906 M_TRAMP. FNDECL is the target function. CHAIN_VALUE is an RTX for
1907 the static chain value for the function. */
1910 bfin_trampoline_init (rtx m_tramp
, tree fndecl
, rtx chain_value
)
1912 rtx t1
= copy_to_reg (XEXP (DECL_RTL (fndecl
), 0));
1913 rtx t2
= copy_to_reg (chain_value
);
1917 emit_block_move (m_tramp
, assemble_trampoline_template (),
1918 GEN_INT (TRAMPOLINE_SIZE
), BLOCK_OP_NORMAL
);
1922 rtx a
= force_reg (Pmode
, plus_constant (Pmode
, XEXP (m_tramp
, 0), 8));
1923 mem
= adjust_address (m_tramp
, Pmode
, 0);
1924 emit_move_insn (mem
, a
);
1928 mem
= adjust_address (m_tramp
, HImode
, i
+ 2);
1929 emit_move_insn (mem
, gen_lowpart (HImode
, t1
));
1930 emit_insn (gen_ashrsi3 (t1
, t1
, GEN_INT (16)));
1931 mem
= adjust_address (m_tramp
, HImode
, i
+ 6);
1932 emit_move_insn (mem
, gen_lowpart (HImode
, t1
));
1934 mem
= adjust_address (m_tramp
, HImode
, i
+ 10);
1935 emit_move_insn (mem
, gen_lowpart (HImode
, t2
));
1936 emit_insn (gen_ashrsi3 (t2
, t2
, GEN_INT (16)));
1937 mem
= adjust_address (m_tramp
, HImode
, i
+ 14);
1938 emit_move_insn (mem
, gen_lowpart (HImode
, t2
));
1941 /* Emit insns to move operands[1] into operands[0]. */
1944 emit_pic_move (rtx
*operands
, machine_mode mode ATTRIBUTE_UNUSED
)
1946 rtx temp
= reload_in_progress
? operands
[0] : gen_reg_rtx (Pmode
);
1948 gcc_assert (!TARGET_FDPIC
|| !(reload_in_progress
|| reload_completed
));
1949 if (GET_CODE (operands
[0]) == MEM
&& SYMBOLIC_CONST (operands
[1]))
1950 operands
[1] = force_reg (SImode
, operands
[1]);
1952 operands
[1] = legitimize_pic_address (operands
[1], temp
,
1953 TARGET_FDPIC
? OUR_FDPIC_REG
1954 : pic_offset_table_rtx
);
1957 /* Expand a move operation in mode MODE. The operands are in OPERANDS.
1958 Returns true if no further code must be generated, false if the caller
1959 should generate an insn to move OPERANDS[1] to OPERANDS[0]. */
1962 expand_move (rtx
*operands
, machine_mode mode
)
1964 rtx op
= operands
[1];
1965 if ((TARGET_ID_SHARED_LIBRARY
|| TARGET_FDPIC
)
1966 && SYMBOLIC_CONST (op
))
1967 emit_pic_move (operands
, mode
);
1968 else if (mode
== SImode
&& GET_CODE (op
) == CONST
1969 && GET_CODE (XEXP (op
, 0)) == PLUS
1970 && GET_CODE (XEXP (XEXP (op
, 0), 0)) == SYMBOL_REF
1971 && !targetm
.legitimate_constant_p (mode
, op
))
1973 rtx dest
= operands
[0];
1975 gcc_assert (!reload_in_progress
&& !reload_completed
);
1977 op0
= force_reg (mode
, XEXP (op
, 0));
1979 if (!insn_data
[CODE_FOR_addsi3
].operand
[2].predicate (op1
, mode
))
1980 op1
= force_reg (mode
, op1
);
1981 if (GET_CODE (dest
) == MEM
)
1982 dest
= gen_reg_rtx (mode
);
1983 emit_insn (gen_addsi3 (dest
, op0
, op1
));
1984 if (dest
== operands
[0])
1988 /* Don't generate memory->memory or constant->memory moves, go through a
1990 else if ((reload_in_progress
| reload_completed
) == 0
1991 && GET_CODE (operands
[0]) == MEM
1992 && GET_CODE (operands
[1]) != REG
)
1993 operands
[1] = force_reg (mode
, operands
[1]);
1997 /* Split one or more DImode RTL references into pairs of SImode
1998 references. The RTL can be REG, offsettable MEM, integer constant, or
1999 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
2000 split and "num" is its length. lo_half and hi_half are output arrays
2001 that parallel "operands". */
2004 split_di (rtx operands
[], int num
, rtx lo_half
[], rtx hi_half
[])
2008 rtx op
= operands
[num
];
2010 /* simplify_subreg refuse to split volatile memory addresses,
2011 but we still have to handle it. */
2012 if (GET_CODE (op
) == MEM
)
2014 lo_half
[num
] = adjust_address (op
, SImode
, 0);
2015 hi_half
[num
] = adjust_address (op
, SImode
, 4);
2019 lo_half
[num
] = simplify_gen_subreg (SImode
, op
,
2020 GET_MODE (op
) == VOIDmode
2021 ? DImode
: GET_MODE (op
), 0);
2022 hi_half
[num
] = simplify_gen_subreg (SImode
, op
,
2023 GET_MODE (op
) == VOIDmode
2024 ? DImode
: GET_MODE (op
), 4);
2030 bfin_longcall_p (rtx op
, int call_cookie
)
2032 gcc_assert (GET_CODE (op
) == SYMBOL_REF
);
2033 if (SYMBOL_REF_WEAK (op
))
2035 if (call_cookie
& CALL_SHORT
)
2037 if (call_cookie
& CALL_LONG
)
2039 if (TARGET_LONG_CALLS
)
2044 /* Expand a call instruction. FNADDR is the call target, RETVAL the return value.
2045 COOKIE is a CONST_INT holding the call_cookie prepared init_cumulative_args.
2046 SIBCALL is nonzero if this is a sibling call. */
2049 bfin_expand_call (rtx retval
, rtx fnaddr
, rtx callarg1
, rtx cookie
, int sibcall
)
2051 rtx use
= NULL
, call
;
2052 rtx callee
= XEXP (fnaddr
, 0);
2055 rtx picreg
= get_hard_reg_initial_val (SImode
, FDPIC_REGNO
);
2056 rtx retsreg
= gen_rtx_REG (Pmode
, REG_RETS
);
2059 /* In an untyped call, we can get NULL for operand 2. */
2060 if (cookie
== NULL_RTX
)
2061 cookie
= const0_rtx
;
2063 /* Static functions and indirect calls don't need the pic register. */
2064 if (!TARGET_FDPIC
&& flag_pic
2065 && GET_CODE (callee
) == SYMBOL_REF
2066 && !SYMBOL_REF_LOCAL_P (callee
))
2067 use_reg (&use
, pic_offset_table_rtx
);
2071 int caller_in_sram
, callee_in_sram
;
2073 /* 0 is not in sram, 1 is in L1 sram, 2 is in L2 sram. */
2074 caller_in_sram
= callee_in_sram
= 0;
2076 if (lookup_attribute ("l1_text",
2077 DECL_ATTRIBUTES (cfun
->decl
)) != NULL_TREE
)
2079 else if (lookup_attribute ("l2",
2080 DECL_ATTRIBUTES (cfun
->decl
)) != NULL_TREE
)
2083 if (GET_CODE (callee
) == SYMBOL_REF
2084 && SYMBOL_REF_DECL (callee
) && DECL_P (SYMBOL_REF_DECL (callee
)))
2086 if (lookup_attribute
2088 DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee
))) != NULL_TREE
)
2090 else if (lookup_attribute
2092 DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee
))) != NULL_TREE
)
2096 if (GET_CODE (callee
) != SYMBOL_REF
2097 || bfin_longcall_p (callee
, INTVAL (cookie
))
2098 || (GET_CODE (callee
) == SYMBOL_REF
2099 && !SYMBOL_REF_LOCAL_P (callee
)
2100 && TARGET_INLINE_PLT
)
2101 || caller_in_sram
!= callee_in_sram
2102 || (caller_in_sram
&& callee_in_sram
2103 && (GET_CODE (callee
) != SYMBOL_REF
2104 || !SYMBOL_REF_LOCAL_P (callee
))))
2107 if (! address_operand (addr
, Pmode
))
2108 addr
= force_reg (Pmode
, addr
);
2110 fnaddr
= gen_reg_rtx (SImode
);
2111 emit_insn (gen_load_funcdescsi (fnaddr
, addr
));
2112 fnaddr
= gen_rtx_MEM (Pmode
, fnaddr
);
2114 picreg
= gen_reg_rtx (SImode
);
2115 emit_insn (gen_load_funcdescsi (picreg
,
2116 plus_constant (Pmode
, addr
, 4)));
2121 else if ((!register_no_elim_operand (callee
, Pmode
)
2122 && GET_CODE (callee
) != SYMBOL_REF
)
2123 || (GET_CODE (callee
) == SYMBOL_REF
2124 && ((TARGET_ID_SHARED_LIBRARY
&& !TARGET_LEAF_ID_SHARED_LIBRARY
)
2125 || bfin_longcall_p (callee
, INTVAL (cookie
)))))
2127 callee
= copy_to_mode_reg (Pmode
, callee
);
2128 fnaddr
= gen_rtx_MEM (Pmode
, callee
);
2130 call
= gen_rtx_CALL (VOIDmode
, fnaddr
, callarg1
);
2133 call
= gen_rtx_SET (retval
, call
);
2135 pat
= gen_rtx_PARALLEL (VOIDmode
, rtvec_alloc (nelts
));
2137 XVECEXP (pat
, 0, n
++) = call
;
2139 XVECEXP (pat
, 0, n
++) = gen_rtx_USE (VOIDmode
, picreg
);
2140 XVECEXP (pat
, 0, n
++) = gen_rtx_USE (VOIDmode
, cookie
);
2142 XVECEXP (pat
, 0, n
++) = ret_rtx
;
2144 XVECEXP (pat
, 0, n
++) = gen_rtx_CLOBBER (VOIDmode
, retsreg
);
2145 call
= emit_call_insn (pat
);
2147 CALL_INSN_FUNCTION_USAGE (call
) = use
;
2150 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
2153 hard_regno_mode_ok (int regno
, machine_mode mode
)
2155 /* Allow only dregs to store value of mode HI or QI */
2156 enum reg_class rclass
= REGNO_REG_CLASS (regno
);
2161 if (mode
== V2HImode
)
2162 return D_REGNO_P (regno
);
2163 if (rclass
== CCREGS
)
2164 return mode
== BImode
;
2165 if (mode
== PDImode
|| mode
== V2PDImode
)
2166 return regno
== REG_A0
|| regno
== REG_A1
;
2168 /* Allow all normal 32-bit regs, except REG_M3, in case regclass ever comes
2169 up with a bad register class (such as ALL_REGS) for DImode. */
2171 return regno
< REG_M3
;
2174 && TEST_HARD_REG_BIT (reg_class_contents
[PROLOGUE_REGS
], regno
))
2177 return TEST_HARD_REG_BIT (reg_class_contents
[MOST_REGS
], regno
);
2180 /* Implements target hook vector_mode_supported_p. */
2183 bfin_vector_mode_supported_p (machine_mode mode
)
2185 return mode
== V2HImode
;
2188 /* Worker function for TARGET_REGISTER_MOVE_COST. */
2191 bfin_register_move_cost (machine_mode mode
,
2192 reg_class_t class1
, reg_class_t class2
)
2194 /* These need secondary reloads, so they're more expensive. */
2195 if ((class1
== CCREGS
&& !reg_class_subset_p (class2
, DREGS
))
2196 || (class2
== CCREGS
&& !reg_class_subset_p (class1
, DREGS
)))
2199 /* If optimizing for size, always prefer reg-reg over reg-memory moves. */
2203 if (GET_MODE_CLASS (mode
) == MODE_INT
)
2205 /* Discourage trying to use the accumulators. */
2206 if (TEST_HARD_REG_BIT (reg_class_contents
[class1
], REG_A0
)
2207 || TEST_HARD_REG_BIT (reg_class_contents
[class1
], REG_A1
)
2208 || TEST_HARD_REG_BIT (reg_class_contents
[class2
], REG_A0
)
2209 || TEST_HARD_REG_BIT (reg_class_contents
[class2
], REG_A1
))
2215 /* Worker function for TARGET_MEMORY_MOVE_COST.
2217 ??? In theory L1 memory has single-cycle latency. We should add a switch
2218 that tells the compiler whether we expect to use only L1 memory for the
2219 program; it'll make the costs more accurate. */
2222 bfin_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED
,
2224 bool in ATTRIBUTE_UNUSED
)
2226 /* Make memory accesses slightly more expensive than any register-register
2227 move. Also, penalize non-DP registers, since they need secondary
2228 reloads to load and store. */
2229 if (! reg_class_subset_p (rclass
, DPREGS
))
2235 /* Inform reload about cases where moving X with a mode MODE to a register in
2236 RCLASS requires an extra scratch register. Return the class needed for the
2237 scratch register. */
2240 bfin_secondary_reload (bool in_p
, rtx x
, reg_class_t rclass_i
,
2241 machine_mode mode
, secondary_reload_info
*sri
)
2243 /* If we have HImode or QImode, we can only use DREGS as secondary registers;
2244 in most other cases we can also use PREGS. */
2245 enum reg_class default_class
= GET_MODE_SIZE (mode
) >= 4 ? DPREGS
: DREGS
;
2246 enum reg_class x_class
= NO_REGS
;
2247 enum rtx_code code
= GET_CODE (x
);
2248 enum reg_class rclass
= (enum reg_class
) rclass_i
;
2251 x
= SUBREG_REG (x
), code
= GET_CODE (x
);
2254 int regno
= REGNO (x
);
2255 if (regno
>= FIRST_PSEUDO_REGISTER
)
2256 regno
= reg_renumber
[regno
];
2261 x_class
= REGNO_REG_CLASS (regno
);
2264 /* We can be asked to reload (plus (FP) (large_constant)) into a DREG.
2265 This happens as a side effect of register elimination, and we need
2266 a scratch register to do it. */
2267 if (fp_plus_const_operand (x
, mode
))
2269 rtx op2
= XEXP (x
, 1);
2270 int large_constant_p
= ! satisfies_constraint_Ks7 (op2
);
2272 if (rclass
== PREGS
|| rclass
== PREGS_CLOBBERED
)
2274 /* If destination is a DREG, we can do this without a scratch register
2275 if the constant is valid for an add instruction. */
2276 if ((rclass
== DREGS
|| rclass
== DPREGS
)
2277 && ! large_constant_p
)
2279 /* Reloading to anything other than a DREG? Use a PREG scratch
2281 sri
->icode
= CODE_FOR_reload_insi
;
2285 /* Data can usually be moved freely between registers of most classes.
2286 AREGS are an exception; they can only move to or from another register
2287 in AREGS or one in DREGS. They can also be assigned the constant 0. */
2288 if (x_class
== AREGS
|| x_class
== EVEN_AREGS
|| x_class
== ODD_AREGS
)
2289 return (rclass
== DREGS
|| rclass
== AREGS
|| rclass
== EVEN_AREGS
2290 || rclass
== ODD_AREGS
2293 if (rclass
== AREGS
|| rclass
== EVEN_AREGS
|| rclass
== ODD_AREGS
)
2297 sri
->icode
= in_p
? CODE_FOR_reload_inpdi
: CODE_FOR_reload_outpdi
;
2301 if (x
!= const0_rtx
&& x_class
!= DREGS
)
2309 /* CCREGS can only be moved from/to DREGS. */
2310 if (rclass
== CCREGS
&& x_class
!= DREGS
)
2312 if (x_class
== CCREGS
&& rclass
!= DREGS
)
2315 /* All registers other than AREGS can load arbitrary constants. The only
2316 case that remains is MEM. */
2318 if (! reg_class_subset_p (rclass
, default_class
))
2319 return default_class
;
2324 /* Implement TARGET_CLASS_LIKELY_SPILLED_P. */
2327 bfin_class_likely_spilled_p (reg_class_t rclass
)
2331 case PREGS_CLOBBERED
:
2347 static struct machine_function
*
2348 bfin_init_machine_status (void)
2350 return ggc_cleared_alloc
<machine_function
> ();
2353 /* Implement the TARGET_OPTION_OVERRIDE hook. */
2356 bfin_option_override (void)
2358 /* If processor type is not specified, enable all workarounds. */
2359 if (bfin_cpu_type
== BFIN_CPU_UNKNOWN
)
2363 for (i
= 0; bfin_cpus
[i
].name
!= NULL
; i
++)
2364 bfin_workarounds
|= bfin_cpus
[i
].workarounds
;
2366 bfin_si_revision
= 0xffff;
2369 if (bfin_csync_anomaly
== 1)
2370 bfin_workarounds
|= WA_SPECULATIVE_SYNCS
;
2371 else if (bfin_csync_anomaly
== 0)
2372 bfin_workarounds
&= ~WA_SPECULATIVE_SYNCS
;
2374 if (bfin_specld_anomaly
== 1)
2375 bfin_workarounds
|= WA_SPECULATIVE_LOADS
;
2376 else if (bfin_specld_anomaly
== 0)
2377 bfin_workarounds
&= ~WA_SPECULATIVE_LOADS
;
2379 if (TARGET_OMIT_LEAF_FRAME_POINTER
)
2380 flag_omit_frame_pointer
= 1;
2382 #ifdef SUBTARGET_FDPIC_NOT_SUPPORTED
2384 error ("-mfdpic is not supported, please use a bfin-linux-uclibc target");
2387 /* Library identification */
2388 if (global_options_set
.x_bfin_library_id
&& ! TARGET_ID_SHARED_LIBRARY
)
2389 error ("-mshared-library-id= specified without -mid-shared-library");
2391 if (stack_limit_rtx
&& TARGET_FDPIC
)
2393 warning (0, "-fstack-limit- options are ignored with -mfdpic; use -mstack-check-l1");
2394 stack_limit_rtx
= NULL_RTX
;
2397 if (stack_limit_rtx
&& TARGET_STACK_CHECK_L1
)
2398 error ("can%'t use multiple stack checking methods together");
2400 if (TARGET_ID_SHARED_LIBRARY
&& TARGET_FDPIC
)
2401 error ("ID shared libraries and FD-PIC mode can%'t be used together");
2403 /* Don't allow the user to specify -mid-shared-library and -msep-data
2404 together, as it makes little sense from a user's point of view... */
2405 if (TARGET_SEP_DATA
&& TARGET_ID_SHARED_LIBRARY
)
2406 error ("cannot specify both -msep-data and -mid-shared-library");
2407 /* ... internally, however, it's nearly the same. */
2408 if (TARGET_SEP_DATA
)
2409 target_flags
|= MASK_ID_SHARED_LIBRARY
| MASK_LEAF_ID_SHARED_LIBRARY
;
2411 if (TARGET_ID_SHARED_LIBRARY
&& flag_pic
== 0)
2414 /* There is no single unaligned SI op for PIC code. Sometimes we
2415 need to use ".4byte" and sometimes we need to use ".picptr".
2416 See bfin_assemble_integer for details. */
2418 targetm
.asm_out
.unaligned_op
.si
= 0;
2420 /* Silently turn off flag_pic if not doing FDPIC or ID shared libraries,
2421 since we don't support it and it'll just break. */
2422 if (flag_pic
&& !TARGET_FDPIC
&& !TARGET_ID_SHARED_LIBRARY
)
2425 if (TARGET_MULTICORE
&& bfin_cpu_type
!= BFIN_CPU_BF561
)
2426 error ("-mmulticore can only be used with BF561");
2428 if (TARGET_COREA
&& !TARGET_MULTICORE
)
2429 error ("-mcorea should be used with -mmulticore");
2431 if (TARGET_COREB
&& !TARGET_MULTICORE
)
2432 error ("-mcoreb should be used with -mmulticore");
2434 if (TARGET_COREA
&& TARGET_COREB
)
2435 error ("-mcorea and -mcoreb can%'t be used together");
2437 flag_schedule_insns
= 0;
2439 init_machine_status
= bfin_init_machine_status
;
2442 /* Return the destination address of BRANCH.
2443 We need to use this instead of get_attr_length, because the
2444 cbranch_with_nops pattern conservatively sets its length to 6, and
2445 we still prefer to use shorter sequences. */
2448 branch_dest (rtx_insn
*branch
)
2452 rtx pat
= PATTERN (branch
);
2453 if (GET_CODE (pat
) == PARALLEL
)
2454 pat
= XVECEXP (pat
, 0, 0);
2455 dest
= SET_SRC (pat
);
2456 if (GET_CODE (dest
) == IF_THEN_ELSE
)
2457 dest
= XEXP (dest
, 1);
2458 dest
= XEXP (dest
, 0);
2459 dest_uid
= INSN_UID (dest
);
2460 return INSN_ADDRESSES (dest_uid
);
2463 /* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates
2464 it's a branch that's predicted taken. */
2467 cbranch_predicted_taken_p (rtx insn
)
2469 rtx x
= find_reg_note (insn
, REG_BR_PROB
, 0);
2473 int pred_val
= XINT (x
, 0);
2475 return pred_val
>= REG_BR_PROB_BASE
/ 2;
2481 /* Templates for use by asm_conditional_branch. */
2483 static const char *ccbranch_templates
[][3] = {
2484 { "if !cc jump %3;", "if cc jump 4 (bp); jump.s %3;", "if cc jump 6 (bp); jump.l %3;" },
2485 { "if cc jump %3;", "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" },
2486 { "if !cc jump %3 (bp);", "if cc jump 4; jump.s %3;", "if cc jump 6; jump.l %3;" },
2487 { "if cc jump %3 (bp);", "if !cc jump 4; jump.s %3;", "if !cc jump 6; jump.l %3;" },
2490 /* Output INSN, which is a conditional branch instruction with operands
2493 We deal with the various forms of conditional branches that can be generated
2494 by bfin_reorg to prevent the hardware from doing speculative loads, by
2495 - emitting a sufficient number of nops, if N_NOPS is nonzero, or
2496 - always emitting the branch as predicted taken, if PREDICT_TAKEN is true.
2497 Either of these is only necessary if the branch is short, otherwise the
2498 template we use ends in an unconditional jump which flushes the pipeline
2502 asm_conditional_branch (rtx_insn
*insn
, rtx
*operands
, int n_nops
, int predict_taken
)
2504 int offset
= branch_dest (insn
) - INSN_ADDRESSES (INSN_UID (insn
));
2505 /* Note : offset for instructions like if cc jmp; jump.[sl] offset
2506 is to be taken from start of if cc rather than jump.
2507 Range for jump.s is (-4094, 4096) instead of (-4096, 4094)
2509 int len
= (offset
>= -1024 && offset
<= 1022 ? 0
2510 : offset
>= -4094 && offset
<= 4096 ? 1
2512 int bp
= predict_taken
&& len
== 0 ? 1 : cbranch_predicted_taken_p (insn
);
2513 int idx
= (bp
<< 1) | (GET_CODE (operands
[0]) == EQ
? BRF
: BRT
);
2514 output_asm_insn (ccbranch_templates
[idx
][len
], operands
);
2515 gcc_assert (n_nops
== 0 || !bp
);
2517 while (n_nops
-- > 0)
2518 output_asm_insn ("nop;", NULL
);
2521 /* Emit rtl for a comparison operation CMP in mode MODE. Operands have been
2522 stored in bfin_compare_op0 and bfin_compare_op1 already. */
2525 bfin_gen_compare (rtx cmp
, machine_mode mode ATTRIBUTE_UNUSED
)
2527 enum rtx_code code1
, code2
;
2528 rtx op0
= XEXP (cmp
, 0), op1
= XEXP (cmp
, 1);
2529 rtx tem
= bfin_cc_rtx
;
2530 enum rtx_code code
= GET_CODE (cmp
);
2532 /* If we have a BImode input, then we already have a compare result, and
2533 do not need to emit another comparison. */
2534 if (GET_MODE (op0
) == BImode
)
2536 gcc_assert ((code
== NE
|| code
== EQ
) && op1
== const0_rtx
);
2537 tem
= op0
, code2
= code
;
2542 /* bfin has these conditions */
2552 code1
= reverse_condition (code
);
2556 emit_insn (gen_rtx_SET (tem
, gen_rtx_fmt_ee (code1
, BImode
, op0
, op1
)));
2559 return gen_rtx_fmt_ee (code2
, BImode
, tem
, CONST0_RTX (BImode
));
2562 /* Return nonzero iff C has exactly one bit set if it is interpreted
2563 as a 32-bit constant. */
2566 log2constp (unsigned HOST_WIDE_INT c
)
2569 return c
!= 0 && (c
& (c
-1)) == 0;
2572 /* Returns the number of consecutive least significant zeros in the binary
2573 representation of *V.
2574 We modify *V to contain the original value arithmetically shifted right by
2575 the number of zeroes. */
2578 shiftr_zero (HOST_WIDE_INT
*v
)
2580 unsigned HOST_WIDE_INT tmp
= *v
;
2581 unsigned HOST_WIDE_INT sgn
;
2587 sgn
= tmp
& ((unsigned HOST_WIDE_INT
) 1 << (HOST_BITS_PER_WIDE_INT
- 1));
2588 while ((tmp
& 0x1) == 0 && n
<= 32)
2590 tmp
= (tmp
>> 1) | sgn
;
2597 /* After reload, split the load of an immediate constant. OPERANDS are the
2598 operands of the movsi_insn pattern which we are splitting. We return
2599 nonzero if we emitted a sequence to load the constant, zero if we emitted
2600 nothing because we want to use the splitter's default sequence. */
2603 split_load_immediate (rtx operands
[])
2605 HOST_WIDE_INT val
= INTVAL (operands
[1]);
2607 HOST_WIDE_INT shifted
= val
;
2608 HOST_WIDE_INT shifted_compl
= ~val
;
2609 int num_zero
= shiftr_zero (&shifted
);
2610 int num_compl_zero
= shiftr_zero (&shifted_compl
);
2611 unsigned int regno
= REGNO (operands
[0]);
2613 /* This case takes care of single-bit set/clear constants, which we could
2614 also implement with BITSET/BITCLR. */
2616 && shifted
>= -32768 && shifted
< 65536
2617 && (D_REGNO_P (regno
)
2618 || (regno
>= REG_P0
&& regno
<= REG_P7
&& num_zero
<= 2)))
2620 emit_insn (gen_movsi (operands
[0], gen_int_mode (shifted
, SImode
)));
2621 emit_insn (gen_ashlsi3 (operands
[0], operands
[0], GEN_INT (num_zero
)));
2626 tmp
|= -(tmp
& 0x8000);
2628 /* If high word has one bit set or clear, try to use a bit operation. */
2629 if (D_REGNO_P (regno
))
2631 if (log2constp (val
& 0xFFFF0000))
2633 emit_insn (gen_movsi (operands
[0], GEN_INT (val
& 0xFFFF)));
2634 emit_insn (gen_iorsi3 (operands
[0], operands
[0],
2635 gen_int_mode (val
& 0xFFFF0000, SImode
)));
2638 else if (log2constp (val
| 0xFFFF) && (val
& 0x8000) != 0)
2640 emit_insn (gen_movsi (operands
[0], GEN_INT (tmp
)));
2641 emit_insn (gen_andsi3 (operands
[0], operands
[0],
2642 gen_int_mode (val
| 0xFFFF, SImode
)));
2646 if (D_REGNO_P (regno
))
2648 if (tmp
>= -64 && tmp
<= 63)
2650 emit_insn (gen_movsi (operands
[0], GEN_INT (tmp
)));
2651 emit_insn (gen_movstricthi_high (operands
[0],
2652 gen_int_mode (val
& -65536,
2657 if ((val
& 0xFFFF0000) == 0)
2659 emit_insn (gen_movsi (operands
[0], const0_rtx
));
2660 emit_insn (gen_movsi_low (operands
[0], operands
[0], operands
[1]));
2664 if ((val
& 0xFFFF0000) == 0xFFFF0000)
2666 emit_insn (gen_movsi (operands
[0], constm1_rtx
));
2667 emit_insn (gen_movsi_low (operands
[0], operands
[0], operands
[1]));
2672 /* Need DREGs for the remaining case. */
2677 && num_compl_zero
&& shifted_compl
>= -64 && shifted_compl
<= 63)
2679 /* If optimizing for size, generate a sequence that has more instructions
2681 emit_insn (gen_movsi (operands
[0], gen_int_mode (shifted_compl
, SImode
)));
2682 emit_insn (gen_ashlsi3 (operands
[0], operands
[0],
2683 GEN_INT (num_compl_zero
)));
2684 emit_insn (gen_one_cmplsi2 (operands
[0], operands
[0]));
2690 /* Return true if the legitimate memory address for a memory operand of mode
2691 MODE. Return false if not. */
2694 bfin_valid_add (machine_mode mode
, HOST_WIDE_INT value
)
2696 unsigned HOST_WIDE_INT v
= value
> 0 ? value
: -value
;
2697 int sz
= GET_MODE_SIZE (mode
);
2698 int shift
= sz
== 1 ? 0 : sz
== 2 ? 1 : 2;
2699 /* The usual offsettable_memref machinery doesn't work so well for this
2700 port, so we deal with the problem here. */
2701 if (value
> 0 && sz
== 8)
2703 return (v
& ~(0x7fff << shift
)) == 0;
2707 bfin_valid_reg_p (unsigned int regno
, int strict
, machine_mode mode
,
2708 enum rtx_code outer_code
)
2711 return REGNO_OK_FOR_BASE_STRICT_P (regno
, mode
, outer_code
, SCRATCH
);
2713 return REGNO_OK_FOR_BASE_NONSTRICT_P (regno
, mode
, outer_code
, SCRATCH
);
2716 /* Recognize an RTL expression that is a valid memory address for an
2717 instruction. The MODE argument is the machine mode for the MEM expression
2718 that wants to use this address.
2720 Blackfin addressing modes are as follows:
2726 W [ Preg + uimm16m2 ]
2735 bfin_legitimate_address_p (machine_mode mode
, rtx x
, bool strict
)
2737 switch (GET_CODE (x
)) {
2739 if (bfin_valid_reg_p (REGNO (x
), strict
, mode
, MEM
))
2743 if (REG_P (XEXP (x
, 0))
2744 && bfin_valid_reg_p (REGNO (XEXP (x
, 0)), strict
, mode
, PLUS
)
2745 && ((GET_CODE (XEXP (x
, 1)) == UNSPEC
&& mode
== SImode
)
2746 || (GET_CODE (XEXP (x
, 1)) == CONST_INT
2747 && bfin_valid_add (mode
, INTVAL (XEXP (x
, 1))))))
2752 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode
)
2753 && REG_P (XEXP (x
, 0))
2754 && bfin_valid_reg_p (REGNO (XEXP (x
, 0)), strict
, mode
, POST_INC
))
2757 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode
)
2758 && XEXP (x
, 0) == stack_pointer_rtx
2759 && REG_P (XEXP (x
, 0))
2760 && bfin_valid_reg_p (REGNO (XEXP (x
, 0)), strict
, mode
, PRE_DEC
))
2769 /* Decide whether we can force certain constants to memory. If we
2770 decide we can't, the caller should be able to cope with it in
2774 bfin_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED
,
2775 rtx x ATTRIBUTE_UNUSED
)
2777 /* We have only one class of non-legitimate constants, and our movsi
2778 expander knows how to handle them. Dropping these constants into the
2779 data section would only shift the problem - we'd still get relocs
2780 outside the object, in the data section rather than the text section. */
2784 /* Ensure that for any constant of the form symbol + offset, the offset
2785 remains within the object. Any other constants are ok.
2786 This ensures that flat binaries never have to deal with relocations
2787 crossing section boundaries. */
2790 bfin_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED
, rtx x
)
2793 HOST_WIDE_INT offset
;
2795 if (GET_CODE (x
) != CONST
)
2799 gcc_assert (GET_CODE (x
) == PLUS
);
2803 if (GET_CODE (sym
) != SYMBOL_REF
2804 || GET_CODE (x
) != CONST_INT
)
2806 offset
= INTVAL (x
);
2808 if (SYMBOL_REF_DECL (sym
) == 0)
2811 || offset
>= int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (sym
))))
2818 bfin_rtx_costs (rtx x
, int code_i
, int outer_code_i
, int opno
, int *total
,
2821 enum rtx_code code
= (enum rtx_code
) code_i
;
2822 enum rtx_code outer_code
= (enum rtx_code
) outer_code_i
;
2823 int cost2
= COSTS_N_INSNS (1);
2829 if (outer_code
== SET
|| outer_code
== PLUS
)
2830 *total
= satisfies_constraint_Ks7 (x
) ? 0 : cost2
;
2831 else if (outer_code
== AND
)
2832 *total
= log2constp (~INTVAL (x
)) ? 0 : cost2
;
2833 else if (outer_code
== LE
|| outer_code
== LT
|| outer_code
== EQ
)
2834 *total
= (INTVAL (x
) >= -4 && INTVAL (x
) <= 3) ? 0 : cost2
;
2835 else if (outer_code
== LEU
|| outer_code
== LTU
)
2836 *total
= (INTVAL (x
) >= 0 && INTVAL (x
) <= 7) ? 0 : cost2
;
2837 else if (outer_code
== MULT
)
2838 *total
= (INTVAL (x
) == 2 || INTVAL (x
) == 4) ? 0 : cost2
;
2839 else if (outer_code
== ASHIFT
&& (INTVAL (x
) == 1 || INTVAL (x
) == 2))
2841 else if (outer_code
== ASHIFT
|| outer_code
== ASHIFTRT
2842 || outer_code
== LSHIFTRT
)
2843 *total
= (INTVAL (x
) >= 0 && INTVAL (x
) <= 31) ? 0 : cost2
;
2844 else if (outer_code
== IOR
|| outer_code
== XOR
)
2845 *total
= (INTVAL (x
) & (INTVAL (x
) - 1)) == 0 ? 0 : cost2
;
2854 *total
= COSTS_N_INSNS (2);
2860 if (GET_MODE (x
) == SImode
)
2862 if (GET_CODE (op0
) == MULT
2863 && GET_CODE (XEXP (op0
, 1)) == CONST_INT
)
2865 HOST_WIDE_INT val
= INTVAL (XEXP (op0
, 1));
2866 if (val
== 2 || val
== 4)
2869 *total
+= rtx_cost (XEXP (op0
, 0), outer_code
, opno
, speed
);
2870 *total
+= rtx_cost (op1
, outer_code
, opno
, speed
);
2875 if (GET_CODE (op0
) != REG
2876 && (GET_CODE (op0
) != SUBREG
|| GET_CODE (SUBREG_REG (op0
)) != REG
))
2877 *total
+= set_src_cost (op0
, speed
);
2878 #if 0 /* We'd like to do this for accuracy, but it biases the loop optimizer
2879 towards creating too many induction variables. */
2880 if (!reg_or_7bit_operand (op1
, SImode
))
2881 *total
+= set_src_cost (op1
, speed
);
2884 else if (GET_MODE (x
) == DImode
)
2887 if (GET_CODE (op1
) != CONST_INT
2888 || !satisfies_constraint_Ks7 (op1
))
2889 *total
+= rtx_cost (op1
, PLUS
, 1, speed
);
2890 if (GET_CODE (op0
) != REG
2891 && (GET_CODE (op0
) != SUBREG
|| GET_CODE (SUBREG_REG (op0
)) != REG
))
2892 *total
+= rtx_cost (op0
, PLUS
, 0, speed
);
2897 if (GET_MODE (x
) == DImode
)
2906 if (GET_MODE (x
) == DImode
)
2913 if (GET_CODE (op0
) != REG
2914 && (GET_CODE (op0
) != SUBREG
|| GET_CODE (SUBREG_REG (op0
)) != REG
))
2915 *total
+= rtx_cost (op0
, code
, 0, speed
);
2925 /* Handle special cases of IOR: rotates, ALIGN insns, movstricthi_high. */
2928 if ((GET_CODE (op0
) == LSHIFTRT
&& GET_CODE (op1
) == ASHIFT
)
2929 || (GET_CODE (op0
) == ASHIFT
&& GET_CODE (op1
) == ZERO_EXTEND
)
2930 || (GET_CODE (op0
) == ASHIFT
&& GET_CODE (op1
) == LSHIFTRT
)
2931 || (GET_CODE (op0
) == AND
&& GET_CODE (op1
) == CONST_INT
))
2938 if (GET_CODE (op0
) != REG
2939 && (GET_CODE (op0
) != SUBREG
|| GET_CODE (SUBREG_REG (op0
)) != REG
))
2940 *total
+= rtx_cost (op0
, code
, 0, speed
);
2942 if (GET_MODE (x
) == DImode
)
2948 if (GET_MODE (x
) != SImode
)
2953 if (! rhs_andsi3_operand (XEXP (x
, 1), SImode
))
2954 *total
+= rtx_cost (XEXP (x
, 1), code
, 1, speed
);
2958 if (! regorlog2_operand (XEXP (x
, 1), SImode
))
2959 *total
+= rtx_cost (XEXP (x
, 1), code
, 1, speed
);
2966 if (outer_code
== SET
2967 && XEXP (x
, 1) == const1_rtx
2968 && GET_CODE (XEXP (x
, 2)) == CONST_INT
)
2984 if (GET_CODE (op0
) == GET_CODE (op1
)
2985 && (GET_CODE (op0
) == ZERO_EXTEND
2986 || GET_CODE (op0
) == SIGN_EXTEND
))
2988 *total
= COSTS_N_INSNS (1);
2989 op0
= XEXP (op0
, 0);
2990 op1
= XEXP (op1
, 0);
2993 *total
= COSTS_N_INSNS (1);
2995 *total
= COSTS_N_INSNS (3);
2997 if (GET_CODE (op0
) != REG
2998 && (GET_CODE (op0
) != SUBREG
|| GET_CODE (SUBREG_REG (op0
)) != REG
))
2999 *total
+= rtx_cost (op0
, MULT
, 0, speed
);
3000 if (GET_CODE (op1
) != REG
3001 && (GET_CODE (op1
) != SUBREG
|| GET_CODE (SUBREG_REG (op1
)) != REG
))
3002 *total
+= rtx_cost (op1
, MULT
, 1, speed
);
3008 *total
= COSTS_N_INSNS (32);
3013 if (outer_code
== SET
)
3022 /* Used for communication between {push,pop}_multiple_operation (which
3023 we use not only as a predicate) and the corresponding output functions. */
3024 static int first_preg_to_save
, first_dreg_to_save
;
3025 static int n_regs_to_save
;
3028 analyze_push_multiple_operation (rtx op
)
3030 int lastdreg
= 8, lastpreg
= 6;
3033 first_preg_to_save
= lastpreg
;
3034 first_dreg_to_save
= lastdreg
;
3035 for (i
= 1, group
= 0; i
< XVECLEN (op
, 0) - 1; i
++)
3037 rtx t
= XVECEXP (op
, 0, i
);
3041 if (GET_CODE (t
) != SET
)
3045 dest
= SET_DEST (t
);
3046 if (GET_CODE (dest
) != MEM
|| ! REG_P (src
))
3048 dest
= XEXP (dest
, 0);
3049 if (GET_CODE (dest
) != PLUS
3050 || ! REG_P (XEXP (dest
, 0))
3051 || REGNO (XEXP (dest
, 0)) != REG_SP
3052 || GET_CODE (XEXP (dest
, 1)) != CONST_INT
3053 || INTVAL (XEXP (dest
, 1)) != -i
* 4)
3056 regno
= REGNO (src
);
3059 if (D_REGNO_P (regno
))
3062 first_dreg_to_save
= lastdreg
= regno
- REG_R0
;
3064 else if (regno
>= REG_P0
&& regno
<= REG_P7
)
3067 first_preg_to_save
= lastpreg
= regno
- REG_P0
;
3077 if (regno
>= REG_P0
&& regno
<= REG_P7
)
3080 first_preg_to_save
= lastpreg
= regno
- REG_P0
;
3082 else if (regno
!= REG_R0
+ lastdreg
+ 1)
3087 else if (group
== 2)
3089 if (regno
!= REG_P0
+ lastpreg
+ 1)
3094 n_regs_to_save
= 8 - first_dreg_to_save
+ 6 - first_preg_to_save
;
3099 analyze_pop_multiple_operation (rtx op
)
3101 int lastdreg
= 8, lastpreg
= 6;
3104 for (i
= 1, group
= 0; i
< XVECLEN (op
, 0); i
++)
3106 rtx t
= XVECEXP (op
, 0, i
);
3110 if (GET_CODE (t
) != SET
)
3114 dest
= SET_DEST (t
);
3115 if (GET_CODE (src
) != MEM
|| ! REG_P (dest
))
3117 src
= XEXP (src
, 0);
3121 if (! REG_P (src
) || REGNO (src
) != REG_SP
)
3124 else if (GET_CODE (src
) != PLUS
3125 || ! REG_P (XEXP (src
, 0))
3126 || REGNO (XEXP (src
, 0)) != REG_SP
3127 || GET_CODE (XEXP (src
, 1)) != CONST_INT
3128 || INTVAL (XEXP (src
, 1)) != (i
- 1) * 4)
3131 regno
= REGNO (dest
);
3134 if (regno
== REG_R7
)
3139 else if (regno
!= REG_P0
+ lastpreg
- 1)
3144 else if (group
== 1)
3146 if (regno
!= REG_R0
+ lastdreg
- 1)
3152 first_dreg_to_save
= lastdreg
;
3153 first_preg_to_save
= lastpreg
;
3154 n_regs_to_save
= 8 - first_dreg_to_save
+ 6 - first_preg_to_save
;
3158 /* Emit assembly code for one multi-register push described by INSN, with
3159 operands in OPERANDS. */
3162 output_push_multiple (rtx insn
, rtx
*operands
)
3167 /* Validate the insn again, and compute first_[dp]reg_to_save. */
3168 ok
= analyze_push_multiple_operation (PATTERN (insn
));
3171 if (first_dreg_to_save
== 8)
3172 sprintf (buf
, "[--sp] = ( p5:%d );\n", first_preg_to_save
);
3173 else if (first_preg_to_save
== 6)
3174 sprintf (buf
, "[--sp] = ( r7:%d );\n", first_dreg_to_save
);
3176 sprintf (buf
, "[--sp] = ( r7:%d, p5:%d );\n",
3177 first_dreg_to_save
, first_preg_to_save
);
3179 output_asm_insn (buf
, operands
);
3182 /* Emit assembly code for one multi-register pop described by INSN, with
3183 operands in OPERANDS. */
3186 output_pop_multiple (rtx insn
, rtx
*operands
)
3191 /* Validate the insn again, and compute first_[dp]reg_to_save. */
3192 ok
= analyze_pop_multiple_operation (PATTERN (insn
));
3195 if (first_dreg_to_save
== 8)
3196 sprintf (buf
, "( p5:%d ) = [sp++];\n", first_preg_to_save
);
3197 else if (first_preg_to_save
== 6)
3198 sprintf (buf
, "( r7:%d ) = [sp++];\n", first_dreg_to_save
);
3200 sprintf (buf
, "( r7:%d, p5:%d ) = [sp++];\n",
3201 first_dreg_to_save
, first_preg_to_save
);
3203 output_asm_insn (buf
, operands
);
3206 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE. */
3209 single_move_for_movmem (rtx dst
, rtx src
, machine_mode mode
, HOST_WIDE_INT offset
)
3211 rtx scratch
= gen_reg_rtx (mode
);
3214 srcmem
= adjust_address_nv (src
, mode
, offset
);
3215 dstmem
= adjust_address_nv (dst
, mode
, offset
);
3216 emit_move_insn (scratch
, srcmem
);
3217 emit_move_insn (dstmem
, scratch
);
3220 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
3221 alignment ALIGN_EXP. Return true if successful, false if we should fall
3222 back on a different method. */
3225 bfin_expand_movmem (rtx dst
, rtx src
, rtx count_exp
, rtx align_exp
)
3227 rtx srcreg
, destreg
, countreg
;
3228 HOST_WIDE_INT align
= 0;
3229 unsigned HOST_WIDE_INT count
= 0;
3231 if (GET_CODE (align_exp
) == CONST_INT
)
3232 align
= INTVAL (align_exp
);
3233 if (GET_CODE (count_exp
) == CONST_INT
)
3235 count
= INTVAL (count_exp
);
3237 if (!TARGET_INLINE_ALL_STRINGOPS
&& count
> 64)
3242 /* If optimizing for size, only do single copies inline. */
3245 if (count
== 2 && align
< 2)
3247 if (count
== 4 && align
< 4)
3249 if (count
!= 1 && count
!= 2 && count
!= 4)
3252 if (align
< 2 && count
!= 1)
3255 destreg
= copy_to_mode_reg (Pmode
, XEXP (dst
, 0));
3256 if (destreg
!= XEXP (dst
, 0))
3257 dst
= replace_equiv_address_nv (dst
, destreg
);
3258 srcreg
= copy_to_mode_reg (Pmode
, XEXP (src
, 0));
3259 if (srcreg
!= XEXP (src
, 0))
3260 src
= replace_equiv_address_nv (src
, srcreg
);
3262 if (count
!= 0 && align
>= 2)
3264 unsigned HOST_WIDE_INT offset
= 0;
3268 if ((count
& ~3) == 4)
3270 single_move_for_movmem (dst
, src
, SImode
, offset
);
3273 else if (count
& ~3)
3275 HOST_WIDE_INT new_count
= ((count
>> 2) & 0x3fffffff) - 1;
3276 countreg
= copy_to_mode_reg (Pmode
, GEN_INT (new_count
));
3278 emit_insn (gen_rep_movsi (destreg
, srcreg
, countreg
, destreg
, srcreg
));
3279 cfun
->machine
->has_loopreg_clobber
= true;
3283 single_move_for_movmem (dst
, src
, HImode
, offset
);
3289 if ((count
& ~1) == 2)
3291 single_move_for_movmem (dst
, src
, HImode
, offset
);
3294 else if (count
& ~1)
3296 HOST_WIDE_INT new_count
= ((count
>> 1) & 0x7fffffff) - 1;
3297 countreg
= copy_to_mode_reg (Pmode
, GEN_INT (new_count
));
3299 emit_insn (gen_rep_movhi (destreg
, srcreg
, countreg
, destreg
, srcreg
));
3300 cfun
->machine
->has_loopreg_clobber
= true;
3305 single_move_for_movmem (dst
, src
, QImode
, offset
);
3312 /* Compute the alignment for a local variable.
3313 TYPE is the data type, and ALIGN is the alignment that
3314 the object would ordinarily have. The value of this macro is used
3315 instead of that alignment to align the object. */
3318 bfin_local_alignment (tree type
, unsigned align
)
3320 /* Increasing alignment for (relatively) big types allows the builtin
3321 memcpy can use 32 bit loads/stores. */
3322 if (TYPE_SIZE (type
)
3323 && TREE_CODE (TYPE_SIZE (type
)) == INTEGER_CST
3324 && wi::gtu_p (TYPE_SIZE (type
), 8)
3330 /* Implement TARGET_SCHED_ISSUE_RATE. */
3333 bfin_issue_rate (void)
3339 bfin_adjust_cost (rtx_insn
*insn
, rtx link
, rtx_insn
*dep_insn
, int cost
)
3341 enum attr_type dep_insn_type
;
3342 int dep_insn_code_number
;
3344 /* Anti and output dependencies have zero cost. */
3345 if (REG_NOTE_KIND (link
) != 0)
3348 dep_insn_code_number
= recog_memoized (dep_insn
);
3350 /* If we can't recognize the insns, we can't really do anything. */
3351 if (dep_insn_code_number
< 0 || recog_memoized (insn
) < 0)
3354 dep_insn_type
= get_attr_type (dep_insn
);
3356 if (dep_insn_type
== TYPE_MOVE
|| dep_insn_type
== TYPE_MCLD
)
3358 rtx pat
= PATTERN (dep_insn
);
3361 if (GET_CODE (pat
) == PARALLEL
)
3362 pat
= XVECEXP (pat
, 0, 0);
3363 dest
= SET_DEST (pat
);
3364 src
= SET_SRC (pat
);
3365 if (! ADDRESS_REGNO_P (REGNO (dest
))
3366 || ! (MEM_P (src
) || D_REGNO_P (REGNO (src
))))
3368 return cost
+ (dep_insn_type
== TYPE_MOVE
? 4 : 3);
3374 /* This function acts like NEXT_INSN, but is aware of three-insn bundles and
3375 skips all subsequent parallel instructions if INSN is the start of such
3378 find_next_insn_start (rtx_insn
*insn
)
3380 if (GET_MODE (insn
) == SImode
)
3382 while (GET_MODE (insn
) != QImode
)
3383 insn
= NEXT_INSN (insn
);
3385 return NEXT_INSN (insn
);
3388 /* This function acts like PREV_INSN, but is aware of three-insn bundles and
3389 skips all subsequent parallel instructions if INSN is the start of such
3392 find_prev_insn_start (rtx_insn
*insn
)
3394 insn
= PREV_INSN (insn
);
3395 gcc_assert (GET_MODE (insn
) != SImode
);
3396 if (GET_MODE (insn
) == QImode
)
3398 while (GET_MODE (PREV_INSN (insn
)) == SImode
)
3399 insn
= PREV_INSN (insn
);
3404 /* Implement TARGET_CAN_USE_DOLOOP_P. */
3407 bfin_can_use_doloop_p (const widest_int
&, const widest_int
&iterations_max
,
3410 /* Due to limitations in the hardware (an initial loop count of 0
3411 does not loop 2^32 times) we must avoid to generate a hardware
3412 loops when we cannot rule out this case. */
3413 if (!flag_unsafe_loop_optimizations
3414 && wi::geu_p (iterations_max
, 0xFFFFFFFF))
3419 /* Increment the counter for the number of loop instructions in the
3420 current function. */
3423 bfin_hardware_loop (void)
3425 cfun
->machine
->has_hardware_loops
++;
3428 /* Maximum loop nesting depth. */
3429 #define MAX_LOOP_DEPTH 2
3431 /* Maximum size of a loop. */
3432 #define MAX_LOOP_LENGTH 2042
3434 /* Maximum distance of the LSETUP instruction from the loop start. */
3435 #define MAX_LSETUP_DISTANCE 30
3437 /* Estimate the length of INSN conservatively. */
3440 length_for_loop (rtx_insn
*insn
)
3443 if (JUMP_P (insn
) && any_condjump_p (insn
) && !optimize_size
)
3445 if (ENABLE_WA_SPECULATIVE_SYNCS
)
3447 else if (ENABLE_WA_SPECULATIVE_LOADS
)
3450 else if (LABEL_P (insn
))
3452 if (ENABLE_WA_SPECULATIVE_SYNCS
)
3456 if (NONDEBUG_INSN_P (insn
))
3457 length
+= get_attr_length (insn
);
3462 /* Optimize LOOP. */
3465 hwloop_optimize (hwloop_info loop
)
3468 rtx_insn
*insn
, *last_insn
;
3469 rtx loop_init
, start_label
, end_label
;
3470 rtx iter_reg
, scratchreg
, scratch_init
, scratch_init_insn
;
3471 rtx lc_reg
, lt_reg
, lb_reg
;
3475 bool clobber0
, clobber1
;
3477 if (loop
->depth
> MAX_LOOP_DEPTH
)
3480 fprintf (dump_file
, ";; loop %d too deep\n", loop
->loop_no
);
3484 /* Get the loop iteration register. */
3485 iter_reg
= loop
->iter_reg
;
3487 gcc_assert (REG_P (iter_reg
));
3489 scratchreg
= NULL_RTX
;
3490 scratch_init
= iter_reg
;
3491 scratch_init_insn
= NULL_RTX
;
3492 if (!PREG_P (iter_reg
) && loop
->incoming_src
)
3494 basic_block bb_in
= loop
->incoming_src
;
3496 for (i
= REG_P0
; i
<= REG_P5
; i
++)
3497 if ((df_regs_ever_live_p (i
)
3498 || (funkind (TREE_TYPE (current_function_decl
)) == SUBROUTINE
3499 && call_used_regs
[i
]))
3500 && !REGNO_REG_SET_P (df_get_live_out (bb_in
), i
))
3502 scratchreg
= gen_rtx_REG (SImode
, i
);
3505 for (insn
= BB_END (bb_in
); insn
!= BB_HEAD (bb_in
);
3506 insn
= PREV_INSN (insn
))
3509 if (NOTE_P (insn
) || BARRIER_P (insn
))
3511 set
= single_set (insn
);
3512 if (set
&& rtx_equal_p (SET_DEST (set
), iter_reg
))
3514 if (CONSTANT_P (SET_SRC (set
)))
3516 scratch_init
= SET_SRC (set
);
3517 scratch_init_insn
= insn
;
3521 else if (reg_mentioned_p (iter_reg
, PATTERN (insn
)))
3526 if (loop
->incoming_src
)
3528 /* Make sure the predecessor is before the loop start label, as required by
3529 the LSETUP instruction. */
3531 insn
= BB_END (loop
->incoming_src
);
3532 /* If we have to insert the LSETUP before a jump, count that jump in the
3534 if (vec_safe_length (loop
->incoming
) > 1
3535 || !(loop
->incoming
->last ()->flags
& EDGE_FALLTHRU
))
3537 gcc_assert (JUMP_P (insn
));
3538 insn
= PREV_INSN (insn
);
3541 for (; insn
&& insn
!= loop
->start_label
; insn
= NEXT_INSN (insn
))
3542 length
+= length_for_loop (insn
);
3547 fprintf (dump_file
, ";; loop %d lsetup not before loop_start\n",
3552 /* Account for the pop of a scratch register where necessary. */
3553 if (!PREG_P (iter_reg
) && scratchreg
== NULL_RTX
3554 && ENABLE_WA_LOAD_LCREGS
)
3557 if (length
> MAX_LSETUP_DISTANCE
)
3560 fprintf (dump_file
, ";; loop %d lsetup too far away\n", loop
->loop_no
);
3565 /* Check if start_label appears before loop_end and calculate the
3566 offset between them. We calculate the length of instructions
3569 for (insn
= loop
->start_label
;
3570 insn
&& insn
!= loop
->loop_end
;
3571 insn
= NEXT_INSN (insn
))
3572 length
+= length_for_loop (insn
);
3577 fprintf (dump_file
, ";; loop %d start_label not before loop_end\n",
3582 loop
->length
= length
;
3583 if (loop
->length
> MAX_LOOP_LENGTH
)
3586 fprintf (dump_file
, ";; loop %d too long\n", loop
->loop_no
);
3590 /* Scan all the blocks to make sure they don't use iter_reg. */
3591 if (loop
->iter_reg_used
|| loop
->iter_reg_used_outside
)
3594 fprintf (dump_file
, ";; loop %d uses iterator\n", loop
->loop_no
);
3598 clobber0
= (TEST_HARD_REG_BIT (loop
->regs_set_in_loop
, REG_LC0
)
3599 || TEST_HARD_REG_BIT (loop
->regs_set_in_loop
, REG_LB0
)
3600 || TEST_HARD_REG_BIT (loop
->regs_set_in_loop
, REG_LT0
));
3601 clobber1
= (TEST_HARD_REG_BIT (loop
->regs_set_in_loop
, REG_LC1
)
3602 || TEST_HARD_REG_BIT (loop
->regs_set_in_loop
, REG_LB1
)
3603 || TEST_HARD_REG_BIT (loop
->regs_set_in_loop
, REG_LT1
));
3604 if (clobber0
&& clobber1
)
3607 fprintf (dump_file
, ";; loop %d no loop reg available\n",
3612 /* There should be an instruction before the loop_end instruction
3613 in the same basic block. And the instruction must not be
3615 - CONDITIONAL BRANCH
3619 - Returns (RTS, RTN, etc.) */
3622 last_insn
= find_prev_insn_start (loop
->loop_end
);
3626 for (; last_insn
!= BB_HEAD (bb
);
3627 last_insn
= find_prev_insn_start (last_insn
))
3628 if (NONDEBUG_INSN_P (last_insn
))
3631 if (last_insn
!= BB_HEAD (bb
))
3634 if (single_pred_p (bb
)
3635 && single_pred_edge (bb
)->flags
& EDGE_FALLTHRU
3636 && single_pred (bb
) != ENTRY_BLOCK_PTR_FOR_FN (cfun
))
3638 bb
= single_pred (bb
);
3639 last_insn
= BB_END (bb
);
3652 fprintf (dump_file
, ";; loop %d has no last instruction\n",
3657 if (JUMP_P (last_insn
) && !any_condjump_p (last_insn
))
3660 fprintf (dump_file
, ";; loop %d has bad last instruction\n",
3664 /* In all other cases, try to replace a bad last insn with a nop. */
3665 else if (JUMP_P (last_insn
)
3666 || CALL_P (last_insn
)
3667 || get_attr_type (last_insn
) == TYPE_SYNC
3668 || get_attr_type (last_insn
) == TYPE_CALL
3669 || get_attr_seq_insns (last_insn
) == SEQ_INSNS_MULTI
3670 || recog_memoized (last_insn
) == CODE_FOR_return_internal
3671 || GET_CODE (PATTERN (last_insn
)) == ASM_INPUT
3672 || asm_noperands (PATTERN (last_insn
)) >= 0)
3674 if (loop
->length
+ 2 > MAX_LOOP_LENGTH
)
3677 fprintf (dump_file
, ";; loop %d too long\n", loop
->loop_no
);
3681 fprintf (dump_file
, ";; loop %d has bad last insn; replace with nop\n",
3684 last_insn
= emit_insn_after (gen_forced_nop (), last_insn
);
3687 loop
->last_insn
= last_insn
;
3689 /* The loop is good for replacement. */
3690 start_label
= loop
->start_label
;
3691 end_label
= gen_label_rtx ();
3692 iter_reg
= loop
->iter_reg
;
3694 if (loop
->depth
== 1 && !clobber1
)
3696 lc_reg
= gen_rtx_REG (SImode
, REG_LC1
);
3697 lb_reg
= gen_rtx_REG (SImode
, REG_LB1
);
3698 lt_reg
= gen_rtx_REG (SImode
, REG_LT1
);
3699 SET_HARD_REG_BIT (loop
->regs_set_in_loop
, REG_LC1
);
3703 lc_reg
= gen_rtx_REG (SImode
, REG_LC0
);
3704 lb_reg
= gen_rtx_REG (SImode
, REG_LB0
);
3705 lt_reg
= gen_rtx_REG (SImode
, REG_LT0
);
3706 SET_HARD_REG_BIT (loop
->regs_set_in_loop
, REG_LC0
);
3709 loop
->end_label
= end_label
;
3711 /* Create a sequence containing the loop setup. */
3714 /* LSETUP only accepts P registers. If we have one, we can use it,
3715 otherwise there are several ways of working around the problem.
3716 If we're not affected by anomaly 312, we can load the LC register
3717 from any iteration register, and use LSETUP without initialization.
3718 If we've found a P scratch register that's not live here, we can
3719 instead copy the iter_reg into that and use an initializing LSETUP.
3720 If all else fails, push and pop P0 and use it as a scratch. */
3721 if (P_REGNO_P (REGNO (iter_reg
)))
3723 loop_init
= gen_lsetup_with_autoinit (lt_reg
, start_label
,
3726 seq_end
= emit_insn (loop_init
);
3728 else if (!ENABLE_WA_LOAD_LCREGS
&& DPREG_P (iter_reg
))
3730 emit_insn (gen_movsi (lc_reg
, iter_reg
));
3731 loop_init
= gen_lsetup_without_autoinit (lt_reg
, start_label
,
3734 seq_end
= emit_insn (loop_init
);
3736 else if (scratchreg
!= NULL_RTX
)
3738 emit_insn (gen_movsi (scratchreg
, scratch_init
));
3739 loop_init
= gen_lsetup_with_autoinit (lt_reg
, start_label
,
3741 lc_reg
, scratchreg
);
3742 seq_end
= emit_insn (loop_init
);
3743 if (scratch_init_insn
!= NULL_RTX
)
3744 delete_insn (scratch_init_insn
);
3748 rtx p0reg
= gen_rtx_REG (SImode
, REG_P0
);
3749 rtx push
= gen_frame_mem (SImode
,
3750 gen_rtx_PRE_DEC (SImode
, stack_pointer_rtx
));
3751 rtx pop
= gen_frame_mem (SImode
,
3752 gen_rtx_POST_INC (SImode
, stack_pointer_rtx
));
3753 emit_insn (gen_movsi (push
, p0reg
));
3754 emit_insn (gen_movsi (p0reg
, scratch_init
));
3755 loop_init
= gen_lsetup_with_autoinit (lt_reg
, start_label
,
3758 emit_insn (loop_init
);
3759 seq_end
= emit_insn (gen_movsi (p0reg
, pop
));
3760 if (scratch_init_insn
!= NULL_RTX
)
3761 delete_insn (scratch_init_insn
);
3766 fprintf (dump_file
, ";; replacing loop %d initializer with\n",
3768 print_rtl_single (dump_file
, loop_init
);
3769 fprintf (dump_file
, ";; replacing loop %d terminator with\n",
3771 print_rtl_single (dump_file
, loop
->loop_end
);
3774 /* If the loop isn't entered at the top, also create a jump to the entry
3776 if (!loop
->incoming_src
&& loop
->head
!= loop
->incoming_dest
)
3778 rtx label
= BB_HEAD (loop
->incoming_dest
);
3779 /* If we're jumping to the final basic block in the loop, and there's
3780 only one cheap instruction before the end (typically an increment of
3781 an induction variable), we can just emit a copy here instead of a
3783 if (loop
->incoming_dest
== loop
->tail
3784 && next_real_insn (label
) == last_insn
3785 && asm_noperands (last_insn
) < 0
3786 && GET_CODE (PATTERN (last_insn
)) == SET
)
3788 seq_end
= emit_insn (copy_rtx (PATTERN (last_insn
)));
3792 emit_jump_insn (gen_jump (label
));
3793 seq_end
= emit_barrier ();
3800 if (loop
->incoming_src
)
3802 rtx_insn
*prev
= BB_END (loop
->incoming_src
);
3803 if (vec_safe_length (loop
->incoming
) > 1
3804 || !(loop
->incoming
->last ()->flags
& EDGE_FALLTHRU
))
3806 gcc_assert (JUMP_P (prev
));
3807 prev
= PREV_INSN (prev
);
3809 emit_insn_after (seq
, prev
);
3817 #ifdef ENABLE_CHECKING
3818 if (loop
->head
!= loop
->incoming_dest
)
3820 /* We aren't entering the loop at the top. Since we've established
3821 that the loop is entered only at one point, this means there
3822 can't be fallthru edges into the head. Any such fallthru edges
3823 would become invalid when we insert the new block, so verify
3824 that this does not in fact happen. */
3825 FOR_EACH_EDGE (e
, ei
, loop
->head
->preds
)
3826 gcc_assert (!(e
->flags
& EDGE_FALLTHRU
));
3830 emit_insn_before (seq
, BB_HEAD (loop
->head
));
3831 seq
= emit_label_before (gen_label_rtx (), seq
);
3833 new_bb
= create_basic_block (seq
, seq_end
, loop
->head
->prev_bb
);
3834 FOR_EACH_EDGE (e
, ei
, loop
->incoming
)
3836 if (!(e
->flags
& EDGE_FALLTHRU
)
3837 || e
->dest
!= loop
->head
)
3838 redirect_edge_and_branch_force (e
, new_bb
);
3840 redirect_edge_succ (e
, new_bb
);
3842 e
= make_edge (new_bb
, loop
->head
, 0);
3845 delete_insn (loop
->loop_end
);
3846 /* Insert the loop end label before the last instruction of the loop. */
3847 emit_label_before (loop
->end_label
, loop
->last_insn
);
3852 /* A callback for the hw-doloop pass. Called when a loop we have discovered
3853 turns out not to be optimizable; we have to split the doloop_end pattern
3854 into a subtract and a test. */
3856 hwloop_fail (hwloop_info loop
)
3858 rtx insn
= loop
->loop_end
;
3860 if (DPREG_P (loop
->iter_reg
))
3862 /* If loop->iter_reg is a DREG or PREG, we can split it here
3863 without scratch register. */
3866 emit_insn_before (gen_addsi3 (loop
->iter_reg
,
3871 test
= gen_rtx_NE (VOIDmode
, loop
->iter_reg
, const0_rtx
);
3872 insn
= emit_jump_insn_before (gen_cbranchsi4 (test
,
3873 loop
->iter_reg
, const0_rtx
,
3877 JUMP_LABEL (insn
) = loop
->start_label
;
3878 LABEL_NUSES (loop
->start_label
)++;
3879 delete_insn (loop
->loop_end
);
3883 splitting_loops
= 1;
3884 try_split (PATTERN (insn
), insn
, 1);
3885 splitting_loops
= 0;
3889 /* A callback for the hw-doloop pass. This function examines INSN; if
3890 it is a loop_end pattern we recognize, return the reg rtx for the
3891 loop counter. Otherwise, return NULL_RTX. */
3894 hwloop_pattern_reg (rtx_insn
*insn
)
3898 if (!JUMP_P (insn
) || recog_memoized (insn
) != CODE_FOR_loop_end
)
3901 reg
= SET_DEST (XVECEXP (PATTERN (insn
), 0, 1));
3907 static struct hw_doloop_hooks bfin_doloop_hooks
=
3914 /* Run from machine_dependent_reorg, this pass looks for doloop_end insns
3915 and tries to rewrite the RTL of these loops so that proper Blackfin
3916 hardware loops are generated. */
3919 bfin_reorg_loops (void)
3921 reorg_loops (true, &bfin_doloop_hooks
);
3924 /* Possibly generate a SEQUENCE out of three insns found in SLOT.
3925 Returns true if we modified the insn chain, false otherwise. */
3927 gen_one_bundle (rtx_insn
*slot
[3])
3929 gcc_assert (slot
[1] != NULL_RTX
);
3931 /* Don't add extra NOPs if optimizing for size. */
3933 && (slot
[0] == NULL_RTX
|| slot
[2] == NULL_RTX
))
3936 /* Verify that we really can do the multi-issue. */
3939 rtx_insn
*t
= NEXT_INSN (slot
[0]);
3940 while (t
!= slot
[1])
3942 if (! NOTE_P (t
) || NOTE_KIND (t
) != NOTE_INSN_DELETED
)
3949 rtx_insn
*t
= NEXT_INSN (slot
[1]);
3950 while (t
!= slot
[2])
3952 if (! NOTE_P (t
) || NOTE_KIND (t
) != NOTE_INSN_DELETED
)
3958 if (slot
[0] == NULL_RTX
)
3960 slot
[0] = emit_insn_before (gen_mnop (), slot
[1]);
3961 df_insn_rescan (slot
[0]);
3963 if (slot
[2] == NULL_RTX
)
3965 slot
[2] = emit_insn_after (gen_forced_nop (), slot
[1]);
3966 df_insn_rescan (slot
[2]);
3969 /* Avoid line number information being printed inside one bundle. */
3970 if (INSN_LOCATION (slot
[1])
3971 && INSN_LOCATION (slot
[1]) != INSN_LOCATION (slot
[0]))
3972 INSN_LOCATION (slot
[1]) = INSN_LOCATION (slot
[0]);
3973 if (INSN_LOCATION (slot
[2])
3974 && INSN_LOCATION (slot
[2]) != INSN_LOCATION (slot
[0]))
3975 INSN_LOCATION (slot
[2]) = INSN_LOCATION (slot
[0]);
3977 /* Terminate them with "|| " instead of ";" in the output. */
3978 PUT_MODE (slot
[0], SImode
);
3979 PUT_MODE (slot
[1], SImode
);
3980 /* Terminate the bundle, for the benefit of reorder_var_tracking_notes. */
3981 PUT_MODE (slot
[2], QImode
);
3985 /* Go through all insns, and use the information generated during scheduling
3986 to generate SEQUENCEs to represent bundles of instructions issued
3990 bfin_gen_bundles (void)
3993 FOR_EACH_BB_FN (bb
, cfun
)
3995 rtx_insn
*insn
, *next
;
3999 slot
[0] = slot
[1] = slot
[2] = NULL
;
4000 for (insn
= BB_HEAD (bb
);; insn
= next
)
4003 rtx delete_this
= NULL_RTX
;
4005 if (NONDEBUG_INSN_P (insn
))
4007 enum attr_type type
= get_attr_type (insn
);
4009 if (type
== TYPE_STALL
)
4011 gcc_assert (n_filled
== 0);
4016 if (type
== TYPE_DSP32
|| type
== TYPE_DSP32SHIFTIMM
)
4018 else if (slot
[1] == NULL_RTX
)
4026 next
= NEXT_INSN (insn
);
4027 while (next
&& insn
!= BB_END (bb
)
4029 && GET_CODE (PATTERN (next
)) != USE
4030 && GET_CODE (PATTERN (next
)) != CLOBBER
))
4033 next
= NEXT_INSN (insn
);
4036 /* BB_END can change due to emitting extra NOPs, so check here. */
4037 at_end
= insn
== BB_END (bb
);
4038 if (delete_this
== NULL_RTX
&& (at_end
|| GET_MODE (next
) == TImode
))
4041 || !gen_one_bundle (slot
))
4042 && slot
[0] != NULL_RTX
)
4044 rtx pat
= PATTERN (slot
[0]);
4045 if (GET_CODE (pat
) == SET
4046 && GET_CODE (SET_SRC (pat
)) == UNSPEC
4047 && XINT (SET_SRC (pat
), 1) == UNSPEC_32BIT
)
4049 SET_SRC (pat
) = XVECEXP (SET_SRC (pat
), 0, 0);
4050 INSN_CODE (slot
[0]) = -1;
4051 df_insn_rescan (slot
[0]);
4055 slot
[0] = slot
[1] = slot
[2] = NULL
;
4057 if (delete_this
!= NULL_RTX
)
4058 delete_insn (delete_this
);
4065 /* Ensure that no var tracking notes are emitted in the middle of a
4066 three-instruction bundle. */
4069 reorder_var_tracking_notes (void)
4072 FOR_EACH_BB_FN (bb
, cfun
)
4074 rtx_insn
*insn
, *next
;
4075 rtx_insn
*queue
= NULL
;
4076 bool in_bundle
= false;
4078 for (insn
= BB_HEAD (bb
); insn
!= BB_END (bb
); insn
= next
)
4080 next
= NEXT_INSN (insn
);
4084 /* Emit queued up notes at the last instruction of a bundle. */
4085 if (GET_MODE (insn
) == QImode
)
4089 rtx_insn
*next_queue
= PREV_INSN (queue
);
4090 SET_PREV_INSN (NEXT_INSN (insn
)) = queue
;
4091 SET_NEXT_INSN (queue
) = NEXT_INSN (insn
);
4092 SET_NEXT_INSN (insn
) = queue
;
4093 SET_PREV_INSN (queue
) = insn
;
4098 else if (GET_MODE (insn
) == SImode
)
4101 else if (NOTE_P (insn
) && NOTE_KIND (insn
) == NOTE_INSN_VAR_LOCATION
)
4105 rtx_insn
*prev
= PREV_INSN (insn
);
4106 SET_PREV_INSN (next
) = prev
;
4107 SET_NEXT_INSN (prev
) = next
;
4109 SET_PREV_INSN (insn
) = queue
;
4117 /* On some silicon revisions, functions shorter than a certain number of cycles
4118 can cause unpredictable behaviour. Work around this by adding NOPs as
4121 workaround_rts_anomaly (void)
4123 rtx_insn
*insn
, *first_insn
= NULL
;
4126 if (! ENABLE_WA_RETS
)
4129 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
4133 if (BARRIER_P (insn
))
4136 if (NOTE_P (insn
) || LABEL_P (insn
))
4139 if (JUMP_TABLE_DATA_P (insn
))
4142 if (first_insn
== NULL_RTX
)
4144 pat
= PATTERN (insn
);
4145 if (GET_CODE (pat
) == USE
|| GET_CODE (pat
) == CLOBBER
4146 || GET_CODE (pat
) == ASM_INPUT
4147 || asm_noperands (pat
) >= 0)
4155 if (recog_memoized (insn
) == CODE_FOR_return_internal
)
4158 /* Nothing to worry about for direct jumps. */
4159 if (!any_condjump_p (insn
))
4165 else if (INSN_P (insn
))
4167 rtx pat
= PATTERN (insn
);
4168 int this_cycles
= 1;
4170 if (GET_CODE (pat
) == PARALLEL
)
4172 if (analyze_push_multiple_operation (pat
)
4173 || analyze_pop_multiple_operation (pat
))
4174 this_cycles
= n_regs_to_save
;
4178 int icode
= recog_memoized (insn
);
4180 if (icode
== CODE_FOR_link
)
4182 else if (icode
== CODE_FOR_unlink
)
4184 else if (icode
== CODE_FOR_mulsi3
)
4187 if (this_cycles
>= cycles
)
4190 cycles
-= this_cycles
;
4195 emit_insn_before (gen_nop (), first_insn
);
4200 /* Return an insn type for INSN that can be used by the caller for anomaly
4201 workarounds. This differs from plain get_attr_type in that it handles
4204 static enum attr_type
4205 type_for_anomaly (rtx_insn
*insn
)
4207 rtx pat
= PATTERN (insn
);
4208 if (rtx_sequence
*seq
= dyn_cast
<rtx_sequence
*> (pat
))
4211 t
= get_attr_type (seq
->insn (1));
4214 t
= get_attr_type (seq
->insn (2));
4220 return get_attr_type (insn
);
4223 /* Return true iff the address found in MEM is based on the register
4224 NP_REG and optionally has a positive offset. */
4226 harmless_null_pointer_p (rtx mem
, int np_reg
)
4228 mem
= XEXP (mem
, 0);
4229 if (GET_CODE (mem
) == POST_INC
|| GET_CODE (mem
) == POST_DEC
)
4230 mem
= XEXP (mem
, 0);
4231 if (REG_P (mem
) && (int) REGNO (mem
) == np_reg
)
4233 if (GET_CODE (mem
) == PLUS
4234 && REG_P (XEXP (mem
, 0)) && (int) REGNO (XEXP (mem
, 0)) == np_reg
)
4236 mem
= XEXP (mem
, 1);
4237 if (GET_CODE (mem
) == CONST_INT
&& INTVAL (mem
) > 0)
4243 /* Return nonzero if INSN contains any loads that may trap. */
4246 trapping_loads_p (rtx_insn
*insn
, int np_reg
, bool after_np_branch
)
4248 rtx mem
= SET_SRC (single_set (insn
));
4250 if (!after_np_branch
)
4252 return ((np_reg
== -1 || !harmless_null_pointer_p (mem
, np_reg
))
4253 && may_trap_p (mem
));
4256 /* Return INSN if it is of TYPE_MCLD. Alternatively, if INSN is the start of
4257 a three-insn bundle, see if one of them is a load and return that if so.
4258 Return NULL if the insn does not contain loads. */
4260 find_load (rtx_insn
*insn
)
4262 if (!NONDEBUG_INSN_P (insn
))
4264 if (get_attr_type (insn
) == TYPE_MCLD
)
4266 if (GET_MODE (insn
) != SImode
)
4269 insn
= NEXT_INSN (insn
);
4270 if ((GET_MODE (insn
) == SImode
|| GET_MODE (insn
) == QImode
)
4271 && get_attr_type (insn
) == TYPE_MCLD
)
4273 } while (GET_MODE (insn
) != QImode
);
4277 /* Determine whether PAT is an indirect call pattern. */
4279 indirect_call_p (rtx pat
)
4281 if (GET_CODE (pat
) == PARALLEL
)
4282 pat
= XVECEXP (pat
, 0, 0);
4283 if (GET_CODE (pat
) == SET
)
4284 pat
= SET_SRC (pat
);
4285 gcc_assert (GET_CODE (pat
) == CALL
);
4286 pat
= XEXP (pat
, 0);
4287 gcc_assert (GET_CODE (pat
) == MEM
);
4288 pat
= XEXP (pat
, 0);
4293 /* During workaround_speculation, track whether we're in the shadow of a
4294 conditional branch that tests a P register for NULL. If so, we can omit
4295 emitting NOPs if we see a load from that P register, since a speculative
4296 access at address 0 isn't a problem, and the load is executed in all other
4298 Global for communication with note_np_check_stores through note_stores.
4300 int np_check_regno
= -1;
4301 bool np_after_branch
= false;
4303 /* Subroutine of workaround_speculation, called through note_stores. */
4305 note_np_check_stores (rtx x
, const_rtx pat ATTRIBUTE_UNUSED
,
4306 void *data ATTRIBUTE_UNUSED
)
4308 if (REG_P (x
) && (REGNO (x
) == REG_CC
|| (int) REGNO (x
) == np_check_regno
))
4309 np_check_regno
= -1;
4313 workaround_speculation (void)
4315 rtx_insn
*insn
, *next
;
4316 rtx_insn
*last_condjump
= NULL
;
4317 int cycles_since_jump
= INT_MAX
;
4318 int delay_added
= 0;
4320 if (! ENABLE_WA_SPECULATIVE_LOADS
&& ! ENABLE_WA_SPECULATIVE_SYNCS
4321 && ! ENABLE_WA_INDIRECT_CALLS
)
4324 /* First pass: find predicted-false branches; if something after them
4325 needs nops, insert them or change the branch to predict true. */
4326 for (insn
= get_insns (); insn
; insn
= next
)
4329 int delay_needed
= 0;
4331 next
= find_next_insn_start (insn
);
4333 if (NOTE_P (insn
) || BARRIER_P (insn
))
4335 if (JUMP_TABLE_DATA_P (insn
))
4340 np_check_regno
= -1;
4344 pat
= PATTERN (insn
);
4345 if (GET_CODE (pat
) == USE
|| GET_CODE (pat
) == CLOBBER
)
4348 if (GET_CODE (pat
) == ASM_INPUT
|| asm_noperands (pat
) >= 0)
4350 np_check_regno
= -1;
4356 /* Is this a condjump based on a null pointer comparison we saw
4358 if (np_check_regno
!= -1
4359 && recog_memoized (insn
) == CODE_FOR_cbranchbi4
)
4361 rtx op
= XEXP (SET_SRC (PATTERN (insn
)), 0);
4362 gcc_assert (GET_CODE (op
) == EQ
|| GET_CODE (op
) == NE
);
4363 if (GET_CODE (op
) == NE
)
4364 np_after_branch
= true;
4366 if (any_condjump_p (insn
)
4367 && ! cbranch_predicted_taken_p (insn
))
4369 last_condjump
= insn
;
4371 cycles_since_jump
= 0;
4374 cycles_since_jump
= INT_MAX
;
4376 else if (CALL_P (insn
))
4378 np_check_regno
= -1;
4379 if (cycles_since_jump
< INT_MAX
)
4380 cycles_since_jump
++;
4381 if (indirect_call_p (pat
) && ENABLE_WA_INDIRECT_CALLS
)
4386 else if (NONDEBUG_INSN_P (insn
))
4388 rtx_insn
*load_insn
= find_load (insn
);
4389 enum attr_type type
= type_for_anomaly (insn
);
4391 if (cycles_since_jump
< INT_MAX
)
4392 cycles_since_jump
++;
4394 /* Detect a comparison of a P register with zero. If we later
4395 see a condjump based on it, we have found a null pointer
4397 if (recog_memoized (insn
) == CODE_FOR_compare_eq
)
4399 rtx src
= SET_SRC (PATTERN (insn
));
4400 if (REG_P (XEXP (src
, 0))
4401 && P_REGNO_P (REGNO (XEXP (src
, 0)))
4402 && XEXP (src
, 1) == const0_rtx
)
4404 np_check_regno
= REGNO (XEXP (src
, 0));
4405 np_after_branch
= false;
4408 np_check_regno
= -1;
4411 if (load_insn
&& ENABLE_WA_SPECULATIVE_LOADS
)
4413 if (trapping_loads_p (load_insn
, np_check_regno
,
4417 else if (type
== TYPE_SYNC
&& ENABLE_WA_SPECULATIVE_SYNCS
)
4420 /* See if we need to forget about a null pointer comparison
4421 we found earlier. */
4422 if (recog_memoized (insn
) != CODE_FOR_compare_eq
)
4424 note_stores (PATTERN (insn
), note_np_check_stores
, NULL
);
4425 if (np_check_regno
!= -1)
4427 if (find_regno_note (insn
, REG_INC
, np_check_regno
))
4428 np_check_regno
= -1;
4434 if (delay_needed
> cycles_since_jump
4435 && (delay_needed
- cycles_since_jump
) > delay_added
)
4439 rtx
*op
= recog_data
.operand
;
4441 delay_needed
-= cycles_since_jump
;
4443 extract_insn (last_condjump
);
4446 pat1
= gen_cbranch_predicted_taken (op
[0], op
[1], op
[2],
4448 cycles_since_jump
= INT_MAX
;
4452 /* Do not adjust cycles_since_jump in this case, so that
4453 we'll increase the number of NOPs for a subsequent insn
4455 pat1
= gen_cbranch_with_nops (op
[0], op
[1], op
[2], op
[3],
4456 GEN_INT (delay_needed
));
4457 delay_added
= delay_needed
;
4459 PATTERN (last_condjump
) = pat1
;
4460 INSN_CODE (last_condjump
) = recog (pat1
, insn
, &num_clobbers
);
4464 cycles_since_jump
= INT_MAX
;
4469 /* Second pass: for predicted-true branches, see if anything at the
4470 branch destination needs extra nops. */
4471 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
4473 int cycles_since_jump
;
4475 && any_condjump_p (insn
)
4476 && (INSN_CODE (insn
) == CODE_FOR_cbranch_predicted_taken
4477 || cbranch_predicted_taken_p (insn
)))
4479 rtx_insn
*target
= JUMP_LABEL_AS_INSN (insn
);
4483 cycles_since_jump
= 0;
4484 for (; target
&& cycles_since_jump
< 3; target
= next_tgt
)
4488 next_tgt
= find_next_insn_start (target
);
4490 if (NOTE_P (target
) || BARRIER_P (target
) || LABEL_P (target
))
4493 if (JUMP_TABLE_DATA_P (target
))
4496 pat
= PATTERN (target
);
4497 if (GET_CODE (pat
) == USE
|| GET_CODE (pat
) == CLOBBER
4498 || GET_CODE (pat
) == ASM_INPUT
4499 || asm_noperands (pat
) >= 0)
4502 if (NONDEBUG_INSN_P (target
))
4504 rtx_insn
*load_insn
= find_load (target
);
4505 enum attr_type type
= type_for_anomaly (target
);
4506 int delay_needed
= 0;
4507 if (cycles_since_jump
< INT_MAX
)
4508 cycles_since_jump
++;
4510 if (load_insn
&& ENABLE_WA_SPECULATIVE_LOADS
)
4512 if (trapping_loads_p (load_insn
, -1, false))
4515 else if (type
== TYPE_SYNC
&& ENABLE_WA_SPECULATIVE_SYNCS
)
4518 if (delay_needed
> cycles_since_jump
)
4520 rtx_insn
*prev
= prev_real_insn (label
);
4521 delay_needed
-= cycles_since_jump
;
4523 fprintf (dump_file
, "Adding %d nops after %d\n",
4524 delay_needed
, INSN_UID (label
));
4526 && INSN_CODE (prev
) == CODE_FOR_cbranch_with_nops
)
4533 "Reducing nops on insn %d.\n",
4536 x
= XVECEXP (x
, 0, 1);
4537 v
= INTVAL (XVECEXP (x
, 0, 0)) - delay_needed
;
4538 XVECEXP (x
, 0, 0) = GEN_INT (v
);
4540 while (delay_needed
-- > 0)
4541 emit_insn_after (gen_nop (), label
);
4550 /* Called just before the final scheduling pass. If we need to insert NOPs
4551 later on to work around speculative loads, insert special placeholder
4552 insns that cause loads to be delayed for as many cycles as necessary
4553 (and possible). This reduces the number of NOPs we need to add.
4554 The dummy insns we generate are later removed by bfin_gen_bundles. */
4556 add_sched_insns_for_speculation (void)
4560 if (! ENABLE_WA_SPECULATIVE_LOADS
&& ! ENABLE_WA_SPECULATIVE_SYNCS
4561 && ! ENABLE_WA_INDIRECT_CALLS
)
4564 /* First pass: find predicted-false branches; if something after them
4565 needs nops, insert them or change the branch to predict true. */
4566 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
4570 if (NOTE_P (insn
) || BARRIER_P (insn
) || LABEL_P (insn
))
4572 if (JUMP_TABLE_DATA_P (insn
))
4575 pat
= PATTERN (insn
);
4576 if (GET_CODE (pat
) == USE
|| GET_CODE (pat
) == CLOBBER
4577 || GET_CODE (pat
) == ASM_INPUT
4578 || asm_noperands (pat
) >= 0)
4583 if (any_condjump_p (insn
)
4584 && !cbranch_predicted_taken_p (insn
))
4586 rtx_insn
*n
= next_real_insn (insn
);
4587 emit_insn_before (gen_stall (GEN_INT (3)), n
);
4592 /* Second pass: for predicted-true branches, see if anything at the
4593 branch destination needs extra nops. */
4594 for (insn
= get_insns (); insn
; insn
= NEXT_INSN (insn
))
4597 && any_condjump_p (insn
)
4598 && (cbranch_predicted_taken_p (insn
)))
4600 rtx target
= JUMP_LABEL (insn
);
4601 rtx_insn
*next
= next_real_insn (target
);
4603 if (GET_CODE (PATTERN (next
)) == UNSPEC_VOLATILE
4604 && get_attr_type (next
) == TYPE_STALL
)
4606 emit_insn_before (gen_stall (GEN_INT (1)), next
);
4611 /* We use the machine specific reorg pass for emitting CSYNC instructions
4612 after conditional branches as needed.
4614 The Blackfin is unusual in that a code sequence like
4617 may speculatively perform the load even if the condition isn't true. This
4618 happens for a branch that is predicted not taken, because the pipeline
4619 isn't flushed or stalled, so the early stages of the following instructions,
4620 which perform the memory reference, are allowed to execute before the
4621 jump condition is evaluated.
4622 Therefore, we must insert additional instructions in all places where this
4623 could lead to incorrect behavior. The manual recommends CSYNC, while
4624 VDSP seems to use NOPs (even though its corresponding compiler option is
4627 When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
4628 When optimizing for size, we turn the branch into a predicted taken one.
4629 This may be slower due to mispredicts, but saves code size. */
4634 /* We are freeing block_for_insn in the toplev to keep compatibility
4635 with old MDEP_REORGS that are not CFG based. Recompute it now. */
4636 compute_bb_for_insn ();
4638 if (flag_schedule_insns_after_reload
)
4640 splitting_for_sched
= 1;
4642 splitting_for_sched
= 0;
4644 add_sched_insns_for_speculation ();
4646 timevar_push (TV_SCHED2
);
4647 if (flag_selective_scheduling2
4648 && !maybe_skip_selective_scheduling ())
4649 run_selective_scheduling ();
4652 timevar_pop (TV_SCHED2
);
4654 /* Examine the schedule and insert nops as necessary for 64-bit parallel
4656 bfin_gen_bundles ();
4661 /* Doloop optimization */
4662 if (cfun
->machine
->has_hardware_loops
)
4663 bfin_reorg_loops ();
4665 workaround_speculation ();
4667 if (flag_var_tracking
)
4669 timevar_push (TV_VAR_TRACKING
);
4670 variable_tracking_main ();
4671 reorder_var_tracking_notes ();
4672 timevar_pop (TV_VAR_TRACKING
);
4675 df_finish_pass (false);
4677 workaround_rts_anomaly ();
4680 /* Handle interrupt_handler, exception_handler and nmi_handler function
4681 attributes; arguments as in struct attribute_spec.handler. */
4684 handle_int_attribute (tree
*node
, tree name
,
4685 tree args ATTRIBUTE_UNUSED
,
4686 int flags ATTRIBUTE_UNUSED
,
4690 if (TREE_CODE (x
) == FUNCTION_DECL
)
4693 if (TREE_CODE (x
) != FUNCTION_TYPE
)
4695 warning (OPT_Wattributes
, "%qE attribute only applies to functions",
4697 *no_add_attrs
= true;
4699 else if (funkind (x
) != SUBROUTINE
)
4700 error ("multiple function type attributes specified");
4705 /* Return 0 if the attributes for two types are incompatible, 1 if they
4706 are compatible, and 2 if they are nearly compatible (which causes a
4707 warning to be generated). */
4710 bfin_comp_type_attributes (const_tree type1
, const_tree type2
)
4712 e_funkind kind1
, kind2
;
4714 if (TREE_CODE (type1
) != FUNCTION_TYPE
)
4717 kind1
= funkind (type1
);
4718 kind2
= funkind (type2
);
4723 /* Check for mismatched modifiers */
4724 if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1
))
4725 != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2
)))
4728 if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1
))
4729 != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2
)))
4732 if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1
))
4733 != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2
)))
4736 if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1
))
4737 != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2
)))
4743 /* Handle a "longcall" or "shortcall" attribute; arguments as in
4744 struct attribute_spec.handler. */
4747 bfin_handle_longcall_attribute (tree
*node
, tree name
,
4748 tree args ATTRIBUTE_UNUSED
,
4749 int flags ATTRIBUTE_UNUSED
,
4752 if (TREE_CODE (*node
) != FUNCTION_TYPE
4753 && TREE_CODE (*node
) != FIELD_DECL
4754 && TREE_CODE (*node
) != TYPE_DECL
)
4756 warning (OPT_Wattributes
, "%qE attribute only applies to functions",
4758 *no_add_attrs
= true;
4761 if ((strcmp (IDENTIFIER_POINTER (name
), "longcall") == 0
4762 && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node
)))
4763 || (strcmp (IDENTIFIER_POINTER (name
), "shortcall") == 0
4764 && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node
))))
4766 warning (OPT_Wattributes
,
4767 "can%'t apply both longcall and shortcall attributes to the same function");
4768 *no_add_attrs
= true;
4774 /* Handle a "l1_text" attribute; arguments as in
4775 struct attribute_spec.handler. */
4778 bfin_handle_l1_text_attribute (tree
*node
, tree name
, tree
ARG_UNUSED (args
),
4779 int ARG_UNUSED (flags
), bool *no_add_attrs
)
4783 if (TREE_CODE (decl
) != FUNCTION_DECL
)
4785 error ("%qE attribute only applies to functions",
4787 *no_add_attrs
= true;
4790 /* The decl may have already been given a section attribute
4791 from a previous declaration. Ensure they match. */
4792 else if (DECL_SECTION_NAME (decl
) != NULL
4793 && strcmp (DECL_SECTION_NAME (decl
),
4796 error ("section of %q+D conflicts with previous declaration",
4798 *no_add_attrs
= true;
4801 set_decl_section_name (decl
, ".l1.text");
4806 /* Handle a "l1_data", "l1_data_A" or "l1_data_B" attribute;
4807 arguments as in struct attribute_spec.handler. */
4810 bfin_handle_l1_data_attribute (tree
*node
, tree name
, tree
ARG_UNUSED (args
),
4811 int ARG_UNUSED (flags
), bool *no_add_attrs
)
4815 if (TREE_CODE (decl
) != VAR_DECL
)
4817 error ("%qE attribute only applies to variables",
4819 *no_add_attrs
= true;
4821 else if (current_function_decl
!= NULL_TREE
4822 && !TREE_STATIC (decl
))
4824 error ("%qE attribute cannot be specified for local variables",
4826 *no_add_attrs
= true;
4830 const char *section_name
;
4832 if (strcmp (IDENTIFIER_POINTER (name
), "l1_data") == 0)
4833 section_name
= ".l1.data";
4834 else if (strcmp (IDENTIFIER_POINTER (name
), "l1_data_A") == 0)
4835 section_name
= ".l1.data.A";
4836 else if (strcmp (IDENTIFIER_POINTER (name
), "l1_data_B") == 0)
4837 section_name
= ".l1.data.B";
4841 /* The decl may have already been given a section attribute
4842 from a previous declaration. Ensure they match. */
4843 if (DECL_SECTION_NAME (decl
) != NULL
4844 && strcmp (DECL_SECTION_NAME (decl
),
4847 error ("section of %q+D conflicts with previous declaration",
4849 *no_add_attrs
= true;
4852 set_decl_section_name (decl
, section_name
);
4858 /* Handle a "l2" attribute; arguments as in struct attribute_spec.handler. */
4861 bfin_handle_l2_attribute (tree
*node
, tree
ARG_UNUSED (name
),
4862 tree
ARG_UNUSED (args
), int ARG_UNUSED (flags
),
4867 if (TREE_CODE (decl
) == FUNCTION_DECL
)
4869 if (DECL_SECTION_NAME (decl
) != NULL
4870 && strcmp (DECL_SECTION_NAME (decl
),
4873 error ("section of %q+D conflicts with previous declaration",
4875 *no_add_attrs
= true;
4878 set_decl_section_name (decl
, ".l2.text");
4880 else if (TREE_CODE (decl
) == VAR_DECL
)
4882 if (DECL_SECTION_NAME (decl
) != NULL
4883 && strcmp (DECL_SECTION_NAME (decl
),
4886 error ("section of %q+D conflicts with previous declaration",
4888 *no_add_attrs
= true;
4891 set_decl_section_name (decl
, ".l2.data");
4897 /* Table of valid machine attributes. */
4898 static const struct attribute_spec bfin_attribute_table
[] =
4900 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
4901 affects_type_identity } */
4902 { "interrupt_handler", 0, 0, false, true, true, handle_int_attribute
,
4904 { "exception_handler", 0, 0, false, true, true, handle_int_attribute
,
4906 { "nmi_handler", 0, 0, false, true, true, handle_int_attribute
, false },
4907 { "nesting", 0, 0, false, true, true, NULL
, false },
4908 { "kspisusp", 0, 0, false, true, true, NULL
, false },
4909 { "saveall", 0, 0, false, true, true, NULL
, false },
4910 { "longcall", 0, 0, false, true, true, bfin_handle_longcall_attribute
,
4912 { "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute
,
4914 { "l1_text", 0, 0, true, false, false, bfin_handle_l1_text_attribute
,
4916 { "l1_data", 0, 0, true, false, false, bfin_handle_l1_data_attribute
,
4918 { "l1_data_A", 0, 0, true, false, false, bfin_handle_l1_data_attribute
,
4920 { "l1_data_B", 0, 0, true, false, false, bfin_handle_l1_data_attribute
,
4922 { "l2", 0, 0, true, false, false, bfin_handle_l2_attribute
, false },
4923 { NULL
, 0, 0, false, false, false, NULL
, false }
4926 /* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to
4927 tell the assembler to generate pointers to function descriptors in
4931 bfin_assemble_integer (rtx value
, unsigned int size
, int aligned_p
)
4933 if (TARGET_FDPIC
&& size
== UNITS_PER_WORD
)
4935 if (GET_CODE (value
) == SYMBOL_REF
4936 && SYMBOL_REF_FUNCTION_P (value
))
4938 fputs ("\t.picptr\tfuncdesc(", asm_out_file
);
4939 output_addr_const (asm_out_file
, value
);
4940 fputs (")\n", asm_out_file
);
4945 /* We've set the unaligned SI op to NULL, so we always have to
4946 handle the unaligned case here. */
4947 assemble_integer_with_op ("\t.4byte\t", value
);
4951 return default_assemble_integer (value
, size
, aligned_p
);
4954 /* Output the assembler code for a thunk function. THUNK_DECL is the
4955 declaration for the thunk function itself, FUNCTION is the decl for
4956 the target function. DELTA is an immediate constant offset to be
4957 added to THIS. If VCALL_OFFSET is nonzero, the word at
4958 *(*this + vcall_offset) should be added to THIS. */
4961 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED
,
4962 tree thunk ATTRIBUTE_UNUSED
, HOST_WIDE_INT delta
,
4963 HOST_WIDE_INT vcall_offset
, tree function
)
4966 /* The this parameter is passed as the first argument. */
4967 rtx this_rtx
= gen_rtx_REG (Pmode
, REG_R0
);
4969 /* Adjust the this parameter by a fixed constant. */
4973 if (delta
>= -64 && delta
<= 63)
4975 xops
[0] = GEN_INT (delta
);
4976 output_asm_insn ("%1 += %0;", xops
);
4978 else if (delta
>= -128 && delta
< -64)
4980 xops
[0] = GEN_INT (delta
+ 64);
4981 output_asm_insn ("%1 += -64; %1 += %0;", xops
);
4983 else if (delta
> 63 && delta
<= 126)
4985 xops
[0] = GEN_INT (delta
- 63);
4986 output_asm_insn ("%1 += 63; %1 += %0;", xops
);
4990 xops
[0] = GEN_INT (delta
);
4991 output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops
);
4995 /* Adjust the this parameter by a value stored in the vtable. */
4998 rtx p2tmp
= gen_rtx_REG (Pmode
, REG_P2
);
4999 rtx tmp
= gen_rtx_REG (Pmode
, REG_R3
);
5003 output_asm_insn ("%2 = r0; %2 = [%2];", xops
);
5005 /* Adjust the this parameter. */
5006 xops
[0] = gen_rtx_MEM (Pmode
, plus_constant (Pmode
, p2tmp
,
5008 if (!memory_operand (xops
[0], Pmode
))
5010 rtx tmp2
= gen_rtx_REG (Pmode
, REG_P1
);
5011 xops
[0] = GEN_INT (vcall_offset
);
5013 output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops
);
5014 xops
[0] = gen_rtx_MEM (Pmode
, p2tmp
);
5017 output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops
);
5020 xops
[0] = XEXP (DECL_RTL (function
), 0);
5021 if (1 || !flag_pic
|| (*targetm
.binds_local_p
) (function
))
5022 output_asm_insn ("jump.l\t%P0", xops
);
5025 /* Codes for all the Blackfin builtins. */
5031 BFIN_BUILTIN_COMPOSE_2X16
,
5032 BFIN_BUILTIN_EXTRACTLO
,
5033 BFIN_BUILTIN_EXTRACTHI
,
5035 BFIN_BUILTIN_SSADD_2X16
,
5036 BFIN_BUILTIN_SSSUB_2X16
,
5037 BFIN_BUILTIN_SSADDSUB_2X16
,
5038 BFIN_BUILTIN_SSSUBADD_2X16
,
5039 BFIN_BUILTIN_MULT_2X16
,
5040 BFIN_BUILTIN_MULTR_2X16
,
5041 BFIN_BUILTIN_NEG_2X16
,
5042 BFIN_BUILTIN_ABS_2X16
,
5043 BFIN_BUILTIN_MIN_2X16
,
5044 BFIN_BUILTIN_MAX_2X16
,
5046 BFIN_BUILTIN_SSADD_1X16
,
5047 BFIN_BUILTIN_SSSUB_1X16
,
5048 BFIN_BUILTIN_MULT_1X16
,
5049 BFIN_BUILTIN_MULTR_1X16
,
5050 BFIN_BUILTIN_NORM_1X16
,
5051 BFIN_BUILTIN_NEG_1X16
,
5052 BFIN_BUILTIN_ABS_1X16
,
5053 BFIN_BUILTIN_MIN_1X16
,
5054 BFIN_BUILTIN_MAX_1X16
,
5056 BFIN_BUILTIN_SUM_2X16
,
5057 BFIN_BUILTIN_DIFFHL_2X16
,
5058 BFIN_BUILTIN_DIFFLH_2X16
,
5060 BFIN_BUILTIN_SSADD_1X32
,
5061 BFIN_BUILTIN_SSSUB_1X32
,
5062 BFIN_BUILTIN_NORM_1X32
,
5063 BFIN_BUILTIN_ROUND_1X32
,
5064 BFIN_BUILTIN_NEG_1X32
,
5065 BFIN_BUILTIN_ABS_1X32
,
5066 BFIN_BUILTIN_MIN_1X32
,
5067 BFIN_BUILTIN_MAX_1X32
,
5068 BFIN_BUILTIN_MULT_1X32
,
5069 BFIN_BUILTIN_MULT_1X32X32
,
5070 BFIN_BUILTIN_MULT_1X32X32NS
,
5072 BFIN_BUILTIN_MULHISILL
,
5073 BFIN_BUILTIN_MULHISILH
,
5074 BFIN_BUILTIN_MULHISIHL
,
5075 BFIN_BUILTIN_MULHISIHH
,
5077 BFIN_BUILTIN_LSHIFT_1X16
,
5078 BFIN_BUILTIN_LSHIFT_2X16
,
5079 BFIN_BUILTIN_SSASHIFT_1X16
,
5080 BFIN_BUILTIN_SSASHIFT_2X16
,
5081 BFIN_BUILTIN_SSASHIFT_1X32
,
5083 BFIN_BUILTIN_CPLX_MUL_16
,
5084 BFIN_BUILTIN_CPLX_MAC_16
,
5085 BFIN_BUILTIN_CPLX_MSU_16
,
5087 BFIN_BUILTIN_CPLX_MUL_16_S40
,
5088 BFIN_BUILTIN_CPLX_MAC_16_S40
,
5089 BFIN_BUILTIN_CPLX_MSU_16_S40
,
5091 BFIN_BUILTIN_CPLX_SQU
,
5093 BFIN_BUILTIN_LOADBYTES
,
5098 #define def_builtin(NAME, TYPE, CODE) \
5100 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
5104 /* Set up all builtin functions for this target. */
5106 bfin_init_builtins (void)
5108 tree V2HI_type_node
= build_vector_type_for_mode (intHI_type_node
, V2HImode
);
5109 tree void_ftype_void
5110 = build_function_type_list (void_type_node
, NULL_TREE
);
5111 tree short_ftype_short
5112 = build_function_type_list (short_integer_type_node
, short_integer_type_node
,
5114 tree short_ftype_int_int
5115 = build_function_type_list (short_integer_type_node
, integer_type_node
,
5116 integer_type_node
, NULL_TREE
);
5117 tree int_ftype_int_int
5118 = build_function_type_list (integer_type_node
, integer_type_node
,
5119 integer_type_node
, NULL_TREE
);
5121 = build_function_type_list (integer_type_node
, integer_type_node
,
5123 tree short_ftype_int
5124 = build_function_type_list (short_integer_type_node
, integer_type_node
,
5126 tree int_ftype_v2hi_v2hi
5127 = build_function_type_list (integer_type_node
, V2HI_type_node
,
5128 V2HI_type_node
, NULL_TREE
);
5129 tree v2hi_ftype_v2hi_v2hi
5130 = build_function_type_list (V2HI_type_node
, V2HI_type_node
,
5131 V2HI_type_node
, NULL_TREE
);
5132 tree v2hi_ftype_v2hi_v2hi_v2hi
5133 = build_function_type_list (V2HI_type_node
, V2HI_type_node
,
5134 V2HI_type_node
, V2HI_type_node
, NULL_TREE
);
5135 tree v2hi_ftype_int_int
5136 = build_function_type_list (V2HI_type_node
, integer_type_node
,
5137 integer_type_node
, NULL_TREE
);
5138 tree v2hi_ftype_v2hi_int
5139 = build_function_type_list (V2HI_type_node
, V2HI_type_node
,
5140 integer_type_node
, NULL_TREE
);
5141 tree int_ftype_short_short
5142 = build_function_type_list (integer_type_node
, short_integer_type_node
,
5143 short_integer_type_node
, NULL_TREE
);
5144 tree v2hi_ftype_v2hi
5145 = build_function_type_list (V2HI_type_node
, V2HI_type_node
, NULL_TREE
);
5146 tree short_ftype_v2hi
5147 = build_function_type_list (short_integer_type_node
, V2HI_type_node
,
5150 = build_function_type_list (integer_type_node
,
5151 build_pointer_type (integer_type_node
),
5154 /* Add the remaining MMX insns with somewhat more complicated types. */
5155 def_builtin ("__builtin_bfin_csync", void_ftype_void
, BFIN_BUILTIN_CSYNC
);
5156 def_builtin ("__builtin_bfin_ssync", void_ftype_void
, BFIN_BUILTIN_SSYNC
);
5158 def_builtin ("__builtin_bfin_ones", short_ftype_int
, BFIN_BUILTIN_ONES
);
5160 def_builtin ("__builtin_bfin_compose_2x16", v2hi_ftype_int_int
,
5161 BFIN_BUILTIN_COMPOSE_2X16
);
5162 def_builtin ("__builtin_bfin_extract_hi", short_ftype_v2hi
,
5163 BFIN_BUILTIN_EXTRACTHI
);
5164 def_builtin ("__builtin_bfin_extract_lo", short_ftype_v2hi
,
5165 BFIN_BUILTIN_EXTRACTLO
);
5167 def_builtin ("__builtin_bfin_min_fr2x16", v2hi_ftype_v2hi_v2hi
,
5168 BFIN_BUILTIN_MIN_2X16
);
5169 def_builtin ("__builtin_bfin_max_fr2x16", v2hi_ftype_v2hi_v2hi
,
5170 BFIN_BUILTIN_MAX_2X16
);
5172 def_builtin ("__builtin_bfin_add_fr2x16", v2hi_ftype_v2hi_v2hi
,
5173 BFIN_BUILTIN_SSADD_2X16
);
5174 def_builtin ("__builtin_bfin_sub_fr2x16", v2hi_ftype_v2hi_v2hi
,
5175 BFIN_BUILTIN_SSSUB_2X16
);
5176 def_builtin ("__builtin_bfin_dspaddsubsat", v2hi_ftype_v2hi_v2hi
,
5177 BFIN_BUILTIN_SSADDSUB_2X16
);
5178 def_builtin ("__builtin_bfin_dspsubaddsat", v2hi_ftype_v2hi_v2hi
,
5179 BFIN_BUILTIN_SSSUBADD_2X16
);
5180 def_builtin ("__builtin_bfin_mult_fr2x16", v2hi_ftype_v2hi_v2hi
,
5181 BFIN_BUILTIN_MULT_2X16
);
5182 def_builtin ("__builtin_bfin_multr_fr2x16", v2hi_ftype_v2hi_v2hi
,
5183 BFIN_BUILTIN_MULTR_2X16
);
5184 def_builtin ("__builtin_bfin_negate_fr2x16", v2hi_ftype_v2hi
,
5185 BFIN_BUILTIN_NEG_2X16
);
5186 def_builtin ("__builtin_bfin_abs_fr2x16", v2hi_ftype_v2hi
,
5187 BFIN_BUILTIN_ABS_2X16
);
5189 def_builtin ("__builtin_bfin_min_fr1x16", short_ftype_int_int
,
5190 BFIN_BUILTIN_MIN_1X16
);
5191 def_builtin ("__builtin_bfin_max_fr1x16", short_ftype_int_int
,
5192 BFIN_BUILTIN_MAX_1X16
);
5194 def_builtin ("__builtin_bfin_add_fr1x16", short_ftype_int_int
,
5195 BFIN_BUILTIN_SSADD_1X16
);
5196 def_builtin ("__builtin_bfin_sub_fr1x16", short_ftype_int_int
,
5197 BFIN_BUILTIN_SSSUB_1X16
);
5198 def_builtin ("__builtin_bfin_mult_fr1x16", short_ftype_int_int
,
5199 BFIN_BUILTIN_MULT_1X16
);
5200 def_builtin ("__builtin_bfin_multr_fr1x16", short_ftype_int_int
,
5201 BFIN_BUILTIN_MULTR_1X16
);
5202 def_builtin ("__builtin_bfin_negate_fr1x16", short_ftype_short
,
5203 BFIN_BUILTIN_NEG_1X16
);
5204 def_builtin ("__builtin_bfin_abs_fr1x16", short_ftype_short
,
5205 BFIN_BUILTIN_ABS_1X16
);
5206 def_builtin ("__builtin_bfin_norm_fr1x16", short_ftype_int
,
5207 BFIN_BUILTIN_NORM_1X16
);
5209 def_builtin ("__builtin_bfin_sum_fr2x16", short_ftype_v2hi
,
5210 BFIN_BUILTIN_SUM_2X16
);
5211 def_builtin ("__builtin_bfin_diff_hl_fr2x16", short_ftype_v2hi
,
5212 BFIN_BUILTIN_DIFFHL_2X16
);
5213 def_builtin ("__builtin_bfin_diff_lh_fr2x16", short_ftype_v2hi
,
5214 BFIN_BUILTIN_DIFFLH_2X16
);
5216 def_builtin ("__builtin_bfin_mulhisill", int_ftype_v2hi_v2hi
,
5217 BFIN_BUILTIN_MULHISILL
);
5218 def_builtin ("__builtin_bfin_mulhisihl", int_ftype_v2hi_v2hi
,
5219 BFIN_BUILTIN_MULHISIHL
);
5220 def_builtin ("__builtin_bfin_mulhisilh", int_ftype_v2hi_v2hi
,
5221 BFIN_BUILTIN_MULHISILH
);
5222 def_builtin ("__builtin_bfin_mulhisihh", int_ftype_v2hi_v2hi
,
5223 BFIN_BUILTIN_MULHISIHH
);
5225 def_builtin ("__builtin_bfin_min_fr1x32", int_ftype_int_int
,
5226 BFIN_BUILTIN_MIN_1X32
);
5227 def_builtin ("__builtin_bfin_max_fr1x32", int_ftype_int_int
,
5228 BFIN_BUILTIN_MAX_1X32
);
5230 def_builtin ("__builtin_bfin_add_fr1x32", int_ftype_int_int
,
5231 BFIN_BUILTIN_SSADD_1X32
);
5232 def_builtin ("__builtin_bfin_sub_fr1x32", int_ftype_int_int
,
5233 BFIN_BUILTIN_SSSUB_1X32
);
5234 def_builtin ("__builtin_bfin_negate_fr1x32", int_ftype_int
,
5235 BFIN_BUILTIN_NEG_1X32
);
5236 def_builtin ("__builtin_bfin_abs_fr1x32", int_ftype_int
,
5237 BFIN_BUILTIN_ABS_1X32
);
5238 def_builtin ("__builtin_bfin_norm_fr1x32", short_ftype_int
,
5239 BFIN_BUILTIN_NORM_1X32
);
5240 def_builtin ("__builtin_bfin_round_fr1x32", short_ftype_int
,
5241 BFIN_BUILTIN_ROUND_1X32
);
5242 def_builtin ("__builtin_bfin_mult_fr1x32", int_ftype_short_short
,
5243 BFIN_BUILTIN_MULT_1X32
);
5244 def_builtin ("__builtin_bfin_mult_fr1x32x32", int_ftype_int_int
,
5245 BFIN_BUILTIN_MULT_1X32X32
);
5246 def_builtin ("__builtin_bfin_mult_fr1x32x32NS", int_ftype_int_int
,
5247 BFIN_BUILTIN_MULT_1X32X32NS
);
5250 def_builtin ("__builtin_bfin_shl_fr1x16", short_ftype_int_int
,
5251 BFIN_BUILTIN_SSASHIFT_1X16
);
5252 def_builtin ("__builtin_bfin_shl_fr2x16", v2hi_ftype_v2hi_int
,
5253 BFIN_BUILTIN_SSASHIFT_2X16
);
5254 def_builtin ("__builtin_bfin_lshl_fr1x16", short_ftype_int_int
,
5255 BFIN_BUILTIN_LSHIFT_1X16
);
5256 def_builtin ("__builtin_bfin_lshl_fr2x16", v2hi_ftype_v2hi_int
,
5257 BFIN_BUILTIN_LSHIFT_2X16
);
5258 def_builtin ("__builtin_bfin_shl_fr1x32", int_ftype_int_int
,
5259 BFIN_BUILTIN_SSASHIFT_1X32
);
5261 /* Complex numbers. */
5262 def_builtin ("__builtin_bfin_cmplx_add", v2hi_ftype_v2hi_v2hi
,
5263 BFIN_BUILTIN_SSADD_2X16
);
5264 def_builtin ("__builtin_bfin_cmplx_sub", v2hi_ftype_v2hi_v2hi
,
5265 BFIN_BUILTIN_SSSUB_2X16
);
5266 def_builtin ("__builtin_bfin_cmplx_mul", v2hi_ftype_v2hi_v2hi
,
5267 BFIN_BUILTIN_CPLX_MUL_16
);
5268 def_builtin ("__builtin_bfin_cmplx_mac", v2hi_ftype_v2hi_v2hi_v2hi
,
5269 BFIN_BUILTIN_CPLX_MAC_16
);
5270 def_builtin ("__builtin_bfin_cmplx_msu", v2hi_ftype_v2hi_v2hi_v2hi
,
5271 BFIN_BUILTIN_CPLX_MSU_16
);
5272 def_builtin ("__builtin_bfin_cmplx_mul_s40", v2hi_ftype_v2hi_v2hi
,
5273 BFIN_BUILTIN_CPLX_MUL_16_S40
);
5274 def_builtin ("__builtin_bfin_cmplx_mac_s40", v2hi_ftype_v2hi_v2hi_v2hi
,
5275 BFIN_BUILTIN_CPLX_MAC_16_S40
);
5276 def_builtin ("__builtin_bfin_cmplx_msu_s40", v2hi_ftype_v2hi_v2hi_v2hi
,
5277 BFIN_BUILTIN_CPLX_MSU_16_S40
);
5278 def_builtin ("__builtin_bfin_csqu_fr16", v2hi_ftype_v2hi
,
5279 BFIN_BUILTIN_CPLX_SQU
);
5281 /* "Unaligned" load. */
5282 def_builtin ("__builtin_bfin_loadbytes", int_ftype_pint
,
5283 BFIN_BUILTIN_LOADBYTES
);
5288 struct builtin_description
5290 const enum insn_code icode
;
5291 const char *const name
;
5292 const enum bfin_builtins code
;
5296 static const struct builtin_description bdesc_2arg
[] =
5298 { CODE_FOR_composev2hi
, "__builtin_bfin_compose_2x16", BFIN_BUILTIN_COMPOSE_2X16
, -1 },
5300 { CODE_FOR_ssashiftv2hi3
, "__builtin_bfin_shl_fr2x16", BFIN_BUILTIN_SSASHIFT_2X16
, -1 },
5301 { CODE_FOR_ssashifthi3
, "__builtin_bfin_shl_fr1x16", BFIN_BUILTIN_SSASHIFT_1X16
, -1 },
5302 { CODE_FOR_lshiftv2hi3
, "__builtin_bfin_lshl_fr2x16", BFIN_BUILTIN_LSHIFT_2X16
, -1 },
5303 { CODE_FOR_lshifthi3
, "__builtin_bfin_lshl_fr1x16", BFIN_BUILTIN_LSHIFT_1X16
, -1 },
5304 { CODE_FOR_ssashiftsi3
, "__builtin_bfin_shl_fr1x32", BFIN_BUILTIN_SSASHIFT_1X32
, -1 },
5306 { CODE_FOR_sminhi3
, "__builtin_bfin_min_fr1x16", BFIN_BUILTIN_MIN_1X16
, -1 },
5307 { CODE_FOR_smaxhi3
, "__builtin_bfin_max_fr1x16", BFIN_BUILTIN_MAX_1X16
, -1 },
5308 { CODE_FOR_ssaddhi3
, "__builtin_bfin_add_fr1x16", BFIN_BUILTIN_SSADD_1X16
, -1 },
5309 { CODE_FOR_sssubhi3
, "__builtin_bfin_sub_fr1x16", BFIN_BUILTIN_SSSUB_1X16
, -1 },
5311 { CODE_FOR_sminsi3
, "__builtin_bfin_min_fr1x32", BFIN_BUILTIN_MIN_1X32
, -1 },
5312 { CODE_FOR_smaxsi3
, "__builtin_bfin_max_fr1x32", BFIN_BUILTIN_MAX_1X32
, -1 },
5313 { CODE_FOR_ssaddsi3
, "__builtin_bfin_add_fr1x32", BFIN_BUILTIN_SSADD_1X32
, -1 },
5314 { CODE_FOR_sssubsi3
, "__builtin_bfin_sub_fr1x32", BFIN_BUILTIN_SSSUB_1X32
, -1 },
5316 { CODE_FOR_sminv2hi3
, "__builtin_bfin_min_fr2x16", BFIN_BUILTIN_MIN_2X16
, -1 },
5317 { CODE_FOR_smaxv2hi3
, "__builtin_bfin_max_fr2x16", BFIN_BUILTIN_MAX_2X16
, -1 },
5318 { CODE_FOR_ssaddv2hi3
, "__builtin_bfin_add_fr2x16", BFIN_BUILTIN_SSADD_2X16
, -1 },
5319 { CODE_FOR_sssubv2hi3
, "__builtin_bfin_sub_fr2x16", BFIN_BUILTIN_SSSUB_2X16
, -1 },
5320 { CODE_FOR_ssaddsubv2hi3
, "__builtin_bfin_dspaddsubsat", BFIN_BUILTIN_SSADDSUB_2X16
, -1 },
5321 { CODE_FOR_sssubaddv2hi3
, "__builtin_bfin_dspsubaddsat", BFIN_BUILTIN_SSSUBADD_2X16
, -1 },
5323 { CODE_FOR_flag_mulhisi
, "__builtin_bfin_mult_fr1x32", BFIN_BUILTIN_MULT_1X32
, MACFLAG_NONE
},
5324 { CODE_FOR_flag_mulhi
, "__builtin_bfin_mult_fr1x16", BFIN_BUILTIN_MULT_1X16
, MACFLAG_T
},
5325 { CODE_FOR_flag_mulhi
, "__builtin_bfin_multr_fr1x16", BFIN_BUILTIN_MULTR_1X16
, MACFLAG_NONE
},
5326 { CODE_FOR_flag_mulv2hi
, "__builtin_bfin_mult_fr2x16", BFIN_BUILTIN_MULT_2X16
, MACFLAG_T
},
5327 { CODE_FOR_flag_mulv2hi
, "__builtin_bfin_multr_fr2x16", BFIN_BUILTIN_MULTR_2X16
, MACFLAG_NONE
},
5329 { CODE_FOR_mulhisi_ll
, "__builtin_bfin_mulhisill", BFIN_BUILTIN_MULHISILL
, -1 },
5330 { CODE_FOR_mulhisi_lh
, "__builtin_bfin_mulhisilh", BFIN_BUILTIN_MULHISILH
, -1 },
5331 { CODE_FOR_mulhisi_hl
, "__builtin_bfin_mulhisihl", BFIN_BUILTIN_MULHISIHL
, -1 },
5332 { CODE_FOR_mulhisi_hh
, "__builtin_bfin_mulhisihh", BFIN_BUILTIN_MULHISIHH
, -1 }
5336 static const struct builtin_description bdesc_1arg
[] =
5338 { CODE_FOR_loadbytes
, "__builtin_bfin_loadbytes", BFIN_BUILTIN_LOADBYTES
, 0 },
5340 { CODE_FOR_ones
, "__builtin_bfin_ones", BFIN_BUILTIN_ONES
, 0 },
5342 { CODE_FOR_clrsbhi2
, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16
, 0 },
5343 { CODE_FOR_ssneghi2
, "__builtin_bfin_negate_fr1x16", BFIN_BUILTIN_NEG_1X16
, 0 },
5344 { CODE_FOR_abshi2
, "__builtin_bfin_abs_fr1x16", BFIN_BUILTIN_ABS_1X16
, 0 },
5346 { CODE_FOR_clrsbsi2
, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32
, 0 },
5347 { CODE_FOR_ssroundsi2
, "__builtin_bfin_round_fr1x32", BFIN_BUILTIN_ROUND_1X32
, 0 },
5348 { CODE_FOR_ssnegsi2
, "__builtin_bfin_negate_fr1x32", BFIN_BUILTIN_NEG_1X32
, 0 },
5349 { CODE_FOR_ssabssi2
, "__builtin_bfin_abs_fr1x32", BFIN_BUILTIN_ABS_1X32
, 0 },
5351 { CODE_FOR_movv2hi_hi_low
, "__builtin_bfin_extract_lo", BFIN_BUILTIN_EXTRACTLO
, 0 },
5352 { CODE_FOR_movv2hi_hi_high
, "__builtin_bfin_extract_hi", BFIN_BUILTIN_EXTRACTHI
, 0 },
5353 { CODE_FOR_ssnegv2hi2
, "__builtin_bfin_negate_fr2x16", BFIN_BUILTIN_NEG_2X16
, 0 },
5354 { CODE_FOR_ssabsv2hi2
, "__builtin_bfin_abs_fr2x16", BFIN_BUILTIN_ABS_2X16
, 0 }
5357 /* Errors in the source file can cause expand_expr to return const0_rtx
5358 where we expect a vector. To avoid crashing, use one of the vector
5359 clear instructions. */
5361 safe_vector_operand (rtx x
, machine_mode mode
)
5363 if (x
!= const0_rtx
)
5365 x
= gen_reg_rtx (SImode
);
5367 emit_insn (gen_movsi (x
, CONST0_RTX (SImode
)));
5368 return gen_lowpart (mode
, x
);
5371 /* Subroutine of bfin_expand_builtin to take care of binop insns. MACFLAG is -1
5372 if this is a normal binary op, or one of the MACFLAG_xxx constants. */
5375 bfin_expand_binop_builtin (enum insn_code icode
, tree exp
, rtx target
,
5379 tree arg0
= CALL_EXPR_ARG (exp
, 0);
5380 tree arg1
= CALL_EXPR_ARG (exp
, 1);
5381 rtx op0
= expand_normal (arg0
);
5382 rtx op1
= expand_normal (arg1
);
5383 machine_mode op0mode
= GET_MODE (op0
);
5384 machine_mode op1mode
= GET_MODE (op1
);
5385 machine_mode tmode
= insn_data
[icode
].operand
[0].mode
;
5386 machine_mode mode0
= insn_data
[icode
].operand
[1].mode
;
5387 machine_mode mode1
= insn_data
[icode
].operand
[2].mode
;
5389 if (VECTOR_MODE_P (mode0
))
5390 op0
= safe_vector_operand (op0
, mode0
);
5391 if (VECTOR_MODE_P (mode1
))
5392 op1
= safe_vector_operand (op1
, mode1
);
5395 || GET_MODE (target
) != tmode
5396 || ! (*insn_data
[icode
].operand
[0].predicate
) (target
, tmode
))
5397 target
= gen_reg_rtx (tmode
);
5399 if ((op0mode
== SImode
|| op0mode
== VOIDmode
) && mode0
== HImode
)
5402 op0
= gen_lowpart (HImode
, op0
);
5404 if ((op1mode
== SImode
|| op1mode
== VOIDmode
) && mode1
== HImode
)
5407 op1
= gen_lowpart (HImode
, op1
);
5409 /* In case the insn wants input operands in modes different from
5410 the result, abort. */
5411 gcc_assert ((op0mode
== mode0
|| op0mode
== VOIDmode
)
5412 && (op1mode
== mode1
|| op1mode
== VOIDmode
));
5414 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5415 op0
= copy_to_mode_reg (mode0
, op0
);
5416 if (! (*insn_data
[icode
].operand
[2].predicate
) (op1
, mode1
))
5417 op1
= copy_to_mode_reg (mode1
, op1
);
5420 pat
= GEN_FCN (icode
) (target
, op0
, op1
);
5422 pat
= GEN_FCN (icode
) (target
, op0
, op1
, GEN_INT (macflag
));
5430 /* Subroutine of bfin_expand_builtin to take care of unop insns. */
5433 bfin_expand_unop_builtin (enum insn_code icode
, tree exp
,
5437 tree arg0
= CALL_EXPR_ARG (exp
, 0);
5438 rtx op0
= expand_normal (arg0
);
5439 machine_mode op0mode
= GET_MODE (op0
);
5440 machine_mode tmode
= insn_data
[icode
].operand
[0].mode
;
5441 machine_mode mode0
= insn_data
[icode
].operand
[1].mode
;
5444 || GET_MODE (target
) != tmode
5445 || ! (*insn_data
[icode
].operand
[0].predicate
) (target
, tmode
))
5446 target
= gen_reg_rtx (tmode
);
5448 if (VECTOR_MODE_P (mode0
))
5449 op0
= safe_vector_operand (op0
, mode0
);
5451 if (op0mode
== SImode
&& mode0
== HImode
)
5454 op0
= gen_lowpart (HImode
, op0
);
5456 gcc_assert (op0mode
== mode0
|| op0mode
== VOIDmode
);
5458 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5459 op0
= copy_to_mode_reg (mode0
, op0
);
5461 pat
= GEN_FCN (icode
) (target
, op0
);
5468 /* Expand an expression EXP that calls a built-in function,
5469 with result going to TARGET if that's convenient
5470 (and in mode MODE if that's convenient).
5471 SUBTARGET may be used as the target for computing one of EXP's operands.
5472 IGNORE is nonzero if the value is to be ignored. */
5475 bfin_expand_builtin (tree exp
, rtx target ATTRIBUTE_UNUSED
,
5476 rtx subtarget ATTRIBUTE_UNUSED
,
5477 machine_mode mode ATTRIBUTE_UNUSED
,
5478 int ignore ATTRIBUTE_UNUSED
)
5481 enum insn_code icode
;
5482 const struct builtin_description
*d
;
5483 tree fndecl
= TREE_OPERAND (CALL_EXPR_FN (exp
), 0);
5484 unsigned int fcode
= DECL_FUNCTION_CODE (fndecl
);
5485 tree arg0
, arg1
, arg2
;
5486 rtx op0
, op1
, op2
, accvec
, pat
, tmp1
, tmp2
, a0reg
, a1reg
;
5487 machine_mode tmode
, mode0
;
5491 case BFIN_BUILTIN_CSYNC
:
5492 emit_insn (gen_csync ());
5494 case BFIN_BUILTIN_SSYNC
:
5495 emit_insn (gen_ssync ());
5498 case BFIN_BUILTIN_DIFFHL_2X16
:
5499 case BFIN_BUILTIN_DIFFLH_2X16
:
5500 case BFIN_BUILTIN_SUM_2X16
:
5501 arg0
= CALL_EXPR_ARG (exp
, 0);
5502 op0
= expand_normal (arg0
);
5503 icode
= (fcode
== BFIN_BUILTIN_DIFFHL_2X16
? CODE_FOR_subhilov2hi3
5504 : fcode
== BFIN_BUILTIN_DIFFLH_2X16
? CODE_FOR_sublohiv2hi3
5505 : CODE_FOR_ssaddhilov2hi3
);
5506 tmode
= insn_data
[icode
].operand
[0].mode
;
5507 mode0
= insn_data
[icode
].operand
[1].mode
;
5510 || GET_MODE (target
) != tmode
5511 || ! (*insn_data
[icode
].operand
[0].predicate
) (target
, tmode
))
5512 target
= gen_reg_rtx (tmode
);
5514 if (VECTOR_MODE_P (mode0
))
5515 op0
= safe_vector_operand (op0
, mode0
);
5517 if (! (*insn_data
[icode
].operand
[1].predicate
) (op0
, mode0
))
5518 op0
= copy_to_mode_reg (mode0
, op0
);
5520 pat
= GEN_FCN (icode
) (target
, op0
, op0
);
5526 case BFIN_BUILTIN_MULT_1X32X32
:
5527 case BFIN_BUILTIN_MULT_1X32X32NS
:
5528 arg0
= CALL_EXPR_ARG (exp
, 0);
5529 arg1
= CALL_EXPR_ARG (exp
, 1);
5530 op0
= expand_normal (arg0
);
5531 op1
= expand_normal (arg1
);
5533 || !register_operand (target
, SImode
))
5534 target
= gen_reg_rtx (SImode
);
5535 if (! register_operand (op0
, SImode
))
5536 op0
= copy_to_mode_reg (SImode
, op0
);
5537 if (! register_operand (op1
, SImode
))
5538 op1
= copy_to_mode_reg (SImode
, op1
);
5540 a1reg
= gen_rtx_REG (PDImode
, REG_A1
);
5541 a0reg
= gen_rtx_REG (PDImode
, REG_A0
);
5542 tmp1
= gen_lowpart (V2HImode
, op0
);
5543 tmp2
= gen_lowpart (V2HImode
, op1
);
5544 emit_insn (gen_flag_macinit1hi (a1reg
,
5545 gen_lowpart (HImode
, op0
),
5546 gen_lowpart (HImode
, op1
),
5547 GEN_INT (MACFLAG_FU
)));
5548 emit_insn (gen_lshrpdi3 (a1reg
, a1reg
, GEN_INT (16)));
5550 if (fcode
== BFIN_BUILTIN_MULT_1X32X32
)
5551 emit_insn (gen_flag_mul_macv2hi_parts_acconly (a0reg
, a1reg
, tmp1
, tmp2
,
5552 const1_rtx
, const1_rtx
,
5553 const1_rtx
, const0_rtx
, a1reg
,
5554 const0_rtx
, GEN_INT (MACFLAG_NONE
),
5555 GEN_INT (MACFLAG_M
)));
5558 /* For saturating multiplication, there's exactly one special case
5559 to be handled: multiplying the smallest negative value with
5560 itself. Due to shift correction in fractional multiplies, this
5561 can overflow. Iff this happens, OP2 will contain 1, which, when
5562 added in 32 bits to the smallest negative, wraps to the largest
5563 positive, which is the result we want. */
5564 op2
= gen_reg_rtx (V2HImode
);
5565 emit_insn (gen_packv2hi (op2
, tmp1
, tmp2
, const0_rtx
, const0_rtx
));
5566 emit_insn (gen_movsibi (gen_rtx_REG (BImode
, REG_CC
),
5567 gen_lowpart (SImode
, op2
)));
5568 emit_insn (gen_flag_mul_macv2hi_parts_acconly_andcc0 (a0reg
, a1reg
, tmp1
, tmp2
,
5569 const1_rtx
, const1_rtx
,
5570 const1_rtx
, const0_rtx
, a1reg
,
5571 const0_rtx
, GEN_INT (MACFLAG_NONE
),
5572 GEN_INT (MACFLAG_M
)));
5573 op2
= gen_reg_rtx (SImode
);
5574 emit_insn (gen_movbisi (op2
, gen_rtx_REG (BImode
, REG_CC
)));
5576 emit_insn (gen_flag_machi_parts_acconly (a1reg
, tmp2
, tmp1
,
5577 const1_rtx
, const0_rtx
,
5578 a1reg
, const0_rtx
, GEN_INT (MACFLAG_M
)));
5579 emit_insn (gen_ashrpdi3 (a1reg
, a1reg
, GEN_INT (15)));
5580 emit_insn (gen_sum_of_accumulators (target
, a0reg
, a0reg
, a1reg
));
5581 if (fcode
== BFIN_BUILTIN_MULT_1X32X32NS
)
5582 emit_insn (gen_addsi3 (target
, target
, op2
));
5585 case BFIN_BUILTIN_CPLX_MUL_16
:
5586 case BFIN_BUILTIN_CPLX_MUL_16_S40
:
5587 arg0
= CALL_EXPR_ARG (exp
, 0);
5588 arg1
= CALL_EXPR_ARG (exp
, 1);
5589 op0
= expand_normal (arg0
);
5590 op1
= expand_normal (arg1
);
5591 accvec
= gen_reg_rtx (V2PDImode
);
5592 icode
= CODE_FOR_flag_macv2hi_parts
;
5593 tmode
= insn_data
[icode
].operand
[0].mode
;
5596 || GET_MODE (target
) != V2HImode
5597 || ! (*insn_data
[icode
].operand
[0].predicate
) (target
, V2HImode
))
5598 target
= gen_reg_rtx (tmode
);
5599 if (! register_operand (op0
, GET_MODE (op0
)))
5600 op0
= copy_to_mode_reg (GET_MODE (op0
), op0
);
5601 if (! register_operand (op1
, GET_MODE (op1
)))
5602 op1
= copy_to_mode_reg (GET_MODE (op1
), op1
);
5604 if (fcode
== BFIN_BUILTIN_CPLX_MUL_16
)
5605 emit_insn (gen_flag_macinit1v2hi_parts (accvec
, op0
, op1
, const0_rtx
,
5606 const0_rtx
, const0_rtx
,
5607 const1_rtx
, GEN_INT (MACFLAG_W32
)));
5609 emit_insn (gen_flag_macinit1v2hi_parts (accvec
, op0
, op1
, const0_rtx
,
5610 const0_rtx
, const0_rtx
,
5611 const1_rtx
, GEN_INT (MACFLAG_NONE
)));
5612 emit_insn (gen_flag_macv2hi_parts (target
, op0
, op1
, const1_rtx
,
5613 const1_rtx
, const1_rtx
,
5614 const0_rtx
, accvec
, const1_rtx
, const0_rtx
,
5615 GEN_INT (MACFLAG_NONE
), accvec
));
5619 case BFIN_BUILTIN_CPLX_MAC_16
:
5620 case BFIN_BUILTIN_CPLX_MSU_16
:
5621 case BFIN_BUILTIN_CPLX_MAC_16_S40
:
5622 case BFIN_BUILTIN_CPLX_MSU_16_S40
:
5623 arg0
= CALL_EXPR_ARG (exp
, 0);
5624 arg1
= CALL_EXPR_ARG (exp
, 1);
5625 arg2
= CALL_EXPR_ARG (exp
, 2);
5626 op0
= expand_normal (arg0
);
5627 op1
= expand_normal (arg1
);
5628 op2
= expand_normal (arg2
);
5629 accvec
= gen_reg_rtx (V2PDImode
);
5630 icode
= CODE_FOR_flag_macv2hi_parts
;
5631 tmode
= insn_data
[icode
].operand
[0].mode
;
5634 || GET_MODE (target
) != V2HImode
5635 || ! (*insn_data
[icode
].operand
[0].predicate
) (target
, V2HImode
))
5636 target
= gen_reg_rtx (tmode
);
5637 if (! register_operand (op1
, GET_MODE (op1
)))
5638 op1
= copy_to_mode_reg (GET_MODE (op1
), op1
);
5639 if (! register_operand (op2
, GET_MODE (op2
)))
5640 op2
= copy_to_mode_reg (GET_MODE (op2
), op2
);
5642 tmp1
= gen_reg_rtx (SImode
);
5643 tmp2
= gen_reg_rtx (SImode
);
5644 emit_insn (gen_ashlsi3 (tmp1
, gen_lowpart (SImode
, op0
), GEN_INT (16)));
5645 emit_move_insn (tmp2
, gen_lowpart (SImode
, op0
));
5646 emit_insn (gen_movstricthi_1 (gen_lowpart (HImode
, tmp2
), const0_rtx
));
5647 emit_insn (gen_load_accumulator_pair (accvec
, tmp1
, tmp2
));
5648 if (fcode
== BFIN_BUILTIN_CPLX_MAC_16
5649 || fcode
== BFIN_BUILTIN_CPLX_MSU_16
)
5650 emit_insn (gen_flag_macv2hi_parts_acconly (accvec
, op1
, op2
, const0_rtx
,
5651 const0_rtx
, const0_rtx
,
5652 const1_rtx
, accvec
, const0_rtx
,
5654 GEN_INT (MACFLAG_W32
)));
5656 emit_insn (gen_flag_macv2hi_parts_acconly (accvec
, op1
, op2
, const0_rtx
,
5657 const0_rtx
, const0_rtx
,
5658 const1_rtx
, accvec
, const0_rtx
,
5660 GEN_INT (MACFLAG_NONE
)));
5661 if (fcode
== BFIN_BUILTIN_CPLX_MAC_16
5662 || fcode
== BFIN_BUILTIN_CPLX_MAC_16_S40
)
5672 emit_insn (gen_flag_macv2hi_parts (target
, op1
, op2
, const1_rtx
,
5673 const1_rtx
, const1_rtx
,
5674 const0_rtx
, accvec
, tmp1
, tmp2
,
5675 GEN_INT (MACFLAG_NONE
), accvec
));
5679 case BFIN_BUILTIN_CPLX_SQU
:
5680 arg0
= CALL_EXPR_ARG (exp
, 0);
5681 op0
= expand_normal (arg0
);
5682 accvec
= gen_reg_rtx (V2PDImode
);
5683 icode
= CODE_FOR_flag_mulv2hi
;
5684 tmp1
= gen_reg_rtx (V2HImode
);
5685 tmp2
= gen_reg_rtx (V2HImode
);
5688 || GET_MODE (target
) != V2HImode
5689 || ! (*insn_data
[icode
].operand
[0].predicate
) (target
, V2HImode
))
5690 target
= gen_reg_rtx (V2HImode
);
5691 if (! register_operand (op0
, GET_MODE (op0
)))
5692 op0
= copy_to_mode_reg (GET_MODE (op0
), op0
);
5694 emit_insn (gen_flag_mulv2hi (tmp1
, op0
, op0
, GEN_INT (MACFLAG_NONE
)));
5696 emit_insn (gen_flag_mulhi_parts (gen_lowpart (HImode
, tmp2
), op0
, op0
,
5697 const0_rtx
, const1_rtx
,
5698 GEN_INT (MACFLAG_NONE
)));
5700 emit_insn (gen_ssaddhi3_high_parts (target
, tmp2
, tmp2
, tmp2
, const0_rtx
,
5702 emit_insn (gen_sssubhi3_low_parts (target
, target
, tmp1
, tmp1
,
5703 const0_rtx
, const1_rtx
));
5711 for (i
= 0, d
= bdesc_2arg
; i
< ARRAY_SIZE (bdesc_2arg
); i
++, d
++)
5712 if (d
->code
== fcode
)
5713 return bfin_expand_binop_builtin (d
->icode
, exp
, target
,
5716 for (i
= 0, d
= bdesc_1arg
; i
< ARRAY_SIZE (bdesc_1arg
); i
++, d
++)
5717 if (d
->code
== fcode
)
5718 return bfin_expand_unop_builtin (d
->icode
, exp
, target
);
5724 bfin_conditional_register_usage (void)
5726 /* initialize condition code flag register rtx */
5727 bfin_cc_rtx
= gen_rtx_REG (BImode
, REG_CC
);
5728 bfin_rets_rtx
= gen_rtx_REG (Pmode
, REG_RETS
);
5730 call_used_regs
[FDPIC_REGNO
] = 1;
5731 if (!TARGET_FDPIC
&& flag_pic
)
5733 fixed_regs
[PIC_OFFSET_TABLE_REGNUM
] = 1;
5734 call_used_regs
[PIC_OFFSET_TABLE_REGNUM
] = 1;
5738 #undef TARGET_INIT_BUILTINS
5739 #define TARGET_INIT_BUILTINS bfin_init_builtins
5741 #undef TARGET_EXPAND_BUILTIN
5742 #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
5744 #undef TARGET_ASM_GLOBALIZE_LABEL
5745 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label
5747 #undef TARGET_ASM_FILE_START
5748 #define TARGET_ASM_FILE_START output_file_start
5750 #undef TARGET_ATTRIBUTE_TABLE
5751 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
5753 #undef TARGET_COMP_TYPE_ATTRIBUTES
5754 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
5756 #undef TARGET_RTX_COSTS
5757 #define TARGET_RTX_COSTS bfin_rtx_costs
5759 #undef TARGET_ADDRESS_COST
5760 #define TARGET_ADDRESS_COST bfin_address_cost
5762 #undef TARGET_REGISTER_MOVE_COST
5763 #define TARGET_REGISTER_MOVE_COST bfin_register_move_cost
5765 #undef TARGET_MEMORY_MOVE_COST
5766 #define TARGET_MEMORY_MOVE_COST bfin_memory_move_cost
5768 #undef TARGET_ASM_INTEGER
5769 #define TARGET_ASM_INTEGER bfin_assemble_integer
5771 #undef TARGET_MACHINE_DEPENDENT_REORG
5772 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
5774 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
5775 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
5777 #undef TARGET_ASM_OUTPUT_MI_THUNK
5778 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
5779 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
5780 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
5782 #undef TARGET_SCHED_ADJUST_COST
5783 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
5785 #undef TARGET_SCHED_ISSUE_RATE
5786 #define TARGET_SCHED_ISSUE_RATE bfin_issue_rate
5788 #undef TARGET_PROMOTE_FUNCTION_MODE
5789 #define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
5791 #undef TARGET_ARG_PARTIAL_BYTES
5792 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
5794 #undef TARGET_FUNCTION_ARG
5795 #define TARGET_FUNCTION_ARG bfin_function_arg
5797 #undef TARGET_FUNCTION_ARG_ADVANCE
5798 #define TARGET_FUNCTION_ARG_ADVANCE bfin_function_arg_advance
5800 #undef TARGET_PASS_BY_REFERENCE
5801 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
5803 #undef TARGET_SETUP_INCOMING_VARARGS
5804 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
5806 #undef TARGET_STRUCT_VALUE_RTX
5807 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
5809 #undef TARGET_VECTOR_MODE_SUPPORTED_P
5810 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
5812 #undef TARGET_OPTION_OVERRIDE
5813 #define TARGET_OPTION_OVERRIDE bfin_option_override
5815 #undef TARGET_SECONDARY_RELOAD
5816 #define TARGET_SECONDARY_RELOAD bfin_secondary_reload
5818 #undef TARGET_CLASS_LIKELY_SPILLED_P
5819 #define TARGET_CLASS_LIKELY_SPILLED_P bfin_class_likely_spilled_p
5821 #undef TARGET_DELEGITIMIZE_ADDRESS
5822 #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address
5824 #undef TARGET_LEGITIMATE_CONSTANT_P
5825 #define TARGET_LEGITIMATE_CONSTANT_P bfin_legitimate_constant_p
5827 #undef TARGET_CANNOT_FORCE_CONST_MEM
5828 #define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem
5830 #undef TARGET_RETURN_IN_MEMORY
5831 #define TARGET_RETURN_IN_MEMORY bfin_return_in_memory
5833 #undef TARGET_LEGITIMATE_ADDRESS_P
5834 #define TARGET_LEGITIMATE_ADDRESS_P bfin_legitimate_address_p
5836 #undef TARGET_FRAME_POINTER_REQUIRED
5837 #define TARGET_FRAME_POINTER_REQUIRED bfin_frame_pointer_required
5839 #undef TARGET_CAN_ELIMINATE
5840 #define TARGET_CAN_ELIMINATE bfin_can_eliminate
5842 #undef TARGET_CONDITIONAL_REGISTER_USAGE
5843 #define TARGET_CONDITIONAL_REGISTER_USAGE bfin_conditional_register_usage
5845 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
5846 #define TARGET_ASM_TRAMPOLINE_TEMPLATE bfin_asm_trampoline_template
5847 #undef TARGET_TRAMPOLINE_INIT
5848 #define TARGET_TRAMPOLINE_INIT bfin_trampoline_init
5850 #undef TARGET_EXTRA_LIVE_ON_ENTRY
5851 #define TARGET_EXTRA_LIVE_ON_ENTRY bfin_extra_live_on_entry
5853 /* Passes after sched2 can break the helpful TImode annotations that
5854 haifa-sched puts on every insn. Just do scheduling in reorg. */
5855 #undef TARGET_DELAY_SCHED2
5856 #define TARGET_DELAY_SCHED2 true
5858 /* Variable tracking should be run after all optimizations which
5859 change order of insns. It also needs a valid CFG. */
5860 #undef TARGET_DELAY_VARTRACK
5861 #define TARGET_DELAY_VARTRACK true
5863 #undef TARGET_CAN_USE_DOLOOP_P
5864 #define TARGET_CAN_USE_DOLOOP_P bfin_can_use_doloop_p
5866 struct gcc_target targetm
= TARGET_INITIALIZER
;