OSDN Git Service

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