OSDN Git Service

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