OSDN Git Service

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