OSDN Git Service

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