* config/bfin/bfin.c (bfin_output_mi_thunk): Use R3 as scratch reg
[official-gcc.git] / gcc / config / bfin / bfin.c
blob43ab3ec85dd7688dff58f92e3d440fd26d13eb4f
1 /* The Blackfin code generation auxiliary output file.
2 Copyright (C) 2005, 2006 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, 51 Franklin Street, Fifth Floor,
20 Boston, MA 02110-1301, 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 "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 "optabs.h"
47 #include "ggc.h"
48 #include "integrate.h"
49 #include "cgraph.h"
50 #include "langhooks.h"
51 #include "bfin-protos.h"
52 #include "tm-preds.h"
53 #include "gt-bfin.h"
54 #include "basic-block.h"
55 #include "cfglayout.h"
56 #include "timevar.h"
58 /* A C structure for machine-specific, per-function data.
59 This is added to the cfun structure. */
60 struct machine_function GTY(())
62 int has_hardware_loops;
65 /* Test and compare insns in bfin.md store the information needed to
66 generate branch and scc insns here. */
67 rtx bfin_compare_op0, bfin_compare_op1;
69 /* RTX for condition code flag register and RETS register */
70 extern GTY(()) rtx bfin_cc_rtx;
71 extern GTY(()) rtx bfin_rets_rtx;
72 rtx bfin_cc_rtx, bfin_rets_rtx;
74 int max_arg_registers = 0;
76 /* Arrays used when emitting register names. */
77 const char *short_reg_names[] = SHORT_REGISTER_NAMES;
78 const char *high_reg_names[] = HIGH_REGISTER_NAMES;
79 const char *dregs_pair_names[] = DREGS_PAIR_NAMES;
80 const char *byte_reg_names[] = BYTE_REGISTER_NAMES;
82 static int arg_regs[] = FUNCTION_ARG_REGISTERS;
84 /* Nonzero if -mshared-library-id was given. */
85 static int bfin_lib_id_given;
87 /* Nonzero if -fschedule-insns2 was given. We override it and
88 call the scheduler ourselves during reorg. */
89 static int bfin_flag_schedule_insns2;
91 /* Determines whether we run variable tracking in machine dependent
92 reorganization. */
93 static int bfin_flag_var_tracking;
95 int splitting_for_sched;
97 static void
98 bfin_globalize_label (FILE *stream, const char *name)
100 fputs (".global ", stream);
101 assemble_name (stream, name);
102 fputc (';',stream);
103 fputc ('\n',stream);
106 static void
107 output_file_start (void)
109 FILE *file = asm_out_file;
110 int i;
112 /* Variable tracking should be run after all optimizations which change order
113 of insns. It also needs a valid CFG. This can't be done in
114 override_options, because flag_var_tracking is finalized after
115 that. */
116 bfin_flag_var_tracking = flag_var_tracking;
117 flag_var_tracking = 0;
119 fprintf (file, ".file \"%s\";\n", input_filename);
121 for (i = 0; arg_regs[i] >= 0; i++)
123 max_arg_registers = i; /* how many arg reg used */
126 /* Called early in the compilation to conditionally modify
127 fixed_regs/call_used_regs. */
129 void
130 conditional_register_usage (void)
132 /* initialize condition code flag register rtx */
133 bfin_cc_rtx = gen_rtx_REG (BImode, REG_CC);
134 bfin_rets_rtx = gen_rtx_REG (Pmode, REG_RETS);
137 /* Examine machine-dependent attributes of function type FUNTYPE and return its
138 type. See the definition of E_FUNKIND. */
140 static e_funkind funkind (tree funtype)
142 tree attrs = TYPE_ATTRIBUTES (funtype);
143 if (lookup_attribute ("interrupt_handler", attrs))
144 return INTERRUPT_HANDLER;
145 else if (lookup_attribute ("exception_handler", attrs))
146 return EXCPT_HANDLER;
147 else if (lookup_attribute ("nmi_handler", attrs))
148 return NMI_HANDLER;
149 else
150 return SUBROUTINE;
153 /* Legitimize PIC addresses. If the address is already position-independent,
154 we return ORIG. Newly generated position-independent addresses go into a
155 reg. This is REG if nonzero, otherwise we allocate register(s) as
156 necessary. PICREG is the register holding the pointer to the PIC offset
157 table. */
159 static rtx
160 legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
162 rtx addr = orig;
163 rtx new = orig;
165 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
167 int unspec;
168 rtx tmp;
170 if (TARGET_ID_SHARED_LIBRARY)
171 unspec = UNSPEC_MOVE_PIC;
172 else if (GET_CODE (addr) == SYMBOL_REF
173 && SYMBOL_REF_FUNCTION_P (addr))
174 unspec = UNSPEC_FUNCDESC_GOT17M4;
175 else
176 unspec = UNSPEC_MOVE_FDPIC;
178 if (reg == 0)
180 gcc_assert (!no_new_pseudos);
181 reg = gen_reg_rtx (Pmode);
184 tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), unspec);
185 new = gen_const_mem (Pmode, gen_rtx_PLUS (Pmode, picreg, tmp));
187 emit_move_insn (reg, new);
188 if (picreg == pic_offset_table_rtx)
189 current_function_uses_pic_offset_table = 1;
190 return reg;
193 else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
195 rtx base;
197 if (GET_CODE (addr) == CONST)
199 addr = XEXP (addr, 0);
200 gcc_assert (GET_CODE (addr) == PLUS);
203 if (XEXP (addr, 0) == picreg)
204 return orig;
206 if (reg == 0)
208 gcc_assert (!no_new_pseudos);
209 reg = gen_reg_rtx (Pmode);
212 base = legitimize_pic_address (XEXP (addr, 0), reg, picreg);
213 addr = legitimize_pic_address (XEXP (addr, 1),
214 base == reg ? NULL_RTX : reg,
215 picreg);
217 if (GET_CODE (addr) == CONST_INT)
219 gcc_assert (! reload_in_progress && ! reload_completed);
220 addr = force_reg (Pmode, addr);
223 if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
225 base = gen_rtx_PLUS (Pmode, base, XEXP (addr, 0));
226 addr = XEXP (addr, 1);
229 return gen_rtx_PLUS (Pmode, base, addr);
232 return new;
235 /* Stack frame layout. */
237 /* Compute the number of DREGS to save with a push_multiple operation.
238 This could include registers that aren't modified in the function,
239 since push_multiple only takes a range of registers.
240 If IS_INTHANDLER, then everything that is live must be saved, even
241 if normally call-clobbered. */
243 static int
244 n_dregs_to_save (bool is_inthandler)
246 unsigned i;
248 for (i = REG_R0; i <= REG_R7; i++)
250 if (regs_ever_live[i] && (is_inthandler || ! call_used_regs[i]))
251 return REG_R7 - i + 1;
253 if (current_function_calls_eh_return)
255 unsigned j;
256 for (j = 0; ; j++)
258 unsigned test = EH_RETURN_DATA_REGNO (j);
259 if (test == INVALID_REGNUM)
260 break;
261 if (test == i)
262 return REG_R7 - i + 1;
267 return 0;
270 /* Like n_dregs_to_save, but compute number of PREGS to save. */
272 static int
273 n_pregs_to_save (bool is_inthandler)
275 unsigned i;
277 for (i = REG_P0; i <= REG_P5; i++)
278 if ((regs_ever_live[i] && (is_inthandler || ! call_used_regs[i]))
279 || (!TARGET_FDPIC
280 && i == PIC_OFFSET_TABLE_REGNUM
281 && (current_function_uses_pic_offset_table
282 || (TARGET_ID_SHARED_LIBRARY && ! current_function_is_leaf))))
283 return REG_P5 - i + 1;
284 return 0;
287 /* Determine if we are going to save the frame pointer in the prologue. */
289 static bool
290 must_save_fp_p (void)
292 return frame_pointer_needed || regs_ever_live[REG_FP];
295 static bool
296 stack_frame_needed_p (void)
298 /* EH return puts a new return address into the frame using an
299 address relative to the frame pointer. */
300 if (current_function_calls_eh_return)
301 return true;
302 return frame_pointer_needed;
305 /* Emit code to save registers in the prologue. SAVEALL is nonzero if we
306 must save all registers; this is used for interrupt handlers.
307 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
308 this for an interrupt (or exception) handler. */
310 static void
311 expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler)
313 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler);
314 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler);
315 int dregno = REG_R7 + 1 - ndregs;
316 int pregno = REG_P5 + 1 - npregs;
317 int total = ndregs + npregs;
318 int i;
319 rtx pat, insn, val;
321 if (total == 0)
322 return;
324 val = GEN_INT (-total * 4);
325 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total + 2));
326 XVECEXP (pat, 0, 0) = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, val),
327 UNSPEC_PUSH_MULTIPLE);
328 XVECEXP (pat, 0, total + 1) = gen_rtx_SET (VOIDmode, spreg,
329 gen_rtx_PLUS (Pmode, spreg,
330 val));
331 RTX_FRAME_RELATED_P (XVECEXP (pat, 0, total + 1)) = 1;
332 for (i = 0; i < total; i++)
334 rtx memref = gen_rtx_MEM (word_mode,
335 gen_rtx_PLUS (Pmode, spreg,
336 GEN_INT (- i * 4 - 4)));
337 rtx subpat;
338 if (ndregs > 0)
340 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
341 dregno++));
342 ndregs--;
344 else
346 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
347 pregno++));
348 npregs++;
350 XVECEXP (pat, 0, i + 1) = subpat;
351 RTX_FRAME_RELATED_P (subpat) = 1;
353 insn = emit_insn (pat);
354 RTX_FRAME_RELATED_P (insn) = 1;
357 /* Emit code to restore registers in the epilogue. SAVEALL is nonzero if we
358 must save all registers; this is used for interrupt handlers.
359 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
360 this for an interrupt (or exception) handler. */
362 static void
363 expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler)
365 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler);
366 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler);
367 int total = ndregs + npregs;
368 int i, regno;
369 rtx pat, insn;
371 if (total == 0)
372 return;
374 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total + 1));
375 XVECEXP (pat, 0, 0) = gen_rtx_SET (VOIDmode, spreg,
376 gen_rtx_PLUS (Pmode, spreg,
377 GEN_INT (total * 4)));
379 if (npregs > 0)
380 regno = REG_P5 + 1;
381 else
382 regno = REG_R7 + 1;
384 for (i = 0; i < total; i++)
386 rtx addr = (i > 0
387 ? gen_rtx_PLUS (Pmode, spreg, GEN_INT (i * 4))
388 : spreg);
389 rtx memref = gen_rtx_MEM (word_mode, addr);
391 regno--;
392 XVECEXP (pat, 0, i + 1)
393 = gen_rtx_SET (VOIDmode, gen_rtx_REG (word_mode, regno), memref);
395 if (npregs > 0)
397 if (--npregs == 0)
398 regno = REG_R7 + 1;
402 insn = emit_insn (pat);
403 RTX_FRAME_RELATED_P (insn) = 1;
406 /* Perform any needed actions needed for a function that is receiving a
407 variable number of arguments.
409 CUM is as above.
411 MODE and TYPE are the mode and type of the current parameter.
413 PRETEND_SIZE is a variable that should be set to the amount of stack
414 that must be pushed by the prolog to pretend that our caller pushed
417 Normally, this macro will push all remaining incoming registers on the
418 stack and set PRETEND_SIZE to the length of the registers pushed.
420 Blackfin specific :
421 - VDSP C compiler manual (our ABI) says that a variable args function
422 should save the R0, R1 and R2 registers in the stack.
423 - The caller will always leave space on the stack for the
424 arguments that are passed in registers, so we dont have
425 to leave any extra space.
426 - now, the vastart pointer can access all arguments from the stack. */
428 static void
429 setup_incoming_varargs (CUMULATIVE_ARGS *cum,
430 enum machine_mode mode ATTRIBUTE_UNUSED,
431 tree type ATTRIBUTE_UNUSED, int *pretend_size,
432 int no_rtl)
434 rtx mem;
435 int i;
437 if (no_rtl)
438 return;
440 /* The move for named arguments will be generated automatically by the
441 compiler. We need to generate the move rtx for the unnamed arguments
442 if they are in the first 3 words. We assume at least 1 named argument
443 exists, so we never generate [ARGP] = R0 here. */
445 for (i = cum->words + 1; i < max_arg_registers; i++)
447 mem = gen_rtx_MEM (Pmode,
448 plus_constant (arg_pointer_rtx, (i * UNITS_PER_WORD)));
449 emit_move_insn (mem, gen_rtx_REG (Pmode, i));
452 *pretend_size = 0;
455 /* Value should be nonzero if functions must have frame pointers.
456 Zero means the frame pointer need not be set up (and parms may
457 be accessed via the stack pointer) in functions that seem suitable. */
460 bfin_frame_pointer_required (void)
462 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
464 if (fkind != SUBROUTINE)
465 return 1;
467 /* We turn on -fomit-frame-pointer if -momit-leaf-frame-pointer is used,
468 so we have to override it for non-leaf functions. */
469 if (TARGET_OMIT_LEAF_FRAME_POINTER && ! current_function_is_leaf)
470 return 1;
472 return 0;
475 /* Return the number of registers pushed during the prologue. */
477 static int
478 n_regs_saved_by_prologue (void)
480 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
481 bool is_inthandler = fkind != SUBROUTINE;
482 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
483 bool all = (lookup_attribute ("saveall", attrs) != NULL_TREE
484 || (is_inthandler && !current_function_is_leaf));
485 int ndregs = all ? 8 : n_dregs_to_save (is_inthandler);
486 int npregs = all ? 6 : n_pregs_to_save (is_inthandler);
487 int n = ndregs + npregs;
489 if (all || stack_frame_needed_p ())
490 /* We use a LINK instruction in this case. */
491 n += 2;
492 else
494 if (must_save_fp_p ())
495 n++;
496 if (! current_function_is_leaf)
497 n++;
500 if (fkind != SUBROUTINE)
502 int i;
504 /* Increment once for ASTAT. */
505 n++;
507 /* RETE/X/N. */
508 if (lookup_attribute ("nesting", attrs))
509 n++;
511 for (i = REG_P7 + 1; i < REG_CC; i++)
512 if (all
513 || regs_ever_live[i]
514 || (!leaf_function_p () && call_used_regs[i]))
515 n += i == REG_A0 || i == REG_A1 ? 2 : 1;
517 return n;
520 /* Return the offset between two registers, one to be eliminated, and the other
521 its replacement, at the start of a routine. */
523 HOST_WIDE_INT
524 bfin_initial_elimination_offset (int from, int to)
526 HOST_WIDE_INT offset = 0;
528 if (from == ARG_POINTER_REGNUM)
529 offset = n_regs_saved_by_prologue () * 4;
531 if (to == STACK_POINTER_REGNUM)
533 if (current_function_outgoing_args_size >= FIXED_STACK_AREA)
534 offset += current_function_outgoing_args_size;
535 else if (current_function_outgoing_args_size)
536 offset += FIXED_STACK_AREA;
538 offset += get_frame_size ();
541 return offset;
544 /* Emit code to load a constant CONSTANT into register REG; setting
545 RTX_FRAME_RELATED_P on all insns we generate if RELATED is true.
546 Make sure that the insns we generate need not be split. */
548 static void
549 frame_related_constant_load (rtx reg, HOST_WIDE_INT constant, bool related)
551 rtx insn;
552 rtx cst = GEN_INT (constant);
554 if (constant >= -32768 && constant < 65536)
555 insn = emit_move_insn (reg, cst);
556 else
558 /* We don't call split_load_immediate here, since dwarf2out.c can get
559 confused about some of the more clever sequences it can generate. */
560 insn = emit_insn (gen_movsi_high (reg, cst));
561 if (related)
562 RTX_FRAME_RELATED_P (insn) = 1;
563 insn = emit_insn (gen_movsi_low (reg, reg, cst));
565 if (related)
566 RTX_FRAME_RELATED_P (insn) = 1;
569 /* Generate efficient code to add a value to a P register. We can use
570 P1 as a scratch register. Set RTX_FRAME_RELATED_P on the generated
571 insns if FRAME is nonzero. */
573 static void
574 add_to_reg (rtx reg, HOST_WIDE_INT value, int frame)
576 if (value == 0)
577 return;
579 /* Choose whether to use a sequence using a temporary register, or
580 a sequence with multiple adds. We can add a signed 7-bit value
581 in one instruction. */
582 if (value > 120 || value < -120)
584 rtx tmpreg = gen_rtx_REG (SImode, REG_P1);
585 rtx insn;
587 if (frame)
588 frame_related_constant_load (tmpreg, value, TRUE);
589 else
590 insn = emit_move_insn (tmpreg, GEN_INT (value));
592 insn = emit_insn (gen_addsi3 (reg, reg, tmpreg));
593 if (frame)
594 RTX_FRAME_RELATED_P (insn) = 1;
596 else
599 int size = value;
600 rtx insn;
602 if (size > 60)
603 size = 60;
604 else if (size < -60)
605 /* We could use -62, but that would leave the stack unaligned, so
606 it's no good. */
607 size = -60;
609 insn = emit_insn (gen_addsi3 (reg, reg, GEN_INT (size)));
610 if (frame)
611 RTX_FRAME_RELATED_P (insn) = 1;
612 value -= size;
614 while (value != 0);
617 /* Generate a LINK insn for a frame sized FRAME_SIZE. If this constant
618 is too large, generate a sequence of insns that has the same effect.
619 SPREG contains (reg:SI REG_SP). */
621 static void
622 emit_link_insn (rtx spreg, HOST_WIDE_INT frame_size)
624 HOST_WIDE_INT link_size = frame_size;
625 rtx insn;
626 int i;
628 if (link_size > 262140)
629 link_size = 262140;
631 /* Use a LINK insn with as big a constant as possible, then subtract
632 any remaining size from the SP. */
633 insn = emit_insn (gen_link (GEN_INT (-8 - link_size)));
634 RTX_FRAME_RELATED_P (insn) = 1;
636 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
638 rtx set = XVECEXP (PATTERN (insn), 0, i);
639 gcc_assert (GET_CODE (set) == SET);
640 RTX_FRAME_RELATED_P (set) = 1;
643 frame_size -= link_size;
645 if (frame_size > 0)
647 /* Must use a call-clobbered PREG that isn't the static chain. */
648 rtx tmpreg = gen_rtx_REG (Pmode, REG_P1);
650 frame_related_constant_load (tmpreg, -frame_size, TRUE);
651 insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg));
652 RTX_FRAME_RELATED_P (insn) = 1;
656 /* Return the number of bytes we must reserve for outgoing arguments
657 in the current function's stack frame. */
659 static HOST_WIDE_INT
660 arg_area_size (void)
662 if (current_function_outgoing_args_size)
664 if (current_function_outgoing_args_size >= FIXED_STACK_AREA)
665 return current_function_outgoing_args_size;
666 else
667 return FIXED_STACK_AREA;
669 return 0;
672 /* Save RETS and FP, and allocate a stack frame. ALL is true if the
673 function must save all its registers (true only for certain interrupt
674 handlers). */
676 static void
677 do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all)
679 frame_size += arg_area_size ();
681 if (all || stack_frame_needed_p ()
682 || (must_save_fp_p () && ! current_function_is_leaf))
683 emit_link_insn (spreg, frame_size);
684 else
686 if (! current_function_is_leaf)
688 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
689 gen_rtx_PRE_DEC (Pmode, spreg)),
690 bfin_rets_rtx);
691 rtx insn = emit_insn (pat);
692 RTX_FRAME_RELATED_P (insn) = 1;
694 if (must_save_fp_p ())
696 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
697 gen_rtx_PRE_DEC (Pmode, spreg)),
698 gen_rtx_REG (Pmode, REG_FP));
699 rtx insn = emit_insn (pat);
700 RTX_FRAME_RELATED_P (insn) = 1;
702 add_to_reg (spreg, -frame_size, 1);
706 /* Like do_link, but used for epilogues to deallocate the stack frame. */
708 static void
709 do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all)
711 frame_size += arg_area_size ();
713 if (all || stack_frame_needed_p ())
714 emit_insn (gen_unlink ());
715 else
717 rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg));
719 add_to_reg (spreg, frame_size, 0);
720 if (must_save_fp_p ())
722 rtx fpreg = gen_rtx_REG (Pmode, REG_FP);
723 emit_move_insn (fpreg, postinc);
724 emit_insn (gen_rtx_USE (VOIDmode, fpreg));
726 if (! current_function_is_leaf)
728 emit_move_insn (bfin_rets_rtx, postinc);
729 emit_insn (gen_rtx_USE (VOIDmode, bfin_rets_rtx));
734 /* Generate a prologue suitable for a function of kind FKIND. This is
735 called for interrupt and exception handler prologues.
736 SPREG contains (reg:SI REG_SP). */
738 static void
739 expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind)
741 int i;
742 HOST_WIDE_INT frame_size = get_frame_size ();
743 rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
744 rtx predec = gen_rtx_MEM (SImode, predec1);
745 rtx insn;
746 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
747 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
748 tree kspisusp = lookup_attribute ("kspisusp", attrs);
750 if (kspisusp)
752 insn = emit_move_insn (spreg, gen_rtx_REG (Pmode, REG_USP));
753 RTX_FRAME_RELATED_P (insn) = 1;
756 /* We need space on the stack in case we need to save the argument
757 registers. */
758 if (fkind == EXCPT_HANDLER)
760 insn = emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (-12)));
761 RTX_FRAME_RELATED_P (insn) = 1;
764 insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
765 RTX_FRAME_RELATED_P (insn) = 1;
767 /* If we're calling other functions, they won't save their call-clobbered
768 registers, so we must save everything here. */
769 if (!current_function_is_leaf)
770 all = true;
771 expand_prologue_reg_save (spreg, all, true);
773 for (i = REG_P7 + 1; i < REG_CC; i++)
774 if (all
775 || regs_ever_live[i]
776 || (!leaf_function_p () && call_used_regs[i]))
778 if (i == REG_A0 || i == REG_A1)
779 insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1),
780 gen_rtx_REG (PDImode, i));
781 else
782 insn = emit_move_insn (predec, gen_rtx_REG (SImode, i));
783 RTX_FRAME_RELATED_P (insn) = 1;
786 if (lookup_attribute ("nesting", attrs))
788 rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
789 : fkind == NMI_HANDLER ? REG_RETN
790 : REG_RETI));
791 insn = emit_move_insn (predec, srcreg);
792 RTX_FRAME_RELATED_P (insn) = 1;
795 do_link (spreg, frame_size, all);
797 if (fkind == EXCPT_HANDLER)
799 rtx r0reg = gen_rtx_REG (SImode, REG_R0);
800 rtx r1reg = gen_rtx_REG (SImode, REG_R1);
801 rtx r2reg = gen_rtx_REG (SImode, REG_R2);
802 rtx insn;
804 insn = emit_move_insn (r0reg, gen_rtx_REG (SImode, REG_SEQSTAT));
805 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
806 NULL_RTX);
807 insn = emit_insn (gen_ashrsi3 (r0reg, r0reg, GEN_INT (26)));
808 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
809 NULL_RTX);
810 insn = emit_insn (gen_ashlsi3 (r0reg, r0reg, GEN_INT (26)));
811 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
812 NULL_RTX);
813 insn = emit_move_insn (r1reg, spreg);
814 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
815 NULL_RTX);
816 insn = emit_move_insn (r2reg, gen_rtx_REG (Pmode, REG_FP));
817 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
818 NULL_RTX);
819 insn = emit_insn (gen_addsi3 (r2reg, r2reg, GEN_INT (8)));
820 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx,
821 NULL_RTX);
825 /* Generate an epilogue suitable for a function of kind FKIND. This is
826 called for interrupt and exception handler epilogues.
827 SPREG contains (reg:SI REG_SP). */
829 static void
830 expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind)
832 int i;
833 rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
834 rtx postinc = gen_rtx_MEM (SImode, postinc1);
835 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
836 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
838 /* A slightly crude technique to stop flow from trying to delete "dead"
839 insns. */
840 MEM_VOLATILE_P (postinc) = 1;
842 do_unlink (spreg, get_frame_size (), all);
844 if (lookup_attribute ("nesting", attrs))
846 rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
847 : fkind == NMI_HANDLER ? REG_RETN
848 : REG_RETI));
849 emit_move_insn (srcreg, postinc);
852 /* If we're calling other functions, they won't save their call-clobbered
853 registers, so we must save (and restore) everything here. */
854 if (!current_function_is_leaf)
855 all = true;
857 for (i = REG_CC - 1; i > REG_P7; i--)
858 if (all
859 || regs_ever_live[i]
860 || (!leaf_function_p () && call_used_regs[i]))
862 if (i == REG_A0 || i == REG_A1)
864 rtx mem = gen_rtx_MEM (PDImode, postinc1);
865 MEM_VOLATILE_P (mem) = 1;
866 emit_move_insn (gen_rtx_REG (PDImode, i), mem);
868 else
869 emit_move_insn (gen_rtx_REG (SImode, i), postinc);
872 expand_epilogue_reg_restore (spreg, all, true);
874 emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
876 /* Deallocate any space we left on the stack in case we needed to save the
877 argument registers. */
878 if (fkind == EXCPT_HANDLER)
879 emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (12)));
881 emit_jump_insn (gen_return_internal (GEN_INT (fkind)));
884 /* Used while emitting the prologue to generate code to load the correct value
885 into the PIC register, which is passed in DEST. */
887 static rtx
888 bfin_load_pic_reg (rtx dest)
890 struct cgraph_local_info *i = NULL;
891 rtx addr, insn;
893 if (flag_unit_at_a_time)
894 i = cgraph_local_info (current_function_decl);
896 /* Functions local to the translation unit don't need to reload the
897 pic reg, since the caller always passes a usable one. */
898 if (i && i->local)
899 return pic_offset_table_rtx;
901 if (bfin_lib_id_given)
902 addr = plus_constant (pic_offset_table_rtx, -4 - bfin_library_id * 4);
903 else
904 addr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
905 gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
906 UNSPEC_LIBRARY_OFFSET));
907 insn = emit_insn (gen_movsi (dest, gen_rtx_MEM (Pmode, addr)));
908 REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_MAYBE_DEAD, const0_rtx, NULL);
909 return dest;
912 /* Generate RTL for the prologue of the current function. */
914 void
915 bfin_expand_prologue (void)
917 rtx insn;
918 HOST_WIDE_INT frame_size = get_frame_size ();
919 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
920 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
921 rtx pic_reg_loaded = NULL_RTX;
923 if (fkind != SUBROUTINE)
925 expand_interrupt_handler_prologue (spreg, fkind);
926 return;
929 if (current_function_limit_stack
930 || TARGET_STACK_CHECK_L1)
932 HOST_WIDE_INT offset
933 = bfin_initial_elimination_offset (ARG_POINTER_REGNUM,
934 STACK_POINTER_REGNUM);
935 rtx lim = current_function_limit_stack ? stack_limit_rtx : NULL_RTX;
936 rtx p2reg = gen_rtx_REG (Pmode, REG_P2);
938 if (!lim)
940 rtx p1reg = gen_rtx_REG (Pmode, REG_P1);
941 emit_move_insn (p2reg, gen_int_mode (0xFFB00000, SImode));
942 emit_move_insn (p2reg, gen_rtx_MEM (Pmode, p2reg));
943 lim = p2reg;
945 if (GET_CODE (lim) == SYMBOL_REF)
947 if (TARGET_ID_SHARED_LIBRARY)
949 rtx p1reg = gen_rtx_REG (Pmode, REG_P1);
950 rtx val;
951 pic_reg_loaded = bfin_load_pic_reg (p2reg);
952 val = legitimize_pic_address (stack_limit_rtx, p1reg,
953 pic_reg_loaded);
954 emit_move_insn (p1reg, val);
955 frame_related_constant_load (p2reg, offset, FALSE);
956 emit_insn (gen_addsi3 (p2reg, p2reg, p1reg));
957 lim = p2reg;
959 else
961 rtx limit = plus_constant (lim, offset);
962 emit_move_insn (p2reg, limit);
963 lim = p2reg;
966 else
968 if (lim != p2reg)
969 emit_move_insn (p2reg, lim);
970 add_to_reg (p2reg, offset, 0);
971 lim = p2reg;
973 emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim));
974 emit_insn (gen_trapifcc ());
976 expand_prologue_reg_save (spreg, 0, false);
978 do_link (spreg, frame_size, false);
980 if (TARGET_ID_SHARED_LIBRARY
981 && !TARGET_SEP_DATA
982 && (current_function_uses_pic_offset_table
983 || !current_function_is_leaf))
984 bfin_load_pic_reg (pic_offset_table_rtx);
987 /* Generate RTL for the epilogue of the current function. NEED_RETURN is zero
988 if this is for a sibcall. EH_RETURN is nonzero if we're expanding an
989 eh_return pattern. */
991 void
992 bfin_expand_epilogue (int need_return, int eh_return)
994 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
995 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
997 if (fkind != SUBROUTINE)
999 expand_interrupt_handler_epilogue (spreg, fkind);
1000 return;
1003 do_unlink (spreg, get_frame_size (), false);
1005 expand_epilogue_reg_restore (spreg, false, false);
1007 /* Omit the return insn if this is for a sibcall. */
1008 if (! need_return)
1009 return;
1011 if (eh_return)
1012 emit_insn (gen_addsi3 (spreg, spreg, gen_rtx_REG (Pmode, REG_P2)));
1014 emit_jump_insn (gen_return_internal (GEN_INT (SUBROUTINE)));
1017 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
1020 bfin_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
1021 unsigned int new_reg)
1023 /* Interrupt functions can only use registers that have already been
1024 saved by the prologue, even if they would normally be
1025 call-clobbered. */
1027 if (funkind (TREE_TYPE (current_function_decl)) != SUBROUTINE
1028 && !regs_ever_live[new_reg])
1029 return 0;
1031 return 1;
1034 /* Return the value of the return address for the frame COUNT steps up
1035 from the current frame, after the prologue.
1036 We punt for everything but the current frame by returning const0_rtx. */
1039 bfin_return_addr_rtx (int count)
1041 if (count != 0)
1042 return const0_rtx;
1044 return get_hard_reg_initial_val (Pmode, REG_RETS);
1047 /* Try machine-dependent ways of modifying an illegitimate address X
1048 to be legitimate. If we find one, return the new, valid address,
1049 otherwise return NULL_RTX.
1051 OLDX is the address as it was before break_out_memory_refs was called.
1052 In some cases it is useful to look at this to decide what needs to be done.
1054 MODE is the mode of the memory reference. */
1057 legitimize_address (rtx x ATTRIBUTE_UNUSED, rtx oldx ATTRIBUTE_UNUSED,
1058 enum machine_mode mode ATTRIBUTE_UNUSED)
1060 return NULL_RTX;
1063 static rtx
1064 bfin_delegitimize_address (rtx orig_x)
1066 rtx x = orig_x, y;
1068 if (GET_CODE (x) != MEM)
1069 return orig_x;
1071 x = XEXP (x, 0);
1072 if (GET_CODE (x) == PLUS
1073 && GET_CODE (XEXP (x, 1)) == UNSPEC
1074 && XINT (XEXP (x, 1), 1) == UNSPEC_MOVE_PIC
1075 && GET_CODE (XEXP (x, 0)) == REG
1076 && REGNO (XEXP (x, 0)) == PIC_OFFSET_TABLE_REGNUM)
1077 return XVECEXP (XEXP (x, 1), 0, 0);
1079 return orig_x;
1082 /* This predicate is used to compute the length of a load/store insn.
1083 OP is a MEM rtx, we return nonzero if its addressing mode requires a
1084 32-bit instruction. */
1087 effective_address_32bit_p (rtx op, enum machine_mode mode)
1089 HOST_WIDE_INT offset;
1091 mode = GET_MODE (op);
1092 op = XEXP (op, 0);
1094 if (GET_CODE (op) != PLUS)
1096 gcc_assert (REG_P (op) || GET_CODE (op) == POST_INC
1097 || GET_CODE (op) == PRE_DEC || GET_CODE (op) == POST_DEC);
1098 return 0;
1101 if (GET_CODE (XEXP (op, 1)) == UNSPEC)
1102 return 1;
1104 offset = INTVAL (XEXP (op, 1));
1106 /* All byte loads use a 16-bit offset. */
1107 if (GET_MODE_SIZE (mode) == 1)
1108 return 1;
1110 if (GET_MODE_SIZE (mode) == 4)
1112 /* Frame pointer relative loads can use a negative offset, all others
1113 are restricted to a small positive one. */
1114 if (XEXP (op, 0) == frame_pointer_rtx)
1115 return offset < -128 || offset > 60;
1116 return offset < 0 || offset > 60;
1119 /* Must be HImode now. */
1120 return offset < 0 || offset > 30;
1123 /* Returns true if X is a memory reference using an I register. */
1124 bool
1125 bfin_dsp_memref_p (rtx x)
1127 if (! MEM_P (x))
1128 return false;
1129 x = XEXP (x, 0);
1130 if (GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_INC
1131 || GET_CODE (x) == POST_DEC || GET_CODE (x) == PRE_DEC)
1132 x = XEXP (x, 0);
1133 return IREG_P (x);
1136 /* Return cost of the memory address ADDR.
1137 All addressing modes are equally cheap on the Blackfin. */
1139 static int
1140 bfin_address_cost (rtx addr ATTRIBUTE_UNUSED)
1142 return 1;
1145 /* Subroutine of print_operand; used to print a memory reference X to FILE. */
1147 void
1148 print_address_operand (FILE *file, rtx x)
1150 switch (GET_CODE (x))
1152 case PLUS:
1153 output_address (XEXP (x, 0));
1154 fprintf (file, "+");
1155 output_address (XEXP (x, 1));
1156 break;
1158 case PRE_DEC:
1159 fprintf (file, "--");
1160 output_address (XEXP (x, 0));
1161 break;
1162 case POST_INC:
1163 output_address (XEXP (x, 0));
1164 fprintf (file, "++");
1165 break;
1166 case POST_DEC:
1167 output_address (XEXP (x, 0));
1168 fprintf (file, "--");
1169 break;
1171 default:
1172 gcc_assert (GET_CODE (x) != MEM);
1173 print_operand (file, x, 0);
1174 break;
1178 /* Adding intp DImode support by Tony
1179 * -- Q: (low word)
1180 * -- R: (high word)
1183 void
1184 print_operand (FILE *file, rtx x, char code)
1186 enum machine_mode mode;
1188 if (code == '!')
1190 if (GET_MODE (current_output_insn) == SImode)
1191 fprintf (file, " ||");
1192 else
1193 fprintf (file, ";");
1194 return;
1197 mode = GET_MODE (x);
1199 switch (code)
1201 case 'j':
1202 switch (GET_CODE (x))
1204 case EQ:
1205 fprintf (file, "e");
1206 break;
1207 case NE:
1208 fprintf (file, "ne");
1209 break;
1210 case GT:
1211 fprintf (file, "g");
1212 break;
1213 case LT:
1214 fprintf (file, "l");
1215 break;
1216 case GE:
1217 fprintf (file, "ge");
1218 break;
1219 case LE:
1220 fprintf (file, "le");
1221 break;
1222 case GTU:
1223 fprintf (file, "g");
1224 break;
1225 case LTU:
1226 fprintf (file, "l");
1227 break;
1228 case GEU:
1229 fprintf (file, "ge");
1230 break;
1231 case LEU:
1232 fprintf (file, "le");
1233 break;
1234 default:
1235 output_operand_lossage ("invalid %%j value");
1237 break;
1239 case 'J': /* reverse logic */
1240 switch (GET_CODE(x))
1242 case EQ:
1243 fprintf (file, "ne");
1244 break;
1245 case NE:
1246 fprintf (file, "e");
1247 break;
1248 case GT:
1249 fprintf (file, "le");
1250 break;
1251 case LT:
1252 fprintf (file, "ge");
1253 break;
1254 case GE:
1255 fprintf (file, "l");
1256 break;
1257 case LE:
1258 fprintf (file, "g");
1259 break;
1260 case GTU:
1261 fprintf (file, "le");
1262 break;
1263 case LTU:
1264 fprintf (file, "ge");
1265 break;
1266 case GEU:
1267 fprintf (file, "l");
1268 break;
1269 case LEU:
1270 fprintf (file, "g");
1271 break;
1272 default:
1273 output_operand_lossage ("invalid %%J value");
1275 break;
1277 default:
1278 switch (GET_CODE (x))
1280 case REG:
1281 if (code == 'h')
1283 gcc_assert (REGNO (x) < 32);
1284 fprintf (file, "%s", short_reg_names[REGNO (x)]);
1285 /*fprintf (file, "\n%d\n ", REGNO (x));*/
1286 break;
1288 else if (code == 'd')
1290 gcc_assert (REGNO (x) < 32);
1291 fprintf (file, "%s", high_reg_names[REGNO (x)]);
1292 break;
1294 else if (code == 'w')
1296 gcc_assert (REGNO (x) == REG_A0 || REGNO (x) == REG_A1);
1297 fprintf (file, "%s.w", reg_names[REGNO (x)]);
1299 else if (code == 'x')
1301 gcc_assert (REGNO (x) == REG_A0 || REGNO (x) == REG_A1);
1302 fprintf (file, "%s.x", reg_names[REGNO (x)]);
1304 else if (code == 'D')
1306 fprintf (file, "%s", dregs_pair_names[REGNO (x)]);
1308 else if (code == 'H')
1310 gcc_assert (mode == DImode || mode == DFmode);
1311 gcc_assert (REG_P (x));
1312 fprintf (file, "%s", reg_names[REGNO (x) + 1]);
1314 else if (code == 'T')
1316 gcc_assert (D_REGNO_P (REGNO (x)));
1317 fprintf (file, "%s", byte_reg_names[REGNO (x)]);
1319 else
1320 fprintf (file, "%s", reg_names[REGNO (x)]);
1321 break;
1323 case MEM:
1324 fputc ('[', file);
1325 x = XEXP (x,0);
1326 print_address_operand (file, x);
1327 fputc (']', file);
1328 break;
1330 case CONST_INT:
1331 if (code == 'M')
1333 switch (INTVAL (x))
1335 case MACFLAG_NONE:
1336 break;
1337 case MACFLAG_FU:
1338 fputs ("(FU)", file);
1339 break;
1340 case MACFLAG_T:
1341 fputs ("(T)", file);
1342 break;
1343 case MACFLAG_TFU:
1344 fputs ("(TFU)", file);
1345 break;
1346 case MACFLAG_W32:
1347 fputs ("(W32)", file);
1348 break;
1349 case MACFLAG_IS:
1350 fputs ("(IS)", file);
1351 break;
1352 case MACFLAG_IU:
1353 fputs ("(IU)", file);
1354 break;
1355 case MACFLAG_IH:
1356 fputs ("(IH)", file);
1357 break;
1358 case MACFLAG_M:
1359 fputs ("(M)", file);
1360 break;
1361 case MACFLAG_ISS2:
1362 fputs ("(ISS2)", file);
1363 break;
1364 case MACFLAG_S2RND:
1365 fputs ("(S2RND)", file);
1366 break;
1367 default:
1368 gcc_unreachable ();
1370 break;
1372 else if (code == 'b')
1374 if (INTVAL (x) == 0)
1375 fputs ("+=", file);
1376 else if (INTVAL (x) == 1)
1377 fputs ("-=", file);
1378 else
1379 gcc_unreachable ();
1380 break;
1382 /* Moves to half registers with d or h modifiers always use unsigned
1383 constants. */
1384 else if (code == 'd')
1385 x = GEN_INT ((INTVAL (x) >> 16) & 0xffff);
1386 else if (code == 'h')
1387 x = GEN_INT (INTVAL (x) & 0xffff);
1388 else if (code == 'N')
1389 x = GEN_INT (-INTVAL (x));
1390 else if (code == 'X')
1391 x = GEN_INT (exact_log2 (0xffffffff & INTVAL (x)));
1392 else if (code == 'Y')
1393 x = GEN_INT (exact_log2 (0xffffffff & ~INTVAL (x)));
1394 else if (code == 'Z')
1395 /* Used for LINK insns. */
1396 x = GEN_INT (-8 - INTVAL (x));
1398 /* fall through */
1400 case SYMBOL_REF:
1401 output_addr_const (file, x);
1402 break;
1404 case CONST_DOUBLE:
1405 output_operand_lossage ("invalid const_double operand");
1406 break;
1408 case UNSPEC:
1409 switch (XINT (x, 1))
1411 case UNSPEC_MOVE_PIC:
1412 output_addr_const (file, XVECEXP (x, 0, 0));
1413 fprintf (file, "@GOT");
1414 break;
1416 case UNSPEC_MOVE_FDPIC:
1417 output_addr_const (file, XVECEXP (x, 0, 0));
1418 fprintf (file, "@GOT17M4");
1419 break;
1421 case UNSPEC_FUNCDESC_GOT17M4:
1422 output_addr_const (file, XVECEXP (x, 0, 0));
1423 fprintf (file, "@FUNCDESC_GOT17M4");
1424 break;
1426 case UNSPEC_LIBRARY_OFFSET:
1427 fprintf (file, "_current_shared_library_p5_offset_");
1428 break;
1430 default:
1431 gcc_unreachable ();
1433 break;
1435 default:
1436 output_addr_const (file, x);
1441 /* Argument support functions. */
1443 /* Initialize a variable CUM of type CUMULATIVE_ARGS
1444 for a call to a function whose data type is FNTYPE.
1445 For a library call, FNTYPE is 0.
1446 VDSP C Compiler manual, our ABI says that
1447 first 3 words of arguments will use R0, R1 and R2.
1450 void
1451 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
1452 rtx libname ATTRIBUTE_UNUSED)
1454 static CUMULATIVE_ARGS zero_cum;
1456 *cum = zero_cum;
1458 /* Set up the number of registers to use for passing arguments. */
1460 cum->nregs = max_arg_registers;
1461 cum->arg_regs = arg_regs;
1463 cum->call_cookie = CALL_NORMAL;
1464 /* Check for a longcall attribute. */
1465 if (fntype && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype)))
1466 cum->call_cookie |= CALL_SHORT;
1467 else if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)))
1468 cum->call_cookie |= CALL_LONG;
1470 return;
1473 /* Update the data in CUM to advance over an argument
1474 of mode MODE and data type TYPE.
1475 (TYPE is null for libcalls where that information may not be available.) */
1477 void
1478 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1479 int named ATTRIBUTE_UNUSED)
1481 int count, bytes, words;
1483 bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1484 words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1486 cum->words += words;
1487 cum->nregs -= words;
1489 if (cum->nregs <= 0)
1491 cum->nregs = 0;
1492 cum->arg_regs = NULL;
1494 else
1496 for (count = 1; count <= words; count++)
1497 cum->arg_regs++;
1500 return;
1503 /* Define where to put the arguments to a function.
1504 Value is zero to push the argument on the stack,
1505 or a hard register in which to store the argument.
1507 MODE is the argument's machine mode.
1508 TYPE is the data type of the argument (as a tree).
1509 This is null for libcalls where that information may
1510 not be available.
1511 CUM is a variable of type CUMULATIVE_ARGS which gives info about
1512 the preceding args and about the function being called.
1513 NAMED is nonzero if this argument is a named parameter
1514 (otherwise it is an extra parameter matching an ellipsis). */
1516 struct rtx_def *
1517 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1518 int named ATTRIBUTE_UNUSED)
1520 int bytes
1521 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1523 if (mode == VOIDmode)
1524 /* Compute operand 2 of the call insn. */
1525 return GEN_INT (cum->call_cookie);
1527 if (bytes == -1)
1528 return NULL_RTX;
1530 if (cum->nregs)
1531 return gen_rtx_REG (mode, *(cum->arg_regs));
1533 return NULL_RTX;
1536 /* For an arg passed partly in registers and partly in memory,
1537 this is the number of bytes passed in registers.
1538 For args passed entirely in registers or entirely in memory, zero.
1540 Refer VDSP C Compiler manual, our ABI.
1541 First 3 words are in registers. So, if an argument is larger
1542 than the registers available, it will span the register and
1543 stack. */
1545 static int
1546 bfin_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1547 tree type ATTRIBUTE_UNUSED,
1548 bool named ATTRIBUTE_UNUSED)
1550 int bytes
1551 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1552 int bytes_left = cum->nregs * UNITS_PER_WORD;
1554 if (bytes == -1)
1555 return 0;
1557 if (bytes_left == 0)
1558 return 0;
1559 if (bytes > bytes_left)
1560 return bytes_left;
1561 return 0;
1564 /* Variable sized types are passed by reference. */
1566 static bool
1567 bfin_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
1568 enum machine_mode mode ATTRIBUTE_UNUSED,
1569 tree type, bool named ATTRIBUTE_UNUSED)
1571 return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
1574 /* Decide whether a type should be returned in memory (true)
1575 or in a register (false). This is called by the macro
1576 RETURN_IN_MEMORY. */
1579 bfin_return_in_memory (tree type)
1581 int size = int_size_in_bytes (type);
1582 return size > 2 * UNITS_PER_WORD || size == -1;
1585 /* Register in which address to store a structure value
1586 is passed to a function. */
1587 static rtx
1588 bfin_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
1589 int incoming ATTRIBUTE_UNUSED)
1591 return gen_rtx_REG (Pmode, REG_P0);
1594 /* Return true when register may be used to pass function parameters. */
1596 bool
1597 function_arg_regno_p (int n)
1599 int i;
1600 for (i = 0; arg_regs[i] != -1; i++)
1601 if (n == arg_regs[i])
1602 return true;
1603 return false;
1606 /* Returns 1 if OP contains a symbol reference */
1609 symbolic_reference_mentioned_p (rtx op)
1611 register const char *fmt;
1612 register int i;
1614 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
1615 return 1;
1617 fmt = GET_RTX_FORMAT (GET_CODE (op));
1618 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
1620 if (fmt[i] == 'E')
1622 register int j;
1624 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
1625 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
1626 return 1;
1629 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
1630 return 1;
1633 return 0;
1636 /* Decide whether we can make a sibling call to a function. DECL is the
1637 declaration of the function being targeted by the call and EXP is the
1638 CALL_EXPR representing the call. */
1640 static bool
1641 bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
1642 tree exp ATTRIBUTE_UNUSED)
1644 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1645 if (fkind != SUBROUTINE)
1646 return false;
1647 if (!TARGET_ID_SHARED_LIBRARY || TARGET_SEP_DATA)
1648 return true;
1650 /* When compiling for ID shared libraries, can't sibcall a local function
1651 from a non-local function, because the local function thinks it does
1652 not need to reload P5 in the prologue, but the sibcall wil pop P5 in the
1653 sibcall epilogue, and we end up with the wrong value in P5. */
1655 if (!flag_unit_at_a_time || decl == NULL)
1656 /* Not enough information. */
1657 return false;
1660 struct cgraph_local_info *this_func, *called_func;
1661 rtx addr, insn;
1663 this_func = cgraph_local_info (current_function_decl);
1664 called_func = cgraph_local_info (decl);
1665 return !called_func->local || this_func->local;
1669 /* Emit RTL insns to initialize the variable parts of a trampoline at
1670 TRAMP. FNADDR is an RTX for the address of the function's pure
1671 code. CXT is an RTX for the static chain value for the function. */
1673 void
1674 initialize_trampoline (tramp, fnaddr, cxt)
1675 rtx tramp, fnaddr, cxt;
1677 rtx t1 = copy_to_reg (fnaddr);
1678 rtx t2 = copy_to_reg (cxt);
1679 rtx addr;
1680 int i = 0;
1682 if (TARGET_FDPIC)
1684 rtx a = memory_address (Pmode, plus_constant (tramp, 8));
1685 addr = memory_address (Pmode, tramp);
1686 emit_move_insn (gen_rtx_MEM (SImode, addr), a);
1687 i = 8;
1690 addr = memory_address (Pmode, plus_constant (tramp, i + 2));
1691 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
1692 emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16)));
1693 addr = memory_address (Pmode, plus_constant (tramp, i + 6));
1694 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
1696 addr = memory_address (Pmode, plus_constant (tramp, i + 10));
1697 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
1698 emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16)));
1699 addr = memory_address (Pmode, plus_constant (tramp, i + 14));
1700 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
1703 /* Emit insns to move operands[1] into operands[0]. */
1705 void
1706 emit_pic_move (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
1708 rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
1710 gcc_assert (!TARGET_FDPIC || !(reload_in_progress || reload_completed));
1711 if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
1712 operands[1] = force_reg (SImode, operands[1]);
1713 else
1714 operands[1] = legitimize_pic_address (operands[1], temp,
1715 TARGET_FDPIC ? OUR_FDPIC_REG
1716 : pic_offset_table_rtx);
1719 /* Expand a move operation in mode MODE. The operands are in OPERANDS.
1720 Returns true if no further code must be generated, false if the caller
1721 should generate an insn to move OPERANDS[1] to OPERANDS[0]. */
1723 bool
1724 expand_move (rtx *operands, enum machine_mode mode)
1726 rtx op = operands[1];
1727 if ((TARGET_ID_SHARED_LIBRARY || TARGET_FDPIC)
1728 && SYMBOLIC_CONST (op))
1729 emit_pic_move (operands, mode);
1730 else if (mode == SImode && GET_CODE (op) == CONST
1731 && GET_CODE (XEXP (op, 0)) == PLUS
1732 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
1733 && !bfin_legitimate_constant_p (op))
1735 rtx dest = operands[0];
1736 rtx op0, op1;
1737 gcc_assert (!reload_in_progress && !reload_completed);
1738 op = XEXP (op, 0);
1739 op0 = force_reg (mode, XEXP (op, 0));
1740 op1 = XEXP (op, 1);
1741 if (!insn_data[CODE_FOR_addsi3].operand[2].predicate (op1, mode))
1742 op1 = force_reg (mode, op1);
1743 if (GET_CODE (dest) == MEM)
1744 dest = gen_reg_rtx (mode);
1745 emit_insn (gen_addsi3 (dest, op0, op1));
1746 if (dest == operands[0])
1747 return true;
1748 operands[1] = dest;
1750 /* Don't generate memory->memory or constant->memory moves, go through a
1751 register */
1752 else if ((reload_in_progress | reload_completed) == 0
1753 && GET_CODE (operands[0]) == MEM
1754 && GET_CODE (operands[1]) != REG)
1755 operands[1] = force_reg (mode, operands[1]);
1756 return false;
1759 /* Split one or more DImode RTL references into pairs of SImode
1760 references. The RTL can be REG, offsettable MEM, integer constant, or
1761 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
1762 split and "num" is its length. lo_half and hi_half are output arrays
1763 that parallel "operands". */
1765 void
1766 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
1768 while (num--)
1770 rtx op = operands[num];
1772 /* simplify_subreg refuse to split volatile memory addresses,
1773 but we still have to handle it. */
1774 if (GET_CODE (op) == MEM)
1776 lo_half[num] = adjust_address (op, SImode, 0);
1777 hi_half[num] = adjust_address (op, SImode, 4);
1779 else
1781 lo_half[num] = simplify_gen_subreg (SImode, op,
1782 GET_MODE (op) == VOIDmode
1783 ? DImode : GET_MODE (op), 0);
1784 hi_half[num] = simplify_gen_subreg (SImode, op,
1785 GET_MODE (op) == VOIDmode
1786 ? DImode : GET_MODE (op), 4);
1791 bool
1792 bfin_longcall_p (rtx op, int call_cookie)
1794 gcc_assert (GET_CODE (op) == SYMBOL_REF);
1795 if (call_cookie & CALL_SHORT)
1796 return 0;
1797 if (call_cookie & CALL_LONG)
1798 return 1;
1799 if (TARGET_LONG_CALLS)
1800 return 1;
1801 return 0;
1804 /* Expand a call instruction. FNADDR is the call target, RETVAL the return value.
1805 COOKIE is a CONST_INT holding the call_cookie prepared init_cumulative_args.
1806 SIBCALL is nonzero if this is a sibling call. */
1808 void
1809 bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
1811 rtx use = NULL, call;
1812 rtx callee = XEXP (fnaddr, 0);
1813 int nelts = 2 + !!sibcall;
1814 rtx pat;
1815 rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REGNO);
1816 int n;
1818 /* In an untyped call, we can get NULL for operand 2. */
1819 if (cookie == NULL_RTX)
1820 cookie = const0_rtx;
1822 /* Static functions and indirect calls don't need the pic register. */
1823 if (!TARGET_FDPIC && flag_pic
1824 && GET_CODE (callee) == SYMBOL_REF
1825 && !SYMBOL_REF_LOCAL_P (callee))
1826 use_reg (&use, pic_offset_table_rtx);
1828 if (TARGET_FDPIC)
1830 if (GET_CODE (callee) != SYMBOL_REF
1831 || bfin_longcall_p (callee, INTVAL (cookie)))
1833 rtx addr = callee;
1834 if (! address_operand (addr, Pmode))
1835 addr = force_reg (Pmode, addr);
1837 fnaddr = gen_reg_rtx (SImode);
1838 emit_insn (gen_load_funcdescsi (fnaddr, addr));
1839 fnaddr = gen_rtx_MEM (Pmode, fnaddr);
1841 picreg = gen_reg_rtx (SImode);
1842 emit_insn (gen_load_funcdescsi (picreg,
1843 plus_constant (addr, 4)));
1846 nelts++;
1848 else if ((!register_no_elim_operand (callee, Pmode)
1849 && GET_CODE (callee) != SYMBOL_REF)
1850 || (GET_CODE (callee) == SYMBOL_REF
1851 && ((TARGET_ID_SHARED_LIBRARY && !TARGET_LEAF_ID_SHARED_LIBRARY)
1852 || bfin_longcall_p (callee, INTVAL (cookie)))))
1854 callee = copy_to_mode_reg (Pmode, callee);
1855 fnaddr = gen_rtx_MEM (Pmode, callee);
1857 call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
1859 if (retval)
1860 call = gen_rtx_SET (VOIDmode, retval, call);
1862 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nelts));
1863 n = 0;
1864 XVECEXP (pat, 0, n++) = call;
1865 if (TARGET_FDPIC)
1866 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, picreg);
1867 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie);
1868 if (sibcall)
1869 XVECEXP (pat, 0, n++) = gen_rtx_RETURN (VOIDmode);
1870 call = emit_call_insn (pat);
1871 if (use)
1872 CALL_INSN_FUNCTION_USAGE (call) = use;
1875 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
1878 hard_regno_mode_ok (int regno, enum machine_mode mode)
1880 /* Allow only dregs to store value of mode HI or QI */
1881 enum reg_class class = REGNO_REG_CLASS (regno);
1883 if (mode == CCmode)
1884 return 0;
1886 if (mode == V2HImode)
1887 return D_REGNO_P (regno);
1888 if (class == CCREGS)
1889 return mode == BImode;
1890 if (mode == PDImode || mode == V2PDImode)
1891 return regno == REG_A0 || regno == REG_A1;
1893 /* Allow all normal 32-bit regs, except REG_M3, in case regclass ever comes
1894 up with a bad register class (such as ALL_REGS) for DImode. */
1895 if (mode == DImode)
1896 return regno < REG_M3;
1898 if (mode == SImode
1899 && TEST_HARD_REG_BIT (reg_class_contents[PROLOGUE_REGS], regno))
1900 return 1;
1902 return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno);
1905 /* Implements target hook vector_mode_supported_p. */
1907 static bool
1908 bfin_vector_mode_supported_p (enum machine_mode mode)
1910 return mode == V2HImode;
1913 /* Return the cost of moving data from a register in class CLASS1 to
1914 one in class CLASS2. A cost of 2 is the default. */
1917 bfin_register_move_cost (enum machine_mode mode,
1918 enum reg_class class1, enum reg_class class2)
1920 /* These need secondary reloads, so they're more expensive. */
1921 if ((class1 == CCREGS && class2 != DREGS)
1922 || (class1 != DREGS && class2 == CCREGS))
1923 return 4;
1925 /* If optimizing for size, always prefer reg-reg over reg-memory moves. */
1926 if (optimize_size)
1927 return 2;
1929 /* There are some stalls involved when moving from a DREG to a different
1930 class reg, and using the value in one of the following instructions.
1931 Attempt to model this by slightly discouraging such moves. */
1932 if (class1 == DREGS && class2 != DREGS)
1933 return 2 * 2;
1935 if (GET_MODE_CLASS (mode) == MODE_INT)
1937 /* Discourage trying to use the accumulators. */
1938 if (TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A0)
1939 || TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A1)
1940 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A0)
1941 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A1))
1942 return 20;
1944 return 2;
1947 /* Return the cost of moving data of mode M between a
1948 register and memory. A value of 2 is the default; this cost is
1949 relative to those in `REGISTER_MOVE_COST'.
1951 ??? In theory L1 memory has single-cycle latency. We should add a switch
1952 that tells the compiler whether we expect to use only L1 memory for the
1953 program; it'll make the costs more accurate. */
1956 bfin_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
1957 enum reg_class class,
1958 int in ATTRIBUTE_UNUSED)
1960 /* Make memory accesses slightly more expensive than any register-register
1961 move. Also, penalize non-DP registers, since they need secondary
1962 reloads to load and store. */
1963 if (! reg_class_subset_p (class, DPREGS))
1964 return 10;
1966 return 8;
1969 /* Inform reload about cases where moving X with a mode MODE to a register in
1970 CLASS requires an extra scratch register. Return the class needed for the
1971 scratch register. */
1973 static enum reg_class
1974 bfin_secondary_reload (bool in_p, rtx x, enum reg_class class,
1975 enum machine_mode mode, secondary_reload_info *sri)
1977 /* If we have HImode or QImode, we can only use DREGS as secondary registers;
1978 in most other cases we can also use PREGS. */
1979 enum reg_class default_class = GET_MODE_SIZE (mode) >= 4 ? DPREGS : DREGS;
1980 enum reg_class x_class = NO_REGS;
1981 enum rtx_code code = GET_CODE (x);
1983 if (code == SUBREG)
1984 x = SUBREG_REG (x), code = GET_CODE (x);
1985 if (REG_P (x))
1987 int regno = REGNO (x);
1988 if (regno >= FIRST_PSEUDO_REGISTER)
1989 regno = reg_renumber[regno];
1991 if (regno == -1)
1992 code = MEM;
1993 else
1994 x_class = REGNO_REG_CLASS (regno);
1997 /* We can be asked to reload (plus (FP) (large_constant)) into a DREG.
1998 This happens as a side effect of register elimination, and we need
1999 a scratch register to do it. */
2000 if (fp_plus_const_operand (x, mode))
2002 rtx op2 = XEXP (x, 1);
2003 int large_constant_p = ! CONST_7BIT_IMM_P (INTVAL (op2));
2005 if (class == PREGS || class == PREGS_CLOBBERED)
2006 return NO_REGS;
2007 /* If destination is a DREG, we can do this without a scratch register
2008 if the constant is valid for an add instruction. */
2009 if ((class == DREGS || class == DPREGS)
2010 && ! large_constant_p)
2011 return NO_REGS;
2012 /* Reloading to anything other than a DREG? Use a PREG scratch
2013 register. */
2014 sri->icode = CODE_FOR_reload_insi;
2015 return NO_REGS;
2018 /* Data can usually be moved freely between registers of most classes.
2019 AREGS are an exception; they can only move to or from another register
2020 in AREGS or one in DREGS. They can also be assigned the constant 0. */
2021 if (x_class == AREGS)
2022 return class == DREGS || class == AREGS ? NO_REGS : DREGS;
2024 if (class == AREGS)
2026 if (x != const0_rtx && x_class != DREGS)
2027 return DREGS;
2028 else
2029 return NO_REGS;
2032 /* CCREGS can only be moved from/to DREGS. */
2033 if (class == CCREGS && x_class != DREGS)
2034 return DREGS;
2035 if (x_class == CCREGS && class != DREGS)
2036 return DREGS;
2038 /* All registers other than AREGS can load arbitrary constants. The only
2039 case that remains is MEM. */
2040 if (code == MEM)
2041 if (! reg_class_subset_p (class, default_class))
2042 return default_class;
2043 return NO_REGS;
2046 /* Implement TARGET_HANDLE_OPTION. */
2048 static bool
2049 bfin_handle_option (size_t code, const char *arg, int value)
2051 switch (code)
2053 case OPT_mshared_library_id_:
2054 if (value > MAX_LIBRARY_ID)
2055 error ("-mshared-library-id=%s is not between 0 and %d",
2056 arg, MAX_LIBRARY_ID);
2057 bfin_lib_id_given = 1;
2058 return true;
2060 default:
2061 return true;
2065 static struct machine_function *
2066 bfin_init_machine_status (void)
2068 struct machine_function *f;
2070 f = ggc_alloc_cleared (sizeof (struct machine_function));
2072 return f;
2075 /* Implement the macro OVERRIDE_OPTIONS. */
2077 void
2078 override_options (void)
2080 if (TARGET_OMIT_LEAF_FRAME_POINTER)
2081 flag_omit_frame_pointer = 1;
2083 /* Library identification */
2084 if (bfin_lib_id_given && ! TARGET_ID_SHARED_LIBRARY)
2085 error ("-mshared-library-id= specified without -mid-shared-library");
2087 if (TARGET_ID_SHARED_LIBRARY && flag_pic == 0)
2088 flag_pic = 1;
2090 if (stack_limit_rtx && TARGET_STACK_CHECK_L1)
2091 error ("Can't use multiple stack checking methods together.");
2093 if (TARGET_ID_SHARED_LIBRARY && TARGET_FDPIC)
2094 error ("ID shared libraries and FD-PIC mode can't be used together.");
2096 /* Don't allow the user to specify -mid-shared-library and -msep-data
2097 together, as it makes little sense from a user's point of view... */
2098 if (TARGET_SEP_DATA && TARGET_ID_SHARED_LIBRARY)
2099 error ("cannot specify both -msep-data and -mid-shared-library");
2100 /* ... internally, however, it's nearly the same. */
2101 if (TARGET_SEP_DATA)
2102 target_flags |= MASK_ID_SHARED_LIBRARY | MASK_LEAF_ID_SHARED_LIBRARY;
2104 /* There is no single unaligned SI op for PIC code. Sometimes we
2105 need to use ".4byte" and sometimes we need to use ".picptr".
2106 See bfin_assemble_integer for details. */
2107 if (TARGET_FDPIC)
2108 targetm.asm_out.unaligned_op.si = 0;
2110 /* Silently turn off flag_pic if not doing FDPIC or ID shared libraries,
2111 since we don't support it and it'll just break. */
2112 if (flag_pic && !TARGET_FDPIC && !TARGET_ID_SHARED_LIBRARY)
2113 flag_pic = 0;
2115 flag_schedule_insns = 0;
2117 /* Passes after sched2 can break the helpful TImode annotations that
2118 haifa-sched puts on every insn. Just do scheduling in reorg. */
2119 bfin_flag_schedule_insns2 = flag_schedule_insns_after_reload;
2120 flag_schedule_insns_after_reload = 0;
2122 init_machine_status = bfin_init_machine_status;
2125 /* Return the destination address of BRANCH.
2126 We need to use this instead of get_attr_length, because the
2127 cbranch_with_nops pattern conservatively sets its length to 6, and
2128 we still prefer to use shorter sequences. */
2130 static int
2131 branch_dest (rtx branch)
2133 rtx dest;
2134 int dest_uid;
2135 rtx pat = PATTERN (branch);
2136 if (GET_CODE (pat) == PARALLEL)
2137 pat = XVECEXP (pat, 0, 0);
2138 dest = SET_SRC (pat);
2139 if (GET_CODE (dest) == IF_THEN_ELSE)
2140 dest = XEXP (dest, 1);
2141 dest = XEXP (dest, 0);
2142 dest_uid = INSN_UID (dest);
2143 return INSN_ADDRESSES (dest_uid);
2146 /* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates
2147 it's a branch that's predicted taken. */
2149 static int
2150 cbranch_predicted_taken_p (rtx insn)
2152 rtx x = find_reg_note (insn, REG_BR_PROB, 0);
2154 if (x)
2156 int pred_val = INTVAL (XEXP (x, 0));
2158 return pred_val >= REG_BR_PROB_BASE / 2;
2161 return 0;
2164 /* Templates for use by asm_conditional_branch. */
2166 static const char *ccbranch_templates[][3] = {
2167 { "if !cc jump %3;", "if cc jump 4 (bp); jump.s %3;", "if cc jump 6 (bp); jump.l %3;" },
2168 { "if cc jump %3;", "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" },
2169 { "if !cc jump %3 (bp);", "if cc jump 4; jump.s %3;", "if cc jump 6; jump.l %3;" },
2170 { "if cc jump %3 (bp);", "if !cc jump 4; jump.s %3;", "if !cc jump 6; jump.l %3;" },
2173 /* Output INSN, which is a conditional branch instruction with operands
2174 OPERANDS.
2176 We deal with the various forms of conditional branches that can be generated
2177 by bfin_reorg to prevent the hardware from doing speculative loads, by
2178 - emitting a sufficient number of nops, if N_NOPS is nonzero, or
2179 - always emitting the branch as predicted taken, if PREDICT_TAKEN is true.
2180 Either of these is only necessary if the branch is short, otherwise the
2181 template we use ends in an unconditional jump which flushes the pipeline
2182 anyway. */
2184 void
2185 asm_conditional_branch (rtx insn, rtx *operands, int n_nops, int predict_taken)
2187 int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
2188 /* Note : offset for instructions like if cc jmp; jump.[sl] offset
2189 is to be taken from start of if cc rather than jump.
2190 Range for jump.s is (-4094, 4096) instead of (-4096, 4094)
2192 int len = (offset >= -1024 && offset <= 1022 ? 0
2193 : offset >= -4094 && offset <= 4096 ? 1
2194 : 2);
2195 int bp = predict_taken && len == 0 ? 1 : cbranch_predicted_taken_p (insn);
2196 int idx = (bp << 1) | (GET_CODE (operands[0]) == EQ ? BRF : BRT);
2197 output_asm_insn (ccbranch_templates[idx][len], operands);
2198 gcc_assert (n_nops == 0 || !bp);
2199 if (len == 0)
2200 while (n_nops-- > 0)
2201 output_asm_insn ("nop;", NULL);
2204 /* Emit rtl for a comparison operation CMP in mode MODE. Operands have been
2205 stored in bfin_compare_op0 and bfin_compare_op1 already. */
2208 bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED)
2210 enum rtx_code code1, code2;
2211 rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1;
2212 rtx tem = bfin_cc_rtx;
2213 enum rtx_code code = GET_CODE (cmp);
2215 /* If we have a BImode input, then we already have a compare result, and
2216 do not need to emit another comparison. */
2217 if (GET_MODE (op0) == BImode)
2219 gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
2220 tem = op0, code2 = code;
2222 else
2224 switch (code) {
2225 /* bfin has these conditions */
2226 case EQ:
2227 case LT:
2228 case LE:
2229 case LEU:
2230 case LTU:
2231 code1 = code;
2232 code2 = NE;
2233 break;
2234 default:
2235 code1 = reverse_condition (code);
2236 code2 = EQ;
2237 break;
2239 emit_insn (gen_rtx_SET (BImode, tem,
2240 gen_rtx_fmt_ee (code1, BImode, op0, op1)));
2243 return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode));
2246 /* Return nonzero iff C has exactly one bit set if it is interpreted
2247 as a 32-bit constant. */
2250 log2constp (unsigned HOST_WIDE_INT c)
2252 c &= 0xFFFFFFFF;
2253 return c != 0 && (c & (c-1)) == 0;
2256 /* Returns the number of consecutive least significant zeros in the binary
2257 representation of *V.
2258 We modify *V to contain the original value arithmetically shifted right by
2259 the number of zeroes. */
2261 static int
2262 shiftr_zero (HOST_WIDE_INT *v)
2264 unsigned HOST_WIDE_INT tmp = *v;
2265 unsigned HOST_WIDE_INT sgn;
2266 int n = 0;
2268 if (tmp == 0)
2269 return 0;
2271 sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1));
2272 while ((tmp & 0x1) == 0 && n <= 32)
2274 tmp = (tmp >> 1) | sgn;
2275 n++;
2277 *v = tmp;
2278 return n;
2281 /* After reload, split the load of an immediate constant. OPERANDS are the
2282 operands of the movsi_insn pattern which we are splitting. We return
2283 nonzero if we emitted a sequence to load the constant, zero if we emitted
2284 nothing because we want to use the splitter's default sequence. */
2287 split_load_immediate (rtx operands[])
2289 HOST_WIDE_INT val = INTVAL (operands[1]);
2290 HOST_WIDE_INT tmp;
2291 HOST_WIDE_INT shifted = val;
2292 HOST_WIDE_INT shifted_compl = ~val;
2293 int num_zero = shiftr_zero (&shifted);
2294 int num_compl_zero = shiftr_zero (&shifted_compl);
2295 unsigned int regno = REGNO (operands[0]);
2296 enum reg_class class1 = REGNO_REG_CLASS (regno);
2298 /* This case takes care of single-bit set/clear constants, which we could
2299 also implement with BITSET/BITCLR. */
2300 if (num_zero
2301 && shifted >= -32768 && shifted < 65536
2302 && (D_REGNO_P (regno)
2303 || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))
2305 emit_insn (gen_movsi (operands[0], GEN_INT (shifted)));
2306 emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));
2307 return 1;
2310 tmp = val & 0xFFFF;
2311 tmp |= -(tmp & 0x8000);
2313 /* If high word has one bit set or clear, try to use a bit operation. */
2314 if (D_REGNO_P (regno))
2316 if (log2constp (val & 0xFFFF0000))
2318 emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));
2319 emit_insn (gen_iorsi3 (operands[0], operands[0], GEN_INT (val & 0xFFFF0000)));
2320 return 1;
2322 else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)
2324 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2325 emit_insn (gen_andsi3 (operands[0], operands[0], GEN_INT (val | 0xFFFF)));
2329 if (D_REGNO_P (regno))
2331 if (CONST_7BIT_IMM_P (tmp))
2333 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2334 emit_insn (gen_movstricthi_high (operands[0], GEN_INT (val & -65536)));
2335 return 1;
2338 if ((val & 0xFFFF0000) == 0)
2340 emit_insn (gen_movsi (operands[0], const0_rtx));
2341 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2342 return 1;
2345 if ((val & 0xFFFF0000) == 0xFFFF0000)
2347 emit_insn (gen_movsi (operands[0], constm1_rtx));
2348 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2349 return 1;
2353 /* Need DREGs for the remaining case. */
2354 if (regno > REG_R7)
2355 return 0;
2357 if (optimize_size
2358 && num_compl_zero && CONST_7BIT_IMM_P (shifted_compl))
2360 /* If optimizing for size, generate a sequence that has more instructions
2361 but is shorter. */
2362 emit_insn (gen_movsi (operands[0], GEN_INT (shifted_compl)));
2363 emit_insn (gen_ashlsi3 (operands[0], operands[0],
2364 GEN_INT (num_compl_zero)));
2365 emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
2366 return 1;
2368 return 0;
2371 /* Return true if the legitimate memory address for a memory operand of mode
2372 MODE. Return false if not. */
2374 static bool
2375 bfin_valid_add (enum machine_mode mode, HOST_WIDE_INT value)
2377 unsigned HOST_WIDE_INT v = value > 0 ? value : -value;
2378 int sz = GET_MODE_SIZE (mode);
2379 int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2;
2380 /* The usual offsettable_memref machinery doesn't work so well for this
2381 port, so we deal with the problem here. */
2382 if (value > 0 && sz == 8)
2383 v += 4;
2384 return (v & ~(0x7fff << shift)) == 0;
2387 static bool
2388 bfin_valid_reg_p (unsigned int regno, int strict, enum machine_mode mode,
2389 enum rtx_code outer_code)
2391 if (strict)
2392 return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH);
2393 else
2394 return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH);
2397 bool
2398 bfin_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
2400 switch (GET_CODE (x)) {
2401 case REG:
2402 if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM))
2403 return true;
2404 break;
2405 case PLUS:
2406 if (REG_P (XEXP (x, 0))
2407 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS)
2408 && ((GET_CODE (XEXP (x, 1)) == UNSPEC && mode == SImode)
2409 || (GET_CODE (XEXP (x, 1)) == CONST_INT
2410 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
2411 return true;
2412 break;
2413 case POST_INC:
2414 case POST_DEC:
2415 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2416 && REG_P (XEXP (x, 0))
2417 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC))
2418 return true;
2419 case PRE_DEC:
2420 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2421 && XEXP (x, 0) == stack_pointer_rtx
2422 && REG_P (XEXP (x, 0))
2423 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC))
2424 return true;
2425 break;
2426 default:
2427 break;
2429 return false;
2432 /* Decide whether we can force certain constants to memory. If we
2433 decide we can't, the caller should be able to cope with it in
2434 another way. */
2436 static bool
2437 bfin_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
2439 /* We have only one class of non-legitimate constants, and our movsi
2440 expander knows how to handle them. Dropping these constants into the
2441 data section would only shift the problem - we'd still get relocs
2442 outside the object, in the data section rather than the text section. */
2443 return true;
2446 /* Ensure that for any constant of the form symbol + offset, the offset
2447 remains within the object. Any other constants are ok.
2448 This ensures that flat binaries never have to deal with relocations
2449 crossing section boundaries. */
2451 bool
2452 bfin_legitimate_constant_p (rtx x)
2454 rtx sym;
2455 HOST_WIDE_INT offset;
2457 if (GET_CODE (x) != CONST)
2458 return true;
2460 x = XEXP (x, 0);
2461 gcc_assert (GET_CODE (x) == PLUS);
2463 sym = XEXP (x, 0);
2464 x = XEXP (x, 1);
2465 if (GET_CODE (sym) != SYMBOL_REF
2466 || GET_CODE (x) != CONST_INT)
2467 return true;
2468 offset = INTVAL (x);
2470 if (SYMBOL_REF_DECL (sym) == 0)
2471 return true;
2472 if (offset < 0
2473 || offset >= int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (sym))))
2474 return false;
2476 return true;
2479 static bool
2480 bfin_rtx_costs (rtx x, int code, int outer_code, int *total)
2482 int cost2 = COSTS_N_INSNS (1);
2483 rtx op0, op1;
2485 switch (code)
2487 case CONST_INT:
2488 if (outer_code == SET || outer_code == PLUS)
2489 *total = CONST_7BIT_IMM_P (INTVAL (x)) ? 0 : cost2;
2490 else if (outer_code == AND)
2491 *total = log2constp (~INTVAL (x)) ? 0 : cost2;
2492 else if (outer_code == LE || outer_code == LT || outer_code == EQ)
2493 *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
2494 else if (outer_code == LEU || outer_code == LTU)
2495 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
2496 else if (outer_code == MULT)
2497 *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
2498 else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
2499 *total = 0;
2500 else if (outer_code == ASHIFT || outer_code == ASHIFTRT
2501 || outer_code == LSHIFTRT)
2502 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
2503 else if (outer_code == IOR || outer_code == XOR)
2504 *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
2505 else
2506 *total = cost2;
2507 return true;
2509 case CONST:
2510 case LABEL_REF:
2511 case SYMBOL_REF:
2512 case CONST_DOUBLE:
2513 *total = COSTS_N_INSNS (2);
2514 return true;
2516 case PLUS:
2517 op0 = XEXP (x, 0);
2518 op1 = XEXP (x, 1);
2519 if (GET_MODE (x) == SImode)
2521 if (GET_CODE (op0) == MULT
2522 && GET_CODE (XEXP (op0, 1)) == CONST_INT)
2524 HOST_WIDE_INT val = INTVAL (XEXP (op0, 1));
2525 if (val == 2 || val == 4)
2527 *total = cost2;
2528 *total += rtx_cost (XEXP (op0, 0), outer_code);
2529 *total += rtx_cost (op1, outer_code);
2530 return true;
2533 *total = cost2;
2534 if (GET_CODE (op0) != REG
2535 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2536 *total += rtx_cost (op0, SET);
2537 #if 0 /* We'd like to do this for accuracy, but it biases the loop optimizer
2538 towards creating too many induction variables. */
2539 if (!reg_or_7bit_operand (op1, SImode))
2540 *total += rtx_cost (op1, SET);
2541 #endif
2543 else if (GET_MODE (x) == DImode)
2545 *total = 6 * cost2;
2546 if (GET_CODE (op1) != CONST_INT
2547 || !CONST_7BIT_IMM_P (INTVAL (op1)))
2548 *total += rtx_cost (op1, PLUS);
2549 if (GET_CODE (op0) != REG
2550 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2551 *total += rtx_cost (op0, PLUS);
2553 return true;
2555 case MINUS:
2556 if (GET_MODE (x) == DImode)
2557 *total = 6 * cost2;
2558 else
2559 *total = cost2;
2560 return true;
2562 case ASHIFT:
2563 case ASHIFTRT:
2564 case LSHIFTRT:
2565 if (GET_MODE (x) == DImode)
2566 *total = 6 * cost2;
2567 else
2568 *total = cost2;
2570 op0 = XEXP (x, 0);
2571 op1 = XEXP (x, 1);
2572 if (GET_CODE (op0) != REG
2573 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2574 *total += rtx_cost (op0, code);
2576 return true;
2578 case IOR:
2579 case AND:
2580 case XOR:
2581 op0 = XEXP (x, 0);
2582 op1 = XEXP (x, 1);
2584 /* Handle special cases of IOR: rotates, ALIGN insns, movstricthi_high. */
2585 if (code == IOR)
2587 if ((GET_CODE (op0) == LSHIFTRT && GET_CODE (op1) == ASHIFT)
2588 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == ZERO_EXTEND)
2589 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT)
2590 || (GET_CODE (op0) == AND && GET_CODE (op1) == CONST_INT))
2592 *total = cost2;
2593 return true;
2597 if (GET_CODE (op0) != REG
2598 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2599 *total += rtx_cost (op0, code);
2601 if (GET_MODE (x) == DImode)
2603 *total = 2 * cost2;
2604 return true;
2606 *total = cost2;
2607 if (GET_MODE (x) != SImode)
2608 return true;
2610 if (code == AND)
2612 if (! rhs_andsi3_operand (XEXP (x, 1), SImode))
2613 *total += rtx_cost (XEXP (x, 1), code);
2615 else
2617 if (! regorlog2_operand (XEXP (x, 1), SImode))
2618 *total += rtx_cost (XEXP (x, 1), code);
2621 return true;
2623 case ZERO_EXTRACT:
2624 case SIGN_EXTRACT:
2625 if (outer_code == SET
2626 && XEXP (x, 1) == const1_rtx
2627 && GET_CODE (XEXP (x, 2)) == CONST_INT)
2629 *total = 2 * cost2;
2630 return true;
2632 /* fall through */
2634 case SIGN_EXTEND:
2635 case ZERO_EXTEND:
2636 *total = cost2;
2637 return true;
2639 case MULT:
2641 op0 = XEXP (x, 0);
2642 op1 = XEXP (x, 1);
2643 if (GET_CODE (op0) == GET_CODE (op1)
2644 && (GET_CODE (op0) == ZERO_EXTEND
2645 || GET_CODE (op0) == SIGN_EXTEND))
2647 *total = COSTS_N_INSNS (1);
2648 op0 = XEXP (op0, 0);
2649 op1 = XEXP (op1, 0);
2651 else if (optimize_size)
2652 *total = COSTS_N_INSNS (1);
2653 else
2654 *total = COSTS_N_INSNS (3);
2656 if (GET_CODE (op0) != REG
2657 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2658 *total += rtx_cost (op0, MULT);
2659 if (GET_CODE (op1) != REG
2660 && (GET_CODE (op1) != SUBREG || GET_CODE (SUBREG_REG (op1)) != REG))
2661 *total += rtx_cost (op1, MULT);
2663 return true;
2665 case UDIV:
2666 case UMOD:
2667 *total = COSTS_N_INSNS (32);
2668 return true;
2670 case VEC_CONCAT:
2671 case VEC_SELECT:
2672 if (outer_code == SET)
2673 *total = cost2;
2674 return true;
2676 default:
2677 return false;
2681 static void
2682 bfin_internal_label (FILE *stream, const char *prefix, unsigned long num)
2684 fprintf (stream, "%s%s$%ld:\n", LOCAL_LABEL_PREFIX, prefix, num);
2687 /* Used for communication between {push,pop}_multiple_operation (which
2688 we use not only as a predicate) and the corresponding output functions. */
2689 static int first_preg_to_save, first_dreg_to_save;
2692 push_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2694 int lastdreg = 8, lastpreg = 6;
2695 int i, group;
2697 first_preg_to_save = lastpreg;
2698 first_dreg_to_save = lastdreg;
2699 for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
2701 rtx t = XVECEXP (op, 0, i);
2702 rtx src, dest;
2703 int regno;
2705 if (GET_CODE (t) != SET)
2706 return 0;
2708 src = SET_SRC (t);
2709 dest = SET_DEST (t);
2710 if (GET_CODE (dest) != MEM || ! REG_P (src))
2711 return 0;
2712 dest = XEXP (dest, 0);
2713 if (GET_CODE (dest) != PLUS
2714 || ! REG_P (XEXP (dest, 0))
2715 || REGNO (XEXP (dest, 0)) != REG_SP
2716 || GET_CODE (XEXP (dest, 1)) != CONST_INT
2717 || INTVAL (XEXP (dest, 1)) != -i * 4)
2718 return 0;
2720 regno = REGNO (src);
2721 if (group == 0)
2723 if (D_REGNO_P (regno))
2725 group = 1;
2726 first_dreg_to_save = lastdreg = regno - REG_R0;
2728 else if (regno >= REG_P0 && regno <= REG_P7)
2730 group = 2;
2731 first_preg_to_save = lastpreg = regno - REG_P0;
2733 else
2734 return 0;
2736 continue;
2739 if (group == 1)
2741 if (regno >= REG_P0 && regno <= REG_P7)
2743 group = 2;
2744 first_preg_to_save = lastpreg = regno - REG_P0;
2746 else if (regno != REG_R0 + lastdreg + 1)
2747 return 0;
2748 else
2749 lastdreg++;
2751 else if (group == 2)
2753 if (regno != REG_P0 + lastpreg + 1)
2754 return 0;
2755 lastpreg++;
2758 return 1;
2762 pop_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
2764 int lastdreg = 8, lastpreg = 6;
2765 int i, group;
2767 for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
2769 rtx t = XVECEXP (op, 0, i);
2770 rtx src, dest;
2771 int regno;
2773 if (GET_CODE (t) != SET)
2774 return 0;
2776 src = SET_SRC (t);
2777 dest = SET_DEST (t);
2778 if (GET_CODE (src) != MEM || ! REG_P (dest))
2779 return 0;
2780 src = XEXP (src, 0);
2782 if (i == 1)
2784 if (! REG_P (src) || REGNO (src) != REG_SP)
2785 return 0;
2787 else if (GET_CODE (src) != PLUS
2788 || ! REG_P (XEXP (src, 0))
2789 || REGNO (XEXP (src, 0)) != REG_SP
2790 || GET_CODE (XEXP (src, 1)) != CONST_INT
2791 || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
2792 return 0;
2794 regno = REGNO (dest);
2795 if (group == 0)
2797 if (regno == REG_R7)
2799 group = 1;
2800 lastdreg = 7;
2802 else if (regno != REG_P0 + lastpreg - 1)
2803 return 0;
2804 else
2805 lastpreg--;
2807 else if (group == 1)
2809 if (regno != REG_R0 + lastdreg - 1)
2810 return 0;
2811 else
2812 lastdreg--;
2815 first_dreg_to_save = lastdreg;
2816 first_preg_to_save = lastpreg;
2817 return 1;
2820 /* Emit assembly code for one multi-register push described by INSN, with
2821 operands in OPERANDS. */
2823 void
2824 output_push_multiple (rtx insn, rtx *operands)
2826 char buf[80];
2827 int ok;
2829 /* Validate the insn again, and compute first_[dp]reg_to_save. */
2830 ok = push_multiple_operation (PATTERN (insn), VOIDmode);
2831 gcc_assert (ok);
2833 if (first_dreg_to_save == 8)
2834 sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
2835 else if (first_preg_to_save == 6)
2836 sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
2837 else
2838 sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
2839 first_dreg_to_save, first_preg_to_save);
2841 output_asm_insn (buf, operands);
2844 /* Emit assembly code for one multi-register pop described by INSN, with
2845 operands in OPERANDS. */
2847 void
2848 output_pop_multiple (rtx insn, rtx *operands)
2850 char buf[80];
2851 int ok;
2853 /* Validate the insn again, and compute first_[dp]reg_to_save. */
2854 ok = pop_multiple_operation (PATTERN (insn), VOIDmode);
2855 gcc_assert (ok);
2857 if (first_dreg_to_save == 8)
2858 sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
2859 else if (first_preg_to_save == 6)
2860 sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
2861 else
2862 sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
2863 first_dreg_to_save, first_preg_to_save);
2865 output_asm_insn (buf, operands);
2868 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE. */
2870 static void
2871 single_move_for_movmem (rtx dst, rtx src, enum machine_mode mode, HOST_WIDE_INT offset)
2873 rtx scratch = gen_reg_rtx (mode);
2874 rtx srcmem, dstmem;
2876 srcmem = adjust_address_nv (src, mode, offset);
2877 dstmem = adjust_address_nv (dst, mode, offset);
2878 emit_move_insn (scratch, srcmem);
2879 emit_move_insn (dstmem, scratch);
2882 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
2883 alignment ALIGN_EXP. Return true if successful, false if we should fall
2884 back on a different method. */
2886 bool
2887 bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
2889 rtx srcreg, destreg, countreg;
2890 HOST_WIDE_INT align = 0;
2891 unsigned HOST_WIDE_INT count = 0;
2893 if (GET_CODE (align_exp) == CONST_INT)
2894 align = INTVAL (align_exp);
2895 if (GET_CODE (count_exp) == CONST_INT)
2897 count = INTVAL (count_exp);
2898 #if 0
2899 if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
2900 return false;
2901 #endif
2904 /* If optimizing for size, only do single copies inline. */
2905 if (optimize_size)
2907 if (count == 2 && align < 2)
2908 return false;
2909 if (count == 4 && align < 4)
2910 return false;
2911 if (count != 1 && count != 2 && count != 4)
2912 return false;
2914 if (align < 2 && count != 1)
2915 return false;
2917 destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
2918 if (destreg != XEXP (dst, 0))
2919 dst = replace_equiv_address_nv (dst, destreg);
2920 srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
2921 if (srcreg != XEXP (src, 0))
2922 src = replace_equiv_address_nv (src, srcreg);
2924 if (count != 0 && align >= 2)
2926 unsigned HOST_WIDE_INT offset = 0;
2928 if (align >= 4)
2930 if ((count & ~3) == 4)
2932 single_move_for_movmem (dst, src, SImode, offset);
2933 offset = 4;
2935 else if (count & ~3)
2937 HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
2938 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
2940 emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
2942 if (count & 2)
2944 single_move_for_movmem (dst, src, HImode, offset);
2945 offset += 2;
2948 else
2950 if ((count & ~1) == 2)
2952 single_move_for_movmem (dst, src, HImode, offset);
2953 offset = 2;
2955 else if (count & ~1)
2957 HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
2958 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
2960 emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
2963 if (count & 1)
2965 single_move_for_movmem (dst, src, QImode, offset);
2967 return true;
2969 return false;
2972 /* Implement TARGET_SCHED_ISSUE_RATE. */
2974 static int
2975 bfin_issue_rate (void)
2977 return 3;
2980 static int
2981 bfin_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
2983 enum attr_type insn_type, dep_insn_type;
2984 int dep_insn_code_number;
2986 /* Anti and output dependencies have zero cost. */
2987 if (REG_NOTE_KIND (link) != 0)
2988 return 0;
2990 dep_insn_code_number = recog_memoized (dep_insn);
2992 /* If we can't recognize the insns, we can't really do anything. */
2993 if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
2994 return cost;
2996 insn_type = get_attr_type (insn);
2997 dep_insn_type = get_attr_type (dep_insn);
2999 if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)
3001 rtx pat = PATTERN (dep_insn);
3002 rtx dest = SET_DEST (pat);
3003 rtx src = SET_SRC (pat);
3004 if (! ADDRESS_REGNO_P (REGNO (dest))
3005 || ! (MEM_P (src) || D_REGNO_P (REGNO (src))))
3006 return cost;
3007 return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);
3010 return cost;
3014 /* Increment the counter for the number of loop instructions in the
3015 current function. */
3017 void
3018 bfin_hardware_loop (void)
3020 cfun->machine->has_hardware_loops++;
3023 /* Maximum loop nesting depth. */
3024 #define MAX_LOOP_DEPTH 2
3026 /* Maximum size of a loop. */
3027 #define MAX_LOOP_LENGTH 2042
3029 /* Maximum distance of the LSETUP instruction from the loop start. */
3030 #define MAX_LSETUP_DISTANCE 30
3032 /* We need to keep a vector of loops */
3033 typedef struct loop_info *loop_info;
3034 DEF_VEC_P (loop_info);
3035 DEF_VEC_ALLOC_P (loop_info,heap);
3037 /* Information about a loop we have found (or are in the process of
3038 finding). */
3039 struct loop_info GTY (())
3041 /* loop number, for dumps */
3042 int loop_no;
3044 /* All edges that jump into and out of the loop. */
3045 VEC(edge,gc) *incoming;
3047 /* We can handle two cases: all incoming edges have the same destination
3048 block, or all incoming edges have the same source block. These two
3049 members are set to the common source or destination we found, or NULL
3050 if different blocks were found. If both are NULL the loop can't be
3051 optimized. */
3052 basic_block incoming_src;
3053 basic_block incoming_dest;
3055 /* First block in the loop. This is the one branched to by the loop_end
3056 insn. */
3057 basic_block head;
3059 /* Last block in the loop (the one with the loop_end insn). */
3060 basic_block tail;
3062 /* The successor block of the loop. This is the one the loop_end insn
3063 falls into. */
3064 basic_block successor;
3066 /* The last instruction in the tail. */
3067 rtx last_insn;
3069 /* The loop_end insn. */
3070 rtx loop_end;
3072 /* The iteration register. */
3073 rtx iter_reg;
3075 /* The new initialization insn. */
3076 rtx init;
3078 /* The new initialization instruction. */
3079 rtx loop_init;
3081 /* The new label placed at the beginning of the loop. */
3082 rtx start_label;
3084 /* The new label placed at the end of the loop. */
3085 rtx end_label;
3087 /* The length of the loop. */
3088 int length;
3090 /* The nesting depth of the loop. */
3091 int depth;
3093 /* Nonzero if we can't optimize this loop. */
3094 int bad;
3096 /* True if we have visited this loop. */
3097 int visited;
3099 /* True if this loop body clobbers any of LC0, LT0, or LB0. */
3100 int clobber_loop0;
3102 /* True if this loop body clobbers any of LC1, LT1, or LB1. */
3103 int clobber_loop1;
3105 /* Next loop in the graph. */
3106 struct loop_info *next;
3108 /* Immediate outer loop of this loop. */
3109 struct loop_info *outer;
3111 /* Vector of blocks only within the loop, including those within
3112 inner loops. */
3113 VEC (basic_block,heap) *blocks;
3115 /* Same information in a bitmap. */
3116 bitmap block_bitmap;
3118 /* Vector of inner loops within this loop */
3119 VEC (loop_info,heap) *loops;
3122 static void
3123 bfin_dump_loops (loop_info loops)
3125 loop_info loop;
3127 for (loop = loops; loop; loop = loop->next)
3129 loop_info i;
3130 basic_block b;
3131 unsigned ix;
3133 fprintf (dump_file, ";; loop %d: ", loop->loop_no);
3134 if (loop->bad)
3135 fprintf (dump_file, "(bad) ");
3136 fprintf (dump_file, "{head:%d, depth:%d}", loop->head->index, loop->depth);
3138 fprintf (dump_file, " blocks: [ ");
3139 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, b); ix++)
3140 fprintf (dump_file, "%d ", b->index);
3141 fprintf (dump_file, "] ");
3143 fprintf (dump_file, " inner loops: [ ");
3144 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, i); ix++)
3145 fprintf (dump_file, "%d ", i->loop_no);
3146 fprintf (dump_file, "]\n");
3148 fprintf (dump_file, "\n");
3151 /* Scan the blocks of LOOP (and its inferiors) looking for basic block
3152 BB. Return true, if we find it. */
3154 static bool
3155 bfin_bb_in_loop (loop_info loop, basic_block bb)
3157 return bitmap_bit_p (loop->block_bitmap, bb->index);
3160 /* Scan the blocks of LOOP (and its inferiors) looking for uses of
3161 REG. Return true, if we find any. Don't count the loop's loop_end
3162 insn if it matches LOOP_END. */
3164 static bool
3165 bfin_scan_loop (loop_info loop, rtx reg, rtx loop_end)
3167 unsigned ix;
3168 basic_block bb;
3170 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
3172 rtx insn;
3174 for (insn = BB_HEAD (bb);
3175 insn != NEXT_INSN (BB_END (bb));
3176 insn = NEXT_INSN (insn))
3178 if (!INSN_P (insn))
3179 continue;
3180 if (insn == loop_end)
3181 continue;
3182 if (reg_mentioned_p (reg, PATTERN (insn)))
3183 return true;
3186 return false;
3189 /* Estimate the length of INSN conservatively. */
3191 static int
3192 length_for_loop (rtx insn)
3194 int length = 0;
3195 if (JUMP_P (insn) && any_condjump_p (insn) && !optimize_size)
3197 if (TARGET_CSYNC_ANOMALY)
3198 length = 8;
3199 else if (TARGET_SPECLD_ANOMALY)
3200 length = 6;
3202 else if (LABEL_P (insn))
3204 if (TARGET_CSYNC_ANOMALY)
3205 length = 4;
3208 if (INSN_P (insn))
3209 length += get_attr_length (insn);
3211 return length;
3214 /* Optimize LOOP. */
3216 static void
3217 bfin_optimize_loop (loop_info loop)
3219 basic_block bb;
3220 loop_info inner;
3221 rtx insn, init_insn, last_insn, nop_insn;
3222 rtx loop_init, start_label, end_label;
3223 rtx reg_lc0, reg_lc1, reg_lt0, reg_lt1, reg_lb0, reg_lb1;
3224 rtx iter_reg;
3225 rtx lc_reg, lt_reg, lb_reg;
3226 rtx seq, seq_end;
3227 int length;
3228 unsigned ix;
3229 int inner_depth = 0;
3231 if (loop->visited)
3232 return;
3234 loop->visited = 1;
3236 if (loop->bad)
3238 if (dump_file)
3239 fprintf (dump_file, ";; loop %d bad when found\n", loop->loop_no);
3240 goto bad_loop;
3243 /* Every loop contains in its list of inner loops every loop nested inside
3244 it, even if there are intermediate loops. This works because we're doing
3245 a depth-first search here and never visit a loop more than once. */
3246 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, inner); ix++)
3248 bfin_optimize_loop (inner);
3250 if (!inner->bad && inner_depth < inner->depth)
3252 inner_depth = inner->depth;
3254 loop->clobber_loop0 |= inner->clobber_loop0;
3255 loop->clobber_loop1 |= inner->clobber_loop1;
3259 loop->depth = inner_depth + 1;
3260 if (loop->depth > MAX_LOOP_DEPTH)
3262 if (dump_file)
3263 fprintf (dump_file, ";; loop %d too deep\n", loop->loop_no);
3264 goto bad_loop;
3267 /* Get the loop iteration register. */
3268 iter_reg = loop->iter_reg;
3270 if (!DPREG_P (iter_reg))
3272 if (dump_file)
3273 fprintf (dump_file, ";; loop %d iteration count NOT in PREG or DREG\n",
3274 loop->loop_no);
3275 goto bad_loop;
3278 if (loop->incoming_src)
3280 /* Make sure the predecessor is before the loop start label, as required by
3281 the LSETUP instruction. */
3282 length = 0;
3283 for (insn = BB_END (loop->incoming_src);
3284 insn && insn != loop->start_label;
3285 insn = NEXT_INSN (insn))
3286 length += length_for_loop (insn);
3288 if (!insn)
3290 if (dump_file)
3291 fprintf (dump_file, ";; loop %d lsetup not before loop_start\n",
3292 loop->loop_no);
3293 goto bad_loop;
3296 if (length > MAX_LSETUP_DISTANCE)
3298 if (dump_file)
3299 fprintf (dump_file, ";; loop %d lsetup too far away\n", loop->loop_no);
3300 goto bad_loop;
3304 /* Check if start_label appears before loop_end and calculate the
3305 offset between them. We calculate the length of instructions
3306 conservatively. */
3307 length = 0;
3308 for (insn = loop->start_label;
3309 insn && insn != loop->loop_end;
3310 insn = NEXT_INSN (insn))
3311 length += length_for_loop (insn);
3313 if (!insn)
3315 if (dump_file)
3316 fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
3317 loop->loop_no);
3318 goto bad_loop;
3321 loop->length = length;
3322 if (loop->length > MAX_LOOP_LENGTH)
3324 if (dump_file)
3325 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
3326 goto bad_loop;
3329 /* Scan all the blocks to make sure they don't use iter_reg. */
3330 if (bfin_scan_loop (loop, iter_reg, loop->loop_end))
3332 if (dump_file)
3333 fprintf (dump_file, ";; loop %d uses iterator\n", loop->loop_no);
3334 goto bad_loop;
3337 /* Scan all the insns to see if the loop body clobber
3338 any hardware loop registers. */
3340 reg_lc0 = gen_rtx_REG (SImode, REG_LC0);
3341 reg_lc1 = gen_rtx_REG (SImode, REG_LC1);
3342 reg_lt0 = gen_rtx_REG (SImode, REG_LT0);
3343 reg_lt1 = gen_rtx_REG (SImode, REG_LT1);
3344 reg_lb0 = gen_rtx_REG (SImode, REG_LB0);
3345 reg_lb1 = gen_rtx_REG (SImode, REG_LB1);
3347 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
3349 rtx insn;
3351 for (insn = BB_HEAD (bb);
3352 insn != NEXT_INSN (BB_END (bb));
3353 insn = NEXT_INSN (insn))
3355 if (!INSN_P (insn))
3356 continue;
3358 if (reg_set_p (reg_lc0, insn)
3359 || reg_set_p (reg_lt0, insn)
3360 || reg_set_p (reg_lb0, insn))
3361 loop->clobber_loop0 = 1;
3363 if (reg_set_p (reg_lc1, insn)
3364 || reg_set_p (reg_lt1, insn)
3365 || reg_set_p (reg_lb1, insn))
3366 loop->clobber_loop1 |= 1;
3370 if ((loop->clobber_loop0 && loop->clobber_loop1)
3371 || (loop->depth == MAX_LOOP_DEPTH && loop->clobber_loop0))
3373 loop->depth = MAX_LOOP_DEPTH + 1;
3374 if (dump_file)
3375 fprintf (dump_file, ";; loop %d no loop reg available\n",
3376 loop->loop_no);
3377 goto bad_loop;
3380 /* There should be an instruction before the loop_end instruction
3381 in the same basic block. And the instruction must not be
3382 - JUMP
3383 - CONDITIONAL BRANCH
3384 - CALL
3385 - CSYNC
3386 - SSYNC
3387 - Returns (RTS, RTN, etc.) */
3389 bb = loop->tail;
3390 last_insn = PREV_INSN (loop->loop_end);
3392 while (1)
3394 for (; last_insn != PREV_INSN (BB_HEAD (bb));
3395 last_insn = PREV_INSN (last_insn))
3396 if (INSN_P (last_insn))
3397 break;
3399 if (last_insn != PREV_INSN (BB_HEAD (bb)))
3400 break;
3402 if (single_pred_p (bb)
3403 && single_pred (bb) != ENTRY_BLOCK_PTR)
3405 bb = single_pred (bb);
3406 last_insn = BB_END (bb);
3407 continue;
3409 else
3411 last_insn = NULL_RTX;
3412 break;
3416 if (!last_insn)
3418 if (dump_file)
3419 fprintf (dump_file, ";; loop %d has no last instruction\n",
3420 loop->loop_no);
3421 goto bad_loop;
3424 if (JUMP_P (last_insn))
3426 loop_info inner = bb->aux;
3427 if (inner
3428 && inner->outer == loop
3429 && inner->loop_end == last_insn
3430 && inner->depth == 1)
3431 /* This jump_insn is the exact loop_end of an inner loop
3432 and to be optimized away. So use the inner's last_insn. */
3433 last_insn = inner->last_insn;
3434 else
3436 if (dump_file)
3437 fprintf (dump_file, ";; loop %d has bad last instruction\n",
3438 loop->loop_no);
3439 goto bad_loop;
3442 else if (CALL_P (last_insn)
3443 || (GET_CODE (PATTERN (last_insn)) != SEQUENCE
3444 && get_attr_type (last_insn) == TYPE_SYNC)
3445 || recog_memoized (last_insn) == CODE_FOR_return_internal)
3447 if (dump_file)
3448 fprintf (dump_file, ";; loop %d has bad last instruction\n",
3449 loop->loop_no);
3450 goto bad_loop;
3453 if (GET_CODE (PATTERN (last_insn)) == ASM_INPUT
3454 || asm_noperands (PATTERN (last_insn)) >= 0
3455 || (GET_CODE (PATTERN (last_insn)) != SEQUENCE
3456 && get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI))
3458 nop_insn = emit_insn_after (gen_nop (), last_insn);
3459 last_insn = nop_insn;
3462 loop->last_insn = last_insn;
3464 /* The loop is good for replacement. */
3465 start_label = loop->start_label;
3466 end_label = gen_label_rtx ();
3467 iter_reg = loop->iter_reg;
3469 if (loop->depth == 1 && !loop->clobber_loop1)
3471 lc_reg = reg_lc1;
3472 lt_reg = reg_lt1;
3473 lb_reg = reg_lb1;
3474 loop->clobber_loop1 = 1;
3476 else
3478 lc_reg = reg_lc0;
3479 lt_reg = reg_lt0;
3480 lb_reg = reg_lb0;
3481 loop->clobber_loop0 = 1;
3484 /* If iter_reg is a DREG, we need generate an instruction to load
3485 the loop count into LC register. */
3486 if (D_REGNO_P (REGNO (iter_reg)))
3488 init_insn = gen_movsi (lc_reg, iter_reg);
3489 loop_init = gen_lsetup_without_autoinit (lt_reg, start_label,
3490 lb_reg, end_label,
3491 lc_reg);
3493 else if (P_REGNO_P (REGNO (iter_reg)))
3495 init_insn = NULL_RTX;
3496 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
3497 lb_reg, end_label,
3498 lc_reg, iter_reg);
3500 else
3501 gcc_unreachable ();
3503 loop->init = init_insn;
3504 loop->end_label = end_label;
3505 loop->loop_init = loop_init;
3507 if (dump_file)
3509 fprintf (dump_file, ";; replacing loop %d initializer with\n",
3510 loop->loop_no);
3511 print_rtl_single (dump_file, loop->loop_init);
3512 fprintf (dump_file, ";; replacing loop %d terminator with\n",
3513 loop->loop_no);
3514 print_rtl_single (dump_file, loop->loop_end);
3517 start_sequence ();
3519 if (loop->init != NULL_RTX)
3520 emit_insn (loop->init);
3521 seq_end = emit_insn (loop->loop_init);
3523 seq = get_insns ();
3524 end_sequence ();
3526 if (loop->incoming_src)
3528 rtx prev = BB_END (loop->incoming_src);
3529 if (VEC_length (edge, loop->incoming) > 1
3530 || !(VEC_last (edge, loop->incoming)->flags & EDGE_FALLTHRU))
3532 gcc_assert (JUMP_P (prev));
3533 prev = PREV_INSN (prev);
3535 emit_insn_after (seq, prev);
3537 else
3539 basic_block new_bb;
3540 edge e;
3541 edge_iterator ei;
3543 if (loop->head != loop->incoming_dest)
3545 FOR_EACH_EDGE (e, ei, loop->head->preds)
3547 if (e->flags & EDGE_FALLTHRU)
3549 rtx newjump = gen_jump (loop->start_label);
3550 emit_insn_before (newjump, BB_HEAD (loop->head));
3551 new_bb = create_basic_block (newjump, newjump, loop->head->prev_bb);
3552 gcc_assert (new_bb = loop->head->prev_bb);
3553 break;
3558 emit_insn_before (seq, BB_HEAD (loop->head));
3559 seq = emit_label_before (gen_label_rtx (), seq);
3561 new_bb = create_basic_block (seq, seq_end, loop->head->prev_bb);
3562 FOR_EACH_EDGE (e, ei, loop->incoming)
3564 if (!(e->flags & EDGE_FALLTHRU)
3565 || e->dest != loop->head)
3566 redirect_edge_and_branch_force (e, new_bb);
3567 else
3568 redirect_edge_succ (e, new_bb);
3572 delete_insn (loop->loop_end);
3573 /* Insert the loop end label before the last instruction of the loop. */
3574 emit_label_before (loop->end_label, loop->last_insn);
3576 return;
3578 bad_loop:
3580 if (dump_file)
3581 fprintf (dump_file, ";; loop %d is bad\n", loop->loop_no);
3583 loop->bad = 1;
3585 if (DPREG_P (loop->iter_reg))
3587 /* If loop->iter_reg is a DREG or PREG, we can split it here
3588 without scratch register. */
3589 rtx insn;
3591 emit_insn_before (gen_addsi3 (loop->iter_reg,
3592 loop->iter_reg,
3593 constm1_rtx),
3594 loop->loop_end);
3596 emit_insn_before (gen_cmpsi (loop->iter_reg, const0_rtx),
3597 loop->loop_end);
3599 insn = emit_jump_insn_before (gen_bne (loop->start_label),
3600 loop->loop_end);
3602 JUMP_LABEL (insn) = loop->start_label;
3603 LABEL_NUSES (loop->start_label)++;
3604 delete_insn (loop->loop_end);
3608 /* Called from bfin_reorg_loops when a potential loop end is found. LOOP is
3609 a newly set up structure describing the loop, it is this function's
3610 responsibility to fill most of it. TAIL_BB and TAIL_INSN point to the
3611 loop_end insn and its enclosing basic block. */
3613 static void
3614 bfin_discover_loop (loop_info loop, basic_block tail_bb, rtx tail_insn)
3616 unsigned dwork = 0;
3617 basic_block bb;
3618 VEC (basic_block,heap) *works = VEC_alloc (basic_block,heap,20);
3620 loop->tail = tail_bb;
3621 loop->head = BRANCH_EDGE (tail_bb)->dest;
3622 loop->successor = FALLTHRU_EDGE (tail_bb)->dest;
3623 loop->loop_end = tail_insn;
3624 loop->last_insn = NULL_RTX;
3625 loop->iter_reg = SET_DEST (XVECEXP (PATTERN (tail_insn), 0, 1));
3626 loop->depth = loop->length = 0;
3627 loop->visited = 0;
3628 loop->clobber_loop0 = loop->clobber_loop1 = 0;
3629 loop->outer = NULL;
3630 loop->loops = NULL;
3631 loop->incoming = VEC_alloc (edge, gc, 2);
3632 loop->init = loop->loop_init = NULL_RTX;
3633 loop->start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (tail_insn), 0, 0)), 1), 0);
3634 loop->end_label = NULL_RTX;
3635 loop->bad = 0;
3637 VEC_safe_push (basic_block, heap, works, loop->head);
3639 while (VEC_iterate (basic_block, works, dwork++, bb))
3641 edge e;
3642 edge_iterator ei;
3643 if (bb == EXIT_BLOCK_PTR)
3645 /* We've reached the exit block. The loop must be bad. */
3646 if (dump_file)
3647 fprintf (dump_file,
3648 ";; Loop is bad - reached exit block while scanning\n");
3649 loop->bad = 1;
3650 break;
3653 if (bitmap_bit_p (loop->block_bitmap, bb->index))
3654 continue;
3656 /* We've not seen this block before. Add it to the loop's
3657 list and then add each successor to the work list. */
3659 VEC_safe_push (basic_block, heap, loop->blocks, bb);
3660 bitmap_set_bit (loop->block_bitmap, bb->index);
3662 if (bb != tail_bb)
3664 FOR_EACH_EDGE (e, ei, bb->succs)
3666 basic_block succ = EDGE_SUCC (bb, ei.index)->dest;
3667 if (!REGNO_REG_SET_P (succ->il.rtl->global_live_at_start,
3668 REGNO (loop->iter_reg)))
3669 continue;
3670 if (!VEC_space (basic_block, works, 1))
3672 if (dwork)
3674 VEC_block_remove (basic_block, works, 0, dwork);
3675 dwork = 0;
3677 else
3678 VEC_reserve (basic_block, heap, works, 1);
3680 VEC_quick_push (basic_block, works, succ);
3685 /* Find the predecessor, and make sure nothing else jumps into this loop. */
3686 if (!loop->bad)
3688 int pass, retry;
3689 for (dwork = 0; VEC_iterate (basic_block, loop->blocks, dwork, bb); dwork++)
3691 edge e;
3692 edge_iterator ei;
3693 FOR_EACH_EDGE (e, ei, bb->preds)
3695 basic_block pred = e->src;
3697 if (!bfin_bb_in_loop (loop, pred))
3699 if (dump_file)
3700 fprintf (dump_file, ";; Loop %d: incoming edge %d -> %d\n",
3701 loop->loop_no, pred->index,
3702 e->dest->index);
3703 VEC_safe_push (edge, gc, loop->incoming, e);
3708 for (pass = 0, retry = 1; retry && pass < 2; pass++)
3710 edge e;
3711 edge_iterator ei;
3712 bool first = true;
3713 retry = 0;
3715 FOR_EACH_EDGE (e, ei, loop->incoming)
3717 if (first)
3719 loop->incoming_src = e->src;
3720 loop->incoming_dest = e->dest;
3721 first = false;
3723 else
3725 if (e->dest != loop->incoming_dest)
3726 loop->incoming_dest = NULL;
3727 if (e->src != loop->incoming_src)
3728 loop->incoming_src = NULL;
3730 if (loop->incoming_src == NULL && loop->incoming_dest == NULL)
3732 if (pass == 0)
3734 if (dump_file)
3735 fprintf (dump_file,
3736 ";; retrying loop %d with forwarder blocks\n",
3737 loop->loop_no);
3738 retry = 1;
3739 break;
3741 loop->bad = 1;
3742 if (dump_file)
3743 fprintf (dump_file,
3744 ";; can't find suitable entry for loop %d\n",
3745 loop->loop_no);
3746 goto out;
3749 if (retry)
3751 retry = 0;
3752 FOR_EACH_EDGE (e, ei, loop->incoming)
3754 if (forwarder_block_p (e->src))
3756 edge e2;
3757 edge_iterator ei2;
3759 if (dump_file)
3760 fprintf (dump_file,
3761 ";; Adding forwarder block %d to loop %d and retrying\n",
3762 e->src->index, loop->loop_no);
3763 VEC_safe_push (basic_block, heap, loop->blocks, e->src);
3764 bitmap_set_bit (loop->block_bitmap, e->src->index);
3765 FOR_EACH_EDGE (e2, ei2, e->src->preds)
3766 VEC_safe_push (edge, gc, loop->incoming, e2);
3767 VEC_unordered_remove (edge, loop->incoming, ei.index);
3768 retry = 1;
3769 break;
3776 out:
3777 VEC_free (basic_block, heap, works);
3780 /* Analyze the structure of the loops in the current function. Use STACK
3781 for bitmap allocations. Returns all the valid candidates for hardware
3782 loops found in this function. */
3783 static loop_info
3784 bfin_discover_loops (bitmap_obstack *stack, FILE *dump_file)
3786 loop_info loops = NULL;
3787 loop_info loop;
3788 basic_block bb;
3789 bitmap tmp_bitmap;
3790 int nloops = 0;
3792 /* Find all the possible loop tails. This means searching for every
3793 loop_end instruction. For each one found, create a loop_info
3794 structure and add the head block to the work list. */
3795 FOR_EACH_BB (bb)
3797 rtx tail = BB_END (bb);
3799 while (GET_CODE (tail) == NOTE)
3800 tail = PREV_INSN (tail);
3802 bb->aux = NULL;
3804 if (INSN_P (tail) && recog_memoized (tail) == CODE_FOR_loop_end)
3806 /* A possible loop end */
3808 loop = XNEW (struct loop_info);
3809 loop->next = loops;
3810 loops = loop;
3811 loop->loop_no = nloops++;
3812 loop->blocks = VEC_alloc (basic_block, heap, 20);
3813 loop->block_bitmap = BITMAP_ALLOC (stack);
3814 bb->aux = loop;
3816 if (dump_file)
3818 fprintf (dump_file, ";; potential loop %d ending at\n",
3819 loop->loop_no);
3820 print_rtl_single (dump_file, tail);
3823 bfin_discover_loop (loop, bb, tail);
3827 tmp_bitmap = BITMAP_ALLOC (stack);
3828 /* Compute loop nestings. */
3829 for (loop = loops; loop; loop = loop->next)
3831 loop_info other;
3832 if (loop->bad)
3833 continue;
3835 for (other = loop->next; other; other = other->next)
3837 if (other->bad)
3838 continue;
3840 bitmap_and (tmp_bitmap, other->block_bitmap, loop->block_bitmap);
3841 if (bitmap_empty_p (tmp_bitmap))
3842 continue;
3843 if (bitmap_equal_p (tmp_bitmap, other->block_bitmap))
3845 other->outer = loop;
3846 VEC_safe_push (loop_info, heap, loop->loops, other);
3848 else if (bitmap_equal_p (tmp_bitmap, loop->block_bitmap))
3850 loop->outer = other;
3851 VEC_safe_push (loop_info, heap, other->loops, loop);
3853 else
3855 if (dump_file)
3856 fprintf (dump_file,
3857 ";; can't find suitable nesting for loops %d and %d\n",
3858 loop->loop_no, other->loop_no);
3859 loop->bad = other->bad = 1;
3863 BITMAP_FREE (tmp_bitmap);
3865 return loops;
3868 /* Free up the loop structures in LOOPS. */
3869 static void
3870 free_loops (loop_info loops)
3872 while (loops)
3874 loop_info loop = loops;
3875 loops = loop->next;
3876 VEC_free (loop_info, heap, loop->loops);
3877 VEC_free (basic_block, heap, loop->blocks);
3878 BITMAP_FREE (loop->block_bitmap);
3879 XDELETE (loop);
3883 #define BB_AUX_INDEX(BB) ((unsigned)(BB)->aux)
3885 /* The taken-branch edge from the loop end can actually go forward. Since the
3886 Blackfin's LSETUP instruction requires that the loop end be after the loop
3887 start, try to reorder a loop's basic blocks when we find such a case. */
3888 static void
3889 bfin_reorder_loops (loop_info loops, FILE *dump_file)
3891 basic_block bb;
3892 loop_info loop;
3894 FOR_EACH_BB (bb)
3895 bb->aux = NULL;
3896 cfg_layout_initialize (CLEANUP_UPDATE_LIFE);
3898 for (loop = loops; loop; loop = loop->next)
3900 unsigned index;
3901 basic_block bb;
3902 edge e;
3903 edge_iterator ei;
3905 if (loop->bad)
3906 continue;
3908 /* Recreate an index for basic blocks that represents their order. */
3909 for (bb = ENTRY_BLOCK_PTR->next_bb, index = 0;
3910 bb != EXIT_BLOCK_PTR;
3911 bb = bb->next_bb, index++)
3912 bb->aux = (PTR) index;
3914 if (BB_AUX_INDEX (loop->head) < BB_AUX_INDEX (loop->tail))
3915 continue;
3917 FOR_EACH_EDGE (e, ei, loop->head->succs)
3919 if (bitmap_bit_p (loop->block_bitmap, e->dest->index)
3920 && BB_AUX_INDEX (e->dest) < BB_AUX_INDEX (loop->tail))
3922 basic_block start_bb = e->dest;
3923 basic_block start_prev_bb = start_bb->prev_bb;
3925 if (dump_file)
3926 fprintf (dump_file, ";; Moving block %d before block %d\n",
3927 loop->head->index, start_bb->index);
3928 loop->head->prev_bb->next_bb = loop->head->next_bb;
3929 loop->head->next_bb->prev_bb = loop->head->prev_bb;
3931 loop->head->prev_bb = start_prev_bb;
3932 loop->head->next_bb = start_bb;
3933 start_prev_bb->next_bb = start_bb->prev_bb = loop->head;
3934 break;
3937 loops = loops->next;
3940 FOR_EACH_BB (bb)
3942 if (bb->next_bb != EXIT_BLOCK_PTR)
3943 bb->aux = bb->next_bb;
3944 else
3945 bb->aux = NULL;
3947 cfg_layout_finalize ();
3950 /* Run from machine_dependent_reorg, this pass looks for doloop_end insns
3951 and tries to rewrite the RTL of these loops so that proper Blackfin
3952 hardware loops are generated. */
3954 static void
3955 bfin_reorg_loops (FILE *dump_file)
3957 loop_info loops = NULL;
3958 loop_info loop;
3959 basic_block bb;
3960 bitmap_obstack stack;
3962 bitmap_obstack_initialize (&stack);
3964 if (dump_file)
3965 fprintf (dump_file, ";; Find loops, first pass\n\n");
3967 loops = bfin_discover_loops (&stack, dump_file);
3969 if (dump_file)
3970 bfin_dump_loops (loops);
3972 bfin_reorder_loops (loops, dump_file);
3973 free_loops (loops);
3975 if (dump_file)
3976 fprintf (dump_file, ";; Find loops, second pass\n\n");
3978 loops = bfin_discover_loops (&stack, dump_file);
3979 if (dump_file)
3981 fprintf (dump_file, ";; All loops found:\n\n");
3982 bfin_dump_loops (loops);
3985 /* Now apply the optimizations. */
3986 for (loop = loops; loop; loop = loop->next)
3987 bfin_optimize_loop (loop);
3989 if (dump_file)
3991 fprintf (dump_file, ";; After hardware loops optimization:\n\n");
3992 bfin_dump_loops (loops);
3995 free_loops (loops);
3997 if (dump_file)
3998 print_rtl (dump_file, get_insns ());
4000 FOR_EACH_BB (bb)
4001 bb->aux = NULL;
4004 /* Possibly generate a SEQUENCE out of three insns found in SLOT.
4005 Returns true if we modified the insn chain, false otherwise. */
4006 static bool
4007 gen_one_bundle (rtx slot[3])
4009 rtx bundle;
4011 gcc_assert (slot[1] != NULL_RTX);
4013 /* Verify that we really can do the multi-issue. */
4014 if (slot[0])
4016 rtx t = NEXT_INSN (slot[0]);
4017 while (t != slot[1])
4019 if (GET_CODE (t) != NOTE
4020 || NOTE_LINE_NUMBER (t) != NOTE_INSN_DELETED)
4021 return false;
4022 t = NEXT_INSN (t);
4025 if (slot[2])
4027 rtx t = NEXT_INSN (slot[1]);
4028 while (t != slot[2])
4030 if (GET_CODE (t) != NOTE
4031 || NOTE_LINE_NUMBER (t) != NOTE_INSN_DELETED)
4032 return false;
4033 t = NEXT_INSN (t);
4037 if (slot[0] == NULL_RTX)
4038 slot[0] = emit_insn_before (gen_mnop (), slot[1]);
4039 if (slot[2] == NULL_RTX)
4040 slot[2] = emit_insn_after (gen_nop (), slot[1]);
4042 /* Avoid line number information being printed inside one bundle. */
4043 if (INSN_LOCATOR (slot[1])
4044 && INSN_LOCATOR (slot[1]) != INSN_LOCATOR (slot[0]))
4045 INSN_LOCATOR (slot[1]) = INSN_LOCATOR (slot[0]);
4046 if (INSN_LOCATOR (slot[2])
4047 && INSN_LOCATOR (slot[2]) != INSN_LOCATOR (slot[0]))
4048 INSN_LOCATOR (slot[2]) = INSN_LOCATOR (slot[0]);
4050 /* Terminate them with "|| " instead of ";" in the output. */
4051 PUT_MODE (slot[0], SImode);
4052 PUT_MODE (slot[1], SImode);
4054 /* This is a cheat to avoid emit_insn's special handling of SEQUENCEs.
4055 Generating a PARALLEL first and changing its code later is the
4056 easiest way to emit a SEQUENCE insn. */
4057 bundle = gen_rtx_PARALLEL (VOIDmode, gen_rtvec (3, slot[0], slot[1], slot[2]));
4058 emit_insn_before (bundle, slot[0]);
4059 remove_insn (slot[0]);
4060 remove_insn (slot[1]);
4061 remove_insn (slot[2]);
4062 PUT_CODE (bundle, SEQUENCE);
4064 return true;
4067 /* Go through all insns, and use the information generated during scheduling
4068 to generate SEQUENCEs to represent bundles of instructions issued
4069 simultaneously. */
4071 static void
4072 bfin_gen_bundles (void)
4074 basic_block bb;
4075 FOR_EACH_BB (bb)
4077 rtx insn, next;
4078 rtx slot[3];
4079 int n_filled = 0;
4081 slot[0] = slot[1] = slot[2] = NULL_RTX;
4082 for (insn = BB_HEAD (bb);; insn = next)
4084 int at_end;
4085 if (INSN_P (insn))
4087 if (get_attr_type (insn) == TYPE_DSP32)
4088 slot[0] = insn;
4089 else if (slot[1] == NULL_RTX)
4090 slot[1] = insn;
4091 else
4092 slot[2] = insn;
4093 n_filled++;
4096 next = NEXT_INSN (insn);
4097 while (next && insn != BB_END (bb)
4098 && !(INSN_P (next)
4099 && GET_CODE (PATTERN (next)) != USE
4100 && GET_CODE (PATTERN (next)) != CLOBBER))
4102 insn = next;
4103 next = NEXT_INSN (insn);
4106 /* BB_END can change due to emitting extra NOPs, so check here. */
4107 at_end = insn == BB_END (bb);
4108 if (at_end || GET_MODE (next) == TImode)
4110 if ((n_filled < 2
4111 || !gen_one_bundle (slot))
4112 && slot[0] != NULL_RTX)
4114 rtx pat = PATTERN (slot[0]);
4115 if (GET_CODE (pat) == SET
4116 && GET_CODE (SET_SRC (pat)) == UNSPEC
4117 && XINT (SET_SRC (pat), 1) == UNSPEC_32BIT)
4119 SET_SRC (pat) = XVECEXP (SET_SRC (pat), 0, 0);
4120 INSN_CODE (slot[0]) = -1;
4123 n_filled = 0;
4124 slot[0] = slot[1] = slot[2] = NULL_RTX;
4126 if (at_end)
4127 break;
4132 /* Return an insn type for INSN that can be used by the caller for anomaly
4133 workarounds. This differs from plain get_attr_type in that it handles
4134 SEQUENCEs. */
4136 static enum attr_type
4137 type_for_anomaly (rtx insn)
4139 rtx pat = PATTERN (insn);
4140 if (GET_CODE (pat) == SEQUENCE)
4142 enum attr_type t;
4143 t = get_attr_type (XVECEXP (pat, 0, 1));
4144 if (t == TYPE_MCLD)
4145 return t;
4146 t = get_attr_type (XVECEXP (pat, 0, 2));
4147 if (t == TYPE_MCLD)
4148 return t;
4149 return TYPE_MCST;
4151 else
4152 return get_attr_type (insn);
4155 /* Return nonzero if INSN contains any loads that may trap. It handles
4156 SEQUENCEs correctly. */
4158 static bool
4159 trapping_loads_p (rtx insn)
4161 rtx pat = PATTERN (insn);
4162 if (GET_CODE (pat) == SEQUENCE)
4164 enum attr_type t;
4165 t = get_attr_type (XVECEXP (pat, 0, 1));
4166 if (t == TYPE_MCLD
4167 && may_trap_p (SET_SRC (PATTERN (XVECEXP (pat, 0, 1)))))
4168 return true;
4169 t = get_attr_type (XVECEXP (pat, 0, 2));
4170 if (t == TYPE_MCLD
4171 && may_trap_p (SET_SRC (PATTERN (XVECEXP (pat, 0, 2)))))
4172 return true;
4173 return false;
4175 else
4176 return may_trap_p (SET_SRC (single_set (insn)));
4179 /* We use the machine specific reorg pass for emitting CSYNC instructions
4180 after conditional branches as needed.
4182 The Blackfin is unusual in that a code sequence like
4183 if cc jump label
4184 r0 = (p0)
4185 may speculatively perform the load even if the condition isn't true. This
4186 happens for a branch that is predicted not taken, because the pipeline
4187 isn't flushed or stalled, so the early stages of the following instructions,
4188 which perform the memory reference, are allowed to execute before the
4189 jump condition is evaluated.
4190 Therefore, we must insert additional instructions in all places where this
4191 could lead to incorrect behavior. The manual recommends CSYNC, while
4192 VDSP seems to use NOPs (even though its corresponding compiler option is
4193 named CSYNC).
4195 When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
4196 When optimizing for size, we turn the branch into a predicted taken one.
4197 This may be slower due to mispredicts, but saves code size. */
4199 static void
4200 bfin_reorg (void)
4202 rtx insn, last_condjump = NULL_RTX;
4203 int cycles_since_jump = INT_MAX;
4205 /* We are freeing block_for_insn in the toplev to keep compatibility
4206 with old MDEP_REORGS that are not CFG based. Recompute it now. */
4207 compute_bb_for_insn ();
4209 if (bfin_flag_schedule_insns2)
4211 splitting_for_sched = 1;
4212 split_all_insns (0);
4213 splitting_for_sched = 0;
4215 update_life_info (NULL, UPDATE_LIFE_GLOBAL_RM_NOTES, PROP_DEATH_NOTES);
4217 timevar_push (TV_SCHED2);
4218 schedule_insns ();
4219 timevar_pop (TV_SCHED2);
4221 /* Examine the schedule and insert nops as necessary for 64-bit parallel
4222 instructions. */
4223 bfin_gen_bundles ();
4226 /* Doloop optimization */
4227 if (cfun->machine->has_hardware_loops)
4228 bfin_reorg_loops (dump_file);
4230 if (! TARGET_SPECLD_ANOMALY && ! TARGET_CSYNC_ANOMALY)
4231 return;
4233 /* First pass: find predicted-false branches; if something after them
4234 needs nops, insert them or change the branch to predict true. */
4235 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4237 rtx pat;
4239 if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
4240 continue;
4242 pat = PATTERN (insn);
4243 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4244 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
4245 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
4246 continue;
4248 if (JUMP_P (insn))
4250 if (any_condjump_p (insn)
4251 && ! cbranch_predicted_taken_p (insn))
4253 last_condjump = insn;
4254 cycles_since_jump = 0;
4256 else
4257 cycles_since_jump = INT_MAX;
4259 else if (INSN_P (insn))
4261 enum attr_type type = type_for_anomaly (insn);
4262 int delay_needed = 0;
4263 if (cycles_since_jump < INT_MAX)
4264 cycles_since_jump++;
4266 if (type == TYPE_MCLD && TARGET_SPECLD_ANOMALY)
4268 if (trapping_loads_p (insn))
4269 delay_needed = 3;
4271 else if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
4272 delay_needed = 4;
4274 if (delay_needed > cycles_since_jump)
4276 rtx pat;
4277 int num_clobbers;
4278 rtx *op = recog_data.operand;
4280 delay_needed -= cycles_since_jump;
4282 extract_insn (last_condjump);
4283 if (optimize_size)
4285 pat = gen_cbranch_predicted_taken (op[0], op[1], op[2],
4286 op[3]);
4287 cycles_since_jump = INT_MAX;
4289 else
4290 /* Do not adjust cycles_since_jump in this case, so that
4291 we'll increase the number of NOPs for a subsequent insn
4292 if necessary. */
4293 pat = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
4294 GEN_INT (delay_needed));
4295 PATTERN (last_condjump) = pat;
4296 INSN_CODE (last_condjump) = recog (pat, insn, &num_clobbers);
4300 /* Second pass: for predicted-true branches, see if anything at the
4301 branch destination needs extra nops. */
4302 if (! TARGET_CSYNC_ANOMALY)
4303 return;
4305 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4307 if (JUMP_P (insn)
4308 && any_condjump_p (insn)
4309 && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken
4310 || cbranch_predicted_taken_p (insn)))
4312 rtx target = JUMP_LABEL (insn);
4313 rtx label = target;
4314 cycles_since_jump = 0;
4315 for (; target && cycles_since_jump < 3; target = NEXT_INSN (target))
4317 rtx pat;
4319 if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
4320 continue;
4322 pat = PATTERN (target);
4323 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4324 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
4325 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
4326 continue;
4328 if (INSN_P (target))
4330 enum attr_type type = type_for_anomaly (target);
4331 int delay_needed = 0;
4332 if (cycles_since_jump < INT_MAX)
4333 cycles_since_jump++;
4335 if (type == TYPE_SYNC && TARGET_CSYNC_ANOMALY)
4336 delay_needed = 2;
4338 if (delay_needed > cycles_since_jump)
4340 rtx prev = prev_real_insn (label);
4341 delay_needed -= cycles_since_jump;
4342 if (dump_file)
4343 fprintf (dump_file, "Adding %d nops after %d\n",
4344 delay_needed, INSN_UID (label));
4345 if (JUMP_P (prev)
4346 && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops)
4348 rtx x;
4349 HOST_WIDE_INT v;
4351 if (dump_file)
4352 fprintf (dump_file,
4353 "Reducing nops on insn %d.\n",
4354 INSN_UID (prev));
4355 x = PATTERN (prev);
4356 x = XVECEXP (x, 0, 1);
4357 v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed;
4358 XVECEXP (x, 0, 0) = GEN_INT (v);
4360 while (delay_needed-- > 0)
4361 emit_insn_after (gen_nop (), label);
4362 break;
4369 if (bfin_flag_var_tracking)
4371 timevar_push (TV_VAR_TRACKING);
4372 variable_tracking_main ();
4373 timevar_pop (TV_VAR_TRACKING);
4377 /* Handle interrupt_handler, exception_handler and nmi_handler function
4378 attributes; arguments as in struct attribute_spec.handler. */
4380 static tree
4381 handle_int_attribute (tree *node, tree name,
4382 tree args ATTRIBUTE_UNUSED,
4383 int flags ATTRIBUTE_UNUSED,
4384 bool *no_add_attrs)
4386 tree x = *node;
4387 if (TREE_CODE (x) == FUNCTION_DECL)
4388 x = TREE_TYPE (x);
4390 if (TREE_CODE (x) != FUNCTION_TYPE)
4392 warning (OPT_Wattributes, "%qs attribute only applies to functions",
4393 IDENTIFIER_POINTER (name));
4394 *no_add_attrs = true;
4396 else if (funkind (x) != SUBROUTINE)
4397 error ("multiple function type attributes specified");
4399 return NULL_TREE;
4402 /* Return 0 if the attributes for two types are incompatible, 1 if they
4403 are compatible, and 2 if they are nearly compatible (which causes a
4404 warning to be generated). */
4406 static int
4407 bfin_comp_type_attributes (tree type1, tree type2)
4409 e_funkind kind1, kind2;
4411 if (TREE_CODE (type1) != FUNCTION_TYPE)
4412 return 1;
4414 kind1 = funkind (type1);
4415 kind2 = funkind (type2);
4417 if (kind1 != kind2)
4418 return 0;
4420 /* Check for mismatched modifiers */
4421 if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
4422 != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
4423 return 0;
4425 if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
4426 != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
4427 return 0;
4429 if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
4430 != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
4431 return 0;
4433 if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1))
4434 != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2)))
4435 return 0;
4437 return 1;
4440 /* Handle a "longcall" or "shortcall" attribute; arguments as in
4441 struct attribute_spec.handler. */
4443 static tree
4444 bfin_handle_longcall_attribute (tree *node, tree name,
4445 tree args ATTRIBUTE_UNUSED,
4446 int flags ATTRIBUTE_UNUSED,
4447 bool *no_add_attrs)
4449 if (TREE_CODE (*node) != FUNCTION_TYPE
4450 && TREE_CODE (*node) != FIELD_DECL
4451 && TREE_CODE (*node) != TYPE_DECL)
4453 warning (OPT_Wattributes, "`%s' attribute only applies to functions",
4454 IDENTIFIER_POINTER (name));
4455 *no_add_attrs = true;
4458 if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0
4459 && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node)))
4460 || (strcmp (IDENTIFIER_POINTER (name), "shortcall") == 0
4461 && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node))))
4463 warning (OPT_Wattributes,
4464 "can't apply both longcall and shortcall attributes to the same function");
4465 *no_add_attrs = true;
4468 return NULL_TREE;
4471 /* Table of valid machine attributes. */
4472 const struct attribute_spec bfin_attribute_table[] =
4474 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
4475 { "interrupt_handler", 0, 0, false, true, true, handle_int_attribute },
4476 { "exception_handler", 0, 0, false, true, true, handle_int_attribute },
4477 { "nmi_handler", 0, 0, false, true, true, handle_int_attribute },
4478 { "nesting", 0, 0, false, true, true, NULL },
4479 { "kspisusp", 0, 0, false, true, true, NULL },
4480 { "saveall", 0, 0, false, true, true, NULL },
4481 { "longcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
4482 { "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
4483 { NULL, 0, 0, false, false, false, NULL }
4486 /* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to
4487 tell the assembler to generate pointers to function descriptors in
4488 some cases. */
4490 static bool
4491 bfin_assemble_integer (rtx value, unsigned int size, int aligned_p)
4493 if (TARGET_FDPIC && size == UNITS_PER_WORD)
4495 if (GET_CODE (value) == SYMBOL_REF
4496 && SYMBOL_REF_FUNCTION_P (value))
4498 fputs ("\t.picptr\tfuncdesc(", asm_out_file);
4499 output_addr_const (asm_out_file, value);
4500 fputs (")\n", asm_out_file);
4501 return true;
4503 if (!aligned_p)
4505 /* We've set the unaligned SI op to NULL, so we always have to
4506 handle the unaligned case here. */
4507 assemble_integer_with_op ("\t.4byte\t", value);
4508 return true;
4511 return default_assemble_integer (value, size, aligned_p);
4514 /* Output the assembler code for a thunk function. THUNK_DECL is the
4515 declaration for the thunk function itself, FUNCTION is the decl for
4516 the target function. DELTA is an immediate constant offset to be
4517 added to THIS. If VCALL_OFFSET is nonzero, the word at
4518 *(*this + vcall_offset) should be added to THIS. */
4520 static void
4521 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
4522 tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
4523 HOST_WIDE_INT vcall_offset, tree function)
4525 rtx xops[3];
4526 /* The this parameter is passed as the first argument. */
4527 rtx this = gen_rtx_REG (Pmode, REG_R0);
4529 /* Adjust the this parameter by a fixed constant. */
4530 if (delta)
4532 xops[1] = this;
4533 if (delta >= -64 && delta <= 63)
4535 xops[0] = GEN_INT (delta);
4536 output_asm_insn ("%1 += %0;", xops);
4538 else if (delta >= -128 && delta < -64)
4540 xops[0] = GEN_INT (delta + 64);
4541 output_asm_insn ("%1 += -64; %1 += %0;", xops);
4543 else if (delta > 63 && delta <= 126)
4545 xops[0] = GEN_INT (delta - 63);
4546 output_asm_insn ("%1 += 63; %1 += %0;", xops);
4548 else
4550 xops[0] = GEN_INT (delta);
4551 output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
4555 /* Adjust the this parameter by a value stored in the vtable. */
4556 if (vcall_offset)
4558 rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
4559 rtx tmp = gen_rtx_REG (Pmode, REG_R3);
4561 xops[1] = tmp;
4562 xops[2] = p2tmp;
4563 output_asm_insn ("%2 = r0; %2 = [%2];", xops);
4565 /* Adjust the this parameter. */
4566 xops[0] = gen_rtx_MEM (Pmode, plus_constant (p2tmp, vcall_offset));
4567 if (!memory_operand (xops[0], Pmode))
4569 rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
4570 xops[0] = GEN_INT (vcall_offset);
4571 xops[1] = tmp2;
4572 output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
4573 xops[0] = gen_rtx_MEM (Pmode, p2tmp);
4575 xops[2] = this;
4576 output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
4579 xops[0] = XEXP (DECL_RTL (function), 0);
4580 if (1 || !flag_pic || (*targetm.binds_local_p) (function))
4581 output_asm_insn ("jump.l\t%P0", xops);
4584 /* Codes for all the Blackfin builtins. */
4585 enum bfin_builtins
4587 BFIN_BUILTIN_CSYNC,
4588 BFIN_BUILTIN_SSYNC,
4589 BFIN_BUILTIN_COMPOSE_2X16,
4590 BFIN_BUILTIN_EXTRACTLO,
4591 BFIN_BUILTIN_EXTRACTHI,
4593 BFIN_BUILTIN_SSADD_2X16,
4594 BFIN_BUILTIN_SSSUB_2X16,
4595 BFIN_BUILTIN_SSADDSUB_2X16,
4596 BFIN_BUILTIN_SSSUBADD_2X16,
4597 BFIN_BUILTIN_MULT_2X16,
4598 BFIN_BUILTIN_MULTR_2X16,
4599 BFIN_BUILTIN_NEG_2X16,
4600 BFIN_BUILTIN_ABS_2X16,
4601 BFIN_BUILTIN_MIN_2X16,
4602 BFIN_BUILTIN_MAX_2X16,
4604 BFIN_BUILTIN_SSADD_1X16,
4605 BFIN_BUILTIN_SSSUB_1X16,
4606 BFIN_BUILTIN_MULT_1X16,
4607 BFIN_BUILTIN_MULTR_1X16,
4608 BFIN_BUILTIN_NORM_1X16,
4609 BFIN_BUILTIN_NEG_1X16,
4610 BFIN_BUILTIN_ABS_1X16,
4611 BFIN_BUILTIN_MIN_1X16,
4612 BFIN_BUILTIN_MAX_1X16,
4614 BFIN_BUILTIN_DIFFHL_2X16,
4615 BFIN_BUILTIN_DIFFLH_2X16,
4617 BFIN_BUILTIN_SSADD_1X32,
4618 BFIN_BUILTIN_SSSUB_1X32,
4619 BFIN_BUILTIN_NORM_1X32,
4620 BFIN_BUILTIN_NEG_1X32,
4621 BFIN_BUILTIN_MIN_1X32,
4622 BFIN_BUILTIN_MAX_1X32,
4623 BFIN_BUILTIN_MULT_1X32,
4625 BFIN_BUILTIN_MULHISILL,
4626 BFIN_BUILTIN_MULHISILH,
4627 BFIN_BUILTIN_MULHISIHL,
4628 BFIN_BUILTIN_MULHISIHH,
4630 BFIN_BUILTIN_LSHIFT_1X16,
4631 BFIN_BUILTIN_LSHIFT_2X16,
4632 BFIN_BUILTIN_SSASHIFT_1X16,
4633 BFIN_BUILTIN_SSASHIFT_2X16,
4635 BFIN_BUILTIN_CPLX_MUL_16,
4636 BFIN_BUILTIN_CPLX_MAC_16,
4637 BFIN_BUILTIN_CPLX_MSU_16,
4639 BFIN_BUILTIN_MAX
4642 #define def_builtin(NAME, TYPE, CODE) \
4643 do { \
4644 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
4645 NULL, NULL_TREE); \
4646 } while (0)
4648 /* Set up all builtin functions for this target. */
4649 static void
4650 bfin_init_builtins (void)
4652 tree V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
4653 tree void_ftype_void
4654 = build_function_type (void_type_node, void_list_node);
4655 tree short_ftype_short
4656 = build_function_type_list (short_integer_type_node, short_integer_type_node,
4657 NULL_TREE);
4658 tree short_ftype_int_int
4659 = build_function_type_list (short_integer_type_node, integer_type_node,
4660 integer_type_node, NULL_TREE);
4661 tree int_ftype_int_int
4662 = build_function_type_list (integer_type_node, integer_type_node,
4663 integer_type_node, NULL_TREE);
4664 tree int_ftype_int
4665 = build_function_type_list (integer_type_node, integer_type_node,
4666 NULL_TREE);
4667 tree short_ftype_int
4668 = build_function_type_list (short_integer_type_node, integer_type_node,
4669 NULL_TREE);
4670 tree int_ftype_v2hi_v2hi
4671 = build_function_type_list (integer_type_node, V2HI_type_node,
4672 V2HI_type_node, NULL_TREE);
4673 tree v2hi_ftype_v2hi_v2hi
4674 = build_function_type_list (V2HI_type_node, V2HI_type_node,
4675 V2HI_type_node, NULL_TREE);
4676 tree v2hi_ftype_v2hi_v2hi_v2hi
4677 = build_function_type_list (V2HI_type_node, V2HI_type_node,
4678 V2HI_type_node, V2HI_type_node, NULL_TREE);
4679 tree v2hi_ftype_int_int
4680 = build_function_type_list (V2HI_type_node, integer_type_node,
4681 integer_type_node, NULL_TREE);
4682 tree v2hi_ftype_v2hi_int
4683 = build_function_type_list (V2HI_type_node, V2HI_type_node,
4684 integer_type_node, NULL_TREE);
4685 tree int_ftype_short_short
4686 = build_function_type_list (integer_type_node, short_integer_type_node,
4687 short_integer_type_node, NULL_TREE);
4688 tree v2hi_ftype_v2hi
4689 = build_function_type_list (V2HI_type_node, V2HI_type_node, NULL_TREE);
4690 tree short_ftype_v2hi
4691 = build_function_type_list (short_integer_type_node, V2HI_type_node,
4692 NULL_TREE);
4694 /* Add the remaining MMX insns with somewhat more complicated types. */
4695 def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC);
4696 def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC);
4698 def_builtin ("__builtin_bfin_compose_2x16", v2hi_ftype_int_int,
4699 BFIN_BUILTIN_COMPOSE_2X16);
4700 def_builtin ("__builtin_bfin_extract_hi", short_ftype_v2hi,
4701 BFIN_BUILTIN_EXTRACTHI);
4702 def_builtin ("__builtin_bfin_extract_lo", short_ftype_v2hi,
4703 BFIN_BUILTIN_EXTRACTLO);
4705 def_builtin ("__builtin_bfin_min_fr2x16", v2hi_ftype_v2hi_v2hi,
4706 BFIN_BUILTIN_MIN_2X16);
4707 def_builtin ("__builtin_bfin_max_fr2x16", v2hi_ftype_v2hi_v2hi,
4708 BFIN_BUILTIN_MAX_2X16);
4710 def_builtin ("__builtin_bfin_add_fr2x16", v2hi_ftype_v2hi_v2hi,
4711 BFIN_BUILTIN_SSADD_2X16);
4712 def_builtin ("__builtin_bfin_sub_fr2x16", v2hi_ftype_v2hi_v2hi,
4713 BFIN_BUILTIN_SSSUB_2X16);
4714 def_builtin ("__builtin_bfin_dspaddsubsat", v2hi_ftype_v2hi_v2hi,
4715 BFIN_BUILTIN_SSADDSUB_2X16);
4716 def_builtin ("__builtin_bfin_dspsubaddsat", v2hi_ftype_v2hi_v2hi,
4717 BFIN_BUILTIN_SSSUBADD_2X16);
4718 def_builtin ("__builtin_bfin_mult_fr2x16", v2hi_ftype_v2hi_v2hi,
4719 BFIN_BUILTIN_MULT_2X16);
4720 def_builtin ("__builtin_bfin_multr_fr2x16", v2hi_ftype_v2hi_v2hi,
4721 BFIN_BUILTIN_MULTR_2X16);
4722 def_builtin ("__builtin_bfin_negate_fr2x16", v2hi_ftype_v2hi,
4723 BFIN_BUILTIN_NEG_2X16);
4724 def_builtin ("__builtin_bfin_abs_fr2x16", v2hi_ftype_v2hi,
4725 BFIN_BUILTIN_ABS_2X16);
4727 def_builtin ("__builtin_bfin_add_fr1x16", short_ftype_int_int,
4728 BFIN_BUILTIN_SSADD_1X16);
4729 def_builtin ("__builtin_bfin_sub_fr1x16", short_ftype_int_int,
4730 BFIN_BUILTIN_SSSUB_1X16);
4731 def_builtin ("__builtin_bfin_mult_fr1x16", short_ftype_int_int,
4732 BFIN_BUILTIN_MULT_1X16);
4733 def_builtin ("__builtin_bfin_multr_fr1x16", short_ftype_int_int,
4734 BFIN_BUILTIN_MULTR_1X16);
4735 def_builtin ("__builtin_bfin_negate_fr1x16", short_ftype_short,
4736 BFIN_BUILTIN_NEG_1X16);
4737 def_builtin ("__builtin_bfin_abs_fr1x16", short_ftype_short,
4738 BFIN_BUILTIN_ABS_1X16);
4739 def_builtin ("__builtin_bfin_norm_fr1x16", short_ftype_int,
4740 BFIN_BUILTIN_NORM_1X16);
4742 def_builtin ("__builtin_bfin_diff_hl_fr2x16", short_ftype_v2hi,
4743 BFIN_BUILTIN_DIFFHL_2X16);
4744 def_builtin ("__builtin_bfin_diff_lh_fr2x16", short_ftype_v2hi,
4745 BFIN_BUILTIN_DIFFLH_2X16);
4747 def_builtin ("__builtin_bfin_mulhisill", int_ftype_v2hi_v2hi,
4748 BFIN_BUILTIN_MULHISILL);
4749 def_builtin ("__builtin_bfin_mulhisihl", int_ftype_v2hi_v2hi,
4750 BFIN_BUILTIN_MULHISIHL);
4751 def_builtin ("__builtin_bfin_mulhisilh", int_ftype_v2hi_v2hi,
4752 BFIN_BUILTIN_MULHISILH);
4753 def_builtin ("__builtin_bfin_mulhisihh", int_ftype_v2hi_v2hi,
4754 BFIN_BUILTIN_MULHISIHH);
4756 def_builtin ("__builtin_bfin_add_fr1x32", int_ftype_int_int,
4757 BFIN_BUILTIN_SSADD_1X32);
4758 def_builtin ("__builtin_bfin_sub_fr1x32", int_ftype_int_int,
4759 BFIN_BUILTIN_SSSUB_1X32);
4760 def_builtin ("__builtin_bfin_negate_fr1x32", int_ftype_int,
4761 BFIN_BUILTIN_NEG_1X32);
4762 def_builtin ("__builtin_bfin_norm_fr1x32", short_ftype_int,
4763 BFIN_BUILTIN_NORM_1X32);
4764 def_builtin ("__builtin_bfin_mult_fr1x32", int_ftype_short_short,
4765 BFIN_BUILTIN_MULT_1X32);
4767 /* Shifts. */
4768 def_builtin ("__builtin_bfin_shl_fr1x16", short_ftype_int_int,
4769 BFIN_BUILTIN_SSASHIFT_1X16);
4770 def_builtin ("__builtin_bfin_shl_fr2x16", v2hi_ftype_v2hi_int,
4771 BFIN_BUILTIN_SSASHIFT_2X16);
4772 def_builtin ("__builtin_bfin_lshl_fr1x16", short_ftype_int_int,
4773 BFIN_BUILTIN_LSHIFT_1X16);
4774 def_builtin ("__builtin_bfin_lshl_fr2x16", v2hi_ftype_v2hi_int,
4775 BFIN_BUILTIN_LSHIFT_2X16);
4777 /* Complex numbers. */
4778 def_builtin ("__builtin_bfin_cmplx_mul", v2hi_ftype_v2hi_v2hi,
4779 BFIN_BUILTIN_CPLX_MUL_16);
4780 def_builtin ("__builtin_bfin_cmplx_mac", v2hi_ftype_v2hi_v2hi_v2hi,
4781 BFIN_BUILTIN_CPLX_MAC_16);
4782 def_builtin ("__builtin_bfin_cmplx_msu", v2hi_ftype_v2hi_v2hi_v2hi,
4783 BFIN_BUILTIN_CPLX_MSU_16);
4787 struct builtin_description
4789 const enum insn_code icode;
4790 const char *const name;
4791 const enum bfin_builtins code;
4792 int macflag;
4795 static const struct builtin_description bdesc_2arg[] =
4797 { CODE_FOR_composev2hi, "__builtin_bfin_compose_2x16", BFIN_BUILTIN_COMPOSE_2X16, -1 },
4799 { CODE_FOR_ssashiftv2hi3, "__builtin_bfin_shl_fr2x16", BFIN_BUILTIN_SSASHIFT_2X16, -1 },
4800 { CODE_FOR_ssashifthi3, "__builtin_bfin_shl_fr1x16", BFIN_BUILTIN_SSASHIFT_1X16, -1 },
4801 { CODE_FOR_lshiftv2hi3, "__builtin_bfin_lshl_fr2x16", BFIN_BUILTIN_LSHIFT_2X16, -1 },
4802 { CODE_FOR_lshifthi3, "__builtin_bfin_lshl_fr1x16", BFIN_BUILTIN_LSHIFT_1X16, -1 },
4804 { CODE_FOR_sminhi3, "__builtin_bfin_min_fr1x16", BFIN_BUILTIN_MIN_1X16, -1 },
4805 { CODE_FOR_smaxhi3, "__builtin_bfin_max_fr1x16", BFIN_BUILTIN_MAX_1X16, -1 },
4806 { CODE_FOR_ssaddhi3, "__builtin_bfin_add_fr1x16", BFIN_BUILTIN_SSADD_1X16, -1 },
4807 { CODE_FOR_sssubhi3, "__builtin_bfin_sub_fr1x16", BFIN_BUILTIN_SSSUB_1X16, -1 },
4809 { CODE_FOR_sminsi3, "__builtin_bfin_min_fr1x32", BFIN_BUILTIN_MIN_1X32, -1 },
4810 { CODE_FOR_smaxsi3, "__builtin_bfin_max_fr1x32", BFIN_BUILTIN_MAX_1X32, -1 },
4811 { CODE_FOR_ssaddsi3, "__builtin_bfin_add_fr1x32", BFIN_BUILTIN_SSADD_1X32, -1 },
4812 { CODE_FOR_sssubsi3, "__builtin_bfin_sub_fr1x32", BFIN_BUILTIN_SSSUB_1X32, -1 },
4814 { CODE_FOR_sminv2hi3, "__builtin_bfin_min_fr2x16", BFIN_BUILTIN_MIN_2X16, -1 },
4815 { CODE_FOR_smaxv2hi3, "__builtin_bfin_max_fr2x16", BFIN_BUILTIN_MAX_2X16, -1 },
4816 { CODE_FOR_ssaddv2hi3, "__builtin_bfin_add_fr2x16", BFIN_BUILTIN_SSADD_2X16, -1 },
4817 { CODE_FOR_sssubv2hi3, "__builtin_bfin_sub_fr2x16", BFIN_BUILTIN_SSSUB_2X16, -1 },
4818 { CODE_FOR_ssaddsubv2hi3, "__builtin_bfin_dspaddsubsat", BFIN_BUILTIN_SSADDSUB_2X16, -1 },
4819 { CODE_FOR_sssubaddv2hi3, "__builtin_bfin_dspsubaddsat", BFIN_BUILTIN_SSSUBADD_2X16, -1 },
4821 { CODE_FOR_flag_mulhisi, "__builtin_bfin_mult_fr1x32", BFIN_BUILTIN_MULT_1X32, MACFLAG_NONE },
4822 { CODE_FOR_flag_mulhi, "__builtin_bfin_mult_fr1x16", BFIN_BUILTIN_MULT_1X16, MACFLAG_T },
4823 { CODE_FOR_flag_mulhi, "__builtin_bfin_multr_fr1x16", BFIN_BUILTIN_MULTR_1X16, MACFLAG_NONE },
4824 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_mult_fr2x16", BFIN_BUILTIN_MULT_2X16, MACFLAG_T },
4825 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_multr_fr2x16", BFIN_BUILTIN_MULTR_2X16, MACFLAG_NONE }
4828 static const struct builtin_description bdesc_1arg[] =
4830 { CODE_FOR_signbitshi2, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16, 0 },
4831 { CODE_FOR_ssneghi2, "__builtin_bfin_negate_fr1x16", BFIN_BUILTIN_NEG_1X16, 0 },
4832 { CODE_FOR_abshi2, "__builtin_bfin_abs_fr1x16", BFIN_BUILTIN_ABS_1X16, 0 },
4834 { CODE_FOR_signbitssi2, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32, 0 },
4835 { CODE_FOR_ssnegsi2, "__builtin_bfin_negate_fr1x32", BFIN_BUILTIN_NEG_1X32, 0 },
4837 { CODE_FOR_movv2hi_hi_low, "__builtin_bfin_extract_lo", BFIN_BUILTIN_EXTRACTLO, 0 },
4838 { CODE_FOR_movv2hi_hi_high, "__builtin_bfin_extract_hi", BFIN_BUILTIN_EXTRACTHI, 0 },
4839 { CODE_FOR_ssnegv2hi2, "__builtin_bfin_negate_fr2x16", BFIN_BUILTIN_NEG_2X16, 0 },
4840 { CODE_FOR_absv2hi2, "__builtin_bfin_abs_fr2x16", BFIN_BUILTIN_ABS_2X16, 0 }
4843 /* Errors in the source file can cause expand_expr to return const0_rtx
4844 where we expect a vector. To avoid crashing, use one of the vector
4845 clear instructions. */
4846 static rtx
4847 safe_vector_operand (rtx x, enum machine_mode mode)
4849 if (x != const0_rtx)
4850 return x;
4851 x = gen_reg_rtx (SImode);
4853 emit_insn (gen_movsi (x, CONST0_RTX (SImode)));
4854 return gen_lowpart (mode, x);
4857 /* Subroutine of bfin_expand_builtin to take care of binop insns. MACFLAG is -1
4858 if this is a normal binary op, or one of the MACFLAG_xxx constants. */
4860 static rtx
4861 bfin_expand_binop_builtin (enum insn_code icode, tree exp, rtx target,
4862 int macflag)
4864 rtx pat;
4865 tree arg0 = CALL_EXPR_ARG (exp, 0);
4866 tree arg1 = CALL_EXPR_ARG (exp, 1);
4867 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4868 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
4869 enum machine_mode op0mode = GET_MODE (op0);
4870 enum machine_mode op1mode = GET_MODE (op1);
4871 enum machine_mode tmode = insn_data[icode].operand[0].mode;
4872 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
4873 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
4875 if (VECTOR_MODE_P (mode0))
4876 op0 = safe_vector_operand (op0, mode0);
4877 if (VECTOR_MODE_P (mode1))
4878 op1 = safe_vector_operand (op1, mode1);
4880 if (! target
4881 || GET_MODE (target) != tmode
4882 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
4883 target = gen_reg_rtx (tmode);
4885 if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode)
4887 op0mode = HImode;
4888 op0 = gen_lowpart (HImode, op0);
4890 if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode)
4892 op1mode = HImode;
4893 op1 = gen_lowpart (HImode, op1);
4895 /* In case the insn wants input operands in modes different from
4896 the result, abort. */
4897 gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
4898 && (op1mode == mode1 || op1mode == VOIDmode));
4900 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
4901 op0 = copy_to_mode_reg (mode0, op0);
4902 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
4903 op1 = copy_to_mode_reg (mode1, op1);
4905 if (macflag == -1)
4906 pat = GEN_FCN (icode) (target, op0, op1);
4907 else
4908 pat = GEN_FCN (icode) (target, op0, op1, GEN_INT (macflag));
4909 if (! pat)
4910 return 0;
4912 emit_insn (pat);
4913 return target;
4916 /* Subroutine of bfin_expand_builtin to take care of unop insns. */
4918 static rtx
4919 bfin_expand_unop_builtin (enum insn_code icode, tree exp,
4920 rtx target)
4922 rtx pat;
4923 tree arg0 = CALL_EXPR_ARG (exp, 0);
4924 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4925 enum machine_mode op0mode = GET_MODE (op0);
4926 enum machine_mode tmode = insn_data[icode].operand[0].mode;
4927 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
4929 if (! target
4930 || GET_MODE (target) != tmode
4931 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
4932 target = gen_reg_rtx (tmode);
4934 if (VECTOR_MODE_P (mode0))
4935 op0 = safe_vector_operand (op0, mode0);
4937 if (op0mode == SImode && mode0 == HImode)
4939 op0mode = HImode;
4940 op0 = gen_lowpart (HImode, op0);
4942 gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
4944 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
4945 op0 = copy_to_mode_reg (mode0, op0);
4947 pat = GEN_FCN (icode) (target, op0);
4948 if (! pat)
4949 return 0;
4950 emit_insn (pat);
4951 return target;
4954 /* Expand an expression EXP that calls a built-in function,
4955 with result going to TARGET if that's convenient
4956 (and in mode MODE if that's convenient).
4957 SUBTARGET may be used as the target for computing one of EXP's operands.
4958 IGNORE is nonzero if the value is to be ignored. */
4960 static rtx
4961 bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
4962 rtx subtarget ATTRIBUTE_UNUSED,
4963 enum machine_mode mode ATTRIBUTE_UNUSED,
4964 int ignore ATTRIBUTE_UNUSED)
4966 size_t i;
4967 enum insn_code icode;
4968 const struct builtin_description *d;
4969 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
4970 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
4971 tree arg0, arg1, arg2;
4972 rtx op0, op1, op2, accvec, pat, tmp1, tmp2;
4973 enum machine_mode tmode, mode0;
4975 switch (fcode)
4977 case BFIN_BUILTIN_CSYNC:
4978 emit_insn (gen_csync ());
4979 return 0;
4980 case BFIN_BUILTIN_SSYNC:
4981 emit_insn (gen_ssync ());
4982 return 0;
4984 case BFIN_BUILTIN_DIFFHL_2X16:
4985 case BFIN_BUILTIN_DIFFLH_2X16:
4986 arg0 = CALL_EXPR_ARG (exp, 0);
4987 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
4988 icode = (fcode == BFIN_BUILTIN_DIFFHL_2X16
4989 ? CODE_FOR_subhilov2hi3 : CODE_FOR_sublohiv2hi3);
4990 tmode = insn_data[icode].operand[0].mode;
4991 mode0 = insn_data[icode].operand[1].mode;
4993 if (! target
4994 || GET_MODE (target) != tmode
4995 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
4996 target = gen_reg_rtx (tmode);
4998 if (VECTOR_MODE_P (mode0))
4999 op0 = safe_vector_operand (op0, mode0);
5001 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5002 op0 = copy_to_mode_reg (mode0, op0);
5004 pat = GEN_FCN (icode) (target, op0, op0);
5005 if (! pat)
5006 return 0;
5007 emit_insn (pat);
5008 return target;
5010 case BFIN_BUILTIN_CPLX_MUL_16:
5011 arg0 = CALL_EXPR_ARG (exp, 0);
5012 arg1 = CALL_EXPR_ARG (exp, 1);
5013 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5014 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
5015 accvec = gen_reg_rtx (V2PDImode);
5017 if (! target
5018 || GET_MODE (target) != V2HImode
5019 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5020 target = gen_reg_rtx (tmode);
5021 if (! register_operand (op0, GET_MODE (op0)))
5022 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
5023 if (! register_operand (op1, GET_MODE (op1)))
5024 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
5026 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
5027 const0_rtx, const0_rtx,
5028 const1_rtx, GEN_INT (MACFLAG_NONE)));
5029 emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
5030 const1_rtx, const1_rtx,
5031 const0_rtx, accvec, const1_rtx, const0_rtx,
5032 GEN_INT (MACFLAG_NONE), accvec));
5034 return target;
5036 case BFIN_BUILTIN_CPLX_MAC_16:
5037 case BFIN_BUILTIN_CPLX_MSU_16:
5038 arg0 = CALL_EXPR_ARG (exp, 0);
5039 arg1 = CALL_EXPR_ARG (exp, 1);
5040 arg2 = CALL_EXPR_ARG (exp, 2);
5041 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5042 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
5043 op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
5044 accvec = gen_reg_rtx (V2PDImode);
5046 if (! target
5047 || GET_MODE (target) != V2HImode
5048 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5049 target = gen_reg_rtx (tmode);
5050 if (! register_operand (op0, GET_MODE (op0)))
5051 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
5052 if (! register_operand (op1, GET_MODE (op1)))
5053 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
5055 tmp1 = gen_reg_rtx (SImode);
5056 tmp2 = gen_reg_rtx (SImode);
5057 emit_insn (gen_ashlsi3 (tmp1, gen_lowpart (SImode, op2), GEN_INT (16)));
5058 emit_move_insn (tmp2, gen_lowpart (SImode, op2));
5059 emit_insn (gen_movstricthi_1 (gen_lowpart (HImode, tmp2), const0_rtx));
5060 emit_insn (gen_load_accumulator_pair (accvec, tmp1, tmp2));
5061 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op0, op1, const0_rtx,
5062 const0_rtx, const0_rtx,
5063 const1_rtx, accvec, const0_rtx,
5064 const0_rtx,
5065 GEN_INT (MACFLAG_W32)));
5066 tmp1 = (fcode == BFIN_BUILTIN_CPLX_MAC_16 ? const1_rtx : const0_rtx);
5067 tmp2 = (fcode == BFIN_BUILTIN_CPLX_MAC_16 ? const0_rtx : const1_rtx);
5068 emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
5069 const1_rtx, const1_rtx,
5070 const0_rtx, accvec, tmp1, tmp2,
5071 GEN_INT (MACFLAG_NONE), accvec));
5073 return target;
5075 default:
5076 break;
5079 for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
5080 if (d->code == fcode)
5081 return bfin_expand_binop_builtin (d->icode, exp, target,
5082 d->macflag);
5084 for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
5085 if (d->code == fcode)
5086 return bfin_expand_unop_builtin (d->icode, exp, target);
5088 gcc_unreachable ();
5091 #undef TARGET_INIT_BUILTINS
5092 #define TARGET_INIT_BUILTINS bfin_init_builtins
5094 #undef TARGET_EXPAND_BUILTIN
5095 #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
5097 #undef TARGET_ASM_GLOBALIZE_LABEL
5098 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label
5100 #undef TARGET_ASM_FILE_START
5101 #define TARGET_ASM_FILE_START output_file_start
5103 #undef TARGET_ATTRIBUTE_TABLE
5104 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
5106 #undef TARGET_COMP_TYPE_ATTRIBUTES
5107 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
5109 #undef TARGET_RTX_COSTS
5110 #define TARGET_RTX_COSTS bfin_rtx_costs
5112 #undef TARGET_ADDRESS_COST
5113 #define TARGET_ADDRESS_COST bfin_address_cost
5115 #undef TARGET_ASM_INTERNAL_LABEL
5116 #define TARGET_ASM_INTERNAL_LABEL bfin_internal_label
5118 #undef TARGET_ASM_INTEGER
5119 #define TARGET_ASM_INTEGER bfin_assemble_integer
5121 #undef TARGET_MACHINE_DEPENDENT_REORG
5122 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
5124 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
5125 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
5127 #undef TARGET_ASM_OUTPUT_MI_THUNK
5128 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
5129 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
5130 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_tree_hwi_hwi_tree_true
5132 #undef TARGET_SCHED_ADJUST_COST
5133 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
5135 #undef TARGET_SCHED_ISSUE_RATE
5136 #define TARGET_SCHED_ISSUE_RATE bfin_issue_rate
5138 #undef TARGET_PROMOTE_PROTOTYPES
5139 #define TARGET_PROMOTE_PROTOTYPES hook_bool_tree_true
5140 #undef TARGET_PROMOTE_FUNCTION_ARGS
5141 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_tree_true
5142 #undef TARGET_PROMOTE_FUNCTION_RETURN
5143 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_tree_true
5145 #undef TARGET_ARG_PARTIAL_BYTES
5146 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
5148 #undef TARGET_PASS_BY_REFERENCE
5149 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
5151 #undef TARGET_SETUP_INCOMING_VARARGS
5152 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
5154 #undef TARGET_STRUCT_VALUE_RTX
5155 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
5157 #undef TARGET_VECTOR_MODE_SUPPORTED_P
5158 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
5160 #undef TARGET_HANDLE_OPTION
5161 #define TARGET_HANDLE_OPTION bfin_handle_option
5163 #undef TARGET_DEFAULT_TARGET_FLAGS
5164 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
5166 #undef TARGET_SECONDARY_RELOAD
5167 #define TARGET_SECONDARY_RELOAD bfin_secondary_reload
5169 #undef TARGET_DELEGITIMIZE_ADDRESS
5170 #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address
5172 #undef TARGET_CANNOT_FORCE_CONST_MEM
5173 #define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem
5175 struct gcc_target targetm = TARGET_INITIALIZER;