OSDN Git Service

* config/bfin/bfin.c (gen_one_bundle): Delete unused local variables.
[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 2, 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 COPYING.  If not, write to
19    the Free Software Foundation, 51 Franklin Street, Fifth Floor,
20    Boston, MA 02110-1301, USA.  */
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "rtl.h"
27 #include "regs.h"
28 #include "hard-reg-set.h"
29 #include "real.h"
30 #include "insn-config.h"
31 #include "insn-codes.h"
32 #include "conditions.h"
33 #include "insn-flags.h"
34 #include "output.h"
35 #include "insn-attr.h"
36 #include "tree.h"
37 #include "flags.h"
38 #include "except.h"
39 #include "function.h"
40 #include "input.h"
41 #include "target.h"
42 #include "target-def.h"
43 #include "expr.h"
44 #include "toplev.h"
45 #include "recog.h"
46 #include "optabs.h"
47 #include "ggc.h"
48 #include "integrate.h"
49 #include "cgraph.h"
50 #include "langhooks.h"
51 #include "bfin-protos.h"
52 #include "tm-preds.h"
53 #include "gt-bfin.h"
54 #include "basic-block.h"
55 #include "cfglayout.h"
56 #include "timevar.h"
57 #include "df.h"
58
59 /* A C structure for machine-specific, per-function data.
60    This is added to the cfun structure.  */
61 struct machine_function GTY(())
62 {
63   int has_hardware_loops;
64 };
65
66 /* Test and compare insns in bfin.md store the information needed to
67    generate branch and scc insns here.  */
68 rtx bfin_compare_op0, bfin_compare_op1;
69
70 /* RTX for condition code flag register and RETS register */
71 extern GTY(()) rtx bfin_cc_rtx;
72 extern GTY(()) rtx bfin_rets_rtx;
73 rtx bfin_cc_rtx, bfin_rets_rtx;
74
75 int max_arg_registers = 0;
76
77 /* Arrays used when emitting register names.  */
78 const char *short_reg_names[]  =  SHORT_REGISTER_NAMES;
79 const char *high_reg_names[]   =  HIGH_REGISTER_NAMES;
80 const char *dregs_pair_names[] =  DREGS_PAIR_NAMES;
81 const char *byte_reg_names[]   =  BYTE_REGISTER_NAMES;
82
83 static int arg_regs[] = FUNCTION_ARG_REGISTERS;
84
85 /* Nonzero if -mshared-library-id was given.  */
86 static int bfin_lib_id_given;
87
88 /* Nonzero if -fschedule-insns2 was given.  We override it and
89    call the scheduler ourselves during reorg.  */
90 static int bfin_flag_schedule_insns2;
91
92 /* Determines whether we run variable tracking in machine dependent
93    reorganization.  */
94 static int bfin_flag_var_tracking;
95
96 /* -mcpu support */
97 bfin_cpu_t bfin_cpu_type = DEFAULT_CPU_TYPE;
98
99 int splitting_for_sched;
100
101 static void
102 bfin_globalize_label (FILE *stream, const char *name)
103 {
104   fputs (".global ", stream);
105   assemble_name (stream, name);
106   fputc (';',stream);
107   fputc ('\n',stream);
108 }
109
110 static void 
111 output_file_start (void) 
112 {
113   FILE *file = asm_out_file;
114   int i;
115
116   /* Variable tracking should be run after all optimizations which change order
117      of insns.  It also needs a valid CFG.  This can't be done in
118      override_options, because flag_var_tracking is finalized after
119      that.  */
120   bfin_flag_var_tracking = flag_var_tracking;
121   flag_var_tracking = 0;
122
123   fprintf (file, ".file \"%s\";\n", input_filename);
124   
125   for (i = 0; arg_regs[i] >= 0; i++)
126     ;
127   max_arg_registers = i;        /* how many arg reg used  */
128 }
129
130 /* Called early in the compilation to conditionally modify
131    fixed_regs/call_used_regs.  */
132
133 void 
134 conditional_register_usage (void)
135 {
136   /* initialize condition code flag register rtx */
137   bfin_cc_rtx = gen_rtx_REG (BImode, REG_CC);
138   bfin_rets_rtx = gen_rtx_REG (Pmode, REG_RETS);
139 }
140
141 /* Examine machine-dependent attributes of function type FUNTYPE and return its
142    type.  See the definition of E_FUNKIND.  */
143
144 static e_funkind funkind (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 (!no_new_pseudos);
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 (!no_new_pseudos);
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               gcc_assert (REGNO (x) < 32);
1315               fprintf (file, "%s", short_reg_names[REGNO (x)]);
1316               /*fprintf (file, "\n%d\n ", REGNO (x));*/
1317               break;
1318             }
1319           else if (code == 'd')
1320             {
1321               gcc_assert (REGNO (x) < 32);
1322               fprintf (file, "%s", high_reg_names[REGNO (x)]);
1323               break;
1324             }
1325           else if (code == 'w')
1326             {
1327               gcc_assert (REGNO (x) == REG_A0 || REGNO (x) == REG_A1);
1328               fprintf (file, "%s.w", reg_names[REGNO (x)]);
1329             }
1330           else if (code == 'x')
1331             {
1332               gcc_assert (REGNO (x) == REG_A0 || REGNO (x) == REG_A1);
1333               fprintf (file, "%s.x", reg_names[REGNO (x)]);
1334             }
1335           else if (code == 'v')
1336             {
1337               if (REGNO (x) == REG_A0)
1338                 fprintf (file, "AV0");
1339               else if (REGNO (x) == REG_A1)
1340                 fprintf (file, "AV1");
1341               else
1342                 output_operand_lossage ("invalid operand for code '%c'", code);
1343             }
1344           else if (code == 'D')
1345             {
1346               fprintf (file, "%s", dregs_pair_names[REGNO (x)]);
1347             }
1348           else if (code == 'H')
1349             {
1350               gcc_assert (mode == DImode || mode == DFmode);
1351               gcc_assert (REG_P (x));
1352               fprintf (file, "%s", reg_names[REGNO (x) + 1]);
1353             }
1354           else if (code == 'T')
1355             {
1356               gcc_assert (D_REGNO_P (REGNO (x)));
1357               fprintf (file, "%s", byte_reg_names[REGNO (x)]);
1358             }
1359           else 
1360             fprintf (file, "%s", reg_names[REGNO (x)]);
1361           break;
1362
1363         case MEM:
1364           fputc ('[', file);
1365           x = XEXP (x,0);
1366           print_address_operand (file, x);
1367           fputc (']', file);
1368           break;
1369
1370         case CONST_INT:
1371           if (code == 'M')
1372             {
1373               switch (INTVAL (x))
1374                 {
1375                 case MACFLAG_NONE:
1376                   break;
1377                 case MACFLAG_FU:
1378                   fputs ("(FU)", file);
1379                   break;
1380                 case MACFLAG_T:
1381                   fputs ("(T)", file);
1382                   break;
1383                 case MACFLAG_TFU:
1384                   fputs ("(TFU)", file);
1385                   break;
1386                 case MACFLAG_W32:
1387                   fputs ("(W32)", file);
1388                   break;
1389                 case MACFLAG_IS:
1390                   fputs ("(IS)", file);
1391                   break;
1392                 case MACFLAG_IU:
1393                   fputs ("(IU)", file);
1394                   break;
1395                 case MACFLAG_IH:
1396                   fputs ("(IH)", file);
1397                   break;
1398                 case MACFLAG_M:
1399                   fputs ("(M)", file);
1400                   break;
1401                 case MACFLAG_IS_M:
1402                   fputs ("(IS,M)", file);
1403                   break;
1404                 case MACFLAG_ISS2:
1405                   fputs ("(ISS2)", file);
1406                   break;
1407                 case MACFLAG_S2RND:
1408                   fputs ("(S2RND)", file);
1409                   break;
1410                 default:
1411                   gcc_unreachable ();
1412                 }
1413               break;
1414             }
1415           else if (code == 'b')
1416             {
1417               if (INTVAL (x) == 0)
1418                 fputs ("+=", file);
1419               else if (INTVAL (x) == 1)
1420                 fputs ("-=", file);
1421               else
1422                 gcc_unreachable ();
1423               break;
1424             }
1425           /* Moves to half registers with d or h modifiers always use unsigned
1426              constants.  */
1427           else if (code == 'd')
1428             x = GEN_INT ((INTVAL (x) >> 16) & 0xffff);
1429           else if (code == 'h')
1430             x = GEN_INT (INTVAL (x) & 0xffff);
1431           else if (code == 'N')
1432             x = GEN_INT (-INTVAL (x));
1433           else if (code == 'X')
1434             x = GEN_INT (exact_log2 (0xffffffff & INTVAL (x)));
1435           else if (code == 'Y')
1436             x = GEN_INT (exact_log2 (0xffffffff & ~INTVAL (x)));
1437           else if (code == 'Z')
1438             /* Used for LINK insns.  */
1439             x = GEN_INT (-8 - INTVAL (x));
1440
1441           /* fall through */
1442
1443         case SYMBOL_REF:
1444           output_addr_const (file, x);
1445           break;
1446
1447         case CONST_DOUBLE:
1448           output_operand_lossage ("invalid const_double operand");
1449           break;
1450
1451         case UNSPEC:
1452           switch (XINT (x, 1))
1453             {
1454             case UNSPEC_MOVE_PIC:
1455               output_addr_const (file, XVECEXP (x, 0, 0));
1456               fprintf (file, "@GOT");
1457               break;
1458
1459             case UNSPEC_MOVE_FDPIC:
1460               output_addr_const (file, XVECEXP (x, 0, 0));
1461               fprintf (file, "@GOT17M4");
1462               break;
1463
1464             case UNSPEC_FUNCDESC_GOT17M4:
1465               output_addr_const (file, XVECEXP (x, 0, 0));
1466               fprintf (file, "@FUNCDESC_GOT17M4");
1467               break;
1468
1469             case UNSPEC_LIBRARY_OFFSET:
1470               fprintf (file, "_current_shared_library_p5_offset_");
1471               break;
1472
1473             default:
1474               gcc_unreachable ();
1475             }
1476           break;
1477
1478         default:
1479           output_addr_const (file, x);
1480         }
1481     }
1482 }
1483 \f
1484 /* Argument support functions.  */
1485
1486 /* Initialize a variable CUM of type CUMULATIVE_ARGS
1487    for a call to a function whose data type is FNTYPE.
1488    For a library call, FNTYPE is 0.  
1489    VDSP C Compiler manual, our ABI says that
1490    first 3 words of arguments will use R0, R1 and R2.
1491 */
1492
1493 void
1494 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
1495                       rtx libname ATTRIBUTE_UNUSED)
1496 {
1497   static CUMULATIVE_ARGS zero_cum;
1498
1499   *cum = zero_cum;
1500
1501   /* Set up the number of registers to use for passing arguments.  */
1502
1503   cum->nregs = max_arg_registers;
1504   cum->arg_regs = arg_regs;
1505
1506   cum->call_cookie = CALL_NORMAL;
1507   /* Check for a longcall attribute.  */
1508   if (fntype && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype)))
1509     cum->call_cookie |= CALL_SHORT;
1510   else if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)))
1511     cum->call_cookie |= CALL_LONG;
1512
1513   return;
1514 }
1515
1516 /* Update the data in CUM to advance over an argument
1517    of mode MODE and data type TYPE.
1518    (TYPE is null for libcalls where that information may not be available.)  */
1519
1520 void
1521 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1522                       int named ATTRIBUTE_UNUSED)
1523 {
1524   int count, bytes, words;
1525
1526   bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1527   words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1528
1529   cum->words += words;
1530   cum->nregs -= words;
1531
1532   if (cum->nregs <= 0)
1533     {
1534       cum->nregs = 0;
1535       cum->arg_regs = NULL;
1536     }
1537   else
1538     {
1539       for (count = 1; count <= words; count++)
1540         cum->arg_regs++;
1541     }
1542
1543   return;
1544 }
1545
1546 /* Define where to put the arguments to a function.
1547    Value is zero to push the argument on the stack,
1548    or a hard register in which to store the argument.
1549
1550    MODE is the argument's machine mode.
1551    TYPE is the data type of the argument (as a tree).
1552     This is null for libcalls where that information may
1553     not be available.
1554    CUM is a variable of type CUMULATIVE_ARGS which gives info about
1555     the preceding args and about the function being called.
1556    NAMED is nonzero if this argument is a named parameter
1557     (otherwise it is an extra parameter matching an ellipsis).  */
1558
1559 struct rtx_def *
1560 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1561               int named ATTRIBUTE_UNUSED)
1562 {
1563   int bytes
1564     = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1565
1566   if (mode == VOIDmode)
1567     /* Compute operand 2 of the call insn.  */
1568     return GEN_INT (cum->call_cookie);
1569
1570   if (bytes == -1)
1571     return NULL_RTX;
1572
1573   if (cum->nregs)
1574     return gen_rtx_REG (mode, *(cum->arg_regs));
1575
1576   return NULL_RTX;
1577 }
1578
1579 /* For an arg passed partly in registers and partly in memory,
1580    this is the number of bytes passed in registers.
1581    For args passed entirely in registers or entirely in memory, zero.
1582
1583    Refer VDSP C Compiler manual, our ABI.
1584    First 3 words are in registers. So, if an argument is larger
1585    than the registers available, it will span the register and
1586    stack.   */
1587
1588 static int
1589 bfin_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1590                         tree type ATTRIBUTE_UNUSED,
1591                         bool named ATTRIBUTE_UNUSED)
1592 {
1593   int bytes
1594     = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1595   int bytes_left = cum->nregs * UNITS_PER_WORD;
1596   
1597   if (bytes == -1)
1598     return 0;
1599
1600   if (bytes_left == 0)
1601     return 0;
1602   if (bytes > bytes_left)
1603     return bytes_left;
1604   return 0;
1605 }
1606
1607 /* Variable sized types are passed by reference.  */
1608
1609 static bool
1610 bfin_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
1611                         enum machine_mode mode ATTRIBUTE_UNUSED,
1612                         tree type, bool named ATTRIBUTE_UNUSED)
1613 {
1614   return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
1615 }
1616
1617 /* Decide whether a type should be returned in memory (true)
1618    or in a register (false).  This is called by the macro
1619    RETURN_IN_MEMORY.  */
1620
1621 int
1622 bfin_return_in_memory (tree type)
1623 {
1624   int size = int_size_in_bytes (type);
1625   return size > 2 * UNITS_PER_WORD || size == -1;
1626 }
1627
1628 /* Register in which address to store a structure value
1629    is passed to a function.  */
1630 static rtx
1631 bfin_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
1632                       int incoming ATTRIBUTE_UNUSED)
1633 {
1634   return gen_rtx_REG (Pmode, REG_P0);
1635 }
1636
1637 /* Return true when register may be used to pass function parameters.  */
1638
1639 bool 
1640 function_arg_regno_p (int n)
1641 {
1642   int i;
1643   for (i = 0; arg_regs[i] != -1; i++)
1644     if (n == arg_regs[i])
1645       return true;
1646   return false;
1647 }
1648
1649 /* Returns 1 if OP contains a symbol reference */
1650
1651 int
1652 symbolic_reference_mentioned_p (rtx op)
1653 {
1654   register const char *fmt;
1655   register int i;
1656
1657   if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
1658     return 1;
1659
1660   fmt = GET_RTX_FORMAT (GET_CODE (op));
1661   for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
1662     {
1663       if (fmt[i] == 'E')
1664         {
1665           register int j;
1666
1667           for (j = XVECLEN (op, i) - 1; j >= 0; j--)
1668             if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
1669               return 1;
1670         }
1671
1672       else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
1673         return 1;
1674     }
1675
1676   return 0;
1677 }
1678
1679 /* Decide whether we can make a sibling call to a function.  DECL is the
1680    declaration of the function being targeted by the call and EXP is the
1681    CALL_EXPR representing the call.  */
1682
1683 static bool
1684 bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
1685                               tree exp ATTRIBUTE_UNUSED)
1686 {
1687   e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1688   if (fkind != SUBROUTINE)
1689     return false;
1690   if (!TARGET_ID_SHARED_LIBRARY || TARGET_SEP_DATA)
1691     return true;
1692
1693   /* When compiling for ID shared libraries, can't sibcall a local function
1694      from a non-local function, because the local function thinks it does
1695      not need to reload P5 in the prologue, but the sibcall wil pop P5 in the
1696      sibcall epilogue, and we end up with the wrong value in P5.  */
1697
1698   if (!flag_unit_at_a_time || decl == NULL)
1699     /* Not enough information.  */
1700     return false;
1701
1702   {
1703     struct cgraph_local_info *this_func, *called_func;
1704  
1705     this_func = cgraph_local_info (current_function_decl);
1706     called_func = cgraph_local_info (decl);
1707     return !called_func->local || this_func->local;
1708   }
1709 }
1710 \f
1711 /* Emit RTL insns to initialize the variable parts of a trampoline at
1712    TRAMP. FNADDR is an RTX for the address of the function's pure
1713    code.  CXT is an RTX for the static chain value for the function.  */
1714
1715 void
1716 initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt)
1717 {
1718   rtx t1 = copy_to_reg (fnaddr);
1719   rtx t2 = copy_to_reg (cxt);
1720   rtx addr;
1721   int i = 0;
1722
1723   if (TARGET_FDPIC)
1724     {
1725       rtx a = memory_address (Pmode, plus_constant (tramp, 8));
1726       addr = memory_address (Pmode, tramp);
1727       emit_move_insn (gen_rtx_MEM (SImode, addr), a);
1728       i = 8;
1729     }
1730
1731   addr = memory_address (Pmode, plus_constant (tramp, i + 2));
1732   emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
1733   emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16)));
1734   addr = memory_address (Pmode, plus_constant (tramp, i + 6));
1735   emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
1736
1737   addr = memory_address (Pmode, plus_constant (tramp, i + 10));
1738   emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
1739   emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16)));
1740   addr = memory_address (Pmode, plus_constant (tramp, i + 14));
1741   emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
1742 }
1743
1744 /* Emit insns to move operands[1] into operands[0].  */
1745
1746 void
1747 emit_pic_move (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
1748 {
1749   rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
1750
1751   gcc_assert (!TARGET_FDPIC || !(reload_in_progress || reload_completed));
1752   if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
1753     operands[1] = force_reg (SImode, operands[1]);
1754   else
1755     operands[1] = legitimize_pic_address (operands[1], temp,
1756                                           TARGET_FDPIC ? OUR_FDPIC_REG
1757                                           : pic_offset_table_rtx);
1758 }
1759
1760 /* Expand a move operation in mode MODE.  The operands are in OPERANDS.
1761    Returns true if no further code must be generated, false if the caller
1762    should generate an insn to move OPERANDS[1] to OPERANDS[0].  */
1763
1764 bool
1765 expand_move (rtx *operands, enum machine_mode mode)
1766 {
1767   rtx op = operands[1];
1768   if ((TARGET_ID_SHARED_LIBRARY || TARGET_FDPIC)
1769       && SYMBOLIC_CONST (op))
1770     emit_pic_move (operands, mode);
1771   else if (mode == SImode && GET_CODE (op) == CONST
1772            && GET_CODE (XEXP (op, 0)) == PLUS
1773            && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
1774            && !bfin_legitimate_constant_p (op))
1775     {
1776       rtx dest = operands[0];
1777       rtx op0, op1;
1778       gcc_assert (!reload_in_progress && !reload_completed);
1779       op = XEXP (op, 0);
1780       op0 = force_reg (mode, XEXP (op, 0));
1781       op1 = XEXP (op, 1);
1782       if (!insn_data[CODE_FOR_addsi3].operand[2].predicate (op1, mode))
1783         op1 = force_reg (mode, op1);
1784       if (GET_CODE (dest) == MEM)
1785         dest = gen_reg_rtx (mode);
1786       emit_insn (gen_addsi3 (dest, op0, op1));
1787       if (dest == operands[0])
1788         return true;
1789       operands[1] = dest;
1790     }
1791   /* Don't generate memory->memory or constant->memory moves, go through a
1792      register */
1793   else if ((reload_in_progress | reload_completed) == 0
1794            && GET_CODE (operands[0]) == MEM
1795            && GET_CODE (operands[1]) != REG)
1796     operands[1] = force_reg (mode, operands[1]);
1797   return false;
1798 }
1799 \f
1800 /* Split one or more DImode RTL references into pairs of SImode
1801    references.  The RTL can be REG, offsettable MEM, integer constant, or
1802    CONST_DOUBLE.  "operands" is a pointer to an array of DImode RTL to
1803    split and "num" is its length.  lo_half and hi_half are output arrays
1804    that parallel "operands".  */
1805
1806 void
1807 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
1808 {
1809   while (num--)
1810     {
1811       rtx op = operands[num];
1812
1813       /* simplify_subreg refuse to split volatile memory addresses,
1814          but we still have to handle it.  */
1815       if (GET_CODE (op) == MEM)
1816         {
1817           lo_half[num] = adjust_address (op, SImode, 0);
1818           hi_half[num] = adjust_address (op, SImode, 4);
1819         }
1820       else
1821         {
1822           lo_half[num] = simplify_gen_subreg (SImode, op,
1823                                               GET_MODE (op) == VOIDmode
1824                                               ? DImode : GET_MODE (op), 0);
1825           hi_half[num] = simplify_gen_subreg (SImode, op,
1826                                               GET_MODE (op) == VOIDmode
1827                                               ? DImode : GET_MODE (op), 4);
1828         }
1829     }
1830 }
1831 \f
1832 bool
1833 bfin_longcall_p (rtx op, int call_cookie)
1834 {
1835   gcc_assert (GET_CODE (op) == SYMBOL_REF);
1836   if (call_cookie & CALL_SHORT)
1837     return 0;
1838   if (call_cookie & CALL_LONG)
1839     return 1;
1840   if (TARGET_LONG_CALLS)
1841     return 1;
1842   return 0;
1843 }
1844
1845 /* Expand a call instruction.  FNADDR is the call target, RETVAL the return value.
1846    COOKIE is a CONST_INT holding the call_cookie prepared init_cumulative_args.
1847    SIBCALL is nonzero if this is a sibling call.  */
1848
1849 void
1850 bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
1851 {
1852   rtx use = NULL, call;
1853   rtx callee = XEXP (fnaddr, 0);
1854   int nelts = 2 + !!sibcall;
1855   rtx pat;
1856   rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REGNO);
1857   int n;
1858
1859   /* In an untyped call, we can get NULL for operand 2.  */
1860   if (cookie == NULL_RTX)
1861     cookie = const0_rtx;
1862
1863   /* Static functions and indirect calls don't need the pic register.  */
1864   if (!TARGET_FDPIC && flag_pic
1865       && GET_CODE (callee) == SYMBOL_REF
1866       && !SYMBOL_REF_LOCAL_P (callee))
1867     use_reg (&use, pic_offset_table_rtx);
1868
1869   if (TARGET_FDPIC)
1870     {
1871       if (GET_CODE (callee) != SYMBOL_REF
1872           || bfin_longcall_p (callee, INTVAL (cookie)))
1873         {
1874           rtx addr = callee;
1875           if (! address_operand (addr, Pmode))
1876             addr = force_reg (Pmode, addr);
1877
1878           fnaddr = gen_reg_rtx (SImode);
1879           emit_insn (gen_load_funcdescsi (fnaddr, addr));
1880           fnaddr = gen_rtx_MEM (Pmode, fnaddr);
1881
1882           picreg = gen_reg_rtx (SImode);
1883           emit_insn (gen_load_funcdescsi (picreg,
1884                                           plus_constant (addr, 4)));
1885         }
1886
1887       nelts++;
1888     }
1889   else if ((!register_no_elim_operand (callee, Pmode)
1890             && GET_CODE (callee) != SYMBOL_REF)
1891            || (GET_CODE (callee) == SYMBOL_REF
1892                && ((TARGET_ID_SHARED_LIBRARY && !TARGET_LEAF_ID_SHARED_LIBRARY)
1893                    || bfin_longcall_p (callee, INTVAL (cookie)))))
1894     {
1895       callee = copy_to_mode_reg (Pmode, callee);
1896       fnaddr = gen_rtx_MEM (Pmode, callee);
1897     }
1898   call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
1899
1900   if (retval)
1901     call = gen_rtx_SET (VOIDmode, retval, call);
1902
1903   pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nelts));
1904   n = 0;
1905   XVECEXP (pat, 0, n++) = call;
1906   if (TARGET_FDPIC)
1907     XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, picreg);
1908   XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie);
1909   if (sibcall)
1910     XVECEXP (pat, 0, n++) = gen_rtx_RETURN (VOIDmode);
1911   call = emit_call_insn (pat);
1912   if (use)
1913     CALL_INSN_FUNCTION_USAGE (call) = use;
1914 }
1915 \f
1916 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE.  */
1917
1918 int
1919 hard_regno_mode_ok (int regno, enum machine_mode mode)
1920 {
1921   /* Allow only dregs to store value of mode HI or QI */
1922   enum reg_class class = REGNO_REG_CLASS (regno);
1923
1924   if (mode == CCmode)
1925     return 0;
1926
1927   if (mode == V2HImode)
1928     return D_REGNO_P (regno);
1929   if (class == CCREGS)
1930     return mode == BImode;
1931   if (mode == PDImode || mode == V2PDImode)
1932     return regno == REG_A0 || regno == REG_A1;
1933
1934   /* Allow all normal 32-bit regs, except REG_M3, in case regclass ever comes
1935      up with a bad register class (such as ALL_REGS) for DImode.  */
1936   if (mode == DImode)
1937     return regno < REG_M3;
1938
1939   if (mode == SImode
1940       && TEST_HARD_REG_BIT (reg_class_contents[PROLOGUE_REGS], regno))
1941     return 1;
1942
1943   return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno);
1944 }
1945
1946 /* Implements target hook vector_mode_supported_p.  */
1947
1948 static bool
1949 bfin_vector_mode_supported_p (enum machine_mode mode)
1950 {
1951   return mode == V2HImode;
1952 }
1953
1954 /* Return the cost of moving data from a register in class CLASS1 to
1955    one in class CLASS2.  A cost of 2 is the default.  */
1956
1957 int
1958 bfin_register_move_cost (enum machine_mode mode,
1959                          enum reg_class class1, enum reg_class class2)
1960 {
1961   /* These need secondary reloads, so they're more expensive.  */
1962   if ((class1 == CCREGS && class2 != DREGS)
1963       || (class1 != DREGS && class2 == CCREGS))
1964     return 4;
1965
1966   /* If optimizing for size, always prefer reg-reg over reg-memory moves.  */
1967   if (optimize_size)
1968     return 2;
1969
1970   /* There are some stalls involved when moving from a DREG to a different
1971      class reg, and using the value in one of the following instructions.
1972      Attempt to model this by slightly discouraging such moves.  */
1973   if (class1 == DREGS && class2 != DREGS)
1974     return 2 * 2;
1975
1976   if (GET_MODE_CLASS (mode) == MODE_INT)
1977     {
1978       /* Discourage trying to use the accumulators.  */
1979       if (TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A0)
1980           || TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A1)
1981           || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A0)
1982           || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A1))
1983         return 20;
1984     }
1985   return 2;
1986 }
1987
1988 /* Return the cost of moving data of mode M between a
1989    register and memory.  A value of 2 is the default; this cost is
1990    relative to those in `REGISTER_MOVE_COST'.
1991
1992    ??? In theory L1 memory has single-cycle latency.  We should add a switch
1993    that tells the compiler whether we expect to use only L1 memory for the
1994    program; it'll make the costs more accurate.  */
1995
1996 int
1997 bfin_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
1998                        enum reg_class class,
1999                        int in ATTRIBUTE_UNUSED)
2000 {
2001   /* Make memory accesses slightly more expensive than any register-register
2002      move.  Also, penalize non-DP registers, since they need secondary
2003      reloads to load and store.  */
2004   if (! reg_class_subset_p (class, DPREGS))
2005     return 10;
2006
2007   return 8;
2008 }
2009
2010 /* Inform reload about cases where moving X with a mode MODE to a register in
2011    CLASS requires an extra scratch register.  Return the class needed for the
2012    scratch register.  */
2013
2014 static enum reg_class
2015 bfin_secondary_reload (bool in_p ATTRIBUTE_UNUSED, rtx x, enum reg_class class,
2016                      enum machine_mode mode, secondary_reload_info *sri)
2017 {
2018   /* If we have HImode or QImode, we can only use DREGS as secondary registers;
2019      in most other cases we can also use PREGS.  */
2020   enum reg_class default_class = GET_MODE_SIZE (mode) >= 4 ? DPREGS : DREGS;
2021   enum reg_class x_class = NO_REGS;
2022   enum rtx_code code = GET_CODE (x);
2023
2024   if (code == SUBREG)
2025     x = SUBREG_REG (x), code = GET_CODE (x);
2026   if (REG_P (x))
2027     {
2028       int regno = REGNO (x);
2029       if (regno >= FIRST_PSEUDO_REGISTER)
2030         regno = reg_renumber[regno];
2031
2032       if (regno == -1)
2033         code = MEM;
2034       else
2035         x_class = REGNO_REG_CLASS (regno);
2036     }
2037
2038   /* We can be asked to reload (plus (FP) (large_constant)) into a DREG.
2039      This happens as a side effect of register elimination, and we need
2040      a scratch register to do it.  */
2041   if (fp_plus_const_operand (x, mode))
2042     {
2043       rtx op2 = XEXP (x, 1);
2044       int large_constant_p = ! CONST_7BIT_IMM_P (INTVAL (op2));
2045
2046       if (class == PREGS || class == PREGS_CLOBBERED)
2047         return NO_REGS;
2048       /* If destination is a DREG, we can do this without a scratch register
2049          if the constant is valid for an add instruction.  */
2050       if ((class == DREGS || class == DPREGS)
2051           && ! large_constant_p)
2052         return NO_REGS;
2053       /* Reloading to anything other than a DREG?  Use a PREG scratch
2054          register.  */
2055       sri->icode = CODE_FOR_reload_insi;
2056       return NO_REGS;
2057     }
2058
2059   /* Data can usually be moved freely between registers of most classes.
2060      AREGS are an exception; they can only move to or from another register
2061      in AREGS or one in DREGS.  They can also be assigned the constant 0.  */
2062   if (x_class == AREGS || x_class == EVEN_AREGS || x_class == ODD_AREGS)
2063     return (class == DREGS || class == AREGS || class == EVEN_AREGS
2064             || class == ODD_AREGS
2065             ? NO_REGS : DREGS);
2066
2067   if (class == AREGS || class == EVEN_AREGS || class == ODD_AREGS)
2068     {
2069       if (x != const0_rtx && x_class != DREGS)
2070         return DREGS;
2071       else
2072         return NO_REGS;
2073     }
2074
2075   /* CCREGS can only be moved from/to DREGS.  */
2076   if (class == CCREGS && x_class != DREGS)
2077     return DREGS;
2078   if (x_class == CCREGS && class != DREGS)
2079     return DREGS;
2080
2081   /* All registers other than AREGS can load arbitrary constants.  The only
2082      case that remains is MEM.  */
2083   if (code == MEM)
2084     if (! reg_class_subset_p (class, default_class))
2085       return default_class;
2086   return NO_REGS;
2087 }
2088 \f
2089 /* Implement TARGET_HANDLE_OPTION.  */
2090
2091 static bool
2092 bfin_handle_option (size_t code, const char *arg, int value)
2093 {
2094   switch (code)
2095     {
2096     case OPT_mshared_library_id_:
2097       if (value > MAX_LIBRARY_ID)
2098         error ("-mshared-library-id=%s is not between 0 and %d",
2099                arg, MAX_LIBRARY_ID);
2100       bfin_lib_id_given = 1;
2101       return true;
2102
2103     case OPT_mcpu_:
2104       if (strcmp (arg, "bf531") == 0)
2105         bfin_cpu_type = BFIN_CPU_BF531;
2106       else if (strcmp (arg, "bf532") == 0)
2107         bfin_cpu_type = BFIN_CPU_BF532;
2108       else if (strcmp (arg, "bf533") == 0)
2109         bfin_cpu_type = BFIN_CPU_BF533;
2110       else if (strcmp (arg, "bf534") == 0)
2111         bfin_cpu_type = BFIN_CPU_BF534;
2112       else if (strcmp (arg, "bf536") == 0)
2113         bfin_cpu_type = BFIN_CPU_BF536;
2114       else if (strcmp (arg, "bf537") == 0)
2115         bfin_cpu_type = BFIN_CPU_BF537;
2116       else if (strcmp (arg, "bf561") == 0)
2117         {
2118           warning (0, "bf561 support is incomplete yet.");
2119           bfin_cpu_type = BFIN_CPU_BF561;
2120         }
2121       else
2122         return false;
2123       return true;
2124
2125     default:
2126       return true;
2127     }
2128 }
2129
2130 static struct machine_function *
2131 bfin_init_machine_status (void)
2132 {
2133   struct machine_function *f;
2134
2135   f = ggc_alloc_cleared (sizeof (struct machine_function));
2136
2137   return f;
2138 }
2139
2140 /* Implement the macro OVERRIDE_OPTIONS.  */
2141
2142 void
2143 override_options (void)
2144 {
2145   if (TARGET_OMIT_LEAF_FRAME_POINTER)
2146     flag_omit_frame_pointer = 1;
2147
2148   /* Library identification */
2149   if (bfin_lib_id_given && ! TARGET_ID_SHARED_LIBRARY)
2150     error ("-mshared-library-id= specified without -mid-shared-library");
2151
2152   if (TARGET_ID_SHARED_LIBRARY && flag_pic == 0)
2153     flag_pic = 1;
2154
2155   if (stack_limit_rtx && TARGET_STACK_CHECK_L1)
2156     error ("Can't use multiple stack checking methods together.");
2157
2158   if (TARGET_ID_SHARED_LIBRARY && TARGET_FDPIC)
2159     error ("ID shared libraries and FD-PIC mode can't be used together.");
2160
2161   /* Don't allow the user to specify -mid-shared-library and -msep-data
2162      together, as it makes little sense from a user's point of view...  */
2163   if (TARGET_SEP_DATA && TARGET_ID_SHARED_LIBRARY)
2164     error ("cannot specify both -msep-data and -mid-shared-library");
2165   /* ... internally, however, it's nearly the same.  */
2166   if (TARGET_SEP_DATA)
2167     target_flags |= MASK_ID_SHARED_LIBRARY | MASK_LEAF_ID_SHARED_LIBRARY;
2168
2169   /* There is no single unaligned SI op for PIC code.  Sometimes we
2170      need to use ".4byte" and sometimes we need to use ".picptr".
2171      See bfin_assemble_integer for details.  */
2172   if (TARGET_FDPIC)
2173     targetm.asm_out.unaligned_op.si = 0;
2174
2175   /* Silently turn off flag_pic if not doing FDPIC or ID shared libraries,
2176      since we don't support it and it'll just break.  */
2177   if (flag_pic && !TARGET_FDPIC && !TARGET_ID_SHARED_LIBRARY)
2178     flag_pic = 0;
2179
2180   flag_schedule_insns = 0;
2181
2182   /* Passes after sched2 can break the helpful TImode annotations that
2183      haifa-sched puts on every insn.  Just do scheduling in reorg.  */
2184   bfin_flag_schedule_insns2 = flag_schedule_insns_after_reload;
2185   flag_schedule_insns_after_reload = 0;
2186
2187   init_machine_status = bfin_init_machine_status;
2188 }
2189
2190 /* Return the destination address of BRANCH.
2191    We need to use this instead of get_attr_length, because the
2192    cbranch_with_nops pattern conservatively sets its length to 6, and
2193    we still prefer to use shorter sequences.  */
2194
2195 static int
2196 branch_dest (rtx branch)
2197 {
2198   rtx dest;
2199   int dest_uid;
2200   rtx pat = PATTERN (branch);
2201   if (GET_CODE (pat) == PARALLEL)
2202     pat = XVECEXP (pat, 0, 0);
2203   dest = SET_SRC (pat);
2204   if (GET_CODE (dest) == IF_THEN_ELSE)
2205     dest = XEXP (dest, 1);
2206   dest = XEXP (dest, 0);
2207   dest_uid = INSN_UID (dest);
2208   return INSN_ADDRESSES (dest_uid);
2209 }
2210
2211 /* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates
2212    it's a branch that's predicted taken.  */
2213
2214 static int
2215 cbranch_predicted_taken_p (rtx insn)
2216 {
2217   rtx x = find_reg_note (insn, REG_BR_PROB, 0);
2218
2219   if (x)
2220     {
2221       int pred_val = INTVAL (XEXP (x, 0));
2222
2223       return pred_val >= REG_BR_PROB_BASE / 2;
2224     }
2225
2226   return 0;
2227 }
2228
2229 /* Templates for use by asm_conditional_branch.  */
2230
2231 static const char *ccbranch_templates[][3] = {
2232   { "if !cc jump %3;",  "if cc jump 4 (bp); jump.s %3;",  "if cc jump 6 (bp); jump.l %3;" },
2233   { "if cc jump %3;",   "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" },
2234   { "if !cc jump %3 (bp);",  "if cc jump 4; jump.s %3;",  "if cc jump 6; jump.l %3;" },
2235   { "if cc jump %3 (bp);",  "if !cc jump 4; jump.s %3;",  "if !cc jump 6; jump.l %3;" },
2236 };
2237
2238 /* Output INSN, which is a conditional branch instruction with operands
2239    OPERANDS.
2240
2241    We deal with the various forms of conditional branches that can be generated
2242    by bfin_reorg to prevent the hardware from doing speculative loads, by
2243    - emitting a sufficient number of nops, if N_NOPS is nonzero, or
2244    - always emitting the branch as predicted taken, if PREDICT_TAKEN is true.
2245    Either of these is only necessary if the branch is short, otherwise the
2246    template we use ends in an unconditional jump which flushes the pipeline
2247    anyway.  */
2248
2249 void
2250 asm_conditional_branch (rtx insn, rtx *operands, int n_nops, int predict_taken)
2251 {
2252   int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
2253   /* Note : offset for instructions like if cc jmp; jump.[sl] offset
2254             is to be taken from start of if cc rather than jump.
2255             Range for jump.s is (-4094, 4096) instead of (-4096, 4094)
2256   */
2257   int len = (offset >= -1024 && offset <= 1022 ? 0
2258              : offset >= -4094 && offset <= 4096 ? 1
2259              : 2);
2260   int bp = predict_taken && len == 0 ? 1 : cbranch_predicted_taken_p (insn);
2261   int idx = (bp << 1) | (GET_CODE (operands[0]) == EQ ? BRF : BRT);
2262   output_asm_insn (ccbranch_templates[idx][len], operands);
2263   gcc_assert (n_nops == 0 || !bp);
2264   if (len == 0)
2265     while (n_nops-- > 0)
2266       output_asm_insn ("nop;", NULL);
2267 }
2268
2269 /* Emit rtl for a comparison operation CMP in mode MODE.  Operands have been
2270    stored in bfin_compare_op0 and bfin_compare_op1 already.  */
2271
2272 rtx
2273 bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED)
2274 {
2275   enum rtx_code code1, code2;
2276   rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1;
2277   rtx tem = bfin_cc_rtx;
2278   enum rtx_code code = GET_CODE (cmp);
2279
2280   /* If we have a BImode input, then we already have a compare result, and
2281      do not need to emit another comparison.  */
2282   if (GET_MODE (op0) == BImode)
2283     {
2284       gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
2285       tem = op0, code2 = code;
2286     }
2287   else
2288     {
2289       switch (code) {
2290         /* bfin has these conditions */
2291       case EQ:
2292       case LT:
2293       case LE:
2294       case LEU:
2295       case LTU:
2296         code1 = code;
2297         code2 = NE;
2298         break;
2299       default:
2300         code1 = reverse_condition (code);
2301         code2 = EQ;
2302         break;
2303       }
2304       emit_insn (gen_rtx_SET (BImode, tem,
2305                               gen_rtx_fmt_ee (code1, BImode, op0, op1)));
2306     }
2307
2308   return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode));
2309 }
2310 \f
2311 /* Return nonzero iff C has exactly one bit set if it is interpreted
2312    as a 32-bit constant.  */
2313
2314 int
2315 log2constp (unsigned HOST_WIDE_INT c)
2316 {
2317   c &= 0xFFFFFFFF;
2318   return c != 0 && (c & (c-1)) == 0;
2319 }
2320
2321 /* Returns the number of consecutive least significant zeros in the binary
2322    representation of *V.
2323    We modify *V to contain the original value arithmetically shifted right by
2324    the number of zeroes.  */
2325
2326 static int
2327 shiftr_zero (HOST_WIDE_INT *v)
2328 {
2329   unsigned HOST_WIDE_INT tmp = *v;
2330   unsigned HOST_WIDE_INT sgn;
2331   int n = 0;
2332
2333   if (tmp == 0)
2334     return 0;
2335
2336   sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1));
2337   while ((tmp & 0x1) == 0 && n <= 32)
2338     {
2339       tmp = (tmp >> 1) | sgn;
2340       n++;
2341     }
2342   *v = tmp;
2343   return n;
2344 }
2345
2346 /* After reload, split the load of an immediate constant.  OPERANDS are the
2347    operands of the movsi_insn pattern which we are splitting.  We return
2348    nonzero if we emitted a sequence to load the constant, zero if we emitted
2349    nothing because we want to use the splitter's default sequence.  */
2350
2351 int
2352 split_load_immediate (rtx operands[])
2353 {
2354   HOST_WIDE_INT val = INTVAL (operands[1]);
2355   HOST_WIDE_INT tmp;
2356   HOST_WIDE_INT shifted = val;
2357   HOST_WIDE_INT shifted_compl = ~val;
2358   int num_zero = shiftr_zero (&shifted);
2359   int num_compl_zero = shiftr_zero (&shifted_compl);
2360   unsigned int regno = REGNO (operands[0]);
2361
2362   /* This case takes care of single-bit set/clear constants, which we could
2363      also implement with BITSET/BITCLR.  */
2364   if (num_zero
2365       && shifted >= -32768 && shifted < 65536
2366       && (D_REGNO_P (regno)
2367           || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))
2368     {
2369       emit_insn (gen_movsi (operands[0], GEN_INT (shifted)));
2370       emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));
2371       return 1;
2372     }
2373
2374   tmp = val & 0xFFFF;
2375   tmp |= -(tmp & 0x8000);
2376
2377   /* If high word has one bit set or clear, try to use a bit operation.  */
2378   if (D_REGNO_P (regno))
2379     {
2380       if (log2constp (val & 0xFFFF0000))
2381         {
2382           emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));
2383           emit_insn (gen_iorsi3 (operands[0], operands[0], GEN_INT (val & 0xFFFF0000)));
2384           return 1;
2385         }
2386       else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)
2387         {
2388           emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2389           emit_insn (gen_andsi3 (operands[0], operands[0], GEN_INT (val | 0xFFFF)));
2390         }
2391     }
2392
2393   if (D_REGNO_P (regno))
2394     {
2395       if (CONST_7BIT_IMM_P (tmp))
2396         {
2397           emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2398           emit_insn (gen_movstricthi_high (operands[0], GEN_INT (val & -65536)));
2399           return 1;
2400         }
2401
2402       if ((val & 0xFFFF0000) == 0)
2403         {
2404           emit_insn (gen_movsi (operands[0], const0_rtx));
2405           emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2406           return 1;
2407         }
2408
2409       if ((val & 0xFFFF0000) == 0xFFFF0000)
2410         {
2411           emit_insn (gen_movsi (operands[0], constm1_rtx));
2412           emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2413           return 1;
2414         }
2415     }
2416
2417   /* Need DREGs for the remaining case.  */
2418   if (regno > REG_R7)
2419     return 0;
2420
2421   if (optimize_size
2422       && num_compl_zero && CONST_7BIT_IMM_P (shifted_compl))
2423     {
2424       /* If optimizing for size, generate a sequence that has more instructions
2425          but is shorter.  */
2426       emit_insn (gen_movsi (operands[0], GEN_INT (shifted_compl)));
2427       emit_insn (gen_ashlsi3 (operands[0], operands[0],
2428                               GEN_INT (num_compl_zero)));
2429       emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
2430       return 1;
2431     }
2432   return 0;
2433 }
2434 \f
2435 /* Return true if the legitimate memory address for a memory operand of mode
2436    MODE.  Return false if not.  */
2437
2438 static bool
2439 bfin_valid_add (enum machine_mode mode, HOST_WIDE_INT value)
2440 {
2441   unsigned HOST_WIDE_INT v = value > 0 ? value : -value;
2442   int sz = GET_MODE_SIZE (mode);
2443   int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2;
2444   /* The usual offsettable_memref machinery doesn't work so well for this
2445      port, so we deal with the problem here.  */
2446   if (value > 0 && sz == 8)
2447     v += 4;
2448   return (v & ~(0x7fff << shift)) == 0;
2449 }
2450
2451 static bool
2452 bfin_valid_reg_p (unsigned int regno, int strict, enum machine_mode mode,
2453                   enum rtx_code outer_code)
2454 {
2455   if (strict)
2456     return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH);
2457   else
2458     return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH);
2459 }
2460
2461 bool
2462 bfin_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
2463 {
2464   switch (GET_CODE (x)) {
2465   case REG:
2466     if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM))
2467       return true;
2468     break;
2469   case PLUS:
2470     if (REG_P (XEXP (x, 0))
2471         && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS)
2472         && ((GET_CODE (XEXP (x, 1)) == UNSPEC && mode == SImode)
2473             || (GET_CODE (XEXP (x, 1)) == CONST_INT
2474                 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
2475       return true;
2476     break;
2477   case POST_INC:
2478   case POST_DEC:
2479     if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2480         && REG_P (XEXP (x, 0))
2481         && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC))
2482       return true;
2483   case PRE_DEC:
2484     if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2485         && XEXP (x, 0) == stack_pointer_rtx
2486         && REG_P (XEXP (x, 0))
2487         && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC))
2488       return true;
2489     break;
2490   default:
2491     break;
2492   }
2493   return false;
2494 }
2495
2496 /* Decide whether we can force certain constants to memory.  If we
2497    decide we can't, the caller should be able to cope with it in
2498    another way.  */
2499
2500 static bool
2501 bfin_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
2502 {
2503   /* We have only one class of non-legitimate constants, and our movsi
2504      expander knows how to handle them.  Dropping these constants into the
2505      data section would only shift the problem - we'd still get relocs
2506      outside the object, in the data section rather than the text section.  */
2507   return true;
2508 }
2509
2510 /* Ensure that for any constant of the form symbol + offset, the offset
2511    remains within the object.  Any other constants are ok.
2512    This ensures that flat binaries never have to deal with relocations
2513    crossing section boundaries.  */
2514
2515 bool
2516 bfin_legitimate_constant_p (rtx x)
2517 {
2518   rtx sym;
2519   HOST_WIDE_INT offset;
2520
2521   if (GET_CODE (x) != CONST)
2522     return true;
2523
2524   x = XEXP (x, 0);
2525   gcc_assert (GET_CODE (x) == PLUS);
2526
2527   sym = XEXP (x, 0);
2528   x = XEXP (x, 1);
2529   if (GET_CODE (sym) != SYMBOL_REF
2530       || GET_CODE (x) != CONST_INT)
2531     return true;
2532   offset = INTVAL (x);
2533
2534   if (SYMBOL_REF_DECL (sym) == 0)
2535     return true;
2536   if (offset < 0
2537       || offset >= int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (sym))))
2538     return false;
2539
2540   return true;
2541 }
2542
2543 static bool
2544 bfin_rtx_costs (rtx x, int code, int outer_code, int *total)
2545 {
2546   int cost2 = COSTS_N_INSNS (1);
2547   rtx op0, op1;
2548
2549   switch (code)
2550     {
2551     case CONST_INT:
2552       if (outer_code == SET || outer_code == PLUS)
2553         *total = CONST_7BIT_IMM_P (INTVAL (x)) ? 0 : cost2;
2554       else if (outer_code == AND)
2555         *total = log2constp (~INTVAL (x)) ? 0 : cost2;
2556       else if (outer_code == LE || outer_code == LT || outer_code == EQ)
2557         *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
2558       else if (outer_code == LEU || outer_code == LTU)
2559         *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
2560       else if (outer_code == MULT)
2561         *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
2562       else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
2563         *total = 0;
2564       else if (outer_code == ASHIFT || outer_code == ASHIFTRT
2565                || outer_code == LSHIFTRT)
2566         *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
2567       else if (outer_code == IOR || outer_code == XOR)
2568         *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
2569       else
2570         *total = cost2;
2571       return true;
2572
2573     case CONST:
2574     case LABEL_REF:
2575     case SYMBOL_REF:
2576     case CONST_DOUBLE:
2577       *total = COSTS_N_INSNS (2);
2578       return true;
2579
2580     case PLUS:
2581       op0 = XEXP (x, 0);
2582       op1 = XEXP (x, 1);
2583       if (GET_MODE (x) == SImode)
2584         {
2585           if (GET_CODE (op0) == MULT
2586               && GET_CODE (XEXP (op0, 1)) == CONST_INT)
2587             {
2588               HOST_WIDE_INT val = INTVAL (XEXP (op0, 1));
2589               if (val == 2 || val == 4)
2590                 {
2591                   *total = cost2;
2592                   *total += rtx_cost (XEXP (op0, 0), outer_code);
2593                   *total += rtx_cost (op1, outer_code);
2594                   return true;
2595                 }
2596             }
2597           *total = cost2;
2598           if (GET_CODE (op0) != REG
2599               && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2600             *total += rtx_cost (op0, SET);
2601 #if 0 /* We'd like to do this for accuracy, but it biases the loop optimizer
2602          towards creating too many induction variables.  */
2603           if (!reg_or_7bit_operand (op1, SImode))
2604             *total += rtx_cost (op1, SET);
2605 #endif
2606         }
2607       else if (GET_MODE (x) == DImode)
2608         {
2609           *total = 6 * cost2;
2610           if (GET_CODE (op1) != CONST_INT
2611               || !CONST_7BIT_IMM_P (INTVAL (op1)))
2612             *total += rtx_cost (op1, PLUS);
2613           if (GET_CODE (op0) != REG
2614               && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2615             *total += rtx_cost (op0, PLUS);
2616         }
2617       return true;
2618
2619     case MINUS:
2620       if (GET_MODE (x) == DImode)
2621         *total = 6 * cost2;
2622       else
2623         *total = cost2;
2624       return true;
2625       
2626     case ASHIFT: 
2627     case ASHIFTRT:
2628     case LSHIFTRT:
2629       if (GET_MODE (x) == DImode)
2630         *total = 6 * cost2;
2631       else
2632         *total = cost2;
2633
2634       op0 = XEXP (x, 0);
2635       op1 = XEXP (x, 1);
2636       if (GET_CODE (op0) != REG
2637           && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2638         *total += rtx_cost (op0, code);
2639
2640       return true;
2641           
2642     case IOR:
2643     case AND:
2644     case XOR:
2645       op0 = XEXP (x, 0);
2646       op1 = XEXP (x, 1);
2647
2648       /* Handle special cases of IOR: rotates, ALIGN insns, movstricthi_high.  */
2649       if (code == IOR)
2650         {
2651           if ((GET_CODE (op0) == LSHIFTRT && GET_CODE (op1) == ASHIFT)
2652               || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == ZERO_EXTEND)
2653               || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT)
2654               || (GET_CODE (op0) == AND && GET_CODE (op1) == CONST_INT))
2655             {
2656               *total = cost2;
2657               return true;
2658             }
2659         }
2660
2661       if (GET_CODE (op0) != REG
2662           && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2663         *total += rtx_cost (op0, code);
2664
2665       if (GET_MODE (x) == DImode)
2666         {
2667           *total = 2 * cost2;
2668           return true;
2669         }
2670       *total = cost2;
2671       if (GET_MODE (x) != SImode)
2672         return true;
2673
2674       if (code == AND)
2675         {
2676           if (! rhs_andsi3_operand (XEXP (x, 1), SImode))
2677             *total += rtx_cost (XEXP (x, 1), code);
2678         }
2679       else
2680         {
2681           if (! regorlog2_operand (XEXP (x, 1), SImode))
2682             *total += rtx_cost (XEXP (x, 1), code);
2683         }
2684
2685       return true;
2686
2687     case ZERO_EXTRACT:
2688     case SIGN_EXTRACT:
2689       if (outer_code == SET
2690           && XEXP (x, 1) == const1_rtx
2691           && GET_CODE (XEXP (x, 2)) == CONST_INT)
2692         {
2693           *total = 2 * cost2;
2694           return true;
2695         }
2696       /* fall through */
2697
2698     case SIGN_EXTEND:
2699     case ZERO_EXTEND:
2700       *total = cost2;
2701       return true;
2702
2703     case MULT:
2704         {
2705           op0 = XEXP (x, 0);
2706           op1 = XEXP (x, 1);
2707           if (GET_CODE (op0) == GET_CODE (op1)
2708               && (GET_CODE (op0) == ZERO_EXTEND
2709                   || GET_CODE (op0) == SIGN_EXTEND))
2710             {
2711               *total = COSTS_N_INSNS (1);
2712               op0 = XEXP (op0, 0);
2713               op1 = XEXP (op1, 0);
2714             }
2715           else if (optimize_size)
2716             *total = COSTS_N_INSNS (1);
2717           else
2718             *total = COSTS_N_INSNS (3);
2719
2720           if (GET_CODE (op0) != REG
2721               && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2722             *total += rtx_cost (op0, MULT);
2723           if (GET_CODE (op1) != REG
2724               && (GET_CODE (op1) != SUBREG || GET_CODE (SUBREG_REG (op1)) != REG))
2725             *total += rtx_cost (op1, MULT);
2726         }
2727       return true;
2728
2729     case UDIV:
2730     case UMOD:
2731       *total = COSTS_N_INSNS (32);
2732       return true;
2733
2734     case VEC_CONCAT:
2735     case VEC_SELECT:
2736       if (outer_code == SET)
2737         *total = cost2;
2738       return true;
2739
2740     default:
2741       return false;
2742     }
2743 }
2744
2745 static void
2746 bfin_internal_label (FILE *stream, const char *prefix, unsigned long num)
2747 {
2748   fprintf (stream, "%s%s$%ld:\n", LOCAL_LABEL_PREFIX, prefix, num);
2749 }
2750 \f
2751 /* Used for communication between {push,pop}_multiple_operation (which
2752    we use not only as a predicate) and the corresponding output functions.  */
2753 static int first_preg_to_save, first_dreg_to_save;
2754
2755 int
2756 push_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2757 {
2758   int lastdreg = 8, lastpreg = 6;
2759   int i, group;
2760
2761   first_preg_to_save = lastpreg;
2762   first_dreg_to_save = lastdreg;
2763   for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
2764     {
2765       rtx t = XVECEXP (op, 0, i);
2766       rtx src, dest;
2767       int regno;
2768
2769       if (GET_CODE (t) != SET)
2770         return 0;
2771
2772       src = SET_SRC (t);
2773       dest = SET_DEST (t);
2774       if (GET_CODE (dest) != MEM || ! REG_P (src))
2775         return 0;
2776       dest = XEXP (dest, 0);
2777       if (GET_CODE (dest) != PLUS
2778           || ! REG_P (XEXP (dest, 0))
2779           || REGNO (XEXP (dest, 0)) != REG_SP
2780           || GET_CODE (XEXP (dest, 1)) != CONST_INT
2781           || INTVAL (XEXP (dest, 1)) != -i * 4)
2782         return 0;
2783
2784       regno = REGNO (src);
2785       if (group == 0)
2786         {
2787           if (D_REGNO_P (regno))
2788             {
2789               group = 1;
2790               first_dreg_to_save = lastdreg = regno - REG_R0;
2791             }
2792           else if (regno >= REG_P0 && regno <= REG_P7)
2793             {
2794               group = 2;
2795               first_preg_to_save = lastpreg = regno - REG_P0;
2796             }
2797           else
2798             return 0;
2799
2800           continue;
2801         }
2802
2803       if (group == 1)
2804         {
2805           if (regno >= REG_P0 && regno <= REG_P7)
2806             {
2807               group = 2;
2808               first_preg_to_save = lastpreg = regno - REG_P0;
2809             }
2810           else if (regno != REG_R0 + lastdreg + 1)
2811             return 0;
2812           else
2813             lastdreg++;
2814         }
2815       else if (group == 2)
2816         {
2817           if (regno != REG_P0 + lastpreg + 1)
2818             return 0;
2819           lastpreg++;
2820         }
2821     }
2822   return 1;
2823 }
2824
2825 int
2826 pop_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2827 {
2828   int lastdreg = 8, lastpreg = 6;
2829   int i, group;
2830
2831   for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
2832     {
2833       rtx t = XVECEXP (op, 0, i);
2834       rtx src, dest;
2835       int regno;
2836
2837       if (GET_CODE (t) != SET)
2838         return 0;
2839
2840       src = SET_SRC (t);
2841       dest = SET_DEST (t);
2842       if (GET_CODE (src) != MEM || ! REG_P (dest))
2843         return 0;
2844       src = XEXP (src, 0);
2845
2846       if (i == 1)
2847         {
2848           if (! REG_P (src) || REGNO (src) != REG_SP)
2849             return 0;
2850         }
2851       else if (GET_CODE (src) != PLUS
2852                || ! REG_P (XEXP (src, 0))
2853                || REGNO (XEXP (src, 0)) != REG_SP
2854                || GET_CODE (XEXP (src, 1)) != CONST_INT
2855                || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
2856         return 0;
2857
2858       regno = REGNO (dest);
2859       if (group == 0)
2860         {
2861           if (regno == REG_R7)
2862             {
2863               group = 1;
2864               lastdreg = 7;
2865             }
2866           else if (regno != REG_P0 + lastpreg - 1)
2867             return 0;
2868           else
2869             lastpreg--;
2870         }
2871       else if (group == 1)
2872         {
2873           if (regno != REG_R0 + lastdreg - 1)
2874             return 0;
2875           else
2876             lastdreg--;
2877         }
2878     }
2879   first_dreg_to_save = lastdreg;
2880   first_preg_to_save = lastpreg;
2881   return 1;
2882 }
2883
2884 /* Emit assembly code for one multi-register push described by INSN, with
2885    operands in OPERANDS.  */
2886
2887 void
2888 output_push_multiple (rtx insn, rtx *operands)
2889 {
2890   char buf[80];
2891   int ok;
2892   
2893   /* Validate the insn again, and compute first_[dp]reg_to_save. */
2894   ok = push_multiple_operation (PATTERN (insn), VOIDmode);
2895   gcc_assert (ok);
2896   
2897   if (first_dreg_to_save == 8)
2898     sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
2899   else if (first_preg_to_save == 6)
2900     sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
2901   else
2902     sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
2903              first_dreg_to_save, first_preg_to_save);
2904
2905   output_asm_insn (buf, operands);
2906 }
2907
2908 /* Emit assembly code for one multi-register pop described by INSN, with
2909    operands in OPERANDS.  */
2910
2911 void
2912 output_pop_multiple (rtx insn, rtx *operands)
2913 {
2914   char buf[80];
2915   int ok;
2916   
2917   /* Validate the insn again, and compute first_[dp]reg_to_save. */
2918   ok = pop_multiple_operation (PATTERN (insn), VOIDmode);
2919   gcc_assert (ok);
2920
2921   if (first_dreg_to_save == 8)
2922     sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
2923   else if (first_preg_to_save == 6)
2924     sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
2925   else
2926     sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
2927              first_dreg_to_save, first_preg_to_save);
2928
2929   output_asm_insn (buf, operands);
2930 }
2931
2932 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE.  */
2933
2934 static void
2935 single_move_for_movmem (rtx dst, rtx src, enum machine_mode mode, HOST_WIDE_INT offset)
2936 {
2937   rtx scratch = gen_reg_rtx (mode);
2938   rtx srcmem, dstmem;
2939
2940   srcmem = adjust_address_nv (src, mode, offset);
2941   dstmem = adjust_address_nv (dst, mode, offset);
2942   emit_move_insn (scratch, srcmem);
2943   emit_move_insn (dstmem, scratch);
2944 }
2945
2946 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
2947    alignment ALIGN_EXP.  Return true if successful, false if we should fall
2948    back on a different method.  */
2949
2950 bool
2951 bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
2952 {
2953   rtx srcreg, destreg, countreg;
2954   HOST_WIDE_INT align = 0;
2955   unsigned HOST_WIDE_INT count = 0;
2956
2957   if (GET_CODE (align_exp) == CONST_INT)
2958     align = INTVAL (align_exp);
2959   if (GET_CODE (count_exp) == CONST_INT)
2960     {
2961       count = INTVAL (count_exp);
2962 #if 0
2963       if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
2964         return false;
2965 #endif
2966     }
2967
2968   /* If optimizing for size, only do single copies inline.  */
2969   if (optimize_size)
2970     {
2971       if (count == 2 && align < 2)
2972         return false;
2973       if (count == 4 && align < 4)
2974         return false;
2975       if (count != 1 && count != 2 && count != 4)
2976         return false;
2977     }
2978   if (align < 2 && count != 1)
2979     return false;
2980
2981   destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
2982   if (destreg != XEXP (dst, 0))
2983     dst = replace_equiv_address_nv (dst, destreg);
2984   srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
2985   if (srcreg != XEXP (src, 0))
2986     src = replace_equiv_address_nv (src, srcreg);
2987
2988   if (count != 0 && align >= 2)
2989     {
2990       unsigned HOST_WIDE_INT offset = 0;
2991
2992       if (align >= 4)
2993         {
2994           if ((count & ~3) == 4)
2995             {
2996               single_move_for_movmem (dst, src, SImode, offset);
2997               offset = 4;
2998             }
2999           else if (count & ~3)
3000             {
3001               HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
3002               countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3003
3004               emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
3005             }
3006           if (count & 2)
3007             {
3008               single_move_for_movmem (dst, src, HImode, offset);
3009               offset += 2;
3010             }
3011         }
3012       else
3013         {
3014           if ((count & ~1) == 2)
3015             {
3016               single_move_for_movmem (dst, src, HImode, offset);
3017               offset = 2;
3018             }
3019           else if (count & ~1)
3020             {
3021               HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
3022               countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3023
3024               emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
3025             }
3026         }
3027       if (count & 1)
3028         {
3029           single_move_for_movmem (dst, src, QImode, offset);
3030         }
3031       return true;
3032     }
3033   return false;
3034 }
3035 \f
3036 /* Compute the alignment for a local variable.
3037    TYPE is the data type, and ALIGN is the alignment that
3038    the object would ordinarily have.  The value of this macro is used
3039    instead of that alignment to align the object.  */
3040
3041 int
3042 bfin_local_alignment (tree type, int align)
3043 {
3044   /* Increasing alignment for (relatively) big types allows the builtin
3045      memcpy can use 32 bit loads/stores.  */
3046   if (TYPE_SIZE (type)
3047       && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
3048       && (TREE_INT_CST_LOW (TYPE_SIZE (type)) > 8
3049           || TREE_INT_CST_HIGH (TYPE_SIZE (type))) && align < 32)
3050     return 32;
3051   return align;
3052 }
3053 \f
3054 /* Implement TARGET_SCHED_ISSUE_RATE.  */
3055
3056 static int
3057 bfin_issue_rate (void)
3058 {
3059   return 3;
3060 }
3061
3062 static int
3063 bfin_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
3064 {
3065   enum attr_type insn_type, dep_insn_type;
3066   int dep_insn_code_number;
3067
3068   /* Anti and output dependencies have zero cost.  */
3069   if (REG_NOTE_KIND (link) != 0)
3070     return 0;
3071
3072   dep_insn_code_number = recog_memoized (dep_insn);
3073
3074   /* If we can't recognize the insns, we can't really do anything.  */
3075   if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
3076     return cost;
3077
3078   insn_type = get_attr_type (insn);
3079   dep_insn_type = get_attr_type (dep_insn);
3080
3081   if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)
3082     {
3083       rtx pat = PATTERN (dep_insn);
3084       rtx dest = SET_DEST (pat);
3085       rtx src = SET_SRC (pat);
3086       if (! ADDRESS_REGNO_P (REGNO (dest))
3087           || ! (MEM_P (src) || D_REGNO_P (REGNO (src))))
3088         return cost;
3089       return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);
3090     }
3091
3092   return cost;
3093 }
3094
3095 \f
3096 /* Increment the counter for the number of loop instructions in the
3097    current function.  */
3098
3099 void
3100 bfin_hardware_loop (void)
3101 {
3102   cfun->machine->has_hardware_loops++;
3103 }
3104
3105 /* Maximum loop nesting depth.  */
3106 #define MAX_LOOP_DEPTH 2
3107
3108 /* Maximum size of a loop.  */
3109 #define MAX_LOOP_LENGTH 2042
3110
3111 /* Maximum distance of the LSETUP instruction from the loop start.  */
3112 #define MAX_LSETUP_DISTANCE 30
3113
3114 /* We need to keep a vector of loops */
3115 typedef struct loop_info *loop_info;
3116 DEF_VEC_P (loop_info);
3117 DEF_VEC_ALLOC_P (loop_info,heap);
3118
3119 /* Information about a loop we have found (or are in the process of
3120    finding).  */
3121 struct loop_info GTY (())
3122 {
3123   /* loop number, for dumps */
3124   int loop_no;
3125
3126   /* All edges that jump into and out of the loop.  */
3127   VEC(edge,gc) *incoming;
3128
3129   /* We can handle two cases: all incoming edges have the same destination
3130      block, or all incoming edges have the same source block.  These two
3131      members are set to the common source or destination we found, or NULL
3132      if different blocks were found.  If both are NULL the loop can't be
3133      optimized.  */
3134   basic_block incoming_src;
3135   basic_block incoming_dest;
3136
3137   /* First block in the loop.  This is the one branched to by the loop_end
3138      insn.  */
3139   basic_block head;
3140
3141   /* Last block in the loop (the one with the loop_end insn).  */
3142   basic_block tail;
3143
3144   /* The successor block of the loop.  This is the one the loop_end insn
3145      falls into.  */
3146   basic_block successor;
3147
3148   /* The last instruction in the tail.  */
3149   rtx last_insn;
3150
3151   /* The loop_end insn.  */
3152   rtx loop_end;
3153
3154   /* The iteration register.  */
3155   rtx iter_reg;
3156
3157   /* The new initialization insn.  */
3158   rtx init;
3159
3160   /* The new initialization instruction.  */
3161   rtx loop_init;
3162
3163   /* The new label placed at the beginning of the loop. */
3164   rtx start_label;
3165
3166   /* The new label placed at the end of the loop. */
3167   rtx end_label;
3168
3169   /* The length of the loop.  */
3170   int length;
3171
3172   /* The nesting depth of the loop.  */
3173   int depth;
3174
3175   /* Nonzero if we can't optimize this loop.  */
3176   int bad;
3177
3178   /* True if we have visited this loop.  */
3179   int visited;
3180
3181   /* True if this loop body clobbers any of LC0, LT0, or LB0.  */
3182   int clobber_loop0;
3183
3184   /* True if this loop body clobbers any of LC1, LT1, or LB1.  */
3185   int clobber_loop1;
3186
3187   /* Next loop in the graph. */
3188   struct loop_info *next;
3189
3190   /* Immediate outer loop of this loop.  */
3191   struct loop_info *outer;
3192
3193   /* Vector of blocks only within the loop, including those within
3194      inner loops.  */
3195   VEC (basic_block,heap) *blocks;
3196
3197   /* Same information in a bitmap.  */
3198   bitmap block_bitmap;
3199
3200   /* Vector of inner loops within this loop  */
3201   VEC (loop_info,heap) *loops;
3202 };
3203
3204 static void
3205 bfin_dump_loops (loop_info loops)
3206 {
3207   loop_info loop;
3208
3209   for (loop = loops; loop; loop = loop->next)
3210     {
3211       loop_info i;
3212       basic_block b;
3213       unsigned ix;
3214
3215       fprintf (dump_file, ";; loop %d: ", loop->loop_no);
3216       if (loop->bad)
3217         fprintf (dump_file, "(bad) ");
3218       fprintf (dump_file, "{head:%d, depth:%d}", loop->head->index, loop->depth);
3219
3220       fprintf (dump_file, " blocks: [ ");
3221       for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, b); ix++)
3222         fprintf (dump_file, "%d ", b->index);
3223       fprintf (dump_file, "] ");
3224
3225       fprintf (dump_file, " inner loops: [ ");
3226       for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, i); ix++)
3227         fprintf (dump_file, "%d ", i->loop_no);
3228       fprintf (dump_file, "]\n");
3229     }
3230   fprintf (dump_file, "\n");
3231 }
3232
3233 /* Scan the blocks of LOOP (and its inferiors) looking for basic block
3234    BB. Return true, if we find it.  */
3235
3236 static bool
3237 bfin_bb_in_loop (loop_info loop, basic_block bb)
3238 {
3239   return bitmap_bit_p (loop->block_bitmap, bb->index);
3240 }
3241
3242 /* Scan the blocks of LOOP (and its inferiors) looking for uses of
3243    REG.  Return true, if we find any.  Don't count the loop's loop_end
3244    insn if it matches LOOP_END.  */
3245
3246 static bool
3247 bfin_scan_loop (loop_info loop, rtx reg, rtx loop_end)
3248 {
3249   unsigned ix;
3250   basic_block bb;
3251
3252   for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
3253     {
3254       rtx insn;
3255
3256       for (insn = BB_HEAD (bb);
3257            insn != NEXT_INSN (BB_END (bb));
3258            insn = NEXT_INSN (insn))
3259         {
3260           if (!INSN_P (insn))
3261             continue;
3262           if (insn == loop_end)
3263             continue;
3264           if (reg_mentioned_p (reg, PATTERN (insn)))
3265             return true;
3266         }
3267     }
3268   return false;
3269 }
3270
3271 /* Estimate the length of INSN conservatively.  */
3272
3273 static int
3274 length_for_loop (rtx insn)
3275 {
3276   int length = 0;
3277   if (JUMP_P (insn) && any_condjump_p (insn) && !optimize_size)
3278     {
3279       if (TARGET_CSYNC_ANOMALY)
3280         length = 8;
3281       else if (TARGET_SPECLD_ANOMALY)
3282         length = 6;
3283     }
3284   else if (LABEL_P (insn))
3285     {
3286       if (TARGET_CSYNC_ANOMALY)
3287         length = 4;
3288     }
3289
3290   if (INSN_P (insn))
3291     length += get_attr_length (insn);
3292
3293   return length;
3294 }
3295
3296 /* Optimize LOOP.  */
3297
3298 static void
3299 bfin_optimize_loop (loop_info loop)
3300 {
3301   basic_block bb;
3302   loop_info inner;
3303   rtx insn, init_insn, last_insn, nop_insn;
3304   rtx loop_init, start_label, end_label;
3305   rtx reg_lc0, reg_lc1, reg_lt0, reg_lt1, reg_lb0, reg_lb1;
3306   rtx iter_reg;
3307   rtx lc_reg, lt_reg, lb_reg;
3308   rtx seq, seq_end;
3309   int length;
3310   unsigned ix;
3311   int inner_depth = 0;
3312
3313   if (loop->visited)
3314     return;
3315
3316   loop->visited = 1;
3317
3318   if (loop->bad)
3319     {
3320       if (dump_file)
3321         fprintf (dump_file, ";; loop %d bad when found\n", loop->loop_no);
3322       goto bad_loop;
3323     }
3324
3325   /* Every loop contains in its list of inner loops every loop nested inside
3326      it, even if there are intermediate loops.  This works because we're doing
3327      a depth-first search here and never visit a loop more than once.  */
3328   for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, inner); ix++)
3329     {
3330       bfin_optimize_loop (inner);
3331
3332       if (!inner->bad && inner_depth < inner->depth)
3333         {
3334           inner_depth = inner->depth;
3335
3336           loop->clobber_loop0 |= inner->clobber_loop0;
3337           loop->clobber_loop1 |= inner->clobber_loop1;
3338         }
3339     }
3340
3341   loop->depth = inner_depth + 1;
3342   if (loop->depth > MAX_LOOP_DEPTH)
3343     {
3344       if (dump_file)
3345         fprintf (dump_file, ";; loop %d too deep\n", loop->loop_no);
3346       goto bad_loop;
3347     }
3348
3349   /* Get the loop iteration register.  */
3350   iter_reg = loop->iter_reg;
3351
3352   if (!DPREG_P (iter_reg))
3353     {
3354       if (dump_file)
3355         fprintf (dump_file, ";; loop %d iteration count NOT in PREG or DREG\n",
3356                  loop->loop_no);
3357       goto bad_loop;
3358     }
3359
3360   if (loop->incoming_src)
3361     {
3362       /* Make sure the predecessor is before the loop start label, as required by
3363          the LSETUP instruction.  */
3364       length = 0;
3365       for (insn = BB_END (loop->incoming_src);
3366            insn && insn != loop->start_label;
3367            insn = NEXT_INSN (insn))
3368         length += length_for_loop (insn);
3369       
3370       if (!insn)
3371         {
3372           if (dump_file)
3373             fprintf (dump_file, ";; loop %d lsetup not before loop_start\n",
3374                      loop->loop_no);
3375           goto bad_loop;
3376         }
3377
3378       if (length > MAX_LSETUP_DISTANCE)
3379         {
3380           if (dump_file)
3381             fprintf (dump_file, ";; loop %d lsetup too far away\n", loop->loop_no);
3382           goto bad_loop;
3383         }
3384     }
3385
3386   /* Check if start_label appears before loop_end and calculate the
3387      offset between them.  We calculate the length of instructions
3388      conservatively.  */
3389   length = 0;
3390   for (insn = loop->start_label;
3391        insn && insn != loop->loop_end;
3392        insn = NEXT_INSN (insn))
3393     length += length_for_loop (insn);
3394
3395   if (!insn)
3396     {
3397       if (dump_file)
3398         fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
3399                  loop->loop_no);
3400       goto bad_loop;
3401     }
3402
3403   loop->length = length;
3404   if (loop->length > MAX_LOOP_LENGTH)
3405     {
3406       if (dump_file)
3407         fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
3408       goto bad_loop;
3409     }
3410
3411   /* Scan all the blocks to make sure they don't use iter_reg.  */
3412   if (bfin_scan_loop (loop, iter_reg, loop->loop_end))
3413     {
3414       if (dump_file)
3415         fprintf (dump_file, ";; loop %d uses iterator\n", loop->loop_no);
3416       goto bad_loop;
3417     }
3418
3419   /* Scan all the insns to see if the loop body clobber
3420      any hardware loop registers. */
3421
3422   reg_lc0 = gen_rtx_REG (SImode, REG_LC0);
3423   reg_lc1 = gen_rtx_REG (SImode, REG_LC1);
3424   reg_lt0 = gen_rtx_REG (SImode, REG_LT0);
3425   reg_lt1 = gen_rtx_REG (SImode, REG_LT1);
3426   reg_lb0 = gen_rtx_REG (SImode, REG_LB0);
3427   reg_lb1 = gen_rtx_REG (SImode, REG_LB1);
3428
3429   for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
3430     {
3431       rtx insn;
3432
3433       for (insn = BB_HEAD (bb);
3434            insn != NEXT_INSN (BB_END (bb));
3435            insn = NEXT_INSN (insn))
3436         {
3437           if (!INSN_P (insn))
3438             continue;
3439
3440           if (reg_set_p (reg_lc0, insn)
3441               || reg_set_p (reg_lt0, insn)
3442               || reg_set_p (reg_lb0, insn))
3443             loop->clobber_loop0 = 1;
3444           
3445           if (reg_set_p (reg_lc1, insn)
3446               || reg_set_p (reg_lt1, insn)
3447               || reg_set_p (reg_lb1, insn))
3448             loop->clobber_loop1 |= 1;
3449         }
3450     }
3451
3452   if ((loop->clobber_loop0 && loop->clobber_loop1)
3453       || (loop->depth == MAX_LOOP_DEPTH && loop->clobber_loop0))
3454     {
3455       loop->depth = MAX_LOOP_DEPTH + 1;
3456       if (dump_file)
3457         fprintf (dump_file, ";; loop %d no loop reg available\n",
3458                  loop->loop_no);
3459       goto bad_loop;
3460     }
3461
3462   /* There should be an instruction before the loop_end instruction
3463      in the same basic block. And the instruction must not be
3464      - JUMP
3465      - CONDITIONAL BRANCH
3466      - CALL
3467      - CSYNC
3468      - SSYNC
3469      - Returns (RTS, RTN, etc.)  */
3470
3471   bb = loop->tail;
3472   last_insn = PREV_INSN (loop->loop_end);
3473
3474   while (1)
3475     {
3476       for (; last_insn != PREV_INSN (BB_HEAD (bb));
3477            last_insn = PREV_INSN (last_insn))
3478         if (INSN_P (last_insn))
3479           break;
3480
3481       if (last_insn != PREV_INSN (BB_HEAD (bb)))
3482         break;
3483
3484       if (single_pred_p (bb)
3485           && single_pred (bb) != ENTRY_BLOCK_PTR)
3486         {
3487           bb = single_pred (bb);
3488           last_insn = BB_END (bb);
3489           continue;
3490         }
3491       else
3492         {
3493           last_insn = NULL_RTX;
3494           break;
3495         }
3496     }
3497
3498   if (!last_insn)
3499     {
3500       if (dump_file)
3501         fprintf (dump_file, ";; loop %d has no last instruction\n",
3502                  loop->loop_no);
3503       goto bad_loop;
3504     }
3505
3506   if (JUMP_P (last_insn))
3507     {
3508       loop_info inner = bb->aux;
3509       if (inner
3510           && inner->outer == loop
3511           && inner->loop_end == last_insn
3512           && inner->depth == 1)
3513         /* This jump_insn is the exact loop_end of an inner loop
3514            and to be optimized away. So use the inner's last_insn.  */
3515         last_insn = inner->last_insn;
3516       else
3517         {
3518           if (dump_file)
3519             fprintf (dump_file, ";; loop %d has bad last instruction\n",
3520                      loop->loop_no);
3521           goto bad_loop;
3522         }
3523     }
3524   else if (CALL_P (last_insn)
3525            || (GET_CODE (PATTERN (last_insn)) != SEQUENCE
3526                && get_attr_type (last_insn) == TYPE_SYNC)
3527            || recog_memoized (last_insn) == CODE_FOR_return_internal)
3528     {
3529       if (dump_file)
3530         fprintf (dump_file, ";; loop %d has bad last instruction\n",
3531                  loop->loop_no);
3532       goto bad_loop;
3533     }
3534
3535   if (GET_CODE (PATTERN (last_insn)) == ASM_INPUT
3536       || asm_noperands (PATTERN (last_insn)) >= 0
3537       || (GET_CODE (PATTERN (last_insn)) != SEQUENCE
3538           && get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI))
3539     {
3540       nop_insn = emit_insn_after (gen_nop (), last_insn);
3541       last_insn = nop_insn;
3542     }
3543
3544   loop->last_insn = last_insn;
3545
3546   /* The loop is good for replacement.  */
3547   start_label = loop->start_label;
3548   end_label = gen_label_rtx ();
3549   iter_reg = loop->iter_reg;
3550
3551   if (loop->depth == 1 && !loop->clobber_loop1)
3552     {
3553       lc_reg = reg_lc1;
3554       lt_reg = reg_lt1;
3555       lb_reg = reg_lb1;
3556       loop->clobber_loop1 = 1;
3557     }
3558   else
3559     {
3560       lc_reg = reg_lc0;
3561       lt_reg = reg_lt0;
3562       lb_reg = reg_lb0;
3563       loop->clobber_loop0 = 1;
3564     }
3565
3566   /* If iter_reg is a DREG, we need generate an instruction to load
3567      the loop count into LC register. */
3568   if (D_REGNO_P (REGNO (iter_reg)))
3569     {
3570       init_insn = gen_movsi (lc_reg, iter_reg);
3571       loop_init = gen_lsetup_without_autoinit (lt_reg, start_label,
3572                                                lb_reg, end_label,
3573                                                lc_reg);
3574     }
3575   else if (P_REGNO_P (REGNO (iter_reg)))
3576     {
3577       init_insn = NULL_RTX;
3578       loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
3579                                             lb_reg, end_label,
3580                                             lc_reg, iter_reg);
3581     }
3582   else
3583     gcc_unreachable ();
3584
3585   loop->init = init_insn;
3586   loop->end_label = end_label;
3587   loop->loop_init = loop_init;
3588
3589   if (dump_file)
3590     {
3591       fprintf (dump_file, ";; replacing loop %d initializer with\n",
3592                loop->loop_no);
3593       print_rtl_single (dump_file, loop->loop_init);
3594       fprintf (dump_file, ";; replacing loop %d terminator with\n",
3595                loop->loop_no);
3596       print_rtl_single (dump_file, loop->loop_end);
3597     }
3598
3599   start_sequence ();
3600
3601   if (loop->init != NULL_RTX)
3602     emit_insn (loop->init);
3603   seq_end = emit_insn (loop->loop_init);
3604
3605   seq = get_insns ();
3606   end_sequence ();
3607
3608   if (loop->incoming_src)
3609     {
3610       rtx prev = BB_END (loop->incoming_src);
3611       if (VEC_length (edge, loop->incoming) > 1
3612           || !(VEC_last (edge, loop->incoming)->flags & EDGE_FALLTHRU))
3613         {
3614           gcc_assert (JUMP_P (prev));
3615           prev = PREV_INSN (prev);
3616         }
3617       emit_insn_after (seq, prev);
3618     }
3619   else
3620     {
3621       basic_block new_bb;
3622       edge e;
3623       edge_iterator ei;
3624       
3625       if (loop->head != loop->incoming_dest)
3626         {
3627           FOR_EACH_EDGE (e, ei, loop->head->preds)
3628             {
3629               if (e->flags & EDGE_FALLTHRU)
3630                 {
3631                   rtx newjump = gen_jump (loop->start_label);
3632                   emit_insn_before (newjump, BB_HEAD (loop->head));
3633                   new_bb = create_basic_block (newjump, newjump, loop->head->prev_bb);
3634                   gcc_assert (new_bb = loop->head->prev_bb);
3635                   break;
3636                 }
3637             }
3638         }
3639
3640       emit_insn_before (seq, BB_HEAD (loop->head));
3641       seq = emit_label_before (gen_label_rtx (), seq);
3642
3643       new_bb = create_basic_block (seq, seq_end, loop->head->prev_bb);
3644       FOR_EACH_EDGE (e, ei, loop->incoming)
3645         {
3646           if (!(e->flags & EDGE_FALLTHRU)
3647               || e->dest != loop->head)
3648             redirect_edge_and_branch_force (e, new_bb);
3649           else
3650             redirect_edge_succ (e, new_bb);
3651         }
3652     }
3653   
3654   delete_insn (loop->loop_end);
3655   /* Insert the loop end label before the last instruction of the loop.  */
3656   emit_label_before (loop->end_label, loop->last_insn);
3657
3658   return;
3659
3660  bad_loop:
3661
3662   if (dump_file)
3663     fprintf (dump_file, ";; loop %d is bad\n", loop->loop_no);
3664
3665   loop->bad = 1;
3666
3667   if (DPREG_P (loop->iter_reg))
3668     {
3669       /* If loop->iter_reg is a DREG or PREG, we can split it here
3670          without scratch register.  */
3671       rtx insn;
3672
3673       emit_insn_before (gen_addsi3 (loop->iter_reg,
3674                                     loop->iter_reg,
3675                                     constm1_rtx),
3676                         loop->loop_end);
3677
3678       emit_insn_before (gen_cmpsi (loop->iter_reg, const0_rtx),
3679                         loop->loop_end);
3680
3681       insn = emit_jump_insn_before (gen_bne (loop->start_label),
3682                                     loop->loop_end);
3683
3684       JUMP_LABEL (insn) = loop->start_label;
3685       LABEL_NUSES (loop->start_label)++;
3686       delete_insn (loop->loop_end);
3687     }
3688 }
3689
3690 /* Called from bfin_reorg_loops when a potential loop end is found.  LOOP is
3691    a newly set up structure describing the loop, it is this function's
3692    responsibility to fill most of it.  TAIL_BB and TAIL_INSN point to the
3693    loop_end insn and its enclosing basic block.  */
3694
3695 static void
3696 bfin_discover_loop (loop_info loop, basic_block tail_bb, rtx tail_insn)
3697 {
3698   unsigned dwork = 0;
3699   basic_block bb;
3700   VEC (basic_block,heap) *works = VEC_alloc (basic_block,heap,20);
3701
3702   loop->tail = tail_bb;
3703   loop->head = BRANCH_EDGE (tail_bb)->dest;
3704   loop->successor = FALLTHRU_EDGE (tail_bb)->dest;
3705   loop->loop_end = tail_insn;
3706   loop->last_insn = NULL_RTX;
3707   loop->iter_reg = SET_DEST (XVECEXP (PATTERN (tail_insn), 0, 1));
3708   loop->depth = loop->length = 0;
3709   loop->visited = 0;
3710   loop->clobber_loop0 = loop->clobber_loop1 = 0;
3711   loop->outer = NULL;
3712   loop->loops = NULL;
3713   loop->incoming = VEC_alloc (edge, gc, 2);
3714   loop->init = loop->loop_init = NULL_RTX;
3715   loop->start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (tail_insn), 0, 0)), 1), 0);
3716   loop->end_label = NULL_RTX;
3717   loop->bad = 0;
3718
3719   VEC_safe_push (basic_block, heap, works, loop->head);
3720
3721   while (VEC_iterate (basic_block, works, dwork++, bb))
3722     {
3723       edge e;
3724       edge_iterator ei;
3725       if (bb == EXIT_BLOCK_PTR)
3726         {
3727           /* We've reached the exit block.  The loop must be bad. */
3728           if (dump_file)
3729             fprintf (dump_file,
3730                      ";; Loop is bad - reached exit block while scanning\n");
3731           loop->bad = 1;
3732           break;
3733         }
3734
3735       if (bitmap_bit_p (loop->block_bitmap, bb->index))
3736         continue;
3737
3738       /* We've not seen this block before.  Add it to the loop's
3739          list and then add each successor to the work list.  */
3740
3741       VEC_safe_push (basic_block, heap, loop->blocks, bb);
3742       bitmap_set_bit (loop->block_bitmap, bb->index);
3743
3744       if (bb != tail_bb)
3745         {
3746           FOR_EACH_EDGE (e, ei, bb->succs)
3747             {
3748               basic_block succ = EDGE_SUCC (bb, ei.index)->dest;
3749               if (!REGNO_REG_SET_P (df_get_live_in (succ),
3750                                     REGNO (loop->iter_reg)))
3751                 continue;
3752               if (!VEC_space (basic_block, works, 1))
3753                 {
3754                   if (dwork)
3755                     {
3756                       VEC_block_remove (basic_block, works, 0, dwork);
3757                       dwork = 0;
3758                     }
3759                   else
3760                     VEC_reserve (basic_block, heap, works, 1);
3761                 }
3762               VEC_quick_push (basic_block, works, succ);
3763             }
3764         }
3765     }
3766
3767   /* Find the predecessor, and make sure nothing else jumps into this loop.  */
3768   if (!loop->bad)
3769     {
3770       int pass, retry;
3771       for (dwork = 0; VEC_iterate (basic_block, loop->blocks, dwork, bb); dwork++)
3772         {
3773           edge e;
3774           edge_iterator ei;
3775           FOR_EACH_EDGE (e, ei, bb->preds)
3776             {
3777               basic_block pred = e->src;
3778
3779               if (!bfin_bb_in_loop (loop, pred))
3780                 {
3781                   if (dump_file)
3782                     fprintf (dump_file, ";; Loop %d: incoming edge %d -> %d\n",
3783                              loop->loop_no, pred->index,
3784                              e->dest->index);
3785                   VEC_safe_push (edge, gc, loop->incoming, e);
3786                 }
3787             }
3788         }
3789
3790       for (pass = 0, retry = 1; retry && pass < 2; pass++)
3791         {
3792           edge e;
3793           edge_iterator ei;
3794           bool first = true;
3795           retry = 0;
3796
3797           FOR_EACH_EDGE (e, ei, loop->incoming)
3798             {
3799               if (first)
3800                 {
3801                   loop->incoming_src = e->src;
3802                   loop->incoming_dest = e->dest;
3803                   first = false;
3804                 }
3805               else
3806                 {
3807                   if (e->dest != loop->incoming_dest)
3808                     loop->incoming_dest = NULL;
3809                   if (e->src != loop->incoming_src)
3810                     loop->incoming_src = NULL;
3811                 }
3812               if (loop->incoming_src == NULL && loop->incoming_dest == NULL)
3813                 {
3814                   if (pass == 0)
3815                     {
3816                       if (dump_file)
3817                         fprintf (dump_file,
3818                                  ";; retrying loop %d with forwarder blocks\n",
3819                                  loop->loop_no);
3820                       retry = 1;
3821                       break;
3822                     }
3823                   loop->bad = 1;
3824                   if (dump_file)
3825                     fprintf (dump_file,
3826                              ";; can't find suitable entry for loop %d\n",
3827                              loop->loop_no);
3828                   goto out;
3829                 }
3830             }
3831           if (retry)
3832             {
3833               retry = 0;
3834               FOR_EACH_EDGE (e, ei, loop->incoming)
3835                 {
3836                   if (forwarder_block_p (e->src))
3837                     {
3838                       edge e2;
3839                       edge_iterator ei2;
3840
3841                       if (dump_file)
3842                         fprintf (dump_file,
3843                                  ";; Adding forwarder block %d to loop %d and retrying\n",
3844                                  e->src->index, loop->loop_no);
3845                       VEC_safe_push (basic_block, heap, loop->blocks, e->src);
3846                       bitmap_set_bit (loop->block_bitmap, e->src->index);
3847                       FOR_EACH_EDGE (e2, ei2, e->src->preds)
3848                         VEC_safe_push (edge, gc, loop->incoming, e2);
3849                       VEC_unordered_remove (edge, loop->incoming, ei.index);
3850                       retry = 1;
3851                       break;
3852                     }
3853                 }
3854             }
3855         }
3856     }
3857
3858  out:
3859   VEC_free (basic_block, heap, works);
3860 }
3861
3862 /* Analyze the structure of the loops in the current function.  Use STACK
3863    for bitmap allocations.  Returns all the valid candidates for hardware
3864    loops found in this function.  */
3865 static loop_info
3866 bfin_discover_loops (bitmap_obstack *stack, FILE *dump_file)
3867 {
3868   loop_info loops = NULL;
3869   loop_info loop;
3870   basic_block bb;
3871   bitmap tmp_bitmap;
3872   int nloops = 0;
3873
3874   /* Find all the possible loop tails.  This means searching for every
3875      loop_end instruction.  For each one found, create a loop_info
3876      structure and add the head block to the work list. */
3877   FOR_EACH_BB (bb)
3878     {
3879       rtx tail = BB_END (bb);
3880
3881       while (GET_CODE (tail) == NOTE)
3882         tail = PREV_INSN (tail);
3883
3884       bb->aux = NULL;
3885
3886       if (INSN_P (tail) && recog_memoized (tail) == CODE_FOR_loop_end)
3887         {
3888           /* A possible loop end */
3889
3890           loop = XNEW (struct loop_info);
3891           loop->next = loops;
3892           loops = loop;
3893           loop->loop_no = nloops++;
3894           loop->blocks = VEC_alloc (basic_block, heap, 20);
3895           loop->block_bitmap = BITMAP_ALLOC (stack);
3896           bb->aux = loop;
3897
3898           if (dump_file)
3899             {
3900               fprintf (dump_file, ";; potential loop %d ending at\n",
3901                        loop->loop_no);
3902               print_rtl_single (dump_file, tail);
3903             }
3904
3905           bfin_discover_loop (loop, bb, tail);
3906         }
3907     }
3908
3909   tmp_bitmap = BITMAP_ALLOC (stack);
3910   /* Compute loop nestings.  */
3911   for (loop = loops; loop; loop = loop->next)
3912     {
3913       loop_info other;
3914       if (loop->bad)
3915         continue;
3916
3917       for (other = loop->next; other; other = other->next)
3918         {
3919           if (other->bad)
3920             continue;
3921
3922           bitmap_and (tmp_bitmap, other->block_bitmap, loop->block_bitmap);
3923           if (bitmap_empty_p (tmp_bitmap))
3924             continue;
3925           if (bitmap_equal_p (tmp_bitmap, other->block_bitmap))
3926             {
3927               other->outer = loop;
3928               VEC_safe_push (loop_info, heap, loop->loops, other);
3929             }
3930           else if (bitmap_equal_p (tmp_bitmap, loop->block_bitmap))
3931             {
3932               loop->outer = other;
3933               VEC_safe_push (loop_info, heap, other->loops, loop);
3934             }
3935           else
3936             {
3937               if (dump_file)
3938                 fprintf (dump_file,
3939                          ";; can't find suitable nesting for loops %d and %d\n",
3940                          loop->loop_no, other->loop_no);
3941               loop->bad = other->bad = 1;
3942             }
3943         }
3944     }
3945   BITMAP_FREE (tmp_bitmap);
3946
3947   return loops;
3948 }
3949
3950 /* Free up the loop structures in LOOPS.  */
3951 static void
3952 free_loops (loop_info loops)
3953 {
3954   while (loops)
3955     {
3956       loop_info loop = loops;
3957       loops = loop->next;
3958       VEC_free (loop_info, heap, loop->loops);
3959       VEC_free (basic_block, heap, loop->blocks);
3960       BITMAP_FREE (loop->block_bitmap);
3961       XDELETE (loop);
3962     }
3963 }
3964
3965 #define BB_AUX_INDEX(BB) ((unsigned)(BB)->aux)
3966
3967 /* The taken-branch edge from the loop end can actually go forward.  Since the
3968    Blackfin's LSETUP instruction requires that the loop end be after the loop
3969    start, try to reorder a loop's basic blocks when we find such a case.  */
3970 static void
3971 bfin_reorder_loops (loop_info loops, FILE *dump_file)
3972 {
3973   basic_block bb;
3974   loop_info loop;
3975
3976   FOR_EACH_BB (bb)
3977     bb->aux = NULL;
3978   cfg_layout_initialize (0);
3979
3980   for (loop = loops; loop; loop = loop->next)
3981     {
3982       unsigned index;
3983       basic_block bb;
3984       edge e;
3985       edge_iterator ei;
3986
3987       if (loop->bad)
3988         continue;
3989
3990       /* Recreate an index for basic blocks that represents their order.  */
3991       for (bb = ENTRY_BLOCK_PTR->next_bb, index = 0;
3992            bb != EXIT_BLOCK_PTR;
3993            bb = bb->next_bb, index++)
3994         bb->aux = (PTR) index;
3995
3996       if (BB_AUX_INDEX (loop->head) < BB_AUX_INDEX (loop->tail))
3997         continue;
3998
3999       FOR_EACH_EDGE (e, ei, loop->head->succs)
4000         {
4001           if (bitmap_bit_p (loop->block_bitmap, e->dest->index)
4002               && BB_AUX_INDEX (e->dest) < BB_AUX_INDEX (loop->tail))
4003             {
4004               basic_block start_bb = e->dest;
4005               basic_block start_prev_bb = start_bb->prev_bb;
4006
4007               if (dump_file)
4008                 fprintf (dump_file, ";; Moving block %d before block %d\n",
4009                          loop->head->index, start_bb->index);
4010               loop->head->prev_bb->next_bb = loop->head->next_bb;
4011               loop->head->next_bb->prev_bb = loop->head->prev_bb;
4012
4013               loop->head->prev_bb = start_prev_bb;
4014               loop->head->next_bb = start_bb;
4015               start_prev_bb->next_bb = start_bb->prev_bb = loop->head;
4016               break;
4017             }
4018         }
4019       loops = loops->next;
4020     }
4021   
4022   FOR_EACH_BB (bb)
4023     {
4024       if (bb->next_bb != EXIT_BLOCK_PTR)
4025         bb->aux = bb->next_bb;
4026       else
4027         bb->aux = NULL;
4028     }
4029   cfg_layout_finalize ();
4030   df_analyze ();
4031 }
4032
4033 /* Run from machine_dependent_reorg, this pass looks for doloop_end insns
4034    and tries to rewrite the RTL of these loops so that proper Blackfin
4035    hardware loops are generated.  */
4036
4037 static void
4038 bfin_reorg_loops (FILE *dump_file)
4039 {
4040   loop_info loops = NULL;
4041   loop_info loop;
4042   basic_block bb;
4043   bitmap_obstack stack;
4044
4045   bitmap_obstack_initialize (&stack);
4046
4047   if (dump_file)
4048     fprintf (dump_file, ";; Find loops, first pass\n\n");
4049
4050   loops = bfin_discover_loops (&stack, dump_file);
4051
4052   if (dump_file)
4053     bfin_dump_loops (loops);
4054
4055   bfin_reorder_loops (loops, dump_file);
4056   free_loops (loops);
4057
4058   if (dump_file)
4059     fprintf (dump_file, ";; Find loops, second pass\n\n");
4060
4061   loops = bfin_discover_loops (&stack, dump_file);
4062   if (dump_file)
4063     {
4064       fprintf (dump_file, ";; All loops found:\n\n");
4065       bfin_dump_loops (loops);
4066     }
4067   
4068   /* Now apply the optimizations.  */
4069   for (loop = loops; loop; loop = loop->next)
4070     bfin_optimize_loop (loop);
4071
4072   if (dump_file)
4073     {
4074       fprintf (dump_file, ";; After hardware loops optimization:\n\n");
4075       bfin_dump_loops (loops);
4076     }
4077
4078   free_loops (loops);
4079
4080   if (dump_file)
4081     print_rtl (dump_file, get_insns ());
4082
4083   FOR_EACH_BB (bb)
4084     bb->aux = NULL;
4085 }
4086 \f
4087 /* Possibly generate a SEQUENCE out of three insns found in SLOT.
4088    Returns true if we modified the insn chain, false otherwise.  */
4089 static bool
4090 gen_one_bundle (rtx slot[3])
4091 {
4092   gcc_assert (slot[1] != NULL_RTX);
4093
4094   /* Verify that we really can do the multi-issue.  */
4095   if (slot[0])
4096     {
4097       rtx t = NEXT_INSN (slot[0]);
4098       while (t != slot[1])
4099         {
4100           if (GET_CODE (t) != NOTE
4101               || NOTE_KIND (t) != NOTE_INSN_DELETED)
4102             return false;
4103           t = NEXT_INSN (t);
4104         }
4105     }
4106   if (slot[2])
4107     {
4108       rtx t = NEXT_INSN (slot[1]);
4109       while (t != slot[2])
4110         {
4111           if (GET_CODE (t) != NOTE
4112               || NOTE_KIND (t) != NOTE_INSN_DELETED)
4113             return false;
4114           t = NEXT_INSN (t);
4115         }
4116     }
4117
4118   if (slot[0] == NULL_RTX)
4119     {
4120       slot[0] = emit_insn_before (gen_mnop (), slot[1]);
4121       df_insn_rescan (slot[0]);
4122     }
4123   if (slot[2] == NULL_RTX)
4124     {
4125       slot[2] = emit_insn_after (gen_forced_nop (), slot[1]);
4126       df_insn_rescan (slot[2]);
4127     }
4128
4129   /* Avoid line number information being printed inside one bundle.  */
4130   if (INSN_LOCATOR (slot[1])
4131       && INSN_LOCATOR (slot[1]) != INSN_LOCATOR (slot[0]))
4132     INSN_LOCATOR (slot[1]) = INSN_LOCATOR (slot[0]);
4133   if (INSN_LOCATOR (slot[2])
4134       && INSN_LOCATOR (slot[2]) != INSN_LOCATOR (slot[0]))
4135     INSN_LOCATOR (slot[2]) = INSN_LOCATOR (slot[0]);
4136
4137   /* Terminate them with "|| " instead of ";" in the output.  */
4138   PUT_MODE (slot[0], SImode);
4139   PUT_MODE (slot[1], SImode);
4140   /* Terminate the bundle, for the benefit of reorder_var_tracking_notes.  */
4141   PUT_MODE (slot[2], QImode);
4142   return true;
4143 }
4144
4145 /* Go through all insns, and use the information generated during scheduling
4146    to generate SEQUENCEs to represent bundles of instructions issued
4147    simultaneously.  */
4148
4149 static void
4150 bfin_gen_bundles (void)
4151 {
4152   basic_block bb;
4153   FOR_EACH_BB (bb)
4154     {
4155       rtx insn, next;
4156       rtx slot[3];
4157       int n_filled = 0;
4158
4159       slot[0] = slot[1] = slot[2] = NULL_RTX;
4160       for (insn = BB_HEAD (bb);; insn = next)
4161         {
4162           int at_end;
4163           if (INSN_P (insn))
4164             {
4165               if (get_attr_type (insn) == TYPE_DSP32)
4166                 slot[0] = insn;
4167               else if (slot[1] == NULL_RTX)
4168                 slot[1] = insn;
4169               else
4170                 slot[2] = insn;
4171               n_filled++;
4172             }
4173
4174           next = NEXT_INSN (insn);
4175           while (next && insn != BB_END (bb)
4176                  && !(INSN_P (next)
4177                       && GET_CODE (PATTERN (next)) != USE
4178                       && GET_CODE (PATTERN (next)) != CLOBBER))
4179             {
4180               insn = next;
4181               next = NEXT_INSN (insn);
4182             }
4183
4184           /* BB_END can change due to emitting extra NOPs, so check here.  */
4185           at_end = insn == BB_END (bb);
4186           if (at_end || GET_MODE (next) == TImode)
4187             {
4188               if ((n_filled < 2
4189                    || !gen_one_bundle (slot))
4190                   && slot[0] != NULL_RTX)
4191                 {
4192                   rtx pat = PATTERN (slot[0]);
4193                   if (GET_CODE (pat) == SET
4194                       && GET_CODE (SET_SRC (pat)) == UNSPEC
4195                       && XINT (SET_SRC (pat), 1) == UNSPEC_32BIT)
4196                     {
4197                       SET_SRC (pat) = XVECEXP (SET_SRC (pat), 0, 0);
4198                       INSN_CODE (slot[0]) = -1;
4199                       df_insn_rescan (slot[0]);
4200                     }
4201                 }
4202               n_filled = 0;
4203               slot[0] = slot[1] = slot[2] = NULL_RTX;
4204             }
4205           if (at_end)
4206             break;
4207         }
4208     }
4209 }
4210
4211 /* Ensure that no var tracking notes are emitted in the middle of a
4212    three-instruction bundle.  */
4213
4214 static void
4215 reorder_var_tracking_notes (void)
4216 {
4217   basic_block bb;
4218   FOR_EACH_BB (bb)
4219     {
4220       rtx insn, next;
4221       rtx queue = NULL_RTX;
4222       bool in_bundle = false;
4223
4224       for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = next)
4225         {
4226           next = NEXT_INSN (insn);
4227
4228           if (INSN_P (insn))
4229             {
4230               /* Emit queued up notes at the last instruction of a bundle.  */
4231               if (GET_MODE (insn) == QImode)
4232                 {
4233                   while (queue)
4234                     {
4235                       rtx next_queue = PREV_INSN (queue);
4236                       PREV_INSN (NEXT_INSN (insn)) = queue;
4237                       NEXT_INSN (queue) = NEXT_INSN (insn);
4238                       NEXT_INSN (insn) = queue;
4239                       PREV_INSN (queue) = insn;
4240                       queue = next_queue;
4241                     }
4242                   in_bundle = false;
4243                 }
4244               else if (GET_MODE (insn) == SImode)
4245                 in_bundle = true;
4246             }
4247           else if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION)
4248             {
4249               if (in_bundle)
4250                 {
4251                   rtx prev = PREV_INSN (insn);
4252                   PREV_INSN (next) = prev;
4253                   NEXT_INSN (prev) = next;
4254
4255                   PREV_INSN (insn) = queue;
4256                   queue = insn;
4257                 }
4258             }
4259         }
4260     }
4261 }
4262 \f
4263 /* Return an insn type for INSN that can be used by the caller for anomaly
4264    workarounds.  This differs from plain get_attr_type in that it handles
4265    SEQUENCEs.  */
4266
4267 static enum attr_type
4268 type_for_anomaly (rtx insn)
4269 {
4270   rtx pat = PATTERN (insn);
4271   if (GET_CODE (pat) == SEQUENCE)
4272     {
4273       enum attr_type t;
4274       t = get_attr_type (XVECEXP (pat, 0, 1));
4275       if (t == TYPE_MCLD)
4276         return t;
4277       t = get_attr_type (XVECEXP (pat, 0, 2));
4278       if (t == TYPE_MCLD)
4279         return t;
4280       return TYPE_MCST;
4281     }
4282   else
4283     return get_attr_type (insn);
4284 }
4285
4286 /* Return nonzero if INSN contains any loads that may trap.  It handles
4287    SEQUENCEs correctly.  */
4288
4289 static bool
4290 trapping_loads_p (rtx insn)
4291 {
4292   rtx pat = PATTERN (insn);
4293   if (GET_CODE (pat) == SEQUENCE)
4294     {
4295       enum attr_type t;
4296       t = get_attr_type (XVECEXP (pat, 0, 1));
4297       if (t == TYPE_MCLD
4298           && may_trap_p (SET_SRC (PATTERN (XVECEXP (pat, 0, 1)))))
4299         return true;
4300       t = get_attr_type (XVECEXP (pat, 0, 2));
4301       if (t == TYPE_MCLD
4302           && may_trap_p (SET_SRC (PATTERN (XVECEXP (pat, 0, 2)))))
4303         return true;
4304       return false;
4305     }
4306   else
4307     return may_trap_p (SET_SRC (single_set (insn)));
4308 }
4309
4310 /* This function acts like NEXT_INSN, but is aware of three-insn bundles and
4311    skips all subsequent parallel instructions if INSN is the start of such
4312    a group.  */
4313 static rtx
4314 find_next_insn_start (rtx insn)
4315 {
4316   if (GET_MODE (insn) == SImode)
4317     {
4318       while (GET_MODE (insn) != QImode)
4319         insn = NEXT_INSN (insn);
4320     }
4321   return NEXT_INSN (insn);
4322 }
4323
4324 /* Return INSN if it is of TYPE_MCLD.  Alternatively, if INSN is the start of
4325    a three-insn bundle, see if one of them is a load and return that if so.
4326    Return NULL_RTX if the insn does not contain loads.  */
4327 static rtx
4328 find_load (rtx insn)
4329 {
4330   if (get_attr_type (insn) == TYPE_MCLD)
4331     return insn;
4332   if (GET_MODE (insn) != SImode)
4333     return NULL_RTX;
4334   do {
4335     insn = NEXT_INSN (insn);
4336     if ((GET_MODE (insn) == SImode || GET_MODE (insn) == QImode)
4337         && get_attr_type (insn) == TYPE_MCLD)
4338       return insn;
4339   } while (GET_MODE (insn) != QImode);
4340   return NULL_RTX;
4341 }
4342
4343 /* We use the machine specific reorg pass for emitting CSYNC instructions
4344    after conditional branches as needed.
4345
4346    The Blackfin is unusual in that a code sequence like
4347      if cc jump label
4348      r0 = (p0)
4349    may speculatively perform the load even if the condition isn't true.  This
4350    happens for a branch that is predicted not taken, because the pipeline
4351    isn't flushed or stalled, so the early stages of the following instructions,
4352    which perform the memory reference, are allowed to execute before the
4353    jump condition is evaluated.
4354    Therefore, we must insert additional instructions in all places where this
4355    could lead to incorrect behavior.  The manual recommends CSYNC, while
4356    VDSP seems to use NOPs (even though its corresponding compiler option is
4357    named CSYNC).
4358
4359    When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
4360    When optimizing for size, we turn the branch into a predicted taken one.
4361    This may be slower due to mispredicts, but saves code size.  */
4362
4363 static void
4364 bfin_reorg (void)
4365 {
4366   rtx insn, next;
4367   rtx last_condjump = NULL_RTX;
4368   int cycles_since_jump = INT_MAX;
4369
4370   /* We are freeing block_for_insn in the toplev to keep compatibility
4371      with old MDEP_REORGS that are not CFG based.  Recompute it now.  */
4372   compute_bb_for_insn ();
4373
4374   if (bfin_flag_schedule_insns2)
4375     {
4376       splitting_for_sched = 1;
4377       split_all_insns ();
4378       splitting_for_sched = 0;
4379
4380       timevar_push (TV_SCHED2);
4381       schedule_insns ();
4382       timevar_pop (TV_SCHED2);
4383
4384       /* Examine the schedule and insert nops as necessary for 64-bit parallel
4385          instructions.  */
4386       bfin_gen_bundles ();
4387     }
4388
4389   df_analyze ();
4390
4391   /* Doloop optimization */
4392   if (cfun->machine->has_hardware_loops)
4393     bfin_reorg_loops (dump_file);
4394
4395   if (! TARGET_SPECLD_ANOMALY && ! TARGET_CSYNC_ANOMALY)
4396     return;
4397
4398   /* First pass: find predicted-false branches; if something after them
4399      needs nops, insert them or change the branch to predict true.  */
4400   for (insn = get_insns (); insn; insn = next)
4401     {
4402       rtx pat;
4403
4404       next = find_next_insn_start (insn);
4405       
4406       if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
4407         continue;
4408
4409       pat = PATTERN (insn);
4410       if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4411           || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
4412           || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
4413         continue;
4414
4415       if (JUMP_P (insn))
4416         {
4417           if (any_condjump_p (insn)
4418               && ! cbranch_predicted_taken_p (insn))
4419             {
4420               last_condjump = insn;
4421               cycles_since_jump = 0;
4422             }
4423           else
4424             cycles_since_jump = INT_MAX;
4425         }
4426       else if (INSN_P (insn))
4427         {
4428           rtx load_insn = find_load (insn);
4429           enum attr_type type = type_for_anomaly (insn);
4430           int delay_needed = 0;
4431           if (cycles_since_jump < INT_MAX)
4432             cycles_since_jump++;
4433
4434           if (load_insn && TARGET_SPECLD_ANOMALY)
4435             {
4436               if (trapping_loads_p (load_insn))
4437                 delay_needed = 3;
4438             }
4439           else if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
4440             delay_needed = 4;
4441
4442           if (delay_needed > cycles_since_jump)
4443             {
4444               rtx pat;
4445               int num_clobbers;
4446               rtx *op = recog_data.operand;
4447
4448               delay_needed -= cycles_since_jump;
4449
4450               extract_insn (last_condjump);
4451               if (optimize_size)
4452                 {
4453                   pat = gen_cbranch_predicted_taken (op[0], op[1], op[2],
4454                                                      op[3]);
4455                   cycles_since_jump = INT_MAX;
4456                 }
4457               else
4458                 /* Do not adjust cycles_since_jump in this case, so that
4459                    we'll increase the number of NOPs for a subsequent insn
4460                    if necessary.  */
4461                 pat = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
4462                                              GEN_INT (delay_needed));
4463               PATTERN (last_condjump) = pat;
4464               INSN_CODE (last_condjump) = recog (pat, insn, &num_clobbers);
4465             }
4466         }
4467     }
4468   /* Second pass: for predicted-true branches, see if anything at the
4469      branch destination needs extra nops.  */
4470   if (! TARGET_CSYNC_ANOMALY)
4471     return;
4472
4473   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4474     {
4475       if (JUMP_P (insn)
4476           && any_condjump_p (insn)
4477           && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken
4478               || cbranch_predicted_taken_p (insn)))
4479         {
4480           rtx target = JUMP_LABEL (insn);
4481           rtx label = target;
4482           cycles_since_jump = 0;
4483           for (; target && cycles_since_jump < 3; target = NEXT_INSN (target))
4484             {
4485               rtx pat;
4486
4487               if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
4488                 continue;
4489
4490               pat = PATTERN (target);
4491               if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4492                   || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
4493                   || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
4494                 continue;
4495
4496               if (INSN_P (target))
4497                 {
4498                   enum attr_type type = type_for_anomaly (target);
4499                   int delay_needed = 0;
4500                   if (cycles_since_jump < INT_MAX)
4501                     cycles_since_jump++;
4502
4503                   if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
4504                     delay_needed = 2;
4505
4506                   if (delay_needed > cycles_since_jump)
4507                     {
4508                       rtx prev = prev_real_insn (label);
4509                       delay_needed -= cycles_since_jump;
4510                       if (dump_file)
4511                         fprintf (dump_file, "Adding %d nops after %d\n",
4512                                  delay_needed, INSN_UID (label));
4513                       if (JUMP_P (prev)
4514                           && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops)
4515                         {
4516                           rtx x;
4517                           HOST_WIDE_INT v;
4518
4519                           if (dump_file)
4520                             fprintf (dump_file,
4521                                      "Reducing nops on insn %d.\n",
4522                                      INSN_UID (prev));
4523                           x = PATTERN (prev);
4524                           x = XVECEXP (x, 0, 1);
4525                           v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed;
4526                           XVECEXP (x, 0, 0) = GEN_INT (v);
4527                         }
4528                       while (delay_needed-- > 0)
4529                         emit_insn_after (gen_nop (), label);
4530                       break;
4531                     }
4532                 }
4533             }
4534         }
4535     }
4536
4537   if (bfin_flag_var_tracking)
4538     {
4539       timevar_push (TV_VAR_TRACKING);
4540       variable_tracking_main ();
4541       reorder_var_tracking_notes ();
4542       timevar_pop (TV_VAR_TRACKING);
4543     }
4544   df_finish_pass ();
4545 }
4546 \f
4547 /* Handle interrupt_handler, exception_handler and nmi_handler function
4548    attributes; arguments as in struct attribute_spec.handler.  */
4549
4550 static tree
4551 handle_int_attribute (tree *node, tree name,
4552                       tree args ATTRIBUTE_UNUSED,
4553                       int flags ATTRIBUTE_UNUSED,
4554                       bool *no_add_attrs)
4555 {
4556   tree x = *node;
4557   if (TREE_CODE (x) == FUNCTION_DECL)
4558     x = TREE_TYPE (x);
4559
4560   if (TREE_CODE (x) != FUNCTION_TYPE)
4561     {
4562       warning (OPT_Wattributes, "%qs attribute only applies to functions",
4563                IDENTIFIER_POINTER (name));
4564       *no_add_attrs = true;
4565     }
4566   else if (funkind (x) != SUBROUTINE)
4567     error ("multiple function type attributes specified");
4568
4569   return NULL_TREE;
4570 }
4571
4572 /* Return 0 if the attributes for two types are incompatible, 1 if they
4573    are compatible, and 2 if they are nearly compatible (which causes a
4574    warning to be generated).  */
4575
4576 static int
4577 bfin_comp_type_attributes (tree type1, tree type2)
4578 {
4579   e_funkind kind1, kind2;
4580
4581   if (TREE_CODE (type1) != FUNCTION_TYPE)
4582     return 1;
4583
4584   kind1 = funkind (type1);
4585   kind2 = funkind (type2);
4586
4587   if (kind1 != kind2)
4588     return 0;
4589   
4590   /*  Check for mismatched modifiers */
4591   if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
4592       != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
4593     return 0;
4594
4595   if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
4596       != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
4597     return 0;
4598
4599   if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
4600       != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
4601     return 0;
4602
4603   if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1))
4604       != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2)))
4605     return 0;
4606
4607   return 1;
4608 }
4609
4610 /* Handle a "longcall" or "shortcall" attribute; arguments as in
4611    struct attribute_spec.handler.  */
4612
4613 static tree
4614 bfin_handle_longcall_attribute (tree *node, tree name, 
4615                                 tree args ATTRIBUTE_UNUSED, 
4616                                 int flags ATTRIBUTE_UNUSED, 
4617                                 bool *no_add_attrs)
4618 {
4619   if (TREE_CODE (*node) != FUNCTION_TYPE
4620       && TREE_CODE (*node) != FIELD_DECL
4621       && TREE_CODE (*node) != TYPE_DECL)
4622     {
4623       warning (OPT_Wattributes, "`%s' attribute only applies to functions",
4624                IDENTIFIER_POINTER (name));
4625       *no_add_attrs = true;
4626     }
4627
4628   if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0
4629        && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node)))
4630       || (strcmp (IDENTIFIER_POINTER (name), "shortcall") == 0
4631           && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node))))
4632     {
4633       warning (OPT_Wattributes,
4634                "can't apply both longcall and shortcall attributes to the same function");
4635       *no_add_attrs = true;
4636     }
4637
4638   return NULL_TREE;
4639 }
4640
4641 /* Table of valid machine attributes.  */
4642 const struct attribute_spec bfin_attribute_table[] =
4643 {
4644   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4645   { "interrupt_handler", 0, 0, false, true,  true, handle_int_attribute },
4646   { "exception_handler", 0, 0, false, true,  true, handle_int_attribute },
4647   { "nmi_handler", 0, 0, false, true,  true, handle_int_attribute },
4648   { "nesting", 0, 0, false, true,  true, NULL },
4649   { "kspisusp", 0, 0, false, true,  true, NULL },
4650   { "saveall", 0, 0, false, true,  true, NULL },
4651   { "longcall",  0, 0, false, true,  true,  bfin_handle_longcall_attribute },
4652   { "shortcall", 0, 0, false, true,  true,  bfin_handle_longcall_attribute },
4653   { NULL, 0, 0, false, false, false, NULL }
4654 };
4655 \f
4656 /* Implementation of TARGET_ASM_INTEGER.  When using FD-PIC, we need to
4657    tell the assembler to generate pointers to function descriptors in
4658    some cases.  */
4659
4660 static bool
4661 bfin_assemble_integer (rtx value, unsigned int size, int aligned_p)
4662 {
4663   if (TARGET_FDPIC && size == UNITS_PER_WORD)
4664     {
4665       if (GET_CODE (value) == SYMBOL_REF
4666           && SYMBOL_REF_FUNCTION_P (value))
4667         {
4668           fputs ("\t.picptr\tfuncdesc(", asm_out_file);
4669           output_addr_const (asm_out_file, value);
4670           fputs (")\n", asm_out_file);
4671           return true;
4672         }
4673       if (!aligned_p)
4674         {
4675           /* We've set the unaligned SI op to NULL, so we always have to
4676              handle the unaligned case here.  */
4677           assemble_integer_with_op ("\t.4byte\t", value);
4678           return true;
4679         }
4680     }
4681   return default_assemble_integer (value, size, aligned_p);
4682 }
4683 \f
4684 /* Output the assembler code for a thunk function.  THUNK_DECL is the
4685    declaration for the thunk function itself, FUNCTION is the decl for
4686    the target function.  DELTA is an immediate constant offset to be
4687    added to THIS.  If VCALL_OFFSET is nonzero, the word at
4688    *(*this + vcall_offset) should be added to THIS.  */
4689
4690 static void
4691 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
4692                       tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
4693                       HOST_WIDE_INT vcall_offset, tree function)
4694 {
4695   rtx xops[3];
4696   /* The this parameter is passed as the first argument.  */
4697   rtx this = gen_rtx_REG (Pmode, REG_R0);
4698
4699   /* Adjust the this parameter by a fixed constant.  */
4700   if (delta)
4701     {
4702       xops[1] = this;
4703       if (delta >= -64 && delta <= 63)
4704         {
4705           xops[0] = GEN_INT (delta);
4706           output_asm_insn ("%1 += %0;", xops);
4707         }
4708       else if (delta >= -128 && delta < -64)
4709         {
4710           xops[0] = GEN_INT (delta + 64);
4711           output_asm_insn ("%1 += -64; %1 += %0;", xops);
4712         }
4713       else if (delta > 63 && delta <= 126)
4714         {
4715           xops[0] = GEN_INT (delta - 63);
4716           output_asm_insn ("%1 += 63; %1 += %0;", xops);
4717         }
4718       else
4719         {
4720           xops[0] = GEN_INT (delta);
4721           output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
4722         }
4723     }
4724
4725   /* Adjust the this parameter by a value stored in the vtable.  */
4726   if (vcall_offset)
4727     {
4728       rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
4729       rtx tmp = gen_rtx_REG (Pmode, REG_R3);
4730
4731       xops[1] = tmp;
4732       xops[2] = p2tmp;
4733       output_asm_insn ("%2 = r0; %2 = [%2];", xops);
4734
4735       /* Adjust the this parameter.  */
4736       xops[0] = gen_rtx_MEM (Pmode, plus_constant (p2tmp, vcall_offset));
4737       if (!memory_operand (xops[0], Pmode))
4738         {
4739           rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
4740           xops[0] = GEN_INT (vcall_offset);
4741           xops[1] = tmp2;
4742           output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
4743           xops[0] = gen_rtx_MEM (Pmode, p2tmp);
4744         }
4745       xops[2] = this;
4746       output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
4747     }
4748
4749   xops[0] = XEXP (DECL_RTL (function), 0);
4750   if (1 || !flag_pic || (*targetm.binds_local_p) (function))
4751     output_asm_insn ("jump.l\t%P0", xops);
4752 }
4753 \f
4754 /* Codes for all the Blackfin builtins.  */
4755 enum bfin_builtins
4756 {
4757   BFIN_BUILTIN_CSYNC,
4758   BFIN_BUILTIN_SSYNC,
4759   BFIN_BUILTIN_COMPOSE_2X16,
4760   BFIN_BUILTIN_EXTRACTLO,
4761   BFIN_BUILTIN_EXTRACTHI,
4762
4763   BFIN_BUILTIN_SSADD_2X16,
4764   BFIN_BUILTIN_SSSUB_2X16,
4765   BFIN_BUILTIN_SSADDSUB_2X16,
4766   BFIN_BUILTIN_SSSUBADD_2X16,
4767   BFIN_BUILTIN_MULT_2X16,
4768   BFIN_BUILTIN_MULTR_2X16,
4769   BFIN_BUILTIN_NEG_2X16,
4770   BFIN_BUILTIN_ABS_2X16,
4771   BFIN_BUILTIN_MIN_2X16,
4772   BFIN_BUILTIN_MAX_2X16,
4773
4774   BFIN_BUILTIN_SSADD_1X16,
4775   BFIN_BUILTIN_SSSUB_1X16,
4776   BFIN_BUILTIN_MULT_1X16,
4777   BFIN_BUILTIN_MULTR_1X16,
4778   BFIN_BUILTIN_NORM_1X16,
4779   BFIN_BUILTIN_NEG_1X16,
4780   BFIN_BUILTIN_ABS_1X16,
4781   BFIN_BUILTIN_MIN_1X16,
4782   BFIN_BUILTIN_MAX_1X16,
4783
4784   BFIN_BUILTIN_SUM_2X16,
4785   BFIN_BUILTIN_DIFFHL_2X16,
4786   BFIN_BUILTIN_DIFFLH_2X16,
4787
4788   BFIN_BUILTIN_SSADD_1X32,
4789   BFIN_BUILTIN_SSSUB_1X32,
4790   BFIN_BUILTIN_NORM_1X32,
4791   BFIN_BUILTIN_ROUND_1X32,
4792   BFIN_BUILTIN_NEG_1X32,
4793   BFIN_BUILTIN_ABS_1X32,
4794   BFIN_BUILTIN_MIN_1X32,
4795   BFIN_BUILTIN_MAX_1X32,
4796   BFIN_BUILTIN_MULT_1X32,
4797   BFIN_BUILTIN_MULT_1X32X32,
4798   BFIN_BUILTIN_MULT_1X32X32NS,
4799
4800   BFIN_BUILTIN_MULHISILL,
4801   BFIN_BUILTIN_MULHISILH,
4802   BFIN_BUILTIN_MULHISIHL,
4803   BFIN_BUILTIN_MULHISIHH,
4804
4805   BFIN_BUILTIN_LSHIFT_1X16,
4806   BFIN_BUILTIN_LSHIFT_2X16,
4807   BFIN_BUILTIN_SSASHIFT_1X16,
4808   BFIN_BUILTIN_SSASHIFT_2X16,
4809   BFIN_BUILTIN_SSASHIFT_1X32,
4810
4811   BFIN_BUILTIN_CPLX_MUL_16,
4812   BFIN_BUILTIN_CPLX_MAC_16,
4813   BFIN_BUILTIN_CPLX_MSU_16,
4814
4815   BFIN_BUILTIN_MAX
4816 };
4817
4818 #define def_builtin(NAME, TYPE, CODE)                                   \
4819 do {                                                                    \
4820   add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD,            \
4821                        NULL, NULL_TREE);                                \
4822 } while (0)
4823
4824 /* Set up all builtin functions for this target.  */
4825 static void
4826 bfin_init_builtins (void)
4827 {
4828   tree V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
4829   tree void_ftype_void
4830     = build_function_type (void_type_node, void_list_node);
4831   tree short_ftype_short
4832     = build_function_type_list (short_integer_type_node, short_integer_type_node,
4833                                 NULL_TREE);
4834   tree short_ftype_int_int
4835     = build_function_type_list (short_integer_type_node, integer_type_node,
4836                                 integer_type_node, NULL_TREE);
4837   tree int_ftype_int_int
4838     = build_function_type_list (integer_type_node, integer_type_node,
4839                                 integer_type_node, NULL_TREE);
4840   tree int_ftype_int
4841     = build_function_type_list (integer_type_node, integer_type_node,
4842                                 NULL_TREE);
4843   tree short_ftype_int
4844     = build_function_type_list (short_integer_type_node, integer_type_node,
4845                                 NULL_TREE);
4846   tree int_ftype_v2hi_v2hi
4847     = build_function_type_list (integer_type_node, V2HI_type_node,
4848                                 V2HI_type_node, NULL_TREE);
4849   tree v2hi_ftype_v2hi_v2hi
4850     = build_function_type_list (V2HI_type_node, V2HI_type_node,
4851                                 V2HI_type_node, NULL_TREE);
4852   tree v2hi_ftype_v2hi_v2hi_v2hi
4853     = build_function_type_list (V2HI_type_node, V2HI_type_node,
4854                                 V2HI_type_node, V2HI_type_node, NULL_TREE);
4855   tree v2hi_ftype_int_int
4856     = build_function_type_list (V2HI_type_node, integer_type_node,
4857                                 integer_type_node, NULL_TREE);
4858   tree v2hi_ftype_v2hi_int
4859     = build_function_type_list (V2HI_type_node, V2HI_type_node,
4860                                 integer_type_node, NULL_TREE);
4861   tree int_ftype_short_short
4862     = build_function_type_list (integer_type_node, short_integer_type_node,
4863                                 short_integer_type_node, NULL_TREE);
4864   tree v2hi_ftype_v2hi
4865     = build_function_type_list (V2HI_type_node, V2HI_type_node, NULL_TREE);
4866   tree short_ftype_v2hi
4867     = build_function_type_list (short_integer_type_node, V2HI_type_node,
4868                                 NULL_TREE);
4869
4870   /* Add the remaining MMX insns with somewhat more complicated types.  */
4871   def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC);
4872   def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC);
4873
4874   def_builtin ("__builtin_bfin_compose_2x16", v2hi_ftype_int_int,
4875                BFIN_BUILTIN_COMPOSE_2X16);
4876   def_builtin ("__builtin_bfin_extract_hi", short_ftype_v2hi,
4877                BFIN_BUILTIN_EXTRACTHI);
4878   def_builtin ("__builtin_bfin_extract_lo", short_ftype_v2hi,
4879                BFIN_BUILTIN_EXTRACTLO);
4880
4881   def_builtin ("__builtin_bfin_min_fr2x16", v2hi_ftype_v2hi_v2hi,
4882                BFIN_BUILTIN_MIN_2X16);
4883   def_builtin ("__builtin_bfin_max_fr2x16", v2hi_ftype_v2hi_v2hi,
4884                BFIN_BUILTIN_MAX_2X16);
4885
4886   def_builtin ("__builtin_bfin_add_fr2x16", v2hi_ftype_v2hi_v2hi,
4887                BFIN_BUILTIN_SSADD_2X16);
4888   def_builtin ("__builtin_bfin_sub_fr2x16", v2hi_ftype_v2hi_v2hi,
4889                BFIN_BUILTIN_SSSUB_2X16);
4890   def_builtin ("__builtin_bfin_dspaddsubsat", v2hi_ftype_v2hi_v2hi,
4891                BFIN_BUILTIN_SSADDSUB_2X16);
4892   def_builtin ("__builtin_bfin_dspsubaddsat", v2hi_ftype_v2hi_v2hi,
4893                BFIN_BUILTIN_SSSUBADD_2X16);
4894   def_builtin ("__builtin_bfin_mult_fr2x16", v2hi_ftype_v2hi_v2hi,
4895                BFIN_BUILTIN_MULT_2X16);
4896   def_builtin ("__builtin_bfin_multr_fr2x16", v2hi_ftype_v2hi_v2hi,
4897                BFIN_BUILTIN_MULTR_2X16);
4898   def_builtin ("__builtin_bfin_negate_fr2x16", v2hi_ftype_v2hi,
4899                BFIN_BUILTIN_NEG_2X16);
4900   def_builtin ("__builtin_bfin_abs_fr2x16", v2hi_ftype_v2hi,
4901                BFIN_BUILTIN_ABS_2X16);
4902
4903   def_builtin ("__builtin_bfin_add_fr1x16", short_ftype_int_int,
4904                BFIN_BUILTIN_SSADD_1X16);
4905   def_builtin ("__builtin_bfin_sub_fr1x16", short_ftype_int_int,
4906                BFIN_BUILTIN_SSSUB_1X16);
4907   def_builtin ("__builtin_bfin_mult_fr1x16", short_ftype_int_int,
4908                BFIN_BUILTIN_MULT_1X16);
4909   def_builtin ("__builtin_bfin_multr_fr1x16", short_ftype_int_int,
4910                BFIN_BUILTIN_MULTR_1X16);
4911   def_builtin ("__builtin_bfin_negate_fr1x16", short_ftype_short,
4912                BFIN_BUILTIN_NEG_1X16);
4913   def_builtin ("__builtin_bfin_abs_fr1x16", short_ftype_short,
4914                BFIN_BUILTIN_ABS_1X16);
4915   def_builtin ("__builtin_bfin_norm_fr1x16", short_ftype_int,
4916                BFIN_BUILTIN_NORM_1X16);
4917
4918   def_builtin ("__builtin_bfin_sum_fr2x16", short_ftype_v2hi,
4919                BFIN_BUILTIN_SUM_2X16);
4920   def_builtin ("__builtin_bfin_diff_hl_fr2x16", short_ftype_v2hi,
4921                BFIN_BUILTIN_DIFFHL_2X16);
4922   def_builtin ("__builtin_bfin_diff_lh_fr2x16", short_ftype_v2hi,
4923                BFIN_BUILTIN_DIFFLH_2X16);
4924
4925   def_builtin ("__builtin_bfin_mulhisill", int_ftype_v2hi_v2hi,
4926                BFIN_BUILTIN_MULHISILL);
4927   def_builtin ("__builtin_bfin_mulhisihl", int_ftype_v2hi_v2hi,
4928                BFIN_BUILTIN_MULHISIHL);
4929   def_builtin ("__builtin_bfin_mulhisilh", int_ftype_v2hi_v2hi,
4930                BFIN_BUILTIN_MULHISILH);
4931   def_builtin ("__builtin_bfin_mulhisihh", int_ftype_v2hi_v2hi,
4932                BFIN_BUILTIN_MULHISIHH);
4933
4934   def_builtin ("__builtin_bfin_add_fr1x32", int_ftype_int_int,
4935                BFIN_BUILTIN_SSADD_1X32);
4936   def_builtin ("__builtin_bfin_sub_fr1x32", int_ftype_int_int,
4937                BFIN_BUILTIN_SSSUB_1X32);
4938   def_builtin ("__builtin_bfin_negate_fr1x32", int_ftype_int,
4939                BFIN_BUILTIN_NEG_1X32);
4940   def_builtin ("__builtin_bfin_abs_fr1x32", int_ftype_int,
4941                BFIN_BUILTIN_ABS_1X32);
4942   def_builtin ("__builtin_bfin_norm_fr1x32", short_ftype_int,
4943                BFIN_BUILTIN_NORM_1X32);
4944   def_builtin ("__builtin_bfin_round_fr1x32", short_ftype_int,
4945                BFIN_BUILTIN_ROUND_1X32);
4946   def_builtin ("__builtin_bfin_mult_fr1x32", int_ftype_short_short,
4947                BFIN_BUILTIN_MULT_1X32);
4948   def_builtin ("__builtin_bfin_mult_fr1x32x32", int_ftype_int_int,
4949                BFIN_BUILTIN_MULT_1X32X32);
4950   def_builtin ("__builtin_bfin_mult_fr1x32x32NS", int_ftype_int_int,
4951                BFIN_BUILTIN_MULT_1X32X32NS);
4952
4953   /* Shifts.  */
4954   def_builtin ("__builtin_bfin_shl_fr1x16", short_ftype_int_int,
4955                BFIN_BUILTIN_SSASHIFT_1X16);
4956   def_builtin ("__builtin_bfin_shl_fr2x16", v2hi_ftype_v2hi_int,
4957                BFIN_BUILTIN_SSASHIFT_2X16);
4958   def_builtin ("__builtin_bfin_lshl_fr1x16", short_ftype_int_int,
4959                BFIN_BUILTIN_LSHIFT_1X16);
4960   def_builtin ("__builtin_bfin_lshl_fr2x16", v2hi_ftype_v2hi_int,
4961                BFIN_BUILTIN_LSHIFT_2X16);
4962   def_builtin ("__builtin_bfin_shl_fr1x32", int_ftype_int_int,
4963                BFIN_BUILTIN_SSASHIFT_1X32);
4964
4965   /* Complex numbers.  */
4966   def_builtin ("__builtin_bfin_cmplx_mul", v2hi_ftype_v2hi_v2hi,
4967                BFIN_BUILTIN_CPLX_MUL_16);
4968   def_builtin ("__builtin_bfin_cmplx_mac", v2hi_ftype_v2hi_v2hi_v2hi,
4969                BFIN_BUILTIN_CPLX_MAC_16);
4970   def_builtin ("__builtin_bfin_cmplx_msu", v2hi_ftype_v2hi_v2hi_v2hi,
4971                BFIN_BUILTIN_CPLX_MSU_16);
4972 }
4973
4974
4975 struct builtin_description
4976 {
4977   const enum insn_code icode;
4978   const char *const name;
4979   const enum bfin_builtins code;
4980   int macflag;
4981 };
4982
4983 static const struct builtin_description bdesc_2arg[] =
4984 {
4985   { CODE_FOR_composev2hi, "__builtin_bfin_compose_2x16", BFIN_BUILTIN_COMPOSE_2X16, -1 },
4986
4987   { CODE_FOR_ssashiftv2hi3, "__builtin_bfin_shl_fr2x16", BFIN_BUILTIN_SSASHIFT_2X16, -1 },
4988   { CODE_FOR_ssashifthi3, "__builtin_bfin_shl_fr1x16", BFIN_BUILTIN_SSASHIFT_1X16, -1 },
4989   { CODE_FOR_lshiftv2hi3, "__builtin_bfin_lshl_fr2x16", BFIN_BUILTIN_LSHIFT_2X16, -1 },
4990   { CODE_FOR_lshifthi3, "__builtin_bfin_lshl_fr1x16", BFIN_BUILTIN_LSHIFT_1X16, -1 },
4991   { CODE_FOR_ssashiftsi3, "__builtin_bfin_shl_fr1x32", BFIN_BUILTIN_SSASHIFT_1X32, -1 },
4992
4993   { CODE_FOR_sminhi3, "__builtin_bfin_min_fr1x16", BFIN_BUILTIN_MIN_1X16, -1 },
4994   { CODE_FOR_smaxhi3, "__builtin_bfin_max_fr1x16", BFIN_BUILTIN_MAX_1X16, -1 },
4995   { CODE_FOR_ssaddhi3, "__builtin_bfin_add_fr1x16", BFIN_BUILTIN_SSADD_1X16, -1 },
4996   { CODE_FOR_sssubhi3, "__builtin_bfin_sub_fr1x16", BFIN_BUILTIN_SSSUB_1X16, -1 },
4997
4998   { CODE_FOR_sminsi3, "__builtin_bfin_min_fr1x32", BFIN_BUILTIN_MIN_1X32, -1 },
4999   { CODE_FOR_smaxsi3, "__builtin_bfin_max_fr1x32", BFIN_BUILTIN_MAX_1X32, -1 },
5000   { CODE_FOR_ssaddsi3, "__builtin_bfin_add_fr1x32", BFIN_BUILTIN_SSADD_1X32, -1 },
5001   { CODE_FOR_sssubsi3, "__builtin_bfin_sub_fr1x32", BFIN_BUILTIN_SSSUB_1X32, -1 },
5002
5003   { CODE_FOR_sminv2hi3, "__builtin_bfin_min_fr2x16", BFIN_BUILTIN_MIN_2X16, -1 },
5004   { CODE_FOR_smaxv2hi3, "__builtin_bfin_max_fr2x16", BFIN_BUILTIN_MAX_2X16, -1 },
5005   { CODE_FOR_ssaddv2hi3, "__builtin_bfin_add_fr2x16", BFIN_BUILTIN_SSADD_2X16, -1 },
5006   { CODE_FOR_sssubv2hi3, "__builtin_bfin_sub_fr2x16", BFIN_BUILTIN_SSSUB_2X16, -1 },
5007   { CODE_FOR_ssaddsubv2hi3, "__builtin_bfin_dspaddsubsat", BFIN_BUILTIN_SSADDSUB_2X16, -1 },
5008   { CODE_FOR_sssubaddv2hi3, "__builtin_bfin_dspsubaddsat", BFIN_BUILTIN_SSSUBADD_2X16, -1 },
5009
5010   { CODE_FOR_flag_mulhisi, "__builtin_bfin_mult_fr1x32", BFIN_BUILTIN_MULT_1X32, MACFLAG_NONE },
5011   { CODE_FOR_flag_mulhi, "__builtin_bfin_mult_fr1x16", BFIN_BUILTIN_MULT_1X16, MACFLAG_T },
5012   { CODE_FOR_flag_mulhi, "__builtin_bfin_multr_fr1x16", BFIN_BUILTIN_MULTR_1X16, MACFLAG_NONE },
5013   { CODE_FOR_flag_mulv2hi, "__builtin_bfin_mult_fr2x16", BFIN_BUILTIN_MULT_2X16, MACFLAG_T },
5014   { CODE_FOR_flag_mulv2hi, "__builtin_bfin_multr_fr2x16", BFIN_BUILTIN_MULTR_2X16, MACFLAG_NONE }
5015 };
5016
5017 static const struct builtin_description bdesc_1arg[] =
5018 {
5019   { CODE_FOR_signbitshi2, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16, 0 },
5020   { CODE_FOR_ssneghi2, "__builtin_bfin_negate_fr1x16", BFIN_BUILTIN_NEG_1X16, 0 },
5021   { CODE_FOR_abshi2, "__builtin_bfin_abs_fr1x16", BFIN_BUILTIN_ABS_1X16, 0 },
5022
5023   { CODE_FOR_signbitssi2, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32, 0 },
5024   { CODE_FOR_ssroundsi2, "__builtin_bfin_round_fr1x32", BFIN_BUILTIN_ROUND_1X32, 0 },
5025   { CODE_FOR_ssnegsi2, "__builtin_bfin_negate_fr1x32", BFIN_BUILTIN_NEG_1X32, 0 },
5026   { CODE_FOR_ssabssi2, "__builtin_bfin_abs_fr1x32", BFIN_BUILTIN_ABS_1X32, 0 },
5027
5028   { CODE_FOR_movv2hi_hi_low, "__builtin_bfin_extract_lo", BFIN_BUILTIN_EXTRACTLO, 0 },
5029   { CODE_FOR_movv2hi_hi_high, "__builtin_bfin_extract_hi", BFIN_BUILTIN_EXTRACTHI, 0 },
5030   { CODE_FOR_ssnegv2hi2, "__builtin_bfin_negate_fr2x16", BFIN_BUILTIN_NEG_2X16, 0 },
5031   { CODE_FOR_ssabsv2hi2, "__builtin_bfin_abs_fr2x16", BFIN_BUILTIN_ABS_2X16, 0 }
5032 };
5033
5034 /* Errors in the source file can cause expand_expr to return const0_rtx
5035    where we expect a vector.  To avoid crashing, use one of the vector
5036    clear instructions.  */
5037 static rtx
5038 safe_vector_operand (rtx x, enum machine_mode mode)
5039 {
5040   if (x != const0_rtx)
5041     return x;
5042   x = gen_reg_rtx (SImode);
5043
5044   emit_insn (gen_movsi (x, CONST0_RTX (SImode)));
5045   return gen_lowpart (mode, x);
5046 }
5047
5048 /* Subroutine of bfin_expand_builtin to take care of binop insns.  MACFLAG is -1
5049    if this is a normal binary op, or one of the MACFLAG_xxx constants.  */
5050
5051 static rtx
5052 bfin_expand_binop_builtin (enum insn_code icode, tree exp, rtx target,
5053                            int macflag)
5054 {
5055   rtx pat;
5056   tree arg0 = CALL_EXPR_ARG (exp, 0);
5057   tree arg1 = CALL_EXPR_ARG (exp, 1);
5058   rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5059   rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
5060   enum machine_mode op0mode = GET_MODE (op0);
5061   enum machine_mode op1mode = GET_MODE (op1);
5062   enum machine_mode tmode = insn_data[icode].operand[0].mode;
5063   enum machine_mode mode0 = insn_data[icode].operand[1].mode;
5064   enum machine_mode mode1 = insn_data[icode].operand[2].mode;
5065
5066   if (VECTOR_MODE_P (mode0))
5067     op0 = safe_vector_operand (op0, mode0);
5068   if (VECTOR_MODE_P (mode1))
5069     op1 = safe_vector_operand (op1, mode1);
5070
5071   if (! target
5072       || GET_MODE (target) != tmode
5073       || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5074     target = gen_reg_rtx (tmode);
5075
5076   if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode)
5077     {
5078       op0mode = HImode;
5079       op0 = gen_lowpart (HImode, op0);
5080     }
5081   if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode)
5082     {
5083       op1mode = HImode;
5084       op1 = gen_lowpart (HImode, op1);
5085     }
5086   /* In case the insn wants input operands in modes different from
5087      the result, abort.  */
5088   gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
5089               && (op1mode == mode1 || op1mode == VOIDmode));
5090
5091   if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5092     op0 = copy_to_mode_reg (mode0, op0);
5093   if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
5094     op1 = copy_to_mode_reg (mode1, op1);
5095
5096   if (macflag == -1)
5097     pat = GEN_FCN (icode) (target, op0, op1);
5098   else
5099     pat = GEN_FCN (icode) (target, op0, op1, GEN_INT (macflag));
5100   if (! pat)
5101     return 0;
5102
5103   emit_insn (pat);
5104   return target;
5105 }
5106
5107 /* Subroutine of bfin_expand_builtin to take care of unop insns.  */
5108
5109 static rtx
5110 bfin_expand_unop_builtin (enum insn_code icode, tree exp,
5111                           rtx target)
5112 {
5113   rtx pat;
5114   tree arg0 = CALL_EXPR_ARG (exp, 0);
5115   rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5116   enum machine_mode op0mode = GET_MODE (op0);
5117   enum machine_mode tmode = insn_data[icode].operand[0].mode;
5118   enum machine_mode mode0 = insn_data[icode].operand[1].mode;
5119
5120   if (! target
5121       || GET_MODE (target) != tmode
5122       || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5123     target = gen_reg_rtx (tmode);
5124
5125   if (VECTOR_MODE_P (mode0))
5126     op0 = safe_vector_operand (op0, mode0);
5127
5128   if (op0mode == SImode && mode0 == HImode)
5129     {
5130       op0mode = HImode;
5131       op0 = gen_lowpart (HImode, op0);
5132     }
5133   gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
5134
5135   if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5136     op0 = copy_to_mode_reg (mode0, op0);
5137
5138   pat = GEN_FCN (icode) (target, op0);
5139   if (! pat)
5140     return 0;
5141   emit_insn (pat);
5142   return target;
5143 }
5144
5145 /* Expand an expression EXP that calls a built-in function,
5146    with result going to TARGET if that's convenient
5147    (and in mode MODE if that's convenient).
5148    SUBTARGET may be used as the target for computing one of EXP's operands.
5149    IGNORE is nonzero if the value is to be ignored.  */
5150
5151 static rtx
5152 bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
5153                      rtx subtarget ATTRIBUTE_UNUSED,
5154                      enum machine_mode mode ATTRIBUTE_UNUSED,
5155                      int ignore ATTRIBUTE_UNUSED)
5156 {
5157   size_t i;
5158   enum insn_code icode;
5159   const struct builtin_description *d;
5160   tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
5161   unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
5162   tree arg0, arg1, arg2;
5163   rtx op0, op1, op2, accvec, pat, tmp1, tmp2, a0reg, a1reg;
5164   enum machine_mode tmode, mode0;
5165
5166   switch (fcode)
5167     {
5168     case BFIN_BUILTIN_CSYNC:
5169       emit_insn (gen_csync ());
5170       return 0;
5171     case BFIN_BUILTIN_SSYNC:
5172       emit_insn (gen_ssync ());
5173       return 0;
5174
5175     case BFIN_BUILTIN_DIFFHL_2X16:
5176     case BFIN_BUILTIN_DIFFLH_2X16:
5177     case BFIN_BUILTIN_SUM_2X16:
5178       arg0 = CALL_EXPR_ARG (exp, 0);
5179       op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5180       icode = (fcode == BFIN_BUILTIN_DIFFHL_2X16 ? CODE_FOR_subhilov2hi3
5181                : fcode == BFIN_BUILTIN_DIFFLH_2X16 ? CODE_FOR_sublohiv2hi3
5182                : CODE_FOR_ssaddhilov2hi3);
5183       tmode = insn_data[icode].operand[0].mode;
5184       mode0 = insn_data[icode].operand[1].mode;
5185
5186       if (! target
5187           || GET_MODE (target) != tmode
5188           || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5189         target = gen_reg_rtx (tmode);
5190
5191       if (VECTOR_MODE_P (mode0))
5192         op0 = safe_vector_operand (op0, mode0);
5193
5194       if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5195         op0 = copy_to_mode_reg (mode0, op0);
5196
5197       pat = GEN_FCN (icode) (target, op0, op0);
5198       if (! pat)
5199         return 0;
5200       emit_insn (pat);
5201       return target;
5202
5203     case BFIN_BUILTIN_MULT_1X32X32:
5204     case BFIN_BUILTIN_MULT_1X32X32NS:
5205       arg0 = CALL_EXPR_ARG (exp, 0);
5206       arg1 = CALL_EXPR_ARG (exp, 1);
5207       op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5208       op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
5209       if (! target
5210           || !register_operand (target, SImode))
5211         target = gen_reg_rtx (SImode);
5212
5213       a1reg = gen_rtx_REG (PDImode, REG_A1);
5214       a0reg = gen_rtx_REG (PDImode, REG_A0);
5215       tmp1 = gen_lowpart (V2HImode, op0);
5216       tmp2 = gen_lowpart (V2HImode, op1);
5217       emit_insn (gen_flag_macinit1hi (a1reg,
5218                                       gen_lowpart (HImode, op0),
5219                                       gen_lowpart (HImode, op1),
5220                                       GEN_INT (MACFLAG_FU)));
5221       emit_insn (gen_lshrpdi3 (a1reg, a1reg, GEN_INT (16)));
5222
5223       if (fcode == BFIN_BUILTIN_MULT_1X32X32)
5224         emit_insn (gen_flag_mul_macv2hi_parts_acconly (a0reg, a1reg, tmp1, tmp2,
5225                                                        const1_rtx, const1_rtx,
5226                                                        const1_rtx, const0_rtx, a1reg,
5227                                                        const0_rtx, GEN_INT (MACFLAG_NONE),
5228                                                        GEN_INT (MACFLAG_M)));
5229       else
5230         {
5231           /* For saturating multiplication, there's exactly one special case
5232              to be handled: multiplying the smallest negative value with
5233              itself.  Due to shift correction in fractional multiplies, this
5234              can overflow.  Iff this happens, OP2 will contain 1, which, when
5235              added in 32 bits to the smallest negative, wraps to the largest
5236              positive, which is the result we want.  */
5237           op2 = gen_reg_rtx (V2HImode);
5238           emit_insn (gen_packv2hi (op2, tmp1, tmp2, const0_rtx, const0_rtx));
5239           emit_insn (gen_movsibi (gen_rtx_REG (BImode, REG_CC),
5240                                   gen_lowpart (SImode, op2)));
5241           emit_insn (gen_flag_mul_macv2hi_parts_acconly_andcc0 (a0reg, a1reg, tmp1, tmp2,
5242                                                                 const1_rtx, const1_rtx,
5243                                                                 const1_rtx, const0_rtx, a1reg,
5244                                                                 const0_rtx, GEN_INT (MACFLAG_NONE),
5245                                                                 GEN_INT (MACFLAG_M)));
5246           op2 = gen_reg_rtx (SImode);
5247           emit_insn (gen_movbisi (op2, gen_rtx_REG (BImode, REG_CC)));
5248         }
5249       emit_insn (gen_flag_machi_parts_acconly (a1reg, tmp2, tmp1,
5250                                                const1_rtx, const0_rtx,
5251                                                a1reg, const0_rtx, GEN_INT (MACFLAG_M)));
5252       emit_insn (gen_ashrpdi3 (a1reg, a1reg, GEN_INT (15)));
5253       emit_insn (gen_sum_of_accumulators (target, a0reg, a0reg, a1reg));
5254       if (fcode == BFIN_BUILTIN_MULT_1X32X32NS)
5255         emit_insn (gen_addsi3 (target, target, op2));
5256       return target;
5257
5258     case BFIN_BUILTIN_CPLX_MUL_16:
5259       arg0 = CALL_EXPR_ARG (exp, 0);
5260       arg1 = CALL_EXPR_ARG (exp, 1);
5261       op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5262       op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
5263       accvec = gen_reg_rtx (V2PDImode);
5264
5265       if (! target
5266           || GET_MODE (target) != V2HImode
5267           || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5268         target = gen_reg_rtx (tmode);
5269       if (! register_operand (op0, GET_MODE (op0)))
5270         op0 = copy_to_mode_reg (GET_MODE (op0), op0);
5271       if (! register_operand (op1, GET_MODE (op1)))
5272         op1 = copy_to_mode_reg (GET_MODE (op1), op1);
5273
5274       emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
5275                                               const0_rtx, const0_rtx,
5276                                               const1_rtx, GEN_INT (MACFLAG_NONE)));
5277       emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
5278                                          const1_rtx, const1_rtx,
5279                                          const0_rtx, accvec, const1_rtx, const0_rtx,
5280                                          GEN_INT (MACFLAG_NONE), accvec));
5281
5282       return target;
5283
5284     case BFIN_BUILTIN_CPLX_MAC_16:
5285     case BFIN_BUILTIN_CPLX_MSU_16:
5286       arg0 = CALL_EXPR_ARG (exp, 0);
5287       arg1 = CALL_EXPR_ARG (exp, 1);
5288       arg2 = CALL_EXPR_ARG (exp, 2);
5289       op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5290       op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
5291       op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
5292       accvec = gen_reg_rtx (V2PDImode);
5293
5294       if (! target
5295           || GET_MODE (target) != V2HImode
5296           || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5297         target = gen_reg_rtx (tmode);
5298       if (! register_operand (op0, GET_MODE (op0)))
5299         op0 = copy_to_mode_reg (GET_MODE (op0), op0);
5300       if (! register_operand (op1, GET_MODE (op1)))
5301         op1 = copy_to_mode_reg (GET_MODE (op1), op1);
5302
5303       tmp1 = gen_reg_rtx (SImode);
5304       tmp2 = gen_reg_rtx (SImode);
5305       emit_insn (gen_ashlsi3 (tmp1, gen_lowpart (SImode, op2), GEN_INT (16)));
5306       emit_move_insn (tmp2, gen_lowpart (SImode, op2));
5307       emit_insn (gen_movstricthi_1 (gen_lowpart (HImode, tmp2), const0_rtx));
5308       emit_insn (gen_load_accumulator_pair (accvec, tmp1, tmp2));
5309       emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op0, op1, const0_rtx,
5310                                                  const0_rtx, const0_rtx,
5311                                                  const1_rtx, accvec, const0_rtx,
5312                                                  const0_rtx,
5313                                                  GEN_INT (MACFLAG_W32)));
5314       tmp1 = (fcode == BFIN_BUILTIN_CPLX_MAC_16 ? const1_rtx : const0_rtx);
5315       tmp2 = (fcode == BFIN_BUILTIN_CPLX_MAC_16 ? const0_rtx : const1_rtx);
5316       emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
5317                                          const1_rtx, const1_rtx,
5318                                          const0_rtx, accvec, tmp1, tmp2,
5319                                          GEN_INT (MACFLAG_NONE), accvec));
5320
5321       return target;
5322
5323     default:
5324       break;
5325     }
5326
5327   for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
5328     if (d->code == fcode)
5329       return bfin_expand_binop_builtin (d->icode, exp, target,
5330                                         d->macflag);
5331
5332   for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
5333     if (d->code == fcode)
5334       return bfin_expand_unop_builtin (d->icode, exp, target);
5335
5336   gcc_unreachable ();
5337 }
5338 \f
5339 #undef TARGET_INIT_BUILTINS
5340 #define TARGET_INIT_BUILTINS bfin_init_builtins
5341
5342 #undef TARGET_EXPAND_BUILTIN
5343 #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
5344
5345 #undef TARGET_ASM_GLOBALIZE_LABEL
5346 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label 
5347
5348 #undef TARGET_ASM_FILE_START
5349 #define TARGET_ASM_FILE_START output_file_start
5350
5351 #undef TARGET_ATTRIBUTE_TABLE
5352 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
5353
5354 #undef TARGET_COMP_TYPE_ATTRIBUTES
5355 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
5356
5357 #undef TARGET_RTX_COSTS
5358 #define TARGET_RTX_COSTS bfin_rtx_costs
5359
5360 #undef  TARGET_ADDRESS_COST
5361 #define TARGET_ADDRESS_COST bfin_address_cost
5362
5363 #undef TARGET_ASM_INTERNAL_LABEL
5364 #define TARGET_ASM_INTERNAL_LABEL bfin_internal_label
5365
5366 #undef  TARGET_ASM_INTEGER
5367 #define TARGET_ASM_INTEGER bfin_assemble_integer
5368
5369 #undef TARGET_MACHINE_DEPENDENT_REORG
5370 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
5371
5372 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
5373 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
5374
5375 #undef TARGET_ASM_OUTPUT_MI_THUNK
5376 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
5377 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
5378 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
5379
5380 #undef TARGET_SCHED_ADJUST_COST
5381 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
5382
5383 #undef TARGET_SCHED_ISSUE_RATE
5384 #define TARGET_SCHED_ISSUE_RATE bfin_issue_rate
5385
5386 #undef TARGET_PROMOTE_PROTOTYPES
5387 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
5388 #undef TARGET_PROMOTE_FUNCTION_ARGS
5389 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
5390 #undef TARGET_PROMOTE_FUNCTION_RETURN
5391 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
5392
5393 #undef TARGET_ARG_PARTIAL_BYTES
5394 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
5395
5396 #undef TARGET_PASS_BY_REFERENCE
5397 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
5398
5399 #undef TARGET_SETUP_INCOMING_VARARGS
5400 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
5401
5402 #undef TARGET_STRUCT_VALUE_RTX
5403 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
5404
5405 #undef TARGET_VECTOR_MODE_SUPPORTED_P
5406 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
5407
5408 #undef TARGET_HANDLE_OPTION
5409 #define TARGET_HANDLE_OPTION bfin_handle_option
5410
5411 #undef TARGET_DEFAULT_TARGET_FLAGS
5412 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
5413
5414 #undef TARGET_SECONDARY_RELOAD
5415 #define TARGET_SECONDARY_RELOAD bfin_secondary_reload
5416
5417 #undef TARGET_DELEGITIMIZE_ADDRESS
5418 #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address
5419
5420 #undef TARGET_CANNOT_FORCE_CONST_MEM
5421 #define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem
5422
5423 struct gcc_target targetm = TARGET_INITIALIZER;