OSDN Git Service

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