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