OSDN Git Service

* config/bfin/bfin.c (bfin_optimize_loop): If the LSETUP goes before
[pf3gnuchains/gcc-fork.git] / gcc / config / bfin / bfin.c
1 /* The Blackfin code generation auxiliary output file.
2    Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
3    Contributed by Analog Devices.
4
5    This file is part of GCC.
6
7    GCC is free software; you can redistribute it and/or modify it
8    under the terms of the GNU General Public License as published
9    by the Free Software Foundation; either version 3, or (at your
10    option) any later version.
11
12    GCC is distributed in the hope that it will be useful, but WITHOUT
13    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15    License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GCC; see the file COPYING3.  If not see
19    <http://www.gnu.org/licenses/>.  */
20
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "rtl.h"
26 #include "regs.h"
27 #include "hard-reg-set.h"
28 #include "real.h"
29 #include "insn-config.h"
30 #include "insn-codes.h"
31 #include "conditions.h"
32 #include "insn-flags.h"
33 #include "output.h"
34 #include "insn-attr.h"
35 #include "tree.h"
36 #include "flags.h"
37 #include "except.h"
38 #include "function.h"
39 #include "input.h"
40 #include "target.h"
41 #include "target-def.h"
42 #include "expr.h"
43 #include "toplev.h"
44 #include "recog.h"
45 #include "optabs.h"
46 #include "ggc.h"
47 #include "integrate.h"
48 #include "cgraph.h"
49 #include "langhooks.h"
50 #include "bfin-protos.h"
51 #include "tm-preds.h"
52 #include "tm-constrs.h"
53 #include "gt-bfin.h"
54 #include "basic-block.h"
55 #include "cfglayout.h"
56 #include "timevar.h"
57 #include "df.h"
58
59 /* A C structure for machine-specific, per-function data.
60    This is added to the cfun structure.  */
61 struct machine_function GTY(())
62 {
63   /* Set if we are notified by the doloop pass that a hardware loop
64      was created.  */
65   int has_hardware_loops;
66   /* Set if we create a memcpy pattern that uses loop registers.  */
67   int has_loopreg_clobber;
68 };
69
70 /* Test and compare insns in bfin.md store the information needed to
71    generate branch and scc insns here.  */
72 rtx bfin_compare_op0, bfin_compare_op1;
73
74 /* RTX for condition code flag register and RETS register */
75 extern GTY(()) rtx bfin_cc_rtx;
76 extern GTY(()) rtx bfin_rets_rtx;
77 rtx bfin_cc_rtx, bfin_rets_rtx;
78
79 int max_arg_registers = 0;
80
81 /* Arrays used when emitting register names.  */
82 const char *short_reg_names[]  =  SHORT_REGISTER_NAMES;
83 const char *high_reg_names[]   =  HIGH_REGISTER_NAMES;
84 const char *dregs_pair_names[] =  DREGS_PAIR_NAMES;
85 const char *byte_reg_names[]   =  BYTE_REGISTER_NAMES;
86
87 static int arg_regs[] = FUNCTION_ARG_REGISTERS;
88
89 /* Nonzero if -mshared-library-id was given.  */
90 static int bfin_lib_id_given;
91
92 /* Nonzero if -fschedule-insns2 was given.  We override it and
93    call the scheduler ourselves during reorg.  */
94 static int bfin_flag_schedule_insns2;
95
96 /* Determines whether we run variable tracking in machine dependent
97    reorganization.  */
98 static int bfin_flag_var_tracking;
99
100 /* -mcpu support */
101 bfin_cpu_t bfin_cpu_type = BFIN_CPU_UNKNOWN;
102
103 /* -msi-revision support. There are three special values:
104    -1      -msi-revision=none.
105    0xffff  -msi-revision=any.  */
106 int bfin_si_revision;
107
108 /* The workarounds enabled */
109 unsigned int bfin_workarounds = 0;
110
111 struct bfin_cpu
112 {
113   const char *name;
114   bfin_cpu_t type;
115   int si_revision;
116   unsigned int workarounds;
117 };
118
119 struct bfin_cpu bfin_cpus[] =
120 {
121   {"bf512", BFIN_CPU_BF512, 0x0000,
122    WA_SPECULATIVE_LOADS},
123
124   {"bf514", BFIN_CPU_BF514, 0x0000,
125    WA_SPECULATIVE_LOADS},
126
127   {"bf516", BFIN_CPU_BF516, 0x0000,
128    WA_SPECULATIVE_LOADS},
129
130   {"bf518", BFIN_CPU_BF518, 0x0000,
131    WA_SPECULATIVE_LOADS},
132
133   {"bf522", BFIN_CPU_BF522, 0x0002,
134    WA_SPECULATIVE_LOADS},
135   {"bf522", BFIN_CPU_BF522, 0x0001,
136    WA_SPECULATIVE_LOADS | WA_RETS},
137   {"bf522", BFIN_CPU_BF522, 0x0000,
138    WA_SPECULATIVE_LOADS | WA_RETS},
139
140   {"bf523", BFIN_CPU_BF523, 0x0002,
141    WA_SPECULATIVE_LOADS},
142   {"bf523", BFIN_CPU_BF523, 0x0001,
143    WA_SPECULATIVE_LOADS | WA_RETS},
144   {"bf523", BFIN_CPU_BF523, 0x0000,
145    WA_SPECULATIVE_LOADS | WA_RETS},
146
147   {"bf524", BFIN_CPU_BF524, 0x0002,
148    WA_SPECULATIVE_LOADS},
149   {"bf524", BFIN_CPU_BF524, 0x0001,
150    WA_SPECULATIVE_LOADS | WA_RETS},
151   {"bf524", BFIN_CPU_BF524, 0x0000,
152    WA_SPECULATIVE_LOADS | WA_RETS},
153
154   {"bf525", BFIN_CPU_BF525, 0x0002,
155    WA_SPECULATIVE_LOADS},
156   {"bf525", BFIN_CPU_BF525, 0x0001,
157    WA_SPECULATIVE_LOADS | WA_RETS},
158   {"bf525", BFIN_CPU_BF525, 0x0000,
159    WA_SPECULATIVE_LOADS | WA_RETS},
160
161   {"bf526", BFIN_CPU_BF526, 0x0002,
162    WA_SPECULATIVE_LOADS},
163   {"bf526", BFIN_CPU_BF526, 0x0001,
164    WA_SPECULATIVE_LOADS | WA_RETS},
165   {"bf526", BFIN_CPU_BF526, 0x0000,
166    WA_SPECULATIVE_LOADS | WA_RETS},
167
168   {"bf527", BFIN_CPU_BF527, 0x0002,
169    WA_SPECULATIVE_LOADS},
170   {"bf527", BFIN_CPU_BF527, 0x0001,
171    WA_SPECULATIVE_LOADS | WA_RETS},
172   {"bf527", BFIN_CPU_BF527, 0x0000,
173    WA_SPECULATIVE_LOADS | WA_RETS},
174
175   {"bf531", BFIN_CPU_BF531, 0x0006,
176    WA_SPECULATIVE_LOADS},
177   {"bf531", BFIN_CPU_BF531, 0x0005,
178    WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315},
179   {"bf531", BFIN_CPU_BF531, 0x0004,
180    WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
181    | WA_05000283 | WA_05000257 | WA_05000315},
182   {"bf531", BFIN_CPU_BF531, 0x0003,
183    WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
184    | WA_05000283 | WA_05000257 | WA_05000315},
185
186   {"bf532", BFIN_CPU_BF532, 0x0006,
187    WA_SPECULATIVE_LOADS},
188   {"bf532", BFIN_CPU_BF532, 0x0005,
189    WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315},
190   {"bf532", BFIN_CPU_BF532, 0x0004,
191    WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
192    | WA_05000283 | WA_05000257 | WA_05000315},
193   {"bf532", BFIN_CPU_BF532, 0x0003,
194    WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
195    | WA_05000283 | WA_05000257 | WA_05000315},
196
197   {"bf533", BFIN_CPU_BF533, 0x0006,
198    WA_SPECULATIVE_LOADS},
199   {"bf533", BFIN_CPU_BF533, 0x0005,
200    WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315},
201   {"bf533", BFIN_CPU_BF533, 0x0004,
202    WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
203    | WA_05000283 | WA_05000257 | WA_05000315},
204   {"bf533", BFIN_CPU_BF533, 0x0003,
205    WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
206    | WA_05000283 | WA_05000257 | WA_05000315},
207
208   {"bf534", BFIN_CPU_BF534, 0x0003,
209    WA_SPECULATIVE_LOADS | WA_RETS},
210   {"bf534", BFIN_CPU_BF534, 0x0002,
211    WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
212    | WA_05000283 | WA_05000257 | WA_05000315},
213   {"bf534", BFIN_CPU_BF534, 0x0001,
214    WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
215    | WA_05000283 | WA_05000257 | WA_05000315},
216
217   {"bf536", BFIN_CPU_BF536, 0x0003,
218    WA_SPECULATIVE_LOADS | WA_RETS},
219   {"bf536", BFIN_CPU_BF536, 0x0002,
220    WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
221    | WA_05000283 | WA_05000257 | WA_05000315},
222   {"bf536", BFIN_CPU_BF536, 0x0001,
223    WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
224    | WA_05000283 | WA_05000257 | WA_05000315},
225
226   {"bf537", BFIN_CPU_BF537, 0x0003,
227    WA_SPECULATIVE_LOADS | WA_RETS},
228   {"bf537", BFIN_CPU_BF537, 0x0002,
229    WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
230    | WA_05000283 | WA_05000257 | WA_05000315},
231   {"bf537", BFIN_CPU_BF537, 0x0001,
232    WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
233    | WA_05000283 | WA_05000257 | WA_05000315},
234
235   {"bf538", BFIN_CPU_BF538, 0x0005,
236    WA_SPECULATIVE_LOADS},
237   {"bf538", BFIN_CPU_BF538, 0x0004,
238    WA_SPECULATIVE_LOADS | WA_RETS},
239   {"bf538", BFIN_CPU_BF538, 0x0003,
240    WA_SPECULATIVE_LOADS | WA_RETS
241    | WA_05000283 | WA_05000315},
242   {"bf538", BFIN_CPU_BF538, 0x0002,
243    WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000257 | WA_05000315},
244
245   {"bf539", BFIN_CPU_BF539, 0x0005,
246    WA_SPECULATIVE_LOADS},
247   {"bf539", BFIN_CPU_BF539, 0x0004,
248    WA_SPECULATIVE_LOADS | WA_RETS},
249   {"bf539", BFIN_CPU_BF539, 0x0003,
250    WA_SPECULATIVE_LOADS | WA_RETS
251    | WA_05000283 | WA_05000315},
252   {"bf539", BFIN_CPU_BF539, 0x0002,
253    WA_SPECULATIVE_LOADS | WA_RETS
254    | WA_05000283 | WA_05000257 | WA_05000315},
255
256   {"bf542", BFIN_CPU_BF542, 0x0002,
257    WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS},
258   {"bf542", BFIN_CPU_BF542, 0x0001,
259    WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
260   {"bf542", BFIN_CPU_BF542, 0x0000,
261    WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
262
263   {"bf544", BFIN_CPU_BF544, 0x0002,
264    WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS},
265   {"bf544", BFIN_CPU_BF544, 0x0001,
266    WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
267   {"bf544", BFIN_CPU_BF544, 0x0000,
268    WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
269
270   {"bf547", BFIN_CPU_BF547, 0x0002,
271    WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS},
272   {"bf547", BFIN_CPU_BF547, 0x0001,
273    WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
274   {"bf547", BFIN_CPU_BF547, 0x0000,
275    WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
276
277   {"bf548", BFIN_CPU_BF548, 0x0002,
278    WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS},
279   {"bf548", BFIN_CPU_BF548, 0x0001,
280    WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
281   {"bf548", BFIN_CPU_BF548, 0x0000,
282    WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
283
284   {"bf549", BFIN_CPU_BF549, 0x0002,
285    WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS},
286   {"bf549", BFIN_CPU_BF549, 0x0001,
287    WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
288   {"bf549", BFIN_CPU_BF549, 0x0000,
289    WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
290
291   {"bf561", BFIN_CPU_BF561, 0x0005, WA_RETS
292    | WA_05000283 | WA_05000315},
293   {"bf561", BFIN_CPU_BF561, 0x0003,
294    WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
295    | WA_05000283 | WA_05000257 | WA_05000315},
296   {"bf561", BFIN_CPU_BF561, 0x0002,
297    WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
298    | WA_05000283 | WA_05000257 | WA_05000315},
299
300   {NULL, 0, 0, 0}
301 };
302
303 int splitting_for_sched;
304
305 static void
306 bfin_globalize_label (FILE *stream, const char *name)
307 {
308   fputs (".global ", stream);
309   assemble_name (stream, name);
310   fputc (';',stream);
311   fputc ('\n',stream);
312 }
313
314 static void 
315 output_file_start (void) 
316 {
317   FILE *file = asm_out_file;
318   int i;
319
320   /* Variable tracking should be run after all optimizations which change order
321      of insns.  It also needs a valid CFG.  This can't be done in
322      override_options, because flag_var_tracking is finalized after
323      that.  */
324   bfin_flag_var_tracking = flag_var_tracking;
325   flag_var_tracking = 0;
326
327   fprintf (file, ".file \"%s\";\n", input_filename);
328   
329   for (i = 0; arg_regs[i] >= 0; i++)
330     ;
331   max_arg_registers = i;        /* how many arg reg used  */
332 }
333
334 /* Called early in the compilation to conditionally modify
335    fixed_regs/call_used_regs.  */
336
337 void 
338 conditional_register_usage (void)
339 {
340   /* initialize condition code flag register rtx */
341   bfin_cc_rtx = gen_rtx_REG (BImode, REG_CC);
342   bfin_rets_rtx = gen_rtx_REG (Pmode, REG_RETS);
343 }
344
345 /* Examine machine-dependent attributes of function type FUNTYPE and return its
346    type.  See the definition of E_FUNKIND.  */
347
348 static e_funkind
349 funkind (const_tree funtype)
350 {
351   tree attrs = TYPE_ATTRIBUTES (funtype);
352   if (lookup_attribute ("interrupt_handler", attrs))
353     return INTERRUPT_HANDLER;
354   else if (lookup_attribute ("exception_handler", attrs))
355     return EXCPT_HANDLER;
356   else if (lookup_attribute ("nmi_handler", attrs))
357     return NMI_HANDLER;
358   else
359     return SUBROUTINE;
360 }
361 \f
362 /* Legitimize PIC addresses.  If the address is already position-independent,
363    we return ORIG.  Newly generated position-independent addresses go into a
364    reg.  This is REG if nonzero, otherwise we allocate register(s) as
365    necessary.  PICREG is the register holding the pointer to the PIC offset
366    table.  */
367
368 static rtx
369 legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
370 {
371   rtx addr = orig;
372   rtx new_rtx = orig;
373
374   if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
375     {
376       int unspec;
377       rtx tmp;
378
379       if (TARGET_ID_SHARED_LIBRARY)
380         unspec = UNSPEC_MOVE_PIC;
381       else if (GET_CODE (addr) == SYMBOL_REF
382                && SYMBOL_REF_FUNCTION_P (addr))
383         unspec = UNSPEC_FUNCDESC_GOT17M4;
384       else
385         unspec = UNSPEC_MOVE_FDPIC;
386
387       if (reg == 0)
388         {
389           gcc_assert (can_create_pseudo_p ());
390           reg = gen_reg_rtx (Pmode);
391         }
392
393       tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), unspec);
394       new_rtx = gen_const_mem (Pmode, gen_rtx_PLUS (Pmode, picreg, tmp));
395
396       emit_move_insn (reg, new_rtx);
397       if (picreg == pic_offset_table_rtx)
398         crtl->uses_pic_offset_table = 1;
399       return reg;
400     }
401
402   else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
403     {
404       rtx base;
405
406       if (GET_CODE (addr) == CONST)
407         {
408           addr = XEXP (addr, 0);
409           gcc_assert (GET_CODE (addr) == PLUS);
410         }
411
412       if (XEXP (addr, 0) == picreg)
413         return orig;
414
415       if (reg == 0)
416         {
417           gcc_assert (can_create_pseudo_p ());
418           reg = gen_reg_rtx (Pmode);
419         }
420
421       base = legitimize_pic_address (XEXP (addr, 0), reg, picreg);
422       addr = legitimize_pic_address (XEXP (addr, 1),
423                                      base == reg ? NULL_RTX : reg,
424                                      picreg);
425
426       if (GET_CODE (addr) == CONST_INT)
427         {
428           gcc_assert (! reload_in_progress && ! reload_completed);
429           addr = force_reg (Pmode, addr);
430         }
431
432       if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
433         {
434           base = gen_rtx_PLUS (Pmode, base, XEXP (addr, 0));
435           addr = XEXP (addr, 1);
436         }
437
438       return gen_rtx_PLUS (Pmode, base, addr);
439     }
440
441   return new_rtx;
442 }
443 \f
444 /* Stack frame layout. */
445
446 /* For a given REGNO, determine whether it must be saved in the function
447    prologue.  IS_INTHANDLER specifies whether we're generating a normal
448    prologue or an interrupt/exception one.  */
449 static bool
450 must_save_p (bool is_inthandler, unsigned regno)
451 {
452   if (D_REGNO_P (regno))
453     {
454       bool is_eh_return_reg = false;
455       if (crtl->calls_eh_return)
456         {
457           unsigned j;
458           for (j = 0; ; j++)
459             {
460               unsigned test = EH_RETURN_DATA_REGNO (j);
461               if (test == INVALID_REGNUM)
462                 break;
463               if (test == regno)
464                 is_eh_return_reg = true;
465             }
466         }
467
468       return (is_eh_return_reg
469               || (df_regs_ever_live_p (regno)
470                   && !fixed_regs[regno]
471                   && (is_inthandler || !call_used_regs[regno])));
472     }
473   else if (P_REGNO_P (regno))
474     {
475       return ((df_regs_ever_live_p (regno)
476                && !fixed_regs[regno]
477                && (is_inthandler || !call_used_regs[regno]))
478               || (is_inthandler
479                   && (ENABLE_WA_05000283 || ENABLE_WA_05000315)
480                   && regno == REG_P5)
481               || (!TARGET_FDPIC
482                   && regno == PIC_OFFSET_TABLE_REGNUM
483                   && (crtl->uses_pic_offset_table
484                       || (TARGET_ID_SHARED_LIBRARY && !current_function_is_leaf))));
485     }
486   else
487     return ((is_inthandler || !call_used_regs[regno])
488             && (df_regs_ever_live_p (regno)
489                 || (!leaf_function_p () && call_used_regs[regno])));
490
491 }
492
493 /* Compute the number of DREGS to save with a push_multiple operation.
494    This could include registers that aren't modified in the function,
495    since push_multiple only takes a range of registers.
496    If IS_INTHANDLER, then everything that is live must be saved, even
497    if normally call-clobbered.
498    If CONSECUTIVE, return the number of registers we can save in one
499    instruction with a push/pop multiple instruction.  */
500
501 static int
502 n_dregs_to_save (bool is_inthandler, bool consecutive)
503 {
504   int count = 0;
505   unsigned i;
506
507   for (i = REG_R7 + 1; i-- != REG_R0;)
508     {
509       if (must_save_p (is_inthandler, i))
510         count++;
511       else if (consecutive)
512         return count;
513     }
514   return count;
515 }
516
517 /* Like n_dregs_to_save, but compute number of PREGS to save.  */
518
519 static int
520 n_pregs_to_save (bool is_inthandler, bool consecutive)
521 {
522   int count = 0;
523   unsigned i;
524
525   for (i = REG_P5 + 1; i-- != REG_P0;)
526     if (must_save_p (is_inthandler, i))
527       count++;
528     else if (consecutive)
529       return count;
530   return count;
531 }
532
533 /* Determine if we are going to save the frame pointer in the prologue.  */
534
535 static bool
536 must_save_fp_p (void)
537 {
538   return frame_pointer_needed || df_regs_ever_live_p (REG_FP);
539 }
540
541 static bool
542 stack_frame_needed_p (void)
543 {
544   /* EH return puts a new return address into the frame using an
545      address relative to the frame pointer.  */
546   if (crtl->calls_eh_return)
547     return true;
548   return frame_pointer_needed;
549 }
550
551 /* Emit code to save registers in the prologue.  SAVEALL is nonzero if we
552    must save all registers; this is used for interrupt handlers.
553    SPREG contains (reg:SI REG_SP).  IS_INTHANDLER is true if we're doing
554    this for an interrupt (or exception) handler.  */
555
556 static void
557 expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler)
558 {
559   rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
560   rtx predec = gen_rtx_MEM (SImode, predec1);
561   int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler, false);
562   int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler, false);
563   int ndregs_consec = saveall ? 8 : n_dregs_to_save (is_inthandler, true);
564   int npregs_consec = saveall ? 6 : n_pregs_to_save (is_inthandler, true);
565   int dregno, pregno;
566   int total_consec = ndregs_consec + npregs_consec;
567   int i, d_to_save;
568
569   if (saveall || is_inthandler)
570     {
571       rtx insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
572
573       RTX_FRAME_RELATED_P (insn) = 1;
574       for (dregno = REG_LT0; dregno <= REG_LB1; dregno++)
575         if (! current_function_is_leaf
576             || cfun->machine->has_hardware_loops
577             || cfun->machine->has_loopreg_clobber
578             || (ENABLE_WA_05000257
579                 && (dregno == REG_LC0 || dregno == REG_LC1)))
580           {
581             insn = emit_move_insn (predec, gen_rtx_REG (SImode, dregno));
582             RTX_FRAME_RELATED_P (insn) = 1;
583           }
584     }
585
586   if (total_consec != 0)
587     {
588       rtx insn;
589       rtx val = GEN_INT (-total_consec * 4);
590       rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_consec + 2));
591
592       XVECEXP (pat, 0, 0) = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, val),
593                                             UNSPEC_PUSH_MULTIPLE);
594       XVECEXP (pat, 0, total_consec + 1) = gen_rtx_SET (VOIDmode, spreg,
595                                                         gen_rtx_PLUS (Pmode,
596                                                                       spreg,
597                                                                       val));
598       RTX_FRAME_RELATED_P (XVECEXP (pat, 0, total_consec + 1)) = 1;
599       d_to_save = ndregs_consec;
600       dregno = REG_R7 + 1 - ndregs_consec;
601       pregno = REG_P5 + 1 - npregs_consec;
602       for (i = 0; i < total_consec; i++)
603         {
604           rtx memref = gen_rtx_MEM (word_mode,
605                                     gen_rtx_PLUS (Pmode, spreg,
606                                                   GEN_INT (- i * 4 - 4)));
607           rtx subpat;
608           if (d_to_save > 0)
609             {
610               subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
611                                                                    dregno++));
612               d_to_save--;
613             }
614           else
615             {
616               subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
617                                                                    pregno++));
618             }
619           XVECEXP (pat, 0, i + 1) = subpat;
620           RTX_FRAME_RELATED_P (subpat) = 1;
621         }
622       insn = emit_insn (pat);
623       RTX_FRAME_RELATED_P (insn) = 1;
624     }
625
626   for (dregno = REG_R0; ndregs != ndregs_consec; dregno++)
627     {
628       if (must_save_p (is_inthandler, dregno))
629         {
630           rtx insn = emit_move_insn (predec, gen_rtx_REG (word_mode, dregno));
631           RTX_FRAME_RELATED_P (insn) = 1;
632           ndregs--;
633         }
634     }
635   for (pregno = REG_P0; npregs != npregs_consec; pregno++)
636     {
637       if (must_save_p (is_inthandler, pregno))
638         {
639           rtx insn = emit_move_insn (predec, gen_rtx_REG (word_mode, pregno));
640           RTX_FRAME_RELATED_P (insn) = 1;
641           npregs--;
642         }
643     }
644   for (i = REG_P7 + 1; i < REG_CC; i++)
645     if (saveall 
646         || (is_inthandler
647             && (df_regs_ever_live_p (i)
648                 || (!leaf_function_p () && call_used_regs[i]))))
649       {
650         rtx insn;
651         if (i == REG_A0 || i == REG_A1)
652           insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1),
653                                  gen_rtx_REG (PDImode, i));
654         else
655           insn = emit_move_insn (predec, gen_rtx_REG (SImode, i));
656         RTX_FRAME_RELATED_P (insn) = 1;
657       }
658 }
659
660 /* Emit code to restore registers in the epilogue.  SAVEALL is nonzero if we
661    must save all registers; this is used for interrupt handlers.
662    SPREG contains (reg:SI REG_SP).  IS_INTHANDLER is true if we're doing
663    this for an interrupt (or exception) handler.  */
664
665 static void
666 expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler)
667 {
668   rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
669   rtx postinc = gen_rtx_MEM (SImode, postinc1);
670
671   int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler, false);
672   int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler, false);
673   int ndregs_consec = saveall ? 8 : n_dregs_to_save (is_inthandler, true);
674   int npregs_consec = saveall ? 6 : n_pregs_to_save (is_inthandler, true);
675   int total_consec = ndregs_consec + npregs_consec;
676   int i, regno;
677   rtx insn;
678
679   /* A slightly crude technique to stop flow from trying to delete "dead"
680      insns.  */
681   MEM_VOLATILE_P (postinc) = 1;
682
683   for (i = REG_CC - 1; i > REG_P7; i--)
684     if (saveall
685         || (is_inthandler
686             && (df_regs_ever_live_p (i)
687                 || (!leaf_function_p () && call_used_regs[i]))))
688       {
689         if (i == REG_A0 || i == REG_A1)
690           {
691             rtx mem = gen_rtx_MEM (PDImode, postinc1);
692             MEM_VOLATILE_P (mem) = 1;
693             emit_move_insn (gen_rtx_REG (PDImode, i), mem);
694           }
695         else
696           emit_move_insn (gen_rtx_REG (SImode, i), postinc);
697       }
698
699   regno = REG_P5 - npregs_consec;
700   for (; npregs != npregs_consec; regno--)
701     {
702       if (must_save_p (is_inthandler, regno))
703         {
704           emit_move_insn (gen_rtx_REG (word_mode, regno), postinc);
705           npregs--;
706         }
707     }
708   regno = REG_R7 - ndregs_consec;
709   for (; ndregs != ndregs_consec; regno--)
710     {
711       if (must_save_p (is_inthandler, regno))
712         {
713           emit_move_insn (gen_rtx_REG (word_mode, regno), postinc);
714           ndregs--;
715         }
716     }
717
718   if (total_consec != 0)
719     {
720       rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_consec + 1));
721       XVECEXP (pat, 0, 0)
722         = gen_rtx_SET (VOIDmode, spreg,
723                        gen_rtx_PLUS (Pmode, spreg,
724                                      GEN_INT (total_consec * 4)));
725
726       if (npregs_consec > 0)
727         regno = REG_P5 + 1;
728       else
729         regno = REG_R7 + 1;
730
731       for (i = 0; i < total_consec; i++)
732         {
733           rtx addr = (i > 0
734                       ? gen_rtx_PLUS (Pmode, spreg, GEN_INT (i * 4))
735                       : spreg);
736           rtx memref = gen_rtx_MEM (word_mode, addr);
737
738           regno--;
739           XVECEXP (pat, 0, i + 1)
740             = gen_rtx_SET (VOIDmode, gen_rtx_REG (word_mode, regno), memref);
741
742           if (npregs_consec > 0)
743             {
744               if (--npregs_consec == 0)
745                 regno = REG_R7 + 1;
746             }
747         }
748
749       insn = emit_insn (pat);
750       RTX_FRAME_RELATED_P (insn) = 1;
751     }
752   if (saveall || is_inthandler)
753     {
754       for (regno = REG_LB1; regno >= REG_LT0; regno--)
755         if (! current_function_is_leaf
756             || cfun->machine->has_hardware_loops
757             || cfun->machine->has_loopreg_clobber
758             || (ENABLE_WA_05000257 && (regno == REG_LC0 || regno == REG_LC1)))
759           emit_move_insn (gen_rtx_REG (SImode, regno), postinc);
760
761       emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
762     }
763 }
764
765 /* Perform any needed actions needed for a function that is receiving a
766    variable number of arguments.
767
768    CUM is as above.
769
770    MODE and TYPE are the mode and type of the current parameter.
771
772    PRETEND_SIZE is a variable that should be set to the amount of stack
773    that must be pushed by the prolog to pretend that our caller pushed
774    it.
775
776    Normally, this macro will push all remaining incoming registers on the
777    stack and set PRETEND_SIZE to the length of the registers pushed.  
778
779    Blackfin specific :
780    - VDSP C compiler manual (our ABI) says that a variable args function
781      should save the R0, R1 and R2 registers in the stack.
782    - The caller will always leave space on the stack for the
783      arguments that are passed in registers, so we dont have
784      to leave any extra space.
785    - now, the vastart pointer can access all arguments from the stack.  */
786
787 static void
788 setup_incoming_varargs (CUMULATIVE_ARGS *cum,
789                         enum machine_mode mode ATTRIBUTE_UNUSED,
790                         tree type ATTRIBUTE_UNUSED, int *pretend_size,
791                         int no_rtl)
792 {
793   rtx mem;
794   int i;
795
796   if (no_rtl)
797     return;
798
799   /* The move for named arguments will be generated automatically by the
800      compiler.  We need to generate the move rtx for the unnamed arguments
801      if they are in the first 3 words.  We assume at least 1 named argument
802      exists, so we never generate [ARGP] = R0 here.  */
803
804   for (i = cum->words + 1; i < max_arg_registers; i++)
805     {
806       mem = gen_rtx_MEM (Pmode,
807                          plus_constant (arg_pointer_rtx, (i * UNITS_PER_WORD)));
808       emit_move_insn (mem, gen_rtx_REG (Pmode, i));
809     }
810
811   *pretend_size = 0;
812 }
813
814 /* Value should be nonzero if functions must have frame pointers.
815    Zero means the frame pointer need not be set up (and parms may
816    be accessed via the stack pointer) in functions that seem suitable.  */
817
818 int
819 bfin_frame_pointer_required (void) 
820 {
821   e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
822
823   if (fkind != SUBROUTINE)
824     return 1;
825
826   /* We turn on -fomit-frame-pointer if -momit-leaf-frame-pointer is used,
827      so we have to override it for non-leaf functions.  */
828   if (TARGET_OMIT_LEAF_FRAME_POINTER && ! current_function_is_leaf)
829     return 1;
830
831   return 0;
832 }
833
834 /* Return the number of registers pushed during the prologue.  */
835
836 static int
837 n_regs_saved_by_prologue (void)
838 {
839   e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
840   bool is_inthandler = fkind != SUBROUTINE;
841   tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
842   bool all = (lookup_attribute ("saveall", attrs) != NULL_TREE
843               || (is_inthandler && !current_function_is_leaf));
844   int ndregs = all ? 8 : n_dregs_to_save (is_inthandler, false);
845   int npregs = all ? 6 : n_pregs_to_save (is_inthandler, false);
846   int n = ndregs + npregs;
847   int i;
848
849   if (all || stack_frame_needed_p ())
850     /* We use a LINK instruction in this case.  */
851     n += 2;
852   else
853     {
854       if (must_save_fp_p ())
855         n++;
856       if (! current_function_is_leaf)
857         n++;
858     }
859
860   if (fkind != SUBROUTINE || all)
861     {
862       /* Increment once for ASTAT.  */
863       n++;
864       if (! current_function_is_leaf
865           || cfun->machine->has_hardware_loops
866           || cfun->machine->has_loopreg_clobber)
867         {
868           n += 6;
869         }
870     }
871
872   if (fkind != SUBROUTINE)
873     {
874       /* RETE/X/N.  */
875       if (lookup_attribute ("nesting", attrs))
876         n++;
877     }
878
879   for (i = REG_P7 + 1; i < REG_CC; i++)
880     if (all
881         || (fkind != SUBROUTINE
882             && (df_regs_ever_live_p (i)
883                 || (!leaf_function_p () && call_used_regs[i]))))
884       n += i == REG_A0 || i == REG_A1 ? 2 : 1;
885
886   return n;
887 }
888
889 /* Return the offset between two registers, one to be eliminated, and the other
890    its replacement, at the start of a routine.  */
891
892 HOST_WIDE_INT
893 bfin_initial_elimination_offset (int from, int to)
894 {
895   HOST_WIDE_INT offset = 0;
896
897   if (from == ARG_POINTER_REGNUM)
898     offset = n_regs_saved_by_prologue () * 4;
899
900   if (to == STACK_POINTER_REGNUM)
901     {
902       if (crtl->outgoing_args_size >= FIXED_STACK_AREA)
903         offset += crtl->outgoing_args_size;
904       else if (crtl->outgoing_args_size)
905         offset += FIXED_STACK_AREA;
906
907       offset += get_frame_size ();
908     }
909
910   return offset;
911 }
912
913 /* Emit code to load a constant CONSTANT into register REG; setting
914    RTX_FRAME_RELATED_P on all insns we generate if RELATED is true.
915    Make sure that the insns we generate need not be split.  */
916
917 static void
918 frame_related_constant_load (rtx reg, HOST_WIDE_INT constant, bool related)
919 {
920   rtx insn;
921   rtx cst = GEN_INT (constant);
922
923   if (constant >= -32768 && constant < 65536)
924     insn = emit_move_insn (reg, cst);
925   else
926     {
927       /* We don't call split_load_immediate here, since dwarf2out.c can get
928          confused about some of the more clever sequences it can generate.  */
929       insn = emit_insn (gen_movsi_high (reg, cst));
930       if (related)
931         RTX_FRAME_RELATED_P (insn) = 1;
932       insn = emit_insn (gen_movsi_low (reg, reg, cst));
933     }
934   if (related)
935     RTX_FRAME_RELATED_P (insn) = 1;
936 }
937
938 /* Generate efficient code to add a value to a P register.
939    Set RTX_FRAME_RELATED_P on the generated insns if FRAME is nonzero.
940    EPILOGUE_P is zero if this function is called for prologue,
941    otherwise it's nonzero. And it's less than zero if this is for
942    sibcall epilogue.  */
943
944 static void
945 add_to_reg (rtx reg, HOST_WIDE_INT value, int frame, int epilogue_p)
946 {
947   if (value == 0)
948     return;
949
950   /* Choose whether to use a sequence using a temporary register, or
951      a sequence with multiple adds.  We can add a signed 7-bit value
952      in one instruction.  */
953   if (value > 120 || value < -120)
954     {
955       rtx tmpreg;
956       rtx tmpreg2;
957       rtx insn;
958
959       tmpreg2 = NULL_RTX;
960
961       /* For prologue or normal epilogue, P1 can be safely used
962          as the temporary register. For sibcall epilogue, we try to find
963          a call used P register, which will be restored in epilogue.
964          If we cannot find such a P register, we have to use one I register
965          to help us.  */
966
967       if (epilogue_p >= 0)
968         tmpreg = gen_rtx_REG (SImode, REG_P1);
969       else
970         {
971           int i;
972           for (i = REG_P0; i <= REG_P5; i++)
973             if ((df_regs_ever_live_p (i) && ! call_used_regs[i])
974                 || (!TARGET_FDPIC
975                     && i == PIC_OFFSET_TABLE_REGNUM
976                     && (crtl->uses_pic_offset_table
977                         || (TARGET_ID_SHARED_LIBRARY
978                             && ! current_function_is_leaf))))
979               break;
980           if (i <= REG_P5)
981             tmpreg = gen_rtx_REG (SImode, i);
982           else
983             {
984               tmpreg = gen_rtx_REG (SImode, REG_P1);
985               tmpreg2 = gen_rtx_REG (SImode, REG_I0);
986               emit_move_insn (tmpreg2, tmpreg);
987             }
988         }
989
990       if (frame)
991         frame_related_constant_load (tmpreg, value, TRUE);
992       else
993         insn = emit_move_insn (tmpreg, GEN_INT (value));
994
995       insn = emit_insn (gen_addsi3 (reg, reg, tmpreg));
996       if (frame)
997         RTX_FRAME_RELATED_P (insn) = 1;
998
999       if (tmpreg2 != NULL_RTX)
1000         emit_move_insn (tmpreg, tmpreg2);
1001     }
1002   else
1003     do
1004       {
1005         int size = value;
1006         rtx insn;
1007
1008         if (size > 60)
1009           size = 60;
1010         else if (size < -60)
1011           /* We could use -62, but that would leave the stack unaligned, so
1012              it's no good.  */
1013           size = -60;
1014
1015         insn = emit_insn (gen_addsi3 (reg, reg, GEN_INT (size)));
1016         if (frame)
1017           RTX_FRAME_RELATED_P (insn) = 1;
1018         value -= size;
1019       }
1020     while (value != 0);
1021 }
1022
1023 /* Generate a LINK insn for a frame sized FRAME_SIZE.  If this constant
1024    is too large, generate a sequence of insns that has the same effect.
1025    SPREG contains (reg:SI REG_SP).  */
1026
1027 static void
1028 emit_link_insn (rtx spreg, HOST_WIDE_INT frame_size)
1029 {
1030   HOST_WIDE_INT link_size = frame_size;
1031   rtx insn;
1032   int i;
1033
1034   if (link_size > 262140)
1035     link_size = 262140;
1036
1037   /* Use a LINK insn with as big a constant as possible, then subtract
1038      any remaining size from the SP.  */
1039   insn = emit_insn (gen_link (GEN_INT (-8 - link_size)));
1040   RTX_FRAME_RELATED_P (insn) = 1;
1041
1042   for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
1043     {
1044       rtx set = XVECEXP (PATTERN (insn), 0, i);
1045       gcc_assert (GET_CODE (set) == SET);
1046       RTX_FRAME_RELATED_P (set) = 1;
1047     }
1048
1049   frame_size -= link_size;
1050
1051   if (frame_size > 0)
1052     {
1053       /* Must use a call-clobbered PREG that isn't the static chain.  */
1054       rtx tmpreg = gen_rtx_REG (Pmode, REG_P1);
1055
1056       frame_related_constant_load (tmpreg, -frame_size, TRUE);
1057       insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg));
1058       RTX_FRAME_RELATED_P (insn) = 1;
1059     }
1060 }
1061
1062 /* Return the number of bytes we must reserve for outgoing arguments
1063    in the current function's stack frame.  */
1064
1065 static HOST_WIDE_INT
1066 arg_area_size (void)
1067 {
1068   if (crtl->outgoing_args_size)
1069     {
1070       if (crtl->outgoing_args_size >= FIXED_STACK_AREA)
1071         return crtl->outgoing_args_size;
1072       else
1073         return FIXED_STACK_AREA;
1074     }
1075   return 0;
1076 }
1077
1078 /* Save RETS and FP, and allocate a stack frame.  ALL is true if the
1079    function must save all its registers (true only for certain interrupt
1080    handlers).  */
1081
1082 static void
1083 do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all)
1084 {
1085   frame_size += arg_area_size ();
1086
1087   if (all || stack_frame_needed_p ()
1088       || (must_save_fp_p () && ! current_function_is_leaf))
1089     emit_link_insn (spreg, frame_size);
1090   else
1091     {
1092       if (! current_function_is_leaf)
1093         {
1094           rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
1095                                             gen_rtx_PRE_DEC (Pmode, spreg)),
1096                                bfin_rets_rtx);
1097           rtx insn = emit_insn (pat);
1098           RTX_FRAME_RELATED_P (insn) = 1;
1099         }
1100       if (must_save_fp_p ())
1101         {
1102           rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
1103                                             gen_rtx_PRE_DEC (Pmode, spreg)),
1104                                gen_rtx_REG (Pmode, REG_FP));
1105           rtx insn = emit_insn (pat);
1106           RTX_FRAME_RELATED_P (insn) = 1;
1107         }
1108       add_to_reg (spreg, -frame_size, 1, 0);
1109     }
1110 }
1111
1112 /* Like do_link, but used for epilogues to deallocate the stack frame.
1113    EPILOGUE_P is zero if this function is called for prologue,
1114    otherwise it's nonzero. And it's less than zero if this is for
1115    sibcall epilogue.  */
1116
1117 static void
1118 do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all, int epilogue_p)
1119 {
1120   frame_size += arg_area_size ();
1121
1122   if (all || stack_frame_needed_p ())
1123     emit_insn (gen_unlink ());
1124   else 
1125     {
1126       rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg));
1127
1128       add_to_reg (spreg, frame_size, 0, epilogue_p);
1129       if (must_save_fp_p ())
1130         {
1131           rtx fpreg = gen_rtx_REG (Pmode, REG_FP);
1132           emit_move_insn (fpreg, postinc);
1133           emit_use (fpreg);
1134         }
1135       if (! current_function_is_leaf)
1136         {
1137           emit_move_insn (bfin_rets_rtx, postinc);
1138           emit_use (bfin_rets_rtx);
1139         }
1140     }
1141 }
1142
1143 /* Generate a prologue suitable for a function of kind FKIND.  This is
1144    called for interrupt and exception handler prologues.
1145    SPREG contains (reg:SI REG_SP).  */
1146
1147 static void
1148 expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind, bool all)
1149 {
1150   HOST_WIDE_INT frame_size = get_frame_size ();
1151   rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
1152   rtx predec = gen_rtx_MEM (SImode, predec1);
1153   rtx insn;
1154   tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1155   tree kspisusp = lookup_attribute ("kspisusp", attrs);
1156
1157   if (kspisusp)
1158     {
1159       insn = emit_move_insn (spreg, gen_rtx_REG (Pmode, REG_USP));
1160       RTX_FRAME_RELATED_P (insn) = 1;
1161     }
1162
1163   /* We need space on the stack in case we need to save the argument
1164      registers.  */
1165   if (fkind == EXCPT_HANDLER)
1166     {
1167       insn = emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (-12)));
1168       RTX_FRAME_RELATED_P (insn) = 1;
1169     }
1170
1171   /* If we're calling other functions, they won't save their call-clobbered
1172      registers, so we must save everything here.  */
1173   if (!current_function_is_leaf)
1174     all = true;
1175   expand_prologue_reg_save (spreg, all, true);
1176
1177   if (ENABLE_WA_05000283 || ENABLE_WA_05000315)
1178     {
1179       rtx chipid = GEN_INT (trunc_int_for_mode (0xFFC00014, SImode));
1180       rtx p5reg = gen_rtx_REG (Pmode, REG_P5);
1181       emit_insn (gen_movbi (bfin_cc_rtx, const1_rtx));
1182       emit_insn (gen_movsi_high (p5reg, chipid));
1183       emit_insn (gen_movsi_low (p5reg, p5reg, chipid));
1184       emit_insn (gen_dummy_load (p5reg, bfin_cc_rtx));
1185     }
1186   
1187   if (lookup_attribute ("nesting", attrs))
1188     {
1189       rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
1190                                         : fkind == NMI_HANDLER ? REG_RETN
1191                                         : REG_RETI));
1192       insn = emit_move_insn (predec, srcreg);
1193       RTX_FRAME_RELATED_P (insn) = 1;
1194     }
1195
1196   do_link (spreg, frame_size, all);
1197
1198   if (fkind == EXCPT_HANDLER)
1199     {
1200       rtx r0reg = gen_rtx_REG (SImode, REG_R0);
1201       rtx r1reg = gen_rtx_REG (SImode, REG_R1);
1202       rtx r2reg = gen_rtx_REG (SImode, REG_R2);
1203       rtx insn;
1204
1205       insn = emit_move_insn (r0reg, gen_rtx_REG (SImode, REG_SEQSTAT));
1206       insn = emit_insn (gen_ashrsi3 (r0reg, r0reg, GEN_INT (26)));
1207       insn = emit_insn (gen_ashlsi3 (r0reg, r0reg, GEN_INT (26)));
1208       insn = emit_move_insn (r1reg, spreg);
1209       insn = emit_move_insn (r2reg, gen_rtx_REG (Pmode, REG_FP));
1210       insn = emit_insn (gen_addsi3 (r2reg, r2reg, GEN_INT (8)));
1211     }
1212 }
1213
1214 /* Generate an epilogue suitable for a function of kind FKIND.  This is
1215    called for interrupt and exception handler epilogues.
1216    SPREG contains (reg:SI REG_SP).  */
1217
1218 static void
1219 expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind, bool all)
1220 {
1221   tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1222   rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
1223   rtx postinc = gen_rtx_MEM (SImode, postinc1);
1224
1225   /* A slightly crude technique to stop flow from trying to delete "dead"
1226      insns.  */
1227   MEM_VOLATILE_P (postinc) = 1;
1228
1229   do_unlink (spreg, get_frame_size (), all, 1);
1230
1231   if (lookup_attribute ("nesting", attrs))
1232     {
1233       rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
1234                                         : fkind == NMI_HANDLER ? REG_RETN
1235                                         : REG_RETI));
1236       emit_move_insn (srcreg, postinc);
1237     }
1238
1239   /* If we're calling other functions, they won't save their call-clobbered
1240      registers, so we must save (and restore) everything here.  */
1241   if (!current_function_is_leaf)
1242     all = true;
1243
1244   expand_epilogue_reg_restore (spreg, all, true);
1245
1246   /* Deallocate any space we left on the stack in case we needed to save the
1247      argument registers.  */
1248   if (fkind == EXCPT_HANDLER)
1249     emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (12)));
1250
1251   emit_jump_insn (gen_return_internal (GEN_INT (fkind)));
1252 }
1253
1254 /* Used while emitting the prologue to generate code to load the correct value
1255    into the PIC register, which is passed in DEST.  */
1256
1257 static rtx
1258 bfin_load_pic_reg (rtx dest)
1259 {
1260   struct cgraph_local_info *i = NULL;
1261   rtx addr, insn;
1262  
1263   i = cgraph_local_info (current_function_decl);
1264  
1265   /* Functions local to the translation unit don't need to reload the
1266      pic reg, since the caller always passes a usable one.  */
1267   if (i && i->local)
1268     return pic_offset_table_rtx;
1269       
1270   if (bfin_lib_id_given)
1271     addr = plus_constant (pic_offset_table_rtx, -4 - bfin_library_id * 4);
1272   else
1273     addr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
1274                          gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
1275                                          UNSPEC_LIBRARY_OFFSET));
1276   insn = emit_insn (gen_movsi (dest, gen_rtx_MEM (Pmode, addr)));
1277   return dest;
1278 }
1279
1280 /* Generate RTL for the prologue of the current function.  */
1281
1282 void
1283 bfin_expand_prologue (void)
1284 {
1285   HOST_WIDE_INT frame_size = get_frame_size ();
1286   rtx spreg = gen_rtx_REG (Pmode, REG_SP);
1287   e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1288   rtx pic_reg_loaded = NULL_RTX;
1289   tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1290   bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
1291
1292   if (fkind != SUBROUTINE)
1293     {
1294       expand_interrupt_handler_prologue (spreg, fkind, all);
1295       return;
1296     }
1297
1298   if (crtl->limit_stack
1299       || (TARGET_STACK_CHECK_L1
1300           && !DECL_NO_LIMIT_STACK (current_function_decl)))
1301     {
1302       HOST_WIDE_INT offset
1303         = bfin_initial_elimination_offset (ARG_POINTER_REGNUM,
1304                                            STACK_POINTER_REGNUM);
1305       rtx lim = crtl->limit_stack ? stack_limit_rtx : NULL_RTX;
1306       rtx p2reg = gen_rtx_REG (Pmode, REG_P2);
1307
1308       if (!lim)
1309         {
1310           emit_move_insn (p2reg, gen_int_mode (0xFFB00000, SImode));
1311           emit_move_insn (p2reg, gen_rtx_MEM (Pmode, p2reg));
1312           lim = p2reg;
1313         }
1314       if (GET_CODE (lim) == SYMBOL_REF)
1315         {
1316           if (TARGET_ID_SHARED_LIBRARY)
1317             {
1318               rtx p1reg = gen_rtx_REG (Pmode, REG_P1);
1319               rtx val;
1320               pic_reg_loaded = bfin_load_pic_reg (p2reg);
1321               val = legitimize_pic_address (stack_limit_rtx, p1reg,
1322                                             pic_reg_loaded);
1323               emit_move_insn (p1reg, val);
1324               frame_related_constant_load (p2reg, offset, FALSE);
1325               emit_insn (gen_addsi3 (p2reg, p2reg, p1reg));
1326               lim = p2reg;
1327             }
1328           else
1329             {
1330               rtx limit = plus_constant (lim, offset);
1331               emit_move_insn (p2reg, limit);
1332               lim = p2reg;
1333             }
1334         }
1335       else
1336         {
1337           if (lim != p2reg)
1338             emit_move_insn (p2reg, lim);
1339           add_to_reg (p2reg, offset, 0, 0);
1340           lim = p2reg;
1341         }
1342       emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim));
1343       emit_insn (gen_trapifcc ());
1344     }
1345   expand_prologue_reg_save (spreg, all, false);
1346
1347   do_link (spreg, frame_size, false);
1348
1349   if (TARGET_ID_SHARED_LIBRARY
1350       && !TARGET_SEP_DATA
1351       && (crtl->uses_pic_offset_table
1352           || !current_function_is_leaf))
1353     bfin_load_pic_reg (pic_offset_table_rtx);
1354 }
1355
1356 /* Generate RTL for the epilogue of the current function.  NEED_RETURN is zero
1357    if this is for a sibcall.  EH_RETURN is nonzero if we're expanding an
1358    eh_return pattern. SIBCALL_P is true if this is a sibcall epilogue,
1359    false otherwise.  */
1360
1361 void
1362 bfin_expand_epilogue (int need_return, int eh_return, bool sibcall_p)
1363 {
1364   rtx spreg = gen_rtx_REG (Pmode, REG_SP);
1365   e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1366   int e = sibcall_p ? -1 : 1;
1367   tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1368   bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
1369
1370   if (fkind != SUBROUTINE)
1371     {
1372       expand_interrupt_handler_epilogue (spreg, fkind, all);
1373       return;
1374     }
1375
1376   do_unlink (spreg, get_frame_size (), false, e);
1377
1378   expand_epilogue_reg_restore (spreg, all, false);
1379
1380   /* Omit the return insn if this is for a sibcall.  */
1381   if (! need_return)
1382     return;
1383
1384   if (eh_return)
1385     emit_insn (gen_addsi3 (spreg, spreg, gen_rtx_REG (Pmode, REG_P2)));
1386
1387   emit_jump_insn (gen_return_internal (GEN_INT (SUBROUTINE)));
1388 }
1389 \f
1390 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG.  */
1391
1392 int
1393 bfin_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
1394                            unsigned int new_reg)
1395 {
1396   /* Interrupt functions can only use registers that have already been
1397      saved by the prologue, even if they would normally be
1398      call-clobbered.  */
1399
1400   if (funkind (TREE_TYPE (current_function_decl)) != SUBROUTINE
1401       && !df_regs_ever_live_p (new_reg))
1402     return 0;
1403
1404   return 1;
1405 }
1406
1407 /* Return the value of the return address for the frame COUNT steps up
1408    from the current frame, after the prologue.
1409    We punt for everything but the current frame by returning const0_rtx.  */
1410
1411 rtx
1412 bfin_return_addr_rtx (int count)
1413 {
1414   if (count != 0)
1415     return const0_rtx;
1416
1417   return get_hard_reg_initial_val (Pmode, REG_RETS);
1418 }
1419
1420 /* Try machine-dependent ways of modifying an illegitimate address X
1421    to be legitimate.  If we find one, return the new, valid address,
1422    otherwise return NULL_RTX.
1423
1424    OLDX is the address as it was before break_out_memory_refs was called.
1425    In some cases it is useful to look at this to decide what needs to be done.
1426
1427    MODE is the mode of the memory reference.  */
1428
1429 rtx
1430 legitimize_address (rtx x ATTRIBUTE_UNUSED, rtx oldx ATTRIBUTE_UNUSED,
1431                     enum machine_mode mode ATTRIBUTE_UNUSED)
1432 {
1433   return NULL_RTX;
1434 }
1435
1436 static rtx
1437 bfin_delegitimize_address (rtx orig_x)
1438 {
1439   rtx x = orig_x;
1440
1441   if (GET_CODE (x) != MEM)
1442     return orig_x;
1443
1444   x = XEXP (x, 0);
1445   if (GET_CODE (x) == PLUS
1446       && GET_CODE (XEXP (x, 1)) == UNSPEC
1447       && XINT (XEXP (x, 1), 1) == UNSPEC_MOVE_PIC
1448       && GET_CODE (XEXP (x, 0)) == REG
1449       && REGNO (XEXP (x, 0)) == PIC_OFFSET_TABLE_REGNUM)
1450     return XVECEXP (XEXP (x, 1), 0, 0);
1451
1452   return orig_x;
1453 }
1454
1455 /* This predicate is used to compute the length of a load/store insn.
1456    OP is a MEM rtx, we return nonzero if its addressing mode requires a
1457    32-bit instruction.  */
1458
1459 int
1460 effective_address_32bit_p (rtx op, enum machine_mode mode) 
1461 {
1462   HOST_WIDE_INT offset;
1463
1464   mode = GET_MODE (op);
1465   op = XEXP (op, 0);
1466
1467   if (GET_CODE (op) != PLUS)
1468     {
1469       gcc_assert (REG_P (op) || GET_CODE (op) == POST_INC
1470                   || GET_CODE (op) == PRE_DEC || GET_CODE (op) == POST_DEC);
1471       return 0;
1472     }
1473
1474   if (GET_CODE (XEXP (op, 1)) == UNSPEC)
1475     return 1;
1476
1477   offset = INTVAL (XEXP (op, 1));
1478
1479   /* All byte loads use a 16-bit offset.  */
1480   if (GET_MODE_SIZE (mode) == 1)
1481     return 1;
1482
1483   if (GET_MODE_SIZE (mode) == 4)
1484     {
1485       /* Frame pointer relative loads can use a negative offset, all others
1486          are restricted to a small positive one.  */
1487       if (XEXP (op, 0) == frame_pointer_rtx)
1488         return offset < -128 || offset > 60;
1489       return offset < 0 || offset > 60;
1490     }
1491
1492   /* Must be HImode now.  */
1493   return offset < 0 || offset > 30;
1494 }
1495
1496 /* Returns true if X is a memory reference using an I register.  */
1497 bool
1498 bfin_dsp_memref_p (rtx x)
1499 {
1500   if (! MEM_P (x))
1501     return false;
1502   x = XEXP (x, 0);
1503   if (GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_INC
1504       || GET_CODE (x) == POST_DEC || GET_CODE (x) == PRE_DEC)
1505     x = XEXP (x, 0);
1506   return IREG_P (x);
1507 }
1508
1509 /* Return cost of the memory address ADDR.
1510    All addressing modes are equally cheap on the Blackfin.  */
1511
1512 static int
1513 bfin_address_cost (rtx addr ATTRIBUTE_UNUSED, bool speed ATTRIBUTE_UNUSED)
1514 {
1515   return 1;
1516 }
1517
1518 /* Subroutine of print_operand; used to print a memory reference X to FILE.  */
1519
1520 void
1521 print_address_operand (FILE *file, rtx x)
1522 {
1523   switch (GET_CODE (x))
1524     {
1525     case PLUS:
1526       output_address (XEXP (x, 0));
1527       fprintf (file, "+");
1528       output_address (XEXP (x, 1));
1529       break;
1530
1531     case PRE_DEC:
1532       fprintf (file, "--");
1533       output_address (XEXP (x, 0));    
1534       break;
1535     case POST_INC:
1536       output_address (XEXP (x, 0));
1537       fprintf (file, "++");
1538       break;
1539     case POST_DEC:
1540       output_address (XEXP (x, 0));
1541       fprintf (file, "--");
1542       break;
1543
1544     default:
1545       gcc_assert (GET_CODE (x) != MEM);
1546       print_operand (file, x, 0);
1547       break;
1548     }
1549 }
1550
1551 /* Adding intp DImode support by Tony
1552  * -- Q: (low  word)
1553  * -- R: (high word)
1554  */
1555
1556 void
1557 print_operand (FILE *file, rtx x, char code)
1558 {
1559   enum machine_mode mode;
1560
1561   if (code == '!')
1562     {
1563       if (GET_MODE (current_output_insn) == SImode)
1564         fprintf (file, " ||");
1565       else
1566         fprintf (file, ";");
1567       return;
1568     }
1569
1570   mode = GET_MODE (x);
1571
1572   switch (code)
1573     {
1574     case 'j':
1575       switch (GET_CODE (x))
1576         {
1577         case EQ:
1578           fprintf (file, "e");
1579           break;
1580         case NE:
1581           fprintf (file, "ne");
1582           break;
1583         case GT:
1584           fprintf (file, "g");
1585           break;
1586         case LT:
1587           fprintf (file, "l");
1588           break;
1589         case GE:
1590           fprintf (file, "ge");
1591           break;
1592         case LE:
1593           fprintf (file, "le");
1594           break;
1595         case GTU:
1596           fprintf (file, "g");
1597           break;
1598         case LTU:
1599           fprintf (file, "l");
1600           break;
1601         case GEU:
1602           fprintf (file, "ge");
1603           break;
1604         case LEU:
1605           fprintf (file, "le");
1606           break;
1607         default:
1608           output_operand_lossage ("invalid %%j value");
1609         }
1610       break;
1611     
1612     case 'J':                                    /* reverse logic */
1613       switch (GET_CODE(x))
1614         {
1615         case EQ:
1616           fprintf (file, "ne");
1617           break;
1618         case NE:
1619           fprintf (file, "e");
1620           break;
1621         case GT:
1622           fprintf (file, "le");
1623           break;
1624         case LT:
1625           fprintf (file, "ge");
1626           break;
1627         case GE:
1628           fprintf (file, "l");
1629           break;
1630         case LE:
1631           fprintf (file, "g");
1632           break;
1633         case GTU:
1634           fprintf (file, "le");
1635           break;
1636         case LTU:
1637           fprintf (file, "ge");
1638           break;
1639         case GEU:
1640           fprintf (file, "l");
1641           break;
1642         case LEU:
1643           fprintf (file, "g");
1644           break;
1645         default:
1646           output_operand_lossage ("invalid %%J value");
1647         }
1648       break;
1649
1650     default:
1651       switch (GET_CODE (x))
1652         {
1653         case REG:
1654           if (code == 'h')
1655             {
1656               if (REGNO (x) < 32)
1657                 fprintf (file, "%s", short_reg_names[REGNO (x)]);
1658               else
1659                 output_operand_lossage ("invalid operand for code '%c'", code);
1660             }
1661           else if (code == 'd')
1662             {
1663               if (REGNO (x) < 32)
1664                 fprintf (file, "%s", high_reg_names[REGNO (x)]);
1665               else
1666                 output_operand_lossage ("invalid operand for code '%c'", code);
1667             }
1668           else if (code == 'w')
1669             {
1670               if (REGNO (x) == REG_A0 || REGNO (x) == REG_A1)
1671                 fprintf (file, "%s.w", reg_names[REGNO (x)]);
1672               else
1673                 output_operand_lossage ("invalid operand for code '%c'", code);
1674             }
1675           else if (code == 'x')
1676             {
1677               if (REGNO (x) == REG_A0 || REGNO (x) == REG_A1)
1678                 fprintf (file, "%s.x", reg_names[REGNO (x)]);
1679               else
1680                 output_operand_lossage ("invalid operand for code '%c'", code);
1681             }
1682           else if (code == 'v')
1683             {
1684               if (REGNO (x) == REG_A0)
1685                 fprintf (file, "AV0");
1686               else if (REGNO (x) == REG_A1)
1687                 fprintf (file, "AV1");
1688               else
1689                 output_operand_lossage ("invalid operand for code '%c'", code);
1690             }
1691           else if (code == 'D')
1692             {
1693               if (D_REGNO_P (REGNO (x)))
1694                 fprintf (file, "%s", dregs_pair_names[REGNO (x)]);
1695               else
1696                 output_operand_lossage ("invalid operand for code '%c'", code);
1697             }
1698           else if (code == 'H')
1699             {
1700               if ((mode == DImode || mode == DFmode) && REG_P (x))
1701                 fprintf (file, "%s", reg_names[REGNO (x) + 1]);
1702               else
1703                 output_operand_lossage ("invalid operand for code '%c'", code);
1704             }
1705           else if (code == 'T')
1706             {
1707               if (D_REGNO_P (REGNO (x)))
1708                 fprintf (file, "%s", byte_reg_names[REGNO (x)]);
1709               else
1710                 output_operand_lossage ("invalid operand for code '%c'", code);
1711             }
1712           else 
1713             fprintf (file, "%s", reg_names[REGNO (x)]);
1714           break;
1715
1716         case MEM:
1717           fputc ('[', file);
1718           x = XEXP (x,0);
1719           print_address_operand (file, x);
1720           fputc (']', file);
1721           break;
1722
1723         case CONST_INT:
1724           if (code == 'M')
1725             {
1726               switch (INTVAL (x))
1727                 {
1728                 case MACFLAG_NONE:
1729                   break;
1730                 case MACFLAG_FU:
1731                   fputs ("(FU)", file);
1732                   break;
1733                 case MACFLAG_T:
1734                   fputs ("(T)", file);
1735                   break;
1736                 case MACFLAG_TFU:
1737                   fputs ("(TFU)", file);
1738                   break;
1739                 case MACFLAG_W32:
1740                   fputs ("(W32)", file);
1741                   break;
1742                 case MACFLAG_IS:
1743                   fputs ("(IS)", file);
1744                   break;
1745                 case MACFLAG_IU:
1746                   fputs ("(IU)", file);
1747                   break;
1748                 case MACFLAG_IH:
1749                   fputs ("(IH)", file);
1750                   break;
1751                 case MACFLAG_M:
1752                   fputs ("(M)", file);
1753                   break;
1754                 case MACFLAG_IS_M:
1755                   fputs ("(IS,M)", file);
1756                   break;
1757                 case MACFLAG_ISS2:
1758                   fputs ("(ISS2)", file);
1759                   break;
1760                 case MACFLAG_S2RND:
1761                   fputs ("(S2RND)", file);
1762                   break;
1763                 default:
1764                   gcc_unreachable ();
1765                 }
1766               break;
1767             }
1768           else if (code == 'b')
1769             {
1770               if (INTVAL (x) == 0)
1771                 fputs ("+=", file);
1772               else if (INTVAL (x) == 1)
1773                 fputs ("-=", file);
1774               else
1775                 gcc_unreachable ();
1776               break;
1777             }
1778           /* Moves to half registers with d or h modifiers always use unsigned
1779              constants.  */
1780           else if (code == 'd')
1781             x = GEN_INT ((INTVAL (x) >> 16) & 0xffff);
1782           else if (code == 'h')
1783             x = GEN_INT (INTVAL (x) & 0xffff);
1784           else if (code == 'N')
1785             x = GEN_INT (-INTVAL (x));
1786           else if (code == 'X')
1787             x = GEN_INT (exact_log2 (0xffffffff & INTVAL (x)));
1788           else if (code == 'Y')
1789             x = GEN_INT (exact_log2 (0xffffffff & ~INTVAL (x)));
1790           else if (code == 'Z')
1791             /* Used for LINK insns.  */
1792             x = GEN_INT (-8 - INTVAL (x));
1793
1794           /* fall through */
1795
1796         case SYMBOL_REF:
1797           output_addr_const (file, x);
1798           break;
1799
1800         case CONST_DOUBLE:
1801           output_operand_lossage ("invalid const_double operand");
1802           break;
1803
1804         case UNSPEC:
1805           switch (XINT (x, 1))
1806             {
1807             case UNSPEC_MOVE_PIC:
1808               output_addr_const (file, XVECEXP (x, 0, 0));
1809               fprintf (file, "@GOT");
1810               break;
1811
1812             case UNSPEC_MOVE_FDPIC:
1813               output_addr_const (file, XVECEXP (x, 0, 0));
1814               fprintf (file, "@GOT17M4");
1815               break;
1816
1817             case UNSPEC_FUNCDESC_GOT17M4:
1818               output_addr_const (file, XVECEXP (x, 0, 0));
1819               fprintf (file, "@FUNCDESC_GOT17M4");
1820               break;
1821
1822             case UNSPEC_LIBRARY_OFFSET:
1823               fprintf (file, "_current_shared_library_p5_offset_");
1824               break;
1825
1826             default:
1827               gcc_unreachable ();
1828             }
1829           break;
1830
1831         default:
1832           output_addr_const (file, x);
1833         }
1834     }
1835 }
1836 \f
1837 /* Argument support functions.  */
1838
1839 /* Initialize a variable CUM of type CUMULATIVE_ARGS
1840    for a call to a function whose data type is FNTYPE.
1841    For a library call, FNTYPE is 0.  
1842    VDSP C Compiler manual, our ABI says that
1843    first 3 words of arguments will use R0, R1 and R2.
1844 */
1845
1846 void
1847 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
1848                       rtx libname ATTRIBUTE_UNUSED)
1849 {
1850   static CUMULATIVE_ARGS zero_cum;
1851
1852   *cum = zero_cum;
1853
1854   /* Set up the number of registers to use for passing arguments.  */
1855
1856   cum->nregs = max_arg_registers;
1857   cum->arg_regs = arg_regs;
1858
1859   cum->call_cookie = CALL_NORMAL;
1860   /* Check for a longcall attribute.  */
1861   if (fntype && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype)))
1862     cum->call_cookie |= CALL_SHORT;
1863   else if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)))
1864     cum->call_cookie |= CALL_LONG;
1865
1866   return;
1867 }
1868
1869 /* Update the data in CUM to advance over an argument
1870    of mode MODE and data type TYPE.
1871    (TYPE is null for libcalls where that information may not be available.)  */
1872
1873 void
1874 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1875                       int named ATTRIBUTE_UNUSED)
1876 {
1877   int count, bytes, words;
1878
1879   bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1880   words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1881
1882   cum->words += words;
1883   cum->nregs -= words;
1884
1885   if (cum->nregs <= 0)
1886     {
1887       cum->nregs = 0;
1888       cum->arg_regs = NULL;
1889     }
1890   else
1891     {
1892       for (count = 1; count <= words; count++)
1893         cum->arg_regs++;
1894     }
1895
1896   return;
1897 }
1898
1899 /* Define where to put the arguments to a function.
1900    Value is zero to push the argument on the stack,
1901    or a hard register in which to store the argument.
1902
1903    MODE is the argument's machine mode.
1904    TYPE is the data type of the argument (as a tree).
1905     This is null for libcalls where that information may
1906     not be available.
1907    CUM is a variable of type CUMULATIVE_ARGS which gives info about
1908     the preceding args and about the function being called.
1909    NAMED is nonzero if this argument is a named parameter
1910     (otherwise it is an extra parameter matching an ellipsis).  */
1911
1912 struct rtx_def *
1913 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1914               int named ATTRIBUTE_UNUSED)
1915 {
1916   int bytes
1917     = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1918
1919   if (mode == VOIDmode)
1920     /* Compute operand 2 of the call insn.  */
1921     return GEN_INT (cum->call_cookie);
1922
1923   if (bytes == -1)
1924     return NULL_RTX;
1925
1926   if (cum->nregs)
1927     return gen_rtx_REG (mode, *(cum->arg_regs));
1928
1929   return NULL_RTX;
1930 }
1931
1932 /* For an arg passed partly in registers and partly in memory,
1933    this is the number of bytes passed in registers.
1934    For args passed entirely in registers or entirely in memory, zero.
1935
1936    Refer VDSP C Compiler manual, our ABI.
1937    First 3 words are in registers. So, if an argument is larger
1938    than the registers available, it will span the register and
1939    stack.   */
1940
1941 static int
1942 bfin_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1943                         tree type ATTRIBUTE_UNUSED,
1944                         bool named ATTRIBUTE_UNUSED)
1945 {
1946   int bytes
1947     = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1948   int bytes_left = cum->nregs * UNITS_PER_WORD;
1949   
1950   if (bytes == -1)
1951     return 0;
1952
1953   if (bytes_left == 0)
1954     return 0;
1955   if (bytes > bytes_left)
1956     return bytes_left;
1957   return 0;
1958 }
1959
1960 /* Variable sized types are passed by reference.  */
1961
1962 static bool
1963 bfin_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
1964                         enum machine_mode mode ATTRIBUTE_UNUSED,
1965                         const_tree type, bool named ATTRIBUTE_UNUSED)
1966 {
1967   return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
1968 }
1969
1970 /* Decide whether a type should be returned in memory (true)
1971    or in a register (false).  This is called by the macro
1972    TARGET_RETURN_IN_MEMORY.  */
1973
1974 static bool
1975 bfin_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
1976 {
1977   int size = int_size_in_bytes (type);
1978   return size > 2 * UNITS_PER_WORD || size == -1;
1979 }
1980
1981 /* Register in which address to store a structure value
1982    is passed to a function.  */
1983 static rtx
1984 bfin_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
1985                       int incoming ATTRIBUTE_UNUSED)
1986 {
1987   return gen_rtx_REG (Pmode, REG_P0);
1988 }
1989
1990 /* Return true when register may be used to pass function parameters.  */
1991
1992 bool 
1993 function_arg_regno_p (int n)
1994 {
1995   int i;
1996   for (i = 0; arg_regs[i] != -1; i++)
1997     if (n == arg_regs[i])
1998       return true;
1999   return false;
2000 }
2001
2002 /* Returns 1 if OP contains a symbol reference */
2003
2004 int
2005 symbolic_reference_mentioned_p (rtx op)
2006 {
2007   register const char *fmt;
2008   register int i;
2009
2010   if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
2011     return 1;
2012
2013   fmt = GET_RTX_FORMAT (GET_CODE (op));
2014   for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
2015     {
2016       if (fmt[i] == 'E')
2017         {
2018           register int j;
2019
2020           for (j = XVECLEN (op, i) - 1; j >= 0; j--)
2021             if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
2022               return 1;
2023         }
2024
2025       else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
2026         return 1;
2027     }
2028
2029   return 0;
2030 }
2031
2032 /* Decide whether we can make a sibling call to a function.  DECL is the
2033    declaration of the function being targeted by the call and EXP is the
2034    CALL_EXPR representing the call.  */
2035
2036 static bool
2037 bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
2038                               tree exp ATTRIBUTE_UNUSED)
2039 {
2040   struct cgraph_local_info *this_func, *called_func;
2041   e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
2042   if (fkind != SUBROUTINE)
2043     return false;
2044   if (!TARGET_ID_SHARED_LIBRARY || TARGET_SEP_DATA)
2045     return true;
2046
2047   /* When compiling for ID shared libraries, can't sibcall a local function
2048      from a non-local function, because the local function thinks it does
2049      not need to reload P5 in the prologue, but the sibcall wil pop P5 in the
2050      sibcall epilogue, and we end up with the wrong value in P5.  */
2051
2052   if (!decl)
2053     /* Not enough information.  */
2054     return false;
2055  
2056   this_func = cgraph_local_info (current_function_decl);
2057   called_func = cgraph_local_info (decl);
2058   return !called_func->local || this_func->local;
2059 }
2060 \f
2061 /* Emit RTL insns to initialize the variable parts of a trampoline at
2062    TRAMP. FNADDR is an RTX for the address of the function's pure
2063    code.  CXT is an RTX for the static chain value for the function.  */
2064
2065 void
2066 initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt)
2067 {
2068   rtx t1 = copy_to_reg (fnaddr);
2069   rtx t2 = copy_to_reg (cxt);
2070   rtx addr;
2071   int i = 0;
2072
2073   if (TARGET_FDPIC)
2074     {
2075       rtx a = memory_address (Pmode, plus_constant (tramp, 8));
2076       addr = memory_address (Pmode, tramp);
2077       emit_move_insn (gen_rtx_MEM (SImode, addr), a);
2078       i = 8;
2079     }
2080
2081   addr = memory_address (Pmode, plus_constant (tramp, i + 2));
2082   emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
2083   emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16)));
2084   addr = memory_address (Pmode, plus_constant (tramp, i + 6));
2085   emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
2086
2087   addr = memory_address (Pmode, plus_constant (tramp, i + 10));
2088   emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
2089   emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16)));
2090   addr = memory_address (Pmode, plus_constant (tramp, i + 14));
2091   emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
2092 }
2093
2094 /* Emit insns to move operands[1] into operands[0].  */
2095
2096 void
2097 emit_pic_move (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
2098 {
2099   rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
2100
2101   gcc_assert (!TARGET_FDPIC || !(reload_in_progress || reload_completed));
2102   if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
2103     operands[1] = force_reg (SImode, operands[1]);
2104   else
2105     operands[1] = legitimize_pic_address (operands[1], temp,
2106                                           TARGET_FDPIC ? OUR_FDPIC_REG
2107                                           : pic_offset_table_rtx);
2108 }
2109
2110 /* Expand a move operation in mode MODE.  The operands are in OPERANDS.
2111    Returns true if no further code must be generated, false if the caller
2112    should generate an insn to move OPERANDS[1] to OPERANDS[0].  */
2113
2114 bool
2115 expand_move (rtx *operands, enum machine_mode mode)
2116 {
2117   rtx op = operands[1];
2118   if ((TARGET_ID_SHARED_LIBRARY || TARGET_FDPIC)
2119       && SYMBOLIC_CONST (op))
2120     emit_pic_move (operands, mode);
2121   else if (mode == SImode && GET_CODE (op) == CONST
2122            && GET_CODE (XEXP (op, 0)) == PLUS
2123            && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
2124            && !bfin_legitimate_constant_p (op))
2125     {
2126       rtx dest = operands[0];
2127       rtx op0, op1;
2128       gcc_assert (!reload_in_progress && !reload_completed);
2129       op = XEXP (op, 0);
2130       op0 = force_reg (mode, XEXP (op, 0));
2131       op1 = XEXP (op, 1);
2132       if (!insn_data[CODE_FOR_addsi3].operand[2].predicate (op1, mode))
2133         op1 = force_reg (mode, op1);
2134       if (GET_CODE (dest) == MEM)
2135         dest = gen_reg_rtx (mode);
2136       emit_insn (gen_addsi3 (dest, op0, op1));
2137       if (dest == operands[0])
2138         return true;
2139       operands[1] = dest;
2140     }
2141   /* Don't generate memory->memory or constant->memory moves, go through a
2142      register */
2143   else if ((reload_in_progress | reload_completed) == 0
2144            && GET_CODE (operands[0]) == MEM
2145            && GET_CODE (operands[1]) != REG)
2146     operands[1] = force_reg (mode, operands[1]);
2147   return false;
2148 }
2149 \f
2150 /* Split one or more DImode RTL references into pairs of SImode
2151    references.  The RTL can be REG, offsettable MEM, integer constant, or
2152    CONST_DOUBLE.  "operands" is a pointer to an array of DImode RTL to
2153    split and "num" is its length.  lo_half and hi_half are output arrays
2154    that parallel "operands".  */
2155
2156 void
2157 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
2158 {
2159   while (num--)
2160     {
2161       rtx op = operands[num];
2162
2163       /* simplify_subreg refuse to split volatile memory addresses,
2164          but we still have to handle it.  */
2165       if (GET_CODE (op) == MEM)
2166         {
2167           lo_half[num] = adjust_address (op, SImode, 0);
2168           hi_half[num] = adjust_address (op, SImode, 4);
2169         }
2170       else
2171         {
2172           lo_half[num] = simplify_gen_subreg (SImode, op,
2173                                               GET_MODE (op) == VOIDmode
2174                                               ? DImode : GET_MODE (op), 0);
2175           hi_half[num] = simplify_gen_subreg (SImode, op,
2176                                               GET_MODE (op) == VOIDmode
2177                                               ? DImode : GET_MODE (op), 4);
2178         }
2179     }
2180 }
2181 \f
2182 bool
2183 bfin_longcall_p (rtx op, int call_cookie)
2184 {
2185   gcc_assert (GET_CODE (op) == SYMBOL_REF);
2186   if (call_cookie & CALL_SHORT)
2187     return 0;
2188   if (call_cookie & CALL_LONG)
2189     return 1;
2190   if (TARGET_LONG_CALLS)
2191     return 1;
2192   return 0;
2193 }
2194
2195 /* Expand a call instruction.  FNADDR is the call target, RETVAL the return value.
2196    COOKIE is a CONST_INT holding the call_cookie prepared init_cumulative_args.
2197    SIBCALL is nonzero if this is a sibling call.  */
2198
2199 void
2200 bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
2201 {
2202   rtx use = NULL, call;
2203   rtx callee = XEXP (fnaddr, 0);
2204   int nelts = 2 + !!sibcall;
2205   rtx pat;
2206   rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REGNO);
2207   int n;
2208
2209   /* In an untyped call, we can get NULL for operand 2.  */
2210   if (cookie == NULL_RTX)
2211     cookie = const0_rtx;
2212
2213   /* Static functions and indirect calls don't need the pic register.  */
2214   if (!TARGET_FDPIC && flag_pic
2215       && GET_CODE (callee) == SYMBOL_REF
2216       && !SYMBOL_REF_LOCAL_P (callee))
2217     use_reg (&use, pic_offset_table_rtx);
2218
2219   if (TARGET_FDPIC)
2220     {
2221       int caller_has_l1_text, callee_has_l1_text;
2222
2223       caller_has_l1_text = callee_has_l1_text = 0;
2224
2225       if (lookup_attribute ("l1_text",
2226                             DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE)
2227         caller_has_l1_text = 1;
2228
2229       if (GET_CODE (callee) == SYMBOL_REF
2230           && SYMBOL_REF_DECL (callee) && DECL_P (SYMBOL_REF_DECL (callee))
2231           && lookup_attribute
2232                ("l1_text",
2233                 DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE)
2234         callee_has_l1_text = 1;
2235
2236       if (GET_CODE (callee) != SYMBOL_REF
2237           || bfin_longcall_p (callee, INTVAL (cookie))
2238           || (GET_CODE (callee) == SYMBOL_REF
2239               && !SYMBOL_REF_LOCAL_P (callee)
2240               && TARGET_INLINE_PLT)
2241           || caller_has_l1_text != callee_has_l1_text
2242           || (caller_has_l1_text && callee_has_l1_text
2243               && (GET_CODE (callee) != SYMBOL_REF
2244                   || !SYMBOL_REF_LOCAL_P (callee))))
2245         {
2246           rtx addr = callee;
2247           if (! address_operand (addr, Pmode))
2248             addr = force_reg (Pmode, addr);
2249
2250           fnaddr = gen_reg_rtx (SImode);
2251           emit_insn (gen_load_funcdescsi (fnaddr, addr));
2252           fnaddr = gen_rtx_MEM (Pmode, fnaddr);
2253
2254           picreg = gen_reg_rtx (SImode);
2255           emit_insn (gen_load_funcdescsi (picreg,
2256                                           plus_constant (addr, 4)));
2257         }
2258
2259       nelts++;
2260     }
2261   else if ((!register_no_elim_operand (callee, Pmode)
2262             && GET_CODE (callee) != SYMBOL_REF)
2263            || (GET_CODE (callee) == SYMBOL_REF
2264                && ((TARGET_ID_SHARED_LIBRARY && !TARGET_LEAF_ID_SHARED_LIBRARY)
2265                    || bfin_longcall_p (callee, INTVAL (cookie)))))
2266     {
2267       callee = copy_to_mode_reg (Pmode, callee);
2268       fnaddr = gen_rtx_MEM (Pmode, callee);
2269     }
2270   call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
2271
2272   if (retval)
2273     call = gen_rtx_SET (VOIDmode, retval, call);
2274
2275   pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nelts));
2276   n = 0;
2277   XVECEXP (pat, 0, n++) = call;
2278   if (TARGET_FDPIC)
2279     XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, picreg);
2280   XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie);
2281   if (sibcall)
2282     XVECEXP (pat, 0, n++) = gen_rtx_RETURN (VOIDmode);
2283   call = emit_call_insn (pat);
2284   if (use)
2285     CALL_INSN_FUNCTION_USAGE (call) = use;
2286 }
2287 \f
2288 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE.  */
2289
2290 int
2291 hard_regno_mode_ok (int regno, enum machine_mode mode)
2292 {
2293   /* Allow only dregs to store value of mode HI or QI */
2294   enum reg_class rclass = REGNO_REG_CLASS (regno);
2295
2296   if (mode == CCmode)
2297     return 0;
2298
2299   if (mode == V2HImode)
2300     return D_REGNO_P (regno);
2301   if (rclass == CCREGS)
2302     return mode == BImode;
2303   if (mode == PDImode || mode == V2PDImode)
2304     return regno == REG_A0 || regno == REG_A1;
2305
2306   /* Allow all normal 32-bit regs, except REG_M3, in case regclass ever comes
2307      up with a bad register class (such as ALL_REGS) for DImode.  */
2308   if (mode == DImode)
2309     return regno < REG_M3;
2310
2311   if (mode == SImode
2312       && TEST_HARD_REG_BIT (reg_class_contents[PROLOGUE_REGS], regno))
2313     return 1;
2314
2315   return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno);
2316 }
2317
2318 /* Implements target hook vector_mode_supported_p.  */
2319
2320 static bool
2321 bfin_vector_mode_supported_p (enum machine_mode mode)
2322 {
2323   return mode == V2HImode;
2324 }
2325
2326 /* Return the cost of moving data from a register in class CLASS1 to
2327    one in class CLASS2.  A cost of 2 is the default.  */
2328
2329 int
2330 bfin_register_move_cost (enum machine_mode mode,
2331                          enum reg_class class1, enum reg_class class2)
2332 {
2333   /* These need secondary reloads, so they're more expensive.  */
2334   if ((class1 == CCREGS && class2 != DREGS)
2335       || (class1 != DREGS && class2 == CCREGS))
2336     return 4;
2337
2338   /* If optimizing for size, always prefer reg-reg over reg-memory moves.  */
2339   if (optimize_size)
2340     return 2;
2341
2342   /* There are some stalls involved when moving from a DREG to a different
2343      class reg, and using the value in one of the following instructions.
2344      Attempt to model this by slightly discouraging such moves.  */
2345   if (class1 == DREGS && class2 != DREGS)
2346     return 2 * 2;
2347
2348   if (GET_MODE_CLASS (mode) == MODE_INT)
2349     {
2350       /* Discourage trying to use the accumulators.  */
2351       if (TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A0)
2352           || TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A1)
2353           || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A0)
2354           || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A1))
2355         return 20;
2356     }
2357   return 2;
2358 }
2359
2360 /* Return the cost of moving data of mode M between a
2361    register and memory.  A value of 2 is the default; this cost is
2362    relative to those in `REGISTER_MOVE_COST'.
2363
2364    ??? In theory L1 memory has single-cycle latency.  We should add a switch
2365    that tells the compiler whether we expect to use only L1 memory for the
2366    program; it'll make the costs more accurate.  */
2367
2368 int
2369 bfin_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
2370                        enum reg_class rclass,
2371                        int in ATTRIBUTE_UNUSED)
2372 {
2373   /* Make memory accesses slightly more expensive than any register-register
2374      move.  Also, penalize non-DP registers, since they need secondary
2375      reloads to load and store.  */
2376   if (! reg_class_subset_p (rclass, DPREGS))
2377     return 10;
2378
2379   return 8;
2380 }
2381
2382 /* Inform reload about cases where moving X with a mode MODE to a register in
2383    RCLASS requires an extra scratch register.  Return the class needed for the
2384    scratch register.  */
2385
2386 static enum reg_class
2387 bfin_secondary_reload (bool in_p, rtx x, enum reg_class rclass,
2388                        enum machine_mode mode, secondary_reload_info *sri)
2389 {
2390   /* If we have HImode or QImode, we can only use DREGS as secondary registers;
2391      in most other cases we can also use PREGS.  */
2392   enum reg_class default_class = GET_MODE_SIZE (mode) >= 4 ? DPREGS : DREGS;
2393   enum reg_class x_class = NO_REGS;
2394   enum rtx_code code = GET_CODE (x);
2395
2396   if (code == SUBREG)
2397     x = SUBREG_REG (x), code = GET_CODE (x);
2398   if (REG_P (x))
2399     {
2400       int regno = REGNO (x);
2401       if (regno >= FIRST_PSEUDO_REGISTER)
2402         regno = reg_renumber[regno];
2403
2404       if (regno == -1)
2405         code = MEM;
2406       else
2407         x_class = REGNO_REG_CLASS (regno);
2408     }
2409
2410   /* We can be asked to reload (plus (FP) (large_constant)) into a DREG.
2411      This happens as a side effect of register elimination, and we need
2412      a scratch register to do it.  */
2413   if (fp_plus_const_operand (x, mode))
2414     {
2415       rtx op2 = XEXP (x, 1);
2416       int large_constant_p = ! satisfies_constraint_Ks7 (op2);
2417
2418       if (rclass == PREGS || rclass == PREGS_CLOBBERED)
2419         return NO_REGS;
2420       /* If destination is a DREG, we can do this without a scratch register
2421          if the constant is valid for an add instruction.  */
2422       if ((rclass == DREGS || rclass == DPREGS)
2423           && ! large_constant_p)
2424         return NO_REGS;
2425       /* Reloading to anything other than a DREG?  Use a PREG scratch
2426          register.  */
2427       sri->icode = CODE_FOR_reload_insi;
2428       return NO_REGS;
2429     }
2430
2431   /* Data can usually be moved freely between registers of most classes.
2432      AREGS are an exception; they can only move to or from another register
2433      in AREGS or one in DREGS.  They can also be assigned the constant 0.  */
2434   if (x_class == AREGS || x_class == EVEN_AREGS || x_class == ODD_AREGS)
2435     return (rclass == DREGS || rclass == AREGS || rclass == EVEN_AREGS
2436             || rclass == ODD_AREGS
2437             ? NO_REGS : DREGS);
2438
2439   if (rclass == AREGS || rclass == EVEN_AREGS || rclass == ODD_AREGS)
2440     {
2441       if (code == MEM)
2442         {
2443           sri->icode = in_p ? CODE_FOR_reload_inpdi : CODE_FOR_reload_outpdi;
2444           return NO_REGS;
2445         }
2446
2447       if (x != const0_rtx && x_class != DREGS)
2448         {
2449           return DREGS;
2450         }
2451       else
2452         return NO_REGS;
2453     }
2454
2455   /* CCREGS can only be moved from/to DREGS.  */
2456   if (rclass == CCREGS && x_class != DREGS)
2457     return DREGS;
2458   if (x_class == CCREGS && rclass != DREGS)
2459     return DREGS;
2460
2461   /* All registers other than AREGS can load arbitrary constants.  The only
2462      case that remains is MEM.  */
2463   if (code == MEM)
2464     if (! reg_class_subset_p (rclass, default_class))
2465       return default_class;
2466
2467   return NO_REGS;
2468 }
2469 \f
2470 /* Implement TARGET_HANDLE_OPTION.  */
2471
2472 static bool
2473 bfin_handle_option (size_t code, const char *arg, int value)
2474 {
2475   switch (code)
2476     {
2477     case OPT_mshared_library_id_:
2478       if (value > MAX_LIBRARY_ID)
2479         error ("-mshared-library-id=%s is not between 0 and %d",
2480                arg, MAX_LIBRARY_ID);
2481       bfin_lib_id_given = 1;
2482       return true;
2483
2484     case OPT_mcpu_:
2485       {
2486         const char *p, *q;
2487         int i;
2488
2489         i = 0;
2490         while ((p = bfin_cpus[i].name) != NULL)
2491           {
2492             if (strncmp (arg, p, strlen (p)) == 0)
2493               break;
2494             i++;
2495           }
2496
2497         if (p == NULL)
2498           {
2499             error ("-mcpu=%s is not valid", arg);
2500             return false;
2501           }
2502
2503         bfin_cpu_type = bfin_cpus[i].type;
2504
2505         q = arg + strlen (p);
2506
2507         if (*q == '\0')
2508           {
2509             bfin_si_revision = bfin_cpus[i].si_revision;
2510             bfin_workarounds |= bfin_cpus[i].workarounds;
2511           }
2512         else if (strcmp (q, "-none") == 0)
2513           bfin_si_revision = -1;
2514         else if (strcmp (q, "-any") == 0)
2515           {
2516             bfin_si_revision = 0xffff;
2517             while (bfin_cpus[i].type == bfin_cpu_type)
2518               {
2519                 bfin_workarounds |= bfin_cpus[i].workarounds;
2520                 i++;
2521               }
2522           }
2523         else
2524           {
2525             unsigned int si_major, si_minor;
2526             int rev_len, n;
2527
2528             rev_len = strlen (q);
2529
2530             if (sscanf (q, "-%u.%u%n", &si_major, &si_minor, &n) != 2
2531                 || n != rev_len
2532                 || si_major > 0xff || si_minor > 0xff)
2533               {
2534               invalid_silicon_revision:
2535                 error ("-mcpu=%s has invalid silicon revision", arg);
2536                 return false;
2537               }
2538
2539             bfin_si_revision = (si_major << 8) | si_minor;
2540
2541             while (bfin_cpus[i].type == bfin_cpu_type
2542                    && bfin_cpus[i].si_revision != bfin_si_revision)
2543               i++;
2544
2545             if (bfin_cpus[i].type != bfin_cpu_type)
2546               goto invalid_silicon_revision;
2547
2548             bfin_workarounds |= bfin_cpus[i].workarounds;
2549           }
2550
2551         return true;
2552       }
2553
2554     default:
2555       return true;
2556     }
2557 }
2558
2559 static struct machine_function *
2560 bfin_init_machine_status (void)
2561 {
2562   struct machine_function *f;
2563
2564   f = GGC_CNEW (struct machine_function);
2565
2566   return f;
2567 }
2568
2569 /* Implement the macro OVERRIDE_OPTIONS.  */
2570
2571 void
2572 override_options (void)
2573 {
2574   /* If processor type is not specified, enable all workarounds.  */
2575   if (bfin_cpu_type == BFIN_CPU_UNKNOWN)
2576     {
2577       int i;
2578
2579       for (i = 0; bfin_cpus[i].name != NULL; i++)
2580         bfin_workarounds |= bfin_cpus[i].workarounds;
2581
2582       bfin_si_revision = 0xffff;
2583     }
2584
2585   if (bfin_csync_anomaly == 1)
2586     bfin_workarounds |= WA_SPECULATIVE_SYNCS;
2587   else if (bfin_csync_anomaly == 0)
2588     bfin_workarounds &= ~WA_SPECULATIVE_SYNCS;
2589
2590   if (bfin_specld_anomaly == 1)
2591     bfin_workarounds |= WA_SPECULATIVE_LOADS;
2592   else if (bfin_specld_anomaly == 0)
2593     bfin_workarounds &= ~WA_SPECULATIVE_LOADS;
2594
2595   if (TARGET_OMIT_LEAF_FRAME_POINTER)
2596     flag_omit_frame_pointer = 1;
2597
2598   /* Library identification */
2599   if (bfin_lib_id_given && ! TARGET_ID_SHARED_LIBRARY)
2600     error ("-mshared-library-id= specified without -mid-shared-library");
2601
2602   if (stack_limit_rtx && TARGET_STACK_CHECK_L1)
2603     error ("Can't use multiple stack checking methods together.");
2604
2605   if (TARGET_ID_SHARED_LIBRARY && TARGET_FDPIC)
2606     error ("ID shared libraries and FD-PIC mode can't be used together.");
2607
2608   /* Don't allow the user to specify -mid-shared-library and -msep-data
2609      together, as it makes little sense from a user's point of view...  */
2610   if (TARGET_SEP_DATA && TARGET_ID_SHARED_LIBRARY)
2611     error ("cannot specify both -msep-data and -mid-shared-library");
2612   /* ... internally, however, it's nearly the same.  */
2613   if (TARGET_SEP_DATA)
2614     target_flags |= MASK_ID_SHARED_LIBRARY | MASK_LEAF_ID_SHARED_LIBRARY;
2615
2616   if (TARGET_ID_SHARED_LIBRARY && flag_pic == 0)
2617     flag_pic = 1;
2618
2619   /* There is no single unaligned SI op for PIC code.  Sometimes we
2620      need to use ".4byte" and sometimes we need to use ".picptr".
2621      See bfin_assemble_integer for details.  */
2622   if (TARGET_FDPIC)
2623     targetm.asm_out.unaligned_op.si = 0;
2624
2625   /* Silently turn off flag_pic if not doing FDPIC or ID shared libraries,
2626      since we don't support it and it'll just break.  */
2627   if (flag_pic && !TARGET_FDPIC && !TARGET_ID_SHARED_LIBRARY)
2628     flag_pic = 0;
2629
2630   if (TARGET_MULTICORE && bfin_cpu_type != BFIN_CPU_BF561)
2631     error ("-mmulticore can only be used with BF561");
2632
2633   if (TARGET_COREA && !TARGET_MULTICORE)
2634     error ("-mcorea should be used with -mmulticore");
2635
2636   if (TARGET_COREB && !TARGET_MULTICORE)
2637     error ("-mcoreb should be used with -mmulticore");
2638
2639   if (TARGET_COREA && TARGET_COREB)
2640     error ("-mcorea and -mcoreb can't be used together");
2641
2642   flag_schedule_insns = 0;
2643
2644   /* Passes after sched2 can break the helpful TImode annotations that
2645      haifa-sched puts on every insn.  Just do scheduling in reorg.  */
2646   bfin_flag_schedule_insns2 = flag_schedule_insns_after_reload;
2647   flag_schedule_insns_after_reload = 0;
2648
2649   init_machine_status = bfin_init_machine_status;
2650 }
2651
2652 /* Return the destination address of BRANCH.
2653    We need to use this instead of get_attr_length, because the
2654    cbranch_with_nops pattern conservatively sets its length to 6, and
2655    we still prefer to use shorter sequences.  */
2656
2657 static int
2658 branch_dest (rtx branch)
2659 {
2660   rtx dest;
2661   int dest_uid;
2662   rtx pat = PATTERN (branch);
2663   if (GET_CODE (pat) == PARALLEL)
2664     pat = XVECEXP (pat, 0, 0);
2665   dest = SET_SRC (pat);
2666   if (GET_CODE (dest) == IF_THEN_ELSE)
2667     dest = XEXP (dest, 1);
2668   dest = XEXP (dest, 0);
2669   dest_uid = INSN_UID (dest);
2670   return INSN_ADDRESSES (dest_uid);
2671 }
2672
2673 /* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates
2674    it's a branch that's predicted taken.  */
2675
2676 static int
2677 cbranch_predicted_taken_p (rtx insn)
2678 {
2679   rtx x = find_reg_note (insn, REG_BR_PROB, 0);
2680
2681   if (x)
2682     {
2683       int pred_val = INTVAL (XEXP (x, 0));
2684
2685       return pred_val >= REG_BR_PROB_BASE / 2;
2686     }
2687
2688   return 0;
2689 }
2690
2691 /* Templates for use by asm_conditional_branch.  */
2692
2693 static const char *ccbranch_templates[][3] = {
2694   { "if !cc jump %3;",  "if cc jump 4 (bp); jump.s %3;",  "if cc jump 6 (bp); jump.l %3;" },
2695   { "if cc jump %3;",   "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" },
2696   { "if !cc jump %3 (bp);",  "if cc jump 4; jump.s %3;",  "if cc jump 6; jump.l %3;" },
2697   { "if cc jump %3 (bp);",  "if !cc jump 4; jump.s %3;",  "if !cc jump 6; jump.l %3;" },
2698 };
2699
2700 /* Output INSN, which is a conditional branch instruction with operands
2701    OPERANDS.
2702
2703    We deal with the various forms of conditional branches that can be generated
2704    by bfin_reorg to prevent the hardware from doing speculative loads, by
2705    - emitting a sufficient number of nops, if N_NOPS is nonzero, or
2706    - always emitting the branch as predicted taken, if PREDICT_TAKEN is true.
2707    Either of these is only necessary if the branch is short, otherwise the
2708    template we use ends in an unconditional jump which flushes the pipeline
2709    anyway.  */
2710
2711 void
2712 asm_conditional_branch (rtx insn, rtx *operands, int n_nops, int predict_taken)
2713 {
2714   int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
2715   /* Note : offset for instructions like if cc jmp; jump.[sl] offset
2716             is to be taken from start of if cc rather than jump.
2717             Range for jump.s is (-4094, 4096) instead of (-4096, 4094)
2718   */
2719   int len = (offset >= -1024 && offset <= 1022 ? 0
2720              : offset >= -4094 && offset <= 4096 ? 1
2721              : 2);
2722   int bp = predict_taken && len == 0 ? 1 : cbranch_predicted_taken_p (insn);
2723   int idx = (bp << 1) | (GET_CODE (operands[0]) == EQ ? BRF : BRT);
2724   output_asm_insn (ccbranch_templates[idx][len], operands);
2725   gcc_assert (n_nops == 0 || !bp);
2726   if (len == 0)
2727     while (n_nops-- > 0)
2728       output_asm_insn ("nop;", NULL);
2729 }
2730
2731 /* Emit rtl for a comparison operation CMP in mode MODE.  Operands have been
2732    stored in bfin_compare_op0 and bfin_compare_op1 already.  */
2733
2734 rtx
2735 bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED)
2736 {
2737   enum rtx_code code1, code2;
2738   rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1;
2739   rtx tem = bfin_cc_rtx;
2740   enum rtx_code code = GET_CODE (cmp);
2741
2742   /* If we have a BImode input, then we already have a compare result, and
2743      do not need to emit another comparison.  */
2744   if (GET_MODE (op0) == BImode)
2745     {
2746       gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
2747       tem = op0, code2 = code;
2748     }
2749   else
2750     {
2751       switch (code) {
2752         /* bfin has these conditions */
2753       case EQ:
2754       case LT:
2755       case LE:
2756       case LEU:
2757       case LTU:
2758         code1 = code;
2759         code2 = NE;
2760         break;
2761       default:
2762         code1 = reverse_condition (code);
2763         code2 = EQ;
2764         break;
2765       }
2766       emit_insn (gen_rtx_SET (BImode, tem,
2767                               gen_rtx_fmt_ee (code1, BImode, op0, op1)));
2768     }
2769
2770   return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode));
2771 }
2772 \f
2773 /* Return nonzero iff C has exactly one bit set if it is interpreted
2774    as a 32-bit constant.  */
2775
2776 int
2777 log2constp (unsigned HOST_WIDE_INT c)
2778 {
2779   c &= 0xFFFFFFFF;
2780   return c != 0 && (c & (c-1)) == 0;
2781 }
2782
2783 /* Returns the number of consecutive least significant zeros in the binary
2784    representation of *V.
2785    We modify *V to contain the original value arithmetically shifted right by
2786    the number of zeroes.  */
2787
2788 static int
2789 shiftr_zero (HOST_WIDE_INT *v)
2790 {
2791   unsigned HOST_WIDE_INT tmp = *v;
2792   unsigned HOST_WIDE_INT sgn;
2793   int n = 0;
2794
2795   if (tmp == 0)
2796     return 0;
2797
2798   sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1));
2799   while ((tmp & 0x1) == 0 && n <= 32)
2800     {
2801       tmp = (tmp >> 1) | sgn;
2802       n++;
2803     }
2804   *v = tmp;
2805   return n;
2806 }
2807
2808 /* After reload, split the load of an immediate constant.  OPERANDS are the
2809    operands of the movsi_insn pattern which we are splitting.  We return
2810    nonzero if we emitted a sequence to load the constant, zero if we emitted
2811    nothing because we want to use the splitter's default sequence.  */
2812
2813 int
2814 split_load_immediate (rtx operands[])
2815 {
2816   HOST_WIDE_INT val = INTVAL (operands[1]);
2817   HOST_WIDE_INT tmp;
2818   HOST_WIDE_INT shifted = val;
2819   HOST_WIDE_INT shifted_compl = ~val;
2820   int num_zero = shiftr_zero (&shifted);
2821   int num_compl_zero = shiftr_zero (&shifted_compl);
2822   unsigned int regno = REGNO (operands[0]);
2823
2824   /* This case takes care of single-bit set/clear constants, which we could
2825      also implement with BITSET/BITCLR.  */
2826   if (num_zero
2827       && shifted >= -32768 && shifted < 65536
2828       && (D_REGNO_P (regno)
2829           || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))
2830     {
2831       emit_insn (gen_movsi (operands[0], GEN_INT (shifted)));
2832       emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));
2833       return 1;
2834     }
2835
2836   tmp = val & 0xFFFF;
2837   tmp |= -(tmp & 0x8000);
2838
2839   /* If high word has one bit set or clear, try to use a bit operation.  */
2840   if (D_REGNO_P (regno))
2841     {
2842       if (log2constp (val & 0xFFFF0000))
2843         {
2844           emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));
2845           emit_insn (gen_iorsi3 (operands[0], operands[0], GEN_INT (val & 0xFFFF0000)));
2846           return 1;
2847         }
2848       else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)
2849         {
2850           emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2851           emit_insn (gen_andsi3 (operands[0], operands[0], GEN_INT (val | 0xFFFF)));
2852         }
2853     }
2854
2855   if (D_REGNO_P (regno))
2856     {
2857       if (tmp >= -64 && tmp <= 63)
2858         {
2859           emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2860           emit_insn (gen_movstricthi_high (operands[0], GEN_INT (val & -65536)));
2861           return 1;
2862         }
2863
2864       if ((val & 0xFFFF0000) == 0)
2865         {
2866           emit_insn (gen_movsi (operands[0], const0_rtx));
2867           emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2868           return 1;
2869         }
2870
2871       if ((val & 0xFFFF0000) == 0xFFFF0000)
2872         {
2873           emit_insn (gen_movsi (operands[0], constm1_rtx));
2874           emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2875           return 1;
2876         }
2877     }
2878
2879   /* Need DREGs for the remaining case.  */
2880   if (regno > REG_R7)
2881     return 0;
2882
2883   if (optimize_size
2884       && num_compl_zero && shifted_compl >= -64 && shifted_compl <= 63)
2885     {
2886       /* If optimizing for size, generate a sequence that has more instructions
2887          but is shorter.  */
2888       emit_insn (gen_movsi (operands[0], GEN_INT (shifted_compl)));
2889       emit_insn (gen_ashlsi3 (operands[0], operands[0],
2890                               GEN_INT (num_compl_zero)));
2891       emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
2892       return 1;
2893     }
2894   return 0;
2895 }
2896 \f
2897 /* Return true if the legitimate memory address for a memory operand of mode
2898    MODE.  Return false if not.  */
2899
2900 static bool
2901 bfin_valid_add (enum machine_mode mode, HOST_WIDE_INT value)
2902 {
2903   unsigned HOST_WIDE_INT v = value > 0 ? value : -value;
2904   int sz = GET_MODE_SIZE (mode);
2905   int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2;
2906   /* The usual offsettable_memref machinery doesn't work so well for this
2907      port, so we deal with the problem here.  */
2908   if (value > 0 && sz == 8)
2909     v += 4;
2910   return (v & ~(0x7fff << shift)) == 0;
2911 }
2912
2913 static bool
2914 bfin_valid_reg_p (unsigned int regno, int strict, enum machine_mode mode,
2915                   enum rtx_code outer_code)
2916 {
2917   if (strict)
2918     return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH);
2919   else
2920     return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH);
2921 }
2922
2923 bool
2924 bfin_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
2925 {
2926   switch (GET_CODE (x)) {
2927   case REG:
2928     if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM))
2929       return true;
2930     break;
2931   case PLUS:
2932     if (REG_P (XEXP (x, 0))
2933         && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS)
2934         && ((GET_CODE (XEXP (x, 1)) == UNSPEC && mode == SImode)
2935             || (GET_CODE (XEXP (x, 1)) == CONST_INT
2936                 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
2937       return true;
2938     break;
2939   case POST_INC:
2940   case POST_DEC:
2941     if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2942         && REG_P (XEXP (x, 0))
2943         && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC))
2944       return true;
2945   case PRE_DEC:
2946     if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2947         && XEXP (x, 0) == stack_pointer_rtx
2948         && REG_P (XEXP (x, 0))
2949         && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC))
2950       return true;
2951     break;
2952   default:
2953     break;
2954   }
2955   return false;
2956 }
2957
2958 /* Decide whether we can force certain constants to memory.  If we
2959    decide we can't, the caller should be able to cope with it in
2960    another way.  */
2961
2962 static bool
2963 bfin_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
2964 {
2965   /* We have only one class of non-legitimate constants, and our movsi
2966      expander knows how to handle them.  Dropping these constants into the
2967      data section would only shift the problem - we'd still get relocs
2968      outside the object, in the data section rather than the text section.  */
2969   return true;
2970 }
2971
2972 /* Ensure that for any constant of the form symbol + offset, the offset
2973    remains within the object.  Any other constants are ok.
2974    This ensures that flat binaries never have to deal with relocations
2975    crossing section boundaries.  */
2976
2977 bool
2978 bfin_legitimate_constant_p (rtx x)
2979 {
2980   rtx sym;
2981   HOST_WIDE_INT offset;
2982
2983   if (GET_CODE (x) != CONST)
2984     return true;
2985
2986   x = XEXP (x, 0);
2987   gcc_assert (GET_CODE (x) == PLUS);
2988
2989   sym = XEXP (x, 0);
2990   x = XEXP (x, 1);
2991   if (GET_CODE (sym) != SYMBOL_REF
2992       || GET_CODE (x) != CONST_INT)
2993     return true;
2994   offset = INTVAL (x);
2995
2996   if (SYMBOL_REF_DECL (sym) == 0)
2997     return true;
2998   if (offset < 0
2999       || offset >= int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (sym))))
3000     return false;
3001
3002   return true;
3003 }
3004
3005 static bool
3006 bfin_rtx_costs (rtx x, int code, int outer_code, int *total, bool speed)
3007 {
3008   int cost2 = COSTS_N_INSNS (1);
3009   rtx op0, op1;
3010
3011   switch (code)
3012     {
3013     case CONST_INT:
3014       if (outer_code == SET || outer_code == PLUS)
3015         *total = satisfies_constraint_Ks7 (x) ? 0 : cost2;
3016       else if (outer_code == AND)
3017         *total = log2constp (~INTVAL (x)) ? 0 : cost2;
3018       else if (outer_code == LE || outer_code == LT || outer_code == EQ)
3019         *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
3020       else if (outer_code == LEU || outer_code == LTU)
3021         *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
3022       else if (outer_code == MULT)
3023         *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
3024       else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
3025         *total = 0;
3026       else if (outer_code == ASHIFT || outer_code == ASHIFTRT
3027                || outer_code == LSHIFTRT)
3028         *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
3029       else if (outer_code == IOR || outer_code == XOR)
3030         *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
3031       else
3032         *total = cost2;
3033       return true;
3034
3035     case CONST:
3036     case LABEL_REF:
3037     case SYMBOL_REF:
3038     case CONST_DOUBLE:
3039       *total = COSTS_N_INSNS (2);
3040       return true;
3041
3042     case PLUS:
3043       op0 = XEXP (x, 0);
3044       op1 = XEXP (x, 1);
3045       if (GET_MODE (x) == SImode)
3046         {
3047           if (GET_CODE (op0) == MULT
3048               && GET_CODE (XEXP (op0, 1)) == CONST_INT)
3049             {
3050               HOST_WIDE_INT val = INTVAL (XEXP (op0, 1));
3051               if (val == 2 || val == 4)
3052                 {
3053                   *total = cost2;
3054                   *total += rtx_cost (XEXP (op0, 0), outer_code, speed);
3055                   *total += rtx_cost (op1, outer_code, speed);
3056                   return true;
3057                 }
3058             }
3059           *total = cost2;
3060           if (GET_CODE (op0) != REG
3061               && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3062             *total += rtx_cost (op0, SET, speed);
3063 #if 0 /* We'd like to do this for accuracy, but it biases the loop optimizer
3064          towards creating too many induction variables.  */
3065           if (!reg_or_7bit_operand (op1, SImode))
3066             *total += rtx_cost (op1, SET, speed);
3067 #endif
3068         }
3069       else if (GET_MODE (x) == DImode)
3070         {
3071           *total = 6 * cost2;
3072           if (GET_CODE (op1) != CONST_INT
3073               || !satisfies_constraint_Ks7 (op1))
3074             *total += rtx_cost (op1, PLUS, speed);
3075           if (GET_CODE (op0) != REG
3076               && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3077             *total += rtx_cost (op0, PLUS, speed);
3078         }
3079       return true;
3080
3081     case MINUS:
3082       if (GET_MODE (x) == DImode)
3083         *total = 6 * cost2;
3084       else
3085         *total = cost2;
3086       return true;
3087       
3088     case ASHIFT: 
3089     case ASHIFTRT:
3090     case LSHIFTRT:
3091       if (GET_MODE (x) == DImode)
3092         *total = 6 * cost2;
3093       else
3094         *total = cost2;
3095
3096       op0 = XEXP (x, 0);
3097       op1 = XEXP (x, 1);
3098       if (GET_CODE (op0) != REG
3099           && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3100         *total += rtx_cost (op0, code, speed);
3101
3102       return true;
3103           
3104     case IOR:
3105     case AND:
3106     case XOR:
3107       op0 = XEXP (x, 0);
3108       op1 = XEXP (x, 1);
3109
3110       /* Handle special cases of IOR: rotates, ALIGN insns, movstricthi_high.  */
3111       if (code == IOR)
3112         {
3113           if ((GET_CODE (op0) == LSHIFTRT && GET_CODE (op1) == ASHIFT)
3114               || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == ZERO_EXTEND)
3115               || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT)
3116               || (GET_CODE (op0) == AND && GET_CODE (op1) == CONST_INT))
3117             {
3118               *total = cost2;
3119               return true;
3120             }
3121         }
3122
3123       if (GET_CODE (op0) != REG
3124           && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3125         *total += rtx_cost (op0, code, speed);
3126
3127       if (GET_MODE (x) == DImode)
3128         {
3129           *total = 2 * cost2;
3130           return true;
3131         }
3132       *total = cost2;
3133       if (GET_MODE (x) != SImode)
3134         return true;
3135
3136       if (code == AND)
3137         {
3138           if (! rhs_andsi3_operand (XEXP (x, 1), SImode))
3139             *total += rtx_cost (XEXP (x, 1), code, speed);
3140         }
3141       else
3142         {
3143           if (! regorlog2_operand (XEXP (x, 1), SImode))
3144             *total += rtx_cost (XEXP (x, 1), code, speed);
3145         }
3146
3147       return true;
3148
3149     case ZERO_EXTRACT:
3150     case SIGN_EXTRACT:
3151       if (outer_code == SET
3152           && XEXP (x, 1) == const1_rtx
3153           && GET_CODE (XEXP (x, 2)) == CONST_INT)
3154         {
3155           *total = 2 * cost2;
3156           return true;
3157         }
3158       /* fall through */
3159
3160     case SIGN_EXTEND:
3161     case ZERO_EXTEND:
3162       *total = cost2;
3163       return true;
3164
3165     case MULT:
3166         {
3167           op0 = XEXP (x, 0);
3168           op1 = XEXP (x, 1);
3169           if (GET_CODE (op0) == GET_CODE (op1)
3170               && (GET_CODE (op0) == ZERO_EXTEND
3171                   || GET_CODE (op0) == SIGN_EXTEND))
3172             {
3173               *total = COSTS_N_INSNS (1);
3174               op0 = XEXP (op0, 0);
3175               op1 = XEXP (op1, 0);
3176             }
3177           else if (!speed)
3178             *total = COSTS_N_INSNS (1);
3179           else
3180             *total = COSTS_N_INSNS (3);
3181
3182           if (GET_CODE (op0) != REG
3183               && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3184             *total += rtx_cost (op0, MULT, speed);
3185           if (GET_CODE (op1) != REG
3186               && (GET_CODE (op1) != SUBREG || GET_CODE (SUBREG_REG (op1)) != REG))
3187             *total += rtx_cost (op1, MULT, speed);
3188         }
3189       return true;
3190
3191     case UDIV:
3192     case UMOD:
3193       *total = COSTS_N_INSNS (32);
3194       return true;
3195
3196     case VEC_CONCAT:
3197     case VEC_SELECT:
3198       if (outer_code == SET)
3199         *total = cost2;
3200       return true;
3201
3202     default:
3203       return false;
3204     }
3205 }
3206 \f
3207 /* Used for communication between {push,pop}_multiple_operation (which
3208    we use not only as a predicate) and the corresponding output functions.  */
3209 static int first_preg_to_save, first_dreg_to_save;
3210 static int n_regs_to_save;
3211
3212 int
3213 push_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
3214 {
3215   int lastdreg = 8, lastpreg = 6;
3216   int i, group;
3217
3218   first_preg_to_save = lastpreg;
3219   first_dreg_to_save = lastdreg;
3220   for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
3221     {
3222       rtx t = XVECEXP (op, 0, i);
3223       rtx src, dest;
3224       int regno;
3225
3226       if (GET_CODE (t) != SET)
3227         return 0;
3228
3229       src = SET_SRC (t);
3230       dest = SET_DEST (t);
3231       if (GET_CODE (dest) != MEM || ! REG_P (src))
3232         return 0;
3233       dest = XEXP (dest, 0);
3234       if (GET_CODE (dest) != PLUS
3235           || ! REG_P (XEXP (dest, 0))
3236           || REGNO (XEXP (dest, 0)) != REG_SP
3237           || GET_CODE (XEXP (dest, 1)) != CONST_INT
3238           || INTVAL (XEXP (dest, 1)) != -i * 4)
3239         return 0;
3240
3241       regno = REGNO (src);
3242       if (group == 0)
3243         {
3244           if (D_REGNO_P (regno))
3245             {
3246               group = 1;
3247               first_dreg_to_save = lastdreg = regno - REG_R0;
3248             }
3249           else if (regno >= REG_P0 && regno <= REG_P7)
3250             {
3251               group = 2;
3252               first_preg_to_save = lastpreg = regno - REG_P0;
3253             }
3254           else
3255             return 0;
3256
3257           continue;
3258         }
3259
3260       if (group == 1)
3261         {
3262           if (regno >= REG_P0 && regno <= REG_P7)
3263             {
3264               group = 2;
3265               first_preg_to_save = lastpreg = regno - REG_P0;
3266             }
3267           else if (regno != REG_R0 + lastdreg + 1)
3268             return 0;
3269           else
3270             lastdreg++;
3271         }
3272       else if (group == 2)
3273         {
3274           if (regno != REG_P0 + lastpreg + 1)
3275             return 0;
3276           lastpreg++;
3277         }
3278     }
3279   n_regs_to_save = 8 - first_dreg_to_save + 6 - first_preg_to_save;
3280   return 1;
3281 }
3282
3283 int
3284 pop_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
3285 {
3286   int lastdreg = 8, lastpreg = 6;
3287   int i, group;
3288
3289   for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
3290     {
3291       rtx t = XVECEXP (op, 0, i);
3292       rtx src, dest;
3293       int regno;
3294
3295       if (GET_CODE (t) != SET)
3296         return 0;
3297
3298       src = SET_SRC (t);
3299       dest = SET_DEST (t);
3300       if (GET_CODE (src) != MEM || ! REG_P (dest))
3301         return 0;
3302       src = XEXP (src, 0);
3303
3304       if (i == 1)
3305         {
3306           if (! REG_P (src) || REGNO (src) != REG_SP)
3307             return 0;
3308         }
3309       else if (GET_CODE (src) != PLUS
3310                || ! REG_P (XEXP (src, 0))
3311                || REGNO (XEXP (src, 0)) != REG_SP
3312                || GET_CODE (XEXP (src, 1)) != CONST_INT
3313                || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
3314         return 0;
3315
3316       regno = REGNO (dest);
3317       if (group == 0)
3318         {
3319           if (regno == REG_R7)
3320             {
3321               group = 1;
3322               lastdreg = 7;
3323             }
3324           else if (regno != REG_P0 + lastpreg - 1)
3325             return 0;
3326           else
3327             lastpreg--;
3328         }
3329       else if (group == 1)
3330         {
3331           if (regno != REG_R0 + lastdreg - 1)
3332             return 0;
3333           else
3334             lastdreg--;
3335         }
3336     }
3337   first_dreg_to_save = lastdreg;
3338   first_preg_to_save = lastpreg;
3339   n_regs_to_save = 8 - first_dreg_to_save + 6 - first_preg_to_save;
3340   return 1;
3341 }
3342
3343 /* Emit assembly code for one multi-register push described by INSN, with
3344    operands in OPERANDS.  */
3345
3346 void
3347 output_push_multiple (rtx insn, rtx *operands)
3348 {
3349   char buf[80];
3350   int ok;
3351   
3352   /* Validate the insn again, and compute first_[dp]reg_to_save. */
3353   ok = push_multiple_operation (PATTERN (insn), VOIDmode);
3354   gcc_assert (ok);
3355   
3356   if (first_dreg_to_save == 8)
3357     sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
3358   else if (first_preg_to_save == 6)
3359     sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
3360   else
3361     sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
3362              first_dreg_to_save, first_preg_to_save);
3363
3364   output_asm_insn (buf, operands);
3365 }
3366
3367 /* Emit assembly code for one multi-register pop described by INSN, with
3368    operands in OPERANDS.  */
3369
3370 void
3371 output_pop_multiple (rtx insn, rtx *operands)
3372 {
3373   char buf[80];
3374   int ok;
3375   
3376   /* Validate the insn again, and compute first_[dp]reg_to_save. */
3377   ok = pop_multiple_operation (PATTERN (insn), VOIDmode);
3378   gcc_assert (ok);
3379
3380   if (first_dreg_to_save == 8)
3381     sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
3382   else if (first_preg_to_save == 6)
3383     sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
3384   else
3385     sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
3386              first_dreg_to_save, first_preg_to_save);
3387
3388   output_asm_insn (buf, operands);
3389 }
3390
3391 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE.  */
3392
3393 static void
3394 single_move_for_movmem (rtx dst, rtx src, enum machine_mode mode, HOST_WIDE_INT offset)
3395 {
3396   rtx scratch = gen_reg_rtx (mode);
3397   rtx srcmem, dstmem;
3398
3399   srcmem = adjust_address_nv (src, mode, offset);
3400   dstmem = adjust_address_nv (dst, mode, offset);
3401   emit_move_insn (scratch, srcmem);
3402   emit_move_insn (dstmem, scratch);
3403 }
3404
3405 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
3406    alignment ALIGN_EXP.  Return true if successful, false if we should fall
3407    back on a different method.  */
3408
3409 bool
3410 bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
3411 {
3412   rtx srcreg, destreg, countreg;
3413   HOST_WIDE_INT align = 0;
3414   unsigned HOST_WIDE_INT count = 0;
3415
3416   if (GET_CODE (align_exp) == CONST_INT)
3417     align = INTVAL (align_exp);
3418   if (GET_CODE (count_exp) == CONST_INT)
3419     {
3420       count = INTVAL (count_exp);
3421 #if 0
3422       if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
3423         return false;
3424 #endif
3425     }
3426
3427   /* If optimizing for size, only do single copies inline.  */
3428   if (optimize_size)
3429     {
3430       if (count == 2 && align < 2)
3431         return false;
3432       if (count == 4 && align < 4)
3433         return false;
3434       if (count != 1 && count != 2 && count != 4)
3435         return false;
3436     }
3437   if (align < 2 && count != 1)
3438     return false;
3439
3440   destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
3441   if (destreg != XEXP (dst, 0))
3442     dst = replace_equiv_address_nv (dst, destreg);
3443   srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
3444   if (srcreg != XEXP (src, 0))
3445     src = replace_equiv_address_nv (src, srcreg);
3446
3447   if (count != 0 && align >= 2)
3448     {
3449       unsigned HOST_WIDE_INT offset = 0;
3450
3451       if (align >= 4)
3452         {
3453           if ((count & ~3) == 4)
3454             {
3455               single_move_for_movmem (dst, src, SImode, offset);
3456               offset = 4;
3457             }
3458           else if (count & ~3)
3459             {
3460               HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
3461               countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3462
3463               emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
3464               cfun->machine->has_loopreg_clobber = true;
3465             }
3466           if (count & 2)
3467             {
3468               single_move_for_movmem (dst, src, HImode, offset);
3469               offset += 2;
3470             }
3471         }
3472       else
3473         {
3474           if ((count & ~1) == 2)
3475             {
3476               single_move_for_movmem (dst, src, HImode, offset);
3477               offset = 2;
3478             }
3479           else if (count & ~1)
3480             {
3481               HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
3482               countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3483
3484               emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
3485               cfun->machine->has_loopreg_clobber = true;
3486             }
3487         }
3488       if (count & 1)
3489         {
3490           single_move_for_movmem (dst, src, QImode, offset);
3491         }
3492       return true;
3493     }
3494   return false;
3495 }
3496 \f
3497 /* Compute the alignment for a local variable.
3498    TYPE is the data type, and ALIGN is the alignment that
3499    the object would ordinarily have.  The value of this macro is used
3500    instead of that alignment to align the object.  */
3501
3502 int
3503 bfin_local_alignment (tree type, int align)
3504 {
3505   /* Increasing alignment for (relatively) big types allows the builtin
3506      memcpy can use 32 bit loads/stores.  */
3507