OSDN Git Service

f305d6bf9cf10173f8d2a0af3304b278bd3a8936
[pf3gnuchains/gcc-fork.git] / gcc / config / bfin / bfin.c
1 /* The Blackfin code generation auxiliary output file.
2    Copyright (C) 2005, 2006  Free Software Foundation, Inc.
3    Contributed by Analog Devices.
4
5    This file is part of GCC.
6
7    GCC is free software; you can redistribute it and/or modify it
8    under the terms of the GNU General Public License as published
9    by the Free Software Foundation; either version 2, or (at your
10    option) any later version.
11
12    GCC is distributed in the hope that it will be useful, but WITHOUT
13    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14    or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15    License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with GCC; see the file COPYING.  If not, write to
19    the Free Software Foundation, 51 Franklin Street, Fifth Floor,
20    Boston, MA 02110-1301, USA.  */
21
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "rtl.h"
27 #include "regs.h"
28 #include "hard-reg-set.h"
29 #include "real.h"
30 #include "insn-config.h"
31 #include "insn-codes.h"
32 #include "conditions.h"
33 #include "insn-flags.h"
34 #include "output.h"
35 #include "insn-attr.h"
36 #include "tree.h"
37 #include "flags.h"
38 #include "except.h"
39 #include "function.h"
40 #include "input.h"
41 #include "target.h"
42 #include "target-def.h"
43 #include "expr.h"
44 #include "toplev.h"
45 #include "recog.h"
46 #include "optabs.h"
47 #include "ggc.h"
48 #include "integrate.h"
49 #include "cgraph.h"
50 #include "langhooks.h"
51 #include "bfin-protos.h"
52 #include "tm-preds.h"
53 #include "gt-bfin.h"
54 #include "basic-block.h"
55
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   if (value > 0 && sz == 8)
2343     v += 4;
2344   return (v & ~(0x7fff << shift)) == 0;
2345 }
2346
2347 static bool
2348 bfin_valid_reg_p (unsigned int regno, int strict, enum machine_mode mode,
2349                   enum rtx_code outer_code)
2350 {
2351   if (strict)
2352     return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH);
2353   else
2354     return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH);
2355 }
2356
2357 bool
2358 bfin_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
2359 {
2360   switch (GET_CODE (x)) {
2361   case REG:
2362     if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM))
2363       return true;
2364     break;
2365   case PLUS:
2366     if (REG_P (XEXP (x, 0))
2367         && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS)
2368         && ((GET_CODE (XEXP (x, 1)) == UNSPEC && mode == SImode)
2369             || (GET_CODE (XEXP (x, 1)) == CONST_INT
2370                 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
2371       return true;
2372     break;
2373   case POST_INC:
2374   case POST_DEC:
2375     if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2376         && REG_P (XEXP (x, 0))
2377         && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC))
2378       return true;
2379   case PRE_DEC:
2380     if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2381         && XEXP (x, 0) == stack_pointer_rtx
2382         && REG_P (XEXP (x, 0))
2383         && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC))
2384       return true;
2385     break;
2386   default:
2387     break;
2388   }
2389   return false;
2390 }
2391
2392 /* Decide whether we can force certain constants to memory.  If we
2393    decide we can't, the caller should be able to cope with it in
2394    another way.  */
2395
2396 static bool
2397 bfin_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
2398 {
2399   /* We have only one class of non-legitimate constants, and our movsi
2400      expander knows how to handle them.  Dropping these constants into the
2401      data section would only shift the problem - we'd still get relocs
2402      outside the object, in the data section rather than the text section.  */
2403   return true;
2404 }
2405
2406 /* Ensure that for any constant of the form symbol + offset, the offset
2407    remains within the object.  Any other constants are ok.
2408    This ensures that flat binaries never have to deal with relocations
2409    crossing section boundaries.  */
2410
2411 bool
2412 bfin_legitimate_constant_p (rtx x)
2413 {
2414   rtx sym;
2415   HOST_WIDE_INT offset;
2416
2417   if (GET_CODE (x) != CONST)
2418     return true;
2419
2420   x = XEXP (x, 0);
2421   gcc_assert (GET_CODE (x) == PLUS);
2422
2423   sym = XEXP (x, 0);
2424   x = XEXP (x, 1);
2425   if (GET_CODE (sym) != SYMBOL_REF
2426       || GET_CODE (x) != CONST_INT)
2427     return true;
2428   offset = INTVAL (x);
2429
2430   if (SYMBOL_REF_DECL (sym) == 0)
2431     return true;
2432   if (offset < 0
2433       || offset >= int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (sym))))
2434     return false;
2435
2436   return true;
2437 }
2438
2439 static bool
2440 bfin_rtx_costs (rtx x, int code, int outer_code, int *total)
2441 {
2442   int cost2 = COSTS_N_INSNS (1);
2443
2444   switch (code)
2445     {
2446     case CONST_INT:
2447       if (outer_code == SET || outer_code == PLUS)
2448         *total = CONST_7BIT_IMM_P (INTVAL (x)) ? 0 : cost2;
2449       else if (outer_code == AND)
2450         *total = log2constp (~INTVAL (x)) ? 0 : cost2;
2451       else if (outer_code == LE || outer_code == LT || outer_code == EQ)
2452         *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
2453       else if (outer_code == LEU || outer_code == LTU)
2454         *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
2455       else if (outer_code == MULT)
2456         *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
2457       else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
2458         *total = 0;
2459       else if (outer_code == ASHIFT || outer_code == ASHIFTRT
2460                || outer_code == LSHIFTRT)
2461         *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
2462       else if (outer_code == IOR || outer_code == XOR)
2463         *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
2464       else
2465         *total = cost2;
2466       return true;
2467
2468     case CONST:
2469     case LABEL_REF:
2470     case SYMBOL_REF:
2471     case CONST_DOUBLE:
2472       *total = COSTS_N_INSNS (2);
2473       return true;
2474
2475     case PLUS:
2476       if (GET_MODE (x) == Pmode)
2477         {
2478           if (GET_CODE (XEXP (x, 0)) == MULT
2479               && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
2480             {
2481               HOST_WIDE_INT val = INTVAL (XEXP (XEXP (x, 0), 1));
2482               if (val == 2 || val == 4)
2483                 {
2484                   *total = cost2;
2485                   *total += rtx_cost (XEXP (XEXP (x, 0), 0), outer_code);
2486                   *total += rtx_cost (XEXP (x, 1), outer_code);
2487                   return true;
2488                 }
2489             }
2490         }
2491
2492       /* fall through */
2493
2494     case MINUS:
2495     case ASHIFT: 
2496     case ASHIFTRT:
2497     case LSHIFTRT:
2498       if (GET_MODE (x) == DImode)
2499         *total = 6 * cost2;
2500       return false;
2501           
2502     case AND:
2503     case IOR:
2504     case XOR:
2505       if (GET_MODE (x) == DImode)
2506         *total = 2 * cost2;
2507       return false;
2508
2509     case MULT:
2510       if (GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD)
2511         *total = COSTS_N_INSNS (3);
2512       return false;
2513
2514     case UDIV:
2515     case UMOD:
2516       *total = COSTS_N_INSNS (32);
2517       return true;
2518
2519     case VEC_CONCAT:
2520     case VEC_SELECT:
2521       if (outer_code == SET)
2522         *total = cost2;
2523       return true;
2524
2525     default:
2526       return false;
2527     }
2528 }
2529
2530 static void
2531 bfin_internal_label (FILE *stream, const char *prefix, unsigned long num)
2532 {
2533   fprintf (stream, "%s%s$%ld:\n", LOCAL_LABEL_PREFIX, prefix, num);
2534 }
2535 \f
2536 /* Used for communication between {push,pop}_multiple_operation (which
2537    we use not only as a predicate) and the corresponding output functions.  */
2538 static int first_preg_to_save, first_dreg_to_save;
2539
2540 int
2541 push_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2542 {
2543   int lastdreg = 8, lastpreg = 6;
2544   int i, group;
2545
2546   first_preg_to_save = lastpreg;
2547   first_dreg_to_save = lastdreg;
2548   for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
2549     {
2550       rtx t = XVECEXP (op, 0, i);
2551       rtx src, dest;
2552       int regno;
2553
2554       if (GET_CODE (t) != SET)
2555         return 0;
2556
2557       src = SET_SRC (t);
2558       dest = SET_DEST (t);
2559       if (GET_CODE (dest) != MEM || ! REG_P (src))
2560         return 0;
2561       dest = XEXP (dest, 0);
2562       if (GET_CODE (dest) != PLUS
2563           || ! REG_P (XEXP (dest, 0))
2564           || REGNO (XEXP (dest, 0)) != REG_SP
2565           || GET_CODE (XEXP (dest, 1)) != CONST_INT
2566           || INTVAL (XEXP (dest, 1)) != -i * 4)
2567         return 0;
2568
2569       regno = REGNO (src);
2570       if (group == 0)
2571         {
2572           if (D_REGNO_P (regno))
2573             {
2574               group = 1;
2575               first_dreg_to_save = lastdreg = regno - REG_R0;
2576             }
2577           else if (regno >= REG_P0 && regno <= REG_P7)
2578             {
2579               group = 2;
2580               first_preg_to_save = lastpreg = regno - REG_P0;
2581             }
2582           else
2583             return 0;
2584
2585           continue;
2586         }
2587
2588       if (group == 1)
2589         {
2590           if (regno >= REG_P0 && regno <= REG_P7)
2591             {
2592               group = 2;
2593               first_preg_to_save = lastpreg = regno - REG_P0;
2594             }
2595           else if (regno != REG_R0 + lastdreg + 1)
2596             return 0;
2597           else
2598             lastdreg++;
2599         }
2600       else if (group == 2)
2601         {
2602           if (regno != REG_P0 + lastpreg + 1)
2603             return 0;
2604           lastpreg++;
2605         }
2606     }
2607   return 1;
2608 }
2609
2610 int
2611 pop_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2612 {
2613   int lastdreg = 8, lastpreg = 6;
2614   int i, group;
2615
2616   for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
2617     {
2618       rtx t = XVECEXP (op, 0, i);
2619       rtx src, dest;
2620       int regno;
2621
2622       if (GET_CODE (t) != SET)
2623         return 0;
2624
2625       src = SET_SRC (t);
2626       dest = SET_DEST (t);
2627       if (GET_CODE (src) != MEM || ! REG_P (dest))
2628         return 0;
2629       src = XEXP (src, 0);
2630
2631       if (i == 1)
2632         {
2633           if (! REG_P (src) || REGNO (src) != REG_SP)
2634             return 0;
2635         }
2636       else if (GET_CODE (src) != PLUS
2637                || ! REG_P (XEXP (src, 0))
2638                || REGNO (XEXP (src, 0)) != REG_SP
2639                || GET_CODE (XEXP (src, 1)) != CONST_INT
2640                || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
2641         return 0;
2642
2643       regno = REGNO (dest);
2644       if (group == 0)
2645         {
2646           if (regno == REG_R7)
2647             {
2648               group = 1;
2649               lastdreg = 7;
2650             }
2651           else if (regno != REG_P0 + lastpreg - 1)
2652             return 0;
2653           else
2654             lastpreg--;
2655         }
2656       else if (group == 1)
2657         {
2658           if (regno != REG_R0 + lastdreg - 1)
2659             return 0;
2660           else
2661             lastdreg--;
2662         }
2663     }
2664   first_dreg_to_save = lastdreg;
2665   first_preg_to_save = lastpreg;
2666   return 1;
2667 }
2668
2669 /* Emit assembly code for one multi-register push described by INSN, with
2670    operands in OPERANDS.  */
2671
2672 void
2673 output_push_multiple (rtx insn, rtx *operands)
2674 {
2675   char buf[80];
2676   int ok;
2677   
2678   /* Validate the insn again, and compute first_[dp]reg_to_save. */
2679   ok = push_multiple_operation (PATTERN (insn), VOIDmode);
2680   gcc_assert (ok);
2681   
2682   if (first_dreg_to_save == 8)
2683     sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
2684   else if (first_preg_to_save == 6)
2685     sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
2686   else
2687     sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
2688              first_dreg_to_save, first_preg_to_save);
2689
2690   output_asm_insn (buf, operands);
2691 }
2692
2693 /* Emit assembly code for one multi-register pop described by INSN, with
2694    operands in OPERANDS.  */
2695
2696 void
2697 output_pop_multiple (rtx insn, rtx *operands)
2698 {
2699   char buf[80];
2700   int ok;
2701   
2702   /* Validate the insn again, and compute first_[dp]reg_to_save. */
2703   ok = pop_multiple_operation (PATTERN (insn), VOIDmode);
2704   gcc_assert (ok);
2705
2706   if (first_dreg_to_save == 8)
2707     sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
2708   else if (first_preg_to_save == 6)
2709     sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
2710   else
2711     sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
2712              first_dreg_to_save, first_preg_to_save);
2713
2714   output_asm_insn (buf, operands);
2715 }
2716
2717 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE.  */
2718
2719 static void
2720 single_move_for_movmem (rtx dst, rtx src, enum machine_mode mode, HOST_WIDE_INT offset)
2721 {
2722   rtx scratch = gen_reg_rtx (mode);
2723   rtx srcmem, dstmem;
2724
2725   srcmem = adjust_address_nv (src, mode, offset);
2726   dstmem = adjust_address_nv (dst, mode, offset);
2727   emit_move_insn (scratch, srcmem);
2728   emit_move_insn (dstmem, scratch);
2729 }
2730
2731 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
2732    alignment ALIGN_EXP.  Return true if successful, false if we should fall
2733    back on a different method.  */
2734
2735 bool
2736 bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
2737 {
2738   rtx srcreg, destreg, countreg;
2739   HOST_WIDE_INT align = 0;
2740   unsigned HOST_WIDE_INT count = 0;
2741
2742   if (GET_CODE (align_exp) == CONST_INT)
2743     align = INTVAL (align_exp);
2744   if (GET_CODE (count_exp) == CONST_INT)
2745     {
2746       count = INTVAL (count_exp);
2747 #if 0
2748       if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
2749         return false;
2750 #endif
2751     }
2752
2753   /* If optimizing for size, only do single copies inline.  */
2754   if (optimize_size)
2755     {
2756       if (count == 2 && align < 2)
2757         return false;
2758       if (count == 4 && align < 4)
2759         return false;
2760       if (count != 1 && count != 2 && count != 4)
2761         return false;
2762     }
2763   if (align < 2 && count != 1)
2764     return false;
2765
2766   destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
2767   if (destreg != XEXP (dst, 0))
2768     dst = replace_equiv_address_nv (dst, destreg);
2769   srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
2770   if (srcreg != XEXP (src, 0))
2771     src = replace_equiv_address_nv (src, srcreg);
2772
2773   if (count != 0 && align >= 2)
2774     {
2775       unsigned HOST_WIDE_INT offset = 0;
2776
2777       if (align >= 4)
2778         {
2779           if ((count & ~3) == 4)
2780             {
2781               single_move_for_movmem (dst, src, SImode, offset);
2782               offset = 4;
2783             }
2784           else if (count & ~3)
2785             {
2786               HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
2787               countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
2788
2789               emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
2790             }
2791           if (count & 2)
2792             {
2793               single_move_for_movmem (dst, src, HImode, offset);
2794               offset += 2;
2795             }
2796         }
2797       else
2798         {
2799           if ((count & ~1) == 2)
2800             {
2801               single_move_for_movmem (dst, src, HImode, offset);
2802               offset = 2;
2803             }
2804           else if (count & ~1)
2805             {
2806               HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
2807               countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
2808
2809               emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
2810             }
2811         }
2812       if (count & 1)
2813         {
2814           single_move_for_movmem (dst, src, QImode, offset);
2815         }
2816       return true;
2817     }
2818   return false;
2819 }
2820 \f
2821 /* Implement TARGET_SCHED_ISSUE_RATE.  */
2822
2823 static int
2824 bfin_issue_rate (void)
2825 {
2826   return 3;
2827 }
2828
2829 static int
2830 bfin_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
2831 {
2832   enum attr_type insn_type, dep_insn_type;
2833   int dep_insn_code_number;
2834
2835   /* Anti and output dependencies have zero cost.  */
2836   if (REG_NOTE_KIND (link) != 0)
2837     return 0;
2838
2839   dep_insn_code_number = recog_memoized (dep_insn);
2840
2841   /* If we can't recognize the insns, we can't really do anything.  */
2842   if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
2843     return cost;
2844
2845   insn_type = get_attr_type (insn);
2846   dep_insn_type = get_attr_type (dep_insn);
2847
2848   if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)
2849     {
2850       rtx pat = PATTERN (dep_insn);
2851       rtx dest = SET_DEST (pat);
2852       rtx src = SET_SRC (pat);
2853       if (! ADDRESS_REGNO_P (REGNO (dest)) || ! D_REGNO_P (REGNO (src)))
2854         return cost;
2855       return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);
2856     }
2857
2858   return cost;
2859 }
2860
2861 \f
2862 /* Increment the counter for the number of loop instructions in the
2863    current function.  */
2864
2865 void
2866 bfin_hardware_loop (void)
2867 {
2868   cfun->machine->has_hardware_loops++;
2869 }
2870
2871 /* Maximum loop nesting depth.  */
2872 #define MAX_LOOP_DEPTH 2
2873
2874 /* Maximum size of a loop.  */
2875 #define MAX_LOOP_LENGTH 2042
2876
2877 /* We need to keep a vector of loops */
2878 typedef struct loop_info *loop_info;
2879 DEF_VEC_P (loop_info);
2880 DEF_VEC_ALLOC_P (loop_info,heap);
2881
2882 /* Information about a loop we have found (or are in the process of
2883    finding).  */
2884 struct loop_info GTY (())
2885 {
2886   /* loop number, for dumps */
2887   int loop_no;
2888
2889   /* Predecessor block of the loop.   This is the one that falls into
2890      the loop and contains the initialization instruction.  */
2891   basic_block predecessor;
2892
2893   /* First block in the loop.  This is the one branched to by the loop_end
2894      insn.  */
2895   basic_block head;
2896
2897   /* Last block in the loop (the one with the loop_end insn).  */
2898   basic_block tail;
2899
2900   /* The successor block of the loop.  This is the one the loop_end insn
2901      falls into.  */
2902   basic_block successor;
2903
2904   /* The last instruction in the tail.  */
2905   rtx last_insn;
2906
2907   /* The loop_end insn.  */
2908   rtx loop_end;
2909
2910   /* The iteration register.  */
2911   rtx iter_reg;
2912
2913   /* The new initialization insn.  */
2914   rtx init;
2915
2916   /* The new initialization instruction.  */
2917   rtx loop_init;
2918
2919   /* The new label placed at the beginning of the loop. */
2920   rtx start_label;
2921
2922   /* The new label placed at the end of the loop. */
2923   rtx end_label;
2924
2925   /* The length of the loop.  */
2926   int length;
2927
2928   /* The nesting depth of the loop.  */
2929   int depth;
2930
2931   /* Nonzero if we can't optimize this loop.  */
2932   int bad;
2933
2934   /* True if we have visited this loop.  */
2935   int visited;
2936
2937   /* True if this loop body clobbers any of LC0, LT0, or LB0.  */
2938   int clobber_loop0;
2939
2940   /* True if this loop body clobbers any of LC1, LT1, or LB1.  */
2941   int clobber_loop1;
2942
2943   /* Next loop in the graph. */
2944   struct loop_info *next;
2945
2946   /* Immediate outer loop of this loop.  */
2947   struct loop_info *outer;
2948
2949   /* Vector of blocks only within the loop, including those within
2950      inner loops.  */
2951   VEC (basic_block,heap) *blocks;
2952
2953   /* Same information in a bitmap.  */
2954   bitmap block_bitmap;
2955
2956   /* Vector of inner loops within this loop  */
2957   VEC (loop_info,heap) *loops;
2958 };
2959
2960 static void
2961 bfin_dump_loops (loop_info loops)
2962 {
2963   loop_info loop;
2964
2965   for (loop = loops; loop; loop = loop->next)
2966     {
2967       loop_info i;
2968       basic_block b;
2969       unsigned ix;
2970
2971       fprintf (dump_file, ";; loop %d: ", loop->loop_no);
2972       if (loop->bad)
2973         fprintf (dump_file, "(bad) ");
2974       fprintf (dump_file, "{head:%d, depth:%d}", loop->head->index, loop->depth);
2975
2976       fprintf (dump_file, " blocks: [ ");
2977       for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, b); ix++)
2978         fprintf (dump_file, "%d ", b->index);
2979       fprintf (dump_file, "] ");
2980
2981       fprintf (dump_file, " inner loops: [ ");
2982       for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, i); ix++)
2983         fprintf (dump_file, "%d ", i->loop_no);
2984       fprintf (dump_file, "]\n");
2985     }
2986   fprintf (dump_file, "\n");
2987 }
2988
2989 /* Scan the blocks of LOOP (and its inferiors) looking for basic block
2990    BB. Return true, if we find it.  */
2991
2992 static bool
2993 bfin_bb_in_loop (loop_info loop, basic_block bb)
2994 {
2995   return bitmap_bit_p (loop->block_bitmap, bb->index);
2996 }
2997
2998 /* Scan the blocks of LOOP (and its inferiors) looking for uses of
2999    REG.  Return true, if we find any.  Don't count the loop's loop_end
3000    insn if it matches LOOP_END.  */
3001
3002 static bool
3003 bfin_scan_loop (loop_info loop, rtx reg, rtx loop_end)
3004 {
3005   unsigned ix;
3006   basic_block bb;
3007
3008   for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
3009     {
3010       rtx insn;
3011
3012       for (insn = BB_HEAD (bb);
3013            insn != NEXT_INSN (BB_END (bb));
3014            insn = NEXT_INSN (insn))
3015         {
3016           if (!INSN_P (insn))
3017             continue;
3018           if (insn == loop_end)
3019             continue;
3020           if (reg_mentioned_p (reg, PATTERN (insn)))
3021             return true;
3022         }
3023     }
3024   return false;
3025 }
3026
3027 /* Optimize LOOP.  */
3028
3029 static void
3030 bfin_optimize_loop (loop_info loop)
3031 {
3032   basic_block bb;
3033   loop_info inner;
3034   rtx insn, init_insn, last_insn, nop_insn;
3035   rtx loop_init, start_label, end_label;
3036   rtx reg_lc0, reg_lc1, reg_lt0, reg_lt1, reg_lb0, reg_lb1;
3037   rtx iter_reg;
3038   rtx lc_reg, lt_reg, lb_reg;
3039   rtx seq;
3040   int length;
3041   unsigned ix;
3042   int inner_depth = 0;
3043
3044   if (loop->visited)
3045     return;
3046
3047   loop->visited = 1;
3048
3049   if (loop->bad)
3050     {
3051       if (dump_file)
3052         fprintf (dump_file, ";; loop %d bad when found\n", loop->loop_no);
3053       goto bad_loop;
3054     }
3055
3056   /* Every loop contains in its list of inner loops every loop nested inside
3057      it, even if there are intermediate loops.  This works because we're doing
3058      a depth-first search here and never visit a loop more than once.  */
3059   for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, inner); ix++)
3060     {
3061       bfin_optimize_loop (inner);
3062
3063       if (!inner->bad && inner_depth < inner->depth)
3064         {
3065           inner_depth = inner->depth;
3066
3067           loop->clobber_loop0 |= inner->clobber_loop0;
3068           loop->clobber_loop1 |= inner->clobber_loop1;
3069         }
3070     }
3071
3072   loop->depth = inner_depth + 1;
3073   if (loop->depth > MAX_LOOP_DEPTH)
3074     {
3075       if (dump_file)
3076         fprintf (dump_file, ";; loop %d too deep\n", loop->loop_no);
3077       goto bad_loop;
3078     }
3079
3080   /* Get the loop iteration register.  */
3081   iter_reg = loop->iter_reg;
3082
3083   if (!DPREG_P (iter_reg))
3084     {
3085       if (dump_file)
3086         fprintf (dump_file, ";; loop %d iteration count NOT in PREG or DREG\n",
3087                  loop->loop_no);
3088       goto bad_loop;
3089     }
3090
3091   /* Check if start_label appears before loop_end and calculate the
3092      offset between them.  We calculate the length of instructions
3093      conservatively.  */
3094   length = 0;
3095   for (insn = loop->start_label;
3096        insn && insn != loop->loop_end;
3097        insn = NEXT_INSN (insn))
3098     {
3099       if (JUMP_P (insn) && any_condjump_p (insn) && !optimize_size)
3100         {
3101           if (TARGET_CSYNC_ANOMALY)
3102             length += 8;
3103           else if (TARGET_SPECLD_ANOMALY)
3104             length += 6;
3105         }
3106       else if (LABEL_P (insn))
3107         {
3108           if (TARGET_CSYNC_ANOMALY)
3109             length += 4;
3110         }
3111
3112       if (INSN_P (insn))
3113         length += get_attr_length (insn);
3114     }
3115
3116   if (!insn)
3117     {
3118       if (dump_file)
3119         fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
3120                  loop->loop_no);
3121       goto bad_loop;
3122     }
3123
3124   loop->length = length;
3125   if (loop->length > MAX_LOOP_LENGTH)
3126     {
3127       if (dump_file)
3128         fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
3129       goto bad_loop;
3130     }
3131
3132   /* Scan all the blocks to make sure they don't use iter_reg.  */
3133   if (bfin_scan_loop (loop, iter_reg, loop->loop_end))
3134     {
3135       if (dump_file)
3136         fprintf (dump_file, ";; loop %d uses iterator\n", loop->loop_no);
3137       goto bad_loop;
3138     }
3139
3140   /* Scan all the insns to see if the loop body clobber
3141      any hardware loop registers. */
3142
3143   reg_lc0 = gen_rtx_REG (SImode, REG_LC0);
3144   reg_lc1 = gen_rtx_REG (SImode, REG_LC1);
3145   reg_lt0 = gen_rtx_REG (SImode, REG_LT0);
3146   reg_lt1 = gen_rtx_REG (SImode, REG_LT1);
3147   reg_lb0 = gen_rtx_REG (SImode, REG_LB0);
3148   reg_lb1 = gen_rtx_REG (SImode, REG_LB1);
3149
3150   for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
3151     {
3152       rtx insn;
3153
3154       for (insn = BB_HEAD (bb);
3155            insn != NEXT_INSN (BB_END (bb));
3156            insn = NEXT_INSN (insn))
3157         {
3158           if (!INSN_P (insn))
3159             continue;
3160
3161           if (reg_set_p (reg_lc0, insn)
3162               || reg_set_p (reg_lt0, insn)
3163               || reg_set_p (reg_lb0, insn))
3164             loop->clobber_loop0 = 1;
3165           
3166           if (reg_set_p (reg_lc1, insn)
3167               || reg_set_p (reg_lt1, insn)
3168               || reg_set_p (reg_lb1, insn))
3169             loop->clobber_loop1 |= 1;
3170         }
3171     }
3172
3173   if ((loop->clobber_loop0 && loop->clobber_loop1)
3174       || (loop->depth == MAX_LOOP_DEPTH && loop->clobber_loop0))
3175     {
3176       loop->depth = MAX_LOOP_DEPTH + 1;
3177       if (dump_file)
3178         fprintf (dump_file, ";; loop %d no loop reg available\n",
3179                  loop->loop_no);
3180       goto bad_loop;
3181     }
3182
3183   /* There should be an instruction before the loop_end instruction
3184      in the same basic block. And the instruction must not be
3185      - JUMP
3186      - CONDITIONAL BRANCH
3187      - CALL
3188      - CSYNC
3189      - SSYNC
3190      - Returns (RTS, RTN, etc.)  */
3191
3192   bb = loop->tail;
3193   last_insn = PREV_INSN (loop->loop_end);
3194
3195   while (1)
3196     {
3197       for (; last_insn != PREV_INSN (BB_HEAD (bb));
3198            last_insn = PREV_INSN (last_insn))
3199         if (INSN_P (last_insn))
3200           break;
3201
3202       if (last_insn != PREV_INSN (BB_HEAD (bb)))
3203         break;
3204
3205       if (single_pred_p (bb)
3206           && single_pred (bb) != ENTRY_BLOCK_PTR)
3207         {
3208           bb = single_pred (bb);
3209           last_insn = BB_END (bb);
3210           continue;
3211         }
3212       else
3213         {
3214           last_insn = NULL_RTX;
3215           break;
3216         }
3217     }
3218
3219   if (!last_insn)
3220     {
3221       if (dump_file)
3222         fprintf (dump_file, ";; loop %d has no last instruction\n",
3223                  loop->loop_no);
3224       goto bad_loop;
3225     }
3226
3227   if (JUMP_P (last_insn))
3228     {
3229       loop_info inner = bb->aux;
3230       if (inner
3231           && inner->outer == loop
3232           && inner->loop_end == last_insn
3233           && inner->depth == 1)
3234         /* This jump_insn is the exact loop_end of an inner loop
3235            and to be optimized away. So use the inner's last_insn.  */
3236         last_insn = inner->last_insn;
3237       else
3238         {
3239           if (dump_file)
3240             fprintf (dump_file, ";; loop %d has bad last instruction\n",
3241                      loop->loop_no);
3242           goto bad_loop;
3243         }
3244     }
3245   else if (CALL_P (last_insn)
3246            || get_attr_type (last_insn) == TYPE_SYNC
3247            || recog_memoized (last_insn) == CODE_FOR_return_internal)
3248     {
3249       if (dump_file)
3250         fprintf (dump_file, ";; loop %d has bad last instruction\n",
3251                  loop->loop_no);
3252       goto bad_loop;
3253     }
3254
3255   if (GET_CODE (PATTERN (last_insn)) == ASM_INPUT
3256       || asm_noperands (PATTERN (last_insn)) >= 0
3257       || get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI)
3258     {
3259       nop_insn = emit_insn_after (gen_nop (), last_insn);
3260       last_insn = nop_insn;
3261     }
3262
3263   loop->last_insn = last_insn;
3264
3265   /* The loop is good for replacement.  */
3266   start_label = loop->start_label;
3267   end_label = gen_label_rtx ();
3268   iter_reg = loop->iter_reg;
3269
3270   if (loop->depth == 1 && !loop->clobber_loop1)
3271     {
3272       lc_reg = reg_lc1;
3273       lt_reg = reg_lt1;
3274       lb_reg = reg_lb1;
3275       loop->clobber_loop1 = 1;
3276     }
3277   else
3278     {
3279       lc_reg = reg_lc0;
3280       lt_reg = reg_lt0;
3281       lb_reg = reg_lb0;
3282       loop->clobber_loop0 = 1;
3283     }
3284
3285   /* If iter_reg is a DREG, we need generate an instruction to load
3286      the loop count into LC register. */
3287   if (D_REGNO_P (REGNO (iter_reg)))
3288     {
3289       init_insn = gen_movsi (lc_reg, iter_reg);
3290       loop_init = gen_lsetup_without_autoinit (lt_reg, start_label,
3291                                                lb_reg, end_label,
3292                                                lc_reg);
3293     }
3294   else if (P_REGNO_P (REGNO (iter_reg)))
3295     {
3296       init_insn = NULL_RTX;
3297       loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
3298                                             lb_reg, end_label,
3299                                             lc_reg, iter_reg);
3300     }
3301   else
3302     gcc_unreachable ();
3303
3304   loop->init = init_insn;
3305   loop->end_label = end_label;
3306   loop->loop_init = loop_init;
3307
3308   if (dump_file)
3309     {
3310       fprintf (dump_file, ";; replacing loop %d initializer with\n",
3311                loop->loop_no);
3312       print_rtl_single (dump_file, loop->loop_init);
3313       fprintf (dump_file, ";; replacing loop %d terminator with\n",
3314                loop->loop_no);
3315       print_rtl_single (dump_file, loop->loop_end);
3316     }
3317
3318   start_sequence ();
3319
3320   if (loop->init != NULL_RTX)
3321     emit_insn (loop->init);
3322   emit_insn(loop->loop_init);
3323   emit_label (loop->start_label);
3324
3325   seq = get_insns ();
3326   end_sequence ();
3327
3328   emit_insn_after (seq, BB_END (loop->predecessor));
3329   delete_insn (loop->loop_end);
3330
3331   /* Insert the loop end label before the last instruction of the loop.  */
3332   emit_label_before (loop->end_label, loop->last_insn);
3333
3334   return;
3335
3336 bad_loop:
3337
3338   if (dump_file)
3339     fprintf (dump_file, ";; loop %d is bad\n", loop->loop_no);
3340
3341   loop->bad = 1;
3342
3343   if (DPREG_P (loop->iter_reg))
3344     {
3345       /* If loop->iter_reg is a DREG or PREG, we can split it here
3346          without scratch register.  */
3347       rtx insn;
3348
3349       emit_insn_before (gen_addsi3 (loop->iter_reg,
3350                                     loop->iter_reg,
3351                                     constm1_rtx),
3352                         loop->loop_end);
3353
3354       emit_insn_before (gen_cmpsi (loop->iter_reg, const0_rtx),
3355                         loop->loop_end);
3356
3357       insn = emit_jump_insn_before (gen_bne (loop->start_label),
3358                                     loop->loop_end);
3359
3360       JUMP_LABEL (insn) = loop->start_label;
3361       LABEL_NUSES (loop->start_label)++;
3362       delete_insn (loop->loop_end);
3363     }
3364 }
3365
3366 /* Called from bfin_reorg_loops when a potential loop end is found.  LOOP is
3367    a newly set up structure describing the loop, it is this function's
3368    responsibility to fill most of it.  TAIL_BB and TAIL_INSN point to the
3369    loop_end insn and its enclosing basic block.  */
3370
3371 static void
3372 bfin_discover_loop (loop_info loop, basic_block tail_bb, rtx tail_insn)
3373 {
3374   unsigned dwork = 0;
3375   basic_block bb;
3376   VEC (basic_block,heap) *works = VEC_alloc (basic_block,heap,20);
3377
3378   loop->tail = tail_bb;
3379   loop->head = BRANCH_EDGE (tail_bb)->dest;
3380   loop->successor = FALLTHRU_EDGE (tail_bb)->dest;
3381   loop->predecessor = NULL;
3382   loop->loop_end = tail_insn;
3383   loop->last_insn = NULL_RTX;
3384   loop->iter_reg = SET_DEST (XVECEXP (PATTERN (tail_insn), 0, 1));
3385   loop->depth = loop->length = 0;
3386   loop->visited = 0;
3387   loop->clobber_loop0 = loop->clobber_loop1 = 0;
3388   loop->outer = NULL;
3389   loop->loops = NULL;
3390
3391   loop->init = loop->loop_init = NULL_RTX;
3392   loop->start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (tail_insn), 0, 0)), 1), 0);
3393   loop->end_label = NULL_RTX;
3394   loop->bad = 0;
3395
3396   VEC_safe_push (basic_block, heap, works, loop->head);
3397
3398   while (VEC_iterate (basic_block, works, dwork++, bb))
3399     {
3400       edge e;
3401       edge_iterator ei;
3402       if (bb == EXIT_BLOCK_PTR)
3403         {
3404           /* We've reached the exit block.  The loop must be bad. */
3405           if (dump_file)
3406             fprintf (dump_file,
3407                      ";; Loop is bad - reached exit block while scanning\n");
3408           loop->bad = 1;
3409           break;
3410         }
3411
3412       if (bitmap_bit_p (loop->block_bitmap, bb->index))
3413         continue;
3414
3415       /* We've not seen this block before.  Add it to the loop's
3416          list and then add each successor to the work list.  */
3417
3418       VEC_safe_push (basic_block, heap, loop->blocks, bb);
3419       bitmap_set_bit (loop->block_bitmap, bb->index);
3420
3421       if (bb != tail_bb)
3422         {
3423           FOR_EACH_EDGE (e, ei, bb->succs)
3424             {
3425               basic_block succ = EDGE_SUCC (bb, ei.index)->dest;
3426               if (!REGNO_REG_SET_P (succ->il.rtl->global_live_at_start,
3427                                     REGNO (loop->iter_reg)))
3428                 continue;
3429               if (!VEC_space (basic_block, works, 1))
3430                 {
3431                   if (dwork)
3432                     {
3433                       VEC_block_remove (basic_block, works, 0, dwork);
3434                       dwork = 0;
3435                     }
3436                   else
3437                     VEC_reserve (basic_block, heap, works, 1);
3438                 }
3439               VEC_quick_push (basic_block, works, succ);
3440             }
3441         }
3442     }
3443
3444   if (!loop->bad)
3445     {
3446       /* Make sure we only have one entry point.  */
3447       if (EDGE_COUNT (loop->head->preds) == 2)
3448         {
3449           loop->predecessor = EDGE_PRED (loop->head, 0)->src;
3450           if (loop->predecessor == loop->tail)
3451             /* We wanted the other predecessor.  */
3452             loop->predecessor = EDGE_PRED (loop->head, 1)->src;
3453
3454           /* We can only place a loop insn on a fall through edge of a
3455              single exit block.  */
3456           if (EDGE_COUNT (loop->predecessor->succs) != 1
3457               || !(EDGE_SUCC (loop->predecessor, 0)->flags & EDGE_FALLTHRU)
3458               /* If loop->predecessor is in loop, loop->head is not really
3459                  the head of the loop.  */
3460               || bfin_bb_in_loop (loop, loop->predecessor))
3461             loop->predecessor = NULL;
3462         }
3463
3464       if (loop->predecessor == NULL)
3465         {
3466           if (dump_file)
3467             fprintf (dump_file, ";; loop has bad predecessor\n");
3468           loop->bad = 1;
3469         }
3470     }
3471
3472 #ifdef ENABLE_CHECKING
3473   /* Make sure nothing jumps into this loop.  This shouldn't happen as we
3474      wouldn't have generated the counted loop patterns in such a case.
3475      However, this test must be done after the test above to detect loops
3476      with invalid headers.  */
3477   if (!loop->bad)
3478     for (dwork = 0; VEC_iterate (basic_block, loop->blocks, dwork, bb); dwork++)
3479       {
3480         edge e;
3481         edge_iterator ei;
3482         if (bb == loop->head)
3483           continue;
3484         FOR_EACH_EDGE (e, ei, bb->preds)
3485           {
3486             basic_block pred = EDGE_PRED (bb, ei.index)->src;
3487             if (!bfin_bb_in_loop (loop, pred))
3488               abort ();
3489           }
3490       }
3491 #endif
3492   VEC_free (basic_block, heap, works);
3493 }
3494
3495 static void
3496 bfin_reorg_loops (FILE *dump_file)
3497 {
3498   bitmap_obstack stack;
3499   bitmap tmp_bitmap;
3500   basic_block bb;
3501   loop_info loops = NULL;
3502   loop_info loop;
3503   int nloops = 0;
3504
3505   bitmap_obstack_initialize (&stack);
3506
3507   /* Find all the possible loop tails.  This means searching for every
3508      loop_end instruction.  For each one found, create a loop_info
3509      structure and add the head block to the work list. */
3510   FOR_EACH_BB (bb)
3511     {
3512       rtx tail = BB_END (bb);
3513
3514       while (GET_CODE (tail) == NOTE)
3515         tail = PREV_INSN (tail);
3516
3517       bb->aux = NULL;
3518
3519       if (INSN_P (tail) && recog_memoized (tail) == CODE_FOR_loop_end)
3520         {
3521           /* A possible loop end */
3522
3523           loop = XNEW (struct loop_info);
3524           loop->next = loops;
3525           loops = loop;
3526           loop->loop_no = nloops++;
3527           loop->blocks = VEC_alloc (basic_block, heap, 20);
3528           loop->block_bitmap = BITMAP_ALLOC (&stack);
3529           bb->aux = loop;
3530
3531           if (dump_file)
3532             {
3533               fprintf (dump_file, ";; potential loop %d ending at\n",
3534                        loop->loop_no);
3535               print_rtl_single (dump_file, tail);
3536             }
3537
3538           bfin_discover_loop (loop, bb, tail);
3539         }
3540     }
3541
3542   tmp_bitmap = BITMAP_ALLOC (&stack);
3543   /* Compute loop nestings.  */
3544   for (loop = loops; loop; loop = loop->next)
3545     {
3546       loop_info other;
3547       if (loop->bad)
3548         continue;
3549
3550       for (other = loop->next; other; other = other->next)
3551         {
3552           if (other->bad)
3553             continue;
3554
3555           bitmap_and (tmp_bitmap, other->block_bitmap, loop->block_bitmap);
3556           if (bitmap_empty_p (tmp_bitmap))
3557             continue;
3558           if (bitmap_equal_p (tmp_bitmap, other->block_bitmap))
3559             {
3560               other->outer = loop;
3561               VEC_safe_push (loop_info, heap, loop->loops, other);
3562             }
3563           else if (bitmap_equal_p (tmp_bitmap, loop->block_bitmap))
3564             {
3565               loop->outer = other;
3566               VEC_safe_push (loop_info, heap, other->loops, loop);
3567             }
3568           else
3569             {
3570               loop->bad = other->bad = 1;
3571             }
3572         }
3573     }
3574   BITMAP_FREE (tmp_bitmap);
3575
3576   if (dump_file)
3577     {
3578       fprintf (dump_file, ";; All loops found:\n\n");
3579       bfin_dump_loops (loops);
3580     }
3581   
3582   /* Now apply the optimizations.  */
3583   for (loop = loops; loop; loop = loop->next)
3584     bfin_optimize_loop (loop);
3585
3586   if (dump_file)
3587     {
3588       fprintf (dump_file, ";; After hardware loops optimization:\n\n");
3589       bfin_dump_loops (loops);
3590     }
3591
3592   /* Free up the loop structures */
3593   while (loops)
3594     {
3595       loop = loops;
3596       loops = loop->next;
3597       VEC_free (loop_info, heap, loop->loops);
3598       VEC_free (basic_block, heap, loop->blocks);
3599       BITMAP_FREE (loop->block_bitmap);
3600       XDELETE (loop);
3601     }
3602
3603   if (dump_file)
3604     print_rtl (dump_file, get_insns ());
3605 }
3606
3607 \f
3608 /* We use the machine specific reorg pass for emitting CSYNC instructions
3609    after conditional branches as needed.
3610
3611    The Blackfin is unusual in that a code sequence like
3612      if cc jump label
3613      r0 = (p0)
3614    may speculatively perform the load even if the condition isn't true.  This
3615    happens for a branch that is predicted not taken, because the pipeline
3616    isn't flushed or stalled, so the early stages of the following instructions,
3617    which perform the memory reference, are allowed to execute before the
3618    jump condition is evaluated.
3619    Therefore, we must insert additional instructions in all places where this
3620    could lead to incorrect behavior.  The manual recommends CSYNC, while
3621    VDSP seems to use NOPs (even though its corresponding compiler option is
3622    named CSYNC).
3623
3624    When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
3625    When optimizing for size, we turn the branch into a predicted taken one.
3626    This may be slower due to mispredicts, but saves code size.  */
3627
3628 static void
3629 bfin_reorg (void)
3630 {
3631   rtx insn, last_condjump = NULL_RTX;
3632   int cycles_since_jump = INT_MAX;
3633
3634   /* Doloop optimization */
3635   if (cfun->machine->has_hardware_loops)
3636     bfin_reorg_loops (dump_file);
3637
3638   if (! TARGET_SPECLD_ANOMALY && ! TARGET_CSYNC_ANOMALY)
3639     return;
3640
3641   /* First pass: find predicted-false branches; if something after them
3642      needs nops, insert them or change the branch to predict true.  */
3643   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
3644     {
3645       rtx pat;
3646
3647       if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
3648         continue;
3649
3650       pat = PATTERN (insn);
3651       if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
3652           || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
3653           || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
3654         continue;
3655
3656       if (JUMP_P (insn))
3657         {
3658           if (any_condjump_p (insn)
3659               && ! cbranch_predicted_taken_p (insn))
3660             {
3661               last_condjump = insn;
3662               cycles_since_jump = 0;
3663             }
3664           else
3665             cycles_since_jump = INT_MAX;
3666         }
3667       else if (INSN_P (insn))
3668         {
3669           enum attr_type type = get_attr_type (insn);
3670           int delay_needed = 0;
3671           if (cycles_since_jump < INT_MAX)
3672             cycles_since_jump++;
3673
3674           if (type == TYPE_MCLD && TARGET_SPECLD_ANOMALY)
3675             {
3676               rtx pat = single_set (insn);
3677               if (may_trap_p (SET_SRC (pat)))
3678                 delay_needed = 3;
3679             }
3680           else if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
3681             delay_needed = 4;
3682
3683           if (delay_needed > cycles_since_jump)
3684             {
3685               rtx pat;
3686               int num_clobbers;
3687               rtx *op = recog_data.operand;
3688
3689               delay_needed -= cycles_since_jump;
3690
3691               extract_insn (last_condjump);
3692               if (optimize_size)
3693                 {
3694                   pat = gen_cbranch_predicted_taken (op[0], op[1], op[2],
3695                                                      op[3]);
3696                   cycles_since_jump = INT_MAX;
3697                 }
3698               else
3699                 /* Do not adjust cycles_since_jump in this case, so that
3700                    we'll increase the number of NOPs for a subsequent insn
3701                    if necessary.  */
3702                 pat = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
3703                                              GEN_INT (delay_needed));
3704               PATTERN (last_condjump) = pat;
3705               INSN_CODE (last_condjump) = recog (pat, insn, &num_clobbers);
3706             }
3707         }
3708     }
3709   /* Second pass: for predicted-true branches, see if anything at the
3710      branch destination needs extra nops.  */
3711   if (! TARGET_CSYNC_ANOMALY)
3712     return;
3713
3714   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
3715     {
3716       if (JUMP_P (insn)
3717           && any_condjump_p (insn)
3718           && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken
3719               || cbranch_predicted_taken_p (insn)))
3720         {
3721           rtx target = JUMP_LABEL (insn);
3722           rtx label = target;
3723           cycles_since_jump = 0;
3724           for (; target && cycles_since_jump < 3; target = NEXT_INSN (target))
3725             {
3726               rtx pat;
3727
3728               if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
3729                 continue;
3730
3731               pat = PATTERN (target);
3732               if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
3733                   || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
3734                   || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
3735                 continue;
3736
3737               if (INSN_P (target))
3738                 {
3739                   enum attr_type type = get_attr_type (target);
3740                   int delay_needed = 0;
3741                   if (cycles_since_jump < INT_MAX)
3742                     cycles_since_jump++;
3743
3744                   if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
3745                     delay_needed = 2;
3746
3747                   if (delay_needed > cycles_since_jump)
3748                     {
3749                       rtx prev = prev_real_insn (label);
3750                       delay_needed -= cycles_since_jump;
3751                       if (dump_file)
3752                         fprintf (dump_file, "Adding %d nops after %d\n",
3753                                  delay_needed, INSN_UID (label));
3754                       if (JUMP_P (prev)
3755                           && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops)
3756                         {
3757                           rtx x;
3758                           HOST_WIDE_INT v;
3759
3760                           if (dump_file)
3761                             fprintf (dump_file,
3762                                      "Reducing nops on insn %d.\n",
3763                                      INSN_UID (prev));
3764                           x = PATTERN (prev);
3765                           x = XVECEXP (x, 0, 1);
3766                           v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed;
3767                           XVECEXP (x, 0, 0) = GEN_INT (v);
3768                         }
3769                       while (delay_needed-- > 0)
3770                         emit_insn_after (gen_nop (), label);
3771                       break;
3772                     }
3773                 }
3774             }
3775         }
3776     }
3777 }
3778 \f
3779 /* Handle interrupt_handler, exception_handler and nmi_handler function
3780    attributes; arguments as in struct attribute_spec.handler.  */
3781
3782 static tree
3783 handle_int_attribute (tree *node, tree name,
3784                       tree args ATTRIBUTE_UNUSED,
3785                       int flags ATTRIBUTE_UNUSED,
3786                       bool *no_add_attrs)
3787 {
3788   tree x = *node;
3789   if (TREE_CODE (x) == FUNCTION_DECL)
3790     x = TREE_TYPE (x);
3791
3792   if (TREE_CODE (x) != FUNCTION_TYPE)
3793     {
3794       warning (OPT_Wattributes, "%qs attribute only applies to functions",
3795                IDENTIFIER_POINTER (name));
3796       *no_add_attrs = true;
3797     }
3798   else if (funkind (x) != SUBROUTINE)
3799     error ("multiple function type attributes specified");
3800
3801   return NULL_TREE;
3802 }
3803
3804 /* Return 0 if the attributes for two types are incompatible, 1 if they
3805    are compatible, and 2 if they are nearly compatible (which causes a
3806    warning to be generated).  */
3807
3808 static int
3809 bfin_comp_type_attributes (tree type1, tree type2)
3810 {
3811   e_funkind kind1, kind2;
3812
3813   if (TREE_CODE (type1) != FUNCTION_TYPE)
3814     return 1;
3815
3816   kind1 = funkind (type1);
3817   kind2 = funkind (type2);
3818
3819   if (kind1 != kind2)
3820     return 0;
3821   
3822   /*  Check for mismatched modifiers */
3823   if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
3824       != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
3825     return 0;
3826
3827   if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
3828       != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
3829     return 0;
3830
3831   if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
3832       != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
3833     return 0;
3834
3835   if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1))
3836       != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2)))
3837     return 0;
3838
3839   return 1;
3840 }
3841
3842 /* Handle a "longcall" or "shortcall" attribute; arguments as in
3843    struct attribute_spec.handler.  */
3844
3845 static tree
3846 bfin_handle_longcall_attribute (tree *node, tree name, 
3847                                 tree args ATTRIBUTE_UNUSED, 
3848                                 int flags ATTRIBUTE_UNUSED, 
3849                                 bool *no_add_attrs)
3850 {
3851   if (TREE_CODE (*node) != FUNCTION_TYPE
3852       && TREE_CODE (*node) != FIELD_DECL
3853       && TREE_CODE (*node) != TYPE_DECL)
3854     {
3855       warning (OPT_Wattributes, "`%s' attribute only applies to functions",
3856                IDENTIFIER_POINTER (name));
3857       *no_add_attrs = true;
3858     }
3859
3860   if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0
3861        && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node)))
3862       || (strcmp (IDENTIFIER_POINTER (name), "shortcall") == 0
3863           && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node))))
3864     {
3865       warning (OPT_Wattributes,
3866                "can't apply both longcall and shortcall attributes to the same function");
3867       *no_add_attrs = true;
3868     }
3869
3870   return NULL_TREE;
3871 }
3872
3873 /* Table of valid machine attributes.  */
3874 const struct attribute_spec bfin_attribute_table[] =
3875 {
3876   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
3877   { "interrupt_handler", 0, 0, false, true,  true, handle_int_attribute },
3878   { "exception_handler", 0, 0, false, true,  true, handle_int_attribute },
3879   { "nmi_handler", 0, 0, false, true,  true, handle_int_attribute },
3880   { "nesting", 0, 0, false, true,  true, NULL },
3881   { "kspisusp", 0, 0, false, true,  true, NULL },
3882   { "saveall", 0, 0, false, true,  true, NULL },
3883   { "longcall",  0, 0, false, true,  true,  bfin_handle_longcall_attribute },
3884   { "shortcall", 0, 0, false, true,  true,  bfin_handle_longcall_attribute },
3885   { NULL, 0, 0, false, false, false, NULL }
3886 };
3887 \f
3888 /* Implementation of TARGET_ASM_INTEGER.  When using FD-PIC, we need to
3889    tell the assembler to generate pointers to function descriptors in
3890    some cases.  */
3891
3892 static bool
3893 bfin_assemble_integer (rtx value, unsigned int size, int aligned_p)
3894 {
3895   if (TARGET_FDPIC && size == UNITS_PER_WORD)
3896     {
3897       if (GET_CODE (value) == SYMBOL_REF
3898           && SYMBOL_REF_FUNCTION_P (value))
3899         {
3900           fputs ("\t.picptr\tfuncdesc(", asm_out_file);
3901           output_addr_const (asm_out_file, value);
3902           fputs (")\n", asm_out_file);
3903           return true;
3904         }
3905       if (!aligned_p)
3906         {
3907           /* We've set the unaligned SI op to NULL, so we always have to
3908              handle the unaligned case here.  */
3909           assemble_integer_with_op ("\t.4byte\t", value);
3910           return true;
3911         }
3912     }
3913   return default_assemble_integer (value, size, aligned_p);
3914 }
3915 \f
3916 /* Output the assembler code for a thunk function.  THUNK_DECL is the
3917    declaration for the thunk function itself, FUNCTION is the decl for
3918    the target function.  DELTA is an immediate constant offset to be
3919    added to THIS.  If VCALL_OFFSET is nonzero, the word at
3920    *(*this + vcall_offset) should be added to THIS.  */
3921
3922 static void
3923 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
3924                       tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
3925                       HOST_WIDE_INT vcall_offset, tree function)
3926 {
3927   rtx xops[3];
3928   /* The this parameter is passed as the first argument.  */
3929   rtx this = gen_rtx_REG (Pmode, REG_R0);
3930
3931   /* Adjust the this parameter by a fixed constant.  */
3932   if (delta)
3933     {
3934       xops[1] = this;
3935       if (delta >= -64 && delta <= 63)
3936         {
3937           xops[0] = GEN_INT (delta);
3938           output_asm_insn ("%1 += %0;", xops);
3939         }
3940       else if (delta >= -128 && delta < -64)
3941         {
3942           xops[0] = GEN_INT (delta + 64);
3943           output_asm_insn ("%1 += -64; %1 += %0;", xops);
3944         }
3945       else if (delta > 63 && delta <= 126)
3946         {
3947           xops[0] = GEN_INT (delta - 63);
3948           output_asm_insn ("%1 += 63; %1 += %0;", xops);
3949         }
3950       else
3951         {
3952           xops[0] = GEN_INT (delta);
3953           output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
3954         }
3955     }
3956
3957   /* Adjust the this parameter by a value stored in the vtable.  */
3958   if (vcall_offset)
3959     {
3960       rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
3961       rtx tmp = gen_rtx_REG (Pmode, REG_R2);
3962
3963       xops[1] = tmp;
3964       xops[2] = p2tmp;
3965       output_asm_insn ("%2 = r0; %2 = [%2];", xops);
3966
3967       /* Adjust the this parameter.  */
3968       xops[0] = gen_rtx_MEM (Pmode, plus_constant (p2tmp, vcall_offset));
3969       if (!memory_operand (xops[0], Pmode))
3970         {
3971           rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
3972           xops[0] = GEN_INT (vcall_offset);
3973           xops[1] = tmp2;
3974           output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
3975           xops[0] = gen_rtx_MEM (Pmode, p2tmp);
3976         }
3977       xops[2] = this;
3978       output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
3979     }
3980
3981   xops[0] = XEXP (DECL_RTL (function), 0);
3982   if (1 || !flag_pic || (*targetm.binds_local_p) (function))
3983     output_asm_insn ("jump.l\t%P0", xops);
3984 }
3985 \f
3986 /* Codes for all the Blackfin builtins.  */
3987 enum bfin_builtins
3988 {
3989   BFIN_BUILTIN_CSYNC,
3990   BFIN_BUILTIN_SSYNC,
3991   BFIN_BUILTIN_COMPOSE_2X16,
3992   BFIN_BUILTIN_EXTRACTLO,
3993   BFIN_BUILTIN_EXTRACTHI,
3994
3995   BFIN_BUILTIN_SSADD_2X16,
3996   BFIN_BUILTIN_SSSUB_2X16,
3997   BFIN_BUILTIN_SSADDSUB_2X16,
3998   BFIN_BUILTIN_SSSUBADD_2X16,
3999   BFIN_BUILTIN_MULT_2X16,
4000   BFIN_BUILTIN_MULTR_2X16,
4001   BFIN_BUILTIN_NEG_2X16,
4002   BFIN_BUILTIN_ABS_2X16,
4003   BFIN_BUILTIN_MIN_2X16,
4004   BFIN_BUILTIN_MAX_2X16,
4005
4006   BFIN_BUILTIN_SSADD_1X16,
4007   BFIN_BUILTIN_SSSUB_1X16,
4008   BFIN_BUILTIN_MULT_1X16,
4009   BFIN_BUILTIN_MULTR_1X16,
4010   BFIN_BUILTIN_NORM_1X16,
4011   BFIN_BUILTIN_NEG_1X16,
4012   BFIN_BUILTIN_ABS_1X16,
4013   BFIN_BUILTIN_MIN_1X16,
4014   BFIN_BUILTIN_MAX_1X16,
4015
4016   BFIN_BUILTIN_DIFFHL_2X16,
4017   BFIN_BUILTIN_DIFFLH_2X16,
4018
4019   BFIN_BUILTIN_SSADD_1X32,
4020   BFIN_BUILTIN_SSSUB_1X32,
4021   BFIN_BUILTIN_NORM_1X32,
4022   BFIN_BUILTIN_NEG_1X32,
4023   BFIN_BUILTIN_MIN_1X32,
4024   BFIN_BUILTIN_MAX_1X32,
4025   BFIN_BUILTIN_MULT_1X32,
4026
4027   BFIN_BUILTIN_MULHISILL,
4028   BFIN_BUILTIN_MULHISILH,
4029   BFIN_BUILTIN_MULHISIHL,
4030   BFIN_BUILTIN_MULHISIHH,
4031
4032   BFIN_BUILTIN_LSHIFT_1X16,
4033   BFIN_BUILTIN_LSHIFT_2X16,
4034   BFIN_BUILTIN_SSASHIFT_1X16,
4035   BFIN_BUILTIN_SSASHIFT_2X16,
4036
4037   BFIN_BUILTIN_CPLX_MUL_16,
4038   BFIN_BUILTIN_CPLX_MAC_16,
4039   BFIN_BUILTIN_CPLX_MSU_16,
4040
4041   BFIN_BUILTIN_MAX
4042 };
4043
4044 #define def_builtin(NAME, TYPE, CODE)                                   \
4045 do {                                                                    \
4046   add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD,            \
4047                        NULL, NULL_TREE);                                \
4048 } while (0)
4049
4050 /* Set up all builtin functions for this target.  */
4051 static void
4052 bfin_init_builtins (void)
4053 {
4054   tree V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
4055   tree void_ftype_void
4056     = build_function_type (void_type_node, void_list_node);
4057   tree short_ftype_short
4058     = build_function_type_list (short_integer_type_node, short_integer_type_node,
4059                                 NULL_TREE);
4060   tree short_ftype_int_int
4061     = build_function_type_list (short_integer_type_node, integer_type_node,
4062                                 integer_type_node, NULL_TREE);
4063   tree int_ftype_int_int
4064     = build_function_type_list (integer_type_node, integer_type_node,
4065                                 integer_type_node, NULL_TREE);
4066   tree int_ftype_int
4067     = build_function_type_list (integer_type_node, integer_type_node,
4068                                 NULL_TREE);
4069   tree short_ftype_int
4070     = build_function_type_list (short_integer_type_node, integer_type_node,
4071                                 NULL_TREE);
4072   tree int_ftype_v2hi_v2hi
4073     = build_function_type_list (integer_type_node, V2HI_type_node,
4074                                 V2HI_type_node, NULL_TREE);
4075   tree v2hi_ftype_v2hi_v2hi
4076     = build_function_type_list (V2HI_type_node, V2HI_type_node,
4077                                 V2HI_type_node, NULL_TREE);
4078   tree v2hi_ftype_v2hi_v2hi_v2hi
4079     = build_function_type_list (V2HI_type_node, V2HI_type_node,
4080                                 V2HI_type_node, V2HI_type_node, NULL_TREE);
4081   tree v2hi_ftype_int_int
4082     = build_function_type_list (V2HI_type_node, integer_type_node,
4083                                 integer_type_node, NULL_TREE);
4084   tree v2hi_ftype_v2hi_int
4085     = build_function_type_list (V2HI_type_node, V2HI_type_node,
4086                                 integer_type_node, NULL_TREE);
4087   tree int_ftype_short_short
4088     = build_function_type_list (integer_type_node, short_integer_type_node,
4089                                 short_integer_type_node, NULL_TREE);
4090   tree v2hi_ftype_v2hi
4091     = build_function_type_list (V2HI_type_node, V2HI_type_node, NULL_TREE);
4092   tree short_ftype_v2hi
4093     = build_function_type_list (short_integer_type_node, V2HI_type_node,
4094                                 NULL_TREE);
4095
4096   /* Add the remaining MMX insns with somewhat more complicated types.  */
4097   def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC);
4098   def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC);
4099
4100   def_builtin ("__builtin_bfin_compose_2x16", v2hi_ftype_int_int,
4101                BFIN_BUILTIN_COMPOSE_2X16);
4102   def_builtin ("__builtin_bfin_extract_hi", short_ftype_v2hi,
4103                BFIN_BUILTIN_EXTRACTHI);
4104   def_builtin ("__builtin_bfin_extract_lo", short_ftype_v2hi,
4105                BFIN_BUILTIN_EXTRACTLO);
4106
4107   def_builtin ("__builtin_bfin_min_fr2x16", v2hi_ftype_v2hi_v2hi,
4108                BFIN_BUILTIN_MIN_2X16);
4109   def_builtin ("__builtin_bfin_max_fr2x16", v2hi_ftype_v2hi_v2hi,
4110                BFIN_BUILTIN_MAX_2X16);
4111
4112   def_builtin ("__builtin_bfin_add_fr2x16", v2hi_ftype_v2hi_v2hi,
4113                BFIN_BUILTIN_SSADD_2X16);
4114   def_builtin ("__builtin_bfin_sub_fr2x16", v2hi_ftype_v2hi_v2hi,
4115                BFIN_BUILTIN_SSSUB_2X16);
4116   def_builtin ("__builtin_bfin_dspaddsubsat", v2hi_ftype_v2hi_v2hi,
4117                BFIN_BUILTIN_SSADDSUB_2X16);
4118   def_builtin ("__builtin_bfin_dspsubaddsat", v2hi_ftype_v2hi_v2hi,
4119                BFIN_BUILTIN_SSSUBADD_2X16);
4120   def_builtin ("__builtin_bfin_mult_fr2x16", v2hi_ftype_v2hi_v2hi,
4121                BFIN_BUILTIN_MULT_2X16);
4122   def_builtin ("__builtin_bfin_multr_fr2x16", v2hi_ftype_v2hi_v2hi,
4123                BFIN_BUILTIN_MULTR_2X16);
4124   def_builtin ("__builtin_bfin_negate_fr2x16", v2hi_ftype_v2hi,
4125                BFIN_BUILTIN_NEG_2X16);
4126   def_builtin ("__builtin_bfin_abs_fr2x16", v2hi_ftype_v2hi,
4127                BFIN_BUILTIN_ABS_2X16);
4128
4129   def_builtin ("__builtin_bfin_add_fr1x16", short_ftype_int_int,
4130                BFIN_BUILTIN_SSADD_1X16);
4131   def_builtin ("__builtin_bfin_sub_fr1x16", short_ftype_int_int,
4132                BFIN_BUILTIN_SSSUB_1X16);
4133   def_builtin ("__builtin_bfin_mult_fr1x16", short_ftype_int_int,
4134                BFIN_BUILTIN_MULT_1X16);
4135   def_builtin ("__builtin_bfin_multr_fr1x16", short_ftype_int_int,
4136                BFIN_BUILTIN_MULTR_1X16);
4137   def_builtin ("__builtin_bfin_negate_fr1x16", short_ftype_short,
4138                BFIN_BUILTIN_NEG_1X16);
4139   def_builtin ("__builtin_bfin_abs_fr1x16", short_ftype_short,
4140                BFIN_BUILTIN_ABS_1X16);
4141   def_builtin ("__builtin_bfin_norm_fr1x16", short_ftype_int,
4142                BFIN_BUILTIN_NORM_1X16);
4143
4144   def_builtin ("__builtin_bfin_diff_hl_fr2x16", short_ftype_v2hi,
4145                BFIN_BUILTIN_DIFFHL_2X16);
4146   def_builtin ("__builtin_bfin_diff_lh_fr2x16", short_ftype_v2hi,
4147                BFIN_BUILTIN_DIFFLH_2X16);
4148
4149   def_builtin ("__builtin_bfin_mulhisill", int_ftype_v2hi_v2hi,
4150                BFIN_BUILTIN_MULHISILL);
4151   def_builtin ("__builtin_bfin_mulhisihl", int_ftype_v2hi_v2hi,
4152                BFIN_BUILTIN_MULHISIHL);
4153   def_builtin ("__builtin_bfin_mulhisilh", int_ftype_v2hi_v2hi,
4154                BFIN_BUILTIN_MULHISILH);
4155   def_builtin ("__builtin_bfin_mulhisihh", int_ftype_v2hi_v2hi,
4156                BFIN_BUILTIN_MULHISIHH);
4157
4158   def_builtin ("__builtin_bfin_add_fr1x32", int_ftype_int_int,
4159                BFIN_BUILTIN_SSADD_1X32);
4160   def_builtin ("__builtin_bfin_sub_fr1x32", int_ftype_int_int,
4161                BFIN_BUILTIN_SSSUB_1X32);
4162   def_builtin ("__builtin_bfin_negate_fr1x32", int_ftype_int,
4163                BFIN_BUILTIN_NEG_1X32);
4164   def_builtin ("__builtin_bfin_norm_fr1x32", short_ftype_int,
4165                BFIN_BUILTIN_NORM_1X32);
4166   def_builtin ("__builtin_bfin_mult_fr1x32", int_ftype_short_short,
4167                BFIN_BUILTIN_MULT_1X32);
4168
4169   /* Shifts.  */
4170   def_builtin ("__builtin_bfin_shl_fr1x16", short_ftype_int_int,
4171                BFIN_BUILTIN_SSASHIFT_1X16);
4172   def_builtin ("__builtin_bfin_shl_fr2x16", v2hi_ftype_v2hi_int,
4173                BFIN_BUILTIN_SSASHIFT_2X16);
4174   def_builtin ("__builtin_bfin_lshl_fr1x16", short_ftype_int_int,
4175                BFIN_BUILTIN_LSHIFT_1X16);
4176   def_builtin ("__builtin_bfin_lshl_fr2x16", v2hi_ftype_v2hi_int,
4177                BFIN_BUILTIN_LSHIFT_2X16);
4178
4179   /* Complex numbers.  */
4180   def_builtin ("__builtin_bfin_cmplx_mul", v2hi_ftype_v2hi_v2hi,
4181                BFIN_BUILTIN_CPLX_MUL_16);
4182   def_builtin ("__builtin_bfin_cmplx_mac", v2hi_ftype_v2hi_v2hi_v2hi,
4183                BFIN_BUILTIN_CPLX_MAC_16);
4184   def_builtin ("__builtin_bfin_cmplx_msu", v2hi_ftype_v2hi_v2hi_v2hi,
4185                BFIN_BUILTIN_CPLX_MSU_16);
4186 }
4187
4188
4189 struct builtin_description
4190 {
4191   const enum insn_code icode;
4192   const char *const name;
4193   const enum bfin_builtins code;
4194   int macflag;
4195 };
4196
4197 static const struct builtin_description bdesc_2arg[] =
4198 {
4199   { CODE_FOR_composev2hi, "__builtin_bfin_compose_2x16", BFIN_BUILTIN_COMPOSE_2X16, -1 },
4200
4201   { CODE_FOR_ssashiftv2hi3, "__builtin_bfin_shl_fr2x16", BFIN_BUILTIN_SSASHIFT_2X16, -1 },
4202   { CODE_FOR_ssashifthi3, "__builtin_bfin_shl_fr1x16", BFIN_BUILTIN_SSASHIFT_1X16, -1 },
4203   { CODE_FOR_lshiftv2hi3, "__builtin_bfin_lshl_fr2x16", BFIN_BUILTIN_LSHIFT_2X16, -1 },
4204   { CODE_FOR_lshifthi3, "__builtin_bfin_lshl_fr1x16", BFIN_BUILTIN_LSHIFT_1X16, -1 },
4205
4206   { CODE_FOR_sminhi3, "__builtin_bfin_min_fr1x16", BFIN_BUILTIN_MIN_1X16, -1 },
4207   { CODE_FOR_smaxhi3, "__builtin_bfin_max_fr1x16", BFIN_BUILTIN_MAX_1X16, -1 },
4208   { CODE_FOR_ssaddhi3, "__builtin_bfin_add_fr1x16", BFIN_BUILTIN_SSADD_1X16, -1 },
4209   { CODE_FOR_sssubhi3, "__builtin_bfin_sub_fr1x16", BFIN_BUILTIN_SSSUB_1X16, -1 },
4210
4211   { CODE_FOR_sminsi3, "__builtin_bfin_min_fr1x32", BFIN_BUILTIN_MIN_1X32, -1 },
4212   { CODE_FOR_smaxsi3, "__builtin_bfin_max_fr1x32", BFIN_BUILTIN_MAX_1X32, -1 },
4213   { CODE_FOR_ssaddsi3, "__builtin_bfin_add_fr1x32", BFIN_BUILTIN_SSADD_1X32, -1 },
4214   { CODE_FOR_sssubsi3, "__builtin_bfin_sub_fr1x32", BFIN_BUILTIN_SSSUB_1X32, -1 },
4215
4216   { CODE_FOR_sminv2hi3, "__builtin_bfin_min_fr2x16", BFIN_BUILTIN_MIN_2X16, -1 },
4217   { CODE_FOR_smaxv2hi3, "__builtin_bfin_max_fr2x16", BFIN_BUILTIN_MAX_2X16, -1 },
4218   { CODE_FOR_ssaddv2hi3, "__builtin_bfin_add_fr2x16", BFIN_BUILTIN_SSADD_2X16, -1 },
4219   { CODE_FOR_sssubv2hi3, "__builtin_bfin_sub_fr2x16", BFIN_BUILTIN_SSSUB_2X16, -1 },
4220   { CODE_FOR_ssaddsubv2hi3, "__builtin_bfin_dspaddsubsat", BFIN_BUILTIN_SSADDSUB_2X16, -1 },
4221   { CODE_FOR_sssubaddv2hi3, "__builtin_bfin_dspsubaddsat", BFIN_BUILTIN_SSSUBADD_2X16, -1 },
4222
4223   { CODE_FOR_flag_mulhisi, "__builtin_bfin_mult_fr1x32", BFIN_BUILTIN_MULT_1X32, MACFLAG_NONE },
4224   { CODE_FOR_flag_mulhi, "__builtin_bfin_mult_fr1x16", BFIN_BUILTIN_MULT_1X16, MACFLAG_T },
4225   { CODE_FOR_flag_mulhi, "__builtin_bfin_multr_fr1x16", BFIN_BUILTIN_MULTR_1X16, MACFLAG_NONE },
4226   { CODE_FOR_flag_mulv2hi, "__builtin_bfin_mult_fr2x16", BFIN_BUILTIN_MULT_2X16, MACFLAG_T },
4227   { CODE_FOR_flag_mulv2hi, "__builtin_bfin_multr_fr2x16", BFIN_BUILTIN_MULTR_2X16, MACFLAG_NONE }
4228 };
4229
4230 static const struct builtin_description bdesc_1arg[] =
4231 {
4232   { CODE_FOR_signbitshi2, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16, 0 },
4233   { CODE_FOR_ssneghi2, "__builtin_bfin_negate_fr1x16", BFIN_BUILTIN_NEG_1X16, 0 },
4234   { CODE_FOR_abshi2, "__builtin_bfin_abs_fr1x16", BFIN_BUILTIN_ABS_1X16, 0 },
4235
4236   { CODE_FOR_signbitssi2, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32, 0 },
4237   { CODE_FOR_ssnegsi2, "__builtin_bfin_negate_fr1x32", BFIN_BUILTIN_NEG_1X32, 0 },
4238
4239   { CODE_FOR_movv2hi_hi_low, "__builtin_bfin_extract_lo", BFIN_BUILTIN_EXTRACTLO, 0 },
4240   { CODE_FOR_movv2hi_hi_high, "__builtin_bfin_extract_hi", BFIN_BUILTIN_EXTRACTHI, 0 },
4241   { CODE_FOR_ssnegv2hi2, "__builtin_bfin_negate_fr2x16", BFIN_BUILTIN_NEG_2X16, 0 },
4242   { CODE_FOR_absv2hi2, "__builtin_bfin_abs_fr2x16", BFIN_BUILTIN_ABS_2X16, 0 }
4243 };
4244
4245 /* Errors in the source file can cause expand_expr to return const0_rtx
4246    where we expect a vector.  To avoid crashing, use one of the vector
4247    clear instructions.  */
4248 static rtx
4249 safe_vector_operand (rtx x, enum machine_mode mode)
4250 {
4251   if (x != const0_rtx)
4252     return x;
4253   x = gen_reg_rtx (SImode);
4254
4255   emit_insn (gen_movsi (x, CONST0_RTX (SImode)));
4256   return gen_lowpart (mode, x);
4257 }
4258
4259 /* Subroutine of bfin_expand_builtin to take care of binop insns.  MACFLAG is -1
4260    if this is a normal binary op, or one of the MACFLAG_xxx constants.  */
4261
4262 static rtx
4263 bfin_expand_binop_builtin (enum insn_code icode, tree arglist, rtx target,
4264                            int macflag)
4265 {
4266   rtx pat;
4267   tree arg0 = TREE_VALUE (arglist);
4268   tree arg1 = TREE_VALUE (TREE_CHAIN (arglist));
4269   rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4270   rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
4271   enum machine_mode op0mode = GET_MODE (op0);
4272   enum machine_mode op1mode = GET_MODE (op1);
4273   enum machine_mode tmode = insn_data[icode].operand[0].mode;
4274   enum machine_mode mode0 = insn_data[icode].operand[1].mode;
4275   enum machine_mode mode1 = insn_data[icode].operand[2].mode;
4276
4277   if (VECTOR_MODE_P (mode0))
4278     op0 = safe_vector_operand (op0, mode0);
4279   if (VECTOR_MODE_P (mode1))
4280     op1 = safe_vector_operand (op1, mode1);
4281
4282   if (! target
4283       || GET_MODE (target) != tmode
4284       || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
4285     target = gen_reg_rtx (tmode);
4286
4287   if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode)
4288     {
4289       op0mode = HImode;
4290       op0 = gen_lowpart (HImode, op0);
4291     }
4292   if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode)
4293     {
4294       op1mode = HImode;
4295       op1 = gen_lowpart (HImode, op1);
4296     }
4297   /* In case the insn wants input operands in modes different from
4298      the result, abort.  */
4299   gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
4300               && (op1mode == mode1 || op1mode == VOIDmode));
4301
4302   if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
4303     op0 = copy_to_mode_reg (mode0, op0);
4304   if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
4305     op1 = copy_to_mode_reg (mode1, op1);
4306
4307   if (macflag == -1)
4308     pat = GEN_FCN (icode) (target, op0, op1);
4309   else
4310     pat = GEN_FCN (icode) (target, op0, op1, GEN_INT (macflag));
4311   if (! pat)
4312     return 0;
4313
4314   emit_insn (pat);
4315   return target;
4316 }
4317
4318 /* Subroutine of bfin_expand_builtin to take care of unop insns.  */
4319
4320 static rtx
4321 bfin_expand_unop_builtin (enum insn_code icode, tree arglist,
4322                           rtx target)
4323 {
4324   rtx pat;
4325   tree arg0 = TREE_VALUE (arglist);
4326   rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4327   enum machine_mode op0mode = GET_MODE (op0);
4328   enum machine_mode tmode = insn_data[icode].operand[0].mode;
4329   enum machine_mode mode0 = insn_data[icode].operand[1].mode;
4330
4331   if (! target
4332       || GET_MODE (target) != tmode
4333       || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
4334     target = gen_reg_rtx (tmode);
4335
4336   if (VECTOR_MODE_P (mode0))
4337     op0 = safe_vector_operand (op0, mode0);
4338
4339   if (op0mode == SImode && mode0 == HImode)
4340     {
4341       op0mode = HImode;
4342       op0 = gen_lowpart (HImode, op0);
4343     }
4344   gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
4345
4346   if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
4347     op0 = copy_to_mode_reg (mode0, op0);
4348
4349   pat = GEN_FCN (icode) (target, op0);
4350   if (! pat)
4351     return 0;
4352   emit_insn (pat);
4353   return target;
4354 }
4355
4356 /* Expand an expression EXP that calls a built-in function,
4357    with result going to TARGET if that's convenient
4358    (and in mode MODE if that's convenient).
4359    SUBTARGET may be used as the target for computing one of EXP's operands.
4360    IGNORE is nonzero if the value is to be ignored.  */
4361
4362 static rtx
4363 bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
4364                      rtx subtarget ATTRIBUTE_UNUSED,
4365                      enum machine_mode mode ATTRIBUTE_UNUSED,
4366                      int ignore ATTRIBUTE_UNUSED)
4367 {
4368   size_t i;
4369   enum insn_code icode;
4370   const struct builtin_description *d;
4371   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
4372   tree arglist = TREE_OPERAND (exp, 1);
4373   unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
4374   tree arg0, arg1, arg2;
4375   rtx op0, op1, op2, accvec, pat, tmp1, tmp2;
4376   enum machine_mode tmode, mode0;
4377
4378   switch (fcode)
4379     {
4380     case BFIN_BUILTIN_CSYNC:
4381       emit_insn (gen_csync ());
4382       return 0;
4383     case BFIN_BUILTIN_SSYNC:
4384       emit_insn (gen_ssync ());
4385       return 0;
4386
4387     case BFIN_BUILTIN_DIFFHL_2X16:
4388     case BFIN_BUILTIN_DIFFLH_2X16:
4389       arg0 = TREE_VALUE (arglist);
4390       op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4391       icode = (fcode == BFIN_BUILTIN_DIFFHL_2X16
4392                ? CODE_FOR_subhilov2hi3 : CODE_FOR_sublohiv2hi3);
4393       tmode = insn_data[icode].operand[0].mode;
4394       mode0 = insn_data[icode].operand[1].mode;
4395
4396       if (! target
4397           || GET_MODE (target) != tmode
4398           || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
4399         target = gen_reg_rtx (tmode);
4400
4401       if (VECTOR_MODE_P (mode0))
4402         op0 = safe_vector_operand (op0, mode0);
4403
4404       if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
4405         op0 = copy_to_mode_reg (mode0, op0);
4406
4407       pat = GEN_FCN (icode) (target, op0, op0);
4408       if (! pat)
4409         return 0;
4410       emit_insn (pat);
4411       return target;
4412
4413     case BFIN_BUILTIN_CPLX_MUL_16:
4414       arg0 = TREE_VALUE (arglist);
4415       arg1 = TREE_VALUE (TREE_CHAIN (arglist));
4416       op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4417       op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
4418       accvec = gen_reg_rtx (V2PDImode);
4419
4420       if (! target
4421           || GET_MODE (target) != V2HImode
4422           || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
4423         target = gen_reg_rtx (tmode);
4424       if (! register_operand (op0, GET_MODE (op0)))
4425         op0 = copy_to_mode_reg (GET_MODE (op0), op0);
4426       if (! register_operand (op1, GET_MODE (op1)))
4427         op1 = copy_to_mode_reg (GET_MODE (op1), op1);
4428
4429       emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
4430                                               const0_rtx, const0_rtx,
4431                                               const1_rtx, GEN_INT (MACFLAG_NONE)));
4432       emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
4433                                          const1_rtx, const1_rtx,
4434                                          const0_rtx, accvec, const1_rtx, const0_rtx,
4435                                          GEN_INT (MACFLAG_NONE), accvec));
4436
4437       return target;
4438
4439     case BFIN_BUILTIN_CPLX_MAC_16:
4440     case BFIN_BUILTIN_CPLX_MSU_16:
4441       arg0 = TREE_VALUE (arglist);
4442       arg1 = TREE_VALUE (TREE_CHAIN (arglist));
4443       arg2 = TREE_VALUE (TREE_CHAIN (TREE_CHAIN (arglist)));
4444       op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4445       op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
4446       op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
4447       accvec = gen_reg_rtx (V2PDImode);
4448
4449       if (! target
4450           || GET_MODE (target) != V2HImode
4451           || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
4452         target = gen_reg_rtx (tmode);
4453       if (! register_operand (op0, GET_MODE (op0)))
4454         op0 = copy_to_mode_reg (GET_MODE (op0), op0);
4455       if (! register_operand (op1, GET_MODE (op1)))
4456         op1 = copy_to_mode_reg (GET_MODE (op1), op1);
4457
4458       tmp1 = gen_reg_rtx (SImode);
4459       tmp2 = gen_reg_rtx (SImode);
4460       emit_insn (gen_ashlsi3 (tmp1, gen_lowpart (SImode, op2), GEN_INT (16)));
4461       emit_move_insn (tmp2, gen_lowpart (SImode, op2));
4462       emit_insn (gen_movstricthi_1 (gen_lowpart (HImode, tmp2), const0_rtx));
4463       emit_insn (gen_load_accumulator_pair (accvec, tmp1, tmp2));
4464       emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op0, op1, const0_rtx,
4465                                                  const0_rtx, const0_rtx,
4466                                                  const1_rtx, accvec, const0_rtx,
4467                                                  const0_rtx,
4468                                                  GEN_INT (MACFLAG_W32)));
4469       tmp1 = (fcode == BFIN_BUILTIN_CPLX_MAC_16 ? const1_rtx : const0_rtx);
4470       tmp2 = (fcode == BFIN_BUILTIN_CPLX_MAC_16 ? const0_rtx : const1_rtx);
4471       emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
4472                                          const1_rtx, const1_rtx,
4473                                          const0_rtx, accvec, tmp1, tmp2,
4474                                          GEN_INT (MACFLAG_NONE), accvec));
4475
4476       return target;
4477
4478     default:
4479       break;
4480     }
4481
4482   for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
4483     if (d->code == fcode)
4484       return bfin_expand_binop_builtin (d->icode, arglist, target,
4485                                         d->macflag);
4486
4487   for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
4488     if (d->code == fcode)
4489       return bfin_expand_unop_builtin (d->icode, arglist, target);
4490
4491   gcc_unreachable ();
4492 }
4493 \f
4494 #undef TARGET_INIT_BUILTINS
4495 #define TARGET_INIT_BUILTINS bfin_init_builtins
4496
4497 #undef TARGET_EXPAND_BUILTIN
4498 #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
4499
4500 #undef TARGET_ASM_GLOBALIZE_LABEL
4501 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label 
4502
4503 #undef TARGET_ASM_FILE_START
4504 #define TARGET_ASM_FILE_START output_file_start
4505
4506 #undef TARGET_ATTRIBUTE_TABLE
4507 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
4508
4509 #undef TARGET_COMP_TYPE_ATTRIBUTES
4510 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
4511
4512 #undef TARGET_RTX_COSTS
4513 #define TARGET_RTX_COSTS bfin_rtx_costs
4514
4515 #undef  TARGET_ADDRESS_COST
4516 #define TARGET_ADDRESS_COST bfin_address_cost
4517
4518 #undef TARGET_ASM_INTERNAL_LABEL
4519 #define TARGET_ASM_INTERNAL_LABEL bfin_internal_label
4520
4521 #undef  TARGET_ASM_INTEGER
4522 #define TARGET_ASM_INTEGER bfin_assemble_integer
4523
4524 #undef TARGET_MACHINE_DEPENDENT_REORG
4525 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
4526
4527 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
4528 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
4529
4530 #undef TARGET_ASM_OUTPUT_MI_THUNK
4531 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
4532 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
4533 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
4534
4535 #undef TARGET_SCHED_ADJUST_COST
4536 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
4537
4538 #undef TARGET_SCHED_ISSUE_RATE
4539 #define TARGET_SCHED_ISSUE_RATE bfin_issue_rate
4540
4541 #undef TARGET_PROMOTE_PROTOTYPES
4542 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
4543 #undef TARGET_PROMOTE_FUNCTION_ARGS
4544 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
4545 #undef TARGET_PROMOTE_FUNCTION_RETURN
4546 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
4547
4548 #undef TARGET_ARG_PARTIAL_BYTES
4549 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
4550
4551 #undef TARGET_PASS_BY_REFERENCE
4552 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
4553
4554 #undef TARGET_SETUP_INCOMING_VARARGS
4555 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
4556
4557 #undef TARGET_STRUCT_VALUE_RTX
4558 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
4559
4560 #undef TARGET_VECTOR_MODE_SUPPORTED_P
4561 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
4562
4563 #undef TARGET_HANDLE_OPTION
4564 #define TARGET_HANDLE_OPTION bfin_handle_option
4565
4566 #undef TARGET_DEFAULT_TARGET_FLAGS
4567 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
4568
4569 #undef TARGET_SECONDARY_RELOAD
4570 #define TARGET_SECONDARY_RELOAD bfin_secondary_reload
4571
4572 #undef TARGET_DELEGITIMIZE_ADDRESS
4573 #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address
4574
4575 #undef TARGET_CANNOT_FORCE_CONST_MEM
4576 #define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem
4577
4578 struct gcc_target targetm = TARGET_INITIALIZER;