PR c/81544 - attribute noreturn and warn_unused_result on the same function accepted
[official-gcc.git] / gcc / config / bfin / bfin.c
bloba5947435f3e99e1200060b8185d6b7ce4bdfaac9
1 /* The Blackfin code generation auxiliary output file.
2 Copyright (C) 2005-2017 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 "backend.h"
25 #include "target.h"
26 #include "rtl.h"
27 #include "tree.h"
28 #include "stringpool.h"
29 #include "attribs.h"
30 #include "cfghooks.h"
31 #include "df.h"
32 #include "memmodel.h"
33 #include "tm_p.h"
34 #include "optabs.h"
35 #include "regs.h"
36 #include "emit-rtl.h"
37 #include "recog.h"
38 #include "cgraph.h"
39 #include "diagnostic-core.h"
40 #include "output.h"
41 #include "insn-attr.h"
42 #include "varasm.h"
43 #include "calls.h"
44 #include "explow.h"
45 #include "expr.h"
46 #include "cfgrtl.h"
47 #include "langhooks.h"
48 #include "tm-constrs.h"
49 #include "gt-bfin.h"
50 #include "sel-sched.h"
51 #include "hw-doloop.h"
52 #include "dumpfile.h"
53 #include "builtins.h"
55 /* This file should be included last. */
56 #include "target-def.h"
58 /* A C structure for machine-specific, per-function data.
59 This is added to the cfun structure. */
60 struct GTY(()) machine_function
62 /* Set if we are notified by the doloop pass that a hardware loop
63 was created. */
64 int has_hardware_loops;
66 /* Set if we create a memcpy pattern that uses loop registers. */
67 int has_loopreg_clobber;
70 /* RTX for condition code flag register and RETS register */
71 extern GTY(()) rtx bfin_cc_rtx;
72 extern GTY(()) rtx bfin_rets_rtx;
73 rtx bfin_cc_rtx, bfin_rets_rtx;
75 int max_arg_registers = 0;
77 /* Arrays used when emitting register names. */
78 const char *short_reg_names[] = SHORT_REGISTER_NAMES;
79 const char *high_reg_names[] = HIGH_REGISTER_NAMES;
80 const char *dregs_pair_names[] = DREGS_PAIR_NAMES;
81 const char *byte_reg_names[] = BYTE_REGISTER_NAMES;
83 static int arg_regs[] = FUNCTION_ARG_REGISTERS;
84 static int ret_regs[] = FUNCTION_RETURN_REGISTERS;
86 int splitting_for_sched, splitting_loops;
88 static void
89 bfin_globalize_label (FILE *stream, const char *name)
91 fputs (".global ", stream);
92 assemble_name (stream, name);
93 fputc (';',stream);
94 fputc ('\n',stream);
97 static void
98 output_file_start (void)
100 FILE *file = asm_out_file;
101 int i;
103 fprintf (file, ".file \"%s\";\n", LOCATION_FILE (input_location));
105 for (i = 0; arg_regs[i] >= 0; i++)
107 max_arg_registers = i; /* how many arg reg used */
110 /* Examine machine-dependent attributes of function type FUNTYPE and return its
111 type. See the definition of E_FUNKIND. */
113 static e_funkind
114 funkind (const_tree funtype)
116 tree attrs = TYPE_ATTRIBUTES (funtype);
117 if (lookup_attribute ("interrupt_handler", attrs))
118 return INTERRUPT_HANDLER;
119 else if (lookup_attribute ("exception_handler", attrs))
120 return EXCPT_HANDLER;
121 else if (lookup_attribute ("nmi_handler", attrs))
122 return NMI_HANDLER;
123 else
124 return SUBROUTINE;
127 /* Legitimize PIC addresses. If the address is already position-independent,
128 we return ORIG. Newly generated position-independent addresses go into a
129 reg. This is REG if nonzero, otherwise we allocate register(s) as
130 necessary. PICREG is the register holding the pointer to the PIC offset
131 table. */
133 static rtx
134 legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
136 rtx addr = orig;
137 rtx new_rtx = orig;
139 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
141 int unspec;
142 rtx tmp;
144 if (TARGET_ID_SHARED_LIBRARY)
145 unspec = UNSPEC_MOVE_PIC;
146 else if (GET_CODE (addr) == SYMBOL_REF
147 && SYMBOL_REF_FUNCTION_P (addr))
148 unspec = UNSPEC_FUNCDESC_GOT17M4;
149 else
150 unspec = UNSPEC_MOVE_FDPIC;
152 if (reg == 0)
154 gcc_assert (can_create_pseudo_p ());
155 reg = gen_reg_rtx (Pmode);
158 tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), unspec);
159 new_rtx = gen_const_mem (Pmode, gen_rtx_PLUS (Pmode, picreg, tmp));
161 emit_move_insn (reg, new_rtx);
162 if (picreg == pic_offset_table_rtx)
163 crtl->uses_pic_offset_table = 1;
164 return reg;
167 else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
169 rtx base;
171 if (GET_CODE (addr) == CONST)
173 addr = XEXP (addr, 0);
174 gcc_assert (GET_CODE (addr) == PLUS);
177 if (XEXP (addr, 0) == picreg)
178 return orig;
180 if (reg == 0)
182 gcc_assert (can_create_pseudo_p ());
183 reg = gen_reg_rtx (Pmode);
186 base = legitimize_pic_address (XEXP (addr, 0), reg, picreg);
187 addr = legitimize_pic_address (XEXP (addr, 1),
188 base == reg ? NULL_RTX : reg,
189 picreg);
191 if (GET_CODE (addr) == CONST_INT)
193 gcc_assert (! reload_in_progress && ! reload_completed);
194 addr = force_reg (Pmode, addr);
197 if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
199 base = gen_rtx_PLUS (Pmode, base, XEXP (addr, 0));
200 addr = XEXP (addr, 1);
203 return gen_rtx_PLUS (Pmode, base, addr);
206 return new_rtx;
209 /* Stack frame layout. */
211 /* For a given REGNO, determine whether it must be saved in the function
212 prologue. IS_INTHANDLER specifies whether we're generating a normal
213 prologue or an interrupt/exception one. */
214 static bool
215 must_save_p (bool is_inthandler, unsigned regno)
217 if (D_REGNO_P (regno))
219 bool is_eh_return_reg = false;
220 if (crtl->calls_eh_return)
222 unsigned j;
223 for (j = 0; ; j++)
225 unsigned test = EH_RETURN_DATA_REGNO (j);
226 if (test == INVALID_REGNUM)
227 break;
228 if (test == regno)
229 is_eh_return_reg = true;
233 return (is_eh_return_reg
234 || (df_regs_ever_live_p (regno)
235 && !fixed_regs[regno]
236 && (is_inthandler || !call_used_regs[regno])));
238 else if (P_REGNO_P (regno))
240 return ((df_regs_ever_live_p (regno)
241 && !fixed_regs[regno]
242 && (is_inthandler || !call_used_regs[regno]))
243 || (is_inthandler
244 && (ENABLE_WA_05000283 || ENABLE_WA_05000315)
245 && regno == REG_P5)
246 || (!TARGET_FDPIC
247 && regno == PIC_OFFSET_TABLE_REGNUM
248 && (crtl->uses_pic_offset_table
249 || (TARGET_ID_SHARED_LIBRARY && !crtl->is_leaf))));
251 else
252 return ((is_inthandler || !call_used_regs[regno])
253 && (df_regs_ever_live_p (regno)
254 || (!leaf_function_p () && call_used_regs[regno])));
258 /* Compute the number of DREGS to save with a push_multiple operation.
259 This could include registers that aren't modified in the function,
260 since push_multiple only takes a range of registers.
261 If IS_INTHANDLER, then everything that is live must be saved, even
262 if normally call-clobbered.
263 If CONSECUTIVE, return the number of registers we can save in one
264 instruction with a push/pop multiple instruction. */
266 static int
267 n_dregs_to_save (bool is_inthandler, bool consecutive)
269 int count = 0;
270 unsigned i;
272 for (i = REG_R7 + 1; i-- != REG_R0;)
274 if (must_save_p (is_inthandler, i))
275 count++;
276 else if (consecutive)
277 return count;
279 return count;
282 /* Like n_dregs_to_save, but compute number of PREGS to save. */
284 static int
285 n_pregs_to_save (bool is_inthandler, bool consecutive)
287 int count = 0;
288 unsigned i;
290 for (i = REG_P5 + 1; i-- != REG_P0;)
291 if (must_save_p (is_inthandler, i))
292 count++;
293 else if (consecutive)
294 return count;
295 return count;
298 /* Determine if we are going to save the frame pointer in the prologue. */
300 static bool
301 must_save_fp_p (void)
303 return df_regs_ever_live_p (REG_FP);
306 /* Determine if we are going to save the RETS register. */
307 static bool
308 must_save_rets_p (void)
310 return df_regs_ever_live_p (REG_RETS);
313 static bool
314 stack_frame_needed_p (void)
316 /* EH return puts a new return address into the frame using an
317 address relative to the frame pointer. */
318 if (crtl->calls_eh_return)
319 return true;
320 return frame_pointer_needed;
323 /* Emit code to save registers in the prologue. SAVEALL is nonzero if we
324 must save all registers; this is used for interrupt handlers.
325 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
326 this for an interrupt (or exception) handler. */
328 static void
329 expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler)
331 rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
332 rtx predec = gen_rtx_MEM (SImode, predec1);
333 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler, false);
334 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler, false);
335 int ndregs_consec = saveall ? 8 : n_dregs_to_save (is_inthandler, true);
336 int npregs_consec = saveall ? 6 : n_pregs_to_save (is_inthandler, true);
337 int dregno, pregno;
338 int total_consec = ndregs_consec + npregs_consec;
339 int i, d_to_save;
341 if (saveall || is_inthandler)
343 rtx_insn *insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
345 RTX_FRAME_RELATED_P (insn) = 1;
346 for (dregno = REG_LT0; dregno <= REG_LB1; dregno++)
347 if (! crtl->is_leaf
348 || cfun->machine->has_hardware_loops
349 || cfun->machine->has_loopreg_clobber
350 || (ENABLE_WA_05000257
351 && (dregno == REG_LC0 || dregno == REG_LC1)))
353 insn = emit_move_insn (predec, gen_rtx_REG (SImode, dregno));
354 RTX_FRAME_RELATED_P (insn) = 1;
358 if (total_consec != 0)
360 rtx_insn *insn;
361 rtx val = GEN_INT (-total_consec * 4);
362 rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_consec + 2));
364 XVECEXP (pat, 0, 0) = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, val),
365 UNSPEC_PUSH_MULTIPLE);
366 XVECEXP (pat, 0, total_consec + 1) = gen_rtx_SET (spreg,
367 gen_rtx_PLUS (Pmode,
368 spreg,
369 val));
370 RTX_FRAME_RELATED_P (XVECEXP (pat, 0, total_consec + 1)) = 1;
371 d_to_save = ndregs_consec;
372 dregno = REG_R7 + 1 - ndregs_consec;
373 pregno = REG_P5 + 1 - npregs_consec;
374 for (i = 0; i < total_consec; i++)
376 rtx memref = gen_rtx_MEM (word_mode,
377 gen_rtx_PLUS (Pmode, spreg,
378 GEN_INT (- i * 4 - 4)));
379 rtx subpat;
380 if (d_to_save > 0)
382 subpat = gen_rtx_SET (memref, gen_rtx_REG (word_mode, dregno++));
383 d_to_save--;
385 else
387 subpat = gen_rtx_SET (memref, gen_rtx_REG (word_mode, pregno++));
389 XVECEXP (pat, 0, i + 1) = subpat;
390 RTX_FRAME_RELATED_P (subpat) = 1;
392 insn = emit_insn (pat);
393 RTX_FRAME_RELATED_P (insn) = 1;
396 for (dregno = REG_R0; ndregs != ndregs_consec; dregno++)
398 if (must_save_p (is_inthandler, dregno))
400 rtx_insn *insn =
401 emit_move_insn (predec, gen_rtx_REG (word_mode, dregno));
402 RTX_FRAME_RELATED_P (insn) = 1;
403 ndregs--;
406 for (pregno = REG_P0; npregs != npregs_consec; pregno++)
408 if (must_save_p (is_inthandler, pregno))
410 rtx_insn *insn =
411 emit_move_insn (predec, gen_rtx_REG (word_mode, pregno));
412 RTX_FRAME_RELATED_P (insn) = 1;
413 npregs--;
416 for (i = REG_P7 + 1; i < REG_CC; i++)
417 if (saveall
418 || (is_inthandler
419 && (df_regs_ever_live_p (i)
420 || (!leaf_function_p () && call_used_regs[i]))))
422 rtx_insn *insn;
423 if (i == REG_A0 || i == REG_A1)
424 insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1),
425 gen_rtx_REG (PDImode, i));
426 else
427 insn = emit_move_insn (predec, gen_rtx_REG (SImode, i));
428 RTX_FRAME_RELATED_P (insn) = 1;
432 /* Emit code to restore registers in the epilogue. SAVEALL is nonzero if we
433 must save all registers; this is used for interrupt handlers.
434 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
435 this for an interrupt (or exception) handler. */
437 static void
438 expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler)
440 rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
441 rtx postinc = gen_rtx_MEM (SImode, postinc1);
443 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler, false);
444 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler, false);
445 int ndregs_consec = saveall ? 8 : n_dregs_to_save (is_inthandler, true);
446 int npregs_consec = saveall ? 6 : n_pregs_to_save (is_inthandler, true);
447 int total_consec = ndregs_consec + npregs_consec;
448 int i, regno;
449 rtx_insn *insn;
451 /* A slightly crude technique to stop flow from trying to delete "dead"
452 insns. */
453 MEM_VOLATILE_P (postinc) = 1;
455 for (i = REG_CC - 1; i > REG_P7; i--)
456 if (saveall
457 || (is_inthandler
458 && (df_regs_ever_live_p (i)
459 || (!leaf_function_p () && call_used_regs[i]))))
461 if (i == REG_A0 || i == REG_A1)
463 rtx mem = gen_rtx_MEM (PDImode, postinc1);
464 MEM_VOLATILE_P (mem) = 1;
465 emit_move_insn (gen_rtx_REG (PDImode, i), mem);
467 else
468 emit_move_insn (gen_rtx_REG (SImode, i), postinc);
471 regno = REG_P5 - npregs_consec;
472 for (; npregs != npregs_consec; regno--)
474 if (must_save_p (is_inthandler, regno))
476 emit_move_insn (gen_rtx_REG (word_mode, regno), postinc);
477 npregs--;
480 regno = REG_R7 - ndregs_consec;
481 for (; ndregs != ndregs_consec; regno--)
483 if (must_save_p (is_inthandler, regno))
485 emit_move_insn (gen_rtx_REG (word_mode, regno), postinc);
486 ndregs--;
490 if (total_consec != 0)
492 rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_consec + 1));
493 XVECEXP (pat, 0, 0)
494 = gen_rtx_SET (spreg, gen_rtx_PLUS (Pmode, spreg,
495 GEN_INT (total_consec * 4)));
497 if (npregs_consec > 0)
498 regno = REG_P5 + 1;
499 else
500 regno = REG_R7 + 1;
502 for (i = 0; i < total_consec; i++)
504 rtx addr = (i > 0
505 ? gen_rtx_PLUS (Pmode, spreg, GEN_INT (i * 4))
506 : spreg);
507 rtx memref = gen_rtx_MEM (word_mode, addr);
509 regno--;
510 XVECEXP (pat, 0, i + 1)
511 = gen_rtx_SET (gen_rtx_REG (word_mode, regno), memref);
513 if (npregs_consec > 0)
515 if (--npregs_consec == 0)
516 regno = REG_R7 + 1;
520 insn = emit_insn (pat);
521 RTX_FRAME_RELATED_P (insn) = 1;
523 if (saveall || is_inthandler)
525 for (regno = REG_LB1; regno >= REG_LT0; regno--)
526 if (! crtl->is_leaf
527 || cfun->machine->has_hardware_loops
528 || cfun->machine->has_loopreg_clobber
529 || (ENABLE_WA_05000257 && (regno == REG_LC0 || regno == REG_LC1)))
530 emit_move_insn (gen_rtx_REG (SImode, regno), postinc);
532 emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
536 /* Perform any needed actions needed for a function that is receiving a
537 variable number of arguments.
539 CUM is as above.
541 MODE and TYPE are the mode and type of the current parameter.
543 PRETEND_SIZE is a variable that should be set to the amount of stack
544 that must be pushed by the prolog to pretend that our caller pushed
547 Normally, this macro will push all remaining incoming registers on the
548 stack and set PRETEND_SIZE to the length of the registers pushed.
550 Blackfin specific :
551 - VDSP C compiler manual (our ABI) says that a variable args function
552 should save the R0, R1 and R2 registers in the stack.
553 - The caller will always leave space on the stack for the
554 arguments that are passed in registers, so we dont have
555 to leave any extra space.
556 - now, the vastart pointer can access all arguments from the stack. */
558 static void
559 setup_incoming_varargs (cumulative_args_t cum,
560 machine_mode mode ATTRIBUTE_UNUSED,
561 tree type ATTRIBUTE_UNUSED, int *pretend_size,
562 int no_rtl)
564 rtx mem;
565 int i;
567 if (no_rtl)
568 return;
570 /* The move for named arguments will be generated automatically by the
571 compiler. We need to generate the move rtx for the unnamed arguments
572 if they are in the first 3 words. We assume at least 1 named argument
573 exists, so we never generate [ARGP] = R0 here. */
575 for (i = get_cumulative_args (cum)->words + 1; i < max_arg_registers; i++)
577 mem = gen_rtx_MEM (Pmode,
578 plus_constant (Pmode, arg_pointer_rtx,
579 (i * UNITS_PER_WORD)));
580 emit_move_insn (mem, gen_rtx_REG (Pmode, i));
583 *pretend_size = 0;
586 /* Value should be nonzero if functions must have frame pointers.
587 Zero means the frame pointer need not be set up (and parms may
588 be accessed via the stack pointer) in functions that seem suitable. */
590 static bool
591 bfin_frame_pointer_required (void)
593 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
595 if (fkind != SUBROUTINE)
596 return true;
598 /* We turn on -fomit-frame-pointer if -momit-leaf-frame-pointer is used,
599 so we have to override it for non-leaf functions. */
600 if (TARGET_OMIT_LEAF_FRAME_POINTER && ! crtl->is_leaf)
601 return true;
603 return false;
606 /* Return the number of registers pushed during the prologue. */
608 static int
609 n_regs_saved_by_prologue (void)
611 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
612 bool is_inthandler = fkind != SUBROUTINE;
613 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
614 bool all = (lookup_attribute ("saveall", attrs) != NULL_TREE
615 || (is_inthandler && !crtl->is_leaf));
616 int ndregs = all ? 8 : n_dregs_to_save (is_inthandler, false);
617 int npregs = all ? 6 : n_pregs_to_save (is_inthandler, false);
618 int n = ndregs + npregs;
619 int i;
621 if (all || stack_frame_needed_p ())
622 n += 2;
623 else
625 if (must_save_fp_p ())
626 n++;
627 if (must_save_rets_p ())
628 n++;
631 if (fkind != SUBROUTINE || all)
633 /* Increment once for ASTAT. */
634 n++;
635 if (! crtl->is_leaf
636 || cfun->machine->has_hardware_loops
637 || cfun->machine->has_loopreg_clobber)
639 n += 6;
643 if (fkind != SUBROUTINE)
645 /* RETE/X/N. */
646 if (lookup_attribute ("nesting", attrs))
647 n++;
650 for (i = REG_P7 + 1; i < REG_CC; i++)
651 if (all
652 || (fkind != SUBROUTINE
653 && (df_regs_ever_live_p (i)
654 || (!leaf_function_p () && call_used_regs[i]))))
655 n += i == REG_A0 || i == REG_A1 ? 2 : 1;
657 return n;
660 /* Given FROM and TO register numbers, say whether this elimination is
661 allowed. Frame pointer elimination is automatically handled.
663 All other eliminations are valid. */
665 static bool
666 bfin_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
668 return (to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true);
671 /* Return the offset between two registers, one to be eliminated, and the other
672 its replacement, at the start of a routine. */
674 HOST_WIDE_INT
675 bfin_initial_elimination_offset (int from, int to)
677 HOST_WIDE_INT offset = 0;
679 if (from == ARG_POINTER_REGNUM)
680 offset = n_regs_saved_by_prologue () * 4;
682 if (to == STACK_POINTER_REGNUM)
684 if (crtl->outgoing_args_size >= FIXED_STACK_AREA)
685 offset += crtl->outgoing_args_size;
686 else if (crtl->outgoing_args_size)
687 offset += FIXED_STACK_AREA;
689 offset += get_frame_size ();
692 return offset;
695 /* Emit code to load a constant CONSTANT into register REG; setting
696 RTX_FRAME_RELATED_P on all insns we generate if RELATED is true.
697 Make sure that the insns we generate need not be split. */
699 static void
700 frame_related_constant_load (rtx reg, HOST_WIDE_INT constant, bool related)
702 rtx_insn *insn;
703 rtx cst = GEN_INT (constant);
705 if (constant >= -32768 && constant < 65536)
706 insn = emit_move_insn (reg, cst);
707 else
709 /* We don't call split_load_immediate here, since dwarf2out.c can get
710 confused about some of the more clever sequences it can generate. */
711 insn = emit_insn (gen_movsi_high (reg, cst));
712 if (related)
713 RTX_FRAME_RELATED_P (insn) = 1;
714 insn = emit_insn (gen_movsi_low (reg, reg, cst));
716 if (related)
717 RTX_FRAME_RELATED_P (insn) = 1;
720 /* Generate efficient code to add a value to a P register.
721 Set RTX_FRAME_RELATED_P on the generated insns if FRAME is nonzero.
722 EPILOGUE_P is zero if this function is called for prologue,
723 otherwise it's nonzero. And it's less than zero if this is for
724 sibcall epilogue. */
726 static void
727 add_to_reg (rtx reg, HOST_WIDE_INT value, int frame, int epilogue_p)
729 if (value == 0)
730 return;
732 /* Choose whether to use a sequence using a temporary register, or
733 a sequence with multiple adds. We can add a signed 7-bit value
734 in one instruction. */
735 if (value > 120 || value < -120)
737 rtx tmpreg;
738 rtx tmpreg2;
739 rtx_insn *insn;
741 tmpreg2 = NULL_RTX;
743 /* For prologue or normal epilogue, P1 can be safely used
744 as the temporary register. For sibcall epilogue, we try to find
745 a call used P register, which will be restored in epilogue.
746 If we cannot find such a P register, we have to use one I register
747 to help us. */
749 if (epilogue_p >= 0)
750 tmpreg = gen_rtx_REG (SImode, REG_P1);
751 else
753 int i;
754 for (i = REG_P0; i <= REG_P5; i++)
755 if ((df_regs_ever_live_p (i) && ! call_used_regs[i])
756 || (!TARGET_FDPIC
757 && i == PIC_OFFSET_TABLE_REGNUM
758 && (crtl->uses_pic_offset_table
759 || (TARGET_ID_SHARED_LIBRARY
760 && ! crtl->is_leaf))))
761 break;
762 if (i <= REG_P5)
763 tmpreg = gen_rtx_REG (SImode, i);
764 else
766 tmpreg = gen_rtx_REG (SImode, REG_P1);
767 tmpreg2 = gen_rtx_REG (SImode, REG_I0);
768 emit_move_insn (tmpreg2, tmpreg);
772 if (frame)
773 frame_related_constant_load (tmpreg, value, TRUE);
774 else
775 insn = emit_move_insn (tmpreg, GEN_INT (value));
777 insn = emit_insn (gen_addsi3 (reg, reg, tmpreg));
778 if (frame)
779 RTX_FRAME_RELATED_P (insn) = 1;
781 if (tmpreg2 != NULL_RTX)
782 emit_move_insn (tmpreg, tmpreg2);
784 else
787 int size = value;
788 rtx_insn *insn;
790 if (size > 60)
791 size = 60;
792 else if (size < -60)
793 /* We could use -62, but that would leave the stack unaligned, so
794 it's no good. */
795 size = -60;
797 insn = emit_insn (gen_addsi3 (reg, reg, GEN_INT (size)));
798 if (frame)
799 RTX_FRAME_RELATED_P (insn) = 1;
800 value -= size;
802 while (value != 0);
805 /* Generate a LINK insn for a frame sized FRAME_SIZE. If this constant
806 is too large, generate a sequence of insns that has the same effect.
807 SPREG contains (reg:SI REG_SP). */
809 static void
810 emit_link_insn (rtx spreg, HOST_WIDE_INT frame_size)
812 HOST_WIDE_INT link_size = frame_size;
813 rtx_insn *insn;
814 int i;
816 if (link_size > 262140)
817 link_size = 262140;
819 /* Use a LINK insn with as big a constant as possible, then subtract
820 any remaining size from the SP. */
821 insn = emit_insn (gen_link (GEN_INT (-8 - link_size)));
822 RTX_FRAME_RELATED_P (insn) = 1;
824 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
826 rtx set = XVECEXP (PATTERN (insn), 0, i);
827 gcc_assert (GET_CODE (set) == SET);
828 RTX_FRAME_RELATED_P (set) = 1;
831 frame_size -= link_size;
833 if (frame_size > 0)
835 /* Must use a call-clobbered PREG that isn't the static chain. */
836 rtx tmpreg = gen_rtx_REG (Pmode, REG_P1);
838 frame_related_constant_load (tmpreg, -frame_size, TRUE);
839 insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg));
840 RTX_FRAME_RELATED_P (insn) = 1;
844 /* Return the number of bytes we must reserve for outgoing arguments
845 in the current function's stack frame. */
847 static HOST_WIDE_INT
848 arg_area_size (void)
850 if (crtl->outgoing_args_size)
852 if (crtl->outgoing_args_size >= FIXED_STACK_AREA)
853 return crtl->outgoing_args_size;
854 else
855 return FIXED_STACK_AREA;
857 return 0;
860 /* Save RETS and FP, and allocate a stack frame. ALL is true if the
861 function must save all its registers (true only for certain interrupt
862 handlers). */
864 static void
865 do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all)
867 frame_size += arg_area_size ();
869 if (all
870 || stack_frame_needed_p ()
871 || (must_save_rets_p () && must_save_fp_p ()))
872 emit_link_insn (spreg, frame_size);
873 else
875 if (must_save_rets_p ())
877 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
878 gen_rtx_PRE_DEC (Pmode, spreg)),
879 bfin_rets_rtx);
880 rtx_insn *insn = emit_insn (pat);
881 RTX_FRAME_RELATED_P (insn) = 1;
883 if (must_save_fp_p ())
885 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
886 gen_rtx_PRE_DEC (Pmode, spreg)),
887 gen_rtx_REG (Pmode, REG_FP));
888 rtx_insn *insn = emit_insn (pat);
889 RTX_FRAME_RELATED_P (insn) = 1;
891 add_to_reg (spreg, -frame_size, 1, 0);
895 /* Like do_link, but used for epilogues to deallocate the stack frame.
896 EPILOGUE_P is zero if this function is called for prologue,
897 otherwise it's nonzero. And it's less than zero if this is for
898 sibcall epilogue. */
900 static void
901 do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all, int epilogue_p)
903 frame_size += arg_area_size ();
905 if (stack_frame_needed_p ())
906 emit_insn (gen_unlink ());
907 else
909 rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg));
911 add_to_reg (spreg, frame_size, 0, epilogue_p);
912 if (all || must_save_fp_p ())
914 rtx fpreg = gen_rtx_REG (Pmode, REG_FP);
915 emit_move_insn (fpreg, postinc);
916 emit_use (fpreg);
918 if (all || must_save_rets_p ())
920 emit_move_insn (bfin_rets_rtx, postinc);
921 emit_use (bfin_rets_rtx);
926 /* Generate a prologue suitable for a function of kind FKIND. This is
927 called for interrupt and exception handler prologues.
928 SPREG contains (reg:SI REG_SP). */
930 static void
931 expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind, bool all)
933 HOST_WIDE_INT frame_size = get_frame_size ();
934 rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
935 rtx predec = gen_rtx_MEM (SImode, predec1);
936 rtx_insn *insn;
937 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
938 tree kspisusp = lookup_attribute ("kspisusp", attrs);
940 if (kspisusp)
942 insn = emit_move_insn (spreg, gen_rtx_REG (Pmode, REG_USP));
943 RTX_FRAME_RELATED_P (insn) = 1;
946 /* We need space on the stack in case we need to save the argument
947 registers. */
948 if (fkind == EXCPT_HANDLER)
950 insn = emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (-12)));
951 RTX_FRAME_RELATED_P (insn) = 1;
954 /* If we're calling other functions, they won't save their call-clobbered
955 registers, so we must save everything here. */
956 if (!crtl->is_leaf)
957 all = true;
958 expand_prologue_reg_save (spreg, all, true);
960 if (ENABLE_WA_05000283 || ENABLE_WA_05000315)
962 rtx chipid = GEN_INT (trunc_int_for_mode (0xFFC00014, SImode));
963 rtx p5reg = gen_rtx_REG (Pmode, REG_P5);
964 emit_insn (gen_movbi (bfin_cc_rtx, const1_rtx));
965 emit_insn (gen_movsi_high (p5reg, chipid));
966 emit_insn (gen_movsi_low (p5reg, p5reg, chipid));
967 emit_insn (gen_dummy_load (p5reg, bfin_cc_rtx));
970 if (lookup_attribute ("nesting", attrs))
972 rtx srcreg = gen_rtx_REG (Pmode, ret_regs[fkind]);
973 insn = emit_move_insn (predec, srcreg);
974 RTX_FRAME_RELATED_P (insn) = 1;
977 do_link (spreg, frame_size, all);
979 if (fkind == EXCPT_HANDLER)
981 rtx r0reg = gen_rtx_REG (SImode, REG_R0);
982 rtx r1reg = gen_rtx_REG (SImode, REG_R1);
983 rtx r2reg = gen_rtx_REG (SImode, REG_R2);
985 emit_move_insn (r0reg, gen_rtx_REG (SImode, REG_SEQSTAT));
986 emit_insn (gen_ashrsi3 (r0reg, r0reg, GEN_INT (26)));
987 emit_insn (gen_ashlsi3 (r0reg, r0reg, GEN_INT (26)));
988 emit_move_insn (r1reg, spreg);
989 emit_move_insn (r2reg, gen_rtx_REG (Pmode, REG_FP));
990 emit_insn (gen_addsi3 (r2reg, r2reg, GEN_INT (8)));
994 /* Generate an epilogue suitable for a function of kind FKIND. This is
995 called for interrupt and exception handler epilogues.
996 SPREG contains (reg:SI REG_SP). */
998 static void
999 expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind, bool all)
1001 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1002 rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
1003 rtx postinc = gen_rtx_MEM (SImode, postinc1);
1005 /* A slightly crude technique to stop flow from trying to delete "dead"
1006 insns. */
1007 MEM_VOLATILE_P (postinc) = 1;
1009 do_unlink (spreg, get_frame_size (), all, 1);
1011 if (lookup_attribute ("nesting", attrs))
1013 rtx srcreg = gen_rtx_REG (Pmode, ret_regs[fkind]);
1014 emit_move_insn (srcreg, postinc);
1017 /* If we're calling other functions, they won't save their call-clobbered
1018 registers, so we must save (and restore) everything here. */
1019 if (!crtl->is_leaf)
1020 all = true;
1022 expand_epilogue_reg_restore (spreg, all, true);
1024 /* Deallocate any space we left on the stack in case we needed to save the
1025 argument registers. */
1026 if (fkind == EXCPT_HANDLER)
1027 emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (12)));
1029 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, ret_regs[fkind])));
1032 /* Used while emitting the prologue to generate code to load the correct value
1033 into the PIC register, which is passed in DEST. */
1035 static rtx
1036 bfin_load_pic_reg (rtx dest)
1038 struct cgraph_local_info *i = NULL;
1039 rtx addr;
1041 i = cgraph_node::local_info (current_function_decl);
1043 /* Functions local to the translation unit don't need to reload the
1044 pic reg, since the caller always passes a usable one. */
1045 if (i && i->local)
1046 return pic_offset_table_rtx;
1048 if (global_options_set.x_bfin_library_id)
1049 addr = plus_constant (Pmode, pic_offset_table_rtx,
1050 -4 - bfin_library_id * 4);
1051 else
1052 addr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
1053 gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
1054 UNSPEC_LIBRARY_OFFSET));
1055 emit_insn (gen_movsi (dest, gen_rtx_MEM (Pmode, addr)));
1056 return dest;
1059 /* Generate RTL for the prologue of the current function. */
1061 void
1062 bfin_expand_prologue (void)
1064 HOST_WIDE_INT frame_size = get_frame_size ();
1065 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
1066 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1067 rtx pic_reg_loaded = NULL_RTX;
1068 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1069 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
1071 if (flag_stack_usage_info)
1072 current_function_static_stack_size = frame_size;
1074 if (fkind != SUBROUTINE)
1076 expand_interrupt_handler_prologue (spreg, fkind, all);
1077 return;
1080 if (crtl->limit_stack
1081 || (TARGET_STACK_CHECK_L1
1082 && !DECL_NO_LIMIT_STACK (current_function_decl)))
1084 HOST_WIDE_INT offset
1085 = bfin_initial_elimination_offset (ARG_POINTER_REGNUM,
1086 STACK_POINTER_REGNUM);
1087 rtx lim = crtl->limit_stack ? stack_limit_rtx : NULL_RTX;
1088 rtx tmp = gen_rtx_REG (Pmode, REG_R3);
1089 rtx p2reg = gen_rtx_REG (Pmode, REG_P2);
1091 emit_move_insn (tmp, p2reg);
1092 if (!lim)
1094 emit_move_insn (p2reg, gen_int_mode (0xFFB00000, SImode));
1095 emit_move_insn (p2reg, gen_rtx_MEM (Pmode, p2reg));
1096 lim = p2reg;
1098 if (GET_CODE (lim) == SYMBOL_REF)
1100 if (TARGET_ID_SHARED_LIBRARY)
1102 rtx p1reg = gen_rtx_REG (Pmode, REG_P1);
1103 rtx val;
1104 pic_reg_loaded = bfin_load_pic_reg (p2reg);
1105 val = legitimize_pic_address (stack_limit_rtx, p1reg,
1106 pic_reg_loaded);
1107 emit_move_insn (p1reg, val);
1108 frame_related_constant_load (p2reg, offset, FALSE);
1109 emit_insn (gen_addsi3 (p2reg, p2reg, p1reg));
1110 lim = p2reg;
1112 else
1114 rtx limit = plus_constant (Pmode, lim, offset);
1115 emit_move_insn (p2reg, limit);
1116 lim = p2reg;
1119 else
1121 if (lim != p2reg)
1122 emit_move_insn (p2reg, lim);
1123 add_to_reg (p2reg, offset, 0, 0);
1124 lim = p2reg;
1126 emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim));
1127 emit_insn (gen_trapifcc ());
1128 emit_move_insn (p2reg, tmp);
1130 expand_prologue_reg_save (spreg, all, false);
1132 do_link (spreg, frame_size, all);
1134 if (TARGET_ID_SHARED_LIBRARY
1135 && !TARGET_SEP_DATA
1136 && (crtl->uses_pic_offset_table
1137 || !crtl->is_leaf))
1138 bfin_load_pic_reg (pic_offset_table_rtx);
1141 /* Generate RTL for the epilogue of the current function. NEED_RETURN is zero
1142 if this is for a sibcall. EH_RETURN is nonzero if we're expanding an
1143 eh_return pattern. SIBCALL_P is true if this is a sibcall epilogue,
1144 false otherwise. */
1146 void
1147 bfin_expand_epilogue (int need_return, int eh_return, bool sibcall_p)
1149 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
1150 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1151 int e = sibcall_p ? -1 : 1;
1152 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1153 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
1155 if (fkind != SUBROUTINE)
1157 expand_interrupt_handler_epilogue (spreg, fkind, all);
1158 return;
1161 do_unlink (spreg, get_frame_size (), all, e);
1163 expand_epilogue_reg_restore (spreg, all, false);
1165 /* Omit the return insn if this is for a sibcall. */
1166 if (! need_return)
1167 return;
1169 if (eh_return)
1170 emit_insn (gen_addsi3 (spreg, spreg, gen_rtx_REG (Pmode, REG_P2)));
1172 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, REG_RETS)));
1175 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
1178 bfin_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
1179 unsigned int new_reg)
1181 /* Interrupt functions can only use registers that have already been
1182 saved by the prologue, even if they would normally be
1183 call-clobbered. */
1185 if (funkind (TREE_TYPE (current_function_decl)) != SUBROUTINE
1186 && !df_regs_ever_live_p (new_reg))
1187 return 0;
1189 return 1;
1192 /* Implement TARGET_EXTRA_LIVE_ON_ENTRY. */
1193 static void
1194 bfin_extra_live_on_entry (bitmap regs)
1196 if (TARGET_FDPIC)
1197 bitmap_set_bit (regs, FDPIC_REGNO);
1200 /* Return the value of the return address for the frame COUNT steps up
1201 from the current frame, after the prologue.
1202 We punt for everything but the current frame by returning const0_rtx. */
1205 bfin_return_addr_rtx (int count)
1207 if (count != 0)
1208 return const0_rtx;
1210 return get_hard_reg_initial_val (Pmode, REG_RETS);
1213 static rtx
1214 bfin_delegitimize_address (rtx orig_x)
1216 rtx x = orig_x;
1218 if (GET_CODE (x) != MEM)
1219 return orig_x;
1221 x = XEXP (x, 0);
1222 if (GET_CODE (x) == PLUS
1223 && GET_CODE (XEXP (x, 1)) == UNSPEC
1224 && XINT (XEXP (x, 1), 1) == UNSPEC_MOVE_PIC
1225 && GET_CODE (XEXP (x, 0)) == REG
1226 && REGNO (XEXP (x, 0)) == PIC_OFFSET_TABLE_REGNUM)
1227 return XVECEXP (XEXP (x, 1), 0, 0);
1229 return orig_x;
1232 /* This predicate is used to compute the length of a load/store insn.
1233 OP is a MEM rtx, we return nonzero if its addressing mode requires a
1234 32-bit instruction. */
1237 effective_address_32bit_p (rtx op, machine_mode mode)
1239 HOST_WIDE_INT offset;
1241 mode = GET_MODE (op);
1242 op = XEXP (op, 0);
1244 if (GET_CODE (op) != PLUS)
1246 gcc_assert (REG_P (op) || GET_CODE (op) == POST_INC
1247 || GET_CODE (op) == PRE_DEC || GET_CODE (op) == POST_DEC);
1248 return 0;
1251 if (GET_CODE (XEXP (op, 1)) == UNSPEC)
1252 return 1;
1254 offset = INTVAL (XEXP (op, 1));
1256 /* All byte loads use a 16-bit offset. */
1257 if (GET_MODE_SIZE (mode) == 1)
1258 return 1;
1260 if (GET_MODE_SIZE (mode) == 4)
1262 /* Frame pointer relative loads can use a negative offset, all others
1263 are restricted to a small positive one. */
1264 if (XEXP (op, 0) == frame_pointer_rtx)
1265 return offset < -128 || offset > 60;
1266 return offset < 0 || offset > 60;
1269 /* Must be HImode now. */
1270 return offset < 0 || offset > 30;
1273 /* Returns true if X is a memory reference using an I register. */
1274 bool
1275 bfin_dsp_memref_p (rtx x)
1277 if (! MEM_P (x))
1278 return false;
1279 x = XEXP (x, 0);
1280 if (GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_INC
1281 || GET_CODE (x) == POST_DEC || GET_CODE (x) == PRE_DEC)
1282 x = XEXP (x, 0);
1283 return IREG_P (x);
1286 /* Return cost of the memory address ADDR.
1287 All addressing modes are equally cheap on the Blackfin. */
1289 static int
1290 bfin_address_cost (rtx addr ATTRIBUTE_UNUSED,
1291 machine_mode mode ATTRIBUTE_UNUSED,
1292 addr_space_t as ATTRIBUTE_UNUSED,
1293 bool speed ATTRIBUTE_UNUSED)
1295 return 1;
1298 /* Subroutine of print_operand; used to print a memory reference X to FILE. */
1300 void
1301 print_address_operand (FILE *file, rtx x)
1303 switch (GET_CODE (x))
1305 case PLUS:
1306 output_address (VOIDmode, XEXP (x, 0));
1307 fprintf (file, "+");
1308 output_address (VOIDmode, XEXP (x, 1));
1309 break;
1311 case PRE_DEC:
1312 fprintf (file, "--");
1313 output_address (VOIDmode, XEXP (x, 0));
1314 break;
1315 case POST_INC:
1316 output_address (VOIDmode, XEXP (x, 0));
1317 fprintf (file, "++");
1318 break;
1319 case POST_DEC:
1320 output_address (VOIDmode, XEXP (x, 0));
1321 fprintf (file, "--");
1322 break;
1324 default:
1325 gcc_assert (GET_CODE (x) != MEM);
1326 print_operand (file, x, 0);
1327 break;
1331 /* Adding intp DImode support by Tony
1332 * -- Q: (low word)
1333 * -- R: (high word)
1336 void
1337 print_operand (FILE *file, rtx x, char code)
1339 machine_mode mode;
1341 if (code == '!')
1343 if (GET_MODE (current_output_insn) == SImode)
1344 fprintf (file, " ||");
1345 else
1346 fprintf (file, ";");
1347 return;
1350 mode = GET_MODE (x);
1352 switch (code)
1354 case 'j':
1355 switch (GET_CODE (x))
1357 case EQ:
1358 fprintf (file, "e");
1359 break;
1360 case NE:
1361 fprintf (file, "ne");
1362 break;
1363 case GT:
1364 fprintf (file, "g");
1365 break;
1366 case LT:
1367 fprintf (file, "l");
1368 break;
1369 case GE:
1370 fprintf (file, "ge");
1371 break;
1372 case LE:
1373 fprintf (file, "le");
1374 break;
1375 case GTU:
1376 fprintf (file, "g");
1377 break;
1378 case LTU:
1379 fprintf (file, "l");
1380 break;
1381 case GEU:
1382 fprintf (file, "ge");
1383 break;
1384 case LEU:
1385 fprintf (file, "le");
1386 break;
1387 default:
1388 output_operand_lossage ("invalid %%j value");
1390 break;
1392 case 'J': /* reverse logic */
1393 switch (GET_CODE(x))
1395 case EQ:
1396 fprintf (file, "ne");
1397 break;
1398 case NE:
1399 fprintf (file, "e");
1400 break;
1401 case GT:
1402 fprintf (file, "le");
1403 break;
1404 case LT:
1405 fprintf (file, "ge");
1406 break;
1407 case GE:
1408 fprintf (file, "l");
1409 break;
1410 case LE:
1411 fprintf (file, "g");
1412 break;
1413 case GTU:
1414 fprintf (file, "le");
1415 break;
1416 case LTU:
1417 fprintf (file, "ge");
1418 break;
1419 case GEU:
1420 fprintf (file, "l");
1421 break;
1422 case LEU:
1423 fprintf (file, "g");
1424 break;
1425 default:
1426 output_operand_lossage ("invalid %%J value");
1428 break;
1430 default:
1431 switch (GET_CODE (x))
1433 case REG:
1434 if (code == 'h')
1436 if (REGNO (x) < 32)
1437 fprintf (file, "%s", short_reg_names[REGNO (x)]);
1438 else
1439 output_operand_lossage ("invalid operand for code '%c'", code);
1441 else if (code == 'd')
1443 if (REGNO (x) < 32)
1444 fprintf (file, "%s", high_reg_names[REGNO (x)]);
1445 else
1446 output_operand_lossage ("invalid operand for code '%c'", code);
1448 else if (code == 'w')
1450 if (REGNO (x) == REG_A0 || REGNO (x) == REG_A1)
1451 fprintf (file, "%s.w", reg_names[REGNO (x)]);
1452 else
1453 output_operand_lossage ("invalid operand for code '%c'", code);
1455 else if (code == 'x')
1457 if (REGNO (x) == REG_A0 || REGNO (x) == REG_A1)
1458 fprintf (file, "%s.x", reg_names[REGNO (x)]);
1459 else
1460 output_operand_lossage ("invalid operand for code '%c'", code);
1462 else if (code == 'v')
1464 if (REGNO (x) == REG_A0)
1465 fprintf (file, "AV0");
1466 else if (REGNO (x) == REG_A1)
1467 fprintf (file, "AV1");
1468 else
1469 output_operand_lossage ("invalid operand for code '%c'", code);
1471 else if (code == 'D')
1473 if (D_REGNO_P (REGNO (x)))
1474 fprintf (file, "%s", dregs_pair_names[REGNO (x)]);
1475 else
1476 output_operand_lossage ("invalid operand for code '%c'", code);
1478 else if (code == 'H')
1480 if ((mode == DImode || mode == DFmode) && REG_P (x))
1481 fprintf (file, "%s", reg_names[REGNO (x) + 1]);
1482 else
1483 output_operand_lossage ("invalid operand for code '%c'", code);
1485 else if (code == 'T')
1487 if (D_REGNO_P (REGNO (x)))
1488 fprintf (file, "%s", byte_reg_names[REGNO (x)]);
1489 else
1490 output_operand_lossage ("invalid operand for code '%c'", code);
1492 else
1493 fprintf (file, "%s", reg_names[REGNO (x)]);
1494 break;
1496 case MEM:
1497 fputc ('[', file);
1498 x = XEXP (x,0);
1499 print_address_operand (file, x);
1500 fputc (']', file);
1501 break;
1503 case CONST_INT:
1504 if (code == 'M')
1506 switch (INTVAL (x))
1508 case MACFLAG_NONE:
1509 break;
1510 case MACFLAG_FU:
1511 fputs ("(FU)", file);
1512 break;
1513 case MACFLAG_T:
1514 fputs ("(T)", file);
1515 break;
1516 case MACFLAG_TFU:
1517 fputs ("(TFU)", file);
1518 break;
1519 case MACFLAG_W32:
1520 fputs ("(W32)", file);
1521 break;
1522 case MACFLAG_IS:
1523 fputs ("(IS)", file);
1524 break;
1525 case MACFLAG_IU:
1526 fputs ("(IU)", file);
1527 break;
1528 case MACFLAG_IH:
1529 fputs ("(IH)", file);
1530 break;
1531 case MACFLAG_M:
1532 fputs ("(M)", file);
1533 break;
1534 case MACFLAG_IS_M:
1535 fputs ("(IS,M)", file);
1536 break;
1537 case MACFLAG_ISS2:
1538 fputs ("(ISS2)", file);
1539 break;
1540 case MACFLAG_S2RND:
1541 fputs ("(S2RND)", file);
1542 break;
1543 default:
1544 gcc_unreachable ();
1546 break;
1548 else if (code == 'b')
1550 if (INTVAL (x) == 0)
1551 fputs ("+=", file);
1552 else if (INTVAL (x) == 1)
1553 fputs ("-=", file);
1554 else
1555 gcc_unreachable ();
1556 break;
1558 /* Moves to half registers with d or h modifiers always use unsigned
1559 constants. */
1560 else if (code == 'd')
1561 x = GEN_INT ((INTVAL (x) >> 16) & 0xffff);
1562 else if (code == 'h')
1563 x = GEN_INT (INTVAL (x) & 0xffff);
1564 else if (code == 'N')
1565 x = GEN_INT (-INTVAL (x));
1566 else if (code == 'X')
1567 x = GEN_INT (exact_log2 (0xffffffff & INTVAL (x)));
1568 else if (code == 'Y')
1569 x = GEN_INT (exact_log2 (0xffffffff & ~INTVAL (x)));
1570 else if (code == 'Z')
1571 /* Used for LINK insns. */
1572 x = GEN_INT (-8 - INTVAL (x));
1574 /* fall through */
1576 case SYMBOL_REF:
1577 output_addr_const (file, x);
1578 break;
1580 case CONST_DOUBLE:
1581 output_operand_lossage ("invalid const_double operand");
1582 break;
1584 case UNSPEC:
1585 switch (XINT (x, 1))
1587 case UNSPEC_MOVE_PIC:
1588 output_addr_const (file, XVECEXP (x, 0, 0));
1589 fprintf (file, "@GOT");
1590 break;
1592 case UNSPEC_MOVE_FDPIC:
1593 output_addr_const (file, XVECEXP (x, 0, 0));
1594 fprintf (file, "@GOT17M4");
1595 break;
1597 case UNSPEC_FUNCDESC_GOT17M4:
1598 output_addr_const (file, XVECEXP (x, 0, 0));
1599 fprintf (file, "@FUNCDESC_GOT17M4");
1600 break;
1602 case UNSPEC_LIBRARY_OFFSET:
1603 fprintf (file, "_current_shared_library_p5_offset_");
1604 break;
1606 default:
1607 gcc_unreachable ();
1609 break;
1611 default:
1612 output_addr_const (file, x);
1617 /* Argument support functions. */
1619 /* Initialize a variable CUM of type CUMULATIVE_ARGS
1620 for a call to a function whose data type is FNTYPE.
1621 For a library call, FNTYPE is 0.
1622 VDSP C Compiler manual, our ABI says that
1623 first 3 words of arguments will use R0, R1 and R2.
1626 void
1627 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
1628 rtx libname ATTRIBUTE_UNUSED)
1630 static CUMULATIVE_ARGS zero_cum;
1632 *cum = zero_cum;
1634 /* Set up the number of registers to use for passing arguments. */
1636 cum->nregs = max_arg_registers;
1637 cum->arg_regs = arg_regs;
1639 cum->call_cookie = CALL_NORMAL;
1640 /* Check for a longcall attribute. */
1641 if (fntype && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype)))
1642 cum->call_cookie |= CALL_SHORT;
1643 else if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)))
1644 cum->call_cookie |= CALL_LONG;
1646 return;
1649 /* Update the data in CUM to advance over an argument
1650 of mode MODE and data type TYPE.
1651 (TYPE is null for libcalls where that information may not be available.) */
1653 static void
1654 bfin_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
1655 const_tree type, bool named ATTRIBUTE_UNUSED)
1657 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
1658 int count, bytes, words;
1660 bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1661 words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1663 cum->words += words;
1664 cum->nregs -= words;
1666 if (cum->nregs <= 0)
1668 cum->nregs = 0;
1669 cum->arg_regs = NULL;
1671 else
1673 for (count = 1; count <= words; count++)
1674 cum->arg_regs++;
1677 return;
1680 /* Define where to put the arguments to a function.
1681 Value is zero to push the argument on the stack,
1682 or a hard register in which to store the argument.
1684 MODE is the argument's machine mode.
1685 TYPE is the data type of the argument (as a tree).
1686 This is null for libcalls where that information may
1687 not be available.
1688 CUM is a variable of type CUMULATIVE_ARGS which gives info about
1689 the preceding args and about the function being called.
1690 NAMED is nonzero if this argument is a named parameter
1691 (otherwise it is an extra parameter matching an ellipsis). */
1693 static rtx
1694 bfin_function_arg (cumulative_args_t cum_v, machine_mode mode,
1695 const_tree type, bool named ATTRIBUTE_UNUSED)
1697 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
1698 int bytes
1699 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1701 if (mode == VOIDmode)
1702 /* Compute operand 2 of the call insn. */
1703 return GEN_INT (cum->call_cookie);
1705 if (bytes == -1)
1706 return NULL_RTX;
1708 if (cum->nregs)
1709 return gen_rtx_REG (mode, *(cum->arg_regs));
1711 return NULL_RTX;
1714 /* For an arg passed partly in registers and partly in memory,
1715 this is the number of bytes passed in registers.
1716 For args passed entirely in registers or entirely in memory, zero.
1718 Refer VDSP C Compiler manual, our ABI.
1719 First 3 words are in registers. So, if an argument is larger
1720 than the registers available, it will span the register and
1721 stack. */
1723 static int
1724 bfin_arg_partial_bytes (cumulative_args_t cum, machine_mode mode,
1725 tree type ATTRIBUTE_UNUSED,
1726 bool named ATTRIBUTE_UNUSED)
1728 int bytes
1729 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1730 int bytes_left = get_cumulative_args (cum)->nregs * UNITS_PER_WORD;
1732 if (bytes == -1)
1733 return 0;
1735 if (bytes_left == 0)
1736 return 0;
1737 if (bytes > bytes_left)
1738 return bytes_left;
1739 return 0;
1742 /* Variable sized types are passed by reference. */
1744 static bool
1745 bfin_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
1746 machine_mode mode ATTRIBUTE_UNUSED,
1747 const_tree type, bool named ATTRIBUTE_UNUSED)
1749 return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
1752 /* Decide whether a type should be returned in memory (true)
1753 or in a register (false). This is called by the macro
1754 TARGET_RETURN_IN_MEMORY. */
1756 static bool
1757 bfin_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
1759 int size = int_size_in_bytes (type);
1760 return size > 2 * UNITS_PER_WORD || size == -1;
1763 /* Register in which address to store a structure value
1764 is passed to a function. */
1765 static rtx
1766 bfin_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
1767 int incoming ATTRIBUTE_UNUSED)
1769 return gen_rtx_REG (Pmode, REG_P0);
1772 /* Return true when register may be used to pass function parameters. */
1774 bool
1775 function_arg_regno_p (int n)
1777 int i;
1778 for (i = 0; arg_regs[i] != -1; i++)
1779 if (n == arg_regs[i])
1780 return true;
1781 return false;
1784 /* Returns 1 if OP contains a symbol reference */
1787 symbolic_reference_mentioned_p (rtx op)
1789 register const char *fmt;
1790 register int i;
1792 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
1793 return 1;
1795 fmt = GET_RTX_FORMAT (GET_CODE (op));
1796 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
1798 if (fmt[i] == 'E')
1800 register int j;
1802 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
1803 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
1804 return 1;
1807 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
1808 return 1;
1811 return 0;
1814 /* Decide whether we can make a sibling call to a function. DECL is the
1815 declaration of the function being targeted by the call and EXP is the
1816 CALL_EXPR representing the call. */
1818 static bool
1819 bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
1820 tree exp ATTRIBUTE_UNUSED)
1822 struct cgraph_local_info *this_func, *called_func;
1823 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1824 if (fkind != SUBROUTINE)
1825 return false;
1826 if (!TARGET_ID_SHARED_LIBRARY || TARGET_SEP_DATA)
1827 return true;
1829 /* When compiling for ID shared libraries, can't sibcall a local function
1830 from a non-local function, because the local function thinks it does
1831 not need to reload P5 in the prologue, but the sibcall wil pop P5 in the
1832 sibcall epilogue, and we end up with the wrong value in P5. */
1834 if (!decl)
1835 /* Not enough information. */
1836 return false;
1838 this_func = cgraph_node::local_info (current_function_decl);
1839 called_func = cgraph_node::local_info (decl);
1840 if (!called_func)
1841 return false;
1842 return !called_func->local || this_func->local;
1845 /* Write a template for a trampoline to F. */
1847 static void
1848 bfin_asm_trampoline_template (FILE *f)
1850 if (TARGET_FDPIC)
1852 fprintf (f, "\t.dd\t0x00000000\n"); /* 0 */
1853 fprintf (f, "\t.dd\t0x00000000\n"); /* 0 */
1854 fprintf (f, "\t.dd\t0x0000e109\n"); /* p1.l = fn low */
1855 fprintf (f, "\t.dd\t0x0000e149\n"); /* p1.h = fn high */
1856 fprintf (f, "\t.dd\t0x0000e10a\n"); /* p2.l = sc low */
1857 fprintf (f, "\t.dd\t0x0000e14a\n"); /* p2.h = sc high */
1858 fprintf (f, "\t.dw\t0xac4b\n"); /* p3 = [p1 + 4] */
1859 fprintf (f, "\t.dw\t0x9149\n"); /* p1 = [p1] */
1860 fprintf (f, "\t.dw\t0x0051\n"); /* jump (p1)*/
1862 else
1864 fprintf (f, "\t.dd\t0x0000e109\n"); /* p1.l = fn low */
1865 fprintf (f, "\t.dd\t0x0000e149\n"); /* p1.h = fn high */
1866 fprintf (f, "\t.dd\t0x0000e10a\n"); /* p2.l = sc low */
1867 fprintf (f, "\t.dd\t0x0000e14a\n"); /* p2.h = sc high */
1868 fprintf (f, "\t.dw\t0x0051\n"); /* jump (p1)*/
1872 /* Emit RTL insns to initialize the variable parts of a trampoline at
1873 M_TRAMP. FNDECL is the target function. CHAIN_VALUE is an RTX for
1874 the static chain value for the function. */
1876 static void
1877 bfin_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
1879 rtx t1 = copy_to_reg (XEXP (DECL_RTL (fndecl), 0));
1880 rtx t2 = copy_to_reg (chain_value);
1881 rtx mem;
1882 int i = 0;
1884 emit_block_move (m_tramp, assemble_trampoline_template (),
1885 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
1887 if (TARGET_FDPIC)
1889 rtx a = force_reg (Pmode, plus_constant (Pmode, XEXP (m_tramp, 0), 8));
1890 mem = adjust_address (m_tramp, Pmode, 0);
1891 emit_move_insn (mem, a);
1892 i = 8;
1895 mem = adjust_address (m_tramp, HImode, i + 2);
1896 emit_move_insn (mem, gen_lowpart (HImode, t1));
1897 emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16)));
1898 mem = adjust_address (m_tramp, HImode, i + 6);
1899 emit_move_insn (mem, gen_lowpart (HImode, t1));
1901 mem = adjust_address (m_tramp, HImode, i + 10);
1902 emit_move_insn (mem, gen_lowpart (HImode, t2));
1903 emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16)));
1904 mem = adjust_address (m_tramp, HImode, i + 14);
1905 emit_move_insn (mem, gen_lowpart (HImode, t2));
1908 /* Emit insns to move operands[1] into operands[0]. */
1910 void
1911 emit_pic_move (rtx *operands, machine_mode mode ATTRIBUTE_UNUSED)
1913 rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
1915 gcc_assert (!TARGET_FDPIC || !(reload_in_progress || reload_completed));
1916 if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
1917 operands[1] = force_reg (SImode, operands[1]);
1918 else
1919 operands[1] = legitimize_pic_address (operands[1], temp,
1920 TARGET_FDPIC ? OUR_FDPIC_REG
1921 : pic_offset_table_rtx);
1924 /* Expand a move operation in mode MODE. The operands are in OPERANDS.
1925 Returns true if no further code must be generated, false if the caller
1926 should generate an insn to move OPERANDS[1] to OPERANDS[0]. */
1928 bool
1929 expand_move (rtx *operands, machine_mode mode)
1931 rtx op = operands[1];
1932 if ((TARGET_ID_SHARED_LIBRARY || TARGET_FDPIC)
1933 && SYMBOLIC_CONST (op))
1934 emit_pic_move (operands, mode);
1935 else if (mode == SImode && GET_CODE (op) == CONST
1936 && GET_CODE (XEXP (op, 0)) == PLUS
1937 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
1938 && !targetm.legitimate_constant_p (mode, op))
1940 rtx dest = operands[0];
1941 rtx op0, op1;
1942 gcc_assert (!reload_in_progress && !reload_completed);
1943 op = XEXP (op, 0);
1944 op0 = force_reg (mode, XEXP (op, 0));
1945 op1 = XEXP (op, 1);
1946 if (!insn_data[CODE_FOR_addsi3].operand[2].predicate (op1, mode))
1947 op1 = force_reg (mode, op1);
1948 if (GET_CODE (dest) == MEM)
1949 dest = gen_reg_rtx (mode);
1950 emit_insn (gen_addsi3 (dest, op0, op1));
1951 if (dest == operands[0])
1952 return true;
1953 operands[1] = dest;
1955 /* Don't generate memory->memory or constant->memory moves, go through a
1956 register */
1957 else if ((reload_in_progress | reload_completed) == 0
1958 && GET_CODE (operands[0]) == MEM
1959 && GET_CODE (operands[1]) != REG)
1960 operands[1] = force_reg (mode, operands[1]);
1961 return false;
1964 /* Split one or more DImode RTL references into pairs of SImode
1965 references. The RTL can be REG, offsettable MEM, integer constant, or
1966 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
1967 split and "num" is its length. lo_half and hi_half are output arrays
1968 that parallel "operands". */
1970 void
1971 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
1973 while (num--)
1975 rtx op = operands[num];
1977 /* simplify_subreg refuse to split volatile memory addresses,
1978 but we still have to handle it. */
1979 if (GET_CODE (op) == MEM)
1981 lo_half[num] = adjust_address (op, SImode, 0);
1982 hi_half[num] = adjust_address (op, SImode, 4);
1984 else
1986 lo_half[num] = simplify_gen_subreg (SImode, op,
1987 GET_MODE (op) == VOIDmode
1988 ? DImode : GET_MODE (op), 0);
1989 hi_half[num] = simplify_gen_subreg (SImode, op,
1990 GET_MODE (op) == VOIDmode
1991 ? DImode : GET_MODE (op), 4);
1996 bool
1997 bfin_longcall_p (rtx op, int call_cookie)
1999 gcc_assert (GET_CODE (op) == SYMBOL_REF);
2000 if (SYMBOL_REF_WEAK (op))
2001 return 1;
2002 if (call_cookie & CALL_SHORT)
2003 return 0;
2004 if (call_cookie & CALL_LONG)
2005 return 1;
2006 if (TARGET_LONG_CALLS)
2007 return 1;
2008 return 0;
2011 /* Expand a call instruction. FNADDR is the call target, RETVAL the return value.
2012 COOKIE is a CONST_INT holding the call_cookie prepared init_cumulative_args.
2013 SIBCALL is nonzero if this is a sibling call. */
2015 void
2016 bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
2018 rtx use = NULL, call;
2019 rtx callee = XEXP (fnaddr, 0);
2020 int nelts = 3;
2021 rtx pat;
2022 rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REGNO);
2023 rtx retsreg = gen_rtx_REG (Pmode, REG_RETS);
2024 int n;
2026 /* In an untyped call, we can get NULL for operand 2. */
2027 if (cookie == NULL_RTX)
2028 cookie = const0_rtx;
2030 /* Static functions and indirect calls don't need the pic register. */
2031 if (!TARGET_FDPIC && flag_pic
2032 && GET_CODE (callee) == SYMBOL_REF
2033 && !SYMBOL_REF_LOCAL_P (callee))
2034 use_reg (&use, pic_offset_table_rtx);
2036 if (TARGET_FDPIC)
2038 int caller_in_sram, callee_in_sram;
2040 /* 0 is not in sram, 1 is in L1 sram, 2 is in L2 sram. */
2041 caller_in_sram = callee_in_sram = 0;
2043 if (lookup_attribute ("l1_text",
2044 DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE)
2045 caller_in_sram = 1;
2046 else if (lookup_attribute ("l2",
2047 DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE)
2048 caller_in_sram = 2;
2050 if (GET_CODE (callee) == SYMBOL_REF
2051 && SYMBOL_REF_DECL (callee) && DECL_P (SYMBOL_REF_DECL (callee)))
2053 if (lookup_attribute
2054 ("l1_text",
2055 DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE)
2056 callee_in_sram = 1;
2057 else if (lookup_attribute
2058 ("l2",
2059 DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE)
2060 callee_in_sram = 2;
2063 if (GET_CODE (callee) != SYMBOL_REF
2064 || bfin_longcall_p (callee, INTVAL (cookie))
2065 || (GET_CODE (callee) == SYMBOL_REF
2066 && !SYMBOL_REF_LOCAL_P (callee)
2067 && TARGET_INLINE_PLT)
2068 || caller_in_sram != callee_in_sram
2069 || (caller_in_sram && callee_in_sram
2070 && (GET_CODE (callee) != SYMBOL_REF
2071 || !SYMBOL_REF_LOCAL_P (callee))))
2073 rtx addr = callee;
2074 if (! address_operand (addr, Pmode))
2075 addr = force_reg (Pmode, addr);
2077 fnaddr = gen_reg_rtx (SImode);
2078 emit_insn (gen_load_funcdescsi (fnaddr, addr));
2079 fnaddr = gen_rtx_MEM (Pmode, fnaddr);
2081 picreg = gen_reg_rtx (SImode);
2082 emit_insn (gen_load_funcdescsi (picreg,
2083 plus_constant (Pmode, addr, 4)));
2086 nelts++;
2088 else if ((!register_no_elim_operand (callee, Pmode)
2089 && GET_CODE (callee) != SYMBOL_REF)
2090 || (GET_CODE (callee) == SYMBOL_REF
2091 && ((TARGET_ID_SHARED_LIBRARY && !TARGET_LEAF_ID_SHARED_LIBRARY)
2092 || bfin_longcall_p (callee, INTVAL (cookie)))))
2094 callee = copy_to_mode_reg (Pmode, callee);
2095 fnaddr = gen_rtx_MEM (Pmode, callee);
2097 call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
2099 if (retval)
2100 call = gen_rtx_SET (retval, call);
2102 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nelts));
2103 n = 0;
2104 XVECEXP (pat, 0, n++) = call;
2105 if (TARGET_FDPIC)
2106 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, picreg);
2107 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie);
2108 if (sibcall)
2109 XVECEXP (pat, 0, n++) = ret_rtx;
2110 else
2111 XVECEXP (pat, 0, n++) = gen_rtx_CLOBBER (VOIDmode, retsreg);
2112 call = emit_call_insn (pat);
2113 if (use)
2114 CALL_INSN_FUNCTION_USAGE (call) = use;
2117 /* Implement TARGET_HARD_REGNO_NREGS. */
2119 static unsigned int
2120 bfin_hard_regno_nregs (unsigned int regno, machine_mode mode)
2122 if (mode == PDImode && (regno == REG_A0 || regno == REG_A1))
2123 return 1;
2124 if (mode == V2PDImode && (regno == REG_A0 || regno == REG_A1))
2125 return 2;
2126 return CLASS_MAX_NREGS (GENERAL_REGS, mode);
2129 /* Implement TARGET_HARD_REGNO_MODE_OK.
2131 Do not allow to store a value in REG_CC for any mode.
2132 Do not allow to store value in pregs if mode is not SI. */
2133 static bool
2134 bfin_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
2136 /* Allow only dregs to store value of mode HI or QI */
2137 enum reg_class rclass = REGNO_REG_CLASS (regno);
2139 if (mode == CCmode)
2140 return false;
2142 if (mode == V2HImode)
2143 return D_REGNO_P (regno);
2144 if (rclass == CCREGS)
2145 return mode == BImode;
2146 if (mode == PDImode || mode == V2PDImode)
2147 return regno == REG_A0 || regno == REG_A1;
2149 /* Allow all normal 32-bit regs, except REG_M3, in case regclass ever comes
2150 up with a bad register class (such as ALL_REGS) for DImode. */
2151 if (mode == DImode)
2152 return regno < REG_M3;
2154 if (mode == SImode
2155 && TEST_HARD_REG_BIT (reg_class_contents[PROLOGUE_REGS], regno))
2156 return true;
2158 return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno);
2161 /* Implement TARGET_MODES_TIEABLE_P. */
2163 static bool
2164 bfin_modes_tieable_p (machine_mode mode1, machine_mode mode2)
2166 return (mode1 == mode2
2167 || ((GET_MODE_CLASS (mode1) == MODE_INT
2168 || GET_MODE_CLASS (mode1) == MODE_FLOAT)
2169 && (GET_MODE_CLASS (mode2) == MODE_INT
2170 || GET_MODE_CLASS (mode2) == MODE_FLOAT)
2171 && mode1 != BImode && mode2 != BImode
2172 && GET_MODE_SIZE (mode1) <= UNITS_PER_WORD
2173 && GET_MODE_SIZE (mode2) <= UNITS_PER_WORD));
2176 /* Implements target hook vector_mode_supported_p. */
2178 static bool
2179 bfin_vector_mode_supported_p (machine_mode mode)
2181 return mode == V2HImode;
2184 /* Worker function for TARGET_REGISTER_MOVE_COST. */
2186 static int
2187 bfin_register_move_cost (machine_mode mode,
2188 reg_class_t class1, reg_class_t class2)
2190 /* These need secondary reloads, so they're more expensive. */
2191 if ((class1 == CCREGS && !reg_class_subset_p (class2, DREGS))
2192 || (class2 == CCREGS && !reg_class_subset_p (class1, DREGS)))
2193 return 4;
2195 /* If optimizing for size, always prefer reg-reg over reg-memory moves. */
2196 if (optimize_size)
2197 return 2;
2199 if (GET_MODE_CLASS (mode) == MODE_INT)
2201 /* Discourage trying to use the accumulators. */
2202 if (TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A0)
2203 || TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A1)
2204 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A0)
2205 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A1))
2206 return 20;
2208 return 2;
2211 /* Worker function for TARGET_MEMORY_MOVE_COST.
2213 ??? In theory L1 memory has single-cycle latency. We should add a switch
2214 that tells the compiler whether we expect to use only L1 memory for the
2215 program; it'll make the costs more accurate. */
2217 static int
2218 bfin_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
2219 reg_class_t rclass,
2220 bool in ATTRIBUTE_UNUSED)
2222 /* Make memory accesses slightly more expensive than any register-register
2223 move. Also, penalize non-DP registers, since they need secondary
2224 reloads to load and store. */
2225 if (! reg_class_subset_p (rclass, DPREGS))
2226 return 10;
2228 return 8;
2231 /* Inform reload about cases where moving X with a mode MODE to a register in
2232 RCLASS requires an extra scratch register. Return the class needed for the
2233 scratch register. */
2235 static reg_class_t
2236 bfin_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
2237 machine_mode mode, secondary_reload_info *sri)
2239 /* If we have HImode or QImode, we can only use DREGS as secondary registers;
2240 in most other cases we can also use PREGS. */
2241 enum reg_class default_class = GET_MODE_SIZE (mode) >= 4 ? DPREGS : DREGS;
2242 enum reg_class x_class = NO_REGS;
2243 enum rtx_code code = GET_CODE (x);
2244 enum reg_class rclass = (enum reg_class) rclass_i;
2246 if (code == SUBREG)
2247 x = SUBREG_REG (x), code = GET_CODE (x);
2248 if (REG_P (x))
2250 int regno = REGNO (x);
2251 if (regno >= FIRST_PSEUDO_REGISTER)
2252 regno = reg_renumber[regno];
2254 if (regno == -1)
2255 code = MEM;
2256 else
2257 x_class = REGNO_REG_CLASS (regno);
2260 /* We can be asked to reload (plus (FP) (large_constant)) into a DREG.
2261 This happens as a side effect of register elimination, and we need
2262 a scratch register to do it. */
2263 if (fp_plus_const_operand (x, mode))
2265 rtx op2 = XEXP (x, 1);
2266 int large_constant_p = ! satisfies_constraint_Ks7 (op2);
2268 if (rclass == PREGS || rclass == PREGS_CLOBBERED)
2269 return NO_REGS;
2270 /* If destination is a DREG, we can do this without a scratch register
2271 if the constant is valid for an add instruction. */
2272 if ((rclass == DREGS || rclass == DPREGS)
2273 && ! large_constant_p)
2274 return NO_REGS;
2275 /* Reloading to anything other than a DREG? Use a PREG scratch
2276 register. */
2277 sri->icode = CODE_FOR_reload_insi;
2278 return NO_REGS;
2281 /* Data can usually be moved freely between registers of most classes.
2282 AREGS are an exception; they can only move to or from another register
2283 in AREGS or one in DREGS. They can also be assigned the constant 0. */
2284 if (x_class == AREGS || x_class == EVEN_AREGS || x_class == ODD_AREGS)
2285 return (rclass == DREGS || rclass == AREGS || rclass == EVEN_AREGS
2286 || rclass == ODD_AREGS
2287 ? NO_REGS : DREGS);
2289 if (rclass == AREGS || rclass == EVEN_AREGS || rclass == ODD_AREGS)
2291 if (code == MEM)
2293 sri->icode = in_p ? CODE_FOR_reload_inpdi : CODE_FOR_reload_outpdi;
2294 return NO_REGS;
2297 if (x != const0_rtx && x_class != DREGS)
2299 return DREGS;
2301 else
2302 return NO_REGS;
2305 /* CCREGS can only be moved from/to DREGS. */
2306 if (rclass == CCREGS && x_class != DREGS)
2307 return DREGS;
2308 if (x_class == CCREGS && rclass != DREGS)
2309 return DREGS;
2311 /* All registers other than AREGS can load arbitrary constants. The only
2312 case that remains is MEM. */
2313 if (code == MEM)
2314 if (! reg_class_subset_p (rclass, default_class))
2315 return default_class;
2317 return NO_REGS;
2320 /* Implement TARGET_CLASS_LIKELY_SPILLED_P. */
2322 static bool
2323 bfin_class_likely_spilled_p (reg_class_t rclass)
2325 switch (rclass)
2327 case PREGS_CLOBBERED:
2328 case PROLOGUE_REGS:
2329 case P0REGS:
2330 case D0REGS:
2331 case D1REGS:
2332 case D2REGS:
2333 case CCREGS:
2334 return true;
2336 default:
2337 break;
2340 return false;
2343 static struct machine_function *
2344 bfin_init_machine_status (void)
2346 return ggc_cleared_alloc<machine_function> ();
2349 /* Implement the TARGET_OPTION_OVERRIDE hook. */
2351 static void
2352 bfin_option_override (void)
2354 /* If processor type is not specified, enable all workarounds. */
2355 if (bfin_cpu_type == BFIN_CPU_UNKNOWN)
2357 int i;
2359 for (i = 0; bfin_cpus[i].name != NULL; i++)
2360 bfin_workarounds |= bfin_cpus[i].workarounds;
2362 bfin_si_revision = 0xffff;
2365 if (bfin_csync_anomaly == 1)
2366 bfin_workarounds |= WA_SPECULATIVE_SYNCS;
2367 else if (bfin_csync_anomaly == 0)
2368 bfin_workarounds &= ~WA_SPECULATIVE_SYNCS;
2370 if (bfin_specld_anomaly == 1)
2371 bfin_workarounds |= WA_SPECULATIVE_LOADS;
2372 else if (bfin_specld_anomaly == 0)
2373 bfin_workarounds &= ~WA_SPECULATIVE_LOADS;
2375 if (TARGET_OMIT_LEAF_FRAME_POINTER)
2376 flag_omit_frame_pointer = 1;
2378 #ifdef SUBTARGET_FDPIC_NOT_SUPPORTED
2379 if (TARGET_FDPIC)
2380 error ("-mfdpic is not supported, please use a bfin-linux-uclibc target");
2381 #endif
2383 /* Library identification */
2384 if (global_options_set.x_bfin_library_id && ! TARGET_ID_SHARED_LIBRARY)
2385 error ("-mshared-library-id= specified without -mid-shared-library");
2387 if (stack_limit_rtx && TARGET_FDPIC)
2389 warning (0, "-fstack-limit- options are ignored with -mfdpic; use -mstack-check-l1");
2390 stack_limit_rtx = NULL_RTX;
2393 if (stack_limit_rtx && TARGET_STACK_CHECK_L1)
2394 error ("can%'t use multiple stack checking methods together");
2396 if (TARGET_ID_SHARED_LIBRARY && TARGET_FDPIC)
2397 error ("ID shared libraries and FD-PIC mode can%'t be used together");
2399 /* Don't allow the user to specify -mid-shared-library and -msep-data
2400 together, as it makes little sense from a user's point of view... */
2401 if (TARGET_SEP_DATA && TARGET_ID_SHARED_LIBRARY)
2402 error ("cannot specify both -msep-data and -mid-shared-library");
2403 /* ... internally, however, it's nearly the same. */
2404 if (TARGET_SEP_DATA)
2405 target_flags |= MASK_ID_SHARED_LIBRARY | MASK_LEAF_ID_SHARED_LIBRARY;
2407 if (TARGET_ID_SHARED_LIBRARY && flag_pic == 0)
2408 flag_pic = 1;
2410 /* There is no single unaligned SI op for PIC code. Sometimes we
2411 need to use ".4byte" and sometimes we need to use ".picptr".
2412 See bfin_assemble_integer for details. */
2413 if (TARGET_FDPIC)
2414 targetm.asm_out.unaligned_op.si = 0;
2416 /* Silently turn off flag_pic if not doing FDPIC or ID shared libraries,
2417 since we don't support it and it'll just break. */
2418 if (flag_pic && !TARGET_FDPIC && !TARGET_ID_SHARED_LIBRARY)
2419 flag_pic = 0;
2421 if (TARGET_MULTICORE && bfin_cpu_type != BFIN_CPU_BF561)
2422 error ("-mmulticore can only be used with BF561");
2424 if (TARGET_COREA && !TARGET_MULTICORE)
2425 error ("-mcorea should be used with -mmulticore");
2427 if (TARGET_COREB && !TARGET_MULTICORE)
2428 error ("-mcoreb should be used with -mmulticore");
2430 if (TARGET_COREA && TARGET_COREB)
2431 error ("-mcorea and -mcoreb can%'t be used together");
2433 flag_schedule_insns = 0;
2435 init_machine_status = bfin_init_machine_status;
2438 /* Return the destination address of BRANCH.
2439 We need to use this instead of get_attr_length, because the
2440 cbranch_with_nops pattern conservatively sets its length to 6, and
2441 we still prefer to use shorter sequences. */
2443 static int
2444 branch_dest (rtx_insn *branch)
2446 rtx dest;
2447 int dest_uid;
2448 rtx pat = PATTERN (branch);
2449 if (GET_CODE (pat) == PARALLEL)
2450 pat = XVECEXP (pat, 0, 0);
2451 dest = SET_SRC (pat);
2452 if (GET_CODE (dest) == IF_THEN_ELSE)
2453 dest = XEXP (dest, 1);
2454 dest = XEXP (dest, 0);
2455 dest_uid = INSN_UID (dest);
2456 return INSN_ADDRESSES (dest_uid);
2459 /* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates
2460 it's a branch that's predicted taken. */
2462 static int
2463 cbranch_predicted_taken_p (rtx insn)
2465 rtx x = find_reg_note (insn, REG_BR_PROB, 0);
2467 if (x)
2469 return profile_probability::from_reg_br_prob_note (XINT (x, 0))
2470 >= profile_probability::even ();
2473 return 0;
2476 /* Templates for use by asm_conditional_branch. */
2478 static const char *ccbranch_templates[][3] = {
2479 { "if !cc jump %3;", "if cc jump 4 (bp); jump.s %3;", "if cc jump 6 (bp); jump.l %3;" },
2480 { "if cc jump %3;", "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" },
2481 { "if !cc jump %3 (bp);", "if cc jump 4; jump.s %3;", "if cc jump 6; jump.l %3;" },
2482 { "if cc jump %3 (bp);", "if !cc jump 4; jump.s %3;", "if !cc jump 6; jump.l %3;" },
2485 /* Output INSN, which is a conditional branch instruction with operands
2486 OPERANDS.
2488 We deal with the various forms of conditional branches that can be generated
2489 by bfin_reorg to prevent the hardware from doing speculative loads, by
2490 - emitting a sufficient number of nops, if N_NOPS is nonzero, or
2491 - always emitting the branch as predicted taken, if PREDICT_TAKEN is true.
2492 Either of these is only necessary if the branch is short, otherwise the
2493 template we use ends in an unconditional jump which flushes the pipeline
2494 anyway. */
2496 void
2497 asm_conditional_branch (rtx_insn *insn, rtx *operands, int n_nops, int predict_taken)
2499 int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
2500 /* Note : offset for instructions like if cc jmp; jump.[sl] offset
2501 is to be taken from start of if cc rather than jump.
2502 Range for jump.s is (-4094, 4096) instead of (-4096, 4094)
2504 int len = (offset >= -1024 && offset <= 1022 ? 0
2505 : offset >= -4094 && offset <= 4096 ? 1
2506 : 2);
2507 int bp = predict_taken && len == 0 ? 1 : cbranch_predicted_taken_p (insn);
2508 int idx = (bp << 1) | (GET_CODE (operands[0]) == EQ ? BRF : BRT);
2509 output_asm_insn (ccbranch_templates[idx][len], operands);
2510 gcc_assert (n_nops == 0 || !bp);
2511 if (len == 0)
2512 while (n_nops-- > 0)
2513 output_asm_insn ("nop;", NULL);
2516 /* Emit rtl for a comparison operation CMP in mode MODE. Operands have been
2517 stored in bfin_compare_op0 and bfin_compare_op1 already. */
2520 bfin_gen_compare (rtx cmp, machine_mode mode ATTRIBUTE_UNUSED)
2522 enum rtx_code code1, code2;
2523 rtx op0 = XEXP (cmp, 0), op1 = XEXP (cmp, 1);
2524 rtx tem = bfin_cc_rtx;
2525 enum rtx_code code = GET_CODE (cmp);
2527 /* If we have a BImode input, then we already have a compare result, and
2528 do not need to emit another comparison. */
2529 if (GET_MODE (op0) == BImode)
2531 gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
2532 tem = op0, code2 = code;
2534 else
2536 switch (code) {
2537 /* bfin has these conditions */
2538 case EQ:
2539 case LT:
2540 case LE:
2541 case LEU:
2542 case LTU:
2543 code1 = code;
2544 code2 = NE;
2545 break;
2546 default:
2547 code1 = reverse_condition (code);
2548 code2 = EQ;
2549 break;
2551 emit_insn (gen_rtx_SET (tem, gen_rtx_fmt_ee (code1, BImode, op0, op1)));
2554 return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode));
2557 /* Return nonzero iff C has exactly one bit set if it is interpreted
2558 as a 32-bit constant. */
2561 log2constp (unsigned HOST_WIDE_INT c)
2563 c &= 0xFFFFFFFF;
2564 return c != 0 && (c & (c-1)) == 0;
2567 /* Returns the number of consecutive least significant zeros in the binary
2568 representation of *V.
2569 We modify *V to contain the original value arithmetically shifted right by
2570 the number of zeroes. */
2572 static int
2573 shiftr_zero (HOST_WIDE_INT *v)
2575 unsigned HOST_WIDE_INT tmp = *v;
2576 unsigned HOST_WIDE_INT sgn;
2577 int n = 0;
2579 if (tmp == 0)
2580 return 0;
2582 sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1));
2583 while ((tmp & 0x1) == 0 && n <= 32)
2585 tmp = (tmp >> 1) | sgn;
2586 n++;
2588 *v = tmp;
2589 return n;
2592 /* After reload, split the load of an immediate constant. OPERANDS are the
2593 operands of the movsi_insn pattern which we are splitting. We return
2594 nonzero if we emitted a sequence to load the constant, zero if we emitted
2595 nothing because we want to use the splitter's default sequence. */
2598 split_load_immediate (rtx operands[])
2600 HOST_WIDE_INT val = INTVAL (operands[1]);
2601 HOST_WIDE_INT tmp;
2602 HOST_WIDE_INT shifted = val;
2603 HOST_WIDE_INT shifted_compl = ~val;
2604 int num_zero = shiftr_zero (&shifted);
2605 int num_compl_zero = shiftr_zero (&shifted_compl);
2606 unsigned int regno = REGNO (operands[0]);
2608 /* This case takes care of single-bit set/clear constants, which we could
2609 also implement with BITSET/BITCLR. */
2610 if (num_zero
2611 && shifted >= -32768 && shifted < 65536
2612 && (D_REGNO_P (regno)
2613 || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))
2615 emit_insn (gen_movsi (operands[0], gen_int_mode (shifted, SImode)));
2616 emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));
2617 return 1;
2620 tmp = val & 0xFFFF;
2621 tmp |= -(tmp & 0x8000);
2623 /* If high word has one bit set or clear, try to use a bit operation. */
2624 if (D_REGNO_P (regno))
2626 if (log2constp (val & 0xFFFF0000))
2628 emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));
2629 emit_insn (gen_iorsi3 (operands[0], operands[0],
2630 gen_int_mode (val & 0xFFFF0000, SImode)));
2631 return 1;
2633 else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)
2635 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2636 emit_insn (gen_andsi3 (operands[0], operands[0],
2637 gen_int_mode (val | 0xFFFF, SImode)));
2641 if (D_REGNO_P (regno))
2643 if (tmp >= -64 && tmp <= 63)
2645 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2646 emit_insn (gen_movstricthi_high (operands[0],
2647 gen_int_mode (val & -65536,
2648 SImode)));
2649 return 1;
2652 if ((val & 0xFFFF0000) == 0)
2654 emit_insn (gen_movsi (operands[0], const0_rtx));
2655 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2656 return 1;
2659 if ((val & 0xFFFF0000) == 0xFFFF0000)
2661 emit_insn (gen_movsi (operands[0], constm1_rtx));
2662 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2663 return 1;
2667 /* Need DREGs for the remaining case. */
2668 if (regno > REG_R7)
2669 return 0;
2671 if (optimize_size
2672 && num_compl_zero && shifted_compl >= -64 && shifted_compl <= 63)
2674 /* If optimizing for size, generate a sequence that has more instructions
2675 but is shorter. */
2676 emit_insn (gen_movsi (operands[0], gen_int_mode (shifted_compl, SImode)));
2677 emit_insn (gen_ashlsi3 (operands[0], operands[0],
2678 GEN_INT (num_compl_zero)));
2679 emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
2680 return 1;
2682 return 0;
2685 /* Return true if the legitimate memory address for a memory operand of mode
2686 MODE. Return false if not. */
2688 static bool
2689 bfin_valid_add (machine_mode mode, HOST_WIDE_INT value)
2691 unsigned HOST_WIDE_INT v = value > 0 ? value : -value;
2692 int sz = GET_MODE_SIZE (mode);
2693 int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2;
2694 /* The usual offsettable_memref machinery doesn't work so well for this
2695 port, so we deal with the problem here. */
2696 if (value > 0 && sz == 8)
2697 v += 4;
2698 return (v & ~(0x7fff << shift)) == 0;
2701 static bool
2702 bfin_valid_reg_p (unsigned int regno, int strict, machine_mode mode,
2703 enum rtx_code outer_code)
2705 if (strict)
2706 return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH);
2707 else
2708 return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH);
2711 /* Recognize an RTL expression that is a valid memory address for an
2712 instruction. The MODE argument is the machine mode for the MEM expression
2713 that wants to use this address.
2715 Blackfin addressing modes are as follows:
2717 [preg]
2718 [preg + imm16]
2720 B [ Preg + uimm15 ]
2721 W [ Preg + uimm16m2 ]
2722 [ Preg + uimm17m4 ]
2724 [preg++]
2725 [preg--]
2726 [--sp]
2729 static bool
2730 bfin_legitimate_address_p (machine_mode mode, rtx x, bool strict)
2732 switch (GET_CODE (x)) {
2733 case REG:
2734 if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM))
2735 return true;
2736 break;
2737 case PLUS:
2738 if (REG_P (XEXP (x, 0))
2739 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS)
2740 && ((GET_CODE (XEXP (x, 1)) == UNSPEC && mode == SImode)
2741 || (GET_CODE (XEXP (x, 1)) == CONST_INT
2742 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
2743 return true;
2744 break;
2745 case POST_INC:
2746 case POST_DEC:
2747 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2748 && REG_P (XEXP (x, 0))
2749 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC))
2750 return true;
2751 break;
2752 case PRE_DEC:
2753 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2754 && XEXP (x, 0) == stack_pointer_rtx
2755 && REG_P (XEXP (x, 0))
2756 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC))
2757 return true;
2758 break;
2759 default:
2760 break;
2762 return false;
2765 /* Decide whether we can force certain constants to memory. If we
2766 decide we can't, the caller should be able to cope with it in
2767 another way. */
2769 static bool
2770 bfin_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED,
2771 rtx x ATTRIBUTE_UNUSED)
2773 /* We have only one class of non-legitimate constants, and our movsi
2774 expander knows how to handle them. Dropping these constants into the
2775 data section would only shift the problem - we'd still get relocs
2776 outside the object, in the data section rather than the text section. */
2777 return true;
2780 /* Ensure that for any constant of the form symbol + offset, the offset
2781 remains within the object. Any other constants are ok.
2782 This ensures that flat binaries never have to deal with relocations
2783 crossing section boundaries. */
2785 static bool
2786 bfin_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
2788 rtx sym;
2789 HOST_WIDE_INT offset;
2791 if (GET_CODE (x) != CONST)
2792 return true;
2794 x = XEXP (x, 0);
2795 gcc_assert (GET_CODE (x) == PLUS);
2797 sym = XEXP (x, 0);
2798 x = XEXP (x, 1);
2799 if (GET_CODE (sym) != SYMBOL_REF
2800 || GET_CODE (x) != CONST_INT)
2801 return true;
2802 offset = INTVAL (x);
2804 if (SYMBOL_REF_DECL (sym) == 0)
2805 return true;
2806 if (offset < 0
2807 || offset >= int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (sym))))
2808 return false;
2810 return true;
2813 static bool
2814 bfin_rtx_costs (rtx x, machine_mode mode, int outer_code_i, int opno,
2815 int *total, bool speed)
2817 enum rtx_code code = GET_CODE (x);
2818 enum rtx_code outer_code = (enum rtx_code) outer_code_i;
2819 int cost2 = COSTS_N_INSNS (1);
2820 rtx op0, op1;
2822 switch (code)
2824 case CONST_INT:
2825 if (outer_code == SET || outer_code == PLUS)
2826 *total = satisfies_constraint_Ks7 (x) ? 0 : cost2;
2827 else if (outer_code == AND)
2828 *total = log2constp (~INTVAL (x)) ? 0 : cost2;
2829 else if (outer_code == LE || outer_code == LT || outer_code == EQ)
2830 *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
2831 else if (outer_code == LEU || outer_code == LTU)
2832 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
2833 else if (outer_code == MULT)
2834 *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
2835 else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
2836 *total = 0;
2837 else if (outer_code == ASHIFT || outer_code == ASHIFTRT
2838 || outer_code == LSHIFTRT)
2839 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
2840 else if (outer_code == IOR || outer_code == XOR)
2841 *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
2842 else
2843 *total = cost2;
2844 return true;
2846 case CONST:
2847 case LABEL_REF:
2848 case SYMBOL_REF:
2849 case CONST_DOUBLE:
2850 *total = COSTS_N_INSNS (2);
2851 return true;
2853 case PLUS:
2854 op0 = XEXP (x, 0);
2855 op1 = XEXP (x, 1);
2856 if (mode == SImode)
2858 if (GET_CODE (op0) == MULT
2859 && GET_CODE (XEXP (op0, 1)) == CONST_INT)
2861 HOST_WIDE_INT val = INTVAL (XEXP (op0, 1));
2862 if (val == 2 || val == 4)
2864 *total = cost2;
2865 *total += rtx_cost (XEXP (op0, 0), mode, outer_code,
2866 opno, speed);
2867 *total += rtx_cost (op1, mode, outer_code, opno, speed);
2868 return true;
2871 *total = cost2;
2872 if (GET_CODE (op0) != REG
2873 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2874 *total += set_src_cost (op0, mode, speed);
2875 #if 0 /* We'd like to do this for accuracy, but it biases the loop optimizer
2876 towards creating too many induction variables. */
2877 if (!reg_or_7bit_operand (op1, SImode))
2878 *total += set_src_cost (op1, mode, speed);
2879 #endif
2881 else if (mode == DImode)
2883 *total = 6 * cost2;
2884 if (GET_CODE (op1) != CONST_INT
2885 || !satisfies_constraint_Ks7 (op1))
2886 *total += rtx_cost (op1, mode, PLUS, 1, speed);
2887 if (GET_CODE (op0) != REG
2888 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2889 *total += rtx_cost (op0, mode, PLUS, 0, speed);
2891 return true;
2893 case MINUS:
2894 if (mode == DImode)
2895 *total = 6 * cost2;
2896 else
2897 *total = cost2;
2898 return true;
2900 case ASHIFT:
2901 case ASHIFTRT:
2902 case LSHIFTRT:
2903 if (mode == DImode)
2904 *total = 6 * cost2;
2905 else
2906 *total = cost2;
2908 op0 = XEXP (x, 0);
2909 op1 = XEXP (x, 1);
2910 if (GET_CODE (op0) != REG
2911 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2912 *total += rtx_cost (op0, mode, code, 0, speed);
2914 return true;
2916 case IOR:
2917 case AND:
2918 case XOR:
2919 op0 = XEXP (x, 0);
2920 op1 = XEXP (x, 1);
2922 /* Handle special cases of IOR: rotates, ALIGN insns, movstricthi_high. */
2923 if (code == IOR)
2925 if ((GET_CODE (op0) == LSHIFTRT && GET_CODE (op1) == ASHIFT)
2926 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == ZERO_EXTEND)
2927 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT)
2928 || (GET_CODE (op0) == AND && GET_CODE (op1) == CONST_INT))
2930 *total = cost2;
2931 return true;
2935 if (GET_CODE (op0) != REG
2936 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2937 *total += rtx_cost (op0, mode, code, 0, speed);
2939 if (mode == DImode)
2941 *total = 2 * cost2;
2942 return true;
2944 *total = cost2;
2945 if (mode != SImode)
2946 return true;
2948 if (code == AND)
2950 if (! rhs_andsi3_operand (XEXP (x, 1), SImode))
2951 *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
2953 else
2955 if (! regorlog2_operand (XEXP (x, 1), SImode))
2956 *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
2959 return true;
2961 case ZERO_EXTRACT:
2962 case SIGN_EXTRACT:
2963 if (outer_code == SET
2964 && XEXP (x, 1) == const1_rtx
2965 && GET_CODE (XEXP (x, 2)) == CONST_INT)
2967 *total = 2 * cost2;
2968 return true;
2970 /* fall through */
2972 case SIGN_EXTEND:
2973 case ZERO_EXTEND:
2974 *total = cost2;
2975 return true;
2977 case MULT:
2979 op0 = XEXP (x, 0);
2980 op1 = XEXP (x, 1);
2981 if (GET_CODE (op0) == GET_CODE (op1)
2982 && (GET_CODE (op0) == ZERO_EXTEND
2983 || GET_CODE (op0) == SIGN_EXTEND))
2985 *total = COSTS_N_INSNS (1);
2986 op0 = XEXP (op0, 0);
2987 op1 = XEXP (op1, 0);
2989 else if (!speed)
2990 *total = COSTS_N_INSNS (1);
2991 else
2992 *total = COSTS_N_INSNS (3);
2994 if (GET_CODE (op0) != REG
2995 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2996 *total += rtx_cost (op0, mode, MULT, 0, speed);
2997 if (GET_CODE (op1) != REG
2998 && (GET_CODE (op1) != SUBREG || GET_CODE (SUBREG_REG (op1)) != REG))
2999 *total += rtx_cost (op1, mode, MULT, 1, speed);
3001 return true;
3003 case UDIV:
3004 case UMOD:
3005 *total = COSTS_N_INSNS (32);
3006 return true;
3008 case VEC_CONCAT:
3009 case VEC_SELECT:
3010 if (outer_code == SET)
3011 *total = cost2;
3012 return true;
3014 default:
3015 return false;
3019 /* Used for communication between {push,pop}_multiple_operation (which
3020 we use not only as a predicate) and the corresponding output functions. */
3021 static int first_preg_to_save, first_dreg_to_save;
3022 static int n_regs_to_save;
3025 analyze_push_multiple_operation (rtx op)
3027 int lastdreg = 8, lastpreg = 6;
3028 int i, group;
3030 first_preg_to_save = lastpreg;
3031 first_dreg_to_save = lastdreg;
3032 for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
3034 rtx t = XVECEXP (op, 0, i);
3035 rtx src, dest;
3036 int regno;
3038 if (GET_CODE (t) != SET)
3039 return 0;
3041 src = SET_SRC (t);
3042 dest = SET_DEST (t);
3043 if (GET_CODE (dest) != MEM || ! REG_P (src))
3044 return 0;
3045 dest = XEXP (dest, 0);
3046 if (GET_CODE (dest) != PLUS
3047 || ! REG_P (XEXP (dest, 0))
3048 || REGNO (XEXP (dest, 0)) != REG_SP
3049 || GET_CODE (XEXP (dest, 1)) != CONST_INT
3050 || INTVAL (XEXP (dest, 1)) != -i * 4)
3051 return 0;
3053 regno = REGNO (src);
3054 if (group == 0)
3056 if (D_REGNO_P (regno))
3058 group = 1;
3059 first_dreg_to_save = lastdreg = regno - REG_R0;
3061 else if (regno >= REG_P0 && regno <= REG_P7)
3063 group = 2;
3064 first_preg_to_save = lastpreg = regno - REG_P0;
3066 else
3067 return 0;
3069 continue;
3072 if (group == 1)
3074 if (regno >= REG_P0 && regno <= REG_P7)
3076 group = 2;
3077 first_preg_to_save = lastpreg = regno - REG_P0;
3079 else if (regno != REG_R0 + lastdreg + 1)
3080 return 0;
3081 else
3082 lastdreg++;
3084 else if (group == 2)
3086 if (regno != REG_P0 + lastpreg + 1)
3087 return 0;
3088 lastpreg++;
3091 n_regs_to_save = 8 - first_dreg_to_save + 6 - first_preg_to_save;
3092 return 1;
3096 analyze_pop_multiple_operation (rtx op)
3098 int lastdreg = 8, lastpreg = 6;
3099 int i, group;
3101 for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
3103 rtx t = XVECEXP (op, 0, i);
3104 rtx src, dest;
3105 int regno;
3107 if (GET_CODE (t) != SET)
3108 return 0;
3110 src = SET_SRC (t);
3111 dest = SET_DEST (t);
3112 if (GET_CODE (src) != MEM || ! REG_P (dest))
3113 return 0;
3114 src = XEXP (src, 0);
3116 if (i == 1)
3118 if (! REG_P (src) || REGNO (src) != REG_SP)
3119 return 0;
3121 else if (GET_CODE (src) != PLUS
3122 || ! REG_P (XEXP (src, 0))
3123 || REGNO (XEXP (src, 0)) != REG_SP
3124 || GET_CODE (XEXP (src, 1)) != CONST_INT
3125 || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
3126 return 0;
3128 regno = REGNO (dest);
3129 if (group == 0)
3131 if (regno == REG_R7)
3133 group = 1;
3134 lastdreg = 7;
3136 else if (regno != REG_P0 + lastpreg - 1)
3137 return 0;
3138 else
3139 lastpreg--;
3141 else if (group == 1)
3143 if (regno != REG_R0 + lastdreg - 1)
3144 return 0;
3145 else
3146 lastdreg--;
3149 first_dreg_to_save = lastdreg;
3150 first_preg_to_save = lastpreg;
3151 n_regs_to_save = 8 - first_dreg_to_save + 6 - first_preg_to_save;
3152 return 1;
3155 /* Emit assembly code for one multi-register push described by INSN, with
3156 operands in OPERANDS. */
3158 void
3159 output_push_multiple (rtx insn, rtx *operands)
3161 char buf[80];
3162 int ok;
3164 /* Validate the insn again, and compute first_[dp]reg_to_save. */
3165 ok = analyze_push_multiple_operation (PATTERN (insn));
3166 gcc_assert (ok);
3168 if (first_dreg_to_save == 8)
3169 sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
3170 else if (first_preg_to_save == 6)
3171 sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
3172 else
3173 sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
3174 first_dreg_to_save, first_preg_to_save);
3176 output_asm_insn (buf, operands);
3179 /* Emit assembly code for one multi-register pop described by INSN, with
3180 operands in OPERANDS. */
3182 void
3183 output_pop_multiple (rtx insn, rtx *operands)
3185 char buf[80];
3186 int ok;
3188 /* Validate the insn again, and compute first_[dp]reg_to_save. */
3189 ok = analyze_pop_multiple_operation (PATTERN (insn));
3190 gcc_assert (ok);
3192 if (first_dreg_to_save == 8)
3193 sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
3194 else if (first_preg_to_save == 6)
3195 sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
3196 else
3197 sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
3198 first_dreg_to_save, first_preg_to_save);
3200 output_asm_insn (buf, operands);
3203 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE. */
3205 static void
3206 single_move_for_movmem (rtx dst, rtx src, machine_mode mode, HOST_WIDE_INT offset)
3208 rtx scratch = gen_reg_rtx (mode);
3209 rtx srcmem, dstmem;
3211 srcmem = adjust_address_nv (src, mode, offset);
3212 dstmem = adjust_address_nv (dst, mode, offset);
3213 emit_move_insn (scratch, srcmem);
3214 emit_move_insn (dstmem, scratch);
3217 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
3218 alignment ALIGN_EXP. Return true if successful, false if we should fall
3219 back on a different method. */
3221 bool
3222 bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
3224 rtx srcreg, destreg, countreg;
3225 HOST_WIDE_INT align = 0;
3226 unsigned HOST_WIDE_INT count = 0;
3228 if (GET_CODE (align_exp) == CONST_INT)
3229 align = INTVAL (align_exp);
3230 if (GET_CODE (count_exp) == CONST_INT)
3232 count = INTVAL (count_exp);
3233 #if 0
3234 if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
3235 return false;
3236 #endif
3239 /* If optimizing for size, only do single copies inline. */
3240 if (optimize_size)
3242 if (count == 2 && align < 2)
3243 return false;
3244 if (count == 4 && align < 4)
3245 return false;
3246 if (count != 1 && count != 2 && count != 4)
3247 return false;
3249 if (align < 2 && count != 1)
3250 return false;
3252 destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
3253 if (destreg != XEXP (dst, 0))
3254 dst = replace_equiv_address_nv (dst, destreg);
3255 srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
3256 if (srcreg != XEXP (src, 0))
3257 src = replace_equiv_address_nv (src, srcreg);
3259 if (count != 0 && align >= 2)
3261 unsigned HOST_WIDE_INT offset = 0;
3263 if (align >= 4)
3265 if ((count & ~3) == 4)
3267 single_move_for_movmem (dst, src, SImode, offset);
3268 offset = 4;
3270 else if (count & ~3)
3272 HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
3273 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3275 emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
3276 cfun->machine->has_loopreg_clobber = true;
3278 if (count & 2)
3280 single_move_for_movmem (dst, src, HImode, offset);
3281 offset += 2;
3284 else
3286 if ((count & ~1) == 2)
3288 single_move_for_movmem (dst, src, HImode, offset);
3289 offset = 2;
3291 else if (count & ~1)
3293 HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
3294 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3296 emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
3297 cfun->machine->has_loopreg_clobber = true;
3300 if (count & 1)
3302 single_move_for_movmem (dst, src, QImode, offset);
3304 return true;
3306 return false;
3309 /* Compute the alignment for a local variable.
3310 TYPE is the data type, and ALIGN is the alignment that
3311 the object would ordinarily have. The value of this macro is used
3312 instead of that alignment to align the object. */
3314 unsigned
3315 bfin_local_alignment (tree type, unsigned align)
3317 /* Increasing alignment for (relatively) big types allows the builtin
3318 memcpy can use 32 bit loads/stores. */
3319 if (TYPE_SIZE (type)
3320 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
3321 && wi::gtu_p (wi::to_wide (TYPE_SIZE (type)), 8)
3322 && align < 32)
3323 return 32;
3324 return align;
3327 /* Implement TARGET_SCHED_ISSUE_RATE. */
3329 static int
3330 bfin_issue_rate (void)
3332 return 3;
3335 static int
3336 bfin_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn, int cost,
3337 unsigned int)
3339 enum attr_type dep_insn_type;
3340 int dep_insn_code_number;
3342 /* Anti and output dependencies have zero cost. */
3343 if (dep_type != 0)
3344 return 0;
3346 dep_insn_code_number = recog_memoized (dep_insn);
3348 /* If we can't recognize the insns, we can't really do anything. */
3349 if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
3350 return cost;
3352 dep_insn_type = get_attr_type (dep_insn);
3354 if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)
3356 rtx pat = PATTERN (dep_insn);
3357 rtx dest, src;
3359 if (GET_CODE (pat) == PARALLEL)
3360 pat = XVECEXP (pat, 0, 0);
3361 dest = SET_DEST (pat);
3362 src = SET_SRC (pat);
3363 if (! ADDRESS_REGNO_P (REGNO (dest))
3364 || ! (MEM_P (src) || D_REGNO_P (REGNO (src))))
3365 return cost;
3366 return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);
3369 return cost;
3372 /* This function acts like NEXT_INSN, but is aware of three-insn bundles and
3373 skips all subsequent parallel instructions if INSN is the start of such
3374 a group. */
3375 static rtx_insn *
3376 find_next_insn_start (rtx_insn *insn)
3378 if (GET_MODE (insn) == SImode)
3380 while (GET_MODE (insn) != QImode)
3381 insn = NEXT_INSN (insn);
3383 return NEXT_INSN (insn);
3386 /* This function acts like PREV_INSN, but is aware of three-insn bundles and
3387 skips all subsequent parallel instructions if INSN is the start of such
3388 a group. */
3389 static rtx_insn *
3390 find_prev_insn_start (rtx_insn *insn)
3392 insn = PREV_INSN (insn);
3393 gcc_assert (GET_MODE (insn) != SImode);
3394 if (GET_MODE (insn) == QImode)
3396 while (GET_MODE (PREV_INSN (insn)) == SImode)
3397 insn = PREV_INSN (insn);
3399 return insn;
3402 /* Implement TARGET_CAN_USE_DOLOOP_P. */
3404 static bool
3405 bfin_can_use_doloop_p (const widest_int &, const widest_int &iterations_max,
3406 unsigned int, bool)
3408 /* Due to limitations in the hardware (an initial loop count of 0
3409 does not loop 2^32 times) we must avoid to generate a hardware
3410 loops when we cannot rule out this case. */
3411 return (wi::ltu_p (iterations_max, 0xFFFFFFFF));
3414 /* Increment the counter for the number of loop instructions in the
3415 current function. */
3417 void
3418 bfin_hardware_loop (void)
3420 cfun->machine->has_hardware_loops++;
3423 /* Maximum loop nesting depth. */
3424 #define MAX_LOOP_DEPTH 2
3426 /* Maximum size of a loop. */
3427 #define MAX_LOOP_LENGTH 2042
3429 /* Maximum distance of the LSETUP instruction from the loop start. */
3430 #define MAX_LSETUP_DISTANCE 30
3432 /* Estimate the length of INSN conservatively. */
3434 static int
3435 length_for_loop (rtx_insn *insn)
3437 int length = 0;
3438 if (JUMP_P (insn) && any_condjump_p (insn) && !optimize_size)
3440 if (ENABLE_WA_SPECULATIVE_SYNCS)
3441 length = 8;
3442 else if (ENABLE_WA_SPECULATIVE_LOADS)
3443 length = 6;
3445 else if (LABEL_P (insn))
3447 if (ENABLE_WA_SPECULATIVE_SYNCS)
3448 length = 4;
3451 if (NONDEBUG_INSN_P (insn))
3452 length += get_attr_length (insn);
3454 return length;
3457 /* Optimize LOOP. */
3459 static bool
3460 hwloop_optimize (hwloop_info loop)
3462 basic_block bb;
3463 rtx_insn *insn, *last_insn;
3464 rtx loop_init, start_label, end_label;
3465 rtx iter_reg, scratchreg, scratch_init;
3466 rtx_insn *scratch_init_insn;
3467 rtx lc_reg, lt_reg, lb_reg;
3468 rtx seq_end;
3469 rtx_insn *seq;
3470 int length;
3471 bool clobber0, clobber1;
3473 if (loop->depth > MAX_LOOP_DEPTH)
3475 if (dump_file)
3476 fprintf (dump_file, ";; loop %d too deep\n", loop->loop_no);
3477 return false;
3480 /* Get the loop iteration register. */
3481 iter_reg = loop->iter_reg;
3483 gcc_assert (REG_P (iter_reg));
3485 scratchreg = NULL_RTX;
3486 scratch_init = iter_reg;
3487 scratch_init_insn = NULL;
3488 if (!PREG_P (iter_reg) && loop->incoming_src)
3490 basic_block bb_in = loop->incoming_src;
3491 int i;
3492 for (i = REG_P0; i <= REG_P5; i++)
3493 if ((df_regs_ever_live_p (i)
3494 || (funkind (TREE_TYPE (current_function_decl)) == SUBROUTINE
3495 && call_used_regs[i]))
3496 && !REGNO_REG_SET_P (df_get_live_out (bb_in), i))
3498 scratchreg = gen_rtx_REG (SImode, i);
3499 break;
3501 for (insn = BB_END (bb_in); insn != BB_HEAD (bb_in);
3502 insn = PREV_INSN (insn))
3504 rtx set;
3505 if (NOTE_P (insn) || BARRIER_P (insn))
3506 continue;
3507 set = single_set (insn);
3508 if (set && rtx_equal_p (SET_DEST (set), iter_reg))
3510 if (CONSTANT_P (SET_SRC (set)))
3512 scratch_init = SET_SRC (set);
3513 scratch_init_insn = insn;
3515 break;
3517 else if (reg_mentioned_p (iter_reg, PATTERN (insn)))
3518 break;
3522 if (loop->incoming_src)
3524 /* Make sure the predecessor is before the loop start label, as required by
3525 the LSETUP instruction. */
3526 length = 0;
3527 insn = BB_END (loop->incoming_src);
3528 /* If we have to insert the LSETUP before a jump, count that jump in the
3529 length. */
3530 if (vec_safe_length (loop->incoming) > 1
3531 || !(loop->incoming->last ()->flags & EDGE_FALLTHRU))
3533 gcc_assert (JUMP_P (insn));
3534 insn = PREV_INSN (insn);
3537 for (; insn && insn != loop->start_label; insn = NEXT_INSN (insn))
3538 length += length_for_loop (insn);
3540 if (!insn)
3542 if (dump_file)
3543 fprintf (dump_file, ";; loop %d lsetup not before loop_start\n",
3544 loop->loop_no);
3545 return false;
3548 /* Account for the pop of a scratch register where necessary. */
3549 if (!PREG_P (iter_reg) && scratchreg == NULL_RTX
3550 && ENABLE_WA_LOAD_LCREGS)
3551 length += 2;
3553 if (length > MAX_LSETUP_DISTANCE)
3555 if (dump_file)
3556 fprintf (dump_file, ";; loop %d lsetup too far away\n", loop->loop_no);
3557 return false;
3561 /* Check if start_label appears before loop_end and calculate the
3562 offset between them. We calculate the length of instructions
3563 conservatively. */
3564 length = 0;
3565 for (insn = loop->start_label;
3566 insn && insn != loop->loop_end;
3567 insn = NEXT_INSN (insn))
3568 length += length_for_loop (insn);
3570 if (!insn)
3572 if (dump_file)
3573 fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
3574 loop->loop_no);
3575 return false;
3578 loop->length = length;
3579 if (loop->length > MAX_LOOP_LENGTH)
3581 if (dump_file)
3582 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
3583 return false;
3586 /* Scan all the blocks to make sure they don't use iter_reg. */
3587 if (loop->iter_reg_used || loop->iter_reg_used_outside)
3589 if (dump_file)
3590 fprintf (dump_file, ";; loop %d uses iterator\n", loop->loop_no);
3591 return false;
3594 clobber0 = (TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC0)
3595 || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LB0)
3596 || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LT0));
3597 clobber1 = (TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC1)
3598 || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LB1)
3599 || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LT1));
3600 if (clobber0 && clobber1)
3602 if (dump_file)
3603 fprintf (dump_file, ";; loop %d no loop reg available\n",
3604 loop->loop_no);
3605 return false;
3608 /* There should be an instruction before the loop_end instruction
3609 in the same basic block. And the instruction must not be
3610 - JUMP
3611 - CONDITIONAL BRANCH
3612 - CALL
3613 - CSYNC
3614 - SSYNC
3615 - Returns (RTS, RTN, etc.) */
3617 bb = loop->tail;
3618 last_insn = find_prev_insn_start (loop->loop_end);
3620 while (1)
3622 for (; last_insn != BB_HEAD (bb);
3623 last_insn = find_prev_insn_start (last_insn))
3624 if (NONDEBUG_INSN_P (last_insn))
3625 break;
3627 if (last_insn != BB_HEAD (bb))
3628 break;
3630 if (single_pred_p (bb)
3631 && single_pred_edge (bb)->flags & EDGE_FALLTHRU
3632 && single_pred (bb) != ENTRY_BLOCK_PTR_FOR_FN (cfun))
3634 bb = single_pred (bb);
3635 last_insn = BB_END (bb);
3636 continue;
3638 else
3640 last_insn = NULL;
3641 break;
3645 if (!last_insn)
3647 if (dump_file)
3648 fprintf (dump_file, ";; loop %d has no last instruction\n",
3649 loop->loop_no);
3650 return false;
3653 if (JUMP_P (last_insn) && !any_condjump_p (last_insn))
3655 if (dump_file)
3656 fprintf (dump_file, ";; loop %d has bad last instruction\n",
3657 loop->loop_no);
3658 return false;
3660 /* In all other cases, try to replace a bad last insn with a nop. */
3661 else if (JUMP_P (last_insn)
3662 || CALL_P (last_insn)
3663 || get_attr_type (last_insn) == TYPE_SYNC
3664 || get_attr_type (last_insn) == TYPE_CALL
3665 || get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI
3666 || recog_memoized (last_insn) == CODE_FOR_return_internal
3667 || GET_CODE (PATTERN (last_insn)) == ASM_INPUT
3668 || asm_noperands (PATTERN (last_insn)) >= 0)
3670 if (loop->length + 2 > MAX_LOOP_LENGTH)
3672 if (dump_file)
3673 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
3674 return false;
3676 if (dump_file)
3677 fprintf (dump_file, ";; loop %d has bad last insn; replace with nop\n",
3678 loop->loop_no);
3680 last_insn = emit_insn_after (gen_forced_nop (), last_insn);
3683 loop->last_insn = last_insn;
3685 /* The loop is good for replacement. */
3686 start_label = loop->start_label;
3687 end_label = gen_label_rtx ();
3688 iter_reg = loop->iter_reg;
3690 if (loop->depth == 1 && !clobber1)
3692 lc_reg = gen_rtx_REG (SImode, REG_LC1);
3693 lb_reg = gen_rtx_REG (SImode, REG_LB1);
3694 lt_reg = gen_rtx_REG (SImode, REG_LT1);
3695 SET_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC1);
3697 else
3699 lc_reg = gen_rtx_REG (SImode, REG_LC0);
3700 lb_reg = gen_rtx_REG (SImode, REG_LB0);
3701 lt_reg = gen_rtx_REG (SImode, REG_LT0);
3702 SET_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC0);
3705 loop->end_label = end_label;
3707 /* Create a sequence containing the loop setup. */
3708 start_sequence ();
3710 /* LSETUP only accepts P registers. If we have one, we can use it,
3711 otherwise there are several ways of working around the problem.
3712 If we're not affected by anomaly 312, we can load the LC register
3713 from any iteration register, and use LSETUP without initialization.
3714 If we've found a P scratch register that's not live here, we can
3715 instead copy the iter_reg into that and use an initializing LSETUP.
3716 If all else fails, push and pop P0 and use it as a scratch. */
3717 if (P_REGNO_P (REGNO (iter_reg)))
3719 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
3720 lb_reg, end_label,
3721 lc_reg, iter_reg);
3722 seq_end = emit_insn (loop_init);
3724 else if (!ENABLE_WA_LOAD_LCREGS && DPREG_P (iter_reg))
3726 emit_insn (gen_movsi (lc_reg, iter_reg));
3727 loop_init = gen_lsetup_without_autoinit (lt_reg, start_label,
3728 lb_reg, end_label,
3729 lc_reg);
3730 seq_end = emit_insn (loop_init);
3732 else if (scratchreg != NULL_RTX)
3734 emit_insn (gen_movsi (scratchreg, scratch_init));
3735 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
3736 lb_reg, end_label,
3737 lc_reg, scratchreg);
3738 seq_end = emit_insn (loop_init);
3739 if (scratch_init_insn != NULL_RTX)
3740 delete_insn (scratch_init_insn);
3742 else
3744 rtx p0reg = gen_rtx_REG (SImode, REG_P0);
3745 rtx push = gen_frame_mem (SImode,
3746 gen_rtx_PRE_DEC (SImode, stack_pointer_rtx));
3747 rtx pop = gen_frame_mem (SImode,
3748 gen_rtx_POST_INC (SImode, stack_pointer_rtx));
3749 emit_insn (gen_movsi (push, p0reg));
3750 emit_insn (gen_movsi (p0reg, scratch_init));
3751 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
3752 lb_reg, end_label,
3753 lc_reg, p0reg);
3754 emit_insn (loop_init);
3755 seq_end = emit_insn (gen_movsi (p0reg, pop));
3756 if (scratch_init_insn != NULL_RTX)
3757 delete_insn (scratch_init_insn);
3760 if (dump_file)
3762 fprintf (dump_file, ";; replacing loop %d initializer with\n",
3763 loop->loop_no);
3764 print_rtl_single (dump_file, loop_init);
3765 fprintf (dump_file, ";; replacing loop %d terminator with\n",
3766 loop->loop_no);
3767 print_rtl_single (dump_file, loop->loop_end);
3770 /* If the loop isn't entered at the top, also create a jump to the entry
3771 point. */
3772 if (!loop->incoming_src && loop->head != loop->incoming_dest)
3774 rtx label = BB_HEAD (loop->incoming_dest);
3775 /* If we're jumping to the final basic block in the loop, and there's
3776 only one cheap instruction before the end (typically an increment of
3777 an induction variable), we can just emit a copy here instead of a
3778 jump. */
3779 if (loop->incoming_dest == loop->tail
3780 && next_real_insn (label) == last_insn
3781 && asm_noperands (last_insn) < 0
3782 && GET_CODE (PATTERN (last_insn)) == SET)
3784 seq_end = emit_insn (copy_rtx (PATTERN (last_insn)));
3786 else
3788 rtx_insn *ret = emit_jump_insn (gen_jump (label));
3789 JUMP_LABEL (ret) = label;
3790 LABEL_NUSES (label)++;
3791 seq_end = emit_barrier ();
3795 seq = get_insns ();
3796 end_sequence ();
3798 if (loop->incoming_src)
3800 rtx_insn *prev = BB_END (loop->incoming_src);
3801 if (vec_safe_length (loop->incoming) > 1
3802 || !(loop->incoming->last ()->flags & EDGE_FALLTHRU))
3804 gcc_assert (JUMP_P (prev));
3805 prev = PREV_INSN (prev);
3806 emit_insn_after (seq, prev);
3808 else
3810 emit_insn_after (seq, prev);
3811 BB_END (loop->incoming_src) = prev;
3812 basic_block new_bb = create_basic_block (seq, seq_end,
3813 loop->head->prev_bb);
3814 edge e = loop->incoming->last ();
3815 gcc_assert (e->flags & EDGE_FALLTHRU);
3816 redirect_edge_succ (e, new_bb);
3817 make_edge (new_bb, loop->head, 0);
3820 else
3822 basic_block new_bb;
3823 edge e;
3824 edge_iterator ei;
3826 if (flag_checking && loop->head != loop->incoming_dest)
3828 /* We aren't entering the loop at the top. Since we've established
3829 that the loop is entered only at one point, this means there
3830 can't be fallthru edges into the head. Any such fallthru edges
3831 would become invalid when we insert the new block, so verify
3832 that this does not in fact happen. */
3833 FOR_EACH_EDGE (e, ei, loop->head->preds)
3834 gcc_assert (!(e->flags & EDGE_FALLTHRU));
3837 emit_insn_before (seq, BB_HEAD (loop->head));
3838 seq = emit_label_before (gen_label_rtx (), seq);
3840 new_bb = create_basic_block (seq, seq_end, loop->head->prev_bb);
3841 FOR_EACH_EDGE (e, ei, loop->incoming)
3843 if (!(e->flags & EDGE_FALLTHRU)
3844 || e->dest != loop->head)
3845 redirect_edge_and_branch_force (e, new_bb);
3846 else
3847 redirect_edge_succ (e, new_bb);
3849 e = make_edge (new_bb, loop->head, 0);
3852 delete_insn (loop->loop_end);
3853 /* Insert the loop end label before the last instruction of the loop. */
3854 emit_label_before (as_a <rtx_code_label *> (loop->end_label),
3855 loop->last_insn);
3857 return true;
3860 /* A callback for the hw-doloop pass. Called when a loop we have discovered
3861 turns out not to be optimizable; we have to split the doloop_end pattern
3862 into a subtract and a test. */
3863 static void
3864 hwloop_fail (hwloop_info loop)
3866 rtx insn = loop->loop_end;
3868 if (DPREG_P (loop->iter_reg))
3870 /* If loop->iter_reg is a DREG or PREG, we can split it here
3871 without scratch register. */
3872 rtx insn, test;
3874 emit_insn_before (gen_addsi3 (loop->iter_reg,
3875 loop->iter_reg,
3876 constm1_rtx),
3877 loop->loop_end);
3879 test = gen_rtx_NE (VOIDmode, loop->iter_reg, const0_rtx);
3880 insn = emit_jump_insn_before (gen_cbranchsi4 (test,
3881 loop->iter_reg, const0_rtx,
3882 loop->start_label),
3883 loop->loop_end);
3885 JUMP_LABEL (insn) = loop->start_label;
3886 LABEL_NUSES (loop->start_label)++;
3887 delete_insn (loop->loop_end);
3889 else
3891 splitting_loops = 1;
3892 try_split (PATTERN (insn), safe_as_a <rtx_insn *> (insn), 1);
3893 splitting_loops = 0;
3897 /* A callback for the hw-doloop pass. This function examines INSN; if
3898 it is a loop_end pattern we recognize, return the reg rtx for the
3899 loop counter. Otherwise, return NULL_RTX. */
3901 static rtx
3902 hwloop_pattern_reg (rtx_insn *insn)
3904 rtx reg;
3906 if (!JUMP_P (insn) || recog_memoized (insn) != CODE_FOR_loop_end)
3907 return NULL_RTX;
3909 reg = SET_DEST (XVECEXP (PATTERN (insn), 0, 1));
3910 if (!REG_P (reg))
3911 return NULL_RTX;
3912 return reg;
3915 static struct hw_doloop_hooks bfin_doloop_hooks =
3917 hwloop_pattern_reg,
3918 hwloop_optimize,
3919 hwloop_fail
3922 /* Run from machine_dependent_reorg, this pass looks for doloop_end insns
3923 and tries to rewrite the RTL of these loops so that proper Blackfin
3924 hardware loops are generated. */
3926 static void
3927 bfin_reorg_loops (void)
3929 reorg_loops (true, &bfin_doloop_hooks);
3932 /* Possibly generate a SEQUENCE out of three insns found in SLOT.
3933 Returns true if we modified the insn chain, false otherwise. */
3934 static bool
3935 gen_one_bundle (rtx_insn *slot[3])
3937 gcc_assert (slot[1] != NULL_RTX);
3939 /* Don't add extra NOPs if optimizing for size. */
3940 if (optimize_size
3941 && (slot[0] == NULL_RTX || slot[2] == NULL_RTX))
3942 return false;
3944 /* Verify that we really can do the multi-issue. */
3945 if (slot[0])
3947 rtx_insn *t = NEXT_INSN (slot[0]);
3948 while (t != slot[1])
3950 if (! NOTE_P (t) || NOTE_KIND (t) != NOTE_INSN_DELETED)
3951 return false;
3952 t = NEXT_INSN (t);
3955 if (slot[2])
3957 rtx_insn *t = NEXT_INSN (slot[1]);
3958 while (t != slot[2])
3960 if (! NOTE_P (t) || NOTE_KIND (t) != NOTE_INSN_DELETED)
3961 return false;
3962 t = NEXT_INSN (t);
3966 if (slot[0] == NULL_RTX)
3968 slot[0] = emit_insn_before (gen_mnop (), slot[1]);
3969 df_insn_rescan (slot[0]);
3971 if (slot[2] == NULL_RTX)
3973 slot[2] = emit_insn_after (gen_forced_nop (), slot[1]);
3974 df_insn_rescan (slot[2]);
3977 /* Avoid line number information being printed inside one bundle. */
3978 if (INSN_LOCATION (slot[1])
3979 && INSN_LOCATION (slot[1]) != INSN_LOCATION (slot[0]))
3980 INSN_LOCATION (slot[1]) = INSN_LOCATION (slot[0]);
3981 if (INSN_LOCATION (slot[2])
3982 && INSN_LOCATION (slot[2]) != INSN_LOCATION (slot[0]))
3983 INSN_LOCATION (slot[2]) = INSN_LOCATION (slot[0]);
3985 /* Terminate them with "|| " instead of ";" in the output. */
3986 PUT_MODE (slot[0], SImode);
3987 PUT_MODE (slot[1], SImode);
3988 /* Terminate the bundle, for the benefit of reorder_var_tracking_notes. */
3989 PUT_MODE (slot[2], QImode);
3990 return true;
3993 /* Go through all insns, and use the information generated during scheduling
3994 to generate SEQUENCEs to represent bundles of instructions issued
3995 simultaneously. */
3997 static void
3998 bfin_gen_bundles (void)
4000 basic_block bb;
4001 FOR_EACH_BB_FN (bb, cfun)
4003 rtx_insn *insn, *next;
4004 rtx_insn *slot[3];
4005 int n_filled = 0;
4007 slot[0] = slot[1] = slot[2] = NULL;
4008 for (insn = BB_HEAD (bb);; insn = next)
4010 int at_end;
4011 rtx_insn *delete_this = NULL;
4013 if (NONDEBUG_INSN_P (insn))
4015 enum attr_type type = get_attr_type (insn);
4017 if (type == TYPE_STALL)
4019 gcc_assert (n_filled == 0);
4020 delete_this = insn;
4022 else
4024 if (type == TYPE_DSP32 || type == TYPE_DSP32SHIFTIMM)
4025 slot[0] = insn;
4026 else if (slot[1] == NULL_RTX)
4027 slot[1] = insn;
4028 else
4029 slot[2] = insn;
4030 n_filled++;
4034 next = NEXT_INSN (insn);
4035 while (next && insn != BB_END (bb)
4036 && !(INSN_P (next)
4037 && GET_CODE (PATTERN (next)) != USE
4038 && GET_CODE (PATTERN (next)) != CLOBBER))
4040 insn = next;
4041 next = NEXT_INSN (insn);
4044 /* BB_END can change due to emitting extra NOPs, so check here. */
4045 at_end = insn == BB_END (bb);
4046 if (delete_this == NULL_RTX && (at_end || GET_MODE (next) == TImode))
4048 if ((n_filled < 2
4049 || !gen_one_bundle (slot))
4050 && slot[0] != NULL_RTX)
4052 rtx pat = PATTERN (slot[0]);
4053 if (GET_CODE (pat) == SET
4054 && GET_CODE (SET_SRC (pat)) == UNSPEC
4055 && XINT (SET_SRC (pat), 1) == UNSPEC_32BIT)
4057 SET_SRC (pat) = XVECEXP (SET_SRC (pat), 0, 0);
4058 INSN_CODE (slot[0]) = -1;
4059 df_insn_rescan (slot[0]);
4062 n_filled = 0;
4063 slot[0] = slot[1] = slot[2] = NULL;
4065 if (delete_this != NULL_RTX)
4066 delete_insn (delete_this);
4067 if (at_end)
4068 break;
4073 /* Ensure that no var tracking notes are emitted in the middle of a
4074 three-instruction bundle. */
4076 static void
4077 reorder_var_tracking_notes (void)
4079 basic_block bb;
4080 FOR_EACH_BB_FN (bb, cfun)
4082 rtx_insn *insn, *next;
4083 rtx_insn *queue = NULL;
4084 bool in_bundle = false;
4086 for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = next)
4088 next = NEXT_INSN (insn);
4090 if (INSN_P (insn))
4092 /* Emit queued up notes at the last instruction of a bundle. */
4093 if (GET_MODE (insn) == QImode)
4095 while (queue)
4097 rtx_insn *next_queue = PREV_INSN (queue);
4098 SET_PREV_INSN (NEXT_INSN (insn)) = queue;
4099 SET_NEXT_INSN (queue) = NEXT_INSN (insn);
4100 SET_NEXT_INSN (insn) = queue;
4101 SET_PREV_INSN (queue) = insn;
4102 queue = next_queue;
4104 in_bundle = false;
4106 else if (GET_MODE (insn) == SImode)
4107 in_bundle = true;
4109 else if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION)
4111 if (in_bundle)
4113 rtx_insn *prev = PREV_INSN (insn);
4114 SET_PREV_INSN (next) = prev;
4115 SET_NEXT_INSN (prev) = next;
4117 SET_PREV_INSN (insn) = queue;
4118 queue = insn;
4125 /* On some silicon revisions, functions shorter than a certain number of cycles
4126 can cause unpredictable behavior. Work around this by adding NOPs as
4127 needed. */
4128 static void
4129 workaround_rts_anomaly (void)
4131 rtx_insn *insn, *first_insn = NULL;
4132 int cycles = 4;
4134 if (! ENABLE_WA_RETS)
4135 return;
4137 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4139 rtx pat;
4141 if (BARRIER_P (insn))
4142 return;
4144 if (NOTE_P (insn) || LABEL_P (insn))
4145 continue;
4147 if (JUMP_TABLE_DATA_P (insn))
4148 continue;
4150 if (first_insn == NULL_RTX)
4151 first_insn = insn;
4152 pat = PATTERN (insn);
4153 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4154 || GET_CODE (pat) == ASM_INPUT
4155 || asm_noperands (pat) >= 0)
4156 continue;
4158 if (CALL_P (insn))
4159 return;
4161 if (JUMP_P (insn))
4163 if (recog_memoized (insn) == CODE_FOR_return_internal)
4164 break;
4166 /* Nothing to worry about for direct jumps. */
4167 if (!any_condjump_p (insn))
4168 return;
4169 if (cycles <= 1)
4170 return;
4171 cycles--;
4173 else if (INSN_P (insn))
4175 rtx pat = PATTERN (insn);
4176 int this_cycles = 1;
4178 if (GET_CODE (pat) == PARALLEL)
4180 if (analyze_push_multiple_operation (pat)
4181 || analyze_pop_multiple_operation (pat))
4182 this_cycles = n_regs_to_save;
4184 else
4186 int icode = recog_memoized (insn);
4188 if (icode == CODE_FOR_link)
4189 this_cycles = 4;
4190 else if (icode == CODE_FOR_unlink)
4191 this_cycles = 3;
4192 else if (icode == CODE_FOR_mulsi3)
4193 this_cycles = 5;
4195 if (this_cycles >= cycles)
4196 return;
4198 cycles -= this_cycles;
4201 while (cycles > 0)
4203 emit_insn_before (gen_nop (), first_insn);
4204 cycles--;
4208 /* Return an insn type for INSN that can be used by the caller for anomaly
4209 workarounds. This differs from plain get_attr_type in that it handles
4210 SEQUENCEs. */
4212 static enum attr_type
4213 type_for_anomaly (rtx_insn *insn)
4215 rtx pat = PATTERN (insn);
4216 if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (pat))
4218 enum attr_type t;
4219 t = get_attr_type (seq->insn (1));
4220 if (t == TYPE_MCLD)
4221 return t;
4222 t = get_attr_type (seq->insn (2));
4223 if (t == TYPE_MCLD)
4224 return t;
4225 return TYPE_MCST;
4227 else
4228 return get_attr_type (insn);
4231 /* Return true iff the address found in MEM is based on the register
4232 NP_REG and optionally has a positive offset. */
4233 static bool
4234 harmless_null_pointer_p (rtx mem, int np_reg)
4236 mem = XEXP (mem, 0);
4237 if (GET_CODE (mem) == POST_INC || GET_CODE (mem) == POST_DEC)
4238 mem = XEXP (mem, 0);
4239 if (REG_P (mem) && (int) REGNO (mem) == np_reg)
4240 return true;
4241 if (GET_CODE (mem) == PLUS
4242 && REG_P (XEXP (mem, 0)) && (int) REGNO (XEXP (mem, 0)) == np_reg)
4244 mem = XEXP (mem, 1);
4245 if (GET_CODE (mem) == CONST_INT && INTVAL (mem) > 0)
4246 return true;
4248 return false;
4251 /* Return nonzero if INSN contains any loads that may trap. */
4253 static bool
4254 trapping_loads_p (rtx_insn *insn, int np_reg, bool after_np_branch)
4256 rtx mem = SET_SRC (single_set (insn));
4258 if (!after_np_branch)
4259 np_reg = -1;
4260 return ((np_reg == -1 || !harmless_null_pointer_p (mem, np_reg))
4261 && may_trap_p (mem));
4264 /* Return INSN if it is of TYPE_MCLD. Alternatively, if INSN is the start of
4265 a three-insn bundle, see if one of them is a load and return that if so.
4266 Return NULL if the insn does not contain loads. */
4267 static rtx_insn *
4268 find_load (rtx_insn *insn)
4270 if (!NONDEBUG_INSN_P (insn))
4271 return NULL;
4272 if (get_attr_type (insn) == TYPE_MCLD)
4273 return insn;
4274 if (GET_MODE (insn) != SImode)
4275 return NULL;
4276 do {
4277 insn = NEXT_INSN (insn);
4278 if ((GET_MODE (insn) == SImode || GET_MODE (insn) == QImode)
4279 && get_attr_type (insn) == TYPE_MCLD)
4280 return insn;
4281 } while (GET_MODE (insn) != QImode);
4282 return NULL;
4285 /* Determine whether PAT is an indirect call pattern. */
4286 static bool
4287 indirect_call_p (rtx pat)
4289 if (GET_CODE (pat) == PARALLEL)
4290 pat = XVECEXP (pat, 0, 0);
4291 if (GET_CODE (pat) == SET)
4292 pat = SET_SRC (pat);
4293 gcc_assert (GET_CODE (pat) == CALL);
4294 pat = XEXP (pat, 0);
4295 gcc_assert (GET_CODE (pat) == MEM);
4296 pat = XEXP (pat, 0);
4298 return REG_P (pat);
4301 /* During workaround_speculation, track whether we're in the shadow of a
4302 conditional branch that tests a P register for NULL. If so, we can omit
4303 emitting NOPs if we see a load from that P register, since a speculative
4304 access at address 0 isn't a problem, and the load is executed in all other
4305 cases anyway.
4306 Global for communication with note_np_check_stores through note_stores.
4308 int np_check_regno = -1;
4309 bool np_after_branch = false;
4311 /* Subroutine of workaround_speculation, called through note_stores. */
4312 static void
4313 note_np_check_stores (rtx x, const_rtx pat ATTRIBUTE_UNUSED,
4314 void *data ATTRIBUTE_UNUSED)
4316 if (REG_P (x) && (REGNO (x) == REG_CC || (int) REGNO (x) == np_check_regno))
4317 np_check_regno = -1;
4320 static void
4321 workaround_speculation (void)
4323 rtx_insn *insn, *next;
4324 rtx_insn *last_condjump = NULL;
4325 int cycles_since_jump = INT_MAX;
4326 int delay_added = 0;
4328 if (! ENABLE_WA_SPECULATIVE_LOADS && ! ENABLE_WA_SPECULATIVE_SYNCS
4329 && ! ENABLE_WA_INDIRECT_CALLS)
4330 return;
4332 /* First pass: find predicted-false branches; if something after them
4333 needs nops, insert them or change the branch to predict true. */
4334 for (insn = get_insns (); insn; insn = next)
4336 rtx pat;
4337 int delay_needed = 0;
4339 next = find_next_insn_start (insn);
4341 if (NOTE_P (insn) || BARRIER_P (insn))
4342 continue;
4343 if (JUMP_TABLE_DATA_P (insn))
4344 continue;
4346 if (LABEL_P (insn))
4348 np_check_regno = -1;
4349 continue;
4352 pat = PATTERN (insn);
4353 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
4354 continue;
4356 if (GET_CODE (pat) == ASM_INPUT || asm_noperands (pat) >= 0)
4358 np_check_regno = -1;
4359 continue;
4362 if (JUMP_P (insn))
4364 /* Is this a condjump based on a null pointer comparison we saw
4365 earlier? */
4366 if (np_check_regno != -1
4367 && recog_memoized (insn) == CODE_FOR_cbranchbi4)
4369 rtx op = XEXP (SET_SRC (PATTERN (insn)), 0);
4370 gcc_assert (GET_CODE (op) == EQ || GET_CODE (op) == NE);
4371 if (GET_CODE (op) == NE)
4372 np_after_branch = true;
4374 if (any_condjump_p (insn)
4375 && ! cbranch_predicted_taken_p (insn))
4377 last_condjump = insn;
4378 delay_added = 0;
4379 cycles_since_jump = 0;
4381 else
4382 cycles_since_jump = INT_MAX;
4384 else if (CALL_P (insn))
4386 np_check_regno = -1;
4387 if (cycles_since_jump < INT_MAX)
4388 cycles_since_jump++;
4389 if (indirect_call_p (pat) && ENABLE_WA_INDIRECT_CALLS)
4391 delay_needed = 3;
4394 else if (NONDEBUG_INSN_P (insn))
4396 rtx_insn *load_insn = find_load (insn);
4397 enum attr_type type = type_for_anomaly (insn);
4399 if (cycles_since_jump < INT_MAX)
4400 cycles_since_jump++;
4402 /* Detect a comparison of a P register with zero. If we later
4403 see a condjump based on it, we have found a null pointer
4404 check. */
4405 if (recog_memoized (insn) == CODE_FOR_compare_eq)
4407 rtx src = SET_SRC (PATTERN (insn));
4408 if (REG_P (XEXP (src, 0))
4409 && P_REGNO_P (REGNO (XEXP (src, 0)))
4410 && XEXP (src, 1) == const0_rtx)
4412 np_check_regno = REGNO (XEXP (src, 0));
4413 np_after_branch = false;
4415 else
4416 np_check_regno = -1;
4419 if (load_insn && ENABLE_WA_SPECULATIVE_LOADS)
4421 if (trapping_loads_p (load_insn, np_check_regno,
4422 np_after_branch))
4423 delay_needed = 4;
4425 else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS)
4426 delay_needed = 3;
4428 /* See if we need to forget about a null pointer comparison
4429 we found earlier. */
4430 if (recog_memoized (insn) != CODE_FOR_compare_eq)
4432 note_stores (PATTERN (insn), note_np_check_stores, NULL);
4433 if (np_check_regno != -1)
4435 if (find_regno_note (insn, REG_INC, np_check_regno))
4436 np_check_regno = -1;
4442 if (delay_needed > cycles_since_jump
4443 && (delay_needed - cycles_since_jump) > delay_added)
4445 rtx pat1;
4446 int num_clobbers;
4447 rtx *op = recog_data.operand;
4449 delay_needed -= cycles_since_jump;
4451 extract_insn (last_condjump);
4452 if (optimize_size)
4454 pat1 = gen_cbranch_predicted_taken (op[0], op[1], op[2],
4455 op[3]);
4456 cycles_since_jump = INT_MAX;
4458 else
4460 /* Do not adjust cycles_since_jump in this case, so that
4461 we'll increase the number of NOPs for a subsequent insn
4462 if necessary. */
4463 pat1 = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
4464 GEN_INT (delay_needed));
4465 delay_added = delay_needed;
4467 PATTERN (last_condjump) = pat1;
4468 INSN_CODE (last_condjump) = recog (pat1, insn, &num_clobbers);
4470 if (CALL_P (insn))
4472 cycles_since_jump = INT_MAX;
4473 delay_added = 0;
4477 /* Second pass: for predicted-true branches, see if anything at the
4478 branch destination needs extra nops. */
4479 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4481 int cycles_since_jump;
4482 if (JUMP_P (insn)
4483 && any_condjump_p (insn)
4484 && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken
4485 || cbranch_predicted_taken_p (insn)))
4487 rtx_insn *target = JUMP_LABEL_AS_INSN (insn);
4488 rtx_insn *label = target;
4489 rtx_insn *next_tgt;
4491 cycles_since_jump = 0;
4492 for (; target && cycles_since_jump < 3; target = next_tgt)
4494 rtx pat;
4496 next_tgt = find_next_insn_start (target);
4498 if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
4499 continue;
4501 if (JUMP_TABLE_DATA_P (target))
4502 continue;
4504 pat = PATTERN (target);
4505 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4506 || GET_CODE (pat) == ASM_INPUT
4507 || asm_noperands (pat) >= 0)
4508 continue;
4510 if (NONDEBUG_INSN_P (target))
4512 rtx_insn *load_insn = find_load (target);
4513 enum attr_type type = type_for_anomaly (target);
4514 int delay_needed = 0;
4515 if (cycles_since_jump < INT_MAX)
4516 cycles_since_jump++;
4518 if (load_insn && ENABLE_WA_SPECULATIVE_LOADS)
4520 if (trapping_loads_p (load_insn, -1, false))
4521 delay_needed = 2;
4523 else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS)
4524 delay_needed = 2;
4526 if (delay_needed > cycles_since_jump)
4528 rtx_insn *prev = prev_real_insn (label);
4529 delay_needed -= cycles_since_jump;
4530 if (dump_file)
4531 fprintf (dump_file, "Adding %d nops after %d\n",
4532 delay_needed, INSN_UID (label));
4533 if (JUMP_P (prev)
4534 && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops)
4536 rtx x;
4537 HOST_WIDE_INT v;
4539 if (dump_file)
4540 fprintf (dump_file,
4541 "Reducing nops on insn %d.\n",
4542 INSN_UID (prev));
4543 x = PATTERN (prev);
4544 x = XVECEXP (x, 0, 1);
4545 v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed;
4546 XVECEXP (x, 0, 0) = GEN_INT (v);
4548 while (delay_needed-- > 0)
4549 emit_insn_after (gen_nop (), label);
4550 break;
4558 /* Called just before the final scheduling pass. If we need to insert NOPs
4559 later on to work around speculative loads, insert special placeholder
4560 insns that cause loads to be delayed for as many cycles as necessary
4561 (and possible). This reduces the number of NOPs we need to add.
4562 The dummy insns we generate are later removed by bfin_gen_bundles. */
4563 static void
4564 add_sched_insns_for_speculation (void)
4566 rtx_insn *insn;
4568 if (! ENABLE_WA_SPECULATIVE_LOADS && ! ENABLE_WA_SPECULATIVE_SYNCS
4569 && ! ENABLE_WA_INDIRECT_CALLS)
4570 return;
4572 /* First pass: find predicted-false branches; if something after them
4573 needs nops, insert them or change the branch to predict true. */
4574 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4576 rtx pat;
4578 if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
4579 continue;
4580 if (JUMP_TABLE_DATA_P (insn))
4581 continue;
4583 pat = PATTERN (insn);
4584 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4585 || GET_CODE (pat) == ASM_INPUT
4586 || asm_noperands (pat) >= 0)
4587 continue;
4589 if (JUMP_P (insn))
4591 if (any_condjump_p (insn)
4592 && !cbranch_predicted_taken_p (insn))
4594 rtx_insn *n = next_real_insn (insn);
4595 emit_insn_before (gen_stall (GEN_INT (3)), n);
4600 /* Second pass: for predicted-true branches, see if anything at the
4601 branch destination needs extra nops. */
4602 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4604 if (JUMP_P (insn)
4605 && any_condjump_p (insn)
4606 && (cbranch_predicted_taken_p (insn)))
4608 rtx target = JUMP_LABEL (insn);
4609 rtx_insn *next = next_real_insn (target);
4611 if (GET_CODE (PATTERN (next)) == UNSPEC_VOLATILE
4612 && get_attr_type (next) == TYPE_STALL)
4613 continue;
4614 emit_insn_before (gen_stall (GEN_INT (1)), next);
4619 /* We use the machine specific reorg pass for emitting CSYNC instructions
4620 after conditional branches as needed.
4622 The Blackfin is unusual in that a code sequence like
4623 if cc jump label
4624 r0 = (p0)
4625 may speculatively perform the load even if the condition isn't true. This
4626 happens for a branch that is predicted not taken, because the pipeline
4627 isn't flushed or stalled, so the early stages of the following instructions,
4628 which perform the memory reference, are allowed to execute before the
4629 jump condition is evaluated.
4630 Therefore, we must insert additional instructions in all places where this
4631 could lead to incorrect behavior. The manual recommends CSYNC, while
4632 VDSP seems to use NOPs (even though its corresponding compiler option is
4633 named CSYNC).
4635 When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
4636 When optimizing for size, we turn the branch into a predicted taken one.
4637 This may be slower due to mispredicts, but saves code size. */
4639 static void
4640 bfin_reorg (void)
4642 /* We are freeing block_for_insn in the toplev to keep compatibility
4643 with old MDEP_REORGS that are not CFG based. Recompute it now. */
4644 compute_bb_for_insn ();
4646 if (flag_schedule_insns_after_reload)
4648 splitting_for_sched = 1;
4649 split_all_insns ();
4650 splitting_for_sched = 0;
4652 add_sched_insns_for_speculation ();
4654 timevar_push (TV_SCHED2);
4655 if (flag_selective_scheduling2
4656 && !maybe_skip_selective_scheduling ())
4657 run_selective_scheduling ();
4658 else
4659 schedule_insns ();
4660 timevar_pop (TV_SCHED2);
4662 /* Examine the schedule and insert nops as necessary for 64-bit parallel
4663 instructions. */
4664 bfin_gen_bundles ();
4667 df_analyze ();
4669 /* Doloop optimization */
4670 if (cfun->machine->has_hardware_loops)
4671 bfin_reorg_loops ();
4673 workaround_speculation ();
4675 if (flag_var_tracking)
4677 timevar_push (TV_VAR_TRACKING);
4678 variable_tracking_main ();
4679 reorder_var_tracking_notes ();
4680 timevar_pop (TV_VAR_TRACKING);
4683 df_finish_pass (false);
4685 workaround_rts_anomaly ();
4688 /* Handle interrupt_handler, exception_handler and nmi_handler function
4689 attributes; arguments as in struct attribute_spec.handler. */
4691 static tree
4692 handle_int_attribute (tree *node, tree name,
4693 tree args ATTRIBUTE_UNUSED,
4694 int flags ATTRIBUTE_UNUSED,
4695 bool *no_add_attrs)
4697 tree x = *node;
4698 if (TREE_CODE (x) == FUNCTION_DECL)
4699 x = TREE_TYPE (x);
4701 if (TREE_CODE (x) != FUNCTION_TYPE)
4703 warning (OPT_Wattributes, "%qE attribute only applies to functions",
4704 name);
4705 *no_add_attrs = true;
4707 else if (funkind (x) != SUBROUTINE)
4708 error ("multiple function type attributes specified");
4710 return NULL_TREE;
4713 /* Return 0 if the attributes for two types are incompatible, 1 if they
4714 are compatible, and 2 if they are nearly compatible (which causes a
4715 warning to be generated). */
4717 static int
4718 bfin_comp_type_attributes (const_tree type1, const_tree type2)
4720 e_funkind kind1, kind2;
4722 if (TREE_CODE (type1) != FUNCTION_TYPE)
4723 return 1;
4725 kind1 = funkind (type1);
4726 kind2 = funkind (type2);
4728 if (kind1 != kind2)
4729 return 0;
4731 /* Check for mismatched modifiers */
4732 if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
4733 != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
4734 return 0;
4736 if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
4737 != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
4738 return 0;
4740 if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
4741 != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
4742 return 0;
4744 if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1))
4745 != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2)))
4746 return 0;
4748 return 1;
4751 /* Handle a "longcall" or "shortcall" attribute; arguments as in
4752 struct attribute_spec.handler. */
4754 static tree
4755 bfin_handle_longcall_attribute (tree *node, tree name,
4756 tree args ATTRIBUTE_UNUSED,
4757 int flags ATTRIBUTE_UNUSED,
4758 bool *no_add_attrs)
4760 if (TREE_CODE (*node) != FUNCTION_TYPE
4761 && TREE_CODE (*node) != FIELD_DECL
4762 && TREE_CODE (*node) != TYPE_DECL)
4764 warning (OPT_Wattributes, "%qE attribute only applies to functions",
4765 name);
4766 *no_add_attrs = true;
4769 if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0
4770 && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node)))
4771 || (strcmp (IDENTIFIER_POINTER (name), "shortcall") == 0
4772 && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node))))
4774 warning (OPT_Wattributes,
4775 "can%'t apply both longcall and shortcall attributes to the same function");
4776 *no_add_attrs = true;
4779 return NULL_TREE;
4782 /* Handle a "l1_text" attribute; arguments as in
4783 struct attribute_spec.handler. */
4785 static tree
4786 bfin_handle_l1_text_attribute (tree *node, tree name, tree ARG_UNUSED (args),
4787 int ARG_UNUSED (flags), bool *no_add_attrs)
4789 tree decl = *node;
4791 if (TREE_CODE (decl) != FUNCTION_DECL)
4793 error ("%qE attribute only applies to functions",
4794 name);
4795 *no_add_attrs = true;
4798 /* The decl may have already been given a section attribute
4799 from a previous declaration. Ensure they match. */
4800 else if (DECL_SECTION_NAME (decl) != NULL
4801 && strcmp (DECL_SECTION_NAME (decl),
4802 ".l1.text") != 0)
4804 error ("section of %q+D conflicts with previous declaration",
4805 decl);
4806 *no_add_attrs = true;
4808 else
4809 set_decl_section_name (decl, ".l1.text");
4811 return NULL_TREE;
4814 /* Handle a "l1_data", "l1_data_A" or "l1_data_B" attribute;
4815 arguments as in struct attribute_spec.handler. */
4817 static tree
4818 bfin_handle_l1_data_attribute (tree *node, tree name, tree ARG_UNUSED (args),
4819 int ARG_UNUSED (flags), bool *no_add_attrs)
4821 tree decl = *node;
4823 if (TREE_CODE (decl) != VAR_DECL)
4825 error ("%qE attribute only applies to variables",
4826 name);
4827 *no_add_attrs = true;
4829 else if (current_function_decl != NULL_TREE
4830 && !TREE_STATIC (decl))
4832 error ("%qE attribute cannot be specified for local variables",
4833 name);
4834 *no_add_attrs = true;
4836 else
4838 const char *section_name;
4840 if (strcmp (IDENTIFIER_POINTER (name), "l1_data") == 0)
4841 section_name = ".l1.data";
4842 else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_A") == 0)
4843 section_name = ".l1.data.A";
4844 else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_B") == 0)
4845 section_name = ".l1.data.B";
4846 else
4847 gcc_unreachable ();
4849 /* The decl may have already been given a section attribute
4850 from a previous declaration. Ensure they match. */
4851 if (DECL_SECTION_NAME (decl) != NULL
4852 && strcmp (DECL_SECTION_NAME (decl),
4853 section_name) != 0)
4855 error ("section of %q+D conflicts with previous declaration",
4856 decl);
4857 *no_add_attrs = true;
4859 else
4860 set_decl_section_name (decl, section_name);
4863 return NULL_TREE;
4866 /* Handle a "l2" attribute; arguments as in struct attribute_spec.handler. */
4868 static tree
4869 bfin_handle_l2_attribute (tree *node, tree ARG_UNUSED (name),
4870 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
4871 bool *no_add_attrs)
4873 tree decl = *node;
4875 if (TREE_CODE (decl) == FUNCTION_DECL)
4877 if (DECL_SECTION_NAME (decl) != NULL
4878 && strcmp (DECL_SECTION_NAME (decl),
4879 ".l2.text") != 0)
4881 error ("section of %q+D conflicts with previous declaration",
4882 decl);
4883 *no_add_attrs = true;
4885 else
4886 set_decl_section_name (decl, ".l2.text");
4888 else if (TREE_CODE (decl) == VAR_DECL)
4890 if (DECL_SECTION_NAME (decl) != NULL
4891 && strcmp (DECL_SECTION_NAME (decl),
4892 ".l2.data") != 0)
4894 error ("section of %q+D conflicts with previous declaration",
4895 decl);
4896 *no_add_attrs = true;
4898 else
4899 set_decl_section_name (decl, ".l2.data");
4902 return NULL_TREE;
4905 /* Table of valid machine attributes. */
4906 static const struct attribute_spec bfin_attribute_table[] =
4908 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
4909 affects_type_identity, exclusions } */
4910 { "interrupt_handler", 0, 0, false, true, true, handle_int_attribute,
4911 false, NULL },
4912 { "exception_handler", 0, 0, false, true, true, handle_int_attribute,
4913 false, NULL },
4914 { "nmi_handler", 0, 0, false, true, true, handle_int_attribute, false,
4915 NULL },
4916 { "nesting", 0, 0, false, true, true, NULL, false, NULL },
4917 { "kspisusp", 0, 0, false, true, true, NULL, false, NULL },
4918 { "saveall", 0, 0, false, true, true, NULL, false, NULL },
4919 { "longcall", 0, 0, false, true, true, bfin_handle_longcall_attribute,
4920 false, NULL },
4921 { "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute,
4922 false, NULL },
4923 { "l1_text", 0, 0, true, false, false, bfin_handle_l1_text_attribute,
4924 false, NULL },
4925 { "l1_data", 0, 0, true, false, false, bfin_handle_l1_data_attribute,
4926 false, NULL },
4927 { "l1_data_A", 0, 0, true, false, false, bfin_handle_l1_data_attribute,
4928 false, NULL },
4929 { "l1_data_B", 0, 0, true, false, false, bfin_handle_l1_data_attribute,
4930 false, NULL },
4931 { "l2", 0, 0, true, false, false, bfin_handle_l2_attribute, false, NULL },
4932 { NULL, 0, 0, false, false, false, NULL, false, NULL }
4935 /* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to
4936 tell the assembler to generate pointers to function descriptors in
4937 some cases. */
4939 static bool
4940 bfin_assemble_integer (rtx value, unsigned int size, int aligned_p)
4942 if (TARGET_FDPIC && size == UNITS_PER_WORD)
4944 if (GET_CODE (value) == SYMBOL_REF
4945 && SYMBOL_REF_FUNCTION_P (value))
4947 fputs ("\t.picptr\tfuncdesc(", asm_out_file);
4948 output_addr_const (asm_out_file, value);
4949 fputs (")\n", asm_out_file);
4950 return true;
4952 if (!aligned_p)
4954 /* We've set the unaligned SI op to NULL, so we always have to
4955 handle the unaligned case here. */
4956 assemble_integer_with_op ("\t.4byte\t", value);
4957 return true;
4960 return default_assemble_integer (value, size, aligned_p);
4963 /* Output the assembler code for a thunk function. THUNK_DECL is the
4964 declaration for the thunk function itself, FUNCTION is the decl for
4965 the target function. DELTA is an immediate constant offset to be
4966 added to THIS. If VCALL_OFFSET is nonzero, the word at
4967 *(*this + vcall_offset) should be added to THIS. */
4969 static void
4970 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
4971 tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
4972 HOST_WIDE_INT vcall_offset, tree function)
4974 rtx xops[3];
4975 /* The this parameter is passed as the first argument. */
4976 rtx this_rtx = gen_rtx_REG (Pmode, REG_R0);
4978 /* Adjust the this parameter by a fixed constant. */
4979 if (delta)
4981 xops[1] = this_rtx;
4982 if (delta >= -64 && delta <= 63)
4984 xops[0] = GEN_INT (delta);
4985 output_asm_insn ("%1 += %0;", xops);
4987 else if (delta >= -128 && delta < -64)
4989 xops[0] = GEN_INT (delta + 64);
4990 output_asm_insn ("%1 += -64; %1 += %0;", xops);
4992 else if (delta > 63 && delta <= 126)
4994 xops[0] = GEN_INT (delta - 63);
4995 output_asm_insn ("%1 += 63; %1 += %0;", xops);
4997 else
4999 xops[0] = GEN_INT (delta);
5000 output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
5004 /* Adjust the this parameter by a value stored in the vtable. */
5005 if (vcall_offset)
5007 rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
5008 rtx tmp = gen_rtx_REG (Pmode, REG_R3);
5010 xops[1] = tmp;
5011 xops[2] = p2tmp;
5012 output_asm_insn ("%2 = r0; %2 = [%2];", xops);
5014 /* Adjust the this parameter. */
5015 xops[0] = gen_rtx_MEM (Pmode, plus_constant (Pmode, p2tmp,
5016 vcall_offset));
5017 if (!memory_operand (xops[0], Pmode))
5019 rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
5020 xops[0] = GEN_INT (vcall_offset);
5021 xops[1] = tmp2;
5022 output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
5023 xops[0] = gen_rtx_MEM (Pmode, p2tmp);
5025 xops[2] = this_rtx;
5026 output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
5029 xops[0] = XEXP (DECL_RTL (function), 0);
5030 if (1 || !flag_pic || (*targetm.binds_local_p) (function))
5031 output_asm_insn ("jump.l\t%P0", xops);
5034 /* Codes for all the Blackfin builtins. */
5035 enum bfin_builtins
5037 BFIN_BUILTIN_CSYNC,
5038 BFIN_BUILTIN_SSYNC,
5039 BFIN_BUILTIN_ONES,
5040 BFIN_BUILTIN_COMPOSE_2X16,
5041 BFIN_BUILTIN_EXTRACTLO,
5042 BFIN_BUILTIN_EXTRACTHI,
5044 BFIN_BUILTIN_SSADD_2X16,
5045 BFIN_BUILTIN_SSSUB_2X16,
5046 BFIN_BUILTIN_SSADDSUB_2X16,
5047 BFIN_BUILTIN_SSSUBADD_2X16,
5048 BFIN_BUILTIN_MULT_2X16,
5049 BFIN_BUILTIN_MULTR_2X16,
5050 BFIN_BUILTIN_NEG_2X16,
5051 BFIN_BUILTIN_ABS_2X16,
5052 BFIN_BUILTIN_MIN_2X16,
5053 BFIN_BUILTIN_MAX_2X16,
5055 BFIN_BUILTIN_SSADD_1X16,
5056 BFIN_BUILTIN_SSSUB_1X16,
5057 BFIN_BUILTIN_MULT_1X16,
5058 BFIN_BUILTIN_MULTR_1X16,
5059 BFIN_BUILTIN_NORM_1X16,
5060 BFIN_BUILTIN_NEG_1X16,
5061 BFIN_BUILTIN_ABS_1X16,
5062 BFIN_BUILTIN_MIN_1X16,
5063 BFIN_BUILTIN_MAX_1X16,
5065 BFIN_BUILTIN_SUM_2X16,
5066 BFIN_BUILTIN_DIFFHL_2X16,
5067 BFIN_BUILTIN_DIFFLH_2X16,
5069 BFIN_BUILTIN_SSADD_1X32,
5070 BFIN_BUILTIN_SSSUB_1X32,
5071 BFIN_BUILTIN_NORM_1X32,
5072 BFIN_BUILTIN_ROUND_1X32,
5073 BFIN_BUILTIN_NEG_1X32,
5074 BFIN_BUILTIN_ABS_1X32,
5075 BFIN_BUILTIN_MIN_1X32,
5076 BFIN_BUILTIN_MAX_1X32,
5077 BFIN_BUILTIN_MULT_1X32,
5078 BFIN_BUILTIN_MULT_1X32X32,
5079 BFIN_BUILTIN_MULT_1X32X32NS,
5081 BFIN_BUILTIN_MULHISILL,
5082 BFIN_BUILTIN_MULHISILH,
5083 BFIN_BUILTIN_MULHISIHL,
5084 BFIN_BUILTIN_MULHISIHH,
5086 BFIN_BUILTIN_LSHIFT_1X16,
5087 BFIN_BUILTIN_LSHIFT_2X16,
5088 BFIN_BUILTIN_SSASHIFT_1X16,
5089 BFIN_BUILTIN_SSASHIFT_2X16,
5090 BFIN_BUILTIN_SSASHIFT_1X32,
5092 BFIN_BUILTIN_CPLX_MUL_16,
5093 BFIN_BUILTIN_CPLX_MAC_16,
5094 BFIN_BUILTIN_CPLX_MSU_16,
5096 BFIN_BUILTIN_CPLX_MUL_16_S40,
5097 BFIN_BUILTIN_CPLX_MAC_16_S40,
5098 BFIN_BUILTIN_CPLX_MSU_16_S40,
5100 BFIN_BUILTIN_CPLX_SQU,
5102 BFIN_BUILTIN_LOADBYTES,
5104 BFIN_BUILTIN_MAX
5107 #define def_builtin(NAME, TYPE, CODE) \
5108 do { \
5109 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
5110 NULL, NULL_TREE); \
5111 } while (0)
5113 /* Set up all builtin functions for this target. */
5114 static void
5115 bfin_init_builtins (void)
5117 tree V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
5118 tree void_ftype_void
5119 = build_function_type_list (void_type_node, NULL_TREE);
5120 tree short_ftype_short
5121 = build_function_type_list (short_integer_type_node, short_integer_type_node,
5122 NULL_TREE);
5123 tree short_ftype_int_int
5124 = build_function_type_list (short_integer_type_node, integer_type_node,
5125 integer_type_node, NULL_TREE);
5126 tree int_ftype_int_int
5127 = build_function_type_list (integer_type_node, integer_type_node,
5128 integer_type_node, NULL_TREE);
5129 tree int_ftype_int
5130 = build_function_type_list (integer_type_node, integer_type_node,
5131 NULL_TREE);
5132 tree short_ftype_int
5133 = build_function_type_list (short_integer_type_node, integer_type_node,
5134 NULL_TREE);
5135 tree int_ftype_v2hi_v2hi
5136 = build_function_type_list (integer_type_node, V2HI_type_node,
5137 V2HI_type_node, NULL_TREE);
5138 tree v2hi_ftype_v2hi_v2hi
5139 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5140 V2HI_type_node, NULL_TREE);
5141 tree v2hi_ftype_v2hi_v2hi_v2hi
5142 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5143 V2HI_type_node, V2HI_type_node, NULL_TREE);
5144 tree v2hi_ftype_int_int
5145 = build_function_type_list (V2HI_type_node, integer_type_node,
5146 integer_type_node, NULL_TREE);
5147 tree v2hi_ftype_v2hi_int
5148 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5149 integer_type_node, NULL_TREE);
5150 tree int_ftype_short_short
5151 = build_function_type_list (integer_type_node, short_integer_type_node,
5152 short_integer_type_node, NULL_TREE);
5153 tree v2hi_ftype_v2hi
5154 = build_function_type_list (V2HI_type_node, V2HI_type_node, NULL_TREE);
5155 tree short_ftype_v2hi
5156 = build_function_type_list (short_integer_type_node, V2HI_type_node,
5157 NULL_TREE);
5158 tree int_ftype_pint
5159 = build_function_type_list (integer_type_node,
5160 build_pointer_type (integer_type_node),
5161 NULL_TREE);
5163 /* Add the remaining MMX insns with somewhat more complicated types. */
5164 def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC);
5165 def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC);
5167 def_builtin ("__builtin_bfin_ones", short_ftype_int, BFIN_BUILTIN_ONES);
5169 def_builtin ("__builtin_bfin_compose_2x16", v2hi_ftype_int_int,
5170 BFIN_BUILTIN_COMPOSE_2X16);
5171 def_builtin ("__builtin_bfin_extract_hi", short_ftype_v2hi,
5172 BFIN_BUILTIN_EXTRACTHI);
5173 def_builtin ("__builtin_bfin_extract_lo", short_ftype_v2hi,
5174 BFIN_BUILTIN_EXTRACTLO);
5176 def_builtin ("__builtin_bfin_min_fr2x16", v2hi_ftype_v2hi_v2hi,
5177 BFIN_BUILTIN_MIN_2X16);
5178 def_builtin ("__builtin_bfin_max_fr2x16", v2hi_ftype_v2hi_v2hi,
5179 BFIN_BUILTIN_MAX_2X16);
5181 def_builtin ("__builtin_bfin_add_fr2x16", v2hi_ftype_v2hi_v2hi,
5182 BFIN_BUILTIN_SSADD_2X16);
5183 def_builtin ("__builtin_bfin_sub_fr2x16", v2hi_ftype_v2hi_v2hi,
5184 BFIN_BUILTIN_SSSUB_2X16);
5185 def_builtin ("__builtin_bfin_dspaddsubsat", v2hi_ftype_v2hi_v2hi,
5186 BFIN_BUILTIN_SSADDSUB_2X16);
5187 def_builtin ("__builtin_bfin_dspsubaddsat", v2hi_ftype_v2hi_v2hi,
5188 BFIN_BUILTIN_SSSUBADD_2X16);
5189 def_builtin ("__builtin_bfin_mult_fr2x16", v2hi_ftype_v2hi_v2hi,
5190 BFIN_BUILTIN_MULT_2X16);
5191 def_builtin ("__builtin_bfin_multr_fr2x16", v2hi_ftype_v2hi_v2hi,
5192 BFIN_BUILTIN_MULTR_2X16);
5193 def_builtin ("__builtin_bfin_negate_fr2x16", v2hi_ftype_v2hi,
5194 BFIN_BUILTIN_NEG_2X16);
5195 def_builtin ("__builtin_bfin_abs_fr2x16", v2hi_ftype_v2hi,
5196 BFIN_BUILTIN_ABS_2X16);
5198 def_builtin ("__builtin_bfin_min_fr1x16", short_ftype_int_int,
5199 BFIN_BUILTIN_MIN_1X16);
5200 def_builtin ("__builtin_bfin_max_fr1x16", short_ftype_int_int,
5201 BFIN_BUILTIN_MAX_1X16);
5203 def_builtin ("__builtin_bfin_add_fr1x16", short_ftype_int_int,
5204 BFIN_BUILTIN_SSADD_1X16);
5205 def_builtin ("__builtin_bfin_sub_fr1x16", short_ftype_int_int,
5206 BFIN_BUILTIN_SSSUB_1X16);
5207 def_builtin ("__builtin_bfin_mult_fr1x16", short_ftype_int_int,
5208 BFIN_BUILTIN_MULT_1X16);
5209 def_builtin ("__builtin_bfin_multr_fr1x16", short_ftype_int_int,
5210 BFIN_BUILTIN_MULTR_1X16);
5211 def_builtin ("__builtin_bfin_negate_fr1x16", short_ftype_short,
5212 BFIN_BUILTIN_NEG_1X16);
5213 def_builtin ("__builtin_bfin_abs_fr1x16", short_ftype_short,
5214 BFIN_BUILTIN_ABS_1X16);
5215 def_builtin ("__builtin_bfin_norm_fr1x16", short_ftype_int,
5216 BFIN_BUILTIN_NORM_1X16);
5218 def_builtin ("__builtin_bfin_sum_fr2x16", short_ftype_v2hi,
5219 BFIN_BUILTIN_SUM_2X16);
5220 def_builtin ("__builtin_bfin_diff_hl_fr2x16", short_ftype_v2hi,
5221 BFIN_BUILTIN_DIFFHL_2X16);
5222 def_builtin ("__builtin_bfin_diff_lh_fr2x16", short_ftype_v2hi,
5223 BFIN_BUILTIN_DIFFLH_2X16);
5225 def_builtin ("__builtin_bfin_mulhisill", int_ftype_v2hi_v2hi,
5226 BFIN_BUILTIN_MULHISILL);
5227 def_builtin ("__builtin_bfin_mulhisihl", int_ftype_v2hi_v2hi,
5228 BFIN_BUILTIN_MULHISIHL);
5229 def_builtin ("__builtin_bfin_mulhisilh", int_ftype_v2hi_v2hi,
5230 BFIN_BUILTIN_MULHISILH);
5231 def_builtin ("__builtin_bfin_mulhisihh", int_ftype_v2hi_v2hi,
5232 BFIN_BUILTIN_MULHISIHH);
5234 def_builtin ("__builtin_bfin_min_fr1x32", int_ftype_int_int,
5235 BFIN_BUILTIN_MIN_1X32);
5236 def_builtin ("__builtin_bfin_max_fr1x32", int_ftype_int_int,
5237 BFIN_BUILTIN_MAX_1X32);
5239 def_builtin ("__builtin_bfin_add_fr1x32", int_ftype_int_int,
5240 BFIN_BUILTIN_SSADD_1X32);
5241 def_builtin ("__builtin_bfin_sub_fr1x32", int_ftype_int_int,
5242 BFIN_BUILTIN_SSSUB_1X32);
5243 def_builtin ("__builtin_bfin_negate_fr1x32", int_ftype_int,
5244 BFIN_BUILTIN_NEG_1X32);
5245 def_builtin ("__builtin_bfin_abs_fr1x32", int_ftype_int,
5246 BFIN_BUILTIN_ABS_1X32);
5247 def_builtin ("__builtin_bfin_norm_fr1x32", short_ftype_int,
5248 BFIN_BUILTIN_NORM_1X32);
5249 def_builtin ("__builtin_bfin_round_fr1x32", short_ftype_int,
5250 BFIN_BUILTIN_ROUND_1X32);
5251 def_builtin ("__builtin_bfin_mult_fr1x32", int_ftype_short_short,
5252 BFIN_BUILTIN_MULT_1X32);
5253 def_builtin ("__builtin_bfin_mult_fr1x32x32", int_ftype_int_int,
5254 BFIN_BUILTIN_MULT_1X32X32);
5255 def_builtin ("__builtin_bfin_mult_fr1x32x32NS", int_ftype_int_int,
5256 BFIN_BUILTIN_MULT_1X32X32NS);
5258 /* Shifts. */
5259 def_builtin ("__builtin_bfin_shl_fr1x16", short_ftype_int_int,
5260 BFIN_BUILTIN_SSASHIFT_1X16);
5261 def_builtin ("__builtin_bfin_shl_fr2x16", v2hi_ftype_v2hi_int,
5262 BFIN_BUILTIN_SSASHIFT_2X16);
5263 def_builtin ("__builtin_bfin_lshl_fr1x16", short_ftype_int_int,
5264 BFIN_BUILTIN_LSHIFT_1X16);
5265 def_builtin ("__builtin_bfin_lshl_fr2x16", v2hi_ftype_v2hi_int,
5266 BFIN_BUILTIN_LSHIFT_2X16);
5267 def_builtin ("__builtin_bfin_shl_fr1x32", int_ftype_int_int,
5268 BFIN_BUILTIN_SSASHIFT_1X32);
5270 /* Complex numbers. */
5271 def_builtin ("__builtin_bfin_cmplx_add", v2hi_ftype_v2hi_v2hi,
5272 BFIN_BUILTIN_SSADD_2X16);
5273 def_builtin ("__builtin_bfin_cmplx_sub", v2hi_ftype_v2hi_v2hi,
5274 BFIN_BUILTIN_SSSUB_2X16);
5275 def_builtin ("__builtin_bfin_cmplx_mul", v2hi_ftype_v2hi_v2hi,
5276 BFIN_BUILTIN_CPLX_MUL_16);
5277 def_builtin ("__builtin_bfin_cmplx_mac", v2hi_ftype_v2hi_v2hi_v2hi,
5278 BFIN_BUILTIN_CPLX_MAC_16);
5279 def_builtin ("__builtin_bfin_cmplx_msu", v2hi_ftype_v2hi_v2hi_v2hi,
5280 BFIN_BUILTIN_CPLX_MSU_16);
5281 def_builtin ("__builtin_bfin_cmplx_mul_s40", v2hi_ftype_v2hi_v2hi,
5282 BFIN_BUILTIN_CPLX_MUL_16_S40);
5283 def_builtin ("__builtin_bfin_cmplx_mac_s40", v2hi_ftype_v2hi_v2hi_v2hi,
5284 BFIN_BUILTIN_CPLX_MAC_16_S40);
5285 def_builtin ("__builtin_bfin_cmplx_msu_s40", v2hi_ftype_v2hi_v2hi_v2hi,
5286 BFIN_BUILTIN_CPLX_MSU_16_S40);
5287 def_builtin ("__builtin_bfin_csqu_fr16", v2hi_ftype_v2hi,
5288 BFIN_BUILTIN_CPLX_SQU);
5290 /* "Unaligned" load. */
5291 def_builtin ("__builtin_bfin_loadbytes", int_ftype_pint,
5292 BFIN_BUILTIN_LOADBYTES);
5297 struct builtin_description
5299 const enum insn_code icode;
5300 const char *const name;
5301 const enum bfin_builtins code;
5302 int macflag;
5305 static const struct builtin_description bdesc_2arg[] =
5307 { CODE_FOR_composev2hi, "__builtin_bfin_compose_2x16", BFIN_BUILTIN_COMPOSE_2X16, -1 },
5309 { CODE_FOR_ssashiftv2hi3, "__builtin_bfin_shl_fr2x16", BFIN_BUILTIN_SSASHIFT_2X16, -1 },
5310 { CODE_FOR_ssashifthi3, "__builtin_bfin_shl_fr1x16", BFIN_BUILTIN_SSASHIFT_1X16, -1 },
5311 { CODE_FOR_lshiftv2hi3, "__builtin_bfin_lshl_fr2x16", BFIN_BUILTIN_LSHIFT_2X16, -1 },
5312 { CODE_FOR_lshifthi3, "__builtin_bfin_lshl_fr1x16", BFIN_BUILTIN_LSHIFT_1X16, -1 },
5313 { CODE_FOR_ssashiftsi3, "__builtin_bfin_shl_fr1x32", BFIN_BUILTIN_SSASHIFT_1X32, -1 },
5315 { CODE_FOR_sminhi3, "__builtin_bfin_min_fr1x16", BFIN_BUILTIN_MIN_1X16, -1 },
5316 { CODE_FOR_smaxhi3, "__builtin_bfin_max_fr1x16", BFIN_BUILTIN_MAX_1X16, -1 },
5317 { CODE_FOR_ssaddhi3, "__builtin_bfin_add_fr1x16", BFIN_BUILTIN_SSADD_1X16, -1 },
5318 { CODE_FOR_sssubhi3, "__builtin_bfin_sub_fr1x16", BFIN_BUILTIN_SSSUB_1X16, -1 },
5320 { CODE_FOR_sminsi3, "__builtin_bfin_min_fr1x32", BFIN_BUILTIN_MIN_1X32, -1 },
5321 { CODE_FOR_smaxsi3, "__builtin_bfin_max_fr1x32", BFIN_BUILTIN_MAX_1X32, -1 },
5322 { CODE_FOR_ssaddsi3, "__builtin_bfin_add_fr1x32", BFIN_BUILTIN_SSADD_1X32, -1 },
5323 { CODE_FOR_sssubsi3, "__builtin_bfin_sub_fr1x32", BFIN_BUILTIN_SSSUB_1X32, -1 },
5325 { CODE_FOR_sminv2hi3, "__builtin_bfin_min_fr2x16", BFIN_BUILTIN_MIN_2X16, -1 },
5326 { CODE_FOR_smaxv2hi3, "__builtin_bfin_max_fr2x16", BFIN_BUILTIN_MAX_2X16, -1 },
5327 { CODE_FOR_ssaddv2hi3, "__builtin_bfin_add_fr2x16", BFIN_BUILTIN_SSADD_2X16, -1 },
5328 { CODE_FOR_sssubv2hi3, "__builtin_bfin_sub_fr2x16", BFIN_BUILTIN_SSSUB_2X16, -1 },
5329 { CODE_FOR_ssaddsubv2hi3, "__builtin_bfin_dspaddsubsat", BFIN_BUILTIN_SSADDSUB_2X16, -1 },
5330 { CODE_FOR_sssubaddv2hi3, "__builtin_bfin_dspsubaddsat", BFIN_BUILTIN_SSSUBADD_2X16, -1 },
5332 { CODE_FOR_flag_mulhisi, "__builtin_bfin_mult_fr1x32", BFIN_BUILTIN_MULT_1X32, MACFLAG_NONE },
5333 { CODE_FOR_flag_mulhi, "__builtin_bfin_mult_fr1x16", BFIN_BUILTIN_MULT_1X16, MACFLAG_T },
5334 { CODE_FOR_flag_mulhi, "__builtin_bfin_multr_fr1x16", BFIN_BUILTIN_MULTR_1X16, MACFLAG_NONE },
5335 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_mult_fr2x16", BFIN_BUILTIN_MULT_2X16, MACFLAG_T },
5336 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_multr_fr2x16", BFIN_BUILTIN_MULTR_2X16, MACFLAG_NONE },
5338 { CODE_FOR_mulhisi_ll, "__builtin_bfin_mulhisill", BFIN_BUILTIN_MULHISILL, -1 },
5339 { CODE_FOR_mulhisi_lh, "__builtin_bfin_mulhisilh", BFIN_BUILTIN_MULHISILH, -1 },
5340 { CODE_FOR_mulhisi_hl, "__builtin_bfin_mulhisihl", BFIN_BUILTIN_MULHISIHL, -1 },
5341 { CODE_FOR_mulhisi_hh, "__builtin_bfin_mulhisihh", BFIN_BUILTIN_MULHISIHH, -1 }
5345 static const struct builtin_description bdesc_1arg[] =
5347 { CODE_FOR_loadbytes, "__builtin_bfin_loadbytes", BFIN_BUILTIN_LOADBYTES, 0 },
5349 { CODE_FOR_ones, "__builtin_bfin_ones", BFIN_BUILTIN_ONES, 0 },
5351 { CODE_FOR_clrsbhi2, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16, 0 },
5352 { CODE_FOR_ssneghi2, "__builtin_bfin_negate_fr1x16", BFIN_BUILTIN_NEG_1X16, 0 },
5353 { CODE_FOR_abshi2, "__builtin_bfin_abs_fr1x16", BFIN_BUILTIN_ABS_1X16, 0 },
5355 { CODE_FOR_clrsbsi2, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32, 0 },
5356 { CODE_FOR_ssroundsi2, "__builtin_bfin_round_fr1x32", BFIN_BUILTIN_ROUND_1X32, 0 },
5357 { CODE_FOR_ssnegsi2, "__builtin_bfin_negate_fr1x32", BFIN_BUILTIN_NEG_1X32, 0 },
5358 { CODE_FOR_ssabssi2, "__builtin_bfin_abs_fr1x32", BFIN_BUILTIN_ABS_1X32, 0 },
5360 { CODE_FOR_movv2hi_hi_low, "__builtin_bfin_extract_lo", BFIN_BUILTIN_EXTRACTLO, 0 },
5361 { CODE_FOR_movv2hi_hi_high, "__builtin_bfin_extract_hi", BFIN_BUILTIN_EXTRACTHI, 0 },
5362 { CODE_FOR_ssnegv2hi2, "__builtin_bfin_negate_fr2x16", BFIN_BUILTIN_NEG_2X16, 0 },
5363 { CODE_FOR_ssabsv2hi2, "__builtin_bfin_abs_fr2x16", BFIN_BUILTIN_ABS_2X16, 0 }
5366 /* Errors in the source file can cause expand_expr to return const0_rtx
5367 where we expect a vector. To avoid crashing, use one of the vector
5368 clear instructions. */
5369 static rtx
5370 safe_vector_operand (rtx x, machine_mode mode)
5372 if (x != const0_rtx)
5373 return x;
5374 x = gen_reg_rtx (SImode);
5376 emit_insn (gen_movsi (x, CONST0_RTX (SImode)));
5377 return gen_lowpart (mode, x);
5380 /* Subroutine of bfin_expand_builtin to take care of binop insns. MACFLAG is -1
5381 if this is a normal binary op, or one of the MACFLAG_xxx constants. */
5383 static rtx
5384 bfin_expand_binop_builtin (enum insn_code icode, tree exp, rtx target,
5385 int macflag)
5387 rtx pat;
5388 tree arg0 = CALL_EXPR_ARG (exp, 0);
5389 tree arg1 = CALL_EXPR_ARG (exp, 1);
5390 rtx op0 = expand_normal (arg0);
5391 rtx op1 = expand_normal (arg1);
5392 machine_mode op0mode = GET_MODE (op0);
5393 machine_mode op1mode = GET_MODE (op1);
5394 machine_mode tmode = insn_data[icode].operand[0].mode;
5395 machine_mode mode0 = insn_data[icode].operand[1].mode;
5396 machine_mode mode1 = insn_data[icode].operand[2].mode;
5398 if (VECTOR_MODE_P (mode0))
5399 op0 = safe_vector_operand (op0, mode0);
5400 if (VECTOR_MODE_P (mode1))
5401 op1 = safe_vector_operand (op1, mode1);
5403 if (! target
5404 || GET_MODE (target) != tmode
5405 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5406 target = gen_reg_rtx (tmode);
5408 if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode)
5410 op0mode = HImode;
5411 op0 = gen_lowpart (HImode, op0);
5413 if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode)
5415 op1mode = HImode;
5416 op1 = gen_lowpart (HImode, op1);
5418 /* In case the insn wants input operands in modes different from
5419 the result, abort. */
5420 gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
5421 && (op1mode == mode1 || op1mode == VOIDmode));
5423 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5424 op0 = copy_to_mode_reg (mode0, op0);
5425 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
5426 op1 = copy_to_mode_reg (mode1, op1);
5428 if (macflag == -1)
5429 pat = GEN_FCN (icode) (target, op0, op1);
5430 else
5431 pat = GEN_FCN (icode) (target, op0, op1, GEN_INT (macflag));
5432 if (! pat)
5433 return 0;
5435 emit_insn (pat);
5436 return target;
5439 /* Subroutine of bfin_expand_builtin to take care of unop insns. */
5441 static rtx
5442 bfin_expand_unop_builtin (enum insn_code icode, tree exp,
5443 rtx target)
5445 rtx pat;
5446 tree arg0 = CALL_EXPR_ARG (exp, 0);
5447 rtx op0 = expand_normal (arg0);
5448 machine_mode op0mode = GET_MODE (op0);
5449 machine_mode tmode = insn_data[icode].operand[0].mode;
5450 machine_mode mode0 = insn_data[icode].operand[1].mode;
5452 if (! target
5453 || GET_MODE (target) != tmode
5454 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5455 target = gen_reg_rtx (tmode);
5457 if (VECTOR_MODE_P (mode0))
5458 op0 = safe_vector_operand (op0, mode0);
5460 if (op0mode == SImode && mode0 == HImode)
5462 op0mode = HImode;
5463 op0 = gen_lowpart (HImode, op0);
5465 gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
5467 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5468 op0 = copy_to_mode_reg (mode0, op0);
5470 pat = GEN_FCN (icode) (target, op0);
5471 if (! pat)
5472 return 0;
5473 emit_insn (pat);
5474 return target;
5477 /* Expand an expression EXP that calls a built-in function,
5478 with result going to TARGET if that's convenient
5479 (and in mode MODE if that's convenient).
5480 SUBTARGET may be used as the target for computing one of EXP's operands.
5481 IGNORE is nonzero if the value is to be ignored. */
5483 static rtx
5484 bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
5485 rtx subtarget ATTRIBUTE_UNUSED,
5486 machine_mode mode ATTRIBUTE_UNUSED,
5487 int ignore ATTRIBUTE_UNUSED)
5489 size_t i;
5490 enum insn_code icode;
5491 const struct builtin_description *d;
5492 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
5493 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
5494 tree arg0, arg1, arg2;
5495 rtx op0, op1, op2, accvec, pat, tmp1, tmp2, a0reg, a1reg;
5496 machine_mode tmode, mode0;
5498 switch (fcode)
5500 case BFIN_BUILTIN_CSYNC:
5501 emit_insn (gen_csync ());
5502 return 0;
5503 case BFIN_BUILTIN_SSYNC:
5504 emit_insn (gen_ssync ());
5505 return 0;
5507 case BFIN_BUILTIN_DIFFHL_2X16:
5508 case BFIN_BUILTIN_DIFFLH_2X16:
5509 case BFIN_BUILTIN_SUM_2X16:
5510 arg0 = CALL_EXPR_ARG (exp, 0);
5511 op0 = expand_normal (arg0);
5512 icode = (fcode == BFIN_BUILTIN_DIFFHL_2X16 ? CODE_FOR_subhilov2hi3
5513 : fcode == BFIN_BUILTIN_DIFFLH_2X16 ? CODE_FOR_sublohiv2hi3
5514 : CODE_FOR_ssaddhilov2hi3);
5515 tmode = insn_data[icode].operand[0].mode;
5516 mode0 = insn_data[icode].operand[1].mode;
5518 if (! target
5519 || GET_MODE (target) != tmode
5520 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5521 target = gen_reg_rtx (tmode);
5523 if (VECTOR_MODE_P (mode0))
5524 op0 = safe_vector_operand (op0, mode0);
5526 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5527 op0 = copy_to_mode_reg (mode0, op0);
5529 pat = GEN_FCN (icode) (target, op0, op0);
5530 if (! pat)
5531 return 0;
5532 emit_insn (pat);
5533 return target;
5535 case BFIN_BUILTIN_MULT_1X32X32:
5536 case BFIN_BUILTIN_MULT_1X32X32NS:
5537 arg0 = CALL_EXPR_ARG (exp, 0);
5538 arg1 = CALL_EXPR_ARG (exp, 1);
5539 op0 = expand_normal (arg0);
5540 op1 = expand_normal (arg1);
5541 if (! target
5542 || !register_operand (target, SImode))
5543 target = gen_reg_rtx (SImode);
5544 if (! register_operand (op0, SImode))
5545 op0 = copy_to_mode_reg (SImode, op0);
5546 if (! register_operand (op1, SImode))
5547 op1 = copy_to_mode_reg (SImode, op1);
5549 a1reg = gen_rtx_REG (PDImode, REG_A1);
5550 a0reg = gen_rtx_REG (PDImode, REG_A0);
5551 tmp1 = gen_lowpart (V2HImode, op0);
5552 tmp2 = gen_lowpart (V2HImode, op1);
5553 emit_insn (gen_flag_macinit1hi (a1reg,
5554 gen_lowpart (HImode, op0),
5555 gen_lowpart (HImode, op1),
5556 GEN_INT (MACFLAG_FU)));
5557 emit_insn (gen_lshrpdi3 (a1reg, a1reg, GEN_INT (16)));
5559 if (fcode == BFIN_BUILTIN_MULT_1X32X32)
5560 emit_insn (gen_flag_mul_macv2hi_parts_acconly (a0reg, a1reg, tmp1, tmp2,
5561 const1_rtx, const1_rtx,
5562 const1_rtx, const0_rtx, a1reg,
5563 const0_rtx, GEN_INT (MACFLAG_NONE),
5564 GEN_INT (MACFLAG_M)));
5565 else
5567 /* For saturating multiplication, there's exactly one special case
5568 to be handled: multiplying the smallest negative value with
5569 itself. Due to shift correction in fractional multiplies, this
5570 can overflow. Iff this happens, OP2 will contain 1, which, when
5571 added in 32 bits to the smallest negative, wraps to the largest
5572 positive, which is the result we want. */
5573 op2 = gen_reg_rtx (V2HImode);
5574 emit_insn (gen_packv2hi (op2, tmp1, tmp2, const0_rtx, const0_rtx));
5575 emit_insn (gen_movsibi (gen_rtx_REG (BImode, REG_CC),
5576 gen_lowpart (SImode, op2)));
5577 emit_insn (gen_flag_mul_macv2hi_parts_acconly_andcc0 (a0reg, a1reg, tmp1, tmp2,
5578 const1_rtx, const1_rtx,
5579 const1_rtx, const0_rtx, a1reg,
5580 const0_rtx, GEN_INT (MACFLAG_NONE),
5581 GEN_INT (MACFLAG_M)));
5582 op2 = gen_reg_rtx (SImode);
5583 emit_insn (gen_movbisi (op2, gen_rtx_REG (BImode, REG_CC)));
5585 emit_insn (gen_flag_machi_parts_acconly (a1reg, tmp2, tmp1,
5586 const1_rtx, const0_rtx,
5587 a1reg, const0_rtx, GEN_INT (MACFLAG_M)));
5588 emit_insn (gen_ashrpdi3 (a1reg, a1reg, GEN_INT (15)));
5589 emit_insn (gen_sum_of_accumulators (target, a0reg, a0reg, a1reg));
5590 if (fcode == BFIN_BUILTIN_MULT_1X32X32NS)
5591 emit_insn (gen_addsi3 (target, target, op2));
5592 return target;
5594 case BFIN_BUILTIN_CPLX_MUL_16:
5595 case BFIN_BUILTIN_CPLX_MUL_16_S40:
5596 arg0 = CALL_EXPR_ARG (exp, 0);
5597 arg1 = CALL_EXPR_ARG (exp, 1);
5598 op0 = expand_normal (arg0);
5599 op1 = expand_normal (arg1);
5600 accvec = gen_reg_rtx (V2PDImode);
5601 icode = CODE_FOR_flag_macv2hi_parts;
5602 tmode = insn_data[icode].operand[0].mode;
5604 if (! target
5605 || GET_MODE (target) != V2HImode
5606 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5607 target = gen_reg_rtx (tmode);
5608 if (! register_operand (op0, GET_MODE (op0)))
5609 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
5610 if (! register_operand (op1, GET_MODE (op1)))
5611 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
5613 if (fcode == BFIN_BUILTIN_CPLX_MUL_16)
5614 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
5615 const0_rtx, const0_rtx,
5616 const1_rtx, GEN_INT (MACFLAG_W32)));
5617 else
5618 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
5619 const0_rtx, const0_rtx,
5620 const1_rtx, GEN_INT (MACFLAG_NONE)));
5621 emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
5622 const1_rtx, const1_rtx,
5623 const0_rtx, accvec, const1_rtx, const0_rtx,
5624 GEN_INT (MACFLAG_NONE), accvec));
5626 return target;
5628 case BFIN_BUILTIN_CPLX_MAC_16:
5629 case BFIN_BUILTIN_CPLX_MSU_16:
5630 case BFIN_BUILTIN_CPLX_MAC_16_S40:
5631 case BFIN_BUILTIN_CPLX_MSU_16_S40:
5632 arg0 = CALL_EXPR_ARG (exp, 0);
5633 arg1 = CALL_EXPR_ARG (exp, 1);
5634 arg2 = CALL_EXPR_ARG (exp, 2);
5635 op0 = expand_normal (arg0);
5636 op1 = expand_normal (arg1);
5637 op2 = expand_normal (arg2);
5638 accvec = gen_reg_rtx (V2PDImode);
5639 icode = CODE_FOR_flag_macv2hi_parts;
5640 tmode = insn_data[icode].operand[0].mode;
5642 if (! target
5643 || GET_MODE (target) != V2HImode
5644 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5645 target = gen_reg_rtx (tmode);
5646 if (! register_operand (op1, GET_MODE (op1)))
5647 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
5648 if (! register_operand (op2, GET_MODE (op2)))
5649 op2 = copy_to_mode_reg (GET_MODE (op2), op2);
5651 tmp1 = gen_reg_rtx (SImode);
5652 tmp2 = gen_reg_rtx (SImode);
5653 emit_insn (gen_ashlsi3 (tmp1, gen_lowpart (SImode, op0), GEN_INT (16)));
5654 emit_move_insn (tmp2, gen_lowpart (SImode, op0));
5655 emit_insn (gen_movstricthi_1 (gen_lowpart (HImode, tmp2), const0_rtx));
5656 emit_insn (gen_load_accumulator_pair (accvec, tmp1, tmp2));
5657 if (fcode == BFIN_BUILTIN_CPLX_MAC_16
5658 || fcode == BFIN_BUILTIN_CPLX_MSU_16)
5659 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx,
5660 const0_rtx, const0_rtx,
5661 const1_rtx, accvec, const0_rtx,
5662 const0_rtx,
5663 GEN_INT (MACFLAG_W32)));
5664 else
5665 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx,
5666 const0_rtx, const0_rtx,
5667 const1_rtx, accvec, const0_rtx,
5668 const0_rtx,
5669 GEN_INT (MACFLAG_NONE)));
5670 if (fcode == BFIN_BUILTIN_CPLX_MAC_16
5671 || fcode == BFIN_BUILTIN_CPLX_MAC_16_S40)
5673 tmp1 = const1_rtx;
5674 tmp2 = const0_rtx;
5676 else
5678 tmp1 = const0_rtx;
5679 tmp2 = const1_rtx;
5681 emit_insn (gen_flag_macv2hi_parts (target, op1, op2, const1_rtx,
5682 const1_rtx, const1_rtx,
5683 const0_rtx, accvec, tmp1, tmp2,
5684 GEN_INT (MACFLAG_NONE), accvec));
5686 return target;
5688 case BFIN_BUILTIN_CPLX_SQU:
5689 arg0 = CALL_EXPR_ARG (exp, 0);
5690 op0 = expand_normal (arg0);
5691 accvec = gen_reg_rtx (V2PDImode);
5692 icode = CODE_FOR_flag_mulv2hi;
5693 tmp1 = gen_reg_rtx (V2HImode);
5694 tmp2 = gen_reg_rtx (V2HImode);
5696 if (! target
5697 || GET_MODE (target) != V2HImode
5698 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5699 target = gen_reg_rtx (V2HImode);
5700 if (! register_operand (op0, GET_MODE (op0)))
5701 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
5703 emit_insn (gen_flag_mulv2hi (tmp1, op0, op0, GEN_INT (MACFLAG_NONE)));
5705 emit_insn (gen_flag_mulhi_parts (gen_lowpart (HImode, tmp2), op0, op0,
5706 const0_rtx, const1_rtx,
5707 GEN_INT (MACFLAG_NONE)));
5709 emit_insn (gen_ssaddhi3_high_parts (target, tmp2, tmp2, tmp2, const0_rtx,
5710 const0_rtx));
5711 emit_insn (gen_sssubhi3_low_parts (target, target, tmp1, tmp1,
5712 const0_rtx, const1_rtx));
5714 return target;
5716 default:
5717 break;
5720 for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
5721 if (d->code == fcode)
5722 return bfin_expand_binop_builtin (d->icode, exp, target,
5723 d->macflag);
5725 for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
5726 if (d->code == fcode)
5727 return bfin_expand_unop_builtin (d->icode, exp, target);
5729 gcc_unreachable ();
5732 static void
5733 bfin_conditional_register_usage (void)
5735 /* initialize condition code flag register rtx */
5736 bfin_cc_rtx = gen_rtx_REG (BImode, REG_CC);
5737 bfin_rets_rtx = gen_rtx_REG (Pmode, REG_RETS);
5738 if (TARGET_FDPIC)
5739 call_used_regs[FDPIC_REGNO] = 1;
5740 if (!TARGET_FDPIC && flag_pic)
5742 fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
5743 call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
5747 #undef TARGET_INIT_BUILTINS
5748 #define TARGET_INIT_BUILTINS bfin_init_builtins
5750 #undef TARGET_EXPAND_BUILTIN
5751 #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
5753 #undef TARGET_ASM_GLOBALIZE_LABEL
5754 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label
5756 #undef TARGET_ASM_FILE_START
5757 #define TARGET_ASM_FILE_START output_file_start
5759 #undef TARGET_ATTRIBUTE_TABLE
5760 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
5762 #undef TARGET_COMP_TYPE_ATTRIBUTES
5763 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
5765 #undef TARGET_RTX_COSTS
5766 #define TARGET_RTX_COSTS bfin_rtx_costs
5768 #undef TARGET_ADDRESS_COST
5769 #define TARGET_ADDRESS_COST bfin_address_cost
5771 #undef TARGET_REGISTER_MOVE_COST
5772 #define TARGET_REGISTER_MOVE_COST bfin_register_move_cost
5774 #undef TARGET_MEMORY_MOVE_COST
5775 #define TARGET_MEMORY_MOVE_COST bfin_memory_move_cost
5777 #undef TARGET_ASM_INTEGER
5778 #define TARGET_ASM_INTEGER bfin_assemble_integer
5780 #undef TARGET_MACHINE_DEPENDENT_REORG
5781 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
5783 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
5784 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
5786 #undef TARGET_ASM_OUTPUT_MI_THUNK
5787 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
5788 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
5789 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
5791 #undef TARGET_SCHED_ADJUST_COST
5792 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
5794 #undef TARGET_SCHED_ISSUE_RATE
5795 #define TARGET_SCHED_ISSUE_RATE bfin_issue_rate
5797 #undef TARGET_PROMOTE_FUNCTION_MODE
5798 #define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
5800 #undef TARGET_ARG_PARTIAL_BYTES
5801 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
5803 #undef TARGET_FUNCTION_ARG
5804 #define TARGET_FUNCTION_ARG bfin_function_arg
5806 #undef TARGET_FUNCTION_ARG_ADVANCE
5807 #define TARGET_FUNCTION_ARG_ADVANCE bfin_function_arg_advance
5809 #undef TARGET_PASS_BY_REFERENCE
5810 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
5812 #undef TARGET_SETUP_INCOMING_VARARGS
5813 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
5815 #undef TARGET_STRUCT_VALUE_RTX
5816 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
5818 #undef TARGET_VECTOR_MODE_SUPPORTED_P
5819 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
5821 #undef TARGET_OPTION_OVERRIDE
5822 #define TARGET_OPTION_OVERRIDE bfin_option_override
5824 #undef TARGET_SECONDARY_RELOAD
5825 #define TARGET_SECONDARY_RELOAD bfin_secondary_reload
5827 #undef TARGET_CLASS_LIKELY_SPILLED_P
5828 #define TARGET_CLASS_LIKELY_SPILLED_P bfin_class_likely_spilled_p
5830 #undef TARGET_DELEGITIMIZE_ADDRESS
5831 #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address
5833 #undef TARGET_LEGITIMATE_CONSTANT_P
5834 #define TARGET_LEGITIMATE_CONSTANT_P bfin_legitimate_constant_p
5836 #undef TARGET_CANNOT_FORCE_CONST_MEM
5837 #define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem
5839 #undef TARGET_RETURN_IN_MEMORY
5840 #define TARGET_RETURN_IN_MEMORY bfin_return_in_memory
5842 #undef TARGET_LRA_P
5843 #define TARGET_LRA_P hook_bool_void_false
5845 #undef TARGET_LEGITIMATE_ADDRESS_P
5846 #define TARGET_LEGITIMATE_ADDRESS_P bfin_legitimate_address_p
5848 #undef TARGET_FRAME_POINTER_REQUIRED
5849 #define TARGET_FRAME_POINTER_REQUIRED bfin_frame_pointer_required
5851 #undef TARGET_CAN_ELIMINATE
5852 #define TARGET_CAN_ELIMINATE bfin_can_eliminate
5854 #undef TARGET_CONDITIONAL_REGISTER_USAGE
5855 #define TARGET_CONDITIONAL_REGISTER_USAGE bfin_conditional_register_usage
5857 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
5858 #define TARGET_ASM_TRAMPOLINE_TEMPLATE bfin_asm_trampoline_template
5859 #undef TARGET_TRAMPOLINE_INIT
5860 #define TARGET_TRAMPOLINE_INIT bfin_trampoline_init
5862 #undef TARGET_EXTRA_LIVE_ON_ENTRY
5863 #define TARGET_EXTRA_LIVE_ON_ENTRY bfin_extra_live_on_entry
5865 /* Passes after sched2 can break the helpful TImode annotations that
5866 haifa-sched puts on every insn. Just do scheduling in reorg. */
5867 #undef TARGET_DELAY_SCHED2
5868 #define TARGET_DELAY_SCHED2 true
5870 /* Variable tracking should be run after all optimizations which
5871 change order of insns. It also needs a valid CFG. */
5872 #undef TARGET_DELAY_VARTRACK
5873 #define TARGET_DELAY_VARTRACK true
5875 #undef TARGET_CAN_USE_DOLOOP_P
5876 #define TARGET_CAN_USE_DOLOOP_P bfin_can_use_doloop_p
5878 #undef TARGET_HARD_REGNO_NREGS
5879 #define TARGET_HARD_REGNO_NREGS bfin_hard_regno_nregs
5880 #undef TARGET_HARD_REGNO_MODE_OK
5881 #define TARGET_HARD_REGNO_MODE_OK bfin_hard_regno_mode_ok
5883 #undef TARGET_MODES_TIEABLE_P
5884 #define TARGET_MODES_TIEABLE_P bfin_modes_tieable_p
5886 #undef TARGET_CONSTANT_ALIGNMENT
5887 #define TARGET_CONSTANT_ALIGNMENT constant_alignment_word_strings
5889 struct gcc_target targetm = TARGET_INITIALIZER;