OSDN Git Service

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