Home | History | Annotate | Line # | Download | only in bfin
bfin.cc revision 1.1.1.1
      1  1.1  mrg /* The Blackfin code generation auxiliary output file.
      2  1.1  mrg    Copyright (C) 2005-2022 Free Software Foundation, Inc.
      3  1.1  mrg    Contributed by Analog Devices.
      4  1.1  mrg 
      5  1.1  mrg    This file is part of GCC.
      6  1.1  mrg 
      7  1.1  mrg    GCC is free software; you can redistribute it and/or modify it
      8  1.1  mrg    under the terms of the GNU General Public License as published
      9  1.1  mrg    by the Free Software Foundation; either version 3, or (at your
     10  1.1  mrg    option) any later version.
     11  1.1  mrg 
     12  1.1  mrg    GCC is distributed in the hope that it will be useful, but WITHOUT
     13  1.1  mrg    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     14  1.1  mrg    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
     15  1.1  mrg    License for more details.
     16  1.1  mrg 
     17  1.1  mrg    You should have received a copy of the GNU General Public License
     18  1.1  mrg    along with GCC; see the file COPYING3.  If not see
     19  1.1  mrg    <http://www.gnu.org/licenses/>.  */
     20  1.1  mrg 
     21  1.1  mrg #define IN_TARGET_CODE 1
     22  1.1  mrg 
     23  1.1  mrg #include "config.h"
     24  1.1  mrg #include "system.h"
     25  1.1  mrg #include "coretypes.h"
     26  1.1  mrg #include "backend.h"
     27  1.1  mrg #include "target.h"
     28  1.1  mrg #include "rtl.h"
     29  1.1  mrg #include "tree.h"
     30  1.1  mrg #include "stringpool.h"
     31  1.1  mrg #include "attribs.h"
     32  1.1  mrg #include "cfghooks.h"
     33  1.1  mrg #include "df.h"
     34  1.1  mrg #include "memmodel.h"
     35  1.1  mrg #include "tm_p.h"
     36  1.1  mrg #include "optabs.h"
     37  1.1  mrg #include "regs.h"
     38  1.1  mrg #include "emit-rtl.h"
     39  1.1  mrg #include "recog.h"
     40  1.1  mrg #include "cgraph.h"
     41  1.1  mrg #include "diagnostic-core.h"
     42  1.1  mrg #include "output.h"
     43  1.1  mrg #include "insn-attr.h"
     44  1.1  mrg #include "varasm.h"
     45  1.1  mrg #include "calls.h"
     46  1.1  mrg #include "explow.h"
     47  1.1  mrg #include "expr.h"
     48  1.1  mrg #include "cfgrtl.h"
     49  1.1  mrg #include "langhooks.h"
     50  1.1  mrg #include "tm-constrs.h"
     51  1.1  mrg #include "gt-bfin.h"
     52  1.1  mrg #include "sel-sched.h"
     53  1.1  mrg #include "hw-doloop.h"
     54  1.1  mrg #include "dumpfile.h"
     55  1.1  mrg #include "builtins.h"
     56  1.1  mrg #include "opts.h"
     57  1.1  mrg 
     58  1.1  mrg /* This file should be included last.  */
     59  1.1  mrg #include "target-def.h"
     60  1.1  mrg 
     61  1.1  mrg /* A C structure for machine-specific, per-function data.
     62  1.1  mrg    This is added to the cfun structure.  */
     63  1.1  mrg struct GTY(()) machine_function
     64  1.1  mrg {
     65  1.1  mrg   /* Set if we are notified by the doloop pass that a hardware loop
     66  1.1  mrg      was created.  */
     67  1.1  mrg   int has_hardware_loops;
     68  1.1  mrg 
     69  1.1  mrg   /* Set if we create a memcpy pattern that uses loop registers.  */
     70  1.1  mrg   int has_loopreg_clobber;
     71  1.1  mrg };
     72  1.1  mrg 
     73  1.1  mrg /* RTX for condition code flag register and RETS register */
     74  1.1  mrg extern GTY(()) rtx bfin_cc_rtx;
     75  1.1  mrg extern GTY(()) rtx bfin_rets_rtx;
     76  1.1  mrg rtx bfin_cc_rtx, bfin_rets_rtx;
     77  1.1  mrg 
     78  1.1  mrg int max_arg_registers = 0;
     79  1.1  mrg 
     80  1.1  mrg /* Arrays used when emitting register names.  */
     81  1.1  mrg const char *short_reg_names[]  =  SHORT_REGISTER_NAMES;
     82  1.1  mrg const char *high_reg_names[]   =  HIGH_REGISTER_NAMES;
     83  1.1  mrg const char *dregs_pair_names[] =  DREGS_PAIR_NAMES;
     84  1.1  mrg const char *byte_reg_names[]   =  BYTE_REGISTER_NAMES;
     85  1.1  mrg 
     86  1.1  mrg static int arg_regs[] = FUNCTION_ARG_REGISTERS;
     87  1.1  mrg static int ret_regs[] = FUNCTION_RETURN_REGISTERS;
     88  1.1  mrg 
     89  1.1  mrg int splitting_for_sched, splitting_loops;
     90  1.1  mrg 
     91  1.1  mrg static void
     92  1.1  mrg bfin_globalize_label (FILE *stream, const char *name)
     93  1.1  mrg {
     94  1.1  mrg   fputs (".global ", stream);
     95  1.1  mrg   assemble_name (stream, name);
     96  1.1  mrg   fputc (';',stream);
     97  1.1  mrg   fputc ('\n',stream);
     98  1.1  mrg }
     99  1.1  mrg 
    100  1.1  mrg static void
    101  1.1  mrg output_file_start (void)
    102  1.1  mrg {
    103  1.1  mrg   FILE *file = asm_out_file;
    104  1.1  mrg   int i;
    105  1.1  mrg 
    106  1.1  mrg   fprintf (file, ".file \"%s\";\n", LOCATION_FILE (input_location));
    107  1.1  mrg 
    108  1.1  mrg   for (i = 0; arg_regs[i] >= 0; i++)
    109  1.1  mrg     ;
    110  1.1  mrg   max_arg_registers = i;	/* how many arg reg used  */
    111  1.1  mrg }
    112  1.1  mrg 
    113  1.1  mrg /* Examine machine-dependent attributes of function type FUNTYPE and return its
    114  1.1  mrg    type.  See the definition of E_FUNKIND.  */
    115  1.1  mrg 
    116  1.1  mrg static e_funkind
    117  1.1  mrg funkind (const_tree funtype)
    118  1.1  mrg {
    119  1.1  mrg   tree attrs = TYPE_ATTRIBUTES (funtype);
    120  1.1  mrg   if (lookup_attribute ("interrupt_handler", attrs))
    121  1.1  mrg     return INTERRUPT_HANDLER;
    122  1.1  mrg   else if (lookup_attribute ("exception_handler", attrs))
    123  1.1  mrg     return EXCPT_HANDLER;
    124  1.1  mrg   else if (lookup_attribute ("nmi_handler", attrs))
    125  1.1  mrg     return NMI_HANDLER;
    126  1.1  mrg   else
    127  1.1  mrg     return SUBROUTINE;
    128  1.1  mrg }
    129  1.1  mrg 
    130  1.1  mrg /* Legitimize PIC addresses.  If the address is already position-independent,
    132  1.1  mrg    we return ORIG.  Newly generated position-independent addresses go into a
    133  1.1  mrg    reg.  This is REG if nonzero, otherwise we allocate register(s) as
    134  1.1  mrg    necessary.  PICREG is the register holding the pointer to the PIC offset
    135  1.1  mrg    table.  */
    136  1.1  mrg 
    137  1.1  mrg static rtx
    138  1.1  mrg legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
    139  1.1  mrg {
    140  1.1  mrg   rtx addr = orig;
    141  1.1  mrg   rtx new_rtx = orig;
    142  1.1  mrg 
    143  1.1  mrg   if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
    144  1.1  mrg     {
    145  1.1  mrg       int unspec;
    146  1.1  mrg       rtx tmp;
    147  1.1  mrg 
    148  1.1  mrg       if (TARGET_ID_SHARED_LIBRARY)
    149  1.1  mrg 	unspec = UNSPEC_MOVE_PIC;
    150  1.1  mrg       else if (GET_CODE (addr) == SYMBOL_REF
    151  1.1  mrg 	       && SYMBOL_REF_FUNCTION_P (addr))
    152  1.1  mrg 	unspec = UNSPEC_FUNCDESC_GOT17M4;
    153  1.1  mrg       else
    154  1.1  mrg 	unspec = UNSPEC_MOVE_FDPIC;
    155  1.1  mrg 
    156  1.1  mrg       if (reg == 0)
    157  1.1  mrg 	{
    158  1.1  mrg 	  gcc_assert (can_create_pseudo_p ());
    159  1.1  mrg 	  reg = gen_reg_rtx (Pmode);
    160  1.1  mrg 	}
    161  1.1  mrg 
    162  1.1  mrg       tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), unspec);
    163  1.1  mrg       new_rtx = gen_const_mem (Pmode, gen_rtx_PLUS (Pmode, picreg, tmp));
    164  1.1  mrg 
    165  1.1  mrg       emit_move_insn (reg, new_rtx);
    166  1.1  mrg       if (picreg == pic_offset_table_rtx)
    167  1.1  mrg 	crtl->uses_pic_offset_table = 1;
    168  1.1  mrg       return reg;
    169  1.1  mrg     }
    170  1.1  mrg 
    171  1.1  mrg   else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
    172  1.1  mrg     {
    173  1.1  mrg       rtx base;
    174  1.1  mrg 
    175  1.1  mrg       if (GET_CODE (addr) == CONST)
    176  1.1  mrg 	{
    177  1.1  mrg 	  addr = XEXP (addr, 0);
    178  1.1  mrg 	  gcc_assert (GET_CODE (addr) == PLUS);
    179  1.1  mrg 	}
    180  1.1  mrg 
    181  1.1  mrg       if (XEXP (addr, 0) == picreg)
    182  1.1  mrg 	return orig;
    183  1.1  mrg 
    184  1.1  mrg       if (reg == 0)
    185  1.1  mrg 	{
    186  1.1  mrg 	  gcc_assert (can_create_pseudo_p ());
    187  1.1  mrg 	  reg = gen_reg_rtx (Pmode);
    188  1.1  mrg 	}
    189  1.1  mrg 
    190  1.1  mrg       base = legitimize_pic_address (XEXP (addr, 0), reg, picreg);
    191  1.1  mrg       addr = legitimize_pic_address (XEXP (addr, 1),
    192  1.1  mrg 				     base == reg ? NULL_RTX : reg,
    193  1.1  mrg 				     picreg);
    194  1.1  mrg 
    195  1.1  mrg       if (GET_CODE (addr) == CONST_INT)
    196  1.1  mrg 	{
    197  1.1  mrg 	  gcc_assert (! reload_in_progress && ! reload_completed);
    198  1.1  mrg 	  addr = force_reg (Pmode, addr);
    199  1.1  mrg 	}
    200  1.1  mrg 
    201  1.1  mrg       if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
    202  1.1  mrg 	{
    203  1.1  mrg 	  base = gen_rtx_PLUS (Pmode, base, XEXP (addr, 0));
    204  1.1  mrg 	  addr = XEXP (addr, 1);
    205  1.1  mrg 	}
    206  1.1  mrg 
    207  1.1  mrg       return gen_rtx_PLUS (Pmode, base, addr);
    208  1.1  mrg     }
    209  1.1  mrg 
    210  1.1  mrg   return new_rtx;
    211  1.1  mrg }
    212  1.1  mrg 
    213  1.1  mrg /* Stack frame layout. */
    215  1.1  mrg 
    216  1.1  mrg /* For a given REGNO, determine whether it must be saved in the function
    217  1.1  mrg    prologue.  IS_INTHANDLER specifies whether we're generating a normal
    218  1.1  mrg    prologue or an interrupt/exception one.  */
    219  1.1  mrg static bool
    220  1.1  mrg must_save_p (bool is_inthandler, unsigned regno)
    221  1.1  mrg {
    222  1.1  mrg   if (D_REGNO_P (regno))
    223  1.1  mrg     {
    224  1.1  mrg       bool is_eh_return_reg = false;
    225  1.1  mrg       if (crtl->calls_eh_return)
    226  1.1  mrg 	{
    227  1.1  mrg 	  unsigned j;
    228  1.1  mrg 	  for (j = 0; ; j++)
    229  1.1  mrg 	    {
    230  1.1  mrg 	      unsigned test = EH_RETURN_DATA_REGNO (j);
    231  1.1  mrg 	      if (test == INVALID_REGNUM)
    232  1.1  mrg 		break;
    233  1.1  mrg 	      if (test == regno)
    234  1.1  mrg 		is_eh_return_reg = true;
    235  1.1  mrg 	    }
    236  1.1  mrg 	}
    237  1.1  mrg 
    238  1.1  mrg       return (is_eh_return_reg
    239  1.1  mrg 	      || (df_regs_ever_live_p (regno)
    240  1.1  mrg 		  && !fixed_regs[regno]
    241  1.1  mrg 		  && (is_inthandler || !call_used_or_fixed_reg_p (regno))));
    242  1.1  mrg     }
    243  1.1  mrg   else if (P_REGNO_P (regno))
    244  1.1  mrg     {
    245  1.1  mrg       return ((df_regs_ever_live_p (regno)
    246  1.1  mrg 	       && !fixed_regs[regno]
    247  1.1  mrg 	       && (is_inthandler || !call_used_or_fixed_reg_p (regno)))
    248  1.1  mrg 	      || (is_inthandler
    249  1.1  mrg 		  && (ENABLE_WA_05000283 || ENABLE_WA_05000315)
    250  1.1  mrg 		  && regno == REG_P5)
    251  1.1  mrg 	      || (!TARGET_FDPIC
    252  1.1  mrg 		  && regno == PIC_OFFSET_TABLE_REGNUM
    253  1.1  mrg 		  && (crtl->uses_pic_offset_table
    254  1.1  mrg 		      || (TARGET_ID_SHARED_LIBRARY && !crtl->is_leaf))));
    255  1.1  mrg     }
    256  1.1  mrg   else
    257  1.1  mrg     return ((is_inthandler || !call_used_or_fixed_reg_p (regno))
    258  1.1  mrg 	    && (df_regs_ever_live_p (regno)
    259  1.1  mrg 		|| (!leaf_function_p () && call_used_or_fixed_reg_p (regno))));
    260  1.1  mrg 
    261  1.1  mrg }
    262  1.1  mrg 
    263  1.1  mrg /* Compute the number of DREGS to save with a push_multiple operation.
    264  1.1  mrg    This could include registers that aren't modified in the function,
    265  1.1  mrg    since push_multiple only takes a range of registers.
    266  1.1  mrg    If IS_INTHANDLER, then everything that is live must be saved, even
    267  1.1  mrg    if normally call-clobbered.
    268  1.1  mrg    If CONSECUTIVE, return the number of registers we can save in one
    269  1.1  mrg    instruction with a push/pop multiple instruction.  */
    270  1.1  mrg 
    271  1.1  mrg static int
    272  1.1  mrg n_dregs_to_save (bool is_inthandler, bool consecutive)
    273  1.1  mrg {
    274  1.1  mrg   int count = 0;
    275  1.1  mrg   unsigned i;
    276  1.1  mrg 
    277  1.1  mrg   for (i = REG_R7 + 1; i-- != REG_R0;)
    278  1.1  mrg     {
    279  1.1  mrg       if (must_save_p (is_inthandler, i))
    280  1.1  mrg 	count++;
    281  1.1  mrg       else if (consecutive)
    282  1.1  mrg 	return count;
    283  1.1  mrg     }
    284  1.1  mrg   return count;
    285  1.1  mrg }
    286  1.1  mrg 
    287  1.1  mrg /* Like n_dregs_to_save, but compute number of PREGS to save.  */
    288  1.1  mrg 
    289  1.1  mrg static int
    290  1.1  mrg n_pregs_to_save (bool is_inthandler, bool consecutive)
    291  1.1  mrg {
    292  1.1  mrg   int count = 0;
    293  1.1  mrg   unsigned i;
    294  1.1  mrg 
    295  1.1  mrg   for (i = REG_P5 + 1; i-- != REG_P0;)
    296  1.1  mrg     if (must_save_p (is_inthandler, i))
    297  1.1  mrg       count++;
    298  1.1  mrg     else if (consecutive)
    299  1.1  mrg       return count;
    300  1.1  mrg   return count;
    301  1.1  mrg }
    302  1.1  mrg 
    303  1.1  mrg /* Determine if we are going to save the frame pointer in the prologue.  */
    304  1.1  mrg 
    305  1.1  mrg static bool
    306  1.1  mrg must_save_fp_p (void)
    307  1.1  mrg {
    308  1.1  mrg   return df_regs_ever_live_p (REG_FP);
    309  1.1  mrg }
    310  1.1  mrg 
    311  1.1  mrg /* Determine if we are going to save the RETS register.  */
    312  1.1  mrg static bool
    313  1.1  mrg must_save_rets_p (void)
    314  1.1  mrg {
    315  1.1  mrg   return df_regs_ever_live_p (REG_RETS);
    316  1.1  mrg }
    317  1.1  mrg 
    318  1.1  mrg static bool
    319  1.1  mrg stack_frame_needed_p (void)
    320  1.1  mrg {
    321  1.1  mrg   /* EH return puts a new return address into the frame using an
    322  1.1  mrg      address relative to the frame pointer.  */
    323  1.1  mrg   if (crtl->calls_eh_return)
    324  1.1  mrg     return true;
    325  1.1  mrg   return frame_pointer_needed;
    326  1.1  mrg }
    327  1.1  mrg 
    328  1.1  mrg /* Emit code to save registers in the prologue.  SAVEALL is nonzero if we
    329  1.1  mrg    must save all registers; this is used for interrupt handlers.
    330  1.1  mrg    SPREG contains (reg:SI REG_SP).  IS_INTHANDLER is true if we're doing
    331  1.1  mrg    this for an interrupt (or exception) handler.  */
    332  1.1  mrg 
    333  1.1  mrg static void
    334  1.1  mrg expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler)
    335  1.1  mrg {
    336  1.1  mrg   rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
    337  1.1  mrg   rtx predec = gen_rtx_MEM (SImode, predec1);
    338  1.1  mrg   int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler, false);
    339  1.1  mrg   int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler, false);
    340  1.1  mrg   int ndregs_consec = saveall ? 8 : n_dregs_to_save (is_inthandler, true);
    341  1.1  mrg   int npregs_consec = saveall ? 6 : n_pregs_to_save (is_inthandler, true);
    342  1.1  mrg   int dregno, pregno;
    343  1.1  mrg   int total_consec = ndregs_consec + npregs_consec;
    344  1.1  mrg   int i, d_to_save;
    345  1.1  mrg 
    346  1.1  mrg   if (saveall || is_inthandler)
    347  1.1  mrg     {
    348  1.1  mrg       rtx_insn *insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
    349  1.1  mrg 
    350  1.1  mrg       RTX_FRAME_RELATED_P (insn) = 1;
    351  1.1  mrg       for (dregno = REG_LT0; dregno <= REG_LB1; dregno++)
    352  1.1  mrg 	if (! crtl->is_leaf
    353  1.1  mrg 	    || cfun->machine->has_hardware_loops
    354  1.1  mrg 	    || cfun->machine->has_loopreg_clobber
    355  1.1  mrg 	    || (ENABLE_WA_05000257
    356  1.1  mrg 		&& (dregno == REG_LC0 || dregno == REG_LC1)))
    357  1.1  mrg 	  {
    358  1.1  mrg 	    insn = emit_move_insn (predec, gen_rtx_REG (SImode, dregno));
    359  1.1  mrg 	    RTX_FRAME_RELATED_P (insn) = 1;
    360  1.1  mrg 	  }
    361  1.1  mrg     }
    362  1.1  mrg 
    363  1.1  mrg   if (total_consec != 0)
    364  1.1  mrg     {
    365  1.1  mrg       rtx_insn *insn;
    366  1.1  mrg       rtx val = GEN_INT (-total_consec * 4);
    367  1.1  mrg       rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_consec + 2));
    368  1.1  mrg 
    369  1.1  mrg       XVECEXP (pat, 0, 0) = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, val),
    370  1.1  mrg 					    UNSPEC_PUSH_MULTIPLE);
    371  1.1  mrg       XVECEXP (pat, 0, total_consec + 1) = gen_rtx_SET (spreg,
    372  1.1  mrg 							gen_rtx_PLUS (Pmode,
    373  1.1  mrg 								      spreg,
    374  1.1  mrg 								      val));
    375  1.1  mrg       RTX_FRAME_RELATED_P (XVECEXP (pat, 0, total_consec + 1)) = 1;
    376  1.1  mrg       d_to_save = ndregs_consec;
    377  1.1  mrg       dregno = REG_R7 + 1 - ndregs_consec;
    378  1.1  mrg       pregno = REG_P5 + 1 - npregs_consec;
    379  1.1  mrg       for (i = 0; i < total_consec; i++)
    380  1.1  mrg 	{
    381  1.1  mrg 	  rtx memref = gen_rtx_MEM (word_mode,
    382  1.1  mrg 				    gen_rtx_PLUS (Pmode, spreg,
    383  1.1  mrg 						  GEN_INT (- i * 4 - 4)));
    384  1.1  mrg 	  rtx subpat;
    385  1.1  mrg 	  if (d_to_save > 0)
    386  1.1  mrg 	    {
    387  1.1  mrg 	      subpat = gen_rtx_SET (memref, gen_rtx_REG (word_mode, dregno++));
    388  1.1  mrg 	      d_to_save--;
    389  1.1  mrg 	    }
    390  1.1  mrg 	  else
    391  1.1  mrg 	    {
    392  1.1  mrg 	      subpat = gen_rtx_SET (memref, gen_rtx_REG (word_mode, pregno++));
    393  1.1  mrg 	    }
    394  1.1  mrg 	  XVECEXP (pat, 0, i + 1) = subpat;
    395  1.1  mrg 	  RTX_FRAME_RELATED_P (subpat) = 1;
    396  1.1  mrg 	}
    397  1.1  mrg       insn = emit_insn (pat);
    398  1.1  mrg       RTX_FRAME_RELATED_P (insn) = 1;
    399  1.1  mrg     }
    400  1.1  mrg 
    401  1.1  mrg   for (dregno = REG_R0; ndregs != ndregs_consec; dregno++)
    402  1.1  mrg     {
    403  1.1  mrg       if (must_save_p (is_inthandler, dregno))
    404  1.1  mrg 	{
    405  1.1  mrg 	  rtx_insn *insn =
    406  1.1  mrg 	    emit_move_insn (predec, gen_rtx_REG (word_mode, dregno));
    407  1.1  mrg 	  RTX_FRAME_RELATED_P (insn) = 1;
    408  1.1  mrg 	  ndregs--;
    409  1.1  mrg 	}
    410  1.1  mrg     }
    411  1.1  mrg   for (pregno = REG_P0; npregs != npregs_consec; pregno++)
    412  1.1  mrg     {
    413  1.1  mrg       if (must_save_p (is_inthandler, pregno))
    414  1.1  mrg 	{
    415  1.1  mrg 	  rtx_insn *insn =
    416  1.1  mrg 	    emit_move_insn (predec, gen_rtx_REG (word_mode, pregno));
    417  1.1  mrg 	  RTX_FRAME_RELATED_P (insn) = 1;
    418  1.1  mrg 	  npregs--;
    419  1.1  mrg 	}
    420  1.1  mrg     }
    421  1.1  mrg   for (i = REG_P7 + 1; i < REG_CC; i++)
    422  1.1  mrg     if (saveall
    423  1.1  mrg 	|| (is_inthandler
    424  1.1  mrg 	    && (df_regs_ever_live_p (i)
    425  1.1  mrg 		|| (!leaf_function_p () && call_used_or_fixed_reg_p (i)))))
    426  1.1  mrg       {
    427  1.1  mrg 	rtx_insn *insn;
    428  1.1  mrg 	if (i == REG_A0 || i == REG_A1)
    429  1.1  mrg 	  insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1),
    430  1.1  mrg 				 gen_rtx_REG (PDImode, i));
    431  1.1  mrg 	else
    432  1.1  mrg 	  insn = emit_move_insn (predec, gen_rtx_REG (SImode, i));
    433  1.1  mrg 	RTX_FRAME_RELATED_P (insn) = 1;
    434  1.1  mrg       }
    435  1.1  mrg }
    436  1.1  mrg 
    437  1.1  mrg /* Emit code to restore registers in the epilogue.  SAVEALL is nonzero if we
    438  1.1  mrg    must save all registers; this is used for interrupt handlers.
    439  1.1  mrg    SPREG contains (reg:SI REG_SP).  IS_INTHANDLER is true if we're doing
    440  1.1  mrg    this for an interrupt (or exception) handler.  */
    441  1.1  mrg 
    442  1.1  mrg static void
    443  1.1  mrg expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler)
    444  1.1  mrg {
    445  1.1  mrg   rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
    446  1.1  mrg   rtx postinc = gen_rtx_MEM (SImode, postinc1);
    447  1.1  mrg 
    448  1.1  mrg   int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler, false);
    449  1.1  mrg   int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler, false);
    450  1.1  mrg   int ndregs_consec = saveall ? 8 : n_dregs_to_save (is_inthandler, true);
    451  1.1  mrg   int npregs_consec = saveall ? 6 : n_pregs_to_save (is_inthandler, true);
    452  1.1  mrg   int total_consec = ndregs_consec + npregs_consec;
    453  1.1  mrg   int i, regno;
    454  1.1  mrg   rtx_insn *insn;
    455  1.1  mrg 
    456  1.1  mrg   /* A slightly crude technique to stop flow from trying to delete "dead"
    457  1.1  mrg      insns.  */
    458  1.1  mrg   MEM_VOLATILE_P (postinc) = 1;
    459  1.1  mrg 
    460  1.1  mrg   for (i = REG_CC - 1; i > REG_P7; i--)
    461  1.1  mrg     if (saveall
    462  1.1  mrg 	|| (is_inthandler
    463  1.1  mrg 	    && (df_regs_ever_live_p (i)
    464  1.1  mrg 		|| (!leaf_function_p () && call_used_or_fixed_reg_p (i)))))
    465  1.1  mrg       {
    466  1.1  mrg 	if (i == REG_A0 || i == REG_A1)
    467  1.1  mrg 	  {
    468  1.1  mrg 	    rtx mem = gen_rtx_MEM (PDImode, postinc1);
    469  1.1  mrg 	    MEM_VOLATILE_P (mem) = 1;
    470  1.1  mrg 	    emit_move_insn (gen_rtx_REG (PDImode, i), mem);
    471  1.1  mrg 	  }
    472  1.1  mrg 	else
    473  1.1  mrg 	  emit_move_insn (gen_rtx_REG (SImode, i), postinc);
    474  1.1  mrg       }
    475  1.1  mrg 
    476  1.1  mrg   regno = REG_P5 - npregs_consec;
    477  1.1  mrg   for (; npregs != npregs_consec; regno--)
    478  1.1  mrg     {
    479  1.1  mrg       if (must_save_p (is_inthandler, regno))
    480  1.1  mrg 	{
    481  1.1  mrg 	  emit_move_insn (gen_rtx_REG (word_mode, regno), postinc);
    482  1.1  mrg 	  npregs--;
    483  1.1  mrg 	}
    484  1.1  mrg     }
    485  1.1  mrg   regno = REG_R7 - ndregs_consec;
    486  1.1  mrg   for (; ndregs != ndregs_consec; regno--)
    487  1.1  mrg     {
    488  1.1  mrg       if (must_save_p (is_inthandler, regno))
    489  1.1  mrg 	{
    490  1.1  mrg 	  emit_move_insn (gen_rtx_REG (word_mode, regno), postinc);
    491  1.1  mrg 	  ndregs--;
    492  1.1  mrg 	}
    493  1.1  mrg     }
    494  1.1  mrg 
    495  1.1  mrg   if (total_consec != 0)
    496  1.1  mrg     {
    497  1.1  mrg       rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_consec + 1));
    498  1.1  mrg       XVECEXP (pat, 0, 0)
    499  1.1  mrg 	= gen_rtx_SET (spreg, gen_rtx_PLUS (Pmode, spreg,
    500  1.1  mrg 					    GEN_INT (total_consec * 4)));
    501  1.1  mrg 
    502  1.1  mrg       if (npregs_consec > 0)
    503  1.1  mrg 	regno = REG_P5 + 1;
    504  1.1  mrg       else
    505  1.1  mrg 	regno = REG_R7 + 1;
    506  1.1  mrg 
    507  1.1  mrg       for (i = 0; i < total_consec; i++)
    508  1.1  mrg 	{
    509  1.1  mrg 	  rtx addr = (i > 0
    510  1.1  mrg 		      ? gen_rtx_PLUS (Pmode, spreg, GEN_INT (i * 4))
    511  1.1  mrg 		      : spreg);
    512  1.1  mrg 	  rtx memref = gen_rtx_MEM (word_mode, addr);
    513  1.1  mrg 
    514  1.1  mrg 	  regno--;
    515  1.1  mrg 	  XVECEXP (pat, 0, i + 1)
    516  1.1  mrg 	    = gen_rtx_SET (gen_rtx_REG (word_mode, regno), memref);
    517  1.1  mrg 
    518  1.1  mrg 	  if (npregs_consec > 0)
    519  1.1  mrg 	    {
    520  1.1  mrg 	      if (--npregs_consec == 0)
    521  1.1  mrg 		regno = REG_R7 + 1;
    522  1.1  mrg 	    }
    523  1.1  mrg 	}
    524  1.1  mrg 
    525  1.1  mrg       insn = emit_insn (pat);
    526  1.1  mrg       RTX_FRAME_RELATED_P (insn) = 1;
    527  1.1  mrg     }
    528  1.1  mrg   if (saveall || is_inthandler)
    529  1.1  mrg     {
    530  1.1  mrg       for (regno = REG_LB1; regno >= REG_LT0; regno--)
    531  1.1  mrg 	if (! crtl->is_leaf
    532  1.1  mrg 	    || cfun->machine->has_hardware_loops
    533  1.1  mrg 	    || cfun->machine->has_loopreg_clobber
    534  1.1  mrg 	    || (ENABLE_WA_05000257 && (regno == REG_LC0 || regno == REG_LC1)))
    535  1.1  mrg 	  emit_move_insn (gen_rtx_REG (SImode, regno), postinc);
    536  1.1  mrg 
    537  1.1  mrg       emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
    538  1.1  mrg     }
    539  1.1  mrg }
    540  1.1  mrg 
    541  1.1  mrg /* Perform any needed actions needed for a function that is receiving a
    542  1.1  mrg    variable number of arguments.
    543  1.1  mrg 
    544  1.1  mrg    CUM is as above.
    545  1.1  mrg 
    546  1.1  mrg    ARG is the last named argument.
    547  1.1  mrg 
    548  1.1  mrg    PRETEND_SIZE is a variable that should be set to the amount of stack
    549  1.1  mrg    that must be pushed by the prolog to pretend that our caller pushed
    550  1.1  mrg    it.
    551  1.1  mrg 
    552  1.1  mrg    Normally, this macro will push all remaining incoming registers on the
    553  1.1  mrg    stack and set PRETEND_SIZE to the length of the registers pushed.
    554  1.1  mrg 
    555  1.1  mrg    Blackfin specific :
    556  1.1  mrg    - VDSP C compiler manual (our ABI) says that a variable args function
    557  1.1  mrg      should save the R0, R1 and R2 registers in the stack.
    558  1.1  mrg    - The caller will always leave space on the stack for the
    559  1.1  mrg      arguments that are passed in registers, so we dont have
    560  1.1  mrg      to leave any extra space.
    561  1.1  mrg    - now, the vastart pointer can access all arguments from the stack.  */
    562  1.1  mrg 
    563  1.1  mrg static void
    564  1.1  mrg setup_incoming_varargs (cumulative_args_t cum,
    565  1.1  mrg 			const function_arg_info &, int *pretend_size,
    566  1.1  mrg 			int no_rtl)
    567  1.1  mrg {
    568  1.1  mrg   rtx mem;
    569  1.1  mrg   int i;
    570  1.1  mrg 
    571  1.1  mrg   if (no_rtl)
    572  1.1  mrg     return;
    573  1.1  mrg 
    574  1.1  mrg   /* The move for named arguments will be generated automatically by the
    575  1.1  mrg      compiler.  We need to generate the move rtx for the unnamed arguments
    576  1.1  mrg      if they are in the first 3 words.  We assume at least 1 named argument
    577  1.1  mrg      exists, so we never generate [ARGP] = R0 here.  */
    578  1.1  mrg 
    579  1.1  mrg   for (i = get_cumulative_args (cum)->words + 1; i < max_arg_registers; i++)
    580  1.1  mrg     {
    581  1.1  mrg       mem = gen_rtx_MEM (Pmode,
    582  1.1  mrg 			 plus_constant (Pmode, arg_pointer_rtx,
    583  1.1  mrg 					(i * UNITS_PER_WORD)));
    584  1.1  mrg       emit_move_insn (mem, gen_rtx_REG (Pmode, i));
    585  1.1  mrg     }
    586  1.1  mrg 
    587  1.1  mrg   *pretend_size = 0;
    588  1.1  mrg }
    589  1.1  mrg 
    590  1.1  mrg /* Value should be nonzero if functions must have frame pointers.
    591  1.1  mrg    Zero means the frame pointer need not be set up (and parms may
    592  1.1  mrg    be accessed via the stack pointer) in functions that seem suitable.  */
    593  1.1  mrg 
    594  1.1  mrg static bool
    595  1.1  mrg bfin_frame_pointer_required (void)
    596  1.1  mrg {
    597  1.1  mrg   e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
    598  1.1  mrg 
    599  1.1  mrg   if (fkind != SUBROUTINE)
    600  1.1  mrg     return true;
    601  1.1  mrg 
    602  1.1  mrg   /* We turn on -fomit-frame-pointer if -momit-leaf-frame-pointer is used,
    603  1.1  mrg      so we have to override it for non-leaf functions.  */
    604  1.1  mrg   if (TARGET_OMIT_LEAF_FRAME_POINTER && ! crtl->is_leaf)
    605  1.1  mrg     return true;
    606  1.1  mrg 
    607  1.1  mrg   return false;
    608  1.1  mrg }
    609  1.1  mrg 
    610  1.1  mrg /* Return the number of registers pushed during the prologue.  */
    611  1.1  mrg 
    612  1.1  mrg static int
    613  1.1  mrg n_regs_saved_by_prologue (void)
    614  1.1  mrg {
    615  1.1  mrg   e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
    616  1.1  mrg   bool is_inthandler = fkind != SUBROUTINE;
    617  1.1  mrg   tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
    618  1.1  mrg   bool all = (lookup_attribute ("saveall", attrs) != NULL_TREE
    619  1.1  mrg 	      || (is_inthandler && !crtl->is_leaf));
    620  1.1  mrg   int ndregs = all ? 8 : n_dregs_to_save (is_inthandler, false);
    621  1.1  mrg   int npregs = all ? 6 : n_pregs_to_save (is_inthandler, false);
    622  1.1  mrg   int n = ndregs + npregs;
    623  1.1  mrg   int i;
    624  1.1  mrg 
    625  1.1  mrg   if (all || stack_frame_needed_p ())
    626  1.1  mrg     n += 2;
    627  1.1  mrg   else
    628  1.1  mrg     {
    629  1.1  mrg       if (must_save_fp_p ())
    630  1.1  mrg 	n++;
    631  1.1  mrg       if (must_save_rets_p ())
    632  1.1  mrg 	n++;
    633  1.1  mrg     }
    634  1.1  mrg 
    635  1.1  mrg   if (fkind != SUBROUTINE || all)
    636  1.1  mrg     {
    637  1.1  mrg       /* Increment once for ASTAT.  */
    638  1.1  mrg       n++;
    639  1.1  mrg       if (! crtl->is_leaf
    640  1.1  mrg 	  || cfun->machine->has_hardware_loops
    641  1.1  mrg 	  || cfun->machine->has_loopreg_clobber)
    642  1.1  mrg 	{
    643  1.1  mrg 	  n += 6;
    644  1.1  mrg 	}
    645  1.1  mrg     }
    646  1.1  mrg 
    647  1.1  mrg   if (fkind != SUBROUTINE)
    648  1.1  mrg     {
    649  1.1  mrg       /* RETE/X/N.  */
    650  1.1  mrg       if (lookup_attribute ("nesting", attrs))
    651  1.1  mrg 	n++;
    652  1.1  mrg     }
    653  1.1  mrg 
    654  1.1  mrg   for (i = REG_P7 + 1; i < REG_CC; i++)
    655  1.1  mrg     if (all
    656  1.1  mrg 	|| (fkind != SUBROUTINE
    657  1.1  mrg 	    && (df_regs_ever_live_p (i)
    658  1.1  mrg 		|| (!leaf_function_p () && call_used_or_fixed_reg_p (i)))))
    659  1.1  mrg       n += i == REG_A0 || i == REG_A1 ? 2 : 1;
    660  1.1  mrg 
    661  1.1  mrg   return n;
    662  1.1  mrg }
    663  1.1  mrg 
    664  1.1  mrg /* Given FROM and TO register numbers, say whether this elimination is
    665  1.1  mrg    allowed.  Frame pointer elimination is automatically handled.
    666  1.1  mrg 
    667  1.1  mrg    All other eliminations are valid.  */
    668  1.1  mrg 
    669  1.1  mrg static bool
    670  1.1  mrg bfin_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
    671  1.1  mrg {
    672  1.1  mrg   return (to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true);
    673  1.1  mrg }
    674  1.1  mrg 
    675  1.1  mrg /* Return the offset between two registers, one to be eliminated, and the other
    676  1.1  mrg    its replacement, at the start of a routine.  */
    677  1.1  mrg 
    678  1.1  mrg HOST_WIDE_INT
    679  1.1  mrg bfin_initial_elimination_offset (int from, int to)
    680  1.1  mrg {
    681  1.1  mrg   HOST_WIDE_INT offset = 0;
    682  1.1  mrg 
    683  1.1  mrg   if (from == ARG_POINTER_REGNUM)
    684  1.1  mrg     offset = n_regs_saved_by_prologue () * 4;
    685  1.1  mrg 
    686  1.1  mrg   if (to == STACK_POINTER_REGNUM)
    687  1.1  mrg     {
    688  1.1  mrg       if (crtl->outgoing_args_size >= FIXED_STACK_AREA)
    689  1.1  mrg 	offset += crtl->outgoing_args_size;
    690  1.1  mrg       else if (crtl->outgoing_args_size)
    691  1.1  mrg 	offset += FIXED_STACK_AREA;
    692  1.1  mrg 
    693  1.1  mrg       offset += get_frame_size ();
    694  1.1  mrg     }
    695  1.1  mrg 
    696  1.1  mrg   return offset;
    697  1.1  mrg }
    698  1.1  mrg 
    699  1.1  mrg /* Emit code to load a constant CONSTANT into register REG; setting
    700  1.1  mrg    RTX_FRAME_RELATED_P on all insns we generate if RELATED is true.
    701  1.1  mrg    Make sure that the insns we generate need not be split.  */
    702  1.1  mrg 
    703  1.1  mrg static void
    704  1.1  mrg frame_related_constant_load (rtx reg, HOST_WIDE_INT constant, bool related)
    705  1.1  mrg {
    706  1.1  mrg   rtx_insn *insn;
    707  1.1  mrg   rtx cst = GEN_INT (constant);
    708  1.1  mrg 
    709  1.1  mrg   if (constant >= -32768 && constant < 65536)
    710  1.1  mrg     insn = emit_move_insn (reg, cst);
    711  1.1  mrg   else
    712  1.1  mrg     {
    713  1.1  mrg       /* We don't call split_load_immediate here, since dwarf2out.cc can get
    714  1.1  mrg 	 confused about some of the more clever sequences it can generate.  */
    715  1.1  mrg       insn = emit_insn (gen_movsi_high (reg, cst));
    716  1.1  mrg       if (related)
    717  1.1  mrg 	RTX_FRAME_RELATED_P (insn) = 1;
    718  1.1  mrg       insn = emit_insn (gen_movsi_low (reg, reg, cst));
    719  1.1  mrg     }
    720  1.1  mrg   if (related)
    721  1.1  mrg     RTX_FRAME_RELATED_P (insn) = 1;
    722  1.1  mrg }
    723  1.1  mrg 
    724  1.1  mrg /* Generate efficient code to add a value to a P register.
    725  1.1  mrg    Set RTX_FRAME_RELATED_P on the generated insns if FRAME is nonzero.
    726  1.1  mrg    EPILOGUE_P is zero if this function is called for prologue,
    727  1.1  mrg    otherwise it's nonzero. And it's less than zero if this is for
    728  1.1  mrg    sibcall epilogue.  */
    729  1.1  mrg 
    730  1.1  mrg static void
    731  1.1  mrg add_to_reg (rtx reg, HOST_WIDE_INT value, int frame, int epilogue_p)
    732  1.1  mrg {
    733  1.1  mrg   if (value == 0)
    734  1.1  mrg     return;
    735  1.1  mrg 
    736  1.1  mrg   /* Choose whether to use a sequence using a temporary register, or
    737  1.1  mrg      a sequence with multiple adds.  We can add a signed 7-bit value
    738  1.1  mrg      in one instruction.  */
    739  1.1  mrg   if (value > 120 || value < -120)
    740  1.1  mrg     {
    741  1.1  mrg       rtx tmpreg;
    742  1.1  mrg       rtx tmpreg2;
    743  1.1  mrg       rtx_insn *insn;
    744  1.1  mrg 
    745  1.1  mrg       tmpreg2 = NULL_RTX;
    746  1.1  mrg 
    747  1.1  mrg       /* For prologue or normal epilogue, P1 can be safely used
    748  1.1  mrg 	 as the temporary register. For sibcall epilogue, we try to find
    749  1.1  mrg 	 a call used P register, which will be restored in epilogue.
    750  1.1  mrg 	 If we cannot find such a P register, we have to use one I register
    751  1.1  mrg 	 to help us.  */
    752  1.1  mrg 
    753  1.1  mrg       if (epilogue_p >= 0)
    754  1.1  mrg 	tmpreg = gen_rtx_REG (SImode, REG_P1);
    755  1.1  mrg       else
    756  1.1  mrg 	{
    757  1.1  mrg 	  int i;
    758  1.1  mrg 	  for (i = REG_P0; i <= REG_P5; i++)
    759  1.1  mrg 	    if ((df_regs_ever_live_p (i) && ! call_used_or_fixed_reg_p (i))
    760  1.1  mrg 		|| (!TARGET_FDPIC
    761  1.1  mrg 		    && i == PIC_OFFSET_TABLE_REGNUM
    762  1.1  mrg 		    && (crtl->uses_pic_offset_table
    763  1.1  mrg 			|| (TARGET_ID_SHARED_LIBRARY
    764  1.1  mrg 			    && ! crtl->is_leaf))))
    765  1.1  mrg 	      break;
    766  1.1  mrg 	  if (i <= REG_P5)
    767  1.1  mrg 	    tmpreg = gen_rtx_REG (SImode, i);
    768  1.1  mrg 	  else
    769  1.1  mrg 	    {
    770  1.1  mrg 	      tmpreg = gen_rtx_REG (SImode, REG_P1);
    771  1.1  mrg 	      tmpreg2 = gen_rtx_REG (SImode, REG_I0);
    772  1.1  mrg 	      emit_move_insn (tmpreg2, tmpreg);
    773  1.1  mrg 	    }
    774  1.1  mrg 	}
    775  1.1  mrg 
    776  1.1  mrg       if (frame)
    777  1.1  mrg 	frame_related_constant_load (tmpreg, value, TRUE);
    778  1.1  mrg       else
    779  1.1  mrg 	insn = emit_move_insn (tmpreg, GEN_INT (value));
    780  1.1  mrg 
    781  1.1  mrg       insn = emit_insn (gen_addsi3 (reg, reg, tmpreg));
    782  1.1  mrg       if (frame)
    783  1.1  mrg 	RTX_FRAME_RELATED_P (insn) = 1;
    784  1.1  mrg 
    785  1.1  mrg       if (tmpreg2 != NULL_RTX)
    786  1.1  mrg 	emit_move_insn (tmpreg, tmpreg2);
    787  1.1  mrg     }
    788  1.1  mrg   else
    789  1.1  mrg     do
    790  1.1  mrg       {
    791  1.1  mrg 	int size = value;
    792  1.1  mrg 	rtx_insn *insn;
    793  1.1  mrg 
    794  1.1  mrg 	if (size > 60)
    795  1.1  mrg 	  size = 60;
    796  1.1  mrg 	else if (size < -60)
    797  1.1  mrg 	  /* We could use -62, but that would leave the stack unaligned, so
    798  1.1  mrg 	     it's no good.  */
    799  1.1  mrg 	  size = -60;
    800  1.1  mrg 
    801  1.1  mrg 	insn = emit_insn (gen_addsi3 (reg, reg, GEN_INT (size)));
    802  1.1  mrg 	if (frame)
    803  1.1  mrg 	  RTX_FRAME_RELATED_P (insn) = 1;
    804  1.1  mrg 	value -= size;
    805  1.1  mrg       }
    806  1.1  mrg     while (value != 0);
    807  1.1  mrg }
    808  1.1  mrg 
    809  1.1  mrg /* Generate a LINK insn for a frame sized FRAME_SIZE.  If this constant
    810  1.1  mrg    is too large, generate a sequence of insns that has the same effect.
    811  1.1  mrg    SPREG contains (reg:SI REG_SP).  */
    812  1.1  mrg 
    813  1.1  mrg static void
    814  1.1  mrg emit_link_insn (rtx spreg, HOST_WIDE_INT frame_size)
    815  1.1  mrg {
    816  1.1  mrg   HOST_WIDE_INT link_size = frame_size;
    817  1.1  mrg   rtx_insn *insn;
    818  1.1  mrg   int i;
    819  1.1  mrg 
    820  1.1  mrg   if (link_size > 262140)
    821  1.1  mrg     link_size = 262140;
    822  1.1  mrg 
    823  1.1  mrg   /* Use a LINK insn with as big a constant as possible, then subtract
    824  1.1  mrg      any remaining size from the SP.  */
    825  1.1  mrg   insn = emit_insn (gen_link (GEN_INT (-8 - link_size)));
    826  1.1  mrg   RTX_FRAME_RELATED_P (insn) = 1;
    827  1.1  mrg 
    828  1.1  mrg   for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
    829  1.1  mrg     {
    830  1.1  mrg       rtx set = XVECEXP (PATTERN (insn), 0, i);
    831  1.1  mrg       gcc_assert (GET_CODE (set) == SET);
    832  1.1  mrg       RTX_FRAME_RELATED_P (set) = 1;
    833  1.1  mrg     }
    834  1.1  mrg 
    835  1.1  mrg   frame_size -= link_size;
    836  1.1  mrg 
    837  1.1  mrg   if (frame_size > 0)
    838  1.1  mrg     {
    839  1.1  mrg       /* Must use a call-clobbered PREG that isn't the static chain.  */
    840  1.1  mrg       rtx tmpreg = gen_rtx_REG (Pmode, REG_P1);
    841  1.1  mrg 
    842  1.1  mrg       frame_related_constant_load (tmpreg, -frame_size, TRUE);
    843  1.1  mrg       insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg));
    844  1.1  mrg       RTX_FRAME_RELATED_P (insn) = 1;
    845  1.1  mrg     }
    846  1.1  mrg }
    847  1.1  mrg 
    848  1.1  mrg /* Return the number of bytes we must reserve for outgoing arguments
    849  1.1  mrg    in the current function's stack frame.  */
    850  1.1  mrg 
    851  1.1  mrg static HOST_WIDE_INT
    852  1.1  mrg arg_area_size (void)
    853  1.1  mrg {
    854  1.1  mrg   if (crtl->outgoing_args_size)
    855  1.1  mrg     {
    856  1.1  mrg       if (crtl->outgoing_args_size >= FIXED_STACK_AREA)
    857  1.1  mrg 	return crtl->outgoing_args_size;
    858  1.1  mrg       else
    859  1.1  mrg 	return FIXED_STACK_AREA;
    860  1.1  mrg     }
    861  1.1  mrg   return 0;
    862  1.1  mrg }
    863  1.1  mrg 
    864  1.1  mrg /* Save RETS and FP, and allocate a stack frame.  ALL is true if the
    865  1.1  mrg    function must save all its registers (true only for certain interrupt
    866  1.1  mrg    handlers).  */
    867  1.1  mrg 
    868  1.1  mrg static void
    869  1.1  mrg do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all)
    870  1.1  mrg {
    871  1.1  mrg   frame_size += arg_area_size ();
    872  1.1  mrg 
    873  1.1  mrg   if (all
    874  1.1  mrg       || stack_frame_needed_p ()
    875  1.1  mrg       || (must_save_rets_p () && must_save_fp_p ()))
    876  1.1  mrg     emit_link_insn (spreg, frame_size);
    877  1.1  mrg   else
    878  1.1  mrg     {
    879  1.1  mrg       if (must_save_rets_p ())
    880  1.1  mrg 	{
    881  1.1  mrg 	  rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
    882  1.1  mrg 					    gen_rtx_PRE_DEC (Pmode, spreg)),
    883  1.1  mrg 			       bfin_rets_rtx);
    884  1.1  mrg 	  rtx_insn *insn = emit_insn (pat);
    885  1.1  mrg 	  RTX_FRAME_RELATED_P (insn) = 1;
    886  1.1  mrg 	}
    887  1.1  mrg       if (must_save_fp_p ())
    888  1.1  mrg 	{
    889  1.1  mrg 	  rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
    890  1.1  mrg 					    gen_rtx_PRE_DEC (Pmode, spreg)),
    891  1.1  mrg 			       gen_rtx_REG (Pmode, REG_FP));
    892  1.1  mrg 	  rtx_insn *insn = emit_insn (pat);
    893  1.1  mrg 	  RTX_FRAME_RELATED_P (insn) = 1;
    894  1.1  mrg 	}
    895  1.1  mrg       add_to_reg (spreg, -frame_size, 1, 0);
    896  1.1  mrg     }
    897  1.1  mrg }
    898  1.1  mrg 
    899  1.1  mrg /* Like do_link, but used for epilogues to deallocate the stack frame.
    900  1.1  mrg    EPILOGUE_P is zero if this function is called for prologue,
    901  1.1  mrg    otherwise it's nonzero. And it's less than zero if this is for
    902  1.1  mrg    sibcall epilogue.  */
    903  1.1  mrg 
    904  1.1  mrg static void
    905  1.1  mrg do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all, int epilogue_p)
    906  1.1  mrg {
    907  1.1  mrg   frame_size += arg_area_size ();
    908  1.1  mrg 
    909  1.1  mrg   if (stack_frame_needed_p ())
    910  1.1  mrg     emit_insn (gen_unlink ());
    911  1.1  mrg   else
    912  1.1  mrg     {
    913  1.1  mrg       rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg));
    914  1.1  mrg 
    915  1.1  mrg       add_to_reg (spreg, frame_size, 0, epilogue_p);
    916  1.1  mrg       if (all || must_save_fp_p ())
    917  1.1  mrg 	{
    918  1.1  mrg 	  rtx fpreg = gen_rtx_REG (Pmode, REG_FP);
    919  1.1  mrg 	  emit_move_insn (fpreg, postinc);
    920  1.1  mrg 	  emit_use (fpreg);
    921  1.1  mrg 	}
    922  1.1  mrg       if (all || must_save_rets_p ())
    923  1.1  mrg 	{
    924  1.1  mrg 	  emit_move_insn (bfin_rets_rtx, postinc);
    925  1.1  mrg 	  emit_use (bfin_rets_rtx);
    926  1.1  mrg 	}
    927  1.1  mrg     }
    928  1.1  mrg }
    929  1.1  mrg 
    930  1.1  mrg /* Generate a prologue suitable for a function of kind FKIND.  This is
    931  1.1  mrg    called for interrupt and exception handler prologues.
    932  1.1  mrg    SPREG contains (reg:SI REG_SP).  */
    933  1.1  mrg 
    934  1.1  mrg static void
    935  1.1  mrg expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind, bool all)
    936  1.1  mrg {
    937  1.1  mrg   HOST_WIDE_INT frame_size = get_frame_size ();
    938  1.1  mrg   rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
    939  1.1  mrg   rtx predec = gen_rtx_MEM (SImode, predec1);
    940  1.1  mrg   rtx_insn *insn;
    941  1.1  mrg   tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
    942  1.1  mrg   tree kspisusp = lookup_attribute ("kspisusp", attrs);
    943  1.1  mrg 
    944  1.1  mrg   if (kspisusp)
    945  1.1  mrg     {
    946  1.1  mrg       insn = emit_move_insn (spreg, gen_rtx_REG (Pmode, REG_USP));
    947  1.1  mrg       RTX_FRAME_RELATED_P (insn) = 1;
    948  1.1  mrg     }
    949  1.1  mrg 
    950  1.1  mrg   /* We need space on the stack in case we need to save the argument
    951  1.1  mrg      registers.  */
    952  1.1  mrg   if (fkind == EXCPT_HANDLER)
    953  1.1  mrg     {
    954  1.1  mrg       insn = emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (-12)));
    955  1.1  mrg       RTX_FRAME_RELATED_P (insn) = 1;
    956  1.1  mrg     }
    957  1.1  mrg 
    958  1.1  mrg   /* If we're calling other functions, they won't save their call-clobbered
    959  1.1  mrg      registers, so we must save everything here.  */
    960  1.1  mrg   if (!crtl->is_leaf)
    961  1.1  mrg     all = true;
    962  1.1  mrg   expand_prologue_reg_save (spreg, all, true);
    963  1.1  mrg 
    964  1.1  mrg   if (ENABLE_WA_05000283 || ENABLE_WA_05000315)
    965  1.1  mrg     {
    966  1.1  mrg       rtx chipid = GEN_INT (trunc_int_for_mode (0xFFC00014, SImode));
    967  1.1  mrg       rtx p5reg = gen_rtx_REG (Pmode, REG_P5);
    968  1.1  mrg       emit_insn (gen_movbi (bfin_cc_rtx, const1_rtx));
    969  1.1  mrg       emit_insn (gen_movsi_high (p5reg, chipid));
    970  1.1  mrg       emit_insn (gen_movsi_low (p5reg, p5reg, chipid));
    971  1.1  mrg       emit_insn (gen_dummy_load (p5reg, bfin_cc_rtx));
    972  1.1  mrg     }
    973  1.1  mrg 
    974  1.1  mrg   if (lookup_attribute ("nesting", attrs))
    975  1.1  mrg     {
    976  1.1  mrg       rtx srcreg = gen_rtx_REG (Pmode, ret_regs[fkind]);
    977  1.1  mrg       insn = emit_move_insn (predec, srcreg);
    978  1.1  mrg       RTX_FRAME_RELATED_P (insn) = 1;
    979  1.1  mrg     }
    980  1.1  mrg 
    981  1.1  mrg   do_link (spreg, frame_size, all);
    982  1.1  mrg 
    983  1.1  mrg   if (fkind == EXCPT_HANDLER)
    984  1.1  mrg     {
    985  1.1  mrg       rtx r0reg = gen_rtx_REG (SImode, REG_R0);
    986  1.1  mrg       rtx r1reg = gen_rtx_REG (SImode, REG_R1);
    987  1.1  mrg       rtx r2reg = gen_rtx_REG (SImode, REG_R2);
    988  1.1  mrg 
    989  1.1  mrg       emit_move_insn (r0reg, gen_rtx_REG (SImode, REG_SEQSTAT));
    990  1.1  mrg       emit_insn (gen_ashrsi3 (r0reg, r0reg, GEN_INT (26)));
    991  1.1  mrg       emit_insn (gen_ashlsi3 (r0reg, r0reg, GEN_INT (26)));
    992  1.1  mrg       emit_move_insn (r1reg, spreg);
    993  1.1  mrg       emit_move_insn (r2reg, gen_rtx_REG (Pmode, REG_FP));
    994  1.1  mrg       emit_insn (gen_addsi3 (r2reg, r2reg, GEN_INT (8)));
    995  1.1  mrg     }
    996  1.1  mrg }
    997  1.1  mrg 
    998  1.1  mrg /* Generate an epilogue suitable for a function of kind FKIND.  This is
    999  1.1  mrg    called for interrupt and exception handler epilogues.
   1000  1.1  mrg    SPREG contains (reg:SI REG_SP).  */
   1001  1.1  mrg 
   1002  1.1  mrg static void
   1003  1.1  mrg expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind, bool all)
   1004  1.1  mrg {
   1005  1.1  mrg   tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
   1006  1.1  mrg   rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
   1007  1.1  mrg   rtx postinc = gen_rtx_MEM (SImode, postinc1);
   1008  1.1  mrg 
   1009  1.1  mrg   /* A slightly crude technique to stop flow from trying to delete "dead"
   1010  1.1  mrg      insns.  */
   1011  1.1  mrg   MEM_VOLATILE_P (postinc) = 1;
   1012  1.1  mrg 
   1013  1.1  mrg   do_unlink (spreg, get_frame_size (), all, 1);
   1014  1.1  mrg 
   1015  1.1  mrg   if (lookup_attribute ("nesting", attrs))
   1016  1.1  mrg     {
   1017  1.1  mrg       rtx srcreg = gen_rtx_REG (Pmode, ret_regs[fkind]);
   1018  1.1  mrg       emit_move_insn (srcreg, postinc);
   1019  1.1  mrg     }
   1020  1.1  mrg 
   1021  1.1  mrg   /* If we're calling other functions, they won't save their call-clobbered
   1022  1.1  mrg      registers, so we must save (and restore) everything here.  */
   1023  1.1  mrg   if (!crtl->is_leaf)
   1024  1.1  mrg     all = true;
   1025  1.1  mrg 
   1026  1.1  mrg   expand_epilogue_reg_restore (spreg, all, true);
   1027  1.1  mrg 
   1028  1.1  mrg   /* Deallocate any space we left on the stack in case we needed to save the
   1029  1.1  mrg      argument registers.  */
   1030  1.1  mrg   if (fkind == EXCPT_HANDLER)
   1031  1.1  mrg     emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (12)));
   1032  1.1  mrg 
   1033  1.1  mrg   emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, ret_regs[fkind])));
   1034  1.1  mrg }
   1035  1.1  mrg 
   1036  1.1  mrg /* Used while emitting the prologue to generate code to load the correct value
   1037  1.1  mrg    into the PIC register, which is passed in DEST.  */
   1038  1.1  mrg 
   1039  1.1  mrg static rtx
   1040  1.1  mrg bfin_load_pic_reg (rtx dest)
   1041  1.1  mrg {
   1042  1.1  mrg   rtx addr;
   1043  1.1  mrg 
   1044  1.1  mrg   cgraph_node *local_info_node
   1045  1.1  mrg     = cgraph_node::local_info_node (current_function_decl);
   1046  1.1  mrg 
   1047  1.1  mrg   /* Functions local to the translation unit don't need to reload the
   1048  1.1  mrg      pic reg, since the caller always passes a usable one.  */
   1049  1.1  mrg   if (local_info_node && local_info_node->local)
   1050  1.1  mrg     return pic_offset_table_rtx;
   1051  1.1  mrg 
   1052  1.1  mrg   if (OPTION_SET_P (bfin_library_id))
   1053  1.1  mrg     addr = plus_constant (Pmode, pic_offset_table_rtx,
   1054  1.1  mrg 			   -4 - bfin_library_id * 4);
   1055  1.1  mrg   else
   1056  1.1  mrg     addr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
   1057  1.1  mrg 			 gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
   1058  1.1  mrg 					 UNSPEC_LIBRARY_OFFSET));
   1059  1.1  mrg   emit_insn (gen_movsi (dest, gen_rtx_MEM (Pmode, addr)));
   1060  1.1  mrg   return dest;
   1061  1.1  mrg }
   1062  1.1  mrg 
   1063  1.1  mrg /* Generate RTL for the prologue of the current function.  */
   1064  1.1  mrg 
   1065  1.1  mrg void
   1066  1.1  mrg bfin_expand_prologue (void)
   1067  1.1  mrg {
   1068  1.1  mrg   HOST_WIDE_INT frame_size = get_frame_size ();
   1069  1.1  mrg   rtx spreg = gen_rtx_REG (Pmode, REG_SP);
   1070  1.1  mrg   e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
   1071  1.1  mrg   rtx pic_reg_loaded = NULL_RTX;
   1072  1.1  mrg   tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
   1073  1.1  mrg   bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
   1074  1.1  mrg 
   1075  1.1  mrg   if (flag_stack_usage_info)
   1076  1.1  mrg     current_function_static_stack_size = frame_size;
   1077  1.1  mrg 
   1078  1.1  mrg   if (fkind != SUBROUTINE)
   1079  1.1  mrg     {
   1080  1.1  mrg       expand_interrupt_handler_prologue (spreg, fkind, all);
   1081  1.1  mrg       return;
   1082  1.1  mrg     }
   1083  1.1  mrg 
   1084  1.1  mrg   if (crtl->limit_stack
   1085  1.1  mrg       || (TARGET_STACK_CHECK_L1
   1086  1.1  mrg 	  && !DECL_NO_LIMIT_STACK (current_function_decl)))
   1087  1.1  mrg     {
   1088  1.1  mrg       HOST_WIDE_INT offset
   1089  1.1  mrg 	= bfin_initial_elimination_offset (ARG_POINTER_REGNUM,
   1090  1.1  mrg 					   STACK_POINTER_REGNUM);
   1091  1.1  mrg       rtx lim = crtl->limit_stack ? stack_limit_rtx : NULL_RTX;
   1092  1.1  mrg       rtx tmp = gen_rtx_REG (Pmode, REG_R3);
   1093  1.1  mrg       rtx p2reg = gen_rtx_REG (Pmode, REG_P2);
   1094  1.1  mrg 
   1095  1.1  mrg       emit_move_insn (tmp, p2reg);
   1096  1.1  mrg       if (!lim)
   1097  1.1  mrg 	{
   1098  1.1  mrg 	  emit_move_insn (p2reg, gen_int_mode (0xFFB00000, SImode));
   1099  1.1  mrg 	  emit_move_insn (p2reg, gen_rtx_MEM (Pmode, p2reg));
   1100  1.1  mrg 	  lim = p2reg;
   1101  1.1  mrg 	}
   1102  1.1  mrg       if (GET_CODE (lim) == SYMBOL_REF)
   1103  1.1  mrg 	{
   1104  1.1  mrg 	  if (TARGET_ID_SHARED_LIBRARY)
   1105  1.1  mrg 	    {
   1106  1.1  mrg 	      rtx p1reg = gen_rtx_REG (Pmode, REG_P1);
   1107  1.1  mrg 	      rtx val;
   1108  1.1  mrg 	      pic_reg_loaded = bfin_load_pic_reg (p2reg);
   1109  1.1  mrg 	      val = legitimize_pic_address (stack_limit_rtx, p1reg,
   1110  1.1  mrg 					    pic_reg_loaded);
   1111  1.1  mrg 	      emit_move_insn (p1reg, val);
   1112  1.1  mrg 	      frame_related_constant_load (p2reg, offset, FALSE);
   1113  1.1  mrg 	      emit_insn (gen_addsi3 (p2reg, p2reg, p1reg));
   1114  1.1  mrg 	      lim = p2reg;
   1115  1.1  mrg 	    }
   1116  1.1  mrg 	  else
   1117  1.1  mrg 	    {
   1118  1.1  mrg 	      rtx limit = plus_constant (Pmode, lim, offset);
   1119  1.1  mrg 	      emit_move_insn (p2reg, limit);
   1120  1.1  mrg 	      lim = p2reg;
   1121  1.1  mrg 	    }
   1122  1.1  mrg 	}
   1123  1.1  mrg       else
   1124  1.1  mrg 	{
   1125  1.1  mrg 	  if (lim != p2reg)
   1126  1.1  mrg 	    emit_move_insn (p2reg, lim);
   1127  1.1  mrg 	  add_to_reg (p2reg, offset, 0, 0);
   1128  1.1  mrg 	  lim = p2reg;
   1129  1.1  mrg 	}
   1130  1.1  mrg       emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim));
   1131  1.1  mrg       emit_insn (gen_trapifcc ());
   1132  1.1  mrg       emit_move_insn (p2reg, tmp);
   1133  1.1  mrg     }
   1134  1.1  mrg   expand_prologue_reg_save (spreg, all, false);
   1135  1.1  mrg 
   1136  1.1  mrg   do_link (spreg, frame_size, all);
   1137  1.1  mrg 
   1138  1.1  mrg   if (TARGET_ID_SHARED_LIBRARY
   1139  1.1  mrg       && !TARGET_SEP_DATA
   1140  1.1  mrg       && (crtl->uses_pic_offset_table
   1141  1.1  mrg 	  || !crtl->is_leaf))
   1142  1.1  mrg     bfin_load_pic_reg (pic_offset_table_rtx);
   1143  1.1  mrg }
   1144  1.1  mrg 
   1145  1.1  mrg /* Generate RTL for the epilogue of the current function.  NEED_RETURN is zero
   1146  1.1  mrg    if this is for a sibcall.  EH_RETURN is nonzero if we're expanding an
   1147  1.1  mrg    eh_return pattern. SIBCALL_P is true if this is a sibcall epilogue,
   1148  1.1  mrg    false otherwise.  */
   1149  1.1  mrg 
   1150  1.1  mrg void
   1151  1.1  mrg bfin_expand_epilogue (int need_return, int eh_return, bool sibcall_p)
   1152  1.1  mrg {
   1153  1.1  mrg   rtx spreg = gen_rtx_REG (Pmode, REG_SP);
   1154  1.1  mrg   e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
   1155  1.1  mrg   int e = sibcall_p ? -1 : 1;
   1156  1.1  mrg   tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
   1157  1.1  mrg   bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
   1158  1.1  mrg 
   1159  1.1  mrg   if (fkind != SUBROUTINE)
   1160  1.1  mrg     {
   1161  1.1  mrg       expand_interrupt_handler_epilogue (spreg, fkind, all);
   1162  1.1  mrg       return;
   1163  1.1  mrg     }
   1164  1.1  mrg 
   1165  1.1  mrg   do_unlink (spreg, get_frame_size (), all, e);
   1166  1.1  mrg 
   1167  1.1  mrg   expand_epilogue_reg_restore (spreg, all, false);
   1168  1.1  mrg 
   1169  1.1  mrg   /* Omit the return insn if this is for a sibcall.  */
   1170  1.1  mrg   if (! need_return)
   1171  1.1  mrg     return;
   1172  1.1  mrg 
   1173  1.1  mrg   if (eh_return)
   1174  1.1  mrg     emit_insn (gen_addsi3 (spreg, spreg, gen_rtx_REG (Pmode, REG_P2)));
   1175  1.1  mrg 
   1176  1.1  mrg   emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, REG_RETS)));
   1177  1.1  mrg }
   1178  1.1  mrg 
   1179  1.1  mrg /* Return nonzero if register OLD_REG can be renamed to register NEW_REG.  */
   1181  1.1  mrg 
   1182  1.1  mrg int
   1183  1.1  mrg bfin_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
   1184  1.1  mrg 			   unsigned int new_reg)
   1185  1.1  mrg {
   1186  1.1  mrg   /* Interrupt functions can only use registers that have already been
   1187  1.1  mrg      saved by the prologue, even if they would normally be
   1188  1.1  mrg      call-clobbered.  */
   1189  1.1  mrg 
   1190  1.1  mrg   if (funkind (TREE_TYPE (current_function_decl)) != SUBROUTINE
   1191  1.1  mrg       && !df_regs_ever_live_p (new_reg))
   1192  1.1  mrg     return 0;
   1193  1.1  mrg 
   1194  1.1  mrg   return 1;
   1195  1.1  mrg }
   1196  1.1  mrg 
   1197  1.1  mrg /* Implement TARGET_EXTRA_LIVE_ON_ENTRY.  */
   1198  1.1  mrg static void
   1199  1.1  mrg bfin_extra_live_on_entry (bitmap regs)
   1200  1.1  mrg {
   1201  1.1  mrg   if (TARGET_FDPIC)
   1202  1.1  mrg     bitmap_set_bit (regs, FDPIC_REGNO);
   1203  1.1  mrg }
   1204  1.1  mrg 
   1205  1.1  mrg /* Return the value of the return address for the frame COUNT steps up
   1206  1.1  mrg    from the current frame, after the prologue.
   1207  1.1  mrg    We punt for everything but the current frame by returning const0_rtx.  */
   1208  1.1  mrg 
   1209  1.1  mrg rtx
   1210  1.1  mrg bfin_return_addr_rtx (int count)
   1211  1.1  mrg {
   1212  1.1  mrg   if (count != 0)
   1213  1.1  mrg     return const0_rtx;
   1214  1.1  mrg 
   1215  1.1  mrg   return get_hard_reg_initial_val (Pmode, REG_RETS);
   1216  1.1  mrg }
   1217  1.1  mrg 
   1218  1.1  mrg static rtx
   1219  1.1  mrg bfin_delegitimize_address (rtx orig_x)
   1220  1.1  mrg {
   1221  1.1  mrg   rtx x = orig_x;
   1222  1.1  mrg 
   1223  1.1  mrg   if (GET_CODE (x) != MEM)
   1224  1.1  mrg     return orig_x;
   1225  1.1  mrg 
   1226  1.1  mrg   x = XEXP (x, 0);
   1227  1.1  mrg   if (GET_CODE (x) == PLUS
   1228  1.1  mrg       && GET_CODE (XEXP (x, 1)) == UNSPEC
   1229  1.1  mrg       && XINT (XEXP (x, 1), 1) == UNSPEC_MOVE_PIC
   1230  1.1  mrg       && GET_CODE (XEXP (x, 0)) == REG
   1231  1.1  mrg       && REGNO (XEXP (x, 0)) == PIC_OFFSET_TABLE_REGNUM)
   1232  1.1  mrg     return XVECEXP (XEXP (x, 1), 0, 0);
   1233  1.1  mrg 
   1234  1.1  mrg   return orig_x;
   1235  1.1  mrg }
   1236  1.1  mrg 
   1237  1.1  mrg /* This predicate is used to compute the length of a load/store insn.
   1238  1.1  mrg    OP is a MEM rtx, we return nonzero if its addressing mode requires a
   1239  1.1  mrg    32-bit instruction.  */
   1240  1.1  mrg 
   1241  1.1  mrg int
   1242  1.1  mrg effective_address_32bit_p (rtx op, machine_mode mode)
   1243  1.1  mrg {
   1244  1.1  mrg   HOST_WIDE_INT offset;
   1245  1.1  mrg 
   1246  1.1  mrg   mode = GET_MODE (op);
   1247  1.1  mrg   op = XEXP (op, 0);
   1248  1.1  mrg 
   1249  1.1  mrg   if (GET_CODE (op) != PLUS)
   1250  1.1  mrg     {
   1251  1.1  mrg       gcc_assert (REG_P (op) || GET_CODE (op) == POST_INC
   1252  1.1  mrg 		  || GET_CODE (op) == PRE_DEC || GET_CODE (op) == POST_DEC);
   1253  1.1  mrg       return 0;
   1254  1.1  mrg     }
   1255  1.1  mrg 
   1256  1.1  mrg   if (GET_CODE (XEXP (op, 1)) == UNSPEC)
   1257  1.1  mrg     return 1;
   1258  1.1  mrg 
   1259  1.1  mrg   offset = INTVAL (XEXP (op, 1));
   1260  1.1  mrg 
   1261  1.1  mrg   /* All byte loads use a 16-bit offset.  */
   1262  1.1  mrg   if (GET_MODE_SIZE (mode) == 1)
   1263  1.1  mrg     return 1;
   1264  1.1  mrg 
   1265  1.1  mrg   if (GET_MODE_SIZE (mode) == 4)
   1266  1.1  mrg     {
   1267  1.1  mrg       /* Frame pointer relative loads can use a negative offset, all others
   1268  1.1  mrg 	 are restricted to a small positive one.  */
   1269  1.1  mrg       if (XEXP (op, 0) == frame_pointer_rtx)
   1270  1.1  mrg 	return offset < -128 || offset > 60;
   1271  1.1  mrg       return offset < 0 || offset > 60;
   1272  1.1  mrg     }
   1273  1.1  mrg 
   1274  1.1  mrg   /* Must be HImode now.  */
   1275  1.1  mrg   return offset < 0 || offset > 30;
   1276  1.1  mrg }
   1277  1.1  mrg 
   1278  1.1  mrg /* Returns true if X is a memory reference using an I register.  */
   1279  1.1  mrg bool
   1280  1.1  mrg bfin_dsp_memref_p (rtx x)
   1281  1.1  mrg {
   1282  1.1  mrg   if (! MEM_P (x))
   1283  1.1  mrg     return false;
   1284  1.1  mrg   x = XEXP (x, 0);
   1285  1.1  mrg   if (GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_INC
   1286  1.1  mrg       || GET_CODE (x) == POST_DEC || GET_CODE (x) == PRE_DEC)
   1287  1.1  mrg     x = XEXP (x, 0);
   1288  1.1  mrg   return IREG_P (x);
   1289  1.1  mrg }
   1290  1.1  mrg 
   1291  1.1  mrg /* Return cost of the memory address ADDR.
   1292  1.1  mrg    All addressing modes are equally cheap on the Blackfin.  */
   1293  1.1  mrg 
   1294  1.1  mrg static int
   1295  1.1  mrg bfin_address_cost (rtx addr ATTRIBUTE_UNUSED,
   1296  1.1  mrg 		   machine_mode mode ATTRIBUTE_UNUSED,
   1297  1.1  mrg 		   addr_space_t as ATTRIBUTE_UNUSED,
   1298  1.1  mrg 		   bool speed ATTRIBUTE_UNUSED)
   1299  1.1  mrg {
   1300  1.1  mrg   return 1;
   1301  1.1  mrg }
   1302  1.1  mrg 
   1303  1.1  mrg /* Subroutine of print_operand; used to print a memory reference X to FILE.  */
   1304  1.1  mrg 
   1305  1.1  mrg void
   1306  1.1  mrg print_address_operand (FILE *file, rtx x)
   1307  1.1  mrg {
   1308  1.1  mrg   switch (GET_CODE (x))
   1309  1.1  mrg     {
   1310  1.1  mrg     case PLUS:
   1311  1.1  mrg       output_address (VOIDmode, XEXP (x, 0));
   1312  1.1  mrg       fprintf (file, "+");
   1313  1.1  mrg       output_address (VOIDmode, XEXP (x, 1));
   1314  1.1  mrg       break;
   1315  1.1  mrg 
   1316  1.1  mrg     case PRE_DEC:
   1317  1.1  mrg       fprintf (file, "--");
   1318  1.1  mrg       output_address (VOIDmode, XEXP (x, 0));
   1319  1.1  mrg       break;
   1320  1.1  mrg     case POST_INC:
   1321  1.1  mrg       output_address (VOIDmode, XEXP (x, 0));
   1322  1.1  mrg       fprintf (file, "++");
   1323  1.1  mrg       break;
   1324  1.1  mrg     case POST_DEC:
   1325  1.1  mrg       output_address (VOIDmode, XEXP (x, 0));
   1326  1.1  mrg       fprintf (file, "--");
   1327  1.1  mrg       break;
   1328  1.1  mrg 
   1329  1.1  mrg     default:
   1330  1.1  mrg       gcc_assert (GET_CODE (x) != MEM);
   1331  1.1  mrg       print_operand (file, x, 0);
   1332  1.1  mrg       break;
   1333  1.1  mrg     }
   1334  1.1  mrg }
   1335  1.1  mrg 
   1336  1.1  mrg /* Adding intp DImode support by Tony
   1337  1.1  mrg  * -- Q: (low  word)
   1338  1.1  mrg  * -- R: (high word)
   1339  1.1  mrg  */
   1340  1.1  mrg 
   1341  1.1  mrg void
   1342  1.1  mrg print_operand (FILE *file, rtx x, char code)
   1343  1.1  mrg {
   1344  1.1  mrg   machine_mode mode;
   1345  1.1  mrg 
   1346  1.1  mrg   if (code == '!')
   1347  1.1  mrg     {
   1348  1.1  mrg       if (GET_MODE (current_output_insn) == SImode)
   1349  1.1  mrg 	fprintf (file, " ||");
   1350  1.1  mrg       else
   1351  1.1  mrg 	fprintf (file, ";");
   1352  1.1  mrg       return;
   1353  1.1  mrg     }
   1354  1.1  mrg 
   1355  1.1  mrg   mode = GET_MODE (x);
   1356  1.1  mrg 
   1357  1.1  mrg   switch (code)
   1358  1.1  mrg     {
   1359  1.1  mrg     case 'j':
   1360  1.1  mrg       switch (GET_CODE (x))
   1361  1.1  mrg 	{
   1362  1.1  mrg 	case EQ:
   1363  1.1  mrg 	  fprintf (file, "e");
   1364  1.1  mrg 	  break;
   1365  1.1  mrg 	case NE:
   1366  1.1  mrg 	  fprintf (file, "ne");
   1367  1.1  mrg 	  break;
   1368  1.1  mrg 	case GT:
   1369  1.1  mrg 	  fprintf (file, "g");
   1370  1.1  mrg 	  break;
   1371  1.1  mrg 	case LT:
   1372  1.1  mrg 	  fprintf (file, "l");
   1373  1.1  mrg 	  break;
   1374  1.1  mrg 	case GE:
   1375  1.1  mrg 	  fprintf (file, "ge");
   1376  1.1  mrg 	  break;
   1377  1.1  mrg 	case LE:
   1378  1.1  mrg 	  fprintf (file, "le");
   1379  1.1  mrg 	  break;
   1380  1.1  mrg 	case GTU:
   1381  1.1  mrg 	  fprintf (file, "g");
   1382  1.1  mrg 	  break;
   1383  1.1  mrg 	case LTU:
   1384  1.1  mrg 	  fprintf (file, "l");
   1385  1.1  mrg 	  break;
   1386  1.1  mrg 	case GEU:
   1387  1.1  mrg 	  fprintf (file, "ge");
   1388  1.1  mrg 	  break;
   1389  1.1  mrg 	case LEU:
   1390  1.1  mrg 	  fprintf (file, "le");
   1391  1.1  mrg 	  break;
   1392  1.1  mrg 	default:
   1393  1.1  mrg 	  output_operand_lossage ("invalid %%j value");
   1394  1.1  mrg 	}
   1395  1.1  mrg       break;
   1396  1.1  mrg 
   1397  1.1  mrg     case 'J':					 /* reverse logic */
   1398  1.1  mrg       switch (GET_CODE(x))
   1399  1.1  mrg 	{
   1400  1.1  mrg 	case EQ:
   1401  1.1  mrg 	  fprintf (file, "ne");
   1402  1.1  mrg 	  break;
   1403  1.1  mrg 	case NE:
   1404  1.1  mrg 	  fprintf (file, "e");
   1405  1.1  mrg 	  break;
   1406  1.1  mrg 	case GT:
   1407  1.1  mrg 	  fprintf (file, "le");
   1408  1.1  mrg 	  break;
   1409  1.1  mrg 	case LT:
   1410  1.1  mrg 	  fprintf (file, "ge");
   1411  1.1  mrg 	  break;
   1412  1.1  mrg 	case GE:
   1413  1.1  mrg 	  fprintf (file, "l");
   1414  1.1  mrg 	  break;
   1415  1.1  mrg 	case LE:
   1416  1.1  mrg 	  fprintf (file, "g");
   1417  1.1  mrg 	  break;
   1418  1.1  mrg 	case GTU:
   1419  1.1  mrg 	  fprintf (file, "le");
   1420  1.1  mrg 	  break;
   1421  1.1  mrg 	case LTU:
   1422  1.1  mrg 	  fprintf (file, "ge");
   1423  1.1  mrg 	  break;
   1424  1.1  mrg 	case GEU:
   1425  1.1  mrg 	  fprintf (file, "l");
   1426  1.1  mrg 	  break;
   1427  1.1  mrg 	case LEU:
   1428  1.1  mrg 	  fprintf (file, "g");
   1429  1.1  mrg 	  break;
   1430  1.1  mrg 	default:
   1431  1.1  mrg 	  output_operand_lossage ("invalid %%J value");
   1432  1.1  mrg 	}
   1433  1.1  mrg       break;
   1434  1.1  mrg 
   1435  1.1  mrg     default:
   1436  1.1  mrg       switch (GET_CODE (x))
   1437  1.1  mrg 	{
   1438  1.1  mrg 	case REG:
   1439  1.1  mrg 	  if (code == 'h')
   1440  1.1  mrg 	    {
   1441  1.1  mrg 	      if (REGNO (x) < 32)
   1442  1.1  mrg 		fprintf (file, "%s", short_reg_names[REGNO (x)]);
   1443  1.1  mrg 	      else
   1444  1.1  mrg 		output_operand_lossage ("invalid operand for code '%c'", code);
   1445  1.1  mrg 	    }
   1446  1.1  mrg 	  else if (code == 'd')
   1447  1.1  mrg 	    {
   1448  1.1  mrg 	      if (REGNO (x) < 32)
   1449  1.1  mrg 		fprintf (file, "%s", high_reg_names[REGNO (x)]);
   1450  1.1  mrg 	      else
   1451  1.1  mrg 		output_operand_lossage ("invalid operand for code '%c'", code);
   1452  1.1  mrg 	    }
   1453  1.1  mrg 	  else if (code == 'w')
   1454  1.1  mrg 	    {
   1455  1.1  mrg 	      if (REGNO (x) == REG_A0 || REGNO (x) == REG_A1)
   1456  1.1  mrg 		fprintf (file, "%s.w", reg_names[REGNO (x)]);
   1457  1.1  mrg 	      else
   1458  1.1  mrg 		output_operand_lossage ("invalid operand for code '%c'", code);
   1459  1.1  mrg 	    }
   1460  1.1  mrg 	  else if (code == 'x')
   1461  1.1  mrg 	    {
   1462  1.1  mrg 	      if (REGNO (x) == REG_A0 || REGNO (x) == REG_A1)
   1463  1.1  mrg 		fprintf (file, "%s.x", reg_names[REGNO (x)]);
   1464  1.1  mrg 	      else
   1465  1.1  mrg 		output_operand_lossage ("invalid operand for code '%c'", code);
   1466  1.1  mrg 	    }
   1467  1.1  mrg 	  else if (code == 'v')
   1468  1.1  mrg 	    {
   1469  1.1  mrg 	      if (REGNO (x) == REG_A0)
   1470  1.1  mrg 		fprintf (file, "AV0");
   1471  1.1  mrg 	      else if (REGNO (x) == REG_A1)
   1472  1.1  mrg 		fprintf (file, "AV1");
   1473  1.1  mrg 	      else
   1474  1.1  mrg 		output_operand_lossage ("invalid operand for code '%c'", code);
   1475  1.1  mrg 	    }
   1476  1.1  mrg 	  else if (code == 'D')
   1477  1.1  mrg 	    {
   1478  1.1  mrg 	      if (D_REGNO_P (REGNO (x)))
   1479  1.1  mrg 		fprintf (file, "%s", dregs_pair_names[REGNO (x)]);
   1480  1.1  mrg 	      else
   1481  1.1  mrg 		output_operand_lossage ("invalid operand for code '%c'", code);
   1482  1.1  mrg 	    }
   1483  1.1  mrg 	  else if (code == 'H')
   1484  1.1  mrg 	    {
   1485  1.1  mrg 	      if ((mode == DImode || mode == DFmode) && REG_P (x))
   1486  1.1  mrg 		fprintf (file, "%s", reg_names[REGNO (x) + 1]);
   1487  1.1  mrg 	      else
   1488  1.1  mrg 		output_operand_lossage ("invalid operand for code '%c'", code);
   1489  1.1  mrg 	    }
   1490  1.1  mrg 	  else if (code == 'T')
   1491  1.1  mrg 	    {
   1492  1.1  mrg 	      if (D_REGNO_P (REGNO (x)))
   1493  1.1  mrg 		fprintf (file, "%s", byte_reg_names[REGNO (x)]);
   1494  1.1  mrg 	      else
   1495  1.1  mrg 		output_operand_lossage ("invalid operand for code '%c'", code);
   1496  1.1  mrg 	    }
   1497  1.1  mrg 	  else
   1498  1.1  mrg 	    fprintf (file, "%s", reg_names[REGNO (x)]);
   1499  1.1  mrg 	  break;
   1500  1.1  mrg 
   1501  1.1  mrg 	case MEM:
   1502  1.1  mrg 	  fputc ('[', file);
   1503  1.1  mrg 	  x = XEXP (x,0);
   1504  1.1  mrg 	  print_address_operand (file, x);
   1505  1.1  mrg 	  fputc (']', file);
   1506  1.1  mrg 	  break;
   1507  1.1  mrg 
   1508  1.1  mrg 	case CONST_INT:
   1509  1.1  mrg 	  if (code == 'M')
   1510  1.1  mrg 	    {
   1511  1.1  mrg 	      switch (INTVAL (x))
   1512  1.1  mrg 		{
   1513  1.1  mrg 		case MACFLAG_NONE:
   1514  1.1  mrg 		  break;
   1515  1.1  mrg 		case MACFLAG_FU:
   1516  1.1  mrg 		  fputs ("(FU)", file);
   1517  1.1  mrg 		  break;
   1518  1.1  mrg 		case MACFLAG_T:
   1519  1.1  mrg 		  fputs ("(T)", file);
   1520  1.1  mrg 		  break;
   1521  1.1  mrg 		case MACFLAG_TFU:
   1522  1.1  mrg 		  fputs ("(TFU)", file);
   1523  1.1  mrg 		  break;
   1524  1.1  mrg 		case MACFLAG_W32:
   1525  1.1  mrg 		  fputs ("(W32)", file);
   1526  1.1  mrg 		  break;
   1527  1.1  mrg 		case MACFLAG_IS:
   1528  1.1  mrg 		  fputs ("(IS)", file);
   1529  1.1  mrg 		  break;
   1530  1.1  mrg 		case MACFLAG_IU:
   1531  1.1  mrg 		  fputs ("(IU)", file);
   1532  1.1  mrg 		  break;
   1533  1.1  mrg 		case MACFLAG_IH:
   1534  1.1  mrg 		  fputs ("(IH)", file);
   1535  1.1  mrg 		  break;
   1536  1.1  mrg 		case MACFLAG_M:
   1537  1.1  mrg 		  fputs ("(M)", file);
   1538  1.1  mrg 		  break;
   1539  1.1  mrg 		case MACFLAG_IS_M:
   1540  1.1  mrg 		  fputs ("(IS,M)", file);
   1541  1.1  mrg 		  break;
   1542  1.1  mrg 		case MACFLAG_ISS2:
   1543  1.1  mrg 		  fputs ("(ISS2)", file);
   1544  1.1  mrg 		  break;
   1545  1.1  mrg 		case MACFLAG_S2RND:
   1546  1.1  mrg 		  fputs ("(S2RND)", file);
   1547  1.1  mrg 		  break;
   1548  1.1  mrg 		default:
   1549  1.1  mrg 		  gcc_unreachable ();
   1550  1.1  mrg 		}
   1551  1.1  mrg 	      break;
   1552  1.1  mrg 	    }
   1553  1.1  mrg 	  else if (code == 'b')
   1554  1.1  mrg 	    {
   1555  1.1  mrg 	      if (INTVAL (x) == 0)
   1556  1.1  mrg 		fputs ("+=", file);
   1557  1.1  mrg 	      else if (INTVAL (x) == 1)
   1558  1.1  mrg 		fputs ("-=", file);
   1559  1.1  mrg 	      else
   1560  1.1  mrg 		gcc_unreachable ();
   1561  1.1  mrg 	      break;
   1562  1.1  mrg 	    }
   1563  1.1  mrg 	  /* Moves to half registers with d or h modifiers always use unsigned
   1564  1.1  mrg 	     constants.  */
   1565  1.1  mrg 	  else if (code == 'd')
   1566  1.1  mrg 	    x = GEN_INT ((INTVAL (x) >> 16) & 0xffff);
   1567  1.1  mrg 	  else if (code == 'h')
   1568  1.1  mrg 	    x = GEN_INT (INTVAL (x) & 0xffff);
   1569  1.1  mrg 	  else if (code == 'N')
   1570  1.1  mrg 	    x = GEN_INT (-INTVAL (x));
   1571  1.1  mrg 	  else if (code == 'X')
   1572  1.1  mrg 	    x = GEN_INT (exact_log2 (0xffffffff & INTVAL (x)));
   1573  1.1  mrg 	  else if (code == 'Y')
   1574  1.1  mrg 	    x = GEN_INT (exact_log2 (0xffffffff & ~INTVAL (x)));
   1575  1.1  mrg 	  else if (code == 'Z')
   1576  1.1  mrg 	    /* Used for LINK insns.  */
   1577  1.1  mrg 	    x = GEN_INT (-8 - INTVAL (x));
   1578  1.1  mrg 
   1579  1.1  mrg 	  /* fall through */
   1580  1.1  mrg 
   1581  1.1  mrg 	case SYMBOL_REF:
   1582  1.1  mrg 	  output_addr_const (file, x);
   1583  1.1  mrg 	  break;
   1584  1.1  mrg 
   1585  1.1  mrg 	case CONST_DOUBLE:
   1586  1.1  mrg 	  output_operand_lossage ("invalid const_double operand");
   1587  1.1  mrg 	  break;
   1588  1.1  mrg 
   1589  1.1  mrg 	case UNSPEC:
   1590  1.1  mrg 	  switch (XINT (x, 1))
   1591  1.1  mrg 	    {
   1592  1.1  mrg 	    case UNSPEC_MOVE_PIC:
   1593  1.1  mrg 	      output_addr_const (file, XVECEXP (x, 0, 0));
   1594  1.1  mrg 	      fprintf (file, "@GOT");
   1595  1.1  mrg 	      break;
   1596  1.1  mrg 
   1597  1.1  mrg 	    case UNSPEC_MOVE_FDPIC:
   1598  1.1  mrg 	      output_addr_const (file, XVECEXP (x, 0, 0));
   1599  1.1  mrg 	      fprintf (file, "@GOT17M4");
   1600  1.1  mrg 	      break;
   1601  1.1  mrg 
   1602  1.1  mrg 	    case UNSPEC_FUNCDESC_GOT17M4:
   1603  1.1  mrg 	      output_addr_const (file, XVECEXP (x, 0, 0));
   1604  1.1  mrg 	      fprintf (file, "@FUNCDESC_GOT17M4");
   1605  1.1  mrg 	      break;
   1606  1.1  mrg 
   1607  1.1  mrg 	    case UNSPEC_LIBRARY_OFFSET:
   1608  1.1  mrg 	      fprintf (file, "_current_shared_library_p5_offset_");
   1609  1.1  mrg 	      break;
   1610  1.1  mrg 
   1611  1.1  mrg 	    default:
   1612  1.1  mrg 	      gcc_unreachable ();
   1613  1.1  mrg 	    }
   1614  1.1  mrg 	  break;
   1615  1.1  mrg 
   1616  1.1  mrg 	default:
   1617  1.1  mrg 	  output_addr_const (file, x);
   1618  1.1  mrg 	}
   1619  1.1  mrg     }
   1620  1.1  mrg }
   1621  1.1  mrg 
   1622  1.1  mrg /* Argument support functions.  */
   1624  1.1  mrg 
   1625  1.1  mrg /* Initialize a variable CUM of type CUMULATIVE_ARGS
   1626  1.1  mrg    for a call to a function whose data type is FNTYPE.
   1627  1.1  mrg    For a library call, FNTYPE is 0.
   1628  1.1  mrg    VDSP C Compiler manual, our ABI says that
   1629  1.1  mrg    first 3 words of arguments will use R0, R1 and R2.
   1630  1.1  mrg */
   1631  1.1  mrg 
   1632  1.1  mrg void
   1633  1.1  mrg init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
   1634  1.1  mrg 		      rtx libname ATTRIBUTE_UNUSED)
   1635  1.1  mrg {
   1636  1.1  mrg   static CUMULATIVE_ARGS zero_cum;
   1637  1.1  mrg 
   1638  1.1  mrg   *cum = zero_cum;
   1639  1.1  mrg 
   1640  1.1  mrg   /* Set up the number of registers to use for passing arguments.  */
   1641  1.1  mrg 
   1642  1.1  mrg   cum->nregs = max_arg_registers;
   1643  1.1  mrg   cum->arg_regs = arg_regs;
   1644  1.1  mrg 
   1645  1.1  mrg   cum->call_cookie = CALL_NORMAL;
   1646  1.1  mrg   /* Check for a longcall attribute.  */
   1647  1.1  mrg   if (fntype && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype)))
   1648  1.1  mrg     cum->call_cookie |= CALL_SHORT;
   1649  1.1  mrg   else if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)))
   1650  1.1  mrg     cum->call_cookie |= CALL_LONG;
   1651  1.1  mrg 
   1652  1.1  mrg   return;
   1653  1.1  mrg }
   1654  1.1  mrg 
   1655  1.1  mrg /* Update the data in CUM to advance over argument ARG.  */
   1656  1.1  mrg 
   1657  1.1  mrg static void
   1658  1.1  mrg bfin_function_arg_advance (cumulative_args_t cum_v,
   1659  1.1  mrg 			   const function_arg_info &arg)
   1660  1.1  mrg {
   1661  1.1  mrg   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   1662  1.1  mrg   int count, bytes, words;
   1663  1.1  mrg 
   1664  1.1  mrg   bytes = arg.promoted_size_in_bytes ();
   1665  1.1  mrg   words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
   1666  1.1  mrg 
   1667  1.1  mrg   cum->words += words;
   1668  1.1  mrg   cum->nregs -= words;
   1669  1.1  mrg 
   1670  1.1  mrg   if (cum->nregs <= 0)
   1671  1.1  mrg     {
   1672  1.1  mrg       cum->nregs = 0;
   1673  1.1  mrg       cum->arg_regs = NULL;
   1674  1.1  mrg     }
   1675  1.1  mrg   else
   1676  1.1  mrg     {
   1677  1.1  mrg       for (count = 1; count <= words; count++)
   1678  1.1  mrg         cum->arg_regs++;
   1679  1.1  mrg     }
   1680  1.1  mrg 
   1681  1.1  mrg   return;
   1682  1.1  mrg }
   1683  1.1  mrg 
   1684  1.1  mrg /* Define where to put the arguments to a function.
   1685  1.1  mrg    Value is zero to push the argument on the stack,
   1686  1.1  mrg    or a hard register in which to store the argument.
   1687  1.1  mrg 
   1688  1.1  mrg    CUM is a variable of type CUMULATIVE_ARGS which gives info about
   1689  1.1  mrg     the preceding args and about the function being called.
   1690  1.1  mrg    ARG is a description of the argument.  */
   1691  1.1  mrg 
   1692  1.1  mrg static rtx
   1693  1.1  mrg bfin_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
   1694  1.1  mrg {
   1695  1.1  mrg   CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
   1696  1.1  mrg   int bytes = arg.promoted_size_in_bytes ();
   1697  1.1  mrg 
   1698  1.1  mrg   if (arg.end_marker_p ())
   1699  1.1  mrg     /* Compute operand 2 of the call insn.  */
   1700  1.1  mrg     return GEN_INT (cum->call_cookie);
   1701  1.1  mrg 
   1702  1.1  mrg   if (bytes == -1)
   1703  1.1  mrg     return NULL_RTX;
   1704  1.1  mrg 
   1705  1.1  mrg   if (cum->nregs)
   1706  1.1  mrg     return gen_rtx_REG (arg.mode, *(cum->arg_regs));
   1707  1.1  mrg 
   1708  1.1  mrg   return NULL_RTX;
   1709  1.1  mrg }
   1710  1.1  mrg 
   1711  1.1  mrg /* For an arg passed partly in registers and partly in memory,
   1712  1.1  mrg    this is the number of bytes passed in registers.
   1713  1.1  mrg    For args passed entirely in registers or entirely in memory, zero.
   1714  1.1  mrg 
   1715  1.1  mrg    Refer VDSP C Compiler manual, our ABI.
   1716  1.1  mrg    First 3 words are in registers. So, if an argument is larger
   1717  1.1  mrg    than the registers available, it will span the register and
   1718  1.1  mrg    stack.   */
   1719  1.1  mrg 
   1720  1.1  mrg static int
   1721  1.1  mrg bfin_arg_partial_bytes (cumulative_args_t cum, const function_arg_info &arg)
   1722  1.1  mrg {
   1723  1.1  mrg   int bytes = arg.promoted_size_in_bytes ();
   1724  1.1  mrg   int bytes_left = get_cumulative_args (cum)->nregs * UNITS_PER_WORD;
   1725  1.1  mrg 
   1726  1.1  mrg   if (bytes == -1)
   1727  1.1  mrg     return 0;
   1728  1.1  mrg 
   1729  1.1  mrg   if (bytes_left == 0)
   1730  1.1  mrg     return 0;
   1731  1.1  mrg   if (bytes > bytes_left)
   1732  1.1  mrg     return bytes_left;
   1733  1.1  mrg   return 0;
   1734  1.1  mrg }
   1735  1.1  mrg 
   1736  1.1  mrg /* Variable sized types are passed by reference.  */
   1737  1.1  mrg 
   1738  1.1  mrg static bool
   1739  1.1  mrg bfin_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
   1740  1.1  mrg {
   1741  1.1  mrg   return arg.type && TREE_CODE (TYPE_SIZE (arg.type)) != INTEGER_CST;
   1742  1.1  mrg }
   1743  1.1  mrg 
   1744  1.1  mrg /* Decide whether a type should be returned in memory (true)
   1745  1.1  mrg    or in a register (false).  This is called by the macro
   1746  1.1  mrg    TARGET_RETURN_IN_MEMORY.  */
   1747  1.1  mrg 
   1748  1.1  mrg static bool
   1749  1.1  mrg bfin_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
   1750  1.1  mrg {
   1751  1.1  mrg   int size = int_size_in_bytes (type);
   1752  1.1  mrg   return size > 2 * UNITS_PER_WORD || size == -1;
   1753  1.1  mrg }
   1754  1.1  mrg 
   1755  1.1  mrg /* Register in which address to store a structure value
   1756  1.1  mrg    is passed to a function.  */
   1757  1.1  mrg static rtx
   1758  1.1  mrg bfin_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
   1759  1.1  mrg 		      int incoming ATTRIBUTE_UNUSED)
   1760  1.1  mrg {
   1761  1.1  mrg   return gen_rtx_REG (Pmode, REG_P0);
   1762  1.1  mrg }
   1763  1.1  mrg 
   1764  1.1  mrg /* Return true when register may be used to pass function parameters.  */
   1765  1.1  mrg 
   1766  1.1  mrg bool
   1767  1.1  mrg function_arg_regno_p (int n)
   1768  1.1  mrg {
   1769  1.1  mrg   int i;
   1770  1.1  mrg   for (i = 0; arg_regs[i] != -1; i++)
   1771  1.1  mrg     if (n == arg_regs[i])
   1772  1.1  mrg       return true;
   1773  1.1  mrg   return false;
   1774  1.1  mrg }
   1775  1.1  mrg 
   1776  1.1  mrg /* Returns 1 if OP contains a symbol reference */
   1777  1.1  mrg 
   1778  1.1  mrg int
   1779  1.1  mrg symbolic_reference_mentioned_p (rtx op)
   1780  1.1  mrg {
   1781  1.1  mrg   const char *fmt;
   1782  1.1  mrg   int i;
   1783  1.1  mrg 
   1784  1.1  mrg   if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
   1785  1.1  mrg     return 1;
   1786  1.1  mrg 
   1787  1.1  mrg   fmt = GET_RTX_FORMAT (GET_CODE (op));
   1788  1.1  mrg   for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
   1789  1.1  mrg     {
   1790  1.1  mrg       if (fmt[i] == 'E')
   1791  1.1  mrg 	{
   1792  1.1  mrg 	  int j;
   1793  1.1  mrg 
   1794  1.1  mrg 	  for (j = XVECLEN (op, i) - 1; j >= 0; j--)
   1795  1.1  mrg 	    if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
   1796  1.1  mrg 	      return 1;
   1797  1.1  mrg 	}
   1798  1.1  mrg 
   1799  1.1  mrg       else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
   1800  1.1  mrg 	return 1;
   1801  1.1  mrg     }
   1802  1.1  mrg 
   1803  1.1  mrg   return 0;
   1804  1.1  mrg }
   1805  1.1  mrg 
   1806  1.1  mrg /* Decide whether we can make a sibling call to a function.  DECL is the
   1807  1.1  mrg    declaration of the function being targeted by the call and EXP is the
   1808  1.1  mrg    CALL_EXPR representing the call.  */
   1809  1.1  mrg 
   1810  1.1  mrg static bool
   1811  1.1  mrg bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
   1812  1.1  mrg 			      tree exp ATTRIBUTE_UNUSED)
   1813  1.1  mrg {
   1814  1.1  mrg   cgraph_node *this_func, *called_func;
   1815  1.1  mrg   e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
   1816  1.1  mrg   if (fkind != SUBROUTINE)
   1817  1.1  mrg     return false;
   1818  1.1  mrg   if (!TARGET_ID_SHARED_LIBRARY || TARGET_SEP_DATA)
   1819  1.1  mrg     return true;
   1820  1.1  mrg 
   1821  1.1  mrg   /* When compiling for ID shared libraries, can't sibcall a local function
   1822  1.1  mrg      from a non-local function, because the local function thinks it does
   1823  1.1  mrg      not need to reload P5 in the prologue, but the sibcall wil pop P5 in the
   1824  1.1  mrg      sibcall epilogue, and we end up with the wrong value in P5.  */
   1825  1.1  mrg 
   1826  1.1  mrg   if (!decl)
   1827  1.1  mrg     /* Not enough information.  */
   1828  1.1  mrg     return false;
   1829  1.1  mrg 
   1830  1.1  mrg   this_func = cgraph_node::local_info_node (current_function_decl);
   1831  1.1  mrg   called_func = cgraph_node::local_info_node (decl);
   1832  1.1  mrg   if (!called_func)
   1833  1.1  mrg     return false;
   1834  1.1  mrg   return !called_func->local || this_func->local;
   1835  1.1  mrg }
   1836  1.1  mrg 
   1837  1.1  mrg /* Write a template for a trampoline to F.  */
   1839  1.1  mrg 
   1840  1.1  mrg static void
   1841  1.1  mrg bfin_asm_trampoline_template (FILE *f)
   1842  1.1  mrg {
   1843  1.1  mrg   if (TARGET_FDPIC)
   1844  1.1  mrg     {
   1845  1.1  mrg       fprintf (f, "\t.dd\t0x00000000\n");	/* 0 */
   1846  1.1  mrg       fprintf (f, "\t.dd\t0x00000000\n");	/* 0 */
   1847  1.1  mrg       fprintf (f, "\t.dd\t0x0000e109\n");	/* p1.l = fn low */
   1848  1.1  mrg       fprintf (f, "\t.dd\t0x0000e149\n");	/* p1.h = fn high */
   1849  1.1  mrg       fprintf (f, "\t.dd\t0x0000e10a\n");	/* p2.l = sc low */
   1850  1.1  mrg       fprintf (f, "\t.dd\t0x0000e14a\n");	/* p2.h = sc high */
   1851  1.1  mrg       fprintf (f, "\t.dw\t0xac4b\n");		/* p3 = [p1 + 4] */
   1852  1.1  mrg       fprintf (f, "\t.dw\t0x9149\n");		/* p1 = [p1] */
   1853  1.1  mrg       fprintf (f, "\t.dw\t0x0051\n");		/* jump (p1)*/
   1854  1.1  mrg     }
   1855  1.1  mrg   else
   1856  1.1  mrg     {
   1857  1.1  mrg       fprintf (f, "\t.dd\t0x0000e109\n");	/* p1.l = fn low */
   1858  1.1  mrg       fprintf (f, "\t.dd\t0x0000e149\n");	/* p1.h = fn high */
   1859  1.1  mrg       fprintf (f, "\t.dd\t0x0000e10a\n");	/* p2.l = sc low */
   1860  1.1  mrg       fprintf (f, "\t.dd\t0x0000e14a\n");	/* p2.h = sc high */
   1861  1.1  mrg       fprintf (f, "\t.dw\t0x0051\n");		/* jump (p1)*/
   1862  1.1  mrg     }
   1863  1.1  mrg }
   1864  1.1  mrg 
   1865  1.1  mrg /* Emit RTL insns to initialize the variable parts of a trampoline at
   1866  1.1  mrg    M_TRAMP. FNDECL is the target function.  CHAIN_VALUE is an RTX for
   1867  1.1  mrg    the static chain value for the function.  */
   1868  1.1  mrg 
   1869  1.1  mrg static void
   1870  1.1  mrg bfin_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
   1871  1.1  mrg {
   1872  1.1  mrg   rtx t1 = copy_to_reg (XEXP (DECL_RTL (fndecl), 0));
   1873  1.1  mrg   rtx t2 = copy_to_reg (chain_value);
   1874  1.1  mrg   rtx mem;
   1875  1.1  mrg   int i = 0;
   1876  1.1  mrg 
   1877  1.1  mrg   emit_block_move (m_tramp, assemble_trampoline_template (),
   1878  1.1  mrg 		   GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
   1879  1.1  mrg 
   1880  1.1  mrg   if (TARGET_FDPIC)
   1881  1.1  mrg     {
   1882  1.1  mrg       rtx a = force_reg (Pmode, plus_constant (Pmode, XEXP (m_tramp, 0), 8));
   1883  1.1  mrg       mem = adjust_address (m_tramp, Pmode, 0);
   1884  1.1  mrg       emit_move_insn (mem, a);
   1885  1.1  mrg       i = 8;
   1886  1.1  mrg     }
   1887  1.1  mrg 
   1888  1.1  mrg   mem = adjust_address (m_tramp, HImode, i + 2);
   1889  1.1  mrg   emit_move_insn (mem, gen_lowpart (HImode, t1));
   1890  1.1  mrg   emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16)));
   1891  1.1  mrg   mem = adjust_address (m_tramp, HImode, i + 6);
   1892  1.1  mrg   emit_move_insn (mem, gen_lowpart (HImode, t1));
   1893  1.1  mrg 
   1894  1.1  mrg   mem = adjust_address (m_tramp, HImode, i + 10);
   1895  1.1  mrg   emit_move_insn (mem, gen_lowpart (HImode, t2));
   1896  1.1  mrg   emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16)));
   1897  1.1  mrg   mem = adjust_address (m_tramp, HImode, i + 14);
   1898  1.1  mrg   emit_move_insn (mem, gen_lowpart (HImode, t2));
   1899  1.1  mrg }
   1900  1.1  mrg 
   1901  1.1  mrg /* Emit insns to move operands[1] into operands[0].  */
   1902  1.1  mrg 
   1903  1.1  mrg void
   1904  1.1  mrg emit_pic_move (rtx *operands, machine_mode mode ATTRIBUTE_UNUSED)
   1905  1.1  mrg {
   1906  1.1  mrg   rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
   1907  1.1  mrg 
   1908  1.1  mrg   gcc_assert (!TARGET_FDPIC || !(reload_in_progress || reload_completed));
   1909  1.1  mrg   if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
   1910  1.1  mrg     operands[1] = force_reg (SImode, operands[1]);
   1911  1.1  mrg   else
   1912  1.1  mrg     operands[1] = legitimize_pic_address (operands[1], temp,
   1913  1.1  mrg 					  TARGET_FDPIC ? OUR_FDPIC_REG
   1914  1.1  mrg 					  : pic_offset_table_rtx);
   1915  1.1  mrg }
   1916  1.1  mrg 
   1917  1.1  mrg /* Expand a move operation in mode MODE.  The operands are in OPERANDS.
   1918  1.1  mrg    Returns true if no further code must be generated, false if the caller
   1919  1.1  mrg    should generate an insn to move OPERANDS[1] to OPERANDS[0].  */
   1920  1.1  mrg 
   1921  1.1  mrg bool
   1922  1.1  mrg expand_move (rtx *operands, machine_mode mode)
   1923  1.1  mrg {
   1924  1.1  mrg   rtx op = operands[1];
   1925  1.1  mrg   if ((TARGET_ID_SHARED_LIBRARY || TARGET_FDPIC)
   1926  1.1  mrg       && SYMBOLIC_CONST (op))
   1927  1.1  mrg     emit_pic_move (operands, mode);
   1928  1.1  mrg   else if (mode == SImode && GET_CODE (op) == CONST
   1929  1.1  mrg 	   && GET_CODE (XEXP (op, 0)) == PLUS
   1930  1.1  mrg 	   && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
   1931  1.1  mrg 	   && !targetm.legitimate_constant_p (mode, op))
   1932  1.1  mrg     {
   1933  1.1  mrg       rtx dest = operands[0];
   1934  1.1  mrg       rtx op0, op1;
   1935  1.1  mrg       gcc_assert (!reload_in_progress && !reload_completed);
   1936  1.1  mrg       op = XEXP (op, 0);
   1937  1.1  mrg       op0 = force_reg (mode, XEXP (op, 0));
   1938  1.1  mrg       op1 = XEXP (op, 1);
   1939  1.1  mrg       if (!insn_data[CODE_FOR_addsi3].operand[2].predicate (op1, mode))
   1940  1.1  mrg 	op1 = force_reg (mode, op1);
   1941  1.1  mrg       if (GET_CODE (dest) == MEM)
   1942  1.1  mrg 	dest = gen_reg_rtx (mode);
   1943  1.1  mrg       emit_insn (gen_addsi3 (dest, op0, op1));
   1944  1.1  mrg       if (dest == operands[0])
   1945  1.1  mrg 	return true;
   1946  1.1  mrg       operands[1] = dest;
   1947  1.1  mrg     }
   1948  1.1  mrg   /* Don't generate memory->memory or constant->memory moves, go through a
   1949  1.1  mrg      register */
   1950  1.1  mrg   else if ((reload_in_progress | reload_completed) == 0
   1951  1.1  mrg 	   && GET_CODE (operands[0]) == MEM
   1952  1.1  mrg     	   && GET_CODE (operands[1]) != REG)
   1953  1.1  mrg     operands[1] = force_reg (mode, operands[1]);
   1954  1.1  mrg   return false;
   1955  1.1  mrg }
   1956  1.1  mrg 
   1957  1.1  mrg /* Split one or more DImode RTL references into pairs of SImode
   1959  1.1  mrg    references.  The RTL can be REG, offsettable MEM, integer constant, or
   1960  1.1  mrg    CONST_DOUBLE.  "operands" is a pointer to an array of DImode RTL to
   1961  1.1  mrg    split and "num" is its length.  lo_half and hi_half are output arrays
   1962  1.1  mrg    that parallel "operands".  */
   1963  1.1  mrg 
   1964  1.1  mrg void
   1965  1.1  mrg split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
   1966  1.1  mrg {
   1967  1.1  mrg   while (num--)
   1968  1.1  mrg     {
   1969  1.1  mrg       rtx op = operands[num];
   1970  1.1  mrg 
   1971  1.1  mrg       /* simplify_subreg refuse to split volatile memory addresses,
   1972  1.1  mrg          but we still have to handle it.  */
   1973  1.1  mrg       if (GET_CODE (op) == MEM)
   1974  1.1  mrg 	{
   1975  1.1  mrg 	  lo_half[num] = adjust_address (op, SImode, 0);
   1976  1.1  mrg 	  hi_half[num] = adjust_address (op, SImode, 4);
   1977  1.1  mrg 	}
   1978  1.1  mrg       else
   1979  1.1  mrg 	{
   1980  1.1  mrg 	  lo_half[num] = simplify_gen_subreg (SImode, op,
   1981  1.1  mrg 					      GET_MODE (op) == VOIDmode
   1982  1.1  mrg 					      ? DImode : GET_MODE (op), 0);
   1983  1.1  mrg 	  hi_half[num] = simplify_gen_subreg (SImode, op,
   1984  1.1  mrg 					      GET_MODE (op) == VOIDmode
   1985  1.1  mrg 					      ? DImode : GET_MODE (op), 4);
   1986  1.1  mrg 	}
   1987  1.1  mrg     }
   1988  1.1  mrg }
   1989  1.1  mrg 
   1990  1.1  mrg bool
   1992  1.1  mrg bfin_longcall_p (rtx op, int call_cookie)
   1993  1.1  mrg {
   1994  1.1  mrg   gcc_assert (GET_CODE (op) == SYMBOL_REF);
   1995  1.1  mrg   if (SYMBOL_REF_WEAK (op))
   1996  1.1  mrg     return 1;
   1997  1.1  mrg   if (call_cookie & CALL_SHORT)
   1998  1.1  mrg     return 0;
   1999  1.1  mrg   if (call_cookie & CALL_LONG)
   2000  1.1  mrg     return 1;
   2001  1.1  mrg   if (TARGET_LONG_CALLS)
   2002  1.1  mrg     return 1;
   2003  1.1  mrg   return 0;
   2004  1.1  mrg }
   2005  1.1  mrg 
   2006  1.1  mrg /* Expand a call instruction.  FNADDR is the call target, RETVAL the return value.
   2007  1.1  mrg    COOKIE is a CONST_INT holding the call_cookie prepared init_cumulative_args.
   2008  1.1  mrg    SIBCALL is nonzero if this is a sibling call.  */
   2009  1.1  mrg 
   2010  1.1  mrg void
   2011  1.1  mrg bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
   2012  1.1  mrg {
   2013  1.1  mrg   rtx use = NULL, call;
   2014  1.1  mrg   rtx callee = XEXP (fnaddr, 0);
   2015  1.1  mrg   int nelts = 3;
   2016  1.1  mrg   rtx pat;
   2017  1.1  mrg   rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REGNO);
   2018  1.1  mrg   rtx retsreg = gen_rtx_REG (Pmode, REG_RETS);
   2019  1.1  mrg   int n;
   2020  1.1  mrg 
   2021  1.1  mrg   /* In an untyped call, we can get NULL for operand 2.  */
   2022  1.1  mrg   if (cookie == NULL_RTX)
   2023  1.1  mrg     cookie = const0_rtx;
   2024  1.1  mrg 
   2025  1.1  mrg   /* Static functions and indirect calls don't need the pic register.  */
   2026  1.1  mrg   if (!TARGET_FDPIC && flag_pic
   2027  1.1  mrg       && GET_CODE (callee) == SYMBOL_REF
   2028  1.1  mrg       && !SYMBOL_REF_LOCAL_P (callee))
   2029  1.1  mrg     use_reg (&use, pic_offset_table_rtx);
   2030  1.1  mrg 
   2031  1.1  mrg   if (TARGET_FDPIC)
   2032  1.1  mrg     {
   2033  1.1  mrg       int caller_in_sram, callee_in_sram;
   2034  1.1  mrg 
   2035  1.1  mrg       /* 0 is not in sram, 1 is in L1 sram, 2 is in L2 sram.  */
   2036  1.1  mrg       caller_in_sram = callee_in_sram = 0;
   2037  1.1  mrg 
   2038  1.1  mrg       if (lookup_attribute ("l1_text",
   2039  1.1  mrg 			    DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE)
   2040  1.1  mrg 	caller_in_sram = 1;
   2041  1.1  mrg       else if (lookup_attribute ("l2",
   2042  1.1  mrg 				 DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE)
   2043  1.1  mrg 	caller_in_sram = 2;
   2044  1.1  mrg 
   2045  1.1  mrg       if (GET_CODE (callee) == SYMBOL_REF
   2046  1.1  mrg 	  && SYMBOL_REF_DECL (callee) && DECL_P (SYMBOL_REF_DECL (callee)))
   2047  1.1  mrg 	{
   2048  1.1  mrg 	  if (lookup_attribute
   2049  1.1  mrg 	      ("l1_text",
   2050  1.1  mrg 	       DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE)
   2051  1.1  mrg 	    callee_in_sram = 1;
   2052  1.1  mrg 	  else if (lookup_attribute
   2053  1.1  mrg 		   ("l2",
   2054  1.1  mrg 		    DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE)
   2055  1.1  mrg 	    callee_in_sram = 2;
   2056  1.1  mrg 	}
   2057  1.1  mrg 
   2058  1.1  mrg       if (GET_CODE (callee) != SYMBOL_REF
   2059  1.1  mrg 	  || bfin_longcall_p (callee, INTVAL (cookie))
   2060  1.1  mrg 	  || (GET_CODE (callee) == SYMBOL_REF
   2061  1.1  mrg 	      && !SYMBOL_REF_LOCAL_P (callee)
   2062  1.1  mrg 	      && TARGET_INLINE_PLT)
   2063  1.1  mrg 	  || caller_in_sram != callee_in_sram
   2064  1.1  mrg 	  || (caller_in_sram && callee_in_sram
   2065  1.1  mrg 	      && (GET_CODE (callee) != SYMBOL_REF
   2066  1.1  mrg 		  || !SYMBOL_REF_LOCAL_P (callee))))
   2067  1.1  mrg 	{
   2068  1.1  mrg 	  rtx addr = callee;
   2069  1.1  mrg 	  if (! address_operand (addr, Pmode))
   2070  1.1  mrg 	    addr = force_reg (Pmode, addr);
   2071  1.1  mrg 
   2072  1.1  mrg 	  fnaddr = gen_reg_rtx (SImode);
   2073  1.1  mrg 	  emit_insn (gen_load_funcdescsi (fnaddr, addr));
   2074  1.1  mrg 	  fnaddr = gen_rtx_MEM (Pmode, fnaddr);
   2075  1.1  mrg 
   2076  1.1  mrg 	  picreg = gen_reg_rtx (SImode);
   2077  1.1  mrg 	  emit_insn (gen_load_funcdescsi (picreg,
   2078  1.1  mrg 					  plus_constant (Pmode, addr, 4)));
   2079  1.1  mrg 	}
   2080  1.1  mrg 
   2081  1.1  mrg       nelts++;
   2082  1.1  mrg     }
   2083  1.1  mrg   else if ((!register_no_elim_operand (callee, Pmode)
   2084  1.1  mrg 	    && GET_CODE (callee) != SYMBOL_REF)
   2085  1.1  mrg 	   || (GET_CODE (callee) == SYMBOL_REF
   2086  1.1  mrg 	       && ((TARGET_ID_SHARED_LIBRARY && !TARGET_LEAF_ID_SHARED_LIBRARY)
   2087  1.1  mrg 		   || bfin_longcall_p (callee, INTVAL (cookie)))))
   2088  1.1  mrg     {
   2089  1.1  mrg       callee = copy_to_mode_reg (Pmode, callee);
   2090  1.1  mrg       fnaddr = gen_rtx_MEM (Pmode, callee);
   2091  1.1  mrg     }
   2092  1.1  mrg   call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
   2093  1.1  mrg 
   2094  1.1  mrg   if (retval)
   2095  1.1  mrg     call = gen_rtx_SET (retval, call);
   2096  1.1  mrg 
   2097  1.1  mrg   pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nelts));
   2098  1.1  mrg   n = 0;
   2099  1.1  mrg   XVECEXP (pat, 0, n++) = call;
   2100  1.1  mrg   if (TARGET_FDPIC)
   2101  1.1  mrg     XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, picreg);
   2102  1.1  mrg   XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie);
   2103  1.1  mrg   if (sibcall)
   2104  1.1  mrg     XVECEXP (pat, 0, n++) = ret_rtx;
   2105  1.1  mrg   else
   2106  1.1  mrg     XVECEXP (pat, 0, n++) = gen_rtx_CLOBBER (VOIDmode, retsreg);
   2107  1.1  mrg   call = emit_call_insn (pat);
   2108  1.1  mrg   if (use)
   2109  1.1  mrg     CALL_INSN_FUNCTION_USAGE (call) = use;
   2110  1.1  mrg }
   2111  1.1  mrg 
   2112  1.1  mrg /* Implement TARGET_HARD_REGNO_NREGS.  */
   2114  1.1  mrg 
   2115  1.1  mrg static unsigned int
   2116  1.1  mrg bfin_hard_regno_nregs (unsigned int regno, machine_mode mode)
   2117  1.1  mrg {
   2118  1.1  mrg   if (mode == PDImode && (regno == REG_A0 || regno == REG_A1))
   2119  1.1  mrg     return 1;
   2120  1.1  mrg   if (mode == V2PDImode && (regno == REG_A0 || regno == REG_A1))
   2121  1.1  mrg     return 2;
   2122  1.1  mrg   return CLASS_MAX_NREGS (GENERAL_REGS, mode);
   2123  1.1  mrg }
   2124  1.1  mrg 
   2125  1.1  mrg /* Implement TARGET_HARD_REGNO_MODE_OK.
   2126  1.1  mrg 
   2127  1.1  mrg    Do not allow to store a value in REG_CC for any mode.
   2128  1.1  mrg    Do not allow to store value in pregs if mode is not SI.  */
   2129  1.1  mrg static bool
   2130  1.1  mrg bfin_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
   2131  1.1  mrg {
   2132  1.1  mrg   /* Allow only dregs to store value of mode HI or QI */
   2133  1.1  mrg   enum reg_class rclass = REGNO_REG_CLASS (regno);
   2134  1.1  mrg 
   2135  1.1  mrg   if (mode == CCmode)
   2136  1.1  mrg     return false;
   2137  1.1  mrg 
   2138  1.1  mrg   if (mode == V2HImode)
   2139  1.1  mrg     return D_REGNO_P (regno);
   2140  1.1  mrg   if (rclass == CCREGS)
   2141  1.1  mrg     return mode == BImode;
   2142  1.1  mrg   if (mode == PDImode || mode == V2PDImode)
   2143  1.1  mrg     return regno == REG_A0 || regno == REG_A1;
   2144  1.1  mrg 
   2145  1.1  mrg   /* Allow all normal 32-bit regs, except REG_M3, in case regclass ever comes
   2146  1.1  mrg      up with a bad register class (such as ALL_REGS) for DImode.  */
   2147  1.1  mrg   if (mode == DImode)
   2148  1.1  mrg     return regno < REG_M3;
   2149  1.1  mrg 
   2150  1.1  mrg   if (mode == SImode
   2151  1.1  mrg       && TEST_HARD_REG_BIT (reg_class_contents[PROLOGUE_REGS], regno))
   2152  1.1  mrg     return true;
   2153  1.1  mrg 
   2154  1.1  mrg   return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno);
   2155  1.1  mrg }
   2156  1.1  mrg 
   2157  1.1  mrg /* Implement TARGET_MODES_TIEABLE_P.  */
   2158  1.1  mrg 
   2159  1.1  mrg static bool
   2160  1.1  mrg bfin_modes_tieable_p (machine_mode mode1, machine_mode mode2)
   2161  1.1  mrg {
   2162  1.1  mrg   return (mode1 == mode2
   2163  1.1  mrg 	  || ((GET_MODE_CLASS (mode1) == MODE_INT
   2164  1.1  mrg 	       || GET_MODE_CLASS (mode1) == MODE_FLOAT)
   2165  1.1  mrg 	      && (GET_MODE_CLASS (mode2) == MODE_INT
   2166  1.1  mrg 		  || GET_MODE_CLASS (mode2) == MODE_FLOAT)
   2167  1.1  mrg 	      && mode1 != BImode && mode2 != BImode
   2168  1.1  mrg 	      && GET_MODE_SIZE (mode1) <= UNITS_PER_WORD
   2169  1.1  mrg 	      && GET_MODE_SIZE (mode2) <= UNITS_PER_WORD));
   2170  1.1  mrg }
   2171  1.1  mrg 
   2172  1.1  mrg /* Implements target hook vector_mode_supported_p.  */
   2173  1.1  mrg 
   2174  1.1  mrg static bool
   2175  1.1  mrg bfin_vector_mode_supported_p (machine_mode mode)
   2176  1.1  mrg {
   2177  1.1  mrg   return mode == V2HImode;
   2178  1.1  mrg }
   2179  1.1  mrg 
   2180  1.1  mrg /* Worker function for TARGET_REGISTER_MOVE_COST.  */
   2181  1.1  mrg 
   2182  1.1  mrg static int
   2183  1.1  mrg bfin_register_move_cost (machine_mode mode,
   2184  1.1  mrg 			 reg_class_t class1, reg_class_t class2)
   2185  1.1  mrg {
   2186  1.1  mrg   /* These need secondary reloads, so they're more expensive.  */
   2187  1.1  mrg   if ((class1 == CCREGS && !reg_class_subset_p (class2, DREGS))
   2188  1.1  mrg       || (class2 == CCREGS && !reg_class_subset_p (class1, DREGS)))
   2189  1.1  mrg     return 4;
   2190  1.1  mrg 
   2191  1.1  mrg   /* If optimizing for size, always prefer reg-reg over reg-memory moves.  */
   2192  1.1  mrg   if (optimize_size)
   2193  1.1  mrg     return 2;
   2194  1.1  mrg 
   2195  1.1  mrg   if (GET_MODE_CLASS (mode) == MODE_INT)
   2196  1.1  mrg     {
   2197  1.1  mrg       /* Discourage trying to use the accumulators.  */
   2198  1.1  mrg       if (TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A0)
   2199  1.1  mrg 	  || TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A1)
   2200  1.1  mrg 	  || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A0)
   2201  1.1  mrg 	  || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A1))
   2202  1.1  mrg 	return 20;
   2203  1.1  mrg     }
   2204  1.1  mrg   return 2;
   2205  1.1  mrg }
   2206  1.1  mrg 
   2207  1.1  mrg /* Worker function for TARGET_MEMORY_MOVE_COST.
   2208  1.1  mrg 
   2209  1.1  mrg    ??? In theory L1 memory has single-cycle latency.  We should add a switch
   2210  1.1  mrg    that tells the compiler whether we expect to use only L1 memory for the
   2211  1.1  mrg    program; it'll make the costs more accurate.  */
   2212  1.1  mrg 
   2213  1.1  mrg static int
   2214  1.1  mrg bfin_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
   2215  1.1  mrg 		       reg_class_t rclass,
   2216  1.1  mrg 		       bool in ATTRIBUTE_UNUSED)
   2217  1.1  mrg {
   2218  1.1  mrg   /* Make memory accesses slightly more expensive than any register-register
   2219  1.1  mrg      move.  Also, penalize non-DP registers, since they need secondary
   2220  1.1  mrg      reloads to load and store.  */
   2221  1.1  mrg   if (! reg_class_subset_p (rclass, DPREGS))
   2222  1.1  mrg     return 10;
   2223  1.1  mrg 
   2224  1.1  mrg   return 8;
   2225  1.1  mrg }
   2226  1.1  mrg 
   2227  1.1  mrg /* Inform reload about cases where moving X with a mode MODE to a register in
   2228  1.1  mrg    RCLASS requires an extra scratch register.  Return the class needed for the
   2229  1.1  mrg    scratch register.  */
   2230  1.1  mrg 
   2231  1.1  mrg static reg_class_t
   2232  1.1  mrg bfin_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
   2233  1.1  mrg 		       machine_mode mode, secondary_reload_info *sri)
   2234  1.1  mrg {
   2235  1.1  mrg   /* If we have HImode or QImode, we can only use DREGS as secondary registers;
   2236  1.1  mrg      in most other cases we can also use PREGS.  */
   2237  1.1  mrg   enum reg_class default_class = GET_MODE_SIZE (mode) >= 4 ? DPREGS : DREGS;
   2238  1.1  mrg   enum reg_class x_class = NO_REGS;
   2239  1.1  mrg   enum rtx_code code = GET_CODE (x);
   2240  1.1  mrg   enum reg_class rclass = (enum reg_class) rclass_i;
   2241  1.1  mrg 
   2242  1.1  mrg   if (code == SUBREG)
   2243  1.1  mrg     x = SUBREG_REG (x), code = GET_CODE (x);
   2244  1.1  mrg   if (REG_P (x))
   2245  1.1  mrg     {
   2246  1.1  mrg       int regno = REGNO (x);
   2247  1.1  mrg       if (regno >= FIRST_PSEUDO_REGISTER)
   2248  1.1  mrg 	regno = reg_renumber[regno];
   2249  1.1  mrg 
   2250  1.1  mrg       if (regno == -1)
   2251  1.1  mrg 	code = MEM;
   2252  1.1  mrg       else
   2253  1.1  mrg 	x_class = REGNO_REG_CLASS (regno);
   2254  1.1  mrg     }
   2255  1.1  mrg 
   2256  1.1  mrg   /* We can be asked to reload (plus (FP) (large_constant)) into a DREG.
   2257  1.1  mrg      This happens as a side effect of register elimination, and we need
   2258  1.1  mrg      a scratch register to do it.  */
   2259  1.1  mrg   if (fp_plus_const_operand (x, mode))
   2260  1.1  mrg     {
   2261  1.1  mrg       rtx op2 = XEXP (x, 1);
   2262  1.1  mrg       int large_constant_p = ! satisfies_constraint_Ks7 (op2);
   2263  1.1  mrg 
   2264  1.1  mrg       if (rclass == PREGS || rclass == PREGS_CLOBBERED)
   2265  1.1  mrg 	return NO_REGS;
   2266  1.1  mrg       /* If destination is a DREG, we can do this without a scratch register
   2267  1.1  mrg 	 if the constant is valid for an add instruction.  */
   2268  1.1  mrg       if ((rclass == DREGS || rclass == DPREGS)
   2269  1.1  mrg 	  && ! large_constant_p)
   2270  1.1  mrg 	return NO_REGS;
   2271  1.1  mrg       /* Reloading to anything other than a DREG?  Use a PREG scratch
   2272  1.1  mrg 	 register.  */
   2273  1.1  mrg       sri->icode = CODE_FOR_reload_insi;
   2274  1.1  mrg       return NO_REGS;
   2275  1.1  mrg     }
   2276  1.1  mrg 
   2277  1.1  mrg   /* Data can usually be moved freely between registers of most classes.
   2278  1.1  mrg      AREGS are an exception; they can only move to or from another register
   2279  1.1  mrg      in AREGS or one in DREGS.  They can also be assigned the constant 0.  */
   2280  1.1  mrg   if (x_class == AREGS || x_class == EVEN_AREGS || x_class == ODD_AREGS)
   2281  1.1  mrg     return (rclass == DREGS || rclass == AREGS || rclass == EVEN_AREGS
   2282  1.1  mrg 	    || rclass == ODD_AREGS
   2283  1.1  mrg 	    ? NO_REGS : DREGS);
   2284  1.1  mrg 
   2285  1.1  mrg   if (rclass == AREGS || rclass == EVEN_AREGS || rclass == ODD_AREGS)
   2286  1.1  mrg     {
   2287  1.1  mrg       if (code == MEM)
   2288  1.1  mrg 	{
   2289  1.1  mrg 	  sri->icode = in_p ? CODE_FOR_reload_inpdi : CODE_FOR_reload_outpdi;
   2290  1.1  mrg 	  return NO_REGS;
   2291  1.1  mrg 	}
   2292  1.1  mrg 
   2293  1.1  mrg       if (x != const0_rtx && x_class != DREGS)
   2294  1.1  mrg 	{
   2295  1.1  mrg 	  return DREGS;
   2296  1.1  mrg 	}
   2297  1.1  mrg       else
   2298  1.1  mrg 	return NO_REGS;
   2299  1.1  mrg     }
   2300  1.1  mrg 
   2301  1.1  mrg   /* CCREGS can only be moved from/to DREGS.  */
   2302  1.1  mrg   if (rclass == CCREGS && x_class != DREGS)
   2303  1.1  mrg     return DREGS;
   2304  1.1  mrg   if (x_class == CCREGS && rclass != DREGS)
   2305  1.1  mrg     return DREGS;
   2306  1.1  mrg 
   2307  1.1  mrg   /* All registers other than AREGS can load arbitrary constants.  The only
   2308  1.1  mrg      case that remains is MEM.  */
   2309  1.1  mrg   if (code == MEM)
   2310  1.1  mrg     if (! reg_class_subset_p (rclass, default_class))
   2311  1.1  mrg       return default_class;
   2312  1.1  mrg 
   2313  1.1  mrg   return NO_REGS;
   2314  1.1  mrg }
   2315  1.1  mrg 
   2316  1.1  mrg /* Implement TARGET_CLASS_LIKELY_SPILLED_P.  */
   2317  1.1  mrg 
   2318  1.1  mrg static bool
   2319  1.1  mrg bfin_class_likely_spilled_p (reg_class_t rclass)
   2320  1.1  mrg {
   2321  1.1  mrg   switch (rclass)
   2322  1.1  mrg     {
   2323  1.1  mrg       case PREGS_CLOBBERED:
   2324  1.1  mrg       case PROLOGUE_REGS:
   2325  1.1  mrg       case P0REGS:
   2326  1.1  mrg       case D0REGS:
   2327  1.1  mrg       case D1REGS:
   2328  1.1  mrg       case D2REGS:
   2329  1.1  mrg       case CCREGS:
   2330  1.1  mrg         return true;
   2331  1.1  mrg 
   2332  1.1  mrg       default:
   2333  1.1  mrg         break;
   2334  1.1  mrg     }
   2335  1.1  mrg 
   2336  1.1  mrg   return false;
   2337  1.1  mrg }
   2338  1.1  mrg 
   2339  1.1  mrg static struct machine_function *
   2341  1.1  mrg bfin_init_machine_status (void)
   2342  1.1  mrg {
   2343  1.1  mrg   return ggc_cleared_alloc<machine_function> ();
   2344  1.1  mrg }
   2345  1.1  mrg 
   2346  1.1  mrg /* Implement the TARGET_OPTION_OVERRIDE hook.  */
   2347  1.1  mrg 
   2348  1.1  mrg static void
   2349  1.1  mrg bfin_option_override (void)
   2350  1.1  mrg {
   2351  1.1  mrg   /* If processor type is not specified, enable all workarounds.  */
   2352  1.1  mrg   if (bfin_cpu_type == BFIN_CPU_UNKNOWN)
   2353  1.1  mrg     {
   2354  1.1  mrg       int i;
   2355  1.1  mrg 
   2356  1.1  mrg       for (i = 0; bfin_cpus[i].name != NULL; i++)
   2357  1.1  mrg 	bfin_workarounds |= bfin_cpus[i].workarounds;
   2358  1.1  mrg 
   2359  1.1  mrg       bfin_si_revision = 0xffff;
   2360  1.1  mrg     }
   2361  1.1  mrg 
   2362  1.1  mrg   if (bfin_csync_anomaly == 1)
   2363  1.1  mrg     bfin_workarounds |= WA_SPECULATIVE_SYNCS;
   2364  1.1  mrg   else if (bfin_csync_anomaly == 0)
   2365  1.1  mrg     bfin_workarounds &= ~WA_SPECULATIVE_SYNCS;
   2366  1.1  mrg 
   2367  1.1  mrg   if (bfin_specld_anomaly == 1)
   2368  1.1  mrg     bfin_workarounds |= WA_SPECULATIVE_LOADS;
   2369  1.1  mrg   else if (bfin_specld_anomaly == 0)
   2370  1.1  mrg     bfin_workarounds &= ~WA_SPECULATIVE_LOADS;
   2371  1.1  mrg 
   2372  1.1  mrg   if (TARGET_OMIT_LEAF_FRAME_POINTER)
   2373  1.1  mrg     flag_omit_frame_pointer = 1;
   2374  1.1  mrg 
   2375  1.1  mrg #ifdef SUBTARGET_FDPIC_NOT_SUPPORTED
   2376  1.1  mrg   if (TARGET_FDPIC)
   2377  1.1  mrg     error ("%<-mfdpic%> is not supported, please use a bfin-linux-uclibc "
   2378  1.1  mrg 	   "target");
   2379  1.1  mrg #endif
   2380  1.1  mrg 
   2381  1.1  mrg   /* Library identification */
   2382  1.1  mrg   if (OPTION_SET_P (bfin_library_id) && ! TARGET_ID_SHARED_LIBRARY)
   2383  1.1  mrg     error ("%<-mshared-library-id=%> specified without "
   2384  1.1  mrg 	   "%<-mid-shared-library%>");
   2385  1.1  mrg 
   2386  1.1  mrg   if (stack_limit_rtx && TARGET_FDPIC)
   2387  1.1  mrg     {
   2388  1.1  mrg       warning (0, "%<-fstack-limit-%> options are ignored with %<-mfdpic%>; "
   2389  1.1  mrg 	       "use %<-mstack-check-l1%>");
   2390  1.1  mrg       stack_limit_rtx = NULL_RTX;
   2391  1.1  mrg     }
   2392  1.1  mrg 
   2393  1.1  mrg   if (stack_limit_rtx && TARGET_STACK_CHECK_L1)
   2394  1.1  mrg     error ("cannot use multiple stack checking methods together");
   2395  1.1  mrg 
   2396  1.1  mrg   if (TARGET_ID_SHARED_LIBRARY && TARGET_FDPIC)
   2397  1.1  mrg     error ("ID shared libraries and FD-PIC mode cannot be used together");
   2398  1.1  mrg 
   2399  1.1  mrg   /* Don't allow the user to specify -mid-shared-library and -msep-data
   2400  1.1  mrg      together, as it makes little sense from a user's point of view...  */
   2401  1.1  mrg   if (TARGET_SEP_DATA && TARGET_ID_SHARED_LIBRARY)
   2402  1.1  mrg     error ("cannot specify both %<-msep-data%> and %<-mid-shared-library%>");
   2403  1.1  mrg   /* ... internally, however, it's nearly the same.  */
   2404  1.1  mrg   if (TARGET_SEP_DATA)
   2405  1.1  mrg     target_flags |= MASK_ID_SHARED_LIBRARY | MASK_LEAF_ID_SHARED_LIBRARY;
   2406  1.1  mrg 
   2407  1.1  mrg   if (TARGET_ID_SHARED_LIBRARY && flag_pic == 0)
   2408  1.1  mrg     flag_pic = 1;
   2409  1.1  mrg 
   2410  1.1  mrg   /* There is no single unaligned SI op for PIC code.  Sometimes we
   2411  1.1  mrg      need to use ".4byte" and sometimes we need to use ".picptr".
   2412  1.1  mrg      See bfin_assemble_integer for details.  */
   2413  1.1  mrg   if (TARGET_FDPIC)
   2414  1.1  mrg     targetm.asm_out.unaligned_op.si = 0;
   2415  1.1  mrg 
   2416  1.1  mrg   /* Silently turn off flag_pic if not doing FDPIC or ID shared libraries,
   2417  1.1  mrg      since we don't support it and it'll just break.  */
   2418  1.1  mrg   if (flag_pic && !TARGET_FDPIC && !TARGET_ID_SHARED_LIBRARY)
   2419  1.1  mrg     flag_pic = 0;
   2420  1.1  mrg 
   2421  1.1  mrg   if (TARGET_MULTICORE && bfin_cpu_type != BFIN_CPU_BF561)
   2422  1.1  mrg     error ("%<-mmulticore%> can only be used with BF561");
   2423  1.1  mrg 
   2424  1.1  mrg   if (TARGET_COREA && !TARGET_MULTICORE)
   2425  1.1  mrg     error ("%<-mcorea%> should be used with %<-mmulticore%>");
   2426  1.1  mrg 
   2427  1.1  mrg   if (TARGET_COREB && !TARGET_MULTICORE)
   2428  1.1  mrg     error ("%<-mcoreb%> should be used with %<-mmulticore%>");
   2429  1.1  mrg 
   2430  1.1  mrg   if (TARGET_COREA && TARGET_COREB)
   2431  1.1  mrg     error ("%<-mcorea%> and %<-mcoreb%> cannot be used together");
   2432  1.1  mrg 
   2433  1.1  mrg   flag_schedule_insns = 0;
   2434  1.1  mrg 
   2435  1.1  mrg   init_machine_status = bfin_init_machine_status;
   2436  1.1  mrg }
   2437  1.1  mrg 
   2438  1.1  mrg /* Return the destination address of BRANCH.
   2439  1.1  mrg    We need to use this instead of get_attr_length, because the
   2440  1.1  mrg    cbranch_with_nops pattern conservatively sets its length to 6, and
   2441  1.1  mrg    we still prefer to use shorter sequences.  */
   2442  1.1  mrg 
   2443  1.1  mrg static int
   2444  1.1  mrg branch_dest (rtx_insn *branch)
   2445  1.1  mrg {
   2446  1.1  mrg   rtx dest;
   2447  1.1  mrg   int dest_uid;
   2448  1.1  mrg   rtx pat = PATTERN (branch);
   2449  1.1  mrg   if (GET_CODE (pat) == PARALLEL)
   2450  1.1  mrg     pat = XVECEXP (pat, 0, 0);
   2451  1.1  mrg   dest = SET_SRC (pat);
   2452  1.1  mrg   if (GET_CODE (dest) == IF_THEN_ELSE)
   2453  1.1  mrg     dest = XEXP (dest, 1);
   2454  1.1  mrg   dest = XEXP (dest, 0);
   2455  1.1  mrg   dest_uid = INSN_UID (dest);
   2456  1.1  mrg   return INSN_ADDRESSES (dest_uid);
   2457  1.1  mrg }
   2458  1.1  mrg 
   2459  1.1  mrg /* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates
   2460  1.1  mrg    it's a branch that's predicted taken.  */
   2461  1.1  mrg 
   2462  1.1  mrg static int
   2463  1.1  mrg cbranch_predicted_taken_p (rtx insn)
   2464  1.1  mrg {
   2465  1.1  mrg   rtx x = find_reg_note (insn, REG_BR_PROB, 0);
   2466  1.1  mrg 
   2467  1.1  mrg   if (x)
   2468  1.1  mrg     {
   2469  1.1  mrg       return profile_probability::from_reg_br_prob_note (XINT (x, 0))
   2470  1.1  mrg 	     >= profile_probability::even ();
   2471  1.1  mrg     }
   2472  1.1  mrg 
   2473  1.1  mrg   return 0;
   2474  1.1  mrg }
   2475  1.1  mrg 
   2476  1.1  mrg /* Templates for use by asm_conditional_branch.  */
   2477  1.1  mrg 
   2478  1.1  mrg static const char *ccbranch_templates[][3] = {
   2479  1.1  mrg   { "if !cc jump %3;",  "if cc jump 4 (bp); jump.s %3;",  "if cc jump 6 (bp); jump.l %3;" },
   2480  1.1  mrg   { "if cc jump %3;",   "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" },
   2481  1.1  mrg   { "if !cc jump %3 (bp);",  "if cc jump 4; jump.s %3;",  "if cc jump 6; jump.l %3;" },
   2482  1.1  mrg   { "if cc jump %3 (bp);",  "if !cc jump 4; jump.s %3;",  "if !cc jump 6; jump.l %3;" },
   2483  1.1  mrg };
   2484  1.1  mrg 
   2485  1.1  mrg /* Output INSN, which is a conditional branch instruction with operands
   2486  1.1  mrg    OPERANDS.
   2487  1.1  mrg 
   2488  1.1  mrg    We deal with the various forms of conditional branches that can be generated
   2489  1.1  mrg    by bfin_reorg to prevent the hardware from doing speculative loads, by
   2490  1.1  mrg    - emitting a sufficient number of nops, if N_NOPS is nonzero, or
   2491  1.1  mrg    - always emitting the branch as predicted taken, if PREDICT_TAKEN is true.
   2492  1.1  mrg    Either of these is only necessary if the branch is short, otherwise the
   2493  1.1  mrg    template we use ends in an unconditional jump which flushes the pipeline
   2494  1.1  mrg    anyway.  */
   2495  1.1  mrg 
   2496  1.1  mrg void
   2497  1.1  mrg asm_conditional_branch (rtx_insn *insn, rtx *operands, int n_nops, int predict_taken)
   2498  1.1  mrg {
   2499  1.1  mrg   int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
   2500  1.1  mrg   /* Note : offset for instructions like if cc jmp; jump.[sl] offset
   2501  1.1  mrg             is to be taken from start of if cc rather than jump.
   2502  1.1  mrg             Range for jump.s is (-4094, 4096) instead of (-4096, 4094)
   2503  1.1  mrg   */
   2504  1.1  mrg   int len = (offset >= -1024 && offset <= 1022 ? 0
   2505  1.1  mrg 	     : offset >= -4094 && offset <= 4096 ? 1
   2506  1.1  mrg 	     : 2);
   2507  1.1  mrg   int bp = predict_taken && len == 0 ? 1 : cbranch_predicted_taken_p (insn);
   2508  1.1  mrg   int idx = (bp << 1) | (GET_CODE (operands[0]) == EQ ? BRF : BRT);
   2509  1.1  mrg   output_asm_insn (ccbranch_templates[idx][len], operands);
   2510  1.1  mrg   gcc_assert (n_nops == 0 || !bp);
   2511  1.1  mrg   if (len == 0)
   2512  1.1  mrg     while (n_nops-- > 0)
   2513  1.1  mrg       output_asm_insn ("nop;", NULL);
   2514  1.1  mrg }
   2515  1.1  mrg 
   2516  1.1  mrg /* Emit rtl for a comparison operation CMP in mode MODE.  Operands have been
   2517  1.1  mrg    stored in bfin_compare_op0 and bfin_compare_op1 already.  */
   2518  1.1  mrg 
   2519  1.1  mrg rtx
   2520  1.1  mrg bfin_gen_compare (rtx cmp, machine_mode mode ATTRIBUTE_UNUSED)
   2521  1.1  mrg {
   2522  1.1  mrg   enum rtx_code code1, code2;
   2523  1.1  mrg   rtx op0 = XEXP (cmp, 0), op1 = XEXP (cmp, 1);
   2524  1.1  mrg   rtx tem = bfin_cc_rtx;
   2525  1.1  mrg   enum rtx_code code = GET_CODE (cmp);
   2526  1.1  mrg 
   2527  1.1  mrg   /* If we have a BImode input, then we already have a compare result, and
   2528  1.1  mrg      do not need to emit another comparison.  */
   2529  1.1  mrg   if (GET_MODE (op0) == BImode)
   2530  1.1  mrg     {
   2531  1.1  mrg       gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
   2532  1.1  mrg       tem = op0, code2 = code;
   2533  1.1  mrg     }
   2534  1.1  mrg   else
   2535  1.1  mrg     {
   2536  1.1  mrg       switch (code) {
   2537  1.1  mrg 	/* bfin has these conditions */
   2538  1.1  mrg       case EQ:
   2539  1.1  mrg       case LT:
   2540  1.1  mrg       case LE:
   2541  1.1  mrg       case LEU:
   2542  1.1  mrg       case LTU:
   2543  1.1  mrg 	code1 = code;
   2544  1.1  mrg 	code2 = NE;
   2545  1.1  mrg 	break;
   2546  1.1  mrg       default:
   2547  1.1  mrg 	code1 = reverse_condition (code);
   2548  1.1  mrg 	code2 = EQ;
   2549  1.1  mrg 	break;
   2550  1.1  mrg       }
   2551  1.1  mrg       emit_insn (gen_rtx_SET (tem, gen_rtx_fmt_ee (code1, BImode, op0, op1)));
   2552  1.1  mrg     }
   2553  1.1  mrg 
   2554  1.1  mrg   return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode));
   2555  1.1  mrg }
   2556  1.1  mrg 
   2557  1.1  mrg /* Return nonzero iff C has exactly one bit set if it is interpreted
   2559  1.1  mrg    as a 32-bit constant.  */
   2560  1.1  mrg 
   2561  1.1  mrg int
   2562  1.1  mrg log2constp (unsigned HOST_WIDE_INT c)
   2563  1.1  mrg {
   2564  1.1  mrg   c &= 0xFFFFFFFF;
   2565  1.1  mrg   return c != 0 && (c & (c-1)) == 0;
   2566  1.1  mrg }
   2567  1.1  mrg 
   2568  1.1  mrg /* Returns the number of consecutive least significant zeros in the binary
   2569  1.1  mrg    representation of *V.
   2570  1.1  mrg    We modify *V to contain the original value arithmetically shifted right by
   2571  1.1  mrg    the number of zeroes.  */
   2572  1.1  mrg 
   2573  1.1  mrg static int
   2574  1.1  mrg shiftr_zero (HOST_WIDE_INT *v)
   2575  1.1  mrg {
   2576  1.1  mrg   unsigned HOST_WIDE_INT tmp = *v;
   2577  1.1  mrg   unsigned HOST_WIDE_INT sgn;
   2578  1.1  mrg   int n = 0;
   2579  1.1  mrg 
   2580  1.1  mrg   if (tmp == 0)
   2581  1.1  mrg     return 0;
   2582  1.1  mrg 
   2583  1.1  mrg   sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1));
   2584  1.1  mrg   while ((tmp & 0x1) == 0 && n <= 32)
   2585  1.1  mrg     {
   2586  1.1  mrg       tmp = (tmp >> 1) | sgn;
   2587  1.1  mrg       n++;
   2588  1.1  mrg     }
   2589  1.1  mrg   *v = tmp;
   2590  1.1  mrg   return n;
   2591  1.1  mrg }
   2592  1.1  mrg 
   2593  1.1  mrg /* After reload, split the load of an immediate constant.  OPERANDS are the
   2594  1.1  mrg    operands of the movsi_insn pattern which we are splitting.  We return
   2595  1.1  mrg    nonzero if we emitted a sequence to load the constant, zero if we emitted
   2596  1.1  mrg    nothing because we want to use the splitter's default sequence.  */
   2597  1.1  mrg 
   2598  1.1  mrg int
   2599  1.1  mrg split_load_immediate (rtx operands[])
   2600  1.1  mrg {
   2601  1.1  mrg   HOST_WIDE_INT val = INTVAL (operands[1]);
   2602  1.1  mrg   HOST_WIDE_INT tmp;
   2603  1.1  mrg   HOST_WIDE_INT shifted = val;
   2604  1.1  mrg   HOST_WIDE_INT shifted_compl = ~val;
   2605  1.1  mrg   int num_zero = shiftr_zero (&shifted);
   2606  1.1  mrg   int num_compl_zero = shiftr_zero (&shifted_compl);
   2607  1.1  mrg   unsigned int regno = REGNO (operands[0]);
   2608  1.1  mrg 
   2609  1.1  mrg   /* This case takes care of single-bit set/clear constants, which we could
   2610  1.1  mrg      also implement with BITSET/BITCLR.  */
   2611  1.1  mrg   if (num_zero
   2612  1.1  mrg       && shifted >= -32768 && shifted < 65536
   2613  1.1  mrg       && (D_REGNO_P (regno)
   2614  1.1  mrg 	  || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))
   2615  1.1  mrg     {
   2616  1.1  mrg       emit_insn (gen_movsi (operands[0], gen_int_mode (shifted, SImode)));
   2617  1.1  mrg       emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));
   2618  1.1  mrg       return 1;
   2619  1.1  mrg     }
   2620  1.1  mrg 
   2621  1.1  mrg   tmp = val & 0xFFFF;
   2622  1.1  mrg   tmp |= -(tmp & 0x8000);
   2623  1.1  mrg 
   2624  1.1  mrg   /* If high word has one bit set or clear, try to use a bit operation.  */
   2625  1.1  mrg   if (D_REGNO_P (regno))
   2626  1.1  mrg     {
   2627  1.1  mrg       if (log2constp (val & 0xFFFF0000))
   2628  1.1  mrg 	{
   2629  1.1  mrg 	  emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));
   2630  1.1  mrg 	  emit_insn (gen_iorsi3 (operands[0], operands[0],
   2631  1.1  mrg 				 gen_int_mode (val & 0xFFFF0000, SImode)));
   2632  1.1  mrg 	  return 1;
   2633  1.1  mrg 	}
   2634  1.1  mrg       else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)
   2635  1.1  mrg 	{
   2636  1.1  mrg 	  emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
   2637  1.1  mrg 	  emit_insn (gen_andsi3 (operands[0], operands[0],
   2638  1.1  mrg 				 gen_int_mode (val | 0xFFFF, SImode)));
   2639  1.1  mrg 	}
   2640  1.1  mrg     }
   2641  1.1  mrg 
   2642  1.1  mrg   if (D_REGNO_P (regno))
   2643  1.1  mrg     {
   2644  1.1  mrg       if (tmp >= -64 && tmp <= 63)
   2645  1.1  mrg 	{
   2646  1.1  mrg 	  emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
   2647  1.1  mrg 	  emit_insn (gen_movstricthi_high (operands[0],
   2648  1.1  mrg 					   gen_int_mode (val & -65536,
   2649  1.1  mrg 							 SImode)));
   2650  1.1  mrg 	  return 1;
   2651  1.1  mrg 	}
   2652  1.1  mrg 
   2653  1.1  mrg       if ((val & 0xFFFF0000) == 0)
   2654  1.1  mrg 	{
   2655  1.1  mrg 	  emit_insn (gen_movsi (operands[0], const0_rtx));
   2656  1.1  mrg 	  emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
   2657  1.1  mrg 	  return 1;
   2658  1.1  mrg 	}
   2659  1.1  mrg 
   2660  1.1  mrg       if ((val & 0xFFFF0000) == 0xFFFF0000)
   2661  1.1  mrg 	{
   2662  1.1  mrg 	  emit_insn (gen_movsi (operands[0], constm1_rtx));
   2663  1.1  mrg 	  emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
   2664  1.1  mrg 	  return 1;
   2665  1.1  mrg 	}
   2666  1.1  mrg     }
   2667  1.1  mrg 
   2668  1.1  mrg   /* Need DREGs for the remaining case.  */
   2669  1.1  mrg   if (regno > REG_R7)
   2670  1.1  mrg     return 0;
   2671  1.1  mrg 
   2672  1.1  mrg   if (optimize_size
   2673  1.1  mrg       && num_compl_zero && shifted_compl >= -64 && shifted_compl <= 63)
   2674  1.1  mrg     {
   2675  1.1  mrg       /* If optimizing for size, generate a sequence that has more instructions
   2676  1.1  mrg 	 but is shorter.  */
   2677  1.1  mrg       emit_insn (gen_movsi (operands[0], gen_int_mode (shifted_compl, SImode)));
   2678  1.1  mrg       emit_insn (gen_ashlsi3 (operands[0], operands[0],
   2679  1.1  mrg 			      GEN_INT (num_compl_zero)));
   2680  1.1  mrg       emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
   2681  1.1  mrg       return 1;
   2682  1.1  mrg     }
   2683  1.1  mrg   return 0;
   2684  1.1  mrg }
   2685  1.1  mrg 
   2686  1.1  mrg /* Return true if the legitimate memory address for a memory operand of mode
   2688  1.1  mrg    MODE.  Return false if not.  */
   2689  1.1  mrg 
   2690  1.1  mrg static bool
   2691  1.1  mrg bfin_valid_add (machine_mode mode, HOST_WIDE_INT value)
   2692  1.1  mrg {
   2693  1.1  mrg   unsigned HOST_WIDE_INT v = value > 0 ? value : -value;
   2694  1.1  mrg   int sz = GET_MODE_SIZE (mode);
   2695  1.1  mrg   int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2;
   2696  1.1  mrg   /* The usual offsettable_memref machinery doesn't work so well for this
   2697  1.1  mrg      port, so we deal with the problem here.  */
   2698  1.1  mrg   if (value > 0 && sz == 8)
   2699  1.1  mrg     v += 4;
   2700  1.1  mrg   return (v & ~(0x7fff << shift)) == 0;
   2701  1.1  mrg }
   2702  1.1  mrg 
   2703  1.1  mrg static bool
   2704  1.1  mrg bfin_valid_reg_p (unsigned int regno, int strict, machine_mode mode,
   2705  1.1  mrg 		  enum rtx_code outer_code)
   2706  1.1  mrg {
   2707  1.1  mrg   if (strict)
   2708  1.1  mrg     return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH);
   2709  1.1  mrg   else
   2710  1.1  mrg     return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH);
   2711  1.1  mrg }
   2712  1.1  mrg 
   2713  1.1  mrg /* Recognize an RTL expression that is a valid memory address for an
   2714  1.1  mrg    instruction.  The MODE argument is the machine mode for the MEM expression
   2715  1.1  mrg    that wants to use this address.
   2716  1.1  mrg 
   2717  1.1  mrg    Blackfin addressing modes are as follows:
   2718  1.1  mrg 
   2719  1.1  mrg       [preg]
   2720  1.1  mrg       [preg + imm16]
   2721  1.1  mrg 
   2722  1.1  mrg       B [ Preg + uimm15 ]
   2723  1.1  mrg       W [ Preg + uimm16m2 ]
   2724  1.1  mrg       [ Preg + uimm17m4 ]
   2725  1.1  mrg 
   2726  1.1  mrg       [preg++]
   2727  1.1  mrg       [preg--]
   2728  1.1  mrg       [--sp]
   2729  1.1  mrg */
   2730  1.1  mrg 
   2731  1.1  mrg static bool
   2732  1.1  mrg bfin_legitimate_address_p (machine_mode mode, rtx x, bool strict)
   2733  1.1  mrg {
   2734  1.1  mrg   switch (GET_CODE (x)) {
   2735  1.1  mrg   case REG:
   2736  1.1  mrg     if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM))
   2737  1.1  mrg       return true;
   2738  1.1  mrg     break;
   2739  1.1  mrg   case PLUS:
   2740  1.1  mrg     if (REG_P (XEXP (x, 0))
   2741  1.1  mrg 	&& bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS)
   2742  1.1  mrg 	&& ((GET_CODE (XEXP (x, 1)) == UNSPEC && mode == SImode)
   2743  1.1  mrg 	    || (GET_CODE (XEXP (x, 1)) == CONST_INT
   2744  1.1  mrg 		&& bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
   2745  1.1  mrg       return true;
   2746  1.1  mrg     break;
   2747  1.1  mrg   case POST_INC:
   2748  1.1  mrg   case POST_DEC:
   2749  1.1  mrg     if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
   2750  1.1  mrg 	&& REG_P (XEXP (x, 0))
   2751  1.1  mrg 	&& bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC))
   2752  1.1  mrg       return true;
   2753  1.1  mrg     break;
   2754  1.1  mrg   case PRE_DEC:
   2755  1.1  mrg     if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
   2756  1.1  mrg 	&& XEXP (x, 0) == stack_pointer_rtx
   2757  1.1  mrg 	&& REG_P (XEXP (x, 0))
   2758  1.1  mrg 	&& bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC))
   2759  1.1  mrg       return true;
   2760  1.1  mrg     break;
   2761  1.1  mrg   default:
   2762  1.1  mrg     break;
   2763  1.1  mrg   }
   2764  1.1  mrg   return false;
   2765  1.1  mrg }
   2766  1.1  mrg 
   2767  1.1  mrg /* Decide whether we can force certain constants to memory.  If we
   2768  1.1  mrg    decide we can't, the caller should be able to cope with it in
   2769  1.1  mrg    another way.  */
   2770  1.1  mrg 
   2771  1.1  mrg static bool
   2772  1.1  mrg bfin_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED,
   2773  1.1  mrg 			     rtx x ATTRIBUTE_UNUSED)
   2774  1.1  mrg {
   2775  1.1  mrg   /* We have only one class of non-legitimate constants, and our movsi
   2776  1.1  mrg      expander knows how to handle them.  Dropping these constants into the
   2777  1.1  mrg      data section would only shift the problem - we'd still get relocs
   2778  1.1  mrg      outside the object, in the data section rather than the text section.  */
   2779  1.1  mrg   return true;
   2780  1.1  mrg }
   2781  1.1  mrg 
   2782  1.1  mrg /* Ensure that for any constant of the form symbol + offset, the offset
   2783  1.1  mrg    remains within the object.  Any other constants are ok.
   2784  1.1  mrg    This ensures that flat binaries never have to deal with relocations
   2785  1.1  mrg    crossing section boundaries.  */
   2786  1.1  mrg 
   2787  1.1  mrg static bool
   2788  1.1  mrg bfin_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
   2789  1.1  mrg {
   2790  1.1  mrg   rtx sym;
   2791  1.1  mrg   HOST_WIDE_INT offset;
   2792  1.1  mrg 
   2793  1.1  mrg   if (GET_CODE (x) != CONST)
   2794  1.1  mrg     return true;
   2795  1.1  mrg 
   2796  1.1  mrg   x = XEXP (x, 0);
   2797  1.1  mrg   gcc_assert (GET_CODE (x) == PLUS);
   2798  1.1  mrg 
   2799  1.1  mrg   sym = XEXP (x, 0);
   2800  1.1  mrg   x = XEXP (x, 1);
   2801  1.1  mrg   if (GET_CODE (sym) != SYMBOL_REF
   2802  1.1  mrg       || GET_CODE (x) != CONST_INT)
   2803  1.1  mrg     return true;
   2804  1.1  mrg   offset = INTVAL (x);
   2805  1.1  mrg 
   2806  1.1  mrg   if (SYMBOL_REF_DECL (sym) == 0)
   2807  1.1  mrg     return true;
   2808  1.1  mrg   if (offset < 0
   2809  1.1  mrg       || offset >= int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (sym))))
   2810  1.1  mrg     return false;
   2811  1.1  mrg 
   2812  1.1  mrg   return true;
   2813  1.1  mrg }
   2814  1.1  mrg 
   2815  1.1  mrg static bool
   2816  1.1  mrg bfin_rtx_costs (rtx x, machine_mode mode, int outer_code_i, int opno,
   2817  1.1  mrg 		int *total, bool speed)
   2818  1.1  mrg {
   2819  1.1  mrg   enum rtx_code code = GET_CODE (x);
   2820  1.1  mrg   enum rtx_code outer_code = (enum rtx_code) outer_code_i;
   2821  1.1  mrg   int cost2 = COSTS_N_INSNS (1);
   2822  1.1  mrg   rtx op0, op1;
   2823  1.1  mrg 
   2824  1.1  mrg   switch (code)
   2825  1.1  mrg     {
   2826  1.1  mrg     case CONST_INT:
   2827  1.1  mrg       if (outer_code == SET || outer_code == PLUS)
   2828  1.1  mrg         *total = satisfies_constraint_Ks7 (x) ? 0 : cost2;
   2829  1.1  mrg       else if (outer_code == AND)
   2830  1.1  mrg         *total = log2constp (~INTVAL (x)) ? 0 : cost2;
   2831  1.1  mrg       else if (outer_code == LE || outer_code == LT || outer_code == EQ)
   2832  1.1  mrg         *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
   2833  1.1  mrg       else if (outer_code == LEU || outer_code == LTU)
   2834  1.1  mrg         *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
   2835  1.1  mrg       else if (outer_code == MULT)
   2836  1.1  mrg         *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
   2837  1.1  mrg       else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
   2838  1.1  mrg         *total = 0;
   2839  1.1  mrg       else if (outer_code == ASHIFT || outer_code == ASHIFTRT
   2840  1.1  mrg 	       || outer_code == LSHIFTRT)
   2841  1.1  mrg         *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
   2842  1.1  mrg       else if (outer_code == IOR || outer_code == XOR)
   2843  1.1  mrg         *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
   2844  1.1  mrg       else
   2845  1.1  mrg 	*total = cost2;
   2846  1.1  mrg       return true;
   2847  1.1  mrg 
   2848  1.1  mrg     case CONST:
   2849  1.1  mrg     case LABEL_REF:
   2850  1.1  mrg     case SYMBOL_REF:
   2851  1.1  mrg     case CONST_DOUBLE:
   2852  1.1  mrg       *total = COSTS_N_INSNS (2);
   2853  1.1  mrg       return true;
   2854  1.1  mrg 
   2855  1.1  mrg     case PLUS:
   2856  1.1  mrg       op0 = XEXP (x, 0);
   2857  1.1  mrg       op1 = XEXP (x, 1);
   2858  1.1  mrg       if (mode == SImode)
   2859  1.1  mrg 	{
   2860  1.1  mrg 	  if (GET_CODE (op0) == MULT
   2861  1.1  mrg 	      && GET_CODE (XEXP (op0, 1)) == CONST_INT)
   2862  1.1  mrg 	    {
   2863  1.1  mrg 	      HOST_WIDE_INT val = INTVAL (XEXP (op0, 1));
   2864  1.1  mrg 	      if (val == 2 || val == 4)
   2865  1.1  mrg 		{
   2866  1.1  mrg 		  *total = cost2;
   2867  1.1  mrg 		  *total += rtx_cost (XEXP (op0, 0), mode, outer_code,
   2868  1.1  mrg 				      opno, speed);
   2869  1.1  mrg 		  *total += rtx_cost (op1, mode, outer_code, opno, speed);
   2870  1.1  mrg 		  return true;
   2871  1.1  mrg 		}
   2872  1.1  mrg 	    }
   2873  1.1  mrg 	  *total = cost2;
   2874  1.1  mrg 	  if (GET_CODE (op0) != REG
   2875  1.1  mrg 	      && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
   2876  1.1  mrg 	    *total += set_src_cost (op0, mode, speed);
   2877  1.1  mrg #if 0 /* We'd like to do this for accuracy, but it biases the loop optimizer
   2878  1.1  mrg 	 towards creating too many induction variables.  */
   2879  1.1  mrg 	  if (!reg_or_7bit_operand (op1, SImode))
   2880  1.1  mrg 	    *total += set_src_cost (op1, mode, speed);
   2881  1.1  mrg #endif
   2882  1.1  mrg 	}
   2883  1.1  mrg       else if (mode == DImode)
   2884  1.1  mrg 	{
   2885  1.1  mrg 	  *total = 6 * cost2;
   2886  1.1  mrg 	  if (GET_CODE (op1) != CONST_INT
   2887  1.1  mrg 	      || !satisfies_constraint_Ks7 (op1))
   2888  1.1  mrg 	    *total += rtx_cost (op1, mode, PLUS, 1, speed);
   2889  1.1  mrg 	  if (GET_CODE (op0) != REG
   2890  1.1  mrg 	      && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
   2891  1.1  mrg 	    *total += rtx_cost (op0, mode, PLUS, 0, speed);
   2892  1.1  mrg 	}
   2893  1.1  mrg       return true;
   2894  1.1  mrg 
   2895  1.1  mrg     case MINUS:
   2896  1.1  mrg       if (mode == DImode)
   2897  1.1  mrg 	*total = 6 * cost2;
   2898  1.1  mrg       else
   2899  1.1  mrg 	*total = cost2;
   2900  1.1  mrg       return true;
   2901  1.1  mrg 
   2902  1.1  mrg     case ASHIFT:
   2903  1.1  mrg     case ASHIFTRT:
   2904  1.1  mrg     case LSHIFTRT:
   2905  1.1  mrg       if (mode == DImode)
   2906  1.1  mrg 	*total = 6 * cost2;
   2907  1.1  mrg       else
   2908  1.1  mrg 	*total = cost2;
   2909  1.1  mrg 
   2910  1.1  mrg       op0 = XEXP (x, 0);
   2911  1.1  mrg       op1 = XEXP (x, 1);
   2912  1.1  mrg       if (GET_CODE (op0) != REG
   2913  1.1  mrg 	  && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
   2914  1.1  mrg 	*total += rtx_cost (op0, mode, code, 0, speed);
   2915  1.1  mrg 
   2916  1.1  mrg       return true;
   2917  1.1  mrg 
   2918  1.1  mrg     case IOR:
   2919  1.1  mrg     case AND:
   2920  1.1  mrg     case XOR:
   2921  1.1  mrg       op0 = XEXP (x, 0);
   2922  1.1  mrg       op1 = XEXP (x, 1);
   2923  1.1  mrg 
   2924  1.1  mrg       /* Handle special cases of IOR: rotates, ALIGN insns, movstricthi_high.  */
   2925  1.1  mrg       if (code == IOR)
   2926  1.1  mrg 	{
   2927  1.1  mrg 	  if ((GET_CODE (op0) == LSHIFTRT && GET_CODE (op1) == ASHIFT)
   2928  1.1  mrg 	      || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == ZERO_EXTEND)
   2929  1.1  mrg 	      || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT)
   2930  1.1  mrg 	      || (GET_CODE (op0) == AND && GET_CODE (op1) == CONST_INT))
   2931  1.1  mrg 	    {
   2932  1.1  mrg 	      *total = cost2;
   2933  1.1  mrg 	      return true;
   2934  1.1  mrg 	    }
   2935  1.1  mrg 	}
   2936  1.1  mrg 
   2937  1.1  mrg       if (GET_CODE (op0) != REG
   2938  1.1  mrg 	  && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
   2939  1.1  mrg 	*total += rtx_cost (op0, mode, code, 0, speed);
   2940  1.1  mrg 
   2941  1.1  mrg       if (mode == DImode)
   2942  1.1  mrg 	{
   2943  1.1  mrg 	  *total = 2 * cost2;
   2944  1.1  mrg 	  return true;
   2945  1.1  mrg 	}
   2946  1.1  mrg       *total = cost2;
   2947  1.1  mrg       if (mode != SImode)
   2948  1.1  mrg 	return true;
   2949  1.1  mrg 
   2950  1.1  mrg       if (code == AND)
   2951  1.1  mrg 	{
   2952  1.1  mrg 	  if (! rhs_andsi3_operand (XEXP (x, 1), SImode))
   2953  1.1  mrg 	    *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
   2954  1.1  mrg 	}
   2955  1.1  mrg       else
   2956  1.1  mrg 	{
   2957  1.1  mrg 	  if (! regorlog2_operand (XEXP (x, 1), SImode))
   2958  1.1  mrg 	    *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
   2959  1.1  mrg 	}
   2960  1.1  mrg 
   2961  1.1  mrg       return true;
   2962  1.1  mrg 
   2963  1.1  mrg     case ZERO_EXTRACT:
   2964  1.1  mrg     case SIGN_EXTRACT:
   2965  1.1  mrg       if (outer_code == SET
   2966  1.1  mrg 	  && XEXP (x, 1) == const1_rtx
   2967  1.1  mrg 	  && GET_CODE (XEXP (x, 2)) == CONST_INT)
   2968  1.1  mrg 	{
   2969  1.1  mrg 	  *total = 2 * cost2;
   2970  1.1  mrg 	  return true;
   2971  1.1  mrg 	}
   2972  1.1  mrg       /* fall through */
   2973  1.1  mrg 
   2974  1.1  mrg     case SIGN_EXTEND:
   2975  1.1  mrg     case ZERO_EXTEND:
   2976  1.1  mrg       *total = cost2;
   2977  1.1  mrg       return true;
   2978  1.1  mrg 
   2979  1.1  mrg     case MULT:
   2980  1.1  mrg 	{
   2981  1.1  mrg 	  op0 = XEXP (x, 0);
   2982  1.1  mrg 	  op1 = XEXP (x, 1);
   2983  1.1  mrg 	  if (GET_CODE (op0) == GET_CODE (op1)
   2984  1.1  mrg 	      && (GET_CODE (op0) == ZERO_EXTEND
   2985  1.1  mrg 		  || GET_CODE (op0) == SIGN_EXTEND))
   2986  1.1  mrg 	    {
   2987  1.1  mrg 	      *total = COSTS_N_INSNS (1);
   2988  1.1  mrg 	      op0 = XEXP (op0, 0);
   2989  1.1  mrg 	      op1 = XEXP (op1, 0);
   2990  1.1  mrg 	    }
   2991  1.1  mrg 	  else if (!speed)
   2992  1.1  mrg 	    *total = COSTS_N_INSNS (1);
   2993  1.1  mrg 	  else
   2994  1.1  mrg 	    *total = COSTS_N_INSNS (3);
   2995  1.1  mrg 
   2996  1.1  mrg 	  if (GET_CODE (op0) != REG
   2997  1.1  mrg 	      && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
   2998  1.1  mrg 	    *total += rtx_cost (op0, mode, MULT, 0, speed);
   2999  1.1  mrg 	  if (GET_CODE (op1) != REG
   3000  1.1  mrg 	      && (GET_CODE (op1) != SUBREG || GET_CODE (SUBREG_REG (op1)) != REG))
   3001  1.1  mrg 	    *total += rtx_cost (op1, mode, MULT, 1, speed);
   3002  1.1  mrg 	}
   3003  1.1  mrg       return true;
   3004  1.1  mrg 
   3005  1.1  mrg     case UDIV:
   3006  1.1  mrg     case UMOD:
   3007  1.1  mrg       *total = COSTS_N_INSNS (32);
   3008  1.1  mrg       return true;
   3009  1.1  mrg 
   3010  1.1  mrg     case VEC_CONCAT:
   3011  1.1  mrg     case VEC_SELECT:
   3012  1.1  mrg       if (outer_code == SET)
   3013  1.1  mrg 	*total = cost2;
   3014  1.1  mrg       return true;
   3015  1.1  mrg 
   3016  1.1  mrg     default:
   3017  1.1  mrg       return false;
   3018  1.1  mrg     }
   3019  1.1  mrg }
   3020  1.1  mrg 
   3021  1.1  mrg /* Used for communication between {push,pop}_multiple_operation (which
   3023  1.1  mrg    we use not only as a predicate) and the corresponding output functions.  */
   3024  1.1  mrg static int first_preg_to_save, first_dreg_to_save;
   3025  1.1  mrg static int n_regs_to_save;
   3026  1.1  mrg 
   3027  1.1  mrg int
   3028  1.1  mrg analyze_push_multiple_operation (rtx op)
   3029  1.1  mrg {
   3030  1.1  mrg   int lastdreg = 8, lastpreg = 6;
   3031  1.1  mrg   int i, group;
   3032  1.1  mrg 
   3033  1.1  mrg   first_preg_to_save = lastpreg;
   3034  1.1  mrg   first_dreg_to_save = lastdreg;
   3035  1.1  mrg   for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
   3036  1.1  mrg     {
   3037  1.1  mrg       rtx t = XVECEXP (op, 0, i);
   3038  1.1  mrg       rtx src, dest;
   3039  1.1  mrg       int regno;
   3040  1.1  mrg 
   3041  1.1  mrg       if (GET_CODE (t) != SET)
   3042  1.1  mrg 	return 0;
   3043  1.1  mrg 
   3044  1.1  mrg       src = SET_SRC (t);
   3045  1.1  mrg       dest = SET_DEST (t);
   3046  1.1  mrg       if (GET_CODE (dest) != MEM || ! REG_P (src))
   3047  1.1  mrg 	return 0;
   3048  1.1  mrg       dest = XEXP (dest, 0);
   3049  1.1  mrg       if (GET_CODE (dest) != PLUS
   3050  1.1  mrg 	  || ! REG_P (XEXP (dest, 0))
   3051  1.1  mrg 	  || REGNO (XEXP (dest, 0)) != REG_SP
   3052  1.1  mrg 	  || GET_CODE (XEXP (dest, 1)) != CONST_INT
   3053  1.1  mrg 	  || INTVAL (XEXP (dest, 1)) != -i * 4)
   3054  1.1  mrg 	return 0;
   3055  1.1  mrg 
   3056  1.1  mrg       regno = REGNO (src);
   3057  1.1  mrg       if (group == 0)
   3058  1.1  mrg 	{
   3059  1.1  mrg 	  if (D_REGNO_P (regno))
   3060  1.1  mrg 	    {
   3061  1.1  mrg 	      group = 1;
   3062  1.1  mrg 	      first_dreg_to_save = lastdreg = regno - REG_R0;
   3063  1.1  mrg 	    }
   3064  1.1  mrg 	  else if (regno >= REG_P0 && regno <= REG_P7)
   3065  1.1  mrg 	    {
   3066  1.1  mrg 	      group = 2;
   3067  1.1  mrg 	      first_preg_to_save = lastpreg = regno - REG_P0;
   3068  1.1  mrg 	    }
   3069  1.1  mrg 	  else
   3070  1.1  mrg 	    return 0;
   3071  1.1  mrg 
   3072  1.1  mrg 	  continue;
   3073  1.1  mrg 	}
   3074  1.1  mrg 
   3075  1.1  mrg       if (group == 1)
   3076  1.1  mrg 	{
   3077  1.1  mrg 	  if (regno >= REG_P0 && regno <= REG_P7)
   3078  1.1  mrg 	    {
   3079  1.1  mrg 	      group = 2;
   3080  1.1  mrg 	      first_preg_to_save = lastpreg = regno - REG_P0;
   3081  1.1  mrg 	    }
   3082  1.1  mrg 	  else if (regno != REG_R0 + lastdreg + 1)
   3083  1.1  mrg 	    return 0;
   3084  1.1  mrg 	  else
   3085  1.1  mrg 	    lastdreg++;
   3086  1.1  mrg 	}
   3087  1.1  mrg       else if (group == 2)
   3088  1.1  mrg 	{
   3089  1.1  mrg 	  if (regno != REG_P0 + lastpreg + 1)
   3090  1.1  mrg 	    return 0;
   3091  1.1  mrg 	  lastpreg++;
   3092  1.1  mrg 	}
   3093  1.1  mrg     }
   3094  1.1  mrg   n_regs_to_save = 8 - first_dreg_to_save + 6 - first_preg_to_save;
   3095  1.1  mrg   return 1;
   3096  1.1  mrg }
   3097  1.1  mrg 
   3098  1.1  mrg int
   3099  1.1  mrg analyze_pop_multiple_operation (rtx op)
   3100  1.1  mrg {
   3101  1.1  mrg   int lastdreg = 8, lastpreg = 6;
   3102  1.1  mrg   int i, group;
   3103  1.1  mrg 
   3104  1.1  mrg   for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
   3105  1.1  mrg     {
   3106  1.1  mrg       rtx t = XVECEXP (op, 0, i);
   3107  1.1  mrg       rtx src, dest;
   3108  1.1  mrg       int regno;
   3109  1.1  mrg 
   3110  1.1  mrg       if (GET_CODE (t) != SET)
   3111  1.1  mrg 	return 0;
   3112  1.1  mrg 
   3113  1.1  mrg       src = SET_SRC (t);
   3114  1.1  mrg       dest = SET_DEST (t);
   3115  1.1  mrg       if (GET_CODE (src) != MEM || ! REG_P (dest))
   3116  1.1  mrg 	return 0;
   3117  1.1  mrg       src = XEXP (src, 0);
   3118  1.1  mrg 
   3119  1.1  mrg       if (i == 1)
   3120  1.1  mrg 	{
   3121  1.1  mrg 	  if (! REG_P (src) || REGNO (src) != REG_SP)
   3122  1.1  mrg 	    return 0;
   3123  1.1  mrg 	}
   3124  1.1  mrg       else if (GET_CODE (src) != PLUS
   3125  1.1  mrg 	       || ! REG_P (XEXP (src, 0))
   3126  1.1  mrg 	       || REGNO (XEXP (src, 0)) != REG_SP
   3127  1.1  mrg 	       || GET_CODE (XEXP (src, 1)) != CONST_INT
   3128  1.1  mrg 	       || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
   3129  1.1  mrg 	return 0;
   3130  1.1  mrg 
   3131  1.1  mrg       regno = REGNO (dest);
   3132  1.1  mrg       if (group == 0)
   3133  1.1  mrg 	{
   3134  1.1  mrg 	  if (regno == REG_R7)
   3135  1.1  mrg 	    {
   3136  1.1  mrg 	      group = 1;
   3137  1.1  mrg 	      lastdreg = 7;
   3138  1.1  mrg 	    }
   3139  1.1  mrg 	  else if (regno != REG_P0 + lastpreg - 1)
   3140  1.1  mrg 	    return 0;
   3141  1.1  mrg 	  else
   3142  1.1  mrg 	    lastpreg--;
   3143  1.1  mrg 	}
   3144  1.1  mrg       else if (group == 1)
   3145  1.1  mrg 	{
   3146  1.1  mrg 	  if (regno != REG_R0 + lastdreg - 1)
   3147  1.1  mrg 	    return 0;
   3148  1.1  mrg 	  else
   3149  1.1  mrg 	    lastdreg--;
   3150  1.1  mrg 	}
   3151  1.1  mrg     }
   3152  1.1  mrg   first_dreg_to_save = lastdreg;
   3153  1.1  mrg   first_preg_to_save = lastpreg;
   3154  1.1  mrg   n_regs_to_save = 8 - first_dreg_to_save + 6 - first_preg_to_save;
   3155  1.1  mrg   return 1;
   3156  1.1  mrg }
   3157  1.1  mrg 
   3158  1.1  mrg /* Emit assembly code for one multi-register push described by INSN, with
   3159  1.1  mrg    operands in OPERANDS.  */
   3160  1.1  mrg 
   3161  1.1  mrg void
   3162  1.1  mrg output_push_multiple (rtx insn, rtx *operands)
   3163  1.1  mrg {
   3164  1.1  mrg   char buf[80];
   3165  1.1  mrg   int ok;
   3166  1.1  mrg 
   3167  1.1  mrg   /* Validate the insn again, and compute first_[dp]reg_to_save. */
   3168  1.1  mrg   ok = analyze_push_multiple_operation (PATTERN (insn));
   3169  1.1  mrg   gcc_assert (ok);
   3170  1.1  mrg 
   3171  1.1  mrg   if (first_dreg_to_save == 8)
   3172  1.1  mrg     sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
   3173  1.1  mrg   else if (first_preg_to_save == 6)
   3174  1.1  mrg     sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
   3175  1.1  mrg   else
   3176  1.1  mrg     sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
   3177  1.1  mrg 	     first_dreg_to_save, first_preg_to_save);
   3178  1.1  mrg 
   3179  1.1  mrg   output_asm_insn (buf, operands);
   3180  1.1  mrg }
   3181  1.1  mrg 
   3182  1.1  mrg /* Emit assembly code for one multi-register pop described by INSN, with
   3183  1.1  mrg    operands in OPERANDS.  */
   3184  1.1  mrg 
   3185  1.1  mrg void
   3186  1.1  mrg output_pop_multiple (rtx insn, rtx *operands)
   3187  1.1  mrg {
   3188  1.1  mrg   char buf[80];
   3189  1.1  mrg   int ok;
   3190  1.1  mrg 
   3191  1.1  mrg   /* Validate the insn again, and compute first_[dp]reg_to_save. */
   3192  1.1  mrg   ok = analyze_pop_multiple_operation (PATTERN (insn));
   3193  1.1  mrg   gcc_assert (ok);
   3194  1.1  mrg 
   3195  1.1  mrg   if (first_dreg_to_save == 8)
   3196  1.1  mrg     sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
   3197  1.1  mrg   else if (first_preg_to_save == 6)
   3198  1.1  mrg     sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
   3199  1.1  mrg   else
   3200  1.1  mrg     sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
   3201  1.1  mrg 	     first_dreg_to_save, first_preg_to_save);
   3202  1.1  mrg 
   3203  1.1  mrg   output_asm_insn (buf, operands);
   3204  1.1  mrg }
   3205  1.1  mrg 
   3206  1.1  mrg /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE.  */
   3207  1.1  mrg 
   3208  1.1  mrg static void
   3209  1.1  mrg single_move_for_cpymem (rtx dst, rtx src, machine_mode mode, HOST_WIDE_INT offset)
   3210  1.1  mrg {
   3211  1.1  mrg   rtx scratch = gen_reg_rtx (mode);
   3212  1.1  mrg   rtx srcmem, dstmem;
   3213  1.1  mrg 
   3214  1.1  mrg   srcmem = adjust_address_nv (src, mode, offset);
   3215  1.1  mrg   dstmem = adjust_address_nv (dst, mode, offset);
   3216  1.1  mrg   emit_move_insn (scratch, srcmem);
   3217  1.1  mrg   emit_move_insn (dstmem, scratch);
   3218  1.1  mrg }
   3219  1.1  mrg 
   3220  1.1  mrg /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
   3221  1.1  mrg    alignment ALIGN_EXP.  Return true if successful, false if we should fall
   3222  1.1  mrg    back on a different method.  */
   3223  1.1  mrg 
   3224  1.1  mrg bool
   3225  1.1  mrg bfin_expand_cpymem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
   3226  1.1  mrg {
   3227  1.1  mrg   rtx srcreg, destreg, countreg;
   3228  1.1  mrg   HOST_WIDE_INT align = 0;
   3229  1.1  mrg   unsigned HOST_WIDE_INT count = 0;
   3230  1.1  mrg 
   3231  1.1  mrg   if (GET_CODE (align_exp) == CONST_INT)
   3232  1.1  mrg     align = INTVAL (align_exp);
   3233  1.1  mrg   if (GET_CODE (count_exp) == CONST_INT)
   3234  1.1  mrg     {
   3235  1.1  mrg       count = INTVAL (count_exp);
   3236  1.1  mrg #if 0
   3237  1.1  mrg       if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
   3238  1.1  mrg 	return false;
   3239  1.1  mrg #endif
   3240  1.1  mrg     }
   3241  1.1  mrg 
   3242  1.1  mrg   /* If optimizing for size, only do single copies inline.  */
   3243  1.1  mrg   if (optimize_size)
   3244  1.1  mrg     {
   3245  1.1  mrg       if (count == 2 && align < 2)
   3246  1.1  mrg 	return false;
   3247  1.1  mrg       if (count == 4 && align < 4)
   3248  1.1  mrg 	return false;
   3249  1.1  mrg       if (count != 1 && count != 2 && count != 4)
   3250  1.1  mrg 	return false;
   3251  1.1  mrg     }
   3252  1.1  mrg   if (align < 2 && count != 1)
   3253  1.1  mrg     return false;
   3254  1.1  mrg 
   3255  1.1  mrg   destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
   3256  1.1  mrg   if (destreg != XEXP (dst, 0))
   3257  1.1  mrg     dst = replace_equiv_address_nv (dst, destreg);
   3258  1.1  mrg   srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
   3259  1.1  mrg   if (srcreg != XEXP (src, 0))
   3260  1.1  mrg     src = replace_equiv_address_nv (src, srcreg);
   3261  1.1  mrg 
   3262  1.1  mrg   if (count != 0 && align >= 2)
   3263  1.1  mrg     {
   3264  1.1  mrg       unsigned HOST_WIDE_INT offset = 0;
   3265  1.1  mrg 
   3266  1.1  mrg       if (align >= 4)
   3267  1.1  mrg 	{
   3268  1.1  mrg 	  if ((count & ~3) == 4)
   3269  1.1  mrg 	    {
   3270  1.1  mrg 	      single_move_for_cpymem (dst, src, SImode, offset);
   3271  1.1  mrg 	      offset = 4;
   3272  1.1  mrg 	    }
   3273  1.1  mrg 	  else if (count & ~3)
   3274  1.1  mrg 	    {
   3275  1.1  mrg 	      HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
   3276  1.1  mrg 	      countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
   3277  1.1  mrg 
   3278  1.1  mrg 	      emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
   3279  1.1  mrg 	      cfun->machine->has_loopreg_clobber = true;
   3280  1.1  mrg 	    }
   3281  1.1  mrg 	  if (count & 2)
   3282  1.1  mrg 	    {
   3283  1.1  mrg 	      single_move_for_cpymem (dst, src, HImode, offset);
   3284  1.1  mrg 	      offset += 2;
   3285  1.1  mrg 	    }
   3286  1.1  mrg 	}
   3287  1.1  mrg       else
   3288  1.1  mrg 	{
   3289  1.1  mrg 	  if ((count & ~1) == 2)
   3290  1.1  mrg 	    {
   3291  1.1  mrg 	      single_move_for_cpymem (dst, src, HImode, offset);
   3292  1.1  mrg 	      offset = 2;
   3293  1.1  mrg 	    }
   3294  1.1  mrg 	  else if (count & ~1)
   3295  1.1  mrg 	    {
   3296  1.1  mrg 	      HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
   3297  1.1  mrg 	      countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
   3298  1.1  mrg 
   3299  1.1  mrg 	      emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
   3300  1.1  mrg 	      cfun->machine->has_loopreg_clobber = true;
   3301  1.1  mrg 	    }
   3302  1.1  mrg 	}
   3303  1.1  mrg       if (count & 1)
   3304  1.1  mrg 	{
   3305  1.1  mrg 	  single_move_for_cpymem (dst, src, QImode, offset);
   3306  1.1  mrg 	}
   3307  1.1  mrg       return true;
   3308  1.1  mrg     }
   3309  1.1  mrg   return false;
   3310  1.1  mrg }
   3311  1.1  mrg 
   3312  1.1  mrg /* Compute the alignment for a local variable.
   3314  1.1  mrg    TYPE is the data type, and ALIGN is the alignment that
   3315  1.1  mrg    the object would ordinarily have.  The value of this macro is used
   3316  1.1  mrg    instead of that alignment to align the object.  */
   3317  1.1  mrg 
   3318  1.1  mrg unsigned
   3319  1.1  mrg bfin_local_alignment (tree type, unsigned align)
   3320  1.1  mrg {
   3321  1.1  mrg   /* Increasing alignment for (relatively) big types allows the builtin
   3322  1.1  mrg      memcpy can use 32 bit loads/stores.  */
   3323  1.1  mrg   if (TYPE_SIZE (type)
   3324  1.1  mrg       && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
   3325  1.1  mrg       && wi::gtu_p (wi::to_wide (TYPE_SIZE (type)), 8)
   3326  1.1  mrg       && align < 32)
   3327  1.1  mrg     return 32;
   3328  1.1  mrg   return align;
   3329  1.1  mrg }
   3330  1.1  mrg 
   3331  1.1  mrg /* Implement TARGET_SCHED_ISSUE_RATE.  */
   3333  1.1  mrg 
   3334  1.1  mrg static int
   3335  1.1  mrg bfin_issue_rate (void)
   3336  1.1  mrg {
   3337  1.1  mrg   return 3;
   3338  1.1  mrg }
   3339  1.1  mrg 
   3340  1.1  mrg static int
   3341  1.1  mrg bfin_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn, int cost,
   3342  1.1  mrg 		  unsigned int)
   3343  1.1  mrg {
   3344  1.1  mrg   enum attr_type dep_insn_type;
   3345  1.1  mrg   int dep_insn_code_number;
   3346  1.1  mrg 
   3347  1.1  mrg   /* Anti and output dependencies have zero cost.  */
   3348  1.1  mrg   if (dep_type != 0)
   3349  1.1  mrg     return 0;
   3350  1.1  mrg 
   3351  1.1  mrg   dep_insn_code_number = recog_memoized (dep_insn);
   3352  1.1  mrg 
   3353  1.1  mrg   /* If we can't recognize the insns, we can't really do anything.  */
   3354  1.1  mrg   if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
   3355  1.1  mrg     return cost;
   3356  1.1  mrg 
   3357  1.1  mrg   dep_insn_type = get_attr_type (dep_insn);
   3358  1.1  mrg 
   3359  1.1  mrg   if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)
   3360  1.1  mrg     {
   3361  1.1  mrg       rtx pat = PATTERN (dep_insn);
   3362  1.1  mrg       rtx dest, src;
   3363  1.1  mrg 
   3364  1.1  mrg       if (GET_CODE (pat) == PARALLEL)
   3365  1.1  mrg 	pat = XVECEXP (pat, 0, 0);
   3366  1.1  mrg       dest = SET_DEST (pat);
   3367  1.1  mrg       src = SET_SRC (pat);
   3368  1.1  mrg       if (! ADDRESS_REGNO_P (REGNO (dest))
   3369  1.1  mrg 	  || ! (MEM_P (src) || D_REGNO_P (REGNO (src))))
   3370  1.1  mrg 	return cost;
   3371  1.1  mrg       return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);
   3372  1.1  mrg     }
   3373  1.1  mrg 
   3374  1.1  mrg   return cost;
   3375  1.1  mrg }
   3376  1.1  mrg 
   3377  1.1  mrg /* This function acts like NEXT_INSN, but is aware of three-insn bundles and
   3379  1.1  mrg    skips all subsequent parallel instructions if INSN is the start of such
   3380  1.1  mrg    a group.  */
   3381  1.1  mrg static rtx_insn *
   3382  1.1  mrg find_next_insn_start (rtx_insn *insn)
   3383  1.1  mrg {
   3384  1.1  mrg   if (GET_MODE (insn) == SImode)
   3385  1.1  mrg     {
   3386  1.1  mrg       while (GET_MODE (insn) != QImode)
   3387  1.1  mrg 	insn = NEXT_INSN (insn);
   3388  1.1  mrg     }
   3389  1.1  mrg   return NEXT_INSN (insn);
   3390  1.1  mrg }
   3391  1.1  mrg 
   3392  1.1  mrg /* This function acts like PREV_INSN, but is aware of three-insn bundles and
   3393  1.1  mrg    skips all subsequent parallel instructions if INSN is the start of such
   3394  1.1  mrg    a group.  */
   3395  1.1  mrg static rtx_insn *
   3396  1.1  mrg find_prev_insn_start (rtx_insn *insn)
   3397  1.1  mrg {
   3398  1.1  mrg   insn = PREV_INSN (insn);
   3399  1.1  mrg   gcc_assert (GET_MODE (insn) != SImode);
   3400  1.1  mrg   if (GET_MODE (insn) == QImode)
   3401  1.1  mrg     {
   3402  1.1  mrg       while (GET_MODE (PREV_INSN (insn)) == SImode)
   3403  1.1  mrg 	insn = PREV_INSN (insn);
   3404  1.1  mrg     }
   3405  1.1  mrg   return insn;
   3406  1.1  mrg }
   3407  1.1  mrg 
   3408  1.1  mrg /* Implement TARGET_CAN_USE_DOLOOP_P.  */
   3410  1.1  mrg 
   3411  1.1  mrg static bool
   3412  1.1  mrg bfin_can_use_doloop_p (const widest_int &, const widest_int &iterations_max,
   3413  1.1  mrg 		       unsigned int, bool)
   3414  1.1  mrg {
   3415  1.1  mrg   /* Due to limitations in the hardware (an initial loop count of 0
   3416  1.1  mrg      does not loop 2^32 times) we must avoid to generate a hardware
   3417  1.1  mrg      loops when we cannot rule out this case.  */
   3418  1.1  mrg   return (wi::ltu_p (iterations_max, 0xFFFFFFFF));
   3419  1.1  mrg }
   3420  1.1  mrg 
   3421  1.1  mrg /* Increment the counter for the number of loop instructions in the
   3422  1.1  mrg    current function.  */
   3423  1.1  mrg 
   3424  1.1  mrg void
   3425  1.1  mrg bfin_hardware_loop (void)
   3426  1.1  mrg {
   3427  1.1  mrg   cfun->machine->has_hardware_loops++;
   3428  1.1  mrg }
   3429  1.1  mrg 
   3430  1.1  mrg /* Maximum loop nesting depth.  */
   3431  1.1  mrg #define MAX_LOOP_DEPTH 2
   3432  1.1  mrg 
   3433  1.1  mrg /* Maximum size of a loop.  */
   3434  1.1  mrg #define MAX_LOOP_LENGTH 2042
   3435  1.1  mrg 
   3436  1.1  mrg /* Maximum distance of the LSETUP instruction from the loop start.  */
   3437  1.1  mrg #define MAX_LSETUP_DISTANCE 30
   3438  1.1  mrg 
   3439  1.1  mrg /* Estimate the length of INSN conservatively.  */
   3440  1.1  mrg 
   3441  1.1  mrg static int
   3442  1.1  mrg length_for_loop (rtx_insn *insn)
   3443  1.1  mrg {
   3444  1.1  mrg   int length = 0;
   3445  1.1  mrg   if (JUMP_P (insn) && any_condjump_p (insn) && !optimize_size)
   3446  1.1  mrg     {
   3447  1.1  mrg       if (ENABLE_WA_SPECULATIVE_SYNCS)
   3448  1.1  mrg 	length = 8;
   3449  1.1  mrg       else if (ENABLE_WA_SPECULATIVE_LOADS)
   3450  1.1  mrg 	length = 6;
   3451  1.1  mrg     }
   3452  1.1  mrg   else if (LABEL_P (insn))
   3453  1.1  mrg     {
   3454  1.1  mrg       if (ENABLE_WA_SPECULATIVE_SYNCS)
   3455  1.1  mrg 	length = 4;
   3456  1.1  mrg     }
   3457  1.1  mrg 
   3458  1.1  mrg   if (NONDEBUG_INSN_P (insn))
   3459  1.1  mrg     length += get_attr_length (insn);
   3460  1.1  mrg 
   3461  1.1  mrg   return length;
   3462  1.1  mrg }
   3463  1.1  mrg 
   3464  1.1  mrg /* Optimize LOOP.  */
   3465  1.1  mrg 
   3466  1.1  mrg static bool
   3467  1.1  mrg hwloop_optimize (hwloop_info loop)
   3468  1.1  mrg {
   3469  1.1  mrg   basic_block bb;
   3470  1.1  mrg   rtx_insn *insn, *last_insn;
   3471  1.1  mrg   rtx loop_init, start_label, end_label;
   3472  1.1  mrg   rtx iter_reg, scratchreg, scratch_init;
   3473  1.1  mrg   rtx_insn *scratch_init_insn;
   3474  1.1  mrg   rtx lc_reg, lt_reg, lb_reg;
   3475  1.1  mrg   rtx seq_end;
   3476  1.1  mrg   rtx_insn *seq;
   3477  1.1  mrg   int length;
   3478  1.1  mrg   bool clobber0, clobber1;
   3479  1.1  mrg 
   3480  1.1  mrg   if (loop->depth > MAX_LOOP_DEPTH)
   3481  1.1  mrg     {
   3482  1.1  mrg       if (dump_file)
   3483  1.1  mrg 	fprintf (dump_file, ";; loop %d too deep\n", loop->loop_no);
   3484  1.1  mrg       return false;
   3485  1.1  mrg     }
   3486  1.1  mrg 
   3487  1.1  mrg   /* Get the loop iteration register.  */
   3488  1.1  mrg   iter_reg = loop->iter_reg;
   3489  1.1  mrg 
   3490  1.1  mrg   gcc_assert (REG_P (iter_reg));
   3491  1.1  mrg 
   3492  1.1  mrg   scratchreg = NULL_RTX;
   3493  1.1  mrg   scratch_init = iter_reg;
   3494  1.1  mrg   scratch_init_insn = NULL;
   3495  1.1  mrg   if (!PREG_P (iter_reg) && loop->incoming_src)
   3496  1.1  mrg     {
   3497  1.1  mrg       basic_block bb_in = loop->incoming_src;
   3498  1.1  mrg       int i;
   3499  1.1  mrg       for (i = REG_P0; i <= REG_P5; i++)
   3500  1.1  mrg 	if ((df_regs_ever_live_p (i)
   3501  1.1  mrg 	     || (funkind (TREE_TYPE (current_function_decl)) == SUBROUTINE
   3502  1.1  mrg 		 && call_used_or_fixed_reg_p (i)))
   3503  1.1  mrg 	    && !REGNO_REG_SET_P (df_get_live_out (bb_in), i))
   3504  1.1  mrg 	  {
   3505  1.1  mrg 	    scratchreg = gen_rtx_REG (SImode, i);
   3506  1.1  mrg 	    break;
   3507  1.1  mrg 	  }
   3508  1.1  mrg       for (insn = BB_END (bb_in); insn != BB_HEAD (bb_in);
   3509  1.1  mrg 	   insn = PREV_INSN (insn))
   3510  1.1  mrg 	{
   3511  1.1  mrg 	  rtx set;
   3512  1.1  mrg 	  if (NOTE_P (insn) || BARRIER_P (insn))
   3513  1.1  mrg 	    continue;
   3514  1.1  mrg 	  set = single_set (insn);
   3515  1.1  mrg 	  if (set && rtx_equal_p (SET_DEST (set), iter_reg))
   3516  1.1  mrg 	    {
   3517  1.1  mrg 	      if (CONSTANT_P (SET_SRC (set)))
   3518  1.1  mrg 		{
   3519  1.1  mrg 		  scratch_init = SET_SRC (set);
   3520  1.1  mrg 		  scratch_init_insn = insn;
   3521  1.1  mrg 		}
   3522  1.1  mrg 	      break;
   3523  1.1  mrg 	    }
   3524  1.1  mrg 	  else if (reg_mentioned_p (iter_reg, PATTERN (insn)))
   3525  1.1  mrg 	    break;
   3526  1.1  mrg 	}
   3527  1.1  mrg     }
   3528  1.1  mrg 
   3529  1.1  mrg   if (loop->incoming_src)
   3530  1.1  mrg     {
   3531  1.1  mrg       /* Make sure the predecessor is before the loop start label, as required by
   3532  1.1  mrg 	 the LSETUP instruction.  */
   3533  1.1  mrg       length = 0;
   3534  1.1  mrg       insn = BB_END (loop->incoming_src);
   3535  1.1  mrg       /* If we have to insert the LSETUP before a jump, count that jump in the
   3536  1.1  mrg 	 length.  */
   3537  1.1  mrg       if (vec_safe_length (loop->incoming) > 1
   3538  1.1  mrg 	  || !(loop->incoming->last ()->flags & EDGE_FALLTHRU))
   3539  1.1  mrg 	{
   3540  1.1  mrg 	  gcc_assert (JUMP_P (insn));
   3541  1.1  mrg 	  insn = PREV_INSN (insn);
   3542  1.1  mrg 	}
   3543  1.1  mrg 
   3544  1.1  mrg       for (; insn && insn != loop->start_label; insn = NEXT_INSN (insn))
   3545  1.1  mrg 	length += length_for_loop (insn);
   3546  1.1  mrg 
   3547  1.1  mrg       if (!insn)
   3548  1.1  mrg 	{
   3549  1.1  mrg 	  if (dump_file)
   3550  1.1  mrg 	    fprintf (dump_file, ";; loop %d lsetup not before loop_start\n",
   3551  1.1  mrg 		     loop->loop_no);
   3552  1.1  mrg 	  return false;
   3553  1.1  mrg 	}
   3554  1.1  mrg 
   3555  1.1  mrg       /* Account for the pop of a scratch register where necessary.  */
   3556  1.1  mrg       if (!PREG_P (iter_reg) && scratchreg == NULL_RTX
   3557  1.1  mrg 	  && ENABLE_WA_LOAD_LCREGS)
   3558  1.1  mrg 	length += 2;
   3559  1.1  mrg 
   3560  1.1  mrg       if (length > MAX_LSETUP_DISTANCE)
   3561  1.1  mrg 	{
   3562  1.1  mrg 	  if (dump_file)
   3563  1.1  mrg 	    fprintf (dump_file, ";; loop %d lsetup too far away\n", loop->loop_no);
   3564  1.1  mrg 	  return false;
   3565  1.1  mrg 	}
   3566  1.1  mrg     }
   3567  1.1  mrg 
   3568  1.1  mrg   /* Check if start_label appears before loop_end and calculate the
   3569  1.1  mrg      offset between them.  We calculate the length of instructions
   3570  1.1  mrg      conservatively.  */
   3571  1.1  mrg   length = 0;
   3572  1.1  mrg   for (insn = loop->start_label;
   3573  1.1  mrg        insn && insn != loop->loop_end;
   3574  1.1  mrg        insn = NEXT_INSN (insn))
   3575  1.1  mrg     length += length_for_loop (insn);
   3576  1.1  mrg 
   3577  1.1  mrg   if (!insn)
   3578  1.1  mrg     {
   3579  1.1  mrg       if (dump_file)
   3580  1.1  mrg 	fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
   3581  1.1  mrg 		 loop->loop_no);
   3582  1.1  mrg       return false;
   3583  1.1  mrg     }
   3584  1.1  mrg 
   3585  1.1  mrg   loop->length = length;
   3586  1.1  mrg   if (loop->length > MAX_LOOP_LENGTH)
   3587  1.1  mrg     {
   3588  1.1  mrg       if (dump_file)
   3589  1.1  mrg 	fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
   3590  1.1  mrg       return false;
   3591  1.1  mrg     }
   3592  1.1  mrg 
   3593  1.1  mrg   /* Scan all the blocks to make sure they don't use iter_reg.  */
   3594  1.1  mrg   if (loop->iter_reg_used || loop->iter_reg_used_outside)
   3595  1.1  mrg     {
   3596  1.1  mrg       if (dump_file)
   3597  1.1  mrg 	fprintf (dump_file, ";; loop %d uses iterator\n", loop->loop_no);
   3598  1.1  mrg       return false;
   3599  1.1  mrg     }
   3600  1.1  mrg 
   3601  1.1  mrg   clobber0 = (TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC0)
   3602  1.1  mrg 	      || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LB0)
   3603  1.1  mrg 	      || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LT0));
   3604  1.1  mrg   clobber1 = (TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC1)
   3605  1.1  mrg 	      || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LB1)
   3606  1.1  mrg 	      || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LT1));
   3607  1.1  mrg   if (clobber0 && clobber1)
   3608  1.1  mrg     {
   3609  1.1  mrg       if (dump_file)
   3610  1.1  mrg 	fprintf (dump_file, ";; loop %d no loop reg available\n",
   3611  1.1  mrg 		 loop->loop_no);
   3612  1.1  mrg       return false;
   3613  1.1  mrg     }
   3614  1.1  mrg 
   3615  1.1  mrg   /* There should be an instruction before the loop_end instruction
   3616  1.1  mrg      in the same basic block. And the instruction must not be
   3617  1.1  mrg      - JUMP
   3618  1.1  mrg      - CONDITIONAL BRANCH
   3619  1.1  mrg      - CALL
   3620  1.1  mrg      - CSYNC
   3621  1.1  mrg      - SSYNC
   3622  1.1  mrg      - Returns (RTS, RTN, etc.)  */
   3623  1.1  mrg 
   3624  1.1  mrg   bb = loop->tail;
   3625  1.1  mrg   last_insn = find_prev_insn_start (loop->loop_end);
   3626  1.1  mrg 
   3627  1.1  mrg   while (1)
   3628  1.1  mrg     {
   3629  1.1  mrg       for (; last_insn != BB_HEAD (bb);
   3630  1.1  mrg 	   last_insn = find_prev_insn_start (last_insn))
   3631  1.1  mrg 	if (NONDEBUG_INSN_P (last_insn))
   3632  1.1  mrg 	  break;
   3633  1.1  mrg 
   3634  1.1  mrg       if (last_insn != BB_HEAD (bb))
   3635  1.1  mrg 	break;
   3636  1.1  mrg 
   3637  1.1  mrg       if (single_pred_p (bb)
   3638  1.1  mrg 	  && single_pred_edge (bb)->flags & EDGE_FALLTHRU
   3639  1.1  mrg 	  && single_pred (bb) != ENTRY_BLOCK_PTR_FOR_FN (cfun))
   3640  1.1  mrg 	{
   3641  1.1  mrg 	  bb = single_pred (bb);
   3642  1.1  mrg 	  last_insn = BB_END (bb);
   3643  1.1  mrg 	  continue;
   3644  1.1  mrg 	}
   3645  1.1  mrg       else
   3646  1.1  mrg 	{
   3647  1.1  mrg 	  last_insn = NULL;
   3648  1.1  mrg 	  break;
   3649  1.1  mrg 	}
   3650  1.1  mrg     }
   3651  1.1  mrg 
   3652  1.1  mrg   if (!last_insn)
   3653  1.1  mrg     {
   3654  1.1  mrg       if (dump_file)
   3655  1.1  mrg 	fprintf (dump_file, ";; loop %d has no last instruction\n",
   3656  1.1  mrg 		 loop->loop_no);
   3657  1.1  mrg       return false;
   3658  1.1  mrg     }
   3659  1.1  mrg 
   3660  1.1  mrg   if (JUMP_P (last_insn) && !any_condjump_p (last_insn))
   3661  1.1  mrg     {
   3662  1.1  mrg       if (dump_file)
   3663  1.1  mrg 	fprintf (dump_file, ";; loop %d has bad last instruction\n",
   3664  1.1  mrg 		 loop->loop_no);
   3665  1.1  mrg       return false;
   3666  1.1  mrg     }
   3667  1.1  mrg   /* In all other cases, try to replace a bad last insn with a nop.  */
   3668  1.1  mrg   else if (JUMP_P (last_insn)
   3669  1.1  mrg 	   || CALL_P (last_insn)
   3670  1.1  mrg 	   || get_attr_type (last_insn) == TYPE_SYNC
   3671  1.1  mrg 	   || get_attr_type (last_insn) == TYPE_CALL
   3672  1.1  mrg 	   || get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI
   3673  1.1  mrg 	   || recog_memoized (last_insn) == CODE_FOR_return_internal
   3674  1.1  mrg 	   || GET_CODE (PATTERN (last_insn)) == ASM_INPUT
   3675  1.1  mrg 	   || asm_noperands (PATTERN (last_insn)) >= 0)
   3676  1.1  mrg     {
   3677  1.1  mrg       if (loop->length + 2 > MAX_LOOP_LENGTH)
   3678  1.1  mrg 	{
   3679  1.1  mrg 	  if (dump_file)
   3680  1.1  mrg 	    fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
   3681  1.1  mrg 	  return false;
   3682  1.1  mrg 	}
   3683  1.1  mrg       if (dump_file)
   3684  1.1  mrg 	fprintf (dump_file, ";; loop %d has bad last insn; replace with nop\n",
   3685  1.1  mrg 		 loop->loop_no);
   3686  1.1  mrg 
   3687  1.1  mrg       last_insn = emit_insn_after (gen_forced_nop (), last_insn);
   3688  1.1  mrg     }
   3689  1.1  mrg 
   3690  1.1  mrg   loop->last_insn = last_insn;
   3691  1.1  mrg 
   3692  1.1  mrg   /* The loop is good for replacement.  */
   3693  1.1  mrg   start_label = loop->start_label;
   3694  1.1  mrg   end_label = gen_label_rtx ();
   3695  1.1  mrg   iter_reg = loop->iter_reg;
   3696  1.1  mrg 
   3697  1.1  mrg   if (loop->depth == 1 && !clobber1)
   3698  1.1  mrg     {
   3699  1.1  mrg       lc_reg = gen_rtx_REG (SImode, REG_LC1);
   3700  1.1  mrg       lb_reg = gen_rtx_REG (SImode, REG_LB1);
   3701  1.1  mrg       lt_reg = gen_rtx_REG (SImode, REG_LT1);
   3702  1.1  mrg       SET_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC1);
   3703  1.1  mrg     }
   3704  1.1  mrg   else
   3705  1.1  mrg     {
   3706  1.1  mrg       lc_reg = gen_rtx_REG (SImode, REG_LC0);
   3707  1.1  mrg       lb_reg = gen_rtx_REG (SImode, REG_LB0);
   3708  1.1  mrg       lt_reg = gen_rtx_REG (SImode, REG_LT0);
   3709  1.1  mrg       SET_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC0);
   3710  1.1  mrg     }
   3711  1.1  mrg 
   3712  1.1  mrg   loop->end_label = end_label;
   3713  1.1  mrg 
   3714  1.1  mrg   /* Create a sequence containing the loop setup.  */
   3715  1.1  mrg   start_sequence ();
   3716  1.1  mrg 
   3717  1.1  mrg   /* LSETUP only accepts P registers.  If we have one, we can use it,
   3718  1.1  mrg      otherwise there are several ways of working around the problem.
   3719  1.1  mrg      If we're not affected by anomaly 312, we can load the LC register
   3720  1.1  mrg      from any iteration register, and use LSETUP without initialization.
   3721  1.1  mrg      If we've found a P scratch register that's not live here, we can
   3722  1.1  mrg      instead copy the iter_reg into that and use an initializing LSETUP.
   3723  1.1  mrg      If all else fails, push and pop P0 and use it as a scratch.  */
   3724  1.1  mrg   if (P_REGNO_P (REGNO (iter_reg)))
   3725  1.1  mrg     {
   3726  1.1  mrg       loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
   3727  1.1  mrg 					    lb_reg, end_label,
   3728  1.1  mrg 					    lc_reg, iter_reg);
   3729  1.1  mrg       seq_end = emit_insn (loop_init);
   3730  1.1  mrg     }
   3731  1.1  mrg   else if (!ENABLE_WA_LOAD_LCREGS && DPREG_P (iter_reg))
   3732  1.1  mrg     {
   3733  1.1  mrg       emit_insn (gen_movsi (lc_reg, iter_reg));
   3734  1.1  mrg       loop_init = gen_lsetup_without_autoinit (lt_reg, start_label,
   3735  1.1  mrg 					       lb_reg, end_label,
   3736  1.1  mrg 					       lc_reg);
   3737  1.1  mrg       seq_end = emit_insn (loop_init);
   3738  1.1  mrg     }
   3739  1.1  mrg   else if (scratchreg != NULL_RTX)
   3740  1.1  mrg     {
   3741  1.1  mrg       emit_insn (gen_movsi (scratchreg, scratch_init));
   3742  1.1  mrg       loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
   3743  1.1  mrg 					    lb_reg, end_label,
   3744  1.1  mrg 					    lc_reg, scratchreg);
   3745  1.1  mrg       seq_end = emit_insn (loop_init);
   3746  1.1  mrg       if (scratch_init_insn != NULL_RTX)
   3747  1.1  mrg 	delete_insn (scratch_init_insn);
   3748  1.1  mrg     }
   3749  1.1  mrg   else
   3750  1.1  mrg     {
   3751  1.1  mrg       rtx p0reg = gen_rtx_REG (SImode, REG_P0);
   3752  1.1  mrg       rtx push = gen_frame_mem (SImode,
   3753  1.1  mrg 				gen_rtx_PRE_DEC (SImode, stack_pointer_rtx));
   3754  1.1  mrg       rtx pop = gen_frame_mem (SImode,
   3755  1.1  mrg 			       gen_rtx_POST_INC (SImode, stack_pointer_rtx));
   3756  1.1  mrg       emit_insn (gen_movsi (push, p0reg));
   3757  1.1  mrg       emit_insn (gen_movsi (p0reg, scratch_init));
   3758  1.1  mrg       loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
   3759  1.1  mrg 					    lb_reg, end_label,
   3760  1.1  mrg 					    lc_reg, p0reg);
   3761  1.1  mrg       emit_insn (loop_init);
   3762  1.1  mrg       seq_end = emit_insn (gen_movsi (p0reg, pop));
   3763  1.1  mrg       if (scratch_init_insn != NULL_RTX)
   3764  1.1  mrg 	delete_insn (scratch_init_insn);
   3765  1.1  mrg     }
   3766  1.1  mrg 
   3767  1.1  mrg   if (dump_file)
   3768  1.1  mrg     {
   3769  1.1  mrg       fprintf (dump_file, ";; replacing loop %d initializer with\n",
   3770  1.1  mrg 	       loop->loop_no);
   3771  1.1  mrg       print_rtl_single (dump_file, loop_init);
   3772  1.1  mrg       fprintf (dump_file, ";; replacing loop %d terminator with\n",
   3773  1.1  mrg 	       loop->loop_no);
   3774  1.1  mrg       print_rtl_single (dump_file, loop->loop_end);
   3775  1.1  mrg     }
   3776  1.1  mrg 
   3777  1.1  mrg   /* If the loop isn't entered at the top, also create a jump to the entry
   3778  1.1  mrg      point.  */
   3779  1.1  mrg   if (!loop->incoming_src && loop->head != loop->incoming_dest)
   3780  1.1  mrg     {
   3781  1.1  mrg       rtx_insn *label = BB_HEAD (loop->incoming_dest);
   3782  1.1  mrg       /* If we're jumping to the final basic block in the loop, and there's
   3783  1.1  mrg 	 only one cheap instruction before the end (typically an increment of
   3784  1.1  mrg 	 an induction variable), we can just emit a copy here instead of a
   3785  1.1  mrg 	 jump.  */
   3786  1.1  mrg       if (loop->incoming_dest == loop->tail
   3787  1.1  mrg 	  && next_real_insn (label) == last_insn
   3788  1.1  mrg 	  && asm_noperands (last_insn) < 0
   3789  1.1  mrg 	  && GET_CODE (PATTERN (last_insn)) == SET)
   3790  1.1  mrg 	{
   3791  1.1  mrg 	  seq_end = emit_insn (copy_rtx (PATTERN (last_insn)));
   3792  1.1  mrg 	}
   3793  1.1  mrg       else
   3794  1.1  mrg 	{
   3795  1.1  mrg 	  rtx_insn *ret = emit_jump_insn (gen_jump (label));
   3796  1.1  mrg 	  JUMP_LABEL (ret) = label;
   3797  1.1  mrg 	  LABEL_NUSES (label)++;
   3798  1.1  mrg 	  seq_end = emit_barrier ();
   3799  1.1  mrg 	}
   3800  1.1  mrg     }
   3801  1.1  mrg 
   3802  1.1  mrg   seq = get_insns ();
   3803  1.1  mrg   end_sequence ();
   3804  1.1  mrg 
   3805  1.1  mrg   if (loop->incoming_src)
   3806  1.1  mrg     {
   3807  1.1  mrg       rtx_insn *prev = BB_END (loop->incoming_src);
   3808  1.1  mrg       if (vec_safe_length (loop->incoming) > 1
   3809  1.1  mrg 	  || !(loop->incoming->last ()->flags & EDGE_FALLTHRU))
   3810  1.1  mrg 	{
   3811  1.1  mrg 	  gcc_assert (JUMP_P (prev));
   3812  1.1  mrg 	  prev = PREV_INSN (prev);
   3813  1.1  mrg 	  emit_insn_after (seq, prev);
   3814  1.1  mrg 	}
   3815  1.1  mrg       else
   3816  1.1  mrg 	{
   3817  1.1  mrg 	  emit_insn_after (seq, prev);
   3818  1.1  mrg 	  BB_END (loop->incoming_src) = prev;
   3819  1.1  mrg 	  basic_block new_bb = create_basic_block (seq, seq_end,
   3820  1.1  mrg 						   loop->head->prev_bb);
   3821  1.1  mrg 	  edge e = loop->incoming->last ();
   3822  1.1  mrg 	  gcc_assert (e->flags & EDGE_FALLTHRU);
   3823  1.1  mrg 	  redirect_edge_succ (e, new_bb);
   3824  1.1  mrg 	  make_edge (new_bb, loop->head, 0);
   3825  1.1  mrg 	}
   3826  1.1  mrg     }
   3827  1.1  mrg   else
   3828  1.1  mrg     {
   3829  1.1  mrg       basic_block new_bb;
   3830  1.1  mrg       edge e;
   3831  1.1  mrg       edge_iterator ei;
   3832  1.1  mrg 
   3833  1.1  mrg       if (flag_checking && loop->head != loop->incoming_dest)
   3834  1.1  mrg 	{
   3835  1.1  mrg 	  /* We aren't entering the loop at the top.  Since we've established
   3836  1.1  mrg 	     that the loop is entered only at one point, this means there
   3837  1.1  mrg 	     can't be fallthru edges into the head.  Any such fallthru edges
   3838  1.1  mrg 	     would become invalid when we insert the new block, so verify
   3839  1.1  mrg 	     that this does not in fact happen.  */
   3840  1.1  mrg 	  FOR_EACH_EDGE (e, ei, loop->head->preds)
   3841  1.1  mrg 	    gcc_assert (!(e->flags & EDGE_FALLTHRU));
   3842  1.1  mrg 	}
   3843  1.1  mrg 
   3844  1.1  mrg       emit_insn_before (seq, BB_HEAD (loop->head));
   3845  1.1  mrg       seq = emit_label_before (gen_label_rtx (), seq);
   3846  1.1  mrg 
   3847  1.1  mrg       new_bb = create_basic_block (seq, seq_end, loop->head->prev_bb);
   3848  1.1  mrg       FOR_EACH_EDGE (e, ei, loop->incoming)
   3849  1.1  mrg 	{
   3850  1.1  mrg 	  if (!(e->flags & EDGE_FALLTHRU)
   3851  1.1  mrg 	      || e->dest != loop->head)
   3852  1.1  mrg 	    redirect_edge_and_branch_force (e, new_bb);
   3853  1.1  mrg 	  else
   3854  1.1  mrg 	    redirect_edge_succ (e, new_bb);
   3855  1.1  mrg 	}
   3856  1.1  mrg       e = make_edge (new_bb, loop->head, 0);
   3857  1.1  mrg     }
   3858  1.1  mrg 
   3859  1.1  mrg   delete_insn (loop->loop_end);
   3860  1.1  mrg   /* Insert the loop end label before the last instruction of the loop.  */
   3861  1.1  mrg   emit_label_before (as_a <rtx_code_label *> (loop->end_label),
   3862  1.1  mrg 		     loop->last_insn);
   3863  1.1  mrg 
   3864  1.1  mrg   return true;
   3865  1.1  mrg }
   3866  1.1  mrg 
   3867  1.1  mrg /* A callback for the hw-doloop pass.  Called when a loop we have discovered
   3868  1.1  mrg    turns out not to be optimizable; we have to split the doloop_end pattern
   3869  1.1  mrg    into a subtract and a test.  */
   3870  1.1  mrg static void
   3871  1.1  mrg hwloop_fail (hwloop_info loop)
   3872  1.1  mrg {
   3873  1.1  mrg   rtx insn = loop->loop_end;
   3874  1.1  mrg 
   3875  1.1  mrg   if (DPREG_P (loop->iter_reg))
   3876  1.1  mrg     {
   3877  1.1  mrg       /* If loop->iter_reg is a DREG or PREG, we can split it here
   3878  1.1  mrg 	 without scratch register.  */
   3879  1.1  mrg       rtx insn, test;
   3880  1.1  mrg 
   3881  1.1  mrg       emit_insn_before (gen_addsi3 (loop->iter_reg,
   3882  1.1  mrg 				    loop->iter_reg,
   3883  1.1  mrg 				    constm1_rtx),
   3884  1.1  mrg 			loop->loop_end);
   3885  1.1  mrg 
   3886  1.1  mrg       test = gen_rtx_NE (VOIDmode, loop->iter_reg, const0_rtx);
   3887  1.1  mrg       insn = emit_jump_insn_before (gen_cbranchsi4 (test,
   3888  1.1  mrg 						    loop->iter_reg, const0_rtx,
   3889  1.1  mrg 						    loop->start_label),
   3890  1.1  mrg 				    loop->loop_end);
   3891  1.1  mrg 
   3892  1.1  mrg       JUMP_LABEL (insn) = loop->start_label;
   3893  1.1  mrg       LABEL_NUSES (loop->start_label)++;
   3894  1.1  mrg       delete_insn (loop->loop_end);
   3895  1.1  mrg     }
   3896  1.1  mrg   else
   3897  1.1  mrg     {
   3898  1.1  mrg       splitting_loops = 1;
   3899  1.1  mrg       try_split (PATTERN (insn), safe_as_a <rtx_insn *> (insn), 1);
   3900  1.1  mrg       splitting_loops = 0;
   3901  1.1  mrg     }
   3902  1.1  mrg }
   3903  1.1  mrg 
   3904  1.1  mrg /* A callback for the hw-doloop pass.  This function examines INSN; if
   3905  1.1  mrg    it is a loop_end pattern we recognize, return the reg rtx for the
   3906  1.1  mrg    loop counter.  Otherwise, return NULL_RTX.  */
   3907  1.1  mrg 
   3908  1.1  mrg static rtx
   3909  1.1  mrg hwloop_pattern_reg (rtx_insn *insn)
   3910  1.1  mrg {
   3911  1.1  mrg   rtx reg;
   3912  1.1  mrg 
   3913  1.1  mrg   if (!JUMP_P (insn) || recog_memoized (insn) != CODE_FOR_loop_end)
   3914  1.1  mrg     return NULL_RTX;
   3915  1.1  mrg 
   3916  1.1  mrg   reg = SET_DEST (XVECEXP (PATTERN (insn), 0, 1));
   3917  1.1  mrg   if (!REG_P (reg))
   3918  1.1  mrg     return NULL_RTX;
   3919  1.1  mrg   return reg;
   3920  1.1  mrg }
   3921  1.1  mrg 
   3922  1.1  mrg static struct hw_doloop_hooks bfin_doloop_hooks =
   3923  1.1  mrg {
   3924  1.1  mrg   hwloop_pattern_reg,
   3925  1.1  mrg   hwloop_optimize,
   3926  1.1  mrg   hwloop_fail
   3927  1.1  mrg };
   3928  1.1  mrg 
   3929  1.1  mrg /* Run from machine_dependent_reorg, this pass looks for doloop_end insns
   3930  1.1  mrg    and tries to rewrite the RTL of these loops so that proper Blackfin
   3931  1.1  mrg    hardware loops are generated.  */
   3932  1.1  mrg 
   3933  1.1  mrg static void
   3934  1.1  mrg bfin_reorg_loops (void)
   3935  1.1  mrg {
   3936  1.1  mrg   reorg_loops (true, &bfin_doloop_hooks);
   3937  1.1  mrg }
   3938  1.1  mrg 
   3939  1.1  mrg /* Possibly generate a SEQUENCE out of three insns found in SLOT.
   3941  1.1  mrg    Returns true if we modified the insn chain, false otherwise.  */
   3942  1.1  mrg static bool
   3943  1.1  mrg gen_one_bundle (rtx_insn *slot[3])
   3944  1.1  mrg {
   3945  1.1  mrg   gcc_assert (slot[1] != NULL_RTX);
   3946  1.1  mrg 
   3947  1.1  mrg   /* Don't add extra NOPs if optimizing for size.  */
   3948  1.1  mrg   if (optimize_size
   3949  1.1  mrg       && (slot[0] == NULL_RTX || slot[2] == NULL_RTX))
   3950  1.1  mrg     return false;
   3951  1.1  mrg 
   3952  1.1  mrg   /* Verify that we really can do the multi-issue.  */
   3953  1.1  mrg   if (slot[0])
   3954  1.1  mrg     {
   3955  1.1  mrg       rtx_insn *t = NEXT_INSN (slot[0]);
   3956  1.1  mrg       while (t != slot[1])
   3957  1.1  mrg 	{
   3958  1.1  mrg 	  if (! NOTE_P (t) || NOTE_KIND (t) != NOTE_INSN_DELETED)
   3959  1.1  mrg 	    return false;
   3960  1.1  mrg 	  t = NEXT_INSN (t);
   3961  1.1  mrg 	}
   3962  1.1  mrg     }
   3963  1.1  mrg   if (slot[2])
   3964  1.1  mrg     {
   3965  1.1  mrg       rtx_insn *t = NEXT_INSN (slot[1]);
   3966  1.1  mrg       while (t != slot[2])
   3967  1.1  mrg 	{
   3968  1.1  mrg 	  if (! NOTE_P (t) || NOTE_KIND (t) != NOTE_INSN_DELETED)
   3969  1.1  mrg 	    return false;
   3970  1.1  mrg 	  t = NEXT_INSN (t);
   3971  1.1  mrg 	}
   3972  1.1  mrg     }
   3973  1.1  mrg 
   3974  1.1  mrg   if (slot[0] == NULL_RTX)
   3975  1.1  mrg     {
   3976  1.1  mrg       slot[0] = emit_insn_before (gen_mnop (), slot[1]);
   3977  1.1  mrg       df_insn_rescan (slot[0]);
   3978  1.1  mrg     }
   3979  1.1  mrg   if (slot[2] == NULL_RTX)
   3980  1.1  mrg     {
   3981  1.1  mrg       slot[2] = emit_insn_after (gen_forced_nop (), slot[1]);
   3982  1.1  mrg       df_insn_rescan (slot[2]);
   3983  1.1  mrg     }
   3984  1.1  mrg 
   3985  1.1  mrg   /* Avoid line number information being printed inside one bundle.  */
   3986  1.1  mrg   if (INSN_LOCATION (slot[1])
   3987  1.1  mrg       && INSN_LOCATION (slot[1]) != INSN_LOCATION (slot[0]))
   3988  1.1  mrg     INSN_LOCATION (slot[1]) = INSN_LOCATION (slot[0]);
   3989  1.1  mrg   if (INSN_LOCATION (slot[2])
   3990  1.1  mrg       && INSN_LOCATION (slot[2]) != INSN_LOCATION (slot[0]))
   3991  1.1  mrg     INSN_LOCATION (slot[2]) = INSN_LOCATION (slot[0]);
   3992  1.1  mrg 
   3993  1.1  mrg   /* Terminate them with "|| " instead of ";" in the output.  */
   3994  1.1  mrg   PUT_MODE (slot[0], SImode);
   3995  1.1  mrg   PUT_MODE (slot[1], SImode);
   3996  1.1  mrg   /* Terminate the bundle, for the benefit of reorder_var_tracking_notes.  */
   3997  1.1  mrg   PUT_MODE (slot[2], QImode);
   3998  1.1  mrg   return true;
   3999  1.1  mrg }
   4000  1.1  mrg 
   4001  1.1  mrg /* Go through all insns, and use the information generated during scheduling
   4002  1.1  mrg    to generate SEQUENCEs to represent bundles of instructions issued
   4003  1.1  mrg    simultaneously.  */
   4004  1.1  mrg 
   4005  1.1  mrg static void
   4006  1.1  mrg bfin_gen_bundles (void)
   4007  1.1  mrg {
   4008  1.1  mrg   basic_block bb;
   4009  1.1  mrg   FOR_EACH_BB_FN (bb, cfun)
   4010  1.1  mrg     {
   4011  1.1  mrg       rtx_insn *insn, *next;
   4012  1.1  mrg       rtx_insn *slot[3];
   4013  1.1  mrg       int n_filled = 0;
   4014  1.1  mrg 
   4015  1.1  mrg       slot[0] = slot[1] = slot[2] = NULL;
   4016  1.1  mrg       for (insn = BB_HEAD (bb);; insn = next)
   4017  1.1  mrg 	{
   4018  1.1  mrg 	  int at_end;
   4019  1.1  mrg 	  rtx_insn *delete_this = NULL;
   4020  1.1  mrg 
   4021  1.1  mrg 	  if (NONDEBUG_INSN_P (insn))
   4022  1.1  mrg 	    {
   4023  1.1  mrg 	      enum attr_type type = get_attr_type (insn);
   4024  1.1  mrg 
   4025  1.1  mrg 	      if (type == TYPE_STALL)
   4026  1.1  mrg 		{
   4027  1.1  mrg 		  gcc_assert (n_filled == 0);
   4028  1.1  mrg 		  delete_this = insn;
   4029  1.1  mrg 		}
   4030  1.1  mrg 	      else
   4031  1.1  mrg 		{
   4032  1.1  mrg 		  if (type == TYPE_DSP32 || type == TYPE_DSP32SHIFTIMM)
   4033  1.1  mrg 		    slot[0] = insn;
   4034  1.1  mrg 		  else if (slot[1] == NULL_RTX)
   4035  1.1  mrg 		    slot[1] = insn;
   4036  1.1  mrg 		  else
   4037  1.1  mrg 		    slot[2] = insn;
   4038  1.1  mrg 		  n_filled++;
   4039  1.1  mrg 		}
   4040  1.1  mrg 	    }
   4041  1.1  mrg 
   4042  1.1  mrg 	  next = NEXT_INSN (insn);
   4043  1.1  mrg 	  while (next && insn != BB_END (bb)
   4044  1.1  mrg 		 && !(INSN_P (next)
   4045  1.1  mrg 		      && GET_CODE (PATTERN (next)) != USE
   4046  1.1  mrg 		      && GET_CODE (PATTERN (next)) != CLOBBER))
   4047  1.1  mrg 	    {
   4048  1.1  mrg 	      insn = next;
   4049  1.1  mrg 	      next = NEXT_INSN (insn);
   4050  1.1  mrg 	    }
   4051  1.1  mrg 
   4052  1.1  mrg 	  /* BB_END can change due to emitting extra NOPs, so check here.  */
   4053  1.1  mrg 	  at_end = insn == BB_END (bb);
   4054  1.1  mrg 	  if (delete_this == NULL_RTX && (at_end || GET_MODE (next) == TImode))
   4055  1.1  mrg 	    {
   4056  1.1  mrg 	      if ((n_filled < 2
   4057  1.1  mrg 		   || !gen_one_bundle (slot))
   4058  1.1  mrg 		  && slot[0] != NULL_RTX)
   4059  1.1  mrg 		{
   4060  1.1  mrg 		  rtx pat = PATTERN (slot[0]);
   4061  1.1  mrg 		  if (GET_CODE (pat) == SET
   4062  1.1  mrg 		      && GET_CODE (SET_SRC (pat)) == UNSPEC
   4063  1.1  mrg 		      && XINT (SET_SRC (pat), 1) == UNSPEC_32BIT)
   4064  1.1  mrg 		    {
   4065  1.1  mrg 		      SET_SRC (pat) = XVECEXP (SET_SRC (pat), 0, 0);
   4066  1.1  mrg 		      INSN_CODE (slot[0]) = -1;
   4067  1.1  mrg 		      df_insn_rescan (slot[0]);
   4068  1.1  mrg 		    }
   4069  1.1  mrg 		}
   4070  1.1  mrg 	      n_filled = 0;
   4071  1.1  mrg 	      slot[0] = slot[1] = slot[2] = NULL;
   4072  1.1  mrg 	    }
   4073  1.1  mrg 	  if (delete_this != NULL_RTX)
   4074  1.1  mrg 	    delete_insn (delete_this);
   4075  1.1  mrg 	  if (at_end)
   4076  1.1  mrg 	    break;
   4077  1.1  mrg 	}
   4078  1.1  mrg     }
   4079  1.1  mrg }
   4080  1.1  mrg 
   4081  1.1  mrg /* Ensure that no var tracking notes are emitted in the middle of a
   4082  1.1  mrg    three-instruction bundle.  */
   4083  1.1  mrg 
   4084  1.1  mrg static void
   4085  1.1  mrg reorder_var_tracking_notes (void)
   4086  1.1  mrg {
   4087  1.1  mrg   basic_block bb;
   4088  1.1  mrg   FOR_EACH_BB_FN (bb, cfun)
   4089  1.1  mrg     {
   4090  1.1  mrg       rtx_insn *insn, *next;
   4091  1.1  mrg       rtx_insn *queue = NULL;
   4092  1.1  mrg       bool in_bundle = false;
   4093  1.1  mrg 
   4094  1.1  mrg       for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = next)
   4095  1.1  mrg 	{
   4096  1.1  mrg 	  next = NEXT_INSN (insn);
   4097  1.1  mrg 
   4098  1.1  mrg 	  if (INSN_P (insn))
   4099  1.1  mrg 	    {
   4100  1.1  mrg 	      /* Emit queued up notes at the last instruction of a bundle.  */
   4101  1.1  mrg 	      if (GET_MODE (insn) == QImode)
   4102  1.1  mrg 		{
   4103  1.1  mrg 		  while (queue)
   4104  1.1  mrg 		    {
   4105  1.1  mrg 		      rtx_insn *next_queue = PREV_INSN (queue);
   4106  1.1  mrg 		      SET_PREV_INSN (NEXT_INSN (insn)) = queue;
   4107  1.1  mrg 		      SET_NEXT_INSN (queue) = NEXT_INSN (insn);
   4108  1.1  mrg 		      SET_NEXT_INSN (insn) = queue;
   4109  1.1  mrg 		      SET_PREV_INSN (queue) = insn;
   4110  1.1  mrg 		      queue = next_queue;
   4111  1.1  mrg 		    }
   4112  1.1  mrg 		  in_bundle = false;
   4113  1.1  mrg 		}
   4114  1.1  mrg 	      else if (GET_MODE (insn) == SImode)
   4115  1.1  mrg 		in_bundle = true;
   4116  1.1  mrg 	    }
   4117  1.1  mrg 	  else if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION)
   4118  1.1  mrg 	    {
   4119  1.1  mrg 	      if (in_bundle)
   4120  1.1  mrg 		{
   4121  1.1  mrg 		  rtx_insn *prev = PREV_INSN (insn);
   4122  1.1  mrg 		  SET_PREV_INSN (next) = prev;
   4123  1.1  mrg 		  SET_NEXT_INSN (prev) = next;
   4124  1.1  mrg 
   4125  1.1  mrg 		  SET_PREV_INSN (insn) = queue;
   4126  1.1  mrg 		  queue = insn;
   4127  1.1  mrg 		}
   4128  1.1  mrg 	    }
   4129  1.1  mrg 	}
   4130  1.1  mrg     }
   4131  1.1  mrg }
   4132  1.1  mrg 
   4133  1.1  mrg /* On some silicon revisions, functions shorter than a certain number of cycles
   4135  1.1  mrg    can cause unpredictable behavior.  Work around this by adding NOPs as
   4136  1.1  mrg    needed.  */
   4137  1.1  mrg static void
   4138  1.1  mrg workaround_rts_anomaly (void)
   4139  1.1  mrg {
   4140  1.1  mrg   rtx_insn *insn, *first_insn = NULL;
   4141  1.1  mrg   int cycles = 4;
   4142  1.1  mrg 
   4143  1.1  mrg   if (! ENABLE_WA_RETS)
   4144  1.1  mrg     return;
   4145  1.1  mrg 
   4146  1.1  mrg   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
   4147  1.1  mrg     {
   4148  1.1  mrg       rtx pat;
   4149  1.1  mrg 
   4150  1.1  mrg       if (BARRIER_P (insn))
   4151  1.1  mrg 	return;
   4152  1.1  mrg 
   4153  1.1  mrg       if (NOTE_P (insn) || LABEL_P (insn))
   4154  1.1  mrg 	continue;
   4155  1.1  mrg 
   4156  1.1  mrg       if (JUMP_TABLE_DATA_P (insn))
   4157  1.1  mrg 	continue;
   4158  1.1  mrg 
   4159  1.1  mrg       if (first_insn == NULL_RTX)
   4160  1.1  mrg 	first_insn = insn;
   4161  1.1  mrg       pat = PATTERN (insn);
   4162  1.1  mrg       if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
   4163  1.1  mrg 	  || GET_CODE (pat) == ASM_INPUT
   4164  1.1  mrg 	  || asm_noperands (pat) >= 0)
   4165  1.1  mrg 	continue;
   4166  1.1  mrg 
   4167  1.1  mrg       if (CALL_P (insn))
   4168  1.1  mrg 	return;
   4169  1.1  mrg 
   4170  1.1  mrg       if (JUMP_P (insn))
   4171  1.1  mrg 	{
   4172  1.1  mrg 	  if (recog_memoized (insn) == CODE_FOR_return_internal)
   4173  1.1  mrg 	    break;
   4174  1.1  mrg 
   4175  1.1  mrg 	  /* Nothing to worry about for direct jumps.  */
   4176  1.1  mrg 	  if (!any_condjump_p (insn))
   4177  1.1  mrg 	    return;
   4178  1.1  mrg 	  if (cycles <= 1)
   4179  1.1  mrg 	    return;
   4180  1.1  mrg 	  cycles--;
   4181  1.1  mrg 	}
   4182  1.1  mrg       else if (INSN_P (insn))
   4183  1.1  mrg 	{
   4184  1.1  mrg 	  rtx pat = PATTERN (insn);
   4185  1.1  mrg 	  int this_cycles = 1;
   4186  1.1  mrg 
   4187  1.1  mrg 	  if (GET_CODE (pat) == PARALLEL)
   4188  1.1  mrg 	    {
   4189  1.1  mrg 	      if (analyze_push_multiple_operation (pat)
   4190  1.1  mrg 		  || analyze_pop_multiple_operation (pat))
   4191  1.1  mrg 		this_cycles = n_regs_to_save;
   4192  1.1  mrg 	    }
   4193  1.1  mrg 	  else
   4194  1.1  mrg 	    {
   4195  1.1  mrg 	      int icode = recog_memoized (insn);
   4196  1.1  mrg 
   4197  1.1  mrg 	      if (icode == CODE_FOR_link)
   4198  1.1  mrg 		this_cycles = 4;
   4199  1.1  mrg 	      else if (icode == CODE_FOR_unlink)
   4200  1.1  mrg 		this_cycles = 3;
   4201  1.1  mrg 	      else if (icode == CODE_FOR_mulsi3)
   4202  1.1  mrg 		this_cycles = 5;
   4203  1.1  mrg 	    }
   4204  1.1  mrg 	  if (this_cycles >= cycles)
   4205  1.1  mrg 	    return;
   4206  1.1  mrg 
   4207  1.1  mrg 	  cycles -= this_cycles;
   4208  1.1  mrg 	}
   4209  1.1  mrg     }
   4210  1.1  mrg   while (cycles > 0)
   4211  1.1  mrg     {
   4212  1.1  mrg       emit_insn_before (gen_nop (), first_insn);
   4213  1.1  mrg       cycles--;
   4214  1.1  mrg     }
   4215  1.1  mrg }
   4216  1.1  mrg 
   4217  1.1  mrg /* Return an insn type for INSN that can be used by the caller for anomaly
   4218  1.1  mrg    workarounds.  This differs from plain get_attr_type in that it handles
   4219  1.1  mrg    SEQUENCEs.  */
   4220  1.1  mrg 
   4221  1.1  mrg static enum attr_type
   4222  1.1  mrg type_for_anomaly (rtx_insn *insn)
   4223  1.1  mrg {
   4224  1.1  mrg   rtx pat = PATTERN (insn);
   4225  1.1  mrg   if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (pat))
   4226  1.1  mrg     {
   4227  1.1  mrg       enum attr_type t;
   4228  1.1  mrg       t = get_attr_type (seq->insn (1));
   4229  1.1  mrg       if (t == TYPE_MCLD)
   4230  1.1  mrg 	return t;
   4231  1.1  mrg       t = get_attr_type (seq->insn (2));
   4232  1.1  mrg       if (t == TYPE_MCLD)
   4233  1.1  mrg 	return t;
   4234  1.1  mrg       return TYPE_MCST;
   4235  1.1  mrg     }
   4236  1.1  mrg   else
   4237  1.1  mrg     return get_attr_type (insn);
   4238  1.1  mrg }
   4239  1.1  mrg 
   4240  1.1  mrg /* Return true iff the address found in MEM is based on the register
   4241  1.1  mrg    NP_REG and optionally has a positive offset.  */
   4242  1.1  mrg static bool
   4243  1.1  mrg harmless_null_pointer_p (rtx mem, int np_reg)
   4244  1.1  mrg {
   4245  1.1  mrg   mem = XEXP (mem, 0);
   4246  1.1  mrg   if (GET_CODE (mem) == POST_INC || GET_CODE (mem) == POST_DEC)
   4247  1.1  mrg     mem = XEXP (mem, 0);
   4248  1.1  mrg   if (REG_P (mem) && (int) REGNO (mem) == np_reg)
   4249  1.1  mrg     return true;
   4250  1.1  mrg   if (GET_CODE (mem) == PLUS
   4251  1.1  mrg       && REG_P (XEXP (mem, 0)) && (int) REGNO (XEXP (mem, 0)) == np_reg)
   4252  1.1  mrg     {
   4253  1.1  mrg       mem = XEXP (mem, 1);
   4254  1.1  mrg       if (GET_CODE (mem) == CONST_INT && INTVAL (mem) > 0)
   4255  1.1  mrg 	return true;
   4256  1.1  mrg     }
   4257  1.1  mrg   return false;
   4258  1.1  mrg }
   4259  1.1  mrg 
   4260  1.1  mrg /* Return nonzero if INSN contains any loads that may trap.  */
   4261  1.1  mrg 
   4262  1.1  mrg static bool
   4263  1.1  mrg trapping_loads_p (rtx_insn *insn, int np_reg, bool after_np_branch)
   4264  1.1  mrg {
   4265  1.1  mrg   rtx mem = SET_SRC (single_set (insn));
   4266  1.1  mrg 
   4267  1.1  mrg   if (!after_np_branch)
   4268  1.1  mrg     np_reg = -1;
   4269  1.1  mrg   return ((np_reg == -1 || !harmless_null_pointer_p (mem, np_reg))
   4270  1.1  mrg 	  && may_trap_p (mem));
   4271  1.1  mrg }
   4272  1.1  mrg 
   4273  1.1  mrg /* Return INSN if it is of TYPE_MCLD.  Alternatively, if INSN is the start of
   4274  1.1  mrg    a three-insn bundle, see if one of them is a load and return that if so.
   4275  1.1  mrg    Return NULL if the insn does not contain loads.  */
   4276  1.1  mrg static rtx_insn *
   4277  1.1  mrg find_load (rtx_insn *insn)
   4278  1.1  mrg {
   4279  1.1  mrg   if (!NONDEBUG_INSN_P (insn))
   4280  1.1  mrg     return NULL;
   4281  1.1  mrg   if (get_attr_type (insn) == TYPE_MCLD)
   4282  1.1  mrg     return insn;
   4283  1.1  mrg   if (GET_MODE (insn) != SImode)
   4284  1.1  mrg     return NULL;
   4285  1.1  mrg   do {
   4286  1.1  mrg     insn = NEXT_INSN (insn);
   4287  1.1  mrg     if ((GET_MODE (insn) == SImode || GET_MODE (insn) == QImode)
   4288  1.1  mrg 	&& get_attr_type (insn) == TYPE_MCLD)
   4289  1.1  mrg       return insn;
   4290  1.1  mrg   } while (GET_MODE (insn) != QImode);
   4291  1.1  mrg   return NULL;
   4292  1.1  mrg }
   4293  1.1  mrg 
   4294  1.1  mrg /* Determine whether PAT is an indirect call pattern.  */
   4295  1.1  mrg static bool
   4296  1.1  mrg indirect_call_p (rtx pat)
   4297  1.1  mrg {
   4298  1.1  mrg   if (GET_CODE (pat) == PARALLEL)
   4299  1.1  mrg     pat = XVECEXP (pat, 0, 0);
   4300  1.1  mrg   if (GET_CODE (pat) == SET)
   4301  1.1  mrg     pat = SET_SRC (pat);
   4302  1.1  mrg   gcc_assert (GET_CODE (pat) == CALL);
   4303  1.1  mrg   pat = XEXP (pat, 0);
   4304  1.1  mrg   gcc_assert (GET_CODE (pat) == MEM);
   4305  1.1  mrg   pat = XEXP (pat, 0);
   4306  1.1  mrg 
   4307  1.1  mrg   return REG_P (pat);
   4308  1.1  mrg }
   4309  1.1  mrg 
   4310  1.1  mrg /* During workaround_speculation, track whether we're in the shadow of a
   4311  1.1  mrg    conditional branch that tests a P register for NULL.  If so, we can omit
   4312  1.1  mrg    emitting NOPs if we see a load from that P register, since a speculative
   4313  1.1  mrg    access at address 0 isn't a problem, and the load is executed in all other
   4314  1.1  mrg    cases anyway.
   4315  1.1  mrg    Global for communication with note_np_check_stores through note_stores.
   4316  1.1  mrg    */
   4317  1.1  mrg int np_check_regno = -1;
   4318  1.1  mrg bool np_after_branch = false;
   4319  1.1  mrg 
   4320  1.1  mrg /* Subroutine of workaround_speculation, called through note_stores.  */
   4321  1.1  mrg static void
   4322  1.1  mrg note_np_check_stores (rtx x, const_rtx pat ATTRIBUTE_UNUSED,
   4323  1.1  mrg 		      void *data ATTRIBUTE_UNUSED)
   4324  1.1  mrg {
   4325  1.1  mrg   if (REG_P (x) && (REGNO (x) == REG_CC || (int) REGNO (x) == np_check_regno))
   4326  1.1  mrg     np_check_regno = -1;
   4327  1.1  mrg }
   4328  1.1  mrg 
   4329  1.1  mrg static void
   4330  1.1  mrg workaround_speculation (void)
   4331  1.1  mrg {
   4332  1.1  mrg   rtx_insn *insn, *next;
   4333  1.1  mrg   rtx_insn *last_condjump = NULL;
   4334  1.1  mrg   int cycles_since_jump = INT_MAX;
   4335  1.1  mrg   int delay_added = 0;
   4336  1.1  mrg 
   4337  1.1  mrg   if (! ENABLE_WA_SPECULATIVE_LOADS && ! ENABLE_WA_SPECULATIVE_SYNCS
   4338  1.1  mrg       && ! ENABLE_WA_INDIRECT_CALLS)
   4339  1.1  mrg     return;
   4340  1.1  mrg 
   4341  1.1  mrg   /* First pass: find predicted-false branches; if something after them
   4342  1.1  mrg      needs nops, insert them or change the branch to predict true.  */
   4343  1.1  mrg   for (insn = get_insns (); insn; insn = next)
   4344  1.1  mrg     {
   4345  1.1  mrg       rtx pat;
   4346  1.1  mrg       int delay_needed = 0;
   4347  1.1  mrg 
   4348  1.1  mrg       next = find_next_insn_start (insn);
   4349  1.1  mrg 
   4350  1.1  mrg       if (NOTE_P (insn) || BARRIER_P (insn))
   4351  1.1  mrg 	continue;
   4352  1.1  mrg       if (JUMP_TABLE_DATA_P (insn))
   4353  1.1  mrg 	continue;
   4354  1.1  mrg 
   4355  1.1  mrg       if (LABEL_P (insn))
   4356  1.1  mrg 	{
   4357  1.1  mrg 	  np_check_regno = -1;
   4358  1.1  mrg 	  continue;
   4359  1.1  mrg 	}
   4360  1.1  mrg 
   4361  1.1  mrg       pat = PATTERN (insn);
   4362  1.1  mrg       if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
   4363  1.1  mrg 	continue;
   4364  1.1  mrg 
   4365  1.1  mrg       if (GET_CODE (pat) == ASM_INPUT || asm_noperands (pat) >= 0)
   4366  1.1  mrg 	{
   4367  1.1  mrg 	  np_check_regno = -1;
   4368  1.1  mrg 	  continue;
   4369  1.1  mrg 	}
   4370  1.1  mrg 
   4371  1.1  mrg       if (JUMP_P (insn))
   4372  1.1  mrg 	{
   4373  1.1  mrg 	  /* Is this a condjump based on a null pointer comparison we saw
   4374  1.1  mrg 	     earlier?  */
   4375  1.1  mrg 	  if (np_check_regno != -1
   4376  1.1  mrg 	      && recog_memoized (insn) == CODE_FOR_cbranchbi4)
   4377  1.1  mrg 	    {
   4378  1.1  mrg 	      rtx op = XEXP (SET_SRC (PATTERN (insn)), 0);
   4379  1.1  mrg 	      gcc_assert (GET_CODE (op) == EQ || GET_CODE (op) == NE);
   4380  1.1  mrg 	      if (GET_CODE (op) == NE)
   4381  1.1  mrg 		np_after_branch = true;
   4382  1.1  mrg 	    }
   4383  1.1  mrg 	  if (any_condjump_p (insn)
   4384  1.1  mrg 	      && ! cbranch_predicted_taken_p (insn))
   4385  1.1  mrg 	    {
   4386  1.1  mrg 	      last_condjump = insn;
   4387  1.1  mrg 	      delay_added = 0;
   4388  1.1  mrg 	      cycles_since_jump = 0;
   4389  1.1  mrg 	    }
   4390  1.1  mrg 	  else
   4391  1.1  mrg 	    cycles_since_jump = INT_MAX;
   4392  1.1  mrg 	}
   4393  1.1  mrg       else if (CALL_P (insn))
   4394  1.1  mrg 	{
   4395  1.1  mrg 	  np_check_regno = -1;
   4396  1.1  mrg 	  if (cycles_since_jump < INT_MAX)
   4397  1.1  mrg 	    cycles_since_jump++;
   4398  1.1  mrg 	  if (indirect_call_p (pat) && ENABLE_WA_INDIRECT_CALLS)
   4399  1.1  mrg 	    {
   4400  1.1  mrg 	      delay_needed = 3;
   4401  1.1  mrg 	    }
   4402  1.1  mrg 	}
   4403  1.1  mrg       else if (NONDEBUG_INSN_P (insn))
   4404  1.1  mrg 	{
   4405  1.1  mrg 	  rtx_insn *load_insn = find_load (insn);
   4406  1.1  mrg 	  enum attr_type type = type_for_anomaly (insn);
   4407  1.1  mrg 
   4408  1.1  mrg 	  if (cycles_since_jump < INT_MAX)
   4409  1.1  mrg 	    cycles_since_jump++;
   4410  1.1  mrg 
   4411  1.1  mrg 	  /* Detect a comparison of a P register with zero.  If we later
   4412  1.1  mrg 	     see a condjump based on it, we have found a null pointer
   4413  1.1  mrg 	     check.  */
   4414  1.1  mrg 	  if (recog_memoized (insn) == CODE_FOR_compare_eq)
   4415  1.1  mrg 	    {
   4416  1.1  mrg 	      rtx src = SET_SRC (PATTERN (insn));
   4417  1.1  mrg 	      if (REG_P (XEXP (src, 0))
   4418  1.1  mrg 		  && P_REGNO_P (REGNO (XEXP (src, 0)))
   4419  1.1  mrg 		  && XEXP (src, 1) == const0_rtx)
   4420  1.1  mrg 		{
   4421  1.1  mrg 		  np_check_regno = REGNO (XEXP (src, 0));
   4422  1.1  mrg 		  np_after_branch = false;
   4423  1.1  mrg 		}
   4424  1.1  mrg 	      else
   4425  1.1  mrg 		np_check_regno = -1;
   4426  1.1  mrg 	    }
   4427  1.1  mrg 
   4428  1.1  mrg 	  if (load_insn && ENABLE_WA_SPECULATIVE_LOADS)
   4429  1.1  mrg 	    {
   4430  1.1  mrg 	      if (trapping_loads_p (load_insn, np_check_regno,
   4431  1.1  mrg 				    np_after_branch))
   4432  1.1  mrg 		delay_needed = 4;
   4433  1.1  mrg 	    }
   4434  1.1  mrg 	  else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS)
   4435  1.1  mrg 	    delay_needed = 3;
   4436  1.1  mrg 
   4437  1.1  mrg 	  /* See if we need to forget about a null pointer comparison
   4438  1.1  mrg 	     we found earlier.  */
   4439  1.1  mrg 	  if (recog_memoized (insn) != CODE_FOR_compare_eq)
   4440  1.1  mrg 	    {
   4441  1.1  mrg 	      note_stores (insn, note_np_check_stores, NULL);
   4442  1.1  mrg 	      if (np_check_regno != -1)
   4443  1.1  mrg 		{
   4444  1.1  mrg 		  if (find_regno_note (insn, REG_INC, np_check_regno))
   4445  1.1  mrg 		    np_check_regno = -1;
   4446  1.1  mrg 		}
   4447  1.1  mrg 	    }
   4448  1.1  mrg 
   4449  1.1  mrg 	}
   4450  1.1  mrg 
   4451  1.1  mrg       if (delay_needed > cycles_since_jump
   4452  1.1  mrg 	  && (delay_needed - cycles_since_jump) > delay_added)
   4453  1.1  mrg 	{
   4454  1.1  mrg 	  rtx pat1;
   4455  1.1  mrg 	  int num_clobbers;
   4456  1.1  mrg 	  rtx *op = recog_data.operand;
   4457  1.1  mrg 
   4458  1.1  mrg 	  delay_needed -= cycles_since_jump;
   4459  1.1  mrg 
   4460  1.1  mrg 	  extract_insn (last_condjump);
   4461  1.1  mrg 	  if (optimize_size)
   4462  1.1  mrg 	    {
   4463  1.1  mrg 	      pat1 = gen_cbranch_predicted_taken (op[0], op[1], op[2],
   4464  1.1  mrg 						 op[3]);
   4465  1.1  mrg 	      cycles_since_jump = INT_MAX;
   4466  1.1  mrg 	    }
   4467  1.1  mrg 	  else
   4468  1.1  mrg 	    {
   4469  1.1  mrg 	      /* Do not adjust cycles_since_jump in this case, so that
   4470  1.1  mrg 		 we'll increase the number of NOPs for a subsequent insn
   4471  1.1  mrg 		 if necessary.  */
   4472  1.1  mrg 	      pat1 = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
   4473  1.1  mrg 					    GEN_INT (delay_needed));
   4474  1.1  mrg 	      delay_added = delay_needed;
   4475  1.1  mrg 	    }
   4476  1.1  mrg 	  PATTERN (last_condjump) = pat1;
   4477  1.1  mrg 	  INSN_CODE (last_condjump) = recog (pat1, insn, &num_clobbers);
   4478  1.1  mrg 	}
   4479  1.1  mrg       if (CALL_P (insn))
   4480  1.1  mrg 	{
   4481  1.1  mrg 	  cycles_since_jump = INT_MAX;
   4482  1.1  mrg 	  delay_added = 0;
   4483  1.1  mrg 	}
   4484  1.1  mrg     }
   4485  1.1  mrg 
   4486  1.1  mrg   /* Second pass: for predicted-true branches, see if anything at the
   4487  1.1  mrg      branch destination needs extra nops.  */
   4488  1.1  mrg   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
   4489  1.1  mrg     {
   4490  1.1  mrg       int cycles_since_jump;
   4491  1.1  mrg       if (JUMP_P (insn)
   4492  1.1  mrg 	  && any_condjump_p (insn)
   4493  1.1  mrg 	  && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken
   4494  1.1  mrg 	      || cbranch_predicted_taken_p (insn)))
   4495  1.1  mrg 	{
   4496  1.1  mrg 	  rtx_insn *target = JUMP_LABEL_AS_INSN (insn);
   4497  1.1  mrg 	  rtx_insn *label = target;
   4498  1.1  mrg 	  rtx_insn *next_tgt;
   4499  1.1  mrg 
   4500  1.1  mrg 	  cycles_since_jump = 0;
   4501  1.1  mrg 	  for (; target && cycles_since_jump < 3; target = next_tgt)
   4502  1.1  mrg 	    {
   4503  1.1  mrg 	      rtx pat;
   4504  1.1  mrg 
   4505  1.1  mrg 	      next_tgt = find_next_insn_start (target);
   4506  1.1  mrg 
   4507  1.1  mrg 	      if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
   4508  1.1  mrg 		continue;
   4509  1.1  mrg 
   4510  1.1  mrg 	      if (JUMP_TABLE_DATA_P (target))
   4511  1.1  mrg 		continue;
   4512  1.1  mrg 
   4513  1.1  mrg 	      pat = PATTERN (target);
   4514  1.1  mrg 	      if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
   4515  1.1  mrg 		  || GET_CODE (pat) == ASM_INPUT
   4516  1.1  mrg 		  || asm_noperands (pat) >= 0)
   4517  1.1  mrg 		continue;
   4518  1.1  mrg 
   4519  1.1  mrg 	      if (NONDEBUG_INSN_P (target))
   4520  1.1  mrg 		{
   4521  1.1  mrg 		  rtx_insn *load_insn = find_load (target);
   4522  1.1  mrg 		  enum attr_type type = type_for_anomaly (target);
   4523  1.1  mrg 		  int delay_needed = 0;
   4524  1.1  mrg 		  if (cycles_since_jump < INT_MAX)
   4525  1.1  mrg 		    cycles_since_jump++;
   4526  1.1  mrg 
   4527  1.1  mrg 		  if (load_insn && ENABLE_WA_SPECULATIVE_LOADS)
   4528  1.1  mrg 		    {
   4529  1.1  mrg 		      if (trapping_loads_p (load_insn, -1, false))
   4530  1.1  mrg 			delay_needed = 2;
   4531  1.1  mrg 		    }
   4532  1.1  mrg 		  else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS)
   4533  1.1  mrg 		    delay_needed = 2;
   4534  1.1  mrg 
   4535  1.1  mrg 		  if (delay_needed > cycles_since_jump)
   4536  1.1  mrg 		    {
   4537  1.1  mrg 		      rtx_insn *prev = prev_real_insn (label);
   4538  1.1  mrg 		      delay_needed -= cycles_since_jump;
   4539  1.1  mrg 		      if (dump_file)
   4540  1.1  mrg 			fprintf (dump_file, "Adding %d nops after %d\n",
   4541  1.1  mrg 				 delay_needed, INSN_UID (label));
   4542  1.1  mrg 		      if (JUMP_P (prev)
   4543  1.1  mrg 			  && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops)
   4544  1.1  mrg 			{
   4545  1.1  mrg 			  rtx x;
   4546  1.1  mrg 			  HOST_WIDE_INT v;
   4547  1.1  mrg 
   4548  1.1  mrg 			  if (dump_file)
   4549  1.1  mrg 			    fprintf (dump_file,
   4550  1.1  mrg 				     "Reducing nops on insn %d.\n",
   4551  1.1  mrg 				     INSN_UID (prev));
   4552  1.1  mrg 			  x = PATTERN (prev);
   4553  1.1  mrg 			  x = XVECEXP (x, 0, 1);
   4554  1.1  mrg 			  v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed;
   4555  1.1  mrg 			  XVECEXP (x, 0, 0) = GEN_INT (v);
   4556  1.1  mrg 			}
   4557  1.1  mrg 		      while (delay_needed-- > 0)
   4558  1.1  mrg 			emit_insn_after (gen_nop (), label);
   4559  1.1  mrg 		      break;
   4560  1.1  mrg 		    }
   4561  1.1  mrg 		}
   4562  1.1  mrg 	    }
   4563  1.1  mrg 	}
   4564  1.1  mrg     }
   4565  1.1  mrg }
   4566  1.1  mrg 
   4567  1.1  mrg /* Called just before the final scheduling pass.  If we need to insert NOPs
   4568  1.1  mrg    later on to work around speculative loads, insert special placeholder
   4569  1.1  mrg    insns that cause loads to be delayed for as many cycles as necessary
   4570  1.1  mrg    (and possible).  This reduces the number of NOPs we need to add.
   4571  1.1  mrg    The dummy insns we generate are later removed by bfin_gen_bundles.  */
   4572  1.1  mrg static void
   4573  1.1  mrg add_sched_insns_for_speculation (void)
   4574  1.1  mrg {
   4575  1.1  mrg   rtx_insn *insn;
   4576  1.1  mrg 
   4577  1.1  mrg   if (! ENABLE_WA_SPECULATIVE_LOADS && ! ENABLE_WA_SPECULATIVE_SYNCS
   4578  1.1  mrg       && ! ENABLE_WA_INDIRECT_CALLS)
   4579  1.1  mrg     return;
   4580  1.1  mrg 
   4581  1.1  mrg   /* First pass: find predicted-false branches; if something after them
   4582  1.1  mrg      needs nops, insert them or change the branch to predict true.  */
   4583  1.1  mrg   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
   4584  1.1  mrg     {
   4585  1.1  mrg       rtx pat;
   4586  1.1  mrg 
   4587  1.1  mrg       if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
   4588  1.1  mrg 	continue;
   4589  1.1  mrg       if (JUMP_TABLE_DATA_P (insn))
   4590  1.1  mrg 	continue;
   4591  1.1  mrg 
   4592  1.1  mrg       pat = PATTERN (insn);
   4593  1.1  mrg       if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
   4594  1.1  mrg 	  || GET_CODE (pat) == ASM_INPUT
   4595  1.1  mrg 	  || asm_noperands (pat) >= 0)
   4596  1.1  mrg 	continue;
   4597  1.1  mrg 
   4598  1.1  mrg       if (JUMP_P (insn))
   4599  1.1  mrg 	{
   4600  1.1  mrg 	  if (any_condjump_p (insn)
   4601  1.1  mrg 	      && !cbranch_predicted_taken_p (insn))
   4602  1.1  mrg 	    {
   4603  1.1  mrg 	      rtx_insn *n = next_real_insn (insn);
   4604  1.1  mrg 	      emit_insn_before (gen_stall (GEN_INT (3)), n);
   4605  1.1  mrg 	    }
   4606  1.1  mrg 	}
   4607  1.1  mrg     }
   4608  1.1  mrg 
   4609  1.1  mrg   /* Second pass: for predicted-true branches, see if anything at the
   4610  1.1  mrg      branch destination needs extra nops.  */
   4611  1.1  mrg   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
   4612  1.1  mrg     {
   4613  1.1  mrg       if (JUMP_P (insn)
   4614  1.1  mrg 	  && any_condjump_p (insn)
   4615  1.1  mrg 	  && (cbranch_predicted_taken_p (insn)))
   4616  1.1  mrg 	{
   4617  1.1  mrg 	  rtx_insn *target = JUMP_LABEL_AS_INSN (insn);
   4618  1.1  mrg 	  rtx_insn *next = next_real_insn (target);
   4619  1.1  mrg 
   4620  1.1  mrg 	  if (GET_CODE (PATTERN (next)) == UNSPEC_VOLATILE
   4621  1.1  mrg 	      && get_attr_type (next) == TYPE_STALL)
   4622  1.1  mrg 	    continue;
   4623  1.1  mrg 	  emit_insn_before (gen_stall (GEN_INT (1)), next);
   4624  1.1  mrg 	}
   4625  1.1  mrg     }
   4626  1.1  mrg }
   4627  1.1  mrg 
   4628  1.1  mrg /* We use the machine specific reorg pass for emitting CSYNC instructions
   4629  1.1  mrg    after conditional branches as needed.
   4630  1.1  mrg 
   4631  1.1  mrg    The Blackfin is unusual in that a code sequence like
   4632  1.1  mrg      if cc jump label
   4633  1.1  mrg      r0 = (p0)
   4634  1.1  mrg    may speculatively perform the load even if the condition isn't true.  This
   4635  1.1  mrg    happens for a branch that is predicted not taken, because the pipeline
   4636  1.1  mrg    isn't flushed or stalled, so the early stages of the following instructions,
   4637  1.1  mrg    which perform the memory reference, are allowed to execute before the
   4638  1.1  mrg    jump condition is evaluated.
   4639  1.1  mrg    Therefore, we must insert additional instructions in all places where this
   4640  1.1  mrg    could lead to incorrect behavior.  The manual recommends CSYNC, while
   4641  1.1  mrg    VDSP seems to use NOPs (even though its corresponding compiler option is
   4642  1.1  mrg    named CSYNC).
   4643  1.1  mrg 
   4644  1.1  mrg    When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
   4645  1.1  mrg    When optimizing for size, we turn the branch into a predicted taken one.
   4646  1.1  mrg    This may be slower due to mispredicts, but saves code size.  */
   4647  1.1  mrg 
   4648  1.1  mrg static void
   4649  1.1  mrg bfin_reorg (void)
   4650  1.1  mrg {
   4651  1.1  mrg   /* We are freeing block_for_insn in the toplev to keep compatibility
   4652  1.1  mrg      with old MDEP_REORGS that are not CFG based.  Recompute it now.  */
   4653  1.1  mrg   compute_bb_for_insn ();
   4654  1.1  mrg 
   4655  1.1  mrg   if (flag_schedule_insns_after_reload)
   4656  1.1  mrg     {
   4657  1.1  mrg       splitting_for_sched = 1;
   4658  1.1  mrg       split_all_insns ();
   4659  1.1  mrg       splitting_for_sched = 0;
   4660  1.1  mrg 
   4661  1.1  mrg       add_sched_insns_for_speculation ();
   4662  1.1  mrg 
   4663  1.1  mrg       timevar_push (TV_SCHED2);
   4664  1.1  mrg       if (flag_selective_scheduling2
   4665  1.1  mrg 	  && !maybe_skip_selective_scheduling ())
   4666  1.1  mrg         run_selective_scheduling ();
   4667  1.1  mrg       else
   4668  1.1  mrg 	schedule_insns ();
   4669  1.1  mrg       timevar_pop (TV_SCHED2);
   4670  1.1  mrg 
   4671  1.1  mrg       /* Examine the schedule and insert nops as necessary for 64-bit parallel
   4672  1.1  mrg 	 instructions.  */
   4673  1.1  mrg       bfin_gen_bundles ();
   4674  1.1  mrg     }
   4675  1.1  mrg 
   4676  1.1  mrg   df_analyze ();
   4677  1.1  mrg 
   4678  1.1  mrg   /* Doloop optimization */
   4679  1.1  mrg   if (cfun->machine->has_hardware_loops)
   4680  1.1  mrg     bfin_reorg_loops ();
   4681  1.1  mrg 
   4682  1.1  mrg   workaround_speculation ();
   4683  1.1  mrg 
   4684  1.1  mrg   if (flag_var_tracking)
   4685  1.1  mrg     {
   4686  1.1  mrg       timevar_push (TV_VAR_TRACKING);
   4687  1.1  mrg       variable_tracking_main ();
   4688  1.1  mrg       reorder_var_tracking_notes ();
   4689  1.1  mrg       timevar_pop (TV_VAR_TRACKING);
   4690  1.1  mrg     }
   4691  1.1  mrg 
   4692  1.1  mrg   df_finish_pass (false);
   4693  1.1  mrg 
   4694  1.1  mrg   workaround_rts_anomaly ();
   4695  1.1  mrg }
   4696  1.1  mrg 
   4697  1.1  mrg /* Handle interrupt_handler, exception_handler and nmi_handler function
   4699  1.1  mrg    attributes; arguments as in struct attribute_spec.handler.  */
   4700  1.1  mrg 
   4701  1.1  mrg static tree
   4702  1.1  mrg handle_int_attribute (tree *node, tree name,
   4703  1.1  mrg 		      tree args ATTRIBUTE_UNUSED,
   4704  1.1  mrg 		      int flags ATTRIBUTE_UNUSED,
   4705  1.1  mrg 		      bool *no_add_attrs)
   4706  1.1  mrg {
   4707  1.1  mrg   tree x = *node;
   4708  1.1  mrg   if (TREE_CODE (x) == FUNCTION_DECL)
   4709  1.1  mrg     x = TREE_TYPE (x);
   4710  1.1  mrg 
   4711  1.1  mrg   if (TREE_CODE (x) != FUNCTION_TYPE)
   4712  1.1  mrg     {
   4713  1.1  mrg       warning (OPT_Wattributes, "%qE attribute only applies to functions",
   4714  1.1  mrg 	       name);
   4715  1.1  mrg       *no_add_attrs = true;
   4716  1.1  mrg     }
   4717  1.1  mrg   else if (funkind (x) != SUBROUTINE)
   4718  1.1  mrg     error ("multiple function type attributes specified");
   4719  1.1  mrg 
   4720  1.1  mrg   return NULL_TREE;
   4721  1.1  mrg }
   4722  1.1  mrg 
   4723  1.1  mrg /* Return 0 if the attributes for two types are incompatible, 1 if they
   4724  1.1  mrg    are compatible, and 2 if they are nearly compatible (which causes a
   4725  1.1  mrg    warning to be generated).  */
   4726  1.1  mrg 
   4727  1.1  mrg static int
   4728  1.1  mrg bfin_comp_type_attributes (const_tree type1, const_tree type2)
   4729  1.1  mrg {
   4730  1.1  mrg   e_funkind kind1, kind2;
   4731  1.1  mrg 
   4732  1.1  mrg   if (TREE_CODE (type1) != FUNCTION_TYPE)
   4733  1.1  mrg     return 1;
   4734  1.1  mrg 
   4735  1.1  mrg   kind1 = funkind (type1);
   4736  1.1  mrg   kind2 = funkind (type2);
   4737  1.1  mrg 
   4738  1.1  mrg   if (kind1 != kind2)
   4739  1.1  mrg     return 0;
   4740  1.1  mrg 
   4741  1.1  mrg   /*  Check for mismatched modifiers */
   4742  1.1  mrg   if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
   4743  1.1  mrg       != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
   4744  1.1  mrg     return 0;
   4745  1.1  mrg 
   4746  1.1  mrg   if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
   4747  1.1  mrg       != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
   4748  1.1  mrg     return 0;
   4749  1.1  mrg 
   4750  1.1  mrg   if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
   4751  1.1  mrg       != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
   4752  1.1  mrg     return 0;
   4753  1.1  mrg 
   4754  1.1  mrg   if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1))
   4755  1.1  mrg       != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2)))
   4756  1.1  mrg     return 0;
   4757  1.1  mrg 
   4758  1.1  mrg   return 1;
   4759  1.1  mrg }
   4760  1.1  mrg 
   4761  1.1  mrg /* Handle a "longcall" or "shortcall" attribute; arguments as in
   4762  1.1  mrg    struct attribute_spec.handler.  */
   4763  1.1  mrg 
   4764  1.1  mrg static tree
   4765  1.1  mrg bfin_handle_longcall_attribute (tree *node, tree name,
   4766  1.1  mrg 				tree args ATTRIBUTE_UNUSED,
   4767  1.1  mrg 				int flags ATTRIBUTE_UNUSED,
   4768  1.1  mrg 				bool *no_add_attrs)
   4769  1.1  mrg {
   4770  1.1  mrg   if (TREE_CODE (*node) != FUNCTION_TYPE
   4771  1.1  mrg       && TREE_CODE (*node) != FIELD_DECL
   4772  1.1  mrg       && TREE_CODE (*node) != TYPE_DECL)
   4773  1.1  mrg     {
   4774  1.1  mrg       warning (OPT_Wattributes, "%qE attribute only applies to functions",
   4775  1.1  mrg 	       name);
   4776  1.1  mrg       *no_add_attrs = true;
   4777  1.1  mrg     }
   4778  1.1  mrg 
   4779  1.1  mrg   if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0
   4780  1.1  mrg        && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node)))
   4781  1.1  mrg       || (strcmp (IDENTIFIER_POINTER (name), "shortcall") == 0
   4782  1.1  mrg 	  && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node))))
   4783  1.1  mrg     {
   4784  1.1  mrg       warning (OPT_Wattributes,
   4785  1.1  mrg 	       "cannot apply both %<longcall%> and %<shortcall%> attributes "
   4786  1.1  mrg 	       "to the same function");
   4787  1.1  mrg       *no_add_attrs = true;
   4788  1.1  mrg     }
   4789  1.1  mrg 
   4790  1.1  mrg   return NULL_TREE;
   4791  1.1  mrg }
   4792  1.1  mrg 
   4793  1.1  mrg /* Handle a "l1_text" attribute; arguments as in
   4794  1.1  mrg    struct attribute_spec.handler.  */
   4795  1.1  mrg 
   4796  1.1  mrg static tree
   4797  1.1  mrg bfin_handle_l1_text_attribute (tree *node, tree name, tree ARG_UNUSED (args),
   4798  1.1  mrg 			       int ARG_UNUSED (flags), bool *no_add_attrs)
   4799  1.1  mrg {
   4800  1.1  mrg   tree decl = *node;
   4801  1.1  mrg 
   4802  1.1  mrg   if (TREE_CODE (decl) != FUNCTION_DECL)
   4803  1.1  mrg     {
   4804  1.1  mrg       error ("%qE attribute only applies to functions",
   4805  1.1  mrg 	     name);
   4806  1.1  mrg       *no_add_attrs = true;
   4807  1.1  mrg     }
   4808  1.1  mrg 
   4809  1.1  mrg   /* The decl may have already been given a section attribute
   4810  1.1  mrg      from a previous declaration. Ensure they match.  */
   4811  1.1  mrg   else if (DECL_SECTION_NAME (decl) != NULL
   4812  1.1  mrg 	   && strcmp (DECL_SECTION_NAME (decl),
   4813  1.1  mrg 		      ".l1.text") != 0)
   4814  1.1  mrg     {
   4815  1.1  mrg       error ("section of %q+D conflicts with previous declaration",
   4816  1.1  mrg 	     decl);
   4817  1.1  mrg       *no_add_attrs = true;
   4818  1.1  mrg     }
   4819  1.1  mrg   else
   4820  1.1  mrg     set_decl_section_name (decl, ".l1.text");
   4821  1.1  mrg 
   4822  1.1  mrg   return NULL_TREE;
   4823  1.1  mrg }
   4824  1.1  mrg 
   4825  1.1  mrg /* Handle a "l1_data", "l1_data_A" or "l1_data_B" attribute;
   4826  1.1  mrg    arguments as in struct attribute_spec.handler.  */
   4827  1.1  mrg 
   4828  1.1  mrg static tree
   4829  1.1  mrg bfin_handle_l1_data_attribute (tree *node, tree name, tree ARG_UNUSED (args),
   4830  1.1  mrg 			       int ARG_UNUSED (flags), bool *no_add_attrs)
   4831  1.1  mrg {
   4832  1.1  mrg   tree decl = *node;
   4833  1.1  mrg 
   4834  1.1  mrg   if (TREE_CODE (decl) != VAR_DECL)
   4835  1.1  mrg     {
   4836  1.1  mrg       error ("%qE attribute only applies to variables",
   4837  1.1  mrg 	     name);
   4838  1.1  mrg       *no_add_attrs = true;
   4839  1.1  mrg     }
   4840  1.1  mrg   else if (current_function_decl != NULL_TREE
   4841  1.1  mrg 	   && !TREE_STATIC (decl))
   4842  1.1  mrg     {
   4843  1.1  mrg       error ("%qE attribute cannot be specified for local variables",
   4844  1.1  mrg 	     name);
   4845  1.1  mrg       *no_add_attrs = true;
   4846  1.1  mrg     }
   4847  1.1  mrg   else
   4848  1.1  mrg     {
   4849  1.1  mrg       const char *section_name;
   4850  1.1  mrg 
   4851  1.1  mrg       if (strcmp (IDENTIFIER_POINTER (name), "l1_data") == 0)
   4852  1.1  mrg 	section_name = ".l1.data";
   4853  1.1  mrg       else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_A") == 0)
   4854  1.1  mrg 	section_name = ".l1.data.A";
   4855  1.1  mrg       else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_B") == 0)
   4856  1.1  mrg 	section_name = ".l1.data.B";
   4857  1.1  mrg       else
   4858  1.1  mrg 	gcc_unreachable ();
   4859  1.1  mrg 
   4860  1.1  mrg       /* The decl may have already been given a section attribute
   4861  1.1  mrg 	 from a previous declaration. Ensure they match.  */
   4862  1.1  mrg       if (DECL_SECTION_NAME (decl) != NULL
   4863  1.1  mrg 	  && strcmp (DECL_SECTION_NAME (decl),
   4864  1.1  mrg 		     section_name) != 0)
   4865  1.1  mrg 	{
   4866  1.1  mrg 	  error ("section of %q+D conflicts with previous declaration",
   4867  1.1  mrg 		 decl);
   4868  1.1  mrg 	  *no_add_attrs = true;
   4869  1.1  mrg 	}
   4870  1.1  mrg       else
   4871  1.1  mrg 	set_decl_section_name (decl, section_name);
   4872  1.1  mrg     }
   4873  1.1  mrg 
   4874  1.1  mrg  return NULL_TREE;
   4875  1.1  mrg }
   4876  1.1  mrg 
   4877  1.1  mrg /* Handle a "l2" attribute; arguments as in struct attribute_spec.handler.  */
   4878  1.1  mrg 
   4879  1.1  mrg static tree
   4880  1.1  mrg bfin_handle_l2_attribute (tree *node, tree ARG_UNUSED (name),
   4881  1.1  mrg 			  tree ARG_UNUSED (args), int ARG_UNUSED (flags),
   4882  1.1  mrg 			  bool *no_add_attrs)
   4883  1.1  mrg {
   4884  1.1  mrg   tree decl = *node;
   4885  1.1  mrg 
   4886  1.1  mrg   if (TREE_CODE (decl) == FUNCTION_DECL)
   4887  1.1  mrg     {
   4888  1.1  mrg       if (DECL_SECTION_NAME (decl) != NULL
   4889  1.1  mrg 	  && strcmp (DECL_SECTION_NAME (decl),
   4890  1.1  mrg 		     ".l2.text") != 0)
   4891  1.1  mrg 	{
   4892  1.1  mrg 	  error ("section of %q+D conflicts with previous declaration",
   4893  1.1  mrg 		 decl);
   4894  1.1  mrg 	  *no_add_attrs = true;
   4895  1.1  mrg 	}
   4896  1.1  mrg       else
   4897  1.1  mrg 	set_decl_section_name (decl, ".l2.text");
   4898  1.1  mrg     }
   4899  1.1  mrg   else if (TREE_CODE (decl) == VAR_DECL)
   4900  1.1  mrg     {
   4901  1.1  mrg       if (DECL_SECTION_NAME (decl) != NULL
   4902  1.1  mrg 	  && strcmp (DECL_SECTION_NAME (decl),
   4903  1.1  mrg 		     ".l2.data") != 0)
   4904  1.1  mrg 	{
   4905  1.1  mrg 	  error ("section of %q+D conflicts with previous declaration",
   4906  1.1  mrg 		 decl);
   4907  1.1  mrg 	  *no_add_attrs = true;
   4908  1.1  mrg 	}
   4909  1.1  mrg       else
   4910  1.1  mrg 	set_decl_section_name (decl, ".l2.data");
   4911  1.1  mrg     }
   4912  1.1  mrg 
   4913  1.1  mrg   return NULL_TREE;
   4914  1.1  mrg }
   4915  1.1  mrg 
   4916  1.1  mrg /* Table of valid machine attributes.  */
   4917  1.1  mrg static const struct attribute_spec bfin_attribute_table[] =
   4918  1.1  mrg {
   4919  1.1  mrg   /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
   4920  1.1  mrg        affects_type_identity, handler, exclude } */
   4921  1.1  mrg   { "interrupt_handler", 0, 0, false, true,  true, false,
   4922  1.1  mrg     handle_int_attribute, NULL },
   4923  1.1  mrg   { "exception_handler", 0, 0, false, true,  true, false,
   4924  1.1  mrg     handle_int_attribute, NULL },
   4925  1.1  mrg   { "nmi_handler", 0, 0, false, true,  true, false, handle_int_attribute,
   4926  1.1  mrg     NULL },
   4927  1.1  mrg   { "nesting", 0, 0, false, true,  true, false, NULL, NULL },
   4928  1.1  mrg   { "kspisusp", 0, 0, false, true,  true, false, NULL, NULL },
   4929  1.1  mrg   { "saveall", 0, 0, false, true,  true, false, NULL, NULL },
   4930  1.1  mrg   { "longcall",  0, 0, false, true,  true, false,
   4931  1.1  mrg     bfin_handle_longcall_attribute, NULL },
   4932  1.1  mrg   { "shortcall", 0, 0, false, true,  true, false,
   4933  1.1  mrg     bfin_handle_longcall_attribute, NULL },
   4934  1.1  mrg   { "l1_text", 0, 0, true, false, false, false,
   4935  1.1  mrg     bfin_handle_l1_text_attribute, NULL },
   4936  1.1  mrg   { "l1_data", 0, 0, true, false, false, false,
   4937  1.1  mrg     bfin_handle_l1_data_attribute, NULL },
   4938  1.1  mrg   { "l1_data_A", 0, 0, true, false, false, false,
   4939  1.1  mrg     bfin_handle_l1_data_attribute, NULL },
   4940  1.1  mrg   { "l1_data_B", 0, 0, true, false, false, false,
   4941  1.1  mrg     bfin_handle_l1_data_attribute, NULL },
   4942  1.1  mrg   { "l2", 0, 0, true, false, false, false, bfin_handle_l2_attribute, NULL },
   4943  1.1  mrg   { NULL, 0, 0, false, false, false, false, NULL, NULL }
   4944  1.1  mrg };
   4945  1.1  mrg 
   4946  1.1  mrg /* Implementation of TARGET_ASM_INTEGER.  When using FD-PIC, we need to
   4948  1.1  mrg    tell the assembler to generate pointers to function descriptors in
   4949  1.1  mrg    some cases.  */
   4950  1.1  mrg 
   4951  1.1  mrg static bool
   4952  1.1  mrg bfin_assemble_integer (rtx value, unsigned int size, int aligned_p)
   4953  1.1  mrg {
   4954  1.1  mrg   if (TARGET_FDPIC && size == UNITS_PER_WORD)
   4955  1.1  mrg     {
   4956  1.1  mrg       if (GET_CODE (value) == SYMBOL_REF
   4957  1.1  mrg 	  && SYMBOL_REF_FUNCTION_P (value))
   4958  1.1  mrg 	{
   4959  1.1  mrg 	  fputs ("\t.picptr\tfuncdesc(", asm_out_file);
   4960  1.1  mrg 	  output_addr_const (asm_out_file, value);
   4961  1.1  mrg 	  fputs (")\n", asm_out_file);
   4962  1.1  mrg 	  return true;
   4963  1.1  mrg 	}
   4964  1.1  mrg       if (!aligned_p)
   4965  1.1  mrg 	{
   4966  1.1  mrg 	  /* We've set the unaligned SI op to NULL, so we always have to
   4967  1.1  mrg 	     handle the unaligned case here.  */
   4968  1.1  mrg 	  assemble_integer_with_op ("\t.4byte\t", value);
   4969  1.1  mrg 	  return true;
   4970  1.1  mrg 	}
   4971  1.1  mrg     }
   4972  1.1  mrg   return default_assemble_integer (value, size, aligned_p);
   4973  1.1  mrg }
   4974  1.1  mrg 
   4975  1.1  mrg /* Output the assembler code for a thunk function.  THUNK_DECL is the
   4977  1.1  mrg    declaration for the thunk function itself, FUNCTION is the decl for
   4978  1.1  mrg    the target function.  DELTA is an immediate constant offset to be
   4979  1.1  mrg    added to THIS.  If VCALL_OFFSET is nonzero, the word at
   4980  1.1  mrg    *(*this + vcall_offset) should be added to THIS.  */
   4981  1.1  mrg 
   4982  1.1  mrg static void
   4983  1.1  mrg bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
   4984  1.1  mrg 		      tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
   4985  1.1  mrg 		      HOST_WIDE_INT vcall_offset, tree function)
   4986  1.1  mrg {
   4987  1.1  mrg   const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk));
   4988  1.1  mrg   rtx xops[3];
   4989  1.1  mrg   /* The this parameter is passed as the first argument.  */
   4990  1.1  mrg   rtx this_rtx = gen_rtx_REG (Pmode, REG_R0);
   4991  1.1  mrg 
   4992  1.1  mrg   assemble_start_function (thunk, fnname);
   4993  1.1  mrg   /* Adjust the this parameter by a fixed constant.  */
   4994  1.1  mrg   if (delta)
   4995  1.1  mrg     {
   4996  1.1  mrg       xops[1] = this_rtx;
   4997  1.1  mrg       if (delta >= -64 && delta <= 63)
   4998  1.1  mrg 	{
   4999  1.1  mrg 	  xops[0] = GEN_INT (delta);
   5000  1.1  mrg 	  output_asm_insn ("%1 += %0;", xops);
   5001  1.1  mrg 	}
   5002  1.1  mrg       else if (delta >= -128 && delta < -64)
   5003  1.1  mrg 	{
   5004  1.1  mrg 	  xops[0] = GEN_INT (delta + 64);
   5005  1.1  mrg 	  output_asm_insn ("%1 += -64; %1 += %0;", xops);
   5006  1.1  mrg 	}
   5007  1.1  mrg       else if (delta > 63 && delta <= 126)
   5008  1.1  mrg 	{
   5009  1.1  mrg 	  xops[0] = GEN_INT (delta - 63);
   5010  1.1  mrg 	  output_asm_insn ("%1 += 63; %1 += %0;", xops);
   5011  1.1  mrg 	}
   5012  1.1  mrg       else
   5013  1.1  mrg 	{
   5014  1.1  mrg 	  xops[0] = GEN_INT (delta);
   5015  1.1  mrg 	  output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
   5016  1.1  mrg 	}
   5017  1.1  mrg     }
   5018  1.1  mrg 
   5019  1.1  mrg   /* Adjust the this parameter by a value stored in the vtable.  */
   5020  1.1  mrg   if (vcall_offset)
   5021  1.1  mrg     {
   5022  1.1  mrg       rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
   5023  1.1  mrg       rtx tmp = gen_rtx_REG (Pmode, REG_R3);
   5024  1.1  mrg 
   5025  1.1  mrg       xops[1] = tmp;
   5026  1.1  mrg       xops[2] = p2tmp;
   5027  1.1  mrg       output_asm_insn ("%2 = r0; %2 = [%2];", xops);
   5028  1.1  mrg 
   5029  1.1  mrg       /* Adjust the this parameter.  */
   5030  1.1  mrg       xops[0] = gen_rtx_MEM (Pmode, plus_constant (Pmode, p2tmp,
   5031  1.1  mrg 						   vcall_offset));
   5032  1.1  mrg       if (!memory_operand (xops[0], Pmode))
   5033  1.1  mrg 	{
   5034  1.1  mrg 	  rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
   5035  1.1  mrg 	  xops[0] = GEN_INT (vcall_offset);
   5036  1.1  mrg 	  xops[1] = tmp2;
   5037  1.1  mrg 	  output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
   5038  1.1  mrg 	  xops[0] = gen_rtx_MEM (Pmode, p2tmp);
   5039  1.1  mrg 	}
   5040  1.1  mrg       xops[2] = this_rtx;
   5041  1.1  mrg       output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
   5042  1.1  mrg     }
   5043  1.1  mrg 
   5044  1.1  mrg   xops[0] = XEXP (DECL_RTL (function), 0);
   5045  1.1  mrg   if (1 || !flag_pic || (*targetm.binds_local_p) (function))
   5046  1.1  mrg     output_asm_insn ("jump.l\t%P0", xops);
   5047  1.1  mrg   assemble_end_function (thunk, fnname);
   5048  1.1  mrg }
   5049  1.1  mrg 
   5050  1.1  mrg /* Codes for all the Blackfin builtins.  */
   5052  1.1  mrg enum bfin_builtins
   5053  1.1  mrg {
   5054  1.1  mrg   BFIN_BUILTIN_CSYNC,
   5055  1.1  mrg   BFIN_BUILTIN_SSYNC,
   5056  1.1  mrg   BFIN_BUILTIN_ONES,
   5057  1.1  mrg   BFIN_BUILTIN_COMPOSE_2X16,
   5058  1.1  mrg   BFIN_BUILTIN_EXTRACTLO,
   5059  1.1  mrg   BFIN_BUILTIN_EXTRACTHI,
   5060  1.1  mrg 
   5061  1.1  mrg   BFIN_BUILTIN_SSADD_2X16,
   5062  1.1  mrg   BFIN_BUILTIN_SSSUB_2X16,
   5063  1.1  mrg   BFIN_BUILTIN_SSADDSUB_2X16,
   5064  1.1  mrg   BFIN_BUILTIN_SSSUBADD_2X16,
   5065  1.1  mrg   BFIN_BUILTIN_MULT_2X16,
   5066  1.1  mrg   BFIN_BUILTIN_MULTR_2X16,
   5067  1.1  mrg   BFIN_BUILTIN_NEG_2X16,
   5068  1.1  mrg   BFIN_BUILTIN_ABS_2X16,
   5069  1.1  mrg   BFIN_BUILTIN_MIN_2X16,
   5070  1.1  mrg   BFIN_BUILTIN_MAX_2X16,
   5071  1.1  mrg 
   5072  1.1  mrg   BFIN_BUILTIN_SSADD_1X16,
   5073  1.1  mrg   BFIN_BUILTIN_SSSUB_1X16,
   5074  1.1  mrg   BFIN_BUILTIN_MULT_1X16,
   5075  1.1  mrg   BFIN_BUILTIN_MULTR_1X16,
   5076  1.1  mrg   BFIN_BUILTIN_NORM_1X16,
   5077  1.1  mrg   BFIN_BUILTIN_NEG_1X16,
   5078  1.1  mrg   BFIN_BUILTIN_ABS_1X16,
   5079  1.1  mrg   BFIN_BUILTIN_MIN_1X16,
   5080  1.1  mrg   BFIN_BUILTIN_MAX_1X16,
   5081  1.1  mrg 
   5082  1.1  mrg   BFIN_BUILTIN_SUM_2X16,
   5083  1.1  mrg   BFIN_BUILTIN_DIFFHL_2X16,
   5084  1.1  mrg   BFIN_BUILTIN_DIFFLH_2X16,
   5085  1.1  mrg 
   5086  1.1  mrg   BFIN_BUILTIN_SSADD_1X32,
   5087  1.1  mrg   BFIN_BUILTIN_SSSUB_1X32,
   5088  1.1  mrg   BFIN_BUILTIN_NORM_1X32,
   5089  1.1  mrg   BFIN_BUILTIN_ROUND_1X32,
   5090  1.1  mrg   BFIN_BUILTIN_NEG_1X32,
   5091  1.1  mrg   BFIN_BUILTIN_ABS_1X32,
   5092  1.1  mrg   BFIN_BUILTIN_MIN_1X32,
   5093  1.1  mrg   BFIN_BUILTIN_MAX_1X32,
   5094  1.1  mrg   BFIN_BUILTIN_MULT_1X32,
   5095  1.1  mrg   BFIN_BUILTIN_MULT_1X32X32,
   5096  1.1  mrg   BFIN_BUILTIN_MULT_1X32X32NS,
   5097  1.1  mrg 
   5098  1.1  mrg   BFIN_BUILTIN_MULHISILL,
   5099  1.1  mrg   BFIN_BUILTIN_MULHISILH,
   5100  1.1  mrg   BFIN_BUILTIN_MULHISIHL,
   5101  1.1  mrg   BFIN_BUILTIN_MULHISIHH,
   5102  1.1  mrg 
   5103  1.1  mrg   BFIN_BUILTIN_LSHIFT_1X16,
   5104  1.1  mrg   BFIN_BUILTIN_LSHIFT_2X16,
   5105  1.1  mrg   BFIN_BUILTIN_SSASHIFT_1X16,
   5106  1.1  mrg   BFIN_BUILTIN_SSASHIFT_2X16,
   5107  1.1  mrg   BFIN_BUILTIN_SSASHIFT_1X32,
   5108  1.1  mrg 
   5109  1.1  mrg   BFIN_BUILTIN_CPLX_MUL_16,
   5110  1.1  mrg   BFIN_BUILTIN_CPLX_MAC_16,
   5111  1.1  mrg   BFIN_BUILTIN_CPLX_MSU_16,
   5112  1.1  mrg 
   5113  1.1  mrg   BFIN_BUILTIN_CPLX_MUL_16_S40,
   5114  1.1  mrg   BFIN_BUILTIN_CPLX_MAC_16_S40,
   5115  1.1  mrg   BFIN_BUILTIN_CPLX_MSU_16_S40,
   5116  1.1  mrg 
   5117  1.1  mrg   BFIN_BUILTIN_CPLX_SQU,
   5118  1.1  mrg 
   5119  1.1  mrg   BFIN_BUILTIN_LOADBYTES,
   5120  1.1  mrg 
   5121  1.1  mrg   BFIN_BUILTIN_MAX
   5122  1.1  mrg };
   5123  1.1  mrg 
   5124  1.1  mrg #define def_builtin(NAME, TYPE, CODE)					\
   5125  1.1  mrg do {									\
   5126  1.1  mrg   add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD,		\
   5127  1.1  mrg 		       NULL, NULL_TREE);				\
   5128  1.1  mrg } while (0)
   5129  1.1  mrg 
   5130  1.1  mrg /* Set up all builtin functions for this target.  */
   5131  1.1  mrg static void
   5132  1.1  mrg bfin_init_builtins (void)
   5133  1.1  mrg {
   5134  1.1  mrg   tree V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
   5135  1.1  mrg   tree void_ftype_void
   5136  1.1  mrg     = build_function_type_list (void_type_node, NULL_TREE);
   5137  1.1  mrg   tree short_ftype_short
   5138  1.1  mrg     = build_function_type_list (short_integer_type_node, short_integer_type_node,
   5139  1.1  mrg 				NULL_TREE);
   5140  1.1  mrg   tree short_ftype_int_int
   5141  1.1  mrg     = build_function_type_list (short_integer_type_node, integer_type_node,
   5142  1.1  mrg 				integer_type_node, NULL_TREE);
   5143  1.1  mrg   tree int_ftype_int_int
   5144  1.1  mrg     = build_function_type_list (integer_type_node, integer_type_node,
   5145  1.1  mrg 				integer_type_node, NULL_TREE);
   5146  1.1  mrg   tree int_ftype_int
   5147  1.1  mrg     = build_function_type_list (integer_type_node, integer_type_node,
   5148  1.1  mrg 				NULL_TREE);
   5149  1.1  mrg   tree short_ftype_int
   5150  1.1  mrg     = build_function_type_list (short_integer_type_node, integer_type_node,
   5151  1.1  mrg 				NULL_TREE);
   5152  1.1  mrg   tree int_ftype_v2hi_v2hi
   5153  1.1  mrg     = build_function_type_list (integer_type_node, V2HI_type_node,
   5154  1.1  mrg 				V2HI_type_node, NULL_TREE);
   5155  1.1  mrg   tree v2hi_ftype_v2hi_v2hi
   5156  1.1  mrg     = build_function_type_list (V2HI_type_node, V2HI_type_node,
   5157  1.1  mrg 				V2HI_type_node, NULL_TREE);
   5158  1.1  mrg   tree v2hi_ftype_v2hi_v2hi_v2hi
   5159  1.1  mrg     = build_function_type_list (V2HI_type_node, V2HI_type_node,
   5160  1.1  mrg 				V2HI_type_node, V2HI_type_node, NULL_TREE);
   5161  1.1  mrg   tree v2hi_ftype_int_int
   5162  1.1  mrg     = build_function_type_list (V2HI_type_node, integer_type_node,
   5163  1.1  mrg 				integer_type_node, NULL_TREE);
   5164  1.1  mrg   tree v2hi_ftype_v2hi_int
   5165  1.1  mrg     = build_function_type_list (V2HI_type_node, V2HI_type_node,
   5166  1.1  mrg 				integer_type_node, NULL_TREE);
   5167  1.1  mrg   tree int_ftype_short_short
   5168  1.1  mrg     = build_function_type_list (integer_type_node, short_integer_type_node,
   5169  1.1  mrg 				short_integer_type_node, NULL_TREE);
   5170  1.1  mrg   tree v2hi_ftype_v2hi
   5171  1.1  mrg     = build_function_type_list (V2HI_type_node, V2HI_type_node, NULL_TREE);
   5172  1.1  mrg   tree short_ftype_v2hi
   5173  1.1  mrg     = build_function_type_list (short_integer_type_node, V2HI_type_node,
   5174  1.1  mrg 				NULL_TREE);
   5175  1.1  mrg   tree int_ftype_pint
   5176  1.1  mrg     = build_function_type_list (integer_type_node,
   5177  1.1  mrg 				build_pointer_type (integer_type_node),
   5178  1.1  mrg 				NULL_TREE);
   5179  1.1  mrg 
   5180  1.1  mrg   /* Add the remaining MMX insns with somewhat more complicated types.  */
   5181  1.1  mrg   def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC);
   5182  1.1  mrg   def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC);
   5183  1.1  mrg 
   5184  1.1  mrg   def_builtin ("__builtin_bfin_ones", short_ftype_int, BFIN_BUILTIN_ONES);
   5185  1.1  mrg 
   5186  1.1  mrg   def_builtin ("__builtin_bfin_compose_2x16", v2hi_ftype_int_int,
   5187  1.1  mrg 	       BFIN_BUILTIN_COMPOSE_2X16);
   5188  1.1  mrg   def_builtin ("__builtin_bfin_extract_hi", short_ftype_v2hi,
   5189  1.1  mrg 	       BFIN_BUILTIN_EXTRACTHI);
   5190  1.1  mrg   def_builtin ("__builtin_bfin_extract_lo", short_ftype_v2hi,
   5191  1.1  mrg 	       BFIN_BUILTIN_EXTRACTLO);
   5192  1.1  mrg 
   5193  1.1  mrg   def_builtin ("__builtin_bfin_min_fr2x16", v2hi_ftype_v2hi_v2hi,
   5194  1.1  mrg 	       BFIN_BUILTIN_MIN_2X16);
   5195  1.1  mrg   def_builtin ("__builtin_bfin_max_fr2x16", v2hi_ftype_v2hi_v2hi,
   5196  1.1  mrg 	       BFIN_BUILTIN_MAX_2X16);
   5197  1.1  mrg 
   5198  1.1  mrg   def_builtin ("__builtin_bfin_add_fr2x16", v2hi_ftype_v2hi_v2hi,
   5199  1.1  mrg 	       BFIN_BUILTIN_SSADD_2X16);
   5200  1.1  mrg   def_builtin ("__builtin_bfin_sub_fr2x16", v2hi_ftype_v2hi_v2hi,
   5201  1.1  mrg 	       BFIN_BUILTIN_SSSUB_2X16);
   5202  1.1  mrg   def_builtin ("__builtin_bfin_dspaddsubsat", v2hi_ftype_v2hi_v2hi,
   5203  1.1  mrg 	       BFIN_BUILTIN_SSADDSUB_2X16);
   5204  1.1  mrg   def_builtin ("__builtin_bfin_dspsubaddsat", v2hi_ftype_v2hi_v2hi,
   5205  1.1  mrg 	       BFIN_BUILTIN_SSSUBADD_2X16);
   5206  1.1  mrg   def_builtin ("__builtin_bfin_mult_fr2x16", v2hi_ftype_v2hi_v2hi,
   5207  1.1  mrg 	       BFIN_BUILTIN_MULT_2X16);
   5208  1.1  mrg   def_builtin ("__builtin_bfin_multr_fr2x16", v2hi_ftype_v2hi_v2hi,
   5209  1.1  mrg 	       BFIN_BUILTIN_MULTR_2X16);
   5210  1.1  mrg   def_builtin ("__builtin_bfin_negate_fr2x16", v2hi_ftype_v2hi,
   5211  1.1  mrg 	       BFIN_BUILTIN_NEG_2X16);
   5212  1.1  mrg   def_builtin ("__builtin_bfin_abs_fr2x16", v2hi_ftype_v2hi,
   5213  1.1  mrg 	       BFIN_BUILTIN_ABS_2X16);
   5214  1.1  mrg 
   5215  1.1  mrg   def_builtin ("__builtin_bfin_min_fr1x16", short_ftype_int_int,
   5216  1.1  mrg 	       BFIN_BUILTIN_MIN_1X16);
   5217  1.1  mrg   def_builtin ("__builtin_bfin_max_fr1x16", short_ftype_int_int,
   5218  1.1  mrg 	       BFIN_BUILTIN_MAX_1X16);
   5219  1.1  mrg 
   5220  1.1  mrg   def_builtin ("__builtin_bfin_add_fr1x16", short_ftype_int_int,
   5221  1.1  mrg 	       BFIN_BUILTIN_SSADD_1X16);
   5222  1.1  mrg   def_builtin ("__builtin_bfin_sub_fr1x16", short_ftype_int_int,
   5223  1.1  mrg 	       BFIN_BUILTIN_SSSUB_1X16);
   5224  1.1  mrg   def_builtin ("__builtin_bfin_mult_fr1x16", short_ftype_int_int,
   5225  1.1  mrg 	       BFIN_BUILTIN_MULT_1X16);
   5226  1.1  mrg   def_builtin ("__builtin_bfin_multr_fr1x16", short_ftype_int_int,
   5227  1.1  mrg 	       BFIN_BUILTIN_MULTR_1X16);
   5228  1.1  mrg   def_builtin ("__builtin_bfin_negate_fr1x16", short_ftype_short,
   5229  1.1  mrg 	       BFIN_BUILTIN_NEG_1X16);
   5230  1.1  mrg   def_builtin ("__builtin_bfin_abs_fr1x16", short_ftype_short,
   5231  1.1  mrg 	       BFIN_BUILTIN_ABS_1X16);
   5232  1.1  mrg   def_builtin ("__builtin_bfin_norm_fr1x16", short_ftype_int,
   5233  1.1  mrg 	       BFIN_BUILTIN_NORM_1X16);
   5234  1.1  mrg 
   5235  1.1  mrg   def_builtin ("__builtin_bfin_sum_fr2x16", short_ftype_v2hi,
   5236  1.1  mrg 	       BFIN_BUILTIN_SUM_2X16);
   5237  1.1  mrg   def_builtin ("__builtin_bfin_diff_hl_fr2x16", short_ftype_v2hi,
   5238  1.1  mrg 	       BFIN_BUILTIN_DIFFHL_2X16);
   5239  1.1  mrg   def_builtin ("__builtin_bfin_diff_lh_fr2x16", short_ftype_v2hi,
   5240  1.1  mrg 	       BFIN_BUILTIN_DIFFLH_2X16);
   5241  1.1  mrg 
   5242  1.1  mrg   def_builtin ("__builtin_bfin_mulhisill", int_ftype_v2hi_v2hi,
   5243  1.1  mrg 	       BFIN_BUILTIN_MULHISILL);
   5244  1.1  mrg   def_builtin ("__builtin_bfin_mulhisihl", int_ftype_v2hi_v2hi,
   5245  1.1  mrg 	       BFIN_BUILTIN_MULHISIHL);
   5246  1.1  mrg   def_builtin ("__builtin_bfin_mulhisilh", int_ftype_v2hi_v2hi,
   5247  1.1  mrg 	       BFIN_BUILTIN_MULHISILH);
   5248  1.1  mrg   def_builtin ("__builtin_bfin_mulhisihh", int_ftype_v2hi_v2hi,
   5249  1.1  mrg 	       BFIN_BUILTIN_MULHISIHH);
   5250  1.1  mrg 
   5251  1.1  mrg   def_builtin ("__builtin_bfin_min_fr1x32", int_ftype_int_int,
   5252  1.1  mrg 	       BFIN_BUILTIN_MIN_1X32);
   5253  1.1  mrg   def_builtin ("__builtin_bfin_max_fr1x32", int_ftype_int_int,
   5254  1.1  mrg 	       BFIN_BUILTIN_MAX_1X32);
   5255  1.1  mrg 
   5256  1.1  mrg   def_builtin ("__builtin_bfin_add_fr1x32", int_ftype_int_int,
   5257  1.1  mrg 	       BFIN_BUILTIN_SSADD_1X32);
   5258  1.1  mrg   def_builtin ("__builtin_bfin_sub_fr1x32", int_ftype_int_int,
   5259  1.1  mrg 	       BFIN_BUILTIN_SSSUB_1X32);
   5260  1.1  mrg   def_builtin ("__builtin_bfin_negate_fr1x32", int_ftype_int,
   5261  1.1  mrg 	       BFIN_BUILTIN_NEG_1X32);
   5262  1.1  mrg   def_builtin ("__builtin_bfin_abs_fr1x32", int_ftype_int,
   5263  1.1  mrg 	       BFIN_BUILTIN_ABS_1X32);
   5264  1.1  mrg   def_builtin ("__builtin_bfin_norm_fr1x32", short_ftype_int,
   5265  1.1  mrg 	       BFIN_BUILTIN_NORM_1X32);
   5266  1.1  mrg   def_builtin ("__builtin_bfin_round_fr1x32", short_ftype_int,
   5267  1.1  mrg 	       BFIN_BUILTIN_ROUND_1X32);
   5268  1.1  mrg   def_builtin ("__builtin_bfin_mult_fr1x32", int_ftype_short_short,
   5269  1.1  mrg 	       BFIN_BUILTIN_MULT_1X32);
   5270  1.1  mrg   def_builtin ("__builtin_bfin_mult_fr1x32x32", int_ftype_int_int,
   5271  1.1  mrg 	       BFIN_BUILTIN_MULT_1X32X32);
   5272  1.1  mrg   def_builtin ("__builtin_bfin_mult_fr1x32x32NS", int_ftype_int_int,
   5273  1.1  mrg 	       BFIN_BUILTIN_MULT_1X32X32NS);
   5274  1.1  mrg 
   5275  1.1  mrg   /* Shifts.  */
   5276  1.1  mrg   def_builtin ("__builtin_bfin_shl_fr1x16", short_ftype_int_int,
   5277  1.1  mrg 	       BFIN_BUILTIN_SSASHIFT_1X16);
   5278  1.1  mrg   def_builtin ("__builtin_bfin_shl_fr2x16", v2hi_ftype_v2hi_int,
   5279  1.1  mrg 	       BFIN_BUILTIN_SSASHIFT_2X16);
   5280  1.1  mrg   def_builtin ("__builtin_bfin_lshl_fr1x16", short_ftype_int_int,
   5281  1.1  mrg 	       BFIN_BUILTIN_LSHIFT_1X16);
   5282  1.1  mrg   def_builtin ("__builtin_bfin_lshl_fr2x16", v2hi_ftype_v2hi_int,
   5283  1.1  mrg 	       BFIN_BUILTIN_LSHIFT_2X16);
   5284  1.1  mrg   def_builtin ("__builtin_bfin_shl_fr1x32", int_ftype_int_int,
   5285  1.1  mrg 	       BFIN_BUILTIN_SSASHIFT_1X32);
   5286  1.1  mrg 
   5287  1.1  mrg   /* Complex numbers.  */
   5288  1.1  mrg   def_builtin ("__builtin_bfin_cmplx_add", v2hi_ftype_v2hi_v2hi,
   5289  1.1  mrg 	       BFIN_BUILTIN_SSADD_2X16);
   5290  1.1  mrg   def_builtin ("__builtin_bfin_cmplx_sub", v2hi_ftype_v2hi_v2hi,
   5291  1.1  mrg 	       BFIN_BUILTIN_SSSUB_2X16);
   5292  1.1  mrg   def_builtin ("__builtin_bfin_cmplx_mul", v2hi_ftype_v2hi_v2hi,
   5293  1.1  mrg 	       BFIN_BUILTIN_CPLX_MUL_16);
   5294  1.1  mrg   def_builtin ("__builtin_bfin_cmplx_mac", v2hi_ftype_v2hi_v2hi_v2hi,
   5295  1.1  mrg 	       BFIN_BUILTIN_CPLX_MAC_16);
   5296  1.1  mrg   def_builtin ("__builtin_bfin_cmplx_msu", v2hi_ftype_v2hi_v2hi_v2hi,
   5297  1.1  mrg 	       BFIN_BUILTIN_CPLX_MSU_16);
   5298  1.1  mrg   def_builtin ("__builtin_bfin_cmplx_mul_s40", v2hi_ftype_v2hi_v2hi,
   5299  1.1  mrg 	       BFIN_BUILTIN_CPLX_MUL_16_S40);
   5300  1.1  mrg   def_builtin ("__builtin_bfin_cmplx_mac_s40", v2hi_ftype_v2hi_v2hi_v2hi,
   5301  1.1  mrg 	       BFIN_BUILTIN_CPLX_MAC_16_S40);
   5302  1.1  mrg   def_builtin ("__builtin_bfin_cmplx_msu_s40", v2hi_ftype_v2hi_v2hi_v2hi,
   5303  1.1  mrg 	       BFIN_BUILTIN_CPLX_MSU_16_S40);
   5304  1.1  mrg   def_builtin ("__builtin_bfin_csqu_fr16", v2hi_ftype_v2hi,
   5305  1.1  mrg 	       BFIN_BUILTIN_CPLX_SQU);
   5306  1.1  mrg 
   5307  1.1  mrg   /* "Unaligned" load.  */
   5308  1.1  mrg   def_builtin ("__builtin_bfin_loadbytes", int_ftype_pint,
   5309  1.1  mrg 	       BFIN_BUILTIN_LOADBYTES);
   5310  1.1  mrg 
   5311  1.1  mrg }
   5312  1.1  mrg 
   5313  1.1  mrg 
   5314  1.1  mrg struct builtin_description
   5315  1.1  mrg {
   5316  1.1  mrg   const enum insn_code icode;
   5317  1.1  mrg   const char *const name;
   5318  1.1  mrg   const enum bfin_builtins code;
   5319  1.1  mrg   int macflag;
   5320  1.1  mrg };
   5321  1.1  mrg 
   5322  1.1  mrg static const struct builtin_description bdesc_2arg[] =
   5323  1.1  mrg {
   5324  1.1  mrg   { CODE_FOR_composev2hi, "__builtin_bfin_compose_2x16", BFIN_BUILTIN_COMPOSE_2X16, -1 },
   5325  1.1  mrg 
   5326  1.1  mrg   { CODE_FOR_ssashiftv2hi3, "__builtin_bfin_shl_fr2x16", BFIN_BUILTIN_SSASHIFT_2X16, -1 },
   5327  1.1  mrg   { CODE_FOR_ssashifthi3, "__builtin_bfin_shl_fr1x16", BFIN_BUILTIN_SSASHIFT_1X16, -1 },
   5328  1.1  mrg   { CODE_FOR_lshiftv2hi3, "__builtin_bfin_lshl_fr2x16", BFIN_BUILTIN_LSHIFT_2X16, -1 },
   5329  1.1  mrg   { CODE_FOR_lshifthi3, "__builtin_bfin_lshl_fr1x16", BFIN_BUILTIN_LSHIFT_1X16, -1 },
   5330  1.1  mrg   { CODE_FOR_ssashiftsi3, "__builtin_bfin_shl_fr1x32", BFIN_BUILTIN_SSASHIFT_1X32, -1 },
   5331  1.1  mrg 
   5332  1.1  mrg   { CODE_FOR_sminhi3, "__builtin_bfin_min_fr1x16", BFIN_BUILTIN_MIN_1X16, -1 },
   5333  1.1  mrg   { CODE_FOR_smaxhi3, "__builtin_bfin_max_fr1x16", BFIN_BUILTIN_MAX_1X16, -1 },
   5334  1.1  mrg   { CODE_FOR_ssaddhi3, "__builtin_bfin_add_fr1x16", BFIN_BUILTIN_SSADD_1X16, -1 },
   5335  1.1  mrg   { CODE_FOR_sssubhi3, "__builtin_bfin_sub_fr1x16", BFIN_BUILTIN_SSSUB_1X16, -1 },
   5336  1.1  mrg 
   5337  1.1  mrg   { CODE_FOR_sminsi3, "__builtin_bfin_min_fr1x32", BFIN_BUILTIN_MIN_1X32, -1 },
   5338  1.1  mrg   { CODE_FOR_smaxsi3, "__builtin_bfin_max_fr1x32", BFIN_BUILTIN_MAX_1X32, -1 },
   5339  1.1  mrg   { CODE_FOR_ssaddsi3, "__builtin_bfin_add_fr1x32", BFIN_BUILTIN_SSADD_1X32, -1 },
   5340  1.1  mrg   { CODE_FOR_sssubsi3, "__builtin_bfin_sub_fr1x32", BFIN_BUILTIN_SSSUB_1X32, -1 },
   5341  1.1  mrg 
   5342  1.1  mrg   { CODE_FOR_sminv2hi3, "__builtin_bfin_min_fr2x16", BFIN_BUILTIN_MIN_2X16, -1 },
   5343  1.1  mrg   { CODE_FOR_smaxv2hi3, "__builtin_bfin_max_fr2x16", BFIN_BUILTIN_MAX_2X16, -1 },
   5344  1.1  mrg   { CODE_FOR_ssaddv2hi3, "__builtin_bfin_add_fr2x16", BFIN_BUILTIN_SSADD_2X16, -1 },
   5345  1.1  mrg   { CODE_FOR_sssubv2hi3, "__builtin_bfin_sub_fr2x16", BFIN_BUILTIN_SSSUB_2X16, -1 },
   5346  1.1  mrg   { CODE_FOR_ssaddsubv2hi3, "__builtin_bfin_dspaddsubsat", BFIN_BUILTIN_SSADDSUB_2X16, -1 },
   5347  1.1  mrg   { CODE_FOR_sssubaddv2hi3, "__builtin_bfin_dspsubaddsat", BFIN_BUILTIN_SSSUBADD_2X16, -1 },
   5348  1.1  mrg 
   5349  1.1  mrg   { CODE_FOR_flag_mulhisi, "__builtin_bfin_mult_fr1x32", BFIN_BUILTIN_MULT_1X32, MACFLAG_NONE },
   5350  1.1  mrg   { CODE_FOR_flag_mulhi, "__builtin_bfin_mult_fr1x16", BFIN_BUILTIN_MULT_1X16, MACFLAG_T },
   5351  1.1  mrg   { CODE_FOR_flag_mulhi, "__builtin_bfin_multr_fr1x16", BFIN_BUILTIN_MULTR_1X16, MACFLAG_NONE },
   5352  1.1  mrg   { CODE_FOR_flag_mulv2hi, "__builtin_bfin_mult_fr2x16", BFIN_BUILTIN_MULT_2X16, MACFLAG_T },
   5353  1.1  mrg   { CODE_FOR_flag_mulv2hi, "__builtin_bfin_multr_fr2x16", BFIN_BUILTIN_MULTR_2X16, MACFLAG_NONE },
   5354  1.1  mrg 
   5355  1.1  mrg   { CODE_FOR_mulhisi_ll, "__builtin_bfin_mulhisill", BFIN_BUILTIN_MULHISILL, -1 },
   5356  1.1  mrg   { CODE_FOR_mulhisi_lh, "__builtin_bfin_mulhisilh", BFIN_BUILTIN_MULHISILH, -1 },
   5357  1.1  mrg   { CODE_FOR_mulhisi_hl, "__builtin_bfin_mulhisihl", BFIN_BUILTIN_MULHISIHL, -1 },
   5358  1.1  mrg   { CODE_FOR_mulhisi_hh, "__builtin_bfin_mulhisihh", BFIN_BUILTIN_MULHISIHH, -1 }
   5359  1.1  mrg 
   5360  1.1  mrg };
   5361  1.1  mrg 
   5362  1.1  mrg static const struct builtin_description bdesc_1arg[] =
   5363  1.1  mrg {
   5364  1.1  mrg   { CODE_FOR_loadbytes, "__builtin_bfin_loadbytes", BFIN_BUILTIN_LOADBYTES, 0 },
   5365  1.1  mrg 
   5366  1.1  mrg   { CODE_FOR_ones, "__builtin_bfin_ones", BFIN_BUILTIN_ONES, 0 },
   5367  1.1  mrg 
   5368  1.1  mrg   { CODE_FOR_clrsbhi2, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16, 0 },
   5369  1.1  mrg   { CODE_FOR_ssneghi2, "__builtin_bfin_negate_fr1x16", BFIN_BUILTIN_NEG_1X16, 0 },
   5370  1.1  mrg   { CODE_FOR_abshi2, "__builtin_bfin_abs_fr1x16", BFIN_BUILTIN_ABS_1X16, 0 },
   5371  1.1  mrg 
   5372  1.1  mrg   { CODE_FOR_clrsbsi2, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32, 0 },
   5373  1.1  mrg   { CODE_FOR_ssroundsi2, "__builtin_bfin_round_fr1x32", BFIN_BUILTIN_ROUND_1X32, 0 },
   5374  1.1  mrg   { CODE_FOR_ssnegsi2, "__builtin_bfin_negate_fr1x32", BFIN_BUILTIN_NEG_1X32, 0 },
   5375  1.1  mrg   { CODE_FOR_ssabssi2, "__builtin_bfin_abs_fr1x32", BFIN_BUILTIN_ABS_1X32, 0 },
   5376  1.1  mrg 
   5377  1.1  mrg   { CODE_FOR_movv2hi_hi_low, "__builtin_bfin_extract_lo", BFIN_BUILTIN_EXTRACTLO, 0 },
   5378  1.1  mrg   { CODE_FOR_movv2hi_hi_high, "__builtin_bfin_extract_hi", BFIN_BUILTIN_EXTRACTHI, 0 },
   5379  1.1  mrg   { CODE_FOR_ssnegv2hi2, "__builtin_bfin_negate_fr2x16", BFIN_BUILTIN_NEG_2X16, 0 },
   5380  1.1  mrg   { CODE_FOR_ssabsv2hi2, "__builtin_bfin_abs_fr2x16", BFIN_BUILTIN_ABS_2X16, 0 }
   5381  1.1  mrg };
   5382  1.1  mrg 
   5383  1.1  mrg /* Errors in the source file can cause expand_expr to return const0_rtx
   5384  1.1  mrg    where we expect a vector.  To avoid crashing, use one of the vector
   5385  1.1  mrg    clear instructions.  */
   5386  1.1  mrg static rtx
   5387  1.1  mrg safe_vector_operand (rtx x, machine_mode mode)
   5388  1.1  mrg {
   5389  1.1  mrg   if (x != const0_rtx)
   5390  1.1  mrg     return x;
   5391  1.1  mrg   x = gen_reg_rtx (SImode);
   5392  1.1  mrg 
   5393  1.1  mrg   emit_insn (gen_movsi (x, CONST0_RTX (SImode)));
   5394  1.1  mrg   return gen_lowpart (mode, x);
   5395  1.1  mrg }
   5396  1.1  mrg 
   5397  1.1  mrg /* Subroutine of bfin_expand_builtin to take care of binop insns.  MACFLAG is -1
   5398  1.1  mrg    if this is a normal binary op, or one of the MACFLAG_xxx constants.  */
   5399  1.1  mrg 
   5400  1.1  mrg static rtx
   5401  1.1  mrg bfin_expand_binop_builtin (enum insn_code icode, tree exp, rtx target,
   5402  1.1  mrg 			   int macflag)
   5403  1.1  mrg {
   5404  1.1  mrg   rtx pat;
   5405  1.1  mrg   tree arg0 = CALL_EXPR_ARG (exp, 0);
   5406  1.1  mrg   tree arg1 = CALL_EXPR_ARG (exp, 1);
   5407  1.1  mrg   rtx op0 = expand_normal (arg0);
   5408  1.1  mrg   rtx op1 = expand_normal (arg1);
   5409  1.1  mrg   machine_mode op0mode = GET_MODE (op0);
   5410  1.1  mrg   machine_mode op1mode = GET_MODE (op1);
   5411  1.1  mrg   machine_mode tmode = insn_data[icode].operand[0].mode;
   5412  1.1  mrg   machine_mode mode0 = insn_data[icode].operand[1].mode;
   5413  1.1  mrg   machine_mode mode1 = insn_data[icode].operand[2].mode;
   5414  1.1  mrg 
   5415  1.1  mrg   if (VECTOR_MODE_P (mode0))
   5416  1.1  mrg     op0 = safe_vector_operand (op0, mode0);
   5417  1.1  mrg   if (VECTOR_MODE_P (mode1))
   5418  1.1  mrg     op1 = safe_vector_operand (op1, mode1);
   5419  1.1  mrg 
   5420  1.1  mrg   if (! target
   5421  1.1  mrg       || GET_MODE (target) != tmode
   5422  1.1  mrg       || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
   5423  1.1  mrg     target = gen_reg_rtx (tmode);
   5424  1.1  mrg 
   5425  1.1  mrg   if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode)
   5426  1.1  mrg     {
   5427  1.1  mrg       op0mode = HImode;
   5428  1.1  mrg       op0 = gen_lowpart (HImode, op0);
   5429  1.1  mrg     }
   5430  1.1  mrg   if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode)
   5431  1.1  mrg     {
   5432  1.1  mrg       op1mode = HImode;
   5433  1.1  mrg       op1 = gen_lowpart (HImode, op1);
   5434  1.1  mrg     }
   5435  1.1  mrg   /* In case the insn wants input operands in modes different from
   5436  1.1  mrg      the result, abort.  */
   5437  1.1  mrg   gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
   5438  1.1  mrg 	      && (op1mode == mode1 || op1mode == VOIDmode));
   5439  1.1  mrg 
   5440  1.1  mrg   if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
   5441  1.1  mrg     op0 = copy_to_mode_reg (mode0, op0);
   5442  1.1  mrg   if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
   5443  1.1  mrg     op1 = copy_to_mode_reg (mode1, op1);
   5444  1.1  mrg 
   5445  1.1  mrg   if (macflag == -1)
   5446  1.1  mrg     pat = GEN_FCN (icode) (target, op0, op1);
   5447  1.1  mrg   else
   5448  1.1  mrg     pat = GEN_FCN (icode) (target, op0, op1, GEN_INT (macflag));
   5449  1.1  mrg   if (! pat)
   5450  1.1  mrg     return 0;
   5451  1.1  mrg 
   5452  1.1  mrg   emit_insn (pat);
   5453  1.1  mrg   return target;
   5454  1.1  mrg }
   5455  1.1  mrg 
   5456  1.1  mrg /* Subroutine of bfin_expand_builtin to take care of unop insns.  */
   5457  1.1  mrg 
   5458  1.1  mrg static rtx
   5459  1.1  mrg bfin_expand_unop_builtin (enum insn_code icode, tree exp,
   5460  1.1  mrg 			  rtx target)
   5461  1.1  mrg {
   5462  1.1  mrg   rtx pat;
   5463  1.1  mrg   tree arg0 = CALL_EXPR_ARG (exp, 0);
   5464  1.1  mrg   rtx op0 = expand_normal (arg0);
   5465  1.1  mrg   machine_mode op0mode = GET_MODE (op0);
   5466  1.1  mrg   machine_mode tmode = insn_data[icode].operand[0].mode;
   5467  1.1  mrg   machine_mode mode0 = insn_data[icode].operand[1].mode;
   5468  1.1  mrg 
   5469  1.1  mrg   if (! target
   5470  1.1  mrg       || GET_MODE (target) != tmode
   5471  1.1  mrg       || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
   5472  1.1  mrg     target = gen_reg_rtx (tmode);
   5473  1.1  mrg 
   5474  1.1  mrg   if (VECTOR_MODE_P (mode0))
   5475  1.1  mrg     op0 = safe_vector_operand (op0, mode0);
   5476  1.1  mrg 
   5477  1.1  mrg   if (op0mode == SImode && mode0 == HImode)
   5478  1.1  mrg     {
   5479  1.1  mrg       op0mode = HImode;
   5480  1.1  mrg       op0 = gen_lowpart (HImode, op0);
   5481  1.1  mrg     }
   5482  1.1  mrg   gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
   5483  1.1  mrg 
   5484  1.1  mrg   if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
   5485  1.1  mrg     op0 = copy_to_mode_reg (mode0, op0);
   5486  1.1  mrg 
   5487  1.1  mrg   pat = GEN_FCN (icode) (target, op0);
   5488  1.1  mrg   if (! pat)
   5489  1.1  mrg     return 0;
   5490  1.1  mrg   emit_insn (pat);
   5491  1.1  mrg   return target;
   5492  1.1  mrg }
   5493  1.1  mrg 
   5494  1.1  mrg /* Expand an expression EXP that calls a built-in function,
   5495  1.1  mrg    with result going to TARGET if that's convenient
   5496  1.1  mrg    (and in mode MODE if that's convenient).
   5497  1.1  mrg    SUBTARGET may be used as the target for computing one of EXP's operands.
   5498  1.1  mrg    IGNORE is nonzero if the value is to be ignored.  */
   5499  1.1  mrg 
   5500  1.1  mrg static rtx
   5501  1.1  mrg bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
   5502  1.1  mrg 		     rtx subtarget ATTRIBUTE_UNUSED,
   5503  1.1  mrg 		     machine_mode mode ATTRIBUTE_UNUSED,
   5504  1.1  mrg 		     int ignore ATTRIBUTE_UNUSED)
   5505  1.1  mrg {
   5506  1.1  mrg   size_t i;
   5507  1.1  mrg   enum insn_code icode;
   5508  1.1  mrg   const struct builtin_description *d;
   5509  1.1  mrg   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
   5510  1.1  mrg   unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
   5511  1.1  mrg   tree arg0, arg1, arg2;
   5512  1.1  mrg   rtx op0, op1, op2, accvec, pat, tmp1, tmp2, a0reg, a1reg;
   5513  1.1  mrg   machine_mode tmode, mode0;
   5514  1.1  mrg 
   5515  1.1  mrg   switch (fcode)
   5516  1.1  mrg     {
   5517  1.1  mrg     case BFIN_BUILTIN_CSYNC:
   5518  1.1  mrg       emit_insn (gen_csync ());
   5519  1.1  mrg       return 0;
   5520  1.1  mrg     case BFIN_BUILTIN_SSYNC:
   5521  1.1  mrg       emit_insn (gen_ssync ());
   5522  1.1  mrg       return 0;
   5523  1.1  mrg 
   5524  1.1  mrg     case BFIN_BUILTIN_DIFFHL_2X16:
   5525  1.1  mrg     case BFIN_BUILTIN_DIFFLH_2X16:
   5526  1.1  mrg     case BFIN_BUILTIN_SUM_2X16:
   5527  1.1  mrg       arg0 = CALL_EXPR_ARG (exp, 0);
   5528  1.1  mrg       op0 = expand_normal (arg0);
   5529  1.1  mrg       icode = (fcode == BFIN_BUILTIN_DIFFHL_2X16 ? CODE_FOR_subhilov2hi3
   5530  1.1  mrg 	       : fcode == BFIN_BUILTIN_DIFFLH_2X16 ? CODE_FOR_sublohiv2hi3
   5531  1.1  mrg 	       : CODE_FOR_ssaddhilov2hi3);
   5532  1.1  mrg       tmode = insn_data[icode].operand[0].mode;
   5533  1.1  mrg       mode0 = insn_data[icode].operand[1].mode;
   5534  1.1  mrg 
   5535  1.1  mrg       if (! target
   5536  1.1  mrg 	  || GET_MODE (target) != tmode
   5537  1.1  mrg 	  || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
   5538  1.1  mrg 	target = gen_reg_rtx (tmode);
   5539  1.1  mrg 
   5540  1.1  mrg       if (VECTOR_MODE_P (mode0))
   5541  1.1  mrg 	op0 = safe_vector_operand (op0, mode0);
   5542  1.1  mrg 
   5543  1.1  mrg       if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
   5544  1.1  mrg 	op0 = copy_to_mode_reg (mode0, op0);
   5545  1.1  mrg 
   5546  1.1  mrg       pat = GEN_FCN (icode) (target, op0, op0);
   5547  1.1  mrg       if (! pat)
   5548  1.1  mrg 	return 0;
   5549  1.1  mrg       emit_insn (pat);
   5550  1.1  mrg       return target;
   5551  1.1  mrg 
   5552  1.1  mrg     case BFIN_BUILTIN_MULT_1X32X32:
   5553  1.1  mrg     case BFIN_BUILTIN_MULT_1X32X32NS:
   5554  1.1  mrg       arg0 = CALL_EXPR_ARG (exp, 0);
   5555  1.1  mrg       arg1 = CALL_EXPR_ARG (exp, 1);
   5556  1.1  mrg       op0 = expand_normal (arg0);
   5557  1.1  mrg       op1 = expand_normal (arg1);
   5558  1.1  mrg       if (! target
   5559  1.1  mrg 	  || !register_operand (target, SImode))
   5560  1.1  mrg 	target = gen_reg_rtx (SImode);
   5561  1.1  mrg       if (! register_operand (op0, SImode))
   5562  1.1  mrg 	op0 = copy_to_mode_reg (SImode, op0);
   5563  1.1  mrg       if (! register_operand (op1, SImode))
   5564  1.1  mrg 	op1 = copy_to_mode_reg (SImode, op1);
   5565  1.1  mrg 
   5566  1.1  mrg       a1reg = gen_rtx_REG (PDImode, REG_A1);
   5567  1.1  mrg       a0reg = gen_rtx_REG (PDImode, REG_A0);
   5568  1.1  mrg       tmp1 = gen_lowpart (V2HImode, op0);
   5569  1.1  mrg       tmp2 = gen_lowpart (V2HImode, op1);
   5570  1.1  mrg       emit_insn (gen_flag_macinit1hi (a1reg,
   5571  1.1  mrg 				      gen_lowpart (HImode, op0),
   5572  1.1  mrg 				      gen_lowpart (HImode, op1),
   5573  1.1  mrg 				      GEN_INT (MACFLAG_FU)));
   5574  1.1  mrg       emit_insn (gen_lshrpdi3 (a1reg, a1reg, GEN_INT (16)));
   5575  1.1  mrg 
   5576  1.1  mrg       if (fcode == BFIN_BUILTIN_MULT_1X32X32)
   5577  1.1  mrg 	emit_insn (gen_flag_mul_macv2hi_parts_acconly (a0reg, a1reg, tmp1, tmp2,
   5578  1.1  mrg 						       const1_rtx, const1_rtx,
   5579  1.1  mrg 						       const1_rtx, const0_rtx, a1reg,
   5580  1.1  mrg 						       const0_rtx, GEN_INT (MACFLAG_NONE),
   5581  1.1  mrg 						       GEN_INT (MACFLAG_M)));
   5582  1.1  mrg       else
   5583  1.1  mrg 	{
   5584  1.1  mrg 	  /* For saturating multiplication, there's exactly one special case
   5585  1.1  mrg 	     to be handled: multiplying the smallest negative value with
   5586  1.1  mrg 	     itself.  Due to shift correction in fractional multiplies, this
   5587  1.1  mrg 	     can overflow.  Iff this happens, OP2 will contain 1, which, when
   5588  1.1  mrg 	     added in 32 bits to the smallest negative, wraps to the largest
   5589  1.1  mrg 	     positive, which is the result we want.  */
   5590  1.1  mrg 	  op2 = gen_reg_rtx (V2HImode);
   5591  1.1  mrg 	  emit_insn (gen_packv2hi (op2, tmp1, tmp2, const0_rtx, const0_rtx));
   5592  1.1  mrg 	  emit_insn (gen_movsibi (gen_rtx_REG (BImode, REG_CC),
   5593  1.1  mrg 				  gen_lowpart (SImode, op2)));
   5594  1.1  mrg 	  emit_insn (gen_flag_mul_macv2hi_parts_acconly_andcc0 (a0reg, a1reg, tmp1, tmp2,
   5595  1.1  mrg 								const1_rtx, const1_rtx,
   5596  1.1  mrg 								const1_rtx, const0_rtx, a1reg,
   5597  1.1  mrg 								const0_rtx, GEN_INT (MACFLAG_NONE),
   5598  1.1  mrg 								GEN_INT (MACFLAG_M)));
   5599  1.1  mrg 	  op2 = gen_reg_rtx (SImode);
   5600  1.1  mrg 	  emit_insn (gen_movbisi (op2, gen_rtx_REG (BImode, REG_CC)));
   5601  1.1  mrg 	}
   5602  1.1  mrg       emit_insn (gen_flag_machi_parts_acconly (a1reg, tmp2, tmp1,
   5603  1.1  mrg 					       const1_rtx, const0_rtx,
   5604  1.1  mrg 					       a1reg, const0_rtx, GEN_INT (MACFLAG_M)));
   5605  1.1  mrg       emit_insn (gen_ashrpdi3 (a1reg, a1reg, GEN_INT (15)));
   5606  1.1  mrg       emit_insn (gen_sum_of_accumulators (target, a0reg, a0reg, a1reg));
   5607  1.1  mrg       if (fcode == BFIN_BUILTIN_MULT_1X32X32NS)
   5608  1.1  mrg 	emit_insn (gen_addsi3 (target, target, op2));
   5609  1.1  mrg       return target;
   5610  1.1  mrg 
   5611  1.1  mrg     case BFIN_BUILTIN_CPLX_MUL_16:
   5612  1.1  mrg     case BFIN_BUILTIN_CPLX_MUL_16_S40:
   5613  1.1  mrg       arg0 = CALL_EXPR_ARG (exp, 0);
   5614  1.1  mrg       arg1 = CALL_EXPR_ARG (exp, 1);
   5615  1.1  mrg       op0 = expand_normal (arg0);
   5616  1.1  mrg       op1 = expand_normal (arg1);
   5617  1.1  mrg       accvec = gen_reg_rtx (V2PDImode);
   5618  1.1  mrg       icode = CODE_FOR_flag_macv2hi_parts;
   5619  1.1  mrg       tmode = insn_data[icode].operand[0].mode;
   5620  1.1  mrg 
   5621  1.1  mrg       if (! target
   5622  1.1  mrg 	  || GET_MODE (target) != V2HImode
   5623  1.1  mrg 	  || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
   5624  1.1  mrg 	target = gen_reg_rtx (tmode);
   5625  1.1  mrg       if (! register_operand (op0, GET_MODE (op0)))
   5626  1.1  mrg 	op0 = copy_to_mode_reg (GET_MODE (op0), op0);
   5627  1.1  mrg       if (! register_operand (op1, GET_MODE (op1)))
   5628  1.1  mrg 	op1 = copy_to_mode_reg (GET_MODE (op1), op1);
   5629  1.1  mrg 
   5630  1.1  mrg       if (fcode == BFIN_BUILTIN_CPLX_MUL_16)
   5631  1.1  mrg 	emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
   5632  1.1  mrg 						const0_rtx, const0_rtx,
   5633  1.1  mrg 						const1_rtx, GEN_INT (MACFLAG_W32)));
   5634  1.1  mrg       else
   5635  1.1  mrg 	emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
   5636  1.1  mrg 						const0_rtx, const0_rtx,
   5637  1.1  mrg 						const1_rtx, GEN_INT (MACFLAG_NONE)));
   5638  1.1  mrg       emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
   5639  1.1  mrg 					 const1_rtx, const1_rtx,
   5640  1.1  mrg 					 const0_rtx, accvec, const1_rtx, const0_rtx,
   5641  1.1  mrg 					 GEN_INT (MACFLAG_NONE), accvec));
   5642  1.1  mrg 
   5643  1.1  mrg       return target;
   5644  1.1  mrg 
   5645  1.1  mrg     case BFIN_BUILTIN_CPLX_MAC_16:
   5646  1.1  mrg     case BFIN_BUILTIN_CPLX_MSU_16:
   5647  1.1  mrg     case BFIN_BUILTIN_CPLX_MAC_16_S40:
   5648  1.1  mrg     case BFIN_BUILTIN_CPLX_MSU_16_S40:
   5649  1.1  mrg       arg0 = CALL_EXPR_ARG (exp, 0);
   5650  1.1  mrg       arg1 = CALL_EXPR_ARG (exp, 1);
   5651  1.1  mrg       arg2 = CALL_EXPR_ARG (exp, 2);
   5652  1.1  mrg       op0 = expand_normal (arg0);
   5653  1.1  mrg       op1 = expand_normal (arg1);
   5654  1.1  mrg       op2 = expand_normal (arg2);
   5655  1.1  mrg       accvec = gen_reg_rtx (V2PDImode);
   5656  1.1  mrg       icode = CODE_FOR_flag_macv2hi_parts;
   5657  1.1  mrg       tmode = insn_data[icode].operand[0].mode;
   5658  1.1  mrg 
   5659  1.1  mrg       if (! target
   5660  1.1  mrg 	  || GET_MODE (target) != V2HImode
   5661  1.1  mrg 	  || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
   5662  1.1  mrg 	target = gen_reg_rtx (tmode);
   5663  1.1  mrg       if (! register_operand (op1, GET_MODE (op1)))
   5664  1.1  mrg 	op1 = copy_to_mode_reg (GET_MODE (op1), op1);
   5665  1.1  mrg       if (! register_operand (op2, GET_MODE (op2)))
   5666  1.1  mrg 	op2 = copy_to_mode_reg (GET_MODE (op2), op2);
   5667  1.1  mrg 
   5668  1.1  mrg       tmp1 = gen_reg_rtx (SImode);
   5669  1.1  mrg       tmp2 = gen_reg_rtx (SImode);
   5670  1.1  mrg       emit_insn (gen_ashlsi3 (tmp1, gen_lowpart (SImode, op0), GEN_INT (16)));
   5671  1.1  mrg       emit_move_insn (tmp2, gen_lowpart (SImode, op0));
   5672  1.1  mrg       emit_insn (gen_movstricthi_1 (gen_lowpart (HImode, tmp2), const0_rtx));
   5673  1.1  mrg       emit_insn (gen_load_accumulator_pair (accvec, tmp1, tmp2));
   5674  1.1  mrg       if (fcode == BFIN_BUILTIN_CPLX_MAC_16
   5675  1.1  mrg 	  || fcode == BFIN_BUILTIN_CPLX_MSU_16)
   5676  1.1  mrg 	emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx,
   5677  1.1  mrg 						   const0_rtx, const0_rtx,
   5678  1.1  mrg 						   const1_rtx, accvec, const0_rtx,
   5679  1.1  mrg 						   const0_rtx,
   5680  1.1  mrg 						   GEN_INT (MACFLAG_W32)));
   5681  1.1  mrg       else
   5682  1.1  mrg 	emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx,
   5683  1.1  mrg 						   const0_rtx, const0_rtx,
   5684  1.1  mrg 						   const1_rtx, accvec, const0_rtx,
   5685  1.1  mrg 						   const0_rtx,
   5686  1.1  mrg 						   GEN_INT (MACFLAG_NONE)));
   5687  1.1  mrg       if (fcode == BFIN_BUILTIN_CPLX_MAC_16
   5688  1.1  mrg 	  || fcode == BFIN_BUILTIN_CPLX_MAC_16_S40)
   5689  1.1  mrg 	{
   5690  1.1  mrg 	  tmp1 = const1_rtx;
   5691  1.1  mrg 	  tmp2 = const0_rtx;
   5692  1.1  mrg 	}
   5693  1.1  mrg       else
   5694  1.1  mrg 	{
   5695  1.1  mrg 	  tmp1 = const0_rtx;
   5696  1.1  mrg 	  tmp2 = const1_rtx;
   5697  1.1  mrg 	}
   5698  1.1  mrg       emit_insn (gen_flag_macv2hi_parts (target, op1, op2, const1_rtx,
   5699  1.1  mrg 					 const1_rtx, const1_rtx,
   5700  1.1  mrg 					 const0_rtx, accvec, tmp1, tmp2,
   5701  1.1  mrg 					 GEN_INT (MACFLAG_NONE), accvec));
   5702  1.1  mrg 
   5703  1.1  mrg       return target;
   5704  1.1  mrg 
   5705  1.1  mrg     case BFIN_BUILTIN_CPLX_SQU:
   5706  1.1  mrg       arg0 = CALL_EXPR_ARG (exp, 0);
   5707  1.1  mrg       op0 = expand_normal (arg0);
   5708  1.1  mrg       accvec = gen_reg_rtx (V2PDImode);
   5709  1.1  mrg       icode = CODE_FOR_flag_mulv2hi;
   5710  1.1  mrg       tmp1 = gen_reg_rtx (V2HImode);
   5711  1.1  mrg       tmp2 = gen_reg_rtx (V2HImode);
   5712  1.1  mrg 
   5713  1.1  mrg       if (! target
   5714  1.1  mrg 	  || GET_MODE (target) != V2HImode
   5715  1.1  mrg 	  || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
   5716  1.1  mrg 	target = gen_reg_rtx (V2HImode);
   5717  1.1  mrg       if (! register_operand (op0, GET_MODE (op0)))
   5718  1.1  mrg 	op0 = copy_to_mode_reg (GET_MODE (op0), op0);
   5719  1.1  mrg 
   5720  1.1  mrg       emit_insn (gen_flag_mulv2hi (tmp1, op0, op0, GEN_INT (MACFLAG_NONE)));
   5721  1.1  mrg 
   5722  1.1  mrg       emit_insn (gen_flag_mulhi_parts (gen_lowpart (HImode, tmp2), op0, op0,
   5723  1.1  mrg 				       const0_rtx, const1_rtx,
   5724  1.1  mrg 				       GEN_INT (MACFLAG_NONE)));
   5725  1.1  mrg 
   5726  1.1  mrg       emit_insn (gen_ssaddhi3_high_parts (target, tmp2, tmp2, tmp2, const0_rtx,
   5727  1.1  mrg 					  const0_rtx));
   5728  1.1  mrg       emit_insn (gen_sssubhi3_low_parts (target, target, tmp1, tmp1,
   5729  1.1  mrg 					 const0_rtx, const1_rtx));
   5730  1.1  mrg 
   5731  1.1  mrg       return target;
   5732  1.1  mrg 
   5733  1.1  mrg     default:
   5734  1.1  mrg       break;
   5735  1.1  mrg     }
   5736  1.1  mrg 
   5737  1.1  mrg   for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
   5738  1.1  mrg     if (d->code == fcode)
   5739  1.1  mrg       return bfin_expand_binop_builtin (d->icode, exp, target,
   5740  1.1  mrg 					d->macflag);
   5741  1.1  mrg 
   5742  1.1  mrg   for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
   5743  1.1  mrg     if (d->code == fcode)
   5744  1.1  mrg       return bfin_expand_unop_builtin (d->icode, exp, target);
   5745  1.1  mrg 
   5746  1.1  mrg   gcc_unreachable ();
   5747  1.1  mrg }
   5748  1.1  mrg 
   5749  1.1  mrg static void
   5750  1.1  mrg bfin_conditional_register_usage (void)
   5751  1.1  mrg {
   5752  1.1  mrg   /* initialize condition code flag register rtx */
   5753  1.1  mrg   bfin_cc_rtx = gen_rtx_REG (BImode, REG_CC);
   5754  1.1  mrg   bfin_rets_rtx = gen_rtx_REG (Pmode, REG_RETS);
   5755  1.1  mrg   if (TARGET_FDPIC)
   5756  1.1  mrg     call_used_regs[FDPIC_REGNO] = 1;
   5757  1.1  mrg   if (!TARGET_FDPIC && flag_pic)
   5758  1.1  mrg     {
   5759  1.1  mrg       fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
   5760  1.1  mrg       call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
   5761  1.1  mrg     }
   5762  1.1  mrg }
   5763  1.1  mrg 
   5764  1.1  mrg #undef TARGET_INIT_BUILTINS
   5766  1.1  mrg #define TARGET_INIT_BUILTINS bfin_init_builtins
   5767  1.1  mrg 
   5768  1.1  mrg #undef TARGET_EXPAND_BUILTIN
   5769  1.1  mrg #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
   5770  1.1  mrg 
   5771  1.1  mrg #undef TARGET_ASM_GLOBALIZE_LABEL
   5772  1.1  mrg #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label
   5773  1.1  mrg 
   5774  1.1  mrg #undef TARGET_ASM_FILE_START
   5775  1.1  mrg #define TARGET_ASM_FILE_START output_file_start
   5776  1.1  mrg 
   5777  1.1  mrg #undef TARGET_ATTRIBUTE_TABLE
   5778  1.1  mrg #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
   5779  1.1  mrg 
   5780  1.1  mrg #undef TARGET_COMP_TYPE_ATTRIBUTES
   5781  1.1  mrg #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
   5782  1.1  mrg 
   5783  1.1  mrg #undef TARGET_RTX_COSTS
   5784  1.1  mrg #define TARGET_RTX_COSTS bfin_rtx_costs
   5785  1.1  mrg 
   5786  1.1  mrg #undef  TARGET_ADDRESS_COST
   5787  1.1  mrg #define TARGET_ADDRESS_COST bfin_address_cost
   5788  1.1  mrg 
   5789  1.1  mrg #undef TARGET_REGISTER_MOVE_COST
   5790  1.1  mrg #define TARGET_REGISTER_MOVE_COST bfin_register_move_cost
   5791  1.1  mrg 
   5792  1.1  mrg #undef TARGET_MEMORY_MOVE_COST
   5793  1.1  mrg #define TARGET_MEMORY_MOVE_COST bfin_memory_move_cost
   5794  1.1  mrg 
   5795  1.1  mrg #undef  TARGET_ASM_INTEGER
   5796  1.1  mrg #define TARGET_ASM_INTEGER bfin_assemble_integer
   5797  1.1  mrg 
   5798  1.1  mrg #undef TARGET_MACHINE_DEPENDENT_REORG
   5799  1.1  mrg #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
   5800  1.1  mrg 
   5801  1.1  mrg #undef TARGET_FUNCTION_OK_FOR_SIBCALL
   5802  1.1  mrg #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
   5803  1.1  mrg 
   5804  1.1  mrg #undef TARGET_ASM_OUTPUT_MI_THUNK
   5805  1.1  mrg #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
   5806  1.1  mrg #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
   5807  1.1  mrg #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
   5808  1.1  mrg 
   5809  1.1  mrg #undef TARGET_SCHED_ADJUST_COST
   5810  1.1  mrg #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
   5811  1.1  mrg 
   5812  1.1  mrg #undef TARGET_SCHED_ISSUE_RATE
   5813  1.1  mrg #define TARGET_SCHED_ISSUE_RATE bfin_issue_rate
   5814  1.1  mrg 
   5815  1.1  mrg #undef TARGET_PROMOTE_FUNCTION_MODE
   5816  1.1  mrg #define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
   5817  1.1  mrg 
   5818  1.1  mrg #undef TARGET_ARG_PARTIAL_BYTES
   5819  1.1  mrg #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
   5820  1.1  mrg 
   5821  1.1  mrg #undef TARGET_FUNCTION_ARG
   5822  1.1  mrg #define TARGET_FUNCTION_ARG bfin_function_arg
   5823  1.1  mrg 
   5824  1.1  mrg #undef TARGET_FUNCTION_ARG_ADVANCE
   5825  1.1  mrg #define TARGET_FUNCTION_ARG_ADVANCE bfin_function_arg_advance
   5826  1.1  mrg 
   5827  1.1  mrg #undef TARGET_PASS_BY_REFERENCE
   5828  1.1  mrg #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
   5829  1.1  mrg 
   5830  1.1  mrg #undef TARGET_SETUP_INCOMING_VARARGS
   5831  1.1  mrg #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
   5832  1.1  mrg 
   5833  1.1  mrg #undef TARGET_STRUCT_VALUE_RTX
   5834  1.1  mrg #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
   5835  1.1  mrg 
   5836  1.1  mrg #undef TARGET_VECTOR_MODE_SUPPORTED_P
   5837  1.1  mrg #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
   5838  1.1  mrg 
   5839  1.1  mrg #undef TARGET_OPTION_OVERRIDE
   5840  1.1  mrg #define TARGET_OPTION_OVERRIDE bfin_option_override
   5841  1.1  mrg 
   5842  1.1  mrg #undef TARGET_SECONDARY_RELOAD
   5843  1.1  mrg #define TARGET_SECONDARY_RELOAD bfin_secondary_reload
   5844  1.1  mrg 
   5845  1.1  mrg #undef TARGET_CLASS_LIKELY_SPILLED_P
   5846  1.1  mrg #define TARGET_CLASS_LIKELY_SPILLED_P bfin_class_likely_spilled_p
   5847  1.1  mrg 
   5848  1.1  mrg #undef TARGET_DELEGITIMIZE_ADDRESS
   5849  1.1  mrg #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address
   5850  1.1  mrg 
   5851  1.1  mrg #undef TARGET_LEGITIMATE_CONSTANT_P
   5852  1.1  mrg #define TARGET_LEGITIMATE_CONSTANT_P bfin_legitimate_constant_p
   5853  1.1  mrg 
   5854  1.1  mrg #undef TARGET_CANNOT_FORCE_CONST_MEM
   5855  1.1  mrg #define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem
   5856  1.1  mrg 
   5857  1.1  mrg #undef TARGET_RETURN_IN_MEMORY
   5858  1.1  mrg #define TARGET_RETURN_IN_MEMORY bfin_return_in_memory
   5859  1.1  mrg 
   5860  1.1  mrg #undef TARGET_LRA_P
   5861  1.1  mrg #define TARGET_LRA_P hook_bool_void_false
   5862  1.1  mrg 
   5863  1.1  mrg #undef TARGET_LEGITIMATE_ADDRESS_P
   5864  1.1  mrg #define TARGET_LEGITIMATE_ADDRESS_P	bfin_legitimate_address_p
   5865  1.1  mrg 
   5866  1.1  mrg #undef TARGET_FRAME_POINTER_REQUIRED
   5867  1.1  mrg #define TARGET_FRAME_POINTER_REQUIRED bfin_frame_pointer_required
   5868  1.1  mrg 
   5869  1.1  mrg #undef TARGET_CAN_ELIMINATE
   5870  1.1  mrg #define TARGET_CAN_ELIMINATE bfin_can_eliminate
   5871  1.1  mrg 
   5872  1.1  mrg #undef TARGET_CONDITIONAL_REGISTER_USAGE
   5873  1.1  mrg #define TARGET_CONDITIONAL_REGISTER_USAGE bfin_conditional_register_usage
   5874  1.1  mrg 
   5875  1.1  mrg #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
   5876  1.1  mrg #define TARGET_ASM_TRAMPOLINE_TEMPLATE bfin_asm_trampoline_template
   5877  1.1  mrg #undef TARGET_TRAMPOLINE_INIT
   5878  1.1  mrg #define TARGET_TRAMPOLINE_INIT bfin_trampoline_init
   5879  1.1  mrg 
   5880  1.1  mrg #undef TARGET_EXTRA_LIVE_ON_ENTRY
   5881  1.1  mrg #define TARGET_EXTRA_LIVE_ON_ENTRY bfin_extra_live_on_entry
   5882  1.1  mrg 
   5883  1.1  mrg /* Passes after sched2 can break the helpful TImode annotations that
   5884  1.1  mrg    haifa-sched puts on every insn.  Just do scheduling in reorg.  */
   5885           #undef TARGET_DELAY_SCHED2
   5886           #define TARGET_DELAY_SCHED2 true
   5887           
   5888           /* Variable tracking should be run after all optimizations which
   5889              change order of insns.  It also needs a valid CFG.  */
   5890           #undef TARGET_DELAY_VARTRACK
   5891           #define TARGET_DELAY_VARTRACK true
   5892           
   5893           #undef TARGET_CAN_USE_DOLOOP_P
   5894           #define TARGET_CAN_USE_DOLOOP_P bfin_can_use_doloop_p
   5895           
   5896           #undef TARGET_HARD_REGNO_NREGS
   5897           #define TARGET_HARD_REGNO_NREGS bfin_hard_regno_nregs
   5898           #undef TARGET_HARD_REGNO_MODE_OK
   5899           #define TARGET_HARD_REGNO_MODE_OK bfin_hard_regno_mode_ok
   5900           
   5901           #undef TARGET_MODES_TIEABLE_P
   5902           #define TARGET_MODES_TIEABLE_P bfin_modes_tieable_p
   5903           
   5904           #undef TARGET_CONSTANT_ALIGNMENT
   5905           #define TARGET_CONSTANT_ALIGNMENT constant_alignment_word_strings
   5906           
   5907           struct gcc_target targetm = TARGET_INITIALIZER;
   5908