OSDN Git Service

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