OSDN Git Service

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