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