OSDN Git Service

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