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