OSDN Git Service

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