OSDN Git Service

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