OSDN Git Service

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