OSDN Git Service

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