OSDN Git Service

f451e910e0e8ce04117c2cde579f19dba43bbe79
[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 "ggc.h"
47 #include "integrate.h"
48 #include "cgraph.h"
49 #include "langhooks.h"
50 #include "bfin-protos.h"
51 #include "tm-preds.h"
52 #include "gt-bfin.h"
53
54 /* Test and compare insns in bfin.md store the information needed to
55    generate branch and scc insns here.  */
56 rtx bfin_compare_op0, bfin_compare_op1;
57
58 /* RTX for condition code flag register and RETS register */
59 extern GTY(()) rtx bfin_cc_rtx;
60 extern GTY(()) rtx bfin_rets_rtx;
61 rtx bfin_cc_rtx, bfin_rets_rtx;
62
63 int max_arg_registers = 0;
64
65 /* Arrays used when emitting register names.  */
66 const char *short_reg_names[]  =  SHORT_REGISTER_NAMES;
67 const char *high_reg_names[]   =  HIGH_REGISTER_NAMES;
68 const char *dregs_pair_names[] =  DREGS_PAIR_NAMES;
69 const char *byte_reg_names[]   =  BYTE_REGISTER_NAMES;
70
71 static int arg_regs[] = FUNCTION_ARG_REGISTERS;
72
73 /* Nonzero if -mshared-library-id was given.  */
74 static int bfin_lib_id_given;
75
76 static void
77 bfin_globalize_label (FILE *stream, const char *name)
78 {
79   fputs (".global ", stream);
80   assemble_name (stream, name);
81   fputc (';',stream);
82   fputc ('\n',stream);
83 }
84
85 static void 
86 output_file_start (void) 
87 {
88   FILE *file = asm_out_file;
89   int i;
90
91   fprintf (file, ".file \"%s\";\n", input_filename);
92   
93   for (i = 0; arg_regs[i] >= 0; i++)
94     ;
95   max_arg_registers = i;        /* how many arg reg used  */
96 }
97
98 /* Called early in the compilation to conditionally modify
99    fixed_regs/call_used_regs.  */
100
101 void 
102 conditional_register_usage (void)
103 {
104   /* initialize condition code flag register rtx */
105   bfin_cc_rtx = gen_rtx_REG (BImode, REG_CC);
106   bfin_rets_rtx = gen_rtx_REG (Pmode, REG_RETS);
107 }
108
109 /* Examine machine-dependent attributes of function type FUNTYPE and return its
110    type.  See the definition of E_FUNKIND.  */
111
112 static e_funkind funkind (tree funtype)
113 {
114   tree attrs = TYPE_ATTRIBUTES (funtype);
115   if (lookup_attribute ("interrupt_handler", attrs))
116     return INTERRUPT_HANDLER;
117   else if (lookup_attribute ("exception_handler", attrs))
118     return EXCPT_HANDLER;
119   else if (lookup_attribute ("nmi_handler", attrs))
120     return NMI_HANDLER;
121   else
122     return SUBROUTINE;
123 }
124 \f
125 /* Legitimize PIC addresses.  If the address is already position-independent,
126    we return ORIG.  Newly generated position-independent addresses go into a
127    reg.  This is REG if nonzero, otherwise we allocate register(s) as
128    necessary.  PICREG is the register holding the pointer to the PIC offset
129    table.  */
130
131 rtx
132 legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
133 {
134   rtx addr = orig;
135   rtx new = orig;
136
137   if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
138     {
139       if (GET_CODE (addr) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (addr))
140         reg = new = orig;
141       else
142         {
143           if (reg == 0)
144             {
145               gcc_assert (!no_new_pseudos);
146               reg = gen_reg_rtx (Pmode);
147             }
148
149           if (flag_pic == 2)
150             {
151               emit_insn (gen_movsi_high_pic (reg, addr));
152               emit_insn (gen_movsi_low_pic (reg, reg, addr));
153               emit_insn (gen_addsi3 (reg, reg, picreg));
154               new = gen_const_mem (Pmode, reg);
155             }
156           else
157             {
158               rtx tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
159                                         UNSPEC_MOVE_PIC);
160               new = gen_const_mem (Pmode,
161                                    gen_rtx_PLUS (Pmode, picreg, tmp));
162             }
163           emit_move_insn (reg, new);
164         }
165       if (picreg == pic_offset_table_rtx)
166         current_function_uses_pic_offset_table = 1;
167       return reg;
168     }
169
170   else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
171     {
172       rtx base;
173
174       if (GET_CODE (addr) == CONST)
175         {
176           addr = XEXP (addr, 0);
177           gcc_assert (GET_CODE (addr) == PLUS);
178         }
179
180       if (XEXP (addr, 0) == picreg)
181         return orig;
182
183       if (reg == 0)
184         {
185           gcc_assert (!no_new_pseudos);
186           reg = gen_reg_rtx (Pmode);
187         }
188
189       base = legitimize_pic_address (XEXP (addr, 0), reg, picreg);
190       addr = legitimize_pic_address (XEXP (addr, 1),
191                                      base == reg ? NULL_RTX : reg,
192                                      picreg);
193
194       if (GET_CODE (addr) == CONST_INT)
195         {
196           gcc_assert (! reload_in_progress && ! reload_completed);
197           addr = force_reg (Pmode, addr);
198         }
199
200       if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
201         {
202           base = gen_rtx_PLUS (Pmode, base, XEXP (addr, 0));
203           addr = XEXP (addr, 1);
204         }
205
206       return gen_rtx_PLUS (Pmode, base, addr);
207     }
208
209   return new;
210 }
211 \f
212 /* Stack frame layout. */
213
214 /* Compute the number of DREGS to save with a push_multiple operation.
215    This could include registers that aren't modified in the function,
216    since push_multiple only takes a range of registers.
217    If IS_INTHANDLER, then everything that is live must be saved, even
218    if normally call-clobbered.  */
219
220 static int
221 n_dregs_to_save (bool is_inthandler)
222 {
223   unsigned i;
224
225   for (i = REG_R0; i <= REG_R7; i++)
226     {
227       if (regs_ever_live[i] && (is_inthandler || ! call_used_regs[i]))
228         return REG_R7 - i + 1;
229
230       if (current_function_calls_eh_return)
231         {
232           unsigned j;
233           for (j = 0; ; j++)
234             {
235               unsigned test = EH_RETURN_DATA_REGNO (j);
236               if (test == INVALID_REGNUM)
237                 break;
238               if (test == i)
239                 return REG_R7 - i + 1;
240             }
241         }
242
243     }
244   return 0;
245 }
246
247 /* Like n_dregs_to_save, but compute number of PREGS to save.  */
248
249 static int
250 n_pregs_to_save (bool is_inthandler)
251 {
252   unsigned i;
253
254   for (i = REG_P0; i <= REG_P5; i++)
255     if ((regs_ever_live[i] && (is_inthandler || ! call_used_regs[i]))
256         || (i == PIC_OFFSET_TABLE_REGNUM
257             && (current_function_uses_pic_offset_table
258                 || (TARGET_ID_SHARED_LIBRARY && ! current_function_is_leaf))))
259       return REG_P5 - i + 1;
260   return 0;
261 }
262
263 /* Determine if we are going to save the frame pointer in the prologue.  */
264
265 static bool
266 must_save_fp_p (void)
267 {
268   return frame_pointer_needed || regs_ever_live[REG_FP];
269 }
270
271 static bool
272 stack_frame_needed_p (void)
273 {
274   /* EH return puts a new return address into the frame using an
275      address relative to the frame pointer.  */
276   if (current_function_calls_eh_return)
277     return true;
278   return frame_pointer_needed;
279 }
280
281 /* Emit code to save registers in the prologue.  SAVEALL is nonzero if we
282    must save all registers; this is used for interrupt handlers.
283    SPREG contains (reg:SI REG_SP).  IS_INTHANDLER is true if we're doing
284    this for an interrupt (or exception) handler.  */
285
286 static void
287 expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler)
288 {
289   int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler);
290   int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler);
291   int dregno = REG_R7 + 1 - ndregs;
292   int pregno = REG_P5 + 1 - npregs;
293   int total = ndregs + npregs;
294   int i;
295   rtx pat, insn, val;
296
297   if (total == 0)
298     return;
299
300   val = GEN_INT (-total * 4);
301   pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total + 2));
302   XVECEXP (pat, 0, 0) = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, val),
303                                         UNSPEC_PUSH_MULTIPLE);
304   XVECEXP (pat, 0, total + 1) = gen_rtx_SET (VOIDmode, spreg,
305                                              gen_rtx_PLUS (Pmode, spreg,
306                                                            val));
307   RTX_FRAME_RELATED_P (XVECEXP (pat, 0, total + 1)) = 1;
308   for (i = 0; i < total; i++)
309     {
310       rtx memref = gen_rtx_MEM (word_mode,
311                                 gen_rtx_PLUS (Pmode, spreg,
312                                               GEN_INT (- i * 4 - 4)));
313       rtx subpat;
314       if (ndregs > 0)
315         {
316           subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
317                                                                dregno++));
318           ndregs--;
319         }
320       else
321         {
322           subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
323                                                                pregno++));
324           npregs++;
325         }
326       XVECEXP (pat, 0, i + 1) = subpat;
327       RTX_FRAME_RELATED_P (subpat) = 1;
328     }
329   insn = emit_insn (pat);
330   RTX_FRAME_RELATED_P (insn) = 1;
331 }
332
333 /* Emit code to restore registers in the epilogue.  SAVEALL is nonzero if we
334    must save all registers; this is used for interrupt handlers.
335    SPREG contains (reg:SI REG_SP).  IS_INTHANDLER is true if we're doing
336    this for an interrupt (or exception) handler.  */
337
338 static void
339 expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler)
340 {
341   int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler);
342   int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler);
343   int total = ndregs + npregs;
344   int i, regno;
345   rtx pat, insn;
346
347   if (total == 0)
348     return;
349
350   pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total + 1));
351   XVECEXP (pat, 0, 0) = gen_rtx_SET (VOIDmode, spreg,
352                                      gen_rtx_PLUS (Pmode, spreg,
353                                                    GEN_INT (total * 4)));
354
355   if (npregs > 0)
356     regno = REG_P5 + 1;
357   else
358     regno = REG_R7 + 1;
359
360   for (i = 0; i < total; i++)
361     {
362       rtx addr = (i > 0
363                   ? gen_rtx_PLUS (Pmode, spreg, GEN_INT (i * 4))
364                   : spreg);
365       rtx memref = gen_rtx_MEM (word_mode, addr);
366
367       regno--;
368       XVECEXP (pat, 0, i + 1)
369         = gen_rtx_SET (VOIDmode, gen_rtx_REG (word_mode, regno), memref);
370
371       if (npregs > 0)
372         {
373           if (--npregs == 0)
374             regno = REG_R7 + 1;
375         }
376     }
377
378   insn = emit_insn (pat);
379   RTX_FRAME_RELATED_P (insn) = 1;
380 }
381
382 /* Perform any needed actions needed for a function that is receiving a
383    variable number of arguments.
384
385    CUM is as above.
386
387    MODE and TYPE are the mode and type of the current parameter.
388
389    PRETEND_SIZE is a variable that should be set to the amount of stack
390    that must be pushed by the prolog to pretend that our caller pushed
391    it.
392
393    Normally, this macro will push all remaining incoming registers on the
394    stack and set PRETEND_SIZE to the length of the registers pushed.  
395
396    Blackfin specific :
397    - VDSP C compiler manual (our ABI) says that a variable args function
398      should save the R0, R1 and R2 registers in the stack.
399    - The caller will always leave space on the stack for the
400      arguments that are passed in registers, so we dont have
401      to leave any extra space.
402    - now, the vastart pointer can access all arguments from the stack.  */
403
404 static void
405 setup_incoming_varargs (CUMULATIVE_ARGS *cum,
406                         enum machine_mode mode ATTRIBUTE_UNUSED,
407                         tree type ATTRIBUTE_UNUSED, int *pretend_size,
408                         int no_rtl)
409 {
410   rtx mem;
411   int i;
412
413   if (no_rtl)
414     return;
415
416   /* The move for named arguments will be generated automatically by the
417      compiler.  We need to generate the move rtx for the unnamed arguments
418      if they are in the first 3 words.  We assume at least 1 named argument
419      exists, so we never generate [ARGP] = R0 here.  */
420
421   for (i = cum->words + 1; i < max_arg_registers; i++)
422     {
423       mem = gen_rtx_MEM (Pmode,
424                          plus_constant (arg_pointer_rtx, (i * UNITS_PER_WORD)));
425       emit_move_insn (mem, gen_rtx_REG (Pmode, i));
426     }
427
428   *pretend_size = 0;
429 }
430
431 /* Value should be nonzero if functions must have frame pointers.
432    Zero means the frame pointer need not be set up (and parms may
433    be accessed via the stack pointer) in functions that seem suitable.  */
434
435 int
436 bfin_frame_pointer_required (void) 
437 {
438   e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
439
440   if (fkind != SUBROUTINE)
441     return 1;
442
443   /* We turn on -fomit-frame-pointer if -momit-leaf-frame-pointer is used,
444      so we have to override it for non-leaf functions.  */
445   if (TARGET_OMIT_LEAF_FRAME_POINTER && ! current_function_is_leaf)
446     return 1;
447
448   return 0;
449 }
450
451 /* Return the number of registers pushed during the prologue.  */
452
453 static int
454 n_regs_saved_by_prologue (void)
455 {
456   e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
457   bool is_inthandler = fkind != SUBROUTINE;
458   tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
459   bool all = (lookup_attribute ("saveall", attrs) != NULL_TREE
460               || (is_inthandler && !current_function_is_leaf));
461   int ndregs = all ? 8 : n_dregs_to_save (is_inthandler);
462   int npregs = all ? 6 : n_pregs_to_save (is_inthandler);  
463   int n = ndregs + npregs;
464
465   if (all || stack_frame_needed_p ())
466     /* We use a LINK instruction in this case.  */
467     n += 2;
468   else
469     {
470       if (must_save_fp_p ())
471         n++;
472       if (! current_function_is_leaf)
473         n++;
474     }
475
476   if (fkind != SUBROUTINE)
477     {
478       int i;
479
480       /* Increment once for ASTAT.  */
481       n++;
482
483       /* RETE/X/N.  */
484       if (lookup_attribute ("nesting", attrs))
485         n++;
486
487       for (i = REG_P7 + 1; i < REG_CC; i++)
488         if (all 
489             || regs_ever_live[i]
490             || (!leaf_function_p () && call_used_regs[i]))
491           n += i == REG_A0 || i == REG_A1 ? 2 : 1;
492     }
493   return n;
494 }
495
496 /* Return the offset between two registers, one to be eliminated, and the other
497    its replacement, at the start of a routine.  */
498
499 HOST_WIDE_INT
500 bfin_initial_elimination_offset (int from, int to)
501 {
502   HOST_WIDE_INT offset = 0;
503
504   if (from == ARG_POINTER_REGNUM)
505     offset = n_regs_saved_by_prologue () * 4;
506
507   if (to == STACK_POINTER_REGNUM)
508     {
509       if (current_function_outgoing_args_size >= FIXED_STACK_AREA)
510         offset += current_function_outgoing_args_size;
511       else if (current_function_outgoing_args_size)
512         offset += FIXED_STACK_AREA;
513
514       offset += get_frame_size ();
515     }
516
517   return offset;
518 }
519
520 /* Emit code to load a constant CONSTANT into register REG; setting
521    RTX_FRAME_RELATED_P on all insns we generate if RELATED is true.
522    Make sure that the insns we generate need not be split.  */
523
524 static void
525 frame_related_constant_load (rtx reg, HOST_WIDE_INT constant, bool related)
526 {
527   rtx insn;
528   rtx cst = GEN_INT (constant);
529
530   if (constant >= -32768 && constant < 65536)
531     insn = emit_move_insn (reg, cst);
532   else
533     {
534       /* We don't call split_load_immediate here, since dwarf2out.c can get
535          confused about some of the more clever sequences it can generate.  */
536       insn = emit_insn (gen_movsi_high (reg, cst));
537       if (related)
538         RTX_FRAME_RELATED_P (insn) = 1;
539       insn = emit_insn (gen_movsi_low (reg, reg, cst));
540     }
541   if (related)
542     RTX_FRAME_RELATED_P (insn) = 1;
543 }
544
545 /* Generate efficient code to add a value to the frame pointer.  We
546    can use P1 as a scratch register.  Set RTX_FRAME_RELATED_P on the
547    generated insns if FRAME is nonzero.  */
548
549 static void
550 add_to_sp (rtx spreg, HOST_WIDE_INT value, int frame)
551 {
552   if (value == 0)
553     return;
554
555   /* Choose whether to use a sequence using a temporary register, or
556      a sequence with multiple adds.  We can add a signed 7 bit value
557      in one instruction.  */
558   if (value > 120 || value < -120)
559     {
560       rtx tmpreg = gen_rtx_REG (SImode, REG_P1);
561       rtx insn;
562
563       if (frame)
564         frame_related_constant_load (tmpreg, value, TRUE);
565       else
566         {
567           insn = emit_move_insn (tmpreg, GEN_INT (value));
568           if (frame)
569             RTX_FRAME_RELATED_P (insn) = 1;
570         }
571
572       insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg));
573       if (frame)
574         RTX_FRAME_RELATED_P (insn) = 1;
575     }
576   else
577     do
578       {
579         int size = value;
580         rtx insn;
581
582         if (size > 60)
583           size = 60;
584         else if (size < -60)
585           /* We could use -62, but that would leave the stack unaligned, so
586              it's no good.  */
587           size = -60;
588
589         insn = emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (size)));
590         if (frame)
591           RTX_FRAME_RELATED_P (insn) = 1;
592         value -= size;
593       }
594     while (value != 0);
595 }
596
597 /* Generate a LINK insn for a frame sized FRAME_SIZE.  If this constant
598    is too large, generate a sequence of insns that has the same effect.
599    SPREG contains (reg:SI REG_SP).  */
600
601 static void
602 emit_link_insn (rtx spreg, HOST_WIDE_INT frame_size)
603 {
604   HOST_WIDE_INT link_size = frame_size;
605   rtx insn;
606   int i;
607
608   if (link_size > 262140)
609     link_size = 262140;
610
611   /* Use a LINK insn with as big a constant as possible, then subtract
612      any remaining size from the SP.  */
613   insn = emit_insn (gen_link (GEN_INT (-8 - link_size)));
614   RTX_FRAME_RELATED_P (insn) = 1;
615
616   for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
617     {
618       rtx set = XVECEXP (PATTERN (insn), 0, i);
619       gcc_assert (GET_CODE (set) == SET);
620       RTX_FRAME_RELATED_P (set) = 1;
621     }
622
623   frame_size -= link_size;
624
625   if (frame_size > 0)
626     {
627       /* Must use a call-clobbered PREG that isn't the static chain.  */
628       rtx tmpreg = gen_rtx_REG (Pmode, REG_P1);
629
630       frame_related_constant_load (tmpreg, -frame_size, TRUE);
631       insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg));
632       RTX_FRAME_RELATED_P (insn) = 1;
633     }
634 }
635
636 /* Return the number of bytes we must reserve for outgoing arguments
637    in the current function's stack frame.  */
638
639 static HOST_WIDE_INT
640 arg_area_size (void)
641 {
642   if (current_function_outgoing_args_size)
643     {
644       if (current_function_outgoing_args_size >= FIXED_STACK_AREA)
645         return current_function_outgoing_args_size;
646       else
647         return FIXED_STACK_AREA;
648     }
649   return 0;
650 }
651
652 /* Save RETS and FP, and allocate a stack frame.  ALL is true if the
653    function must save all its registers (true only for certain interrupt
654    handlers).  */
655
656 static void
657 do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all)
658 {
659   frame_size += arg_area_size ();
660
661   if (all || stack_frame_needed_p ()
662       || (must_save_fp_p () && ! current_function_is_leaf))
663     emit_link_insn (spreg, frame_size);
664   else
665     {
666       if (! current_function_is_leaf)
667         {
668           rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
669                                             gen_rtx_PRE_DEC (Pmode, spreg)),
670                                bfin_rets_rtx);
671           rtx insn = emit_insn (pat);
672           RTX_FRAME_RELATED_P (insn) = 1;
673         }
674       if (must_save_fp_p ())
675         {
676           rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
677                                             gen_rtx_PRE_DEC (Pmode, spreg)),
678                                gen_rtx_REG (Pmode, REG_FP));
679           rtx insn = emit_insn (pat);
680           RTX_FRAME_RELATED_P (insn) = 1;
681         }
682       add_to_sp (spreg, -frame_size, 1);
683     }
684 }
685
686 /* Like do_link, but used for epilogues to deallocate the stack frame.  */
687
688 static void
689 do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all)
690 {
691   frame_size += arg_area_size ();
692
693   if (all || stack_frame_needed_p ())
694     emit_insn (gen_unlink ());
695   else 
696     {
697       rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg));
698
699       add_to_sp (spreg, frame_size, 0);
700       if (must_save_fp_p ())
701         {
702           rtx fpreg = gen_rtx_REG (Pmode, REG_FP);
703           emit_move_insn (fpreg, postinc);
704           emit_insn (gen_rtx_USE (VOIDmode, fpreg));
705         }
706       if (! current_function_is_leaf)
707         {
708           emit_move_insn (bfin_rets_rtx, postinc);
709           emit_insn (gen_rtx_USE (VOIDmode, bfin_rets_rtx));
710         }
711     }
712 }
713
714 /* Generate a prologue suitable for a function of kind FKIND.  This is
715    called for interrupt and exception handler prologues.
716    SPREG contains (reg:SI REG_SP).  */
717
718 static void
719 expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind)
720 {
721   int i;
722   HOST_WIDE_INT frame_size = get_frame_size ();
723   rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
724   rtx predec = gen_rtx_MEM (SImode, predec1);
725   rtx insn;
726   tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
727   bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
728   tree kspisusp = lookup_attribute ("kspisusp", attrs);
729
730   if (kspisusp)
731     {
732       insn = emit_move_insn (spreg, gen_rtx_REG (Pmode, REG_USP));
733       RTX_FRAME_RELATED_P (insn) = 1;
734     }
735
736   /* We need space on the stack in case we need to save the argument
737      registers.  */
738   if (fkind == EXCPT_HANDLER)
739     {
740       insn = emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (-12)));
741       RTX_FRAME_RELATED_P (insn) = 1;
742     }
743
744   insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
745   RTX_FRAME_RELATED_P (insn) = 1;
746
747   /* If we're calling other functions, they won't save their call-clobbered
748      registers, so we must save everything here.  */
749   if (!current_function_is_leaf)
750     all = true;
751   expand_prologue_reg_save (spreg, all, true);
752
753   for (i = REG_P7 + 1; i < REG_CC; i++)
754     if (all 
755         || regs_ever_live[i]
756         || (!leaf_function_p () && call_used_regs[i]))
757       {
758         if (i == REG_A0 || i == REG_A1)
759           insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1),
760                                  gen_rtx_REG (PDImode, i));
761         else
762           insn = emit_move_insn (predec, gen_rtx_REG (SImode, i));
763         RTX_FRAME_RELATED_P (insn) = 1;
764       }
765
766   if (lookup_attribute ("nesting", attrs))
767     {
768       rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
769                                         : fkind == NMI_HANDLER ? REG_RETN
770                                         : REG_RETI));
771       insn = emit_move_insn (predec, srcreg);
772       RTX_FRAME_RELATED_P (insn) = 1;
773     }
774
775   do_link (spreg, frame_size, all);
776
777   if (fkind == EXCPT_HANDLER)
778     {
779       rtx r0reg = gen_rtx_REG (SImode, REG_R0);
780       rtx r1reg = gen_rtx_REG (SImode, REG_R1);
781       rtx r2reg = gen_rtx_REG (SImode, REG_R2);
782       rtx insn;
783
784       insn = emit_move_insn (r0reg, gen_rtx_REG (SImode, REG_SEQSTAT));
785       REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
786                                             NULL_RTX);
787       insn = emit_insn (gen_ashrsi3 (r0reg, r0reg, GEN_INT (26)));
788       REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
789                                             NULL_RTX);
790       insn = emit_insn (gen_ashlsi3 (r0reg, r0reg, GEN_INT (26)));
791       REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
792                                             NULL_RTX);
793       insn = emit_move_insn (r1reg, spreg);
794       REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
795                                             NULL_RTX);
796       insn = emit_move_insn (r2reg, gen_rtx_REG (Pmode, REG_FP));
797       REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
798                                             NULL_RTX);
799       insn = emit_insn (gen_addsi3 (r2reg, r2reg, GEN_INT (8)));
800       REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
801                                             NULL_RTX);
802     }
803 }
804
805 /* Generate an epilogue suitable for a function of kind FKIND.  This is
806    called for interrupt and exception handler epilogues.
807    SPREG contains (reg:SI REG_SP).  */
808
809 static void
810 expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind)
811 {
812   int i;
813   rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
814   rtx postinc = gen_rtx_MEM (SImode, postinc1);
815   tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
816   bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
817
818   /* A slightly crude technique to stop flow from trying to delete "dead"
819      insns.  */
820   MEM_VOLATILE_P (postinc) = 1;
821
822   do_unlink (spreg, get_frame_size (), all);
823
824   if (lookup_attribute ("nesting", attrs))
825     {
826       rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
827                                         : fkind == NMI_HANDLER ? REG_RETN
828                                         : REG_RETI));
829       emit_move_insn (srcreg, postinc);
830     }
831
832   /* If we're calling other functions, they won't save their call-clobbered
833      registers, so we must save (and restore) everything here.  */
834   if (!current_function_is_leaf)
835     all = true;
836
837   for (i = REG_CC - 1; i > REG_P7; i--)
838     if (all
839         || regs_ever_live[i]
840         || (!leaf_function_p () && call_used_regs[i]))
841       {
842         if (i == REG_A0 || i == REG_A1)
843           {
844             rtx mem = gen_rtx_MEM (PDImode, postinc1);
845             MEM_VOLATILE_P (mem) = 1;
846             emit_move_insn (gen_rtx_REG (PDImode, i), mem);
847           }
848         else
849           emit_move_insn (gen_rtx_REG (SImode, i), postinc);
850       }
851
852   expand_epilogue_reg_restore (spreg, all, true);
853
854   emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
855
856   /* Deallocate any space we left on the stack in case we needed to save the
857      argument registers.  */
858   if (fkind == EXCPT_HANDLER)
859     emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (12)));
860
861   emit_jump_insn (gen_return_internal (GEN_INT (fkind)));
862 }
863
864 /* Used while emitting the prologue to generate code to load the correct value
865    into the PIC register, which is passed in DEST.  */
866
867 static rtx
868 bfin_load_pic_reg (rtx dest)
869 {
870   struct cgraph_local_info *i = NULL;
871   rtx addr, insn;
872  
873   if (flag_unit_at_a_time)
874     i = cgraph_local_info (current_function_decl);
875  
876   /* Functions local to the translation unit don't need to reload the
877      pic reg, since the caller always passes a usable one.  */
878   if (i && i->local)
879     return pic_offset_table_rtx;
880       
881   if (bfin_lib_id_given)
882     addr = plus_constant (pic_offset_table_rtx, -4 - bfin_library_id * 4);
883   else
884     addr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
885                          gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
886                                          UNSPEC_LIBRARY_OFFSET));
887   insn = emit_insn (gen_movsi (dest, gen_rtx_MEM (Pmode, addr)));
888   REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
889   return dest;
890 }
891
892 /* Generate RTL for the prologue of the current function.  */
893
894 void
895 bfin_expand_prologue (void)
896 {
897   rtx insn;
898   HOST_WIDE_INT frame_size = get_frame_size ();
899   rtx spreg = gen_rtx_REG (Pmode, REG_SP);
900   e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
901   rtx pic_reg_loaded = NULL_RTX;
902
903   if (fkind != SUBROUTINE)
904     {
905       expand_interrupt_handler_prologue (spreg, fkind);
906       return;
907     }
908
909   if (current_function_limit_stack)
910     {
911       HOST_WIDE_INT offset
912         = bfin_initial_elimination_offset (ARG_POINTER_REGNUM,
913                                            STACK_POINTER_REGNUM);
914       rtx lim = stack_limit_rtx;
915
916       if (GET_CODE (lim) == SYMBOL_REF)
917         {
918           rtx p2reg = gen_rtx_REG (Pmode, REG_P2);
919           if (TARGET_ID_SHARED_LIBRARY)
920             {
921               rtx p1reg = gen_rtx_REG (Pmode, REG_P1);
922               rtx val;
923               pic_reg_loaded = bfin_load_pic_reg (p2reg);
924               val = legitimize_pic_address (stack_limit_rtx, p1reg,
925                                             pic_reg_loaded);
926               emit_move_insn (p1reg, val);
927               frame_related_constant_load (p2reg, offset, FALSE);
928               emit_insn (gen_addsi3 (p2reg, p2reg, p1reg));
929               lim = p2reg;
930             }
931           else
932             {
933               rtx limit = plus_constant (stack_limit_rtx, offset);
934               emit_move_insn (p2reg, limit);
935               lim = p2reg;
936             }
937         }
938       emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim));
939       emit_insn (gen_trapifcc ());
940     }
941   expand_prologue_reg_save (spreg, 0, false);
942
943   do_link (spreg, frame_size, false);
944
945   if (TARGET_ID_SHARED_LIBRARY
946       && (current_function_uses_pic_offset_table
947           || !current_function_is_leaf))
948     bfin_load_pic_reg (pic_offset_table_rtx);
949 }
950
951 /* Generate RTL for the epilogue of the current function.  NEED_RETURN is zero
952    if this is for a sibcall.  EH_RETURN is nonzero if we're expanding an
953    eh_return pattern.  */
954
955 void
956 bfin_expand_epilogue (int need_return, int eh_return)
957 {
958   rtx spreg = gen_rtx_REG (Pmode, REG_SP);
959   e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
960
961   if (fkind != SUBROUTINE)
962     {
963       expand_interrupt_handler_epilogue (spreg, fkind);
964       return;
965     }
966
967   do_unlink (spreg, get_frame_size (), false);
968
969   expand_epilogue_reg_restore (spreg, false, false);
970
971   /* Omit the return insn if this is for a sibcall.  */
972   if (! need_return)
973     return;
974
975   if (eh_return)
976     emit_insn (gen_addsi3 (spreg, spreg, gen_rtx_REG (Pmode, REG_P2)));
977
978   emit_jump_insn (gen_return_internal (GEN_INT (SUBROUTINE)));
979 }
980 \f
981 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG.  */
982
983 int
984 bfin_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
985                            unsigned int new_reg)
986 {
987   /* Interrupt functions can only use registers that have already been
988      saved by the prologue, even if they would normally be
989      call-clobbered.  */
990
991   if (funkind (TREE_TYPE (current_function_decl)) != SUBROUTINE
992       && !regs_ever_live[new_reg])
993     return 0;
994
995   return 1;
996 }
997
998 /* Return the value of the return address for the frame COUNT steps up
999    from the current frame, after the prologue.
1000    We punt for everything but the current frame by returning const0_rtx.  */
1001
1002 rtx
1003 bfin_return_addr_rtx (int count)
1004 {
1005   if (count != 0)
1006     return const0_rtx;
1007
1008   return get_hard_reg_initial_val (Pmode, REG_RETS);
1009 }
1010
1011 /* Try machine-dependent ways of modifying an illegitimate address X
1012    to be legitimate.  If we find one, return the new, valid address,
1013    otherwise return NULL_RTX.
1014
1015    OLDX is the address as it was before break_out_memory_refs was called.
1016    In some cases it is useful to look at this to decide what needs to be done.
1017
1018    MODE is the mode of the memory reference.  */
1019
1020 rtx
1021 legitimize_address (rtx x ATTRIBUTE_UNUSED, rtx oldx ATTRIBUTE_UNUSED,
1022                     enum machine_mode mode ATTRIBUTE_UNUSED)
1023 {
1024   return NULL_RTX;
1025 }
1026
1027 /* This predicate is used to compute the length of a load/store insn.
1028    OP is a MEM rtx, we return nonzero if its addressing mode requires a
1029    32 bit instruction.  */
1030
1031 int
1032 effective_address_32bit_p (rtx op, enum machine_mode mode) 
1033 {
1034   HOST_WIDE_INT offset;
1035
1036   mode = GET_MODE (op);
1037   op = XEXP (op, 0);
1038
1039   if (GET_CODE (op) != PLUS)
1040     {
1041       gcc_assert (REG_P (op) || GET_CODE (op) == POST_INC
1042                   || GET_CODE (op) == PRE_DEC || GET_CODE (op) == POST_DEC);
1043       return 0;
1044     }
1045
1046   offset = INTVAL (XEXP (op, 1));
1047
1048   /* All byte loads use a 16 bit offset.  */
1049   if (GET_MODE_SIZE (mode) == 1)
1050     return 1;
1051
1052   if (GET_MODE_SIZE (mode) == 4)
1053     {
1054       /* Frame pointer relative loads can use a negative offset, all others
1055          are restricted to a small positive one.  */
1056       if (XEXP (op, 0) == frame_pointer_rtx)
1057         return offset < -128 || offset > 60;
1058       return offset < 0 || offset > 60;
1059     }
1060
1061   /* Must be HImode now.  */
1062   return offset < 0 || offset > 30;
1063 }
1064
1065 /* Returns true if X is a memory reference using an I register.  */
1066 bool
1067 bfin_dsp_memref_p (rtx x)
1068 {
1069   if (! MEM_P (x))
1070     return false;
1071   x = XEXP (x, 0);
1072   if (GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_INC
1073       || GET_CODE (x) == POST_DEC || GET_CODE (x) == PRE_DEC)
1074     x = XEXP (x, 0);
1075   return IREG_P (x);
1076 }
1077
1078 /* Return cost of the memory address ADDR.
1079    All addressing modes are equally cheap on the Blackfin.  */
1080
1081 static int
1082 bfin_address_cost (rtx addr ATTRIBUTE_UNUSED)
1083 {
1084   return 1;
1085 }
1086
1087 /* Subroutine of print_operand; used to print a memory reference X to FILE.  */
1088
1089 void
1090 print_address_operand (FILE *file, rtx x)
1091 {
1092   switch (GET_CODE (x))
1093     {
1094     case PLUS:
1095       output_address (XEXP (x, 0));
1096       fprintf (file, "+");
1097       output_address (XEXP (x, 1));
1098       break;
1099
1100     case PRE_DEC:
1101       fprintf (file, "--");
1102       output_address (XEXP (x, 0));    
1103       break;
1104     case POST_INC:
1105       output_address (XEXP (x, 0));
1106       fprintf (file, "++");
1107       break;
1108     case POST_DEC:
1109       output_address (XEXP (x, 0));
1110       fprintf (file, "--");
1111       break;
1112
1113     default:
1114       gcc_assert (GET_CODE (x) != MEM);
1115       print_operand (file, x, 0);
1116       break;
1117     }
1118 }
1119
1120 /* Adding intp DImode support by Tony
1121  * -- Q: (low  word)
1122  * -- R: (high word)
1123  */
1124
1125 void
1126 print_operand (FILE *file, rtx x, char code)
1127 {
1128   enum machine_mode mode = GET_MODE (x);
1129
1130   switch (code)
1131     {
1132     case 'j':
1133       switch (GET_CODE (x))
1134         {
1135         case EQ:
1136           fprintf (file, "e");
1137           break;
1138         case NE:
1139           fprintf (file, "ne");
1140           break;
1141         case GT:
1142           fprintf (file, "g");
1143           break;
1144         case LT:
1145           fprintf (file, "l");
1146           break;
1147         case GE:
1148           fprintf (file, "ge");
1149           break;
1150         case LE:
1151           fprintf (file, "le");
1152           break;
1153         case GTU:
1154           fprintf (file, "g");
1155           break;
1156         case LTU:
1157           fprintf (file, "l");
1158           break;
1159         case GEU:
1160           fprintf (file, "ge");
1161           break;
1162         case LEU:
1163           fprintf (file, "le");
1164           break;
1165         default:
1166           output_operand_lossage ("invalid %%j value");
1167         }
1168       break;
1169     
1170     case 'J':                                    /* reverse logic */
1171       switch (GET_CODE(x))
1172         {
1173         case EQ:
1174           fprintf (file, "ne");
1175           break;
1176         case NE:
1177           fprintf (file, "e");
1178           break;
1179         case GT:
1180           fprintf (file, "le");
1181           break;
1182         case LT:
1183           fprintf (file, "ge");
1184           break;
1185         case GE:
1186           fprintf (file, "l");
1187           break;
1188         case LE:
1189           fprintf (file, "g");
1190           break;
1191         case GTU:
1192           fprintf (file, "le");
1193           break;
1194         case LTU:
1195           fprintf (file, "ge");
1196           break;
1197         case GEU:
1198           fprintf (file, "l");
1199           break;
1200         case LEU:
1201           fprintf (file, "g");
1202           break;
1203         default:
1204           output_operand_lossage ("invalid %%J value");
1205         }
1206       break;
1207
1208     default:
1209       switch (GET_CODE (x))
1210         {
1211         case REG:
1212           if (code == 'h')
1213             {
1214               gcc_assert (REGNO (x) < 32);
1215               fprintf (file, "%s", short_reg_names[REGNO (x)]);
1216               /*fprintf (file, "\n%d\n ", REGNO (x));*/
1217               break;
1218             }
1219           else if (code == 'd')
1220             {
1221               gcc_assert (REGNO (x) < 32);
1222               fprintf (file, "%s", high_reg_names[REGNO (x)]);
1223               break;
1224             }
1225           else if (code == 'w')
1226             {
1227               gcc_assert (REGNO (x) == REG_A0 || REGNO (x) == REG_A1);
1228               fprintf (file, "%s.w", reg_names[REGNO (x)]);
1229             }
1230           else if (code == 'x')
1231             {
1232               gcc_assert (REGNO (x) == REG_A0 || REGNO (x) == REG_A1);
1233               fprintf (file, "%s.x", reg_names[REGNO (x)]);
1234             }
1235           else if (code == 'D')
1236             {
1237               fprintf (file, "%s", dregs_pair_names[REGNO (x)]);
1238             }
1239           else if (code == 'H')
1240             {
1241               gcc_assert (mode == DImode || mode == DFmode);
1242               gcc_assert (REG_P (x));
1243               fprintf (file, "%s", reg_names[REGNO (x) + 1]);
1244             }
1245           else if (code == 'T')
1246             {
1247               gcc_assert (D_REGNO_P (REGNO (x)));
1248               fprintf (file, "%s", byte_reg_names[REGNO (x)]);
1249             }
1250           else 
1251             fprintf (file, "%s", reg_names[REGNO (x)]);
1252           break;
1253
1254         case MEM:
1255           fputc ('[', file);
1256           x = XEXP (x,0);
1257           print_address_operand (file, x);
1258           fputc (']', file);
1259           break;
1260
1261         case CONST_INT:
1262           if (code == 'M')
1263             {
1264               switch (INTVAL (x))
1265                 {
1266                 case MACFLAG_NONE:
1267                   break;
1268                 case MACFLAG_FU:
1269                   fputs ("(FU)", file);
1270                   break;
1271                 case MACFLAG_T:
1272                   fputs ("(T)", file);
1273                   break;
1274                 case MACFLAG_TFU:
1275                   fputs ("(TFU)", file);
1276                   break;
1277                 case MACFLAG_W32:
1278                   fputs ("(W32)", file);
1279                   break;
1280                 case MACFLAG_IS:
1281                   fputs ("(IS)", file);
1282                   break;
1283                 case MACFLAG_IU:
1284                   fputs ("(IU)", file);
1285                   break;
1286                 case MACFLAG_IH:
1287                   fputs ("(IH)", file);
1288                   break;
1289                 case MACFLAG_M:
1290                   fputs ("(M)", file);
1291                   break;
1292                 case MACFLAG_ISS2:
1293                   fputs ("(ISS2)", file);
1294                   break;
1295                 case MACFLAG_S2RND:
1296                   fputs ("(S2RND)", file);
1297                   break;
1298                 default:
1299                   gcc_unreachable ();
1300                 }
1301               break;
1302             }
1303           else if (code == 'b')
1304             {
1305               if (INTVAL (x) == 0)
1306                 fputs ("+=", file);
1307               else if (INTVAL (x) == 1)
1308                 fputs ("-=", file);
1309               else
1310                 gcc_unreachable ();
1311               break;
1312             }
1313           /* Moves to half registers with d or h modifiers always use unsigned
1314              constants.  */
1315           else if (code == 'd')
1316             x = GEN_INT ((INTVAL (x) >> 16) & 0xffff);
1317           else if (code == 'h')
1318             x = GEN_INT (INTVAL (x) & 0xffff);
1319           else if (code == 'X')
1320             x = GEN_INT (exact_log2 (0xffffffff & INTVAL (x)));
1321           else if (code == 'Y')
1322             x = GEN_INT (exact_log2 (0xffffffff & ~INTVAL (x)));
1323           else if (code == 'Z')
1324             /* Used for LINK insns.  */
1325             x = GEN_INT (-8 - INTVAL (x));
1326
1327           /* fall through */
1328
1329         case SYMBOL_REF:
1330           output_addr_const (file, x);
1331           break;
1332
1333         case CONST_DOUBLE:
1334           output_operand_lossage ("invalid const_double operand");
1335           break;
1336
1337         case UNSPEC:
1338           switch (XINT (x, 1))
1339             {
1340             case UNSPEC_MOVE_PIC:
1341               output_addr_const (file, XVECEXP (x, 0, 0));
1342               fprintf (file, "@GOT");
1343               break;
1344
1345             case UNSPEC_LIBRARY_OFFSET:
1346               fprintf (file, "_current_shared_library_p5_offset_");
1347               break;
1348
1349             default:
1350               gcc_unreachable ();
1351             }
1352           break;
1353
1354         default:
1355           output_addr_const (file, x);
1356         }
1357     }
1358 }
1359 \f
1360 /* Argument support functions.  */
1361
1362 /* Initialize a variable CUM of type CUMULATIVE_ARGS
1363    for a call to a function whose data type is FNTYPE.
1364    For a library call, FNTYPE is 0.  
1365    VDSP C Compiler manual, our ABI says that
1366    first 3 words of arguments will use R0, R1 and R2.
1367 */
1368
1369 void
1370 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
1371                       rtx libname ATTRIBUTE_UNUSED)
1372 {
1373   static CUMULATIVE_ARGS zero_cum;
1374
1375   *cum = zero_cum;
1376
1377   /* Set up the number of registers to use for passing arguments.  */
1378
1379   cum->nregs = max_arg_registers;
1380   cum->arg_regs = arg_regs;
1381
1382   cum->call_cookie = CALL_NORMAL;
1383   /* Check for a longcall attribute.  */
1384   if (fntype && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype)))
1385     cum->call_cookie |= CALL_SHORT;
1386   else if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)))
1387     cum->call_cookie |= CALL_LONG;
1388
1389   return;
1390 }
1391
1392 /* Update the data in CUM to advance over an argument
1393    of mode MODE and data type TYPE.
1394    (TYPE is null for libcalls where that information may not be available.)  */
1395
1396 void
1397 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1398                       int named ATTRIBUTE_UNUSED)
1399 {
1400   int count, bytes, words;
1401
1402   bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1403   words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1404
1405   cum->words += words;
1406   cum->nregs -= words;
1407
1408   if (cum->nregs <= 0)
1409     {
1410       cum->nregs = 0;
1411       cum->arg_regs = NULL;
1412     }
1413   else
1414     {
1415       for (count = 1; count <= words; count++)
1416         cum->arg_regs++;
1417     }
1418
1419   return;
1420 }
1421
1422 /* Define where to put the arguments to a function.
1423    Value is zero to push the argument on the stack,
1424    or a hard register in which to store the argument.
1425
1426    MODE is the argument's machine mode.
1427    TYPE is the data type of the argument (as a tree).
1428     This is null for libcalls where that information may
1429     not be available.
1430    CUM is a variable of type CUMULATIVE_ARGS which gives info about
1431     the preceding args and about the function being called.
1432    NAMED is nonzero if this argument is a named parameter
1433     (otherwise it is an extra parameter matching an ellipsis).  */
1434
1435 struct rtx_def *
1436 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1437               int named ATTRIBUTE_UNUSED)
1438 {
1439   int bytes
1440     = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1441
1442   if (mode == VOIDmode)
1443     /* Compute operand 2 of the call insn.  */
1444     return GEN_INT (cum->call_cookie);
1445
1446   if (bytes == -1)
1447     return NULL_RTX;
1448
1449   if (cum->nregs)
1450     return gen_rtx_REG (mode, *(cum->arg_regs));
1451
1452   return NULL_RTX;
1453 }
1454
1455 /* For an arg passed partly in registers and partly in memory,
1456    this is the number of bytes passed in registers.
1457    For args passed entirely in registers or entirely in memory, zero.
1458
1459    Refer VDSP C Compiler manual, our ABI.
1460    First 3 words are in registers. So, if a an argument is larger
1461    than the registers available, it will span the register and
1462    stack.   */
1463
1464 static int
1465 bfin_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1466                         tree type ATTRIBUTE_UNUSED,
1467                         bool named ATTRIBUTE_UNUSED)
1468 {
1469   int bytes
1470     = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1471   int bytes_left = cum->nregs * UNITS_PER_WORD;
1472   
1473   if (bytes == -1)
1474     return 0;
1475
1476   if (bytes_left == 0)
1477     return 0;
1478   if (bytes > bytes_left)
1479     return bytes_left;
1480   return 0;
1481 }
1482
1483 /* Variable sized types are passed by reference.  */
1484
1485 static bool
1486 bfin_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
1487                         enum machine_mode mode ATTRIBUTE_UNUSED,
1488                         tree type, bool named ATTRIBUTE_UNUSED)
1489 {
1490   return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
1491 }
1492
1493 /* Decide whether a type should be returned in memory (true)
1494    or in a register (false).  This is called by the macro
1495    RETURN_IN_MEMORY.  */
1496
1497 int
1498 bfin_return_in_memory (tree type)
1499 {
1500   int size = int_size_in_bytes (type);
1501   return size > 2 * UNITS_PER_WORD || size == -1;
1502 }
1503
1504 /* Register in which address to store a structure value
1505    is passed to a function.  */
1506 static rtx
1507 bfin_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
1508                       int incoming ATTRIBUTE_UNUSED)
1509 {
1510   return gen_rtx_REG (Pmode, REG_P0);
1511 }
1512
1513 /* Return true when register may be used to pass function parameters.  */
1514
1515 bool 
1516 function_arg_regno_p (int n)
1517 {
1518   int i;
1519   for (i = 0; arg_regs[i] != -1; i++)
1520     if (n == arg_regs[i])
1521       return true;
1522   return false;
1523 }
1524
1525 /* Returns 1 if OP contains a symbol reference */
1526
1527 int
1528 symbolic_reference_mentioned_p (rtx op)
1529 {
1530   register const char *fmt;
1531   register int i;
1532
1533   if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
1534     return 1;
1535
1536   fmt = GET_RTX_FORMAT (GET_CODE (op));
1537   for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
1538     {
1539       if (fmt[i] == 'E')
1540         {
1541           register int j;
1542
1543           for (j = XVECLEN (op, i) - 1; j >= 0; j--)
1544             if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
1545               return 1;
1546         }
1547
1548       else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
1549         return 1;
1550     }
1551
1552   return 0;
1553 }
1554
1555 /* Decide whether we can make a sibling call to a function.  DECL is the
1556    declaration of the function being targeted by the call and EXP is the
1557    CALL_EXPR representing the call.  */
1558
1559 static bool
1560 bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
1561                               tree exp ATTRIBUTE_UNUSED)
1562 {
1563   e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1564   return fkind == SUBROUTINE;
1565 }
1566 \f
1567 /* Emit RTL insns to initialize the variable parts of a trampoline at
1568    TRAMP. FNADDR is an RTX for the address of the function's pure
1569    code.  CXT is an RTX for the static chain value for the function.  */
1570
1571 void
1572 initialize_trampoline (tramp, fnaddr, cxt)
1573      rtx tramp, fnaddr, cxt;
1574 {
1575   rtx t1 = copy_to_reg (fnaddr);
1576   rtx t2 = copy_to_reg (cxt);
1577   rtx addr;
1578
1579   addr = memory_address (Pmode, plus_constant (tramp, 2));
1580   emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
1581   emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16)));
1582   addr = memory_address (Pmode, plus_constant (tramp, 6));
1583   emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
1584
1585   addr = memory_address (Pmode, plus_constant (tramp, 10));
1586   emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
1587   emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16)));
1588   addr = memory_address (Pmode, plus_constant (tramp, 14));
1589   emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
1590 }
1591
1592 /* Emit insns to move operands[1] into operands[0].  */
1593
1594 void
1595 emit_pic_move (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
1596 {
1597   rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
1598
1599   if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
1600     operands[1] = force_reg (SImode, operands[1]);
1601   else
1602     operands[1] = legitimize_pic_address (operands[1], temp,
1603                                           pic_offset_table_rtx);
1604 }
1605
1606 /* Expand a move operation in mode MODE.  The operands are in OPERANDS.  */
1607
1608 void
1609 expand_move (rtx *operands, enum machine_mode mode)
1610 {
1611   if (flag_pic && SYMBOLIC_CONST (operands[1]))
1612     emit_pic_move (operands, mode);
1613
1614   /* Don't generate memory->memory or constant->memory moves, go through a
1615      register */
1616   else if ((reload_in_progress | reload_completed) == 0
1617            && GET_CODE (operands[0]) == MEM
1618            && GET_CODE (operands[1]) != REG)
1619     operands[1] = force_reg (mode, operands[1]);
1620 }
1621 \f
1622 /* Split one or more DImode RTL references into pairs of SImode
1623    references.  The RTL can be REG, offsettable MEM, integer constant, or
1624    CONST_DOUBLE.  "operands" is a pointer to an array of DImode RTL to
1625    split and "num" is its length.  lo_half and hi_half are output arrays
1626    that parallel "operands".  */
1627
1628 void
1629 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
1630 {
1631   while (num--)
1632     {
1633       rtx op = operands[num];
1634
1635       /* simplify_subreg refuse to split volatile memory addresses,
1636          but we still have to handle it.  */
1637       if (GET_CODE (op) == MEM)
1638         {
1639           lo_half[num] = adjust_address (op, SImode, 0);
1640           hi_half[num] = adjust_address (op, SImode, 4);
1641         }
1642       else
1643         {
1644           lo_half[num] = simplify_gen_subreg (SImode, op,
1645                                               GET_MODE (op) == VOIDmode
1646                                               ? DImode : GET_MODE (op), 0);
1647           hi_half[num] = simplify_gen_subreg (SImode, op,
1648                                               GET_MODE (op) == VOIDmode
1649                                               ? DImode : GET_MODE (op), 4);
1650         }
1651     }
1652 }
1653 \f
1654 bool
1655 bfin_longcall_p (rtx op, int call_cookie)
1656 {
1657   gcc_assert (GET_CODE (op) == SYMBOL_REF);
1658   if (call_cookie & CALL_SHORT)
1659     return 0;
1660   if (call_cookie & CALL_LONG)
1661     return 1;
1662   if (TARGET_LONG_CALLS)
1663     return 1;
1664   return 0;
1665 }
1666
1667 /* Expand a call instruction.  FNADDR is the call target, RETVAL the return value.
1668    COOKIE is a CONST_INT holding the call_cookie prepared init_cumulative_args.
1669    SIBCALL is nonzero if this is a sibling call.  */
1670
1671 void
1672 bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
1673 {
1674   rtx use = NULL, call;
1675   rtx callee = XEXP (fnaddr, 0);
1676   rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (sibcall ? 3 : 2));
1677
1678   /* In an untyped call, we can get NULL for operand 2.  */
1679   if (cookie == NULL_RTX)
1680     cookie = const0_rtx;
1681
1682   /* Static functions and indirect calls don't need the pic register.  */
1683   if (flag_pic
1684       && GET_CODE (callee) == SYMBOL_REF
1685       && !SYMBOL_REF_LOCAL_P (callee))
1686     use_reg (&use, pic_offset_table_rtx);
1687
1688   if ((!register_no_elim_operand (callee, Pmode)
1689        && GET_CODE (callee) != SYMBOL_REF)
1690       || (GET_CODE (callee) == SYMBOL_REF
1691           && (flag_pic
1692               || bfin_longcall_p (callee, INTVAL (cookie)))))
1693     {
1694       callee = copy_to_mode_reg (Pmode, callee);
1695       fnaddr = gen_rtx_MEM (Pmode, callee);
1696     }
1697   call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
1698
1699   if (retval)
1700     call = gen_rtx_SET (VOIDmode, retval, call);
1701
1702   XVECEXP (pat, 0, 0) = call;
1703   XVECEXP (pat, 0, 1) = gen_rtx_USE (VOIDmode, cookie);
1704   if (sibcall)
1705     XVECEXP (pat, 0, 2) = gen_rtx_RETURN (VOIDmode);
1706   call = emit_call_insn (pat);
1707   if (use)
1708     CALL_INSN_FUNCTION_USAGE (call) = use;
1709 }
1710 \f
1711 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE.  */
1712
1713 int
1714 hard_regno_mode_ok (int regno, enum machine_mode mode)
1715 {
1716   /* Allow only dregs to store value of mode HI or QI */
1717   enum reg_class class = REGNO_REG_CLASS (regno);
1718
1719   if (mode == CCmode)
1720     return 0;
1721
1722   if (mode == V2HImode)
1723     return D_REGNO_P (regno);
1724   if (class == CCREGS)
1725     return mode == BImode;
1726   if (mode == PDImode || mode == V2PDImode)
1727     return regno == REG_A0 || regno == REG_A1;
1728   if (mode == SImode
1729       && TEST_HARD_REG_BIT (reg_class_contents[PROLOGUE_REGS], regno))
1730     return 1;
1731       
1732   return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno);
1733 }
1734
1735 /* Implements target hook vector_mode_supported_p.  */
1736
1737 static bool
1738 bfin_vector_mode_supported_p (enum machine_mode mode)
1739 {
1740   return mode == V2HImode;
1741 }
1742
1743 /* Return the cost of moving data from a register in class CLASS1 to
1744    one in class CLASS2.  A cost of 2 is the default.  */
1745
1746 int
1747 bfin_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
1748                          enum reg_class class1, enum reg_class class2)
1749 {
1750   /* These need secondary reloads, so they're more expensive.  */
1751   if ((class1 == CCREGS && class2 != DREGS)
1752       || (class1 != DREGS && class2 == CCREGS))
1753     return 4;
1754
1755   /* If optimizing for size, always prefer reg-reg over reg-memory moves.  */
1756   if (optimize_size)
1757     return 2;
1758
1759   /* There are some stalls involved when moving from a DREG to a different
1760      class reg, and using the value in one of the following instructions.
1761      Attempt to model this by slightly discouraging such moves.  */
1762   if (class1 == DREGS && class2 != DREGS)
1763     return 2 * 2;
1764
1765   return 2;
1766 }
1767
1768 /* Return the cost of moving data of mode M between a
1769    register and memory.  A value of 2 is the default; this cost is
1770    relative to those in `REGISTER_MOVE_COST'.
1771
1772    ??? In theory L1 memory has single-cycle latency.  We should add a switch
1773    that tells the compiler whether we expect to use only L1 memory for the
1774    program; it'll make the costs more accurate.  */
1775
1776 int
1777 bfin_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
1778                        enum reg_class class,
1779                        int in ATTRIBUTE_UNUSED)
1780 {
1781   /* Make memory accesses slightly more expensive than any register-register
1782      move.  Also, penalize non-DP registers, since they need secondary
1783      reloads to load and store.  */
1784   if (! reg_class_subset_p (class, DPREGS))
1785     return 10;
1786
1787   return 8;
1788 }
1789
1790 /* Inform reload about cases where moving X with a mode MODE to a register in
1791    CLASS requires an extra scratch register.  Return the class needed for the
1792    scratch register.  */
1793
1794 static enum reg_class
1795 bfin_secondary_reload (bool in_p, rtx x, enum reg_class class,
1796                      enum machine_mode mode, secondary_reload_info *sri)
1797 {
1798   /* If we have HImode or QImode, we can only use DREGS as secondary registers;
1799      in most other cases we can also use PREGS.  */
1800   enum reg_class default_class = GET_MODE_SIZE (mode) >= 4 ? DPREGS : DREGS;
1801   enum reg_class x_class = NO_REGS;
1802   enum rtx_code code = GET_CODE (x);
1803
1804   if (code == SUBREG)
1805     x = SUBREG_REG (x), code = GET_CODE (x);
1806   if (REG_P (x))
1807     {
1808       int regno = REGNO (x);
1809       if (regno >= FIRST_PSEUDO_REGISTER)
1810         regno = reg_renumber[regno];
1811
1812       if (regno == -1)
1813         code = MEM;
1814       else
1815         x_class = REGNO_REG_CLASS (regno);
1816     }
1817
1818   /* We can be asked to reload (plus (FP) (large_constant)) into a DREG.
1819      This happens as a side effect of register elimination, and we need
1820      a scratch register to do it.  */
1821   if (fp_plus_const_operand (x, mode))
1822     {
1823       rtx op2 = XEXP (x, 1);
1824       int large_constant_p = ! CONST_7BIT_IMM_P (INTVAL (op2));
1825
1826       if (class == PREGS || class == PREGS_CLOBBERED)
1827         return NO_REGS;
1828       /* If destination is a DREG, we can do this without a scratch register
1829          if the constant is valid for an add instruction.  */
1830       if ((class == DREGS || class == DPREGS)
1831           && ! large_constant_p)
1832         return NO_REGS;
1833       /* Reloading to anything other than a DREG?  Use a PREG scratch
1834          register.  */
1835       sri->icode = CODE_FOR_reload_insi;
1836       return NO_REGS;
1837     }
1838
1839   /* Data can usually be moved freely between registers of most classes.
1840      AREGS are an exception; they can only move to or from another register
1841      in AREGS or one in DREGS.  They can also be assigned the constant 0.  */
1842   if (x_class == AREGS)
1843     return class == DREGS || class == AREGS ? NO_REGS : DREGS;
1844
1845   if (class == AREGS)
1846     {
1847       if (x != const0_rtx && x_class != DREGS)
1848         return DREGS;
1849       else
1850         return NO_REGS;
1851     }
1852
1853   /* CCREGS can only be moved from/to DREGS.  */
1854   if (class == CCREGS && x_class != DREGS)
1855     return DREGS;
1856   if (x_class == CCREGS && class != DREGS)
1857     return DREGS;
1858
1859   /* All registers other than AREGS can load arbitrary constants.  The only
1860      case that remains is MEM.  */
1861   if (code == MEM)
1862     if (! reg_class_subset_p (class, default_class))
1863       return default_class;
1864   return NO_REGS;
1865 }
1866 \f
1867 /* Implement TARGET_HANDLE_OPTION.  */
1868
1869 static bool
1870 bfin_handle_option (size_t code, const char *arg, int value)
1871 {
1872   switch (code)
1873     {
1874     case OPT_mshared_library_id_:
1875       if (value > MAX_LIBRARY_ID)
1876         error ("-mshared-library-id=%s is not between 0 and %d",
1877                arg, MAX_LIBRARY_ID);
1878       bfin_lib_id_given = 1;
1879       return true;
1880
1881     default:
1882       return true;
1883     }
1884 }
1885
1886 /* Implement the macro OVERRIDE_OPTIONS.  */
1887
1888 void
1889 override_options (void)
1890 {
1891   if (TARGET_OMIT_LEAF_FRAME_POINTER)
1892     flag_omit_frame_pointer = 1;
1893
1894   /* Library identification */
1895   if (bfin_lib_id_given && ! TARGET_ID_SHARED_LIBRARY)
1896     error ("-mshared-library-id= specified without -mid-shared-library");
1897
1898   if (TARGET_ID_SHARED_LIBRARY)
1899     /* ??? Provide a way to use a bigger GOT.  */
1900     flag_pic = 1;
1901
1902   flag_schedule_insns = 0;
1903 }
1904
1905 /* Return the destination address of BRANCH.
1906    We need to use this instead of get_attr_length, because the
1907    cbranch_with_nops pattern conservatively sets its length to 6, and
1908    we still prefer to use shorter sequences.  */
1909
1910 static int
1911 branch_dest (rtx branch)
1912 {
1913   rtx dest;
1914   int dest_uid;
1915   rtx pat = PATTERN (branch);
1916   if (GET_CODE (pat) == PARALLEL)
1917     pat = XVECEXP (pat, 0, 0);
1918   dest = SET_SRC (pat);
1919   if (GET_CODE (dest) == IF_THEN_ELSE)
1920     dest = XEXP (dest, 1);
1921   dest = XEXP (dest, 0);
1922   dest_uid = INSN_UID (dest);
1923   return INSN_ADDRESSES (dest_uid);
1924 }
1925
1926 /* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates
1927    it's a branch that's predicted taken.  */
1928
1929 static int
1930 cbranch_predicted_taken_p (rtx insn)
1931 {
1932   rtx x = find_reg_note (insn, REG_BR_PROB, 0);
1933
1934   if (x)
1935     {
1936       int pred_val = INTVAL (XEXP (x, 0));
1937
1938       return pred_val >= REG_BR_PROB_BASE / 2;
1939     }
1940
1941   return 0;
1942 }
1943
1944 /* Templates for use by asm_conditional_branch.  */
1945
1946 static const char *ccbranch_templates[][3] = {
1947   { "if !cc jump %3;",  "if cc jump 4 (bp); jump.s %3;",  "if cc jump 6 (bp); jump.l %3;" },
1948   { "if cc jump %3;",   "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" },
1949   { "if !cc jump %3 (bp);",  "if cc jump 4; jump.s %3;",  "if cc jump 6; jump.l %3;" },
1950   { "if cc jump %3 (bp);",  "if !cc jump 4; jump.s %3;",  "if !cc jump 6; jump.l %3;" },
1951 };
1952
1953 /* Output INSN, which is a conditional branch instruction with operands
1954    OPERANDS.
1955
1956    We deal with the various forms of conditional branches that can be generated
1957    by bfin_reorg to prevent the hardware from doing speculative loads, by
1958    - emitting a sufficient number of nops, if N_NOPS is nonzero, or
1959    - always emitting the branch as predicted taken, if PREDICT_TAKEN is true.
1960    Either of these is only necessary if the branch is short, otherwise the
1961    template we use ends in an unconditional jump which flushes the pipeline
1962    anyway.  */
1963
1964 void
1965 asm_conditional_branch (rtx insn, rtx *operands, int n_nops, int predict_taken)
1966 {
1967   int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
1968   /* Note : offset for instructions like if cc jmp; jump.[sl] offset
1969             is to be taken from start of if cc rather than jump.
1970             Range for jump.s is (-4094, 4096) instead of (-4096, 4094)
1971   */
1972   int len = (offset >= -1024 && offset <= 1022 ? 0
1973              : offset >= -4094 && offset <= 4096 ? 1
1974              : 2);
1975   int bp = predict_taken && len == 0 ? 1 : cbranch_predicted_taken_p (insn);
1976   int idx = (bp << 1) | (GET_CODE (operands[0]) == EQ ? BRF : BRT);
1977   output_asm_insn (ccbranch_templates[idx][len], operands);
1978   gcc_assert (n_nops == 0 || !bp);
1979   if (len == 0)
1980     while (n_nops-- > 0)
1981       output_asm_insn ("nop;", NULL);
1982 }
1983
1984 /* Emit rtl for a comparison operation CMP in mode MODE.  Operands have been
1985    stored in bfin_compare_op0 and bfin_compare_op1 already.  */
1986
1987 rtx
1988 bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED)
1989 {
1990   enum rtx_code code1, code2;
1991   rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1;
1992   rtx tem = bfin_cc_rtx;
1993   enum rtx_code code = GET_CODE (cmp);
1994
1995   /* If we have a BImode input, then we already have a compare result, and
1996      do not need to emit another comparison.  */
1997   if (GET_MODE (op0) == BImode)
1998     {
1999       gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
2000       tem = op0, code2 = code;
2001     }
2002   else
2003     {
2004       switch (code) {
2005         /* bfin has these conditions */
2006       case EQ:
2007       case LT:
2008       case LE:
2009       case LEU:
2010       case LTU:
2011         code1 = code;
2012         code2 = NE;
2013         break;
2014       default:
2015         code1 = reverse_condition (code);
2016         code2 = EQ;
2017         break;
2018       }
2019       emit_insn (gen_rtx_SET (BImode, tem,
2020                               gen_rtx_fmt_ee (code1, BImode, op0, op1)));
2021     }
2022
2023   return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode));
2024 }
2025 \f
2026 /* Return nonzero iff C has exactly one bit set if it is interpreted
2027    as a 32 bit constant.  */
2028
2029 int
2030 log2constp (unsigned HOST_WIDE_INT c)
2031 {
2032   c &= 0xFFFFFFFF;
2033   return c != 0 && (c & (c-1)) == 0;
2034 }
2035
2036 /* Returns the number of consecutive least significant zeros in the binary
2037    representation of *V.
2038    We modify *V to contain the original value arithmetically shifted right by
2039    the number of zeroes.  */
2040
2041 static int
2042 shiftr_zero (HOST_WIDE_INT *v)
2043 {
2044   unsigned HOST_WIDE_INT tmp = *v;
2045   unsigned HOST_WIDE_INT sgn;
2046   int n = 0;
2047
2048   if (tmp == 0)
2049     return 0;
2050
2051   sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1));
2052   while ((tmp & 0x1) == 0 && n <= 32)
2053     {
2054       tmp = (tmp >> 1) | sgn;
2055       n++;
2056     }
2057   *v = tmp;
2058   return n;
2059 }
2060
2061 /* After reload, split the load of an immediate constant.  OPERANDS are the
2062    operands of the movsi_insn pattern which we are splitting.  We return
2063    nonzero if we emitted a sequence to load the constant, zero if we emitted
2064    nothing because we want to use the splitter's default sequence.  */
2065
2066 int
2067 split_load_immediate (rtx operands[])
2068 {
2069   HOST_WIDE_INT val = INTVAL (operands[1]);
2070   HOST_WIDE_INT tmp;
2071   HOST_WIDE_INT shifted = val;
2072   HOST_WIDE_INT shifted_compl = ~val;
2073   int num_zero = shiftr_zero (&shifted);
2074   int num_compl_zero = shiftr_zero (&shifted_compl);
2075   unsigned int regno = REGNO (operands[0]);
2076   enum reg_class class1 = REGNO_REG_CLASS (regno);
2077
2078   /* This case takes care of single-bit set/clear constants, which we could
2079      also implement with BITSET/BITCLR.  */
2080   if (num_zero
2081       && shifted >= -32768 && shifted < 65536
2082       && (D_REGNO_P (regno)
2083           || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))
2084     {
2085       emit_insn (gen_movsi (operands[0], GEN_INT (shifted)));
2086       emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));
2087       return 1;
2088     }
2089
2090   tmp = val & 0xFFFF;
2091   tmp |= -(tmp & 0x8000);
2092
2093   /* If high word has one bit set or clear, try to use a bit operation.  */
2094   if (D_REGNO_P (regno))
2095     {
2096       if (log2constp (val & 0xFFFF0000))
2097         {
2098           emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));
2099           emit_insn (gen_iorsi3 (operands[0], operands[0], GEN_INT (val & 0xFFFF0000)));
2100           return 1;
2101         }
2102       else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)
2103         {
2104           emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2105           emit_insn (gen_andsi3 (operands[0], operands[0], GEN_INT (val | 0xFFFF)));
2106         }
2107     }
2108
2109   if (D_REGNO_P (regno))
2110     {
2111       if (CONST_7BIT_IMM_P (tmp))
2112         {
2113           emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2114           emit_insn (gen_movstricthi_high (operands[0], GEN_INT (val & -65536)));
2115           return 1;
2116         }
2117
2118       if ((val & 0xFFFF0000) == 0)
2119         {
2120           emit_insn (gen_movsi (operands[0], const0_rtx));
2121           emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2122           return 1;
2123         }
2124
2125       if ((val & 0xFFFF0000) == 0xFFFF0000)
2126         {
2127           emit_insn (gen_movsi (operands[0], constm1_rtx));
2128           emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2129           return 1;
2130         }
2131     }
2132
2133   /* Need DREGs for the remaining case.  */
2134   if (regno > REG_R7)
2135     return 0;
2136
2137   if (optimize_size
2138       && num_compl_zero && CONST_7BIT_IMM_P (shifted_compl))
2139     {
2140       /* If optimizing for size, generate a sequence that has more instructions
2141          but is shorter.  */
2142       emit_insn (gen_movsi (operands[0], GEN_INT (shifted_compl)));
2143       emit_insn (gen_ashlsi3 (operands[0], operands[0],
2144                               GEN_INT (num_compl_zero)));
2145       emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
2146       return 1;
2147     }
2148   return 0;
2149 }
2150 \f
2151 /* Return true if the legitimate memory address for a memory operand of mode
2152    MODE.  Return false if not.  */
2153
2154 static bool
2155 bfin_valid_add (enum machine_mode mode, HOST_WIDE_INT value)
2156 {
2157   unsigned HOST_WIDE_INT v = value > 0 ? value : -value;
2158   int sz = GET_MODE_SIZE (mode);
2159   int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2;
2160   /* The usual offsettable_memref machinery doesn't work so well for this
2161      port, so we deal with the problem here.  */
2162   unsigned HOST_WIDE_INT mask = sz == 8 ? 0x7ffe : 0x7fff;
2163   return (v & ~(mask << shift)) == 0;
2164 }
2165
2166 static bool
2167 bfin_valid_reg_p (unsigned int regno, int strict, enum machine_mode mode,
2168                   enum rtx_code outer_code)
2169 {
2170   if (strict)
2171     return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH);
2172   else
2173     return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH);
2174 }
2175
2176 bool
2177 bfin_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
2178 {
2179   switch (GET_CODE (x)) {
2180   case REG:
2181     if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM))
2182       return true;
2183     break;
2184   case PLUS:
2185     if (REG_P (XEXP (x, 0))
2186         && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS)
2187         && ((GET_CODE (XEXP (x, 1)) == UNSPEC && mode == SImode)
2188             || (GET_CODE (XEXP (x, 1)) == CONST_INT
2189                 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
2190       return true;
2191     break;
2192   case POST_INC:
2193   case POST_DEC:
2194     if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2195         && REG_P (XEXP (x, 0))
2196         && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC))
2197       return true;
2198   case PRE_DEC:
2199     if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2200         && XEXP (x, 0) == stack_pointer_rtx
2201         && REG_P (XEXP (x, 0))
2202         && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC))
2203       return true;
2204     break;
2205   default:
2206     break;
2207   }
2208   return false;
2209 }
2210
2211 static bool
2212 bfin_rtx_costs (rtx x, int code, int outer_code, int *total)
2213 {
2214   int cost2 = COSTS_N_INSNS (1);
2215
2216   switch (code)
2217     {
2218     case CONST_INT:
2219       if (outer_code == SET || outer_code == PLUS)
2220         *total = CONST_7BIT_IMM_P (INTVAL (x)) ? 0 : cost2;
2221       else if (outer_code == AND)
2222         *total = log2constp (~INTVAL (x)) ? 0 : cost2;
2223       else if (outer_code == LE || outer_code == LT || outer_code == EQ)
2224         *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
2225       else if (outer_code == LEU || outer_code == LTU)
2226         *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
2227       else if (outer_code == MULT)
2228         *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
2229       else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
2230         *total = 0;
2231       else if (outer_code == ASHIFT || outer_code == ASHIFTRT
2232                || outer_code == LSHIFTRT)
2233         *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
2234       else if (outer_code == IOR || outer_code == XOR)
2235         *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
2236       else
2237         *total = cost2;
2238       return true;
2239
2240     case CONST:
2241     case LABEL_REF:
2242     case SYMBOL_REF:
2243     case CONST_DOUBLE:
2244       *total = COSTS_N_INSNS (2);
2245       return true;
2246
2247     case PLUS:
2248       if (GET_MODE (x) == Pmode)
2249         {
2250           if (GET_CODE (XEXP (x, 0)) == MULT
2251               && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
2252             {
2253               HOST_WIDE_INT val = INTVAL (XEXP (XEXP (x, 0), 1));
2254               if (val == 2 || val == 4)
2255                 {
2256                   *total = cost2;
2257                   *total += rtx_cost (XEXP (XEXP (x, 0), 0), outer_code);
2258                   *total += rtx_cost (XEXP (x, 1), outer_code);
2259                   return true;
2260                 }
2261             }
2262         }
2263
2264       /* fall through */
2265
2266     case MINUS:
2267     case ASHIFT: 
2268     case ASHIFTRT:
2269     case LSHIFTRT:
2270       if (GET_MODE (x) == DImode)
2271         *total = 6 * cost2;
2272       return false;
2273           
2274     case AND:
2275     case IOR:
2276     case XOR:
2277       if (GET_MODE (x) == DImode)
2278         *total = 2 * cost2;
2279       return false;
2280
2281     case MULT:
2282       if (GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD)
2283         *total = COSTS_N_INSNS (3);
2284       return false;
2285
2286     default:
2287       return false;
2288     }
2289 }
2290
2291 static void
2292 bfin_internal_label (FILE *stream, const char *prefix, unsigned long num)
2293 {
2294   fprintf (stream, "%s%s$%ld:\n", LOCAL_LABEL_PREFIX, prefix, num);
2295 }
2296 \f
2297 /* Used for communication between {push,pop}_multiple_operation (which
2298    we use not only as a predicate) and the corresponding output functions.  */
2299 static int first_preg_to_save, first_dreg_to_save;
2300
2301 int
2302 push_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2303 {
2304   int lastdreg = 8, lastpreg = 6;
2305   int i, group;
2306
2307   first_preg_to_save = lastpreg;
2308   first_dreg_to_save = lastdreg;
2309   for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
2310     {
2311       rtx t = XVECEXP (op, 0, i);
2312       rtx src, dest;
2313       int regno;
2314
2315       if (GET_CODE (t) != SET)
2316         return 0;
2317
2318       src = SET_SRC (t);
2319       dest = SET_DEST (t);
2320       if (GET_CODE (dest) != MEM || ! REG_P (src))
2321         return 0;
2322       dest = XEXP (dest, 0);
2323       if (GET_CODE (dest) != PLUS
2324           || ! REG_P (XEXP (dest, 0))
2325           || REGNO (XEXP (dest, 0)) != REG_SP
2326           || GET_CODE (XEXP (dest, 1)) != CONST_INT
2327           || INTVAL (XEXP (dest, 1)) != -i * 4)
2328         return 0;
2329
2330       regno = REGNO (src);
2331       if (group == 0)
2332         {
2333           if (D_REGNO_P (regno))
2334             {
2335               group = 1;
2336               first_dreg_to_save = lastdreg = regno - REG_R0;
2337             }
2338           else if (regno >= REG_P0 && regno <= REG_P7)
2339             {
2340               group = 2;
2341               first_preg_to_save = lastpreg = regno - REG_P0;
2342             }
2343           else
2344             return 0;
2345
2346           continue;
2347         }
2348
2349       if (group == 1)
2350         {
2351           if (regno >= REG_P0 && regno <= REG_P7)
2352             {
2353               group = 2;
2354               first_preg_to_save = lastpreg = regno - REG_P0;
2355             }
2356           else if (regno != REG_R0 + lastdreg + 1)
2357             return 0;
2358           else
2359             lastdreg++;
2360         }
2361       else if (group == 2)
2362         {
2363           if (regno != REG_P0 + lastpreg + 1)
2364             return 0;
2365           lastpreg++;
2366         }
2367     }
2368   return 1;
2369 }
2370
2371 int
2372 pop_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2373 {
2374   int lastdreg = 8, lastpreg = 6;
2375   int i, group;
2376
2377   for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
2378     {
2379       rtx t = XVECEXP (op, 0, i);
2380       rtx src, dest;
2381       int regno;
2382
2383       if (GET_CODE (t) != SET)
2384         return 0;
2385
2386       src = SET_SRC (t);
2387       dest = SET_DEST (t);
2388       if (GET_CODE (src) != MEM || ! REG_P (dest))
2389         return 0;
2390       src = XEXP (src, 0);
2391
2392       if (i == 1)
2393         {
2394           if (! REG_P (src) || REGNO (src) != REG_SP)
2395             return 0;
2396         }
2397       else if (GET_CODE (src) != PLUS
2398                || ! REG_P (XEXP (src, 0))
2399                || REGNO (XEXP (src, 0)) != REG_SP
2400                || GET_CODE (XEXP (src, 1)) != CONST_INT
2401                || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
2402         return 0;
2403
2404       regno = REGNO (dest);
2405       if (group == 0)
2406         {
2407           if (regno == REG_R7)
2408             {
2409               group = 1;
2410               lastdreg = 7;
2411             }
2412           else if (regno != REG_P0 + lastpreg - 1)
2413             return 0;
2414           else
2415             lastpreg--;
2416         }
2417       else if (group == 1)
2418         {
2419           if (regno != REG_R0 + lastdreg - 1)
2420             return 0;
2421           else
2422             lastdreg--;
2423         }
2424     }
2425   first_dreg_to_save = lastdreg;
2426   first_preg_to_save = lastpreg;
2427   return 1;
2428 }
2429
2430 /* Emit assembly code for one multi-register push described by INSN, with
2431    operands in OPERANDS.  */
2432
2433 void
2434 output_push_multiple (rtx insn, rtx *operands)
2435 {
2436   char buf[80];
2437   int ok;
2438   
2439   /* Validate the insn again, and compute first_[dp]reg_to_save. */
2440   ok = push_multiple_operation (PATTERN (insn), VOIDmode);
2441   gcc_assert (ok);
2442   
2443   if (first_dreg_to_save == 8)
2444     sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
2445   else if (first_preg_to_save == 6)
2446     sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
2447   else
2448     sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
2449              first_dreg_to_save, first_preg_to_save);
2450
2451   output_asm_insn (buf, operands);
2452 }
2453
2454 /* Emit assembly code for one multi-register pop described by INSN, with
2455    operands in OPERANDS.  */
2456
2457 void
2458 output_pop_multiple (rtx insn, rtx *operands)
2459 {
2460   char buf[80];
2461   int ok;
2462   
2463   /* Validate the insn again, and compute first_[dp]reg_to_save. */
2464   ok = pop_multiple_operation (PATTERN (insn), VOIDmode);
2465   gcc_assert (ok);
2466
2467   if (first_dreg_to_save == 8)
2468     sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
2469   else if (first_preg_to_save == 6)
2470     sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
2471   else
2472     sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
2473              first_dreg_to_save, first_preg_to_save);
2474
2475   output_asm_insn (buf, operands);
2476 }
2477
2478 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE.  */
2479
2480 static void
2481 single_move_for_movmem (rtx dst, rtx src, enum machine_mode mode, HOST_WIDE_INT offset)
2482 {
2483   rtx scratch = gen_reg_rtx (mode);
2484   rtx srcmem, dstmem;
2485
2486   srcmem = adjust_address_nv (src, mode, offset);
2487   dstmem = adjust_address_nv (dst, mode, offset);
2488   emit_move_insn (scratch, srcmem);
2489   emit_move_insn (dstmem, scratch);
2490 }
2491
2492 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
2493    alignment ALIGN_EXP.  Return true if successful, false if we should fall
2494    back on a different method.  */
2495
2496 bool
2497 bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
2498 {
2499   rtx srcreg, destreg, countreg;
2500   HOST_WIDE_INT align = 0;
2501   unsigned HOST_WIDE_INT count = 0;
2502
2503   if (GET_CODE (align_exp) == CONST_INT)
2504     align = INTVAL (align_exp);
2505   if (GET_CODE (count_exp) == CONST_INT)
2506     {
2507       count = INTVAL (count_exp);
2508 #if 0
2509       if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
2510         return false;
2511 #endif
2512     }
2513
2514   /* If optimizing for size, only do single copies inline.  */
2515   if (optimize_size)
2516     {
2517       if (count == 2 && align < 2)
2518         return false;
2519       if (count == 4 && align < 4)
2520         return false;
2521       if (count != 1 && count != 2 && count != 4)
2522         return false;
2523     }
2524   if (align < 2 && count != 1)
2525     return false;
2526
2527   destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
2528   if (destreg != XEXP (dst, 0))
2529     dst = replace_equiv_address_nv (dst, destreg);
2530   srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
2531   if (srcreg != XEXP (src, 0))
2532     src = replace_equiv_address_nv (src, srcreg);
2533
2534   if (count != 0 && align >= 2)
2535     {
2536       unsigned HOST_WIDE_INT offset = 0;
2537
2538       if (align >= 4)
2539         {
2540           if ((count & ~3) == 4)
2541             {
2542               single_move_for_movmem (dst, src, SImode, offset);
2543               offset = 4;
2544             }
2545           else if (count & ~3)
2546             {
2547               HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
2548               countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
2549
2550               emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
2551             }
2552           if (count & 2)
2553             {
2554               single_move_for_movmem (dst, src, HImode, offset);
2555               offset += 2;
2556             }
2557         }
2558       else
2559         {
2560           if ((count & ~1) == 2)
2561             {
2562               single_move_for_movmem (dst, src, HImode, offset);
2563               offset = 2;
2564             }
2565           else if (count & ~1)
2566             {
2567               HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
2568               countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
2569
2570               emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
2571             }
2572         }
2573       if (count & 1)
2574         {
2575           single_move_for_movmem (dst, src, QImode, offset);
2576         }
2577       return true;
2578     }
2579   return false;
2580 }
2581
2582 \f
2583 static int
2584 bfin_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
2585 {
2586   enum attr_type insn_type, dep_insn_type;
2587   int dep_insn_code_number;
2588
2589   /* Anti and output dependencies have zero cost.  */
2590   if (REG_NOTE_KIND (link) != 0)
2591     return 0;
2592
2593   dep_insn_code_number = recog_memoized (dep_insn);
2594
2595   /* If we can't recognize the insns, we can't really do anything.  */
2596   if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
2597     return cost;
2598
2599   insn_type = get_attr_type (insn);
2600   dep_insn_type = get_attr_type (dep_insn);
2601
2602   if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)
2603     {
2604       rtx pat = PATTERN (dep_insn);
2605       rtx dest = SET_DEST (pat);
2606       rtx src = SET_SRC (pat);
2607       if (! ADDRESS_REGNO_P (REGNO (dest)) || ! D_REGNO_P (REGNO (src)))
2608         return cost;
2609       return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);
2610     }
2611
2612   return cost;
2613 }
2614 \f
2615 /* We use the machine specific reorg pass for emitting CSYNC instructions
2616    after conditional branches as needed.
2617
2618    The Blackfin is unusual in that a code sequence like
2619      if cc jump label
2620      r0 = (p0)
2621    may speculatively perform the load even if the condition isn't true.  This
2622    happens for a branch that is predicted not taken, because the pipeline
2623    isn't flushed or stalled, so the early stages of the following instructions,
2624    which perform the memory reference, are allowed to execute before the
2625    jump condition is evaluated.
2626    Therefore, we must insert additional instructions in all places where this
2627    could lead to incorrect behavior.  The manual recommends CSYNC, while
2628    VDSP seems to use NOPs (even though its corresponding compiler option is
2629    named CSYNC).
2630
2631    When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
2632    When optimizing for size, we turn the branch into a predicted taken one.
2633    This may be slower due to mispredicts, but saves code size.  */
2634
2635 static void
2636 bfin_reorg (void)
2637 {
2638   rtx insn, last_condjump = NULL_RTX;
2639   int cycles_since_jump = INT_MAX;
2640
2641   if (! TARGET_SPECLD_ANOMALY || ! TARGET_CSYNC_ANOMALY)
2642     return;
2643
2644   /* First pass: find predicted-false branches; if something after them
2645      needs nops, insert them or change the branch to predict true.  */
2646   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2647     {
2648       rtx pat;
2649
2650       if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
2651         continue;
2652
2653       pat = PATTERN (insn);
2654       if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
2655           || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
2656           || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
2657         continue;
2658
2659       if (JUMP_P (insn))
2660         {
2661           if (any_condjump_p (insn)
2662               && ! cbranch_predicted_taken_p (insn))
2663             {
2664               last_condjump = insn;
2665               cycles_since_jump = 0;
2666             }
2667           else
2668             cycles_since_jump = INT_MAX;
2669         }
2670       else if (INSN_P (insn))
2671         {
2672           enum attr_type type = get_attr_type (insn);
2673           int delay_needed = 0;
2674           if (cycles_since_jump < INT_MAX)
2675             cycles_since_jump++;
2676
2677           if (type == TYPE_MCLD && TARGET_SPECLD_ANOMALY)
2678             {
2679               rtx pat = single_set (insn);
2680               if (may_trap_p (SET_SRC (pat)))
2681                 delay_needed = 3;
2682             }
2683           else if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
2684             delay_needed = 4;
2685
2686           if (delay_needed > cycles_since_jump)
2687             {
2688               rtx pat;
2689               int num_clobbers;
2690               rtx *op = recog_data.operand;
2691
2692               delay_needed -= cycles_since_jump;
2693
2694               extract_insn (last_condjump);
2695               if (optimize_size)
2696                 {
2697                   pat = gen_cbranch_predicted_taken (op[0], op[1], op[2],
2698                                                      op[3]);
2699                   cycles_since_jump = INT_MAX;
2700                 }
2701               else
2702                 /* Do not adjust cycles_since_jump in this case, so that
2703                    we'll increase the number of NOPs for a subsequent insn
2704                    if necessary.  */
2705                 pat = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
2706                                              GEN_INT (delay_needed));
2707               PATTERN (last_condjump) = pat;
2708               INSN_CODE (last_condjump) = recog (pat, insn, &num_clobbers);
2709             }
2710         }
2711     }
2712   /* Second pass: for predicted-true branches, see if anything at the
2713      branch destination needs extra nops.  */
2714   if (! TARGET_CSYNC_ANOMALY)
2715     return;
2716
2717   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2718     {
2719       if (JUMP_P (insn)
2720           && any_condjump_p (insn)
2721           && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken
2722               || cbranch_predicted_taken_p (insn)))
2723         {
2724           rtx target = JUMP_LABEL (insn);
2725           rtx label = target;
2726           cycles_since_jump = 0;
2727           for (; target && cycles_since_jump < 3; target = NEXT_INSN (target))
2728             {
2729               rtx pat;
2730
2731               if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
2732                 continue;
2733
2734               pat = PATTERN (target);
2735               if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
2736                   || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
2737                   || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
2738                 continue;
2739
2740               if (INSN_P (target))
2741                 {
2742                   enum attr_type type = get_attr_type (target);
2743                   int delay_needed = 0;
2744                   if (cycles_since_jump < INT_MAX)
2745                     cycles_since_jump++;
2746
2747                   if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
2748                     delay_needed = 2;
2749
2750                   if (delay_needed > cycles_since_jump)
2751                     {
2752                       rtx prev = prev_real_insn (label);
2753                       delay_needed -= cycles_since_jump;
2754                       if (dump_file)
2755                         fprintf (dump_file, "Adding %d nops after %d\n",
2756                                  delay_needed, INSN_UID (label));
2757                       if (JUMP_P (prev)
2758                           && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops)
2759                         {
2760                           rtx x;
2761                           HOST_WIDE_INT v;
2762
2763                           if (dump_file)
2764                             fprintf (dump_file,
2765                                      "Reducing nops on insn %d.\n",
2766                                      INSN_UID (prev));
2767                           x = PATTERN (prev);
2768                           x = XVECEXP (x, 0, 1);
2769                           v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed;
2770                           XVECEXP (x, 0, 0) = GEN_INT (v);
2771                         }
2772                       while (delay_needed-- > 0)
2773                         emit_insn_after (gen_nop (), label);
2774                       break;
2775                     }
2776                 }
2777             }
2778         }
2779     }
2780 }
2781 \f
2782 /* Handle interrupt_handler, exception_handler and nmi_handler function
2783    attributes; arguments as in struct attribute_spec.handler.  */
2784
2785 static tree
2786 handle_int_attribute (tree *node, tree name,
2787                       tree args ATTRIBUTE_UNUSED,
2788                       int flags ATTRIBUTE_UNUSED,
2789                       bool *no_add_attrs)
2790 {
2791   tree x = *node;
2792   if (TREE_CODE (x) == FUNCTION_DECL)
2793     x = TREE_TYPE (x);
2794
2795   if (TREE_CODE (x) != FUNCTION_TYPE)
2796     {
2797       warning (OPT_Wattributes, "%qs attribute only applies to functions",
2798                IDENTIFIER_POINTER (name));
2799       *no_add_attrs = true;
2800     }
2801   else if (funkind (x) != SUBROUTINE)
2802     error ("multiple function type attributes specified");
2803
2804   return NULL_TREE;
2805 }
2806
2807 /* Return 0 if the attributes for two types are incompatible, 1 if they
2808    are compatible, and 2 if they are nearly compatible (which causes a
2809    warning to be generated).  */
2810
2811 static int
2812 bfin_comp_type_attributes (tree type1, tree type2)
2813 {
2814   e_funkind kind1, kind2;
2815
2816   if (TREE_CODE (type1) != FUNCTION_TYPE)
2817     return 1;
2818
2819   kind1 = funkind (type1);
2820   kind2 = funkind (type2);
2821
2822   if (kind1 != kind2)
2823     return 0;
2824   
2825   /*  Check for mismatched modifiers */
2826   if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
2827       != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
2828     return 0;
2829
2830   if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
2831       != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
2832     return 0;
2833
2834   if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
2835       != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
2836     return 0;
2837
2838   if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1))
2839       != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2)))
2840     return 0;
2841
2842   return 1;
2843 }
2844
2845 /* Handle a "longcall" or "shortcall" attribute; arguments as in
2846    struct attribute_spec.handler.  */
2847
2848 static tree
2849 bfin_handle_longcall_attribute (tree *node, tree name, 
2850                                 tree args ATTRIBUTE_UNUSED, 
2851                                 int flags ATTRIBUTE_UNUSED, 
2852                                 bool *no_add_attrs)
2853 {
2854   if (TREE_CODE (*node) != FUNCTION_TYPE
2855       && TREE_CODE (*node) != FIELD_DECL
2856       && TREE_CODE (*node) != TYPE_DECL)
2857     {
2858       warning (OPT_Wattributes, "`%s' attribute only applies to functions",
2859                IDENTIFIER_POINTER (name));
2860       *no_add_attrs = true;
2861     }
2862
2863   if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0
2864        && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node)))
2865       || (strcmp (IDENTIFIER_POINTER (name), "shortcall") == 0
2866           && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node))))
2867     {
2868       warning (OPT_Wattributes,
2869                "can't apply both longcall and shortcall attributes to the same function");
2870       *no_add_attrs = true;
2871     }
2872
2873   return NULL_TREE;
2874 }
2875
2876 /* Table of valid machine attributes.  */
2877 const struct attribute_spec bfin_attribute_table[] =
2878 {
2879   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
2880   { "interrupt_handler", 0, 0, false, true,  true, handle_int_attribute },
2881   { "exception_handler", 0, 0, false, true,  true, handle_int_attribute },
2882   { "nmi_handler", 0, 0, false, true,  true, handle_int_attribute },
2883   { "nesting", 0, 0, false, true,  true, NULL },
2884   { "kspisusp", 0, 0, false, true,  true, NULL },
2885   { "saveall", 0, 0, false, true,  true, NULL },
2886   { "longcall",  0, 0, false, true,  true,  bfin_handle_longcall_attribute },
2887   { "shortcall", 0, 0, false, true,  true,  bfin_handle_longcall_attribute },
2888   { NULL, 0, 0, false, false, false, NULL }
2889 };
2890 \f
2891 /* Output the assembler code for a thunk function.  THUNK_DECL is the
2892    declaration for the thunk function itself, FUNCTION is the decl for
2893    the target function.  DELTA is an immediate constant offset to be
2894    added to THIS.  If VCALL_OFFSET is nonzero, the word at
2895    *(*this + vcall_offset) should be added to THIS.  */
2896
2897 static void
2898 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
2899                       tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
2900                       HOST_WIDE_INT vcall_offset, tree function)
2901 {
2902   rtx xops[3];
2903   /* The this parameter is passed as the first argument.  */
2904   rtx this = gen_rtx_REG (Pmode, REG_R0);
2905
2906   /* Adjust the this parameter by a fixed constant.  */
2907   if (delta)
2908     {
2909       xops[1] = this;
2910       if (delta >= -64 && delta <= 63)
2911         {
2912           xops[0] = GEN_INT (delta);
2913           output_asm_insn ("%1 += %0;", xops);
2914         }
2915       else if (delta >= -128 && delta < -64)
2916         {
2917           xops[0] = GEN_INT (delta + 64);
2918           output_asm_insn ("%1 += -64; %1 += %0;", xops);
2919         }
2920       else if (delta > 63 && delta <= 126)
2921         {
2922           xops[0] = GEN_INT (delta - 63);
2923           output_asm_insn ("%1 += 63; %1 += %0;", xops);
2924         }
2925       else
2926         {
2927           xops[0] = GEN_INT (delta);
2928           output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
2929         }
2930     }
2931
2932   /* Adjust the this parameter by a value stored in the vtable.  */
2933   if (vcall_offset)
2934     {
2935       rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
2936       rtx tmp = gen_rtx_REG (Pmode, REG_R2);
2937
2938       xops[1] = tmp;
2939       xops[2] = p2tmp;
2940       output_asm_insn ("%2 = r0; %2 = [%2];", xops);
2941
2942       /* Adjust the this parameter.  */
2943       xops[0] = gen_rtx_MEM (Pmode, plus_constant (p2tmp, vcall_offset));
2944       if (!memory_operand (xops[0], Pmode))
2945         {
2946           rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
2947           xops[0] = GEN_INT (vcall_offset);
2948           xops[1] = tmp2;
2949           output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
2950           xops[0] = gen_rtx_MEM (Pmode, p2tmp);
2951         }
2952       xops[2] = this;
2953       output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
2954     }
2955
2956   xops[0] = XEXP (DECL_RTL (function), 0);
2957   if (1 || !flag_pic || (*targetm.binds_local_p) (function))
2958     output_asm_insn ("jump.l\t%P0", xops);
2959 }
2960 \f
2961 /* Codes for all the Blackfin builtins.  */
2962 enum bfin_builtins
2963 {
2964   BFIN_BUILTIN_CSYNC,
2965   BFIN_BUILTIN_SSYNC,
2966   BFIN_BUILTIN_MAX
2967 };
2968
2969 #define def_builtin(NAME, TYPE, CODE)                                   \
2970 do {                                                                    \
2971   lang_hooks.builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD,     \
2972                                NULL, NULL_TREE);                        \
2973 } while (0)
2974
2975 /* Set up all builtin functions for this target.  */
2976 static void
2977 bfin_init_builtins (void)
2978 {
2979   tree void_ftype_void
2980     = build_function_type (void_type_node, void_list_node);
2981
2982   /* Add the remaining MMX insns with somewhat more complicated types.  */
2983   def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC);
2984   def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC);
2985 }
2986
2987 /* Expand an expression EXP that calls a built-in function,
2988    with result going to TARGET if that's convenient
2989    (and in mode MODE if that's convenient).
2990    SUBTARGET may be used as the target for computing one of EXP's operands.
2991    IGNORE is nonzero if the value is to be ignored.  */
2992
2993 static rtx
2994 bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
2995                      rtx subtarget ATTRIBUTE_UNUSED,
2996                      enum machine_mode mode ATTRIBUTE_UNUSED,
2997                      int ignore ATTRIBUTE_UNUSED)
2998 {
2999   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
3000   unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
3001
3002   switch (fcode)
3003     {
3004     case BFIN_BUILTIN_CSYNC:
3005       emit_insn (gen_csync ());
3006       return 0;
3007     case BFIN_BUILTIN_SSYNC:
3008       emit_insn (gen_ssync ());
3009       return 0;
3010
3011     default:
3012       gcc_unreachable ();
3013     }
3014 }
3015 \f
3016 #undef TARGET_INIT_BUILTINS
3017 #define TARGET_INIT_BUILTINS bfin_init_builtins
3018
3019 #undef TARGET_EXPAND_BUILTIN
3020 #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
3021
3022 #undef TARGET_ASM_GLOBALIZE_LABEL
3023 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label 
3024
3025 #undef TARGET_ASM_FILE_START
3026 #define TARGET_ASM_FILE_START output_file_start
3027
3028 #undef TARGET_ATTRIBUTE_TABLE
3029 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
3030
3031 #undef TARGET_COMP_TYPE_ATTRIBUTES
3032 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
3033
3034 #undef TARGET_RTX_COSTS
3035 #define TARGET_RTX_COSTS bfin_rtx_costs
3036
3037 #undef  TARGET_ADDRESS_COST
3038 #define TARGET_ADDRESS_COST bfin_address_cost
3039
3040 #undef TARGET_ASM_INTERNAL_LABEL
3041 #define TARGET_ASM_INTERNAL_LABEL bfin_internal_label
3042
3043 #undef TARGET_MACHINE_DEPENDENT_REORG
3044 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
3045
3046 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
3047 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
3048
3049 #undef TARGET_ASM_OUTPUT_MI_THUNK
3050 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
3051 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
3052 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
3053
3054 #undef TARGET_SCHED_ADJUST_COST
3055 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
3056
3057 #undef TARGET_PROMOTE_PROTOTYPES
3058 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
3059 #undef TARGET_PROMOTE_FUNCTION_ARGS
3060 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
3061 #undef TARGET_PROMOTE_FUNCTION_RETURN
3062 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
3063
3064 #undef TARGET_ARG_PARTIAL_BYTES
3065 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
3066
3067 #undef TARGET_PASS_BY_REFERENCE
3068 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
3069
3070 #undef TARGET_SETUP_INCOMING_VARARGS
3071 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
3072
3073 #undef TARGET_STRUCT_VALUE_RTX
3074 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
3075
3076 #undef TARGET_VECTOR_MODE_SUPPORTED_P
3077 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
3078
3079 #undef TARGET_HANDLE_OPTION
3080 #define TARGET_HANDLE_OPTION bfin_handle_option
3081
3082 #undef TARGET_DEFAULT_TARGET_FLAGS
3083 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
3084
3085 #undef TARGET_SECONDARY_RELOAD
3086 #define TARGET_SECONDARY_RELOAD bfin_secondary_reload
3087
3088 struct gcc_target targetm = TARGET_INITIALIZER;