* common.opt (-Wattributes): New. Default true.
[official-gcc.git] / gcc / config / bfin / bfin.c
blob8f3e0547457b21de411aa591374f0564b50343b2
1 /* The Blackfin code generation auxiliary output file.
2 Copyright (C) 2005 Free Software Foundation, Inc.
3 Contributed by Analog Devices.
5 This file is part of GCC.
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.
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.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING. If not, write to
19 the Free Software Foundation, 59 Temple Place - Suite 330,
20 Boston, MA 02111-1307, USA. */
22 #include "config.h"
23 #include "system.h"
24 #include "coretypes.h"
25 #include "tm.h"
26 #include "rtl.h"
27 #include "regs.h"
28 #include "hard-reg-set.h"
29 #include "real.h"
30 #include "insn-config.h"
31 #include "conditions.h"
32 #include "insn-flags.h"
33 #include "output.h"
34 #include "insn-attr.h"
35 #include "tree.h"
36 #include "flags.h"
37 #include "except.h"
38 #include "function.h"
39 #include "input.h"
40 #include "target.h"
41 #include "target-def.h"
42 #include "expr.h"
43 #include "toplev.h"
44 #include "recog.h"
45 #include "ggc.h"
46 #include "integrate.h"
47 #include "bfin-protos.h"
48 #include "tm-preds.h"
49 #include "gt-bfin.h"
51 /* Test and compare insns in bfin.md store the information needed to
52 generate branch and scc insns here. */
53 rtx bfin_compare_op0, bfin_compare_op1;
55 /* RTX for condition code flag register and RETS register */
56 extern GTY(()) rtx bfin_cc_rtx;
57 extern GTY(()) rtx bfin_rets_rtx;
58 rtx bfin_cc_rtx, bfin_rets_rtx;
60 int max_arg_registers = 0;
62 /* Arrays used when emitting register names. */
63 const char *short_reg_names[] = SHORT_REGISTER_NAMES;
64 const char *high_reg_names[] = HIGH_REGISTER_NAMES;
65 const char *dregs_pair_names[] = DREGS_PAIR_NAMES;
66 const char *byte_reg_names[] = BYTE_REGISTER_NAMES;
68 static int arg_regs[] = FUNCTION_ARG_REGISTERS;
70 /* The value passed to -mshared-library-id=. */
71 static int bfin_library_id;
72 /* Nonzero if -mshared-library-id was given. */
73 static int bfin_lib_id_given;
75 static void
76 bfin_globalize_label (FILE *stream, const char *name)
78 fputs (".global ", stream);
79 assemble_name (stream, name);
80 fputc (';',stream);
81 fputc ('\n',stream);
84 static void
85 output_file_start (void)
87 FILE *file = asm_out_file;
88 int i;
90 fprintf (file, ".file \"%s\";\n", input_filename);
92 for (i = 0; arg_regs[i] >= 0; i++)
94 max_arg_registers = i; /* how many arg reg used */
97 /* Called early in the compilation to conditionally modify
98 fixed_regs/call_used_regs. */
100 void
101 conditional_register_usage (void)
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);
108 /* Examine machine-dependent attributes of function type FUNTYPE and return its
109 type. See the definition of E_FUNKIND. */
111 static e_funkind funkind (tree funtype)
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;
124 /* Stack frame layout. */
126 /* Compute the number of DREGS to save with a push_multiple operation.
127 This could include registers that aren't modified in the function,
128 since push_multiple only takes a range of registers. */
130 static int
131 n_dregs_to_save (void)
133 unsigned i;
135 for (i = REG_R0; i <= REG_R7; i++)
137 if (regs_ever_live[i] && ! call_used_regs[i])
138 return REG_R7 - i + 1;
140 if (current_function_calls_eh_return)
142 unsigned j;
143 for (j = 0; ; j++)
145 unsigned test = EH_RETURN_DATA_REGNO (j);
146 if (test == INVALID_REGNUM)
147 break;
148 if (test == i)
149 return REG_R7 - i + 1;
154 return 0;
157 /* Like n_dregs_to_save, but compute number of PREGS to save. */
159 static int
160 n_pregs_to_save (void)
162 unsigned i;
164 for (i = REG_P0; i <= REG_P5; i++)
165 if ((regs_ever_live[i] && ! call_used_regs[i])
166 || (i == PIC_OFFSET_TABLE_REGNUM
167 && (current_function_uses_pic_offset_table
168 || (TARGET_ID_SHARED_LIBRARY && ! current_function_is_leaf))))
169 return REG_P5 - i + 1;
170 return 0;
173 /* Determine if we are going to save the frame pointer in the prologue. */
175 static bool
176 must_save_fp_p (void)
178 return (frame_pointer_needed || regs_ever_live[REG_FP]);
181 static bool
182 stack_frame_needed_p (void)
184 /* EH return puts a new return address into the frame using an
185 address relative to the frame pointer. */
186 if (current_function_calls_eh_return)
187 return true;
188 return frame_pointer_needed;
191 /* Emit code to save registers in the prologue. SAVEALL is nonzero if we
192 must save all registers; this is used for interrupt handlers.
193 SPREG contains (reg:SI REG_SP). */
195 static void
196 expand_prologue_reg_save (rtx spreg, int saveall)
198 int ndregs = saveall ? 8 : n_dregs_to_save ();
199 int npregs = saveall ? 6 : n_pregs_to_save ();
200 int dregno = REG_R7 + 1 - ndregs;
201 int pregno = REG_P5 + 1 - npregs;
202 int total = ndregs + npregs;
203 int i;
204 rtx pat, insn, val;
206 if (total == 0)
207 return;
209 val = GEN_INT (-total * 4);
210 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total + 2));
211 XVECEXP (pat, 0, 0) = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, val),
212 UNSPEC_PUSH_MULTIPLE);
213 XVECEXP (pat, 0, total + 1) = gen_rtx_SET (VOIDmode, spreg,
214 gen_rtx_PLUS (Pmode, spreg,
215 val));
216 RTX_FRAME_RELATED_P (XVECEXP (pat, 0, total + 1)) = 1;
217 for (i = 0; i < total; i++)
219 rtx memref = gen_rtx_MEM (word_mode,
220 gen_rtx_PLUS (Pmode, spreg,
221 GEN_INT (- i * 4 - 4)));
222 rtx subpat;
223 if (ndregs > 0)
225 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
226 dregno++));
227 ndregs--;
229 else
231 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
232 pregno++));
233 npregs++;
235 XVECEXP (pat, 0, i + 1) = subpat;
236 RTX_FRAME_RELATED_P (subpat) = 1;
238 insn = emit_insn (pat);
239 RTX_FRAME_RELATED_P (insn) = 1;
242 /* Emit code to restore registers in the epilogue. SAVEALL is nonzero if we
243 must save all registers; this is used for interrupt handlers.
244 SPREG contains (reg:SI REG_SP). */
246 static void
247 expand_epilogue_reg_restore (rtx spreg, int saveall)
249 int ndregs = saveall ? 8 : n_dregs_to_save ();
250 int npregs = saveall ? 6 : n_pregs_to_save ();
251 int total = ndregs + npregs;
252 int i, regno;
253 rtx pat, insn;
255 if (total == 0)
256 return;
258 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total + 1));
259 XVECEXP (pat, 0, 0) = gen_rtx_SET (VOIDmode, spreg,
260 gen_rtx_PLUS (Pmode, spreg,
261 GEN_INT (total * 4)));
263 if (npregs > 0)
264 regno = REG_P5 + 1;
265 else
266 regno = REG_R7 + 1;
268 for (i = 0; i < total; i++)
270 rtx addr = (i > 0
271 ? gen_rtx_PLUS (Pmode, spreg, GEN_INT (i * 4))
272 : spreg);
273 rtx memref = gen_rtx_MEM (word_mode, addr);
275 regno--;
276 XVECEXP (pat, 0, i + 1)
277 = gen_rtx_SET (VOIDmode, gen_rtx_REG (word_mode, regno), memref);
279 if (npregs > 0)
281 if (--npregs == 0)
282 regno = REG_R7 + 1;
286 insn = emit_insn (pat);
287 RTX_FRAME_RELATED_P (insn) = 1;
290 /* Perform any needed actions needed for a function that is receiving a
291 variable number of arguments.
293 CUM is as above.
295 MODE and TYPE are the mode and type of the current parameter.
297 PRETEND_SIZE is a variable that should be set to the amount of stack
298 that must be pushed by the prolog to pretend that our caller pushed
301 Normally, this macro will push all remaining incoming registers on the
302 stack and set PRETEND_SIZE to the length of the registers pushed.
304 Blackfin specific :
305 - VDSP C compiler manual (our ABI) says that a variable args function
306 should save the R0, R1 and R2 registers in the stack.
307 - The caller will always leave space on the stack for the
308 arguments that are passed in registers, so we dont have
309 to leave any extra space.
310 - now, the vastart pointer can access all arguments from the stack. */
312 static void
313 setup_incoming_varargs (CUMULATIVE_ARGS *cum,
314 enum machine_mode mode ATTRIBUTE_UNUSED,
315 tree type ATTRIBUTE_UNUSED, int *pretend_size,
316 int no_rtl)
318 rtx mem;
319 int i;
321 if (no_rtl)
322 return;
324 /* The move for named arguments will be generated automatically by the
325 compiler. We need to generate the move rtx for the unnamed arguments
326 if they are in the first 3 words. We assume at least 1 named argument
327 exists, so we never generate [ARGP] = R0 here. */
329 for (i = cum->words + 1; i < max_arg_registers; i++)
331 mem = gen_rtx_MEM (Pmode,
332 plus_constant (arg_pointer_rtx, (i * UNITS_PER_WORD)));
333 emit_move_insn (mem, gen_rtx_REG (Pmode, i));
336 *pretend_size = 0;
339 /* Value should be nonzero if functions must have frame pointers.
340 Zero means the frame pointer need not be set up (and parms may
341 be accessed via the stack pointer) in functions that seem suitable. */
344 bfin_frame_pointer_required (void)
346 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
348 if (fkind != SUBROUTINE)
349 return 1;
351 /* We turn on on -fomit-frame-pointer if -momit-leaf-frame-pointer is used,
352 so we have to override it for non-leaf functions. */
353 if (TARGET_OMIT_LEAF_FRAME_POINTER && ! current_function_is_leaf)
354 return 1;
356 return 0;
359 /* Return the number of registers pushed during the prologue. */
361 static int
362 n_regs_saved_by_prologue (void)
364 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
365 int n = n_dregs_to_save () + n_pregs_to_save ();
367 if (stack_frame_needed_p ())
368 /* We use a LINK instruction in this case. */
369 n += 2;
370 else
372 if (must_save_fp_p ())
373 n++;
374 if (! current_function_is_leaf)
375 n++;
378 if (fkind != SUBROUTINE)
380 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
381 tree all = lookup_attribute ("saveall", attrs);
382 int i;
384 /* Increment once for ASTAT. */
385 n++;
387 /* RETE/X/N. */
388 if (lookup_attribute ("nesting", attrs))
389 n++;
391 for (i = REG_P7 + 1; i < REG_CC; i++)
392 if (all
393 || regs_ever_live[i]
394 || (!leaf_function_p () && call_used_regs[i]))
395 n += i == REG_A0 || i == REG_A1 ? 2 : 1;
397 return n;
400 /* Return the offset between two registers, one to be eliminated, and the other
401 its replacement, at the start of a routine. */
403 HOST_WIDE_INT
404 bfin_initial_elimination_offset (int from, int to)
406 HOST_WIDE_INT offset = 0;
408 if (from == ARG_POINTER_REGNUM)
409 offset = n_regs_saved_by_prologue () * 4;
411 if (to == STACK_POINTER_REGNUM)
413 if (current_function_outgoing_args_size >= FIXED_STACK_AREA)
414 offset += current_function_outgoing_args_size;
415 else if (current_function_outgoing_args_size)
416 offset += FIXED_STACK_AREA;
418 offset += get_frame_size ();
421 return offset;
424 /* Emit code to load a constant CONSTANT into register REG; setting
425 RTX_FRAME_RELATED_P on all insns we generate. Make sure that the insns
426 we generate need not be split. */
428 static void
429 frame_related_constant_load (rtx reg, HOST_WIDE_INT constant)
431 rtx insn;
432 rtx cst = GEN_INT (constant);
434 if (constant >= -32768 && constant < 65536)
435 insn = emit_move_insn (reg, cst);
436 else
438 /* We don't call split_load_immediate here, since dwarf2out.c can get
439 confused about some of the more clever sequences it can generate. */
440 insn = emit_insn (gen_movsi_high (reg, cst));
441 RTX_FRAME_RELATED_P (insn) = 1;
442 insn = emit_insn (gen_movsi_low (reg, reg, cst));
444 RTX_FRAME_RELATED_P (insn) = 1;
447 /* Generate efficient code to add a value to the frame pointer. We
448 can use P1 as a scratch register. Set RTX_FRAME_RELATED_P on the
449 generated insns if FRAME is nonzero. */
451 static void
452 add_to_sp (rtx spreg, HOST_WIDE_INT value, int frame)
454 if (value == 0)
455 return;
457 /* Choose whether to use a sequence using a temporary register, or
458 a sequence with multiple adds. We can add a signed 7 bit value
459 in one instruction. */
460 if (value > 120 || value < -120)
462 rtx tmpreg = gen_rtx_REG (SImode, REG_P1);
463 rtx insn;
465 if (frame)
466 frame_related_constant_load (tmpreg, value);
467 else
469 insn = emit_move_insn (tmpreg, GEN_INT (value));
470 if (frame)
471 RTX_FRAME_RELATED_P (insn) = 1;
474 insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg));
475 if (frame)
476 RTX_FRAME_RELATED_P (insn) = 1;
478 else
481 int size = value;
482 rtx insn;
484 if (size > 60)
485 size = 60;
486 else if (size < -60)
487 /* We could use -62, but that would leave the stack unaligned, so
488 it's no good. */
489 size = -60;
491 insn = emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (size)));
492 if (frame)
493 RTX_FRAME_RELATED_P (insn) = 1;
494 value -= size;
496 while (value != 0);
499 /* Generate a LINK insn for a frame sized FRAME_SIZE. If this constant
500 is too large, generate a sequence of insns that has the same effect.
501 SPREG contains (reg:SI REG_SP). */
503 static void
504 emit_link_insn (rtx spreg, HOST_WIDE_INT frame_size)
506 HOST_WIDE_INT link_size = frame_size;
507 rtx insn;
508 int i;
510 if (link_size > 262140)
511 link_size = 262140;
513 /* Use a LINK insn with as big a constant as possible, then subtract
514 any remaining size from the SP. */
515 insn = emit_insn (gen_link (GEN_INT (-8 - link_size)));
516 RTX_FRAME_RELATED_P (insn) = 1;
518 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
520 rtx set = XVECEXP (PATTERN (insn), 0, i);
521 gcc_assert (GET_CODE (set) == SET);
522 RTX_FRAME_RELATED_P (set) = 1;
525 frame_size -= link_size;
527 if (frame_size > 0)
529 /* Must use a call-clobbered PREG that isn't the static chain. */
530 rtx tmpreg = gen_rtx_REG (Pmode, REG_P1);
532 frame_related_constant_load (tmpreg, -frame_size);
533 insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg));
534 RTX_FRAME_RELATED_P (insn) = 1;
538 /* Return the number of bytes we must reserve for outgoing arguments
539 in the current function's stack frame. */
541 static HOST_WIDE_INT
542 arg_area_size (void)
544 if (current_function_outgoing_args_size)
546 if (current_function_outgoing_args_size >= FIXED_STACK_AREA)
547 return current_function_outgoing_args_size;
548 else
549 return FIXED_STACK_AREA;
551 return 0;
554 /* Save RETS and FP, and allocate a stack frame. */
556 static void
557 do_link (rtx spreg, HOST_WIDE_INT frame_size)
559 frame_size += arg_area_size ();
561 if (stack_frame_needed_p ()
562 || (must_save_fp_p () && ! current_function_is_leaf))
563 emit_link_insn (spreg, frame_size);
564 else
566 if (! current_function_is_leaf)
568 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
569 gen_rtx_PRE_DEC (Pmode, spreg)),
570 bfin_rets_rtx);
571 rtx insn = emit_insn (pat);
572 RTX_FRAME_RELATED_P (insn) = 1;
574 if (must_save_fp_p ())
576 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
577 gen_rtx_PRE_DEC (Pmode, spreg)),
578 gen_rtx_REG (Pmode, REG_FP));
579 rtx insn = emit_insn (pat);
580 RTX_FRAME_RELATED_P (insn) = 1;
582 add_to_sp (spreg, -frame_size, 1);
586 /* Like do_link, but used for epilogues to deallocate the stack frame. */
588 static void
589 do_unlink (rtx spreg, HOST_WIDE_INT frame_size)
591 frame_size += arg_area_size ();
593 if (stack_frame_needed_p ())
594 emit_insn (gen_unlink ());
595 else
597 rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg));
599 add_to_sp (spreg, frame_size, 0);
600 if (must_save_fp_p ())
602 rtx fpreg = gen_rtx_REG (Pmode, REG_FP);
603 emit_move_insn (fpreg, postinc);
604 emit_insn (gen_rtx_USE (VOIDmode, fpreg));
606 if (! current_function_is_leaf)
608 emit_move_insn (bfin_rets_rtx, postinc);
609 emit_insn (gen_rtx_USE (VOIDmode, bfin_rets_rtx));
614 /* Generate a prologue suitable for a function of kind FKIND. This is
615 called for interrupt and exception handler prologues.
616 SPREG contains (reg:SI REG_SP). */
618 static void
619 expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind)
621 int i;
622 HOST_WIDE_INT frame_size = get_frame_size ();
623 rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
624 rtx predec = gen_rtx_MEM (SImode, predec1);
625 rtx insn;
626 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
627 tree all = lookup_attribute ("saveall", attrs);
628 tree kspisusp = lookup_attribute ("kspisusp", attrs);
630 if (kspisusp)
632 insn = emit_move_insn (spreg, gen_rtx_REG (Pmode, REG_USP));
633 RTX_FRAME_RELATED_P (insn) = 1;
636 /* We need space on the stack in case we need to save the argument
637 registers. */
638 if (fkind == EXCPT_HANDLER)
640 insn = emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (-12)));
641 RTX_FRAME_RELATED_P (insn) = 1;
644 insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
645 RTX_FRAME_RELATED_P (insn) = 1;
647 expand_prologue_reg_save (spreg, all != NULL_TREE);
649 for (i = REG_P7 + 1; i < REG_CC; i++)
650 if (all
651 || regs_ever_live[i]
652 || (!leaf_function_p () && call_used_regs[i]))
654 if (i == REG_A0 || i == REG_A1)
655 insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1),
656 gen_rtx_REG (PDImode, i));
657 else
658 insn = emit_move_insn (predec, gen_rtx_REG (SImode, i));
659 RTX_FRAME_RELATED_P (insn) = 1;
662 if (lookup_attribute ("nesting", attrs))
664 rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
665 : fkind == NMI_HANDLER ? REG_RETN
666 : REG_RETI));
667 insn = emit_move_insn (predec, srcreg);
668 RTX_FRAME_RELATED_P (insn) = 1;
671 do_link (spreg, frame_size);
673 if (fkind == EXCPT_HANDLER)
675 rtx r0reg = gen_rtx_REG (SImode, REG_R0);
676 rtx r1reg = gen_rtx_REG (SImode, REG_R1);
677 rtx r2reg = gen_rtx_REG (SImode, REG_R2);
678 rtx insn;
680 insn = emit_move_insn (r0reg, gen_rtx_REG (SImode, REG_SEQSTAT));
681 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
682 NULL_RTX);
683 insn = emit_insn (gen_ashrsi3 (r0reg, r0reg, GEN_INT (26)));
684 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
685 NULL_RTX);
686 insn = emit_insn (gen_ashlsi3 (r0reg, r0reg, GEN_INT (26)));
687 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
688 NULL_RTX);
689 insn = emit_move_insn (r1reg, spreg);
690 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
691 NULL_RTX);
692 insn = emit_move_insn (r2reg, gen_rtx_REG (Pmode, REG_FP));
693 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
694 NULL_RTX);
695 insn = emit_insn (gen_addsi3 (r2reg, r2reg, GEN_INT (8)));
696 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
697 NULL_RTX);
701 /* Generate an epilogue suitable for a function of kind FKIND. This is
702 called for interrupt and exception handler epilogues.
703 SPREG contains (reg:SI REG_SP). */
705 static void
706 expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind)
708 int i;
709 rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
710 rtx postinc = gen_rtx_MEM (SImode, postinc1);
711 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
712 tree all = lookup_attribute ("saveall", attrs);
714 /* A slightly crude technique to stop flow from trying to delete "dead"
715 insns. */
716 MEM_VOLATILE_P (postinc) = 1;
718 do_unlink (spreg, get_frame_size ());
720 if (lookup_attribute ("nesting", attrs))
722 rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
723 : fkind == NMI_HANDLER ? REG_RETN
724 : REG_RETI));
725 emit_move_insn (srcreg, postinc);
728 for (i = REG_CC - 1; i > REG_P7; i--)
729 if (all
730 || regs_ever_live[i]
731 || (!leaf_function_p () && call_used_regs[i]))
733 if (i == REG_A0 || i == REG_A1)
735 rtx mem = gen_rtx_MEM (PDImode, postinc1);
736 MEM_VOLATILE_P (mem) = 1;
737 emit_move_insn (gen_rtx_REG (PDImode, i), mem);
739 else
740 emit_move_insn (gen_rtx_REG (SImode, i), postinc);
743 expand_epilogue_reg_restore (spreg, all != NULL_TREE);
745 emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
747 /* Deallocate any space we left on the stack in case we needed to save the
748 argument registers. */
749 if (fkind == EXCPT_HANDLER)
750 emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (12)));
752 emit_jump_insn (gen_return_internal (GEN_INT (fkind)));
755 /* Generate RTL for the prologue of the current function. */
757 void
758 bfin_expand_prologue (void)
760 rtx insn;
761 HOST_WIDE_INT frame_size = get_frame_size ();
762 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
763 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
765 if (fkind != SUBROUTINE)
767 expand_interrupt_handler_prologue (spreg, fkind);
768 return;
771 expand_prologue_reg_save (spreg, 0);
773 do_link (spreg, frame_size);
775 if (TARGET_ID_SHARED_LIBRARY
776 && (current_function_uses_pic_offset_table
777 || !current_function_is_leaf))
779 rtx addr;
781 if (bfin_lib_id_given)
782 addr = plus_constant (pic_offset_table_rtx, -4 - bfin_library_id * 4);
783 else
784 addr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
785 gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
786 UNSPEC_LIBRARY_OFFSET));
787 insn = emit_insn (gen_movsi (pic_offset_table_rtx,
788 gen_rtx_MEM (Pmode, addr)));
789 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
793 /* Generate RTL for the epilogue of the current function. NEED_RETURN is zero
794 if this is for a sibcall. EH_RETURN is nonzero if we're expanding an
795 eh_return pattern. */
797 void
798 bfin_expand_epilogue (int need_return, int eh_return)
800 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
801 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
803 if (fkind != SUBROUTINE)
805 expand_interrupt_handler_epilogue (spreg, fkind);
806 return;
809 do_unlink (spreg, get_frame_size ());
811 expand_epilogue_reg_restore (spreg, 0);
813 /* Omit the return insn if this is for a sibcall. */
814 if (! need_return)
815 return;
817 if (eh_return)
818 emit_insn (gen_addsi3 (spreg, spreg, gen_rtx_REG (Pmode, REG_P2)));
820 emit_jump_insn (gen_return_internal (GEN_INT (SUBROUTINE)));
823 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
826 bfin_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
827 unsigned int new_reg)
829 /* Interrupt functions can only use registers that have already been
830 saved by the prologue, even if they would normally be
831 call-clobbered. */
833 if (funkind (TREE_TYPE (current_function_decl)) != SUBROUTINE
834 && !regs_ever_live[new_reg])
835 return 0;
837 return 1;
840 /* Return the value of the return address for the frame COUNT steps up
841 from the current frame, after the prologue.
842 We punt for everything but the current frame by returning const0_rtx. */
845 bfin_return_addr_rtx (int count)
847 if (count != 0)
848 return const0_rtx;
850 return get_hard_reg_initial_val (Pmode, REG_RETS);
853 /* Try machine-dependent ways of modifying an illegitimate address X
854 to be legitimate. If we find one, return the new, valid address,
855 otherwise return NULL_RTX.
857 OLDX is the address as it was before break_out_memory_refs was called.
858 In some cases it is useful to look at this to decide what needs to be done.
860 MODE is the mode of the memory reference. */
863 legitimize_address (rtx x ATTRIBUTE_UNUSED, rtx oldx ATTRIBUTE_UNUSED,
864 enum machine_mode mode ATTRIBUTE_UNUSED)
866 return NULL_RTX;
869 /* This predicate is used to compute the length of a load/store insn.
870 OP is a MEM rtx, we return nonzero if its addressing mode requires a
871 32 bit instruction. */
874 effective_address_32bit_p (rtx op, enum machine_mode mode)
876 HOST_WIDE_INT offset;
878 mode = GET_MODE (op);
879 op = XEXP (op, 0);
881 if (GET_CODE (op) != PLUS)
883 gcc_assert (REG_P (op) || GET_CODE (op) == POST_INC
884 || GET_CODE (op) == PRE_DEC || GET_CODE (op) == POST_DEC);
885 return 0;
888 offset = INTVAL (XEXP (op, 1));
890 /* All byte loads use a 16 bit offset. */
891 if (GET_MODE_SIZE (mode) == 1)
892 return 1;
894 if (GET_MODE_SIZE (mode) == 4)
896 /* Frame pointer relative loads can use a negative offset, all others
897 are restricted to a small positive one. */
898 if (XEXP (op, 0) == frame_pointer_rtx)
899 return offset < -128 || offset > 60;
900 return offset < 0 || offset > 60;
903 /* Must be HImode now. */
904 return offset < 0 || offset > 30;
907 /* Return cost of the memory address ADDR.
908 All addressing modes are equally cheap on the Blackfin. */
910 static int
911 bfin_address_cost (rtx addr ATTRIBUTE_UNUSED)
913 return 1;
916 /* Subroutine of print_operand; used to print a memory reference X to FILE. */
918 void
919 print_address_operand (FILE *file, rtx x)
921 switch (GET_CODE (x))
923 case PLUS:
924 output_address (XEXP (x, 0));
925 fprintf (file, "+");
926 output_address (XEXP (x, 1));
927 break;
929 case PRE_DEC:
930 fprintf (file, "--");
931 output_address (XEXP (x, 0));
932 break;
933 case POST_INC:
934 output_address (XEXP (x, 0));
935 fprintf (file, "++");
936 break;
937 case POST_DEC:
938 output_address (XEXP (x, 0));
939 fprintf (file, "--");
940 break;
942 default:
943 gcc_assert (GET_CODE (x) != MEM);
944 print_operand (file, x, 0);
945 break;
949 /* Adding intp DImode support by Tony
950 * -- Q: (low word)
951 * -- R: (high word)
954 void
955 print_operand (FILE *file, rtx x, char code)
957 enum machine_mode mode = GET_MODE (x);
959 switch (code)
961 case 'j':
962 switch (GET_CODE (x))
964 case EQ:
965 fprintf (file, "e");
966 break;
967 case NE:
968 fprintf (file, "ne");
969 break;
970 case GT:
971 fprintf (file, "g");
972 break;
973 case LT:
974 fprintf (file, "l");
975 break;
976 case GE:
977 fprintf (file, "ge");
978 break;
979 case LE:
980 fprintf (file, "le");
981 break;
982 case GTU:
983 fprintf (file, "g");
984 break;
985 case LTU:
986 fprintf (file, "l");
987 break;
988 case GEU:
989 fprintf (file, "ge");
990 break;
991 case LEU:
992 fprintf (file, "le");
993 break;
994 default:
995 output_operand_lossage ("invalid %%j value");
997 break;
999 case 'J': /* reverse logic */
1000 switch (GET_CODE(x))
1002 case EQ:
1003 fprintf (file, "ne");
1004 break;
1005 case NE:
1006 fprintf (file, "e");
1007 break;
1008 case GT:
1009 fprintf (file, "le");
1010 break;
1011 case LT:
1012 fprintf (file, "ge");
1013 break;
1014 case GE:
1015 fprintf (file, "l");
1016 break;
1017 case LE:
1018 fprintf (file, "g");
1019 break;
1020 case GTU:
1021 fprintf (file, "le");
1022 break;
1023 case LTU:
1024 fprintf (file, "ge");
1025 break;
1026 case GEU:
1027 fprintf (file, "l");
1028 break;
1029 case LEU:
1030 fprintf (file, "g");
1031 break;
1032 default:
1033 output_operand_lossage ("invalid %%J value");
1035 break;
1037 default:
1038 switch (GET_CODE (x))
1040 case REG:
1041 if (code == 'h')
1043 gcc_assert (REGNO (x) < 32);
1044 fprintf (file, "%s", short_reg_names[REGNO (x)]);
1045 /*fprintf (file, "\n%d\n ", REGNO (x));*/
1046 break;
1048 else if (code == 'd')
1050 gcc_assert (REGNO (x) < 32);
1051 fprintf (file, "%s", high_reg_names[REGNO (x)]);
1052 break;
1054 else if (code == 'w')
1056 gcc_assert (REGNO (x) == REG_A0 || REGNO (x) == REG_A1);
1057 fprintf (file, "%s.w", reg_names[REGNO (x)]);
1059 else if (code == 'x')
1061 gcc_assert (REGNO (x) == REG_A0 || REGNO (x) == REG_A1);
1062 fprintf (file, "%s.x", reg_names[REGNO (x)]);
1064 else if (code == 'D')
1066 fprintf (file, "%s", dregs_pair_names[REGNO (x)]);
1068 else if (code == 'H')
1070 gcc_assert (mode == DImode || mode == DFmode);
1071 gcc_assert (REG_P (x));
1072 fprintf (file, "%s", reg_names[REGNO (x) + 1]);
1074 else if (code == 'T')
1076 gcc_assert (D_REGNO_P (REGNO (x)));
1077 fprintf (file, "%s", byte_reg_names[REGNO (x)]);
1079 else
1080 fprintf (file, "%s", reg_names[REGNO (x)]);
1081 break;
1083 case MEM:
1084 fputc ('[', file);
1085 x = XEXP (x,0);
1086 print_address_operand (file, x);
1087 fputc (']', file);
1088 break;
1090 case CONST_INT:
1091 /* Moves to half registers with d or h modifiers always use unsigned
1092 constants. */
1093 if (code == 'd')
1094 x = GEN_INT ((INTVAL (x) >> 16) & 0xffff);
1095 else if (code == 'h')
1096 x = GEN_INT (INTVAL (x) & 0xffff);
1097 else if (code == 'X')
1098 x = GEN_INT (exact_log2 (0xffffffff & INTVAL (x)));
1099 else if (code == 'Y')
1100 x = GEN_INT (exact_log2 (0xffffffff & ~INTVAL (x)));
1101 else if (code == 'Z')
1102 /* Used for LINK insns. */
1103 x = GEN_INT (-8 - INTVAL (x));
1105 /* fall through */
1107 case SYMBOL_REF:
1108 output_addr_const (file, x);
1109 if (code == 'G' && flag_pic)
1110 fprintf (file, "@GOT");
1111 break;
1113 case CONST_DOUBLE:
1114 output_operand_lossage ("invalid const_double operand");
1115 break;
1117 case UNSPEC:
1118 switch (XINT (x, 1))
1120 case UNSPEC_MOVE_PIC:
1121 output_addr_const (file, XVECEXP (x, 0, 0));
1122 fprintf (file, "@GOT");
1123 break;
1125 case UNSPEC_LIBRARY_OFFSET:
1126 fprintf (file, "_current_shared_library_p5_offset_");
1127 break;
1129 default:
1130 gcc_unreachable ();
1132 break;
1134 default:
1135 output_addr_const (file, x);
1140 /* Argument support functions. */
1142 /* Initialize a variable CUM of type CUMULATIVE_ARGS
1143 for a call to a function whose data type is FNTYPE.
1144 For a library call, FNTYPE is 0.
1145 VDSP C Compiler manual, our ABI says that
1146 first 3 words of arguments will use R0, R1 and R2.
1149 void
1150 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype ATTRIBUTE_UNUSED,
1151 rtx libname ATTRIBUTE_UNUSED)
1153 static CUMULATIVE_ARGS zero_cum;
1155 *cum = zero_cum;
1157 /* Set up the number of registers to use for passing arguments. */
1159 cum->nregs = max_arg_registers;
1160 cum->arg_regs = arg_regs;
1162 return;
1165 /* Update the data in CUM to advance over an argument
1166 of mode MODE and data type TYPE.
1167 (TYPE is null for libcalls where that information may not be available.) */
1169 void
1170 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1171 int named ATTRIBUTE_UNUSED)
1173 int count, bytes, words;
1175 bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1176 words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1178 cum->words += words;
1179 cum->nregs -= words;
1181 if (cum->nregs <= 0)
1183 cum->nregs = 0;
1184 cum->arg_regs = NULL;
1186 else
1188 for (count = 1; count <= words; count++)
1189 cum->arg_regs++;
1192 return;
1195 /* Define where to put the arguments to a function.
1196 Value is zero to push the argument on the stack,
1197 or a hard register in which to store the argument.
1199 MODE is the argument's machine mode.
1200 TYPE is the data type of the argument (as a tree).
1201 This is null for libcalls where that information may
1202 not be available.
1203 CUM is a variable of type CUMULATIVE_ARGS which gives info about
1204 the preceding args and about the function being called.
1205 NAMED is nonzero if this argument is a named parameter
1206 (otherwise it is an extra parameter matching an ellipsis). */
1208 struct rtx_def *
1209 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1210 int named ATTRIBUTE_UNUSED)
1212 int bytes
1213 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1215 if (bytes == -1)
1216 return NULL_RTX;
1218 if (cum->nregs)
1219 return gen_rtx_REG (mode, *(cum->arg_regs));
1221 return NULL_RTX;
1224 /* For an arg passed partly in registers and partly in memory,
1225 this is the number of bytes passed in registers.
1226 For args passed entirely in registers or entirely in memory, zero.
1228 Refer VDSP C Compiler manual, our ABI.
1229 First 3 words are in registers. So, if a an argument is larger
1230 than the registers available, it will span the register and
1231 stack. */
1233 static int
1234 bfin_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1235 tree type ATTRIBUTE_UNUSED,
1236 bool named ATTRIBUTE_UNUSED)
1238 int bytes
1239 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1240 int bytes_left = cum->nregs * UNITS_PER_WORD;
1242 if (bytes == -1)
1243 return 0;
1245 if (bytes_left == 0)
1246 return 0;
1247 if (bytes > bytes_left)
1248 return bytes_left;
1249 return 0;
1252 /* Variable sized types are passed by reference. */
1254 static bool
1255 bfin_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
1256 enum machine_mode mode ATTRIBUTE_UNUSED,
1257 tree type, bool named ATTRIBUTE_UNUSED)
1259 return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
1262 /* Decide whether a type should be returned in memory (true)
1263 or in a register (false). This is called by the macro
1264 RETURN_IN_MEMORY. */
1267 bfin_return_in_memory (tree type)
1269 int size;
1270 enum machine_mode mode = TYPE_MODE (type);
1272 if (mode == BLKmode)
1273 return 1;
1274 size = int_size_in_bytes (type);
1275 if (VECTOR_MODE_P (mode) || mode == TImode)
1277 /* User-created vectors small enough to fit in REG. */
1278 if (size < 8)
1279 return 0;
1280 if (size == 8 || size == 16)
1281 return 1;
1284 if (size > 12)
1285 return 1;
1286 return 0;
1289 /* Register in which address to store a structure value
1290 is passed to a function. */
1291 static rtx
1292 bfin_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
1293 int incoming ATTRIBUTE_UNUSED)
1295 return gen_rtx_REG (Pmode, REG_P0);
1298 /* Return true when register may be used to pass function parameters. */
1300 bool
1301 function_arg_regno_p (int n)
1303 int i;
1304 for (i = 0; arg_regs[i] != -1; i++)
1305 if (n == arg_regs[i])
1306 return true;
1307 return false;
1310 /* Returns 1 if OP contains a symbol reference */
1313 symbolic_reference_mentioned_p (rtx op)
1315 register const char *fmt;
1316 register int i;
1318 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
1319 return 1;
1321 fmt = GET_RTX_FORMAT (GET_CODE (op));
1322 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
1324 if (fmt[i] == 'E')
1326 register int j;
1328 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
1329 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
1330 return 1;
1333 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
1334 return 1;
1337 return 0;
1340 /* Decide whether we can make a sibling call to a function. DECL is the
1341 declaration of the function being targeted by the call and EXP is the
1342 CALL_EXPR representing the call. */
1344 static bool
1345 bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
1346 tree exp ATTRIBUTE_UNUSED)
1348 return true;
1351 /* Emit RTL insns to initialize the variable parts of a trampoline at
1352 TRAMP. FNADDR is an RTX for the address of the function's pure
1353 code. CXT is an RTX for the static chain value for the function. */
1355 void
1356 initialize_trampoline (tramp, fnaddr, cxt)
1357 rtx tramp, fnaddr, cxt;
1359 rtx t1 = copy_to_reg (fnaddr);
1360 rtx t2 = copy_to_reg (cxt);
1361 rtx addr;
1363 addr = memory_address (Pmode, plus_constant (tramp, 2));
1364 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
1365 emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16)));
1366 addr = memory_address (Pmode, plus_constant (tramp, 6));
1367 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
1369 addr = memory_address (Pmode, plus_constant (tramp, 10));
1370 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
1371 emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16)));
1372 addr = memory_address (Pmode, plus_constant (tramp, 14));
1373 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
1376 /* Legitimize PIC addresses. If the address is already position-independent,
1377 we return ORIG. Newly generated position-independent addresses go into a
1378 reg. This is REG if nonzero, otherwise we allocate register(s) as
1379 necessary. */
1382 legitimize_pic_address (rtx orig, rtx reg)
1384 rtx addr = orig;
1385 rtx new = orig;
1387 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
1389 if (GET_CODE (addr) == SYMBOL_REF && CONSTANT_POOL_ADDRESS_P (addr))
1390 reg = new = orig;
1391 else
1393 if (reg == 0)
1395 gcc_assert (!no_new_pseudos);
1396 reg = gen_reg_rtx (Pmode);
1399 if (flag_pic == 2)
1401 emit_insn (gen_movsi_high_pic (reg, addr));
1402 emit_insn (gen_movsi_low_pic (reg, reg, addr));
1403 emit_insn (gen_addsi3 (reg, reg, pic_offset_table_rtx));
1404 new = gen_rtx_MEM (Pmode, reg);
1406 else
1408 rtx tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr),
1409 UNSPEC_MOVE_PIC);
1410 new = gen_rtx_MEM (Pmode,
1411 gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
1412 tmp));
1414 emit_move_insn (reg, new);
1416 current_function_uses_pic_offset_table = 1;
1417 return reg;
1420 else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
1422 rtx base;
1424 if (GET_CODE (addr) == CONST)
1426 addr = XEXP (addr, 0);
1427 gcc_assert (GET_CODE (addr) == PLUS);
1430 if (XEXP (addr, 0) == pic_offset_table_rtx)
1431 return orig;
1433 if (reg == 0)
1435 gcc_assert (!no_new_pseudos);
1436 reg = gen_reg_rtx (Pmode);
1439 base = legitimize_pic_address (XEXP (addr, 0), reg);
1440 addr = legitimize_pic_address (XEXP (addr, 1),
1441 base == reg ? NULL_RTX : reg);
1443 if (GET_CODE (addr) == CONST_INT)
1445 gcc_assert (! reload_in_progress && ! reload_completed);
1446 addr = force_reg (Pmode, addr);
1449 if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
1451 base = gen_rtx_PLUS (Pmode, base, XEXP (addr, 0));
1452 addr = XEXP (addr, 1);
1455 return gen_rtx_PLUS (Pmode, base, addr);
1458 return new;
1461 /* Emit insns to move operands[1] into operands[0]. */
1463 void
1464 emit_pic_move (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
1466 rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
1468 if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
1469 operands[1] = force_reg (SImode, operands[1]);
1470 else
1471 operands[1] = legitimize_pic_address (operands[1], temp);
1474 /* Expand a move operation in mode MODE. The operands are in OPERANDS. */
1476 void
1477 expand_move (rtx *operands, enum machine_mode mode)
1479 if (flag_pic && SYMBOLIC_CONST (operands[1]))
1480 emit_pic_move (operands, mode);
1482 /* Don't generate memory->memory or constant->memory moves, go through a
1483 register */
1484 else if ((reload_in_progress | reload_completed) == 0
1485 && GET_CODE (operands[0]) == MEM
1486 && GET_CODE (operands[1]) != REG)
1487 operands[1] = force_reg (mode, operands[1]);
1490 /* Split one or more DImode RTL references into pairs of SImode
1491 references. The RTL can be REG, offsettable MEM, integer constant, or
1492 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
1493 split and "num" is its length. lo_half and hi_half are output arrays
1494 that parallel "operands". */
1496 void
1497 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
1499 while (num--)
1501 rtx op = operands[num];
1503 /* simplify_subreg refuse to split volatile memory addresses,
1504 but we still have to handle it. */
1505 if (GET_CODE (op) == MEM)
1507 lo_half[num] = adjust_address (op, SImode, 0);
1508 hi_half[num] = adjust_address (op, SImode, 4);
1510 else
1512 lo_half[num] = simplify_gen_subreg (SImode, op,
1513 GET_MODE (op) == VOIDmode
1514 ? DImode : GET_MODE (op), 0);
1515 hi_half[num] = simplify_gen_subreg (SImode, op,
1516 GET_MODE (op) == VOIDmode
1517 ? DImode : GET_MODE (op), 4);
1522 /* Expand a call instruction. FNADDR is the call target, RETVAL the return value.
1523 SIBCALL is nonzero if this is a sibling call. */
1525 void
1526 bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, int sibcall)
1528 rtx use = NULL, call;
1530 /* Static functions and indirect calls don't need the pic register. */
1531 if (flag_pic
1532 && GET_CODE (XEXP (fnaddr, 0)) == SYMBOL_REF
1533 && ! SYMBOL_REF_LOCAL_P (XEXP (fnaddr, 0)))
1534 use_reg (&use, pic_offset_table_rtx);
1536 if (! call_insn_operand (XEXP (fnaddr, 0), Pmode))
1538 fnaddr = copy_to_mode_reg (Pmode, XEXP (fnaddr, 0));
1539 fnaddr = gen_rtx_MEM (Pmode, fnaddr);
1541 call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
1543 if (retval)
1544 call = gen_rtx_SET (VOIDmode, retval, call);
1545 if (sibcall)
1547 rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (2));
1548 XVECEXP (pat, 0, 0) = call;
1549 XVECEXP (pat, 0, 1) = gen_rtx_RETURN (VOIDmode);
1550 call = pat;
1552 call = emit_call_insn (call);
1553 if (use)
1554 CALL_INSN_FUNCTION_USAGE (call) = use;
1557 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
1560 hard_regno_mode_ok (int regno, enum machine_mode mode)
1562 /* Allow only dregs to store value of mode HI or QI */
1563 enum reg_class class = REGNO_REG_CLASS (regno);
1565 if (mode == CCmode)
1566 return 0;
1568 if (mode == V2HImode)
1569 return D_REGNO_P (regno);
1570 if (class == CCREGS)
1571 return mode == BImode;
1572 if (mode == PDImode)
1573 return regno == REG_A0 || regno == REG_A1;
1574 if (mode == SImode
1575 && TEST_HARD_REG_BIT (reg_class_contents[PROLOGUE_REGS], regno))
1576 return 1;
1578 return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno);
1581 /* Implements target hook vector_mode_supported_p. */
1583 static bool
1584 bfin_vector_mode_supported_p (enum machine_mode mode)
1586 return mode == V2HImode;
1589 /* Return the cost of moving data from a register in class CLASS1 to
1590 one in class CLASS2. A cost of 2 is the default. */
1593 bfin_register_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
1594 enum reg_class class1, enum reg_class class2)
1596 /* If optimizing for size, always prefer reg-reg over reg-memory moves. */
1597 if (optimize_size)
1598 return 2;
1600 /* There are some stalls involved when moving from a DREG to a different
1601 class reg, and using the value in one of the following instructions.
1602 Attempt to model this by slightly discouraging such moves. */
1603 if (class1 == DREGS && class2 != DREGS)
1604 return 2 * 2;
1606 return 2;
1609 /* Return the cost of moving data of mode M between a
1610 register and memory. A value of 2 is the default; this cost is
1611 relative to those in `REGISTER_MOVE_COST'.
1613 ??? In theory L1 memory has single-cycle latency. We should add a switch
1614 that tells the compiler whether we expect to use only L1 memory for the
1615 program; it'll make the costs more accurate. */
1618 bfin_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
1619 enum reg_class class,
1620 int in ATTRIBUTE_UNUSED)
1622 /* Make memory accesses slightly more expensive than any register-register
1623 move. Also, penalize non-DP registers, since they need secondary
1624 reloads to load and store. */
1625 if (! reg_class_subset_p (class, DPREGS))
1626 return 10;
1628 return 8;
1631 /* Inform reload about cases where moving X with a mode MODE to a register in
1632 CLASS requires an extra scratch register. Return the class needed for the
1633 scratch register. */
1635 enum reg_class
1636 secondary_input_reload_class (enum reg_class class, enum machine_mode mode,
1637 rtx x)
1639 /* If we have HImode or QImode, we can only use DREGS as secondary registers;
1640 in most other cases we can also use PREGS. */
1641 enum reg_class default_class = GET_MODE_SIZE (mode) >= 4 ? DPREGS : DREGS;
1642 enum reg_class x_class = NO_REGS;
1643 enum rtx_code code = GET_CODE (x);
1645 if (code == SUBREG)
1646 x = SUBREG_REG (x), code = GET_CODE (x);
1647 if (REG_P (x))
1649 int regno = REGNO (x);
1650 if (regno >= FIRST_PSEUDO_REGISTER)
1651 regno = reg_renumber[regno];
1653 if (regno == -1)
1654 code = MEM;
1655 else
1656 x_class = REGNO_REG_CLASS (regno);
1659 /* We can be asked to reload (plus (FP) (large_constant)) into a DREG.
1660 This happens as a side effect of register elimination, and we need
1661 a scratch register to do it. */
1662 if (fp_plus_const_operand (x, mode))
1664 rtx op2 = XEXP (x, 1);
1665 int large_constant_p = ! CONST_7BIT_IMM_P (INTVAL (op2));
1667 if (class == PREGS || class == PREGS_CLOBBERED)
1668 return NO_REGS;
1669 /* If destination is a DREG, we can do this without a scratch register
1670 if the constant is valid for an add instruction. */
1671 if (class == DREGS || class == DPREGS)
1672 return large_constant_p ? PREGS : NO_REGS;
1673 /* Reloading to anything other than a DREG? Use a PREG scratch
1674 register. */
1675 return PREGS;
1678 /* Data can usually be moved freely between registers of most classes.
1679 AREGS are an exception; they can only move to or from another register
1680 in AREGS or one in DREGS. They can also be assigned the constant 0. */
1681 if (x_class == AREGS)
1682 return class == DREGS || class == AREGS ? NO_REGS : DREGS;
1684 if (class == AREGS)
1686 if (x != const0_rtx && x_class != DREGS)
1687 return DREGS;
1688 else
1689 return NO_REGS;
1692 /* CCREGS can only be moved from/to DREGS. */
1693 if (class == CCREGS && x_class != DREGS)
1694 return DREGS;
1695 if (x_class == CCREGS && class != DREGS)
1696 return DREGS;
1697 /* All registers other than AREGS can load arbitrary constants. The only
1698 case that remains is MEM. */
1699 if (code == MEM)
1700 if (! reg_class_subset_p (class, default_class))
1701 return default_class;
1702 return NO_REGS;
1705 /* Like secondary_input_reload_class; and all we do is call that function. */
1707 enum reg_class
1708 secondary_output_reload_class (enum reg_class class, enum machine_mode mode,
1709 rtx x)
1711 return secondary_input_reload_class (class, mode, x);
1714 /* Implement TARGET_HANDLE_OPTION. */
1716 static bool
1717 bfin_handle_option (size_t code, const char *arg, int value)
1719 switch (code)
1721 case OPT_mshared_library_id_:
1722 if (value > MAX_LIBRARY_ID)
1723 error ("-mshared-library-id=%s is not between 0 and %d",
1724 arg, MAX_LIBRARY_ID);
1725 else
1726 bfin_library_id = value;
1727 bfin_lib_id_given = 1;
1728 return true;
1730 default:
1731 return true;
1735 /* Implement the macro OVERRIDE_OPTIONS. */
1737 void
1738 override_options (void)
1740 if (TARGET_OMIT_LEAF_FRAME_POINTER)
1741 flag_omit_frame_pointer = 1;
1743 /* Library identification */
1744 if (bfin_lib_id_given && ! TARGET_ID_SHARED_LIBRARY)
1745 error ("-mshared-library-id= specified without -mid-shared-library");
1747 if (TARGET_ID_SHARED_LIBRARY)
1748 /* ??? Provide a way to use a bigger GOT. */
1749 flag_pic = 1;
1751 flag_schedule_insns = 0;
1754 /* Return the destination address of BRANCH.
1755 We need to use this instead of get_attr_length, because the
1756 cbranch_with_nops pattern conservatively sets its length to 6, and
1757 we still prefer to use shorter sequences. */
1759 static int
1760 branch_dest (rtx branch)
1762 rtx dest;
1763 int dest_uid;
1764 rtx pat = PATTERN (branch);
1765 if (GET_CODE (pat) == PARALLEL)
1766 pat = XVECEXP (pat, 0, 0);
1767 dest = SET_SRC (pat);
1768 if (GET_CODE (dest) == IF_THEN_ELSE)
1769 dest = XEXP (dest, 1);
1770 dest = XEXP (dest, 0);
1771 dest_uid = INSN_UID (dest);
1772 return INSN_ADDRESSES (dest_uid);
1775 /* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates
1776 it's a branch that's predicted taken. */
1778 static int
1779 cbranch_predicted_taken_p (rtx insn)
1781 rtx x = find_reg_note (insn, REG_BR_PROB, 0);
1783 if (x)
1785 int pred_val = INTVAL (XEXP (x, 0));
1787 return pred_val >= REG_BR_PROB_BASE / 2;
1790 return 0;
1793 /* Templates for use by asm_conditional_branch. */
1795 static const char *ccbranch_templates[][3] = {
1796 { "if !cc jump %3;", "if cc jump 4 (bp); jump.s %3;", "if cc jump 6 (bp); jump.l %3;" },
1797 { "if cc jump %3;", "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" },
1798 { "if !cc jump %3 (bp);", "if cc jump 4; jump.s %3;", "if cc jump 6; jump.l %3;" },
1799 { "if cc jump %3 (bp);", "if !cc jump 4; jump.s %3;", "if !cc jump 6; jump.l %3;" },
1802 /* Output INSN, which is a conditional branch instruction with operands
1803 OPERANDS.
1805 We deal with the various forms of conditional branches that can be generated
1806 by bfin_reorg to prevent the hardware from doing speculative loads, by
1807 - emitting a sufficient number of nops, if N_NOPS is nonzero, or
1808 - always emitting the branch as predicted taken, if PREDICT_TAKEN is true.
1809 Either of these is only necessary if the branch is short, otherwise the
1810 template we use ends in an unconditional jump which flushes the pipeline
1811 anyway. */
1813 void
1814 asm_conditional_branch (rtx insn, rtx *operands, int n_nops, int predict_taken)
1816 int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
1817 /* Note : offset for instructions like if cc jmp; jump.[sl] offset
1818 is to be taken from start of if cc rather than jump.
1819 Range for jump.s is (-4094, 4096) instead of (-4096, 4094)
1821 int len = (offset >= -1024 && offset <= 1022 ? 0
1822 : offset >= -4094 && offset <= 4096 ? 1
1823 : 2);
1824 int bp = predict_taken && len == 0 ? 1 : cbranch_predicted_taken_p (insn);
1825 int idx = (bp << 1) | (GET_CODE (operands[0]) == EQ ? BRF : BRT);
1826 output_asm_insn (ccbranch_templates[idx][len], operands);
1827 gcc_assert (n_nops == 0 || !bp);
1828 if (len == 0)
1829 while (n_nops-- > 0)
1830 output_asm_insn ("nop;", NULL);
1833 /* Emit rtl for a comparison operation CMP in mode MODE. Operands have been
1834 stored in bfin_compare_op0 and bfin_compare_op1 already. */
1837 bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED)
1839 enum rtx_code code1, code2;
1840 rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1;
1841 rtx tem = bfin_cc_rtx;
1842 enum rtx_code code = GET_CODE (cmp);
1844 /* If we have a BImode input, then we already have a compare result, and
1845 do not need to emit another comparison. */
1846 if (GET_MODE (op0) == BImode)
1848 gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
1849 tem = op0, code2 = code;
1851 else
1853 switch (code) {
1854 /* bfin has these conditions */
1855 case EQ:
1856 case LT:
1857 case LE:
1858 case LEU:
1859 case LTU:
1860 code1 = code;
1861 code2 = NE;
1862 break;
1863 default:
1864 code1 = reverse_condition (code);
1865 code2 = EQ;
1866 break;
1868 emit_insn (gen_rtx_SET (BImode, tem,
1869 gen_rtx_fmt_ee (code1, BImode, op0, op1)));
1872 return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode));
1875 /* Return nonzero iff C has exactly one bit set if it is interpreted
1876 as a 32 bit constant. */
1879 log2constp (unsigned HOST_WIDE_INT c)
1881 c &= 0xFFFFFFFF;
1882 return c != 0 && (c & (c-1)) == 0;
1885 /* Returns the number of consecutive least significant zeros in the binary
1886 representation of *V.
1887 We modify *V to contain the original value arithmetically shifted right by
1888 the number of zeroes. */
1890 static int
1891 shiftr_zero (HOST_WIDE_INT *v)
1893 unsigned HOST_WIDE_INT tmp = *v;
1894 unsigned HOST_WIDE_INT sgn;
1895 int n = 0;
1897 if (tmp == 0)
1898 return 0;
1900 sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1));
1901 while ((tmp & 0x1) == 0 && n <= 32)
1903 tmp = (tmp >> 1) | sgn;
1904 n++;
1906 *v = tmp;
1907 return n;
1910 /* After reload, split the load of an immediate constant. OPERANDS are the
1911 operands of the movsi_insn pattern which we are splitting. We return
1912 nonzero if we emitted a sequence to load the constant, zero if we emitted
1913 nothing because we want to use the splitter's default sequence. */
1916 split_load_immediate (rtx operands[])
1918 HOST_WIDE_INT val = INTVAL (operands[1]);
1919 HOST_WIDE_INT tmp;
1920 HOST_WIDE_INT shifted = val;
1921 HOST_WIDE_INT shifted_compl = ~val;
1922 int num_zero = shiftr_zero (&shifted);
1923 int num_compl_zero = shiftr_zero (&shifted_compl);
1924 unsigned int regno = REGNO (operands[0]);
1925 enum reg_class class1 = REGNO_REG_CLASS (regno);
1927 /* This case takes care of single-bit set/clear constants, which we could
1928 also implement with BITSET/BITCLR. */
1929 if (num_zero
1930 && shifted >= -32768 && shifted < 65536
1931 && (D_REGNO_P (regno)
1932 || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))
1934 emit_insn (gen_movsi (operands[0], GEN_INT (shifted)));
1935 emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));
1936 return 1;
1939 tmp = val & 0xFFFF;
1940 tmp |= -(tmp & 0x8000);
1942 /* If high word has one bit set or clear, try to use a bit operation. */
1943 if (D_REGNO_P (regno))
1945 if (log2constp (val & 0xFFFF0000))
1947 emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));
1948 emit_insn (gen_iorsi3 (operands[0], operands[0], GEN_INT (val & 0xFFFF0000)));
1949 return 1;
1951 else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)
1953 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
1954 emit_insn (gen_andsi3 (operands[0], operands[0], GEN_INT (val | 0xFFFF)));
1958 if (D_REGNO_P (regno))
1960 if (CONST_7BIT_IMM_P (tmp))
1962 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
1963 emit_insn (gen_movstricthi_high (operands[0], GEN_INT (val & -65536)));
1964 return 1;
1967 if ((val & 0xFFFF0000) == 0)
1969 emit_insn (gen_movsi (operands[0], const0_rtx));
1970 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
1971 return 1;
1974 if ((val & 0xFFFF0000) == 0xFFFF0000)
1976 emit_insn (gen_movsi (operands[0], constm1_rtx));
1977 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
1978 return 1;
1982 /* Need DREGs for the remaining case. */
1983 if (regno > REG_R7)
1984 return 0;
1986 if (optimize_size
1987 && num_compl_zero && CONST_7BIT_IMM_P (shifted_compl))
1989 /* If optimizing for size, generate a sequence that has more instructions
1990 but is shorter. */
1991 emit_insn (gen_movsi (operands[0], GEN_INT (shifted_compl)));
1992 emit_insn (gen_ashlsi3 (operands[0], operands[0],
1993 GEN_INT (num_compl_zero)));
1994 emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
1995 return 1;
1997 return 0;
2000 /* Return true if the legitimate memory address for a memory operand of mode
2001 MODE. Return false if not. */
2003 static bool
2004 bfin_valid_add (enum machine_mode mode, HOST_WIDE_INT value)
2006 unsigned HOST_WIDE_INT v = value > 0 ? value : -value;
2007 int sz = GET_MODE_SIZE (mode);
2008 int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2;
2009 /* The usual offsettable_memref machinery doesn't work so well for this
2010 port, so we deal with the problem here. */
2011 unsigned HOST_WIDE_INT mask = sz == 8 ? 0x7ffe : 0x7fff;
2012 return (v & ~(mask << shift)) == 0;
2015 static bool
2016 bfin_valid_reg_p (unsigned int regno, int strict)
2018 return ((strict && REGNO_OK_FOR_BASE_STRICT_P (regno))
2019 || (!strict && REGNO_OK_FOR_BASE_NONSTRICT_P (regno)));
2022 bool
2023 bfin_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
2025 switch (GET_CODE (x)) {
2026 case REG:
2027 if (bfin_valid_reg_p (REGNO (x), strict))
2028 return true;
2029 break;
2030 case PLUS:
2031 if (REG_P (XEXP (x, 0))
2032 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict)
2033 && (GET_CODE (XEXP (x, 1)) == UNSPEC
2034 || (GET_CODE (XEXP (x, 1)) == CONST_INT
2035 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
2036 return true;
2037 break;
2038 case POST_INC:
2039 case POST_DEC:
2040 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2041 && REG_P (XEXP (x, 0))
2042 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict))
2043 return true;
2044 case PRE_DEC:
2045 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2046 && XEXP (x, 0) == stack_pointer_rtx
2047 && REG_P (XEXP (x, 0))
2048 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict))
2049 return true;
2050 break;
2051 default:
2052 break;
2054 return false;
2057 static bool
2058 bfin_rtx_costs (rtx x, int code, int outer_code, int *total)
2060 int cost2 = COSTS_N_INSNS (1);
2062 switch (code)
2064 case CONST_INT:
2065 if (outer_code == SET || outer_code == PLUS)
2066 *total = CONST_7BIT_IMM_P (INTVAL (x)) ? 0 : cost2;
2067 else if (outer_code == AND)
2068 *total = log2constp (~INTVAL (x)) ? 0 : cost2;
2069 else if (outer_code == LE || outer_code == LT || outer_code == EQ)
2070 *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
2071 else if (outer_code == LEU || outer_code == LTU)
2072 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
2073 else if (outer_code == MULT)
2074 *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
2075 else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
2076 *total = 0;
2077 else if (outer_code == ASHIFT || outer_code == ASHIFTRT
2078 || outer_code == LSHIFTRT)
2079 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
2080 else if (outer_code == IOR || outer_code == XOR)
2081 *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
2082 else
2083 *total = cost2;
2084 return true;
2086 case CONST:
2087 case LABEL_REF:
2088 case SYMBOL_REF:
2089 case CONST_DOUBLE:
2090 *total = COSTS_N_INSNS (2);
2091 return true;
2093 case PLUS:
2094 if (GET_MODE (x) == Pmode)
2096 if (GET_CODE (XEXP (x, 0)) == MULT
2097 && GET_CODE (XEXP (XEXP (x, 0), 1)) == CONST_INT)
2099 HOST_WIDE_INT val = INTVAL (XEXP (XEXP (x, 0), 1));
2100 if (val == 2 || val == 4)
2102 *total = cost2;
2103 *total += rtx_cost (XEXP (XEXP (x, 0), 0), outer_code);
2104 *total += rtx_cost (XEXP (x, 1), outer_code);
2105 return true;
2110 /* fall through */
2112 case MINUS:
2113 case ASHIFT:
2114 case ASHIFTRT:
2115 case LSHIFTRT:
2116 if (GET_MODE (x) == DImode)
2117 *total = 6 * cost2;
2118 return false;
2120 case AND:
2121 case IOR:
2122 case XOR:
2123 if (GET_MODE (x) == DImode)
2124 *total = 2 * cost2;
2125 return false;
2127 case MULT:
2128 if (GET_MODE_SIZE (GET_MODE (x)) <= UNITS_PER_WORD)
2129 *total = COSTS_N_INSNS (3);
2130 return false;
2132 default:
2133 return false;
2137 static void
2138 bfin_internal_label (FILE *stream, const char *prefix, unsigned long num)
2140 fprintf (stream, "%s%s$%ld:\n", LOCAL_LABEL_PREFIX, prefix, num);
2143 /* Used for communication between {push,pop}_multiple_operation (which
2144 we use not only as a predicate) and the corresponding output functions. */
2145 static int first_preg_to_save, first_dreg_to_save;
2148 push_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2150 int lastdreg = 8, lastpreg = 6;
2151 int i, group;
2153 first_preg_to_save = lastpreg;
2154 first_dreg_to_save = lastdreg;
2155 for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
2157 rtx t = XVECEXP (op, 0, i);
2158 rtx src, dest;
2159 int regno;
2161 if (GET_CODE (t) != SET)
2162 return 0;
2164 src = SET_SRC (t);
2165 dest = SET_DEST (t);
2166 if (GET_CODE (dest) != MEM || ! REG_P (src))
2167 return 0;
2168 dest = XEXP (dest, 0);
2169 if (GET_CODE (dest) != PLUS
2170 || ! REG_P (XEXP (dest, 0))
2171 || REGNO (XEXP (dest, 0)) != REG_SP
2172 || GET_CODE (XEXP (dest, 1)) != CONST_INT
2173 || INTVAL (XEXP (dest, 1)) != -i * 4)
2174 return 0;
2176 regno = REGNO (src);
2177 if (group == 0)
2179 if (D_REGNO_P (regno))
2181 group = 1;
2182 first_dreg_to_save = lastdreg = regno - REG_R0;
2184 else if (regno >= REG_P0 && regno <= REG_P7)
2186 group = 2;
2187 first_preg_to_save = lastpreg = regno - REG_P0;
2189 else
2190 return 0;
2192 continue;
2195 if (group == 1)
2197 if (regno >= REG_P0 && regno <= REG_P7)
2199 group = 2;
2200 first_preg_to_save = lastpreg = regno - REG_P0;
2202 else if (regno != REG_R0 + lastdreg + 1)
2203 return 0;
2204 else
2205 lastdreg++;
2207 else if (group == 2)
2209 if (regno != REG_P0 + lastpreg + 1)
2210 return 0;
2211 lastpreg++;
2214 return 1;
2218 pop_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2220 int lastdreg = 8, lastpreg = 6;
2221 int i, group;
2223 for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
2225 rtx t = XVECEXP (op, 0, i);
2226 rtx src, dest;
2227 int regno;
2229 if (GET_CODE (t) != SET)
2230 return 0;
2232 src = SET_SRC (t);
2233 dest = SET_DEST (t);
2234 if (GET_CODE (src) != MEM || ! REG_P (dest))
2235 return 0;
2236 src = XEXP (src, 0);
2238 if (i == 1)
2240 if (! REG_P (src) || REGNO (src) != REG_SP)
2241 return 0;
2243 else if (GET_CODE (src) != PLUS
2244 || ! REG_P (XEXP (src, 0))
2245 || REGNO (XEXP (src, 0)) != REG_SP
2246 || GET_CODE (XEXP (src, 1)) != CONST_INT
2247 || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
2248 return 0;
2250 regno = REGNO (dest);
2251 if (group == 0)
2253 if (regno == REG_R7)
2255 group = 1;
2256 lastdreg = 7;
2258 else if (regno != REG_P0 + lastpreg - 1)
2259 return 0;
2260 else
2261 lastpreg--;
2263 else if (group == 1)
2265 if (regno != REG_R0 + lastdreg - 1)
2266 return 0;
2267 else
2268 lastdreg--;
2271 first_dreg_to_save = lastdreg;
2272 first_preg_to_save = lastpreg;
2273 return 1;
2276 /* Emit assembly code for one multi-register push described by INSN, with
2277 operands in OPERANDS. */
2279 void
2280 output_push_multiple (rtx insn, rtx *operands)
2282 char buf[80];
2283 int ok;
2285 /* Validate the insn again, and compute first_[dp]reg_to_save. */
2286 ok = push_multiple_operation (PATTERN (insn), VOIDmode);
2287 gcc_assert (ok);
2289 if (first_dreg_to_save == 8)
2290 sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
2291 else if (first_preg_to_save == 6)
2292 sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
2293 else
2294 sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
2295 first_dreg_to_save, first_preg_to_save);
2297 output_asm_insn (buf, operands);
2300 /* Emit assembly code for one multi-register pop described by INSN, with
2301 operands in OPERANDS. */
2303 void
2304 output_pop_multiple (rtx insn, rtx *operands)
2306 char buf[80];
2307 int ok;
2309 /* Validate the insn again, and compute first_[dp]reg_to_save. */
2310 ok = pop_multiple_operation (PATTERN (insn), VOIDmode);
2311 gcc_assert (ok);
2313 if (first_dreg_to_save == 8)
2314 sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
2315 else if (first_preg_to_save == 6)
2316 sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
2317 else
2318 sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
2319 first_dreg_to_save, first_preg_to_save);
2321 output_asm_insn (buf, operands);
2324 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE. */
2326 static void
2327 single_move_for_strmov (rtx dst, rtx src, enum machine_mode mode, HOST_WIDE_INT offset)
2329 rtx scratch = gen_reg_rtx (mode);
2330 rtx srcmem, dstmem;
2332 srcmem = adjust_address_nv (src, mode, offset);
2333 dstmem = adjust_address_nv (dst, mode, offset);
2334 emit_move_insn (scratch, srcmem);
2335 emit_move_insn (dstmem, scratch);
2338 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
2339 alignment ALIGN_EXP. Return true if successful, false if we should fall
2340 back on a different method. */
2342 bool
2343 bfin_expand_strmov (rtx dst, rtx src, rtx count_exp, rtx align_exp)
2345 rtx srcreg, destreg, countreg;
2346 HOST_WIDE_INT align = 0;
2347 unsigned HOST_WIDE_INT count = 0;
2349 if (GET_CODE (align_exp) == CONST_INT)
2350 align = INTVAL (align_exp);
2351 if (GET_CODE (count_exp) == CONST_INT)
2353 count = INTVAL (count_exp);
2354 #if 0
2355 if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
2356 return false;
2357 #endif
2360 /* If optimizing for size, only do single copies inline. */
2361 if (optimize_size)
2363 if (count == 2 && align < 2)
2364 return false;
2365 if (count == 4 && align < 4)
2366 return false;
2367 if (count != 1 && count != 2 && count != 4)
2368 return false;
2370 if (align < 2 && count != 1)
2371 return false;
2373 destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
2374 if (destreg != XEXP (dst, 0))
2375 dst = replace_equiv_address_nv (dst, destreg);
2376 srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
2377 if (srcreg != XEXP (src, 0))
2378 src = replace_equiv_address_nv (src, srcreg);
2380 if (count != 0 && align >= 2)
2382 unsigned HOST_WIDE_INT offset = 0;
2384 if (align >= 4)
2386 if ((count & ~3) == 4)
2388 single_move_for_strmov (dst, src, SImode, offset);
2389 offset = 4;
2391 else if (count & ~3)
2393 HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
2394 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
2396 emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
2399 else
2401 if ((count & ~1) == 2)
2403 single_move_for_strmov (dst, src, HImode, offset);
2404 offset = 2;
2406 else if (count & ~1)
2408 HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
2409 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
2411 emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
2414 if (count & 2)
2416 single_move_for_strmov (dst, src, HImode, offset);
2417 offset += 2;
2419 if (count & 1)
2421 single_move_for_strmov (dst, src, QImode, offset);
2423 return true;
2425 return false;
2429 static int
2430 bfin_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
2432 enum attr_type insn_type, dep_insn_type;
2433 int dep_insn_code_number;
2435 /* Anti and output dependencies have zero cost. */
2436 if (REG_NOTE_KIND (link) != 0)
2437 return 0;
2439 dep_insn_code_number = recog_memoized (dep_insn);
2441 /* If we can't recognize the insns, we can't really do anything. */
2442 if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
2443 return cost;
2445 insn_type = get_attr_type (insn);
2446 dep_insn_type = get_attr_type (dep_insn);
2448 if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)
2450 rtx pat = PATTERN (dep_insn);
2451 rtx dest = SET_DEST (pat);
2452 rtx src = SET_SRC (pat);
2453 if (! ADDRESS_REGNO_P (REGNO (dest)) || ! D_REGNO_P (REGNO (src)))
2454 return cost;
2455 return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);
2458 return cost;
2461 /* We use the machine specific reorg pass for emitting CSYNC instructions
2462 after conditional branches as needed.
2464 The Blackfin is unusual in that a code sequence like
2465 if cc jump label
2466 r0 = (p0)
2467 may speculatively perform the load even if the condition isn't true. This
2468 happens for a branch that is predicted not taken, because the pipeline
2469 isn't flushed or stalled, so the early stages of the following instructions,
2470 which perform the memory reference, are allowed to execute before the
2471 jump condition is evaluated.
2472 Therefore, we must insert additional instructions in all places where this
2473 could lead to incorrect behaviour. The manual recommends CSYNC, while
2474 VDSP seems to use NOPs (even though its corresponding compiler option is
2475 named CSYNC).
2477 When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
2478 When optimizing for size, we turn the branch into a predicted taken one.
2479 This may be slower due to mispredicts, but saves code size. */
2481 static void
2482 bfin_reorg (void)
2484 rtx insn, last_condjump = NULL_RTX;
2485 int cycles_since_jump = INT_MAX;
2487 if (! TARGET_CSYNC)
2488 return;
2490 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
2492 rtx pat;
2494 if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
2495 continue;
2497 pat = PATTERN (insn);
2498 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
2499 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
2500 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
2501 continue;
2503 if (JUMP_P (insn))
2505 if (any_condjump_p (insn)
2506 && ! cbranch_predicted_taken_p (insn))
2508 last_condjump = insn;
2509 cycles_since_jump = 0;
2511 else
2512 cycles_since_jump = INT_MAX;
2514 else if (INSN_P (insn))
2516 enum attr_type type = get_attr_type (insn);
2517 if (cycles_since_jump < INT_MAX)
2518 cycles_since_jump++;
2520 if (type == TYPE_MCLD && cycles_since_jump < 3)
2522 rtx pat;
2524 pat = single_set (insn);
2525 if (may_trap_p (SET_SRC (pat)))
2527 int num_clobbers;
2528 rtx *op = recog_data.operand;
2530 extract_insn (last_condjump);
2531 if (optimize_size)
2532 pat = gen_cbranch_predicted_taken (op[0], op[1], op[2],
2533 op[3]);
2534 else
2535 pat = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
2536 GEN_INT (3 - cycles_since_jump));
2537 PATTERN (last_condjump) = pat;
2538 INSN_CODE (last_condjump) = recog (pat, insn, &num_clobbers);
2539 cycles_since_jump = INT_MAX;
2546 /* Handle interrupt_handler, exception_handler and nmi_handler function
2547 attributes; arguments as in struct attribute_spec.handler. */
2549 static tree
2550 handle_int_attribute (tree *node, tree name,
2551 tree args ATTRIBUTE_UNUSED,
2552 int flags ATTRIBUTE_UNUSED,
2553 bool *no_add_attrs)
2555 tree x = *node;
2556 if (TREE_CODE (x) == FUNCTION_DECL)
2557 x = TREE_TYPE (x);
2559 if (TREE_CODE (x) != FUNCTION_TYPE)
2561 warning (OPT_Wattributes, "%qs attribute only applies to functions",
2562 IDENTIFIER_POINTER (name));
2563 *no_add_attrs = true;
2565 else if (funkind (x) != SUBROUTINE)
2566 error ("multiple function type attributes specified");
2568 return NULL_TREE;
2571 /* Return 0 if the attributes for two types are incompatible, 1 if they
2572 are compatible, and 2 if they are nearly compatible (which causes a
2573 warning to be generated). */
2575 static int
2576 bfin_comp_type_attributes (tree type1, tree type2)
2578 e_funkind kind1, kind2;
2580 if (TREE_CODE (type1) != FUNCTION_TYPE)
2581 return 1;
2583 kind1 = funkind (type1);
2584 kind2 = funkind (type2);
2586 if (kind1 != kind2)
2587 return 0;
2589 /* Check for mismatched modifiers */
2590 if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
2591 != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
2592 return 0;
2594 if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
2595 != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
2596 return 0;
2598 if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
2599 != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
2600 return 0;
2602 return 1;
2605 /* Table of valid machine attributes. */
2606 const struct attribute_spec bfin_attribute_table[] =
2608 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
2609 { "interrupt_handler", 0, 0, false, true, true, handle_int_attribute },
2610 { "exception_handler", 0, 0, false, true, true, handle_int_attribute },
2611 { "nmi_handler", 0, 0, false, true, true, handle_int_attribute },
2612 { "nesting", 0, 0, false, true, true, NULL },
2613 { "kspisusp", 0, 0, false, true, true, NULL },
2614 { "saveall", 0, 0, false, true, true, NULL },
2615 { NULL, 0, 0, false, false, false, NULL }
2618 /* Output the assembler code for a thunk function. THUNK_DECL is the
2619 declaration for the thunk function itself, FUNCTION is the decl for
2620 the target function. DELTA is an immediate constant offset to be
2621 added to THIS. If VCALL_OFFSET is nonzero, the word at
2622 *(*this + vcall_offset) should be added to THIS. */
2624 static void
2625 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
2626 tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
2627 HOST_WIDE_INT vcall_offset, tree function)
2629 rtx xops[3];
2630 /* The this parameter is passed as the first argument. */
2631 rtx this = gen_rtx_REG (Pmode, REG_R0);
2633 /* Adjust the this parameter by a fixed constant. */
2634 if (delta)
2636 xops[1] = this;
2637 if (delta >= -64 && delta <= 63)
2639 xops[0] = GEN_INT (delta);
2640 output_asm_insn ("%1 += %0;", xops);
2642 else if (delta >= -128 && delta < -64)
2644 xops[0] = GEN_INT (delta + 64);
2645 output_asm_insn ("%1 += -64; %1 += %0;", xops);
2647 else if (delta > 63 && delta <= 126)
2649 xops[0] = GEN_INT (delta - 63);
2650 output_asm_insn ("%1 += 63; %1 += %0;", xops);
2652 else
2654 xops[0] = GEN_INT (delta);
2655 output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
2659 /* Adjust the this parameter by a value stored in the vtable. */
2660 if (vcall_offset)
2662 rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
2663 rtx tmp = gen_rtx_REG (Pmode, REG_R2);
2665 xops[1] = tmp;
2666 xops[2] = p2tmp;
2667 output_asm_insn ("%2 = r0; %2 = [%2];", xops);
2669 /* Adjust the this parameter. */
2670 xops[0] = gen_rtx_MEM (Pmode, plus_constant (p2tmp, vcall_offset));
2671 if (!memory_operand (xops[0], Pmode))
2673 rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
2674 xops[0] = GEN_INT (vcall_offset);
2675 xops[1] = tmp2;
2676 output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
2677 xops[0] = gen_rtx_MEM (Pmode, p2tmp);
2679 xops[2] = this;
2680 output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
2683 xops[0] = XEXP (DECL_RTL (function), 0);
2684 if (1 || !flag_pic || (*targetm.binds_local_p) (function))
2685 output_asm_insn ("jump.l\t%P0", xops);
2688 #undef TARGET_ASM_GLOBALIZE_LABEL
2689 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label
2691 #undef TARGET_ASM_FILE_START
2692 #define TARGET_ASM_FILE_START output_file_start
2694 #undef TARGET_ATTRIBUTE_TABLE
2695 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
2697 #undef TARGET_COMP_TYPE_ATTRIBUTES
2698 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
2700 #undef TARGET_RTX_COSTS
2701 #define TARGET_RTX_COSTS bfin_rtx_costs
2703 #undef TARGET_ADDRESS_COST
2704 #define TARGET_ADDRESS_COST bfin_address_cost
2706 #undef TARGET_ASM_INTERNAL_LABEL
2707 #define TARGET_ASM_INTERNAL_LABEL bfin_internal_label
2709 #undef TARGET_MACHINE_DEPENDENT_REORG
2710 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
2712 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
2713 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
2715 #undef TARGET_ASM_OUTPUT_MI_THUNK
2716 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
2717 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
2718 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
2720 #undef TARGET_SCHED_ADJUST_COST
2721 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
2723 #undef TARGET_PROMOTE_PROTOTYPES
2724 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
2725 #undef TARGET_PROMOTE_FUNCTION_ARGS
2726 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
2727 #undef TARGET_PROMOTE_FUNCTION_RETURN
2728 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
2730 #undef TARGET_ARG_PARTIAL_BYTES
2731 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
2733 #undef TARGET_PASS_BY_REFERENCE
2734 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
2736 #undef TARGET_SETUP_INCOMING_VARARGS
2737 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
2739 #undef TARGET_STRUCT_VALUE_RTX
2740 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
2742 #undef TARGET_VECTOR_MODE_SUPPORTED_P
2743 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
2745 #undef TARGET_HANDLE_OPTION
2746 #define TARGET_HANDLE_OPTION bfin_handle_option
2748 struct gcc_target targetm = TARGET_INITIALIZER;