OSDN Git Service

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