PR target/84564
[official-gcc.git] / gcc / config / bfin / bfin.c
blobb656f13d3157b39a164208ac15fad2157f677466
1 /* The Blackfin code generation auxiliary output file.
2 Copyright (C) 2005-2018 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 #define IN_TARGET_CODE 1
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "backend.h"
27 #include "target.h"
28 #include "rtl.h"
29 #include "tree.h"
30 #include "stringpool.h"
31 #include "attribs.h"
32 #include "cfghooks.h"
33 #include "df.h"
34 #include "memmodel.h"
35 #include "tm_p.h"
36 #include "optabs.h"
37 #include "regs.h"
38 #include "emit-rtl.h"
39 #include "recog.h"
40 #include "cgraph.h"
41 #include "diagnostic-core.h"
42 #include "output.h"
43 #include "insn-attr.h"
44 #include "varasm.h"
45 #include "calls.h"
46 #include "explow.h"
47 #include "expr.h"
48 #include "cfgrtl.h"
49 #include "langhooks.h"
50 #include "tm-constrs.h"
51 #include "gt-bfin.h"
52 #include "sel-sched.h"
53 #include "hw-doloop.h"
54 #include "dumpfile.h"
55 #include "builtins.h"
57 /* This file should be included last. */
58 #include "target-def.h"
60 /* A C structure for machine-specific, per-function data.
61 This is added to the cfun structure. */
62 struct GTY(()) machine_function
64 /* Set if we are notified by the doloop pass that a hardware loop
65 was created. */
66 int has_hardware_loops;
68 /* Set if we create a memcpy pattern that uses loop registers. */
69 int has_loopreg_clobber;
72 /* RTX for condition code flag register and RETS register */
73 extern GTY(()) rtx bfin_cc_rtx;
74 extern GTY(()) rtx bfin_rets_rtx;
75 rtx bfin_cc_rtx, bfin_rets_rtx;
77 int max_arg_registers = 0;
79 /* Arrays used when emitting register names. */
80 const char *short_reg_names[] = SHORT_REGISTER_NAMES;
81 const char *high_reg_names[] = HIGH_REGISTER_NAMES;
82 const char *dregs_pair_names[] = DREGS_PAIR_NAMES;
83 const char *byte_reg_names[] = BYTE_REGISTER_NAMES;
85 static int arg_regs[] = FUNCTION_ARG_REGISTERS;
86 static int ret_regs[] = FUNCTION_RETURN_REGISTERS;
88 int splitting_for_sched, splitting_loops;
90 static void
91 bfin_globalize_label (FILE *stream, const char *name)
93 fputs (".global ", stream);
94 assemble_name (stream, name);
95 fputc (';',stream);
96 fputc ('\n',stream);
99 static void
100 output_file_start (void)
102 FILE *file = asm_out_file;
103 int i;
105 fprintf (file, ".file \"%s\";\n", LOCATION_FILE (input_location));
107 for (i = 0; arg_regs[i] >= 0; i++)
109 max_arg_registers = i; /* how many arg reg used */
112 /* Examine machine-dependent attributes of function type FUNTYPE and return its
113 type. See the definition of E_FUNKIND. */
115 static e_funkind
116 funkind (const_tree funtype)
118 tree attrs = TYPE_ATTRIBUTES (funtype);
119 if (lookup_attribute ("interrupt_handler", attrs))
120 return INTERRUPT_HANDLER;
121 else if (lookup_attribute ("exception_handler", attrs))
122 return EXCPT_HANDLER;
123 else if (lookup_attribute ("nmi_handler", attrs))
124 return NMI_HANDLER;
125 else
126 return SUBROUTINE;
129 /* Legitimize PIC addresses. If the address is already position-independent,
130 we return ORIG. Newly generated position-independent addresses go into a
131 reg. This is REG if nonzero, otherwise we allocate register(s) as
132 necessary. PICREG is the register holding the pointer to the PIC offset
133 table. */
135 static rtx
136 legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
138 rtx addr = orig;
139 rtx new_rtx = orig;
141 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
143 int unspec;
144 rtx tmp;
146 if (TARGET_ID_SHARED_LIBRARY)
147 unspec = UNSPEC_MOVE_PIC;
148 else if (GET_CODE (addr) == SYMBOL_REF
149 && SYMBOL_REF_FUNCTION_P (addr))
150 unspec = UNSPEC_FUNCDESC_GOT17M4;
151 else
152 unspec = UNSPEC_MOVE_FDPIC;
154 if (reg == 0)
156 gcc_assert (can_create_pseudo_p ());
157 reg = gen_reg_rtx (Pmode);
160 tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), unspec);
161 new_rtx = gen_const_mem (Pmode, gen_rtx_PLUS (Pmode, picreg, tmp));
163 emit_move_insn (reg, new_rtx);
164 if (picreg == pic_offset_table_rtx)
165 crtl->uses_pic_offset_table = 1;
166 return reg;
169 else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
171 rtx base;
173 if (GET_CODE (addr) == CONST)
175 addr = XEXP (addr, 0);
176 gcc_assert (GET_CODE (addr) == PLUS);
179 if (XEXP (addr, 0) == picreg)
180 return orig;
182 if (reg == 0)
184 gcc_assert (can_create_pseudo_p ());
185 reg = gen_reg_rtx (Pmode);
188 base = legitimize_pic_address (XEXP (addr, 0), reg, picreg);
189 addr = legitimize_pic_address (XEXP (addr, 1),
190 base == reg ? NULL_RTX : reg,
191 picreg);
193 if (GET_CODE (addr) == CONST_INT)
195 gcc_assert (! reload_in_progress && ! reload_completed);
196 addr = force_reg (Pmode, addr);
199 if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
201 base = gen_rtx_PLUS (Pmode, base, XEXP (addr, 0));
202 addr = XEXP (addr, 1);
205 return gen_rtx_PLUS (Pmode, base, addr);
208 return new_rtx;
211 /* Stack frame layout. */
213 /* For a given REGNO, determine whether it must be saved in the function
214 prologue. IS_INTHANDLER specifies whether we're generating a normal
215 prologue or an interrupt/exception one. */
216 static bool
217 must_save_p (bool is_inthandler, unsigned regno)
219 if (D_REGNO_P (regno))
221 bool is_eh_return_reg = false;
222 if (crtl->calls_eh_return)
224 unsigned j;
225 for (j = 0; ; j++)
227 unsigned test = EH_RETURN_DATA_REGNO (j);
228 if (test == INVALID_REGNUM)
229 break;
230 if (test == regno)
231 is_eh_return_reg = true;
235 return (is_eh_return_reg
236 || (df_regs_ever_live_p (regno)
237 && !fixed_regs[regno]
238 && (is_inthandler || !call_used_regs[regno])));
240 else if (P_REGNO_P (regno))
242 return ((df_regs_ever_live_p (regno)
243 && !fixed_regs[regno]
244 && (is_inthandler || !call_used_regs[regno]))
245 || (is_inthandler
246 && (ENABLE_WA_05000283 || ENABLE_WA_05000315)
247 && regno == REG_P5)
248 || (!TARGET_FDPIC
249 && regno == PIC_OFFSET_TABLE_REGNUM
250 && (crtl->uses_pic_offset_table
251 || (TARGET_ID_SHARED_LIBRARY && !crtl->is_leaf))));
253 else
254 return ((is_inthandler || !call_used_regs[regno])
255 && (df_regs_ever_live_p (regno)
256 || (!leaf_function_p () && call_used_regs[regno])));
260 /* Compute the number of DREGS to save with a push_multiple operation.
261 This could include registers that aren't modified in the function,
262 since push_multiple only takes a range of registers.
263 If IS_INTHANDLER, then everything that is live must be saved, even
264 if normally call-clobbered.
265 If CONSECUTIVE, return the number of registers we can save in one
266 instruction with a push/pop multiple instruction. */
268 static int
269 n_dregs_to_save (bool is_inthandler, bool consecutive)
271 int count = 0;
272 unsigned i;
274 for (i = REG_R7 + 1; i-- != REG_R0;)
276 if (must_save_p (is_inthandler, i))
277 count++;
278 else if (consecutive)
279 return count;
281 return count;
284 /* Like n_dregs_to_save, but compute number of PREGS to save. */
286 static int
287 n_pregs_to_save (bool is_inthandler, bool consecutive)
289 int count = 0;
290 unsigned i;
292 for (i = REG_P5 + 1; i-- != REG_P0;)
293 if (must_save_p (is_inthandler, i))
294 count++;
295 else if (consecutive)
296 return count;
297 return count;
300 /* Determine if we are going to save the frame pointer in the prologue. */
302 static bool
303 must_save_fp_p (void)
305 return df_regs_ever_live_p (REG_FP);
308 /* Determine if we are going to save the RETS register. */
309 static bool
310 must_save_rets_p (void)
312 return df_regs_ever_live_p (REG_RETS);
315 static bool
316 stack_frame_needed_p (void)
318 /* EH return puts a new return address into the frame using an
319 address relative to the frame pointer. */
320 if (crtl->calls_eh_return)
321 return true;
322 return frame_pointer_needed;
325 /* Emit code to save registers in the prologue. SAVEALL is nonzero if we
326 must save all registers; this is used for interrupt handlers.
327 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
328 this for an interrupt (or exception) handler. */
330 static void
331 expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler)
333 rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
334 rtx predec = gen_rtx_MEM (SImode, predec1);
335 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler, false);
336 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler, false);
337 int ndregs_consec = saveall ? 8 : n_dregs_to_save (is_inthandler, true);
338 int npregs_consec = saveall ? 6 : n_pregs_to_save (is_inthandler, true);
339 int dregno, pregno;
340 int total_consec = ndregs_consec + npregs_consec;
341 int i, d_to_save;
343 if (saveall || is_inthandler)
345 rtx_insn *insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
347 RTX_FRAME_RELATED_P (insn) = 1;
348 for (dregno = REG_LT0; dregno <= REG_LB1; dregno++)
349 if (! crtl->is_leaf
350 || cfun->machine->has_hardware_loops
351 || cfun->machine->has_loopreg_clobber
352 || (ENABLE_WA_05000257
353 && (dregno == REG_LC0 || dregno == REG_LC1)))
355 insn = emit_move_insn (predec, gen_rtx_REG (SImode, dregno));
356 RTX_FRAME_RELATED_P (insn) = 1;
360 if (total_consec != 0)
362 rtx_insn *insn;
363 rtx val = GEN_INT (-total_consec * 4);
364 rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_consec + 2));
366 XVECEXP (pat, 0, 0) = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, val),
367 UNSPEC_PUSH_MULTIPLE);
368 XVECEXP (pat, 0, total_consec + 1) = gen_rtx_SET (spreg,
369 gen_rtx_PLUS (Pmode,
370 spreg,
371 val));
372 RTX_FRAME_RELATED_P (XVECEXP (pat, 0, total_consec + 1)) = 1;
373 d_to_save = ndregs_consec;
374 dregno = REG_R7 + 1 - ndregs_consec;
375 pregno = REG_P5 + 1 - npregs_consec;
376 for (i = 0; i < total_consec; i++)
378 rtx memref = gen_rtx_MEM (word_mode,
379 gen_rtx_PLUS (Pmode, spreg,
380 GEN_INT (- i * 4 - 4)));
381 rtx subpat;
382 if (d_to_save > 0)
384 subpat = gen_rtx_SET (memref, gen_rtx_REG (word_mode, dregno++));
385 d_to_save--;
387 else
389 subpat = gen_rtx_SET (memref, gen_rtx_REG (word_mode, pregno++));
391 XVECEXP (pat, 0, i + 1) = subpat;
392 RTX_FRAME_RELATED_P (subpat) = 1;
394 insn = emit_insn (pat);
395 RTX_FRAME_RELATED_P (insn) = 1;
398 for (dregno = REG_R0; ndregs != ndregs_consec; dregno++)
400 if (must_save_p (is_inthandler, dregno))
402 rtx_insn *insn =
403 emit_move_insn (predec, gen_rtx_REG (word_mode, dregno));
404 RTX_FRAME_RELATED_P (insn) = 1;
405 ndregs--;
408 for (pregno = REG_P0; npregs != npregs_consec; pregno++)
410 if (must_save_p (is_inthandler, pregno))
412 rtx_insn *insn =
413 emit_move_insn (predec, gen_rtx_REG (word_mode, pregno));
414 RTX_FRAME_RELATED_P (insn) = 1;
415 npregs--;
418 for (i = REG_P7 + 1; i < REG_CC; i++)
419 if (saveall
420 || (is_inthandler
421 && (df_regs_ever_live_p (i)
422 || (!leaf_function_p () && call_used_regs[i]))))
424 rtx_insn *insn;
425 if (i == REG_A0 || i == REG_A1)
426 insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1),
427 gen_rtx_REG (PDImode, i));
428 else
429 insn = emit_move_insn (predec, gen_rtx_REG (SImode, i));
430 RTX_FRAME_RELATED_P (insn) = 1;
434 /* Emit code to restore registers in the epilogue. SAVEALL is nonzero if we
435 must save all registers; this is used for interrupt handlers.
436 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
437 this for an interrupt (or exception) handler. */
439 static void
440 expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler)
442 rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
443 rtx postinc = gen_rtx_MEM (SImode, postinc1);
445 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler, false);
446 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler, false);
447 int ndregs_consec = saveall ? 8 : n_dregs_to_save (is_inthandler, true);
448 int npregs_consec = saveall ? 6 : n_pregs_to_save (is_inthandler, true);
449 int total_consec = ndregs_consec + npregs_consec;
450 int i, regno;
451 rtx_insn *insn;
453 /* A slightly crude technique to stop flow from trying to delete "dead"
454 insns. */
455 MEM_VOLATILE_P (postinc) = 1;
457 for (i = REG_CC - 1; i > REG_P7; i--)
458 if (saveall
459 || (is_inthandler
460 && (df_regs_ever_live_p (i)
461 || (!leaf_function_p () && call_used_regs[i]))))
463 if (i == REG_A0 || i == REG_A1)
465 rtx mem = gen_rtx_MEM (PDImode, postinc1);
466 MEM_VOLATILE_P (mem) = 1;
467 emit_move_insn (gen_rtx_REG (PDImode, i), mem);
469 else
470 emit_move_insn (gen_rtx_REG (SImode, i), postinc);
473 regno = REG_P5 - npregs_consec;
474 for (; npregs != npregs_consec; regno--)
476 if (must_save_p (is_inthandler, regno))
478 emit_move_insn (gen_rtx_REG (word_mode, regno), postinc);
479 npregs--;
482 regno = REG_R7 - ndregs_consec;
483 for (; ndregs != ndregs_consec; regno--)
485 if (must_save_p (is_inthandler, regno))
487 emit_move_insn (gen_rtx_REG (word_mode, regno), postinc);
488 ndregs--;
492 if (total_consec != 0)
494 rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_consec + 1));
495 XVECEXP (pat, 0, 0)
496 = gen_rtx_SET (spreg, gen_rtx_PLUS (Pmode, spreg,
497 GEN_INT (total_consec * 4)));
499 if (npregs_consec > 0)
500 regno = REG_P5 + 1;
501 else
502 regno = REG_R7 + 1;
504 for (i = 0; i < total_consec; i++)
506 rtx addr = (i > 0
507 ? gen_rtx_PLUS (Pmode, spreg, GEN_INT (i * 4))
508 : spreg);
509 rtx memref = gen_rtx_MEM (word_mode, addr);
511 regno--;
512 XVECEXP (pat, 0, i + 1)
513 = gen_rtx_SET (gen_rtx_REG (word_mode, regno), memref);
515 if (npregs_consec > 0)
517 if (--npregs_consec == 0)
518 regno = REG_R7 + 1;
522 insn = emit_insn (pat);
523 RTX_FRAME_RELATED_P (insn) = 1;
525 if (saveall || is_inthandler)
527 for (regno = REG_LB1; regno >= REG_LT0; regno--)
528 if (! crtl->is_leaf
529 || cfun->machine->has_hardware_loops
530 || cfun->machine->has_loopreg_clobber
531 || (ENABLE_WA_05000257 && (regno == REG_LC0 || regno == REG_LC1)))
532 emit_move_insn (gen_rtx_REG (SImode, regno), postinc);
534 emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
538 /* Perform any needed actions needed for a function that is receiving a
539 variable number of arguments.
541 CUM is as above.
543 MODE and TYPE are the mode and type of the current parameter.
545 PRETEND_SIZE is a variable that should be set to the amount of stack
546 that must be pushed by the prolog to pretend that our caller pushed
549 Normally, this macro will push all remaining incoming registers on the
550 stack and set PRETEND_SIZE to the length of the registers pushed.
552 Blackfin specific :
553 - VDSP C compiler manual (our ABI) says that a variable args function
554 should save the R0, R1 and R2 registers in the stack.
555 - The caller will always leave space on the stack for the
556 arguments that are passed in registers, so we dont have
557 to leave any extra space.
558 - now, the vastart pointer can access all arguments from the stack. */
560 static void
561 setup_incoming_varargs (cumulative_args_t cum,
562 machine_mode mode ATTRIBUTE_UNUSED,
563 tree type ATTRIBUTE_UNUSED, int *pretend_size,
564 int no_rtl)
566 rtx mem;
567 int i;
569 if (no_rtl)
570 return;
572 /* The move for named arguments will be generated automatically by the
573 compiler. We need to generate the move rtx for the unnamed arguments
574 if they are in the first 3 words. We assume at least 1 named argument
575 exists, so we never generate [ARGP] = R0 here. */
577 for (i = get_cumulative_args (cum)->words + 1; i < max_arg_registers; i++)
579 mem = gen_rtx_MEM (Pmode,
580 plus_constant (Pmode, arg_pointer_rtx,
581 (i * UNITS_PER_WORD)));
582 emit_move_insn (mem, gen_rtx_REG (Pmode, i));
585 *pretend_size = 0;
588 /* Value should be nonzero if functions must have frame pointers.
589 Zero means the frame pointer need not be set up (and parms may
590 be accessed via the stack pointer) in functions that seem suitable. */
592 static bool
593 bfin_frame_pointer_required (void)
595 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
597 if (fkind != SUBROUTINE)
598 return true;
600 /* We turn on -fomit-frame-pointer if -momit-leaf-frame-pointer is used,
601 so we have to override it for non-leaf functions. */
602 if (TARGET_OMIT_LEAF_FRAME_POINTER && ! crtl->is_leaf)
603 return true;
605 return false;
608 /* Return the number of registers pushed during the prologue. */
610 static int
611 n_regs_saved_by_prologue (void)
613 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
614 bool is_inthandler = fkind != SUBROUTINE;
615 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
616 bool all = (lookup_attribute ("saveall", attrs) != NULL_TREE
617 || (is_inthandler && !crtl->is_leaf));
618 int ndregs = all ? 8 : n_dregs_to_save (is_inthandler, false);
619 int npregs = all ? 6 : n_pregs_to_save (is_inthandler, false);
620 int n = ndregs + npregs;
621 int i;
623 if (all || stack_frame_needed_p ())
624 n += 2;
625 else
627 if (must_save_fp_p ())
628 n++;
629 if (must_save_rets_p ())
630 n++;
633 if (fkind != SUBROUTINE || all)
635 /* Increment once for ASTAT. */
636 n++;
637 if (! crtl->is_leaf
638 || cfun->machine->has_hardware_loops
639 || cfun->machine->has_loopreg_clobber)
641 n += 6;
645 if (fkind != SUBROUTINE)
647 /* RETE/X/N. */
648 if (lookup_attribute ("nesting", attrs))
649 n++;
652 for (i = REG_P7 + 1; i < REG_CC; i++)
653 if (all
654 || (fkind != SUBROUTINE
655 && (df_regs_ever_live_p (i)
656 || (!leaf_function_p () && call_used_regs[i]))))
657 n += i == REG_A0 || i == REG_A1 ? 2 : 1;
659 return n;
662 /* Given FROM and TO register numbers, say whether this elimination is
663 allowed. Frame pointer elimination is automatically handled.
665 All other eliminations are valid. */
667 static bool
668 bfin_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
670 return (to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true);
673 /* Return the offset between two registers, one to be eliminated, and the other
674 its replacement, at the start of a routine. */
676 HOST_WIDE_INT
677 bfin_initial_elimination_offset (int from, int to)
679 HOST_WIDE_INT offset = 0;
681 if (from == ARG_POINTER_REGNUM)
682 offset = n_regs_saved_by_prologue () * 4;
684 if (to == STACK_POINTER_REGNUM)
686 if (crtl->outgoing_args_size >= FIXED_STACK_AREA)
687 offset += crtl->outgoing_args_size;
688 else if (crtl->outgoing_args_size)
689 offset += FIXED_STACK_AREA;
691 offset += get_frame_size ();
694 return offset;
697 /* Emit code to load a constant CONSTANT into register REG; setting
698 RTX_FRAME_RELATED_P on all insns we generate if RELATED is true.
699 Make sure that the insns we generate need not be split. */
701 static void
702 frame_related_constant_load (rtx reg, HOST_WIDE_INT constant, bool related)
704 rtx_insn *insn;
705 rtx cst = GEN_INT (constant);
707 if (constant >= -32768 && constant < 65536)
708 insn = emit_move_insn (reg, cst);
709 else
711 /* We don't call split_load_immediate here, since dwarf2out.c can get
712 confused about some of the more clever sequences it can generate. */
713 insn = emit_insn (gen_movsi_high (reg, cst));
714 if (related)
715 RTX_FRAME_RELATED_P (insn) = 1;
716 insn = emit_insn (gen_movsi_low (reg, reg, cst));
718 if (related)
719 RTX_FRAME_RELATED_P (insn) = 1;
722 /* Generate efficient code to add a value to a P register.
723 Set RTX_FRAME_RELATED_P on the generated insns if FRAME is nonzero.
724 EPILOGUE_P is zero if this function is called for prologue,
725 otherwise it's nonzero. And it's less than zero if this is for
726 sibcall epilogue. */
728 static void
729 add_to_reg (rtx reg, HOST_WIDE_INT value, int frame, int epilogue_p)
731 if (value == 0)
732 return;
734 /* Choose whether to use a sequence using a temporary register, or
735 a sequence with multiple adds. We can add a signed 7-bit value
736 in one instruction. */
737 if (value > 120 || value < -120)
739 rtx tmpreg;
740 rtx tmpreg2;
741 rtx_insn *insn;
743 tmpreg2 = NULL_RTX;
745 /* For prologue or normal epilogue, P1 can be safely used
746 as the temporary register. For sibcall epilogue, we try to find
747 a call used P register, which will be restored in epilogue.
748 If we cannot find such a P register, we have to use one I register
749 to help us. */
751 if (epilogue_p >= 0)
752 tmpreg = gen_rtx_REG (SImode, REG_P1);
753 else
755 int i;
756 for (i = REG_P0; i <= REG_P5; i++)
757 if ((df_regs_ever_live_p (i) && ! call_used_regs[i])
758 || (!TARGET_FDPIC
759 && i == PIC_OFFSET_TABLE_REGNUM
760 && (crtl->uses_pic_offset_table
761 || (TARGET_ID_SHARED_LIBRARY
762 && ! crtl->is_leaf))))
763 break;
764 if (i <= REG_P5)
765 tmpreg = gen_rtx_REG (SImode, i);
766 else
768 tmpreg = gen_rtx_REG (SImode, REG_P1);
769 tmpreg2 = gen_rtx_REG (SImode, REG_I0);
770 emit_move_insn (tmpreg2, tmpreg);
774 if (frame)
775 frame_related_constant_load (tmpreg, value, TRUE);
776 else
777 insn = emit_move_insn (tmpreg, GEN_INT (value));
779 insn = emit_insn (gen_addsi3 (reg, reg, tmpreg));
780 if (frame)
781 RTX_FRAME_RELATED_P (insn) = 1;
783 if (tmpreg2 != NULL_RTX)
784 emit_move_insn (tmpreg, tmpreg2);
786 else
789 int size = value;
790 rtx_insn *insn;
792 if (size > 60)
793 size = 60;
794 else if (size < -60)
795 /* We could use -62, but that would leave the stack unaligned, so
796 it's no good. */
797 size = -60;
799 insn = emit_insn (gen_addsi3 (reg, reg, GEN_INT (size)));
800 if (frame)
801 RTX_FRAME_RELATED_P (insn) = 1;
802 value -= size;
804 while (value != 0);
807 /* Generate a LINK insn for a frame sized FRAME_SIZE. If this constant
808 is too large, generate a sequence of insns that has the same effect.
809 SPREG contains (reg:SI REG_SP). */
811 static void
812 emit_link_insn (rtx spreg, HOST_WIDE_INT frame_size)
814 HOST_WIDE_INT link_size = frame_size;
815 rtx_insn *insn;
816 int i;
818 if (link_size > 262140)
819 link_size = 262140;
821 /* Use a LINK insn with as big a constant as possible, then subtract
822 any remaining size from the SP. */
823 insn = emit_insn (gen_link (GEN_INT (-8 - link_size)));
824 RTX_FRAME_RELATED_P (insn) = 1;
826 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
828 rtx set = XVECEXP (PATTERN (insn), 0, i);
829 gcc_assert (GET_CODE (set) == SET);
830 RTX_FRAME_RELATED_P (set) = 1;
833 frame_size -= link_size;
835 if (frame_size > 0)
837 /* Must use a call-clobbered PREG that isn't the static chain. */
838 rtx tmpreg = gen_rtx_REG (Pmode, REG_P1);
840 frame_related_constant_load (tmpreg, -frame_size, TRUE);
841 insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg));
842 RTX_FRAME_RELATED_P (insn) = 1;
846 /* Return the number of bytes we must reserve for outgoing arguments
847 in the current function's stack frame. */
849 static HOST_WIDE_INT
850 arg_area_size (void)
852 if (crtl->outgoing_args_size)
854 if (crtl->outgoing_args_size >= FIXED_STACK_AREA)
855 return crtl->outgoing_args_size;
856 else
857 return FIXED_STACK_AREA;
859 return 0;
862 /* Save RETS and FP, and allocate a stack frame. ALL is true if the
863 function must save all its registers (true only for certain interrupt
864 handlers). */
866 static void
867 do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all)
869 frame_size += arg_area_size ();
871 if (all
872 || stack_frame_needed_p ()
873 || (must_save_rets_p () && must_save_fp_p ()))
874 emit_link_insn (spreg, frame_size);
875 else
877 if (must_save_rets_p ())
879 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
880 gen_rtx_PRE_DEC (Pmode, spreg)),
881 bfin_rets_rtx);
882 rtx_insn *insn = emit_insn (pat);
883 RTX_FRAME_RELATED_P (insn) = 1;
885 if (must_save_fp_p ())
887 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
888 gen_rtx_PRE_DEC (Pmode, spreg)),
889 gen_rtx_REG (Pmode, REG_FP));
890 rtx_insn *insn = emit_insn (pat);
891 RTX_FRAME_RELATED_P (insn) = 1;
893 add_to_reg (spreg, -frame_size, 1, 0);
897 /* Like do_link, but used for epilogues to deallocate the stack frame.
898 EPILOGUE_P is zero if this function is called for prologue,
899 otherwise it's nonzero. And it's less than zero if this is for
900 sibcall epilogue. */
902 static void
903 do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all, int epilogue_p)
905 frame_size += arg_area_size ();
907 if (stack_frame_needed_p ())
908 emit_insn (gen_unlink ());
909 else
911 rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg));
913 add_to_reg (spreg, frame_size, 0, epilogue_p);
914 if (all || must_save_fp_p ())
916 rtx fpreg = gen_rtx_REG (Pmode, REG_FP);
917 emit_move_insn (fpreg, postinc);
918 emit_use (fpreg);
920 if (all || must_save_rets_p ())
922 emit_move_insn (bfin_rets_rtx, postinc);
923 emit_use (bfin_rets_rtx);
928 /* Generate a prologue suitable for a function of kind FKIND. This is
929 called for interrupt and exception handler prologues.
930 SPREG contains (reg:SI REG_SP). */
932 static void
933 expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind, bool all)
935 HOST_WIDE_INT frame_size = get_frame_size ();
936 rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
937 rtx predec = gen_rtx_MEM (SImode, predec1);
938 rtx_insn *insn;
939 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
940 tree kspisusp = lookup_attribute ("kspisusp", attrs);
942 if (kspisusp)
944 insn = emit_move_insn (spreg, gen_rtx_REG (Pmode, REG_USP));
945 RTX_FRAME_RELATED_P (insn) = 1;
948 /* We need space on the stack in case we need to save the argument
949 registers. */
950 if (fkind == EXCPT_HANDLER)
952 insn = emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (-12)));
953 RTX_FRAME_RELATED_P (insn) = 1;
956 /* If we're calling other functions, they won't save their call-clobbered
957 registers, so we must save everything here. */
958 if (!crtl->is_leaf)
959 all = true;
960 expand_prologue_reg_save (spreg, all, true);
962 if (ENABLE_WA_05000283 || ENABLE_WA_05000315)
964 rtx chipid = GEN_INT (trunc_int_for_mode (0xFFC00014, SImode));
965 rtx p5reg = gen_rtx_REG (Pmode, REG_P5);
966 emit_insn (gen_movbi (bfin_cc_rtx, const1_rtx));
967 emit_insn (gen_movsi_high (p5reg, chipid));
968 emit_insn (gen_movsi_low (p5reg, p5reg, chipid));
969 emit_insn (gen_dummy_load (p5reg, bfin_cc_rtx));
972 if (lookup_attribute ("nesting", attrs))
974 rtx srcreg = gen_rtx_REG (Pmode, ret_regs[fkind]);
975 insn = emit_move_insn (predec, srcreg);
976 RTX_FRAME_RELATED_P (insn) = 1;
979 do_link (spreg, frame_size, all);
981 if (fkind == EXCPT_HANDLER)
983 rtx r0reg = gen_rtx_REG (SImode, REG_R0);
984 rtx r1reg = gen_rtx_REG (SImode, REG_R1);
985 rtx r2reg = gen_rtx_REG (SImode, REG_R2);
987 emit_move_insn (r0reg, gen_rtx_REG (SImode, REG_SEQSTAT));
988 emit_insn (gen_ashrsi3 (r0reg, r0reg, GEN_INT (26)));
989 emit_insn (gen_ashlsi3 (r0reg, r0reg, GEN_INT (26)));
990 emit_move_insn (r1reg, spreg);
991 emit_move_insn (r2reg, gen_rtx_REG (Pmode, REG_FP));
992 emit_insn (gen_addsi3 (r2reg, r2reg, GEN_INT (8)));
996 /* Generate an epilogue suitable for a function of kind FKIND. This is
997 called for interrupt and exception handler epilogues.
998 SPREG contains (reg:SI REG_SP). */
1000 static void
1001 expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind, bool all)
1003 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1004 rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
1005 rtx postinc = gen_rtx_MEM (SImode, postinc1);
1007 /* A slightly crude technique to stop flow from trying to delete "dead"
1008 insns. */
1009 MEM_VOLATILE_P (postinc) = 1;
1011 do_unlink (spreg, get_frame_size (), all, 1);
1013 if (lookup_attribute ("nesting", attrs))
1015 rtx srcreg = gen_rtx_REG (Pmode, ret_regs[fkind]);
1016 emit_move_insn (srcreg, postinc);
1019 /* If we're calling other functions, they won't save their call-clobbered
1020 registers, so we must save (and restore) everything here. */
1021 if (!crtl->is_leaf)
1022 all = true;
1024 expand_epilogue_reg_restore (spreg, all, true);
1026 /* Deallocate any space we left on the stack in case we needed to save the
1027 argument registers. */
1028 if (fkind == EXCPT_HANDLER)
1029 emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (12)));
1031 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, ret_regs[fkind])));
1034 /* Used while emitting the prologue to generate code to load the correct value
1035 into the PIC register, which is passed in DEST. */
1037 static rtx
1038 bfin_load_pic_reg (rtx dest)
1040 struct cgraph_local_info *i = NULL;
1041 rtx addr;
1043 i = cgraph_node::local_info (current_function_decl);
1045 /* Functions local to the translation unit don't need to reload the
1046 pic reg, since the caller always passes a usable one. */
1047 if (i && i->local)
1048 return pic_offset_table_rtx;
1050 if (global_options_set.x_bfin_library_id)
1051 addr = plus_constant (Pmode, pic_offset_table_rtx,
1052 -4 - bfin_library_id * 4);
1053 else
1054 addr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
1055 gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
1056 UNSPEC_LIBRARY_OFFSET));
1057 emit_insn (gen_movsi (dest, gen_rtx_MEM (Pmode, addr)));
1058 return dest;
1061 /* Generate RTL for the prologue of the current function. */
1063 void
1064 bfin_expand_prologue (void)
1066 HOST_WIDE_INT frame_size = get_frame_size ();
1067 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
1068 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1069 rtx pic_reg_loaded = NULL_RTX;
1070 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1071 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
1073 if (flag_stack_usage_info)
1074 current_function_static_stack_size = frame_size;
1076 if (fkind != SUBROUTINE)
1078 expand_interrupt_handler_prologue (spreg, fkind, all);
1079 return;
1082 if (crtl->limit_stack
1083 || (TARGET_STACK_CHECK_L1
1084 && !DECL_NO_LIMIT_STACK (current_function_decl)))
1086 HOST_WIDE_INT offset
1087 = bfin_initial_elimination_offset (ARG_POINTER_REGNUM,
1088 STACK_POINTER_REGNUM);
1089 rtx lim = crtl->limit_stack ? stack_limit_rtx : NULL_RTX;
1090 rtx tmp = gen_rtx_REG (Pmode, REG_R3);
1091 rtx p2reg = gen_rtx_REG (Pmode, REG_P2);
1093 emit_move_insn (tmp, p2reg);
1094 if (!lim)
1096 emit_move_insn (p2reg, gen_int_mode (0xFFB00000, SImode));
1097 emit_move_insn (p2reg, gen_rtx_MEM (Pmode, p2reg));
1098 lim = p2reg;
1100 if (GET_CODE (lim) == SYMBOL_REF)
1102 if (TARGET_ID_SHARED_LIBRARY)
1104 rtx p1reg = gen_rtx_REG (Pmode, REG_P1);
1105 rtx val;
1106 pic_reg_loaded = bfin_load_pic_reg (p2reg);
1107 val = legitimize_pic_address (stack_limit_rtx, p1reg,
1108 pic_reg_loaded);
1109 emit_move_insn (p1reg, val);
1110 frame_related_constant_load (p2reg, offset, FALSE);
1111 emit_insn (gen_addsi3 (p2reg, p2reg, p1reg));
1112 lim = p2reg;
1114 else
1116 rtx limit = plus_constant (Pmode, lim, offset);
1117 emit_move_insn (p2reg, limit);
1118 lim = p2reg;
1121 else
1123 if (lim != p2reg)
1124 emit_move_insn (p2reg, lim);
1125 add_to_reg (p2reg, offset, 0, 0);
1126 lim = p2reg;
1128 emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim));
1129 emit_insn (gen_trapifcc ());
1130 emit_move_insn (p2reg, tmp);
1132 expand_prologue_reg_save (spreg, all, false);
1134 do_link (spreg, frame_size, all);
1136 if (TARGET_ID_SHARED_LIBRARY
1137 && !TARGET_SEP_DATA
1138 && (crtl->uses_pic_offset_table
1139 || !crtl->is_leaf))
1140 bfin_load_pic_reg (pic_offset_table_rtx);
1143 /* Generate RTL for the epilogue of the current function. NEED_RETURN is zero
1144 if this is for a sibcall. EH_RETURN is nonzero if we're expanding an
1145 eh_return pattern. SIBCALL_P is true if this is a sibcall epilogue,
1146 false otherwise. */
1148 void
1149 bfin_expand_epilogue (int need_return, int eh_return, bool sibcall_p)
1151 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
1152 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1153 int e = sibcall_p ? -1 : 1;
1154 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1155 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
1157 if (fkind != SUBROUTINE)
1159 expand_interrupt_handler_epilogue (spreg, fkind, all);
1160 return;
1163 do_unlink (spreg, get_frame_size (), all, e);
1165 expand_epilogue_reg_restore (spreg, all, false);
1167 /* Omit the return insn if this is for a sibcall. */
1168 if (! need_return)
1169 return;
1171 if (eh_return)
1172 emit_insn (gen_addsi3 (spreg, spreg, gen_rtx_REG (Pmode, REG_P2)));
1174 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, REG_RETS)));
1177 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
1180 bfin_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
1181 unsigned int new_reg)
1183 /* Interrupt functions can only use registers that have already been
1184 saved by the prologue, even if they would normally be
1185 call-clobbered. */
1187 if (funkind (TREE_TYPE (current_function_decl)) != SUBROUTINE
1188 && !df_regs_ever_live_p (new_reg))
1189 return 0;
1191 return 1;
1194 /* Implement TARGET_EXTRA_LIVE_ON_ENTRY. */
1195 static void
1196 bfin_extra_live_on_entry (bitmap regs)
1198 if (TARGET_FDPIC)
1199 bitmap_set_bit (regs, FDPIC_REGNO);
1202 /* Return the value of the return address for the frame COUNT steps up
1203 from the current frame, after the prologue.
1204 We punt for everything but the current frame by returning const0_rtx. */
1207 bfin_return_addr_rtx (int count)
1209 if (count != 0)
1210 return const0_rtx;
1212 return get_hard_reg_initial_val (Pmode, REG_RETS);
1215 static rtx
1216 bfin_delegitimize_address (rtx orig_x)
1218 rtx x = orig_x;
1220 if (GET_CODE (x) != MEM)
1221 return orig_x;
1223 x = XEXP (x, 0);
1224 if (GET_CODE (x) == PLUS
1225 && GET_CODE (XEXP (x, 1)) == UNSPEC
1226 && XINT (XEXP (x, 1), 1) == UNSPEC_MOVE_PIC
1227 && GET_CODE (XEXP (x, 0)) == REG
1228 && REGNO (XEXP (x, 0)) == PIC_OFFSET_TABLE_REGNUM)
1229 return XVECEXP (XEXP (x, 1), 0, 0);
1231 return orig_x;
1234 /* This predicate is used to compute the length of a load/store insn.
1235 OP is a MEM rtx, we return nonzero if its addressing mode requires a
1236 32-bit instruction. */
1239 effective_address_32bit_p (rtx op, machine_mode mode)
1241 HOST_WIDE_INT offset;
1243 mode = GET_MODE (op);
1244 op = XEXP (op, 0);
1246 if (GET_CODE (op) != PLUS)
1248 gcc_assert (REG_P (op) || GET_CODE (op) == POST_INC
1249 || GET_CODE (op) == PRE_DEC || GET_CODE (op) == POST_DEC);
1250 return 0;
1253 if (GET_CODE (XEXP (op, 1)) == UNSPEC)
1254 return 1;
1256 offset = INTVAL (XEXP (op, 1));
1258 /* All byte loads use a 16-bit offset. */
1259 if (GET_MODE_SIZE (mode) == 1)
1260 return 1;
1262 if (GET_MODE_SIZE (mode) == 4)
1264 /* Frame pointer relative loads can use a negative offset, all others
1265 are restricted to a small positive one. */
1266 if (XEXP (op, 0) == frame_pointer_rtx)
1267 return offset < -128 || offset > 60;
1268 return offset < 0 || offset > 60;
1271 /* Must be HImode now. */
1272 return offset < 0 || offset > 30;
1275 /* Returns true if X is a memory reference using an I register. */
1276 bool
1277 bfin_dsp_memref_p (rtx x)
1279 if (! MEM_P (x))
1280 return false;
1281 x = XEXP (x, 0);
1282 if (GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_INC
1283 || GET_CODE (x) == POST_DEC || GET_CODE (x) == PRE_DEC)
1284 x = XEXP (x, 0);
1285 return IREG_P (x);
1288 /* Return cost of the memory address ADDR.
1289 All addressing modes are equally cheap on the Blackfin. */
1291 static int
1292 bfin_address_cost (rtx addr ATTRIBUTE_UNUSED,
1293 machine_mode mode ATTRIBUTE_UNUSED,
1294 addr_space_t as ATTRIBUTE_UNUSED,
1295 bool speed ATTRIBUTE_UNUSED)
1297 return 1;
1300 /* Subroutine of print_operand; used to print a memory reference X to FILE. */
1302 void
1303 print_address_operand (FILE *file, rtx x)
1305 switch (GET_CODE (x))
1307 case PLUS:
1308 output_address (VOIDmode, XEXP (x, 0));
1309 fprintf (file, "+");
1310 output_address (VOIDmode, XEXP (x, 1));
1311 break;
1313 case PRE_DEC:
1314 fprintf (file, "--");
1315 output_address (VOIDmode, XEXP (x, 0));
1316 break;
1317 case POST_INC:
1318 output_address (VOIDmode, XEXP (x, 0));
1319 fprintf (file, "++");
1320 break;
1321 case POST_DEC:
1322 output_address (VOIDmode, XEXP (x, 0));
1323 fprintf (file, "--");
1324 break;
1326 default:
1327 gcc_assert (GET_CODE (x) != MEM);
1328 print_operand (file, x, 0);
1329 break;
1333 /* Adding intp DImode support by Tony
1334 * -- Q: (low word)
1335 * -- R: (high word)
1338 void
1339 print_operand (FILE *file, rtx x, char code)
1341 machine_mode mode;
1343 if (code == '!')
1345 if (GET_MODE (current_output_insn) == SImode)
1346 fprintf (file, " ||");
1347 else
1348 fprintf (file, ";");
1349 return;
1352 mode = GET_MODE (x);
1354 switch (code)
1356 case 'j':
1357 switch (GET_CODE (x))
1359 case EQ:
1360 fprintf (file, "e");
1361 break;
1362 case NE:
1363 fprintf (file, "ne");
1364 break;
1365 case GT:
1366 fprintf (file, "g");
1367 break;
1368 case LT:
1369 fprintf (file, "l");
1370 break;
1371 case GE:
1372 fprintf (file, "ge");
1373 break;
1374 case LE:
1375 fprintf (file, "le");
1376 break;
1377 case GTU:
1378 fprintf (file, "g");
1379 break;
1380 case LTU:
1381 fprintf (file, "l");
1382 break;
1383 case GEU:
1384 fprintf (file, "ge");
1385 break;
1386 case LEU:
1387 fprintf (file, "le");
1388 break;
1389 default:
1390 output_operand_lossage ("invalid %%j value");
1392 break;
1394 case 'J': /* reverse logic */
1395 switch (GET_CODE(x))
1397 case EQ:
1398 fprintf (file, "ne");
1399 break;
1400 case NE:
1401 fprintf (file, "e");
1402 break;
1403 case GT:
1404 fprintf (file, "le");
1405 break;
1406 case LT:
1407 fprintf (file, "ge");
1408 break;
1409 case GE:
1410 fprintf (file, "l");
1411 break;
1412 case LE:
1413 fprintf (file, "g");
1414 break;
1415 case GTU:
1416 fprintf (file, "le");
1417 break;
1418 case LTU:
1419 fprintf (file, "ge");
1420 break;
1421 case GEU:
1422 fprintf (file, "l");
1423 break;
1424 case LEU:
1425 fprintf (file, "g");
1426 break;
1427 default:
1428 output_operand_lossage ("invalid %%J value");
1430 break;
1432 default:
1433 switch (GET_CODE (x))
1435 case REG:
1436 if (code == 'h')
1438 if (REGNO (x) < 32)
1439 fprintf (file, "%s", short_reg_names[REGNO (x)]);
1440 else
1441 output_operand_lossage ("invalid operand for code '%c'", code);
1443 else if (code == 'd')
1445 if (REGNO (x) < 32)
1446 fprintf (file, "%s", high_reg_names[REGNO (x)]);
1447 else
1448 output_operand_lossage ("invalid operand for code '%c'", code);
1450 else if (code == 'w')
1452 if (REGNO (x) == REG_A0 || REGNO (x) == REG_A1)
1453 fprintf (file, "%s.w", reg_names[REGNO (x)]);
1454 else
1455 output_operand_lossage ("invalid operand for code '%c'", code);
1457 else if (code == 'x')
1459 if (REGNO (x) == REG_A0 || REGNO (x) == REG_A1)
1460 fprintf (file, "%s.x", reg_names[REGNO (x)]);
1461 else
1462 output_operand_lossage ("invalid operand for code '%c'", code);
1464 else if (code == 'v')
1466 if (REGNO (x) == REG_A0)
1467 fprintf (file, "AV0");
1468 else if (REGNO (x) == REG_A1)
1469 fprintf (file, "AV1");
1470 else
1471 output_operand_lossage ("invalid operand for code '%c'", code);
1473 else if (code == 'D')
1475 if (D_REGNO_P (REGNO (x)))
1476 fprintf (file, "%s", dregs_pair_names[REGNO (x)]);
1477 else
1478 output_operand_lossage ("invalid operand for code '%c'", code);
1480 else if (code == 'H')
1482 if ((mode == DImode || mode == DFmode) && REG_P (x))
1483 fprintf (file, "%s", reg_names[REGNO (x) + 1]);
1484 else
1485 output_operand_lossage ("invalid operand for code '%c'", code);
1487 else if (code == 'T')
1489 if (D_REGNO_P (REGNO (x)))
1490 fprintf (file, "%s", byte_reg_names[REGNO (x)]);
1491 else
1492 output_operand_lossage ("invalid operand for code '%c'", code);
1494 else
1495 fprintf (file, "%s", reg_names[REGNO (x)]);
1496 break;
1498 case MEM:
1499 fputc ('[', file);
1500 x = XEXP (x,0);
1501 print_address_operand (file, x);
1502 fputc (']', file);
1503 break;
1505 case CONST_INT:
1506 if (code == 'M')
1508 switch (INTVAL (x))
1510 case MACFLAG_NONE:
1511 break;
1512 case MACFLAG_FU:
1513 fputs ("(FU)", file);
1514 break;
1515 case MACFLAG_T:
1516 fputs ("(T)", file);
1517 break;
1518 case MACFLAG_TFU:
1519 fputs ("(TFU)", file);
1520 break;
1521 case MACFLAG_W32:
1522 fputs ("(W32)", file);
1523 break;
1524 case MACFLAG_IS:
1525 fputs ("(IS)", file);
1526 break;
1527 case MACFLAG_IU:
1528 fputs ("(IU)", file);
1529 break;
1530 case MACFLAG_IH:
1531 fputs ("(IH)", file);
1532 break;
1533 case MACFLAG_M:
1534 fputs ("(M)", file);
1535 break;
1536 case MACFLAG_IS_M:
1537 fputs ("(IS,M)", file);
1538 break;
1539 case MACFLAG_ISS2:
1540 fputs ("(ISS2)", file);
1541 break;
1542 case MACFLAG_S2RND:
1543 fputs ("(S2RND)", file);
1544 break;
1545 default:
1546 gcc_unreachable ();
1548 break;
1550 else if (code == 'b')
1552 if (INTVAL (x) == 0)
1553 fputs ("+=", file);
1554 else if (INTVAL (x) == 1)
1555 fputs ("-=", file);
1556 else
1557 gcc_unreachable ();
1558 break;
1560 /* Moves to half registers with d or h modifiers always use unsigned
1561 constants. */
1562 else if (code == 'd')
1563 x = GEN_INT ((INTVAL (x) >> 16) & 0xffff);
1564 else if (code == 'h')
1565 x = GEN_INT (INTVAL (x) & 0xffff);
1566 else if (code == 'N')
1567 x = GEN_INT (-INTVAL (x));
1568 else if (code == 'X')
1569 x = GEN_INT (exact_log2 (0xffffffff & INTVAL (x)));
1570 else if (code == 'Y')
1571 x = GEN_INT (exact_log2 (0xffffffff & ~INTVAL (x)));
1572 else if (code == 'Z')
1573 /* Used for LINK insns. */
1574 x = GEN_INT (-8 - INTVAL (x));
1576 /* fall through */
1578 case SYMBOL_REF:
1579 output_addr_const (file, x);
1580 break;
1582 case CONST_DOUBLE:
1583 output_operand_lossage ("invalid const_double operand");
1584 break;
1586 case UNSPEC:
1587 switch (XINT (x, 1))
1589 case UNSPEC_MOVE_PIC:
1590 output_addr_const (file, XVECEXP (x, 0, 0));
1591 fprintf (file, "@GOT");
1592 break;
1594 case UNSPEC_MOVE_FDPIC:
1595 output_addr_const (file, XVECEXP (x, 0, 0));
1596 fprintf (file, "@GOT17M4");
1597 break;
1599 case UNSPEC_FUNCDESC_GOT17M4:
1600 output_addr_const (file, XVECEXP (x, 0, 0));
1601 fprintf (file, "@FUNCDESC_GOT17M4");
1602 break;
1604 case UNSPEC_LIBRARY_OFFSET:
1605 fprintf (file, "_current_shared_library_p5_offset_");
1606 break;
1608 default:
1609 gcc_unreachable ();
1611 break;
1613 default:
1614 output_addr_const (file, x);
1619 /* Argument support functions. */
1621 /* Initialize a variable CUM of type CUMULATIVE_ARGS
1622 for a call to a function whose data type is FNTYPE.
1623 For a library call, FNTYPE is 0.
1624 VDSP C Compiler manual, our ABI says that
1625 first 3 words of arguments will use R0, R1 and R2.
1628 void
1629 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
1630 rtx libname ATTRIBUTE_UNUSED)
1632 static CUMULATIVE_ARGS zero_cum;
1634 *cum = zero_cum;
1636 /* Set up the number of registers to use for passing arguments. */
1638 cum->nregs = max_arg_registers;
1639 cum->arg_regs = arg_regs;
1641 cum->call_cookie = CALL_NORMAL;
1642 /* Check for a longcall attribute. */
1643 if (fntype && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype)))
1644 cum->call_cookie |= CALL_SHORT;
1645 else if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)))
1646 cum->call_cookie |= CALL_LONG;
1648 return;
1651 /* Update the data in CUM to advance over an argument
1652 of mode MODE and data type TYPE.
1653 (TYPE is null for libcalls where that information may not be available.) */
1655 static void
1656 bfin_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
1657 const_tree type, bool named ATTRIBUTE_UNUSED)
1659 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
1660 int count, bytes, words;
1662 bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1663 words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1665 cum->words += words;
1666 cum->nregs -= words;
1668 if (cum->nregs <= 0)
1670 cum->nregs = 0;
1671 cum->arg_regs = NULL;
1673 else
1675 for (count = 1; count <= words; count++)
1676 cum->arg_regs++;
1679 return;
1682 /* Define where to put the arguments to a function.
1683 Value is zero to push the argument on the stack,
1684 or a hard register in which to store the argument.
1686 MODE is the argument's machine mode.
1687 TYPE is the data type of the argument (as a tree).
1688 This is null for libcalls where that information may
1689 not be available.
1690 CUM is a variable of type CUMULATIVE_ARGS which gives info about
1691 the preceding args and about the function being called.
1692 NAMED is nonzero if this argument is a named parameter
1693 (otherwise it is an extra parameter matching an ellipsis). */
1695 static rtx
1696 bfin_function_arg (cumulative_args_t cum_v, machine_mode mode,
1697 const_tree type, bool named ATTRIBUTE_UNUSED)
1699 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
1700 int bytes
1701 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1703 if (mode == VOIDmode)
1704 /* Compute operand 2 of the call insn. */
1705 return GEN_INT (cum->call_cookie);
1707 if (bytes == -1)
1708 return NULL_RTX;
1710 if (cum->nregs)
1711 return gen_rtx_REG (mode, *(cum->arg_regs));
1713 return NULL_RTX;
1716 /* For an arg passed partly in registers and partly in memory,
1717 this is the number of bytes passed in registers.
1718 For args passed entirely in registers or entirely in memory, zero.
1720 Refer VDSP C Compiler manual, our ABI.
1721 First 3 words are in registers. So, if an argument is larger
1722 than the registers available, it will span the register and
1723 stack. */
1725 static int
1726 bfin_arg_partial_bytes (cumulative_args_t cum, machine_mode mode,
1727 tree type ATTRIBUTE_UNUSED,
1728 bool named ATTRIBUTE_UNUSED)
1730 int bytes
1731 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1732 int bytes_left = get_cumulative_args (cum)->nregs * UNITS_PER_WORD;
1734 if (bytes == -1)
1735 return 0;
1737 if (bytes_left == 0)
1738 return 0;
1739 if (bytes > bytes_left)
1740 return bytes_left;
1741 return 0;
1744 /* Variable sized types are passed by reference. */
1746 static bool
1747 bfin_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
1748 machine_mode mode ATTRIBUTE_UNUSED,
1749 const_tree type, bool named ATTRIBUTE_UNUSED)
1751 return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
1754 /* Decide whether a type should be returned in memory (true)
1755 or in a register (false). This is called by the macro
1756 TARGET_RETURN_IN_MEMORY. */
1758 static bool
1759 bfin_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
1761 int size = int_size_in_bytes (type);
1762 return size > 2 * UNITS_PER_WORD || size == -1;
1765 /* Register in which address to store a structure value
1766 is passed to a function. */
1767 static rtx
1768 bfin_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
1769 int incoming ATTRIBUTE_UNUSED)
1771 return gen_rtx_REG (Pmode, REG_P0);
1774 /* Return true when register may be used to pass function parameters. */
1776 bool
1777 function_arg_regno_p (int n)
1779 int i;
1780 for (i = 0; arg_regs[i] != -1; i++)
1781 if (n == arg_regs[i])
1782 return true;
1783 return false;
1786 /* Returns 1 if OP contains a symbol reference */
1789 symbolic_reference_mentioned_p (rtx op)
1791 register const char *fmt;
1792 register int i;
1794 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
1795 return 1;
1797 fmt = GET_RTX_FORMAT (GET_CODE (op));
1798 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
1800 if (fmt[i] == 'E')
1802 register int j;
1804 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
1805 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
1806 return 1;
1809 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
1810 return 1;
1813 return 0;
1816 /* Decide whether we can make a sibling call to a function. DECL is the
1817 declaration of the function being targeted by the call and EXP is the
1818 CALL_EXPR representing the call. */
1820 static bool
1821 bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
1822 tree exp ATTRIBUTE_UNUSED)
1824 struct cgraph_local_info *this_func, *called_func;
1825 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1826 if (fkind != SUBROUTINE)
1827 return false;
1828 if (!TARGET_ID_SHARED_LIBRARY || TARGET_SEP_DATA)
1829 return true;
1831 /* When compiling for ID shared libraries, can't sibcall a local function
1832 from a non-local function, because the local function thinks it does
1833 not need to reload P5 in the prologue, but the sibcall wil pop P5 in the
1834 sibcall epilogue, and we end up with the wrong value in P5. */
1836 if (!decl)
1837 /* Not enough information. */
1838 return false;
1840 this_func = cgraph_node::local_info (current_function_decl);
1841 called_func = cgraph_node::local_info (decl);
1842 if (!called_func)
1843 return false;
1844 return !called_func->local || this_func->local;
1847 /* Write a template for a trampoline to F. */
1849 static void
1850 bfin_asm_trampoline_template (FILE *f)
1852 if (TARGET_FDPIC)
1854 fprintf (f, "\t.dd\t0x00000000\n"); /* 0 */
1855 fprintf (f, "\t.dd\t0x00000000\n"); /* 0 */
1856 fprintf (f, "\t.dd\t0x0000e109\n"); /* p1.l = fn low */
1857 fprintf (f, "\t.dd\t0x0000e149\n"); /* p1.h = fn high */
1858 fprintf (f, "\t.dd\t0x0000e10a\n"); /* p2.l = sc low */
1859 fprintf (f, "\t.dd\t0x0000e14a\n"); /* p2.h = sc high */
1860 fprintf (f, "\t.dw\t0xac4b\n"); /* p3 = [p1 + 4] */
1861 fprintf (f, "\t.dw\t0x9149\n"); /* p1 = [p1] */
1862 fprintf (f, "\t.dw\t0x0051\n"); /* jump (p1)*/
1864 else
1866 fprintf (f, "\t.dd\t0x0000e109\n"); /* p1.l = fn low */
1867 fprintf (f, "\t.dd\t0x0000e149\n"); /* p1.h = fn high */
1868 fprintf (f, "\t.dd\t0x0000e10a\n"); /* p2.l = sc low */
1869 fprintf (f, "\t.dd\t0x0000e14a\n"); /* p2.h = sc high */
1870 fprintf (f, "\t.dw\t0x0051\n"); /* jump (p1)*/
1874 /* Emit RTL insns to initialize the variable parts of a trampoline at
1875 M_TRAMP. FNDECL is the target function. CHAIN_VALUE is an RTX for
1876 the static chain value for the function. */
1878 static void
1879 bfin_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
1881 rtx t1 = copy_to_reg (XEXP (DECL_RTL (fndecl), 0));
1882 rtx t2 = copy_to_reg (chain_value);
1883 rtx mem;
1884 int i = 0;
1886 emit_block_move (m_tramp, assemble_trampoline_template (),
1887 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
1889 if (TARGET_FDPIC)
1891 rtx a = force_reg (Pmode, plus_constant (Pmode, XEXP (m_tramp, 0), 8));
1892 mem = adjust_address (m_tramp, Pmode, 0);
1893 emit_move_insn (mem, a);
1894 i = 8;
1897 mem = adjust_address (m_tramp, HImode, i + 2);
1898 emit_move_insn (mem, gen_lowpart (HImode, t1));
1899 emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16)));
1900 mem = adjust_address (m_tramp, HImode, i + 6);
1901 emit_move_insn (mem, gen_lowpart (HImode, t1));
1903 mem = adjust_address (m_tramp, HImode, i + 10);
1904 emit_move_insn (mem, gen_lowpart (HImode, t2));
1905 emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16)));
1906 mem = adjust_address (m_tramp, HImode, i + 14);
1907 emit_move_insn (mem, gen_lowpart (HImode, t2));
1910 /* Emit insns to move operands[1] into operands[0]. */
1912 void
1913 emit_pic_move (rtx *operands, machine_mode mode ATTRIBUTE_UNUSED)
1915 rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
1917 gcc_assert (!TARGET_FDPIC || !(reload_in_progress || reload_completed));
1918 if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
1919 operands[1] = force_reg (SImode, operands[1]);
1920 else
1921 operands[1] = legitimize_pic_address (operands[1], temp,
1922 TARGET_FDPIC ? OUR_FDPIC_REG
1923 : pic_offset_table_rtx);
1926 /* Expand a move operation in mode MODE. The operands are in OPERANDS.
1927 Returns true if no further code must be generated, false if the caller
1928 should generate an insn to move OPERANDS[1] to OPERANDS[0]. */
1930 bool
1931 expand_move (rtx *operands, machine_mode mode)
1933 rtx op = operands[1];
1934 if ((TARGET_ID_SHARED_LIBRARY || TARGET_FDPIC)
1935 && SYMBOLIC_CONST (op))
1936 emit_pic_move (operands, mode);
1937 else if (mode == SImode && GET_CODE (op) == CONST
1938 && GET_CODE (XEXP (op, 0)) == PLUS
1939 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
1940 && !targetm.legitimate_constant_p (mode, op))
1942 rtx dest = operands[0];
1943 rtx op0, op1;
1944 gcc_assert (!reload_in_progress && !reload_completed);
1945 op = XEXP (op, 0);
1946 op0 = force_reg (mode, XEXP (op, 0));
1947 op1 = XEXP (op, 1);
1948 if (!insn_data[CODE_FOR_addsi3].operand[2].predicate (op1, mode))
1949 op1 = force_reg (mode, op1);
1950 if (GET_CODE (dest) == MEM)
1951 dest = gen_reg_rtx (mode);
1952 emit_insn (gen_addsi3 (dest, op0, op1));
1953 if (dest == operands[0])
1954 return true;
1955 operands[1] = dest;
1957 /* Don't generate memory->memory or constant->memory moves, go through a
1958 register */
1959 else if ((reload_in_progress | reload_completed) == 0
1960 && GET_CODE (operands[0]) == MEM
1961 && GET_CODE (operands[1]) != REG)
1962 operands[1] = force_reg (mode, operands[1]);
1963 return false;
1966 /* Split one or more DImode RTL references into pairs of SImode
1967 references. The RTL can be REG, offsettable MEM, integer constant, or
1968 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
1969 split and "num" is its length. lo_half and hi_half are output arrays
1970 that parallel "operands". */
1972 void
1973 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
1975 while (num--)
1977 rtx op = operands[num];
1979 /* simplify_subreg refuse to split volatile memory addresses,
1980 but we still have to handle it. */
1981 if (GET_CODE (op) == MEM)
1983 lo_half[num] = adjust_address (op, SImode, 0);
1984 hi_half[num] = adjust_address (op, SImode, 4);
1986 else
1988 lo_half[num] = simplify_gen_subreg (SImode, op,
1989 GET_MODE (op) == VOIDmode
1990 ? DImode : GET_MODE (op), 0);
1991 hi_half[num] = simplify_gen_subreg (SImode, op,
1992 GET_MODE (op) == VOIDmode
1993 ? DImode : GET_MODE (op), 4);
1998 bool
1999 bfin_longcall_p (rtx op, int call_cookie)
2001 gcc_assert (GET_CODE (op) == SYMBOL_REF);
2002 if (SYMBOL_REF_WEAK (op))
2003 return 1;
2004 if (call_cookie & CALL_SHORT)
2005 return 0;
2006 if (call_cookie & CALL_LONG)
2007 return 1;
2008 if (TARGET_LONG_CALLS)
2009 return 1;
2010 return 0;
2013 /* Expand a call instruction. FNADDR is the call target, RETVAL the return value.
2014 COOKIE is a CONST_INT holding the call_cookie prepared init_cumulative_args.
2015 SIBCALL is nonzero if this is a sibling call. */
2017 void
2018 bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
2020 rtx use = NULL, call;
2021 rtx callee = XEXP (fnaddr, 0);
2022 int nelts = 3;
2023 rtx pat;
2024 rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REGNO);
2025 rtx retsreg = gen_rtx_REG (Pmode, REG_RETS);
2026 int n;
2028 /* In an untyped call, we can get NULL for operand 2. */
2029 if (cookie == NULL_RTX)
2030 cookie = const0_rtx;
2032 /* Static functions and indirect calls don't need the pic register. */
2033 if (!TARGET_FDPIC && flag_pic
2034 && GET_CODE (callee) == SYMBOL_REF
2035 && !SYMBOL_REF_LOCAL_P (callee))
2036 use_reg (&use, pic_offset_table_rtx);
2038 if (TARGET_FDPIC)
2040 int caller_in_sram, callee_in_sram;
2042 /* 0 is not in sram, 1 is in L1 sram, 2 is in L2 sram. */
2043 caller_in_sram = callee_in_sram = 0;
2045 if (lookup_attribute ("l1_text",
2046 DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE)
2047 caller_in_sram = 1;
2048 else if (lookup_attribute ("l2",
2049 DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE)
2050 caller_in_sram = 2;
2052 if (GET_CODE (callee) == SYMBOL_REF
2053 && SYMBOL_REF_DECL (callee) && DECL_P (SYMBOL_REF_DECL (callee)))
2055 if (lookup_attribute
2056 ("l1_text",
2057 DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE)
2058 callee_in_sram = 1;
2059 else if (lookup_attribute
2060 ("l2",
2061 DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE)
2062 callee_in_sram = 2;
2065 if (GET_CODE (callee) != SYMBOL_REF
2066 || bfin_longcall_p (callee, INTVAL (cookie))
2067 || (GET_CODE (callee) == SYMBOL_REF
2068 && !SYMBOL_REF_LOCAL_P (callee)
2069 && TARGET_INLINE_PLT)
2070 || caller_in_sram != callee_in_sram
2071 || (caller_in_sram && callee_in_sram
2072 && (GET_CODE (callee) != SYMBOL_REF
2073 || !SYMBOL_REF_LOCAL_P (callee))))
2075 rtx addr = callee;
2076 if (! address_operand (addr, Pmode))
2077 addr = force_reg (Pmode, addr);
2079 fnaddr = gen_reg_rtx (SImode);
2080 emit_insn (gen_load_funcdescsi (fnaddr, addr));
2081 fnaddr = gen_rtx_MEM (Pmode, fnaddr);
2083 picreg = gen_reg_rtx (SImode);
2084 emit_insn (gen_load_funcdescsi (picreg,
2085 plus_constant (Pmode, addr, 4)));
2088 nelts++;
2090 else if ((!register_no_elim_operand (callee, Pmode)
2091 && GET_CODE (callee) != SYMBOL_REF)
2092 || (GET_CODE (callee) == SYMBOL_REF
2093 && ((TARGET_ID_SHARED_LIBRARY && !TARGET_LEAF_ID_SHARED_LIBRARY)
2094 || bfin_longcall_p (callee, INTVAL (cookie)))))
2096 callee = copy_to_mode_reg (Pmode, callee);
2097 fnaddr = gen_rtx_MEM (Pmode, callee);
2099 call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
2101 if (retval)
2102 call = gen_rtx_SET (retval, call);
2104 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nelts));
2105 n = 0;
2106 XVECEXP (pat, 0, n++) = call;
2107 if (TARGET_FDPIC)
2108 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, picreg);
2109 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie);
2110 if (sibcall)
2111 XVECEXP (pat, 0, n++) = ret_rtx;
2112 else
2113 XVECEXP (pat, 0, n++) = gen_rtx_CLOBBER (VOIDmode, retsreg);
2114 call = emit_call_insn (pat);
2115 if (use)
2116 CALL_INSN_FUNCTION_USAGE (call) = use;
2119 /* Implement TARGET_HARD_REGNO_NREGS. */
2121 static unsigned int
2122 bfin_hard_regno_nregs (unsigned int regno, machine_mode mode)
2124 if (mode == PDImode && (regno == REG_A0 || regno == REG_A1))
2125 return 1;
2126 if (mode == V2PDImode && (regno == REG_A0 || regno == REG_A1))
2127 return 2;
2128 return CLASS_MAX_NREGS (GENERAL_REGS, mode);
2131 /* Implement TARGET_HARD_REGNO_MODE_OK.
2133 Do not allow to store a value in REG_CC for any mode.
2134 Do not allow to store value in pregs if mode is not SI. */
2135 static bool
2136 bfin_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
2138 /* Allow only dregs to store value of mode HI or QI */
2139 enum reg_class rclass = REGNO_REG_CLASS (regno);
2141 if (mode == CCmode)
2142 return false;
2144 if (mode == V2HImode)
2145 return D_REGNO_P (regno);
2146 if (rclass == CCREGS)
2147 return mode == BImode;
2148 if (mode == PDImode || mode == V2PDImode)
2149 return regno == REG_A0 || regno == REG_A1;
2151 /* Allow all normal 32-bit regs, except REG_M3, in case regclass ever comes
2152 up with a bad register class (such as ALL_REGS) for DImode. */
2153 if (mode == DImode)
2154 return regno < REG_M3;
2156 if (mode == SImode
2157 && TEST_HARD_REG_BIT (reg_class_contents[PROLOGUE_REGS], regno))
2158 return true;
2160 return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno);
2163 /* Implement TARGET_MODES_TIEABLE_P. */
2165 static bool
2166 bfin_modes_tieable_p (machine_mode mode1, machine_mode mode2)
2168 return (mode1 == mode2
2169 || ((GET_MODE_CLASS (mode1) == MODE_INT
2170 || GET_MODE_CLASS (mode1) == MODE_FLOAT)
2171 && (GET_MODE_CLASS (mode2) == MODE_INT
2172 || GET_MODE_CLASS (mode2) == MODE_FLOAT)
2173 && mode1 != BImode && mode2 != BImode
2174 && GET_MODE_SIZE (mode1) <= UNITS_PER_WORD
2175 && GET_MODE_SIZE (mode2) <= UNITS_PER_WORD));
2178 /* Implements target hook vector_mode_supported_p. */
2180 static bool
2181 bfin_vector_mode_supported_p (machine_mode mode)
2183 return mode == V2HImode;
2186 /* Worker function for TARGET_REGISTER_MOVE_COST. */
2188 static int
2189 bfin_register_move_cost (machine_mode mode,
2190 reg_class_t class1, reg_class_t class2)
2192 /* These need secondary reloads, so they're more expensive. */
2193 if ((class1 == CCREGS && !reg_class_subset_p (class2, DREGS))
2194 || (class2 == CCREGS && !reg_class_subset_p (class1, DREGS)))
2195 return 4;
2197 /* If optimizing for size, always prefer reg-reg over reg-memory moves. */
2198 if (optimize_size)
2199 return 2;
2201 if (GET_MODE_CLASS (mode) == MODE_INT)
2203 /* Discourage trying to use the accumulators. */
2204 if (TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A0)
2205 || TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A1)
2206 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A0)
2207 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A1))
2208 return 20;
2210 return 2;
2213 /* Worker function for TARGET_MEMORY_MOVE_COST.
2215 ??? In theory L1 memory has single-cycle latency. We should add a switch
2216 that tells the compiler whether we expect to use only L1 memory for the
2217 program; it'll make the costs more accurate. */
2219 static int
2220 bfin_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
2221 reg_class_t rclass,
2222 bool in ATTRIBUTE_UNUSED)
2224 /* Make memory accesses slightly more expensive than any register-register
2225 move. Also, penalize non-DP registers, since they need secondary
2226 reloads to load and store. */
2227 if (! reg_class_subset_p (rclass, DPREGS))
2228 return 10;
2230 return 8;
2233 /* Inform reload about cases where moving X with a mode MODE to a register in
2234 RCLASS requires an extra scratch register. Return the class needed for the
2235 scratch register. */
2237 static reg_class_t
2238 bfin_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
2239 machine_mode mode, secondary_reload_info *sri)
2241 /* If we have HImode or QImode, we can only use DREGS as secondary registers;
2242 in most other cases we can also use PREGS. */
2243 enum reg_class default_class = GET_MODE_SIZE (mode) >= 4 ? DPREGS : DREGS;
2244 enum reg_class x_class = NO_REGS;
2245 enum rtx_code code = GET_CODE (x);
2246 enum reg_class rclass = (enum reg_class) rclass_i;
2248 if (code == SUBREG)
2249 x = SUBREG_REG (x), code = GET_CODE (x);
2250 if (REG_P (x))
2252 int regno = REGNO (x);
2253 if (regno >= FIRST_PSEUDO_REGISTER)
2254 regno = reg_renumber[regno];
2256 if (regno == -1)
2257 code = MEM;
2258 else
2259 x_class = REGNO_REG_CLASS (regno);
2262 /* We can be asked to reload (plus (FP) (large_constant)) into a DREG.
2263 This happens as a side effect of register elimination, and we need
2264 a scratch register to do it. */
2265 if (fp_plus_const_operand (x, mode))
2267 rtx op2 = XEXP (x, 1);
2268 int large_constant_p = ! satisfies_constraint_Ks7 (op2);
2270 if (rclass == PREGS || rclass == PREGS_CLOBBERED)
2271 return NO_REGS;
2272 /* If destination is a DREG, we can do this without a scratch register
2273 if the constant is valid for an add instruction. */
2274 if ((rclass == DREGS || rclass == DPREGS)
2275 && ! large_constant_p)
2276 return NO_REGS;
2277 /* Reloading to anything other than a DREG? Use a PREG scratch
2278 register. */
2279 sri->icode = CODE_FOR_reload_insi;
2280 return NO_REGS;
2283 /* Data can usually be moved freely between registers of most classes.
2284 AREGS are an exception; they can only move to or from another register
2285 in AREGS or one in DREGS. They can also be assigned the constant 0. */
2286 if (x_class == AREGS || x_class == EVEN_AREGS || x_class == ODD_AREGS)
2287 return (rclass == DREGS || rclass == AREGS || rclass == EVEN_AREGS
2288 || rclass == ODD_AREGS
2289 ? NO_REGS : DREGS);
2291 if (rclass == AREGS || rclass == EVEN_AREGS || rclass == ODD_AREGS)
2293 if (code == MEM)
2295 sri->icode = in_p ? CODE_FOR_reload_inpdi : CODE_FOR_reload_outpdi;
2296 return NO_REGS;
2299 if (x != const0_rtx && x_class != DREGS)
2301 return DREGS;
2303 else
2304 return NO_REGS;
2307 /* CCREGS can only be moved from/to DREGS. */
2308 if (rclass == CCREGS && x_class != DREGS)
2309 return DREGS;
2310 if (x_class == CCREGS && rclass != DREGS)
2311 return DREGS;
2313 /* All registers other than AREGS can load arbitrary constants. The only
2314 case that remains is MEM. */
2315 if (code == MEM)
2316 if (! reg_class_subset_p (rclass, default_class))
2317 return default_class;
2319 return NO_REGS;
2322 /* Implement TARGET_CLASS_LIKELY_SPILLED_P. */
2324 static bool
2325 bfin_class_likely_spilled_p (reg_class_t rclass)
2327 switch (rclass)
2329 case PREGS_CLOBBERED:
2330 case PROLOGUE_REGS:
2331 case P0REGS:
2332 case D0REGS:
2333 case D1REGS:
2334 case D2REGS:
2335 case CCREGS:
2336 return true;
2338 default:
2339 break;
2342 return false;
2345 static struct machine_function *
2346 bfin_init_machine_status (void)
2348 return ggc_cleared_alloc<machine_function> ();
2351 /* Implement the TARGET_OPTION_OVERRIDE hook. */
2353 static void
2354 bfin_option_override (void)
2356 /* If processor type is not specified, enable all workarounds. */
2357 if (bfin_cpu_type == BFIN_CPU_UNKNOWN)
2359 int i;
2361 for (i = 0; bfin_cpus[i].name != NULL; i++)
2362 bfin_workarounds |= bfin_cpus[i].workarounds;
2364 bfin_si_revision = 0xffff;
2367 if (bfin_csync_anomaly == 1)
2368 bfin_workarounds |= WA_SPECULATIVE_SYNCS;
2369 else if (bfin_csync_anomaly == 0)
2370 bfin_workarounds &= ~WA_SPECULATIVE_SYNCS;
2372 if (bfin_specld_anomaly == 1)
2373 bfin_workarounds |= WA_SPECULATIVE_LOADS;
2374 else if (bfin_specld_anomaly == 0)
2375 bfin_workarounds &= ~WA_SPECULATIVE_LOADS;
2377 if (TARGET_OMIT_LEAF_FRAME_POINTER)
2378 flag_omit_frame_pointer = 1;
2380 #ifdef SUBTARGET_FDPIC_NOT_SUPPORTED
2381 if (TARGET_FDPIC)
2382 error ("-mfdpic is not supported, please use a bfin-linux-uclibc target");
2383 #endif
2385 /* Library identification */
2386 if (global_options_set.x_bfin_library_id && ! TARGET_ID_SHARED_LIBRARY)
2387 error ("-mshared-library-id= specified without -mid-shared-library");
2389 if (stack_limit_rtx && TARGET_FDPIC)
2391 warning (0, "-fstack-limit- options are ignored with -mfdpic; use -mstack-check-l1");
2392 stack_limit_rtx = NULL_RTX;
2395 if (stack_limit_rtx && TARGET_STACK_CHECK_L1)
2396 error ("can%'t use multiple stack checking methods together");
2398 if (TARGET_ID_SHARED_LIBRARY && TARGET_FDPIC)
2399 error ("ID shared libraries and FD-PIC mode can%'t be used together");
2401 /* Don't allow the user to specify -mid-shared-library and -msep-data
2402 together, as it makes little sense from a user's point of view... */
2403 if (TARGET_SEP_DATA && TARGET_ID_SHARED_LIBRARY)
2404 error ("cannot specify both -msep-data and -mid-shared-library");
2405 /* ... internally, however, it's nearly the same. */
2406 if (TARGET_SEP_DATA)
2407 target_flags |= MASK_ID_SHARED_LIBRARY | MASK_LEAF_ID_SHARED_LIBRARY;
2409 if (TARGET_ID_SHARED_LIBRARY && flag_pic == 0)
2410 flag_pic = 1;
2412 /* There is no single unaligned SI op for PIC code. Sometimes we
2413 need to use ".4byte" and sometimes we need to use ".picptr".
2414 See bfin_assemble_integer for details. */
2415 if (TARGET_FDPIC)
2416 targetm.asm_out.unaligned_op.si = 0;
2418 /* Silently turn off flag_pic if not doing FDPIC or ID shared libraries,
2419 since we don't support it and it'll just break. */
2420 if (flag_pic && !TARGET_FDPIC && !TARGET_ID_SHARED_LIBRARY)
2421 flag_pic = 0;
2423 if (TARGET_MULTICORE && bfin_cpu_type != BFIN_CPU_BF561)
2424 error ("-mmulticore can only be used with BF561");
2426 if (TARGET_COREA && !TARGET_MULTICORE)
2427 error ("-mcorea should be used with -mmulticore");
2429 if (TARGET_COREB && !TARGET_MULTICORE)
2430 error ("-mcoreb should be used with -mmulticore");
2432 if (TARGET_COREA && TARGET_COREB)
2433 error ("-mcorea and -mcoreb can%'t be used together");
2435 flag_schedule_insns = 0;
2437 init_machine_status = bfin_init_machine_status;
2440 /* Return the destination address of BRANCH.
2441 We need to use this instead of get_attr_length, because the
2442 cbranch_with_nops pattern conservatively sets its length to 6, and
2443 we still prefer to use shorter sequences. */
2445 static int
2446 branch_dest (rtx_insn *branch)
2448 rtx dest;
2449 int dest_uid;
2450 rtx pat = PATTERN (branch);
2451 if (GET_CODE (pat) == PARALLEL)
2452 pat = XVECEXP (pat, 0, 0);
2453 dest = SET_SRC (pat);
2454 if (GET_CODE (dest) == IF_THEN_ELSE)
2455 dest = XEXP (dest, 1);
2456 dest = XEXP (dest, 0);
2457 dest_uid = INSN_UID (dest);
2458 return INSN_ADDRESSES (dest_uid);
2461 /* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates
2462 it's a branch that's predicted taken. */
2464 static int
2465 cbranch_predicted_taken_p (rtx insn)
2467 rtx x = find_reg_note (insn, REG_BR_PROB, 0);
2469 if (x)
2471 return profile_probability::from_reg_br_prob_note (XINT (x, 0))
2472 >= profile_probability::even ();
2475 return 0;
2478 /* Templates for use by asm_conditional_branch. */
2480 static const char *ccbranch_templates[][3] = {
2481 { "if !cc jump %3;", "if cc jump 4 (bp); jump.s %3;", "if cc jump 6 (bp); jump.l %3;" },
2482 { "if cc jump %3;", "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" },
2483 { "if !cc jump %3 (bp);", "if cc jump 4; jump.s %3;", "if cc jump 6; jump.l %3;" },
2484 { "if cc jump %3 (bp);", "if !cc jump 4; jump.s %3;", "if !cc jump 6; jump.l %3;" },
2487 /* Output INSN, which is a conditional branch instruction with operands
2488 OPERANDS.
2490 We deal with the various forms of conditional branches that can be generated
2491 by bfin_reorg to prevent the hardware from doing speculative loads, by
2492 - emitting a sufficient number of nops, if N_NOPS is nonzero, or
2493 - always emitting the branch as predicted taken, if PREDICT_TAKEN is true.
2494 Either of these is only necessary if the branch is short, otherwise the
2495 template we use ends in an unconditional jump which flushes the pipeline
2496 anyway. */
2498 void
2499 asm_conditional_branch (rtx_insn *insn, rtx *operands, int n_nops, int predict_taken)
2501 int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
2502 /* Note : offset for instructions like if cc jmp; jump.[sl] offset
2503 is to be taken from start of if cc rather than jump.
2504 Range for jump.s is (-4094, 4096) instead of (-4096, 4094)
2506 int len = (offset >= -1024 && offset <= 1022 ? 0
2507 : offset >= -4094 && offset <= 4096 ? 1
2508 : 2);
2509 int bp = predict_taken && len == 0 ? 1 : cbranch_predicted_taken_p (insn);
2510 int idx = (bp << 1) | (GET_CODE (operands[0]) == EQ ? BRF : BRT);
2511 output_asm_insn (ccbranch_templates[idx][len], operands);
2512 gcc_assert (n_nops == 0 || !bp);
2513 if (len == 0)
2514 while (n_nops-- > 0)
2515 output_asm_insn ("nop;", NULL);
2518 /* Emit rtl for a comparison operation CMP in mode MODE. Operands have been
2519 stored in bfin_compare_op0 and bfin_compare_op1 already. */
2522 bfin_gen_compare (rtx cmp, machine_mode mode ATTRIBUTE_UNUSED)
2524 enum rtx_code code1, code2;
2525 rtx op0 = XEXP (cmp, 0), op1 = XEXP (cmp, 1);
2526 rtx tem = bfin_cc_rtx;
2527 enum rtx_code code = GET_CODE (cmp);
2529 /* If we have a BImode input, then we already have a compare result, and
2530 do not need to emit another comparison. */
2531 if (GET_MODE (op0) == BImode)
2533 gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
2534 tem = op0, code2 = code;
2536 else
2538 switch (code) {
2539 /* bfin has these conditions */
2540 case EQ:
2541 case LT:
2542 case LE:
2543 case LEU:
2544 case LTU:
2545 code1 = code;
2546 code2 = NE;
2547 break;
2548 default:
2549 code1 = reverse_condition (code);
2550 code2 = EQ;
2551 break;
2553 emit_insn (gen_rtx_SET (tem, gen_rtx_fmt_ee (code1, BImode, op0, op1)));
2556 return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode));
2559 /* Return nonzero iff C has exactly one bit set if it is interpreted
2560 as a 32-bit constant. */
2563 log2constp (unsigned HOST_WIDE_INT c)
2565 c &= 0xFFFFFFFF;
2566 return c != 0 && (c & (c-1)) == 0;
2569 /* Returns the number of consecutive least significant zeros in the binary
2570 representation of *V.
2571 We modify *V to contain the original value arithmetically shifted right by
2572 the number of zeroes. */
2574 static int
2575 shiftr_zero (HOST_WIDE_INT *v)
2577 unsigned HOST_WIDE_INT tmp = *v;
2578 unsigned HOST_WIDE_INT sgn;
2579 int n = 0;
2581 if (tmp == 0)
2582 return 0;
2584 sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1));
2585 while ((tmp & 0x1) == 0 && n <= 32)
2587 tmp = (tmp >> 1) | sgn;
2588 n++;
2590 *v = tmp;
2591 return n;
2594 /* After reload, split the load of an immediate constant. OPERANDS are the
2595 operands of the movsi_insn pattern which we are splitting. We return
2596 nonzero if we emitted a sequence to load the constant, zero if we emitted
2597 nothing because we want to use the splitter's default sequence. */
2600 split_load_immediate (rtx operands[])
2602 HOST_WIDE_INT val = INTVAL (operands[1]);
2603 HOST_WIDE_INT tmp;
2604 HOST_WIDE_INT shifted = val;
2605 HOST_WIDE_INT shifted_compl = ~val;
2606 int num_zero = shiftr_zero (&shifted);
2607 int num_compl_zero = shiftr_zero (&shifted_compl);
2608 unsigned int regno = REGNO (operands[0]);
2610 /* This case takes care of single-bit set/clear constants, which we could
2611 also implement with BITSET/BITCLR. */
2612 if (num_zero
2613 && shifted >= -32768 && shifted < 65536
2614 && (D_REGNO_P (regno)
2615 || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))
2617 emit_insn (gen_movsi (operands[0], gen_int_mode (shifted, SImode)));
2618 emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));
2619 return 1;
2622 tmp = val & 0xFFFF;
2623 tmp |= -(tmp & 0x8000);
2625 /* If high word has one bit set or clear, try to use a bit operation. */
2626 if (D_REGNO_P (regno))
2628 if (log2constp (val & 0xFFFF0000))
2630 emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));
2631 emit_insn (gen_iorsi3 (operands[0], operands[0],
2632 gen_int_mode (val & 0xFFFF0000, SImode)));
2633 return 1;
2635 else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)
2637 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2638 emit_insn (gen_andsi3 (operands[0], operands[0],
2639 gen_int_mode (val | 0xFFFF, SImode)));
2643 if (D_REGNO_P (regno))
2645 if (tmp >= -64 && tmp <= 63)
2647 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2648 emit_insn (gen_movstricthi_high (operands[0],
2649 gen_int_mode (val & -65536,
2650 SImode)));
2651 return 1;
2654 if ((val & 0xFFFF0000) == 0)
2656 emit_insn (gen_movsi (operands[0], const0_rtx));
2657 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2658 return 1;
2661 if ((val & 0xFFFF0000) == 0xFFFF0000)
2663 emit_insn (gen_movsi (operands[0], constm1_rtx));
2664 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2665 return 1;
2669 /* Need DREGs for the remaining case. */
2670 if (regno > REG_R7)
2671 return 0;
2673 if (optimize_size
2674 && num_compl_zero && shifted_compl >= -64 && shifted_compl <= 63)
2676 /* If optimizing for size, generate a sequence that has more instructions
2677 but is shorter. */
2678 emit_insn (gen_movsi (operands[0], gen_int_mode (shifted_compl, SImode)));
2679 emit_insn (gen_ashlsi3 (operands[0], operands[0],
2680 GEN_INT (num_compl_zero)));
2681 emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
2682 return 1;
2684 return 0;
2687 /* Return true if the legitimate memory address for a memory operand of mode
2688 MODE. Return false if not. */
2690 static bool
2691 bfin_valid_add (machine_mode mode, HOST_WIDE_INT value)
2693 unsigned HOST_WIDE_INT v = value > 0 ? value : -value;
2694 int sz = GET_MODE_SIZE (mode);
2695 int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2;
2696 /* The usual offsettable_memref machinery doesn't work so well for this
2697 port, so we deal with the problem here. */
2698 if (value > 0 && sz == 8)
2699 v += 4;
2700 return (v & ~(0x7fff << shift)) == 0;
2703 static bool
2704 bfin_valid_reg_p (unsigned int regno, int strict, machine_mode mode,
2705 enum rtx_code outer_code)
2707 if (strict)
2708 return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH);
2709 else
2710 return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH);
2713 /* Recognize an RTL expression that is a valid memory address for an
2714 instruction. The MODE argument is the machine mode for the MEM expression
2715 that wants to use this address.
2717 Blackfin addressing modes are as follows:
2719 [preg]
2720 [preg + imm16]
2722 B [ Preg + uimm15 ]
2723 W [ Preg + uimm16m2 ]
2724 [ Preg + uimm17m4 ]
2726 [preg++]
2727 [preg--]
2728 [--sp]
2731 static bool
2732 bfin_legitimate_address_p (machine_mode mode, rtx x, bool strict)
2734 switch (GET_CODE (x)) {
2735 case REG:
2736 if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM))
2737 return true;
2738 break;
2739 case PLUS:
2740 if (REG_P (XEXP (x, 0))
2741 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS)
2742 && ((GET_CODE (XEXP (x, 1)) == UNSPEC && mode == SImode)
2743 || (GET_CODE (XEXP (x, 1)) == CONST_INT
2744 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
2745 return true;
2746 break;
2747 case POST_INC:
2748 case POST_DEC:
2749 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2750 && REG_P (XEXP (x, 0))
2751 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC))
2752 return true;
2753 break;
2754 case PRE_DEC:
2755 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2756 && XEXP (x, 0) == stack_pointer_rtx
2757 && REG_P (XEXP (x, 0))
2758 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC))
2759 return true;
2760 break;
2761 default:
2762 break;
2764 return false;
2767 /* Decide whether we can force certain constants to memory. If we
2768 decide we can't, the caller should be able to cope with it in
2769 another way. */
2771 static bool
2772 bfin_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED,
2773 rtx x ATTRIBUTE_UNUSED)
2775 /* We have only one class of non-legitimate constants, and our movsi
2776 expander knows how to handle them. Dropping these constants into the
2777 data section would only shift the problem - we'd still get relocs
2778 outside the object, in the data section rather than the text section. */
2779 return true;
2782 /* Ensure that for any constant of the form symbol + offset, the offset
2783 remains within the object. Any other constants are ok.
2784 This ensures that flat binaries never have to deal with relocations
2785 crossing section boundaries. */
2787 static bool
2788 bfin_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
2790 rtx sym;
2791 HOST_WIDE_INT offset;
2793 if (GET_CODE (x) != CONST)
2794 return true;
2796 x = XEXP (x, 0);
2797 gcc_assert (GET_CODE (x) == PLUS);
2799 sym = XEXP (x, 0);
2800 x = XEXP (x, 1);
2801 if (GET_CODE (sym) != SYMBOL_REF
2802 || GET_CODE (x) != CONST_INT)
2803 return true;
2804 offset = INTVAL (x);
2806 if (SYMBOL_REF_DECL (sym) == 0)
2807 return true;
2808 if (offset < 0
2809 || offset >= int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (sym))))
2810 return false;
2812 return true;
2815 static bool
2816 bfin_rtx_costs (rtx x, machine_mode mode, int outer_code_i, int opno,
2817 int *total, bool speed)
2819 enum rtx_code code = GET_CODE (x);
2820 enum rtx_code outer_code = (enum rtx_code) outer_code_i;
2821 int cost2 = COSTS_N_INSNS (1);
2822 rtx op0, op1;
2824 switch (code)
2826 case CONST_INT:
2827 if (outer_code == SET || outer_code == PLUS)
2828 *total = satisfies_constraint_Ks7 (x) ? 0 : cost2;
2829 else if (outer_code == AND)
2830 *total = log2constp (~INTVAL (x)) ? 0 : cost2;
2831 else if (outer_code == LE || outer_code == LT || outer_code == EQ)
2832 *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
2833 else if (outer_code == LEU || outer_code == LTU)
2834 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
2835 else if (outer_code == MULT)
2836 *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
2837 else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
2838 *total = 0;
2839 else if (outer_code == ASHIFT || outer_code == ASHIFTRT
2840 || outer_code == LSHIFTRT)
2841 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
2842 else if (outer_code == IOR || outer_code == XOR)
2843 *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
2844 else
2845 *total = cost2;
2846 return true;
2848 case CONST:
2849 case LABEL_REF:
2850 case SYMBOL_REF:
2851 case CONST_DOUBLE:
2852 *total = COSTS_N_INSNS (2);
2853 return true;
2855 case PLUS:
2856 op0 = XEXP (x, 0);
2857 op1 = XEXP (x, 1);
2858 if (mode == SImode)
2860 if (GET_CODE (op0) == MULT
2861 && GET_CODE (XEXP (op0, 1)) == CONST_INT)
2863 HOST_WIDE_INT val = INTVAL (XEXP (op0, 1));
2864 if (val == 2 || val == 4)
2866 *total = cost2;
2867 *total += rtx_cost (XEXP (op0, 0), mode, outer_code,
2868 opno, speed);
2869 *total += rtx_cost (op1, mode, outer_code, opno, speed);
2870 return true;
2873 *total = cost2;
2874 if (GET_CODE (op0) != REG
2875 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2876 *total += set_src_cost (op0, mode, speed);
2877 #if 0 /* We'd like to do this for accuracy, but it biases the loop optimizer
2878 towards creating too many induction variables. */
2879 if (!reg_or_7bit_operand (op1, SImode))
2880 *total += set_src_cost (op1, mode, speed);
2881 #endif
2883 else if (mode == DImode)
2885 *total = 6 * cost2;
2886 if (GET_CODE (op1) != CONST_INT
2887 || !satisfies_constraint_Ks7 (op1))
2888 *total += rtx_cost (op1, mode, PLUS, 1, speed);
2889 if (GET_CODE (op0) != REG
2890 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2891 *total += rtx_cost (op0, mode, PLUS, 0, speed);
2893 return true;
2895 case MINUS:
2896 if (mode == DImode)
2897 *total = 6 * cost2;
2898 else
2899 *total = cost2;
2900 return true;
2902 case ASHIFT:
2903 case ASHIFTRT:
2904 case LSHIFTRT:
2905 if (mode == DImode)
2906 *total = 6 * cost2;
2907 else
2908 *total = cost2;
2910 op0 = XEXP (x, 0);
2911 op1 = XEXP (x, 1);
2912 if (GET_CODE (op0) != REG
2913 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2914 *total += rtx_cost (op0, mode, code, 0, speed);
2916 return true;
2918 case IOR:
2919 case AND:
2920 case XOR:
2921 op0 = XEXP (x, 0);
2922 op1 = XEXP (x, 1);
2924 /* Handle special cases of IOR: rotates, ALIGN insns, movstricthi_high. */
2925 if (code == IOR)
2927 if ((GET_CODE (op0) == LSHIFTRT && GET_CODE (op1) == ASHIFT)
2928 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == ZERO_EXTEND)
2929 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT)
2930 || (GET_CODE (op0) == AND && GET_CODE (op1) == CONST_INT))
2932 *total = cost2;
2933 return true;
2937 if (GET_CODE (op0) != REG
2938 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2939 *total += rtx_cost (op0, mode, code, 0, speed);
2941 if (mode == DImode)
2943 *total = 2 * cost2;
2944 return true;
2946 *total = cost2;
2947 if (mode != SImode)
2948 return true;
2950 if (code == AND)
2952 if (! rhs_andsi3_operand (XEXP (x, 1), SImode))
2953 *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
2955 else
2957 if (! regorlog2_operand (XEXP (x, 1), SImode))
2958 *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
2961 return true;
2963 case ZERO_EXTRACT:
2964 case SIGN_EXTRACT:
2965 if (outer_code == SET
2966 && XEXP (x, 1) == const1_rtx
2967 && GET_CODE (XEXP (x, 2)) == CONST_INT)
2969 *total = 2 * cost2;
2970 return true;
2972 /* fall through */
2974 case SIGN_EXTEND:
2975 case ZERO_EXTEND:
2976 *total = cost2;
2977 return true;
2979 case MULT:
2981 op0 = XEXP (x, 0);
2982 op1 = XEXP (x, 1);
2983 if (GET_CODE (op0) == GET_CODE (op1)
2984 && (GET_CODE (op0) == ZERO_EXTEND
2985 || GET_CODE (op0) == SIGN_EXTEND))
2987 *total = COSTS_N_INSNS (1);
2988 op0 = XEXP (op0, 0);
2989 op1 = XEXP (op1, 0);
2991 else if (!speed)
2992 *total = COSTS_N_INSNS (1);
2993 else
2994 *total = COSTS_N_INSNS (3);
2996 if (GET_CODE (op0) != REG
2997 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2998 *total += rtx_cost (op0, mode, MULT, 0, speed);
2999 if (GET_CODE (op1) != REG
3000 && (GET_CODE (op1) != SUBREG || GET_CODE (SUBREG_REG (op1)) != REG))
3001 *total += rtx_cost (op1, mode, MULT, 1, speed);
3003 return true;
3005 case UDIV:
3006 case UMOD:
3007 *total = COSTS_N_INSNS (32);
3008 return true;
3010 case VEC_CONCAT:
3011 case VEC_SELECT:
3012 if (outer_code == SET)
3013 *total = cost2;
3014 return true;
3016 default:
3017 return false;
3021 /* Used for communication between {push,pop}_multiple_operation (which
3022 we use not only as a predicate) and the corresponding output functions. */
3023 static int first_preg_to_save, first_dreg_to_save;
3024 static int n_regs_to_save;
3027 analyze_push_multiple_operation (rtx op)
3029 int lastdreg = 8, lastpreg = 6;
3030 int i, group;
3032 first_preg_to_save = lastpreg;
3033 first_dreg_to_save = lastdreg;
3034 for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
3036 rtx t = XVECEXP (op, 0, i);
3037 rtx src, dest;
3038 int regno;
3040 if (GET_CODE (t) != SET)
3041 return 0;
3043 src = SET_SRC (t);
3044 dest = SET_DEST (t);
3045 if (GET_CODE (dest) != MEM || ! REG_P (src))
3046 return 0;
3047 dest = XEXP (dest, 0);
3048 if (GET_CODE (dest) != PLUS
3049 || ! REG_P (XEXP (dest, 0))
3050 || REGNO (XEXP (dest, 0)) != REG_SP
3051 || GET_CODE (XEXP (dest, 1)) != CONST_INT
3052 || INTVAL (XEXP (dest, 1)) != -i * 4)
3053 return 0;
3055 regno = REGNO (src);
3056 if (group == 0)
3058 if (D_REGNO_P (regno))
3060 group = 1;
3061 first_dreg_to_save = lastdreg = regno - REG_R0;
3063 else if (regno >= REG_P0 && regno <= REG_P7)
3065 group = 2;
3066 first_preg_to_save = lastpreg = regno - REG_P0;
3068 else
3069 return 0;
3071 continue;
3074 if (group == 1)
3076 if (regno >= REG_P0 && regno <= REG_P7)
3078 group = 2;
3079 first_preg_to_save = lastpreg = regno - REG_P0;
3081 else if (regno != REG_R0 + lastdreg + 1)
3082 return 0;
3083 else
3084 lastdreg++;
3086 else if (group == 2)
3088 if (regno != REG_P0 + lastpreg + 1)
3089 return 0;
3090 lastpreg++;
3093 n_regs_to_save = 8 - first_dreg_to_save + 6 - first_preg_to_save;
3094 return 1;
3098 analyze_pop_multiple_operation (rtx op)
3100 int lastdreg = 8, lastpreg = 6;
3101 int i, group;
3103 for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
3105 rtx t = XVECEXP (op, 0, i);
3106 rtx src, dest;
3107 int regno;
3109 if (GET_CODE (t) != SET)
3110 return 0;
3112 src = SET_SRC (t);
3113 dest = SET_DEST (t);
3114 if (GET_CODE (src) != MEM || ! REG_P (dest))
3115 return 0;
3116 src = XEXP (src, 0);
3118 if (i == 1)
3120 if (! REG_P (src) || REGNO (src) != REG_SP)
3121 return 0;
3123 else if (GET_CODE (src) != PLUS
3124 || ! REG_P (XEXP (src, 0))
3125 || REGNO (XEXP (src, 0)) != REG_SP
3126 || GET_CODE (XEXP (src, 1)) != CONST_INT
3127 || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
3128 return 0;
3130 regno = REGNO (dest);
3131 if (group == 0)
3133 if (regno == REG_R7)
3135 group = 1;
3136 lastdreg = 7;
3138 else if (regno != REG_P0 + lastpreg - 1)
3139 return 0;
3140 else
3141 lastpreg--;
3143 else if (group == 1)
3145 if (regno != REG_R0 + lastdreg - 1)
3146 return 0;
3147 else
3148 lastdreg--;
3151 first_dreg_to_save = lastdreg;
3152 first_preg_to_save = lastpreg;
3153 n_regs_to_save = 8 - first_dreg_to_save + 6 - first_preg_to_save;
3154 return 1;
3157 /* Emit assembly code for one multi-register push described by INSN, with
3158 operands in OPERANDS. */
3160 void
3161 output_push_multiple (rtx insn, rtx *operands)
3163 char buf[80];
3164 int ok;
3166 /* Validate the insn again, and compute first_[dp]reg_to_save. */
3167 ok = analyze_push_multiple_operation (PATTERN (insn));
3168 gcc_assert (ok);
3170 if (first_dreg_to_save == 8)
3171 sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
3172 else if (first_preg_to_save == 6)
3173 sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
3174 else
3175 sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
3176 first_dreg_to_save, first_preg_to_save);
3178 output_asm_insn (buf, operands);
3181 /* Emit assembly code for one multi-register pop described by INSN, with
3182 operands in OPERANDS. */
3184 void
3185 output_pop_multiple (rtx insn, rtx *operands)
3187 char buf[80];
3188 int ok;
3190 /* Validate the insn again, and compute first_[dp]reg_to_save. */
3191 ok = analyze_pop_multiple_operation (PATTERN (insn));
3192 gcc_assert (ok);
3194 if (first_dreg_to_save == 8)
3195 sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
3196 else if (first_preg_to_save == 6)
3197 sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
3198 else
3199 sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
3200 first_dreg_to_save, first_preg_to_save);
3202 output_asm_insn (buf, operands);
3205 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE. */
3207 static void
3208 single_move_for_movmem (rtx dst, rtx src, machine_mode mode, HOST_WIDE_INT offset)
3210 rtx scratch = gen_reg_rtx (mode);
3211 rtx srcmem, dstmem;
3213 srcmem = adjust_address_nv (src, mode, offset);
3214 dstmem = adjust_address_nv (dst, mode, offset);
3215 emit_move_insn (scratch, srcmem);
3216 emit_move_insn (dstmem, scratch);
3219 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
3220 alignment ALIGN_EXP. Return true if successful, false if we should fall
3221 back on a different method. */
3223 bool
3224 bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
3226 rtx srcreg, destreg, countreg;
3227 HOST_WIDE_INT align = 0;
3228 unsigned HOST_WIDE_INT count = 0;
3230 if (GET_CODE (align_exp) == CONST_INT)
3231 align = INTVAL (align_exp);
3232 if (GET_CODE (count_exp) == CONST_INT)
3234 count = INTVAL (count_exp);
3235 #if 0
3236 if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
3237 return false;
3238 #endif
3241 /* If optimizing for size, only do single copies inline. */
3242 if (optimize_size)
3244 if (count == 2 && align < 2)
3245 return false;
3246 if (count == 4 && align < 4)
3247 return false;
3248 if (count != 1 && count != 2 && count != 4)
3249 return false;
3251 if (align < 2 && count != 1)
3252 return false;
3254 destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
3255 if (destreg != XEXP (dst, 0))
3256 dst = replace_equiv_address_nv (dst, destreg);
3257 srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
3258 if (srcreg != XEXP (src, 0))
3259 src = replace_equiv_address_nv (src, srcreg);
3261 if (count != 0 && align >= 2)
3263 unsigned HOST_WIDE_INT offset = 0;
3265 if (align >= 4)
3267 if ((count & ~3) == 4)
3269 single_move_for_movmem (dst, src, SImode, offset);
3270 offset = 4;
3272 else if (count & ~3)
3274 HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
3275 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3277 emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
3278 cfun->machine->has_loopreg_clobber = true;
3280 if (count & 2)
3282 single_move_for_movmem (dst, src, HImode, offset);
3283 offset += 2;
3286 else
3288 if ((count & ~1) == 2)
3290 single_move_for_movmem (dst, src, HImode, offset);
3291 offset = 2;
3293 else if (count & ~1)
3295 HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
3296 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3298 emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
3299 cfun->machine->has_loopreg_clobber = true;
3302 if (count & 1)
3304 single_move_for_movmem (dst, src, QImode, offset);
3306 return true;
3308 return false;
3311 /* Compute the alignment for a local variable.
3312 TYPE is the data type, and ALIGN is the alignment that
3313 the object would ordinarily have. The value of this macro is used
3314 instead of that alignment to align the object. */
3316 unsigned
3317 bfin_local_alignment (tree type, unsigned align)
3319 /* Increasing alignment for (relatively) big types allows the builtin
3320 memcpy can use 32 bit loads/stores. */
3321 if (TYPE_SIZE (type)
3322 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
3323 && wi::gtu_p (wi::to_wide (TYPE_SIZE (type)), 8)
3324 && align < 32)
3325 return 32;
3326 return align;
3329 /* Implement TARGET_SCHED_ISSUE_RATE. */
3331 static int
3332 bfin_issue_rate (void)
3334 return 3;
3337 static int
3338 bfin_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn, int cost,
3339 unsigned int)
3341 enum attr_type dep_insn_type;
3342 int dep_insn_code_number;
3344 /* Anti and output dependencies have zero cost. */
3345 if (dep_type != 0)
3346 return 0;
3348 dep_insn_code_number = recog_memoized (dep_insn);
3350 /* If we can't recognize the insns, we can't really do anything. */
3351 if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
3352 return cost;
3354 dep_insn_type = get_attr_type (dep_insn);
3356 if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)
3358 rtx pat = PATTERN (dep_insn);
3359 rtx dest, src;
3361 if (GET_CODE (pat) == PARALLEL)
3362 pat = XVECEXP (pat, 0, 0);
3363 dest = SET_DEST (pat);
3364 src = SET_SRC (pat);
3365 if (! ADDRESS_REGNO_P (REGNO (dest))
3366 || ! (MEM_P (src) || D_REGNO_P (REGNO (src))))
3367 return cost;
3368 return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);
3371 return cost;
3374 /* This function acts like NEXT_INSN, but is aware of three-insn bundles and
3375 skips all subsequent parallel instructions if INSN is the start of such
3376 a group. */
3377 static rtx_insn *
3378 find_next_insn_start (rtx_insn *insn)
3380 if (GET_MODE (insn) == SImode)
3382 while (GET_MODE (insn) != QImode)
3383 insn = NEXT_INSN (insn);
3385 return NEXT_INSN (insn);
3388 /* This function acts like PREV_INSN, but is aware of three-insn bundles and
3389 skips all subsequent parallel instructions if INSN is the start of such
3390 a group. */
3391 static rtx_insn *
3392 find_prev_insn_start (rtx_insn *insn)
3394 insn = PREV_INSN (insn);
3395 gcc_assert (GET_MODE (insn) != SImode);
3396 if (GET_MODE (insn) == QImode)
3398 while (GET_MODE (PREV_INSN (insn)) == SImode)
3399 insn = PREV_INSN (insn);
3401 return insn;
3404 /* Implement TARGET_CAN_USE_DOLOOP_P. */
3406 static bool
3407 bfin_can_use_doloop_p (const widest_int &, const widest_int &iterations_max,
3408 unsigned int, bool)
3410 /* Due to limitations in the hardware (an initial loop count of 0
3411 does not loop 2^32 times) we must avoid to generate a hardware
3412 loops when we cannot rule out this case. */
3413 return (wi::ltu_p (iterations_max, 0xFFFFFFFF));
3416 /* Increment the counter for the number of loop instructions in the
3417 current function. */
3419 void
3420 bfin_hardware_loop (void)
3422 cfun->machine->has_hardware_loops++;
3425 /* Maximum loop nesting depth. */
3426 #define MAX_LOOP_DEPTH 2
3428 /* Maximum size of a loop. */
3429 #define MAX_LOOP_LENGTH 2042
3431 /* Maximum distance of the LSETUP instruction from the loop start. */
3432 #define MAX_LSETUP_DISTANCE 30
3434 /* Estimate the length of INSN conservatively. */
3436 static int
3437 length_for_loop (rtx_insn *insn)
3439 int length = 0;
3440 if (JUMP_P (insn) && any_condjump_p (insn) && !optimize_size)
3442 if (ENABLE_WA_SPECULATIVE_SYNCS)
3443 length = 8;
3444 else if (ENABLE_WA_SPECULATIVE_LOADS)
3445 length = 6;
3447 else if (LABEL_P (insn))
3449 if (ENABLE_WA_SPECULATIVE_SYNCS)
3450 length = 4;
3453 if (NONDEBUG_INSN_P (insn))
3454 length += get_attr_length (insn);
3456 return length;
3459 /* Optimize LOOP. */
3461 static bool
3462 hwloop_optimize (hwloop_info loop)
3464 basic_block bb;
3465 rtx_insn *insn, *last_insn;
3466 rtx loop_init, start_label, end_label;
3467 rtx iter_reg, scratchreg, scratch_init;
3468 rtx_insn *scratch_init_insn;
3469 rtx lc_reg, lt_reg, lb_reg;
3470 rtx seq_end;
3471 rtx_insn *seq;
3472 int length;
3473 bool clobber0, clobber1;
3475 if (loop->depth > MAX_LOOP_DEPTH)
3477 if (dump_file)
3478 fprintf (dump_file, ";; loop %d too deep\n", loop->loop_no);
3479 return false;
3482 /* Get the loop iteration register. */
3483 iter_reg = loop->iter_reg;
3485 gcc_assert (REG_P (iter_reg));
3487 scratchreg = NULL_RTX;
3488 scratch_init = iter_reg;
3489 scratch_init_insn = NULL;
3490 if (!PREG_P (iter_reg) && loop->incoming_src)
3492 basic_block bb_in = loop->incoming_src;
3493 int i;
3494 for (i = REG_P0; i <= REG_P5; i++)
3495 if ((df_regs_ever_live_p (i)
3496 || (funkind (TREE_TYPE (current_function_decl)) == SUBROUTINE
3497 && call_used_regs[i]))
3498 && !REGNO_REG_SET_P (df_get_live_out (bb_in), i))
3500 scratchreg = gen_rtx_REG (SImode, i);
3501 break;
3503 for (insn = BB_END (bb_in); insn != BB_HEAD (bb_in);
3504 insn = PREV_INSN (insn))
3506 rtx set;
3507 if (NOTE_P (insn) || BARRIER_P (insn))
3508 continue;
3509 set = single_set (insn);
3510 if (set && rtx_equal_p (SET_DEST (set), iter_reg))
3512 if (CONSTANT_P (SET_SRC (set)))
3514 scratch_init = SET_SRC (set);
3515 scratch_init_insn = insn;
3517 break;
3519 else if (reg_mentioned_p (iter_reg, PATTERN (insn)))
3520 break;
3524 if (loop->incoming_src)
3526 /* Make sure the predecessor is before the loop start label, as required by
3527 the LSETUP instruction. */
3528 length = 0;
3529 insn = BB_END (loop->incoming_src);
3530 /* If we have to insert the LSETUP before a jump, count that jump in the
3531 length. */
3532 if (vec_safe_length (loop->incoming) > 1
3533 || !(loop->incoming->last ()->flags & EDGE_FALLTHRU))
3535 gcc_assert (JUMP_P (insn));
3536 insn = PREV_INSN (insn);
3539 for (; insn && insn != loop->start_label; insn = NEXT_INSN (insn))
3540 length += length_for_loop (insn);
3542 if (!insn)
3544 if (dump_file)
3545 fprintf (dump_file, ";; loop %d lsetup not before loop_start\n",
3546 loop->loop_no);
3547 return false;
3550 /* Account for the pop of a scratch register where necessary. */
3551 if (!PREG_P (iter_reg) && scratchreg == NULL_RTX
3552 && ENABLE_WA_LOAD_LCREGS)
3553 length += 2;
3555 if (length > MAX_LSETUP_DISTANCE)
3557 if (dump_file)
3558 fprintf (dump_file, ";; loop %d lsetup too far away\n", loop->loop_no);
3559 return false;
3563 /* Check if start_label appears before loop_end and calculate the
3564 offset between them. We calculate the length of instructions
3565 conservatively. */
3566 length = 0;
3567 for (insn = loop->start_label;
3568 insn && insn != loop->loop_end;
3569 insn = NEXT_INSN (insn))
3570 length += length_for_loop (insn);
3572 if (!insn)
3574 if (dump_file)
3575 fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
3576 loop->loop_no);
3577 return false;
3580 loop->length = length;
3581 if (loop->length > MAX_LOOP_LENGTH)
3583 if (dump_file)
3584 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
3585 return false;
3588 /* Scan all the blocks to make sure they don't use iter_reg. */
3589 if (loop->iter_reg_used || loop->iter_reg_used_outside)
3591 if (dump_file)
3592 fprintf (dump_file, ";; loop %d uses iterator\n", loop->loop_no);
3593 return false;
3596 clobber0 = (TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC0)
3597 || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LB0)
3598 || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LT0));
3599 clobber1 = (TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC1)
3600 || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LB1)
3601 || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LT1));
3602 if (clobber0 && clobber1)
3604 if (dump_file)
3605 fprintf (dump_file, ";; loop %d no loop reg available\n",
3606 loop->loop_no);
3607 return false;
3610 /* There should be an instruction before the loop_end instruction
3611 in the same basic block. And the instruction must not be
3612 - JUMP
3613 - CONDITIONAL BRANCH
3614 - CALL
3615 - CSYNC
3616 - SSYNC
3617 - Returns (RTS, RTN, etc.) */
3619 bb = loop->tail;
3620 last_insn = find_prev_insn_start (loop->loop_end);
3622 while (1)
3624 for (; last_insn != BB_HEAD (bb);
3625 last_insn = find_prev_insn_start (last_insn))
3626 if (NONDEBUG_INSN_P (last_insn))
3627 break;
3629 if (last_insn != BB_HEAD (bb))
3630 break;
3632 if (single_pred_p (bb)
3633 && single_pred_edge (bb)->flags & EDGE_FALLTHRU
3634 && single_pred (bb) != ENTRY_BLOCK_PTR_FOR_FN (cfun))
3636 bb = single_pred (bb);
3637 last_insn = BB_END (bb);
3638 continue;
3640 else
3642 last_insn = NULL;
3643 break;
3647 if (!last_insn)
3649 if (dump_file)
3650 fprintf (dump_file, ";; loop %d has no last instruction\n",
3651 loop->loop_no);
3652 return false;
3655 if (JUMP_P (last_insn) && !any_condjump_p (last_insn))
3657 if (dump_file)
3658 fprintf (dump_file, ";; loop %d has bad last instruction\n",
3659 loop->loop_no);
3660 return false;
3662 /* In all other cases, try to replace a bad last insn with a nop. */
3663 else if (JUMP_P (last_insn)
3664 || CALL_P (last_insn)
3665 || get_attr_type (last_insn) == TYPE_SYNC
3666 || get_attr_type (last_insn) == TYPE_CALL
3667 || get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI
3668 || recog_memoized (last_insn) == CODE_FOR_return_internal
3669 || GET_CODE (PATTERN (last_insn)) == ASM_INPUT
3670 || asm_noperands (PATTERN (last_insn)) >= 0)
3672 if (loop->length + 2 > MAX_LOOP_LENGTH)
3674 if (dump_file)
3675 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
3676 return false;
3678 if (dump_file)
3679 fprintf (dump_file, ";; loop %d has bad last insn; replace with nop\n",
3680 loop->loop_no);
3682 last_insn = emit_insn_after (gen_forced_nop (), last_insn);
3685 loop->last_insn = last_insn;
3687 /* The loop is good for replacement. */
3688 start_label = loop->start_label;
3689 end_label = gen_label_rtx ();
3690 iter_reg = loop->iter_reg;
3692 if (loop->depth == 1 && !clobber1)
3694 lc_reg = gen_rtx_REG (SImode, REG_LC1);
3695 lb_reg = gen_rtx_REG (SImode, REG_LB1);
3696 lt_reg = gen_rtx_REG (SImode, REG_LT1);
3697 SET_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC1);
3699 else
3701 lc_reg = gen_rtx_REG (SImode, REG_LC0);
3702 lb_reg = gen_rtx_REG (SImode, REG_LB0);
3703 lt_reg = gen_rtx_REG (SImode, REG_LT0);
3704 SET_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC0);
3707 loop->end_label = end_label;
3709 /* Create a sequence containing the loop setup. */
3710 start_sequence ();
3712 /* LSETUP only accepts P registers. If we have one, we can use it,
3713 otherwise there are several ways of working around the problem.
3714 If we're not affected by anomaly 312, we can load the LC register
3715 from any iteration register, and use LSETUP without initialization.
3716 If we've found a P scratch register that's not live here, we can
3717 instead copy the iter_reg into that and use an initializing LSETUP.
3718 If all else fails, push and pop P0 and use it as a scratch. */
3719 if (P_REGNO_P (REGNO (iter_reg)))
3721 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
3722 lb_reg, end_label,
3723 lc_reg, iter_reg);
3724 seq_end = emit_insn (loop_init);
3726 else if (!ENABLE_WA_LOAD_LCREGS && DPREG_P (iter_reg))
3728 emit_insn (gen_movsi (lc_reg, iter_reg));
3729 loop_init = gen_lsetup_without_autoinit (lt_reg, start_label,
3730 lb_reg, end_label,
3731 lc_reg);
3732 seq_end = emit_insn (loop_init);
3734 else if (scratchreg != NULL_RTX)
3736 emit_insn (gen_movsi (scratchreg, scratch_init));
3737 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
3738 lb_reg, end_label,
3739 lc_reg, scratchreg);
3740 seq_end = emit_insn (loop_init);
3741 if (scratch_init_insn != NULL_RTX)
3742 delete_insn (scratch_init_insn);
3744 else
3746 rtx p0reg = gen_rtx_REG (SImode, REG_P0);
3747 rtx push = gen_frame_mem (SImode,
3748 gen_rtx_PRE_DEC (SImode, stack_pointer_rtx));
3749 rtx pop = gen_frame_mem (SImode,
3750 gen_rtx_POST_INC (SImode, stack_pointer_rtx));
3751 emit_insn (gen_movsi (push, p0reg));
3752 emit_insn (gen_movsi (p0reg, scratch_init));
3753 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
3754 lb_reg, end_label,
3755 lc_reg, p0reg);
3756 emit_insn (loop_init);
3757 seq_end = emit_insn (gen_movsi (p0reg, pop));
3758 if (scratch_init_insn != NULL_RTX)
3759 delete_insn (scratch_init_insn);
3762 if (dump_file)
3764 fprintf (dump_file, ";; replacing loop %d initializer with\n",
3765 loop->loop_no);
3766 print_rtl_single (dump_file, loop_init);
3767 fprintf (dump_file, ";; replacing loop %d terminator with\n",
3768 loop->loop_no);
3769 print_rtl_single (dump_file, loop->loop_end);
3772 /* If the loop isn't entered at the top, also create a jump to the entry
3773 point. */
3774 if (!loop->incoming_src && loop->head != loop->incoming_dest)
3776 rtx label = BB_HEAD (loop->incoming_dest);
3777 /* If we're jumping to the final basic block in the loop, and there's
3778 only one cheap instruction before the end (typically an increment of
3779 an induction variable), we can just emit a copy here instead of a
3780 jump. */
3781 if (loop->incoming_dest == loop->tail
3782 && next_real_insn (label) == last_insn
3783 && asm_noperands (last_insn) < 0
3784 && GET_CODE (PATTERN (last_insn)) == SET)
3786 seq_end = emit_insn (copy_rtx (PATTERN (last_insn)));
3788 else
3790 rtx_insn *ret = emit_jump_insn (gen_jump (label));
3791 JUMP_LABEL (ret) = label;
3792 LABEL_NUSES (label)++;
3793 seq_end = emit_barrier ();
3797 seq = get_insns ();
3798 end_sequence ();
3800 if (loop->incoming_src)
3802 rtx_insn *prev = BB_END (loop->incoming_src);
3803 if (vec_safe_length (loop->incoming) > 1
3804 || !(loop->incoming->last ()->flags & EDGE_FALLTHRU))
3806 gcc_assert (JUMP_P (prev));
3807 prev = PREV_INSN (prev);
3808 emit_insn_after (seq, prev);
3810 else
3812 emit_insn_after (seq, prev);
3813 BB_END (loop->incoming_src) = prev;
3814 basic_block new_bb = create_basic_block (seq, seq_end,
3815 loop->head->prev_bb);
3816 edge e = loop->incoming->last ();
3817 gcc_assert (e->flags & EDGE_FALLTHRU);
3818 redirect_edge_succ (e, new_bb);
3819 make_edge (new_bb, loop->head, 0);
3822 else
3824 basic_block new_bb;
3825 edge e;
3826 edge_iterator ei;
3828 if (flag_checking && loop->head != loop->incoming_dest)
3830 /* We aren't entering the loop at the top. Since we've established
3831 that the loop is entered only at one point, this means there
3832 can't be fallthru edges into the head. Any such fallthru edges
3833 would become invalid when we insert the new block, so verify
3834 that this does not in fact happen. */
3835 FOR_EACH_EDGE (e, ei, loop->head->preds)
3836 gcc_assert (!(e->flags & EDGE_FALLTHRU));
3839 emit_insn_before (seq, BB_HEAD (loop->head));
3840 seq = emit_label_before (gen_label_rtx (), seq);
3842 new_bb = create_basic_block (seq, seq_end, loop->head->prev_bb);
3843 FOR_EACH_EDGE (e, ei, loop->incoming)
3845 if (!(e->flags & EDGE_FALLTHRU)
3846 || e->dest != loop->head)
3847 redirect_edge_and_branch_force (e, new_bb);
3848 else
3849 redirect_edge_succ (e, new_bb);
3851 e = make_edge (new_bb, loop->head, 0);
3854 delete_insn (loop->loop_end);
3855 /* Insert the loop end label before the last instruction of the loop. */
3856 emit_label_before (as_a <rtx_code_label *> (loop->end_label),
3857 loop->last_insn);
3859 return true;
3862 /* A callback for the hw-doloop pass. Called when a loop we have discovered
3863 turns out not to be optimizable; we have to split the doloop_end pattern
3864 into a subtract and a test. */
3865 static void
3866 hwloop_fail (hwloop_info loop)
3868 rtx insn = loop->loop_end;
3870 if (DPREG_P (loop->iter_reg))
3872 /* If loop->iter_reg is a DREG or PREG, we can split it here
3873 without scratch register. */
3874 rtx insn, test;
3876 emit_insn_before (gen_addsi3 (loop->iter_reg,
3877 loop->iter_reg,
3878 constm1_rtx),
3879 loop->loop_end);
3881 test = gen_rtx_NE (VOIDmode, loop->iter_reg, const0_rtx);
3882 insn = emit_jump_insn_before (gen_cbranchsi4 (test,
3883 loop->iter_reg, const0_rtx,
3884 loop->start_label),
3885 loop->loop_end);
3887 JUMP_LABEL (insn) = loop->start_label;
3888 LABEL_NUSES (loop->start_label)++;
3889 delete_insn (loop->loop_end);
3891 else
3893 splitting_loops = 1;
3894 try_split (PATTERN (insn), safe_as_a <rtx_insn *> (insn), 1);
3895 splitting_loops = 0;
3899 /* A callback for the hw-doloop pass. This function examines INSN; if
3900 it is a loop_end pattern we recognize, return the reg rtx for the
3901 loop counter. Otherwise, return NULL_RTX. */
3903 static rtx
3904 hwloop_pattern_reg (rtx_insn *insn)
3906 rtx reg;
3908 if (!JUMP_P (insn) || recog_memoized (insn) != CODE_FOR_loop_end)
3909 return NULL_RTX;
3911 reg = SET_DEST (XVECEXP (PATTERN (insn), 0, 1));
3912 if (!REG_P (reg))
3913 return NULL_RTX;
3914 return reg;
3917 static struct hw_doloop_hooks bfin_doloop_hooks =
3919 hwloop_pattern_reg,
3920 hwloop_optimize,
3921 hwloop_fail
3924 /* Run from machine_dependent_reorg, this pass looks for doloop_end insns
3925 and tries to rewrite the RTL of these loops so that proper Blackfin
3926 hardware loops are generated. */
3928 static void
3929 bfin_reorg_loops (void)
3931 reorg_loops (true, &bfin_doloop_hooks);
3934 /* Possibly generate a SEQUENCE out of three insns found in SLOT.
3935 Returns true if we modified the insn chain, false otherwise. */
3936 static bool
3937 gen_one_bundle (rtx_insn *slot[3])
3939 gcc_assert (slot[1] != NULL_RTX);
3941 /* Don't add extra NOPs if optimizing for size. */
3942 if (optimize_size
3943 && (slot[0] == NULL_RTX || slot[2] == NULL_RTX))
3944 return false;
3946 /* Verify that we really can do the multi-issue. */
3947 if (slot[0])
3949 rtx_insn *t = NEXT_INSN (slot[0]);
3950 while (t != slot[1])
3952 if (! NOTE_P (t) || NOTE_KIND (t) != NOTE_INSN_DELETED)
3953 return false;
3954 t = NEXT_INSN (t);
3957 if (slot[2])
3959 rtx_insn *t = NEXT_INSN (slot[1]);
3960 while (t != slot[2])
3962 if (! NOTE_P (t) || NOTE_KIND (t) != NOTE_INSN_DELETED)
3963 return false;
3964 t = NEXT_INSN (t);
3968 if (slot[0] == NULL_RTX)
3970 slot[0] = emit_insn_before (gen_mnop (), slot[1]);
3971 df_insn_rescan (slot[0]);
3973 if (slot[2] == NULL_RTX)
3975 slot[2] = emit_insn_after (gen_forced_nop (), slot[1]);
3976 df_insn_rescan (slot[2]);
3979 /* Avoid line number information being printed inside one bundle. */
3980 if (INSN_LOCATION (slot[1])
3981 && INSN_LOCATION (slot[1]) != INSN_LOCATION (slot[0]))
3982 INSN_LOCATION (slot[1]) = INSN_LOCATION (slot[0]);
3983 if (INSN_LOCATION (slot[2])
3984 && INSN_LOCATION (slot[2]) != INSN_LOCATION (slot[0]))
3985 INSN_LOCATION (slot[2]) = INSN_LOCATION (slot[0]);
3987 /* Terminate them with "|| " instead of ";" in the output. */
3988 PUT_MODE (slot[0], SImode);
3989 PUT_MODE (slot[1], SImode);
3990 /* Terminate the bundle, for the benefit of reorder_var_tracking_notes. */
3991 PUT_MODE (slot[2], QImode);
3992 return true;
3995 /* Go through all insns, and use the information generated during scheduling
3996 to generate SEQUENCEs to represent bundles of instructions issued
3997 simultaneously. */
3999 static void
4000 bfin_gen_bundles (void)
4002 basic_block bb;
4003 FOR_EACH_BB_FN (bb, cfun)
4005 rtx_insn *insn, *next;
4006 rtx_insn *slot[3];
4007 int n_filled = 0;
4009 slot[0] = slot[1] = slot[2] = NULL;
4010 for (insn = BB_HEAD (bb);; insn = next)
4012 int at_end;
4013 rtx_insn *delete_this = NULL;
4015 if (NONDEBUG_INSN_P (insn))
4017 enum attr_type type = get_attr_type (insn);
4019 if (type == TYPE_STALL)
4021 gcc_assert (n_filled == 0);
4022 delete_this = insn;
4024 else
4026 if (type == TYPE_DSP32 || type == TYPE_DSP32SHIFTIMM)
4027 slot[0] = insn;
4028 else if (slot[1] == NULL_RTX)
4029 slot[1] = insn;
4030 else
4031 slot[2] = insn;
4032 n_filled++;
4036 next = NEXT_INSN (insn);
4037 while (next && insn != BB_END (bb)
4038 && !(INSN_P (next)
4039 && GET_CODE (PATTERN (next)) != USE
4040 && GET_CODE (PATTERN (next)) != CLOBBER))
4042 insn = next;
4043 next = NEXT_INSN (insn);
4046 /* BB_END can change due to emitting extra NOPs, so check here. */
4047 at_end = insn == BB_END (bb);
4048 if (delete_this == NULL_RTX && (at_end || GET_MODE (next) == TImode))
4050 if ((n_filled < 2
4051 || !gen_one_bundle (slot))
4052 && slot[0] != NULL_RTX)
4054 rtx pat = PATTERN (slot[0]);
4055 if (GET_CODE (pat) == SET
4056 && GET_CODE (SET_SRC (pat)) == UNSPEC
4057 && XINT (SET_SRC (pat), 1) == UNSPEC_32BIT)
4059 SET_SRC (pat) = XVECEXP (SET_SRC (pat), 0, 0);
4060 INSN_CODE (slot[0]) = -1;
4061 df_insn_rescan (slot[0]);
4064 n_filled = 0;
4065 slot[0] = slot[1] = slot[2] = NULL;
4067 if (delete_this != NULL_RTX)
4068 delete_insn (delete_this);
4069 if (at_end)
4070 break;
4075 /* Ensure that no var tracking notes are emitted in the middle of a
4076 three-instruction bundle. */
4078 static void
4079 reorder_var_tracking_notes (void)
4081 basic_block bb;
4082 FOR_EACH_BB_FN (bb, cfun)
4084 rtx_insn *insn, *next;
4085 rtx_insn *queue = NULL;
4086 bool in_bundle = false;
4088 for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = next)
4090 next = NEXT_INSN (insn);
4092 if (INSN_P (insn))
4094 /* Emit queued up notes at the last instruction of a bundle. */
4095 if (GET_MODE (insn) == QImode)
4097 while (queue)
4099 rtx_insn *next_queue = PREV_INSN (queue);
4100 SET_PREV_INSN (NEXT_INSN (insn)) = queue;
4101 SET_NEXT_INSN (queue) = NEXT_INSN (insn);
4102 SET_NEXT_INSN (insn) = queue;
4103 SET_PREV_INSN (queue) = insn;
4104 queue = next_queue;
4106 in_bundle = false;
4108 else if (GET_MODE (insn) == SImode)
4109 in_bundle = true;
4111 else if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION)
4113 if (in_bundle)
4115 rtx_insn *prev = PREV_INSN (insn);
4116 SET_PREV_INSN (next) = prev;
4117 SET_NEXT_INSN (prev) = next;
4119 SET_PREV_INSN (insn) = queue;
4120 queue = insn;
4127 /* On some silicon revisions, functions shorter than a certain number of cycles
4128 can cause unpredictable behavior. Work around this by adding NOPs as
4129 needed. */
4130 static void
4131 workaround_rts_anomaly (void)
4133 rtx_insn *insn, *first_insn = NULL;
4134 int cycles = 4;
4136 if (! ENABLE_WA_RETS)
4137 return;
4139 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4141 rtx pat;
4143 if (BARRIER_P (insn))
4144 return;
4146 if (NOTE_P (insn) || LABEL_P (insn))
4147 continue;
4149 if (JUMP_TABLE_DATA_P (insn))
4150 continue;
4152 if (first_insn == NULL_RTX)
4153 first_insn = insn;
4154 pat = PATTERN (insn);
4155 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4156 || GET_CODE (pat) == ASM_INPUT
4157 || asm_noperands (pat) >= 0)
4158 continue;
4160 if (CALL_P (insn))
4161 return;
4163 if (JUMP_P (insn))
4165 if (recog_memoized (insn) == CODE_FOR_return_internal)
4166 break;
4168 /* Nothing to worry about for direct jumps. */
4169 if (!any_condjump_p (insn))
4170 return;
4171 if (cycles <= 1)
4172 return;
4173 cycles--;
4175 else if (INSN_P (insn))
4177 rtx pat = PATTERN (insn);
4178 int this_cycles = 1;
4180 if (GET_CODE (pat) == PARALLEL)
4182 if (analyze_push_multiple_operation (pat)
4183 || analyze_pop_multiple_operation (pat))
4184 this_cycles = n_regs_to_save;
4186 else
4188 int icode = recog_memoized (insn);
4190 if (icode == CODE_FOR_link)
4191 this_cycles = 4;
4192 else if (icode == CODE_FOR_unlink)
4193 this_cycles = 3;
4194 else if (icode == CODE_FOR_mulsi3)
4195 this_cycles = 5;
4197 if (this_cycles >= cycles)
4198 return;
4200 cycles -= this_cycles;
4203 while (cycles > 0)
4205 emit_insn_before (gen_nop (), first_insn);
4206 cycles--;
4210 /* Return an insn type for INSN that can be used by the caller for anomaly
4211 workarounds. This differs from plain get_attr_type in that it handles
4212 SEQUENCEs. */
4214 static enum attr_type
4215 type_for_anomaly (rtx_insn *insn)
4217 rtx pat = PATTERN (insn);
4218 if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (pat))
4220 enum attr_type t;
4221 t = get_attr_type (seq->insn (1));
4222 if (t == TYPE_MCLD)
4223 return t;
4224 t = get_attr_type (seq->insn (2));
4225 if (t == TYPE_MCLD)
4226 return t;
4227 return TYPE_MCST;
4229 else
4230 return get_attr_type (insn);
4233 /* Return true iff the address found in MEM is based on the register
4234 NP_REG and optionally has a positive offset. */
4235 static bool
4236 harmless_null_pointer_p (rtx mem, int np_reg)
4238 mem = XEXP (mem, 0);
4239 if (GET_CODE (mem) == POST_INC || GET_CODE (mem) == POST_DEC)
4240 mem = XEXP (mem, 0);
4241 if (REG_P (mem) && (int) REGNO (mem) == np_reg)
4242 return true;
4243 if (GET_CODE (mem) == PLUS
4244 && REG_P (XEXP (mem, 0)) && (int) REGNO (XEXP (mem, 0)) == np_reg)
4246 mem = XEXP (mem, 1);
4247 if (GET_CODE (mem) == CONST_INT && INTVAL (mem) > 0)
4248 return true;
4250 return false;
4253 /* Return nonzero if INSN contains any loads that may trap. */
4255 static bool
4256 trapping_loads_p (rtx_insn *insn, int np_reg, bool after_np_branch)
4258 rtx mem = SET_SRC (single_set (insn));
4260 if (!after_np_branch)
4261 np_reg = -1;
4262 return ((np_reg == -1 || !harmless_null_pointer_p (mem, np_reg))
4263 && may_trap_p (mem));
4266 /* Return INSN if it is of TYPE_MCLD. Alternatively, if INSN is the start of
4267 a three-insn bundle, see if one of them is a load and return that if so.
4268 Return NULL if the insn does not contain loads. */
4269 static rtx_insn *
4270 find_load (rtx_insn *insn)
4272 if (!NONDEBUG_INSN_P (insn))
4273 return NULL;
4274 if (get_attr_type (insn) == TYPE_MCLD)
4275 return insn;
4276 if (GET_MODE (insn) != SImode)
4277 return NULL;
4278 do {
4279 insn = NEXT_INSN (insn);
4280 if ((GET_MODE (insn) == SImode || GET_MODE (insn) == QImode)
4281 && get_attr_type (insn) == TYPE_MCLD)
4282 return insn;
4283 } while (GET_MODE (insn) != QImode);
4284 return NULL;
4287 /* Determine whether PAT is an indirect call pattern. */
4288 static bool
4289 indirect_call_p (rtx pat)
4291 if (GET_CODE (pat) == PARALLEL)
4292 pat = XVECEXP (pat, 0, 0);
4293 if (GET_CODE (pat) == SET)
4294 pat = SET_SRC (pat);
4295 gcc_assert (GET_CODE (pat) == CALL);
4296 pat = XEXP (pat, 0);
4297 gcc_assert (GET_CODE (pat) == MEM);
4298 pat = XEXP (pat, 0);
4300 return REG_P (pat);
4303 /* During workaround_speculation, track whether we're in the shadow of a
4304 conditional branch that tests a P register for NULL. If so, we can omit
4305 emitting NOPs if we see a load from that P register, since a speculative
4306 access at address 0 isn't a problem, and the load is executed in all other
4307 cases anyway.
4308 Global for communication with note_np_check_stores through note_stores.
4310 int np_check_regno = -1;
4311 bool np_after_branch = false;
4313 /* Subroutine of workaround_speculation, called through note_stores. */
4314 static void
4315 note_np_check_stores (rtx x, const_rtx pat ATTRIBUTE_UNUSED,
4316 void *data ATTRIBUTE_UNUSED)
4318 if (REG_P (x) && (REGNO (x) == REG_CC || (int) REGNO (x) == np_check_regno))
4319 np_check_regno = -1;
4322 static void
4323 workaround_speculation (void)
4325 rtx_insn *insn, *next;
4326 rtx_insn *last_condjump = NULL;
4327 int cycles_since_jump = INT_MAX;
4328 int delay_added = 0;
4330 if (! ENABLE_WA_SPECULATIVE_LOADS && ! ENABLE_WA_SPECULATIVE_SYNCS
4331 && ! ENABLE_WA_INDIRECT_CALLS)
4332 return;
4334 /* First pass: find predicted-false branches; if something after them
4335 needs nops, insert them or change the branch to predict true. */
4336 for (insn = get_insns (); insn; insn = next)
4338 rtx pat;
4339 int delay_needed = 0;
4341 next = find_next_insn_start (insn);
4343 if (NOTE_P (insn) || BARRIER_P (insn))
4344 continue;
4345 if (JUMP_TABLE_DATA_P (insn))
4346 continue;
4348 if (LABEL_P (insn))
4350 np_check_regno = -1;
4351 continue;
4354 pat = PATTERN (insn);
4355 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
4356 continue;
4358 if (GET_CODE (pat) == ASM_INPUT || asm_noperands (pat) >= 0)
4360 np_check_regno = -1;
4361 continue;
4364 if (JUMP_P (insn))
4366 /* Is this a condjump based on a null pointer comparison we saw
4367 earlier? */
4368 if (np_check_regno != -1
4369 && recog_memoized (insn) == CODE_FOR_cbranchbi4)
4371 rtx op = XEXP (SET_SRC (PATTERN (insn)), 0);
4372 gcc_assert (GET_CODE (op) == EQ || GET_CODE (op) == NE);
4373 if (GET_CODE (op) == NE)
4374 np_after_branch = true;
4376 if (any_condjump_p (insn)
4377 && ! cbranch_predicted_taken_p (insn))
4379 last_condjump = insn;
4380 delay_added = 0;
4381 cycles_since_jump = 0;
4383 else
4384 cycles_since_jump = INT_MAX;
4386 else if (CALL_P (insn))
4388 np_check_regno = -1;
4389 if (cycles_since_jump < INT_MAX)
4390 cycles_since_jump++;
4391 if (indirect_call_p (pat) && ENABLE_WA_INDIRECT_CALLS)
4393 delay_needed = 3;
4396 else if (NONDEBUG_INSN_P (insn))
4398 rtx_insn *load_insn = find_load (insn);
4399 enum attr_type type = type_for_anomaly (insn);
4401 if (cycles_since_jump < INT_MAX)
4402 cycles_since_jump++;
4404 /* Detect a comparison of a P register with zero. If we later
4405 see a condjump based on it, we have found a null pointer
4406 check. */
4407 if (recog_memoized (insn) == CODE_FOR_compare_eq)
4409 rtx src = SET_SRC (PATTERN (insn));
4410 if (REG_P (XEXP (src, 0))
4411 && P_REGNO_P (REGNO (XEXP (src, 0)))
4412 && XEXP (src, 1) == const0_rtx)
4414 np_check_regno = REGNO (XEXP (src, 0));
4415 np_after_branch = false;
4417 else
4418 np_check_regno = -1;
4421 if (load_insn && ENABLE_WA_SPECULATIVE_LOADS)
4423 if (trapping_loads_p (load_insn, np_check_regno,
4424 np_after_branch))
4425 delay_needed = 4;
4427 else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS)
4428 delay_needed = 3;
4430 /* See if we need to forget about a null pointer comparison
4431 we found earlier. */
4432 if (recog_memoized (insn) != CODE_FOR_compare_eq)
4434 note_stores (PATTERN (insn), note_np_check_stores, NULL);
4435 if (np_check_regno != -1)
4437 if (find_regno_note (insn, REG_INC, np_check_regno))
4438 np_check_regno = -1;
4444 if (delay_needed > cycles_since_jump
4445 && (delay_needed - cycles_since_jump) > delay_added)
4447 rtx pat1;
4448 int num_clobbers;
4449 rtx *op = recog_data.operand;
4451 delay_needed -= cycles_since_jump;
4453 extract_insn (last_condjump);
4454 if (optimize_size)
4456 pat1 = gen_cbranch_predicted_taken (op[0], op[1], op[2],
4457 op[3]);
4458 cycles_since_jump = INT_MAX;
4460 else
4462 /* Do not adjust cycles_since_jump in this case, so that
4463 we'll increase the number of NOPs for a subsequent insn
4464 if necessary. */
4465 pat1 = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
4466 GEN_INT (delay_needed));
4467 delay_added = delay_needed;
4469 PATTERN (last_condjump) = pat1;
4470 INSN_CODE (last_condjump) = recog (pat1, insn, &num_clobbers);
4472 if (CALL_P (insn))
4474 cycles_since_jump = INT_MAX;
4475 delay_added = 0;
4479 /* Second pass: for predicted-true branches, see if anything at the
4480 branch destination needs extra nops. */
4481 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4483 int cycles_since_jump;
4484 if (JUMP_P (insn)
4485 && any_condjump_p (insn)
4486 && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken
4487 || cbranch_predicted_taken_p (insn)))
4489 rtx_insn *target = JUMP_LABEL_AS_INSN (insn);
4490 rtx_insn *label = target;
4491 rtx_insn *next_tgt;
4493 cycles_since_jump = 0;
4494 for (; target && cycles_since_jump < 3; target = next_tgt)
4496 rtx pat;
4498 next_tgt = find_next_insn_start (target);
4500 if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
4501 continue;
4503 if (JUMP_TABLE_DATA_P (target))
4504 continue;
4506 pat = PATTERN (target);
4507 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4508 || GET_CODE (pat) == ASM_INPUT
4509 || asm_noperands (pat) >= 0)
4510 continue;
4512 if (NONDEBUG_INSN_P (target))
4514 rtx_insn *load_insn = find_load (target);
4515 enum attr_type type = type_for_anomaly (target);
4516 int delay_needed = 0;
4517 if (cycles_since_jump < INT_MAX)
4518 cycles_since_jump++;
4520 if (load_insn && ENABLE_WA_SPECULATIVE_LOADS)
4522 if (trapping_loads_p (load_insn, -1, false))
4523 delay_needed = 2;
4525 else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS)
4526 delay_needed = 2;
4528 if (delay_needed > cycles_since_jump)
4530 rtx_insn *prev = prev_real_insn (label);
4531 delay_needed -= cycles_since_jump;
4532 if (dump_file)
4533 fprintf (dump_file, "Adding %d nops after %d\n",
4534 delay_needed, INSN_UID (label));
4535 if (JUMP_P (prev)
4536 && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops)
4538 rtx x;
4539 HOST_WIDE_INT v;
4541 if (dump_file)
4542 fprintf (dump_file,
4543 "Reducing nops on insn %d.\n",
4544 INSN_UID (prev));
4545 x = PATTERN (prev);
4546 x = XVECEXP (x, 0, 1);
4547 v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed;
4548 XVECEXP (x, 0, 0) = GEN_INT (v);
4550 while (delay_needed-- > 0)
4551 emit_insn_after (gen_nop (), label);
4552 break;
4560 /* Called just before the final scheduling pass. If we need to insert NOPs
4561 later on to work around speculative loads, insert special placeholder
4562 insns that cause loads to be delayed for as many cycles as necessary
4563 (and possible). This reduces the number of NOPs we need to add.
4564 The dummy insns we generate are later removed by bfin_gen_bundles. */
4565 static void
4566 add_sched_insns_for_speculation (void)
4568 rtx_insn *insn;
4570 if (! ENABLE_WA_SPECULATIVE_LOADS && ! ENABLE_WA_SPECULATIVE_SYNCS
4571 && ! ENABLE_WA_INDIRECT_CALLS)
4572 return;
4574 /* First pass: find predicted-false branches; if something after them
4575 needs nops, insert them or change the branch to predict true. */
4576 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4578 rtx pat;
4580 if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
4581 continue;
4582 if (JUMP_TABLE_DATA_P (insn))
4583 continue;
4585 pat = PATTERN (insn);
4586 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4587 || GET_CODE (pat) == ASM_INPUT
4588 || asm_noperands (pat) >= 0)
4589 continue;
4591 if (JUMP_P (insn))
4593 if (any_condjump_p (insn)
4594 && !cbranch_predicted_taken_p (insn))
4596 rtx_insn *n = next_real_insn (insn);
4597 emit_insn_before (gen_stall (GEN_INT (3)), n);
4602 /* Second pass: for predicted-true branches, see if anything at the
4603 branch destination needs extra nops. */
4604 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4606 if (JUMP_P (insn)
4607 && any_condjump_p (insn)
4608 && (cbranch_predicted_taken_p (insn)))
4610 rtx target = JUMP_LABEL (insn);
4611 rtx_insn *next = next_real_insn (target);
4613 if (GET_CODE (PATTERN (next)) == UNSPEC_VOLATILE
4614 && get_attr_type (next) == TYPE_STALL)
4615 continue;
4616 emit_insn_before (gen_stall (GEN_INT (1)), next);
4621 /* We use the machine specific reorg pass for emitting CSYNC instructions
4622 after conditional branches as needed.
4624 The Blackfin is unusual in that a code sequence like
4625 if cc jump label
4626 r0 = (p0)
4627 may speculatively perform the load even if the condition isn't true. This
4628 happens for a branch that is predicted not taken, because the pipeline
4629 isn't flushed or stalled, so the early stages of the following instructions,
4630 which perform the memory reference, are allowed to execute before the
4631 jump condition is evaluated.
4632 Therefore, we must insert additional instructions in all places where this
4633 could lead to incorrect behavior. The manual recommends CSYNC, while
4634 VDSP seems to use NOPs (even though its corresponding compiler option is
4635 named CSYNC).
4637 When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
4638 When optimizing for size, we turn the branch into a predicted taken one.
4639 This may be slower due to mispredicts, but saves code size. */
4641 static void
4642 bfin_reorg (void)
4644 /* We are freeing block_for_insn in the toplev to keep compatibility
4645 with old MDEP_REORGS that are not CFG based. Recompute it now. */
4646 compute_bb_for_insn ();
4648 if (flag_schedule_insns_after_reload)
4650 splitting_for_sched = 1;
4651 split_all_insns ();
4652 splitting_for_sched = 0;
4654 add_sched_insns_for_speculation ();
4656 timevar_push (TV_SCHED2);
4657 if (flag_selective_scheduling2
4658 && !maybe_skip_selective_scheduling ())
4659 run_selective_scheduling ();
4660 else
4661 schedule_insns ();
4662 timevar_pop (TV_SCHED2);
4664 /* Examine the schedule and insert nops as necessary for 64-bit parallel
4665 instructions. */
4666 bfin_gen_bundles ();
4669 df_analyze ();
4671 /* Doloop optimization */
4672 if (cfun->machine->has_hardware_loops)
4673 bfin_reorg_loops ();
4675 workaround_speculation ();
4677 if (flag_var_tracking)
4679 timevar_push (TV_VAR_TRACKING);
4680 variable_tracking_main ();
4681 reorder_var_tracking_notes ();
4682 timevar_pop (TV_VAR_TRACKING);
4685 df_finish_pass (false);
4687 workaround_rts_anomaly ();
4690 /* Handle interrupt_handler, exception_handler and nmi_handler function
4691 attributes; arguments as in struct attribute_spec.handler. */
4693 static tree
4694 handle_int_attribute (tree *node, tree name,
4695 tree args ATTRIBUTE_UNUSED,
4696 int flags ATTRIBUTE_UNUSED,
4697 bool *no_add_attrs)
4699 tree x = *node;
4700 if (TREE_CODE (x) == FUNCTION_DECL)
4701 x = TREE_TYPE (x);
4703 if (TREE_CODE (x) != FUNCTION_TYPE)
4705 warning (OPT_Wattributes, "%qE attribute only applies to functions",
4706 name);
4707 *no_add_attrs = true;
4709 else if (funkind (x) != SUBROUTINE)
4710 error ("multiple function type attributes specified");
4712 return NULL_TREE;
4715 /* Return 0 if the attributes for two types are incompatible, 1 if they
4716 are compatible, and 2 if they are nearly compatible (which causes a
4717 warning to be generated). */
4719 static int
4720 bfin_comp_type_attributes (const_tree type1, const_tree type2)
4722 e_funkind kind1, kind2;
4724 if (TREE_CODE (type1) != FUNCTION_TYPE)
4725 return 1;
4727 kind1 = funkind (type1);
4728 kind2 = funkind (type2);
4730 if (kind1 != kind2)
4731 return 0;
4733 /* Check for mismatched modifiers */
4734 if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
4735 != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
4736 return 0;
4738 if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
4739 != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
4740 return 0;
4742 if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
4743 != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
4744 return 0;
4746 if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1))
4747 != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2)))
4748 return 0;
4750 return 1;
4753 /* Handle a "longcall" or "shortcall" attribute; arguments as in
4754 struct attribute_spec.handler. */
4756 static tree
4757 bfin_handle_longcall_attribute (tree *node, tree name,
4758 tree args ATTRIBUTE_UNUSED,
4759 int flags ATTRIBUTE_UNUSED,
4760 bool *no_add_attrs)
4762 if (TREE_CODE (*node) != FUNCTION_TYPE
4763 && TREE_CODE (*node) != FIELD_DECL
4764 && TREE_CODE (*node) != TYPE_DECL)
4766 warning (OPT_Wattributes, "%qE attribute only applies to functions",
4767 name);
4768 *no_add_attrs = true;
4771 if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0
4772 && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node)))
4773 || (strcmp (IDENTIFIER_POINTER (name), "shortcall") == 0
4774 && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node))))
4776 warning (OPT_Wattributes,
4777 "can%'t apply both longcall and shortcall attributes to the same function");
4778 *no_add_attrs = true;
4781 return NULL_TREE;
4784 /* Handle a "l1_text" attribute; arguments as in
4785 struct attribute_spec.handler. */
4787 static tree
4788 bfin_handle_l1_text_attribute (tree *node, tree name, tree ARG_UNUSED (args),
4789 int ARG_UNUSED (flags), bool *no_add_attrs)
4791 tree decl = *node;
4793 if (TREE_CODE (decl) != FUNCTION_DECL)
4795 error ("%qE attribute only applies to functions",
4796 name);
4797 *no_add_attrs = true;
4800 /* The decl may have already been given a section attribute
4801 from a previous declaration. Ensure they match. */
4802 else if (DECL_SECTION_NAME (decl) != NULL
4803 && strcmp (DECL_SECTION_NAME (decl),
4804 ".l1.text") != 0)
4806 error ("section of %q+D conflicts with previous declaration",
4807 decl);
4808 *no_add_attrs = true;
4810 else
4811 set_decl_section_name (decl, ".l1.text");
4813 return NULL_TREE;
4816 /* Handle a "l1_data", "l1_data_A" or "l1_data_B" attribute;
4817 arguments as in struct attribute_spec.handler. */
4819 static tree
4820 bfin_handle_l1_data_attribute (tree *node, tree name, tree ARG_UNUSED (args),
4821 int ARG_UNUSED (flags), bool *no_add_attrs)
4823 tree decl = *node;
4825 if (TREE_CODE (decl) != VAR_DECL)
4827 error ("%qE attribute only applies to variables",
4828 name);
4829 *no_add_attrs = true;
4831 else if (current_function_decl != NULL_TREE
4832 && !TREE_STATIC (decl))
4834 error ("%qE attribute cannot be specified for local variables",
4835 name);
4836 *no_add_attrs = true;
4838 else
4840 const char *section_name;
4842 if (strcmp (IDENTIFIER_POINTER (name), "l1_data") == 0)
4843 section_name = ".l1.data";
4844 else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_A") == 0)
4845 section_name = ".l1.data.A";
4846 else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_B") == 0)
4847 section_name = ".l1.data.B";
4848 else
4849 gcc_unreachable ();
4851 /* The decl may have already been given a section attribute
4852 from a previous declaration. Ensure they match. */
4853 if (DECL_SECTION_NAME (decl) != NULL
4854 && strcmp (DECL_SECTION_NAME (decl),
4855 section_name) != 0)
4857 error ("section of %q+D conflicts with previous declaration",
4858 decl);
4859 *no_add_attrs = true;
4861 else
4862 set_decl_section_name (decl, section_name);
4865 return NULL_TREE;
4868 /* Handle a "l2" attribute; arguments as in struct attribute_spec.handler. */
4870 static tree
4871 bfin_handle_l2_attribute (tree *node, tree ARG_UNUSED (name),
4872 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
4873 bool *no_add_attrs)
4875 tree decl = *node;
4877 if (TREE_CODE (decl) == FUNCTION_DECL)
4879 if (DECL_SECTION_NAME (decl) != NULL
4880 && strcmp (DECL_SECTION_NAME (decl),
4881 ".l2.text") != 0)
4883 error ("section of %q+D conflicts with previous declaration",
4884 decl);
4885 *no_add_attrs = true;
4887 else
4888 set_decl_section_name (decl, ".l2.text");
4890 else if (TREE_CODE (decl) == VAR_DECL)
4892 if (DECL_SECTION_NAME (decl) != NULL
4893 && strcmp (DECL_SECTION_NAME (decl),
4894 ".l2.data") != 0)
4896 error ("section of %q+D conflicts with previous declaration",
4897 decl);
4898 *no_add_attrs = true;
4900 else
4901 set_decl_section_name (decl, ".l2.data");
4904 return NULL_TREE;
4907 /* Table of valid machine attributes. */
4908 static const struct attribute_spec bfin_attribute_table[] =
4910 /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
4911 affects_type_identity, handler, exclude } */
4912 { "interrupt_handler", 0, 0, false, true, true, false,
4913 handle_int_attribute, NULL },
4914 { "exception_handler", 0, 0, false, true, true, false,
4915 handle_int_attribute, NULL },
4916 { "nmi_handler", 0, 0, false, true, true, false, handle_int_attribute,
4917 NULL },
4918 { "nesting", 0, 0, false, true, true, false, NULL, NULL },
4919 { "kspisusp", 0, 0, false, true, true, false, NULL, NULL },
4920 { "saveall", 0, 0, false, true, true, false, NULL, NULL },
4921 { "longcall", 0, 0, false, true, true, false,
4922 bfin_handle_longcall_attribute, NULL },
4923 { "shortcall", 0, 0, false, true, true, false,
4924 bfin_handle_longcall_attribute, NULL },
4925 { "l1_text", 0, 0, true, false, false, false,
4926 bfin_handle_l1_text_attribute, NULL },
4927 { "l1_data", 0, 0, true, false, false, false,
4928 bfin_handle_l1_data_attribute, NULL },
4929 { "l1_data_A", 0, 0, true, false, false, false,
4930 bfin_handle_l1_data_attribute, NULL },
4931 { "l1_data_B", 0, 0, true, false, false, false,
4932 bfin_handle_l1_data_attribute, NULL },
4933 { "l2", 0, 0, true, false, false, false, bfin_handle_l2_attribute, NULL },
4934 { NULL, 0, 0, false, false, false, false, NULL, NULL }
4937 /* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to
4938 tell the assembler to generate pointers to function descriptors in
4939 some cases. */
4941 static bool
4942 bfin_assemble_integer (rtx value, unsigned int size, int aligned_p)
4944 if (TARGET_FDPIC && size == UNITS_PER_WORD)
4946 if (GET_CODE (value) == SYMBOL_REF
4947 && SYMBOL_REF_FUNCTION_P (value))
4949 fputs ("\t.picptr\tfuncdesc(", asm_out_file);
4950 output_addr_const (asm_out_file, value);
4951 fputs (")\n", asm_out_file);
4952 return true;
4954 if (!aligned_p)
4956 /* We've set the unaligned SI op to NULL, so we always have to
4957 handle the unaligned case here. */
4958 assemble_integer_with_op ("\t.4byte\t", value);
4959 return true;
4962 return default_assemble_integer (value, size, aligned_p);
4965 /* Output the assembler code for a thunk function. THUNK_DECL is the
4966 declaration for the thunk function itself, FUNCTION is the decl for
4967 the target function. DELTA is an immediate constant offset to be
4968 added to THIS. If VCALL_OFFSET is nonzero, the word at
4969 *(*this + vcall_offset) should be added to THIS. */
4971 static void
4972 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
4973 tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
4974 HOST_WIDE_INT vcall_offset, tree function)
4976 rtx xops[3];
4977 /* The this parameter is passed as the first argument. */
4978 rtx this_rtx = gen_rtx_REG (Pmode, REG_R0);
4980 /* Adjust the this parameter by a fixed constant. */
4981 if (delta)
4983 xops[1] = this_rtx;
4984 if (delta >= -64 && delta <= 63)
4986 xops[0] = GEN_INT (delta);
4987 output_asm_insn ("%1 += %0;", xops);
4989 else if (delta >= -128 && delta < -64)
4991 xops[0] = GEN_INT (delta + 64);
4992 output_asm_insn ("%1 += -64; %1 += %0;", xops);
4994 else if (delta > 63 && delta <= 126)
4996 xops[0] = GEN_INT (delta - 63);
4997 output_asm_insn ("%1 += 63; %1 += %0;", xops);
4999 else
5001 xops[0] = GEN_INT (delta);
5002 output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
5006 /* Adjust the this parameter by a value stored in the vtable. */
5007 if (vcall_offset)
5009 rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
5010 rtx tmp = gen_rtx_REG (Pmode, REG_R3);
5012 xops[1] = tmp;
5013 xops[2] = p2tmp;
5014 output_asm_insn ("%2 = r0; %2 = [%2];", xops);
5016 /* Adjust the this parameter. */
5017 xops[0] = gen_rtx_MEM (Pmode, plus_constant (Pmode, p2tmp,
5018 vcall_offset));
5019 if (!memory_operand (xops[0], Pmode))
5021 rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
5022 xops[0] = GEN_INT (vcall_offset);
5023 xops[1] = tmp2;
5024 output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
5025 xops[0] = gen_rtx_MEM (Pmode, p2tmp);
5027 xops[2] = this_rtx;
5028 output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
5031 xops[0] = XEXP (DECL_RTL (function), 0);
5032 if (1 || !flag_pic || (*targetm.binds_local_p) (function))
5033 output_asm_insn ("jump.l\t%P0", xops);
5036 /* Codes for all the Blackfin builtins. */
5037 enum bfin_builtins
5039 BFIN_BUILTIN_CSYNC,
5040 BFIN_BUILTIN_SSYNC,
5041 BFIN_BUILTIN_ONES,
5042 BFIN_BUILTIN_COMPOSE_2X16,
5043 BFIN_BUILTIN_EXTRACTLO,
5044 BFIN_BUILTIN_EXTRACTHI,
5046 BFIN_BUILTIN_SSADD_2X16,
5047 BFIN_BUILTIN_SSSUB_2X16,
5048 BFIN_BUILTIN_SSADDSUB_2X16,
5049 BFIN_BUILTIN_SSSUBADD_2X16,
5050 BFIN_BUILTIN_MULT_2X16,
5051 BFIN_BUILTIN_MULTR_2X16,
5052 BFIN_BUILTIN_NEG_2X16,
5053 BFIN_BUILTIN_ABS_2X16,
5054 BFIN_BUILTIN_MIN_2X16,
5055 BFIN_BUILTIN_MAX_2X16,
5057 BFIN_BUILTIN_SSADD_1X16,
5058 BFIN_BUILTIN_SSSUB_1X16,
5059 BFIN_BUILTIN_MULT_1X16,
5060 BFIN_BUILTIN_MULTR_1X16,
5061 BFIN_BUILTIN_NORM_1X16,
5062 BFIN_BUILTIN_NEG_1X16,
5063 BFIN_BUILTIN_ABS_1X16,
5064 BFIN_BUILTIN_MIN_1X16,
5065 BFIN_BUILTIN_MAX_1X16,
5067 BFIN_BUILTIN_SUM_2X16,
5068 BFIN_BUILTIN_DIFFHL_2X16,
5069 BFIN_BUILTIN_DIFFLH_2X16,
5071 BFIN_BUILTIN_SSADD_1X32,
5072 BFIN_BUILTIN_SSSUB_1X32,
5073 BFIN_BUILTIN_NORM_1X32,
5074 BFIN_BUILTIN_ROUND_1X32,
5075 BFIN_BUILTIN_NEG_1X32,
5076 BFIN_BUILTIN_ABS_1X32,
5077 BFIN_BUILTIN_MIN_1X32,
5078 BFIN_BUILTIN_MAX_1X32,
5079 BFIN_BUILTIN_MULT_1X32,
5080 BFIN_BUILTIN_MULT_1X32X32,
5081 BFIN_BUILTIN_MULT_1X32X32NS,
5083 BFIN_BUILTIN_MULHISILL,
5084 BFIN_BUILTIN_MULHISILH,
5085 BFIN_BUILTIN_MULHISIHL,
5086 BFIN_BUILTIN_MULHISIHH,
5088 BFIN_BUILTIN_LSHIFT_1X16,
5089 BFIN_BUILTIN_LSHIFT_2X16,
5090 BFIN_BUILTIN_SSASHIFT_1X16,
5091 BFIN_BUILTIN_SSASHIFT_2X16,
5092 BFIN_BUILTIN_SSASHIFT_1X32,
5094 BFIN_BUILTIN_CPLX_MUL_16,
5095 BFIN_BUILTIN_CPLX_MAC_16,
5096 BFIN_BUILTIN_CPLX_MSU_16,
5098 BFIN_BUILTIN_CPLX_MUL_16_S40,
5099 BFIN_BUILTIN_CPLX_MAC_16_S40,
5100 BFIN_BUILTIN_CPLX_MSU_16_S40,
5102 BFIN_BUILTIN_CPLX_SQU,
5104 BFIN_BUILTIN_LOADBYTES,
5106 BFIN_BUILTIN_MAX
5109 #define def_builtin(NAME, TYPE, CODE) \
5110 do { \
5111 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
5112 NULL, NULL_TREE); \
5113 } while (0)
5115 /* Set up all builtin functions for this target. */
5116 static void
5117 bfin_init_builtins (void)
5119 tree V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
5120 tree void_ftype_void
5121 = build_function_type_list (void_type_node, NULL_TREE);
5122 tree short_ftype_short
5123 = build_function_type_list (short_integer_type_node, short_integer_type_node,
5124 NULL_TREE);
5125 tree short_ftype_int_int
5126 = build_function_type_list (short_integer_type_node, integer_type_node,
5127 integer_type_node, NULL_TREE);
5128 tree int_ftype_int_int
5129 = build_function_type_list (integer_type_node, integer_type_node,
5130 integer_type_node, NULL_TREE);
5131 tree int_ftype_int
5132 = build_function_type_list (integer_type_node, integer_type_node,
5133 NULL_TREE);
5134 tree short_ftype_int
5135 = build_function_type_list (short_integer_type_node, integer_type_node,
5136 NULL_TREE);
5137 tree int_ftype_v2hi_v2hi
5138 = build_function_type_list (integer_type_node, V2HI_type_node,
5139 V2HI_type_node, NULL_TREE);
5140 tree v2hi_ftype_v2hi_v2hi
5141 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5142 V2HI_type_node, NULL_TREE);
5143 tree v2hi_ftype_v2hi_v2hi_v2hi
5144 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5145 V2HI_type_node, V2HI_type_node, NULL_TREE);
5146 tree v2hi_ftype_int_int
5147 = build_function_type_list (V2HI_type_node, integer_type_node,
5148 integer_type_node, NULL_TREE);
5149 tree v2hi_ftype_v2hi_int
5150 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5151 integer_type_node, NULL_TREE);
5152 tree int_ftype_short_short
5153 = build_function_type_list (integer_type_node, short_integer_type_node,
5154 short_integer_type_node, NULL_TREE);
5155 tree v2hi_ftype_v2hi
5156 = build_function_type_list (V2HI_type_node, V2HI_type_node, NULL_TREE);
5157 tree short_ftype_v2hi
5158 = build_function_type_list (short_integer_type_node, V2HI_type_node,
5159 NULL_TREE);
5160 tree int_ftype_pint
5161 = build_function_type_list (integer_type_node,
5162 build_pointer_type (integer_type_node),
5163 NULL_TREE);
5165 /* Add the remaining MMX insns with somewhat more complicated types. */
5166 def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC);
5167 def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC);
5169 def_builtin ("__builtin_bfin_ones", short_ftype_int, BFIN_BUILTIN_ONES);
5171 def_builtin ("__builtin_bfin_compose_2x16", v2hi_ftype_int_int,
5172 BFIN_BUILTIN_COMPOSE_2X16);
5173 def_builtin ("__builtin_bfin_extract_hi", short_ftype_v2hi,
5174 BFIN_BUILTIN_EXTRACTHI);
5175 def_builtin ("__builtin_bfin_extract_lo", short_ftype_v2hi,
5176 BFIN_BUILTIN_EXTRACTLO);
5178 def_builtin ("__builtin_bfin_min_fr2x16", v2hi_ftype_v2hi_v2hi,
5179 BFIN_BUILTIN_MIN_2X16);
5180 def_builtin ("__builtin_bfin_max_fr2x16", v2hi_ftype_v2hi_v2hi,
5181 BFIN_BUILTIN_MAX_2X16);
5183 def_builtin ("__builtin_bfin_add_fr2x16", v2hi_ftype_v2hi_v2hi,
5184 BFIN_BUILTIN_SSADD_2X16);
5185 def_builtin ("__builtin_bfin_sub_fr2x16", v2hi_ftype_v2hi_v2hi,
5186 BFIN_BUILTIN_SSSUB_2X16);
5187 def_builtin ("__builtin_bfin_dspaddsubsat", v2hi_ftype_v2hi_v2hi,
5188 BFIN_BUILTIN_SSADDSUB_2X16);
5189 def_builtin ("__builtin_bfin_dspsubaddsat", v2hi_ftype_v2hi_v2hi,
5190 BFIN_BUILTIN_SSSUBADD_2X16);
5191 def_builtin ("__builtin_bfin_mult_fr2x16", v2hi_ftype_v2hi_v2hi,
5192 BFIN_BUILTIN_MULT_2X16);
5193 def_builtin ("__builtin_bfin_multr_fr2x16", v2hi_ftype_v2hi_v2hi,
5194 BFIN_BUILTIN_MULTR_2X16);
5195 def_builtin ("__builtin_bfin_negate_fr2x16", v2hi_ftype_v2hi,
5196 BFIN_BUILTIN_NEG_2X16);
5197 def_builtin ("__builtin_bfin_abs_fr2x16", v2hi_ftype_v2hi,
5198 BFIN_BUILTIN_ABS_2X16);
5200 def_builtin ("__builtin_bfin_min_fr1x16", short_ftype_int_int,
5201 BFIN_BUILTIN_MIN_1X16);
5202 def_builtin ("__builtin_bfin_max_fr1x16", short_ftype_int_int,
5203 BFIN_BUILTIN_MAX_1X16);
5205 def_builtin ("__builtin_bfin_add_fr1x16", short_ftype_int_int,
5206 BFIN_BUILTIN_SSADD_1X16);
5207 def_builtin ("__builtin_bfin_sub_fr1x16", short_ftype_int_int,
5208 BFIN_BUILTIN_SSSUB_1X16);
5209 def_builtin ("__builtin_bfin_mult_fr1x16", short_ftype_int_int,
5210 BFIN_BUILTIN_MULT_1X16);
5211 def_builtin ("__builtin_bfin_multr_fr1x16", short_ftype_int_int,
5212 BFIN_BUILTIN_MULTR_1X16);
5213 def_builtin ("__builtin_bfin_negate_fr1x16", short_ftype_short,
5214 BFIN_BUILTIN_NEG_1X16);
5215 def_builtin ("__builtin_bfin_abs_fr1x16", short_ftype_short,
5216 BFIN_BUILTIN_ABS_1X16);
5217 def_builtin ("__builtin_bfin_norm_fr1x16", short_ftype_int,
5218 BFIN_BUILTIN_NORM_1X16);
5220 def_builtin ("__builtin_bfin_sum_fr2x16", short_ftype_v2hi,
5221 BFIN_BUILTIN_SUM_2X16);
5222 def_builtin ("__builtin_bfin_diff_hl_fr2x16", short_ftype_v2hi,
5223 BFIN_BUILTIN_DIFFHL_2X16);
5224 def_builtin ("__builtin_bfin_diff_lh_fr2x16", short_ftype_v2hi,
5225 BFIN_BUILTIN_DIFFLH_2X16);
5227 def_builtin ("__builtin_bfin_mulhisill", int_ftype_v2hi_v2hi,
5228 BFIN_BUILTIN_MULHISILL);
5229 def_builtin ("__builtin_bfin_mulhisihl", int_ftype_v2hi_v2hi,
5230 BFIN_BUILTIN_MULHISIHL);
5231 def_builtin ("__builtin_bfin_mulhisilh", int_ftype_v2hi_v2hi,
5232 BFIN_BUILTIN_MULHISILH);
5233 def_builtin ("__builtin_bfin_mulhisihh", int_ftype_v2hi_v2hi,
5234 BFIN_BUILTIN_MULHISIHH);
5236 def_builtin ("__builtin_bfin_min_fr1x32", int_ftype_int_int,
5237 BFIN_BUILTIN_MIN_1X32);
5238 def_builtin ("__builtin_bfin_max_fr1x32", int_ftype_int_int,
5239 BFIN_BUILTIN_MAX_1X32);
5241 def_builtin ("__builtin_bfin_add_fr1x32", int_ftype_int_int,
5242 BFIN_BUILTIN_SSADD_1X32);
5243 def_builtin ("__builtin_bfin_sub_fr1x32", int_ftype_int_int,
5244 BFIN_BUILTIN_SSSUB_1X32);
5245 def_builtin ("__builtin_bfin_negate_fr1x32", int_ftype_int,
5246 BFIN_BUILTIN_NEG_1X32);
5247 def_builtin ("__builtin_bfin_abs_fr1x32", int_ftype_int,
5248 BFIN_BUILTIN_ABS_1X32);
5249 def_builtin ("__builtin_bfin_norm_fr1x32", short_ftype_int,
5250 BFIN_BUILTIN_NORM_1X32);
5251 def_builtin ("__builtin_bfin_round_fr1x32", short_ftype_int,
5252 BFIN_BUILTIN_ROUND_1X32);
5253 def_builtin ("__builtin_bfin_mult_fr1x32", int_ftype_short_short,
5254 BFIN_BUILTIN_MULT_1X32);
5255 def_builtin ("__builtin_bfin_mult_fr1x32x32", int_ftype_int_int,
5256 BFIN_BUILTIN_MULT_1X32X32);
5257 def_builtin ("__builtin_bfin_mult_fr1x32x32NS", int_ftype_int_int,
5258 BFIN_BUILTIN_MULT_1X32X32NS);
5260 /* Shifts. */
5261 def_builtin ("__builtin_bfin_shl_fr1x16", short_ftype_int_int,
5262 BFIN_BUILTIN_SSASHIFT_1X16);
5263 def_builtin ("__builtin_bfin_shl_fr2x16", v2hi_ftype_v2hi_int,
5264 BFIN_BUILTIN_SSASHIFT_2X16);
5265 def_builtin ("__builtin_bfin_lshl_fr1x16", short_ftype_int_int,
5266 BFIN_BUILTIN_LSHIFT_1X16);
5267 def_builtin ("__builtin_bfin_lshl_fr2x16", v2hi_ftype_v2hi_int,
5268 BFIN_BUILTIN_LSHIFT_2X16);
5269 def_builtin ("__builtin_bfin_shl_fr1x32", int_ftype_int_int,
5270 BFIN_BUILTIN_SSASHIFT_1X32);
5272 /* Complex numbers. */
5273 def_builtin ("__builtin_bfin_cmplx_add", v2hi_ftype_v2hi_v2hi,
5274 BFIN_BUILTIN_SSADD_2X16);
5275 def_builtin ("__builtin_bfin_cmplx_sub", v2hi_ftype_v2hi_v2hi,
5276 BFIN_BUILTIN_SSSUB_2X16);
5277 def_builtin ("__builtin_bfin_cmplx_mul", v2hi_ftype_v2hi_v2hi,
5278 BFIN_BUILTIN_CPLX_MUL_16);
5279 def_builtin ("__builtin_bfin_cmplx_mac", v2hi_ftype_v2hi_v2hi_v2hi,
5280 BFIN_BUILTIN_CPLX_MAC_16);
5281 def_builtin ("__builtin_bfin_cmplx_msu", v2hi_ftype_v2hi_v2hi_v2hi,
5282 BFIN_BUILTIN_CPLX_MSU_16);
5283 def_builtin ("__builtin_bfin_cmplx_mul_s40", v2hi_ftype_v2hi_v2hi,
5284 BFIN_BUILTIN_CPLX_MUL_16_S40);
5285 def_builtin ("__builtin_bfin_cmplx_mac_s40", v2hi_ftype_v2hi_v2hi_v2hi,
5286 BFIN_BUILTIN_CPLX_MAC_16_S40);
5287 def_builtin ("__builtin_bfin_cmplx_msu_s40", v2hi_ftype_v2hi_v2hi_v2hi,
5288 BFIN_BUILTIN_CPLX_MSU_16_S40);
5289 def_builtin ("__builtin_bfin_csqu_fr16", v2hi_ftype_v2hi,
5290 BFIN_BUILTIN_CPLX_SQU);
5292 /* "Unaligned" load. */
5293 def_builtin ("__builtin_bfin_loadbytes", int_ftype_pint,
5294 BFIN_BUILTIN_LOADBYTES);
5299 struct builtin_description
5301 const enum insn_code icode;
5302 const char *const name;
5303 const enum bfin_builtins code;
5304 int macflag;
5307 static const struct builtin_description bdesc_2arg[] =
5309 { CODE_FOR_composev2hi, "__builtin_bfin_compose_2x16", BFIN_BUILTIN_COMPOSE_2X16, -1 },
5311 { CODE_FOR_ssashiftv2hi3, "__builtin_bfin_shl_fr2x16", BFIN_BUILTIN_SSASHIFT_2X16, -1 },
5312 { CODE_FOR_ssashifthi3, "__builtin_bfin_shl_fr1x16", BFIN_BUILTIN_SSASHIFT_1X16, -1 },
5313 { CODE_FOR_lshiftv2hi3, "__builtin_bfin_lshl_fr2x16", BFIN_BUILTIN_LSHIFT_2X16, -1 },
5314 { CODE_FOR_lshifthi3, "__builtin_bfin_lshl_fr1x16", BFIN_BUILTIN_LSHIFT_1X16, -1 },
5315 { CODE_FOR_ssashiftsi3, "__builtin_bfin_shl_fr1x32", BFIN_BUILTIN_SSASHIFT_1X32, -1 },
5317 { CODE_FOR_sminhi3, "__builtin_bfin_min_fr1x16", BFIN_BUILTIN_MIN_1X16, -1 },
5318 { CODE_FOR_smaxhi3, "__builtin_bfin_max_fr1x16", BFIN_BUILTIN_MAX_1X16, -1 },
5319 { CODE_FOR_ssaddhi3, "__builtin_bfin_add_fr1x16", BFIN_BUILTIN_SSADD_1X16, -1 },
5320 { CODE_FOR_sssubhi3, "__builtin_bfin_sub_fr1x16", BFIN_BUILTIN_SSSUB_1X16, -1 },
5322 { CODE_FOR_sminsi3, "__builtin_bfin_min_fr1x32", BFIN_BUILTIN_MIN_1X32, -1 },
5323 { CODE_FOR_smaxsi3, "__builtin_bfin_max_fr1x32", BFIN_BUILTIN_MAX_1X32, -1 },
5324 { CODE_FOR_ssaddsi3, "__builtin_bfin_add_fr1x32", BFIN_BUILTIN_SSADD_1X32, -1 },
5325 { CODE_FOR_sssubsi3, "__builtin_bfin_sub_fr1x32", BFIN_BUILTIN_SSSUB_1X32, -1 },
5327 { CODE_FOR_sminv2hi3, "__builtin_bfin_min_fr2x16", BFIN_BUILTIN_MIN_2X16, -1 },
5328 { CODE_FOR_smaxv2hi3, "__builtin_bfin_max_fr2x16", BFIN_BUILTIN_MAX_2X16, -1 },
5329 { CODE_FOR_ssaddv2hi3, "__builtin_bfin_add_fr2x16", BFIN_BUILTIN_SSADD_2X16, -1 },
5330 { CODE_FOR_sssubv2hi3, "__builtin_bfin_sub_fr2x16", BFIN_BUILTIN_SSSUB_2X16, -1 },
5331 { CODE_FOR_ssaddsubv2hi3, "__builtin_bfin_dspaddsubsat", BFIN_BUILTIN_SSADDSUB_2X16, -1 },
5332 { CODE_FOR_sssubaddv2hi3, "__builtin_bfin_dspsubaddsat", BFIN_BUILTIN_SSSUBADD_2X16, -1 },
5334 { CODE_FOR_flag_mulhisi, "__builtin_bfin_mult_fr1x32", BFIN_BUILTIN_MULT_1X32, MACFLAG_NONE },
5335 { CODE_FOR_flag_mulhi, "__builtin_bfin_mult_fr1x16", BFIN_BUILTIN_MULT_1X16, MACFLAG_T },
5336 { CODE_FOR_flag_mulhi, "__builtin_bfin_multr_fr1x16", BFIN_BUILTIN_MULTR_1X16, MACFLAG_NONE },
5337 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_mult_fr2x16", BFIN_BUILTIN_MULT_2X16, MACFLAG_T },
5338 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_multr_fr2x16", BFIN_BUILTIN_MULTR_2X16, MACFLAG_NONE },
5340 { CODE_FOR_mulhisi_ll, "__builtin_bfin_mulhisill", BFIN_BUILTIN_MULHISILL, -1 },
5341 { CODE_FOR_mulhisi_lh, "__builtin_bfin_mulhisilh", BFIN_BUILTIN_MULHISILH, -1 },
5342 { CODE_FOR_mulhisi_hl, "__builtin_bfin_mulhisihl", BFIN_BUILTIN_MULHISIHL, -1 },
5343 { CODE_FOR_mulhisi_hh, "__builtin_bfin_mulhisihh", BFIN_BUILTIN_MULHISIHH, -1 }
5347 static const struct builtin_description bdesc_1arg[] =
5349 { CODE_FOR_loadbytes, "__builtin_bfin_loadbytes", BFIN_BUILTIN_LOADBYTES, 0 },
5351 { CODE_FOR_ones, "__builtin_bfin_ones", BFIN_BUILTIN_ONES, 0 },
5353 { CODE_FOR_clrsbhi2, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16, 0 },
5354 { CODE_FOR_ssneghi2, "__builtin_bfin_negate_fr1x16", BFIN_BUILTIN_NEG_1X16, 0 },
5355 { CODE_FOR_abshi2, "__builtin_bfin_abs_fr1x16", BFIN_BUILTIN_ABS_1X16, 0 },
5357 { CODE_FOR_clrsbsi2, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32, 0 },
5358 { CODE_FOR_ssroundsi2, "__builtin_bfin_round_fr1x32", BFIN_BUILTIN_ROUND_1X32, 0 },
5359 { CODE_FOR_ssnegsi2, "__builtin_bfin_negate_fr1x32", BFIN_BUILTIN_NEG_1X32, 0 },
5360 { CODE_FOR_ssabssi2, "__builtin_bfin_abs_fr1x32", BFIN_BUILTIN_ABS_1X32, 0 },
5362 { CODE_FOR_movv2hi_hi_low, "__builtin_bfin_extract_lo", BFIN_BUILTIN_EXTRACTLO, 0 },
5363 { CODE_FOR_movv2hi_hi_high, "__builtin_bfin_extract_hi", BFIN_BUILTIN_EXTRACTHI, 0 },
5364 { CODE_FOR_ssnegv2hi2, "__builtin_bfin_negate_fr2x16", BFIN_BUILTIN_NEG_2X16, 0 },
5365 { CODE_FOR_ssabsv2hi2, "__builtin_bfin_abs_fr2x16", BFIN_BUILTIN_ABS_2X16, 0 }
5368 /* Errors in the source file can cause expand_expr to return const0_rtx
5369 where we expect a vector. To avoid crashing, use one of the vector
5370 clear instructions. */
5371 static rtx
5372 safe_vector_operand (rtx x, machine_mode mode)
5374 if (x != const0_rtx)
5375 return x;
5376 x = gen_reg_rtx (SImode);
5378 emit_insn (gen_movsi (x, CONST0_RTX (SImode)));
5379 return gen_lowpart (mode, x);
5382 /* Subroutine of bfin_expand_builtin to take care of binop insns. MACFLAG is -1
5383 if this is a normal binary op, or one of the MACFLAG_xxx constants. */
5385 static rtx
5386 bfin_expand_binop_builtin (enum insn_code icode, tree exp, rtx target,
5387 int macflag)
5389 rtx pat;
5390 tree arg0 = CALL_EXPR_ARG (exp, 0);
5391 tree arg1 = CALL_EXPR_ARG (exp, 1);
5392 rtx op0 = expand_normal (arg0);
5393 rtx op1 = expand_normal (arg1);
5394 machine_mode op0mode = GET_MODE (op0);
5395 machine_mode op1mode = GET_MODE (op1);
5396 machine_mode tmode = insn_data[icode].operand[0].mode;
5397 machine_mode mode0 = insn_data[icode].operand[1].mode;
5398 machine_mode mode1 = insn_data[icode].operand[2].mode;
5400 if (VECTOR_MODE_P (mode0))
5401 op0 = safe_vector_operand (op0, mode0);
5402 if (VECTOR_MODE_P (mode1))
5403 op1 = safe_vector_operand (op1, mode1);
5405 if (! target
5406 || GET_MODE (target) != tmode
5407 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5408 target = gen_reg_rtx (tmode);
5410 if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode)
5412 op0mode = HImode;
5413 op0 = gen_lowpart (HImode, op0);
5415 if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode)
5417 op1mode = HImode;
5418 op1 = gen_lowpart (HImode, op1);
5420 /* In case the insn wants input operands in modes different from
5421 the result, abort. */
5422 gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
5423 && (op1mode == mode1 || op1mode == VOIDmode));
5425 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5426 op0 = copy_to_mode_reg (mode0, op0);
5427 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
5428 op1 = copy_to_mode_reg (mode1, op1);
5430 if (macflag == -1)
5431 pat = GEN_FCN (icode) (target, op0, op1);
5432 else
5433 pat = GEN_FCN (icode) (target, op0, op1, GEN_INT (macflag));
5434 if (! pat)
5435 return 0;
5437 emit_insn (pat);
5438 return target;
5441 /* Subroutine of bfin_expand_builtin to take care of unop insns. */
5443 static rtx
5444 bfin_expand_unop_builtin (enum insn_code icode, tree exp,
5445 rtx target)
5447 rtx pat;
5448 tree arg0 = CALL_EXPR_ARG (exp, 0);
5449 rtx op0 = expand_normal (arg0);
5450 machine_mode op0mode = GET_MODE (op0);
5451 machine_mode tmode = insn_data[icode].operand[0].mode;
5452 machine_mode mode0 = insn_data[icode].operand[1].mode;
5454 if (! target
5455 || GET_MODE (target) != tmode
5456 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5457 target = gen_reg_rtx (tmode);
5459 if (VECTOR_MODE_P (mode0))
5460 op0 = safe_vector_operand (op0, mode0);
5462 if (op0mode == SImode && mode0 == HImode)
5464 op0mode = HImode;
5465 op0 = gen_lowpart (HImode, op0);
5467 gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
5469 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5470 op0 = copy_to_mode_reg (mode0, op0);
5472 pat = GEN_FCN (icode) (target, op0);
5473 if (! pat)
5474 return 0;
5475 emit_insn (pat);
5476 return target;
5479 /* Expand an expression EXP that calls a built-in function,
5480 with result going to TARGET if that's convenient
5481 (and in mode MODE if that's convenient).
5482 SUBTARGET may be used as the target for computing one of EXP's operands.
5483 IGNORE is nonzero if the value is to be ignored. */
5485 static rtx
5486 bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
5487 rtx subtarget ATTRIBUTE_UNUSED,
5488 machine_mode mode ATTRIBUTE_UNUSED,
5489 int ignore ATTRIBUTE_UNUSED)
5491 size_t i;
5492 enum insn_code icode;
5493 const struct builtin_description *d;
5494 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
5495 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
5496 tree arg0, arg1, arg2;
5497 rtx op0, op1, op2, accvec, pat, tmp1, tmp2, a0reg, a1reg;
5498 machine_mode tmode, mode0;
5500 switch (fcode)
5502 case BFIN_BUILTIN_CSYNC:
5503 emit_insn (gen_csync ());
5504 return 0;
5505 case BFIN_BUILTIN_SSYNC:
5506 emit_insn (gen_ssync ());
5507 return 0;
5509 case BFIN_BUILTIN_DIFFHL_2X16:
5510 case BFIN_BUILTIN_DIFFLH_2X16:
5511 case BFIN_BUILTIN_SUM_2X16:
5512 arg0 = CALL_EXPR_ARG (exp, 0);
5513 op0 = expand_normal (arg0);
5514 icode = (fcode == BFIN_BUILTIN_DIFFHL_2X16 ? CODE_FOR_subhilov2hi3
5515 : fcode == BFIN_BUILTIN_DIFFLH_2X16 ? CODE_FOR_sublohiv2hi3
5516 : CODE_FOR_ssaddhilov2hi3);
5517 tmode = insn_data[icode].operand[0].mode;
5518 mode0 = insn_data[icode].operand[1].mode;
5520 if (! target
5521 || GET_MODE (target) != tmode
5522 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5523 target = gen_reg_rtx (tmode);
5525 if (VECTOR_MODE_P (mode0))
5526 op0 = safe_vector_operand (op0, mode0);
5528 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5529 op0 = copy_to_mode_reg (mode0, op0);
5531 pat = GEN_FCN (icode) (target, op0, op0);
5532 if (! pat)
5533 return 0;
5534 emit_insn (pat);
5535 return target;
5537 case BFIN_BUILTIN_MULT_1X32X32:
5538 case BFIN_BUILTIN_MULT_1X32X32NS:
5539 arg0 = CALL_EXPR_ARG (exp, 0);
5540 arg1 = CALL_EXPR_ARG (exp, 1);
5541 op0 = expand_normal (arg0);
5542 op1 = expand_normal (arg1);
5543 if (! target
5544 || !register_operand (target, SImode))
5545 target = gen_reg_rtx (SImode);
5546 if (! register_operand (op0, SImode))
5547 op0 = copy_to_mode_reg (SImode, op0);
5548 if (! register_operand (op1, SImode))
5549 op1 = copy_to_mode_reg (SImode, op1);
5551 a1reg = gen_rtx_REG (PDImode, REG_A1);
5552 a0reg = gen_rtx_REG (PDImode, REG_A0);
5553 tmp1 = gen_lowpart (V2HImode, op0);
5554 tmp2 = gen_lowpart (V2HImode, op1);
5555 emit_insn (gen_flag_macinit1hi (a1reg,
5556 gen_lowpart (HImode, op0),
5557 gen_lowpart (HImode, op1),
5558 GEN_INT (MACFLAG_FU)));
5559 emit_insn (gen_lshrpdi3 (a1reg, a1reg, GEN_INT (16)));
5561 if (fcode == BFIN_BUILTIN_MULT_1X32X32)
5562 emit_insn (gen_flag_mul_macv2hi_parts_acconly (a0reg, a1reg, tmp1, tmp2,
5563 const1_rtx, const1_rtx,
5564 const1_rtx, const0_rtx, a1reg,
5565 const0_rtx, GEN_INT (MACFLAG_NONE),
5566 GEN_INT (MACFLAG_M)));
5567 else
5569 /* For saturating multiplication, there's exactly one special case
5570 to be handled: multiplying the smallest negative value with
5571 itself. Due to shift correction in fractional multiplies, this
5572 can overflow. Iff this happens, OP2 will contain 1, which, when
5573 added in 32 bits to the smallest negative, wraps to the largest
5574 positive, which is the result we want. */
5575 op2 = gen_reg_rtx (V2HImode);
5576 emit_insn (gen_packv2hi (op2, tmp1, tmp2, const0_rtx, const0_rtx));
5577 emit_insn (gen_movsibi (gen_rtx_REG (BImode, REG_CC),
5578 gen_lowpart (SImode, op2)));
5579 emit_insn (gen_flag_mul_macv2hi_parts_acconly_andcc0 (a0reg, a1reg, tmp1, tmp2,
5580 const1_rtx, const1_rtx,
5581 const1_rtx, const0_rtx, a1reg,
5582 const0_rtx, GEN_INT (MACFLAG_NONE),
5583 GEN_INT (MACFLAG_M)));
5584 op2 = gen_reg_rtx (SImode);
5585 emit_insn (gen_movbisi (op2, gen_rtx_REG (BImode, REG_CC)));
5587 emit_insn (gen_flag_machi_parts_acconly (a1reg, tmp2, tmp1,
5588 const1_rtx, const0_rtx,
5589 a1reg, const0_rtx, GEN_INT (MACFLAG_M)));
5590 emit_insn (gen_ashrpdi3 (a1reg, a1reg, GEN_INT (15)));
5591 emit_insn (gen_sum_of_accumulators (target, a0reg, a0reg, a1reg));
5592 if (fcode == BFIN_BUILTIN_MULT_1X32X32NS)
5593 emit_insn (gen_addsi3 (target, target, op2));
5594 return target;
5596 case BFIN_BUILTIN_CPLX_MUL_16:
5597 case BFIN_BUILTIN_CPLX_MUL_16_S40:
5598 arg0 = CALL_EXPR_ARG (exp, 0);
5599 arg1 = CALL_EXPR_ARG (exp, 1);
5600 op0 = expand_normal (arg0);
5601 op1 = expand_normal (arg1);
5602 accvec = gen_reg_rtx (V2PDImode);
5603 icode = CODE_FOR_flag_macv2hi_parts;
5604 tmode = insn_data[icode].operand[0].mode;
5606 if (! target
5607 || GET_MODE (target) != V2HImode
5608 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5609 target = gen_reg_rtx (tmode);
5610 if (! register_operand (op0, GET_MODE (op0)))
5611 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
5612 if (! register_operand (op1, GET_MODE (op1)))
5613 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
5615 if (fcode == BFIN_BUILTIN_CPLX_MUL_16)
5616 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
5617 const0_rtx, const0_rtx,
5618 const1_rtx, GEN_INT (MACFLAG_W32)));
5619 else
5620 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
5621 const0_rtx, const0_rtx,
5622 const1_rtx, GEN_INT (MACFLAG_NONE)));
5623 emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
5624 const1_rtx, const1_rtx,
5625 const0_rtx, accvec, const1_rtx, const0_rtx,
5626 GEN_INT (MACFLAG_NONE), accvec));
5628 return target;
5630 case BFIN_BUILTIN_CPLX_MAC_16:
5631 case BFIN_BUILTIN_CPLX_MSU_16:
5632 case BFIN_BUILTIN_CPLX_MAC_16_S40:
5633 case BFIN_BUILTIN_CPLX_MSU_16_S40:
5634 arg0 = CALL_EXPR_ARG (exp, 0);
5635 arg1 = CALL_EXPR_ARG (exp, 1);
5636 arg2 = CALL_EXPR_ARG (exp, 2);
5637 op0 = expand_normal (arg0);
5638 op1 = expand_normal (arg1);
5639 op2 = expand_normal (arg2);
5640 accvec = gen_reg_rtx (V2PDImode);
5641 icode = CODE_FOR_flag_macv2hi_parts;
5642 tmode = insn_data[icode].operand[0].mode;
5644 if (! target
5645 || GET_MODE (target) != V2HImode
5646 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5647 target = gen_reg_rtx (tmode);
5648 if (! register_operand (op1, GET_MODE (op1)))
5649 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
5650 if (! register_operand (op2, GET_MODE (op2)))
5651 op2 = copy_to_mode_reg (GET_MODE (op2), op2);
5653 tmp1 = gen_reg_rtx (SImode);
5654 tmp2 = gen_reg_rtx (SImode);
5655 emit_insn (gen_ashlsi3 (tmp1, gen_lowpart (SImode, op0), GEN_INT (16)));
5656 emit_move_insn (tmp2, gen_lowpart (SImode, op0));
5657 emit_insn (gen_movstricthi_1 (gen_lowpart (HImode, tmp2), const0_rtx));
5658 emit_insn (gen_load_accumulator_pair (accvec, tmp1, tmp2));
5659 if (fcode == BFIN_BUILTIN_CPLX_MAC_16
5660 || fcode == BFIN_BUILTIN_CPLX_MSU_16)
5661 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx,
5662 const0_rtx, const0_rtx,
5663 const1_rtx, accvec, const0_rtx,
5664 const0_rtx,
5665 GEN_INT (MACFLAG_W32)));
5666 else
5667 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx,
5668 const0_rtx, const0_rtx,
5669 const1_rtx, accvec, const0_rtx,
5670 const0_rtx,
5671 GEN_INT (MACFLAG_NONE)));
5672 if (fcode == BFIN_BUILTIN_CPLX_MAC_16
5673 || fcode == BFIN_BUILTIN_CPLX_MAC_16_S40)
5675 tmp1 = const1_rtx;
5676 tmp2 = const0_rtx;
5678 else
5680 tmp1 = const0_rtx;
5681 tmp2 = const1_rtx;
5683 emit_insn (gen_flag_macv2hi_parts (target, op1, op2, const1_rtx,
5684 const1_rtx, const1_rtx,
5685 const0_rtx, accvec, tmp1, tmp2,
5686 GEN_INT (MACFLAG_NONE), accvec));
5688 return target;
5690 case BFIN_BUILTIN_CPLX_SQU:
5691 arg0 = CALL_EXPR_ARG (exp, 0);
5692 op0 = expand_normal (arg0);
5693 accvec = gen_reg_rtx (V2PDImode);
5694 icode = CODE_FOR_flag_mulv2hi;
5695 tmp1 = gen_reg_rtx (V2HImode);
5696 tmp2 = gen_reg_rtx (V2HImode);
5698 if (! target
5699 || GET_MODE (target) != V2HImode
5700 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5701 target = gen_reg_rtx (V2HImode);
5702 if (! register_operand (op0, GET_MODE (op0)))
5703 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
5705 emit_insn (gen_flag_mulv2hi (tmp1, op0, op0, GEN_INT (MACFLAG_NONE)));
5707 emit_insn (gen_flag_mulhi_parts (gen_lowpart (HImode, tmp2), op0, op0,
5708 const0_rtx, const1_rtx,
5709 GEN_INT (MACFLAG_NONE)));
5711 emit_insn (gen_ssaddhi3_high_parts (target, tmp2, tmp2, tmp2, const0_rtx,
5712 const0_rtx));
5713 emit_insn (gen_sssubhi3_low_parts (target, target, tmp1, tmp1,
5714 const0_rtx, const1_rtx));
5716 return target;
5718 default:
5719 break;
5722 for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
5723 if (d->code == fcode)
5724 return bfin_expand_binop_builtin (d->icode, exp, target,
5725 d->macflag);
5727 for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
5728 if (d->code == fcode)
5729 return bfin_expand_unop_builtin (d->icode, exp, target);
5731 gcc_unreachable ();
5734 static void
5735 bfin_conditional_register_usage (void)
5737 /* initialize condition code flag register rtx */
5738 bfin_cc_rtx = gen_rtx_REG (BImode, REG_CC);
5739 bfin_rets_rtx = gen_rtx_REG (Pmode, REG_RETS);
5740 if (TARGET_FDPIC)
5741 call_used_regs[FDPIC_REGNO] = 1;
5742 if (!TARGET_FDPIC && flag_pic)
5744 fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
5745 call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
5749 #undef TARGET_INIT_BUILTINS
5750 #define TARGET_INIT_BUILTINS bfin_init_builtins
5752 #undef TARGET_EXPAND_BUILTIN
5753 #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
5755 #undef TARGET_ASM_GLOBALIZE_LABEL
5756 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label
5758 #undef TARGET_ASM_FILE_START
5759 #define TARGET_ASM_FILE_START output_file_start
5761 #undef TARGET_ATTRIBUTE_TABLE
5762 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
5764 #undef TARGET_COMP_TYPE_ATTRIBUTES
5765 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
5767 #undef TARGET_RTX_COSTS
5768 #define TARGET_RTX_COSTS bfin_rtx_costs
5770 #undef TARGET_ADDRESS_COST
5771 #define TARGET_ADDRESS_COST bfin_address_cost
5773 #undef TARGET_REGISTER_MOVE_COST
5774 #define TARGET_REGISTER_MOVE_COST bfin_register_move_cost
5776 #undef TARGET_MEMORY_MOVE_COST
5777 #define TARGET_MEMORY_MOVE_COST bfin_memory_move_cost
5779 #undef TARGET_ASM_INTEGER
5780 #define TARGET_ASM_INTEGER bfin_assemble_integer
5782 #undef TARGET_MACHINE_DEPENDENT_REORG
5783 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
5785 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
5786 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
5788 #undef TARGET_ASM_OUTPUT_MI_THUNK
5789 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
5790 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
5791 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
5793 #undef TARGET_SCHED_ADJUST_COST
5794 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
5796 #undef TARGET_SCHED_ISSUE_RATE
5797 #define TARGET_SCHED_ISSUE_RATE bfin_issue_rate
5799 #undef TARGET_PROMOTE_FUNCTION_MODE
5800 #define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
5802 #undef TARGET_ARG_PARTIAL_BYTES
5803 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
5805 #undef TARGET_FUNCTION_ARG
5806 #define TARGET_FUNCTION_ARG bfin_function_arg
5808 #undef TARGET_FUNCTION_ARG_ADVANCE
5809 #define TARGET_FUNCTION_ARG_ADVANCE bfin_function_arg_advance
5811 #undef TARGET_PASS_BY_REFERENCE
5812 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
5814 #undef TARGET_SETUP_INCOMING_VARARGS
5815 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
5817 #undef TARGET_STRUCT_VALUE_RTX
5818 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
5820 #undef TARGET_VECTOR_MODE_SUPPORTED_P
5821 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
5823 #undef TARGET_OPTION_OVERRIDE
5824 #define TARGET_OPTION_OVERRIDE bfin_option_override
5826 #undef TARGET_SECONDARY_RELOAD
5827 #define TARGET_SECONDARY_RELOAD bfin_secondary_reload
5829 #undef TARGET_CLASS_LIKELY_SPILLED_P
5830 #define TARGET_CLASS_LIKELY_SPILLED_P bfin_class_likely_spilled_p
5832 #undef TARGET_DELEGITIMIZE_ADDRESS
5833 #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address
5835 #undef TARGET_LEGITIMATE_CONSTANT_P
5836 #define TARGET_LEGITIMATE_CONSTANT_P bfin_legitimate_constant_p
5838 #undef TARGET_CANNOT_FORCE_CONST_MEM
5839 #define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem
5841 #undef TARGET_RETURN_IN_MEMORY
5842 #define TARGET_RETURN_IN_MEMORY bfin_return_in_memory
5844 #undef TARGET_LRA_P
5845 #define TARGET_LRA_P hook_bool_void_false
5847 #undef TARGET_LEGITIMATE_ADDRESS_P
5848 #define TARGET_LEGITIMATE_ADDRESS_P bfin_legitimate_address_p
5850 #undef TARGET_FRAME_POINTER_REQUIRED
5851 #define TARGET_FRAME_POINTER_REQUIRED bfin_frame_pointer_required
5853 #undef TARGET_CAN_ELIMINATE
5854 #define TARGET_CAN_ELIMINATE bfin_can_eliminate
5856 #undef TARGET_CONDITIONAL_REGISTER_USAGE
5857 #define TARGET_CONDITIONAL_REGISTER_USAGE bfin_conditional_register_usage
5859 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
5860 #define TARGET_ASM_TRAMPOLINE_TEMPLATE bfin_asm_trampoline_template
5861 #undef TARGET_TRAMPOLINE_INIT
5862 #define TARGET_TRAMPOLINE_INIT bfin_trampoline_init
5864 #undef TARGET_EXTRA_LIVE_ON_ENTRY
5865 #define TARGET_EXTRA_LIVE_ON_ENTRY bfin_extra_live_on_entry
5867 /* Passes after sched2 can break the helpful TImode annotations that
5868 haifa-sched puts on every insn. Just do scheduling in reorg. */
5869 #undef TARGET_DELAY_SCHED2
5870 #define TARGET_DELAY_SCHED2 true
5872 /* Variable tracking should be run after all optimizations which
5873 change order of insns. It also needs a valid CFG. */
5874 #undef TARGET_DELAY_VARTRACK
5875 #define TARGET_DELAY_VARTRACK true
5877 #undef TARGET_CAN_USE_DOLOOP_P
5878 #define TARGET_CAN_USE_DOLOOP_P bfin_can_use_doloop_p
5880 #undef TARGET_HARD_REGNO_NREGS
5881 #define TARGET_HARD_REGNO_NREGS bfin_hard_regno_nregs
5882 #undef TARGET_HARD_REGNO_MODE_OK
5883 #define TARGET_HARD_REGNO_MODE_OK bfin_hard_regno_mode_ok
5885 #undef TARGET_MODES_TIEABLE_P
5886 #define TARGET_MODES_TIEABLE_P bfin_modes_tieable_p
5888 #undef TARGET_CONSTANT_ALIGNMENT
5889 #define TARGET_CONSTANT_ALIGNMENT constant_alignment_word_strings
5891 struct gcc_target targetm = TARGET_INITIALIZER;