OSDN Git Service

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