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