recog_memoized works on an rtx_insn *
[official-gcc.git] / gcc / config / bfin / bfin.c
blobe34e24a33b788c510bfe36d30ad2997cdfddc110
1 /* The Blackfin code generation auxiliary output file.
2 Copyright (C) 2005-2014 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 3, 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 COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "rtl.h"
26 #include "regs.h"
27 #include "hard-reg-set.h"
28 #include "insn-config.h"
29 #include "insn-codes.h"
30 #include "conditions.h"
31 #include "insn-flags.h"
32 #include "output.h"
33 #include "insn-attr.h"
34 #include "tree.h"
35 #include "varasm.h"
36 #include "calls.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 "diagnostic-core.h"
45 #include "recog.h"
46 #include "optabs.h"
47 #include "ggc.h"
48 #include "cgraph.h"
49 #include "langhooks.h"
50 #include "bfin-protos.h"
51 #include "tm_p.h"
52 #include "tm-preds.h"
53 #include "tm-constrs.h"
54 #include "gt-bfin.h"
55 #include "basic-block.h"
56 #include "timevar.h"
57 #include "df.h"
58 #include "sel-sched.h"
59 #include "hw-doloop.h"
60 #include "opts.h"
61 #include "dumpfile.h"
62 #include "builtins.h"
64 /* A C structure for machine-specific, per-function data.
65 This is added to the cfun structure. */
66 struct GTY(()) machine_function
68 /* Set if we are notified by the doloop pass that a hardware loop
69 was created. */
70 int has_hardware_loops;
72 /* Set if we create a memcpy pattern that uses loop registers. */
73 int has_loopreg_clobber;
76 /* RTX for condition code flag register and RETS register */
77 extern GTY(()) rtx bfin_cc_rtx;
78 extern GTY(()) rtx bfin_rets_rtx;
79 rtx bfin_cc_rtx, bfin_rets_rtx;
81 int max_arg_registers = 0;
83 /* Arrays used when emitting register names. */
84 const char *short_reg_names[] = SHORT_REGISTER_NAMES;
85 const char *high_reg_names[] = HIGH_REGISTER_NAMES;
86 const char *dregs_pair_names[] = DREGS_PAIR_NAMES;
87 const char *byte_reg_names[] = BYTE_REGISTER_NAMES;
89 static int arg_regs[] = FUNCTION_ARG_REGISTERS;
90 static int ret_regs[] = FUNCTION_RETURN_REGISTERS;
92 int splitting_for_sched, splitting_loops;
94 static void
95 bfin_globalize_label (FILE *stream, const char *name)
97 fputs (".global ", stream);
98 assemble_name (stream, name);
99 fputc (';',stream);
100 fputc ('\n',stream);
103 static void
104 output_file_start (void)
106 FILE *file = asm_out_file;
107 int i;
109 fprintf (file, ".file \"%s\";\n", LOCATION_FILE (input_location));
111 for (i = 0; arg_regs[i] >= 0; i++)
113 max_arg_registers = i; /* how many arg reg used */
116 /* Examine machine-dependent attributes of function type FUNTYPE and return its
117 type. See the definition of E_FUNKIND. */
119 static e_funkind
120 funkind (const_tree funtype)
122 tree attrs = TYPE_ATTRIBUTES (funtype);
123 if (lookup_attribute ("interrupt_handler", attrs))
124 return INTERRUPT_HANDLER;
125 else if (lookup_attribute ("exception_handler", attrs))
126 return EXCPT_HANDLER;
127 else if (lookup_attribute ("nmi_handler", attrs))
128 return NMI_HANDLER;
129 else
130 return SUBROUTINE;
133 /* Legitimize PIC addresses. If the address is already position-independent,
134 we return ORIG. Newly generated position-independent addresses go into a
135 reg. This is REG if nonzero, otherwise we allocate register(s) as
136 necessary. PICREG is the register holding the pointer to the PIC offset
137 table. */
139 static rtx
140 legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
142 rtx addr = orig;
143 rtx new_rtx = orig;
145 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
147 int unspec;
148 rtx tmp;
150 if (TARGET_ID_SHARED_LIBRARY)
151 unspec = UNSPEC_MOVE_PIC;
152 else if (GET_CODE (addr) == SYMBOL_REF
153 && SYMBOL_REF_FUNCTION_P (addr))
154 unspec = UNSPEC_FUNCDESC_GOT17M4;
155 else
156 unspec = UNSPEC_MOVE_FDPIC;
158 if (reg == 0)
160 gcc_assert (can_create_pseudo_p ());
161 reg = gen_reg_rtx (Pmode);
164 tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), unspec);
165 new_rtx = gen_const_mem (Pmode, gen_rtx_PLUS (Pmode, picreg, tmp));
167 emit_move_insn (reg, new_rtx);
168 if (picreg == pic_offset_table_rtx)
169 crtl->uses_pic_offset_table = 1;
170 return reg;
173 else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
175 rtx base;
177 if (GET_CODE (addr) == CONST)
179 addr = XEXP (addr, 0);
180 gcc_assert (GET_CODE (addr) == PLUS);
183 if (XEXP (addr, 0) == picreg)
184 return orig;
186 if (reg == 0)
188 gcc_assert (can_create_pseudo_p ());
189 reg = gen_reg_rtx (Pmode);
192 base = legitimize_pic_address (XEXP (addr, 0), reg, picreg);
193 addr = legitimize_pic_address (XEXP (addr, 1),
194 base == reg ? NULL_RTX : reg,
195 picreg);
197 if (GET_CODE (addr) == CONST_INT)
199 gcc_assert (! reload_in_progress && ! reload_completed);
200 addr = force_reg (Pmode, addr);
203 if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
205 base = gen_rtx_PLUS (Pmode, base, XEXP (addr, 0));
206 addr = XEXP (addr, 1);
209 return gen_rtx_PLUS (Pmode, base, addr);
212 return new_rtx;
215 /* Stack frame layout. */
217 /* For a given REGNO, determine whether it must be saved in the function
218 prologue. IS_INTHANDLER specifies whether we're generating a normal
219 prologue or an interrupt/exception one. */
220 static bool
221 must_save_p (bool is_inthandler, unsigned regno)
223 if (D_REGNO_P (regno))
225 bool is_eh_return_reg = false;
226 if (crtl->calls_eh_return)
228 unsigned j;
229 for (j = 0; ; j++)
231 unsigned test = EH_RETURN_DATA_REGNO (j);
232 if (test == INVALID_REGNUM)
233 break;
234 if (test == regno)
235 is_eh_return_reg = true;
239 return (is_eh_return_reg
240 || (df_regs_ever_live_p (regno)
241 && !fixed_regs[regno]
242 && (is_inthandler || !call_used_regs[regno])));
244 else if (P_REGNO_P (regno))
246 return ((df_regs_ever_live_p (regno)
247 && !fixed_regs[regno]
248 && (is_inthandler || !call_used_regs[regno]))
249 || (is_inthandler
250 && (ENABLE_WA_05000283 || ENABLE_WA_05000315)
251 && regno == REG_P5)
252 || (!TARGET_FDPIC
253 && regno == PIC_OFFSET_TABLE_REGNUM
254 && (crtl->uses_pic_offset_table
255 || (TARGET_ID_SHARED_LIBRARY && !crtl->is_leaf))));
257 else
258 return ((is_inthandler || !call_used_regs[regno])
259 && (df_regs_ever_live_p (regno)
260 || (!leaf_function_p () && call_used_regs[regno])));
264 /* Compute the number of DREGS to save with a push_multiple operation.
265 This could include registers that aren't modified in the function,
266 since push_multiple only takes a range of registers.
267 If IS_INTHANDLER, then everything that is live must be saved, even
268 if normally call-clobbered.
269 If CONSECUTIVE, return the number of registers we can save in one
270 instruction with a push/pop multiple instruction. */
272 static int
273 n_dregs_to_save (bool is_inthandler, bool consecutive)
275 int count = 0;
276 unsigned i;
278 for (i = REG_R7 + 1; i-- != REG_R0;)
280 if (must_save_p (is_inthandler, i))
281 count++;
282 else if (consecutive)
283 return count;
285 return count;
288 /* Like n_dregs_to_save, but compute number of PREGS to save. */
290 static int
291 n_pregs_to_save (bool is_inthandler, bool consecutive)
293 int count = 0;
294 unsigned i;
296 for (i = REG_P5 + 1; i-- != REG_P0;)
297 if (must_save_p (is_inthandler, i))
298 count++;
299 else if (consecutive)
300 return count;
301 return count;
304 /* Determine if we are going to save the frame pointer in the prologue. */
306 static bool
307 must_save_fp_p (void)
309 return df_regs_ever_live_p (REG_FP);
312 /* Determine if we are going to save the RETS register. */
313 static bool
314 must_save_rets_p (void)
316 return df_regs_ever_live_p (REG_RETS);
319 static bool
320 stack_frame_needed_p (void)
322 /* EH return puts a new return address into the frame using an
323 address relative to the frame pointer. */
324 if (crtl->calls_eh_return)
325 return true;
326 return frame_pointer_needed;
329 /* Emit code to save registers in the prologue. SAVEALL is nonzero if we
330 must save all registers; this is used for interrupt handlers.
331 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
332 this for an interrupt (or exception) handler. */
334 static void
335 expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler)
337 rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
338 rtx predec = gen_rtx_MEM (SImode, predec1);
339 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler, false);
340 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler, false);
341 int ndregs_consec = saveall ? 8 : n_dregs_to_save (is_inthandler, true);
342 int npregs_consec = saveall ? 6 : n_pregs_to_save (is_inthandler, true);
343 int dregno, pregno;
344 int total_consec = ndregs_consec + npregs_consec;
345 int i, d_to_save;
347 if (saveall || is_inthandler)
349 rtx_insn *insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
351 RTX_FRAME_RELATED_P (insn) = 1;
352 for (dregno = REG_LT0; dregno <= REG_LB1; dregno++)
353 if (! crtl->is_leaf
354 || cfun->machine->has_hardware_loops
355 || cfun->machine->has_loopreg_clobber
356 || (ENABLE_WA_05000257
357 && (dregno == REG_LC0 || dregno == REG_LC1)))
359 insn = emit_move_insn (predec, gen_rtx_REG (SImode, dregno));
360 RTX_FRAME_RELATED_P (insn) = 1;
364 if (total_consec != 0)
366 rtx_insn *insn;
367 rtx val = GEN_INT (-total_consec * 4);
368 rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_consec + 2));
370 XVECEXP (pat, 0, 0) = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, val),
371 UNSPEC_PUSH_MULTIPLE);
372 XVECEXP (pat, 0, total_consec + 1) = gen_rtx_SET (VOIDmode, spreg,
373 gen_rtx_PLUS (Pmode,
374 spreg,
375 val));
376 RTX_FRAME_RELATED_P (XVECEXP (pat, 0, total_consec + 1)) = 1;
377 d_to_save = ndregs_consec;
378 dregno = REG_R7 + 1 - ndregs_consec;
379 pregno = REG_P5 + 1 - npregs_consec;
380 for (i = 0; i < total_consec; i++)
382 rtx memref = gen_rtx_MEM (word_mode,
383 gen_rtx_PLUS (Pmode, spreg,
384 GEN_INT (- i * 4 - 4)));
385 rtx subpat;
386 if (d_to_save > 0)
388 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
389 dregno++));
390 d_to_save--;
392 else
394 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
395 pregno++));
397 XVECEXP (pat, 0, i + 1) = subpat;
398 RTX_FRAME_RELATED_P (subpat) = 1;
400 insn = emit_insn (pat);
401 RTX_FRAME_RELATED_P (insn) = 1;
404 for (dregno = REG_R0; ndregs != ndregs_consec; dregno++)
406 if (must_save_p (is_inthandler, dregno))
408 rtx_insn *insn =
409 emit_move_insn (predec, gen_rtx_REG (word_mode, dregno));
410 RTX_FRAME_RELATED_P (insn) = 1;
411 ndregs--;
414 for (pregno = REG_P0; npregs != npregs_consec; pregno++)
416 if (must_save_p (is_inthandler, pregno))
418 rtx_insn *insn =
419 emit_move_insn (predec, gen_rtx_REG (word_mode, pregno));
420 RTX_FRAME_RELATED_P (insn) = 1;
421 npregs--;
424 for (i = REG_P7 + 1; i < REG_CC; i++)
425 if (saveall
426 || (is_inthandler
427 && (df_regs_ever_live_p (i)
428 || (!leaf_function_p () && call_used_regs[i]))))
430 rtx_insn *insn;
431 if (i == REG_A0 || i == REG_A1)
432 insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1),
433 gen_rtx_REG (PDImode, i));
434 else
435 insn = emit_move_insn (predec, gen_rtx_REG (SImode, i));
436 RTX_FRAME_RELATED_P (insn) = 1;
440 /* Emit code to restore registers in the epilogue. SAVEALL is nonzero if we
441 must save all registers; this is used for interrupt handlers.
442 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
443 this for an interrupt (or exception) handler. */
445 static void
446 expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler)
448 rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
449 rtx postinc = gen_rtx_MEM (SImode, postinc1);
451 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler, false);
452 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler, false);
453 int ndregs_consec = saveall ? 8 : n_dregs_to_save (is_inthandler, true);
454 int npregs_consec = saveall ? 6 : n_pregs_to_save (is_inthandler, true);
455 int total_consec = ndregs_consec + npregs_consec;
456 int i, regno;
457 rtx_insn *insn;
459 /* A slightly crude technique to stop flow from trying to delete "dead"
460 insns. */
461 MEM_VOLATILE_P (postinc) = 1;
463 for (i = REG_CC - 1; i > REG_P7; i--)
464 if (saveall
465 || (is_inthandler
466 && (df_regs_ever_live_p (i)
467 || (!leaf_function_p () && call_used_regs[i]))))
469 if (i == REG_A0 || i == REG_A1)
471 rtx mem = gen_rtx_MEM (PDImode, postinc1);
472 MEM_VOLATILE_P (mem) = 1;
473 emit_move_insn (gen_rtx_REG (PDImode, i), mem);
475 else
476 emit_move_insn (gen_rtx_REG (SImode, i), postinc);
479 regno = REG_P5 - npregs_consec;
480 for (; npregs != npregs_consec; regno--)
482 if (must_save_p (is_inthandler, regno))
484 emit_move_insn (gen_rtx_REG (word_mode, regno), postinc);
485 npregs--;
488 regno = REG_R7 - ndregs_consec;
489 for (; ndregs != ndregs_consec; regno--)
491 if (must_save_p (is_inthandler, regno))
493 emit_move_insn (gen_rtx_REG (word_mode, regno), postinc);
494 ndregs--;
498 if (total_consec != 0)
500 rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_consec + 1));
501 XVECEXP (pat, 0, 0)
502 = gen_rtx_SET (VOIDmode, spreg,
503 gen_rtx_PLUS (Pmode, spreg,
504 GEN_INT (total_consec * 4)));
506 if (npregs_consec > 0)
507 regno = REG_P5 + 1;
508 else
509 regno = REG_R7 + 1;
511 for (i = 0; i < total_consec; i++)
513 rtx addr = (i > 0
514 ? gen_rtx_PLUS (Pmode, spreg, GEN_INT (i * 4))
515 : spreg);
516 rtx memref = gen_rtx_MEM (word_mode, addr);
518 regno--;
519 XVECEXP (pat, 0, i + 1)
520 = gen_rtx_SET (VOIDmode, gen_rtx_REG (word_mode, regno), memref);
522 if (npregs_consec > 0)
524 if (--npregs_consec == 0)
525 regno = REG_R7 + 1;
529 insn = emit_insn (pat);
530 RTX_FRAME_RELATED_P (insn) = 1;
532 if (saveall || is_inthandler)
534 for (regno = REG_LB1; regno >= REG_LT0; regno--)
535 if (! crtl->is_leaf
536 || cfun->machine->has_hardware_loops
537 || cfun->machine->has_loopreg_clobber
538 || (ENABLE_WA_05000257 && (regno == REG_LC0 || regno == REG_LC1)))
539 emit_move_insn (gen_rtx_REG (SImode, regno), postinc);
541 emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
545 /* Perform any needed actions needed for a function that is receiving a
546 variable number of arguments.
548 CUM is as above.
550 MODE and TYPE are the mode and type of the current parameter.
552 PRETEND_SIZE is a variable that should be set to the amount of stack
553 that must be pushed by the prolog to pretend that our caller pushed
556 Normally, this macro will push all remaining incoming registers on the
557 stack and set PRETEND_SIZE to the length of the registers pushed.
559 Blackfin specific :
560 - VDSP C compiler manual (our ABI) says that a variable args function
561 should save the R0, R1 and R2 registers in the stack.
562 - The caller will always leave space on the stack for the
563 arguments that are passed in registers, so we dont have
564 to leave any extra space.
565 - now, the vastart pointer can access all arguments from the stack. */
567 static void
568 setup_incoming_varargs (cumulative_args_t cum,
569 enum machine_mode mode ATTRIBUTE_UNUSED,
570 tree type ATTRIBUTE_UNUSED, int *pretend_size,
571 int no_rtl)
573 rtx mem;
574 int i;
576 if (no_rtl)
577 return;
579 /* The move for named arguments will be generated automatically by the
580 compiler. We need to generate the move rtx for the unnamed arguments
581 if they are in the first 3 words. We assume at least 1 named argument
582 exists, so we never generate [ARGP] = R0 here. */
584 for (i = get_cumulative_args (cum)->words + 1; i < max_arg_registers; i++)
586 mem = gen_rtx_MEM (Pmode,
587 plus_constant (Pmode, arg_pointer_rtx,
588 (i * UNITS_PER_WORD)));
589 emit_move_insn (mem, gen_rtx_REG (Pmode, i));
592 *pretend_size = 0;
595 /* Value should be nonzero if functions must have frame pointers.
596 Zero means the frame pointer need not be set up (and parms may
597 be accessed via the stack pointer) in functions that seem suitable. */
599 static bool
600 bfin_frame_pointer_required (void)
602 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
604 if (fkind != SUBROUTINE)
605 return true;
607 /* We turn on -fomit-frame-pointer if -momit-leaf-frame-pointer is used,
608 so we have to override it for non-leaf functions. */
609 if (TARGET_OMIT_LEAF_FRAME_POINTER && ! crtl->is_leaf)
610 return true;
612 return false;
615 /* Return the number of registers pushed during the prologue. */
617 static int
618 n_regs_saved_by_prologue (void)
620 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
621 bool is_inthandler = fkind != SUBROUTINE;
622 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
623 bool all = (lookup_attribute ("saveall", attrs) != NULL_TREE
624 || (is_inthandler && !crtl->is_leaf));
625 int ndregs = all ? 8 : n_dregs_to_save (is_inthandler, false);
626 int npregs = all ? 6 : n_pregs_to_save (is_inthandler, false);
627 int n = ndregs + npregs;
628 int i;
630 if (all || stack_frame_needed_p ())
631 n += 2;
632 else
634 if (must_save_fp_p ())
635 n++;
636 if (must_save_rets_p ())
637 n++;
640 if (fkind != SUBROUTINE || all)
642 /* Increment once for ASTAT. */
643 n++;
644 if (! crtl->is_leaf
645 || cfun->machine->has_hardware_loops
646 || cfun->machine->has_loopreg_clobber)
648 n += 6;
652 if (fkind != SUBROUTINE)
654 /* RETE/X/N. */
655 if (lookup_attribute ("nesting", attrs))
656 n++;
659 for (i = REG_P7 + 1; i < REG_CC; i++)
660 if (all
661 || (fkind != SUBROUTINE
662 && (df_regs_ever_live_p (i)
663 || (!leaf_function_p () && call_used_regs[i]))))
664 n += i == REG_A0 || i == REG_A1 ? 2 : 1;
666 return n;
669 /* Given FROM and TO register numbers, say whether this elimination is
670 allowed. Frame pointer elimination is automatically handled.
672 All other eliminations are valid. */
674 static bool
675 bfin_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
677 return (to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true);
680 /* Return the offset between two registers, one to be eliminated, and the other
681 its replacement, at the start of a routine. */
683 HOST_WIDE_INT
684 bfin_initial_elimination_offset (int from, int to)
686 HOST_WIDE_INT offset = 0;
688 if (from == ARG_POINTER_REGNUM)
689 offset = n_regs_saved_by_prologue () * 4;
691 if (to == STACK_POINTER_REGNUM)
693 if (crtl->outgoing_args_size >= FIXED_STACK_AREA)
694 offset += crtl->outgoing_args_size;
695 else if (crtl->outgoing_args_size)
696 offset += FIXED_STACK_AREA;
698 offset += get_frame_size ();
701 return offset;
704 /* Emit code to load a constant CONSTANT into register REG; setting
705 RTX_FRAME_RELATED_P on all insns we generate if RELATED is true.
706 Make sure that the insns we generate need not be split. */
708 static void
709 frame_related_constant_load (rtx reg, HOST_WIDE_INT constant, bool related)
711 rtx_insn *insn;
712 rtx cst = GEN_INT (constant);
714 if (constant >= -32768 && constant < 65536)
715 insn = emit_move_insn (reg, cst);
716 else
718 /* We don't call split_load_immediate here, since dwarf2out.c can get
719 confused about some of the more clever sequences it can generate. */
720 insn = emit_insn (gen_movsi_high (reg, cst));
721 if (related)
722 RTX_FRAME_RELATED_P (insn) = 1;
723 insn = emit_insn (gen_movsi_low (reg, reg, cst));
725 if (related)
726 RTX_FRAME_RELATED_P (insn) = 1;
729 /* Generate efficient code to add a value to a P register.
730 Set RTX_FRAME_RELATED_P on the generated insns if FRAME is nonzero.
731 EPILOGUE_P is zero if this function is called for prologue,
732 otherwise it's nonzero. And it's less than zero if this is for
733 sibcall epilogue. */
735 static void
736 add_to_reg (rtx reg, HOST_WIDE_INT value, int frame, int epilogue_p)
738 if (value == 0)
739 return;
741 /* Choose whether to use a sequence using a temporary register, or
742 a sequence with multiple adds. We can add a signed 7-bit value
743 in one instruction. */
744 if (value > 120 || value < -120)
746 rtx tmpreg;
747 rtx tmpreg2;
748 rtx_insn *insn;
750 tmpreg2 = NULL_RTX;
752 /* For prologue or normal epilogue, P1 can be safely used
753 as the temporary register. For sibcall epilogue, we try to find
754 a call used P register, which will be restored in epilogue.
755 If we cannot find such a P register, we have to use one I register
756 to help us. */
758 if (epilogue_p >= 0)
759 tmpreg = gen_rtx_REG (SImode, REG_P1);
760 else
762 int i;
763 for (i = REG_P0; i <= REG_P5; i++)
764 if ((df_regs_ever_live_p (i) && ! call_used_regs[i])
765 || (!TARGET_FDPIC
766 && i == PIC_OFFSET_TABLE_REGNUM
767 && (crtl->uses_pic_offset_table
768 || (TARGET_ID_SHARED_LIBRARY
769 && ! crtl->is_leaf))))
770 break;
771 if (i <= REG_P5)
772 tmpreg = gen_rtx_REG (SImode, i);
773 else
775 tmpreg = gen_rtx_REG (SImode, REG_P1);
776 tmpreg2 = gen_rtx_REG (SImode, REG_I0);
777 emit_move_insn (tmpreg2, tmpreg);
781 if (frame)
782 frame_related_constant_load (tmpreg, value, TRUE);
783 else
784 insn = emit_move_insn (tmpreg, GEN_INT (value));
786 insn = emit_insn (gen_addsi3 (reg, reg, tmpreg));
787 if (frame)
788 RTX_FRAME_RELATED_P (insn) = 1;
790 if (tmpreg2 != NULL_RTX)
791 emit_move_insn (tmpreg, tmpreg2);
793 else
796 int size = value;
797 rtx_insn *insn;
799 if (size > 60)
800 size = 60;
801 else if (size < -60)
802 /* We could use -62, but that would leave the stack unaligned, so
803 it's no good. */
804 size = -60;
806 insn = emit_insn (gen_addsi3 (reg, reg, GEN_INT (size)));
807 if (frame)
808 RTX_FRAME_RELATED_P (insn) = 1;
809 value -= size;
811 while (value != 0);
814 /* Generate a LINK insn for a frame sized FRAME_SIZE. If this constant
815 is too large, generate a sequence of insns that has the same effect.
816 SPREG contains (reg:SI REG_SP). */
818 static void
819 emit_link_insn (rtx spreg, HOST_WIDE_INT frame_size)
821 HOST_WIDE_INT link_size = frame_size;
822 rtx_insn *insn;
823 int i;
825 if (link_size > 262140)
826 link_size = 262140;
828 /* Use a LINK insn with as big a constant as possible, then subtract
829 any remaining size from the SP. */
830 insn = emit_insn (gen_link (GEN_INT (-8 - link_size)));
831 RTX_FRAME_RELATED_P (insn) = 1;
833 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
835 rtx set = XVECEXP (PATTERN (insn), 0, i);
836 gcc_assert (GET_CODE (set) == SET);
837 RTX_FRAME_RELATED_P (set) = 1;
840 frame_size -= link_size;
842 if (frame_size > 0)
844 /* Must use a call-clobbered PREG that isn't the static chain. */
845 rtx tmpreg = gen_rtx_REG (Pmode, REG_P1);
847 frame_related_constant_load (tmpreg, -frame_size, TRUE);
848 insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg));
849 RTX_FRAME_RELATED_P (insn) = 1;
853 /* Return the number of bytes we must reserve for outgoing arguments
854 in the current function's stack frame. */
856 static HOST_WIDE_INT
857 arg_area_size (void)
859 if (crtl->outgoing_args_size)
861 if (crtl->outgoing_args_size >= FIXED_STACK_AREA)
862 return crtl->outgoing_args_size;
863 else
864 return FIXED_STACK_AREA;
866 return 0;
869 /* Save RETS and FP, and allocate a stack frame. ALL is true if the
870 function must save all its registers (true only for certain interrupt
871 handlers). */
873 static void
874 do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all)
876 frame_size += arg_area_size ();
878 if (all
879 || stack_frame_needed_p ()
880 || (must_save_rets_p () && must_save_fp_p ()))
881 emit_link_insn (spreg, frame_size);
882 else
884 if (must_save_rets_p ())
886 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
887 gen_rtx_PRE_DEC (Pmode, spreg)),
888 bfin_rets_rtx);
889 rtx_insn *insn = emit_insn (pat);
890 RTX_FRAME_RELATED_P (insn) = 1;
892 if (must_save_fp_p ())
894 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
895 gen_rtx_PRE_DEC (Pmode, spreg)),
896 gen_rtx_REG (Pmode, REG_FP));
897 rtx_insn *insn = emit_insn (pat);
898 RTX_FRAME_RELATED_P (insn) = 1;
900 add_to_reg (spreg, -frame_size, 1, 0);
904 /* Like do_link, but used for epilogues to deallocate the stack frame.
905 EPILOGUE_P is zero if this function is called for prologue,
906 otherwise it's nonzero. And it's less than zero if this is for
907 sibcall epilogue. */
909 static void
910 do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all, int epilogue_p)
912 frame_size += arg_area_size ();
914 if (stack_frame_needed_p ())
915 emit_insn (gen_unlink ());
916 else
918 rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg));
920 add_to_reg (spreg, frame_size, 0, epilogue_p);
921 if (all || must_save_fp_p ())
923 rtx fpreg = gen_rtx_REG (Pmode, REG_FP);
924 emit_move_insn (fpreg, postinc);
925 emit_use (fpreg);
927 if (all || must_save_rets_p ())
929 emit_move_insn (bfin_rets_rtx, postinc);
930 emit_use (bfin_rets_rtx);
935 /* Generate a prologue suitable for a function of kind FKIND. This is
936 called for interrupt and exception handler prologues.
937 SPREG contains (reg:SI REG_SP). */
939 static void
940 expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind, bool all)
942 HOST_WIDE_INT frame_size = get_frame_size ();
943 rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
944 rtx predec = gen_rtx_MEM (SImode, predec1);
945 rtx_insn *insn;
946 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
947 tree kspisusp = lookup_attribute ("kspisusp", attrs);
949 if (kspisusp)
951 insn = emit_move_insn (spreg, gen_rtx_REG (Pmode, REG_USP));
952 RTX_FRAME_RELATED_P (insn) = 1;
955 /* We need space on the stack in case we need to save the argument
956 registers. */
957 if (fkind == EXCPT_HANDLER)
959 insn = emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (-12)));
960 RTX_FRAME_RELATED_P (insn) = 1;
963 /* If we're calling other functions, they won't save their call-clobbered
964 registers, so we must save everything here. */
965 if (!crtl->is_leaf)
966 all = true;
967 expand_prologue_reg_save (spreg, all, true);
969 if (ENABLE_WA_05000283 || ENABLE_WA_05000315)
971 rtx chipid = GEN_INT (trunc_int_for_mode (0xFFC00014, SImode));
972 rtx p5reg = gen_rtx_REG (Pmode, REG_P5);
973 emit_insn (gen_movbi (bfin_cc_rtx, const1_rtx));
974 emit_insn (gen_movsi_high (p5reg, chipid));
975 emit_insn (gen_movsi_low (p5reg, p5reg, chipid));
976 emit_insn (gen_dummy_load (p5reg, bfin_cc_rtx));
979 if (lookup_attribute ("nesting", attrs))
981 rtx srcreg = gen_rtx_REG (Pmode, ret_regs[fkind]);
982 insn = emit_move_insn (predec, srcreg);
983 RTX_FRAME_RELATED_P (insn) = 1;
986 do_link (spreg, frame_size, all);
988 if (fkind == EXCPT_HANDLER)
990 rtx r0reg = gen_rtx_REG (SImode, REG_R0);
991 rtx r1reg = gen_rtx_REG (SImode, REG_R1);
992 rtx r2reg = gen_rtx_REG (SImode, REG_R2);
994 emit_move_insn (r0reg, gen_rtx_REG (SImode, REG_SEQSTAT));
995 emit_insn (gen_ashrsi3 (r0reg, r0reg, GEN_INT (26)));
996 emit_insn (gen_ashlsi3 (r0reg, r0reg, GEN_INT (26)));
997 emit_move_insn (r1reg, spreg);
998 emit_move_insn (r2reg, gen_rtx_REG (Pmode, REG_FP));
999 emit_insn (gen_addsi3 (r2reg, r2reg, GEN_INT (8)));
1003 /* Generate an epilogue suitable for a function of kind FKIND. This is
1004 called for interrupt and exception handler epilogues.
1005 SPREG contains (reg:SI REG_SP). */
1007 static void
1008 expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind, bool all)
1010 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1011 rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
1012 rtx postinc = gen_rtx_MEM (SImode, postinc1);
1014 /* A slightly crude technique to stop flow from trying to delete "dead"
1015 insns. */
1016 MEM_VOLATILE_P (postinc) = 1;
1018 do_unlink (spreg, get_frame_size (), all, 1);
1020 if (lookup_attribute ("nesting", attrs))
1022 rtx srcreg = gen_rtx_REG (Pmode, ret_regs[fkind]);
1023 emit_move_insn (srcreg, postinc);
1026 /* If we're calling other functions, they won't save their call-clobbered
1027 registers, so we must save (and restore) everything here. */
1028 if (!crtl->is_leaf)
1029 all = true;
1031 expand_epilogue_reg_restore (spreg, all, true);
1033 /* Deallocate any space we left on the stack in case we needed to save the
1034 argument registers. */
1035 if (fkind == EXCPT_HANDLER)
1036 emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (12)));
1038 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, ret_regs[fkind])));
1041 /* Used while emitting the prologue to generate code to load the correct value
1042 into the PIC register, which is passed in DEST. */
1044 static rtx
1045 bfin_load_pic_reg (rtx dest)
1047 struct cgraph_local_info *i = NULL;
1048 rtx addr;
1050 i = cgraph_node::local_info (current_function_decl);
1052 /* Functions local to the translation unit don't need to reload the
1053 pic reg, since the caller always passes a usable one. */
1054 if (i && i->local)
1055 return pic_offset_table_rtx;
1057 if (global_options_set.x_bfin_library_id)
1058 addr = plus_constant (Pmode, pic_offset_table_rtx,
1059 -4 - bfin_library_id * 4);
1060 else
1061 addr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
1062 gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
1063 UNSPEC_LIBRARY_OFFSET));
1064 emit_insn (gen_movsi (dest, gen_rtx_MEM (Pmode, addr)));
1065 return dest;
1068 /* Generate RTL for the prologue of the current function. */
1070 void
1071 bfin_expand_prologue (void)
1073 HOST_WIDE_INT frame_size = get_frame_size ();
1074 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
1075 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1076 rtx pic_reg_loaded = NULL_RTX;
1077 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1078 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
1080 if (fkind != SUBROUTINE)
1082 expand_interrupt_handler_prologue (spreg, fkind, all);
1083 return;
1086 if (crtl->limit_stack
1087 || (TARGET_STACK_CHECK_L1
1088 && !DECL_NO_LIMIT_STACK (current_function_decl)))
1090 HOST_WIDE_INT offset
1091 = bfin_initial_elimination_offset (ARG_POINTER_REGNUM,
1092 STACK_POINTER_REGNUM);
1093 rtx lim = crtl->limit_stack ? stack_limit_rtx : NULL_RTX;
1094 rtx tmp = gen_rtx_REG (Pmode, REG_R3);
1095 rtx p2reg = gen_rtx_REG (Pmode, REG_P2);
1097 emit_move_insn (tmp, p2reg);
1098 if (!lim)
1100 emit_move_insn (p2reg, gen_int_mode (0xFFB00000, SImode));
1101 emit_move_insn (p2reg, gen_rtx_MEM (Pmode, p2reg));
1102 lim = p2reg;
1104 if (GET_CODE (lim) == SYMBOL_REF)
1106 if (TARGET_ID_SHARED_LIBRARY)
1108 rtx p1reg = gen_rtx_REG (Pmode, REG_P1);
1109 rtx val;
1110 pic_reg_loaded = bfin_load_pic_reg (p2reg);
1111 val = legitimize_pic_address (stack_limit_rtx, p1reg,
1112 pic_reg_loaded);
1113 emit_move_insn (p1reg, val);
1114 frame_related_constant_load (p2reg, offset, FALSE);
1115 emit_insn (gen_addsi3 (p2reg, p2reg, p1reg));
1116 lim = p2reg;
1118 else
1120 rtx limit = plus_constant (Pmode, lim, offset);
1121 emit_move_insn (p2reg, limit);
1122 lim = p2reg;
1125 else
1127 if (lim != p2reg)
1128 emit_move_insn (p2reg, lim);
1129 add_to_reg (p2reg, offset, 0, 0);
1130 lim = p2reg;
1132 emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim));
1133 emit_insn (gen_trapifcc ());
1134 emit_move_insn (p2reg, tmp);
1136 expand_prologue_reg_save (spreg, all, false);
1138 do_link (spreg, frame_size, all);
1140 if (TARGET_ID_SHARED_LIBRARY
1141 && !TARGET_SEP_DATA
1142 && (crtl->uses_pic_offset_table
1143 || !crtl->is_leaf))
1144 bfin_load_pic_reg (pic_offset_table_rtx);
1147 /* Generate RTL for the epilogue of the current function. NEED_RETURN is zero
1148 if this is for a sibcall. EH_RETURN is nonzero if we're expanding an
1149 eh_return pattern. SIBCALL_P is true if this is a sibcall epilogue,
1150 false otherwise. */
1152 void
1153 bfin_expand_epilogue (int need_return, int eh_return, bool sibcall_p)
1155 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
1156 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1157 int e = sibcall_p ? -1 : 1;
1158 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1159 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
1161 if (fkind != SUBROUTINE)
1163 expand_interrupt_handler_epilogue (spreg, fkind, all);
1164 return;
1167 do_unlink (spreg, get_frame_size (), all, e);
1169 expand_epilogue_reg_restore (spreg, all, false);
1171 /* Omit the return insn if this is for a sibcall. */
1172 if (! need_return)
1173 return;
1175 if (eh_return)
1176 emit_insn (gen_addsi3 (spreg, spreg, gen_rtx_REG (Pmode, REG_P2)));
1178 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, REG_RETS)));
1181 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
1184 bfin_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
1185 unsigned int new_reg)
1187 /* Interrupt functions can only use registers that have already been
1188 saved by the prologue, even if they would normally be
1189 call-clobbered. */
1191 if (funkind (TREE_TYPE (current_function_decl)) != SUBROUTINE
1192 && !df_regs_ever_live_p (new_reg))
1193 return 0;
1195 return 1;
1198 /* Implement TARGET_EXTRA_LIVE_ON_ENTRY. */
1199 static void
1200 bfin_extra_live_on_entry (bitmap regs)
1202 if (TARGET_FDPIC)
1203 bitmap_set_bit (regs, FDPIC_REGNO);
1206 /* Return the value of the return address for the frame COUNT steps up
1207 from the current frame, after the prologue.
1208 We punt for everything but the current frame by returning const0_rtx. */
1211 bfin_return_addr_rtx (int count)
1213 if (count != 0)
1214 return const0_rtx;
1216 return get_hard_reg_initial_val (Pmode, REG_RETS);
1219 static rtx
1220 bfin_delegitimize_address (rtx orig_x)
1222 rtx x = orig_x;
1224 if (GET_CODE (x) != MEM)
1225 return orig_x;
1227 x = XEXP (x, 0);
1228 if (GET_CODE (x) == PLUS
1229 && GET_CODE (XEXP (x, 1)) == UNSPEC
1230 && XINT (XEXP (x, 1), 1) == UNSPEC_MOVE_PIC
1231 && GET_CODE (XEXP (x, 0)) == REG
1232 && REGNO (XEXP (x, 0)) == PIC_OFFSET_TABLE_REGNUM)
1233 return XVECEXP (XEXP (x, 1), 0, 0);
1235 return orig_x;
1238 /* This predicate is used to compute the length of a load/store insn.
1239 OP is a MEM rtx, we return nonzero if its addressing mode requires a
1240 32-bit instruction. */
1243 effective_address_32bit_p (rtx op, enum machine_mode mode)
1245 HOST_WIDE_INT offset;
1247 mode = GET_MODE (op);
1248 op = XEXP (op, 0);
1250 if (GET_CODE (op) != PLUS)
1252 gcc_assert (REG_P (op) || GET_CODE (op) == POST_INC
1253 || GET_CODE (op) == PRE_DEC || GET_CODE (op) == POST_DEC);
1254 return 0;
1257 if (GET_CODE (XEXP (op, 1)) == UNSPEC)
1258 return 1;
1260 offset = INTVAL (XEXP (op, 1));
1262 /* All byte loads use a 16-bit offset. */
1263 if (GET_MODE_SIZE (mode) == 1)
1264 return 1;
1266 if (GET_MODE_SIZE (mode) == 4)
1268 /* Frame pointer relative loads can use a negative offset, all others
1269 are restricted to a small positive one. */
1270 if (XEXP (op, 0) == frame_pointer_rtx)
1271 return offset < -128 || offset > 60;
1272 return offset < 0 || offset > 60;
1275 /* Must be HImode now. */
1276 return offset < 0 || offset > 30;
1279 /* Returns true if X is a memory reference using an I register. */
1280 bool
1281 bfin_dsp_memref_p (rtx x)
1283 if (! MEM_P (x))
1284 return false;
1285 x = XEXP (x, 0);
1286 if (GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_INC
1287 || GET_CODE (x) == POST_DEC || GET_CODE (x) == PRE_DEC)
1288 x = XEXP (x, 0);
1289 return IREG_P (x);
1292 /* Return cost of the memory address ADDR.
1293 All addressing modes are equally cheap on the Blackfin. */
1295 static int
1296 bfin_address_cost (rtx addr ATTRIBUTE_UNUSED,
1297 enum machine_mode mode ATTRIBUTE_UNUSED,
1298 addr_space_t as ATTRIBUTE_UNUSED,
1299 bool speed ATTRIBUTE_UNUSED)
1301 return 1;
1304 /* Subroutine of print_operand; used to print a memory reference X to FILE. */
1306 void
1307 print_address_operand (FILE *file, rtx x)
1309 switch (GET_CODE (x))
1311 case PLUS:
1312 output_address (XEXP (x, 0));
1313 fprintf (file, "+");
1314 output_address (XEXP (x, 1));
1315 break;
1317 case PRE_DEC:
1318 fprintf (file, "--");
1319 output_address (XEXP (x, 0));
1320 break;
1321 case POST_INC:
1322 output_address (XEXP (x, 0));
1323 fprintf (file, "++");
1324 break;
1325 case POST_DEC:
1326 output_address (XEXP (x, 0));
1327 fprintf (file, "--");
1328 break;
1330 default:
1331 gcc_assert (GET_CODE (x) != MEM);
1332 print_operand (file, x, 0);
1333 break;
1337 /* Adding intp DImode support by Tony
1338 * -- Q: (low word)
1339 * -- R: (high word)
1342 void
1343 print_operand (FILE *file, rtx x, char code)
1345 enum machine_mode mode;
1347 if (code == '!')
1349 if (GET_MODE (current_output_insn) == SImode)
1350 fprintf (file, " ||");
1351 else
1352 fprintf (file, ";");
1353 return;
1356 mode = GET_MODE (x);
1358 switch (code)
1360 case 'j':
1361 switch (GET_CODE (x))
1363 case EQ:
1364 fprintf (file, "e");
1365 break;
1366 case NE:
1367 fprintf (file, "ne");
1368 break;
1369 case GT:
1370 fprintf (file, "g");
1371 break;
1372 case LT:
1373 fprintf (file, "l");
1374 break;
1375 case GE:
1376 fprintf (file, "ge");
1377 break;
1378 case LE:
1379 fprintf (file, "le");
1380 break;
1381 case GTU:
1382 fprintf (file, "g");
1383 break;
1384 case LTU:
1385 fprintf (file, "l");
1386 break;
1387 case GEU:
1388 fprintf (file, "ge");
1389 break;
1390 case LEU:
1391 fprintf (file, "le");
1392 break;
1393 default:
1394 output_operand_lossage ("invalid %%j value");
1396 break;
1398 case 'J': /* reverse logic */
1399 switch (GET_CODE(x))
1401 case EQ:
1402 fprintf (file, "ne");
1403 break;
1404 case NE:
1405 fprintf (file, "e");
1406 break;
1407 case GT:
1408 fprintf (file, "le");
1409 break;
1410 case LT:
1411 fprintf (file, "ge");
1412 break;
1413 case GE:
1414 fprintf (file, "l");
1415 break;
1416 case LE:
1417 fprintf (file, "g");
1418 break;
1419 case GTU:
1420 fprintf (file, "le");
1421 break;
1422 case LTU:
1423 fprintf (file, "ge");
1424 break;
1425 case GEU:
1426 fprintf (file, "l");
1427 break;
1428 case LEU:
1429 fprintf (file, "g");
1430 break;
1431 default:
1432 output_operand_lossage ("invalid %%J value");
1434 break;
1436 default:
1437 switch (GET_CODE (x))
1439 case REG:
1440 if (code == 'h')
1442 if (REGNO (x) < 32)
1443 fprintf (file, "%s", short_reg_names[REGNO (x)]);
1444 else
1445 output_operand_lossage ("invalid operand for code '%c'", code);
1447 else if (code == 'd')
1449 if (REGNO (x) < 32)
1450 fprintf (file, "%s", high_reg_names[REGNO (x)]);
1451 else
1452 output_operand_lossage ("invalid operand for code '%c'", code);
1454 else if (code == 'w')
1456 if (REGNO (x) == REG_A0 || REGNO (x) == REG_A1)
1457 fprintf (file, "%s.w", reg_names[REGNO (x)]);
1458 else
1459 output_operand_lossage ("invalid operand for code '%c'", code);
1461 else if (code == 'x')
1463 if (REGNO (x) == REG_A0 || REGNO (x) == REG_A1)
1464 fprintf (file, "%s.x", reg_names[REGNO (x)]);
1465 else
1466 output_operand_lossage ("invalid operand for code '%c'", code);
1468 else if (code == 'v')
1470 if (REGNO (x) == REG_A0)
1471 fprintf (file, "AV0");
1472 else if (REGNO (x) == REG_A1)
1473 fprintf (file, "AV1");
1474 else
1475 output_operand_lossage ("invalid operand for code '%c'", code);
1477 else if (code == 'D')
1479 if (D_REGNO_P (REGNO (x)))
1480 fprintf (file, "%s", dregs_pair_names[REGNO (x)]);
1481 else
1482 output_operand_lossage ("invalid operand for code '%c'", code);
1484 else if (code == 'H')
1486 if ((mode == DImode || mode == DFmode) && REG_P (x))
1487 fprintf (file, "%s", reg_names[REGNO (x) + 1]);
1488 else
1489 output_operand_lossage ("invalid operand for code '%c'", code);
1491 else if (code == 'T')
1493 if (D_REGNO_P (REGNO (x)))
1494 fprintf (file, "%s", byte_reg_names[REGNO (x)]);
1495 else
1496 output_operand_lossage ("invalid operand for code '%c'", code);
1498 else
1499 fprintf (file, "%s", reg_names[REGNO (x)]);
1500 break;
1502 case MEM:
1503 fputc ('[', file);
1504 x = XEXP (x,0);
1505 print_address_operand (file, x);
1506 fputc (']', file);
1507 break;
1509 case CONST_INT:
1510 if (code == 'M')
1512 switch (INTVAL (x))
1514 case MACFLAG_NONE:
1515 break;
1516 case MACFLAG_FU:
1517 fputs ("(FU)", file);
1518 break;
1519 case MACFLAG_T:
1520 fputs ("(T)", file);
1521 break;
1522 case MACFLAG_TFU:
1523 fputs ("(TFU)", file);
1524 break;
1525 case MACFLAG_W32:
1526 fputs ("(W32)", file);
1527 break;
1528 case MACFLAG_IS:
1529 fputs ("(IS)", file);
1530 break;
1531 case MACFLAG_IU:
1532 fputs ("(IU)", file);
1533 break;
1534 case MACFLAG_IH:
1535 fputs ("(IH)", file);
1536 break;
1537 case MACFLAG_M:
1538 fputs ("(M)", file);
1539 break;
1540 case MACFLAG_IS_M:
1541 fputs ("(IS,M)", file);
1542 break;
1543 case MACFLAG_ISS2:
1544 fputs ("(ISS2)", file);
1545 break;
1546 case MACFLAG_S2RND:
1547 fputs ("(S2RND)", file);
1548 break;
1549 default:
1550 gcc_unreachable ();
1552 break;
1554 else if (code == 'b')
1556 if (INTVAL (x) == 0)
1557 fputs ("+=", file);
1558 else if (INTVAL (x) == 1)
1559 fputs ("-=", file);
1560 else
1561 gcc_unreachable ();
1562 break;
1564 /* Moves to half registers with d or h modifiers always use unsigned
1565 constants. */
1566 else if (code == 'd')
1567 x = GEN_INT ((INTVAL (x) >> 16) & 0xffff);
1568 else if (code == 'h')
1569 x = GEN_INT (INTVAL (x) & 0xffff);
1570 else if (code == 'N')
1571 x = GEN_INT (-INTVAL (x));
1572 else if (code == 'X')
1573 x = GEN_INT (exact_log2 (0xffffffff & INTVAL (x)));
1574 else if (code == 'Y')
1575 x = GEN_INT (exact_log2 (0xffffffff & ~INTVAL (x)));
1576 else if (code == 'Z')
1577 /* Used for LINK insns. */
1578 x = GEN_INT (-8 - INTVAL (x));
1580 /* fall through */
1582 case SYMBOL_REF:
1583 output_addr_const (file, x);
1584 break;
1586 case CONST_DOUBLE:
1587 output_operand_lossage ("invalid const_double operand");
1588 break;
1590 case UNSPEC:
1591 switch (XINT (x, 1))
1593 case UNSPEC_MOVE_PIC:
1594 output_addr_const (file, XVECEXP (x, 0, 0));
1595 fprintf (file, "@GOT");
1596 break;
1598 case UNSPEC_MOVE_FDPIC:
1599 output_addr_const (file, XVECEXP (x, 0, 0));
1600 fprintf (file, "@GOT17M4");
1601 break;
1603 case UNSPEC_FUNCDESC_GOT17M4:
1604 output_addr_const (file, XVECEXP (x, 0, 0));
1605 fprintf (file, "@FUNCDESC_GOT17M4");
1606 break;
1608 case UNSPEC_LIBRARY_OFFSET:
1609 fprintf (file, "_current_shared_library_p5_offset_");
1610 break;
1612 default:
1613 gcc_unreachable ();
1615 break;
1617 default:
1618 output_addr_const (file, x);
1623 /* Argument support functions. */
1625 /* Initialize a variable CUM of type CUMULATIVE_ARGS
1626 for a call to a function whose data type is FNTYPE.
1627 For a library call, FNTYPE is 0.
1628 VDSP C Compiler manual, our ABI says that
1629 first 3 words of arguments will use R0, R1 and R2.
1632 void
1633 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
1634 rtx libname ATTRIBUTE_UNUSED)
1636 static CUMULATIVE_ARGS zero_cum;
1638 *cum = zero_cum;
1640 /* Set up the number of registers to use for passing arguments. */
1642 cum->nregs = max_arg_registers;
1643 cum->arg_regs = arg_regs;
1645 cum->call_cookie = CALL_NORMAL;
1646 /* Check for a longcall attribute. */
1647 if (fntype && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype)))
1648 cum->call_cookie |= CALL_SHORT;
1649 else if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)))
1650 cum->call_cookie |= CALL_LONG;
1652 return;
1655 /* Update the data in CUM to advance over an argument
1656 of mode MODE and data type TYPE.
1657 (TYPE is null for libcalls where that information may not be available.) */
1659 static void
1660 bfin_function_arg_advance (cumulative_args_t cum_v, enum machine_mode mode,
1661 const_tree type, bool named ATTRIBUTE_UNUSED)
1663 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
1664 int count, bytes, words;
1666 bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1667 words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1669 cum->words += words;
1670 cum->nregs -= words;
1672 if (cum->nregs <= 0)
1674 cum->nregs = 0;
1675 cum->arg_regs = NULL;
1677 else
1679 for (count = 1; count <= words; count++)
1680 cum->arg_regs++;
1683 return;
1686 /* Define where to put the arguments to a function.
1687 Value is zero to push the argument on the stack,
1688 or a hard register in which to store the argument.
1690 MODE is the argument's machine mode.
1691 TYPE is the data type of the argument (as a tree).
1692 This is null for libcalls where that information may
1693 not be available.
1694 CUM is a variable of type CUMULATIVE_ARGS which gives info about
1695 the preceding args and about the function being called.
1696 NAMED is nonzero if this argument is a named parameter
1697 (otherwise it is an extra parameter matching an ellipsis). */
1699 static rtx
1700 bfin_function_arg (cumulative_args_t cum_v, enum machine_mode mode,
1701 const_tree type, bool named ATTRIBUTE_UNUSED)
1703 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
1704 int bytes
1705 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1707 if (mode == VOIDmode)
1708 /* Compute operand 2 of the call insn. */
1709 return GEN_INT (cum->call_cookie);
1711 if (bytes == -1)
1712 return NULL_RTX;
1714 if (cum->nregs)
1715 return gen_rtx_REG (mode, *(cum->arg_regs));
1717 return NULL_RTX;
1720 /* For an arg passed partly in registers and partly in memory,
1721 this is the number of bytes passed in registers.
1722 For args passed entirely in registers or entirely in memory, zero.
1724 Refer VDSP C Compiler manual, our ABI.
1725 First 3 words are in registers. So, if an argument is larger
1726 than the registers available, it will span the register and
1727 stack. */
1729 static int
1730 bfin_arg_partial_bytes (cumulative_args_t cum, enum machine_mode mode,
1731 tree type ATTRIBUTE_UNUSED,
1732 bool named ATTRIBUTE_UNUSED)
1734 int bytes
1735 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1736 int bytes_left = get_cumulative_args (cum)->nregs * UNITS_PER_WORD;
1738 if (bytes == -1)
1739 return 0;
1741 if (bytes_left == 0)
1742 return 0;
1743 if (bytes > bytes_left)
1744 return bytes_left;
1745 return 0;
1748 /* Variable sized types are passed by reference. */
1750 static bool
1751 bfin_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
1752 enum machine_mode mode ATTRIBUTE_UNUSED,
1753 const_tree type, bool named ATTRIBUTE_UNUSED)
1755 return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
1758 /* Decide whether a type should be returned in memory (true)
1759 or in a register (false). This is called by the macro
1760 TARGET_RETURN_IN_MEMORY. */
1762 static bool
1763 bfin_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
1765 int size = int_size_in_bytes (type);
1766 return size > 2 * UNITS_PER_WORD || size == -1;
1769 /* Register in which address to store a structure value
1770 is passed to a function. */
1771 static rtx
1772 bfin_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
1773 int incoming ATTRIBUTE_UNUSED)
1775 return gen_rtx_REG (Pmode, REG_P0);
1778 /* Return true when register may be used to pass function parameters. */
1780 bool
1781 function_arg_regno_p (int n)
1783 int i;
1784 for (i = 0; arg_regs[i] != -1; i++)
1785 if (n == arg_regs[i])
1786 return true;
1787 return false;
1790 /* Returns 1 if OP contains a symbol reference */
1793 symbolic_reference_mentioned_p (rtx op)
1795 register const char *fmt;
1796 register int i;
1798 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
1799 return 1;
1801 fmt = GET_RTX_FORMAT (GET_CODE (op));
1802 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
1804 if (fmt[i] == 'E')
1806 register int j;
1808 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
1809 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
1810 return 1;
1813 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
1814 return 1;
1817 return 0;
1820 /* Decide whether we can make a sibling call to a function. DECL is the
1821 declaration of the function being targeted by the call and EXP is the
1822 CALL_EXPR representing the call. */
1824 static bool
1825 bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
1826 tree exp ATTRIBUTE_UNUSED)
1828 struct cgraph_local_info *this_func, *called_func;
1829 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1830 if (fkind != SUBROUTINE)
1831 return false;
1832 if (!TARGET_ID_SHARED_LIBRARY || TARGET_SEP_DATA)
1833 return true;
1835 /* When compiling for ID shared libraries, can't sibcall a local function
1836 from a non-local function, because the local function thinks it does
1837 not need to reload P5 in the prologue, but the sibcall wil pop P5 in the
1838 sibcall epilogue, and we end up with the wrong value in P5. */
1840 if (!decl)
1841 /* Not enough information. */
1842 return false;
1844 this_func = cgraph_node::local_info (current_function_decl);
1845 called_func = cgraph_node::local_info (decl);
1846 if (!called_func)
1847 return false;
1848 return !called_func->local || this_func->local;
1851 /* Write a template for a trampoline to F. */
1853 static void
1854 bfin_asm_trampoline_template (FILE *f)
1856 if (TARGET_FDPIC)
1858 fprintf (f, "\t.dd\t0x00000000\n"); /* 0 */
1859 fprintf (f, "\t.dd\t0x00000000\n"); /* 0 */
1860 fprintf (f, "\t.dd\t0x0000e109\n"); /* p1.l = fn low */
1861 fprintf (f, "\t.dd\t0x0000e149\n"); /* p1.h = fn high */
1862 fprintf (f, "\t.dd\t0x0000e10a\n"); /* p2.l = sc low */
1863 fprintf (f, "\t.dd\t0x0000e14a\n"); /* p2.h = sc high */
1864 fprintf (f, "\t.dw\t0xac4b\n"); /* p3 = [p1 + 4] */
1865 fprintf (f, "\t.dw\t0x9149\n"); /* p1 = [p1] */
1866 fprintf (f, "\t.dw\t0x0051\n"); /* jump (p1)*/
1868 else
1870 fprintf (f, "\t.dd\t0x0000e109\n"); /* p1.l = fn low */
1871 fprintf (f, "\t.dd\t0x0000e149\n"); /* p1.h = fn high */
1872 fprintf (f, "\t.dd\t0x0000e10a\n"); /* p2.l = sc low */
1873 fprintf (f, "\t.dd\t0x0000e14a\n"); /* p2.h = sc high */
1874 fprintf (f, "\t.dw\t0x0051\n"); /* jump (p1)*/
1878 /* Emit RTL insns to initialize the variable parts of a trampoline at
1879 M_TRAMP. FNDECL is the target function. CHAIN_VALUE is an RTX for
1880 the static chain value for the function. */
1882 static void
1883 bfin_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
1885 rtx t1 = copy_to_reg (XEXP (DECL_RTL (fndecl), 0));
1886 rtx t2 = copy_to_reg (chain_value);
1887 rtx mem;
1888 int i = 0;
1890 emit_block_move (m_tramp, assemble_trampoline_template (),
1891 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
1893 if (TARGET_FDPIC)
1895 rtx a = force_reg (Pmode, plus_constant (Pmode, XEXP (m_tramp, 0), 8));
1896 mem = adjust_address (m_tramp, Pmode, 0);
1897 emit_move_insn (mem, a);
1898 i = 8;
1901 mem = adjust_address (m_tramp, HImode, i + 2);
1902 emit_move_insn (mem, gen_lowpart (HImode, t1));
1903 emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16)));
1904 mem = adjust_address (m_tramp, HImode, i + 6);
1905 emit_move_insn (mem, gen_lowpart (HImode, t1));
1907 mem = adjust_address (m_tramp, HImode, i + 10);
1908 emit_move_insn (mem, gen_lowpart (HImode, t2));
1909 emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16)));
1910 mem = adjust_address (m_tramp, HImode, i + 14);
1911 emit_move_insn (mem, gen_lowpart (HImode, t2));
1914 /* Emit insns to move operands[1] into operands[0]. */
1916 void
1917 emit_pic_move (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
1919 rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
1921 gcc_assert (!TARGET_FDPIC || !(reload_in_progress || reload_completed));
1922 if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
1923 operands[1] = force_reg (SImode, operands[1]);
1924 else
1925 operands[1] = legitimize_pic_address (operands[1], temp,
1926 TARGET_FDPIC ? OUR_FDPIC_REG
1927 : pic_offset_table_rtx);
1930 /* Expand a move operation in mode MODE. The operands are in OPERANDS.
1931 Returns true if no further code must be generated, false if the caller
1932 should generate an insn to move OPERANDS[1] to OPERANDS[0]. */
1934 bool
1935 expand_move (rtx *operands, enum machine_mode mode)
1937 rtx op = operands[1];
1938 if ((TARGET_ID_SHARED_LIBRARY || TARGET_FDPIC)
1939 && SYMBOLIC_CONST (op))
1940 emit_pic_move (operands, mode);
1941 else if (mode == SImode && GET_CODE (op) == CONST
1942 && GET_CODE (XEXP (op, 0)) == PLUS
1943 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
1944 && !targetm.legitimate_constant_p (mode, op))
1946 rtx dest = operands[0];
1947 rtx op0, op1;
1948 gcc_assert (!reload_in_progress && !reload_completed);
1949 op = XEXP (op, 0);
1950 op0 = force_reg (mode, XEXP (op, 0));
1951 op1 = XEXP (op, 1);
1952 if (!insn_data[CODE_FOR_addsi3].operand[2].predicate (op1, mode))
1953 op1 = force_reg (mode, op1);
1954 if (GET_CODE (dest) == MEM)
1955 dest = gen_reg_rtx (mode);
1956 emit_insn (gen_addsi3 (dest, op0, op1));
1957 if (dest == operands[0])
1958 return true;
1959 operands[1] = dest;
1961 /* Don't generate memory->memory or constant->memory moves, go through a
1962 register */
1963 else if ((reload_in_progress | reload_completed) == 0
1964 && GET_CODE (operands[0]) == MEM
1965 && GET_CODE (operands[1]) != REG)
1966 operands[1] = force_reg (mode, operands[1]);
1967 return false;
1970 /* Split one or more DImode RTL references into pairs of SImode
1971 references. The RTL can be REG, offsettable MEM, integer constant, or
1972 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
1973 split and "num" is its length. lo_half and hi_half are output arrays
1974 that parallel "operands". */
1976 void
1977 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
1979 while (num--)
1981 rtx op = operands[num];
1983 /* simplify_subreg refuse to split volatile memory addresses,
1984 but we still have to handle it. */
1985 if (GET_CODE (op) == MEM)
1987 lo_half[num] = adjust_address (op, SImode, 0);
1988 hi_half[num] = adjust_address (op, SImode, 4);
1990 else
1992 lo_half[num] = simplify_gen_subreg (SImode, op,
1993 GET_MODE (op) == VOIDmode
1994 ? DImode : GET_MODE (op), 0);
1995 hi_half[num] = simplify_gen_subreg (SImode, op,
1996 GET_MODE (op) == VOIDmode
1997 ? DImode : GET_MODE (op), 4);
2002 bool
2003 bfin_longcall_p (rtx op, int call_cookie)
2005 gcc_assert (GET_CODE (op) == SYMBOL_REF);
2006 if (SYMBOL_REF_WEAK (op))
2007 return 1;
2008 if (call_cookie & CALL_SHORT)
2009 return 0;
2010 if (call_cookie & CALL_LONG)
2011 return 1;
2012 if (TARGET_LONG_CALLS)
2013 return 1;
2014 return 0;
2017 /* Expand a call instruction. FNADDR is the call target, RETVAL the return value.
2018 COOKIE is a CONST_INT holding the call_cookie prepared init_cumulative_args.
2019 SIBCALL is nonzero if this is a sibling call. */
2021 void
2022 bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
2024 rtx use = NULL, call;
2025 rtx callee = XEXP (fnaddr, 0);
2026 int nelts = 3;
2027 rtx pat;
2028 rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REGNO);
2029 rtx retsreg = gen_rtx_REG (Pmode, REG_RETS);
2030 int n;
2032 /* In an untyped call, we can get NULL for operand 2. */
2033 if (cookie == NULL_RTX)
2034 cookie = const0_rtx;
2036 /* Static functions and indirect calls don't need the pic register. */
2037 if (!TARGET_FDPIC && flag_pic
2038 && GET_CODE (callee) == SYMBOL_REF
2039 && !SYMBOL_REF_LOCAL_P (callee))
2040 use_reg (&use, pic_offset_table_rtx);
2042 if (TARGET_FDPIC)
2044 int caller_in_sram, callee_in_sram;
2046 /* 0 is not in sram, 1 is in L1 sram, 2 is in L2 sram. */
2047 caller_in_sram = callee_in_sram = 0;
2049 if (lookup_attribute ("l1_text",
2050 DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE)
2051 caller_in_sram = 1;
2052 else if (lookup_attribute ("l2",
2053 DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE)
2054 caller_in_sram = 2;
2056 if (GET_CODE (callee) == SYMBOL_REF
2057 && SYMBOL_REF_DECL (callee) && DECL_P (SYMBOL_REF_DECL (callee)))
2059 if (lookup_attribute
2060 ("l1_text",
2061 DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE)
2062 callee_in_sram = 1;
2063 else if (lookup_attribute
2064 ("l2",
2065 DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE)
2066 callee_in_sram = 2;
2069 if (GET_CODE (callee) != SYMBOL_REF
2070 || bfin_longcall_p (callee, INTVAL (cookie))
2071 || (GET_CODE (callee) == SYMBOL_REF
2072 && !SYMBOL_REF_LOCAL_P (callee)
2073 && TARGET_INLINE_PLT)
2074 || caller_in_sram != callee_in_sram
2075 || (caller_in_sram && callee_in_sram
2076 && (GET_CODE (callee) != SYMBOL_REF
2077 || !SYMBOL_REF_LOCAL_P (callee))))
2079 rtx addr = callee;
2080 if (! address_operand (addr, Pmode))
2081 addr = force_reg (Pmode, addr);
2083 fnaddr = gen_reg_rtx (SImode);
2084 emit_insn (gen_load_funcdescsi (fnaddr, addr));
2085 fnaddr = gen_rtx_MEM (Pmode, fnaddr);
2087 picreg = gen_reg_rtx (SImode);
2088 emit_insn (gen_load_funcdescsi (picreg,
2089 plus_constant (Pmode, addr, 4)));
2092 nelts++;
2094 else if ((!register_no_elim_operand (callee, Pmode)
2095 && GET_CODE (callee) != SYMBOL_REF)
2096 || (GET_CODE (callee) == SYMBOL_REF
2097 && ((TARGET_ID_SHARED_LIBRARY && !TARGET_LEAF_ID_SHARED_LIBRARY)
2098 || bfin_longcall_p (callee, INTVAL (cookie)))))
2100 callee = copy_to_mode_reg (Pmode, callee);
2101 fnaddr = gen_rtx_MEM (Pmode, callee);
2103 call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
2105 if (retval)
2106 call = gen_rtx_SET (VOIDmode, retval, call);
2108 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nelts));
2109 n = 0;
2110 XVECEXP (pat, 0, n++) = call;
2111 if (TARGET_FDPIC)
2112 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, picreg);
2113 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie);
2114 if (sibcall)
2115 XVECEXP (pat, 0, n++) = ret_rtx;
2116 else
2117 XVECEXP (pat, 0, n++) = gen_rtx_CLOBBER (VOIDmode, retsreg);
2118 call = emit_call_insn (pat);
2119 if (use)
2120 CALL_INSN_FUNCTION_USAGE (call) = use;
2123 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
2126 hard_regno_mode_ok (int regno, enum machine_mode mode)
2128 /* Allow only dregs to store value of mode HI or QI */
2129 enum reg_class rclass = REGNO_REG_CLASS (regno);
2131 if (mode == CCmode)
2132 return 0;
2134 if (mode == V2HImode)
2135 return D_REGNO_P (regno);
2136 if (rclass == CCREGS)
2137 return mode == BImode;
2138 if (mode == PDImode || mode == V2PDImode)
2139 return regno == REG_A0 || regno == REG_A1;
2141 /* Allow all normal 32-bit regs, except REG_M3, in case regclass ever comes
2142 up with a bad register class (such as ALL_REGS) for DImode. */
2143 if (mode == DImode)
2144 return regno < REG_M3;
2146 if (mode == SImode
2147 && TEST_HARD_REG_BIT (reg_class_contents[PROLOGUE_REGS], regno))
2148 return 1;
2150 return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno);
2153 /* Implements target hook vector_mode_supported_p. */
2155 static bool
2156 bfin_vector_mode_supported_p (enum machine_mode mode)
2158 return mode == V2HImode;
2161 /* Worker function for TARGET_REGISTER_MOVE_COST. */
2163 static int
2164 bfin_register_move_cost (enum machine_mode mode,
2165 reg_class_t class1, reg_class_t class2)
2167 /* These need secondary reloads, so they're more expensive. */
2168 if ((class1 == CCREGS && !reg_class_subset_p (class2, DREGS))
2169 || (class2 == CCREGS && !reg_class_subset_p (class1, DREGS)))
2170 return 4;
2172 /* If optimizing for size, always prefer reg-reg over reg-memory moves. */
2173 if (optimize_size)
2174 return 2;
2176 if (GET_MODE_CLASS (mode) == MODE_INT)
2178 /* Discourage trying to use the accumulators. */
2179 if (TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A0)
2180 || TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A1)
2181 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A0)
2182 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A1))
2183 return 20;
2185 return 2;
2188 /* Worker function for TARGET_MEMORY_MOVE_COST.
2190 ??? In theory L1 memory has single-cycle latency. We should add a switch
2191 that tells the compiler whether we expect to use only L1 memory for the
2192 program; it'll make the costs more accurate. */
2194 static int
2195 bfin_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
2196 reg_class_t rclass,
2197 bool in ATTRIBUTE_UNUSED)
2199 /* Make memory accesses slightly more expensive than any register-register
2200 move. Also, penalize non-DP registers, since they need secondary
2201 reloads to load and store. */
2202 if (! reg_class_subset_p (rclass, DPREGS))
2203 return 10;
2205 return 8;
2208 /* Inform reload about cases where moving X with a mode MODE to a register in
2209 RCLASS requires an extra scratch register. Return the class needed for the
2210 scratch register. */
2212 static reg_class_t
2213 bfin_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
2214 enum machine_mode mode, secondary_reload_info *sri)
2216 /* If we have HImode or QImode, we can only use DREGS as secondary registers;
2217 in most other cases we can also use PREGS. */
2218 enum reg_class default_class = GET_MODE_SIZE (mode) >= 4 ? DPREGS : DREGS;
2219 enum reg_class x_class = NO_REGS;
2220 enum rtx_code code = GET_CODE (x);
2221 enum reg_class rclass = (enum reg_class) rclass_i;
2223 if (code == SUBREG)
2224 x = SUBREG_REG (x), code = GET_CODE (x);
2225 if (REG_P (x))
2227 int regno = REGNO (x);
2228 if (regno >= FIRST_PSEUDO_REGISTER)
2229 regno = reg_renumber[regno];
2231 if (regno == -1)
2232 code = MEM;
2233 else
2234 x_class = REGNO_REG_CLASS (regno);
2237 /* We can be asked to reload (plus (FP) (large_constant)) into a DREG.
2238 This happens as a side effect of register elimination, and we need
2239 a scratch register to do it. */
2240 if (fp_plus_const_operand (x, mode))
2242 rtx op2 = XEXP (x, 1);
2243 int large_constant_p = ! satisfies_constraint_Ks7 (op2);
2245 if (rclass == PREGS || rclass == PREGS_CLOBBERED)
2246 return NO_REGS;
2247 /* If destination is a DREG, we can do this without a scratch register
2248 if the constant is valid for an add instruction. */
2249 if ((rclass == DREGS || rclass == DPREGS)
2250 && ! large_constant_p)
2251 return NO_REGS;
2252 /* Reloading to anything other than a DREG? Use a PREG scratch
2253 register. */
2254 sri->icode = CODE_FOR_reload_insi;
2255 return NO_REGS;
2258 /* Data can usually be moved freely between registers of most classes.
2259 AREGS are an exception; they can only move to or from another register
2260 in AREGS or one in DREGS. They can also be assigned the constant 0. */
2261 if (x_class == AREGS || x_class == EVEN_AREGS || x_class == ODD_AREGS)
2262 return (rclass == DREGS || rclass == AREGS || rclass == EVEN_AREGS
2263 || rclass == ODD_AREGS
2264 ? NO_REGS : DREGS);
2266 if (rclass == AREGS || rclass == EVEN_AREGS || rclass == ODD_AREGS)
2268 if (code == MEM)
2270 sri->icode = in_p ? CODE_FOR_reload_inpdi : CODE_FOR_reload_outpdi;
2271 return NO_REGS;
2274 if (x != const0_rtx && x_class != DREGS)
2276 return DREGS;
2278 else
2279 return NO_REGS;
2282 /* CCREGS can only be moved from/to DREGS. */
2283 if (rclass == CCREGS && x_class != DREGS)
2284 return DREGS;
2285 if (x_class == CCREGS && rclass != DREGS)
2286 return DREGS;
2288 /* All registers other than AREGS can load arbitrary constants. The only
2289 case that remains is MEM. */
2290 if (code == MEM)
2291 if (! reg_class_subset_p (rclass, default_class))
2292 return default_class;
2294 return NO_REGS;
2297 /* Implement TARGET_CLASS_LIKELY_SPILLED_P. */
2299 static bool
2300 bfin_class_likely_spilled_p (reg_class_t rclass)
2302 switch (rclass)
2304 case PREGS_CLOBBERED:
2305 case PROLOGUE_REGS:
2306 case P0REGS:
2307 case D0REGS:
2308 case D1REGS:
2309 case D2REGS:
2310 case CCREGS:
2311 return true;
2313 default:
2314 break;
2317 return false;
2320 static struct machine_function *
2321 bfin_init_machine_status (void)
2323 return ggc_cleared_alloc<machine_function> ();
2326 /* Implement the TARGET_OPTION_OVERRIDE hook. */
2328 static void
2329 bfin_option_override (void)
2331 /* If processor type is not specified, enable all workarounds. */
2332 if (bfin_cpu_type == BFIN_CPU_UNKNOWN)
2334 int i;
2336 for (i = 0; bfin_cpus[i].name != NULL; i++)
2337 bfin_workarounds |= bfin_cpus[i].workarounds;
2339 bfin_si_revision = 0xffff;
2342 if (bfin_csync_anomaly == 1)
2343 bfin_workarounds |= WA_SPECULATIVE_SYNCS;
2344 else if (bfin_csync_anomaly == 0)
2345 bfin_workarounds &= ~WA_SPECULATIVE_SYNCS;
2347 if (bfin_specld_anomaly == 1)
2348 bfin_workarounds |= WA_SPECULATIVE_LOADS;
2349 else if (bfin_specld_anomaly == 0)
2350 bfin_workarounds &= ~WA_SPECULATIVE_LOADS;
2352 if (TARGET_OMIT_LEAF_FRAME_POINTER)
2353 flag_omit_frame_pointer = 1;
2355 #ifdef SUBTARGET_FDPIC_NOT_SUPPORTED
2356 if (TARGET_FDPIC)
2357 error ("-mfdpic is not supported, please use a bfin-linux-uclibc target");
2358 #endif
2360 /* Library identification */
2361 if (global_options_set.x_bfin_library_id && ! TARGET_ID_SHARED_LIBRARY)
2362 error ("-mshared-library-id= specified without -mid-shared-library");
2364 if (stack_limit_rtx && TARGET_FDPIC)
2366 warning (0, "-fstack-limit- options are ignored with -mfdpic; use -mstack-check-l1");
2367 stack_limit_rtx = NULL_RTX;
2370 if (stack_limit_rtx && TARGET_STACK_CHECK_L1)
2371 error ("can%'t use multiple stack checking methods together");
2373 if (TARGET_ID_SHARED_LIBRARY && TARGET_FDPIC)
2374 error ("ID shared libraries and FD-PIC mode can%'t be used together");
2376 /* Don't allow the user to specify -mid-shared-library and -msep-data
2377 together, as it makes little sense from a user's point of view... */
2378 if (TARGET_SEP_DATA && TARGET_ID_SHARED_LIBRARY)
2379 error ("cannot specify both -msep-data and -mid-shared-library");
2380 /* ... internally, however, it's nearly the same. */
2381 if (TARGET_SEP_DATA)
2382 target_flags |= MASK_ID_SHARED_LIBRARY | MASK_LEAF_ID_SHARED_LIBRARY;
2384 if (TARGET_ID_SHARED_LIBRARY && flag_pic == 0)
2385 flag_pic = 1;
2387 /* There is no single unaligned SI op for PIC code. Sometimes we
2388 need to use ".4byte" and sometimes we need to use ".picptr".
2389 See bfin_assemble_integer for details. */
2390 if (TARGET_FDPIC)
2391 targetm.asm_out.unaligned_op.si = 0;
2393 /* Silently turn off flag_pic if not doing FDPIC or ID shared libraries,
2394 since we don't support it and it'll just break. */
2395 if (flag_pic && !TARGET_FDPIC && !TARGET_ID_SHARED_LIBRARY)
2396 flag_pic = 0;
2398 if (TARGET_MULTICORE && bfin_cpu_type != BFIN_CPU_BF561)
2399 error ("-mmulticore can only be used with BF561");
2401 if (TARGET_COREA && !TARGET_MULTICORE)
2402 error ("-mcorea should be used with -mmulticore");
2404 if (TARGET_COREB && !TARGET_MULTICORE)
2405 error ("-mcoreb should be used with -mmulticore");
2407 if (TARGET_COREA && TARGET_COREB)
2408 error ("-mcorea and -mcoreb can%'t be used together");
2410 flag_schedule_insns = 0;
2412 init_machine_status = bfin_init_machine_status;
2415 /* Return the destination address of BRANCH.
2416 We need to use this instead of get_attr_length, because the
2417 cbranch_with_nops pattern conservatively sets its length to 6, and
2418 we still prefer to use shorter sequences. */
2420 static int
2421 branch_dest (rtx_insn *branch)
2423 rtx dest;
2424 int dest_uid;
2425 rtx pat = PATTERN (branch);
2426 if (GET_CODE (pat) == PARALLEL)
2427 pat = XVECEXP (pat, 0, 0);
2428 dest = SET_SRC (pat);
2429 if (GET_CODE (dest) == IF_THEN_ELSE)
2430 dest = XEXP (dest, 1);
2431 dest = XEXP (dest, 0);
2432 dest_uid = INSN_UID (dest);
2433 return INSN_ADDRESSES (dest_uid);
2436 /* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates
2437 it's a branch that's predicted taken. */
2439 static int
2440 cbranch_predicted_taken_p (rtx insn)
2442 rtx x = find_reg_note (insn, REG_BR_PROB, 0);
2444 if (x)
2446 int pred_val = XINT (x, 0);
2448 return pred_val >= REG_BR_PROB_BASE / 2;
2451 return 0;
2454 /* Templates for use by asm_conditional_branch. */
2456 static const char *ccbranch_templates[][3] = {
2457 { "if !cc jump %3;", "if cc jump 4 (bp); jump.s %3;", "if cc jump 6 (bp); jump.l %3;" },
2458 { "if cc jump %3;", "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" },
2459 { "if !cc jump %3 (bp);", "if cc jump 4; jump.s %3;", "if cc jump 6; jump.l %3;" },
2460 { "if cc jump %3 (bp);", "if !cc jump 4; jump.s %3;", "if !cc jump 6; jump.l %3;" },
2463 /* Output INSN, which is a conditional branch instruction with operands
2464 OPERANDS.
2466 We deal with the various forms of conditional branches that can be generated
2467 by bfin_reorg to prevent the hardware from doing speculative loads, by
2468 - emitting a sufficient number of nops, if N_NOPS is nonzero, or
2469 - always emitting the branch as predicted taken, if PREDICT_TAKEN is true.
2470 Either of these is only necessary if the branch is short, otherwise the
2471 template we use ends in an unconditional jump which flushes the pipeline
2472 anyway. */
2474 void
2475 asm_conditional_branch (rtx_insn *insn, rtx *operands, int n_nops, int predict_taken)
2477 int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
2478 /* Note : offset for instructions like if cc jmp; jump.[sl] offset
2479 is to be taken from start of if cc rather than jump.
2480 Range for jump.s is (-4094, 4096) instead of (-4096, 4094)
2482 int len = (offset >= -1024 && offset <= 1022 ? 0
2483 : offset >= -4094 && offset <= 4096 ? 1
2484 : 2);
2485 int bp = predict_taken && len == 0 ? 1 : cbranch_predicted_taken_p (insn);
2486 int idx = (bp << 1) | (GET_CODE (operands[0]) == EQ ? BRF : BRT);
2487 output_asm_insn (ccbranch_templates[idx][len], operands);
2488 gcc_assert (n_nops == 0 || !bp);
2489 if (len == 0)
2490 while (n_nops-- > 0)
2491 output_asm_insn ("nop;", NULL);
2494 /* Emit rtl for a comparison operation CMP in mode MODE. Operands have been
2495 stored in bfin_compare_op0 and bfin_compare_op1 already. */
2498 bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED)
2500 enum rtx_code code1, code2;
2501 rtx op0 = XEXP (cmp, 0), op1 = XEXP (cmp, 1);
2502 rtx tem = bfin_cc_rtx;
2503 enum rtx_code code = GET_CODE (cmp);
2505 /* If we have a BImode input, then we already have a compare result, and
2506 do not need to emit another comparison. */
2507 if (GET_MODE (op0) == BImode)
2509 gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
2510 tem = op0, code2 = code;
2512 else
2514 switch (code) {
2515 /* bfin has these conditions */
2516 case EQ:
2517 case LT:
2518 case LE:
2519 case LEU:
2520 case LTU:
2521 code1 = code;
2522 code2 = NE;
2523 break;
2524 default:
2525 code1 = reverse_condition (code);
2526 code2 = EQ;
2527 break;
2529 emit_insn (gen_rtx_SET (VOIDmode, tem,
2530 gen_rtx_fmt_ee (code1, BImode, op0, op1)));
2533 return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode));
2536 /* Return nonzero iff C has exactly one bit set if it is interpreted
2537 as a 32-bit constant. */
2540 log2constp (unsigned HOST_WIDE_INT c)
2542 c &= 0xFFFFFFFF;
2543 return c != 0 && (c & (c-1)) == 0;
2546 /* Returns the number of consecutive least significant zeros in the binary
2547 representation of *V.
2548 We modify *V to contain the original value arithmetically shifted right by
2549 the number of zeroes. */
2551 static int
2552 shiftr_zero (HOST_WIDE_INT *v)
2554 unsigned HOST_WIDE_INT tmp = *v;
2555 unsigned HOST_WIDE_INT sgn;
2556 int n = 0;
2558 if (tmp == 0)
2559 return 0;
2561 sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1));
2562 while ((tmp & 0x1) == 0 && n <= 32)
2564 tmp = (tmp >> 1) | sgn;
2565 n++;
2567 *v = tmp;
2568 return n;
2571 /* After reload, split the load of an immediate constant. OPERANDS are the
2572 operands of the movsi_insn pattern which we are splitting. We return
2573 nonzero if we emitted a sequence to load the constant, zero if we emitted
2574 nothing because we want to use the splitter's default sequence. */
2577 split_load_immediate (rtx operands[])
2579 HOST_WIDE_INT val = INTVAL (operands[1]);
2580 HOST_WIDE_INT tmp;
2581 HOST_WIDE_INT shifted = val;
2582 HOST_WIDE_INT shifted_compl = ~val;
2583 int num_zero = shiftr_zero (&shifted);
2584 int num_compl_zero = shiftr_zero (&shifted_compl);
2585 unsigned int regno = REGNO (operands[0]);
2587 /* This case takes care of single-bit set/clear constants, which we could
2588 also implement with BITSET/BITCLR. */
2589 if (num_zero
2590 && shifted >= -32768 && shifted < 65536
2591 && (D_REGNO_P (regno)
2592 || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))
2594 emit_insn (gen_movsi (operands[0], gen_int_mode (shifted, SImode)));
2595 emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));
2596 return 1;
2599 tmp = val & 0xFFFF;
2600 tmp |= -(tmp & 0x8000);
2602 /* If high word has one bit set or clear, try to use a bit operation. */
2603 if (D_REGNO_P (regno))
2605 if (log2constp (val & 0xFFFF0000))
2607 emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));
2608 emit_insn (gen_iorsi3 (operands[0], operands[0],
2609 gen_int_mode (val & 0xFFFF0000, SImode)));
2610 return 1;
2612 else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)
2614 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2615 emit_insn (gen_andsi3 (operands[0], operands[0],
2616 gen_int_mode (val | 0xFFFF, SImode)));
2620 if (D_REGNO_P (regno))
2622 if (tmp >= -64 && tmp <= 63)
2624 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2625 emit_insn (gen_movstricthi_high (operands[0],
2626 gen_int_mode (val & -65536,
2627 SImode)));
2628 return 1;
2631 if ((val & 0xFFFF0000) == 0)
2633 emit_insn (gen_movsi (operands[0], const0_rtx));
2634 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2635 return 1;
2638 if ((val & 0xFFFF0000) == 0xFFFF0000)
2640 emit_insn (gen_movsi (operands[0], constm1_rtx));
2641 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2642 return 1;
2646 /* Need DREGs for the remaining case. */
2647 if (regno > REG_R7)
2648 return 0;
2650 if (optimize_size
2651 && num_compl_zero && shifted_compl >= -64 && shifted_compl <= 63)
2653 /* If optimizing for size, generate a sequence that has more instructions
2654 but is shorter. */
2655 emit_insn (gen_movsi (operands[0], gen_int_mode (shifted_compl, SImode)));
2656 emit_insn (gen_ashlsi3 (operands[0], operands[0],
2657 GEN_INT (num_compl_zero)));
2658 emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
2659 return 1;
2661 return 0;
2664 /* Return true if the legitimate memory address for a memory operand of mode
2665 MODE. Return false if not. */
2667 static bool
2668 bfin_valid_add (enum machine_mode mode, HOST_WIDE_INT value)
2670 unsigned HOST_WIDE_INT v = value > 0 ? value : -value;
2671 int sz = GET_MODE_SIZE (mode);
2672 int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2;
2673 /* The usual offsettable_memref machinery doesn't work so well for this
2674 port, so we deal with the problem here. */
2675 if (value > 0 && sz == 8)
2676 v += 4;
2677 return (v & ~(0x7fff << shift)) == 0;
2680 static bool
2681 bfin_valid_reg_p (unsigned int regno, int strict, enum machine_mode mode,
2682 enum rtx_code outer_code)
2684 if (strict)
2685 return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH);
2686 else
2687 return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH);
2690 /* Recognize an RTL expression that is a valid memory address for an
2691 instruction. The MODE argument is the machine mode for the MEM expression
2692 that wants to use this address.
2694 Blackfin addressing modes are as follows:
2696 [preg]
2697 [preg + imm16]
2699 B [ Preg + uimm15 ]
2700 W [ Preg + uimm16m2 ]
2701 [ Preg + uimm17m4 ]
2703 [preg++]
2704 [preg--]
2705 [--sp]
2708 static bool
2709 bfin_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
2711 switch (GET_CODE (x)) {
2712 case REG:
2713 if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM))
2714 return true;
2715 break;
2716 case PLUS:
2717 if (REG_P (XEXP (x, 0))
2718 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS)
2719 && ((GET_CODE (XEXP (x, 1)) == UNSPEC && mode == SImode)
2720 || (GET_CODE (XEXP (x, 1)) == CONST_INT
2721 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
2722 return true;
2723 break;
2724 case POST_INC:
2725 case POST_DEC:
2726 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2727 && REG_P (XEXP (x, 0))
2728 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC))
2729 return true;
2730 case PRE_DEC:
2731 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2732 && XEXP (x, 0) == stack_pointer_rtx
2733 && REG_P (XEXP (x, 0))
2734 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC))
2735 return true;
2736 break;
2737 default:
2738 break;
2740 return false;
2743 /* Decide whether we can force certain constants to memory. If we
2744 decide we can't, the caller should be able to cope with it in
2745 another way. */
2747 static bool
2748 bfin_cannot_force_const_mem (enum machine_mode mode ATTRIBUTE_UNUSED,
2749 rtx x ATTRIBUTE_UNUSED)
2751 /* We have only one class of non-legitimate constants, and our movsi
2752 expander knows how to handle them. Dropping these constants into the
2753 data section would only shift the problem - we'd still get relocs
2754 outside the object, in the data section rather than the text section. */
2755 return true;
2758 /* Ensure that for any constant of the form symbol + offset, the offset
2759 remains within the object. Any other constants are ok.
2760 This ensures that flat binaries never have to deal with relocations
2761 crossing section boundaries. */
2763 static bool
2764 bfin_legitimate_constant_p (enum machine_mode mode ATTRIBUTE_UNUSED, rtx x)
2766 rtx sym;
2767 HOST_WIDE_INT offset;
2769 if (GET_CODE (x) != CONST)
2770 return true;
2772 x = XEXP (x, 0);
2773 gcc_assert (GET_CODE (x) == PLUS);
2775 sym = XEXP (x, 0);
2776 x = XEXP (x, 1);
2777 if (GET_CODE (sym) != SYMBOL_REF
2778 || GET_CODE (x) != CONST_INT)
2779 return true;
2780 offset = INTVAL (x);
2782 if (SYMBOL_REF_DECL (sym) == 0)
2783 return true;
2784 if (offset < 0
2785 || offset >= int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (sym))))
2786 return false;
2788 return true;
2791 static bool
2792 bfin_rtx_costs (rtx x, int code_i, int outer_code_i, int opno, int *total,
2793 bool speed)
2795 enum rtx_code code = (enum rtx_code) code_i;
2796 enum rtx_code outer_code = (enum rtx_code) outer_code_i;
2797 int cost2 = COSTS_N_INSNS (1);
2798 rtx op0, op1;
2800 switch (code)
2802 case CONST_INT:
2803 if (outer_code == SET || outer_code == PLUS)
2804 *total = satisfies_constraint_Ks7 (x) ? 0 : cost2;
2805 else if (outer_code == AND)
2806 *total = log2constp (~INTVAL (x)) ? 0 : cost2;
2807 else if (outer_code == LE || outer_code == LT || outer_code == EQ)
2808 *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
2809 else if (outer_code == LEU || outer_code == LTU)
2810 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
2811 else if (outer_code == MULT)
2812 *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
2813 else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
2814 *total = 0;
2815 else if (outer_code == ASHIFT || outer_code == ASHIFTRT
2816 || outer_code == LSHIFTRT)
2817 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
2818 else if (outer_code == IOR || outer_code == XOR)
2819 *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
2820 else
2821 *total = cost2;
2822 return true;
2824 case CONST:
2825 case LABEL_REF:
2826 case SYMBOL_REF:
2827 case CONST_DOUBLE:
2828 *total = COSTS_N_INSNS (2);
2829 return true;
2831 case PLUS:
2832 op0 = XEXP (x, 0);
2833 op1 = XEXP (x, 1);
2834 if (GET_MODE (x) == SImode)
2836 if (GET_CODE (op0) == MULT
2837 && GET_CODE (XEXP (op0, 1)) == CONST_INT)
2839 HOST_WIDE_INT val = INTVAL (XEXP (op0, 1));
2840 if (val == 2 || val == 4)
2842 *total = cost2;
2843 *total += rtx_cost (XEXP (op0, 0), outer_code, opno, speed);
2844 *total += rtx_cost (op1, outer_code, opno, speed);
2845 return true;
2848 *total = cost2;
2849 if (GET_CODE (op0) != REG
2850 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2851 *total += set_src_cost (op0, speed);
2852 #if 0 /* We'd like to do this for accuracy, but it biases the loop optimizer
2853 towards creating too many induction variables. */
2854 if (!reg_or_7bit_operand (op1, SImode))
2855 *total += set_src_cost (op1, speed);
2856 #endif
2858 else if (GET_MODE (x) == DImode)
2860 *total = 6 * cost2;
2861 if (GET_CODE (op1) != CONST_INT
2862 || !satisfies_constraint_Ks7 (op1))
2863 *total += rtx_cost (op1, PLUS, 1, speed);
2864 if (GET_CODE (op0) != REG
2865 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2866 *total += rtx_cost (op0, PLUS, 0, speed);
2868 return true;
2870 case MINUS:
2871 if (GET_MODE (x) == DImode)
2872 *total = 6 * cost2;
2873 else
2874 *total = cost2;
2875 return true;
2877 case ASHIFT:
2878 case ASHIFTRT:
2879 case LSHIFTRT:
2880 if (GET_MODE (x) == DImode)
2881 *total = 6 * cost2;
2882 else
2883 *total = cost2;
2885 op0 = XEXP (x, 0);
2886 op1 = XEXP (x, 1);
2887 if (GET_CODE (op0) != REG
2888 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2889 *total += rtx_cost (op0, code, 0, speed);
2891 return true;
2893 case IOR:
2894 case AND:
2895 case XOR:
2896 op0 = XEXP (x, 0);
2897 op1 = XEXP (x, 1);
2899 /* Handle special cases of IOR: rotates, ALIGN insns, movstricthi_high. */
2900 if (code == IOR)
2902 if ((GET_CODE (op0) == LSHIFTRT && GET_CODE (op1) == ASHIFT)
2903 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == ZERO_EXTEND)
2904 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT)
2905 || (GET_CODE (op0) == AND && GET_CODE (op1) == CONST_INT))
2907 *total = cost2;
2908 return true;
2912 if (GET_CODE (op0) != REG
2913 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2914 *total += rtx_cost (op0, code, 0, speed);
2916 if (GET_MODE (x) == DImode)
2918 *total = 2 * cost2;
2919 return true;
2921 *total = cost2;
2922 if (GET_MODE (x) != SImode)
2923 return true;
2925 if (code == AND)
2927 if (! rhs_andsi3_operand (XEXP (x, 1), SImode))
2928 *total += rtx_cost (XEXP (x, 1), code, 1, speed);
2930 else
2932 if (! regorlog2_operand (XEXP (x, 1), SImode))
2933 *total += rtx_cost (XEXP (x, 1), code, 1, speed);
2936 return true;
2938 case ZERO_EXTRACT:
2939 case SIGN_EXTRACT:
2940 if (outer_code == SET
2941 && XEXP (x, 1) == const1_rtx
2942 && GET_CODE (XEXP (x, 2)) == CONST_INT)
2944 *total = 2 * cost2;
2945 return true;
2947 /* fall through */
2949 case SIGN_EXTEND:
2950 case ZERO_EXTEND:
2951 *total = cost2;
2952 return true;
2954 case MULT:
2956 op0 = XEXP (x, 0);
2957 op1 = XEXP (x, 1);
2958 if (GET_CODE (op0) == GET_CODE (op1)
2959 && (GET_CODE (op0) == ZERO_EXTEND
2960 || GET_CODE (op0) == SIGN_EXTEND))
2962 *total = COSTS_N_INSNS (1);
2963 op0 = XEXP (op0, 0);
2964 op1 = XEXP (op1, 0);
2966 else if (!speed)
2967 *total = COSTS_N_INSNS (1);
2968 else
2969 *total = COSTS_N_INSNS (3);
2971 if (GET_CODE (op0) != REG
2972 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2973 *total += rtx_cost (op0, MULT, 0, speed);
2974 if (GET_CODE (op1) != REG
2975 && (GET_CODE (op1) != SUBREG || GET_CODE (SUBREG_REG (op1)) != REG))
2976 *total += rtx_cost (op1, MULT, 1, speed);
2978 return true;
2980 case UDIV:
2981 case UMOD:
2982 *total = COSTS_N_INSNS (32);
2983 return true;
2985 case VEC_CONCAT:
2986 case VEC_SELECT:
2987 if (outer_code == SET)
2988 *total = cost2;
2989 return true;
2991 default:
2992 return false;
2996 /* Used for communication between {push,pop}_multiple_operation (which
2997 we use not only as a predicate) and the corresponding output functions. */
2998 static int first_preg_to_save, first_dreg_to_save;
2999 static int n_regs_to_save;
3002 analyze_push_multiple_operation (rtx op)
3004 int lastdreg = 8, lastpreg = 6;
3005 int i, group;
3007 first_preg_to_save = lastpreg;
3008 first_dreg_to_save = lastdreg;
3009 for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
3011 rtx t = XVECEXP (op, 0, i);
3012 rtx src, dest;
3013 int regno;
3015 if (GET_CODE (t) != SET)
3016 return 0;
3018 src = SET_SRC (t);
3019 dest = SET_DEST (t);
3020 if (GET_CODE (dest) != MEM || ! REG_P (src))
3021 return 0;
3022 dest = XEXP (dest, 0);
3023 if (GET_CODE (dest) != PLUS
3024 || ! REG_P (XEXP (dest, 0))
3025 || REGNO (XEXP (dest, 0)) != REG_SP
3026 || GET_CODE (XEXP (dest, 1)) != CONST_INT
3027 || INTVAL (XEXP (dest, 1)) != -i * 4)
3028 return 0;
3030 regno = REGNO (src);
3031 if (group == 0)
3033 if (D_REGNO_P (regno))
3035 group = 1;
3036 first_dreg_to_save = lastdreg = regno - REG_R0;
3038 else if (regno >= REG_P0 && regno <= REG_P7)
3040 group = 2;
3041 first_preg_to_save = lastpreg = regno - REG_P0;
3043 else
3044 return 0;
3046 continue;
3049 if (group == 1)
3051 if (regno >= REG_P0 && regno <= REG_P7)
3053 group = 2;
3054 first_preg_to_save = lastpreg = regno - REG_P0;
3056 else if (regno != REG_R0 + lastdreg + 1)
3057 return 0;
3058 else
3059 lastdreg++;
3061 else if (group == 2)
3063 if (regno != REG_P0 + lastpreg + 1)
3064 return 0;
3065 lastpreg++;
3068 n_regs_to_save = 8 - first_dreg_to_save + 6 - first_preg_to_save;
3069 return 1;
3073 analyze_pop_multiple_operation (rtx op)
3075 int lastdreg = 8, lastpreg = 6;
3076 int i, group;
3078 for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
3080 rtx t = XVECEXP (op, 0, i);
3081 rtx src, dest;
3082 int regno;
3084 if (GET_CODE (t) != SET)
3085 return 0;
3087 src = SET_SRC (t);
3088 dest = SET_DEST (t);
3089 if (GET_CODE (src) != MEM || ! REG_P (dest))
3090 return 0;
3091 src = XEXP (src, 0);
3093 if (i == 1)
3095 if (! REG_P (src) || REGNO (src) != REG_SP)
3096 return 0;
3098 else if (GET_CODE (src) != PLUS
3099 || ! REG_P (XEXP (src, 0))
3100 || REGNO (XEXP (src, 0)) != REG_SP
3101 || GET_CODE (XEXP (src, 1)) != CONST_INT
3102 || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
3103 return 0;
3105 regno = REGNO (dest);
3106 if (group == 0)
3108 if (regno == REG_R7)
3110 group = 1;
3111 lastdreg = 7;
3113 else if (regno != REG_P0 + lastpreg - 1)
3114 return 0;
3115 else
3116 lastpreg--;
3118 else if (group == 1)
3120 if (regno != REG_R0 + lastdreg - 1)
3121 return 0;
3122 else
3123 lastdreg--;
3126 first_dreg_to_save = lastdreg;
3127 first_preg_to_save = lastpreg;
3128 n_regs_to_save = 8 - first_dreg_to_save + 6 - first_preg_to_save;
3129 return 1;
3132 /* Emit assembly code for one multi-register push described by INSN, with
3133 operands in OPERANDS. */
3135 void
3136 output_push_multiple (rtx insn, rtx *operands)
3138 char buf[80];
3139 int ok;
3141 /* Validate the insn again, and compute first_[dp]reg_to_save. */
3142 ok = analyze_push_multiple_operation (PATTERN (insn));
3143 gcc_assert (ok);
3145 if (first_dreg_to_save == 8)
3146 sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
3147 else if (first_preg_to_save == 6)
3148 sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
3149 else
3150 sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
3151 first_dreg_to_save, first_preg_to_save);
3153 output_asm_insn (buf, operands);
3156 /* Emit assembly code for one multi-register pop described by INSN, with
3157 operands in OPERANDS. */
3159 void
3160 output_pop_multiple (rtx insn, rtx *operands)
3162 char buf[80];
3163 int ok;
3165 /* Validate the insn again, and compute first_[dp]reg_to_save. */
3166 ok = analyze_pop_multiple_operation (PATTERN (insn));
3167 gcc_assert (ok);
3169 if (first_dreg_to_save == 8)
3170 sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
3171 else if (first_preg_to_save == 6)
3172 sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
3173 else
3174 sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
3175 first_dreg_to_save, first_preg_to_save);
3177 output_asm_insn (buf, operands);
3180 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE. */
3182 static void
3183 single_move_for_movmem (rtx dst, rtx src, enum machine_mode mode, HOST_WIDE_INT offset)
3185 rtx scratch = gen_reg_rtx (mode);
3186 rtx srcmem, dstmem;
3188 srcmem = adjust_address_nv (src, mode, offset);
3189 dstmem = adjust_address_nv (dst, mode, offset);
3190 emit_move_insn (scratch, srcmem);
3191 emit_move_insn (dstmem, scratch);
3194 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
3195 alignment ALIGN_EXP. Return true if successful, false if we should fall
3196 back on a different method. */
3198 bool
3199 bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
3201 rtx srcreg, destreg, countreg;
3202 HOST_WIDE_INT align = 0;
3203 unsigned HOST_WIDE_INT count = 0;
3205 if (GET_CODE (align_exp) == CONST_INT)
3206 align = INTVAL (align_exp);
3207 if (GET_CODE (count_exp) == CONST_INT)
3209 count = INTVAL (count_exp);
3210 #if 0
3211 if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
3212 return false;
3213 #endif
3216 /* If optimizing for size, only do single copies inline. */
3217 if (optimize_size)
3219 if (count == 2 && align < 2)
3220 return false;
3221 if (count == 4 && align < 4)
3222 return false;
3223 if (count != 1 && count != 2 && count != 4)
3224 return false;
3226 if (align < 2 && count != 1)
3227 return false;
3229 destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
3230 if (destreg != XEXP (dst, 0))
3231 dst = replace_equiv_address_nv (dst, destreg);
3232 srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
3233 if (srcreg != XEXP (src, 0))
3234 src = replace_equiv_address_nv (src, srcreg);
3236 if (count != 0 && align >= 2)
3238 unsigned HOST_WIDE_INT offset = 0;
3240 if (align >= 4)
3242 if ((count & ~3) == 4)
3244 single_move_for_movmem (dst, src, SImode, offset);
3245 offset = 4;
3247 else if (count & ~3)
3249 HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
3250 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3252 emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
3253 cfun->machine->has_loopreg_clobber = true;
3255 if (count & 2)
3257 single_move_for_movmem (dst, src, HImode, offset);
3258 offset += 2;
3261 else
3263 if ((count & ~1) == 2)
3265 single_move_for_movmem (dst, src, HImode, offset);
3266 offset = 2;
3268 else if (count & ~1)
3270 HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
3271 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3273 emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
3274 cfun->machine->has_loopreg_clobber = true;
3277 if (count & 1)
3279 single_move_for_movmem (dst, src, QImode, offset);
3281 return true;
3283 return false;
3286 /* Compute the alignment for a local variable.
3287 TYPE is the data type, and ALIGN is the alignment that
3288 the object would ordinarily have. The value of this macro is used
3289 instead of that alignment to align the object. */
3291 unsigned
3292 bfin_local_alignment (tree type, unsigned align)
3294 /* Increasing alignment for (relatively) big types allows the builtin
3295 memcpy can use 32 bit loads/stores. */
3296 if (TYPE_SIZE (type)
3297 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
3298 && wi::gtu_p (TYPE_SIZE (type), 8)
3299 && align < 32)
3300 return 32;
3301 return align;
3304 /* Implement TARGET_SCHED_ISSUE_RATE. */
3306 static int
3307 bfin_issue_rate (void)
3309 return 3;
3312 static int
3313 bfin_adjust_cost (rtx_insn *insn, rtx link, rtx_insn *dep_insn, int cost)
3315 enum attr_type dep_insn_type;
3316 int dep_insn_code_number;
3318 /* Anti and output dependencies have zero cost. */
3319 if (REG_NOTE_KIND (link) != 0)
3320 return 0;
3322 dep_insn_code_number = recog_memoized (dep_insn);
3324 /* If we can't recognize the insns, we can't really do anything. */
3325 if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
3326 return cost;
3328 dep_insn_type = get_attr_type (dep_insn);
3330 if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)
3332 rtx pat = PATTERN (dep_insn);
3333 rtx dest, src;
3335 if (GET_CODE (pat) == PARALLEL)
3336 pat = XVECEXP (pat, 0, 0);
3337 dest = SET_DEST (pat);
3338 src = SET_SRC (pat);
3339 if (! ADDRESS_REGNO_P (REGNO (dest))
3340 || ! (MEM_P (src) || D_REGNO_P (REGNO (src))))
3341 return cost;
3342 return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);
3345 return cost;
3348 /* This function acts like NEXT_INSN, but is aware of three-insn bundles and
3349 skips all subsequent parallel instructions if INSN is the start of such
3350 a group. */
3351 static rtx_insn *
3352 find_next_insn_start (rtx_insn *insn)
3354 if (GET_MODE (insn) == SImode)
3356 while (GET_MODE (insn) != QImode)
3357 insn = NEXT_INSN (insn);
3359 return NEXT_INSN (insn);
3362 /* This function acts like PREV_INSN, but is aware of three-insn bundles and
3363 skips all subsequent parallel instructions if INSN is the start of such
3364 a group. */
3365 static rtx_insn *
3366 find_prev_insn_start (rtx_insn *insn)
3368 insn = PREV_INSN (insn);
3369 gcc_assert (GET_MODE (insn) != SImode);
3370 if (GET_MODE (insn) == QImode)
3372 while (GET_MODE (PREV_INSN (insn)) == SImode)
3373 insn = PREV_INSN (insn);
3375 return insn;
3378 /* Implement TARGET_CAN_USE_DOLOOP_P. */
3380 static bool
3381 bfin_can_use_doloop_p (const widest_int &, const widest_int &iterations_max,
3382 unsigned int, bool)
3384 /* Due to limitations in the hardware (an initial loop count of 0
3385 does not loop 2^32 times) we must avoid to generate a hardware
3386 loops when we cannot rule out this case. */
3387 if (!flag_unsafe_loop_optimizations
3388 && wi::geu_p (iterations_max, 0xFFFFFFFF))
3389 return false;
3390 return true;
3393 /* Increment the counter for the number of loop instructions in the
3394 current function. */
3396 void
3397 bfin_hardware_loop (void)
3399 cfun->machine->has_hardware_loops++;
3402 /* Maximum loop nesting depth. */
3403 #define MAX_LOOP_DEPTH 2
3405 /* Maximum size of a loop. */
3406 #define MAX_LOOP_LENGTH 2042
3408 /* Maximum distance of the LSETUP instruction from the loop start. */
3409 #define MAX_LSETUP_DISTANCE 30
3411 /* Estimate the length of INSN conservatively. */
3413 static int
3414 length_for_loop (rtx_insn *insn)
3416 int length = 0;
3417 if (JUMP_P (insn) && any_condjump_p (insn) && !optimize_size)
3419 if (ENABLE_WA_SPECULATIVE_SYNCS)
3420 length = 8;
3421 else if (ENABLE_WA_SPECULATIVE_LOADS)
3422 length = 6;
3424 else if (LABEL_P (insn))
3426 if (ENABLE_WA_SPECULATIVE_SYNCS)
3427 length = 4;
3430 if (NONDEBUG_INSN_P (insn))
3431 length += get_attr_length (insn);
3433 return length;
3436 /* Optimize LOOP. */
3438 static bool
3439 hwloop_optimize (hwloop_info loop)
3441 basic_block bb;
3442 rtx_insn *insn, *last_insn;
3443 rtx loop_init, start_label, end_label;
3444 rtx iter_reg, scratchreg, scratch_init, scratch_init_insn;
3445 rtx lc_reg, lt_reg, lb_reg;
3446 rtx seq_end;
3447 rtx_insn *seq;
3448 int length;
3449 bool clobber0, clobber1;
3451 if (loop->depth > MAX_LOOP_DEPTH)
3453 if (dump_file)
3454 fprintf (dump_file, ";; loop %d too deep\n", loop->loop_no);
3455 return false;
3458 /* Get the loop iteration register. */
3459 iter_reg = loop->iter_reg;
3461 gcc_assert (REG_P (iter_reg));
3463 scratchreg = NULL_RTX;
3464 scratch_init = iter_reg;
3465 scratch_init_insn = NULL_RTX;
3466 if (!PREG_P (iter_reg) && loop->incoming_src)
3468 basic_block bb_in = loop->incoming_src;
3469 int i;
3470 for (i = REG_P0; i <= REG_P5; i++)
3471 if ((df_regs_ever_live_p (i)
3472 || (funkind (TREE_TYPE (current_function_decl)) == SUBROUTINE
3473 && call_used_regs[i]))
3474 && !REGNO_REG_SET_P (df_get_live_out (bb_in), i))
3476 scratchreg = gen_rtx_REG (SImode, i);
3477 break;
3479 for (insn = BB_END (bb_in); insn != BB_HEAD (bb_in);
3480 insn = PREV_INSN (insn))
3482 rtx set;
3483 if (NOTE_P (insn) || BARRIER_P (insn))
3484 continue;
3485 set = single_set (insn);
3486 if (set && rtx_equal_p (SET_DEST (set), iter_reg))
3488 if (CONSTANT_P (SET_SRC (set)))
3490 scratch_init = SET_SRC (set);
3491 scratch_init_insn = insn;
3493 break;
3495 else if (reg_mentioned_p (iter_reg, PATTERN (insn)))
3496 break;
3500 if (loop->incoming_src)
3502 /* Make sure the predecessor is before the loop start label, as required by
3503 the LSETUP instruction. */
3504 length = 0;
3505 insn = BB_END (loop->incoming_src);
3506 /* If we have to insert the LSETUP before a jump, count that jump in the
3507 length. */
3508 if (vec_safe_length (loop->incoming) > 1
3509 || !(loop->incoming->last ()->flags & EDGE_FALLTHRU))
3511 gcc_assert (JUMP_P (insn));
3512 insn = PREV_INSN (insn);
3515 for (; insn && insn != loop->start_label; insn = NEXT_INSN (insn))
3516 length += length_for_loop (insn);
3518 if (!insn)
3520 if (dump_file)
3521 fprintf (dump_file, ";; loop %d lsetup not before loop_start\n",
3522 loop->loop_no);
3523 return false;
3526 /* Account for the pop of a scratch register where necessary. */
3527 if (!PREG_P (iter_reg) && scratchreg == NULL_RTX
3528 && ENABLE_WA_LOAD_LCREGS)
3529 length += 2;
3531 if (length > MAX_LSETUP_DISTANCE)
3533 if (dump_file)
3534 fprintf (dump_file, ";; loop %d lsetup too far away\n", loop->loop_no);
3535 return false;
3539 /* Check if start_label appears before loop_end and calculate the
3540 offset between them. We calculate the length of instructions
3541 conservatively. */
3542 length = 0;
3543 for (insn = loop->start_label;
3544 insn && insn != loop->loop_end;
3545 insn = NEXT_INSN (insn))
3546 length += length_for_loop (insn);
3548 if (!insn)
3550 if (dump_file)
3551 fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
3552 loop->loop_no);
3553 return false;
3556 loop->length = length;
3557 if (loop->length > MAX_LOOP_LENGTH)
3559 if (dump_file)
3560 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
3561 return false;
3564 /* Scan all the blocks to make sure they don't use iter_reg. */
3565 if (loop->iter_reg_used || loop->iter_reg_used_outside)
3567 if (dump_file)
3568 fprintf (dump_file, ";; loop %d uses iterator\n", loop->loop_no);
3569 return false;
3572 clobber0 = (TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC0)
3573 || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LB0)
3574 || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LT0));
3575 clobber1 = (TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC1)
3576 || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LB1)
3577 || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LT1));
3578 if (clobber0 && clobber1)
3580 if (dump_file)
3581 fprintf (dump_file, ";; loop %d no loop reg available\n",
3582 loop->loop_no);
3583 return false;
3586 /* There should be an instruction before the loop_end instruction
3587 in the same basic block. And the instruction must not be
3588 - JUMP
3589 - CONDITIONAL BRANCH
3590 - CALL
3591 - CSYNC
3592 - SSYNC
3593 - Returns (RTS, RTN, etc.) */
3595 bb = loop->tail;
3596 last_insn = find_prev_insn_start (loop->loop_end);
3598 while (1)
3600 for (; last_insn != BB_HEAD (bb);
3601 last_insn = find_prev_insn_start (last_insn))
3602 if (NONDEBUG_INSN_P (last_insn))
3603 break;
3605 if (last_insn != BB_HEAD (bb))
3606 break;
3608 if (single_pred_p (bb)
3609 && single_pred_edge (bb)->flags & EDGE_FALLTHRU
3610 && single_pred (bb) != ENTRY_BLOCK_PTR_FOR_FN (cfun))
3612 bb = single_pred (bb);
3613 last_insn = BB_END (bb);
3614 continue;
3616 else
3618 last_insn = NULL;
3619 break;
3623 if (!last_insn)
3625 if (dump_file)
3626 fprintf (dump_file, ";; loop %d has no last instruction\n",
3627 loop->loop_no);
3628 return false;
3631 if (JUMP_P (last_insn) && !any_condjump_p (last_insn))
3633 if (dump_file)
3634 fprintf (dump_file, ";; loop %d has bad last instruction\n",
3635 loop->loop_no);
3636 return false;
3638 /* In all other cases, try to replace a bad last insn with a nop. */
3639 else if (JUMP_P (last_insn)
3640 || CALL_P (last_insn)
3641 || get_attr_type (last_insn) == TYPE_SYNC
3642 || get_attr_type (last_insn) == TYPE_CALL
3643 || get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI
3644 || recog_memoized (last_insn) == CODE_FOR_return_internal
3645 || GET_CODE (PATTERN (last_insn)) == ASM_INPUT
3646 || asm_noperands (PATTERN (last_insn)) >= 0)
3648 if (loop->length + 2 > MAX_LOOP_LENGTH)
3650 if (dump_file)
3651 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
3652 return false;
3654 if (dump_file)
3655 fprintf (dump_file, ";; loop %d has bad last insn; replace with nop\n",
3656 loop->loop_no);
3658 last_insn = emit_insn_after (gen_forced_nop (), last_insn);
3661 loop->last_insn = last_insn;
3663 /* The loop is good for replacement. */
3664 start_label = loop->start_label;
3665 end_label = gen_label_rtx ();
3666 iter_reg = loop->iter_reg;
3668 if (loop->depth == 1 && !clobber1)
3670 lc_reg = gen_rtx_REG (SImode, REG_LC1);
3671 lb_reg = gen_rtx_REG (SImode, REG_LB1);
3672 lt_reg = gen_rtx_REG (SImode, REG_LT1);
3673 SET_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC1);
3675 else
3677 lc_reg = gen_rtx_REG (SImode, REG_LC0);
3678 lb_reg = gen_rtx_REG (SImode, REG_LB0);
3679 lt_reg = gen_rtx_REG (SImode, REG_LT0);
3680 SET_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC0);
3683 loop->end_label = end_label;
3685 /* Create a sequence containing the loop setup. */
3686 start_sequence ();
3688 /* LSETUP only accepts P registers. If we have one, we can use it,
3689 otherwise there are several ways of working around the problem.
3690 If we're not affected by anomaly 312, we can load the LC register
3691 from any iteration register, and use LSETUP without initialization.
3692 If we've found a P scratch register that's not live here, we can
3693 instead copy the iter_reg into that and use an initializing LSETUP.
3694 If all else fails, push and pop P0 and use it as a scratch. */
3695 if (P_REGNO_P (REGNO (iter_reg)))
3697 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
3698 lb_reg, end_label,
3699 lc_reg, iter_reg);
3700 seq_end = emit_insn (loop_init);
3702 else if (!ENABLE_WA_LOAD_LCREGS && DPREG_P (iter_reg))
3704 emit_insn (gen_movsi (lc_reg, iter_reg));
3705 loop_init = gen_lsetup_without_autoinit (lt_reg, start_label,
3706 lb_reg, end_label,
3707 lc_reg);
3708 seq_end = emit_insn (loop_init);
3710 else if (scratchreg != NULL_RTX)
3712 emit_insn (gen_movsi (scratchreg, scratch_init));
3713 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
3714 lb_reg, end_label,
3715 lc_reg, scratchreg);
3716 seq_end = emit_insn (loop_init);
3717 if (scratch_init_insn != NULL_RTX)
3718 delete_insn (scratch_init_insn);
3720 else
3722 rtx p0reg = gen_rtx_REG (SImode, REG_P0);
3723 rtx push = gen_frame_mem (SImode,
3724 gen_rtx_PRE_DEC (SImode, stack_pointer_rtx));
3725 rtx pop = gen_frame_mem (SImode,
3726 gen_rtx_POST_INC (SImode, stack_pointer_rtx));
3727 emit_insn (gen_movsi (push, p0reg));
3728 emit_insn (gen_movsi (p0reg, scratch_init));
3729 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
3730 lb_reg, end_label,
3731 lc_reg, p0reg);
3732 emit_insn (loop_init);
3733 seq_end = emit_insn (gen_movsi (p0reg, pop));
3734 if (scratch_init_insn != NULL_RTX)
3735 delete_insn (scratch_init_insn);
3738 if (dump_file)
3740 fprintf (dump_file, ";; replacing loop %d initializer with\n",
3741 loop->loop_no);
3742 print_rtl_single (dump_file, loop_init);
3743 fprintf (dump_file, ";; replacing loop %d terminator with\n",
3744 loop->loop_no);
3745 print_rtl_single (dump_file, loop->loop_end);
3748 /* If the loop isn't entered at the top, also create a jump to the entry
3749 point. */
3750 if (!loop->incoming_src && loop->head != loop->incoming_dest)
3752 rtx label = BB_HEAD (loop->incoming_dest);
3753 /* If we're jumping to the final basic block in the loop, and there's
3754 only one cheap instruction before the end (typically an increment of
3755 an induction variable), we can just emit a copy here instead of a
3756 jump. */
3757 if (loop->incoming_dest == loop->tail
3758 && next_real_insn (label) == last_insn
3759 && asm_noperands (last_insn) < 0
3760 && GET_CODE (PATTERN (last_insn)) == SET)
3762 seq_end = emit_insn (copy_rtx (PATTERN (last_insn)));
3764 else
3766 emit_jump_insn (gen_jump (label));
3767 seq_end = emit_barrier ();
3771 seq = get_insns ();
3772 end_sequence ();
3774 if (loop->incoming_src)
3776 rtx_insn *prev = BB_END (loop->incoming_src);
3777 if (vec_safe_length (loop->incoming) > 1
3778 || !(loop->incoming->last ()->flags & EDGE_FALLTHRU))
3780 gcc_assert (JUMP_P (prev));
3781 prev = PREV_INSN (prev);
3783 emit_insn_after (seq, prev);
3785 else
3787 basic_block new_bb;
3788 edge e;
3789 edge_iterator ei;
3791 #ifdef ENABLE_CHECKING
3792 if (loop->head != loop->incoming_dest)
3794 /* We aren't entering the loop at the top. Since we've established
3795 that the loop is entered only at one point, this means there
3796 can't be fallthru edges into the head. Any such fallthru edges
3797 would become invalid when we insert the new block, so verify
3798 that this does not in fact happen. */
3799 FOR_EACH_EDGE (e, ei, loop->head->preds)
3800 gcc_assert (!(e->flags & EDGE_FALLTHRU));
3802 #endif
3804 emit_insn_before (seq, BB_HEAD (loop->head));
3805 seq = emit_label_before (gen_label_rtx (), seq);
3807 new_bb = create_basic_block (seq, seq_end, loop->head->prev_bb);
3808 FOR_EACH_EDGE (e, ei, loop->incoming)
3810 if (!(e->flags & EDGE_FALLTHRU)
3811 || e->dest != loop->head)
3812 redirect_edge_and_branch_force (e, new_bb);
3813 else
3814 redirect_edge_succ (e, new_bb);
3816 e = make_edge (new_bb, loop->head, 0);
3819 delete_insn (loop->loop_end);
3820 /* Insert the loop end label before the last instruction of the loop. */
3821 emit_label_before (loop->end_label, loop->last_insn);
3823 return true;
3826 /* A callback for the hw-doloop pass. Called when a loop we have discovered
3827 turns out not to be optimizable; we have to split the doloop_end pattern
3828 into a subtract and a test. */
3829 static void
3830 hwloop_fail (hwloop_info loop)
3832 rtx insn = loop->loop_end;
3834 if (DPREG_P (loop->iter_reg))
3836 /* If loop->iter_reg is a DREG or PREG, we can split it here
3837 without scratch register. */
3838 rtx insn, test;
3840 emit_insn_before (gen_addsi3 (loop->iter_reg,
3841 loop->iter_reg,
3842 constm1_rtx),
3843 loop->loop_end);
3845 test = gen_rtx_NE (VOIDmode, loop->iter_reg, const0_rtx);
3846 insn = emit_jump_insn_before (gen_cbranchsi4 (test,
3847 loop->iter_reg, const0_rtx,
3848 loop->start_label),
3849 loop->loop_end);
3851 JUMP_LABEL (insn) = loop->start_label;
3852 LABEL_NUSES (loop->start_label)++;
3853 delete_insn (loop->loop_end);
3855 else
3857 splitting_loops = 1;
3858 try_split (PATTERN (insn), insn, 1);
3859 splitting_loops = 0;
3863 /* A callback for the hw-doloop pass. This function examines INSN; if
3864 it is a loop_end pattern we recognize, return the reg rtx for the
3865 loop counter. Otherwise, return NULL_RTX. */
3867 static rtx
3868 hwloop_pattern_reg (rtx_insn *insn)
3870 rtx reg;
3872 if (!JUMP_P (insn) || recog_memoized (insn) != CODE_FOR_loop_end)
3873 return NULL_RTX;
3875 reg = SET_DEST (XVECEXP (PATTERN (insn), 0, 1));
3876 if (!REG_P (reg))
3877 return NULL_RTX;
3878 return reg;
3881 static struct hw_doloop_hooks bfin_doloop_hooks =
3883 hwloop_pattern_reg,
3884 hwloop_optimize,
3885 hwloop_fail
3888 /* Run from machine_dependent_reorg, this pass looks for doloop_end insns
3889 and tries to rewrite the RTL of these loops so that proper Blackfin
3890 hardware loops are generated. */
3892 static void
3893 bfin_reorg_loops (void)
3895 reorg_loops (true, &bfin_doloop_hooks);
3898 /* Possibly generate a SEQUENCE out of three insns found in SLOT.
3899 Returns true if we modified the insn chain, false otherwise. */
3900 static bool
3901 gen_one_bundle (rtx_insn *slot[3])
3903 gcc_assert (slot[1] != NULL_RTX);
3905 /* Don't add extra NOPs if optimizing for size. */
3906 if (optimize_size
3907 && (slot[0] == NULL_RTX || slot[2] == NULL_RTX))
3908 return false;
3910 /* Verify that we really can do the multi-issue. */
3911 if (slot[0])
3913 rtx_insn *t = NEXT_INSN (slot[0]);
3914 while (t != slot[1])
3916 if (! NOTE_P (t) || NOTE_KIND (t) != NOTE_INSN_DELETED)
3917 return false;
3918 t = NEXT_INSN (t);
3921 if (slot[2])
3923 rtx_insn *t = NEXT_INSN (slot[1]);
3924 while (t != slot[2])
3926 if (! NOTE_P (t) || NOTE_KIND (t) != NOTE_INSN_DELETED)
3927 return false;
3928 t = NEXT_INSN (t);
3932 if (slot[0] == NULL_RTX)
3934 slot[0] = emit_insn_before (gen_mnop (), slot[1]);
3935 df_insn_rescan (slot[0]);
3937 if (slot[2] == NULL_RTX)
3939 slot[2] = emit_insn_after (gen_forced_nop (), slot[1]);
3940 df_insn_rescan (slot[2]);
3943 /* Avoid line number information being printed inside one bundle. */
3944 if (INSN_LOCATION (slot[1])
3945 && INSN_LOCATION (slot[1]) != INSN_LOCATION (slot[0]))
3946 INSN_LOCATION (slot[1]) = INSN_LOCATION (slot[0]);
3947 if (INSN_LOCATION (slot[2])
3948 && INSN_LOCATION (slot[2]) != INSN_LOCATION (slot[0]))
3949 INSN_LOCATION (slot[2]) = INSN_LOCATION (slot[0]);
3951 /* Terminate them with "|| " instead of ";" in the output. */
3952 PUT_MODE (slot[0], SImode);
3953 PUT_MODE (slot[1], SImode);
3954 /* Terminate the bundle, for the benefit of reorder_var_tracking_notes. */
3955 PUT_MODE (slot[2], QImode);
3956 return true;
3959 /* Go through all insns, and use the information generated during scheduling
3960 to generate SEQUENCEs to represent bundles of instructions issued
3961 simultaneously. */
3963 static void
3964 bfin_gen_bundles (void)
3966 basic_block bb;
3967 FOR_EACH_BB_FN (bb, cfun)
3969 rtx_insn *insn, *next;
3970 rtx_insn *slot[3];
3971 int n_filled = 0;
3973 slot[0] = slot[1] = slot[2] = NULL;
3974 for (insn = BB_HEAD (bb);; insn = next)
3976 int at_end;
3977 rtx delete_this = NULL_RTX;
3979 if (NONDEBUG_INSN_P (insn))
3981 enum attr_type type = get_attr_type (insn);
3983 if (type == TYPE_STALL)
3985 gcc_assert (n_filled == 0);
3986 delete_this = insn;
3988 else
3990 if (type == TYPE_DSP32 || type == TYPE_DSP32SHIFTIMM)
3991 slot[0] = insn;
3992 else if (slot[1] == NULL_RTX)
3993 slot[1] = insn;
3994 else
3995 slot[2] = insn;
3996 n_filled++;
4000 next = NEXT_INSN (insn);
4001 while (next && insn != BB_END (bb)
4002 && !(INSN_P (next)
4003 && GET_CODE (PATTERN (next)) != USE
4004 && GET_CODE (PATTERN (next)) != CLOBBER))
4006 insn = next;
4007 next = NEXT_INSN (insn);
4010 /* BB_END can change due to emitting extra NOPs, so check here. */
4011 at_end = insn == BB_END (bb);
4012 if (delete_this == NULL_RTX && (at_end || GET_MODE (next) == TImode))
4014 if ((n_filled < 2
4015 || !gen_one_bundle (slot))
4016 && slot[0] != NULL_RTX)
4018 rtx pat = PATTERN (slot[0]);
4019 if (GET_CODE (pat) == SET
4020 && GET_CODE (SET_SRC (pat)) == UNSPEC
4021 && XINT (SET_SRC (pat), 1) == UNSPEC_32BIT)
4023 SET_SRC (pat) = XVECEXP (SET_SRC (pat), 0, 0);
4024 INSN_CODE (slot[0]) = -1;
4025 df_insn_rescan (slot[0]);
4028 n_filled = 0;
4029 slot[0] = slot[1] = slot[2] = NULL;
4031 if (delete_this != NULL_RTX)
4032 delete_insn (delete_this);
4033 if (at_end)
4034 break;
4039 /* Ensure that no var tracking notes are emitted in the middle of a
4040 three-instruction bundle. */
4042 static void
4043 reorder_var_tracking_notes (void)
4045 basic_block bb;
4046 FOR_EACH_BB_FN (bb, cfun)
4048 rtx_insn *insn, *next;
4049 rtx_insn *queue = NULL;
4050 bool in_bundle = false;
4052 for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = next)
4054 next = NEXT_INSN (insn);
4056 if (INSN_P (insn))
4058 /* Emit queued up notes at the last instruction of a bundle. */
4059 if (GET_MODE (insn) == QImode)
4061 while (queue)
4063 rtx_insn *next_queue = PREV_INSN (queue);
4064 SET_PREV_INSN (NEXT_INSN (insn)) = queue;
4065 SET_NEXT_INSN (queue) = NEXT_INSN (insn);
4066 SET_NEXT_INSN (insn) = queue;
4067 SET_PREV_INSN (queue) = insn;
4068 queue = next_queue;
4070 in_bundle = false;
4072 else if (GET_MODE (insn) == SImode)
4073 in_bundle = true;
4075 else if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION)
4077 if (in_bundle)
4079 rtx_insn *prev = PREV_INSN (insn);
4080 SET_PREV_INSN (next) = prev;
4081 SET_NEXT_INSN (prev) = next;
4083 SET_PREV_INSN (insn) = queue;
4084 queue = insn;
4091 /* On some silicon revisions, functions shorter than a certain number of cycles
4092 can cause unpredictable behaviour. Work around this by adding NOPs as
4093 needed. */
4094 static void
4095 workaround_rts_anomaly (void)
4097 rtx_insn *insn, *first_insn = NULL;
4098 int cycles = 4;
4100 if (! ENABLE_WA_RETS)
4101 return;
4103 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4105 rtx pat;
4107 if (BARRIER_P (insn))
4108 return;
4110 if (NOTE_P (insn) || LABEL_P (insn))
4111 continue;
4113 if (JUMP_TABLE_DATA_P (insn))
4114 continue;
4116 if (first_insn == NULL_RTX)
4117 first_insn = insn;
4118 pat = PATTERN (insn);
4119 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4120 || GET_CODE (pat) == ASM_INPUT
4121 || asm_noperands (pat) >= 0)
4122 continue;
4124 if (CALL_P (insn))
4125 return;
4127 if (JUMP_P (insn))
4129 if (recog_memoized (insn) == CODE_FOR_return_internal)
4130 break;
4132 /* Nothing to worry about for direct jumps. */
4133 if (!any_condjump_p (insn))
4134 return;
4135 if (cycles <= 1)
4136 return;
4137 cycles--;
4139 else if (INSN_P (insn))
4141 rtx pat = PATTERN (insn);
4142 int this_cycles = 1;
4144 if (GET_CODE (pat) == PARALLEL)
4146 if (analyze_push_multiple_operation (pat)
4147 || analyze_pop_multiple_operation (pat))
4148 this_cycles = n_regs_to_save;
4150 else
4152 int icode = recog_memoized (insn);
4154 if (icode == CODE_FOR_link)
4155 this_cycles = 4;
4156 else if (icode == CODE_FOR_unlink)
4157 this_cycles = 3;
4158 else if (icode == CODE_FOR_mulsi3)
4159 this_cycles = 5;
4161 if (this_cycles >= cycles)
4162 return;
4164 cycles -= this_cycles;
4167 while (cycles > 0)
4169 emit_insn_before (gen_nop (), first_insn);
4170 cycles--;
4174 /* Return an insn type for INSN that can be used by the caller for anomaly
4175 workarounds. This differs from plain get_attr_type in that it handles
4176 SEQUENCEs. */
4178 static enum attr_type
4179 type_for_anomaly (rtx insn)
4181 rtx pat = PATTERN (insn);
4182 if (GET_CODE (pat) == SEQUENCE)
4184 enum attr_type t;
4185 t = get_attr_type (XVECEXP (pat, 0, 1));
4186 if (t == TYPE_MCLD)
4187 return t;
4188 t = get_attr_type (XVECEXP (pat, 0, 2));
4189 if (t == TYPE_MCLD)
4190 return t;
4191 return TYPE_MCST;
4193 else
4194 return get_attr_type (insn);
4197 /* Return true iff the address found in MEM is based on the register
4198 NP_REG and optionally has a positive offset. */
4199 static bool
4200 harmless_null_pointer_p (rtx mem, int np_reg)
4202 mem = XEXP (mem, 0);
4203 if (GET_CODE (mem) == POST_INC || GET_CODE (mem) == POST_DEC)
4204 mem = XEXP (mem, 0);
4205 if (REG_P (mem) && (int) REGNO (mem) == np_reg)
4206 return true;
4207 if (GET_CODE (mem) == PLUS
4208 && REG_P (XEXP (mem, 0)) && (int) REGNO (XEXP (mem, 0)) == np_reg)
4210 mem = XEXP (mem, 1);
4211 if (GET_CODE (mem) == CONST_INT && INTVAL (mem) > 0)
4212 return true;
4214 return false;
4217 /* Return nonzero if INSN contains any loads that may trap. */
4219 static bool
4220 trapping_loads_p (rtx insn, int np_reg, bool after_np_branch)
4222 rtx mem = SET_SRC (single_set (insn));
4224 if (!after_np_branch)
4225 np_reg = -1;
4226 return ((np_reg == -1 || !harmless_null_pointer_p (mem, np_reg))
4227 && may_trap_p (mem));
4230 /* Return INSN if it is of TYPE_MCLD. Alternatively, if INSN is the start of
4231 a three-insn bundle, see if one of them is a load and return that if so.
4232 Return NULL_RTX if the insn does not contain loads. */
4233 static rtx
4234 find_load (rtx_insn *insn)
4236 if (!NONDEBUG_INSN_P (insn))
4237 return NULL_RTX;
4238 if (get_attr_type (insn) == TYPE_MCLD)
4239 return insn;
4240 if (GET_MODE (insn) != SImode)
4241 return NULL_RTX;
4242 do {
4243 insn = NEXT_INSN (insn);
4244 if ((GET_MODE (insn) == SImode || GET_MODE (insn) == QImode)
4245 && get_attr_type (insn) == TYPE_MCLD)
4246 return insn;
4247 } while (GET_MODE (insn) != QImode);
4248 return NULL_RTX;
4251 /* Determine whether PAT is an indirect call pattern. */
4252 static bool
4253 indirect_call_p (rtx pat)
4255 if (GET_CODE (pat) == PARALLEL)
4256 pat = XVECEXP (pat, 0, 0);
4257 if (GET_CODE (pat) == SET)
4258 pat = SET_SRC (pat);
4259 gcc_assert (GET_CODE (pat) == CALL);
4260 pat = XEXP (pat, 0);
4261 gcc_assert (GET_CODE (pat) == MEM);
4262 pat = XEXP (pat, 0);
4264 return REG_P (pat);
4267 /* During workaround_speculation, track whether we're in the shadow of a
4268 conditional branch that tests a P register for NULL. If so, we can omit
4269 emitting NOPs if we see a load from that P register, since a speculative
4270 access at address 0 isn't a problem, and the load is executed in all other
4271 cases anyway.
4272 Global for communication with note_np_check_stores through note_stores.
4274 int np_check_regno = -1;
4275 bool np_after_branch = false;
4277 /* Subroutine of workaround_speculation, called through note_stores. */
4278 static void
4279 note_np_check_stores (rtx x, const_rtx pat ATTRIBUTE_UNUSED,
4280 void *data ATTRIBUTE_UNUSED)
4282 if (REG_P (x) && (REGNO (x) == REG_CC || (int) REGNO (x) == np_check_regno))
4283 np_check_regno = -1;
4286 static void
4287 workaround_speculation (void)
4289 rtx_insn *insn, *next;
4290 rtx_insn *last_condjump = NULL;
4291 int cycles_since_jump = INT_MAX;
4292 int delay_added = 0;
4294 if (! ENABLE_WA_SPECULATIVE_LOADS && ! ENABLE_WA_SPECULATIVE_SYNCS
4295 && ! ENABLE_WA_INDIRECT_CALLS)
4296 return;
4298 /* First pass: find predicted-false branches; if something after them
4299 needs nops, insert them or change the branch to predict true. */
4300 for (insn = get_insns (); insn; insn = next)
4302 rtx pat;
4303 int delay_needed = 0;
4305 next = find_next_insn_start (insn);
4307 if (NOTE_P (insn) || BARRIER_P (insn))
4308 continue;
4309 if (JUMP_TABLE_DATA_P (insn))
4310 continue;
4312 if (LABEL_P (insn))
4314 np_check_regno = -1;
4315 continue;
4318 pat = PATTERN (insn);
4319 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
4320 continue;
4322 if (GET_CODE (pat) == ASM_INPUT || asm_noperands (pat) >= 0)
4324 np_check_regno = -1;
4325 continue;
4328 if (JUMP_P (insn))
4330 /* Is this a condjump based on a null pointer comparison we saw
4331 earlier? */
4332 if (np_check_regno != -1
4333 && recog_memoized (insn) == CODE_FOR_cbranchbi4)
4335 rtx op = XEXP (SET_SRC (PATTERN (insn)), 0);
4336 gcc_assert (GET_CODE (op) == EQ || GET_CODE (op) == NE);
4337 if (GET_CODE (op) == NE)
4338 np_after_branch = true;
4340 if (any_condjump_p (insn)
4341 && ! cbranch_predicted_taken_p (insn))
4343 last_condjump = insn;
4344 delay_added = 0;
4345 cycles_since_jump = 0;
4347 else
4348 cycles_since_jump = INT_MAX;
4350 else if (CALL_P (insn))
4352 np_check_regno = -1;
4353 if (cycles_since_jump < INT_MAX)
4354 cycles_since_jump++;
4355 if (indirect_call_p (pat) && ENABLE_WA_INDIRECT_CALLS)
4357 delay_needed = 3;
4360 else if (NONDEBUG_INSN_P (insn))
4362 rtx load_insn = find_load (insn);
4363 enum attr_type type = type_for_anomaly (insn);
4365 if (cycles_since_jump < INT_MAX)
4366 cycles_since_jump++;
4368 /* Detect a comparison of a P register with zero. If we later
4369 see a condjump based on it, we have found a null pointer
4370 check. */
4371 if (recog_memoized (insn) == CODE_FOR_compare_eq)
4373 rtx src = SET_SRC (PATTERN (insn));
4374 if (REG_P (XEXP (src, 0))
4375 && P_REGNO_P (REGNO (XEXP (src, 0)))
4376 && XEXP (src, 1) == const0_rtx)
4378 np_check_regno = REGNO (XEXP (src, 0));
4379 np_after_branch = false;
4381 else
4382 np_check_regno = -1;
4385 if (load_insn && ENABLE_WA_SPECULATIVE_LOADS)
4387 if (trapping_loads_p (load_insn, np_check_regno,
4388 np_after_branch))
4389 delay_needed = 4;
4391 else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS)
4392 delay_needed = 3;
4394 /* See if we need to forget about a null pointer comparison
4395 we found earlier. */
4396 if (recog_memoized (insn) != CODE_FOR_compare_eq)
4398 note_stores (PATTERN (insn), note_np_check_stores, NULL);
4399 if (np_check_regno != -1)
4401 if (find_regno_note (insn, REG_INC, np_check_regno))
4402 np_check_regno = -1;
4408 if (delay_needed > cycles_since_jump
4409 && (delay_needed - cycles_since_jump) > delay_added)
4411 rtx pat1;
4412 int num_clobbers;
4413 rtx *op = recog_data.operand;
4415 delay_needed -= cycles_since_jump;
4417 extract_insn (last_condjump);
4418 if (optimize_size)
4420 pat1 = gen_cbranch_predicted_taken (op[0], op[1], op[2],
4421 op[3]);
4422 cycles_since_jump = INT_MAX;
4424 else
4426 /* Do not adjust cycles_since_jump in this case, so that
4427 we'll increase the number of NOPs for a subsequent insn
4428 if necessary. */
4429 pat1 = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
4430 GEN_INT (delay_needed));
4431 delay_added = delay_needed;
4433 PATTERN (last_condjump) = pat1;
4434 INSN_CODE (last_condjump) = recog (pat1, insn, &num_clobbers);
4436 if (CALL_P (insn))
4438 cycles_since_jump = INT_MAX;
4439 delay_added = 0;
4443 /* Second pass: for predicted-true branches, see if anything at the
4444 branch destination needs extra nops. */
4445 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4447 int cycles_since_jump;
4448 if (JUMP_P (insn)
4449 && any_condjump_p (insn)
4450 && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken
4451 || cbranch_predicted_taken_p (insn)))
4453 rtx_insn *target = JUMP_LABEL_AS_INSN (insn);
4454 rtx label = target;
4455 rtx_insn *next_tgt;
4457 cycles_since_jump = 0;
4458 for (; target && cycles_since_jump < 3; target = next_tgt)
4460 rtx pat;
4462 next_tgt = find_next_insn_start (target);
4464 if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
4465 continue;
4467 if (JUMP_TABLE_DATA_P (target))
4468 continue;
4470 pat = PATTERN (target);
4471 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4472 || GET_CODE (pat) == ASM_INPUT
4473 || asm_noperands (pat) >= 0)
4474 continue;
4476 if (NONDEBUG_INSN_P (target))
4478 rtx load_insn = find_load (target);
4479 enum attr_type type = type_for_anomaly (target);
4480 int delay_needed = 0;
4481 if (cycles_since_jump < INT_MAX)
4482 cycles_since_jump++;
4484 if (load_insn && ENABLE_WA_SPECULATIVE_LOADS)
4486 if (trapping_loads_p (load_insn, -1, false))
4487 delay_needed = 2;
4489 else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS)
4490 delay_needed = 2;
4492 if (delay_needed > cycles_since_jump)
4494 rtx prev = prev_real_insn (label);
4495 delay_needed -= cycles_since_jump;
4496 if (dump_file)
4497 fprintf (dump_file, "Adding %d nops after %d\n",
4498 delay_needed, INSN_UID (label));
4499 if (JUMP_P (prev)
4500 && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops)
4502 rtx x;
4503 HOST_WIDE_INT v;
4505 if (dump_file)
4506 fprintf (dump_file,
4507 "Reducing nops on insn %d.\n",
4508 INSN_UID (prev));
4509 x = PATTERN (prev);
4510 x = XVECEXP (x, 0, 1);
4511 v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed;
4512 XVECEXP (x, 0, 0) = GEN_INT (v);
4514 while (delay_needed-- > 0)
4515 emit_insn_after (gen_nop (), label);
4516 break;
4524 /* Called just before the final scheduling pass. If we need to insert NOPs
4525 later on to work around speculative loads, insert special placeholder
4526 insns that cause loads to be delayed for as many cycles as necessary
4527 (and possible). This reduces the number of NOPs we need to add.
4528 The dummy insns we generate are later removed by bfin_gen_bundles. */
4529 static void
4530 add_sched_insns_for_speculation (void)
4532 rtx_insn *insn;
4534 if (! ENABLE_WA_SPECULATIVE_LOADS && ! ENABLE_WA_SPECULATIVE_SYNCS
4535 && ! ENABLE_WA_INDIRECT_CALLS)
4536 return;
4538 /* First pass: find predicted-false branches; if something after them
4539 needs nops, insert them or change the branch to predict true. */
4540 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4542 rtx pat;
4544 if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
4545 continue;
4546 if (JUMP_TABLE_DATA_P (insn))
4547 continue;
4549 pat = PATTERN (insn);
4550 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4551 || GET_CODE (pat) == ASM_INPUT
4552 || asm_noperands (pat) >= 0)
4553 continue;
4555 if (JUMP_P (insn))
4557 if (any_condjump_p (insn)
4558 && !cbranch_predicted_taken_p (insn))
4560 rtx n = next_real_insn (insn);
4561 emit_insn_before (gen_stall (GEN_INT (3)), n);
4566 /* Second pass: for predicted-true branches, see if anything at the
4567 branch destination needs extra nops. */
4568 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4570 if (JUMP_P (insn)
4571 && any_condjump_p (insn)
4572 && (cbranch_predicted_taken_p (insn)))
4574 rtx target = JUMP_LABEL (insn);
4575 rtx next = next_real_insn (target);
4577 if (GET_CODE (PATTERN (next)) == UNSPEC_VOLATILE
4578 && get_attr_type (next) == TYPE_STALL)
4579 continue;
4580 emit_insn_before (gen_stall (GEN_INT (1)), next);
4585 /* We use the machine specific reorg pass for emitting CSYNC instructions
4586 after conditional branches as needed.
4588 The Blackfin is unusual in that a code sequence like
4589 if cc jump label
4590 r0 = (p0)
4591 may speculatively perform the load even if the condition isn't true. This
4592 happens for a branch that is predicted not taken, because the pipeline
4593 isn't flushed or stalled, so the early stages of the following instructions,
4594 which perform the memory reference, are allowed to execute before the
4595 jump condition is evaluated.
4596 Therefore, we must insert additional instructions in all places where this
4597 could lead to incorrect behavior. The manual recommends CSYNC, while
4598 VDSP seems to use NOPs (even though its corresponding compiler option is
4599 named CSYNC).
4601 When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
4602 When optimizing for size, we turn the branch into a predicted taken one.
4603 This may be slower due to mispredicts, but saves code size. */
4605 static void
4606 bfin_reorg (void)
4608 /* We are freeing block_for_insn in the toplev to keep compatibility
4609 with old MDEP_REORGS that are not CFG based. Recompute it now. */
4610 compute_bb_for_insn ();
4612 if (flag_schedule_insns_after_reload)
4614 splitting_for_sched = 1;
4615 split_all_insns ();
4616 splitting_for_sched = 0;
4618 add_sched_insns_for_speculation ();
4620 timevar_push (TV_SCHED2);
4621 if (flag_selective_scheduling2
4622 && !maybe_skip_selective_scheduling ())
4623 run_selective_scheduling ();
4624 else
4625 schedule_insns ();
4626 timevar_pop (TV_SCHED2);
4628 /* Examine the schedule and insert nops as necessary for 64-bit parallel
4629 instructions. */
4630 bfin_gen_bundles ();
4633 df_analyze ();
4635 /* Doloop optimization */
4636 if (cfun->machine->has_hardware_loops)
4637 bfin_reorg_loops ();
4639 workaround_speculation ();
4641 if (flag_var_tracking)
4643 timevar_push (TV_VAR_TRACKING);
4644 variable_tracking_main ();
4645 reorder_var_tracking_notes ();
4646 timevar_pop (TV_VAR_TRACKING);
4649 df_finish_pass (false);
4651 workaround_rts_anomaly ();
4654 /* Handle interrupt_handler, exception_handler and nmi_handler function
4655 attributes; arguments as in struct attribute_spec.handler. */
4657 static tree
4658 handle_int_attribute (tree *node, tree name,
4659 tree args ATTRIBUTE_UNUSED,
4660 int flags ATTRIBUTE_UNUSED,
4661 bool *no_add_attrs)
4663 tree x = *node;
4664 if (TREE_CODE (x) == FUNCTION_DECL)
4665 x = TREE_TYPE (x);
4667 if (TREE_CODE (x) != FUNCTION_TYPE)
4669 warning (OPT_Wattributes, "%qE attribute only applies to functions",
4670 name);
4671 *no_add_attrs = true;
4673 else if (funkind (x) != SUBROUTINE)
4674 error ("multiple function type attributes specified");
4676 return NULL_TREE;
4679 /* Return 0 if the attributes for two types are incompatible, 1 if they
4680 are compatible, and 2 if they are nearly compatible (which causes a
4681 warning to be generated). */
4683 static int
4684 bfin_comp_type_attributes (const_tree type1, const_tree type2)
4686 e_funkind kind1, kind2;
4688 if (TREE_CODE (type1) != FUNCTION_TYPE)
4689 return 1;
4691 kind1 = funkind (type1);
4692 kind2 = funkind (type2);
4694 if (kind1 != kind2)
4695 return 0;
4697 /* Check for mismatched modifiers */
4698 if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
4699 != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
4700 return 0;
4702 if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
4703 != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
4704 return 0;
4706 if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
4707 != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
4708 return 0;
4710 if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1))
4711 != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2)))
4712 return 0;
4714 return 1;
4717 /* Handle a "longcall" or "shortcall" attribute; arguments as in
4718 struct attribute_spec.handler. */
4720 static tree
4721 bfin_handle_longcall_attribute (tree *node, tree name,
4722 tree args ATTRIBUTE_UNUSED,
4723 int flags ATTRIBUTE_UNUSED,
4724 bool *no_add_attrs)
4726 if (TREE_CODE (*node) != FUNCTION_TYPE
4727 && TREE_CODE (*node) != FIELD_DECL
4728 && TREE_CODE (*node) != TYPE_DECL)
4730 warning (OPT_Wattributes, "%qE attribute only applies to functions",
4731 name);
4732 *no_add_attrs = true;
4735 if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0
4736 && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node)))
4737 || (strcmp (IDENTIFIER_POINTER (name), "shortcall") == 0
4738 && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node))))
4740 warning (OPT_Wattributes,
4741 "can%'t apply both longcall and shortcall attributes to the same function");
4742 *no_add_attrs = true;
4745 return NULL_TREE;
4748 /* Handle a "l1_text" attribute; arguments as in
4749 struct attribute_spec.handler. */
4751 static tree
4752 bfin_handle_l1_text_attribute (tree *node, tree name, tree ARG_UNUSED (args),
4753 int ARG_UNUSED (flags), bool *no_add_attrs)
4755 tree decl = *node;
4757 if (TREE_CODE (decl) != FUNCTION_DECL)
4759 error ("%qE attribute only applies to functions",
4760 name);
4761 *no_add_attrs = true;
4764 /* The decl may have already been given a section attribute
4765 from a previous declaration. Ensure they match. */
4766 else if (DECL_SECTION_NAME (decl) != NULL
4767 && strcmp (DECL_SECTION_NAME (decl),
4768 ".l1.text") != 0)
4770 error ("section of %q+D conflicts with previous declaration",
4771 decl);
4772 *no_add_attrs = true;
4774 else
4775 set_decl_section_name (decl, ".l1.text");
4777 return NULL_TREE;
4780 /* Handle a "l1_data", "l1_data_A" or "l1_data_B" attribute;
4781 arguments as in struct attribute_spec.handler. */
4783 static tree
4784 bfin_handle_l1_data_attribute (tree *node, tree name, tree ARG_UNUSED (args),
4785 int ARG_UNUSED (flags), bool *no_add_attrs)
4787 tree decl = *node;
4789 if (TREE_CODE (decl) != VAR_DECL)
4791 error ("%qE attribute only applies to variables",
4792 name);
4793 *no_add_attrs = true;
4795 else if (current_function_decl != NULL_TREE
4796 && !TREE_STATIC (decl))
4798 error ("%qE attribute cannot be specified for local variables",
4799 name);
4800 *no_add_attrs = true;
4802 else
4804 const char *section_name;
4806 if (strcmp (IDENTIFIER_POINTER (name), "l1_data") == 0)
4807 section_name = ".l1.data";
4808 else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_A") == 0)
4809 section_name = ".l1.data.A";
4810 else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_B") == 0)
4811 section_name = ".l1.data.B";
4812 else
4813 gcc_unreachable ();
4815 /* The decl may have already been given a section attribute
4816 from a previous declaration. Ensure they match. */
4817 if (DECL_SECTION_NAME (decl) != NULL
4818 && strcmp (DECL_SECTION_NAME (decl),
4819 section_name) != 0)
4821 error ("section of %q+D conflicts with previous declaration",
4822 decl);
4823 *no_add_attrs = true;
4825 else
4826 set_decl_section_name (decl, section_name);
4829 return NULL_TREE;
4832 /* Handle a "l2" attribute; arguments as in struct attribute_spec.handler. */
4834 static tree
4835 bfin_handle_l2_attribute (tree *node, tree ARG_UNUSED (name),
4836 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
4837 bool *no_add_attrs)
4839 tree decl = *node;
4841 if (TREE_CODE (decl) == FUNCTION_DECL)
4843 if (DECL_SECTION_NAME (decl) != NULL
4844 && strcmp (DECL_SECTION_NAME (decl),
4845 ".l2.text") != 0)
4847 error ("section of %q+D conflicts with previous declaration",
4848 decl);
4849 *no_add_attrs = true;
4851 else
4852 set_decl_section_name (decl, ".l2.text");
4854 else if (TREE_CODE (decl) == VAR_DECL)
4856 if (DECL_SECTION_NAME (decl) != NULL
4857 && strcmp (DECL_SECTION_NAME (decl),
4858 ".l2.data") != 0)
4860 error ("section of %q+D conflicts with previous declaration",
4861 decl);
4862 *no_add_attrs = true;
4864 else
4865 set_decl_section_name (decl, ".l2.data");
4868 return NULL_TREE;
4871 /* Table of valid machine attributes. */
4872 static const struct attribute_spec bfin_attribute_table[] =
4874 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
4875 affects_type_identity } */
4876 { "interrupt_handler", 0, 0, false, true, true, handle_int_attribute,
4877 false },
4878 { "exception_handler", 0, 0, false, true, true, handle_int_attribute,
4879 false },
4880 { "nmi_handler", 0, 0, false, true, true, handle_int_attribute, false },
4881 { "nesting", 0, 0, false, true, true, NULL, false },
4882 { "kspisusp", 0, 0, false, true, true, NULL, false },
4883 { "saveall", 0, 0, false, true, true, NULL, false },
4884 { "longcall", 0, 0, false, true, true, bfin_handle_longcall_attribute,
4885 false },
4886 { "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute,
4887 false },
4888 { "l1_text", 0, 0, true, false, false, bfin_handle_l1_text_attribute,
4889 false },
4890 { "l1_data", 0, 0, true, false, false, bfin_handle_l1_data_attribute,
4891 false },
4892 { "l1_data_A", 0, 0, true, false, false, bfin_handle_l1_data_attribute,
4893 false },
4894 { "l1_data_B", 0, 0, true, false, false, bfin_handle_l1_data_attribute,
4895 false },
4896 { "l2", 0, 0, true, false, false, bfin_handle_l2_attribute, false },
4897 { NULL, 0, 0, false, false, false, NULL, false }
4900 /* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to
4901 tell the assembler to generate pointers to function descriptors in
4902 some cases. */
4904 static bool
4905 bfin_assemble_integer (rtx value, unsigned int size, int aligned_p)
4907 if (TARGET_FDPIC && size == UNITS_PER_WORD)
4909 if (GET_CODE (value) == SYMBOL_REF
4910 && SYMBOL_REF_FUNCTION_P (value))
4912 fputs ("\t.picptr\tfuncdesc(", asm_out_file);
4913 output_addr_const (asm_out_file, value);
4914 fputs (")\n", asm_out_file);
4915 return true;
4917 if (!aligned_p)
4919 /* We've set the unaligned SI op to NULL, so we always have to
4920 handle the unaligned case here. */
4921 assemble_integer_with_op ("\t.4byte\t", value);
4922 return true;
4925 return default_assemble_integer (value, size, aligned_p);
4928 /* Output the assembler code for a thunk function. THUNK_DECL is the
4929 declaration for the thunk function itself, FUNCTION is the decl for
4930 the target function. DELTA is an immediate constant offset to be
4931 added to THIS. If VCALL_OFFSET is nonzero, the word at
4932 *(*this + vcall_offset) should be added to THIS. */
4934 static void
4935 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
4936 tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
4937 HOST_WIDE_INT vcall_offset, tree function)
4939 rtx xops[3];
4940 /* The this parameter is passed as the first argument. */
4941 rtx this_rtx = gen_rtx_REG (Pmode, REG_R0);
4943 /* Adjust the this parameter by a fixed constant. */
4944 if (delta)
4946 xops[1] = this_rtx;
4947 if (delta >= -64 && delta <= 63)
4949 xops[0] = GEN_INT (delta);
4950 output_asm_insn ("%1 += %0;", xops);
4952 else if (delta >= -128 && delta < -64)
4954 xops[0] = GEN_INT (delta + 64);
4955 output_asm_insn ("%1 += -64; %1 += %0;", xops);
4957 else if (delta > 63 && delta <= 126)
4959 xops[0] = GEN_INT (delta - 63);
4960 output_asm_insn ("%1 += 63; %1 += %0;", xops);
4962 else
4964 xops[0] = GEN_INT (delta);
4965 output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
4969 /* Adjust the this parameter by a value stored in the vtable. */
4970 if (vcall_offset)
4972 rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
4973 rtx tmp = gen_rtx_REG (Pmode, REG_R3);
4975 xops[1] = tmp;
4976 xops[2] = p2tmp;
4977 output_asm_insn ("%2 = r0; %2 = [%2];", xops);
4979 /* Adjust the this parameter. */
4980 xops[0] = gen_rtx_MEM (Pmode, plus_constant (Pmode, p2tmp,
4981 vcall_offset));
4982 if (!memory_operand (xops[0], Pmode))
4984 rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
4985 xops[0] = GEN_INT (vcall_offset);
4986 xops[1] = tmp2;
4987 output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
4988 xops[0] = gen_rtx_MEM (Pmode, p2tmp);
4990 xops[2] = this_rtx;
4991 output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
4994 xops[0] = XEXP (DECL_RTL (function), 0);
4995 if (1 || !flag_pic || (*targetm.binds_local_p) (function))
4996 output_asm_insn ("jump.l\t%P0", xops);
4999 /* Codes for all the Blackfin builtins. */
5000 enum bfin_builtins
5002 BFIN_BUILTIN_CSYNC,
5003 BFIN_BUILTIN_SSYNC,
5004 BFIN_BUILTIN_ONES,
5005 BFIN_BUILTIN_COMPOSE_2X16,
5006 BFIN_BUILTIN_EXTRACTLO,
5007 BFIN_BUILTIN_EXTRACTHI,
5009 BFIN_BUILTIN_SSADD_2X16,
5010 BFIN_BUILTIN_SSSUB_2X16,
5011 BFIN_BUILTIN_SSADDSUB_2X16,
5012 BFIN_BUILTIN_SSSUBADD_2X16,
5013 BFIN_BUILTIN_MULT_2X16,
5014 BFIN_BUILTIN_MULTR_2X16,
5015 BFIN_BUILTIN_NEG_2X16,
5016 BFIN_BUILTIN_ABS_2X16,
5017 BFIN_BUILTIN_MIN_2X16,
5018 BFIN_BUILTIN_MAX_2X16,
5020 BFIN_BUILTIN_SSADD_1X16,
5021 BFIN_BUILTIN_SSSUB_1X16,
5022 BFIN_BUILTIN_MULT_1X16,
5023 BFIN_BUILTIN_MULTR_1X16,
5024 BFIN_BUILTIN_NORM_1X16,
5025 BFIN_BUILTIN_NEG_1X16,
5026 BFIN_BUILTIN_ABS_1X16,
5027 BFIN_BUILTIN_MIN_1X16,
5028 BFIN_BUILTIN_MAX_1X16,
5030 BFIN_BUILTIN_SUM_2X16,
5031 BFIN_BUILTIN_DIFFHL_2X16,
5032 BFIN_BUILTIN_DIFFLH_2X16,
5034 BFIN_BUILTIN_SSADD_1X32,
5035 BFIN_BUILTIN_SSSUB_1X32,
5036 BFIN_BUILTIN_NORM_1X32,
5037 BFIN_BUILTIN_ROUND_1X32,
5038 BFIN_BUILTIN_NEG_1X32,
5039 BFIN_BUILTIN_ABS_1X32,
5040 BFIN_BUILTIN_MIN_1X32,
5041 BFIN_BUILTIN_MAX_1X32,
5042 BFIN_BUILTIN_MULT_1X32,
5043 BFIN_BUILTIN_MULT_1X32X32,
5044 BFIN_BUILTIN_MULT_1X32X32NS,
5046 BFIN_BUILTIN_MULHISILL,
5047 BFIN_BUILTIN_MULHISILH,
5048 BFIN_BUILTIN_MULHISIHL,
5049 BFIN_BUILTIN_MULHISIHH,
5051 BFIN_BUILTIN_LSHIFT_1X16,
5052 BFIN_BUILTIN_LSHIFT_2X16,
5053 BFIN_BUILTIN_SSASHIFT_1X16,
5054 BFIN_BUILTIN_SSASHIFT_2X16,
5055 BFIN_BUILTIN_SSASHIFT_1X32,
5057 BFIN_BUILTIN_CPLX_MUL_16,
5058 BFIN_BUILTIN_CPLX_MAC_16,
5059 BFIN_BUILTIN_CPLX_MSU_16,
5061 BFIN_BUILTIN_CPLX_MUL_16_S40,
5062 BFIN_BUILTIN_CPLX_MAC_16_S40,
5063 BFIN_BUILTIN_CPLX_MSU_16_S40,
5065 BFIN_BUILTIN_CPLX_SQU,
5067 BFIN_BUILTIN_LOADBYTES,
5069 BFIN_BUILTIN_MAX
5072 #define def_builtin(NAME, TYPE, CODE) \
5073 do { \
5074 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
5075 NULL, NULL_TREE); \
5076 } while (0)
5078 /* Set up all builtin functions for this target. */
5079 static void
5080 bfin_init_builtins (void)
5082 tree V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
5083 tree void_ftype_void
5084 = build_function_type_list (void_type_node, NULL_TREE);
5085 tree short_ftype_short
5086 = build_function_type_list (short_integer_type_node, short_integer_type_node,
5087 NULL_TREE);
5088 tree short_ftype_int_int
5089 = build_function_type_list (short_integer_type_node, integer_type_node,
5090 integer_type_node, NULL_TREE);
5091 tree int_ftype_int_int
5092 = build_function_type_list (integer_type_node, integer_type_node,
5093 integer_type_node, NULL_TREE);
5094 tree int_ftype_int
5095 = build_function_type_list (integer_type_node, integer_type_node,
5096 NULL_TREE);
5097 tree short_ftype_int
5098 = build_function_type_list (short_integer_type_node, integer_type_node,
5099 NULL_TREE);
5100 tree int_ftype_v2hi_v2hi
5101 = build_function_type_list (integer_type_node, V2HI_type_node,
5102 V2HI_type_node, NULL_TREE);
5103 tree v2hi_ftype_v2hi_v2hi
5104 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5105 V2HI_type_node, NULL_TREE);
5106 tree v2hi_ftype_v2hi_v2hi_v2hi
5107 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5108 V2HI_type_node, V2HI_type_node, NULL_TREE);
5109 tree v2hi_ftype_int_int
5110 = build_function_type_list (V2HI_type_node, integer_type_node,
5111 integer_type_node, NULL_TREE);
5112 tree v2hi_ftype_v2hi_int
5113 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5114 integer_type_node, NULL_TREE);
5115 tree int_ftype_short_short
5116 = build_function_type_list (integer_type_node, short_integer_type_node,
5117 short_integer_type_node, NULL_TREE);
5118 tree v2hi_ftype_v2hi
5119 = build_function_type_list (V2HI_type_node, V2HI_type_node, NULL_TREE);
5120 tree short_ftype_v2hi
5121 = build_function_type_list (short_integer_type_node, V2HI_type_node,
5122 NULL_TREE);
5123 tree int_ftype_pint
5124 = build_function_type_list (integer_type_node,
5125 build_pointer_type (integer_type_node),
5126 NULL_TREE);
5128 /* Add the remaining MMX insns with somewhat more complicated types. */
5129 def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC);
5130 def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC);
5132 def_builtin ("__builtin_bfin_ones", short_ftype_int, BFIN_BUILTIN_ONES);
5134 def_builtin ("__builtin_bfin_compose_2x16", v2hi_ftype_int_int,
5135 BFIN_BUILTIN_COMPOSE_2X16);
5136 def_builtin ("__builtin_bfin_extract_hi", short_ftype_v2hi,
5137 BFIN_BUILTIN_EXTRACTHI);
5138 def_builtin ("__builtin_bfin_extract_lo", short_ftype_v2hi,
5139 BFIN_BUILTIN_EXTRACTLO);
5141 def_builtin ("__builtin_bfin_min_fr2x16", v2hi_ftype_v2hi_v2hi,
5142 BFIN_BUILTIN_MIN_2X16);
5143 def_builtin ("__builtin_bfin_max_fr2x16", v2hi_ftype_v2hi_v2hi,
5144 BFIN_BUILTIN_MAX_2X16);
5146 def_builtin ("__builtin_bfin_add_fr2x16", v2hi_ftype_v2hi_v2hi,
5147 BFIN_BUILTIN_SSADD_2X16);
5148 def_builtin ("__builtin_bfin_sub_fr2x16", v2hi_ftype_v2hi_v2hi,
5149 BFIN_BUILTIN_SSSUB_2X16);
5150 def_builtin ("__builtin_bfin_dspaddsubsat", v2hi_ftype_v2hi_v2hi,
5151 BFIN_BUILTIN_SSADDSUB_2X16);
5152 def_builtin ("__builtin_bfin_dspsubaddsat", v2hi_ftype_v2hi_v2hi,
5153 BFIN_BUILTIN_SSSUBADD_2X16);
5154 def_builtin ("__builtin_bfin_mult_fr2x16", v2hi_ftype_v2hi_v2hi,
5155 BFIN_BUILTIN_MULT_2X16);
5156 def_builtin ("__builtin_bfin_multr_fr2x16", v2hi_ftype_v2hi_v2hi,
5157 BFIN_BUILTIN_MULTR_2X16);
5158 def_builtin ("__builtin_bfin_negate_fr2x16", v2hi_ftype_v2hi,
5159 BFIN_BUILTIN_NEG_2X16);
5160 def_builtin ("__builtin_bfin_abs_fr2x16", v2hi_ftype_v2hi,
5161 BFIN_BUILTIN_ABS_2X16);
5163 def_builtin ("__builtin_bfin_min_fr1x16", short_ftype_int_int,
5164 BFIN_BUILTIN_MIN_1X16);
5165 def_builtin ("__builtin_bfin_max_fr1x16", short_ftype_int_int,
5166 BFIN_BUILTIN_MAX_1X16);
5168 def_builtin ("__builtin_bfin_add_fr1x16", short_ftype_int_int,
5169 BFIN_BUILTIN_SSADD_1X16);
5170 def_builtin ("__builtin_bfin_sub_fr1x16", short_ftype_int_int,
5171 BFIN_BUILTIN_SSSUB_1X16);
5172 def_builtin ("__builtin_bfin_mult_fr1x16", short_ftype_int_int,
5173 BFIN_BUILTIN_MULT_1X16);
5174 def_builtin ("__builtin_bfin_multr_fr1x16", short_ftype_int_int,
5175 BFIN_BUILTIN_MULTR_1X16);
5176 def_builtin ("__builtin_bfin_negate_fr1x16", short_ftype_short,
5177 BFIN_BUILTIN_NEG_1X16);
5178 def_builtin ("__builtin_bfin_abs_fr1x16", short_ftype_short,
5179 BFIN_BUILTIN_ABS_1X16);
5180 def_builtin ("__builtin_bfin_norm_fr1x16", short_ftype_int,
5181 BFIN_BUILTIN_NORM_1X16);
5183 def_builtin ("__builtin_bfin_sum_fr2x16", short_ftype_v2hi,
5184 BFIN_BUILTIN_SUM_2X16);
5185 def_builtin ("__builtin_bfin_diff_hl_fr2x16", short_ftype_v2hi,
5186 BFIN_BUILTIN_DIFFHL_2X16);
5187 def_builtin ("__builtin_bfin_diff_lh_fr2x16", short_ftype_v2hi,
5188 BFIN_BUILTIN_DIFFLH_2X16);
5190 def_builtin ("__builtin_bfin_mulhisill", int_ftype_v2hi_v2hi,
5191 BFIN_BUILTIN_MULHISILL);
5192 def_builtin ("__builtin_bfin_mulhisihl", int_ftype_v2hi_v2hi,
5193 BFIN_BUILTIN_MULHISIHL);
5194 def_builtin ("__builtin_bfin_mulhisilh", int_ftype_v2hi_v2hi,
5195 BFIN_BUILTIN_MULHISILH);
5196 def_builtin ("__builtin_bfin_mulhisihh", int_ftype_v2hi_v2hi,
5197 BFIN_BUILTIN_MULHISIHH);
5199 def_builtin ("__builtin_bfin_min_fr1x32", int_ftype_int_int,
5200 BFIN_BUILTIN_MIN_1X32);
5201 def_builtin ("__builtin_bfin_max_fr1x32", int_ftype_int_int,
5202 BFIN_BUILTIN_MAX_1X32);
5204 def_builtin ("__builtin_bfin_add_fr1x32", int_ftype_int_int,
5205 BFIN_BUILTIN_SSADD_1X32);
5206 def_builtin ("__builtin_bfin_sub_fr1x32", int_ftype_int_int,
5207 BFIN_BUILTIN_SSSUB_1X32);
5208 def_builtin ("__builtin_bfin_negate_fr1x32", int_ftype_int,
5209 BFIN_BUILTIN_NEG_1X32);
5210 def_builtin ("__builtin_bfin_abs_fr1x32", int_ftype_int,
5211 BFIN_BUILTIN_ABS_1X32);
5212 def_builtin ("__builtin_bfin_norm_fr1x32", short_ftype_int,
5213 BFIN_BUILTIN_NORM_1X32);
5214 def_builtin ("__builtin_bfin_round_fr1x32", short_ftype_int,
5215 BFIN_BUILTIN_ROUND_1X32);
5216 def_builtin ("__builtin_bfin_mult_fr1x32", int_ftype_short_short,
5217 BFIN_BUILTIN_MULT_1X32);
5218 def_builtin ("__builtin_bfin_mult_fr1x32x32", int_ftype_int_int,
5219 BFIN_BUILTIN_MULT_1X32X32);
5220 def_builtin ("__builtin_bfin_mult_fr1x32x32NS", int_ftype_int_int,
5221 BFIN_BUILTIN_MULT_1X32X32NS);
5223 /* Shifts. */
5224 def_builtin ("__builtin_bfin_shl_fr1x16", short_ftype_int_int,
5225 BFIN_BUILTIN_SSASHIFT_1X16);
5226 def_builtin ("__builtin_bfin_shl_fr2x16", v2hi_ftype_v2hi_int,
5227 BFIN_BUILTIN_SSASHIFT_2X16);
5228 def_builtin ("__builtin_bfin_lshl_fr1x16", short_ftype_int_int,
5229 BFIN_BUILTIN_LSHIFT_1X16);
5230 def_builtin ("__builtin_bfin_lshl_fr2x16", v2hi_ftype_v2hi_int,
5231 BFIN_BUILTIN_LSHIFT_2X16);
5232 def_builtin ("__builtin_bfin_shl_fr1x32", int_ftype_int_int,
5233 BFIN_BUILTIN_SSASHIFT_1X32);
5235 /* Complex numbers. */
5236 def_builtin ("__builtin_bfin_cmplx_add", v2hi_ftype_v2hi_v2hi,
5237 BFIN_BUILTIN_SSADD_2X16);
5238 def_builtin ("__builtin_bfin_cmplx_sub", v2hi_ftype_v2hi_v2hi,
5239 BFIN_BUILTIN_SSSUB_2X16);
5240 def_builtin ("__builtin_bfin_cmplx_mul", v2hi_ftype_v2hi_v2hi,
5241 BFIN_BUILTIN_CPLX_MUL_16);
5242 def_builtin ("__builtin_bfin_cmplx_mac", v2hi_ftype_v2hi_v2hi_v2hi,
5243 BFIN_BUILTIN_CPLX_MAC_16);
5244 def_builtin ("__builtin_bfin_cmplx_msu", v2hi_ftype_v2hi_v2hi_v2hi,
5245 BFIN_BUILTIN_CPLX_MSU_16);
5246 def_builtin ("__builtin_bfin_cmplx_mul_s40", v2hi_ftype_v2hi_v2hi,
5247 BFIN_BUILTIN_CPLX_MUL_16_S40);
5248 def_builtin ("__builtin_bfin_cmplx_mac_s40", v2hi_ftype_v2hi_v2hi_v2hi,
5249 BFIN_BUILTIN_CPLX_MAC_16_S40);
5250 def_builtin ("__builtin_bfin_cmplx_msu_s40", v2hi_ftype_v2hi_v2hi_v2hi,
5251 BFIN_BUILTIN_CPLX_MSU_16_S40);
5252 def_builtin ("__builtin_bfin_csqu_fr16", v2hi_ftype_v2hi,
5253 BFIN_BUILTIN_CPLX_SQU);
5255 /* "Unaligned" load. */
5256 def_builtin ("__builtin_bfin_loadbytes", int_ftype_pint,
5257 BFIN_BUILTIN_LOADBYTES);
5262 struct builtin_description
5264 const enum insn_code icode;
5265 const char *const name;
5266 const enum bfin_builtins code;
5267 int macflag;
5270 static const struct builtin_description bdesc_2arg[] =
5272 { CODE_FOR_composev2hi, "__builtin_bfin_compose_2x16", BFIN_BUILTIN_COMPOSE_2X16, -1 },
5274 { CODE_FOR_ssashiftv2hi3, "__builtin_bfin_shl_fr2x16", BFIN_BUILTIN_SSASHIFT_2X16, -1 },
5275 { CODE_FOR_ssashifthi3, "__builtin_bfin_shl_fr1x16", BFIN_BUILTIN_SSASHIFT_1X16, -1 },
5276 { CODE_FOR_lshiftv2hi3, "__builtin_bfin_lshl_fr2x16", BFIN_BUILTIN_LSHIFT_2X16, -1 },
5277 { CODE_FOR_lshifthi3, "__builtin_bfin_lshl_fr1x16", BFIN_BUILTIN_LSHIFT_1X16, -1 },
5278 { CODE_FOR_ssashiftsi3, "__builtin_bfin_shl_fr1x32", BFIN_BUILTIN_SSASHIFT_1X32, -1 },
5280 { CODE_FOR_sminhi3, "__builtin_bfin_min_fr1x16", BFIN_BUILTIN_MIN_1X16, -1 },
5281 { CODE_FOR_smaxhi3, "__builtin_bfin_max_fr1x16", BFIN_BUILTIN_MAX_1X16, -1 },
5282 { CODE_FOR_ssaddhi3, "__builtin_bfin_add_fr1x16", BFIN_BUILTIN_SSADD_1X16, -1 },
5283 { CODE_FOR_sssubhi3, "__builtin_bfin_sub_fr1x16", BFIN_BUILTIN_SSSUB_1X16, -1 },
5285 { CODE_FOR_sminsi3, "__builtin_bfin_min_fr1x32", BFIN_BUILTIN_MIN_1X32, -1 },
5286 { CODE_FOR_smaxsi3, "__builtin_bfin_max_fr1x32", BFIN_BUILTIN_MAX_1X32, -1 },
5287 { CODE_FOR_ssaddsi3, "__builtin_bfin_add_fr1x32", BFIN_BUILTIN_SSADD_1X32, -1 },
5288 { CODE_FOR_sssubsi3, "__builtin_bfin_sub_fr1x32", BFIN_BUILTIN_SSSUB_1X32, -1 },
5290 { CODE_FOR_sminv2hi3, "__builtin_bfin_min_fr2x16", BFIN_BUILTIN_MIN_2X16, -1 },
5291 { CODE_FOR_smaxv2hi3, "__builtin_bfin_max_fr2x16", BFIN_BUILTIN_MAX_2X16, -1 },
5292 { CODE_FOR_ssaddv2hi3, "__builtin_bfin_add_fr2x16", BFIN_BUILTIN_SSADD_2X16, -1 },
5293 { CODE_FOR_sssubv2hi3, "__builtin_bfin_sub_fr2x16", BFIN_BUILTIN_SSSUB_2X16, -1 },
5294 { CODE_FOR_ssaddsubv2hi3, "__builtin_bfin_dspaddsubsat", BFIN_BUILTIN_SSADDSUB_2X16, -1 },
5295 { CODE_FOR_sssubaddv2hi3, "__builtin_bfin_dspsubaddsat", BFIN_BUILTIN_SSSUBADD_2X16, -1 },
5297 { CODE_FOR_flag_mulhisi, "__builtin_bfin_mult_fr1x32", BFIN_BUILTIN_MULT_1X32, MACFLAG_NONE },
5298 { CODE_FOR_flag_mulhi, "__builtin_bfin_mult_fr1x16", BFIN_BUILTIN_MULT_1X16, MACFLAG_T },
5299 { CODE_FOR_flag_mulhi, "__builtin_bfin_multr_fr1x16", BFIN_BUILTIN_MULTR_1X16, MACFLAG_NONE },
5300 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_mult_fr2x16", BFIN_BUILTIN_MULT_2X16, MACFLAG_T },
5301 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_multr_fr2x16", BFIN_BUILTIN_MULTR_2X16, MACFLAG_NONE },
5303 { CODE_FOR_mulhisi_ll, "__builtin_bfin_mulhisill", BFIN_BUILTIN_MULHISILL, -1 },
5304 { CODE_FOR_mulhisi_lh, "__builtin_bfin_mulhisilh", BFIN_BUILTIN_MULHISILH, -1 },
5305 { CODE_FOR_mulhisi_hl, "__builtin_bfin_mulhisihl", BFIN_BUILTIN_MULHISIHL, -1 },
5306 { CODE_FOR_mulhisi_hh, "__builtin_bfin_mulhisihh", BFIN_BUILTIN_MULHISIHH, -1 }
5310 static const struct builtin_description bdesc_1arg[] =
5312 { CODE_FOR_loadbytes, "__builtin_bfin_loadbytes", BFIN_BUILTIN_LOADBYTES, 0 },
5314 { CODE_FOR_ones, "__builtin_bfin_ones", BFIN_BUILTIN_ONES, 0 },
5316 { CODE_FOR_clrsbhi2, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16, 0 },
5317 { CODE_FOR_ssneghi2, "__builtin_bfin_negate_fr1x16", BFIN_BUILTIN_NEG_1X16, 0 },
5318 { CODE_FOR_abshi2, "__builtin_bfin_abs_fr1x16", BFIN_BUILTIN_ABS_1X16, 0 },
5320 { CODE_FOR_clrsbsi2, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32, 0 },
5321 { CODE_FOR_ssroundsi2, "__builtin_bfin_round_fr1x32", BFIN_BUILTIN_ROUND_1X32, 0 },
5322 { CODE_FOR_ssnegsi2, "__builtin_bfin_negate_fr1x32", BFIN_BUILTIN_NEG_1X32, 0 },
5323 { CODE_FOR_ssabssi2, "__builtin_bfin_abs_fr1x32", BFIN_BUILTIN_ABS_1X32, 0 },
5325 { CODE_FOR_movv2hi_hi_low, "__builtin_bfin_extract_lo", BFIN_BUILTIN_EXTRACTLO, 0 },
5326 { CODE_FOR_movv2hi_hi_high, "__builtin_bfin_extract_hi", BFIN_BUILTIN_EXTRACTHI, 0 },
5327 { CODE_FOR_ssnegv2hi2, "__builtin_bfin_negate_fr2x16", BFIN_BUILTIN_NEG_2X16, 0 },
5328 { CODE_FOR_ssabsv2hi2, "__builtin_bfin_abs_fr2x16", BFIN_BUILTIN_ABS_2X16, 0 }
5331 /* Errors in the source file can cause expand_expr to return const0_rtx
5332 where we expect a vector. To avoid crashing, use one of the vector
5333 clear instructions. */
5334 static rtx
5335 safe_vector_operand (rtx x, enum machine_mode mode)
5337 if (x != const0_rtx)
5338 return x;
5339 x = gen_reg_rtx (SImode);
5341 emit_insn (gen_movsi (x, CONST0_RTX (SImode)));
5342 return gen_lowpart (mode, x);
5345 /* Subroutine of bfin_expand_builtin to take care of binop insns. MACFLAG is -1
5346 if this is a normal binary op, or one of the MACFLAG_xxx constants. */
5348 static rtx
5349 bfin_expand_binop_builtin (enum insn_code icode, tree exp, rtx target,
5350 int macflag)
5352 rtx pat;
5353 tree arg0 = CALL_EXPR_ARG (exp, 0);
5354 tree arg1 = CALL_EXPR_ARG (exp, 1);
5355 rtx op0 = expand_normal (arg0);
5356 rtx op1 = expand_normal (arg1);
5357 enum machine_mode op0mode = GET_MODE (op0);
5358 enum machine_mode op1mode = GET_MODE (op1);
5359 enum machine_mode tmode = insn_data[icode].operand[0].mode;
5360 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
5361 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
5363 if (VECTOR_MODE_P (mode0))
5364 op0 = safe_vector_operand (op0, mode0);
5365 if (VECTOR_MODE_P (mode1))
5366 op1 = safe_vector_operand (op1, mode1);
5368 if (! target
5369 || GET_MODE (target) != tmode
5370 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5371 target = gen_reg_rtx (tmode);
5373 if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode)
5375 op0mode = HImode;
5376 op0 = gen_lowpart (HImode, op0);
5378 if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode)
5380 op1mode = HImode;
5381 op1 = gen_lowpart (HImode, op1);
5383 /* In case the insn wants input operands in modes different from
5384 the result, abort. */
5385 gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
5386 && (op1mode == mode1 || op1mode == VOIDmode));
5388 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5389 op0 = copy_to_mode_reg (mode0, op0);
5390 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
5391 op1 = copy_to_mode_reg (mode1, op1);
5393 if (macflag == -1)
5394 pat = GEN_FCN (icode) (target, op0, op1);
5395 else
5396 pat = GEN_FCN (icode) (target, op0, op1, GEN_INT (macflag));
5397 if (! pat)
5398 return 0;
5400 emit_insn (pat);
5401 return target;
5404 /* Subroutine of bfin_expand_builtin to take care of unop insns. */
5406 static rtx
5407 bfin_expand_unop_builtin (enum insn_code icode, tree exp,
5408 rtx target)
5410 rtx pat;
5411 tree arg0 = CALL_EXPR_ARG (exp, 0);
5412 rtx op0 = expand_normal (arg0);
5413 enum machine_mode op0mode = GET_MODE (op0);
5414 enum machine_mode tmode = insn_data[icode].operand[0].mode;
5415 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
5417 if (! target
5418 || GET_MODE (target) != tmode
5419 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5420 target = gen_reg_rtx (tmode);
5422 if (VECTOR_MODE_P (mode0))
5423 op0 = safe_vector_operand (op0, mode0);
5425 if (op0mode == SImode && mode0 == HImode)
5427 op0mode = HImode;
5428 op0 = gen_lowpart (HImode, op0);
5430 gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
5432 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5433 op0 = copy_to_mode_reg (mode0, op0);
5435 pat = GEN_FCN (icode) (target, op0);
5436 if (! pat)
5437 return 0;
5438 emit_insn (pat);
5439 return target;
5442 /* Expand an expression EXP that calls a built-in function,
5443 with result going to TARGET if that's convenient
5444 (and in mode MODE if that's convenient).
5445 SUBTARGET may be used as the target for computing one of EXP's operands.
5446 IGNORE is nonzero if the value is to be ignored. */
5448 static rtx
5449 bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
5450 rtx subtarget ATTRIBUTE_UNUSED,
5451 enum machine_mode mode ATTRIBUTE_UNUSED,
5452 int ignore ATTRIBUTE_UNUSED)
5454 size_t i;
5455 enum insn_code icode;
5456 const struct builtin_description *d;
5457 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
5458 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
5459 tree arg0, arg1, arg2;
5460 rtx op0, op1, op2, accvec, pat, tmp1, tmp2, a0reg, a1reg;
5461 enum machine_mode tmode, mode0;
5463 switch (fcode)
5465 case BFIN_BUILTIN_CSYNC:
5466 emit_insn (gen_csync ());
5467 return 0;
5468 case BFIN_BUILTIN_SSYNC:
5469 emit_insn (gen_ssync ());
5470 return 0;
5472 case BFIN_BUILTIN_DIFFHL_2X16:
5473 case BFIN_BUILTIN_DIFFLH_2X16:
5474 case BFIN_BUILTIN_SUM_2X16:
5475 arg0 = CALL_EXPR_ARG (exp, 0);
5476 op0 = expand_normal (arg0);
5477 icode = (fcode == BFIN_BUILTIN_DIFFHL_2X16 ? CODE_FOR_subhilov2hi3
5478 : fcode == BFIN_BUILTIN_DIFFLH_2X16 ? CODE_FOR_sublohiv2hi3
5479 : CODE_FOR_ssaddhilov2hi3);
5480 tmode = insn_data[icode].operand[0].mode;
5481 mode0 = insn_data[icode].operand[1].mode;
5483 if (! target
5484 || GET_MODE (target) != tmode
5485 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5486 target = gen_reg_rtx (tmode);
5488 if (VECTOR_MODE_P (mode0))
5489 op0 = safe_vector_operand (op0, mode0);
5491 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5492 op0 = copy_to_mode_reg (mode0, op0);
5494 pat = GEN_FCN (icode) (target, op0, op0);
5495 if (! pat)
5496 return 0;
5497 emit_insn (pat);
5498 return target;
5500 case BFIN_BUILTIN_MULT_1X32X32:
5501 case BFIN_BUILTIN_MULT_1X32X32NS:
5502 arg0 = CALL_EXPR_ARG (exp, 0);
5503 arg1 = CALL_EXPR_ARG (exp, 1);
5504 op0 = expand_normal (arg0);
5505 op1 = expand_normal (arg1);
5506 if (! target
5507 || !register_operand (target, SImode))
5508 target = gen_reg_rtx (SImode);
5509 if (! register_operand (op0, SImode))
5510 op0 = copy_to_mode_reg (SImode, op0);
5511 if (! register_operand (op1, SImode))
5512 op1 = copy_to_mode_reg (SImode, op1);
5514 a1reg = gen_rtx_REG (PDImode, REG_A1);
5515 a0reg = gen_rtx_REG (PDImode, REG_A0);
5516 tmp1 = gen_lowpart (V2HImode, op0);
5517 tmp2 = gen_lowpart (V2HImode, op1);
5518 emit_insn (gen_flag_macinit1hi (a1reg,
5519 gen_lowpart (HImode, op0),
5520 gen_lowpart (HImode, op1),
5521 GEN_INT (MACFLAG_FU)));
5522 emit_insn (gen_lshrpdi3 (a1reg, a1reg, GEN_INT (16)));
5524 if (fcode == BFIN_BUILTIN_MULT_1X32X32)
5525 emit_insn (gen_flag_mul_macv2hi_parts_acconly (a0reg, a1reg, tmp1, tmp2,
5526 const1_rtx, const1_rtx,
5527 const1_rtx, const0_rtx, a1reg,
5528 const0_rtx, GEN_INT (MACFLAG_NONE),
5529 GEN_INT (MACFLAG_M)));
5530 else
5532 /* For saturating multiplication, there's exactly one special case
5533 to be handled: multiplying the smallest negative value with
5534 itself. Due to shift correction in fractional multiplies, this
5535 can overflow. Iff this happens, OP2 will contain 1, which, when
5536 added in 32 bits to the smallest negative, wraps to the largest
5537 positive, which is the result we want. */
5538 op2 = gen_reg_rtx (V2HImode);
5539 emit_insn (gen_packv2hi (op2, tmp1, tmp2, const0_rtx, const0_rtx));
5540 emit_insn (gen_movsibi (gen_rtx_REG (BImode, REG_CC),
5541 gen_lowpart (SImode, op2)));
5542 emit_insn (gen_flag_mul_macv2hi_parts_acconly_andcc0 (a0reg, a1reg, tmp1, tmp2,
5543 const1_rtx, const1_rtx,
5544 const1_rtx, const0_rtx, a1reg,
5545 const0_rtx, GEN_INT (MACFLAG_NONE),
5546 GEN_INT (MACFLAG_M)));
5547 op2 = gen_reg_rtx (SImode);
5548 emit_insn (gen_movbisi (op2, gen_rtx_REG (BImode, REG_CC)));
5550 emit_insn (gen_flag_machi_parts_acconly (a1reg, tmp2, tmp1,
5551 const1_rtx, const0_rtx,
5552 a1reg, const0_rtx, GEN_INT (MACFLAG_M)));
5553 emit_insn (gen_ashrpdi3 (a1reg, a1reg, GEN_INT (15)));
5554 emit_insn (gen_sum_of_accumulators (target, a0reg, a0reg, a1reg));
5555 if (fcode == BFIN_BUILTIN_MULT_1X32X32NS)
5556 emit_insn (gen_addsi3 (target, target, op2));
5557 return target;
5559 case BFIN_BUILTIN_CPLX_MUL_16:
5560 case BFIN_BUILTIN_CPLX_MUL_16_S40:
5561 arg0 = CALL_EXPR_ARG (exp, 0);
5562 arg1 = CALL_EXPR_ARG (exp, 1);
5563 op0 = expand_normal (arg0);
5564 op1 = expand_normal (arg1);
5565 accvec = gen_reg_rtx (V2PDImode);
5566 icode = CODE_FOR_flag_macv2hi_parts;
5567 tmode = insn_data[icode].operand[0].mode;
5569 if (! target
5570 || GET_MODE (target) != V2HImode
5571 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5572 target = gen_reg_rtx (tmode);
5573 if (! register_operand (op0, GET_MODE (op0)))
5574 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
5575 if (! register_operand (op1, GET_MODE (op1)))
5576 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
5578 if (fcode == BFIN_BUILTIN_CPLX_MUL_16)
5579 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
5580 const0_rtx, const0_rtx,
5581 const1_rtx, GEN_INT (MACFLAG_W32)));
5582 else
5583 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
5584 const0_rtx, const0_rtx,
5585 const1_rtx, GEN_INT (MACFLAG_NONE)));
5586 emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
5587 const1_rtx, const1_rtx,
5588 const0_rtx, accvec, const1_rtx, const0_rtx,
5589 GEN_INT (MACFLAG_NONE), accvec));
5591 return target;
5593 case BFIN_BUILTIN_CPLX_MAC_16:
5594 case BFIN_BUILTIN_CPLX_MSU_16:
5595 case BFIN_BUILTIN_CPLX_MAC_16_S40:
5596 case BFIN_BUILTIN_CPLX_MSU_16_S40:
5597 arg0 = CALL_EXPR_ARG (exp, 0);
5598 arg1 = CALL_EXPR_ARG (exp, 1);
5599 arg2 = CALL_EXPR_ARG (exp, 2);
5600 op0 = expand_normal (arg0);
5601 op1 = expand_normal (arg1);
5602 op2 = expand_normal (arg2);
5603 accvec = gen_reg_rtx (V2PDImode);
5604 icode = CODE_FOR_flag_macv2hi_parts;
5605 tmode = insn_data[icode].operand[0].mode;
5607 if (! target
5608 || GET_MODE (target) != V2HImode
5609 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5610 target = gen_reg_rtx (tmode);
5611 if (! register_operand (op1, GET_MODE (op1)))
5612 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
5613 if (! register_operand (op2, GET_MODE (op2)))
5614 op2 = copy_to_mode_reg (GET_MODE (op2), op2);
5616 tmp1 = gen_reg_rtx (SImode);
5617 tmp2 = gen_reg_rtx (SImode);
5618 emit_insn (gen_ashlsi3 (tmp1, gen_lowpart (SImode, op0), GEN_INT (16)));
5619 emit_move_insn (tmp2, gen_lowpart (SImode, op0));
5620 emit_insn (gen_movstricthi_1 (gen_lowpart (HImode, tmp2), const0_rtx));
5621 emit_insn (gen_load_accumulator_pair (accvec, tmp1, tmp2));
5622 if (fcode == BFIN_BUILTIN_CPLX_MAC_16
5623 || fcode == BFIN_BUILTIN_CPLX_MSU_16)
5624 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx,
5625 const0_rtx, const0_rtx,
5626 const1_rtx, accvec, const0_rtx,
5627 const0_rtx,
5628 GEN_INT (MACFLAG_W32)));
5629 else
5630 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx,
5631 const0_rtx, const0_rtx,
5632 const1_rtx, accvec, const0_rtx,
5633 const0_rtx,
5634 GEN_INT (MACFLAG_NONE)));
5635 if (fcode == BFIN_BUILTIN_CPLX_MAC_16
5636 || fcode == BFIN_BUILTIN_CPLX_MAC_16_S40)
5638 tmp1 = const1_rtx;
5639 tmp2 = const0_rtx;
5641 else
5643 tmp1 = const0_rtx;
5644 tmp2 = const1_rtx;
5646 emit_insn (gen_flag_macv2hi_parts (target, op1, op2, const1_rtx,
5647 const1_rtx, const1_rtx,
5648 const0_rtx, accvec, tmp1, tmp2,
5649 GEN_INT (MACFLAG_NONE), accvec));
5651 return target;
5653 case BFIN_BUILTIN_CPLX_SQU:
5654 arg0 = CALL_EXPR_ARG (exp, 0);
5655 op0 = expand_normal (arg0);
5656 accvec = gen_reg_rtx (V2PDImode);
5657 icode = CODE_FOR_flag_mulv2hi;
5658 tmp1 = gen_reg_rtx (V2HImode);
5659 tmp2 = gen_reg_rtx (V2HImode);
5661 if (! target
5662 || GET_MODE (target) != V2HImode
5663 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5664 target = gen_reg_rtx (V2HImode);
5665 if (! register_operand (op0, GET_MODE (op0)))
5666 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
5668 emit_insn (gen_flag_mulv2hi (tmp1, op0, op0, GEN_INT (MACFLAG_NONE)));
5670 emit_insn (gen_flag_mulhi_parts (gen_lowpart (HImode, tmp2), op0, op0,
5671 const0_rtx, const1_rtx,
5672 GEN_INT (MACFLAG_NONE)));
5674 emit_insn (gen_ssaddhi3_high_parts (target, tmp2, tmp2, tmp2, const0_rtx,
5675 const0_rtx));
5676 emit_insn (gen_sssubhi3_low_parts (target, target, tmp1, tmp1,
5677 const0_rtx, const1_rtx));
5679 return target;
5681 default:
5682 break;
5685 for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
5686 if (d->code == fcode)
5687 return bfin_expand_binop_builtin (d->icode, exp, target,
5688 d->macflag);
5690 for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
5691 if (d->code == fcode)
5692 return bfin_expand_unop_builtin (d->icode, exp, target);
5694 gcc_unreachable ();
5697 static void
5698 bfin_conditional_register_usage (void)
5700 /* initialize condition code flag register rtx */
5701 bfin_cc_rtx = gen_rtx_REG (BImode, REG_CC);
5702 bfin_rets_rtx = gen_rtx_REG (Pmode, REG_RETS);
5703 if (TARGET_FDPIC)
5704 call_used_regs[FDPIC_REGNO] = 1;
5705 if (!TARGET_FDPIC && flag_pic)
5707 fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
5708 call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
5712 #undef TARGET_INIT_BUILTINS
5713 #define TARGET_INIT_BUILTINS bfin_init_builtins
5715 #undef TARGET_EXPAND_BUILTIN
5716 #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
5718 #undef TARGET_ASM_GLOBALIZE_LABEL
5719 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label
5721 #undef TARGET_ASM_FILE_START
5722 #define TARGET_ASM_FILE_START output_file_start
5724 #undef TARGET_ATTRIBUTE_TABLE
5725 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
5727 #undef TARGET_COMP_TYPE_ATTRIBUTES
5728 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
5730 #undef TARGET_RTX_COSTS
5731 #define TARGET_RTX_COSTS bfin_rtx_costs
5733 #undef TARGET_ADDRESS_COST
5734 #define TARGET_ADDRESS_COST bfin_address_cost
5736 #undef TARGET_REGISTER_MOVE_COST
5737 #define TARGET_REGISTER_MOVE_COST bfin_register_move_cost
5739 #undef TARGET_MEMORY_MOVE_COST
5740 #define TARGET_MEMORY_MOVE_COST bfin_memory_move_cost
5742 #undef TARGET_ASM_INTEGER
5743 #define TARGET_ASM_INTEGER bfin_assemble_integer
5745 #undef TARGET_MACHINE_DEPENDENT_REORG
5746 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
5748 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
5749 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
5751 #undef TARGET_ASM_OUTPUT_MI_THUNK
5752 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
5753 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
5754 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
5756 #undef TARGET_SCHED_ADJUST_COST
5757 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
5759 #undef TARGET_SCHED_ISSUE_RATE
5760 #define TARGET_SCHED_ISSUE_RATE bfin_issue_rate
5762 #undef TARGET_PROMOTE_FUNCTION_MODE
5763 #define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
5765 #undef TARGET_ARG_PARTIAL_BYTES
5766 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
5768 #undef TARGET_FUNCTION_ARG
5769 #define TARGET_FUNCTION_ARG bfin_function_arg
5771 #undef TARGET_FUNCTION_ARG_ADVANCE
5772 #define TARGET_FUNCTION_ARG_ADVANCE bfin_function_arg_advance
5774 #undef TARGET_PASS_BY_REFERENCE
5775 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
5777 #undef TARGET_SETUP_INCOMING_VARARGS
5778 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
5780 #undef TARGET_STRUCT_VALUE_RTX
5781 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
5783 #undef TARGET_VECTOR_MODE_SUPPORTED_P
5784 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
5786 #undef TARGET_OPTION_OVERRIDE
5787 #define TARGET_OPTION_OVERRIDE bfin_option_override
5789 #undef TARGET_SECONDARY_RELOAD
5790 #define TARGET_SECONDARY_RELOAD bfin_secondary_reload
5792 #undef TARGET_CLASS_LIKELY_SPILLED_P
5793 #define TARGET_CLASS_LIKELY_SPILLED_P bfin_class_likely_spilled_p
5795 #undef TARGET_DELEGITIMIZE_ADDRESS
5796 #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address
5798 #undef TARGET_LEGITIMATE_CONSTANT_P
5799 #define TARGET_LEGITIMATE_CONSTANT_P bfin_legitimate_constant_p
5801 #undef TARGET_CANNOT_FORCE_CONST_MEM
5802 #define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem
5804 #undef TARGET_RETURN_IN_MEMORY
5805 #define TARGET_RETURN_IN_MEMORY bfin_return_in_memory
5807 #undef TARGET_LEGITIMATE_ADDRESS_P
5808 #define TARGET_LEGITIMATE_ADDRESS_P bfin_legitimate_address_p
5810 #undef TARGET_FRAME_POINTER_REQUIRED
5811 #define TARGET_FRAME_POINTER_REQUIRED bfin_frame_pointer_required
5813 #undef TARGET_CAN_ELIMINATE
5814 #define TARGET_CAN_ELIMINATE bfin_can_eliminate
5816 #undef TARGET_CONDITIONAL_REGISTER_USAGE
5817 #define TARGET_CONDITIONAL_REGISTER_USAGE bfin_conditional_register_usage
5819 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
5820 #define TARGET_ASM_TRAMPOLINE_TEMPLATE bfin_asm_trampoline_template
5821 #undef TARGET_TRAMPOLINE_INIT
5822 #define TARGET_TRAMPOLINE_INIT bfin_trampoline_init
5824 #undef TARGET_EXTRA_LIVE_ON_ENTRY
5825 #define TARGET_EXTRA_LIVE_ON_ENTRY bfin_extra_live_on_entry
5827 /* Passes after sched2 can break the helpful TImode annotations that
5828 haifa-sched puts on every insn. Just do scheduling in reorg. */
5829 #undef TARGET_DELAY_SCHED2
5830 #define TARGET_DELAY_SCHED2 true
5832 /* Variable tracking should be run after all optimizations which
5833 change order of insns. It also needs a valid CFG. */
5834 #undef TARGET_DELAY_VARTRACK
5835 #define TARGET_DELAY_VARTRACK true
5837 #undef TARGET_CAN_USE_DOLOOP_P
5838 #define TARGET_CAN_USE_DOLOOP_P bfin_can_use_doloop_p
5840 struct gcc_target targetm = TARGET_INITIALIZER;