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