OSDN Git Service

* config/bfin/predicates.md (cc_operand): Delete predicate. All uses
[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 /* Return cost of the memory address ADDR.
1066    All addressing modes are equally cheap on the Blackfin.  */
1067
1068 static int
1069 bfin_address_cost (rtx addr ATTRIBUTE_UNUSED)
1070 {
1071   return 1;
1072 }
1073
1074 /* Subroutine of print_operand; used to print a memory reference X to FILE.  */
1075
1076 void
1077 print_address_operand (FILE *file, rtx x)
1078 {
1079   switch (GET_CODE (x))
1080     {
1081     case PLUS:
1082       output_address (XEXP (x, 0));
1083       fprintf (file, "+");
1084       output_address (XEXP (x, 1));
1085       break;
1086
1087     case PRE_DEC:
1088       fprintf (file, "--");
1089       output_address (XEXP (x, 0));    
1090       break;
1091     case POST_INC:
1092       output_address (XEXP (x, 0));
1093       fprintf (file, "++");
1094       break;
1095     case POST_DEC:
1096       output_address (XEXP (x, 0));
1097       fprintf (file, "--");
1098       break;
1099
1100     default:
1101       gcc_assert (GET_CODE (x) != MEM);
1102       print_operand (file, x, 0);
1103       break;
1104     }
1105 }
1106
1107 /* Adding intp DImode support by Tony
1108  * -- Q: (low  word)
1109  * -- R: (high word)
1110  */
1111
1112 void
1113 print_operand (FILE *file, rtx x, char code)
1114 {
1115   enum machine_mode mode = GET_MODE (x);
1116
1117   switch (code)
1118     {
1119     case 'j':
1120       switch (GET_CODE (x))
1121         {
1122         case EQ:
1123           fprintf (file, "e");
1124           break;
1125         case NE:
1126           fprintf (file, "ne");
1127           break;
1128         case GT:
1129           fprintf (file, "g");
1130           break;
1131         case LT:
1132           fprintf (file, "l");
1133           break;
1134         case GE:
1135           fprintf (file, "ge");
1136           break;
1137         case LE:
1138           fprintf (file, "le");
1139           break;
1140         case GTU:
1141           fprintf (file, "g");
1142           break;
1143         case LTU:
1144           fprintf (file, "l");
1145           break;
1146         case GEU:
1147           fprintf (file, "ge");
1148           break;
1149         case LEU:
1150           fprintf (file, "le");
1151           break;
1152         default:
1153           output_operand_lossage ("invalid %%j value");
1154         }
1155       break;
1156     
1157     case 'J':                                    /* reverse logic */
1158       switch (GET_CODE(x))
1159         {
1160         case EQ:
1161           fprintf (file, "ne");
1162           break;
1163         case NE:
1164           fprintf (file, "e");
1165           break;
1166         case GT:
1167           fprintf (file, "le");
1168           break;
1169         case LT:
1170           fprintf (file, "ge");
1171           break;
1172         case GE:
1173           fprintf (file, "l");
1174           break;
1175         case LE:
1176           fprintf (file, "g");
1177           break;
1178         case GTU:
1179           fprintf (file, "le");
1180           break;
1181         case LTU:
1182           fprintf (file, "ge");
1183           break;
1184         case GEU:
1185           fprintf (file, "l");
1186           break;
1187         case LEU:
1188           fprintf (file, "g");
1189           break;
1190         default:
1191           output_operand_lossage ("invalid %%J value");
1192         }
1193       break;
1194
1195     default:
1196       switch (GET_CODE (x))
1197         {
1198         case REG:
1199           if (code == 'h')
1200             {
1201               gcc_assert (REGNO (x) < 32);
1202               fprintf (file, "%s", short_reg_names[REGNO (x)]);
1203               /*fprintf (file, "\n%d\n ", REGNO (x));*/
1204               break;
1205             }
1206           else if (code == 'd')
1207             {
1208               gcc_assert (REGNO (x) < 32);
1209               fprintf (file, "%s", high_reg_names[REGNO (x)]);
1210               break;
1211             }
1212           else if (code == 'w')
1213             {
1214               gcc_assert (REGNO (x) == REG_A0 || REGNO (x) == REG_A1);
1215               fprintf (file, "%s.w", reg_names[REGNO (x)]);
1216             }
1217           else if (code == 'x')
1218             {
1219               gcc_assert (REGNO (x) == REG_A0 || REGNO (x) == REG_A1);
1220               fprintf (file, "%s.x", reg_names[REGNO (x)]);
1221             }
1222           else if (code == 'D')
1223             {
1224               fprintf (file, "%s", dregs_pair_names[REGNO (x)]);
1225             }
1226           else if (code == 'H')
1227             {
1228               gcc_assert (mode == DImode || mode == DFmode);
1229               gcc_assert (REG_P (x));
1230               fprintf (file, "%s", reg_names[REGNO (x) + 1]);
1231             }
1232           else if (code == 'T')
1233             {
1234               gcc_assert (D_REGNO_P (REGNO (x)));
1235               fprintf (file, "%s", byte_reg_names[REGNO (x)]);
1236             }
1237           else 
1238             fprintf (file, "%s", reg_names[REGNO (x)]);
1239           break;
1240
1241         case MEM:
1242           fputc ('[', file);
1243           x = XEXP (x,0);
1244           print_address_operand (file, x);
1245           fputc (']', file);
1246           break;
1247
1248         case CONST_INT:
1249           /* Moves to half registers with d or h modifiers always use unsigned
1250              constants.  */
1251           if (code == 'd')
1252             x = GEN_INT ((INTVAL (x) >> 16) & 0xffff);
1253           else if (code == 'h')
1254             x = GEN_INT (INTVAL (x) & 0xffff);
1255           else if (code == 'X')
1256             x = GEN_INT (exact_log2 (0xffffffff & INTVAL (x)));
1257           else if (code == 'Y')
1258             x = GEN_INT (exact_log2 (0xffffffff & ~INTVAL (x)));
1259           else if (code == 'Z')
1260             /* Used for LINK insns.  */
1261             x = GEN_INT (-8 - INTVAL (x));
1262
1263           /* fall through */
1264
1265         case SYMBOL_REF:
1266           output_addr_const (file, x);
1267           if (code == 'G' && flag_pic)
1268             fprintf (file, "@GOT");
1269           break;
1270
1271         case CONST_DOUBLE:
1272           output_operand_lossage ("invalid const_double operand");
1273           break;
1274
1275         case UNSPEC:
1276           switch (XINT (x, 1))
1277             {
1278             case UNSPEC_MOVE_PIC:
1279               output_addr_const (file, XVECEXP (x, 0, 0));
1280               fprintf (file, "@GOT");
1281               break;
1282
1283             case UNSPEC_LIBRARY_OFFSET:
1284               fprintf (file, "_current_shared_library_p5_offset_");
1285               break;
1286
1287             default:
1288               gcc_unreachable ();
1289             }
1290           break;
1291
1292         default:
1293           output_addr_const (file, x);
1294         }
1295     }
1296 }
1297 \f
1298 /* Argument support functions.  */
1299
1300 /* Initialize a variable CUM of type CUMULATIVE_ARGS
1301    for a call to a function whose data type is FNTYPE.
1302    For a library call, FNTYPE is 0.  
1303    VDSP C Compiler manual, our ABI says that
1304    first 3 words of arguments will use R0, R1 and R2.
1305 */
1306
1307 void
1308 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
1309                       rtx libname ATTRIBUTE_UNUSED)
1310 {
1311   static CUMULATIVE_ARGS zero_cum;
1312
1313   *cum = zero_cum;
1314
1315   /* Set up the number of registers to use for passing arguments.  */
1316
1317   cum->nregs = max_arg_registers;
1318   cum->arg_regs = arg_regs;
1319
1320   cum->call_cookie = CALL_NORMAL;
1321   /* Check for a longcall attribute.  */
1322   if (fntype && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype)))
1323     cum->call_cookie |= CALL_SHORT;
1324   else if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)))
1325     cum->call_cookie |= CALL_LONG;
1326
1327   return;
1328 }
1329
1330 /* Update the data in CUM to advance over an argument
1331    of mode MODE and data type TYPE.
1332    (TYPE is null for libcalls where that information may not be available.)  */
1333
1334 void
1335 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1336                       int named ATTRIBUTE_UNUSED)
1337 {
1338   int count, bytes, words;
1339
1340   bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1341   words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1342
1343   cum->words += words;
1344   cum->nregs -= words;
1345
1346   if (cum->nregs <= 0)
1347     {
1348       cum->nregs = 0;
1349       cum->arg_regs = NULL;
1350     }
1351   else
1352     {
1353       for (count = 1; count <= words; count++)
1354         cum->arg_regs++;
1355     }
1356
1357   return;
1358 }
1359
1360 /* Define where to put the arguments to a function.
1361    Value is zero to push the argument on the stack,
1362    or a hard register in which to store the argument.
1363
1364    MODE is the argument's machine mode.
1365    TYPE is the data type of the argument (as a tree).
1366     This is null for libcalls where that information may
1367     not be available.
1368    CUM is a variable of type CUMULATIVE_ARGS which gives info about
1369     the preceding args and about the function being called.
1370    NAMED is nonzero if this argument is a named parameter
1371     (otherwise it is an extra parameter matching an ellipsis).  */
1372
1373 struct rtx_def *
1374 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1375               int named ATTRIBUTE_UNUSED)
1376 {
1377   int bytes
1378     = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1379
1380   if (mode == VOIDmode)
1381     /* Compute operand 2 of the call insn.  */
1382     return GEN_INT (cum->call_cookie);
1383
1384   if (bytes == -1)
1385     return NULL_RTX;
1386
1387   if (cum->nregs)
1388     return gen_rtx_REG (mode, *(cum->arg_regs));
1389
1390   return NULL_RTX;
1391 }
1392
1393 /* For an arg passed partly in registers and partly in memory,
1394    this is the number of bytes passed in registers.
1395    For args passed entirely in registers or entirely in memory, zero.
1396
1397    Refer VDSP C Compiler manual, our ABI.
1398    First 3 words are in registers. So, if a an argument is larger
1399    than the registers available, it will span the register and
1400    stack.   */
1401
1402 static int
1403 bfin_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1404                         tree type ATTRIBUTE_UNUSED,
1405                         bool named ATTRIBUTE_UNUSED)
1406 {
1407   int bytes
1408     = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1409   int bytes_left = cum->nregs * UNITS_PER_WORD;
1410   
1411   if (bytes == -1)
1412     return 0;
1413
1414   if (bytes_left == 0)
1415     return 0;
1416   if (bytes > bytes_left)
1417     return bytes_left;
1418   return 0;
1419 }
1420
1421 /* Variable sized types are passed by reference.  */
1422
1423 static bool
1424 bfin_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
1425                         enum machine_mode mode ATTRIBUTE_UNUSED,
1426                         tree type, bool named ATTRIBUTE_UNUSED)
1427 {
1428   return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
1429 }
1430
1431 /* Decide whether a type should be returned in memory (true)
1432    or in a register (false).  This is called by the macro
1433    RETURN_IN_MEMORY.  */
1434
1435 int
1436 bfin_return_in_memory (tree type)
1437 {
1438   int size = int_size_in_bytes (type);
1439   return size > 2 * UNITS_PER_WORD || size == -1;
1440 }
1441
1442 /* Register in which address to store a structure value
1443    is passed to a function.  */
1444 static rtx
1445 bfin_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
1446                       int incoming ATTRIBUTE_UNUSED)
1447 {
1448   return gen_rtx_REG (Pmode, REG_P0);
1449 }
1450
1451 /* Return true when register may be used to pass function parameters.  */
1452
1453 bool 
1454 function_arg_regno_p (int n)
1455 {
1456   int i;
1457   for (i = 0; arg_regs[i] != -1; i++)
1458     if (n == arg_regs[i])
1459       return true;
1460   return false;
1461 }
1462
1463 /* Returns 1 if OP contains a symbol reference */
1464
1465 int
1466 symbolic_reference_mentioned_p (rtx op)
1467 {
1468   register const char *fmt;
1469   register int i;
1470
1471   if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
1472     return 1;
1473
1474   fmt = GET_RTX_FORMAT (GET_CODE (op));
1475   for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
1476     {
1477       if (fmt[i] == 'E')
1478         {
1479           register int j;
1480
1481           for (j = XVECLEN (op, i) - 1; j >= 0; j--)
1482             if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
1483               return 1;
1484         }
1485
1486       else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
1487         return 1;
1488     }
1489
1490   return 0;
1491 }
1492
1493 /* Decide whether we can make a sibling call to a function.  DECL is the
1494    declaration of the function being targeted by the call and EXP is the
1495    CALL_EXPR representing the call.  */
1496
1497 static bool
1498 bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
1499                               tree exp ATTRIBUTE_UNUSED)
1500 {
1501   e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1502   return fkind == SUBROUTINE;
1503 }
1504 \f
1505 /* Emit RTL insns to initialize the variable parts of a trampoline at
1506    TRAMP. FNADDR is an RTX for the address of the function's pure
1507    code.  CXT is an RTX for the static chain value for the function.  */
1508
1509 void
1510 initialize_trampoline (tramp, fnaddr, cxt)
1511      rtx tramp, fnaddr, cxt;
1512 {
1513   rtx t1 = copy_to_reg (fnaddr);
1514   rtx t2 = copy_to_reg (cxt);
1515   rtx addr;
1516
1517   addr = memory_address (Pmode, plus_constant (tramp, 2));
1518   emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
1519   emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16)));
1520   addr = memory_address (Pmode, plus_constant (tramp, 6));
1521   emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
1522
1523   addr = memory_address (Pmode, plus_constant (tramp, 10));
1524   emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
1525   emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16)));
1526   addr = memory_address (Pmode, plus_constant (tramp, 14));
1527   emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
1528 }
1529
1530 /* Emit insns to move operands[1] into operands[0].  */
1531
1532 void
1533 emit_pic_move (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
1534 {
1535   rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
1536
1537   if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
1538     operands[1] = force_reg (SImode, operands[1]);
1539   else
1540     operands[1] = legitimize_pic_address (operands[1], temp,
1541                                           pic_offset_table_rtx);
1542 }
1543
1544 /* Expand a move operation in mode MODE.  The operands are in OPERANDS.  */
1545
1546 void
1547 expand_move (rtx *operands, enum machine_mode mode)
1548 {
1549   if (flag_pic && SYMBOLIC_CONST (operands[1]))
1550     emit_pic_move (operands, mode);
1551
1552   /* Don't generate memory->memory or constant->memory moves, go through a
1553      register */
1554   else if ((reload_in_progress | reload_completed) == 0
1555            && GET_CODE (operands[0]) == MEM
1556            && GET_CODE (operands[1]) != REG)
1557     operands[1] = force_reg (mode, operands[1]);
1558 }
1559 \f
1560 /* Split one or more DImode RTL references into pairs of SImode
1561    references.  The RTL can be REG, offsettable MEM, integer constant, or
1562    CONST_DOUBLE.  "operands" is a pointer to an array of DImode RTL to
1563    split and "num" is its length.  lo_half and hi_half are output arrays
1564    that parallel "operands".  */
1565
1566 void
1567 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
1568 {
1569   while (num--)
1570     {
1571       rtx op = operands[num];
1572
1573       /* simplify_subreg refuse to split volatile memory addresses,
1574          but we still have to handle it.  */
1575       if (GET_CODE (op) == MEM)
1576         {
1577           lo_half[num] = adjust_address (op, SImode, 0);
1578           hi_half[num] = adjust_address (op, SImode, 4);
1579         }
1580       else
1581         {
1582           lo_half[num] = simplify_gen_subreg (SImode, op,
1583                                               GET_MODE (op) == VOIDmode
1584                                               ? DImode : GET_MODE (op), 0);
1585           hi_half[num] = simplify_gen_subreg (SImode, op,
1586                                               GET_MODE (op) == VOIDmode
1587                                               ? DImode : GET_MODE (op), 4);
1588         }
1589     }
1590 }
1591 \f
1592 bool
1593 bfin_longcall_p (rtx op, int call_cookie)
1594 {
1595   gcc_assert (GET_CODE (op) == SYMBOL_REF);
1596   if (call_cookie & CALL_SHORT)
1597     return 0;
1598   if (call_cookie & CALL_LONG)
1599     return 1;
1600   if (TARGET_LONG_CALLS)
1601     return 1;
1602   return 0;
1603 }
1604
1605 /* Expand a call instruction.  FNADDR is the call target, RETVAL the return value.
1606    COOKIE is a CONST_INT holding the call_cookie prepared init_cumulative_args.
1607    SIBCALL is nonzero if this is a sibling call.  */
1608
1609 void
1610 bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
1611 {
1612   rtx use = NULL, call;
1613   rtx callee = XEXP (fnaddr, 0);
1614   rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (sibcall ? 3 : 2));
1615
1616   /* In an untyped call, we can get NULL for operand 2.  */
1617   if (cookie == NULL_RTX)
1618     cookie = const0_rtx;
1619
1620   /* Static functions and indirect calls don't need the pic register.  */
1621   if (flag_pic
1622       && GET_CODE (callee) == SYMBOL_REF
1623       && !SYMBOL_REF_LOCAL_P (callee))
1624     use_reg (&use, pic_offset_table_rtx);
1625
1626   if ((!register_no_elim_operand (callee, Pmode)
1627        && GET_CODE (callee) != SYMBOL_REF)
1628       || (GET_CODE (callee) == SYMBOL_REF
1629           && (flag_pic
1630               || bfin_longcall_p (callee, INTVAL (cookie)))))
1631     {
1632       callee = copy_to_mode_reg (Pmode, callee);
1633       fnaddr = gen_rtx_MEM (Pmode, callee);
1634     }
1635   call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
1636
1637   if (retval)
1638     call = gen_rtx_SET (VOIDmode, retval, call);
1639
1640   XVECEXP (pat, 0, 0) = call;
1641   XVECEXP (pat, 0, 1) = gen_rtx_USE (VOIDmode, cookie);
1642   if (sibcall)
1643     XVECEXP (pat, 0, 2) = gen_rtx_RETURN (VOIDmode);
1644   call = emit_call_insn (pat);
1645   if (use)
1646     CALL_INSN_FUNCTION_USAGE (call) = use;
1647 }
1648 \f
1649 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE.  */
1650
1651 int
1652 hard_regno_mode_ok (int regno, enum machine_mode mode)
1653 {
1654   /* Allow only dregs to store value of mode HI or QI */
1655   enum reg_class class = REGNO_REG_CLASS (regno);
1656
1657   if (mode == CCmode)
1658     return 0;
1659
1660   if (mode == V2HImode)
1661     return D_REGNO_P (regno);
1662   if (class == CCREGS)
1663     return mode == BImode;
1664   if (mode == PDImode)
1665     return regno == REG_A0 || regno == REG_A1;
1666   if (mode == SImode
1667       && TEST_HARD_REG_BIT (reg_class_contents[PROLOGUE_REGS], regno))
1668     return 1;
1669       
1670   return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno);
1671 }
1672
1673 /* Implements target hook vector_mode_supported_p.  */
1674
1675 static bool
1676 bfin_vector_mode_supported_p (enum machine_mode mode)
1677 {
1678   return mode == V2HImode;
1679 }
1680
1681 /* Return the cost of moving data from a register in class CLASS1 to
1682    one in class CLASS2.  A cost of 2 is the default.  */
1683
1684 int
1685 bfin_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
1686                          enum reg_class class1, enum reg_class class2)
1687 {
1688   /* These need secondary reloads, so they're more expensive.  */
1689   if ((class1 == CCREGS && class2 != DREGS)
1690       || (class1 != DREGS && class2 == CCREGS))
1691     return 4;
1692
1693   /* If optimizing for size, always prefer reg-reg over reg-memory moves.  */
1694   if (optimize_size)
1695     return 2;
1696
1697   /* There are some stalls involved when moving from a DREG to a different
1698      class reg, and using the value in one of the following instructions.
1699      Attempt to model this by slightly discouraging such moves.  */
1700   if (class1 == DREGS && class2 != DREGS)
1701     return 2 * 2;
1702
1703   return 2;
1704 }
1705
1706 /* Return the cost of moving data of mode M between a
1707    register and memory.  A value of 2 is the default; this cost is
1708    relative to those in `REGISTER_MOVE_COST'.
1709
1710    ??? In theory L1 memory has single-cycle latency.  We should add a switch
1711    that tells the compiler whether we expect to use only L1 memory for the
1712    program; it'll make the costs more accurate.  */
1713
1714 int
1715 bfin_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
1716                        enum reg_class class,
1717                        int in ATTRIBUTE_UNUSED)
1718 {
1719   /* Make memory accesses slightly more expensive than any register-register
1720      move.  Also, penalize non-DP registers, since they need secondary
1721      reloads to load and store.  */
1722   if (! reg_class_subset_p (class, DPREGS))
1723     return 10;
1724
1725   return 8;
1726 }
1727
1728 /* Inform reload about cases where moving X with a mode MODE to a register in
1729    CLASS requires an extra scratch register.  Return the class needed for the
1730    scratch register.  */
1731
1732 static enum reg_class
1733 bfin_secondary_reload (bool in_p, rtx x, enum reg_class class,
1734                      enum machine_mode mode, secondary_reload_info *sri)
1735 {
1736   /* If we have HImode or QImode, we can only use DREGS as secondary registers;
1737      in most other cases we can also use PREGS.  */
1738   enum reg_class default_class = GET_MODE_SIZE (mode) >= 4 ? DPREGS : DREGS;
1739   enum reg_class x_class = NO_REGS;
1740   enum rtx_code code = GET_CODE (x);
1741
1742   if (code == SUBREG)
1743     x = SUBREG_REG (x), code = GET_CODE (x);
1744   if (REG_P (x))
1745     {
1746       int regno = REGNO (x);
1747       if (regno >= FIRST_PSEUDO_REGISTER)
1748         regno = reg_renumber[regno];
1749
1750       if (regno == -1)
1751         code = MEM;
1752       else
1753         x_class = REGNO_REG_CLASS (regno);
1754     }
1755
1756   /* We can be asked to reload (plus (FP) (large_constant)) into a DREG.
1757      This happens as a side effect of register elimination, and we need
1758      a scratch register to do it.  */
1759   if (fp_plus_const_operand (x, mode))
1760     {
1761       rtx op2 = XEXP (x, 1);
1762       int large_constant_p = ! CONST_7BIT_IMM_P (INTVAL (op2));
1763
1764       if (class == PREGS || class == PREGS_CLOBBERED)
1765         return NO_REGS;
1766       /* If destination is a DREG, we can do this without a scratch register
1767          if the constant is valid for an add instruction.  */
1768       if ((class == DREGS || class == DPREGS)
1769           && ! large_constant_p)
1770         return NO_REGS;
1771       /* Reloading to anything other than a DREG?  Use a PREG scratch
1772          register.  */
1773       sri->icode = CODE_FOR_reload_insi;
1774       return NO_REGS;
1775     }
1776
1777   /* Data can usually be moved freely between registers of most classes.
1778      AREGS are an exception; they can only move to or from another register
1779      in AREGS or one in DREGS.  They can also be assigned the constant 0.  */
1780   if (x_class == AREGS)
1781     return class == DREGS || class == AREGS ? NO_REGS : DREGS;
1782
1783   if (class == AREGS)
1784     {
1785       if (x != const0_rtx && x_class != DREGS)
1786         return DREGS;
1787       else
1788         return NO_REGS;
1789     }
1790
1791   /* CCREGS can only be moved from/to DREGS.  */
1792   if (class == CCREGS && x_class != DREGS)
1793     return DREGS;
1794   if (x_class == CCREGS && class != DREGS)
1795     return DREGS;
1796
1797   /* All registers other than AREGS can load arbitrary constants.  The only
1798      case that remains is MEM.  */
1799   if (code == MEM)
1800     if (! reg_class_subset_p (class, default_class))
1801       return default_class;
1802   return NO_REGS;
1803 }
1804 \f
1805 /* Implement TARGET_HANDLE_OPTION.  */
1806
1807 static bool
1808 bfin_handle_option (size_t code, const char *arg, int value)
1809 {
1810   switch (code)
1811     {
1812     case OPT_mshared_library_id_:
1813       if (value > MAX_LIBRARY_ID)
1814         error ("-mshared-library-id=%s is not between 0 and %d",
1815                arg, MAX_LIBRARY_ID);
1816       bfin_lib_id_given = 1;
1817       return true;
1818
1819     default:
1820       return true;
1821     }
1822 }
1823
1824 /* Implement the macro OVERRIDE_OPTIONS.  */
1825
1826 void
1827 override_options (void)
1828 {
1829   if (TARGET_OMIT_LEAF_FRAME_POINTER)
1830     flag_omit_frame_pointer = 1;
1831
1832   /* Library identification */
1833   if (bfin_lib_id_given && ! TARGET_ID_SHARED_LIBRARY)
1834     error ("-mshared-library-id= specified without -mid-shared-library");
1835
1836   if (TARGET_ID_SHARED_LIBRARY)
1837     /* ??? Provide a way to use a bigger GOT.  */
1838     flag_pic = 1;
1839
1840   flag_schedule_insns = 0;
1841 }
1842
1843 /* Return the destination address of BRANCH.
1844    We need to use this instead of get_attr_length, because the
1845    cbranch_with_nops pattern conservatively sets its length to 6, and
1846    we still prefer to use shorter sequences.  */
1847
1848 static int
1849 branch_dest (rtx branch)
1850 {
1851   rtx dest;
1852   int dest_uid;
1853   rtx pat = PATTERN (branch);
1854   if (GET_CODE (pat) == PARALLEL)
1855     pat = XVECEXP (pat, 0, 0);
1856   dest = SET_SRC (pat);
1857   if (GET_CODE (dest) == IF_THEN_ELSE)
1858     dest = XEXP (dest, 1);
1859   dest = XEXP (dest, 0);
1860   dest_uid = INSN_UID (dest);
1861   return INSN_ADDRESSES (dest_uid);
1862 }
1863
1864 /* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates
1865    it's a branch that's predicted taken.  */
1866
1867 static int
1868 cbranch_predicted_taken_p (rtx insn)
1869 {
1870   rtx x = find_reg_note (insn, REG_BR_PROB, 0);
1871
1872   if (x)
1873     {
1874       int pred_val = INTVAL (XEXP (x, 0));
1875
1876       return pred_val >= REG_BR_PROB_BASE / 2;
1877     }
1878
1879   return 0;
1880 }
1881
1882 /* Templates for use by asm_conditional_branch.  */
1883
1884 static const char *ccbranch_templates[][3] = {
1885   { "if !cc jump %3;",  "if cc jump 4 (bp); jump.s %3;",  "if cc jump 6 (bp); jump.l %3;" },
1886   { "if cc jump %3;",   "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" },
1887   { "if !cc jump %3 (bp);",  "if cc jump 4; jump.s %3;",  "if cc jump 6; jump.l %3;" },
1888   { "if cc jump %3 (bp);",  "if !cc jump 4; jump.s %3;",  "if !cc jump 6; jump.l %3;" },
1889 };
1890
1891 /* Output INSN, which is a conditional branch instruction with operands
1892    OPERANDS.
1893
1894    We deal with the various forms of conditional branches that can be generated
1895    by bfin_reorg to prevent the hardware from doing speculative loads, by
1896    - emitting a sufficient number of nops, if N_NOPS is nonzero, or
1897    - always emitting the branch as predicted taken, if PREDICT_TAKEN is true.
1898    Either of these is only necessary if the branch is short, otherwise the
1899    template we use ends in an unconditional jump which flushes the pipeline
1900    anyway.  */
1901
1902 void
1903 asm_conditional_branch (rtx insn, rtx *operands, int n_nops, int predict_taken)
1904 {
1905   int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
1906   /* Note : offset for instructions like if cc jmp; jump.[sl] offset
1907             is to be taken from start of if cc rather than jump.
1908             Range for jump.s is (-4094, 4096) instead of (-4096, 4094)
1909   */
1910   int len = (offset >= -1024 && offset <= 1022 ? 0
1911              : offset >= -4094 && offset <= 4096 ? 1
1912              : 2);
1913   int bp = predict_taken && len == 0 ? 1 : cbranch_predicted_taken_p (insn);
1914   int idx = (bp << 1) | (GET_CODE (operands[0]) == EQ ? BRF : BRT);
1915   output_asm_insn (ccbranch_templates[idx][len], operands);
1916   gcc_assert (n_nops == 0 || !bp);
1917   if (len == 0)
1918     while (n_nops-- > 0)
1919       output_asm_insn ("nop;", NULL);
1920 }
1921
1922 /* Emit rtl for a comparison operation CMP in mode MODE.  Operands have been
1923    stored in bfin_compare_op0 and bfin_compare_op1 already.  */
1924
1925 rtx
1926 bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED)
1927 {
1928   enum rtx_code code1, code2;
1929   rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1;
1930   rtx tem = bfin_cc_rtx;
1931   enum rtx_code code = GET_CODE (cmp);
1932
1933   /* If we have a BImode input, then we already have a compare result, and
1934      do not need to emit another comparison.  */
1935   if (GET_MODE (op0) == BImode)
1936     {
1937       gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
1938       tem = op0, code2 = code;
1939     }
1940   else
1941     {
1942       switch (code) {
1943         /* bfin has these conditions */
1944       case EQ:
1945       case LT:
1946       case LE:
1947       case LEU:
1948       case LTU:
1949         code1 = code;
1950         code2 = NE;
1951         break;
1952       default:
1953         code1 = reverse_condition (code);
1954         code2 = EQ;
1955         break;
1956       }
1957       emit_insn (gen_rtx_SET (BImode, tem,
1958                               gen_rtx_fmt_ee (code1, BImode, op0, op1)));
1959     }
1960
1961   return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode));
1962 }
1963 \f
1964 /* Return nonzero iff C has exactly one bit set if it is interpreted
1965    as a 32 bit constant.  */
1966
1967 int
1968 log2constp (unsigned HOST_WIDE_INT c)
1969 {
1970   c &= 0xFFFFFFFF;
1971   return c != 0 && (c & (c-1)) == 0;
1972 }
1973
1974 /* Returns the number of consecutive least significant zeros in the binary
1975    representation of *V.
1976    We modify *V to contain the original value arithmetically shifted right by
1977    the number of zeroes.  */
1978
1979 static int
1980 shiftr_zero (HOST_WIDE_INT *v)
1981 {
1982   unsigned HOST_WIDE_INT tmp = *v;
1983   unsigned HOST_WIDE_INT sgn;
1984   int n = 0;
1985
1986   if (tmp == 0)
1987     return 0;
1988
1989   sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1));
1990   while ((tmp & 0x1) == 0 && n <= 32)
1991     {
1992       tmp = (tmp >> 1) | sgn;
1993       n++;
1994     }
1995   *v = tmp;
1996   return n;
1997 }
1998
1999 /* After reload, split the load of an immediate constant.  OPERANDS are the
2000    operands of the movsi_insn pattern which we are splitting.  We return
2001    nonzero if we emitted a sequence to load the constant, zero if we emitted
2002    nothing because we want to use the splitter's default sequence.  */
2003
2004 int
2005 split_load_immediate (rtx operands[])
2006 {
2007   HOST_WIDE_INT val = INTVAL (operands[1]);
2008   HOST_WIDE_INT tmp;
2009   HOST_WIDE_INT shifted = val;
2010   HOST_WIDE_INT shifted_compl = ~val;
2011   int num_zero = shiftr_zero (&shifted);
2012   int num_compl_zero = shiftr_zero (&shifted_compl);
2013   unsigned int regno = REGNO (operands[0]);
2014   enum reg_class class1 = REGNO_REG_CLASS (regno);
2015
2016   /* This case takes care of single-bit set/clear constants, which we could
2017      also implement with BITSET/BITCLR.  */
2018   if (num_zero
2019       && shifted >= -32768 && shifted < 65536
2020       && (D_REGNO_P (regno)
2021           || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))
2022     {
2023       emit_insn (gen_movsi (operands[0], GEN_INT (shifted)));
2024       emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));
2025       return 1;
2026     }
2027
2028   tmp = val & 0xFFFF;
2029   tmp |= -(tmp & 0x8000);
2030
2031   /* If high word has one bit set or clear, try to use a bit operation.  */
2032   if (D_REGNO_P (regno))
2033     {
2034       if (log2constp (val & 0xFFFF0000))
2035         {
2036           emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));
2037           emit_insn (gen_iorsi3 (operands[0], operands[0], GEN_INT (val & 0xFFFF0000)));
2038           return 1;
2039         }
2040       else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)
2041         {
2042           emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2043           emit_insn (gen_andsi3 (operands[0], operands[0], GEN_INT (val | 0xFFFF)));
2044         }
2045     }
2046
2047   if (D_REGNO_P (regno))
2048     {
2049       if (CONST_7BIT_IMM_P (tmp))
2050         {
2051           emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2052           emit_insn (gen_movstricthi_high (operands[0], GEN_INT (val & -65536)));
2053           return 1;
2054         }
2055
2056       if ((val & 0xFFFF0000) == 0)
2057         {
2058           emit_insn (gen_movsi (operands[0], const0_rtx));
2059           emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2060           return 1;
2061         }
2062
2063       if ((val & 0xFFFF0000) == 0xFFFF0000)
2064         {
2065           emit_insn (gen_movsi (operands[0], constm1_rtx));
2066           emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2067           return 1;
2068         }
2069     }
2070
2071   /* Need DREGs for the remaining case.  */
2072   if (regno > REG_R7)
2073     return 0;
2074
2075   if (optimize_size
2076       && num_compl_zero && CONST_7BIT_IMM_P (shifted_compl))
2077     {
2078       /* If optimizing for size, generate a sequence that has more instructions
2079          but is shorter.  */
2080       emit_insn (gen_movsi (operands[0], GEN_INT (shifted_compl)));
2081       emit_insn (gen_ashlsi3 (operands[0], operands[0],
2082                               GEN_INT (num_compl_zero)));
2083       emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
2084       return 1;
2085     }
2086   return 0;
2087 }
2088 \f
2089 /* Return true if the legitimate memory address for a memory operand of mode
2090    MODE.  Return false if not.  */
2091
2092 static bool
2093 bfin_valid_add (enum machine_mode mode, HOST_WIDE_INT value)
2094 {
2095   unsigned HOST_WIDE_INT v = value > 0 ? value : -value;
2096   int sz = GET_MODE_SIZE (mode);
2097   int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2;
2098   /* The usual offsettable_memref machinery doesn't work so well for this
2099      port, so we deal with the problem here.  */
2100   unsigned HOST_WIDE_INT mask = sz == 8 ? 0x7ffe : 0x7fff;
2101   return (v & ~(mask << shift)) == 0;
2102 }
2103
2104 static bool
2105 bfin_valid_reg_p (unsigned int regno, int strict)
2106 {
2107   return ((strict && REGNO_OK_FOR_BASE_STRICT_P (regno))
2108           || (!strict && REGNO_OK_FOR_BASE_NONSTRICT_P (regno)));
2109 }
2110
2111 bool
2112 bfin_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
2113 {
2114   switch (GET_CODE (x)) {
2115   case REG:
2116     if (bfin_valid_reg_p (REGNO (x), strict))
2117       return true;
2118     break;
2119   case PLUS:
2120     if (REG_P (XEXP (x, 0))
2121         && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict)
2122         && (GET_CODE (XEXP (x, 1)) == UNSPEC
2123             || (GET_CODE (XEXP (x, 1)) == CONST_INT
2124                 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
2125       return true;
2126     break;
2127   case POST_INC:
2128   case POST_DEC:
2129     if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2130         && REG_P (XEXP (x, 0))
2131         && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict))
2132       return true;
2133   case PRE_DEC:
2134     if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2135         && XEXP (x, 0) == stack_pointer_rtx
2136         && REG_P (XEXP (x, 0))
2137         && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict))
2138       return true;
2139     break;
2140   default:
2141     break;
2142   }
2143   return false;
2144 }
2145
2146 static bool
2147 bfin_rtx_costs (rtx x, int code, int outer_code, int *total)
2148 {
2149   int cost2 = COSTS_N_INSNS (1);
2150
2151   switch (code)
2152     {
2153     case CONST_INT:
2154       if (outer_code == SET || outer_code == PLUS)
2155         *total = CONST_7BIT_IMM_P (INTVAL (x)) ? 0 : cost2;
2156       else if (outer_code == AND)
2157         *total = log2constp (~INTVAL (x)) ? 0 : cost2;
2158       else if (outer_code == LE || outer_code == LT || outer_code == EQ)
2159         *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
2160       else if (outer_code == LEU || outer_code == LTU)
2161         *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
2162       else if (outer_code == MULT)
2163         *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
2164       else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
2165         *total = 0;
2166       else if (outer_code == ASHIFT || outer_code == ASHIFTRT
2167                || outer_code == LSHIFTRT)
2168         *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
2169       else if (outer_code == IOR || outer_code == XOR)
2170         *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
2171       else
2172         *total = cost2;
2173       return true;
2174
2175     case CONST:
2176     case LABEL_REF:
2177     case SYMBOL_REF:
2178     case CONST_DOUBLE:
2179       *total = COSTS_N_INSNS (2);
2180       return true;
2181
2182     case PLUS:
2183       if (GET_MODE (x) == Pmode)
2184         {
2185           if (GET_CODE (XEXP (x, 0)) == MULT
2186               && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
2187             {
2188               HOST_WIDE_INT val = INTVAL (XEXP (XEXP (x, 0), 1));
2189               if (val == 2 || val == 4)
2190                 {
2191                   *total = cost2;
2192                   *total += rtx_cost (XEXP (XEXP (x, 0), 0), outer_code);
2193                   *total += rtx_cost (XEXP (x, 1), outer_code);
2194                   return true;
2195                 }
2196             }
2197         }
2198
2199       /* fall through */
2200
2201     case MINUS:
2202     case ASHIFT: 
2203     case ASHIFTRT:
2204     case LSHIFTRT:
2205       if (GET_MODE (x) == DImode)
2206         *total = 6 * cost2;
2207       return false;
2208           
2209     case AND:
2210     case IOR:
2211     case XOR:
2212       if (GET_MODE (x) == DImode)
2213         *total = 2 * cost2;
2214       return false;
2215
2216     case MULT:
2217       if (GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD)
2218         *total = COSTS_N_INSNS (3);
2219       return false;
2220
2221     default:
2222       return false;
2223     }
2224 }
2225
2226 static void
2227 bfin_internal_label (FILE *stream, const char *prefix, unsigned long num)
2228 {
2229   fprintf (stream, "%s%s$%ld:\n", LOCAL_LABEL_PREFIX, prefix, num);
2230 }
2231 \f
2232 /* Used for communication between {push,pop}_multiple_operation (which
2233    we use not only as a predicate) and the corresponding output functions.  */
2234 static int first_preg_to_save, first_dreg_to_save;
2235
2236 int
2237 push_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2238 {
2239   int lastdreg = 8, lastpreg = 6;
2240   int i, group;
2241
2242   first_preg_to_save = lastpreg;
2243   first_dreg_to_save = lastdreg;
2244   for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
2245     {
2246       rtx t = XVECEXP (op, 0, i);
2247       rtx src, dest;
2248       int regno;
2249
2250       if (GET_CODE (t) != SET)
2251         return 0;
2252
2253       src = SET_SRC (t);
2254       dest = SET_DEST (t);
2255       if (GET_CODE (dest) != MEM || ! REG_P (src))
2256         return 0;
2257       dest = XEXP (dest, 0);
2258       if (GET_CODE (dest) != PLUS
2259           || ! REG_P (XEXP (dest, 0))
2260           || REGNO (XEXP (dest, 0)) != REG_SP
2261           || GET_CODE (XEXP (dest, 1)) != CONST_INT
2262           || INTVAL (XEXP (dest, 1)) != -i * 4)
2263         return 0;
2264
2265       regno = REGNO (src);
2266       if (group == 0)
2267         {
2268           if (D_REGNO_P (regno))
2269             {
2270               group = 1;
2271               first_dreg_to_save = lastdreg = regno - REG_R0;
2272             }
2273           else if (regno >= REG_P0 && regno <= REG_P7)
2274             {
2275               group = 2;
2276               first_preg_to_save = lastpreg = regno - REG_P0;
2277             }
2278           else
2279             return 0;
2280
2281           continue;
2282         }
2283
2284       if (group == 1)
2285         {
2286           if (regno >= REG_P0 && regno <= REG_P7)
2287             {
2288               group = 2;
2289               first_preg_to_save = lastpreg = regno - REG_P0;
2290             }
2291           else if (regno != REG_R0 + lastdreg + 1)
2292             return 0;
2293           else
2294             lastdreg++;
2295         }
2296       else if (group == 2)
2297         {
2298           if (regno != REG_P0 + lastpreg + 1)
2299             return 0;
2300           lastpreg++;
2301         }
2302     }
2303   return 1;
2304 }
2305
2306 int
2307 pop_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2308 {
2309   int lastdreg = 8, lastpreg = 6;
2310   int i, group;
2311
2312   for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
2313     {
2314       rtx t = XVECEXP (op, 0, i);
2315       rtx src, dest;
2316       int regno;
2317
2318       if (GET_CODE (t) != SET)
2319         return 0;
2320
2321       src = SET_SRC (t);
2322       dest = SET_DEST (t);
2323       if (GET_CODE (src) != MEM || ! REG_P (dest))
2324         return 0;
2325       src = XEXP (src, 0);
2326
2327       if (i == 1)
2328         {
2329           if (! REG_P (src) || REGNO (src) != REG_SP)
2330             return 0;
2331         }
2332       else if (GET_CODE (src) != PLUS
2333                || ! REG_P (XEXP (src, 0))
2334                || REGNO (XEXP (src, 0)) != REG_SP
2335                || GET_CODE (XEXP (src, 1)) != CONST_INT
2336                || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
2337         return 0;
2338
2339       regno = REGNO (dest);
2340       if (group == 0)
2341         {
2342           if (regno == REG_R7)
2343             {
2344               group = 1;
2345               lastdreg = 7;
2346             }
2347           else if (regno != REG_P0 + lastpreg - 1)
2348             return 0;
2349           else
2350             lastpreg--;
2351         }
2352       else if (group == 1)
2353         {
2354           if (regno != REG_R0 + lastdreg - 1)
2355             return 0;
2356           else
2357             lastdreg--;
2358         }
2359     }
2360   first_dreg_to_save = lastdreg;
2361   first_preg_to_save = lastpreg;
2362   return 1;
2363 }
2364
2365 /* Emit assembly code for one multi-register push described by INSN, with
2366    operands in OPERANDS.  */
2367
2368 void
2369 output_push_multiple (rtx insn, rtx *operands)
2370 {
2371   char buf[80];
2372   int ok;
2373   
2374   /* Validate the insn again, and compute first_[dp]reg_to_save. */
2375   ok = push_multiple_operation (PATTERN (insn), VOIDmode);
2376   gcc_assert (ok);
2377   
2378   if (first_dreg_to_save == 8)
2379     sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
2380   else if (first_preg_to_save == 6)
2381     sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
2382   else
2383     sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
2384              first_dreg_to_save, first_preg_to_save);
2385
2386   output_asm_insn (buf, operands);
2387 }
2388
2389 /* Emit assembly code for one multi-register pop described by INSN, with
2390    operands in OPERANDS.  */
2391
2392 void
2393 output_pop_multiple (rtx insn, rtx *operands)
2394 {
2395   char buf[80];
2396   int ok;
2397   
2398   /* Validate the insn again, and compute first_[dp]reg_to_save. */
2399   ok = pop_multiple_operation (PATTERN (insn), VOIDmode);
2400   gcc_assert (ok);
2401
2402   if (first_dreg_to_save == 8)
2403     sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
2404   else if (first_preg_to_save == 6)
2405     sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
2406   else
2407     sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
2408              first_dreg_to_save, first_preg_to_save);
2409
2410   output_asm_insn (buf, operands);
2411 }
2412
2413 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE.  */
2414
2415 static void
2416 single_move_for_strmov (rtx dst, rtx src, enum machine_mode mode, HOST_WIDE_INT offset)
2417 {
2418   rtx scratch = gen_reg_rtx (mode);
2419   rtx srcmem, dstmem;
2420
2421   srcmem = adjust_address_nv (src, mode, offset);
2422   dstmem = adjust_address_nv (dst, mode, offset);
2423   emit_move_insn (scratch, srcmem);
2424   emit_move_insn (dstmem, scratch);
2425 }
2426
2427 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
2428    alignment ALIGN_EXP.  Return true if successful, false if we should fall
2429    back on a different method.  */
2430
2431 bool
2432 bfin_expand_strmov (rtx dst, rtx src, rtx count_exp, rtx align_exp)
2433 {
2434   rtx srcreg, destreg, countreg;
2435   HOST_WIDE_INT align = 0;
2436   unsigned HOST_WIDE_INT count = 0;
2437
2438   if (GET_CODE (align_exp) == CONST_INT)
2439     align = INTVAL (align_exp);
2440   if (GET_CODE (count_exp) == CONST_INT)
2441     {
2442       count = INTVAL (count_exp);
2443 #if 0
2444       if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
2445         return false;
2446 #endif
2447     }
2448
2449   /* If optimizing for size, only do single copies inline.  */
2450   if (optimize_size)
2451     {
2452       if (count == 2 && align < 2)
2453         return false;
2454       if (count == 4 && align < 4)
2455         return false;
2456       if (count != 1 && count != 2 && count != 4)
2457         return false;
2458     }
2459   if (align < 2 && count != 1)
2460     return false;
2461
2462   destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
2463   if (destreg != XEXP (dst, 0))
2464     dst = replace_equiv_address_nv (dst, destreg);
2465   srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
2466   if (srcreg != XEXP (src, 0))
2467     src = replace_equiv_address_nv (src, srcreg);
2468
2469   if (count != 0 && align >= 2)
2470     {
2471       unsigned HOST_WIDE_INT offset = 0;
2472
2473       if (align >= 4)
2474         {
2475           if ((count & ~3) == 4)
2476             {
2477               single_move_for_strmov (dst, src, SImode, offset);
2478               offset = 4;
2479             }
2480           else if (count & ~3)
2481             {
2482               HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
2483               countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
2484
2485               emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
2486             }
2487           if (count & 2)
2488             {
2489               single_move_for_strmov (dst, src, HImode, offset);
2490               offset += 2;
2491             }
2492         }
2493       else
2494         {
2495           if ((count & ~1) == 2)
2496             {
2497               single_move_for_strmov (dst, src, HImode, offset);
2498               offset = 2;
2499             }
2500           else if (count & ~1)
2501             {
2502               HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
2503               countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
2504
2505               emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
2506             }
2507         }
2508       if (count & 1)
2509         {
2510           single_move_for_strmov (dst, src, QImode, offset);
2511         }
2512       return true;
2513     }
2514   return false;
2515 }
2516
2517 \f
2518 static int
2519 bfin_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
2520 {
2521   enum attr_type insn_type, dep_insn_type;
2522   int dep_insn_code_number;
2523
2524   /* Anti and output dependencies have zero cost.  */
2525   if (REG_NOTE_KIND (link) != 0)
2526     return 0;
2527
2528   dep_insn_code_number = recog_memoized (dep_insn);
2529
2530   /* If we can't recognize the insns, we can't really do anything.  */
2531   if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
2532     return cost;
2533
2534   insn_type = get_attr_type (insn);
2535   dep_insn_type = get_attr_type (dep_insn);
2536
2537   if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)
2538     {
2539       rtx pat = PATTERN (dep_insn);
2540       rtx dest = SET_DEST (pat);
2541       rtx src = SET_SRC (pat);
2542       if (! ADDRESS_REGNO_P (REGNO (dest)) || ! D_REGNO_P (REGNO (src)))
2543         return cost;
2544       return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);
2545     }
2546
2547   return cost;
2548 }
2549 \f
2550 /* We use the machine specific reorg pass for emitting CSYNC instructions
2551    after conditional branches as needed.
2552
2553    The Blackfin is unusual in that a code sequence like
2554      if cc jump label
2555      r0 = (p0)
2556    may speculatively perform the load even if the condition isn't true.  This
2557    happens for a branch that is predicted not taken, because the pipeline
2558    isn't flushed or stalled, so the early stages of the following instructions,
2559    which perform the memory reference, are allowed to execute before the
2560    jump condition is evaluated.
2561    Therefore, we must insert additional instructions in all places where this
2562    could lead to incorrect behavior.  The manual recommends CSYNC, while
2563    VDSP seems to use NOPs (even though its corresponding compiler option is
2564    named CSYNC).
2565
2566    When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
2567    When optimizing for size, we turn the branch into a predicted taken one.
2568    This may be slower due to mispredicts, but saves code size.  */
2569
2570 static void
2571 bfin_reorg (void)
2572 {
2573   rtx insn, last_condjump = NULL_RTX;
2574   int cycles_since_jump = INT_MAX;
2575
2576   if (! TARGET_SPECLD_ANOMALY || ! TARGET_CSYNC_ANOMALY)
2577     return;
2578
2579   /* First pass: find predicted-false branches; if something after them
2580      needs nops, insert them or change the branch to predict true.  */
2581   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2582     {
2583       rtx pat;
2584
2585       if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
2586         continue;
2587
2588       pat = PATTERN (insn);
2589       if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
2590           || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
2591           || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
2592         continue;
2593
2594       if (JUMP_P (insn))
2595         {
2596           if (any_condjump_p (insn)
2597               && ! cbranch_predicted_taken_p (insn))
2598             {
2599               last_condjump = insn;
2600               cycles_since_jump = 0;
2601             }
2602           else
2603             cycles_since_jump = INT_MAX;
2604         }
2605       else if (INSN_P (insn))
2606         {
2607           enum attr_type type = get_attr_type (insn);
2608           int delay_needed = 0;
2609           if (cycles_since_jump < INT_MAX)
2610             cycles_since_jump++;
2611
2612           if (type == TYPE_MCLD && TARGET_SPECLD_ANOMALY)
2613             {
2614               rtx pat = single_set (insn);
2615               if (may_trap_p (SET_SRC (pat)))
2616                 delay_needed = 3;
2617             }
2618           else if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
2619             delay_needed = 4;
2620
2621           if (delay_needed > cycles_since_jump)
2622             {
2623               rtx pat;
2624               int num_clobbers;
2625               rtx *op = recog_data.operand;
2626
2627               delay_needed -= cycles_since_jump;
2628
2629               extract_insn (last_condjump);
2630               if (optimize_size)
2631                 {
2632                   pat = gen_cbranch_predicted_taken (op[0], op[1], op[2],
2633                                                      op[3]);
2634                   cycles_since_jump = INT_MAX;
2635                 }
2636               else
2637                 /* Do not adjust cycles_since_jump in this case, so that
2638                    we'll increase the number of NOPs for a subsequent insn
2639                    if necessary.  */
2640                 pat = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
2641                                              GEN_INT (delay_needed));
2642               PATTERN (last_condjump) = pat;
2643               INSN_CODE (last_condjump) = recog (pat, insn, &num_clobbers);
2644             }
2645         }
2646     }
2647   /* Second pass: for predicted-true branches, see if anything at the
2648      branch destination needs extra nops.  */
2649   if (! TARGET_CSYNC_ANOMALY)
2650     return;
2651
2652   for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2653     {
2654       if (JUMP_P (insn)
2655           && any_condjump_p (insn)
2656           && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken
2657               || cbranch_predicted_taken_p (insn)))
2658         {
2659           rtx target = JUMP_LABEL (insn);
2660           rtx label = target;
2661           cycles_since_jump = 0;
2662           for (; target && cycles_since_jump < 3; target = NEXT_INSN (target))
2663             {
2664               rtx pat;
2665
2666               if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
2667                 continue;
2668
2669               pat = PATTERN (target);
2670               if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
2671                   || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
2672                   || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
2673                 continue;
2674
2675               if (INSN_P (target))
2676                 {
2677                   enum attr_type type = get_attr_type (target);
2678                   int delay_needed = 0;
2679                   if (cycles_since_jump < INT_MAX)
2680                     cycles_since_jump++;
2681
2682                   if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
2683                     delay_needed = 2;
2684
2685                   if (delay_needed > cycles_since_jump)
2686                     {
2687                       rtx prev = prev_real_insn (label);
2688                       delay_needed -= cycles_since_jump;
2689                       if (dump_file)
2690                         fprintf (dump_file, "Adding %d nops after %d\n",
2691                                  delay_needed, INSN_UID (label));
2692                       if (JUMP_P (prev)
2693                           && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops)
2694                         {
2695                           rtx x;
2696                           HOST_WIDE_INT v;
2697
2698                           if (dump_file)
2699                             fprintf (dump_file,
2700                                      "Reducing nops on insn %d.\n",
2701                                      INSN_UID (prev));
2702                           x = PATTERN (prev);
2703                           x = XVECEXP (x, 0, 1);
2704                           v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed;
2705                           XVECEXP (x, 0, 0) = GEN_INT (v);
2706                         }
2707                       while (delay_needed-- > 0)
2708                         emit_insn_after (gen_nop (), label);
2709                       break;
2710                     }
2711                 }
2712             }
2713         }
2714     }
2715 }
2716 \f
2717 /* Handle interrupt_handler, exception_handler and nmi_handler function
2718    attributes; arguments as in struct attribute_spec.handler.  */
2719
2720 static tree
2721 handle_int_attribute (tree *node, tree name,
2722                       tree args ATTRIBUTE_UNUSED,
2723                       int flags ATTRIBUTE_UNUSED,
2724                       bool *no_add_attrs)
2725 {
2726   tree x = *node;
2727   if (TREE_CODE (x) == FUNCTION_DECL)
2728     x = TREE_TYPE (x);
2729
2730   if (TREE_CODE (x) != FUNCTION_TYPE)
2731     {
2732       warning (OPT_Wattributes, "%qs attribute only applies to functions",
2733                IDENTIFIER_POINTER (name));
2734       *no_add_attrs = true;
2735     }
2736   else if (funkind (x) != SUBROUTINE)
2737     error ("multiple function type attributes specified");
2738
2739   return NULL_TREE;
2740 }
2741
2742 /* Return 0 if the attributes for two types are incompatible, 1 if they
2743    are compatible, and 2 if they are nearly compatible (which causes a
2744    warning to be generated).  */
2745
2746 static int
2747 bfin_comp_type_attributes (tree type1, tree type2)
2748 {
2749   e_funkind kind1, kind2;
2750
2751   if (TREE_CODE (type1) != FUNCTION_TYPE)
2752     return 1;
2753
2754   kind1 = funkind (type1);
2755   kind2 = funkind (type2);
2756
2757   if (kind1 != kind2)
2758     return 0;
2759   
2760   /*  Check for mismatched modifiers */
2761   if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
2762       != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
2763     return 0;
2764
2765   if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
2766       != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
2767     return 0;
2768
2769   if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
2770       != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
2771     return 0;
2772
2773   if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1))
2774       != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2)))
2775     return 0;
2776
2777   return 1;
2778 }
2779
2780 /* Handle a "longcall" or "shortcall" attribute; arguments as in
2781    struct attribute_spec.handler.  */
2782
2783 static tree
2784 bfin_handle_longcall_attribute (tree *node, tree name, 
2785                                 tree args ATTRIBUTE_UNUSED, 
2786                                 int flags ATTRIBUTE_UNUSED, 
2787                                 bool *no_add_attrs)
2788 {
2789   if (TREE_CODE (*node) != FUNCTION_TYPE
2790       && TREE_CODE (*node) != FIELD_DECL
2791       && TREE_CODE (*node) != TYPE_DECL)
2792     {
2793       warning (OPT_Wattributes, "`%s' attribute only applies to functions",
2794                IDENTIFIER_POINTER (name));
2795       *no_add_attrs = true;
2796     }
2797
2798   if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0
2799        && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node)))
2800       || (strcmp (IDENTIFIER_POINTER (name), "shortcall") == 0
2801           && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node))))
2802     {
2803       warning (OPT_Wattributes,
2804                "can't apply both longcall and shortcall attributes to the same function");
2805       *no_add_attrs = true;
2806     }
2807
2808   return NULL_TREE;
2809 }
2810
2811 /* Table of valid machine attributes.  */
2812 const struct attribute_spec bfin_attribute_table[] =
2813 {
2814   /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
2815   { "interrupt_handler", 0, 0, false, true,  true, handle_int_attribute },
2816   { "exception_handler", 0, 0, false, true,  true, handle_int_attribute },
2817   { "nmi_handler", 0, 0, false, true,  true, handle_int_attribute },
2818   { "nesting", 0, 0, false, true,  true, NULL },
2819   { "kspisusp", 0, 0, false, true,  true, NULL },
2820   { "saveall", 0, 0, false, true,  true, NULL },
2821   { "longcall",  0, 0, false, true,  true,  bfin_handle_longcall_attribute },
2822   { "shortcall", 0, 0, false, true,  true,  bfin_handle_longcall_attribute },
2823   { NULL, 0, 0, false, false, false, NULL }
2824 };
2825 \f
2826 /* Output the assembler code for a thunk function.  THUNK_DECL is the
2827    declaration for the thunk function itself, FUNCTION is the decl for
2828    the target function.  DELTA is an immediate constant offset to be
2829    added to THIS.  If VCALL_OFFSET is nonzero, the word at
2830    *(*this + vcall_offset) should be added to THIS.  */
2831
2832 static void
2833 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
2834                       tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
2835                       HOST_WIDE_INT vcall_offset, tree function)
2836 {
2837   rtx xops[3];
2838   /* The this parameter is passed as the first argument.  */
2839   rtx this = gen_rtx_REG (Pmode, REG_R0);
2840
2841   /* Adjust the this parameter by a fixed constant.  */
2842   if (delta)
2843     {
2844       xops[1] = this;
2845       if (delta >= -64 && delta <= 63)
2846         {
2847           xops[0] = GEN_INT (delta);
2848           output_asm_insn ("%1 += %0;", xops);
2849         }
2850       else if (delta >= -128 && delta < -64)
2851         {
2852           xops[0] = GEN_INT (delta + 64);
2853           output_asm_insn ("%1 += -64; %1 += %0;", xops);
2854         }
2855       else if (delta > 63 && delta <= 126)
2856         {
2857           xops[0] = GEN_INT (delta - 63);
2858           output_asm_insn ("%1 += 63; %1 += %0;", xops);
2859         }
2860       else
2861         {
2862           xops[0] = GEN_INT (delta);
2863           output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
2864         }
2865     }
2866
2867   /* Adjust the this parameter by a value stored in the vtable.  */
2868   if (vcall_offset)
2869     {
2870       rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
2871       rtx tmp = gen_rtx_REG (Pmode, REG_R2);
2872
2873       xops[1] = tmp;
2874       xops[2] = p2tmp;
2875       output_asm_insn ("%2 = r0; %2 = [%2];", xops);
2876
2877       /* Adjust the this parameter.  */
2878       xops[0] = gen_rtx_MEM (Pmode, plus_constant (p2tmp, vcall_offset));
2879       if (!memory_operand (xops[0], Pmode))
2880         {
2881           rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
2882           xops[0] = GEN_INT (vcall_offset);
2883           xops[1] = tmp2;
2884           output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
2885           xops[0] = gen_rtx_MEM (Pmode, p2tmp);
2886         }
2887       xops[2] = this;
2888       output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
2889     }
2890
2891   xops[0] = XEXP (DECL_RTL (function), 0);
2892   if (1 || !flag_pic || (*targetm.binds_local_p) (function))
2893     output_asm_insn ("jump.l\t%P0", xops);
2894 }
2895 \f
2896 /* Codes for all the Blackfin builtins.  */
2897 enum bfin_builtins
2898 {
2899   BFIN_BUILTIN_CSYNC,
2900   BFIN_BUILTIN_SSYNC,
2901   BFIN_BUILTIN_MAX
2902 };
2903
2904 #define def_builtin(NAME, TYPE, CODE)                                   \
2905 do {                                                                    \
2906   lang_hooks.builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD,     \
2907                                NULL, NULL_TREE);                        \
2908 } while (0)
2909
2910 /* Set up all builtin functions for this target.  */
2911 static void
2912 bfin_init_builtins (void)
2913 {
2914   tree void_ftype_void
2915     = build_function_type (void_type_node, void_list_node);
2916
2917   /* Add the remaining MMX insns with somewhat more complicated types.  */
2918   def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC);
2919   def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC);
2920 }
2921
2922 /* Expand an expression EXP that calls a built-in function,
2923    with result going to TARGET if that's convenient
2924    (and in mode MODE if that's convenient).
2925    SUBTARGET may be used as the target for computing one of EXP's operands.
2926    IGNORE is nonzero if the value is to be ignored.  */
2927
2928 static rtx
2929 bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
2930                      rtx subtarget ATTRIBUTE_UNUSED,
2931                      enum machine_mode mode ATTRIBUTE_UNUSED,
2932                      int ignore ATTRIBUTE_UNUSED)
2933 {
2934   tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
2935   unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
2936
2937   switch (fcode)
2938     {
2939     case BFIN_BUILTIN_CSYNC:
2940       emit_insn (gen_csync ());
2941       return 0;
2942     case BFIN_BUILTIN_SSYNC:
2943       emit_insn (gen_ssync ());
2944       return 0;
2945
2946     default:
2947       gcc_unreachable ();
2948     }
2949 }
2950 \f
2951 #undef TARGET_INIT_BUILTINS
2952 #define TARGET_INIT_BUILTINS bfin_init_builtins
2953
2954 #undef TARGET_EXPAND_BUILTIN
2955 #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
2956
2957 #undef TARGET_ASM_GLOBALIZE_LABEL
2958 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label 
2959
2960 #undef TARGET_ASM_FILE_START
2961 #define TARGET_ASM_FILE_START output_file_start
2962
2963 #undef TARGET_ATTRIBUTE_TABLE
2964 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
2965
2966 #undef TARGET_COMP_TYPE_ATTRIBUTES
2967 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
2968
2969 #undef TARGET_RTX_COSTS
2970 #define TARGET_RTX_COSTS bfin_rtx_costs
2971
2972 #undef  TARGET_ADDRESS_COST
2973 #define TARGET_ADDRESS_COST bfin_address_cost
2974
2975 #undef TARGET_ASM_INTERNAL_LABEL
2976 #define TARGET_ASM_INTERNAL_LABEL bfin_internal_label
2977
2978 #undef TARGET_MACHINE_DEPENDENT_REORG
2979 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
2980
2981 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
2982 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
2983
2984 #undef TARGET_ASM_OUTPUT_MI_THUNK
2985 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
2986 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
2987 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
2988
2989 #undef TARGET_SCHED_ADJUST_COST
2990 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
2991
2992 #undef TARGET_PROMOTE_PROTOTYPES
2993 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
2994 #undef TARGET_PROMOTE_FUNCTION_ARGS
2995 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
2996 #undef TARGET_PROMOTE_FUNCTION_RETURN
2997 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
2998
2999 #undef TARGET_ARG_PARTIAL_BYTES
3000 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
3001
3002 #undef TARGET_PASS_BY_REFERENCE
3003 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
3004
3005 #undef TARGET_SETUP_INCOMING_VARARGS
3006 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
3007
3008 #undef TARGET_STRUCT_VALUE_RTX
3009 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
3010
3011 #undef TARGET_VECTOR_MODE_SUPPORTED_P
3012 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
3013
3014 #undef TARGET_HANDLE_OPTION
3015 #define TARGET_HANDLE_OPTION bfin_handle_option
3016
3017 #undef TARGET_DEFAULT_TARGET_FLAGS
3018 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
3019
3020 #undef TARGET_SECONDARY_RELOAD
3021 #define TARGET_SECONDARY_RELOAD bfin_secondary_reload
3022
3023 struct gcc_target targetm = TARGET_INITIALIZER;