OSDN Git Service

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