OSDN Git Service

ac237d73bd2e5710528234387d9ede0b0614f054
[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 int
816 bfin_frame_pointer_required (void) 
817 {
818   e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
819
820   if (fkind != SUBROUTINE)
821     return 1;
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 1;
827
828   return 0;
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 bool
2899 bfin_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
2900 {
2901   switch (GET_CODE (x)) {
2902   case REG:
2903     if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM))
2904       return true;
2905     break;
2906   case PLUS:
2907     if (REG_P (XEXP (x, 0))
2908         && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS)
2909         && ((GET_CODE (XEXP (x, 1)) == UNSPEC && mode == SImode)
2910             || (GET_CODE (XEXP (x, 1)) == CONST_INT
2911                 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
2912       return true;
2913     break;
2914   case POST_INC:
2915   case POST_DEC:
2916     if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2917         && REG_P (XEXP (x, 0))
2918         && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC))
2919       return true;
2920   case PRE_DEC:
2921     if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2922         && XEXP (x, 0) == stack_pointer_rtx
2923         && REG_P (XEXP (x, 0))
2924         && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC))
2925       return true;
2926     break;
2927   default:
2928     break;
2929   }
2930   return false;
2931 }
2932
2933 /* Decide whether we can force certain constants to memory.  If we
2934    decide we can't, the caller should be able to cope with it in
2935    another way.  */
2936
2937 static bool
2938 bfin_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
2939 {
2940   /* We have only one class of non-legitimate constants, and our movsi
2941      expander knows how to handle them.  Dropping these constants into the
2942      data section would only shift the problem - we'd still get relocs
2943      outside the object, in the data section rather than the text section.  */
2944   return true;
2945 }
2946
2947 /* Ensure that for any constant of the form symbol + offset, the offset
2948    remains within the object.  Any other constants are ok.
2949    This ensures that flat binaries never have to deal with relocations
2950    crossing section boundaries.  */
2951
2952 bool
2953 bfin_legitimate_constant_p (rtx x)
2954 {
2955   rtx sym;
2956   HOST_WIDE_INT offset;
2957
2958   if (GET_CODE (x) != CONST)
2959     return true;
2960
2961   x = XEXP (x, 0);
2962   gcc_assert (GET_CODE (x) == PLUS);
2963
2964   sym = XEXP (x, 0);
2965   x = XEXP (x, 1);
2966   if (GET_CODE (sym) != SYMBOL_REF
2967       || GET_CODE (x) != CONST_INT)
2968     return true;
2969   offset = INTVAL (x);
2970
2971   if (SYMBOL_REF_DECL (sym) == 0)
2972     return true;
2973   if (offset < 0
2974       || offset >= int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (sym))))
2975     return false;
2976
2977   return true;
2978 }
2979
2980 static bool
2981 bfin_rtx_costs (rtx x, int code, int outer_code, int *total, bool speed)
2982 {
2983   int cost2 = COSTS_N_INSNS (1);
2984   rtx op0, op1;
2985
2986   switch (code)
2987     {
2988     case CONST_INT:
2989       if (outer_code == SET || outer_code == PLUS)
2990         *total = satisfies_constraint_Ks7 (x) ? 0 : cost2;
2991       else if (outer_code == AND)
2992         *total = log2constp (~INTVAL (x)) ? 0 : cost2;
2993       else if (outer_code == LE || outer_code == LT || outer_code == EQ)
2994         *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
2995       else if (outer_code == LEU || outer_code == LTU)
2996         *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
2997       else if (outer_code == MULT)
2998         *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
2999       else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
3000         *total = 0;
3001       else if (outer_code == ASHIFT || outer_code == ASHIFTRT
3002                || outer_code == LSHIFTRT)
3003         *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
3004       else if (outer_code == IOR || outer_code == XOR)
3005         *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
3006       else
3007         *total = cost2;
3008       return true;
3009
3010     case CONST:
3011     case LABEL_REF:
3012     case SYMBOL_REF:
3013     case CONST_DOUBLE:
3014       *total = COSTS_N_INSNS (2);
3015       return true;
3016
3017     case PLUS:
3018       op0 = XEXP (x, 0);
3019       op1 = XEXP (x, 1);
3020       if (GET_MODE (x) == SImode)
3021         {
3022           if (GET_CODE (op0) == MULT
3023               && GET_CODE (XEXP (op0, 1)) == CONST_INT)
3024             {
3025               HOST_WIDE_INT val = INTVAL (XEXP (op0, 1));
3026               if (val == 2 || val == 4)
3027                 {
3028                   *total = cost2;
3029                   *total += rtx_cost (XEXP (op0, 0), outer_code, speed);
3030                   *total += rtx_cost (op1, outer_code, speed);
3031                   return true;
3032                 }
3033             }
3034           *total = cost2;
3035           if (GET_CODE (op0) != REG
3036               && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3037             *total += rtx_cost (op0, SET, speed);
3038 #if 0 /* We'd like to do this for accuracy, but it biases the loop optimizer
3039          towards creating too many induction variables.  */
3040           if (!reg_or_7bit_operand (op1, SImode))
3041             *total += rtx_cost (op1, SET, speed);
3042 #endif
3043         }
3044       else if (GET_MODE (x) == DImode)
3045         {
3046           *total = 6 * cost2;
3047           if (GET_CODE (op1) != CONST_INT
3048               || !satisfies_constraint_Ks7 (op1))
3049             *total += rtx_cost (op1, PLUS, speed);
3050           if (GET_CODE (op0) != REG
3051               && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3052             *total += rtx_cost (op0, PLUS, speed);
3053         }
3054       return true;
3055
3056     case MINUS:
3057       if (GET_MODE (x) == DImode)
3058         *total = 6 * cost2;
3059       else
3060         *total = cost2;
3061       return true;
3062       
3063     case ASHIFT: 
3064     case ASHIFTRT:
3065     case LSHIFTRT:
3066       if (GET_MODE (x) == DImode)
3067         *total = 6 * cost2;
3068       else
3069         *total = cost2;
3070
3071       op0 = XEXP (x, 0);
3072       op1 = XEXP (x, 1);
3073       if (GET_CODE (op0) != REG
3074           && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3075         *total += rtx_cost (op0, code, speed);
3076
3077       return true;
3078           
3079     case IOR:
3080     case AND:
3081     case XOR:
3082       op0 = XEXP (x, 0);
3083       op1 = XEXP (x, 1);
3084
3085       /* Handle special cases of IOR: rotates, ALIGN insns, movstricthi_high.  */
3086       if (code == IOR)
3087         {
3088           if ((GET_CODE (op0) == LSHIFTRT && GET_CODE (op1) == ASHIFT)
3089               || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == ZERO_EXTEND)
3090               || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT)
3091               || (GET_CODE (op0) == AND && GET_CODE (op1) == CONST_INT))
3092             {
3093               *total = cost2;
3094               return true;
3095             }
3096         }
3097
3098       if (GET_CODE (op0) != REG
3099           && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3100         *total += rtx_cost (op0, code, speed);
3101
3102       if (GET_MODE (x) == DImode)
3103         {
3104           *total = 2 * cost2;
3105           return true;
3106         }
3107       *total = cost2;
3108       if (GET_MODE (x) != SImode)
3109         return true;
3110
3111       if (code == AND)
3112         {
3113           if (! rhs_andsi3_operand (XEXP (x, 1), SImode))
3114             *total += rtx_cost (XEXP (x, 1), code, speed);
3115         }
3116       else
3117         {
3118           if (! regorlog2_operand (XEXP (x, 1), SImode))
3119             *total += rtx_cost (XEXP (x, 1), code, speed);
3120         }
3121
3122       return true;
3123
3124     case ZERO_EXTRACT:
3125     case SIGN_EXTRACT:
3126       if (outer_code == SET
3127           && XEXP (x, 1) == const1_rtx
3128           && GET_CODE (XEXP (x, 2)) == CONST_INT)
3129         {
3130           *total = 2 * cost2;
3131           return true;
3132         }
3133       /* fall through */
3134
3135     case SIGN_EXTEND:
3136     case ZERO_EXTEND:
3137       *total = cost2;
3138       return true;
3139
3140     case MULT:
3141         {
3142           op0 = XEXP (x, 0);
3143           op1 = XEXP (x, 1);
3144           if (GET_CODE (op0) == GET_CODE (op1)
3145               && (GET_CODE (op0) == ZERO_EXTEND
3146                   || GET_CODE (op0) == SIGN_EXTEND))
3147             {
3148               *total = COSTS_N_INSNS (1);
3149               op0 = XEXP (op0, 0);
3150               op1 = XEXP (op1, 0);
3151             }
3152           else if (!speed)
3153             *total = COSTS_N_INSNS (1);
3154           else
3155             *total = COSTS_N_INSNS (3);
3156
3157           if (GET_CODE (op0) != REG
3158               && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3159             *total += rtx_cost (op0, MULT, speed);
3160           if (GET_CODE (op1) != REG
3161               && (GET_CODE (op1) != SUBREG || GET_CODE (SUBREG_REG (op1)) != REG))
3162             *total += rtx_cost (op1, MULT, speed);
3163         }
3164       return true;
3165
3166     case UDIV:
3167     case UMOD:
3168       *total = COSTS_N_INSNS (32);
3169       return true;
3170
3171     case VEC_CONCAT:
3172     case VEC_SELECT:
3173       if (outer_code == SET)
3174         *total = cost2;
3175       return true;
3176
3177     default:
3178       return false;
3179     }
3180 }
3181 \f
3182 /* Used for communication between {push,pop}_multiple_operation (which
3183    we use not only as a predicate) and the corresponding output functions.  */
3184 static int first_preg_to_save, first_dreg_to_save;
3185 static int n_regs_to_save;
3186
3187 int
3188 push_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
3189 {
3190   int lastdreg = 8, lastpreg = 6;
3191   int i, group;
3192
3193   first_preg_to_save = lastpreg;
3194   first_dreg_to_save = lastdreg;
3195   for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
3196     {
3197       rtx t = XVECEXP (op, 0, i);
3198       rtx src, dest;
3199       int regno;
3200
3201       if (GET_CODE (t) != SET)
3202         return 0;
3203
3204       src = SET_SRC (t);
3205       dest = SET_DEST (t);
3206       if (GET_CODE (dest) != MEM || ! REG_P (src))
3207         return 0;
3208       dest = XEXP (dest, 0);
3209       if (GET_CODE (dest) != PLUS
3210           || ! REG_P (XEXP (dest, 0))
3211           || REGNO (XEXP (dest, 0)) != REG_SP
3212           || GET_CODE (XEXP (dest, 1)) != CONST_INT
3213           || INTVAL (XEXP (dest, 1)) != -i * 4)
3214         return 0;
3215
3216       regno = REGNO (src);
3217       if (group == 0)
3218         {
3219           if (D_REGNO_P (regno))
3220             {
3221               group = 1;
3222               first_dreg_to_save = lastdreg = regno - REG_R0;
3223             }
3224           else if (regno >= REG_P0 && regno <= REG_P7)
3225             {
3226               group = 2;
3227               first_preg_to_save = lastpreg = regno - REG_P0;
3228             }
3229           else
3230             return 0;
3231
3232           continue;
3233         }
3234
3235       if (group == 1)
3236         {
3237           if (regno >= REG_P0 && regno <= REG_P7)
3238             {
3239               group = 2;
3240               first_preg_to_save = lastpreg = regno - REG_P0;
3241             }
3242           else if (regno != REG_R0 + lastdreg + 1)
3243             return 0;
3244           else
3245             lastdreg++;
3246         }
3247       else if (group == 2)
3248         {
3249           if (regno != REG_P0 + lastpreg + 1)
3250             return 0;
3251           lastpreg++;
3252         }
3253     }
3254   n_regs_to_save = 8 - first_dreg_to_save + 6 - first_preg_to_save;
3255   return 1;
3256 }
3257
3258 int
3259 pop_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
3260 {
3261   int lastdreg = 8, lastpreg = 6;
3262   int i, group;
3263
3264   for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
3265     {
3266       rtx t = XVECEXP (op, 0, i);
3267       rtx src, dest;
3268       int regno;
3269
3270       if (GET_CODE (t) != SET)
3271         return 0;
3272
3273       src = SET_SRC (t);
3274       dest = SET_DEST (t);
3275       if (GET_CODE (src) != MEM || ! REG_P (dest))
3276         return 0;
3277       src = XEXP (src, 0);
3278
3279       if (i == 1)
3280         {
3281           if (! REG_P (src) || REGNO (src) != REG_SP)
3282             return 0;
3283         }
3284       else if (GET_CODE (src) != PLUS
3285                || ! REG_P (XEXP (src, 0))
3286                || REGNO (XEXP (src, 0)) != REG_SP
3287                || GET_CODE (XEXP (src, 1)) != CONST_INT
3288                || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
3289         return 0;
3290
3291       regno = REGNO (dest);
3292       if (group == 0)
3293         {
3294           if (regno == REG_R7)
3295             {
3296               group = 1;
3297               lastdreg = 7;
3298             }
3299           else if (regno != REG_P0 + lastpreg - 1)
3300             return 0;
3301           else
3302             lastpreg--;
3303         }
3304       else if (group == 1)
3305         {
3306           if (regno != REG_R0 + lastdreg - 1)
3307             return 0;
3308           else
3309             lastdreg--;
3310         }
3311     }
3312   first_dreg_to_save = lastdreg;
3313   first_preg_to_save = lastpreg;
3314   n_regs_to_save = 8 - first_dreg_to_save + 6 - first_preg_to_save;
3315   return 1;
3316 }
3317
3318 /* Emit assembly code for one multi-register push described by INSN, with
3319    operands in OPERANDS.  */
3320
3321 void
3322 output_push_multiple (rtx insn, rtx *operands)
3323 {
3324   char buf[80];
3325   int ok;
3326   
3327   /* Validate the insn again, and compute first_[dp]reg_to_save. */
3328   ok = push_multiple_operation (PATTERN (insn), VOIDmode);
3329   gcc_assert (ok);
3330   
3331   if (first_dreg_to_save == 8)
3332     sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
3333   else if (first_preg_to_save == 6)
3334     sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
3335   else
3336     sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
3337              first_dreg_to_save, first_preg_to_save);
3338
3339   output_asm_insn (buf, operands);
3340 }
3341
3342 /* Emit assembly code for one multi-register pop described by INSN, with
3343    operands in OPERANDS.  */
3344
3345 void
3346 output_pop_multiple (rtx insn, rtx *operands)
3347 {
3348   char buf[80];
3349   int ok;
3350   
3351   /* Validate the insn again, and compute first_[dp]reg_to_save. */
3352   ok = pop_multiple_operation (PATTERN (insn), VOIDmode);
3353   gcc_assert (ok);
3354
3355   if (first_dreg_to_save == 8)
3356     sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
3357   else if (first_preg_to_save == 6)
3358     sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
3359   else
3360     sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
3361              first_dreg_to_save, first_preg_to_save);
3362
3363   output_asm_insn (buf, operands);
3364 }
3365
3366 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE.  */
3367
3368 static void
3369 single_move_for_movmem (rtx dst, rtx src, enum machine_mode mode, HOST_WIDE_INT offset)
3370 {
3371   rtx scratch = gen_reg_rtx (mode);
3372   rtx srcmem, dstmem;
3373
3374   srcmem = adjust_address_nv (src, mode, offset);
3375   dstmem = adjust_address_nv (dst, mode, offset);
3376   emit_move_insn (scratch, srcmem);
3377   emit_move_insn (dstmem, scratch);
3378 }
3379
3380 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
3381    alignment ALIGN_EXP.  Return true if successful, false if we should fall
3382    back on a different method.  */
3383
3384 bool
3385 bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
3386 {
3387   rtx srcreg, destreg, countreg;
3388   HOST_WIDE_INT align = 0;
3389   unsigned HOST_WIDE_INT count = 0;
3390
3391   if (GET_CODE (align_exp) == CONST_INT)
3392     align = INTVAL (align_exp);
3393   if (GET_CODE (count_exp) == CONST_INT)
3394     {
3395       count = INTVAL (count_exp);
3396 #if 0
3397       if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
3398         return false;
3399 #endif
3400     }
3401
3402   /* If optimizing for size, only do single copies inline.  */
3403   if (optimize_size)
3404     {
3405       if (count == 2 && align < 2)
3406         return false;
3407       if (count == 4 && align < 4)
3408         return false;
3409       if (count != 1 && count != 2 && count != 4)
3410         return false;
3411     }
3412   if (align < 2 && count != 1)
3413     return false;
3414
3415   destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
3416   if (destreg != XEXP (dst, 0))
3417     dst = replace_equiv_address_nv (dst, destreg);
3418   srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
3419   if (srcreg != XEXP (src, 0))
3420     src = replace_equiv_address_nv (src, srcreg);
3421
3422   if (count != 0 && align >= 2)
3423     {
3424       unsigned HOST_WIDE_INT offset = 0;
3425
3426       if (align >= 4)
3427         {
3428           if ((count & ~3) == 4)
3429             {
3430               single_move_for_movmem (dst, src, SImode, offset);
3431               offset = 4;
3432             }
3433           else if (count & ~3)
3434             {
3435               HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
3436               countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3437
3438               emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
3439               cfun->machine->has_loopreg_clobber = true;
3440             }
3441           if (count & 2)
3442             {
3443               single_move_for_movmem (dst, src, HImode, offset);
3444               offset += 2;
3445             }
3446         }
3447       else
3448         {
3449           if ((count & ~1) == 2)
3450             {
3451               single_move_for_movmem (dst, src, HImode, offset);
3452               offset = 2;
3453             }
3454           else if (count & ~1)
3455             {
3456               HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
3457               countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3458
3459               emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
3460               cfun->machine->has_loopreg_clobber = true;
3461             }
3462         }
3463       if (count & 1)
3464         {
3465           single_move_for_movmem (dst, src, QImode, offset);
3466         }
3467       return true;
3468     }
3469   return false;
3470 }
3471 \f
3472 /* Compute the alignment for a local variable.
3473    TYPE is the data type, and ALIGN is the alignment that
3474    the object would ordinarily have.  The value of this macro is used
3475    instead of that alignment to align the object.  */
3476
3477 int
3478 bfin_local_alignment (tree type, int align)
3479 {
3480   /* Increasing alignment for (relatively) big types allows the builtin
3481      memcpy can use 32 bit loads/stores.  */
3482   if (TYPE_SIZE (type)
3483       && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
3484       && (TREE_INT_CST_LOW (TYPE_SIZE (type)) > 8
3485           || TREE_INT_CST_HIGH (TYPE_SIZE (type))) && align < 32)
3486     return 32;
3487   return align;
3488 }
3489 \f
3490 /* Implement TARGET_SCHED_ISSUE_RATE.  */
3491
3492 static int
3493 bfin_issue_rate (void)
3494 {
3495   return 3;
3496 }
3497
3498 static int
3499 bfin_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
3500 {
3501   enum attr_type insn_type, dep_insn_type;
3502   int dep_insn_code_number;
3503
3504   /* Anti and output dependencies have zero cost.  */
3505   if (REG_NOTE_KIND (link) != 0)
3506     return 0;
3507
3508   dep_insn_code_number = recog_memoized (dep_insn);
3509
3510   /* If we can't recognize the insns, we can't really do anything.  */
3511   if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
3512     return cost;
3513
3514   insn_type = get_attr_type (insn);
3515   dep_insn_type = get_attr_type (dep_insn);
3516
3517   if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)
3518     {
3519       rtx pat = PATTERN (dep_insn);
3520       if (GET_CODE (pat) == PARALLEL)
3521         pat = XVECEXP (pat, 0, 0);
3522       rtx dest = SET_DEST (pat);
3523       rtx src = SET_SRC (pat);
3524       if (! ADDRESS_REGNO_P (REGNO (dest))
3525           || ! (MEM_P (src) || D_REGNO_P (REGNO (src))))
3526         return cost;
3527       return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);
3528     }
3529
3530   return cost;
3531 }
3532 \f
3533 /* This function acts like NEXT_INSN, but is aware of three-insn bundles and
3534    skips all subsequent parallel instructions if INSN is the start of such
3535    a group.  */
3536 static rtx
3537 find_next_insn_start (rtx insn)
3538 {
3539   if (GET_MODE (insn) == SImode)
3540     {
3541       while (GET_MODE (insn) != QImode)
3542         insn = NEXT_INSN (insn);
3543     }
3544   return NEXT_INSN (insn);
3545 }
3546
3547 /* This function acts like PREV_INSN, but is aware of three-insn bundles and
3548    skips all subsequent parallel instructions if INSN is the start of such
3549    a group.  */
3550 static rtx
3551 find_prev_insn_start (rtx insn)
3552 {
3553   insn = PREV_INSN (insn);
3554   gcc_assert (GET_MODE (insn) != SImode);
3555   if (GET_MODE (insn) == QImode)
3556     {
3557       while (GET_MODE (PREV_INSN (insn)) == SImode)
3558         insn = PREV_INSN (insn);
3559     }
3560   return insn;
3561 }
3562 \f
3563 /* Increment the counter for the number of loop instructions in the
3564    current function.  */
3565
3566 void
3567 bfin_hardware_loop (void)
3568 {
3569   cfun->machine->has_hardware_loops++;
3570 }
3571
3572 /* Maximum loop nesting depth.  */
3573 #define MAX_LOOP_DEPTH 2
3574
3575 /* Maximum size of a loop.  */
3576 #define MAX_LOOP_LENGTH 2042
3577
3578 /* Maximum distance of the LSETUP instruction from the loop start.  */
3579 #define MAX_LSETUP_DISTANCE 30
3580
3581 /* We need to keep a vector of loops */
3582 typedef struct loop_info *loop_info;
3583 DEF_VEC_P (loop_info);
3584 DEF_VEC_ALLOC_P (loop_info,heap);
3585
3586 /* Information about a loop we have found (or are in the process of
3587    finding).  */
3588 struct GTY (()) loop_info
3589 {
3590   /* loop number, for dumps */
3591   int loop_no;
3592
3593   /* All edges that jump into and out of the loop.  */
3594   VEC(edge,gc) *incoming;
3595
3596   /* We can handle two cases: all incoming edges have the same destination
3597      block, or all incoming edges have the same source block.  These two
3598      members are set to the common source or destination we found, or NULL
3599      if different blocks were found.  If both are NULL the loop can't be
3600      optimized.  */
3601   basic_block incoming_src;
3602   basic_block incoming_dest;
3603
3604   /* First block in the loop.  This is the one branched to by the loop_end
3605      insn.  */
3606   basic_block head;
3607
3608   /* Last block in the loop (the one with the loop_end insn).  */
3609   basic_block tail;
3610
3611   /* The successor block of the loop.  This is the one the loop_end insn
3612      falls into.  */
3613   basic_block successor;
3614
3615   /* The last instruction in the tail.  */
3616   rtx last_insn;
3617
3618   /* The loop_end insn.  */
3619   rtx loop_end;
3620
3621   /* The iteration register.  */
3622   rtx iter_reg;
3623
3624   /* The new label placed at the beginning of the loop. */
3625   rtx start_label;
3626
3627   /* The new label placed at the end of the loop. */
3628   rtx end_label;
3629
3630   /* The length of the loop.  */
3631   int length;
3632
3633   /* The nesting depth of the loop.  */
3634   int depth;
3635
3636   /* Nonzero if we can't optimize this loop.  */
3637   int bad;
3638
3639   /* True if we have visited this loop.  */
3640   int visited;
3641
3642   /* True if this loop body clobbers any of LC0, LT0, or LB0.  */
3643   int clobber_loop0;
3644
3645   /* True if this loop body clobbers any of LC1, LT1, or LB1.  */
3646   int clobber_loop1;
3647
3648   /* Next loop in the graph. */
3649   struct loop_info *next;
3650
3651   /* Immediate outer loop of this loop.  */
3652   struct loop_info *outer;
3653
3654   /* Vector of blocks only within the loop, including those within
3655      inner loops.  */
3656   VEC (basic_block,heap) *blocks;
3657
3658   /* Same information in a bitmap.  */
3659   bitmap block_bitmap;
3660
3661   /* Vector of inner loops within this loop  */
3662   VEC (loop_info,heap) *loops;
3663 };
3664
3665 static void
3666 bfin_dump_loops (loop_info loops)
3667 {
3668   loop_info loop;
3669
3670   for (loop = loops; loop; loop = loop->next)
3671     {
3672       loop_info i;
3673       basic_block b;
3674       unsigned ix;
3675
3676       fprintf (dump_file, ";; loop %d: ", loop->loop_no);
3677       if (loop->bad)
3678         fprintf (dump_file, "(bad) ");
3679       fprintf (dump_file, "{head:%d, depth:%d}", loop->head->index, loop->depth);
3680
3681       fprintf (dump_file, " blocks: [ ");
3682       for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, b); ix++)
3683         fprintf (dump_file, "%d ", b->index);
3684       fprintf (dump_file, "] ");
3685
3686       fprintf (dump_file, " inner loops: [ ");
3687       for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, i); ix++)
3688         fprintf (dump_file, "%d ", i->loop_no);
3689       fprintf (dump_file, "]\n");
3690     }
3691   fprintf (dump_file, "\n");
3692 }
3693
3694 /* Scan the blocks of LOOP (and its inferiors) looking for basic block
3695    BB. Return true, if we find it.  */
3696
3697 static bool
3698 bfin_bb_in_loop (loop_info loop, basic_block bb)
3699 {
3700   return bitmap_bit_p (loop->block_bitmap, bb->index);
3701 }
3702
3703 /* Scan the blocks of LOOP (and its inferiors) looking for uses of
3704    REG.  Return true, if we find any.  Don't count the loop's loop_end
3705    insn if it matches LOOP_END.  */
3706
3707 static bool
3708 bfin_scan_loop (loop_info loop, rtx reg, rtx loop_end)
3709 {
3710   unsigned ix;
3711   basic_block bb;
3712
3713   for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
3714     {
3715       rtx insn;
3716
3717       for (insn = BB_HEAD (bb);
3718            insn != NEXT_INSN (BB_END (bb));
3719            insn = NEXT_INSN (insn))
3720         {
3721           if (!INSN_P (insn))
3722             continue;
3723           if (insn == loop_end)
3724             continue;
3725           if (reg_mentioned_p (reg, PATTERN (insn)))
3726             return true;
3727         }
3728     }
3729   return false;
3730 }
3731
3732 /* Estimate the length of INSN conservatively.  */
3733
3734 static int
3735 length_for_loop (rtx insn)
3736 {
3737   int length = 0;
3738   if (JUMP_P (insn) && any_condjump_p (insn) && !optimize_size)
3739     {
3740       if (ENABLE_WA_SPECULATIVE_SYNCS)
3741         length = 8;
3742       else if (ENABLE_WA_SPECULATIVE_LOADS)
3743         length = 6;
3744     }
3745   else if (LABEL_P (insn))
3746     {
3747       if (ENABLE_WA_SPECULATIVE_SYNCS)
3748         length = 4;
3749     }
3750
3751   if (INSN_P (insn))
3752     length += get_attr_length (insn);
3753
3754   return length;
3755 }
3756
3757 /* Optimize LOOP.  */
3758
3759 static void
3760 bfin_optimize_loop (loop_info loop)
3761 {
3762   basic_block bb;
3763   loop_info inner;
3764   rtx insn, last_insn;
3765   rtx loop_init, start_label, end_label;
3766   rtx reg_lc0, reg_lc1, reg_lt0, reg_lt1, reg_lb0, reg_lb1;
3767   rtx iter_reg, scratchreg, scratch_init, scratch_init_insn;
3768   rtx lc_reg, lt_reg, lb_reg;
3769   rtx seq, seq_end;
3770   int length;
3771   unsigned ix;
3772   int inner_depth = 0;
3773
3774   if (loop->visited)
3775     return;
3776
3777   loop->visited = 1;
3778
3779   if (loop->bad)
3780     {
3781       if (dump_file)
3782         fprintf (dump_file, ";; loop %d bad when found\n", loop->loop_no);
3783       goto bad_loop;
3784     }
3785
3786   /* Every loop contains in its list of inner loops every loop nested inside
3787      it, even if there are intermediate loops.  This works because we're doing
3788      a depth-first search here and never visit a loop more than once.  */
3789   for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, inner); ix++)
3790     {
3791       bfin_optimize_loop (inner);
3792
3793       if (!inner->bad && inner_depth < inner->depth)
3794         {
3795           inner_depth = inner->depth;
3796
3797           loop->clobber_loop0 |= inner->clobber_loop0;
3798           loop->clobber_loop1 |= inner->clobber_loop1;
3799         }
3800     }
3801
3802   loop->depth = inner_depth + 1;
3803   if (loop->depth > MAX_LOOP_DEPTH)
3804     {
3805       if (dump_file)
3806         fprintf (dump_file, ";; loop %d too deep\n", loop->loop_no);
3807       goto bad_loop;
3808     }
3809
3810   /* Get the loop iteration register.  */
3811   iter_reg = loop->iter_reg;
3812
3813   if (!REG_P (iter_reg))
3814     {
3815       if (dump_file)
3816         fprintf (dump_file, ";; loop %d iteration count not in a register\n",
3817                  loop->loop_no);
3818       goto bad_loop;
3819     }
3820   scratchreg = NULL_RTX;
3821   scratch_init = iter_reg;
3822   scratch_init_insn = NULL_RTX;
3823   if (!PREG_P (iter_reg) && loop->incoming_src)
3824     {
3825       basic_block bb_in = loop->incoming_src;
3826       int i;
3827       for (i = REG_P0; i <= REG_P5; i++)
3828         if ((df_regs_ever_live_p (i)
3829              || (funkind (TREE_TYPE (current_function_decl)) == SUBROUTINE
3830                  && call_used_regs[i]))
3831             && !REGNO_REG_SET_P (df_get_live_out (bb_in), i))
3832           {
3833             scratchreg = gen_rtx_REG (SImode, i);
3834             break;
3835           }
3836       for (insn = BB_END (bb_in); insn != BB_HEAD (bb_in);
3837            insn = PREV_INSN (insn))
3838         {
3839           rtx set;
3840           if (NOTE_P (insn) || BARRIER_P (insn))
3841             continue;
3842           set = single_set (insn);
3843           if (set && rtx_equal_p (SET_DEST (set), iter_reg))
3844             {
3845               if (CONSTANT_P (SET_SRC (set)))
3846                 {
3847                   scratch_init = SET_SRC (set);
3848                   scratch_init_insn = insn;
3849                 }
3850               break;
3851             }
3852           else if (reg_mentioned_p (iter_reg, PATTERN (insn)))
3853             break;
3854         }
3855     }
3856
3857   if (loop->incoming_src)
3858     {
3859       /* Make sure the predecessor is before the loop start label, as required by
3860          the LSETUP instruction.  */
3861       length = 0;
3862       insn = BB_END (loop->incoming_src);
3863       /* If we have to insert the LSETUP before a jump, count that jump in the
3864          length.  */
3865       if (VEC_length (edge, loop->incoming) > 1
3866           || !(VEC_last (edge, loop->incoming)->flags & EDGE_FALLTHRU))
3867         {
3868           gcc_assert (JUMP_P (insn));
3869           insn = PREV_INSN (insn);
3870         }
3871
3872       for (; insn && insn != loop->start_label; insn = NEXT_INSN (insn))
3873         length += length_for_loop (insn);
3874
3875       if (!insn)
3876         {
3877           if (dump_file)
3878             fprintf (dump_file, ";; loop %d lsetup not before loop_start\n",
3879                      loop->loop_no);
3880           goto bad_loop;
3881         }
3882
3883       /* Account for the pop of a scratch register where necessary.  */
3884       if (!PREG_P (iter_reg) && scratchreg == NULL_RTX
3885           && ENABLE_WA_LOAD_LCREGS)
3886         length += 2;
3887
3888       if (length > MAX_LSETUP_DISTANCE)
3889         {
3890           if (dump_file)
3891             fprintf (dump_file, ";; loop %d lsetup too far away\n", loop->loop_no);
3892           goto bad_loop;
3893         }
3894     }
3895
3896   /* Check if start_label appears before loop_end and calculate the
3897      offset between them.  We calculate the length of instructions
3898      conservatively.  */
3899   length = 0;
3900   for (insn = loop->start_label;
3901        insn && insn != loop->loop_end;
3902        insn = NEXT_INSN (insn))
3903     length += length_for_loop (insn);
3904
3905   if (!insn)
3906     {
3907       if (dump_file)
3908         fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
3909                  loop->loop_no);
3910       goto bad_loop;
3911     }
3912
3913   loop->length = length;
3914   if (loop->length > MAX_LOOP_LENGTH)
3915     {
3916       if (dump_file)
3917         fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
3918       goto bad_loop;
3919     }
3920
3921   /* Scan all the blocks to make sure they don't use iter_reg.  */
3922   if (bfin_scan_loop (loop, iter_reg, loop->loop_end))
3923     {
3924       if (dump_file)
3925         fprintf (dump_file, ";; loop %d uses iterator\n", loop->loop_no);
3926       goto bad_loop;
3927     }
3928
3929   /* Scan all the insns to see if the loop body clobber
3930      any hardware loop registers. */
3931
3932   reg_lc0 = gen_rtx_REG (SImode, REG_LC0);
3933   reg_lc1 = gen_rtx_REG (SImode, REG_LC1);
3934   reg_lt0 = gen_rtx_REG (SImode, REG_LT0);
3935   reg_lt1 = gen_rtx_REG (SImode, REG_LT1);
3936   reg_lb0 = gen_rtx_REG (SImode, REG_LB0);
3937   reg_lb1 = gen_rtx_REG (SImode, REG_LB1);
3938
3939   for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
3940     {
3941       rtx insn;
3942
3943       for (insn = BB_HEAD (bb);
3944            insn != NEXT_INSN (BB_END (bb));
3945            insn = NEXT_INSN (insn))
3946         {
3947           if (!INSN_P (insn))
3948             continue;
3949
3950           if (reg_set_p (reg_lc0, insn)
3951               || reg_set_p (reg_lt0, insn)
3952               || reg_set_p (reg_lb0, insn))
3953             loop->clobber_loop0 = 1;
3954           
3955           if (reg_set_p (reg_lc1, insn)
3956               || reg_set_p (reg_lt1, insn)
3957               || reg_set_p (reg_lb1, insn))
3958             loop->clobber_loop1 |= 1;
3959         }
3960     }
3961
3962   if ((loop->clobber_loop0 && loop->clobber_loop1)
3963       || (loop->depth == MAX_LOOP_DEPTH && loop->clobber_loop0))
3964     {
3965       loop->depth = MAX_LOOP_DEPTH + 1;
3966       if (dump_file)
3967         fprintf (dump_file, ";; loop %d no loop reg available\n",
3968                  loop->loop_no);
3969       goto bad_loop;
3970     }
3971
3972   /* There should be an instruction before the loop_end instruction
3973      in the same basic block. And the instruction must not be
3974      - JUMP
3975      - CONDITIONAL BRANCH
3976      - CALL
3977      - CSYNC
3978      - SSYNC
3979      - Returns (RTS, RTN, etc.)  */
3980
3981   bb = loop->tail;
3982   last_insn = find_prev_insn_start (loop->loop_end);
3983
3984   while (1)
3985     {
3986       for (; last_insn != BB_HEAD (bb);
3987            last_insn = find_prev_insn_start (last_insn))
3988         if (INSN_P (last_insn))
3989           break;
3990
3991       if (last_insn != BB_HEAD (bb))
3992         break;
3993
3994       if (single_pred_p (bb)
3995           && single_pred_edge (bb)->flags & EDGE_FALLTHRU
3996           && single_pred (bb) != ENTRY_BLOCK_PTR)
3997         {
3998           bb = single_pred (bb);
3999           last_insn = BB_END (bb);
4000           continue;
4001         }
4002       else
4003         {
4004           last_insn = NULL_RTX;
4005           break;
4006         }
4007     }
4008
4009   if (!last_insn)
4010     {
4011       if (dump_file)
4012         fprintf (dump_file, ";; loop %d has no last instruction\n",
4013                  loop->loop_no);
4014       goto bad_loop;
4015     }
4016
4017   if (JUMP_P (last_insn) && !any_condjump_p (last_insn))
4018     {
4019       if (dump_file)
4020         fprintf (dump_file, ";; loop %d has bad last instruction\n",
4021                  loop->loop_no);
4022       goto bad_loop;
4023     }
4024   /* In all other cases, try to replace a bad last insn with a nop.  */
4025   else if (JUMP_P (last_insn)
4026            || CALL_P (last_insn)
4027            || get_attr_type (last_insn) == TYPE_SYNC
4028            || get_attr_type (last_insn) == TYPE_CALL
4029            || get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI
4030            || recog_memoized (last_insn) == CODE_FOR_return_internal
4031            || GET_CODE (PATTERN (last_insn)) == ASM_INPUT
4032            || asm_noperands (PATTERN (last_insn)) >= 0)
4033     {
4034       if (loop->length + 2 > MAX_LOOP_LENGTH)
4035         {
4036           if (dump_file)
4037             fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
4038           goto bad_loop;
4039         }
4040       if (dump_file)
4041         fprintf (dump_file, ";; loop %d has bad last insn; replace with nop\n",
4042                  loop->loop_no);
4043
4044       last_insn = emit_insn_after (gen_forced_nop (), last_insn);
4045     }
4046
4047   loop->last_insn = last_insn;
4048
4049   /* The loop is good for replacement.  */
4050   start_label = loop->start_label;
4051   end_label = gen_label_rtx ();
4052   iter_reg = loop->iter_reg;
4053
4054   if (loop->depth == 1 && !loop->clobber_loop1)
4055     {
4056       lc_reg = reg_lc1;
4057       lt_reg = reg_lt1;
4058       lb_reg = reg_lb1;
4059       loop->clobber_loop1 = 1;
4060     }
4061   else
4062     {
4063       lc_reg = reg_lc0;
4064       lt_reg = reg_lt0;
4065       lb_reg = reg_lb0;
4066       loop->clobber_loop0 = 1;
4067     }
4068
4069   loop->end_label = end_label;
4070
4071   /* Create a sequence containing the loop setup.  */
4072   start_sequence ();
4073
4074   /* LSETUP only accepts P registers.  If we have one, we can use it,
4075      otherwise there are several ways of working around the problem.
4076      If we're not affected by anomaly 312, we can load the LC register
4077      from any iteration register, and use LSETUP without initialization.
4078      If we've found a P scratch register that's not live here, we can
4079      instead copy the iter_reg into that and use an initializing LSETUP.
4080      If all else fails, push and pop P0 and use it as a scratch.  */
4081   if (P_REGNO_P (REGNO (iter_reg)))
4082     {
4083       loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
4084                                             lb_reg, end_label,
4085                                             lc_reg, iter_reg);
4086       seq_end = emit_insn (loop_init);
4087     }
4088   else if (!ENABLE_WA_LOAD_LCREGS && DPREG_P (iter_reg))
4089     {
4090       emit_insn (gen_movsi (lc_reg, iter_reg));
4091       loop_init = gen_lsetup_without_autoinit (lt_reg, start_label,
4092                                                lb_reg, end_label,
4093                                                lc_reg);
4094       seq_end = emit_insn (loop_init);
4095     }
4096   else if (scratchreg != NULL_RTX)
4097     {
4098       emit_insn (gen_movsi (scratchreg, scratch_init));
4099       loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
4100                                             lb_reg, end_label,
4101                                             lc_reg, scratchreg);
4102       seq_end = emit_insn (loop_init);
4103       if (scratch_init_insn != NULL_RTX)
4104         delete_insn (scratch_init_insn);
4105     }
4106   else
4107     {
4108       rtx p0reg = gen_rtx_REG (SImode, REG_P0);
4109       rtx push = gen_frame_mem (SImode,
4110                                 gen_rtx_PRE_DEC (SImode, stack_pointer_rtx));
4111       rtx pop = gen_frame_mem (SImode,
4112                                gen_rtx_POST_INC (SImode, stack_pointer_rtx));
4113       emit_insn (gen_movsi (push, p0reg));
4114       emit_insn (gen_movsi (p0reg, scratch_init));
4115       loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
4116                                             lb_reg, end_label,
4117                                             lc_reg, p0reg);
4118       emit_insn (loop_init);
4119       seq_end = emit_insn (gen_movsi (p0reg, pop));
4120       if (scratch_init_insn != NULL_RTX)
4121         delete_insn (scratch_init_insn);
4122     }
4123
4124   if (dump_file)
4125     {
4126       fprintf (dump_file, ";; replacing loop %d initializer with\n",
4127                loop->loop_no);
4128       print_rtl_single (dump_file, loop_init);
4129       fprintf (dump_file, ";; replacing loop %d terminator with\n",
4130                loop->loop_no);
4131       print_rtl_single (dump_file, loop->loop_end);
4132     }
4133
4134   /* If the loop isn't entered at the top, also create a jump to the entry
4135      point.  */
4136   if (!loop->incoming_src && loop->head != loop->incoming_dest)
4137     {
4138       rtx label = BB_HEAD (loop->incoming_dest);
4139       /* If we're jumping to the final basic block in the loop, and there's
4140          only one cheap instruction before the end (typically an increment of
4141          an induction variable), we can just emit a copy here instead of a
4142          jump.  */
4143       if (loop->incoming_dest == loop->tail
4144           && next_real_insn (label) == last_insn
4145           && asm_noperands (last_insn) < 0
4146           && GET_CODE (PATTERN (last_insn)) == SET)
4147         {
4148           seq_end = emit_insn (copy_rtx (PATTERN (last_insn)));
4149         }
4150       else
4151         seq_end = emit_jump_insn (gen_jump (label));
4152     }
4153
4154   seq = get_insns ();
4155   end_sequence ();
4156
4157   if (loop->incoming_src)
4158     {
4159       rtx prev = BB_END (loop->incoming_src);
4160       if (VEC_length (edge, loop->incoming) > 1
4161           || !(VEC_last (edge, loop->incoming)->flags & EDGE_FALLTHRU))
4162         {
4163           gcc_assert (JUMP_P (prev));
4164           prev = PREV_INSN (prev);
4165         }
4166       emit_insn_after (seq, prev);
4167     }
4168   else
4169     {
4170       basic_block new_bb;
4171       edge e;
4172       edge_iterator ei;
4173
4174 #ifdef ENABLE_CHECKING
4175       if (loop->head != loop->incoming_dest)
4176         {
4177           /* We aren't entering the loop at the top.  Since we've established
4178              that the loop is entered only at one point, this means there
4179              can't be fallthru edges into the head.  Any such fallthru edges
4180              would become invalid when we insert the new block, so verify
4181              that this does not in fact happen.  */
4182           FOR_EACH_EDGE (e, ei, loop->head->preds)
4183             gcc_assert (!(e->flags & EDGE_FALLTHRU));
4184         }
4185 #endif
4186
4187       emit_insn_before (seq, BB_HEAD (loop->head));
4188       seq = emit_label_before (gen_label_rtx (), seq);
4189
4190       new_bb = create_basic_block (seq, seq_end, loop->head->prev_bb);
4191       FOR_EACH_EDGE (e, ei, loop->incoming)
4192         {
4193           if (!(e->flags & EDGE_FALLTHRU)
4194               || e->dest != loop->head)
4195             redirect_edge_and_branch_force (e, new_bb);
4196           else
4197             redirect_edge_succ (e, new_bb);
4198         }
4199     }
4200
4201   delete_insn (loop->loop_end);
4202   /* Insert the loop end label before the last instruction of the loop.  */
4203   emit_label_before (loop->end_label, loop->last_insn);
4204
4205   return;
4206
4207  bad_loop:
4208
4209   if (dump_file)
4210     fprintf (dump_file, ";; loop %d is bad\n", loop->loop_no);
4211
4212   loop->bad = 1;
4213
4214   if (DPREG_P (loop->iter_reg))
4215     {
4216       /* If loop->iter_reg is a DREG or PREG, we can split it here
4217          without scratch register.  */
4218       rtx insn, test;
4219
4220       emit_insn_before (gen_addsi3 (loop->iter_reg,
4221                                     loop->iter_reg,
4222                                     constm1_rtx),
4223                         loop->loop_end);
4224
4225       test = gen_rtx_NE (VOIDmode, loop->iter_reg, const0_rtx);
4226       insn = emit_jump_insn_before (gen_cbranchsi4 (test,
4227                                                     loop->iter_reg, const0_rtx,
4228                                                     loop->start_label),
4229                                     loop->loop_end);
4230
4231       JUMP_LABEL (insn) = loop->start_label;
4232       LABEL_NUSES (loop->start_label)++;
4233       delete_insn (loop->loop_end);
4234     }
4235 }
4236
4237 /* Called from bfin_reorg_loops when a potential loop end is found.  LOOP is
4238    a newly set up structure describing the loop, it is this function's
4239    responsibility to fill most of it.  TAIL_BB and TAIL_INSN point to the
4240    loop_end insn and its enclosing basic block.  */
4241
4242 static void
4243 bfin_discover_loop (loop_info loop, basic_block tail_bb, rtx tail_insn)
4244 {
4245   unsigned dwork = 0;
4246   basic_block bb;
4247   VEC (basic_block,heap) *works = VEC_alloc (basic_block,heap,20);
4248
4249   loop->tail = tail_bb;
4250   loop->head = BRANCH_EDGE (tail_bb)->dest;
4251   loop->successor = FALLTHRU_EDGE (tail_bb)->dest;
4252   loop->loop_end = tail_insn;
4253   loop->last_insn = NULL_RTX;
4254   loop->iter_reg = SET_DEST (XVECEXP (PATTERN (tail_insn), 0, 1));
4255   loop->depth = loop->length = 0;
4256   loop->visited = 0;
4257   loop->clobber_loop0 = loop->clobber_loop1 = 0;
4258   loop->outer = NULL;
4259   loop->loops = NULL;
4260   loop->incoming = VEC_alloc (edge, gc, 2);
4261   loop->start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (tail_insn), 0, 0)), 1), 0);
4262   loop->end_label = NULL_RTX;
4263   loop->bad = 0;
4264
4265   VEC_safe_push (basic_block, heap, works, loop->head);
4266
4267   while (VEC_iterate (basic_block, works, dwork++, bb))
4268     {
4269       edge e;
4270       edge_iterator ei;
4271       if (bb == EXIT_BLOCK_PTR)
4272         {
4273           /* We've reached the exit block.  The loop must be bad. */
4274           if (dump_file)
4275             fprintf (dump_file,
4276                      ";; Loop is bad - reached exit block while scanning\n");
4277           loop->bad = 1;
4278           break;
4279         }
4280
4281       if (bitmap_bit_p (loop->block_bitmap, bb->index))
4282         continue;
4283
4284       /* We've not seen this block before.  Add it to the loop's
4285          list and then add each successor to the work list.  */
4286
4287       VEC_safe_push (basic_block, heap, loop->blocks, bb);
4288       bitmap_set_bit (loop->block_bitmap, bb->index);
4289
4290       if (bb != tail_bb)
4291         {
4292           FOR_EACH_EDGE (e, ei, bb->succs)
4293             {
4294               basic_block succ = EDGE_SUCC (bb, ei.index)->dest;
4295               if (!REGNO_REG_SET_P (df_get_live_in (succ),
4296                                     REGNO (loop->iter_reg)))
4297                 continue;
4298               if (!VEC_space (basic_block, works, 1))
4299                 {
4300                   if (dwork)
4301                     {
4302                       VEC_block_remove (basic_block, works, 0, dwork);
4303                       dwork = 0;
4304                     }
4305                   else
4306                     VEC_reserve (basic_block, heap, works, 1);
4307                 }
4308               VEC_quick_push (basic_block, works, succ);
4309             }
4310         }
4311     }
4312
4313   /* Find the predecessor, and make sure nothing else jumps into this loop.  */
4314   if (!loop->bad)
4315     {
4316       int pass, retry;
4317       for (dwork = 0; VEC_iterate (basic_block, loop->blocks, dwork, bb); dwork++)
4318         {
4319           edge e;
4320           edge_iterator ei;
4321           FOR_EACH_EDGE (e, ei, bb->preds)
4322             {
4323               basic_block pred = e->src;
4324
4325               if (!bfin_bb_in_loop (loop, pred))
4326                 {
4327                   if (dump_file)
4328                     fprintf (dump_file, ";; Loop %d: incoming edge %d -> %d\n",
4329                              loop->loop_no, pred->index,
4330                              e->dest->index);
4331                   VEC_safe_push (edge, gc, loop->incoming, e);
4332                 }
4333             }
4334         }
4335
4336       for (pass = 0, retry = 1; retry && pass < 2; pass++)
4337         {
4338           edge e;
4339           edge_iterator ei;
4340           bool first = true;
4341           retry = 0;
4342
4343           FOR_EACH_EDGE (e, ei, loop->incoming)
4344             {
4345               if (first)
4346                 {
4347                   loop->incoming_src = e->src;
4348                   loop->incoming_dest = e->dest;
4349                   first = false;
4350                 }
4351               else
4352                 {
4353                   if (e->dest != loop->incoming_dest)
4354                     loop->incoming_dest = NULL;
4355                   if (e->src != loop->incoming_src)
4356                     loop->incoming_src = NULL;
4357                 }
4358               if (loop->incoming_src == NULL && loop->incoming_dest == NULL)
4359                 {
4360                   if (pass == 0)
4361                     {
4362                       if (dump_file)
4363                         fprintf (dump_file,
4364                                  ";; retrying loop %d with forwarder blocks\n",
4365                                  loop->loop_no);
4366                       retry = 1;
4367                       break;
4368                     }
4369                   loop->bad = 1;
4370                   if (dump_file)
4371                     fprintf (dump_file,
4372                              ";; can't find suitable entry for loop %d\n",
4373                              loop->loop_no);
4374                   goto out;
4375                 }
4376             }
4377           if (retry)
4378             {
4379               retry = 0;
4380               FOR_EACH_EDGE (e, ei, loop->incoming)
4381                 {
4382                   if (forwarder_block_p (e->src))
4383                     {
4384                       edge e2;
4385                       edge_iterator ei2;
4386
4387                       if (dump_file)
4388                         fprintf (dump_file,
4389                                  ";; Adding forwarder block %d to loop %d and retrying\n",
4390                                  e->src->index, loop->loop_no);
4391                       VEC_safe_push (basic_block, heap, loop->blocks, e->src);
4392                       bitmap_set_bit (loop->block_bitmap, e->src->index);
4393                       FOR_EACH_EDGE (e2, ei2, e->src->preds)
4394                         VEC_safe_push (edge, gc, loop->incoming, e2);
4395                       VEC_unordered_remove (edge, loop->incoming, ei.index);
4396                       retry = 1;
4397                       break;
4398                     }
4399                 }
4400               if (!retry)
4401                 {
4402                   if (dump_file)
4403                     fprintf (dump_file, ";; No forwarder blocks found\n");
4404                   loop->bad = 1;
4405                 }
4406             }
4407         }
4408     }
4409
4410  out:
4411   VEC_free (basic_block, heap, works);
4412 }
4413
4414 /* Analyze the structure of the loops in the current function.  Use STACK
4415    for bitmap allocations.  Returns all the valid candidates for hardware
4416    loops found in this function.  */
4417 static loop_info
4418 bfin_discover_loops (bitmap_obstack *stack, FILE *dump_file)
4419 {
4420   loop_info loops = NULL;
4421   loop_info loop;
4422   basic_block bb;
4423   bitmap tmp_bitmap;
4424   int nloops = 0;
4425
4426   /* Find all the possible loop tails.  This means searching for every
4427      loop_end instruction.  For each one found, create a loop_info
4428      structure and add the head block to the work list. */
4429   FOR_EACH_BB (bb)
4430     {
4431       rtx tail = BB_END (bb);
4432
4433       while (GET_CODE (tail) == NOTE)
4434         tail = PREV_INSN (tail);
4435
4436       bb->aux = NULL;
4437
4438       if (INSN_P (tail) && recog_memoized (tail) == CODE_FOR_loop_end)
4439         {
4440           rtx insn;
4441           /* A possible loop end */
4442
4443           /* There's a degenerate case we can handle - an empty loop consisting
4444              of only a back branch.  Handle that by deleting the branch.  */
4445           insn = BB_HEAD (BRANCH_EDGE (bb)->dest);
4446           if (next_real_insn (insn) == tail)
4447             {
4448               if (dump_file)
4449                 {
4450                   fprintf (dump_file, ";; degenerate loop ending at\n");
4451                   print_rtl_single (dump_file, tail);
4452                 }
4453               delete_insn_and_edges (tail);
4454               continue;
4455             }
4456
4457           loop = XNEW (struct loop_info);
4458           loop->next = loops;
4459           loops = loop;
4460           loop->loop_no = nloops++;
4461           loop->blocks = VEC_alloc (basic_block, heap, 20);
4462           loop->block_bitmap = BITMAP_ALLOC (stack);
4463           bb->aux = loop;
4464
4465           if (dump_file)
4466             {
4467               fprintf (dump_file, ";; potential loop %d ending at\n",
4468                        loop->loop_no);
4469               print_rtl_single (dump_file, tail);
4470             }
4471
4472           bfin_discover_loop (loop, bb, tail);
4473         }
4474     }
4475
4476   tmp_bitmap = BITMAP_ALLOC (stack);
4477   /* Compute loop nestings.  */
4478   for (loop = loops; loop; loop = loop->next)
4479     {
4480       loop_info other;
4481       if (loop->bad)
4482         continue;
4483
4484       for (other = loop->next; other; other = other->next)
4485         {
4486           if (other->bad)
4487             continue;
4488
4489           bitmap_and (tmp_bitmap, other->block_bitmap, loop->block_bitmap);
4490           if (bitmap_empty_p (tmp_bitmap))
4491             continue;
4492           if (bitmap_equal_p (tmp_bitmap, other->block_bitmap))
4493             {
4494               other->outer = loop;
4495               VEC_safe_push (loop_info, heap, loop->loops, other);
4496             }
4497           else if (bitmap_equal_p (tmp_bitmap, loop->block_bitmap))
4498             {
4499               loop->outer = other;
4500               VEC_safe_push (loop_info, heap, other->loops, loop);
4501             }
4502           else
4503             {
4504               if (dump_file)
4505                 fprintf (dump_file,
4506                          ";; can't find suitable nesting for loops %d and %d\n",
4507                          loop->loop_no, other->loop_no);
4508               loop->bad = other->bad = 1;
4509             }
4510         }
4511     }
4512   BITMAP_FREE (tmp_bitmap);
4513
4514   return loops;
4515 }
4516
4517 /* Free up the loop structures in LOOPS.  */
4518 static void
4519 free_loops (loop_info loops)
4520 {
4521   while (loops)
4522     {
4523       loop_info loop = loops;
4524       loops = loop->next;
4525       VEC_free (loop_info, heap, loop->loops);
4526       VEC_free (basic_block, heap, loop->blocks);
4527       BITMAP_FREE (loop->block_bitmap);
4528       XDELETE (loop);
4529     }
4530 }
4531
4532 #define BB_AUX_INDEX(BB) ((unsigned)(BB)->aux)
4533
4534 /* The taken-branch edge from the loop end can actually go forward.  Since the
4535    Blackfin's LSETUP instruction requires that the loop end be after the loop
4536    start, try to reorder a loop's basic blocks when we find such a case.  */
4537 static void
4538 bfin_reorder_loops (loop_info loops, FILE *dump_file)
4539 {
4540   basic_block bb;
4541   loop_info loop;
4542
4543   FOR_EACH_BB (bb)
4544     bb->aux = NULL;
4545   cfg_layout_initialize (0);
4546
4547   for (loop = loops; loop; loop = loop->next)
4548     {
4549       unsigned index;
4550       basic_block bb;
4551       edge e;
4552       edge_iterator ei;
4553
4554       if (loop->bad)
4555         continue;
4556
4557       /* Recreate an index for basic blocks that represents their order.  */
4558       for (bb = ENTRY_BLOCK_PTR->next_bb, index = 0;
4559            bb != EXIT_BLOCK_PTR;
4560            bb = bb->next_bb, index++)
4561         bb->aux = (PTR) index;
4562
4563       if (BB_AUX_INDEX (loop->head) < BB_AUX_INDEX (loop->tail))
4564         continue;
4565
4566       FOR_EACH_EDGE (e, ei, loop->head->succs)
4567         {
4568           if (bitmap_bit_p (loop->block_bitmap, e->dest->index)
4569               && BB_AUX_INDEX (e->dest) < BB_AUX_INDEX (loop->tail))
4570             {
4571               basic_block start_bb = e->dest;
4572               basic_block start_prev_bb = start_bb->prev_bb;
4573
4574               if (dump_file)
4575                 fprintf (dump_file, ";; Moving block %d before block %d\n",
4576                          loop->head->index, start_bb->index);
4577               loop->head->prev_bb->next_bb = loop->head->next_bb;
4578               loop->head->next_bb->prev_bb = loop->head->prev_bb;
4579
4580               loop->head->prev_bb = start_prev_bb;
4581               loop->head->next_bb = start_bb;
4582               start_prev_bb->next_bb = start_bb->prev_bb = loop->head;
4583               break;
4584             }
4585         }
4586       loops = loops->next;
4587     }
4588   
4589   FOR_EACH_BB (bb)
4590     {
4591       if (bb->next_bb != EXIT_BLOCK_PTR)
4592         bb->aux = bb->next_bb;
4593       else
4594         bb->aux = NULL;
4595     }
4596   cfg_layout_finalize ();
4597   df_analyze ();
4598 }
4599
4600 /* Run from machine_dependent_reorg, this pass looks for doloop_end insns
4601    and tries to rewrite the RTL of these loops so that proper Blackfin
4602    hardware loops are generated.  */
4603
4604 static void
4605 bfin_reorg_loops (FILE *dump_file)
4606 {
4607   loop_info loops = NULL;
4608   loop_info loop;
4609   basic_block bb;
4610   bitmap_obstack stack;
4611
4612   bitmap_obstack_initialize (&stack);
4613
4614   if (dump_file)
4615     fprintf (dump_file, ";; Find loops, first pass\n\n");
4616
4617   loops = bfin_discover_loops (&stack, dump_file);
4618
4619   if (dump_file)
4620     bfin_dump_loops (loops);
4621
4622   bfin_reorder_loops (loops, dump_file);
4623   free_loops (loops);
4624
4625   if (dump_file)
4626     fprintf (dump_file, ";; Find loops, second pass\n\n");
4627
4628   loops = bfin_discover_loops (&stack, dump_file);
4629   if (dump_file)
4630     {
4631       fprintf (dump_file, ";; All loops found:\n\n");
4632       bfin_dump_loops (loops);
4633     }
4634
4635   /* Now apply the optimizations.  */
4636   for (loop = loops; loop; loop = loop->next)
4637     bfin_optimize_loop (loop);
4638
4639   if (dump_file)
4640     {
4641       fprintf (dump_file, ";; After hardware loops optimization:\n\n");
4642       bfin_dump_loops (loops);
4643     }
4644
4645   free_loops (loops);
4646
4647   if (dump_file)
4648     print_rtl (dump_file, get_insns ());
4649
4650   FOR_EACH_BB (bb)
4651     bb->aux = NULL;
4652
4653   splitting_loops = 1;
4654   FOR_EACH_BB (bb)
4655     {
4656       rtx insn = BB_END (bb);
4657       if (!JUMP_P (insn))
4658         continue;
4659
4660       try_split (PATTERN (insn), insn, 1);
4661     }
4662   splitting_loops = 0;
4663 }
4664 \f
4665 /* Possibly generate a SEQUENCE out of three insns found in SLOT.
4666    Returns true if we modified the insn chain, false otherwise.  */
4667 static bool
4668 gen_one_bundle (rtx slot[3])
4669 {
4670   gcc_assert (slot[1] != NULL_RTX);
4671
4672   /* Don't add extra NOPs if optimizing for size.  */
4673   if (optimize_size
4674       && (slot[0] == NULL_RTX || slot[2] == NULL_RTX))
4675     return false;
4676
4677   /* Verify that we really can do the multi-issue.  */
4678   if (slot[0])
4679     {
4680       rtx t = NEXT_INSN (slot[0]);
4681       while (t != slot[1])
4682         {
4683           if (GET_CODE (t) != NOTE
4684               || NOTE_KIND (t) != NOTE_INSN_DELETED)
4685             return false;
4686           t = NEXT_INSN (t);
4687         }
4688     }
4689   if (slot[2])
4690     {
4691       rtx t = NEXT_INSN (slot[1]);
4692       while (t != slot[2])
4693         {
4694           if (GET_CODE (t) != NOTE
4695               || NOTE_KIND (t) != NOTE_INSN_DELETED)
4696             return false;
4697           t = NEXT_INSN (t);
4698         }
4699     }
4700
4701   if (slot[0] == NULL_RTX)
4702     {
4703       slot[0] = emit_insn_before (gen_mnop (), slot[1]);
4704       df_insn_rescan (slot[0]);
4705     }
4706   if (slot[2] == NULL_RTX)
4707     {
4708       slot[2] = emit_insn_after (gen_forced_nop (), slot[1]);
4709       df_insn_rescan (slot[2]);
4710     }
4711
4712   /* Avoid line number information being printed inside one bundle.  */
4713   if (INSN_LOCATOR (slot[1])
4714       && INSN_LOCATOR (slot[1]) != INSN_LOCATOR (slot[0]))
4715     INSN_LOCATOR (slot[1]) = INSN_LOCATOR (slot[0]);
4716   if (INSN_LOCATOR (slot[2])
4717       && INSN_LOCATOR (slot[2]) != INSN_LOCATOR (slot[0]))
4718     INSN_LOCATOR (slot[2]) = INSN_LOCATOR (slot[0]);
4719
4720   /* Terminate them with "|| " instead of ";" in the output.  */
4721   PUT_MODE (slot[0], SImode);
4722   PUT_MODE (slot[1], SImode);
4723   /* Terminate the bundle, for the benefit of reorder_var_tracking_notes.  */
4724   PUT_MODE (slot[2], QImode);
4725   return true;
4726 }
4727
4728 /* Go through all insns, and use the information generated during scheduling
4729    to generate SEQUENCEs to represent bundles of instructions issued
4730    simultaneously.  */
4731
4732 static void
4733 bfin_gen_bundles (void)
4734 {
4735   basic_block bb;
4736   FOR_EACH_BB (bb)
4737     {
4738       rtx insn, next;
4739       rtx slot[3];
4740       int n_filled = 0;
4741
4742       slot[0] = slot[1] = slot[2] = NULL_RTX;
4743       for (insn = BB_HEAD (bb);; insn = next)
4744         {
4745           int at_end;
4746           if (INSN_P (insn))
4747             {
4748               if (get_attr_type (insn) == TYPE_DSP32)
4749                 slot[0] = insn;
4750               else if (slot[1] == NULL_RTX)
4751                 slot[1] = insn;
4752               else
4753                 slot[2] = insn;
4754               n_filled++;
4755             }
4756
4757           next = NEXT_INSN (insn);
4758           while (next && insn != BB_END (bb)
4759                  && !(INSN_P (next)
4760                       && GET_CODE (PATTERN (next)) != USE
4761                       && GET_CODE (PATTERN (next)) != CLOBBER))
4762             {
4763               insn = next;
4764               next = NEXT_INSN (insn);
4765             }
4766
4767           /* BB_END can change due to emitting extra NOPs, so check here.  */
4768           at_end = insn == BB_END (bb);
4769           if (at_end || GET_MODE (next) == TImode)
4770             {
4771               if ((n_filled < 2
4772                    || !gen_one_bundle (slot))
4773                   && slot[0] != NULL_RTX)
4774                 {
4775                   rtx pat = PATTERN (slot[0]);
4776                   if (GET_CODE (pat) == SET
4777                       && GET_CODE (SET_SRC (pat)) == UNSPEC
4778                       && XINT (SET_SRC (pat), 1) == UNSPEC_32BIT)
4779                     {
4780                       SET_SRC (pat) = XVECEXP (SET_SRC (pat), 0, 0);
4781                       INSN_CODE (slot[0]) = -1;
4782                       df_insn_rescan (slot[0]);
4783                     }
4784                 }
4785               n_filled = 0;
4786               slot[0] = slot[1] = slot[2] = NULL_RTX;
4787             }
4788           if (at_end)
4789             break;
4790         }
4791     }
4792 }
4793
4794 /* Ensure that no var tracking notes are emitted in the middle of a
4795    three-instruction bundle.  */
4796
4797 static void
4798 reorder_var_tracking_notes (void)
4799 {
4800   basic_block bb;
4801   FOR_EACH_BB (bb)
4802     {
4803       rtx insn, next;
4804       rtx queue = NULL_RTX;
4805       bool in_bundle = false;
4806
4807       for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = next)
4808         {
4809           next = NEXT_INSN (insn);
4810
4811           if (INSN_P (insn))
4812             {
4813               /* Emit queued up notes at the last instruction of a bundle.  */
4814               if (GET_MODE (insn) == QImode)
4815                 {
4816                   while (queue)
4817                     {
4818                       rtx next_queue = PREV_INSN (queue);
4819                       PREV_INSN (NEXT_INSN (insn)) = queue;
4820                       NEXT_INSN (queue) = NEXT_INSN (insn);
4821                       NEXT_INSN (insn) = queue;
4822                       PREV_INSN (queue) = insn;
4823                       queue = next_queue;
4824                     }
4825                   in_bundle = false;
4826                 }
4827               else if (GET_MODE (insn) == SImode)
4828                 in_bundle = true;
4829             }
4830           else if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION)
4831             {
4832               if (in_bundle)
4833                 {
4834                   rtx prev = PREV_INSN (insn);
4835                   PREV_INSN (next) = prev;
4836                   NEXT_INSN (prev) = next;
4837
4838                   PREV_INSN (insn) = queue;
4839                   queue = insn;
4840                 }
4841             }
4842         }
4843     }
4844 }
4845 \f
4846 /* On some silicon revisions, functions shorter than a certain number of cycles
4847    can cause unpredictable behaviour.  Work around this by adding NOPs as
4848    needed.  */
4849 static void
4850 workaround_rts_anomaly (void)
4851 {
4852   rtx insn, first_insn = NULL_RTX;
4853   int cycles = 4;
4854
4855   if (! ENABLE_WA_RETS)
4856     return;
4857
4858   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4859     {
4860       rtx pat;
4861
4862       if (BARRIER_P (insn))
4863         return;
4864       
4865       if (NOTE_P (insn) || LABEL_P (insn))
4866         continue;
4867
4868       if (first_insn == NULL_RTX)
4869         first_insn = insn;
4870       pat = PATTERN (insn);
4871       if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4872           || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
4873           || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
4874         continue;
4875
4876       if (CALL_P (insn))
4877         return;
4878
4879       if (JUMP_P (insn))
4880         {
4881           if (recog_memoized (insn) == CODE_FOR_return_internal)
4882             break;
4883
4884           /* Nothing to worry about for direct jumps.  */
4885           if (!any_condjump_p (insn))
4886             return;
4887           if (cycles <= 1)
4888             return;
4889           cycles--;
4890         }
4891       else if (INSN_P (insn))
4892         {
4893           rtx pat = PATTERN (insn);
4894           int this_cycles = 1;
4895
4896           if (GET_CODE (pat) == PARALLEL)
4897             {
4898               if (push_multiple_operation (pat, VOIDmode)
4899                   || pop_multiple_operation (pat, VOIDmode))
4900                 this_cycles = n_regs_to_save;
4901             }
4902           else
4903             {
4904               enum insn_code icode = recog_memoized (insn);
4905               if (icode == CODE_FOR_link)
4906                 this_cycles = 4;
4907               else if (icode == CODE_FOR_unlink)
4908                 this_cycles = 3;
4909               else if (icode == CODE_FOR_mulsi3)
4910                 this_cycles = 5;
4911             }
4912           if (this_cycles >= cycles)
4913             return;
4914
4915           cycles -= this_cycles;
4916         }
4917     }
4918   while (cycles > 0)
4919     {
4920       emit_insn_before (gen_nop (), first_insn);
4921       cycles--;
4922     }
4923 }
4924
4925 /* Return an insn type for INSN that can be used by the caller for anomaly
4926    workarounds.  This differs from plain get_attr_type in that it handles
4927    SEQUENCEs.  */
4928
4929 static enum attr_type
4930 type_for_anomaly (rtx insn)
4931 {
4932   rtx pat = PATTERN (insn);
4933   if (GET_CODE (pat) == SEQUENCE)
4934     {
4935       enum attr_type t;
4936       t = get_attr_type (XVECEXP (pat, 0, 1));
4937       if (t == TYPE_MCLD)
4938         return t;
4939       t = get_attr_type (XVECEXP (pat, 0, 2));
4940       if (t == TYPE_MCLD)
4941         return t;
4942       return TYPE_MCST;
4943     }
4944   else
4945     return get_attr_type (insn);
4946 }
4947
4948 /* Return nonzero if INSN contains any loads that may trap.  It handles
4949    SEQUENCEs correctly.  */
4950
4951 static bool
4952 trapping_loads_p (rtx insn)
4953 {
4954   rtx pat = PATTERN (insn);
4955   if (GET_CODE (pat) == SEQUENCE)
4956     {
4957       enum attr_type t;
4958       t = get_attr_type (XVECEXP (pat, 0, 1));
4959       if (t == TYPE_MCLD
4960           && may_trap_p (SET_SRC (PATTERN (XVECEXP (pat, 0, 1)))))
4961         return true;
4962       t = get_attr_type (XVECEXP (pat, 0, 2));
4963       if (t == TYPE_MCLD
4964           && may_trap_p (SET_SRC (PATTERN (XVECEXP (pat, 0, 2)))))
4965         return true;
4966       return false;
4967     }
4968   else
4969     return may_trap_p (SET_SRC (single_set (insn)));
4970 }
4971
4972 /* Return INSN if it is of TYPE_MCLD.  Alternatively, if INSN is the start of
4973    a three-insn bundle, see if one of them is a load and return that if so.
4974    Return NULL_RTX if the insn does not contain loads.  */
4975 static rtx
4976 find_load (rtx insn)
4977 {
4978   if (get_attr_type (insn) == TYPE_MCLD)
4979     return insn;
4980   if (GET_MODE (insn) != SImode)
4981     return NULL_RTX;
4982   do {
4983     insn = NEXT_INSN (insn);
4984     if ((GET_MODE (insn) == SImode || GET_MODE (insn) == QImode)
4985         && get_attr_type (insn) == TYPE_MCLD)
4986       return insn;
4987   } while (GET_MODE (insn) != QImode);
4988   return NULL_RTX;
4989 }
4990
4991 /* Determine whether PAT is an indirect call pattern.  */
4992 static bool
4993 indirect_call_p (rtx pat)
4994 {
4995   if (GET_CODE (pat) == PARALLEL)
4996     pat = XVECEXP (pat, 0, 0);
4997   if (GET_CODE (pat) == SET)
4998     pat = SET_SRC (pat);
4999   gcc_assert (GET_CODE (pat) == CALL);
5000   pat = XEXP (pat, 0);
5001   gcc_assert (GET_CODE (pat) == MEM);
5002   pat = XEXP (pat, 0);
5003   
5004   return REG_P (pat);
5005 }
5006
5007 static void
5008 workaround_speculation (void)
5009 {
5010   rtx insn, next;
5011   rtx last_condjump = NULL_RTX;
5012   int cycles_since_jump = INT_MAX;
5013   int delay_added = 0;
5014
5015   if (! ENABLE_WA_SPECULATIVE_LOADS && ! ENABLE_WA_SPECULATIVE_SYNCS
5016       && ! ENABLE_WA_INDIRECT_CALLS)
5017     return;
5018
5019   /* First pass: find predicted-false branches; if something after them
5020      needs nops, insert them or change the branch to predict true.  */
5021   for (insn = get_insns (); insn; insn = next)
5022     {
5023       rtx pat;
5024       int delay_needed = 0;
5025
5026       next = find_next_insn_start (insn);
5027       
5028       if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
5029         continue;
5030
5031       pat = PATTERN (insn);
5032       if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
5033           || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
5034           || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
5035         continue;
5036
5037       if (JUMP_P (insn))
5038         {
5039           if (any_condjump_p (insn)
5040               && ! cbranch_predicted_taken_p (insn))
5041             {
5042               last_condjump = insn;
5043               delay_added = 0;
5044               cycles_since_jump = 0;
5045             }
5046           else
5047             cycles_since_jump = INT_MAX;
5048         }
5049       else if (CALL_P (insn))
5050         {
5051           if (cycles_since_jump < INT_MAX)
5052             cycles_since_jump++;
5053           if (indirect_call_p (pat) && ENABLE_WA_INDIRECT_CALLS)
5054             {
5055               delay_needed = 3;
5056             }
5057         }
5058       else if (INSN_P (insn))
5059         {
5060           rtx load_insn = find_load (insn);
5061           enum attr_type type = type_for_anomaly (insn);
5062
5063           if (cycles_since_jump < INT_MAX)
5064             cycles_since_jump++;
5065
5066           if (load_insn && ENABLE_WA_SPECULATIVE_LOADS)
5067             {
5068               if (trapping_loads_p (load_insn))
5069                 delay_needed = 4;
5070             }
5071           else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS)
5072             delay_needed = 3;
5073         }
5074
5075       if (delay_needed > cycles_since_jump
5076           && (delay_needed - cycles_since_jump) > delay_added)
5077         {
5078           rtx pat1;
5079           int num_clobbers;
5080           rtx *op = recog_data.operand;
5081
5082           delay_needed -= cycles_since_jump;
5083
5084           extract_insn (last_condjump);
5085           if (optimize_size)
5086             {
5087               pat1 = gen_cbranch_predicted_taken (op[0], op[1], op[2],
5088                                                  op[3]);
5089               cycles_since_jump = INT_MAX;
5090             }
5091           else
5092             {
5093               /* Do not adjust cycles_since_jump in this case, so that
5094                  we'll increase the number of NOPs for a subsequent insn
5095                  if necessary.  */
5096               pat1 = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
5097                                             GEN_INT (delay_needed));
5098               delay_added = delay_needed;
5099             }
5100           PATTERN (last_condjump) = pat1;
5101           INSN_CODE (last_condjump) = recog (pat1, insn, &num_clobbers);
5102         }
5103       if (CALL_P (insn))
5104         {
5105           cycles_since_jump = INT_MAX;
5106           delay_added = 0;
5107         }
5108     }
5109
5110   /* Second pass: for predicted-true branches, see if anything at the
5111      branch destination needs extra nops.  */
5112   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5113     {
5114       int cycles_since_jump;
5115       if (JUMP_P (insn)
5116           && any_condjump_p (insn)
5117           && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken
5118               || cbranch_predicted_taken_p (insn)))
5119         {
5120           rtx target = JUMP_LABEL (insn);
5121           rtx label = target;
5122           rtx next_tgt;
5123
5124           cycles_since_jump = 0;
5125           for (; target && cycles_since_jump < 3; target = next_tgt)
5126             {
5127               rtx pat;
5128
5129               next_tgt = find_next_insn_start (target);
5130
5131               if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
5132                 continue;
5133
5134               pat = PATTERN (target);
5135               if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
5136                   || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
5137                   || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
5138                 continue;
5139
5140               if (INSN_P (target))
5141                 {
5142                   rtx load_insn = find_load (target);
5143                   enum attr_type type = type_for_anomaly (target);
5144                   int delay_needed = 0;
5145                   if (cycles_since_jump < INT_MAX)
5146                     cycles_since_jump++;
5147
5148                   if (load_insn && ENABLE_WA_SPECULATIVE_LOADS)
5149                     {
5150                       if (trapping_loads_p (load_insn))
5151                         delay_needed = 2;
5152                     }
5153                   else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS)
5154                     delay_needed = 2;
5155
5156                   if (delay_needed > cycles_since_jump)
5157                     {
5158                       rtx prev = prev_real_insn (label);
5159                       delay_needed -= cycles_since_jump;
5160                       if (dump_file)
5161                         fprintf (dump_file, "Adding %d nops after %d\n",
5162                                  delay_needed, INSN_UID (label));
5163                       if (JUMP_P (prev)
5164                           && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops)
5165                         {
5166                           rtx x;
5167                           HOST_WIDE_INT v;
5168
5169                           if (dump_file)
5170                             fprintf (dump_file,
5171                                      "Reducing nops on insn %d.\n",
5172                                      INSN_UID (prev));
5173                           x = PATTERN (prev);
5174                           x = XVECEXP (x, 0, 1);
5175                           v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed;
5176                           XVECEXP (x, 0, 0) = GEN_INT (v);
5177                         }
5178                       while (delay_needed-- > 0)
5179                         emit_insn_after (gen_nop (), label);
5180                       break;
5181                     }
5182                 }
5183             }
5184         }
5185     }
5186 }
5187
5188 /* We use the machine specific reorg pass for emitting CSYNC instructions
5189    after conditional branches as needed.
5190
5191    The Blackfin is unusual in that a code sequence like
5192      if cc jump label
5193      r0 = (p0)
5194    may speculatively perform the load even if the condition isn't true.  This
5195    happens for a branch that is predicted not taken, because the pipeline
5196    isn't flushed or stalled, so the early stages of the following instructions,
5197    which perform the memory reference, are allowed to execute before the
5198    jump condition is evaluated.
5199    Therefore, we must insert additional instructions in all places where this
5200    could lead to incorrect behavior.  The manual recommends CSYNC, while
5201    VDSP seems to use NOPs (even though its corresponding compiler option is
5202    named CSYNC).
5203
5204    When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
5205    When optimizing for size, we turn the branch into a predicted taken one.
5206    This may be slower due to mispredicts, but saves code size.  */
5207
5208 static void
5209 bfin_reorg (void)
5210 {
5211   /* We are freeing block_for_insn in the toplev to keep compatibility
5212      with old MDEP_REORGS that are not CFG based.  Recompute it now.  */
5213   compute_bb_for_insn ();
5214
5215   if (bfin_flag_schedule_insns2)
5216     {
5217       splitting_for_sched = 1;
5218       split_all_insns ();
5219       splitting_for_sched = 0;
5220
5221       timevar_push (TV_SCHED2);
5222       schedule_insns ();
5223       timevar_pop (TV_SCHED2);
5224
5225       /* Examine the schedule and insert nops as necessary for 64-bit parallel
5226          instructions.  */
5227       bfin_gen_bundles ();
5228     }
5229
5230   df_analyze ();
5231
5232   /* Doloop optimization */
5233   if (cfun->machine->has_hardware_loops)
5234     bfin_reorg_loops (dump_file);
5235
5236   workaround_speculation ();
5237
5238   if (bfin_flag_var_tracking)
5239     {
5240       timevar_push (TV_VAR_TRACKING);
5241       variable_tracking_main ();
5242       reorder_var_tracking_notes ();
5243       timevar_pop (TV_VAR_TRACKING);
5244     }
5245
5246   df_finish_pass (false);
5247
5248   workaround_rts_anomaly ();
5249 }
5250 \f
5251 /* Handle interrupt_handler, exception_handler and nmi_handler function
5252    attributes; arguments as in struct attribute_spec.handler.  */
5253
5254 static tree
5255 handle_int_attribute (tree *node, tree name,
5256                       tree args ATTRIBUTE_UNUSED,
5257                       int flags ATTRIBUTE_UNUSED,
5258                       bool *no_add_attrs)
5259 {
5260   tree x = *node;
5261   if (TREE_CODE (x) == FUNCTION_DECL)
5262     x = TREE_TYPE (x);
5263
5264   if (TREE_CODE (x) != FUNCTION_TYPE)
5265     {
5266       warning (OPT_Wattributes, "%qE attribute only applies to functions",
5267                name);
5268       *no_add_attrs = true;
5269     }
5270   else if (funkind (x) != SUBROUTINE)
5271     error ("multiple function type attributes specified");
5272
5273   return NULL_TREE;
5274 }
5275
5276 /* Return 0 if the attributes for two types are incompatible, 1 if they
5277    are compatible, and 2 if they are nearly compatible (which causes a
5278    warning to be generated).  */
5279
5280 static int
5281 bfin_comp_type_attributes (const_tree type1, const_tree type2)
5282 {
5283   e_funkind kind1, kind2;
5284
5285   if (TREE_CODE (type1) != FUNCTION_TYPE)
5286     return 1;
5287
5288   kind1 = funkind (type1);
5289   kind2 = funkind (type2);
5290
5291   if (kind1 != kind2)
5292     return 0;
5293   
5294   /*  Check for mismatched modifiers */
5295   if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
5296       != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
5297     return 0;
5298
5299   if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
5300       != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
5301     return 0;
5302
5303   if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
5304       != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
5305     return 0;
5306
5307   if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1))
5308       != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2)))
5309     return 0;
5310
5311   return 1;
5312 }
5313
5314 /* Handle a "longcall" or "shortcall" attribute; arguments as in
5315    struct attribute_spec.handler.  */
5316
5317 static tree
5318 bfin_handle_longcall_attribute (tree *node, tree name, 
5319                                 tree args ATTRIBUTE_UNUSED, 
5320                                 int flags ATTRIBUTE_UNUSED, 
5321                                 bool *no_add_attrs)
5322 {
5323   if (TREE_CODE (*node) != FUNCTION_TYPE
5324       && TREE_CODE (*node) != FIELD_DECL
5325       && TREE_CODE (*node) != TYPE_DECL)
5326     {
5327       warning (OPT_Wattributes, "%qE attribute only applies to functions",
5328                name);
5329       *no_add_attrs = true;
5330     }
5331
5332   if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0
5333        && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node)))
5334       || (strcmp (IDENTIFIER_POINTER (name), "shortcall") == 0
5335           && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node))))
5336     {
5337       warning (OPT_Wattributes,
5338                "can't apply both longcall and shortcall attributes to the same function");
5339       *no_add_attrs = true;
5340     }
5341
5342   return NULL_TREE;
5343 }
5344
5345 /* Handle a "l1_text" attribute; arguments as in
5346    struct attribute_spec.handler.  */
5347
5348 static tree
5349 bfin_handle_l1_text_attribute (tree *node, tree name, tree ARG_UNUSED (args),
5350                                int ARG_UNUSED (flags), bool *no_add_attrs)
5351 {
5352   tree decl = *node;
5353
5354   if (TREE_CODE (decl) != FUNCTION_DECL)
5355     {
5356       error ("%qE attribute only applies to functions",
5357              name);
5358       *no_add_attrs = true;
5359     }
5360
5361   /* The decl may have already been given a section attribute
5362      from a previous declaration. Ensure they match.  */
5363   else if (DECL_SECTION_NAME (decl) != NULL_TREE
5364            && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
5365                       ".l1.text") != 0)
5366     {
5367       error ("section of %q+D conflicts with previous declaration",
5368              decl);
5369       *no_add_attrs = true;
5370     }
5371   else
5372     DECL_SECTION_NAME (decl) = build_string (9, ".l1.text");
5373
5374   return NULL_TREE;
5375 }
5376
5377 /* Handle a "l1_data", "l1_data_A" or "l1_data_B" attribute;
5378    arguments as in struct attribute_spec.handler.  */
5379
5380 static tree
5381 bfin_handle_l1_data_attribute (tree *node, tree name, tree ARG_UNUSED (args),
5382                                int ARG_UNUSED (flags), bool *no_add_attrs)
5383 {
5384   tree decl = *node;
5385
5386   if (TREE_CODE (decl) != VAR_DECL)
5387     {
5388       error ("%qE attribute only applies to variables",
5389              name);
5390       *no_add_attrs = true;
5391     }
5392   else if (current_function_decl != NULL_TREE
5393            && !TREE_STATIC (decl))
5394     {
5395       error ("%qE attribute cannot be specified for local variables",
5396              name);
5397       *no_add_attrs = true;
5398     }
5399   else
5400     {
5401       const char *section_name;
5402
5403       if (strcmp (IDENTIFIER_POINTER (name), "l1_data") == 0)
5404         section_name = ".l1.data";
5405       else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_A") == 0)
5406         section_name = ".l1.data.A";
5407       else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_B") == 0)
5408         section_name = ".l1.data.B";
5409       else
5410         gcc_unreachable ();
5411
5412       /* The decl may have already been given a section attribute
5413          from a previous declaration. Ensure they match.  */
5414       if (DECL_SECTION_NAME (decl) != NULL_TREE
5415           && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
5416                      section_name) != 0)
5417         {
5418           error ("section of %q+D conflicts with previous declaration",
5419                  decl);
5420           *no_add_attrs = true;
5421         }
5422       else
5423         DECL_SECTION_NAME (decl)
5424           = build_string (strlen (section_name) + 1, section_name);
5425     }
5426
5427  return NULL_TREE;
5428 }
5429
5430 /* Table of valid machine attributes.  */
5431 const struct attribute_spec bfin_attribute_table[] =
5432 {
5433   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
5434   { "interrupt_handler", 0, 0, false, true,  true, handle_int_attribute },
5435   { "exception_handler", 0, 0, false, true,  true, handle_int_attribute },
5436   { "nmi_handler", 0, 0, false, true,  true, handle_int_attribute },
5437   { "nesting", 0, 0, false, true,  true, NULL },
5438   { "kspisusp", 0, 0, false, true,  true, NULL },
5439   { "saveall", 0, 0, false, true,  true, NULL },
5440   { "longcall",  0, 0, false, true,  true,  bfin_handle_longcall_attribute },
5441   { "shortcall", 0, 0, false, true,  true,  bfin_handle_longcall_attribute },
5442   { "l1_text", 0, 0, true, false, false,  bfin_handle_l1_text_attribute },
5443   { "l1_data", 0, 0, true, false, false,  bfin_handle_l1_data_attribute },
5444   { "l1_data_A", 0, 0, true, false, false, bfin_handle_l1_data_attribute },
5445   { "l1_data_B", 0, 0, true, false, false,  bfin_handle_l1_data_attribute },
5446   { NULL, 0, 0, false, false, false, NULL }
5447 };
5448 \f
5449 /* Implementation of TARGET_ASM_INTEGER.  When using FD-PIC, we need to
5450    tell the assembler to generate pointers to function descriptors in
5451    some cases.  */
5452
5453 static bool
5454 bfin_assemble_integer (rtx value, unsigned int size, int aligned_p)
5455 {
5456   if (TARGET_FDPIC && size == UNITS_PER_WORD)
5457     {
5458       if (GET_CODE (value) == SYMBOL_REF
5459           && SYMBOL_REF_FUNCTION_P (value))
5460         {
5461           fputs ("\t.picptr\tfuncdesc(", asm_out_file);
5462           output_addr_const (asm_out_file, value);
5463           fputs (")\n", asm_out_file);
5464           return true;
5465         }
5466       if (!aligned_p)
5467         {
5468           /* We've set the unaligned SI op to NULL, so we always have to
5469              handle the unaligned case here.  */
5470           assemble_integer_with_op ("\t.4byte\t", value);
5471           return true;
5472         }
5473     }
5474   return default_assemble_integer (value, size, aligned_p);
5475 }
5476 \f
5477 /* Output the assembler code for a thunk function.  THUNK_DECL is the
5478    declaration for the thunk function itself, FUNCTION is the decl for
5479    the target function.  DELTA is an immediate constant offset to be
5480    added to THIS.  If VCALL_OFFSET is nonzero, the word at
5481    *(*this + vcall_offset) should be added to THIS.  */
5482
5483 static void
5484 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
5485                       tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
5486                       HOST_WIDE_INT vcall_offset, tree function)
5487 {
5488   rtx xops[3];
5489   /* The this parameter is passed as the first argument.  */
5490   rtx this_rtx = gen_rtx_REG (Pmode, REG_R0);
5491
5492   /* Adjust the this parameter by a fixed constant.  */
5493   if (delta)
5494     {
5495       xops[1] = this_rtx;
5496       if (delta >= -64 && delta <= 63)
5497         {
5498           xops[0] = GEN_INT (delta);
5499           output_asm_insn ("%1 += %0;", xops);
5500         }
5501       else if (delta >= -128 && delta < -64)
5502         {
5503           xops[0] = GEN_INT (delta + 64);
5504           output_asm_insn ("%1 += -64; %1 += %0;", xops);
5505         }
5506       else if (delta > 63 && delta <= 126)
5507         {
5508           xops[0] = GEN_INT (delta - 63);
5509           output_asm_insn ("%1 += 63; %1 += %0;", xops);
5510         }
5511       else
5512         {
5513           xops[0] = GEN_INT (delta);
5514           output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
5515         }
5516     }
5517
5518   /* Adjust the this parameter by a value stored in the vtable.  */
5519   if (vcall_offset)
5520     {
5521       rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
5522       rtx tmp = gen_rtx_REG (Pmode, REG_R3);
5523
5524       xops[1] = tmp;
5525       xops[2] = p2tmp;
5526       output_asm_insn ("%2 = r0; %2 = [%2];", xops);
5527
5528       /* Adjust the this parameter.  */
5529       xops[0] = gen_rtx_MEM (Pmode, plus_constant (p2tmp, vcall_offset));
5530       if (!memory_operand (xops[0], Pmode))
5531         {
5532           rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
5533           xops[0] = GEN_INT (vcall_offset);
5534           xops[1] = tmp2;
5535           output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
5536           xops[0] = gen_rtx_MEM (Pmode, p2tmp);
5537         }
5538       xops[2] = this_rtx;
5539       output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
5540     }
5541
5542   xops[0] = XEXP (DECL_RTL (function), 0);
5543   if (1 || !flag_pic || (*targetm.binds_local_p) (function))
5544     output_asm_insn ("jump.l\t%P0", xops);
5545 }
5546 \f
5547 /* Codes for all the Blackfin builtins.  */
5548 enum bfin_builtins
5549 {
5550   BFIN_BUILTIN_CSYNC,
5551   BFIN_BUILTIN_SSYNC,
5552   BFIN_BUILTIN_ONES,
5553   BFIN_BUILTIN_COMPOSE_2X16,
5554   BFIN_BUILTIN_EXTRACTLO,
5555   BFIN_BUILTIN_EXTRACTHI,
5556
5557   BFIN_BUILTIN_SSADD_2X16,
5558   BFIN_BUILTIN_SSSUB_2X16,
5559   BFIN_BUILTIN_SSADDSUB_2X16,
5560   BFIN_BUILTIN_SSSUBADD_2X16,
5561   BFIN_BUILTIN_MULT_2X16,
5562   BFIN_BUILTIN_MULTR_2X16,
5563   BFIN_BUILTIN_NEG_2X16,
5564   BFIN_BUILTIN_ABS_2X16,
5565   BFIN_BUILTIN_MIN_2X16,
5566   BFIN_BUILTIN_MAX_2X16,
5567
5568   BFIN_BUILTIN_SSADD_1X16,
5569   BFIN_BUILTIN_SSSUB_1X16,
5570   BFIN_BUILTIN_MULT_1X16,
5571   BFIN_BUILTIN_MULTR_1X16,
5572   BFIN_BUILTIN_NORM_1X16,
5573   BFIN_BUILTIN_NEG_1X16,
5574   BFIN_BUILTIN_ABS_1X16,
5575   BFIN_BUILTIN_MIN_1X16,
5576   BFIN_BUILTIN_MAX_1X16,
5577
5578   BFIN_BUILTIN_SUM_2X16,
5579   BFIN_BUILTIN_DIFFHL_2X16,
5580   BFIN_BUILTIN_DIFFLH_2X16,
5581
5582   BFIN_BUILTIN_SSADD_1X32,
5583   BFIN_BUILTIN_SSSUB_1X32,
5584   BFIN_BUILTIN_NORM_1X32,
5585   BFIN_BUILTIN_ROUND_1X32,
5586   BFIN_BUILTIN_NEG_1X32,
5587   BFIN_BUILTIN_ABS_1X32,
5588   BFIN_BUILTIN_MIN_1X32,
5589   BFIN_BUILTIN_MAX_1X32,
5590   BFIN_BUILTIN_MULT_1X32,
5591   BFIN_BUILTIN_MULT_1X32X32,
5592   BFIN_BUILTIN_MULT_1X32X32NS,
5593
5594   BFIN_BUILTIN_MULHISILL,
5595   BFIN_BUILTIN_MULHISILH,
5596   BFIN_BUILTIN_MULHISIHL,
5597   BFIN_BUILTIN_MULHISIHH,
5598
5599   BFIN_BUILTIN_LSHIFT_1X16,
5600   BFIN_BUILTIN_LSHIFT_2X16,
5601   BFIN_BUILTIN_SSASHIFT_1X16,
5602   BFIN_BUILTIN_SSASHIFT_2X16,
5603   BFIN_BUILTIN_SSASHIFT_1X32,
5604
5605   BFIN_BUILTIN_CPLX_MUL_16,
5606   BFIN_BUILTIN_CPLX_MAC_16,
5607   BFIN_BUILTIN_CPLX_MSU_16,
5608
5609   BFIN_BUILTIN_CPLX_MUL_16_S40,
5610   BFIN_BUILTIN_CPLX_MAC_16_S40,
5611   BFIN_BUILTIN_CPLX_MSU_16_S40,
5612
5613   BFIN_BUILTIN_CPLX_SQU,
5614
5615   BFIN_BUILTIN_LOADBYTES,
5616
5617   BFIN_BUILTIN_MAX
5618 };
5619
5620 #define def_builtin(NAME, TYPE, CODE)                                   \
5621 do {                                                                    \
5622   add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD,            \
5623                        NULL, NULL_TREE);                                \
5624 } while (0)
5625
5626 /* Set up all builtin functions for this target.  */
5627 static void
5628 bfin_init_builtins (void)
5629 {
5630   tree V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
5631   tree void_ftype_void
5632     = build_function_type (void_type_node, void_list_node);
5633   tree short_ftype_short
5634     = build_function_type_list (short_integer_type_node, short_integer_type_node,
5635                                 NULL_TREE);
5636   tree short_ftype_int_int
5637     = build_function_type_list (short_integer_type_node, integer_type_node,
5638                                 integer_type_node, NULL_TREE);
5639   tree int_ftype_int_int
5640     = build_function_type_list (integer_type_node, integer_type_node,
5641                                 integer_type_node, NULL_TREE);
5642   tree int_ftype_int
5643     = build_function_type_list (integer_type_node, integer_type_node,
5644                                 NULL_TREE);
5645   tree short_ftype_int
5646     = build_function_type_list (short_integer_type_node, integer_type_node,
5647                                 NULL_TREE);
5648   tree int_ftype_v2hi_v2hi
5649     = build_function_type_list (integer_type_node, V2HI_type_node,
5650                                 V2HI_type_node, NULL_TREE);
5651   tree v2hi_ftype_v2hi_v2hi
5652     = build_function_type_list (V2HI_type_node, V2HI_type_node,
5653                                 V2HI_type_node, NULL_TREE);
5654   tree v2hi_ftype_v2hi_v2hi_v2hi
5655     = build_function_type_list (V2HI_type_node, V2HI_type_node,
5656                                 V2HI_type_node, V2HI_type_node, NULL_TREE);
5657   tree v2hi_ftype_int_int
5658     = build_function_type_list (V2HI_type_node, integer_type_node,
5659                                 integer_type_node, NULL_TREE);
5660   tree v2hi_ftype_v2hi_int
5661     = build_function_type_list (V2HI_type_node, V2HI_type_node,
5662                                 integer_type_node, NULL_TREE);
5663   tree int_ftype_short_short
5664     = build_function_type_list (integer_type_node, short_integer_type_node,
5665                                 short_integer_type_node, NULL_TREE);
5666   tree v2hi_ftype_v2hi
5667     = build_function_type_list (V2HI_type_node, V2HI_type_node, NULL_TREE);
5668   tree short_ftype_v2hi
5669     = build_function_type_list (short_integer_type_node, V2HI_type_node,
5670                                 NULL_TREE);
5671   tree int_ftype_pint
5672     = build_function_type_list (integer_type_node,
5673                                 build_pointer_type (integer_type_node),
5674                                 NULL_TREE);
5675   
5676   /* Add the remaining MMX insns with somewhat more complicated types.  */
5677   def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC);
5678   def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC);
5679
5680   def_builtin ("__builtin_bfin_ones", short_ftype_int, BFIN_BUILTIN_ONES);
5681
5682   def_builtin ("__builtin_bfin_compose_2x16", v2hi_ftype_int_int,
5683                BFIN_BUILTIN_COMPOSE_2X16);
5684   def_builtin ("__builtin_bfin_extract_hi", short_ftype_v2hi,
5685                BFIN_BUILTIN_EXTRACTHI);
5686   def_builtin ("__builtin_bfin_extract_lo", short_ftype_v2hi,
5687                BFIN_BUILTIN_EXTRACTLO);
5688
5689   def_builtin ("__builtin_bfin_min_fr2x16", v2hi_ftype_v2hi_v2hi,
5690                BFIN_BUILTIN_MIN_2X16);
5691   def_builtin ("__builtin_bfin_max_fr2x16", v2hi_ftype_v2hi_v2hi,
5692                BFIN_BUILTIN_MAX_2X16);
5693
5694   def_builtin ("__builtin_bfin_add_fr2x16", v2hi_ftype_v2hi_v2hi,
5695                BFIN_BUILTIN_SSADD_2X16);
5696   def_builtin ("__builtin_bfin_sub_fr2x16", v2hi_ftype_v2hi_v2hi,
5697                BFIN_BUILTIN_SSSUB_2X16);
5698   def_builtin ("__builtin_bfin_dspaddsubsat", v2hi_ftype_v2hi_v2hi,
5699                BFIN_BUILTIN_SSADDSUB_2X16);
5700   def_builtin ("__builtin_bfin_dspsubaddsat", v2hi_ftype_v2hi_v2hi,
5701                BFIN_BUILTIN_SSSUBADD_2X16);
5702   def_builtin ("__builtin_bfin_mult_fr2x16", v2hi_ftype_v2hi_v2hi,
5703                BFIN_BUILTIN_MULT_2X16);
5704   def_builtin ("__builtin_bfin_multr_fr2x16", v2hi_ftype_v2hi_v2hi,
5705                BFIN_BUILTIN_MULTR_2X16);
5706   def_builtin ("__builtin_bfin_negate_fr2x16", v2hi_ftype_v2hi,
5707                BFIN_BUILTIN_NEG_2X16);
5708   def_builtin ("__builtin_bfin_abs_fr2x16", v2hi_ftype_v2hi,
5709                BFIN_BUILTIN_ABS_2X16);
5710
5711   def_builtin ("__builtin_bfin_min_fr1x16", short_ftype_int_int,
5712                BFIN_BUILTIN_MIN_1X16);
5713   def_builtin ("__builtin_bfin_max_fr1x16", short_ftype_int_int,
5714                BFIN_BUILTIN_MAX_1X16);
5715
5716   def_builtin ("__builtin_bfin_add_fr1x16", short_ftype_int_int,
5717                BFIN_BUILTIN_SSADD_1X16);
5718   def_builtin ("__builtin_bfin_sub_fr1x16", short_ftype_int_int,
5719                BFIN_BUILTIN_SSSUB_1X16);
5720   def_builtin ("__builtin_bfin_mult_fr1x16", short_ftype_int_int,
5721                BFIN_BUILTIN_MULT_1X16);
5722   def_builtin ("__builtin_bfin_multr_fr1x16", short_ftype_int_int,
5723                BFIN_BUILTIN_MULTR_1X16);
5724   def_builtin ("__builtin_bfin_negate_fr1x16", short_ftype_short,
5725                BFIN_BUILTIN_NEG_1X16);
5726   def_builtin ("__builtin_bfin_abs_fr1x16", short_ftype_short,
5727                BFIN_BUILTIN_ABS_1X16);
5728   def_builtin ("__builtin_bfin_norm_fr1x16", short_ftype_int,
5729                BFIN_BUILTIN_NORM_1X16);
5730
5731   def_builtin ("__builtin_bfin_sum_fr2x16", short_ftype_v2hi,
5732                BFIN_BUILTIN_SUM_2X16);
5733   def_builtin ("__builtin_bfin_diff_hl_fr2x16", short_ftype_v2hi,
5734                BFIN_BUILTIN_DIFFHL_2X16);
5735   def_builtin ("__builtin_bfin_diff_lh_fr2x16", short_ftype_v2hi,
5736                BFIN_BUILTIN_DIFFLH_2X16);
5737
5738   def_builtin ("__builtin_bfin_mulhisill", int_ftype_v2hi_v2hi,
5739                BFIN_BUILTIN_MULHISILL);
5740   def_builtin ("__builtin_bfin_mulhisihl", int_ftype_v2hi_v2hi,
5741                BFIN_BUILTIN_MULHISIHL);
5742   def_builtin ("__builtin_bfin_mulhisilh", int_ftype_v2hi_v2hi,
5743                BFIN_BUILTIN_MULHISILH);
5744   def_builtin ("__builtin_bfin_mulhisihh", int_ftype_v2hi_v2hi,
5745                BFIN_BUILTIN_MULHISIHH);
5746
5747   def_builtin ("__builtin_bfin_min_fr1x32", int_ftype_int_int,
5748                BFIN_BUILTIN_MIN_1X32);
5749   def_builtin ("__builtin_bfin_max_fr1x32", int_ftype_int_int,
5750                BFIN_BUILTIN_MAX_1X32);
5751
5752   def_builtin ("__builtin_bfin_add_fr1x32", int_ftype_int_int,
5753                BFIN_BUILTIN_SSADD_1X32);
5754   def_builtin ("__builtin_bfin_sub_fr1x32", int_ftype_int_int,
5755                BFIN_BUILTIN_SSSUB_1X32);
5756   def_builtin ("__builtin_bfin_negate_fr1x32", int_ftype_int,
5757                BFIN_BUILTIN_NEG_1X32);
5758   def_builtin ("__builtin_bfin_abs_fr1x32", int_ftype_int,
5759                BFIN_BUILTIN_ABS_1X32);
5760   def_builtin ("__builtin_bfin_norm_fr1x32", short_ftype_int,
5761                BFIN_BUILTIN_NORM_1X32);
5762   def_builtin ("__builtin_bfin_round_fr1x32", short_ftype_int,
5763                BFIN_BUILTIN_ROUND_1X32);
5764   def_builtin ("__builtin_bfin_mult_fr1x32", int_ftype_short_short,
5765                BFIN_BUILTIN_MULT_1X32);
5766   def_builtin ("__builtin_bfin_mult_fr1x32x32", int_ftype_int_int,
5767                BFIN_BUILTIN_MULT_1X32X32);
5768   def_builtin ("__builtin_bfin_mult_fr1x32x32NS", int_ftype_int_int,
5769                BFIN_BUILTIN_MULT_1X32X32NS);
5770
5771   /* Shifts.  */
5772   def_builtin ("__builtin_bfin_shl_fr1x16", short_ftype_int_int,
5773                BFIN_BUILTIN_SSASHIFT_1X16);
5774   def_builtin ("__builtin_bfin_shl_fr2x16", v2hi_ftype_v2hi_int,
5775                BFIN_BUILTIN_SSASHIFT_2X16);
5776   def_builtin ("__builtin_bfin_lshl_fr1x16", short_ftype_int_int,
5777                BFIN_BUILTIN_LSHIFT_1X16);
5778   def_builtin ("__builtin_bfin_lshl_fr2x16", v2hi_ftype_v2hi_int,
5779                BFIN_BUILTIN_LSHIFT_2X16);
5780   def_builtin ("__builtin_bfin_shl_fr1x32", int_ftype_int_int,
5781                BFIN_BUILTIN_SSASHIFT_1X32);
5782
5783   /* Complex numbers.  */
5784   def_builtin ("__builtin_bfin_cmplx_add", v2hi_ftype_v2hi_v2hi,
5785                BFIN_BUILTIN_SSADD_2X16);
5786   def_builtin ("__builtin_bfin_cmplx_sub", v2hi_ftype_v2hi_v2hi,
5787                BFIN_BUILTIN_SSSUB_2X16);
5788   def_builtin ("__builtin_bfin_cmplx_mul", v2hi_ftype_v2hi_v2hi,
5789                BFIN_BUILTIN_CPLX_MUL_16);
5790   def_builtin ("__builtin_bfin_cmplx_mac", v2hi_ftype_v2hi_v2hi_v2hi,
5791                BFIN_BUILTIN_CPLX_MAC_16);
5792   def_builtin ("__builtin_bfin_cmplx_msu", v2hi_ftype_v2hi_v2hi_v2hi,
5793                BFIN_BUILTIN_CPLX_MSU_16);
5794   def_builtin ("__builtin_bfin_cmplx_mul_s40", v2hi_ftype_v2hi_v2hi,
5795                BFIN_BUILTIN_CPLX_MUL_16_S40);
5796   def_builtin ("__builtin_bfin_cmplx_mac_s40", v2hi_ftype_v2hi_v2hi_v2hi,
5797                BFIN_BUILTIN_CPLX_MAC_16_S40);
5798   def_builtin ("__builtin_bfin_cmplx_msu_s40", v2hi_ftype_v2hi_v2hi_v2hi,
5799                BFIN_BUILTIN_CPLX_MSU_16_S40);
5800   def_builtin ("__builtin_bfin_csqu_fr16", v2hi_ftype_v2hi,
5801                BFIN_BUILTIN_CPLX_SQU);
5802
5803   /* "Unaligned" load.  */
5804   def_builtin ("__builtin_bfin_loadbytes", int_ftype_pint,
5805                BFIN_BUILTIN_LOADBYTES);
5806
5807 }
5808
5809
5810 struct builtin_description
5811 {
5812   const enum insn_code icode;
5813   const char *const name;
5814   const enum bfin_builtins code;
5815   int macflag;
5816 };
5817
5818 static const struct builtin_description bdesc_2arg[] =
5819 {
5820   { CODE_FOR_composev2hi, "__builtin_bfin_compose_2x16", BFIN_BUILTIN_COMPOSE_2X16, -1 },
5821
5822   { CODE_FOR_ssashiftv2hi3, "__builtin_bfin_shl_fr2x16", BFIN_BUILTIN_SSASHIFT_2X16, -1 },
5823   { CODE_FOR_ssashifthi3, "__builtin_bfin_shl_fr1x16", BFIN_BUILTIN_SSASHIFT_1X16, -1 },
5824   { CODE_FOR_lshiftv2hi3, "__builtin_bfin_lshl_fr2x16", BFIN_BUILTIN_LSHIFT_2X16, -1 },
5825   { CODE_FOR_lshifthi3, "__builtin_bfin_lshl_fr1x16", BFIN_BUILTIN_LSHIFT_1X16, -1 },
5826   { CODE_FOR_ssashiftsi3, "__builtin_bfin_shl_fr1x32", BFIN_BUILTIN_SSASHIFT_1X32, -1 },
5827
5828   { CODE_FOR_sminhi3, "__builtin_bfin_min_fr1x16", BFIN_BUILTIN_MIN_1X16, -1 },
5829   { CODE_FOR_smaxhi3, "__builtin_bfin_max_fr1x16", BFIN_BUILTIN_MAX_1X16, -1 },
5830   { CODE_FOR_ssaddhi3, "__builtin_bfin_add_fr1x16", BFIN_BUILTIN_SSADD_1X16, -1 },
5831   { CODE_FOR_sssubhi3, "__builtin_bfin_sub_fr1x16", BFIN_BUILTIN_SSSUB_1X16, -1 },
5832
5833   { CODE_FOR_sminsi3, "__builtin_bfin_min_fr1x32", BFIN_BUILTIN_MIN_1X32, -1 },
5834   { CODE_FOR_smaxsi3, "__builtin_bfin_max_fr1x32", BFIN_BUILTIN_MAX_1X32, -1 },
5835   { CODE_FOR_ssaddsi3, "__builtin_bfin_add_fr1x32", BFIN_BUILTIN_SSADD_1X32, -1 },
5836   { CODE_FOR_sssubsi3, "__builtin_bfin_sub_fr1x32", BFIN_BUILTIN_SSSUB_1X32, -1 },
5837
5838   { CODE_FOR_sminv2hi3, "__builtin_bfin_min_fr2x16", BFIN_BUILTIN_MIN_2X16, -1 },
5839   { CODE_FOR_smaxv2hi3, "__builtin_bfin_max_fr2x16", BFIN_BUILTIN_MAX_2X16, -1 },
5840   { CODE_FOR_ssaddv2hi3, "__builtin_bfin_add_fr2x16", BFIN_BUILTIN_SSADD_2X16, -1 },
5841   { CODE_FOR_sssubv2hi3, "__builtin_bfin_sub_fr2x16", BFIN_BUILTIN_SSSUB_2X16, -1 },
5842   { CODE_FOR_ssaddsubv2hi3, "__builtin_bfin_dspaddsubsat", BFIN_BUILTIN_SSADDSUB_2X16, -1 },
5843   { CODE_FOR_sssubaddv2hi3, "__builtin_bfin_dspsubaddsat", BFIN_BUILTIN_SSSUBADD_2X16, -1 },
5844
5845   { CODE_FOR_flag_mulhisi, "__builtin_bfin_mult_fr1x32", BFIN_BUILTIN_MULT_1X32, MACFLAG_NONE },
5846   { CODE_FOR_flag_mulhi, "__builtin_bfin_mult_fr1x16", BFIN_BUILTIN_MULT_1X16, MACFLAG_T },
5847   { CODE_FOR_flag_mulhi, "__builtin_bfin_multr_fr1x16", BFIN_BUILTIN_MULTR_1X16, MACFLAG_NONE },
5848   { CODE_FOR_flag_mulv2hi, "__builtin_bfin_mult_fr2x16", BFIN_BUILTIN_MULT_2X16, MACFLAG_T },
5849   { CODE_FOR_flag_mulv2hi, "__builtin_bfin_multr_fr2x16", BFIN_BUILTIN_MULTR_2X16, MACFLAG_NONE },
5850
5851   { CODE_FOR_mulhisi_ll, "__builtin_bfin_mulhisill", BFIN_BUILTIN_MULHISILL, -1 },
5852   { CODE_FOR_mulhisi_lh, "__builtin_bfin_mulhisilh", BFIN_BUILTIN_MULHISILH, -1 },
5853   { CODE_FOR_mulhisi_hl, "__builtin_bfin_mulhisihl", BFIN_BUILTIN_MULHISIHL, -1 },
5854   { CODE_FOR_mulhisi_hh, "__builtin_bfin_mulhisihh", BFIN_BUILTIN_MULHISIHH, -1 }
5855
5856 };
5857
5858 static const struct builtin_description bdesc_1arg[] =
5859 {
5860   { CODE_FOR_loadbytes, "__builtin_bfin_loadbytes", BFIN_BUILTIN_LOADBYTES, 0 },
5861
5862   { CODE_FOR_ones, "__builtin_bfin_ones", BFIN_BUILTIN_ONES, 0 },
5863
5864   { CODE_FOR_signbitshi2, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16, 0 },
5865   { CODE_FOR_ssneghi2, "__builtin_bfin_negate_fr1x16", BFIN_BUILTIN_NEG_1X16, 0 },
5866   { CODE_FOR_abshi2, "__builtin_bfin_abs_fr1x16", BFIN_BUILTIN_ABS_1X16, 0 },
5867
5868   { CODE_FOR_signbitssi2, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32, 0 },
5869   { CODE_FOR_ssroundsi2, "__builtin_bfin_round_fr1x32", BFIN_BUILTIN_ROUND_1X32, 0 },
5870   { CODE_FOR_ssnegsi2, "__builtin_bfin_negate_fr1x32", BFIN_BUILTIN_NEG_1X32, 0 },
5871   { CODE_FOR_ssabssi2, "__builtin_bfin_abs_fr1x32", BFIN_BUILTIN_ABS_1X32, 0 },
5872
5873   { CODE_FOR_movv2hi_hi_low, "__builtin_bfin_extract_lo", BFIN_BUILTIN_EXTRACTLO, 0 },
5874   { CODE_FOR_movv2hi_hi_high, "__builtin_bfin_extract_hi", BFIN_BUILTIN_EXTRACTHI, 0 },
5875   { CODE_FOR_ssnegv2hi2, "__builtin_bfin_negate_fr2x16", BFIN_BUILTIN_NEG_2X16, 0 },
5876   { CODE_FOR_ssabsv2hi2, "__builtin_bfin_abs_fr2x16", BFIN_BUILTIN_ABS_2X16, 0 }
5877 };
5878
5879 /* Errors in the source file can cause expand_expr to return const0_rtx
5880    where we expect a vector.  To avoid crashing, use one of the vector
5881    clear instructions.  */
5882 static rtx
5883 safe_vector_operand (rtx x, enum machine_mode mode)
5884 {
5885   if (x != const0_rtx)
5886     return x;
5887   x = gen_reg_rtx (SImode);
5888
5889   emit_insn (gen_movsi (x, CONST0_RTX (SImode)));
5890   return gen_lowpart (mode, x);
5891 }
5892
5893 /* Subroutine of bfin_expand_builtin to take care of binop insns.  MACFLAG is -1
5894    if this is a normal binary op, or one of the MACFLAG_xxx constants.  */
5895
5896 static rtx
5897 bfin_expand_binop_builtin (enum insn_code icode, tree exp, rtx target,
5898                            int macflag)
5899 {
5900   rtx pat;
5901   tree arg0 = CALL_EXPR_ARG (exp, 0);
5902   tree arg1 = CALL_EXPR_ARG (exp, 1);
5903   rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5904   rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
5905   enum machine_mode op0mode = GET_MODE (op0);
5906   enum machine_mode op1mode = GET_MODE (op1);
5907   enum machine_mode tmode = insn_data[icode].operand[0].mode;
5908   enum machine_mode mode0 = insn_data[icode].operand[1].mode;
5909   enum machine_mode mode1 = insn_data[icode].operand[2].mode;
5910
5911   if (VECTOR_MODE_P (mode0))
5912     op0 = safe_vector_operand (op0, mode0);
5913   if (VECTOR_MODE_P (mode1))
5914     op1 = safe_vector_operand (op1, mode1);
5915
5916   if (! target
5917       || GET_MODE (target) != tmode
5918       || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5919     target = gen_reg_rtx (tmode);
5920
5921   if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode)
5922     {
5923       op0mode = HImode;
5924       op0 = gen_lowpart (HImode, op0);
5925     }
5926   if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode)
5927     {
5928       op1mode = HImode;
5929       op1 = gen_lowpart (HImode, op1);
5930     }
5931   /* In case the insn wants input operands in modes different from
5932      the result, abort.  */
5933   gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
5934               && (op1mode == mode1 || op1mode == VOIDmode));
5935
5936   if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5937     op0 = copy_to_mode_reg (mode0, op0);
5938   if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
5939     op1 = copy_to_mode_reg (mode1, op1);
5940
5941   if (macflag == -1)
5942     pat = GEN_FCN (icode) (target, op0, op1);
5943   else
5944     pat = GEN_FCN (icode) (target, op0, op1, GEN_INT (macflag));
5945   if (! pat)
5946     return 0;
5947
5948   emit_insn (pat);
5949   return target;
5950 }
5951
5952 /* Subroutine of bfin_expand_builtin to take care of unop insns.  */
5953
5954 static rtx
5955 bfin_expand_unop_builtin (enum insn_code icode, tree exp,
5956                           rtx target)
5957 {
5958   rtx pat;
5959   tree arg0 = CALL_EXPR_ARG (exp, 0);
5960   rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5961   enum machine_mode op0mode = GET_MODE (op0);
5962   enum machine_mode tmode = insn_data[icode].operand[0].mode;
5963   enum machine_mode mode0 = insn_data[icode].operand[1].mode;
5964
5965   if (! target
5966       || GET_MODE (target) != tmode
5967       || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5968     target = gen_reg_rtx (tmode);
5969
5970   if (VECTOR_MODE_P (mode0))
5971     op0 = safe_vector_operand (op0, mode0);
5972
5973   if (op0mode == SImode && mode0 == HImode)
5974     {
5975       op0mode = HImode;
5976       op0 = gen_lowpart (HImode, op0);
5977     }
5978   gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
5979
5980   if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5981     op0 = copy_to_mode_reg (mode0, op0);
5982
5983   pat = GEN_FCN (icode) (target, op0);
5984   if (! pat)
5985     return 0;
5986   emit_insn (pat);
5987   return target;
5988 }
5989
5990 /* Expand an expression EXP that calls a built-in function,
5991    with result going to TARGET if that's convenient
5992    (and in mode MODE if that's convenient).
5993    SUBTARGET may be used as the target for computing one of EXP's operands.
5994    IGNORE is nonzero if the value is to be ignored.  */
5995
5996 static rtx
5997 bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
5998                      rtx subtarget ATTRIBUTE_UNUSED,
5999                      enum machine_mode mode ATTRIBUTE_UNUSED,
6000                      int ignore ATTRIBUTE_UNUSED)
6001 {
6002   size_t i;
6003   enum insn_code icode;
6004   const struct builtin_description *d;
6005   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
6006   unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
6007   tree arg0, arg1, arg2;
6008   rtx op0, op1, op2, accvec, pat, tmp1, tmp2, a0reg, a1reg;
6009   enum machine_mode tmode, mode0;
6010
6011   switch (fcode)
6012     {
6013     case BFIN_BUILTIN_CSYNC:
6014       emit_insn (gen_csync ());
6015       return 0;
6016     case BFIN_BUILTIN_SSYNC:
6017       emit_insn (gen_ssync ());
6018       return 0;
6019
6020     case BFIN_BUILTIN_DIFFHL_2X16:
6021     case BFIN_BUILTIN_DIFFLH_2X16:
6022     case BFIN_BUILTIN_SUM_2X16:
6023       arg0 = CALL_EXPR_ARG (exp, 0);
6024       op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
6025       icode = (fcode == BFIN_BUILTIN_DIFFHL_2X16 ? CODE_FOR_subhilov2hi3
6026                : fcode == BFIN_BUILTIN_DIFFLH_2X16 ? CODE_FOR_sublohiv2hi3
6027                : CODE_FOR_ssaddhilov2hi3);
6028       tmode = insn_data[icode].operand[0].mode;
6029       mode0 = insn_data[icode].operand[1].mode;
6030
6031       if (! target
6032           || GET_MODE (target) != tmode
6033           || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
6034         target = gen_reg_rtx (tmode);
6035
6036       if (VECTOR_MODE_P (mode0))
6037         op0 = safe_vector_operand (op0, mode0);
6038
6039       if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6040         op0 = copy_to_mode_reg (mode0, op0);
6041
6042       pat = GEN_FCN (icode) (target, op0, op0);
6043       if (! pat)
6044         return 0;
6045       emit_insn (pat);
6046       return target;
6047
6048     case BFIN_BUILTIN_MULT_1X32X32:
6049     case BFIN_BUILTIN_MULT_1X32X32NS:
6050       arg0 = CALL_EXPR_ARG (exp, 0);
6051       arg1 = CALL_EXPR_ARG (exp, 1);
6052       op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
6053       op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
6054       if (! target
6055           || !register_operand (target, SImode))
6056         target = gen_reg_rtx (SImode);
6057
6058       a1reg = gen_rtx_REG (PDImode, REG_A1);
6059       a0reg = gen_rtx_REG (PDImode, REG_A0);
6060       tmp1 = gen_lowpart (V2HImode, op0);
6061       tmp2 = gen_lowpart (V2HImode, op1);
6062       emit_insn (gen_flag_macinit1hi (a1reg,
6063                                       gen_lowpart (HImode, op0),
6064                                       gen_lowpart (HImode, op1),
6065                                       GEN_INT (MACFLAG_FU)));
6066       emit_insn (gen_lshrpdi3 (a1reg, a1reg, GEN_INT (16)));
6067
6068       if (fcode == BFIN_BUILTIN_MULT_1X32X32)
6069         emit_insn (gen_flag_mul_macv2hi_parts_acconly (a0reg, a1reg, tmp1, tmp2,
6070                                                        const1_rtx, const1_rtx,
6071                                                        const1_rtx, const0_rtx, a1reg,
6072                                                        const0_rtx, GEN_INT (MACFLAG_NONE),
6073                                                        GEN_INT (MACFLAG_M)));
6074       else
6075         {
6076           /* For saturating multiplication, there's exactly one special case
6077              to be handled: multiplying the smallest negative value with
6078              itself.  Due to shift correction in fractional multiplies, this
6079              can overflow.  Iff this happens, OP2 will contain 1, which, when
6080              added in 32 bits to the smallest negative, wraps to the largest
6081              positive, which is the result we want.  */
6082           op2 = gen_reg_rtx (V2HImode);
6083           emit_insn (gen_packv2hi (op2, tmp1, tmp2, const0_rtx, const0_rtx));
6084           emit_insn (gen_movsibi (gen_rtx_REG (BImode, REG_CC),
6085                                   gen_lowpart (SImode, op2)));
6086           emit_insn (gen_flag_mul_macv2hi_parts_acconly_andcc0 (a0reg, a1reg, tmp1, tmp2,
6087                                                                 const1_rtx, const1_rtx,
6088                                                                 const1_rtx, const0_rtx, a1reg,
6089                                                                 const0_rtx, GEN_INT (MACFLAG_NONE),
6090                                                                 GEN_INT (MACFLAG_M)));
6091           op2 = gen_reg_rtx (SImode);
6092           emit_insn (gen_movbisi (op2, gen_rtx_REG (BImode, REG_CC)));
6093         }
6094       emit_insn (gen_flag_machi_parts_acconly (a1reg, tmp2, tmp1,
6095                                                const1_rtx, const0_rtx,
6096                                                a1reg, const0_rtx, GEN_INT (MACFLAG_M)));
6097       emit_insn (gen_ashrpdi3 (a1reg, a1reg, GEN_INT (15)));
6098       emit_insn (gen_sum_of_accumulators (target, a0reg, a0reg, a1reg));
6099       if (fcode == BFIN_BUILTIN_MULT_1X32X32NS)
6100         emit_insn (gen_addsi3 (target, target, op2));
6101       return target;
6102
6103     case BFIN_BUILTIN_CPLX_MUL_16:
6104     case BFIN_BUILTIN_CPLX_MUL_16_S40:
6105       arg0 = CALL_EXPR_ARG (exp, 0);
6106       arg1 = CALL_EXPR_ARG (exp, 1);
6107       op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
6108       op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
6109       accvec = gen_reg_rtx (V2PDImode);
6110
6111       if (! target
6112           || GET_MODE (target) != V2HImode
6113           || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
6114         target = gen_reg_rtx (tmode);
6115       if (! register_operand (op0, GET_MODE (op0)))
6116         op0 = copy_to_mode_reg (GET_MODE (op0), op0);
6117       if (! register_operand (op1, GET_MODE (op1)))
6118         op1 = copy_to_mode_reg (GET_MODE (op1), op1);
6119
6120       if (fcode == BFIN_BUILTIN_CPLX_MUL_16)
6121         emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
6122                                                 const0_rtx, const0_rtx,
6123                                                 const1_rtx, GEN_INT (MACFLAG_W32)));
6124       else
6125         emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
6126                                                 const0_rtx, const0_rtx,
6127                                                 const1_rtx, GEN_INT (MACFLAG_NONE)));
6128       emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
6129                                          const1_rtx, const1_rtx,
6130                                          const0_rtx, accvec, const1_rtx, const0_rtx,
6131                                          GEN_INT (MACFLAG_NONE), accvec));
6132
6133       return target;
6134
6135     case BFIN_BUILTIN_CPLX_MAC_16:
6136     case BFIN_BUILTIN_CPLX_MSU_16:
6137     case BFIN_BUILTIN_CPLX_MAC_16_S40:
6138     case BFIN_BUILTIN_CPLX_MSU_16_S40:
6139       arg0 = CALL_EXPR_ARG (exp, 0);
6140       arg1 = CALL_EXPR_ARG (exp, 1);
6141       arg2 = CALL_EXPR_ARG (exp, 2);
6142       op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
6143       op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
6144       op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
6145       accvec = gen_reg_rtx (V2PDImode);
6146
6147       if (! target
6148           || GET_MODE (target) != V2HImode
6149           || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
6150         target = gen_reg_rtx (tmode);
6151       if (! register_operand (op1, GET_MODE (op1)))
6152         op1 = copy_to_mode_reg (GET_MODE (op1), op1);
6153       if (! register_operand (op2, GET_MODE (op2)))
6154         op2 = copy_to_mode_reg (GET_MODE (op2), op2);
6155
6156       tmp1 = gen_reg_rtx (SImode);
6157       tmp2 = gen_reg_rtx (SImode);
6158       emit_insn (gen_ashlsi3 (tmp1, gen_lowpart (SImode, op0), GEN_INT (16)));
6159       emit_move_insn (tmp2, gen_lowpart (SImode, op0));
6160       emit_insn (gen_movstricthi_1 (gen_lowpart (HImode, tmp2), const0_rtx));
6161       emit_insn (gen_load_accumulator_pair (accvec, tmp1, tmp2));
6162       if (fcode == BFIN_BUILTIN_CPLX_MAC_16
6163           || fcode == BFIN_BUILTIN_CPLX_MSU_16)
6164         emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx,
6165                                                    const0_rtx, const0_rtx,
6166                                                    const1_rtx, accvec, const0_rtx,
6167                                                    const0_rtx,
6168                                                    GEN_INT (MACFLAG_W32)));
6169       else
6170         emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx,
6171                                                    const0_rtx, const0_rtx,
6172                                                    const1_rtx, accvec, const0_rtx,
6173                                                    const0_rtx,
6174                                                    GEN_INT (MACFLAG_NONE)));
6175       if (fcode == BFIN_BUILTIN_CPLX_MAC_16
6176           || fcode == BFIN_BUILTIN_CPLX_MAC_16_S40)
6177         {
6178           tmp1 = const1_rtx;
6179           tmp2 = const0_rtx;
6180         }
6181       else
6182         {
6183           tmp1 = const0_rtx;
6184           tmp2 = const1_rtx;
6185         }
6186       emit_insn (gen_flag_macv2hi_parts (target, op1, op2, const1_rtx,
6187                                          const1_rtx, const1_rtx,
6188                                          const0_rtx, accvec, tmp1, tmp2,
6189                                          GEN_INT (MACFLAG_NONE), accvec));
6190
6191       return target;
6192
6193     case BFIN_BUILTIN_CPLX_SQU:
6194       arg0 = CALL_EXPR_ARG (exp, 0);
6195       op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
6196       accvec = gen_reg_rtx (V2PDImode);
6197       icode = CODE_FOR_flag_mulv2hi;
6198       tmp1 = gen_reg_rtx (V2HImode);
6199       tmp2 = gen_reg_rtx (V2HImode);
6200
6201       if (! target
6202           || GET_MODE (target) != V2HImode
6203           || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
6204         target = gen_reg_rtx (V2HImode);
6205       if (! register_operand (op0, GET_MODE (op0)))
6206         op0 = copy_to_mode_reg (GET_MODE (op0), op0);
6207
6208       emit_insn (gen_flag_mulv2hi (tmp1, op0, op0, GEN_INT (MACFLAG_NONE)));
6209
6210       emit_insn (gen_flag_mulhi_parts (gen_lowpart (HImode, tmp2), op0, op0,
6211                                        const0_rtx, const1_rtx,
6212                                        GEN_INT (MACFLAG_NONE)));
6213
6214       emit_insn (gen_ssaddhi3_high_parts (target, tmp2, tmp2, tmp2, const0_rtx,
6215                                           const0_rtx));
6216       emit_insn (gen_sssubhi3_low_parts (target, target, tmp1, tmp1,
6217                                          const0_rtx, const1_rtx));
6218
6219       return target;
6220
6221     default:
6222       break;
6223     }
6224
6225   for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
6226     if (d->code == fcode)
6227       return bfin_expand_binop_builtin (d->icode, exp, target,
6228                                         d->macflag);
6229
6230   for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
6231     if (d->code == fcode)
6232       return bfin_expand_unop_builtin (d->icode, exp, target);
6233
6234   gcc_unreachable ();
6235 }
6236 \f
6237 #undef TARGET_INIT_BUILTINS
6238 #define TARGET_INIT_BUILTINS bfin_init_builtins
6239
6240 #undef TARGET_EXPAND_BUILTIN
6241 #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
6242
6243 #undef TARGET_ASM_GLOBALIZE_LABEL
6244 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label 
6245
6246 #undef TARGET_ASM_FILE_START
6247 #define TARGET_ASM_FILE_START output_file_start
6248
6249 #undef TARGET_ATTRIBUTE_TABLE
6250 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
6251
6252 #undef TARGET_COMP_TYPE_ATTRIBUTES
6253 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
6254
6255 #undef TARGET_RTX_COSTS
6256 #define TARGET_RTX_COSTS bfin_rtx_costs
6257
6258 #undef  TARGET_ADDRESS_COST
6259 #define TARGET_ADDRESS_COST bfin_address_cost
6260
6261 #undef  TARGET_ASM_INTEGER
6262 #define TARGET_ASM_INTEGER bfin_assemble_integer
6263
6264 #undef TARGET_MACHINE_DEPENDENT_REORG
6265 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
6266
6267 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
6268 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
6269
6270 #undef TARGET_ASM_OUTPUT_MI_THUNK
6271 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
6272 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
6273 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
6274
6275 #undef TARGET_SCHED_ADJUST_COST
6276 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
6277
6278 #undef TARGET_SCHED_ISSUE_RATE
6279 #define TARGET_SCHED_ISSUE_RATE bfin_issue_rate
6280
6281 #undef TARGET_PROMOTE_PROTOTYPES
6282 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
6283 #undef TARGET_PROMOTE_FUNCTION_ARGS
6284 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
6285 #undef TARGET_PROMOTE_FUNCTION_RETURN
6286 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true
6287
6288 #undef TARGET_ARG_PARTIAL_BYTES
6289 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
6290
6291 #undef TARGET_PASS_BY_REFERENCE
6292 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
6293
6294 #undef TARGET_SETUP_INCOMING_VARARGS
6295 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
6296
6297 #undef TARGET_STRUCT_VALUE_RTX
6298 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
6299
6300 #undef TARGET_VECTOR_MODE_SUPPORTED_P
6301 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
6302
6303 #undef TARGET_HANDLE_OPTION
6304 #define TARGET_HANDLE_OPTION bfin_handle_option
6305
6306 #undef TARGET_DEFAULT_TARGET_FLAGS
6307 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
6308
6309 #undef TARGET_SECONDARY_RELOAD
6310 #define TARGET_SECONDARY_RELOAD bfin_secondary_reload
6311
6312 #undef TARGET_DELEGITIMIZE_ADDRESS
6313 #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address
6314
6315 #undef TARGET_CANNOT_FORCE_CONST_MEM
6316 #define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem
6317
6318 #undef TARGET_RETURN_IN_MEMORY
6319 #define TARGET_RETURN_IN_MEMORY bfin_return_in_memory
6320
6321 struct gcc_target targetm = TARGET_INITIALIZER;