OSDN Git Service

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