OSDN Git Service

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