OSDN Git Service

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