gcc/
[official-gcc.git] / gcc / config / bfin / bfin.c
blob2768266e0ec3ab5f900103fbea4d276482ccc6df
1 /* The Blackfin code generation auxiliary output file.
2 Copyright (C) 2005-2015 Free Software Foundation, Inc.
3 Contributed by Analog Devices.
5 This file is part of GCC.
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published
9 by the Free Software Foundation; either version 3, or (at your
10 option) any later version.
12 GCC is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
21 #include "config.h"
22 #include "system.h"
23 #include "coretypes.h"
24 #include "tm.h"
25 #include "rtl.h"
26 #include "regs.h"
27 #include "hard-reg-set.h"
28 #include "insn-config.h"
29 #include "insn-codes.h"
30 #include "conditions.h"
31 #include "insn-flags.h"
32 #include "output.h"
33 #include "insn-attr.h"
34 #include "hash-set.h"
35 #include "machmode.h"
36 #include "vec.h"
37 #include "double-int.h"
38 #include "input.h"
39 #include "alias.h"
40 #include "symtab.h"
41 #include "wide-int.h"
42 #include "inchash.h"
43 #include "tree.h"
44 #include "fold-const.h"
45 #include "varasm.h"
46 #include "calls.h"
47 #include "flags.h"
48 #include "except.h"
49 #include "function.h"
50 #include "target.h"
51 #include "target-def.h"
52 #include "hashtab.h"
53 #include "statistics.h"
54 #include "real.h"
55 #include "fixed-value.h"
56 #include "expmed.h"
57 #include "dojump.h"
58 #include "explow.h"
59 #include "emit-rtl.h"
60 #include "stmt.h"
61 #include "expr.h"
62 #include "diagnostic-core.h"
63 #include "recog.h"
64 #include "optabs.h"
65 #include "ggc.h"
66 #include "predict.h"
67 #include "dominance.h"
68 #include "cfg.h"
69 #include "cfgrtl.h"
70 #include "cfganal.h"
71 #include "lcm.h"
72 #include "cfgbuild.h"
73 #include "cfgcleanup.h"
74 #include "basic-block.h"
75 #include "hash-map.h"
76 #include "is-a.h"
77 #include "plugin-api.h"
78 #include "ipa-ref.h"
79 #include "cgraph.h"
80 #include "langhooks.h"
81 #include "bfin-protos.h"
82 #include "tm_p.h"
83 #include "tm-preds.h"
84 #include "tm-constrs.h"
85 #include "gt-bfin.h"
86 #include "timevar.h"
87 #include "df.h"
88 #include "sel-sched.h"
89 #include "hw-doloop.h"
90 #include "opts.h"
91 #include "dumpfile.h"
92 #include "builtins.h"
94 /* A C structure for machine-specific, per-function data.
95 This is added to the cfun structure. */
96 struct GTY(()) machine_function
98 /* Set if we are notified by the doloop pass that a hardware loop
99 was created. */
100 int has_hardware_loops;
102 /* Set if we create a memcpy pattern that uses loop registers. */
103 int has_loopreg_clobber;
106 /* RTX for condition code flag register and RETS register */
107 extern GTY(()) rtx bfin_cc_rtx;
108 extern GTY(()) rtx bfin_rets_rtx;
109 rtx bfin_cc_rtx, bfin_rets_rtx;
111 int max_arg_registers = 0;
113 /* Arrays used when emitting register names. */
114 const char *short_reg_names[] = SHORT_REGISTER_NAMES;
115 const char *high_reg_names[] = HIGH_REGISTER_NAMES;
116 const char *dregs_pair_names[] = DREGS_PAIR_NAMES;
117 const char *byte_reg_names[] = BYTE_REGISTER_NAMES;
119 static int arg_regs[] = FUNCTION_ARG_REGISTERS;
120 static int ret_regs[] = FUNCTION_RETURN_REGISTERS;
122 int splitting_for_sched, splitting_loops;
124 static void
125 bfin_globalize_label (FILE *stream, const char *name)
127 fputs (".global ", stream);
128 assemble_name (stream, name);
129 fputc (';',stream);
130 fputc ('\n',stream);
133 static void
134 output_file_start (void)
136 FILE *file = asm_out_file;
137 int i;
139 fprintf (file, ".file \"%s\";\n", LOCATION_FILE (input_location));
141 for (i = 0; arg_regs[i] >= 0; i++)
143 max_arg_registers = i; /* how many arg reg used */
146 /* Examine machine-dependent attributes of function type FUNTYPE and return its
147 type. See the definition of E_FUNKIND. */
149 static e_funkind
150 funkind (const_tree funtype)
152 tree attrs = TYPE_ATTRIBUTES (funtype);
153 if (lookup_attribute ("interrupt_handler", attrs))
154 return INTERRUPT_HANDLER;
155 else if (lookup_attribute ("exception_handler", attrs))
156 return EXCPT_HANDLER;
157 else if (lookup_attribute ("nmi_handler", attrs))
158 return NMI_HANDLER;
159 else
160 return SUBROUTINE;
163 /* Legitimize PIC addresses. If the address is already position-independent,
164 we return ORIG. Newly generated position-independent addresses go into a
165 reg. This is REG if nonzero, otherwise we allocate register(s) as
166 necessary. PICREG is the register holding the pointer to the PIC offset
167 table. */
169 static rtx
170 legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
172 rtx addr = orig;
173 rtx new_rtx = orig;
175 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
177 int unspec;
178 rtx tmp;
180 if (TARGET_ID_SHARED_LIBRARY)
181 unspec = UNSPEC_MOVE_PIC;
182 else if (GET_CODE (addr) == SYMBOL_REF
183 && SYMBOL_REF_FUNCTION_P (addr))
184 unspec = UNSPEC_FUNCDESC_GOT17M4;
185 else
186 unspec = UNSPEC_MOVE_FDPIC;
188 if (reg == 0)
190 gcc_assert (can_create_pseudo_p ());
191 reg = gen_reg_rtx (Pmode);
194 tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), unspec);
195 new_rtx = gen_const_mem (Pmode, gen_rtx_PLUS (Pmode, picreg, tmp));
197 emit_move_insn (reg, new_rtx);
198 if (picreg == pic_offset_table_rtx)
199 crtl->uses_pic_offset_table = 1;
200 return reg;
203 else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
205 rtx base;
207 if (GET_CODE (addr) == CONST)
209 addr = XEXP (addr, 0);
210 gcc_assert (GET_CODE (addr) == PLUS);
213 if (XEXP (addr, 0) == picreg)
214 return orig;
216 if (reg == 0)
218 gcc_assert (can_create_pseudo_p ());
219 reg = gen_reg_rtx (Pmode);
222 base = legitimize_pic_address (XEXP (addr, 0), reg, picreg);
223 addr = legitimize_pic_address (XEXP (addr, 1),
224 base == reg ? NULL_RTX : reg,
225 picreg);
227 if (GET_CODE (addr) == CONST_INT)
229 gcc_assert (! reload_in_progress && ! reload_completed);
230 addr = force_reg (Pmode, addr);
233 if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
235 base = gen_rtx_PLUS (Pmode, base, XEXP (addr, 0));
236 addr = XEXP (addr, 1);
239 return gen_rtx_PLUS (Pmode, base, addr);
242 return new_rtx;
245 /* Stack frame layout. */
247 /* For a given REGNO, determine whether it must be saved in the function
248 prologue. IS_INTHANDLER specifies whether we're generating a normal
249 prologue or an interrupt/exception one. */
250 static bool
251 must_save_p (bool is_inthandler, unsigned regno)
253 if (D_REGNO_P (regno))
255 bool is_eh_return_reg = false;
256 if (crtl->calls_eh_return)
258 unsigned j;
259 for (j = 0; ; j++)
261 unsigned test = EH_RETURN_DATA_REGNO (j);
262 if (test == INVALID_REGNUM)
263 break;
264 if (test == regno)
265 is_eh_return_reg = true;
269 return (is_eh_return_reg
270 || (df_regs_ever_live_p (regno)
271 && !fixed_regs[regno]
272 && (is_inthandler || !call_used_regs[regno])));
274 else if (P_REGNO_P (regno))
276 return ((df_regs_ever_live_p (regno)
277 && !fixed_regs[regno]
278 && (is_inthandler || !call_used_regs[regno]))
279 || (is_inthandler
280 && (ENABLE_WA_05000283 || ENABLE_WA_05000315)
281 && regno == REG_P5)
282 || (!TARGET_FDPIC
283 && regno == PIC_OFFSET_TABLE_REGNUM
284 && (crtl->uses_pic_offset_table
285 || (TARGET_ID_SHARED_LIBRARY && !crtl->is_leaf))));
287 else
288 return ((is_inthandler || !call_used_regs[regno])
289 && (df_regs_ever_live_p (regno)
290 || (!leaf_function_p () && call_used_regs[regno])));
294 /* Compute the number of DREGS to save with a push_multiple operation.
295 This could include registers that aren't modified in the function,
296 since push_multiple only takes a range of registers.
297 If IS_INTHANDLER, then everything that is live must be saved, even
298 if normally call-clobbered.
299 If CONSECUTIVE, return the number of registers we can save in one
300 instruction with a push/pop multiple instruction. */
302 static int
303 n_dregs_to_save (bool is_inthandler, bool consecutive)
305 int count = 0;
306 unsigned i;
308 for (i = REG_R7 + 1; i-- != REG_R0;)
310 if (must_save_p (is_inthandler, i))
311 count++;
312 else if (consecutive)
313 return count;
315 return count;
318 /* Like n_dregs_to_save, but compute number of PREGS to save. */
320 static int
321 n_pregs_to_save (bool is_inthandler, bool consecutive)
323 int count = 0;
324 unsigned i;
326 for (i = REG_P5 + 1; i-- != REG_P0;)
327 if (must_save_p (is_inthandler, i))
328 count++;
329 else if (consecutive)
330 return count;
331 return count;
334 /* Determine if we are going to save the frame pointer in the prologue. */
336 static bool
337 must_save_fp_p (void)
339 return df_regs_ever_live_p (REG_FP);
342 /* Determine if we are going to save the RETS register. */
343 static bool
344 must_save_rets_p (void)
346 return df_regs_ever_live_p (REG_RETS);
349 static bool
350 stack_frame_needed_p (void)
352 /* EH return puts a new return address into the frame using an
353 address relative to the frame pointer. */
354 if (crtl->calls_eh_return)
355 return true;
356 return frame_pointer_needed;
359 /* Emit code to save registers in the prologue. SAVEALL is nonzero if we
360 must save all registers; this is used for interrupt handlers.
361 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
362 this for an interrupt (or exception) handler. */
364 static void
365 expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler)
367 rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
368 rtx predec = gen_rtx_MEM (SImode, predec1);
369 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler, false);
370 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler, false);
371 int ndregs_consec = saveall ? 8 : n_dregs_to_save (is_inthandler, true);
372 int npregs_consec = saveall ? 6 : n_pregs_to_save (is_inthandler, true);
373 int dregno, pregno;
374 int total_consec = ndregs_consec + npregs_consec;
375 int i, d_to_save;
377 if (saveall || is_inthandler)
379 rtx_insn *insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
381 RTX_FRAME_RELATED_P (insn) = 1;
382 for (dregno = REG_LT0; dregno <= REG_LB1; dregno++)
383 if (! crtl->is_leaf
384 || cfun->machine->has_hardware_loops
385 || cfun->machine->has_loopreg_clobber
386 || (ENABLE_WA_05000257
387 && (dregno == REG_LC0 || dregno == REG_LC1)))
389 insn = emit_move_insn (predec, gen_rtx_REG (SImode, dregno));
390 RTX_FRAME_RELATED_P (insn) = 1;
394 if (total_consec != 0)
396 rtx_insn *insn;
397 rtx val = GEN_INT (-total_consec * 4);
398 rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_consec + 2));
400 XVECEXP (pat, 0, 0) = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, val),
401 UNSPEC_PUSH_MULTIPLE);
402 XVECEXP (pat, 0, total_consec + 1) = gen_rtx_SET (spreg,
403 gen_rtx_PLUS (Pmode,
404 spreg,
405 val));
406 RTX_FRAME_RELATED_P (XVECEXP (pat, 0, total_consec + 1)) = 1;
407 d_to_save = ndregs_consec;
408 dregno = REG_R7 + 1 - ndregs_consec;
409 pregno = REG_P5 + 1 - npregs_consec;
410 for (i = 0; i < total_consec; i++)
412 rtx memref = gen_rtx_MEM (word_mode,
413 gen_rtx_PLUS (Pmode, spreg,
414 GEN_INT (- i * 4 - 4)));
415 rtx subpat;
416 if (d_to_save > 0)
418 subpat = gen_rtx_SET (memref, gen_rtx_REG (word_mode, dregno++));
419 d_to_save--;
421 else
423 subpat = gen_rtx_SET (memref, gen_rtx_REG (word_mode, pregno++));
425 XVECEXP (pat, 0, i + 1) = subpat;
426 RTX_FRAME_RELATED_P (subpat) = 1;
428 insn = emit_insn (pat);
429 RTX_FRAME_RELATED_P (insn) = 1;
432 for (dregno = REG_R0; ndregs != ndregs_consec; dregno++)
434 if (must_save_p (is_inthandler, dregno))
436 rtx_insn *insn =
437 emit_move_insn (predec, gen_rtx_REG (word_mode, dregno));
438 RTX_FRAME_RELATED_P (insn) = 1;
439 ndregs--;
442 for (pregno = REG_P0; npregs != npregs_consec; pregno++)
444 if (must_save_p (is_inthandler, pregno))
446 rtx_insn *insn =
447 emit_move_insn (predec, gen_rtx_REG (word_mode, pregno));
448 RTX_FRAME_RELATED_P (insn) = 1;
449 npregs--;
452 for (i = REG_P7 + 1; i < REG_CC; i++)
453 if (saveall
454 || (is_inthandler
455 && (df_regs_ever_live_p (i)
456 || (!leaf_function_p () && call_used_regs[i]))))
458 rtx_insn *insn;
459 if (i == REG_A0 || i == REG_A1)
460 insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1),
461 gen_rtx_REG (PDImode, i));
462 else
463 insn = emit_move_insn (predec, gen_rtx_REG (SImode, i));
464 RTX_FRAME_RELATED_P (insn) = 1;
468 /* Emit code to restore registers in the epilogue. SAVEALL is nonzero if we
469 must save all registers; this is used for interrupt handlers.
470 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
471 this for an interrupt (or exception) handler. */
473 static void
474 expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler)
476 rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
477 rtx postinc = gen_rtx_MEM (SImode, postinc1);
479 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler, false);
480 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler, false);
481 int ndregs_consec = saveall ? 8 : n_dregs_to_save (is_inthandler, true);
482 int npregs_consec = saveall ? 6 : n_pregs_to_save (is_inthandler, true);
483 int total_consec = ndregs_consec + npregs_consec;
484 int i, regno;
485 rtx_insn *insn;
487 /* A slightly crude technique to stop flow from trying to delete "dead"
488 insns. */
489 MEM_VOLATILE_P (postinc) = 1;
491 for (i = REG_CC - 1; i > REG_P7; i--)
492 if (saveall
493 || (is_inthandler
494 && (df_regs_ever_live_p (i)
495 || (!leaf_function_p () && call_used_regs[i]))))
497 if (i == REG_A0 || i == REG_A1)
499 rtx mem = gen_rtx_MEM (PDImode, postinc1);
500 MEM_VOLATILE_P (mem) = 1;
501 emit_move_insn (gen_rtx_REG (PDImode, i), mem);
503 else
504 emit_move_insn (gen_rtx_REG (SImode, i), postinc);
507 regno = REG_P5 - npregs_consec;
508 for (; npregs != npregs_consec; regno--)
510 if (must_save_p (is_inthandler, regno))
512 emit_move_insn (gen_rtx_REG (word_mode, regno), postinc);
513 npregs--;
516 regno = REG_R7 - ndregs_consec;
517 for (; ndregs != ndregs_consec; regno--)
519 if (must_save_p (is_inthandler, regno))
521 emit_move_insn (gen_rtx_REG (word_mode, regno), postinc);
522 ndregs--;
526 if (total_consec != 0)
528 rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_consec + 1));
529 XVECEXP (pat, 0, 0)
530 = gen_rtx_SET (spreg, gen_rtx_PLUS (Pmode, spreg,
531 GEN_INT (total_consec * 4)));
533 if (npregs_consec > 0)
534 regno = REG_P5 + 1;
535 else
536 regno = REG_R7 + 1;
538 for (i = 0; i < total_consec; i++)
540 rtx addr = (i > 0
541 ? gen_rtx_PLUS (Pmode, spreg, GEN_INT (i * 4))
542 : spreg);
543 rtx memref = gen_rtx_MEM (word_mode, addr);
545 regno--;
546 XVECEXP (pat, 0, i + 1)
547 = gen_rtx_SET (gen_rtx_REG (word_mode, regno), memref);
549 if (npregs_consec > 0)
551 if (--npregs_consec == 0)
552 regno = REG_R7 + 1;
556 insn = emit_insn (pat);
557 RTX_FRAME_RELATED_P (insn) = 1;
559 if (saveall || is_inthandler)
561 for (regno = REG_LB1; regno >= REG_LT0; regno--)
562 if (! crtl->is_leaf
563 || cfun->machine->has_hardware_loops
564 || cfun->machine->has_loopreg_clobber
565 || (ENABLE_WA_05000257 && (regno == REG_LC0 || regno == REG_LC1)))
566 emit_move_insn (gen_rtx_REG (SImode, regno), postinc);
568 emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
572 /* Perform any needed actions needed for a function that is receiving a
573 variable number of arguments.
575 CUM is as above.
577 MODE and TYPE are the mode and type of the current parameter.
579 PRETEND_SIZE is a variable that should be set to the amount of stack
580 that must be pushed by the prolog to pretend that our caller pushed
583 Normally, this macro will push all remaining incoming registers on the
584 stack and set PRETEND_SIZE to the length of the registers pushed.
586 Blackfin specific :
587 - VDSP C compiler manual (our ABI) says that a variable args function
588 should save the R0, R1 and R2 registers in the stack.
589 - The caller will always leave space on the stack for the
590 arguments that are passed in registers, so we dont have
591 to leave any extra space.
592 - now, the vastart pointer can access all arguments from the stack. */
594 static void
595 setup_incoming_varargs (cumulative_args_t cum,
596 machine_mode mode ATTRIBUTE_UNUSED,
597 tree type ATTRIBUTE_UNUSED, int *pretend_size,
598 int no_rtl)
600 rtx mem;
601 int i;
603 if (no_rtl)
604 return;
606 /* The move for named arguments will be generated automatically by the
607 compiler. We need to generate the move rtx for the unnamed arguments
608 if they are in the first 3 words. We assume at least 1 named argument
609 exists, so we never generate [ARGP] = R0 here. */
611 for (i = get_cumulative_args (cum)->words + 1; i < max_arg_registers; i++)
613 mem = gen_rtx_MEM (Pmode,
614 plus_constant (Pmode, arg_pointer_rtx,
615 (i * UNITS_PER_WORD)));
616 emit_move_insn (mem, gen_rtx_REG (Pmode, i));
619 *pretend_size = 0;
622 /* Value should be nonzero if functions must have frame pointers.
623 Zero means the frame pointer need not be set up (and parms may
624 be accessed via the stack pointer) in functions that seem suitable. */
626 static bool
627 bfin_frame_pointer_required (void)
629 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
631 if (fkind != SUBROUTINE)
632 return true;
634 /* We turn on -fomit-frame-pointer if -momit-leaf-frame-pointer is used,
635 so we have to override it for non-leaf functions. */
636 if (TARGET_OMIT_LEAF_FRAME_POINTER && ! crtl->is_leaf)
637 return true;
639 return false;
642 /* Return the number of registers pushed during the prologue. */
644 static int
645 n_regs_saved_by_prologue (void)
647 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
648 bool is_inthandler = fkind != SUBROUTINE;
649 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
650 bool all = (lookup_attribute ("saveall", attrs) != NULL_TREE
651 || (is_inthandler && !crtl->is_leaf));
652 int ndregs = all ? 8 : n_dregs_to_save (is_inthandler, false);
653 int npregs = all ? 6 : n_pregs_to_save (is_inthandler, false);
654 int n = ndregs + npregs;
655 int i;
657 if (all || stack_frame_needed_p ())
658 n += 2;
659 else
661 if (must_save_fp_p ())
662 n++;
663 if (must_save_rets_p ())
664 n++;
667 if (fkind != SUBROUTINE || all)
669 /* Increment once for ASTAT. */
670 n++;
671 if (! crtl->is_leaf
672 || cfun->machine->has_hardware_loops
673 || cfun->machine->has_loopreg_clobber)
675 n += 6;
679 if (fkind != SUBROUTINE)
681 /* RETE/X/N. */
682 if (lookup_attribute ("nesting", attrs))
683 n++;
686 for (i = REG_P7 + 1; i < REG_CC; i++)
687 if (all
688 || (fkind != SUBROUTINE
689 && (df_regs_ever_live_p (i)
690 || (!leaf_function_p () && call_used_regs[i]))))
691 n += i == REG_A0 || i == REG_A1 ? 2 : 1;
693 return n;
696 /* Given FROM and TO register numbers, say whether this elimination is
697 allowed. Frame pointer elimination is automatically handled.
699 All other eliminations are valid. */
701 static bool
702 bfin_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
704 return (to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true);
707 /* Return the offset between two registers, one to be eliminated, and the other
708 its replacement, at the start of a routine. */
710 HOST_WIDE_INT
711 bfin_initial_elimination_offset (int from, int to)
713 HOST_WIDE_INT offset = 0;
715 if (from == ARG_POINTER_REGNUM)
716 offset = n_regs_saved_by_prologue () * 4;
718 if (to == STACK_POINTER_REGNUM)
720 if (crtl->outgoing_args_size >= FIXED_STACK_AREA)
721 offset += crtl->outgoing_args_size;
722 else if (crtl->outgoing_args_size)
723 offset += FIXED_STACK_AREA;
725 offset += get_frame_size ();
728 return offset;
731 /* Emit code to load a constant CONSTANT into register REG; setting
732 RTX_FRAME_RELATED_P on all insns we generate if RELATED is true.
733 Make sure that the insns we generate need not be split. */
735 static void
736 frame_related_constant_load (rtx reg, HOST_WIDE_INT constant, bool related)
738 rtx_insn *insn;
739 rtx cst = GEN_INT (constant);
741 if (constant >= -32768 && constant < 65536)
742 insn = emit_move_insn (reg, cst);
743 else
745 /* We don't call split_load_immediate here, since dwarf2out.c can get
746 confused about some of the more clever sequences it can generate. */
747 insn = emit_insn (gen_movsi_high (reg, cst));
748 if (related)
749 RTX_FRAME_RELATED_P (insn) = 1;
750 insn = emit_insn (gen_movsi_low (reg, reg, cst));
752 if (related)
753 RTX_FRAME_RELATED_P (insn) = 1;
756 /* Generate efficient code to add a value to a P register.
757 Set RTX_FRAME_RELATED_P on the generated insns if FRAME is nonzero.
758 EPILOGUE_P is zero if this function is called for prologue,
759 otherwise it's nonzero. And it's less than zero if this is for
760 sibcall epilogue. */
762 static void
763 add_to_reg (rtx reg, HOST_WIDE_INT value, int frame, int epilogue_p)
765 if (value == 0)
766 return;
768 /* Choose whether to use a sequence using a temporary register, or
769 a sequence with multiple adds. We can add a signed 7-bit value
770 in one instruction. */
771 if (value > 120 || value < -120)
773 rtx tmpreg;
774 rtx tmpreg2;
775 rtx_insn *insn;
777 tmpreg2 = NULL_RTX;
779 /* For prologue or normal epilogue, P1 can be safely used
780 as the temporary register. For sibcall epilogue, we try to find
781 a call used P register, which will be restored in epilogue.
782 If we cannot find such a P register, we have to use one I register
783 to help us. */
785 if (epilogue_p >= 0)
786 tmpreg = gen_rtx_REG (SImode, REG_P1);
787 else
789 int i;
790 for (i = REG_P0; i <= REG_P5; i++)
791 if ((df_regs_ever_live_p (i) && ! call_used_regs[i])
792 || (!TARGET_FDPIC
793 && i == PIC_OFFSET_TABLE_REGNUM
794 && (crtl->uses_pic_offset_table
795 || (TARGET_ID_SHARED_LIBRARY
796 && ! crtl->is_leaf))))
797 break;
798 if (i <= REG_P5)
799 tmpreg = gen_rtx_REG (SImode, i);
800 else
802 tmpreg = gen_rtx_REG (SImode, REG_P1);
803 tmpreg2 = gen_rtx_REG (SImode, REG_I0);
804 emit_move_insn (tmpreg2, tmpreg);
808 if (frame)
809 frame_related_constant_load (tmpreg, value, TRUE);
810 else
811 insn = emit_move_insn (tmpreg, GEN_INT (value));
813 insn = emit_insn (gen_addsi3 (reg, reg, tmpreg));
814 if (frame)
815 RTX_FRAME_RELATED_P (insn) = 1;
817 if (tmpreg2 != NULL_RTX)
818 emit_move_insn (tmpreg, tmpreg2);
820 else
823 int size = value;
824 rtx_insn *insn;
826 if (size > 60)
827 size = 60;
828 else if (size < -60)
829 /* We could use -62, but that would leave the stack unaligned, so
830 it's no good. */
831 size = -60;
833 insn = emit_insn (gen_addsi3 (reg, reg, GEN_INT (size)));
834 if (frame)
835 RTX_FRAME_RELATED_P (insn) = 1;
836 value -= size;
838 while (value != 0);
841 /* Generate a LINK insn for a frame sized FRAME_SIZE. If this constant
842 is too large, generate a sequence of insns that has the same effect.
843 SPREG contains (reg:SI REG_SP). */
845 static void
846 emit_link_insn (rtx spreg, HOST_WIDE_INT frame_size)
848 HOST_WIDE_INT link_size = frame_size;
849 rtx_insn *insn;
850 int i;
852 if (link_size > 262140)
853 link_size = 262140;
855 /* Use a LINK insn with as big a constant as possible, then subtract
856 any remaining size from the SP. */
857 insn = emit_insn (gen_link (GEN_INT (-8 - link_size)));
858 RTX_FRAME_RELATED_P (insn) = 1;
860 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
862 rtx set = XVECEXP (PATTERN (insn), 0, i);
863 gcc_assert (GET_CODE (set) == SET);
864 RTX_FRAME_RELATED_P (set) = 1;
867 frame_size -= link_size;
869 if (frame_size > 0)
871 /* Must use a call-clobbered PREG that isn't the static chain. */
872 rtx tmpreg = gen_rtx_REG (Pmode, REG_P1);
874 frame_related_constant_load (tmpreg, -frame_size, TRUE);
875 insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg));
876 RTX_FRAME_RELATED_P (insn) = 1;
880 /* Return the number of bytes we must reserve for outgoing arguments
881 in the current function's stack frame. */
883 static HOST_WIDE_INT
884 arg_area_size (void)
886 if (crtl->outgoing_args_size)
888 if (crtl->outgoing_args_size >= FIXED_STACK_AREA)
889 return crtl->outgoing_args_size;
890 else
891 return FIXED_STACK_AREA;
893 return 0;
896 /* Save RETS and FP, and allocate a stack frame. ALL is true if the
897 function must save all its registers (true only for certain interrupt
898 handlers). */
900 static void
901 do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all)
903 frame_size += arg_area_size ();
905 if (all
906 || stack_frame_needed_p ()
907 || (must_save_rets_p () && must_save_fp_p ()))
908 emit_link_insn (spreg, frame_size);
909 else
911 if (must_save_rets_p ())
913 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
914 gen_rtx_PRE_DEC (Pmode, spreg)),
915 bfin_rets_rtx);
916 rtx_insn *insn = emit_insn (pat);
917 RTX_FRAME_RELATED_P (insn) = 1;
919 if (must_save_fp_p ())
921 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
922 gen_rtx_PRE_DEC (Pmode, spreg)),
923 gen_rtx_REG (Pmode, REG_FP));
924 rtx_insn *insn = emit_insn (pat);
925 RTX_FRAME_RELATED_P (insn) = 1;
927 add_to_reg (spreg, -frame_size, 1, 0);
931 /* Like do_link, but used for epilogues to deallocate the stack frame.
932 EPILOGUE_P is zero if this function is called for prologue,
933 otherwise it's nonzero. And it's less than zero if this is for
934 sibcall epilogue. */
936 static void
937 do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all, int epilogue_p)
939 frame_size += arg_area_size ();
941 if (stack_frame_needed_p ())
942 emit_insn (gen_unlink ());
943 else
945 rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg));
947 add_to_reg (spreg, frame_size, 0, epilogue_p);
948 if (all || must_save_fp_p ())
950 rtx fpreg = gen_rtx_REG (Pmode, REG_FP);
951 emit_move_insn (fpreg, postinc);
952 emit_use (fpreg);
954 if (all || must_save_rets_p ())
956 emit_move_insn (bfin_rets_rtx, postinc);
957 emit_use (bfin_rets_rtx);
962 /* Generate a prologue suitable for a function of kind FKIND. This is
963 called for interrupt and exception handler prologues.
964 SPREG contains (reg:SI REG_SP). */
966 static void
967 expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind, bool all)
969 HOST_WIDE_INT frame_size = get_frame_size ();
970 rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
971 rtx predec = gen_rtx_MEM (SImode, predec1);
972 rtx_insn *insn;
973 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
974 tree kspisusp = lookup_attribute ("kspisusp", attrs);
976 if (kspisusp)
978 insn = emit_move_insn (spreg, gen_rtx_REG (Pmode, REG_USP));
979 RTX_FRAME_RELATED_P (insn) = 1;
982 /* We need space on the stack in case we need to save the argument
983 registers. */
984 if (fkind == EXCPT_HANDLER)
986 insn = emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (-12)));
987 RTX_FRAME_RELATED_P (insn) = 1;
990 /* If we're calling other functions, they won't save their call-clobbered
991 registers, so we must save everything here. */
992 if (!crtl->is_leaf)
993 all = true;
994 expand_prologue_reg_save (spreg, all, true);
996 if (ENABLE_WA_05000283 || ENABLE_WA_05000315)
998 rtx chipid = GEN_INT (trunc_int_for_mode (0xFFC00014, SImode));
999 rtx p5reg = gen_rtx_REG (Pmode, REG_P5);
1000 emit_insn (gen_movbi (bfin_cc_rtx, const1_rtx));
1001 emit_insn (gen_movsi_high (p5reg, chipid));
1002 emit_insn (gen_movsi_low (p5reg, p5reg, chipid));
1003 emit_insn (gen_dummy_load (p5reg, bfin_cc_rtx));
1006 if (lookup_attribute ("nesting", attrs))
1008 rtx srcreg = gen_rtx_REG (Pmode, ret_regs[fkind]);
1009 insn = emit_move_insn (predec, srcreg);
1010 RTX_FRAME_RELATED_P (insn) = 1;
1013 do_link (spreg, frame_size, all);
1015 if (fkind == EXCPT_HANDLER)
1017 rtx r0reg = gen_rtx_REG (SImode, REG_R0);
1018 rtx r1reg = gen_rtx_REG (SImode, REG_R1);
1019 rtx r2reg = gen_rtx_REG (SImode, REG_R2);
1021 emit_move_insn (r0reg, gen_rtx_REG (SImode, REG_SEQSTAT));
1022 emit_insn (gen_ashrsi3 (r0reg, r0reg, GEN_INT (26)));
1023 emit_insn (gen_ashlsi3 (r0reg, r0reg, GEN_INT (26)));
1024 emit_move_insn (r1reg, spreg);
1025 emit_move_insn (r2reg, gen_rtx_REG (Pmode, REG_FP));
1026 emit_insn (gen_addsi3 (r2reg, r2reg, GEN_INT (8)));
1030 /* Generate an epilogue suitable for a function of kind FKIND. This is
1031 called for interrupt and exception handler epilogues.
1032 SPREG contains (reg:SI REG_SP). */
1034 static void
1035 expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind, bool all)
1037 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1038 rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
1039 rtx postinc = gen_rtx_MEM (SImode, postinc1);
1041 /* A slightly crude technique to stop flow from trying to delete "dead"
1042 insns. */
1043 MEM_VOLATILE_P (postinc) = 1;
1045 do_unlink (spreg, get_frame_size (), all, 1);
1047 if (lookup_attribute ("nesting", attrs))
1049 rtx srcreg = gen_rtx_REG (Pmode, ret_regs[fkind]);
1050 emit_move_insn (srcreg, postinc);
1053 /* If we're calling other functions, they won't save their call-clobbered
1054 registers, so we must save (and restore) everything here. */
1055 if (!crtl->is_leaf)
1056 all = true;
1058 expand_epilogue_reg_restore (spreg, all, true);
1060 /* Deallocate any space we left on the stack in case we needed to save the
1061 argument registers. */
1062 if (fkind == EXCPT_HANDLER)
1063 emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (12)));
1065 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, ret_regs[fkind])));
1068 /* Used while emitting the prologue to generate code to load the correct value
1069 into the PIC register, which is passed in DEST. */
1071 static rtx
1072 bfin_load_pic_reg (rtx dest)
1074 struct cgraph_local_info *i = NULL;
1075 rtx addr;
1077 i = cgraph_node::local_info (current_function_decl);
1079 /* Functions local to the translation unit don't need to reload the
1080 pic reg, since the caller always passes a usable one. */
1081 if (i && i->local)
1082 return pic_offset_table_rtx;
1084 if (global_options_set.x_bfin_library_id)
1085 addr = plus_constant (Pmode, pic_offset_table_rtx,
1086 -4 - bfin_library_id * 4);
1087 else
1088 addr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
1089 gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
1090 UNSPEC_LIBRARY_OFFSET));
1091 emit_insn (gen_movsi (dest, gen_rtx_MEM (Pmode, addr)));
1092 return dest;
1095 /* Generate RTL for the prologue of the current function. */
1097 void
1098 bfin_expand_prologue (void)
1100 HOST_WIDE_INT frame_size = get_frame_size ();
1101 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
1102 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1103 rtx pic_reg_loaded = NULL_RTX;
1104 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1105 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
1107 if (fkind != SUBROUTINE)
1109 expand_interrupt_handler_prologue (spreg, fkind, all);
1110 return;
1113 if (crtl->limit_stack
1114 || (TARGET_STACK_CHECK_L1
1115 && !DECL_NO_LIMIT_STACK (current_function_decl)))
1117 HOST_WIDE_INT offset
1118 = bfin_initial_elimination_offset (ARG_POINTER_REGNUM,
1119 STACK_POINTER_REGNUM);
1120 rtx lim = crtl->limit_stack ? stack_limit_rtx : NULL_RTX;
1121 rtx tmp = gen_rtx_REG (Pmode, REG_R3);
1122 rtx p2reg = gen_rtx_REG (Pmode, REG_P2);
1124 emit_move_insn (tmp, p2reg);
1125 if (!lim)
1127 emit_move_insn (p2reg, gen_int_mode (0xFFB00000, SImode));
1128 emit_move_insn (p2reg, gen_rtx_MEM (Pmode, p2reg));
1129 lim = p2reg;
1131 if (GET_CODE (lim) == SYMBOL_REF)
1133 if (TARGET_ID_SHARED_LIBRARY)
1135 rtx p1reg = gen_rtx_REG (Pmode, REG_P1);
1136 rtx val;
1137 pic_reg_loaded = bfin_load_pic_reg (p2reg);
1138 val = legitimize_pic_address (stack_limit_rtx, p1reg,
1139 pic_reg_loaded);
1140 emit_move_insn (p1reg, val);
1141 frame_related_constant_load (p2reg, offset, FALSE);
1142 emit_insn (gen_addsi3 (p2reg, p2reg, p1reg));
1143 lim = p2reg;
1145 else
1147 rtx limit = plus_constant (Pmode, lim, offset);
1148 emit_move_insn (p2reg, limit);
1149 lim = p2reg;
1152 else
1154 if (lim != p2reg)
1155 emit_move_insn (p2reg, lim);
1156 add_to_reg (p2reg, offset, 0, 0);
1157 lim = p2reg;
1159 emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim));
1160 emit_insn (gen_trapifcc ());
1161 emit_move_insn (p2reg, tmp);
1163 expand_prologue_reg_save (spreg, all, false);
1165 do_link (spreg, frame_size, all);
1167 if (TARGET_ID_SHARED_LIBRARY
1168 && !TARGET_SEP_DATA
1169 && (crtl->uses_pic_offset_table
1170 || !crtl->is_leaf))
1171 bfin_load_pic_reg (pic_offset_table_rtx);
1174 /* Generate RTL for the epilogue of the current function. NEED_RETURN is zero
1175 if this is for a sibcall. EH_RETURN is nonzero if we're expanding an
1176 eh_return pattern. SIBCALL_P is true if this is a sibcall epilogue,
1177 false otherwise. */
1179 void
1180 bfin_expand_epilogue (int need_return, int eh_return, bool sibcall_p)
1182 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
1183 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1184 int e = sibcall_p ? -1 : 1;
1185 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1186 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
1188 if (fkind != SUBROUTINE)
1190 expand_interrupt_handler_epilogue (spreg, fkind, all);
1191 return;
1194 do_unlink (spreg, get_frame_size (), all, e);
1196 expand_epilogue_reg_restore (spreg, all, false);
1198 /* Omit the return insn if this is for a sibcall. */
1199 if (! need_return)
1200 return;
1202 if (eh_return)
1203 emit_insn (gen_addsi3 (spreg, spreg, gen_rtx_REG (Pmode, REG_P2)));
1205 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, REG_RETS)));
1208 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
1211 bfin_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
1212 unsigned int new_reg)
1214 /* Interrupt functions can only use registers that have already been
1215 saved by the prologue, even if they would normally be
1216 call-clobbered. */
1218 if (funkind (TREE_TYPE (current_function_decl)) != SUBROUTINE
1219 && !df_regs_ever_live_p (new_reg))
1220 return 0;
1222 return 1;
1225 /* Implement TARGET_EXTRA_LIVE_ON_ENTRY. */
1226 static void
1227 bfin_extra_live_on_entry (bitmap regs)
1229 if (TARGET_FDPIC)
1230 bitmap_set_bit (regs, FDPIC_REGNO);
1233 /* Return the value of the return address for the frame COUNT steps up
1234 from the current frame, after the prologue.
1235 We punt for everything but the current frame by returning const0_rtx. */
1238 bfin_return_addr_rtx (int count)
1240 if (count != 0)
1241 return const0_rtx;
1243 return get_hard_reg_initial_val (Pmode, REG_RETS);
1246 static rtx
1247 bfin_delegitimize_address (rtx orig_x)
1249 rtx x = orig_x;
1251 if (GET_CODE (x) != MEM)
1252 return orig_x;
1254 x = XEXP (x, 0);
1255 if (GET_CODE (x) == PLUS
1256 && GET_CODE (XEXP (x, 1)) == UNSPEC
1257 && XINT (XEXP (x, 1), 1) == UNSPEC_MOVE_PIC
1258 && GET_CODE (XEXP (x, 0)) == REG
1259 && REGNO (XEXP (x, 0)) == PIC_OFFSET_TABLE_REGNUM)
1260 return XVECEXP (XEXP (x, 1), 0, 0);
1262 return orig_x;
1265 /* This predicate is used to compute the length of a load/store insn.
1266 OP is a MEM rtx, we return nonzero if its addressing mode requires a
1267 32-bit instruction. */
1270 effective_address_32bit_p (rtx op, machine_mode mode)
1272 HOST_WIDE_INT offset;
1274 mode = GET_MODE (op);
1275 op = XEXP (op, 0);
1277 if (GET_CODE (op) != PLUS)
1279 gcc_assert (REG_P (op) || GET_CODE (op) == POST_INC
1280 || GET_CODE (op) == PRE_DEC || GET_CODE (op) == POST_DEC);
1281 return 0;
1284 if (GET_CODE (XEXP (op, 1)) == UNSPEC)
1285 return 1;
1287 offset = INTVAL (XEXP (op, 1));
1289 /* All byte loads use a 16-bit offset. */
1290 if (GET_MODE_SIZE (mode) == 1)
1291 return 1;
1293 if (GET_MODE_SIZE (mode) == 4)
1295 /* Frame pointer relative loads can use a negative offset, all others
1296 are restricted to a small positive one. */
1297 if (XEXP (op, 0) == frame_pointer_rtx)
1298 return offset < -128 || offset > 60;
1299 return offset < 0 || offset > 60;
1302 /* Must be HImode now. */
1303 return offset < 0 || offset > 30;
1306 /* Returns true if X is a memory reference using an I register. */
1307 bool
1308 bfin_dsp_memref_p (rtx x)
1310 if (! MEM_P (x))
1311 return false;
1312 x = XEXP (x, 0);
1313 if (GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_INC
1314 || GET_CODE (x) == POST_DEC || GET_CODE (x) == PRE_DEC)
1315 x = XEXP (x, 0);
1316 return IREG_P (x);
1319 /* Return cost of the memory address ADDR.
1320 All addressing modes are equally cheap on the Blackfin. */
1322 static int
1323 bfin_address_cost (rtx addr ATTRIBUTE_UNUSED,
1324 machine_mode mode ATTRIBUTE_UNUSED,
1325 addr_space_t as ATTRIBUTE_UNUSED,
1326 bool speed ATTRIBUTE_UNUSED)
1328 return 1;
1331 /* Subroutine of print_operand; used to print a memory reference X to FILE. */
1333 void
1334 print_address_operand (FILE *file, rtx x)
1336 switch (GET_CODE (x))
1338 case PLUS:
1339 output_address (XEXP (x, 0));
1340 fprintf (file, "+");
1341 output_address (XEXP (x, 1));
1342 break;
1344 case PRE_DEC:
1345 fprintf (file, "--");
1346 output_address (XEXP (x, 0));
1347 break;
1348 case POST_INC:
1349 output_address (XEXP (x, 0));
1350 fprintf (file, "++");
1351 break;
1352 case POST_DEC:
1353 output_address (XEXP (x, 0));
1354 fprintf (file, "--");
1355 break;
1357 default:
1358 gcc_assert (GET_CODE (x) != MEM);
1359 print_operand (file, x, 0);
1360 break;
1364 /* Adding intp DImode support by Tony
1365 * -- Q: (low word)
1366 * -- R: (high word)
1369 void
1370 print_operand (FILE *file, rtx x, char code)
1372 machine_mode mode;
1374 if (code == '!')
1376 if (GET_MODE (current_output_insn) == SImode)
1377 fprintf (file, " ||");
1378 else
1379 fprintf (file, ";");
1380 return;
1383 mode = GET_MODE (x);
1385 switch (code)
1387 case 'j':
1388 switch (GET_CODE (x))
1390 case EQ:
1391 fprintf (file, "e");
1392 break;
1393 case NE:
1394 fprintf (file, "ne");
1395 break;
1396 case GT:
1397 fprintf (file, "g");
1398 break;
1399 case LT:
1400 fprintf (file, "l");
1401 break;
1402 case GE:
1403 fprintf (file, "ge");
1404 break;
1405 case LE:
1406 fprintf (file, "le");
1407 break;
1408 case GTU:
1409 fprintf (file, "g");
1410 break;
1411 case LTU:
1412 fprintf (file, "l");
1413 break;
1414 case GEU:
1415 fprintf (file, "ge");
1416 break;
1417 case LEU:
1418 fprintf (file, "le");
1419 break;
1420 default:
1421 output_operand_lossage ("invalid %%j value");
1423 break;
1425 case 'J': /* reverse logic */
1426 switch (GET_CODE(x))
1428 case EQ:
1429 fprintf (file, "ne");
1430 break;
1431 case NE:
1432 fprintf (file, "e");
1433 break;
1434 case GT:
1435 fprintf (file, "le");
1436 break;
1437 case LT:
1438 fprintf (file, "ge");
1439 break;
1440 case GE:
1441 fprintf (file, "l");
1442 break;
1443 case LE:
1444 fprintf (file, "g");
1445 break;
1446 case GTU:
1447 fprintf (file, "le");
1448 break;
1449 case LTU:
1450 fprintf (file, "ge");
1451 break;
1452 case GEU:
1453 fprintf (file, "l");
1454 break;
1455 case LEU:
1456 fprintf (file, "g");
1457 break;
1458 default:
1459 output_operand_lossage ("invalid %%J value");
1461 break;
1463 default:
1464 switch (GET_CODE (x))
1466 case REG:
1467 if (code == 'h')
1469 if (REGNO (x) < 32)
1470 fprintf (file, "%s", short_reg_names[REGNO (x)]);
1471 else
1472 output_operand_lossage ("invalid operand for code '%c'", code);
1474 else if (code == 'd')
1476 if (REGNO (x) < 32)
1477 fprintf (file, "%s", high_reg_names[REGNO (x)]);
1478 else
1479 output_operand_lossage ("invalid operand for code '%c'", code);
1481 else if (code == 'w')
1483 if (REGNO (x) == REG_A0 || REGNO (x) == REG_A1)
1484 fprintf (file, "%s.w", reg_names[REGNO (x)]);
1485 else
1486 output_operand_lossage ("invalid operand for code '%c'", code);
1488 else if (code == 'x')
1490 if (REGNO (x) == REG_A0 || REGNO (x) == REG_A1)
1491 fprintf (file, "%s.x", reg_names[REGNO (x)]);
1492 else
1493 output_operand_lossage ("invalid operand for code '%c'", code);
1495 else if (code == 'v')
1497 if (REGNO (x) == REG_A0)
1498 fprintf (file, "AV0");
1499 else if (REGNO (x) == REG_A1)
1500 fprintf (file, "AV1");
1501 else
1502 output_operand_lossage ("invalid operand for code '%c'", code);
1504 else if (code == 'D')
1506 if (D_REGNO_P (REGNO (x)))
1507 fprintf (file, "%s", dregs_pair_names[REGNO (x)]);
1508 else
1509 output_operand_lossage ("invalid operand for code '%c'", code);
1511 else if (code == 'H')
1513 if ((mode == DImode || mode == DFmode) && REG_P (x))
1514 fprintf (file, "%s", reg_names[REGNO (x) + 1]);
1515 else
1516 output_operand_lossage ("invalid operand for code '%c'", code);
1518 else if (code == 'T')
1520 if (D_REGNO_P (REGNO (x)))
1521 fprintf (file, "%s", byte_reg_names[REGNO (x)]);
1522 else
1523 output_operand_lossage ("invalid operand for code '%c'", code);
1525 else
1526 fprintf (file, "%s", reg_names[REGNO (x)]);
1527 break;
1529 case MEM:
1530 fputc ('[', file);
1531 x = XEXP (x,0);
1532 print_address_operand (file, x);
1533 fputc (']', file);
1534 break;
1536 case CONST_INT:
1537 if (code == 'M')
1539 switch (INTVAL (x))
1541 case MACFLAG_NONE:
1542 break;
1543 case MACFLAG_FU:
1544 fputs ("(FU)", file);
1545 break;
1546 case MACFLAG_T:
1547 fputs ("(T)", file);
1548 break;
1549 case MACFLAG_TFU:
1550 fputs ("(TFU)", file);
1551 break;
1552 case MACFLAG_W32:
1553 fputs ("(W32)", file);
1554 break;
1555 case MACFLAG_IS:
1556 fputs ("(IS)", file);
1557 break;
1558 case MACFLAG_IU:
1559 fputs ("(IU)", file);
1560 break;
1561 case MACFLAG_IH:
1562 fputs ("(IH)", file);
1563 break;
1564 case MACFLAG_M:
1565 fputs ("(M)", file);
1566 break;
1567 case MACFLAG_IS_M:
1568 fputs ("(IS,M)", file);
1569 break;
1570 case MACFLAG_ISS2:
1571 fputs ("(ISS2)", file);
1572 break;
1573 case MACFLAG_S2RND:
1574 fputs ("(S2RND)", file);
1575 break;
1576 default:
1577 gcc_unreachable ();
1579 break;
1581 else if (code == 'b')
1583 if (INTVAL (x) == 0)
1584 fputs ("+=", file);
1585 else if (INTVAL (x) == 1)
1586 fputs ("-=", file);
1587 else
1588 gcc_unreachable ();
1589 break;
1591 /* Moves to half registers with d or h modifiers always use unsigned
1592 constants. */
1593 else if (code == 'd')
1594 x = GEN_INT ((INTVAL (x) >> 16) & 0xffff);
1595 else if (code == 'h')
1596 x = GEN_INT (INTVAL (x) & 0xffff);
1597 else if (code == 'N')
1598 x = GEN_INT (-INTVAL (x));
1599 else if (code == 'X')
1600 x = GEN_INT (exact_log2 (0xffffffff & INTVAL (x)));
1601 else if (code == 'Y')
1602 x = GEN_INT (exact_log2 (0xffffffff & ~INTVAL (x)));
1603 else if (code == 'Z')
1604 /* Used for LINK insns. */
1605 x = GEN_INT (-8 - INTVAL (x));
1607 /* fall through */
1609 case SYMBOL_REF:
1610 output_addr_const (file, x);
1611 break;
1613 case CONST_DOUBLE:
1614 output_operand_lossage ("invalid const_double operand");
1615 break;
1617 case UNSPEC:
1618 switch (XINT (x, 1))
1620 case UNSPEC_MOVE_PIC:
1621 output_addr_const (file, XVECEXP (x, 0, 0));
1622 fprintf (file, "@GOT");
1623 break;
1625 case UNSPEC_MOVE_FDPIC:
1626 output_addr_const (file, XVECEXP (x, 0, 0));
1627 fprintf (file, "@GOT17M4");
1628 break;
1630 case UNSPEC_FUNCDESC_GOT17M4:
1631 output_addr_const (file, XVECEXP (x, 0, 0));
1632 fprintf (file, "@FUNCDESC_GOT17M4");
1633 break;
1635 case UNSPEC_LIBRARY_OFFSET:
1636 fprintf (file, "_current_shared_library_p5_offset_");
1637 break;
1639 default:
1640 gcc_unreachable ();
1642 break;
1644 default:
1645 output_addr_const (file, x);
1650 /* Argument support functions. */
1652 /* Initialize a variable CUM of type CUMULATIVE_ARGS
1653 for a call to a function whose data type is FNTYPE.
1654 For a library call, FNTYPE is 0.
1655 VDSP C Compiler manual, our ABI says that
1656 first 3 words of arguments will use R0, R1 and R2.
1659 void
1660 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
1661 rtx libname ATTRIBUTE_UNUSED)
1663 static CUMULATIVE_ARGS zero_cum;
1665 *cum = zero_cum;
1667 /* Set up the number of registers to use for passing arguments. */
1669 cum->nregs = max_arg_registers;
1670 cum->arg_regs = arg_regs;
1672 cum->call_cookie = CALL_NORMAL;
1673 /* Check for a longcall attribute. */
1674 if (fntype && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype)))
1675 cum->call_cookie |= CALL_SHORT;
1676 else if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)))
1677 cum->call_cookie |= CALL_LONG;
1679 return;
1682 /* Update the data in CUM to advance over an argument
1683 of mode MODE and data type TYPE.
1684 (TYPE is null for libcalls where that information may not be available.) */
1686 static void
1687 bfin_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
1688 const_tree type, bool named ATTRIBUTE_UNUSED)
1690 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
1691 int count, bytes, words;
1693 bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1694 words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1696 cum->words += words;
1697 cum->nregs -= words;
1699 if (cum->nregs <= 0)
1701 cum->nregs = 0;
1702 cum->arg_regs = NULL;
1704 else
1706 for (count = 1; count <= words; count++)
1707 cum->arg_regs++;
1710 return;
1713 /* Define where to put the arguments to a function.
1714 Value is zero to push the argument on the stack,
1715 or a hard register in which to store the argument.
1717 MODE is the argument's machine mode.
1718 TYPE is the data type of the argument (as a tree).
1719 This is null for libcalls where that information may
1720 not be available.
1721 CUM is a variable of type CUMULATIVE_ARGS which gives info about
1722 the preceding args and about the function being called.
1723 NAMED is nonzero if this argument is a named parameter
1724 (otherwise it is an extra parameter matching an ellipsis). */
1726 static rtx
1727 bfin_function_arg (cumulative_args_t cum_v, machine_mode mode,
1728 const_tree type, bool named ATTRIBUTE_UNUSED)
1730 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
1731 int bytes
1732 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1734 if (mode == VOIDmode)
1735 /* Compute operand 2 of the call insn. */
1736 return GEN_INT (cum->call_cookie);
1738 if (bytes == -1)
1739 return NULL_RTX;
1741 if (cum->nregs)
1742 return gen_rtx_REG (mode, *(cum->arg_regs));
1744 return NULL_RTX;
1747 /* For an arg passed partly in registers and partly in memory,
1748 this is the number of bytes passed in registers.
1749 For args passed entirely in registers or entirely in memory, zero.
1751 Refer VDSP C Compiler manual, our ABI.
1752 First 3 words are in registers. So, if an argument is larger
1753 than the registers available, it will span the register and
1754 stack. */
1756 static int
1757 bfin_arg_partial_bytes (cumulative_args_t cum, machine_mode mode,
1758 tree type ATTRIBUTE_UNUSED,
1759 bool named ATTRIBUTE_UNUSED)
1761 int bytes
1762 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1763 int bytes_left = get_cumulative_args (cum)->nregs * UNITS_PER_WORD;
1765 if (bytes == -1)
1766 return 0;
1768 if (bytes_left == 0)
1769 return 0;
1770 if (bytes > bytes_left)
1771 return bytes_left;
1772 return 0;
1775 /* Variable sized types are passed by reference. */
1777 static bool
1778 bfin_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
1779 machine_mode mode ATTRIBUTE_UNUSED,
1780 const_tree type, bool named ATTRIBUTE_UNUSED)
1782 return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
1785 /* Decide whether a type should be returned in memory (true)
1786 or in a register (false). This is called by the macro
1787 TARGET_RETURN_IN_MEMORY. */
1789 static bool
1790 bfin_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
1792 int size = int_size_in_bytes (type);
1793 return size > 2 * UNITS_PER_WORD || size == -1;
1796 /* Register in which address to store a structure value
1797 is passed to a function. */
1798 static rtx
1799 bfin_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
1800 int incoming ATTRIBUTE_UNUSED)
1802 return gen_rtx_REG (Pmode, REG_P0);
1805 /* Return true when register may be used to pass function parameters. */
1807 bool
1808 function_arg_regno_p (int n)
1810 int i;
1811 for (i = 0; arg_regs[i] != -1; i++)
1812 if (n == arg_regs[i])
1813 return true;
1814 return false;
1817 /* Returns 1 if OP contains a symbol reference */
1820 symbolic_reference_mentioned_p (rtx op)
1822 register const char *fmt;
1823 register int i;
1825 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
1826 return 1;
1828 fmt = GET_RTX_FORMAT (GET_CODE (op));
1829 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
1831 if (fmt[i] == 'E')
1833 register int j;
1835 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
1836 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
1837 return 1;
1840 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
1841 return 1;
1844 return 0;
1847 /* Decide whether we can make a sibling call to a function. DECL is the
1848 declaration of the function being targeted by the call and EXP is the
1849 CALL_EXPR representing the call. */
1851 static bool
1852 bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
1853 tree exp ATTRIBUTE_UNUSED)
1855 struct cgraph_local_info *this_func, *called_func;
1856 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1857 if (fkind != SUBROUTINE)
1858 return false;
1859 if (!TARGET_ID_SHARED_LIBRARY || TARGET_SEP_DATA)
1860 return true;
1862 /* When compiling for ID shared libraries, can't sibcall a local function
1863 from a non-local function, because the local function thinks it does
1864 not need to reload P5 in the prologue, but the sibcall wil pop P5 in the
1865 sibcall epilogue, and we end up with the wrong value in P5. */
1867 if (!decl)
1868 /* Not enough information. */
1869 return false;
1871 this_func = cgraph_node::local_info (current_function_decl);
1872 called_func = cgraph_node::local_info (decl);
1873 if (!called_func)
1874 return false;
1875 return !called_func->local || this_func->local;
1878 /* Write a template for a trampoline to F. */
1880 static void
1881 bfin_asm_trampoline_template (FILE *f)
1883 if (TARGET_FDPIC)
1885 fprintf (f, "\t.dd\t0x00000000\n"); /* 0 */
1886 fprintf (f, "\t.dd\t0x00000000\n"); /* 0 */
1887 fprintf (f, "\t.dd\t0x0000e109\n"); /* p1.l = fn low */
1888 fprintf (f, "\t.dd\t0x0000e149\n"); /* p1.h = fn high */
1889 fprintf (f, "\t.dd\t0x0000e10a\n"); /* p2.l = sc low */
1890 fprintf (f, "\t.dd\t0x0000e14a\n"); /* p2.h = sc high */
1891 fprintf (f, "\t.dw\t0xac4b\n"); /* p3 = [p1 + 4] */
1892 fprintf (f, "\t.dw\t0x9149\n"); /* p1 = [p1] */
1893 fprintf (f, "\t.dw\t0x0051\n"); /* jump (p1)*/
1895 else
1897 fprintf (f, "\t.dd\t0x0000e109\n"); /* p1.l = fn low */
1898 fprintf (f, "\t.dd\t0x0000e149\n"); /* p1.h = fn high */
1899 fprintf (f, "\t.dd\t0x0000e10a\n"); /* p2.l = sc low */
1900 fprintf (f, "\t.dd\t0x0000e14a\n"); /* p2.h = sc high */
1901 fprintf (f, "\t.dw\t0x0051\n"); /* jump (p1)*/
1905 /* Emit RTL insns to initialize the variable parts of a trampoline at
1906 M_TRAMP. FNDECL is the target function. CHAIN_VALUE is an RTX for
1907 the static chain value for the function. */
1909 static void
1910 bfin_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
1912 rtx t1 = copy_to_reg (XEXP (DECL_RTL (fndecl), 0));
1913 rtx t2 = copy_to_reg (chain_value);
1914 rtx mem;
1915 int i = 0;
1917 emit_block_move (m_tramp, assemble_trampoline_template (),
1918 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
1920 if (TARGET_FDPIC)
1922 rtx a = force_reg (Pmode, plus_constant (Pmode, XEXP (m_tramp, 0), 8));
1923 mem = adjust_address (m_tramp, Pmode, 0);
1924 emit_move_insn (mem, a);
1925 i = 8;
1928 mem = adjust_address (m_tramp, HImode, i + 2);
1929 emit_move_insn (mem, gen_lowpart (HImode, t1));
1930 emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16)));
1931 mem = adjust_address (m_tramp, HImode, i + 6);
1932 emit_move_insn (mem, gen_lowpart (HImode, t1));
1934 mem = adjust_address (m_tramp, HImode, i + 10);
1935 emit_move_insn (mem, gen_lowpart (HImode, t2));
1936 emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16)));
1937 mem = adjust_address (m_tramp, HImode, i + 14);
1938 emit_move_insn (mem, gen_lowpart (HImode, t2));
1941 /* Emit insns to move operands[1] into operands[0]. */
1943 void
1944 emit_pic_move (rtx *operands, machine_mode mode ATTRIBUTE_UNUSED)
1946 rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
1948 gcc_assert (!TARGET_FDPIC || !(reload_in_progress || reload_completed));
1949 if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
1950 operands[1] = force_reg (SImode, operands[1]);
1951 else
1952 operands[1] = legitimize_pic_address (operands[1], temp,
1953 TARGET_FDPIC ? OUR_FDPIC_REG
1954 : pic_offset_table_rtx);
1957 /* Expand a move operation in mode MODE. The operands are in OPERANDS.
1958 Returns true if no further code must be generated, false if the caller
1959 should generate an insn to move OPERANDS[1] to OPERANDS[0]. */
1961 bool
1962 expand_move (rtx *operands, machine_mode mode)
1964 rtx op = operands[1];
1965 if ((TARGET_ID_SHARED_LIBRARY || TARGET_FDPIC)
1966 && SYMBOLIC_CONST (op))
1967 emit_pic_move (operands, mode);
1968 else if (mode == SImode && GET_CODE (op) == CONST
1969 && GET_CODE (XEXP (op, 0)) == PLUS
1970 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
1971 && !targetm.legitimate_constant_p (mode, op))
1973 rtx dest = operands[0];
1974 rtx op0, op1;
1975 gcc_assert (!reload_in_progress && !reload_completed);
1976 op = XEXP (op, 0);
1977 op0 = force_reg (mode, XEXP (op, 0));
1978 op1 = XEXP (op, 1);
1979 if (!insn_data[CODE_FOR_addsi3].operand[2].predicate (op1, mode))
1980 op1 = force_reg (mode, op1);
1981 if (GET_CODE (dest) == MEM)
1982 dest = gen_reg_rtx (mode);
1983 emit_insn (gen_addsi3 (dest, op0, op1));
1984 if (dest == operands[0])
1985 return true;
1986 operands[1] = dest;
1988 /* Don't generate memory->memory or constant->memory moves, go through a
1989 register */
1990 else if ((reload_in_progress | reload_completed) == 0
1991 && GET_CODE (operands[0]) == MEM
1992 && GET_CODE (operands[1]) != REG)
1993 operands[1] = force_reg (mode, operands[1]);
1994 return false;
1997 /* Split one or more DImode RTL references into pairs of SImode
1998 references. The RTL can be REG, offsettable MEM, integer constant, or
1999 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
2000 split and "num" is its length. lo_half and hi_half are output arrays
2001 that parallel "operands". */
2003 void
2004 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
2006 while (num--)
2008 rtx op = operands[num];
2010 /* simplify_subreg refuse to split volatile memory addresses,
2011 but we still have to handle it. */
2012 if (GET_CODE (op) == MEM)
2014 lo_half[num] = adjust_address (op, SImode, 0);
2015 hi_half[num] = adjust_address (op, SImode, 4);
2017 else
2019 lo_half[num] = simplify_gen_subreg (SImode, op,
2020 GET_MODE (op) == VOIDmode
2021 ? DImode : GET_MODE (op), 0);
2022 hi_half[num] = simplify_gen_subreg (SImode, op,
2023 GET_MODE (op) == VOIDmode
2024 ? DImode : GET_MODE (op), 4);
2029 bool
2030 bfin_longcall_p (rtx op, int call_cookie)
2032 gcc_assert (GET_CODE (op) == SYMBOL_REF);
2033 if (SYMBOL_REF_WEAK (op))
2034 return 1;
2035 if (call_cookie & CALL_SHORT)
2036 return 0;
2037 if (call_cookie & CALL_LONG)
2038 return 1;
2039 if (TARGET_LONG_CALLS)
2040 return 1;
2041 return 0;
2044 /* Expand a call instruction. FNADDR is the call target, RETVAL the return value.
2045 COOKIE is a CONST_INT holding the call_cookie prepared init_cumulative_args.
2046 SIBCALL is nonzero if this is a sibling call. */
2048 void
2049 bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
2051 rtx use = NULL, call;
2052 rtx callee = XEXP (fnaddr, 0);
2053 int nelts = 3;
2054 rtx pat;
2055 rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REGNO);
2056 rtx retsreg = gen_rtx_REG (Pmode, REG_RETS);
2057 int n;
2059 /* In an untyped call, we can get NULL for operand 2. */
2060 if (cookie == NULL_RTX)
2061 cookie = const0_rtx;
2063 /* Static functions and indirect calls don't need the pic register. */
2064 if (!TARGET_FDPIC && flag_pic
2065 && GET_CODE (callee) == SYMBOL_REF
2066 && !SYMBOL_REF_LOCAL_P (callee))
2067 use_reg (&use, pic_offset_table_rtx);
2069 if (TARGET_FDPIC)
2071 int caller_in_sram, callee_in_sram;
2073 /* 0 is not in sram, 1 is in L1 sram, 2 is in L2 sram. */
2074 caller_in_sram = callee_in_sram = 0;
2076 if (lookup_attribute ("l1_text",
2077 DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE)
2078 caller_in_sram = 1;
2079 else if (lookup_attribute ("l2",
2080 DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE)
2081 caller_in_sram = 2;
2083 if (GET_CODE (callee) == SYMBOL_REF
2084 && SYMBOL_REF_DECL (callee) && DECL_P (SYMBOL_REF_DECL (callee)))
2086 if (lookup_attribute
2087 ("l1_text",
2088 DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE)
2089 callee_in_sram = 1;
2090 else if (lookup_attribute
2091 ("l2",
2092 DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE)
2093 callee_in_sram = 2;
2096 if (GET_CODE (callee) != SYMBOL_REF
2097 || bfin_longcall_p (callee, INTVAL (cookie))
2098 || (GET_CODE (callee) == SYMBOL_REF
2099 && !SYMBOL_REF_LOCAL_P (callee)
2100 && TARGET_INLINE_PLT)
2101 || caller_in_sram != callee_in_sram
2102 || (caller_in_sram && callee_in_sram
2103 && (GET_CODE (callee) != SYMBOL_REF
2104 || !SYMBOL_REF_LOCAL_P (callee))))
2106 rtx addr = callee;
2107 if (! address_operand (addr, Pmode))
2108 addr = force_reg (Pmode, addr);
2110 fnaddr = gen_reg_rtx (SImode);
2111 emit_insn (gen_load_funcdescsi (fnaddr, addr));
2112 fnaddr = gen_rtx_MEM (Pmode, fnaddr);
2114 picreg = gen_reg_rtx (SImode);
2115 emit_insn (gen_load_funcdescsi (picreg,
2116 plus_constant (Pmode, addr, 4)));
2119 nelts++;
2121 else if ((!register_no_elim_operand (callee, Pmode)
2122 && GET_CODE (callee) != SYMBOL_REF)
2123 || (GET_CODE (callee) == SYMBOL_REF
2124 && ((TARGET_ID_SHARED_LIBRARY && !TARGET_LEAF_ID_SHARED_LIBRARY)
2125 || bfin_longcall_p (callee, INTVAL (cookie)))))
2127 callee = copy_to_mode_reg (Pmode, callee);
2128 fnaddr = gen_rtx_MEM (Pmode, callee);
2130 call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
2132 if (retval)
2133 call = gen_rtx_SET (retval, call);
2135 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nelts));
2136 n = 0;
2137 XVECEXP (pat, 0, n++) = call;
2138 if (TARGET_FDPIC)
2139 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, picreg);
2140 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie);
2141 if (sibcall)
2142 XVECEXP (pat, 0, n++) = ret_rtx;
2143 else
2144 XVECEXP (pat, 0, n++) = gen_rtx_CLOBBER (VOIDmode, retsreg);
2145 call = emit_call_insn (pat);
2146 if (use)
2147 CALL_INSN_FUNCTION_USAGE (call) = use;
2150 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
2153 hard_regno_mode_ok (int regno, machine_mode mode)
2155 /* Allow only dregs to store value of mode HI or QI */
2156 enum reg_class rclass = REGNO_REG_CLASS (regno);
2158 if (mode == CCmode)
2159 return 0;
2161 if (mode == V2HImode)
2162 return D_REGNO_P (regno);
2163 if (rclass == CCREGS)
2164 return mode == BImode;
2165 if (mode == PDImode || mode == V2PDImode)
2166 return regno == REG_A0 || regno == REG_A1;
2168 /* Allow all normal 32-bit regs, except REG_M3, in case regclass ever comes
2169 up with a bad register class (such as ALL_REGS) for DImode. */
2170 if (mode == DImode)
2171 return regno < REG_M3;
2173 if (mode == SImode
2174 && TEST_HARD_REG_BIT (reg_class_contents[PROLOGUE_REGS], regno))
2175 return 1;
2177 return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno);
2180 /* Implements target hook vector_mode_supported_p. */
2182 static bool
2183 bfin_vector_mode_supported_p (machine_mode mode)
2185 return mode == V2HImode;
2188 /* Worker function for TARGET_REGISTER_MOVE_COST. */
2190 static int
2191 bfin_register_move_cost (machine_mode mode,
2192 reg_class_t class1, reg_class_t class2)
2194 /* These need secondary reloads, so they're more expensive. */
2195 if ((class1 == CCREGS && !reg_class_subset_p (class2, DREGS))
2196 || (class2 == CCREGS && !reg_class_subset_p (class1, DREGS)))
2197 return 4;
2199 /* If optimizing for size, always prefer reg-reg over reg-memory moves. */
2200 if (optimize_size)
2201 return 2;
2203 if (GET_MODE_CLASS (mode) == MODE_INT)
2205 /* Discourage trying to use the accumulators. */
2206 if (TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A0)
2207 || TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A1)
2208 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A0)
2209 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A1))
2210 return 20;
2212 return 2;
2215 /* Worker function for TARGET_MEMORY_MOVE_COST.
2217 ??? In theory L1 memory has single-cycle latency. We should add a switch
2218 that tells the compiler whether we expect to use only L1 memory for the
2219 program; it'll make the costs more accurate. */
2221 static int
2222 bfin_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
2223 reg_class_t rclass,
2224 bool in ATTRIBUTE_UNUSED)
2226 /* Make memory accesses slightly more expensive than any register-register
2227 move. Also, penalize non-DP registers, since they need secondary
2228 reloads to load and store. */
2229 if (! reg_class_subset_p (rclass, DPREGS))
2230 return 10;
2232 return 8;
2235 /* Inform reload about cases where moving X with a mode MODE to a register in
2236 RCLASS requires an extra scratch register. Return the class needed for the
2237 scratch register. */
2239 static reg_class_t
2240 bfin_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
2241 machine_mode mode, secondary_reload_info *sri)
2243 /* If we have HImode or QImode, we can only use DREGS as secondary registers;
2244 in most other cases we can also use PREGS. */
2245 enum reg_class default_class = GET_MODE_SIZE (mode) >= 4 ? DPREGS : DREGS;
2246 enum reg_class x_class = NO_REGS;
2247 enum rtx_code code = GET_CODE (x);
2248 enum reg_class rclass = (enum reg_class) rclass_i;
2250 if (code == SUBREG)
2251 x = SUBREG_REG (x), code = GET_CODE (x);
2252 if (REG_P (x))
2254 int regno = REGNO (x);
2255 if (regno >= FIRST_PSEUDO_REGISTER)
2256 regno = reg_renumber[regno];
2258 if (regno == -1)
2259 code = MEM;
2260 else
2261 x_class = REGNO_REG_CLASS (regno);
2264 /* We can be asked to reload (plus (FP) (large_constant)) into a DREG.
2265 This happens as a side effect of register elimination, and we need
2266 a scratch register to do it. */
2267 if (fp_plus_const_operand (x, mode))
2269 rtx op2 = XEXP (x, 1);
2270 int large_constant_p = ! satisfies_constraint_Ks7 (op2);
2272 if (rclass == PREGS || rclass == PREGS_CLOBBERED)
2273 return NO_REGS;
2274 /* If destination is a DREG, we can do this without a scratch register
2275 if the constant is valid for an add instruction. */
2276 if ((rclass == DREGS || rclass == DPREGS)
2277 && ! large_constant_p)
2278 return NO_REGS;
2279 /* Reloading to anything other than a DREG? Use a PREG scratch
2280 register. */
2281 sri->icode = CODE_FOR_reload_insi;
2282 return NO_REGS;
2285 /* Data can usually be moved freely between registers of most classes.
2286 AREGS are an exception; they can only move to or from another register
2287 in AREGS or one in DREGS. They can also be assigned the constant 0. */
2288 if (x_class == AREGS || x_class == EVEN_AREGS || x_class == ODD_AREGS)
2289 return (rclass == DREGS || rclass == AREGS || rclass == EVEN_AREGS
2290 || rclass == ODD_AREGS
2291 ? NO_REGS : DREGS);
2293 if (rclass == AREGS || rclass == EVEN_AREGS || rclass == ODD_AREGS)
2295 if (code == MEM)
2297 sri->icode = in_p ? CODE_FOR_reload_inpdi : CODE_FOR_reload_outpdi;
2298 return NO_REGS;
2301 if (x != const0_rtx && x_class != DREGS)
2303 return DREGS;
2305 else
2306 return NO_REGS;
2309 /* CCREGS can only be moved from/to DREGS. */
2310 if (rclass == CCREGS && x_class != DREGS)
2311 return DREGS;
2312 if (x_class == CCREGS && rclass != DREGS)
2313 return DREGS;
2315 /* All registers other than AREGS can load arbitrary constants. The only
2316 case that remains is MEM. */
2317 if (code == MEM)
2318 if (! reg_class_subset_p (rclass, default_class))
2319 return default_class;
2321 return NO_REGS;
2324 /* Implement TARGET_CLASS_LIKELY_SPILLED_P. */
2326 static bool
2327 bfin_class_likely_spilled_p (reg_class_t rclass)
2329 switch (rclass)
2331 case PREGS_CLOBBERED:
2332 case PROLOGUE_REGS:
2333 case P0REGS:
2334 case D0REGS:
2335 case D1REGS:
2336 case D2REGS:
2337 case CCREGS:
2338 return true;
2340 default:
2341 break;
2344 return false;
2347 static struct machine_function *
2348 bfin_init_machine_status (void)
2350 return ggc_cleared_alloc<machine_function> ();
2353 /* Implement the TARGET_OPTION_OVERRIDE hook. */
2355 static void
2356 bfin_option_override (void)
2358 /* If processor type is not specified, enable all workarounds. */
2359 if (bfin_cpu_type == BFIN_CPU_UNKNOWN)
2361 int i;
2363 for (i = 0; bfin_cpus[i].name != NULL; i++)
2364 bfin_workarounds |= bfin_cpus[i].workarounds;
2366 bfin_si_revision = 0xffff;
2369 if (bfin_csync_anomaly == 1)
2370 bfin_workarounds |= WA_SPECULATIVE_SYNCS;
2371 else if (bfin_csync_anomaly == 0)
2372 bfin_workarounds &= ~WA_SPECULATIVE_SYNCS;
2374 if (bfin_specld_anomaly == 1)
2375 bfin_workarounds |= WA_SPECULATIVE_LOADS;
2376 else if (bfin_specld_anomaly == 0)
2377 bfin_workarounds &= ~WA_SPECULATIVE_LOADS;
2379 if (TARGET_OMIT_LEAF_FRAME_POINTER)
2380 flag_omit_frame_pointer = 1;
2382 #ifdef SUBTARGET_FDPIC_NOT_SUPPORTED
2383 if (TARGET_FDPIC)
2384 error ("-mfdpic is not supported, please use a bfin-linux-uclibc target");
2385 #endif
2387 /* Library identification */
2388 if (global_options_set.x_bfin_library_id && ! TARGET_ID_SHARED_LIBRARY)
2389 error ("-mshared-library-id= specified without -mid-shared-library");
2391 if (stack_limit_rtx && TARGET_FDPIC)
2393 warning (0, "-fstack-limit- options are ignored with -mfdpic; use -mstack-check-l1");
2394 stack_limit_rtx = NULL_RTX;
2397 if (stack_limit_rtx && TARGET_STACK_CHECK_L1)
2398 error ("can%'t use multiple stack checking methods together");
2400 if (TARGET_ID_SHARED_LIBRARY && TARGET_FDPIC)
2401 error ("ID shared libraries and FD-PIC mode can%'t be used together");
2403 /* Don't allow the user to specify -mid-shared-library and -msep-data
2404 together, as it makes little sense from a user's point of view... */
2405 if (TARGET_SEP_DATA && TARGET_ID_SHARED_LIBRARY)
2406 error ("cannot specify both -msep-data and -mid-shared-library");
2407 /* ... internally, however, it's nearly the same. */
2408 if (TARGET_SEP_DATA)
2409 target_flags |= MASK_ID_SHARED_LIBRARY | MASK_LEAF_ID_SHARED_LIBRARY;
2411 if (TARGET_ID_SHARED_LIBRARY && flag_pic == 0)
2412 flag_pic = 1;
2414 /* There is no single unaligned SI op for PIC code. Sometimes we
2415 need to use ".4byte" and sometimes we need to use ".picptr".
2416 See bfin_assemble_integer for details. */
2417 if (TARGET_FDPIC)
2418 targetm.asm_out.unaligned_op.si = 0;
2420 /* Silently turn off flag_pic if not doing FDPIC or ID shared libraries,
2421 since we don't support it and it'll just break. */
2422 if (flag_pic && !TARGET_FDPIC && !TARGET_ID_SHARED_LIBRARY)
2423 flag_pic = 0;
2425 if (TARGET_MULTICORE && bfin_cpu_type != BFIN_CPU_BF561)
2426 error ("-mmulticore can only be used with BF561");
2428 if (TARGET_COREA && !TARGET_MULTICORE)
2429 error ("-mcorea should be used with -mmulticore");
2431 if (TARGET_COREB && !TARGET_MULTICORE)
2432 error ("-mcoreb should be used with -mmulticore");
2434 if (TARGET_COREA && TARGET_COREB)
2435 error ("-mcorea and -mcoreb can%'t be used together");
2437 flag_schedule_insns = 0;
2439 init_machine_status = bfin_init_machine_status;
2442 /* Return the destination address of BRANCH.
2443 We need to use this instead of get_attr_length, because the
2444 cbranch_with_nops pattern conservatively sets its length to 6, and
2445 we still prefer to use shorter sequences. */
2447 static int
2448 branch_dest (rtx_insn *branch)
2450 rtx dest;
2451 int dest_uid;
2452 rtx pat = PATTERN (branch);
2453 if (GET_CODE (pat) == PARALLEL)
2454 pat = XVECEXP (pat, 0, 0);
2455 dest = SET_SRC (pat);
2456 if (GET_CODE (dest) == IF_THEN_ELSE)
2457 dest = XEXP (dest, 1);
2458 dest = XEXP (dest, 0);
2459 dest_uid = INSN_UID (dest);
2460 return INSN_ADDRESSES (dest_uid);
2463 /* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates
2464 it's a branch that's predicted taken. */
2466 static int
2467 cbranch_predicted_taken_p (rtx insn)
2469 rtx x = find_reg_note (insn, REG_BR_PROB, 0);
2471 if (x)
2473 int pred_val = XINT (x, 0);
2475 return pred_val >= REG_BR_PROB_BASE / 2;
2478 return 0;
2481 /* Templates for use by asm_conditional_branch. */
2483 static const char *ccbranch_templates[][3] = {
2484 { "if !cc jump %3;", "if cc jump 4 (bp); jump.s %3;", "if cc jump 6 (bp); jump.l %3;" },
2485 { "if cc jump %3;", "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" },
2486 { "if !cc jump %3 (bp);", "if cc jump 4; jump.s %3;", "if cc jump 6; jump.l %3;" },
2487 { "if cc jump %3 (bp);", "if !cc jump 4; jump.s %3;", "if !cc jump 6; jump.l %3;" },
2490 /* Output INSN, which is a conditional branch instruction with operands
2491 OPERANDS.
2493 We deal with the various forms of conditional branches that can be generated
2494 by bfin_reorg to prevent the hardware from doing speculative loads, by
2495 - emitting a sufficient number of nops, if N_NOPS is nonzero, or
2496 - always emitting the branch as predicted taken, if PREDICT_TAKEN is true.
2497 Either of these is only necessary if the branch is short, otherwise the
2498 template we use ends in an unconditional jump which flushes the pipeline
2499 anyway. */
2501 void
2502 asm_conditional_branch (rtx_insn *insn, rtx *operands, int n_nops, int predict_taken)
2504 int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
2505 /* Note : offset for instructions like if cc jmp; jump.[sl] offset
2506 is to be taken from start of if cc rather than jump.
2507 Range for jump.s is (-4094, 4096) instead of (-4096, 4094)
2509 int len = (offset >= -1024 && offset <= 1022 ? 0
2510 : offset >= -4094 && offset <= 4096 ? 1
2511 : 2);
2512 int bp = predict_taken && len == 0 ? 1 : cbranch_predicted_taken_p (insn);
2513 int idx = (bp << 1) | (GET_CODE (operands[0]) == EQ ? BRF : BRT);
2514 output_asm_insn (ccbranch_templates[idx][len], operands);
2515 gcc_assert (n_nops == 0 || !bp);
2516 if (len == 0)
2517 while (n_nops-- > 0)
2518 output_asm_insn ("nop;", NULL);
2521 /* Emit rtl for a comparison operation CMP in mode MODE. Operands have been
2522 stored in bfin_compare_op0 and bfin_compare_op1 already. */
2525 bfin_gen_compare (rtx cmp, machine_mode mode ATTRIBUTE_UNUSED)
2527 enum rtx_code code1, code2;
2528 rtx op0 = XEXP (cmp, 0), op1 = XEXP (cmp, 1);
2529 rtx tem = bfin_cc_rtx;
2530 enum rtx_code code = GET_CODE (cmp);
2532 /* If we have a BImode input, then we already have a compare result, and
2533 do not need to emit another comparison. */
2534 if (GET_MODE (op0) == BImode)
2536 gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
2537 tem = op0, code2 = code;
2539 else
2541 switch (code) {
2542 /* bfin has these conditions */
2543 case EQ:
2544 case LT:
2545 case LE:
2546 case LEU:
2547 case LTU:
2548 code1 = code;
2549 code2 = NE;
2550 break;
2551 default:
2552 code1 = reverse_condition (code);
2553 code2 = EQ;
2554 break;
2556 emit_insn (gen_rtx_SET (tem, gen_rtx_fmt_ee (code1, BImode, op0, op1)));
2559 return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode));
2562 /* Return nonzero iff C has exactly one bit set if it is interpreted
2563 as a 32-bit constant. */
2566 log2constp (unsigned HOST_WIDE_INT c)
2568 c &= 0xFFFFFFFF;
2569 return c != 0 && (c & (c-1)) == 0;
2572 /* Returns the number of consecutive least significant zeros in the binary
2573 representation of *V.
2574 We modify *V to contain the original value arithmetically shifted right by
2575 the number of zeroes. */
2577 static int
2578 shiftr_zero (HOST_WIDE_INT *v)
2580 unsigned HOST_WIDE_INT tmp = *v;
2581 unsigned HOST_WIDE_INT sgn;
2582 int n = 0;
2584 if (tmp == 0)
2585 return 0;
2587 sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1));
2588 while ((tmp & 0x1) == 0 && n <= 32)
2590 tmp = (tmp >> 1) | sgn;
2591 n++;
2593 *v = tmp;
2594 return n;
2597 /* After reload, split the load of an immediate constant. OPERANDS are the
2598 operands of the movsi_insn pattern which we are splitting. We return
2599 nonzero if we emitted a sequence to load the constant, zero if we emitted
2600 nothing because we want to use the splitter's default sequence. */
2603 split_load_immediate (rtx operands[])
2605 HOST_WIDE_INT val = INTVAL (operands[1]);
2606 HOST_WIDE_INT tmp;
2607 HOST_WIDE_INT shifted = val;
2608 HOST_WIDE_INT shifted_compl = ~val;
2609 int num_zero = shiftr_zero (&shifted);
2610 int num_compl_zero = shiftr_zero (&shifted_compl);
2611 unsigned int regno = REGNO (operands[0]);
2613 /* This case takes care of single-bit set/clear constants, which we could
2614 also implement with BITSET/BITCLR. */
2615 if (num_zero
2616 && shifted >= -32768 && shifted < 65536
2617 && (D_REGNO_P (regno)
2618 || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))
2620 emit_insn (gen_movsi (operands[0], gen_int_mode (shifted, SImode)));
2621 emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));
2622 return 1;
2625 tmp = val & 0xFFFF;
2626 tmp |= -(tmp & 0x8000);
2628 /* If high word has one bit set or clear, try to use a bit operation. */
2629 if (D_REGNO_P (regno))
2631 if (log2constp (val & 0xFFFF0000))
2633 emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));
2634 emit_insn (gen_iorsi3 (operands[0], operands[0],
2635 gen_int_mode (val & 0xFFFF0000, SImode)));
2636 return 1;
2638 else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)
2640 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2641 emit_insn (gen_andsi3 (operands[0], operands[0],
2642 gen_int_mode (val | 0xFFFF, SImode)));
2646 if (D_REGNO_P (regno))
2648 if (tmp >= -64 && tmp <= 63)
2650 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2651 emit_insn (gen_movstricthi_high (operands[0],
2652 gen_int_mode (val & -65536,
2653 SImode)));
2654 return 1;
2657 if ((val & 0xFFFF0000) == 0)
2659 emit_insn (gen_movsi (operands[0], const0_rtx));
2660 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2661 return 1;
2664 if ((val & 0xFFFF0000) == 0xFFFF0000)
2666 emit_insn (gen_movsi (operands[0], constm1_rtx));
2667 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2668 return 1;
2672 /* Need DREGs for the remaining case. */
2673 if (regno > REG_R7)
2674 return 0;
2676 if (optimize_size
2677 && num_compl_zero && shifted_compl >= -64 && shifted_compl <= 63)
2679 /* If optimizing for size, generate a sequence that has more instructions
2680 but is shorter. */
2681 emit_insn (gen_movsi (operands[0], gen_int_mode (shifted_compl, SImode)));
2682 emit_insn (gen_ashlsi3 (operands[0], operands[0],
2683 GEN_INT (num_compl_zero)));
2684 emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
2685 return 1;
2687 return 0;
2690 /* Return true if the legitimate memory address for a memory operand of mode
2691 MODE. Return false if not. */
2693 static bool
2694 bfin_valid_add (machine_mode mode, HOST_WIDE_INT value)
2696 unsigned HOST_WIDE_INT v = value > 0 ? value : -value;
2697 int sz = GET_MODE_SIZE (mode);
2698 int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2;
2699 /* The usual offsettable_memref machinery doesn't work so well for this
2700 port, so we deal with the problem here. */
2701 if (value > 0 && sz == 8)
2702 v += 4;
2703 return (v & ~(0x7fff << shift)) == 0;
2706 static bool
2707 bfin_valid_reg_p (unsigned int regno, int strict, machine_mode mode,
2708 enum rtx_code outer_code)
2710 if (strict)
2711 return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH);
2712 else
2713 return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH);
2716 /* Recognize an RTL expression that is a valid memory address for an
2717 instruction. The MODE argument is the machine mode for the MEM expression
2718 that wants to use this address.
2720 Blackfin addressing modes are as follows:
2722 [preg]
2723 [preg + imm16]
2725 B [ Preg + uimm15 ]
2726 W [ Preg + uimm16m2 ]
2727 [ Preg + uimm17m4 ]
2729 [preg++]
2730 [preg--]
2731 [--sp]
2734 static bool
2735 bfin_legitimate_address_p (machine_mode mode, rtx x, bool strict)
2737 switch (GET_CODE (x)) {
2738 case REG:
2739 if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM))
2740 return true;
2741 break;
2742 case PLUS:
2743 if (REG_P (XEXP (x, 0))
2744 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS)
2745 && ((GET_CODE (XEXP (x, 1)) == UNSPEC && mode == SImode)
2746 || (GET_CODE (XEXP (x, 1)) == CONST_INT
2747 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
2748 return true;
2749 break;
2750 case POST_INC:
2751 case POST_DEC:
2752 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2753 && REG_P (XEXP (x, 0))
2754 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC))
2755 return true;
2756 case PRE_DEC:
2757 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2758 && XEXP (x, 0) == stack_pointer_rtx
2759 && REG_P (XEXP (x, 0))
2760 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC))
2761 return true;
2762 break;
2763 default:
2764 break;
2766 return false;
2769 /* Decide whether we can force certain constants to memory. If we
2770 decide we can't, the caller should be able to cope with it in
2771 another way. */
2773 static bool
2774 bfin_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED,
2775 rtx x ATTRIBUTE_UNUSED)
2777 /* We have only one class of non-legitimate constants, and our movsi
2778 expander knows how to handle them. Dropping these constants into the
2779 data section would only shift the problem - we'd still get relocs
2780 outside the object, in the data section rather than the text section. */
2781 return true;
2784 /* Ensure that for any constant of the form symbol + offset, the offset
2785 remains within the object. Any other constants are ok.
2786 This ensures that flat binaries never have to deal with relocations
2787 crossing section boundaries. */
2789 static bool
2790 bfin_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
2792 rtx sym;
2793 HOST_WIDE_INT offset;
2795 if (GET_CODE (x) != CONST)
2796 return true;
2798 x = XEXP (x, 0);
2799 gcc_assert (GET_CODE (x) == PLUS);
2801 sym = XEXP (x, 0);
2802 x = XEXP (x, 1);
2803 if (GET_CODE (sym) != SYMBOL_REF
2804 || GET_CODE (x) != CONST_INT)
2805 return true;
2806 offset = INTVAL (x);
2808 if (SYMBOL_REF_DECL (sym) == 0)
2809 return true;
2810 if (offset < 0
2811 || offset >= int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (sym))))
2812 return false;
2814 return true;
2817 static bool
2818 bfin_rtx_costs (rtx x, int code_i, int outer_code_i, int opno, int *total,
2819 bool speed)
2821 enum rtx_code code = (enum rtx_code) code_i;
2822 enum rtx_code outer_code = (enum rtx_code) outer_code_i;
2823 int cost2 = COSTS_N_INSNS (1);
2824 rtx op0, op1;
2826 switch (code)
2828 case CONST_INT:
2829 if (outer_code == SET || outer_code == PLUS)
2830 *total = satisfies_constraint_Ks7 (x) ? 0 : cost2;
2831 else if (outer_code == AND)
2832 *total = log2constp (~INTVAL (x)) ? 0 : cost2;
2833 else if (outer_code == LE || outer_code == LT || outer_code == EQ)
2834 *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
2835 else if (outer_code == LEU || outer_code == LTU)
2836 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
2837 else if (outer_code == MULT)
2838 *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
2839 else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
2840 *total = 0;
2841 else if (outer_code == ASHIFT || outer_code == ASHIFTRT
2842 || outer_code == LSHIFTRT)
2843 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
2844 else if (outer_code == IOR || outer_code == XOR)
2845 *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
2846 else
2847 *total = cost2;
2848 return true;
2850 case CONST:
2851 case LABEL_REF:
2852 case SYMBOL_REF:
2853 case CONST_DOUBLE:
2854 *total = COSTS_N_INSNS (2);
2855 return true;
2857 case PLUS:
2858 op0 = XEXP (x, 0);
2859 op1 = XEXP (x, 1);
2860 if (GET_MODE (x) == SImode)
2862 if (GET_CODE (op0) == MULT
2863 && GET_CODE (XEXP (op0, 1)) == CONST_INT)
2865 HOST_WIDE_INT val = INTVAL (XEXP (op0, 1));
2866 if (val == 2 || val == 4)
2868 *total = cost2;
2869 *total += rtx_cost (XEXP (op0, 0), outer_code, opno, speed);
2870 *total += rtx_cost (op1, outer_code, opno, speed);
2871 return true;
2874 *total = cost2;
2875 if (GET_CODE (op0) != REG
2876 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2877 *total += set_src_cost (op0, speed);
2878 #if 0 /* We'd like to do this for accuracy, but it biases the loop optimizer
2879 towards creating too many induction variables. */
2880 if (!reg_or_7bit_operand (op1, SImode))
2881 *total += set_src_cost (op1, speed);
2882 #endif
2884 else if (GET_MODE (x) == DImode)
2886 *total = 6 * cost2;
2887 if (GET_CODE (op1) != CONST_INT
2888 || !satisfies_constraint_Ks7 (op1))
2889 *total += rtx_cost (op1, PLUS, 1, speed);
2890 if (GET_CODE (op0) != REG
2891 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2892 *total += rtx_cost (op0, PLUS, 0, speed);
2894 return true;
2896 case MINUS:
2897 if (GET_MODE (x) == DImode)
2898 *total = 6 * cost2;
2899 else
2900 *total = cost2;
2901 return true;
2903 case ASHIFT:
2904 case ASHIFTRT:
2905 case LSHIFTRT:
2906 if (GET_MODE (x) == DImode)
2907 *total = 6 * cost2;
2908 else
2909 *total = cost2;
2911 op0 = XEXP (x, 0);
2912 op1 = XEXP (x, 1);
2913 if (GET_CODE (op0) != REG
2914 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2915 *total += rtx_cost (op0, code, 0, speed);
2917 return true;
2919 case IOR:
2920 case AND:
2921 case XOR:
2922 op0 = XEXP (x, 0);
2923 op1 = XEXP (x, 1);
2925 /* Handle special cases of IOR: rotates, ALIGN insns, movstricthi_high. */
2926 if (code == IOR)
2928 if ((GET_CODE (op0) == LSHIFTRT && GET_CODE (op1) == ASHIFT)
2929 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == ZERO_EXTEND)
2930 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT)
2931 || (GET_CODE (op0) == AND && GET_CODE (op1) == CONST_INT))
2933 *total = cost2;
2934 return true;
2938 if (GET_CODE (op0) != REG
2939 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2940 *total += rtx_cost (op0, code, 0, speed);
2942 if (GET_MODE (x) == DImode)
2944 *total = 2 * cost2;
2945 return true;
2947 *total = cost2;
2948 if (GET_MODE (x) != SImode)
2949 return true;
2951 if (code == AND)
2953 if (! rhs_andsi3_operand (XEXP (x, 1), SImode))
2954 *total += rtx_cost (XEXP (x, 1), code, 1, speed);
2956 else
2958 if (! regorlog2_operand (XEXP (x, 1), SImode))
2959 *total += rtx_cost (XEXP (x, 1), code, 1, speed);
2962 return true;
2964 case ZERO_EXTRACT:
2965 case SIGN_EXTRACT:
2966 if (outer_code == SET
2967 && XEXP (x, 1) == const1_rtx
2968 && GET_CODE (XEXP (x, 2)) == CONST_INT)
2970 *total = 2 * cost2;
2971 return true;
2973 /* fall through */
2975 case SIGN_EXTEND:
2976 case ZERO_EXTEND:
2977 *total = cost2;
2978 return true;
2980 case MULT:
2982 op0 = XEXP (x, 0);
2983 op1 = XEXP (x, 1);
2984 if (GET_CODE (op0) == GET_CODE (op1)
2985 && (GET_CODE (op0) == ZERO_EXTEND
2986 || GET_CODE (op0) == SIGN_EXTEND))
2988 *total = COSTS_N_INSNS (1);
2989 op0 = XEXP (op0, 0);
2990 op1 = XEXP (op1, 0);
2992 else if (!speed)
2993 *total = COSTS_N_INSNS (1);
2994 else
2995 *total = COSTS_N_INSNS (3);
2997 if (GET_CODE (op0) != REG
2998 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2999 *total += rtx_cost (op0, MULT, 0, speed);
3000 if (GET_CODE (op1) != REG
3001 && (GET_CODE (op1) != SUBREG || GET_CODE (SUBREG_REG (op1)) != REG))
3002 *total += rtx_cost (op1, MULT, 1, speed);
3004 return true;
3006 case UDIV:
3007 case UMOD:
3008 *total = COSTS_N_INSNS (32);
3009 return true;
3011 case VEC_CONCAT:
3012 case VEC_SELECT:
3013 if (outer_code == SET)
3014 *total = cost2;
3015 return true;
3017 default:
3018 return false;
3022 /* Used for communication between {push,pop}_multiple_operation (which
3023 we use not only as a predicate) and the corresponding output functions. */
3024 static int first_preg_to_save, first_dreg_to_save;
3025 static int n_regs_to_save;
3028 analyze_push_multiple_operation (rtx op)
3030 int lastdreg = 8, lastpreg = 6;
3031 int i, group;
3033 first_preg_to_save = lastpreg;
3034 first_dreg_to_save = lastdreg;
3035 for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
3037 rtx t = XVECEXP (op, 0, i);
3038 rtx src, dest;
3039 int regno;
3041 if (GET_CODE (t) != SET)
3042 return 0;
3044 src = SET_SRC (t);
3045 dest = SET_DEST (t);
3046 if (GET_CODE (dest) != MEM || ! REG_P (src))
3047 return 0;
3048 dest = XEXP (dest, 0);
3049 if (GET_CODE (dest) != PLUS
3050 || ! REG_P (XEXP (dest, 0))
3051 || REGNO (XEXP (dest, 0)) != REG_SP
3052 || GET_CODE (XEXP (dest, 1)) != CONST_INT
3053 || INTVAL (XEXP (dest, 1)) != -i * 4)
3054 return 0;
3056 regno = REGNO (src);
3057 if (group == 0)
3059 if (D_REGNO_P (regno))
3061 group = 1;
3062 first_dreg_to_save = lastdreg = regno - REG_R0;
3064 else if (regno >= REG_P0 && regno <= REG_P7)
3066 group = 2;
3067 first_preg_to_save = lastpreg = regno - REG_P0;
3069 else
3070 return 0;
3072 continue;
3075 if (group == 1)
3077 if (regno >= REG_P0 && regno <= REG_P7)
3079 group = 2;
3080 first_preg_to_save = lastpreg = regno - REG_P0;
3082 else if (regno != REG_R0 + lastdreg + 1)
3083 return 0;
3084 else
3085 lastdreg++;
3087 else if (group == 2)
3089 if (regno != REG_P0 + lastpreg + 1)
3090 return 0;
3091 lastpreg++;
3094 n_regs_to_save = 8 - first_dreg_to_save + 6 - first_preg_to_save;
3095 return 1;
3099 analyze_pop_multiple_operation (rtx op)
3101 int lastdreg = 8, lastpreg = 6;
3102 int i, group;
3104 for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
3106 rtx t = XVECEXP (op, 0, i);
3107 rtx src, dest;
3108 int regno;
3110 if (GET_CODE (t) != SET)
3111 return 0;
3113 src = SET_SRC (t);
3114 dest = SET_DEST (t);
3115 if (GET_CODE (src) != MEM || ! REG_P (dest))
3116 return 0;
3117 src = XEXP (src, 0);
3119 if (i == 1)
3121 if (! REG_P (src) || REGNO (src) != REG_SP)
3122 return 0;
3124 else if (GET_CODE (src) != PLUS
3125 || ! REG_P (XEXP (src, 0))
3126 || REGNO (XEXP (src, 0)) != REG_SP
3127 || GET_CODE (XEXP (src, 1)) != CONST_INT
3128 || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
3129 return 0;
3131 regno = REGNO (dest);
3132 if (group == 0)
3134 if (regno == REG_R7)
3136 group = 1;
3137 lastdreg = 7;
3139 else if (regno != REG_P0 + lastpreg - 1)
3140 return 0;
3141 else
3142 lastpreg--;
3144 else if (group == 1)
3146 if (regno != REG_R0 + lastdreg - 1)
3147 return 0;
3148 else
3149 lastdreg--;
3152 first_dreg_to_save = lastdreg;
3153 first_preg_to_save = lastpreg;
3154 n_regs_to_save = 8 - first_dreg_to_save + 6 - first_preg_to_save;
3155 return 1;
3158 /* Emit assembly code for one multi-register push described by INSN, with
3159 operands in OPERANDS. */
3161 void
3162 output_push_multiple (rtx insn, rtx *operands)
3164 char buf[80];
3165 int ok;
3167 /* Validate the insn again, and compute first_[dp]reg_to_save. */
3168 ok = analyze_push_multiple_operation (PATTERN (insn));
3169 gcc_assert (ok);
3171 if (first_dreg_to_save == 8)
3172 sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
3173 else if (first_preg_to_save == 6)
3174 sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
3175 else
3176 sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
3177 first_dreg_to_save, first_preg_to_save);
3179 output_asm_insn (buf, operands);
3182 /* Emit assembly code for one multi-register pop described by INSN, with
3183 operands in OPERANDS. */
3185 void
3186 output_pop_multiple (rtx insn, rtx *operands)
3188 char buf[80];
3189 int ok;
3191 /* Validate the insn again, and compute first_[dp]reg_to_save. */
3192 ok = analyze_pop_multiple_operation (PATTERN (insn));
3193 gcc_assert (ok);
3195 if (first_dreg_to_save == 8)
3196 sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
3197 else if (first_preg_to_save == 6)
3198 sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
3199 else
3200 sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
3201 first_dreg_to_save, first_preg_to_save);
3203 output_asm_insn (buf, operands);
3206 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE. */
3208 static void
3209 single_move_for_movmem (rtx dst, rtx src, machine_mode mode, HOST_WIDE_INT offset)
3211 rtx scratch = gen_reg_rtx (mode);
3212 rtx srcmem, dstmem;
3214 srcmem = adjust_address_nv (src, mode, offset);
3215 dstmem = adjust_address_nv (dst, mode, offset);
3216 emit_move_insn (scratch, srcmem);
3217 emit_move_insn (dstmem, scratch);
3220 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
3221 alignment ALIGN_EXP. Return true if successful, false if we should fall
3222 back on a different method. */
3224 bool
3225 bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
3227 rtx srcreg, destreg, countreg;
3228 HOST_WIDE_INT align = 0;
3229 unsigned HOST_WIDE_INT count = 0;
3231 if (GET_CODE (align_exp) == CONST_INT)
3232 align = INTVAL (align_exp);
3233 if (GET_CODE (count_exp) == CONST_INT)
3235 count = INTVAL (count_exp);
3236 #if 0
3237 if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
3238 return false;
3239 #endif
3242 /* If optimizing for size, only do single copies inline. */
3243 if (optimize_size)
3245 if (count == 2 && align < 2)
3246 return false;
3247 if (count == 4 && align < 4)
3248 return false;
3249 if (count != 1 && count != 2 && count != 4)
3250 return false;
3252 if (align < 2 && count != 1)
3253 return false;
3255 destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
3256 if (destreg != XEXP (dst, 0))
3257 dst = replace_equiv_address_nv (dst, destreg);
3258 srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
3259 if (srcreg != XEXP (src, 0))
3260 src = replace_equiv_address_nv (src, srcreg);
3262 if (count != 0 && align >= 2)
3264 unsigned HOST_WIDE_INT offset = 0;
3266 if (align >= 4)
3268 if ((count & ~3) == 4)
3270 single_move_for_movmem (dst, src, SImode, offset);
3271 offset = 4;
3273 else if (count & ~3)
3275 HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
3276 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3278 emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
3279 cfun->machine->has_loopreg_clobber = true;
3281 if (count & 2)
3283 single_move_for_movmem (dst, src, HImode, offset);
3284 offset += 2;
3287 else
3289 if ((count & ~1) == 2)
3291 single_move_for_movmem (dst, src, HImode, offset);
3292 offset = 2;
3294 else if (count & ~1)
3296 HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
3297 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3299 emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
3300 cfun->machine->has_loopreg_clobber = true;
3303 if (count & 1)
3305 single_move_for_movmem (dst, src, QImode, offset);
3307 return true;
3309 return false;
3312 /* Compute the alignment for a local variable.
3313 TYPE is the data type, and ALIGN is the alignment that
3314 the object would ordinarily have. The value of this macro is used
3315 instead of that alignment to align the object. */
3317 unsigned
3318 bfin_local_alignment (tree type, unsigned align)
3320 /* Increasing alignment for (relatively) big types allows the builtin
3321 memcpy can use 32 bit loads/stores. */
3322 if (TYPE_SIZE (type)
3323 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
3324 && wi::gtu_p (TYPE_SIZE (type), 8)
3325 && align < 32)
3326 return 32;
3327 return align;
3330 /* Implement TARGET_SCHED_ISSUE_RATE. */
3332 static int
3333 bfin_issue_rate (void)
3335 return 3;
3338 static int
3339 bfin_adjust_cost (rtx_insn *insn, rtx link, rtx_insn *dep_insn, int cost)
3341 enum attr_type dep_insn_type;
3342 int dep_insn_code_number;
3344 /* Anti and output dependencies have zero cost. */
3345 if (REG_NOTE_KIND (link) != 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 if (!flag_unsafe_loop_optimizations
3414 && wi::geu_p (iterations_max, 0xFFFFFFFF))
3415 return false;
3416 return true;
3419 /* Increment the counter for the number of loop instructions in the
3420 current function. */
3422 void
3423 bfin_hardware_loop (void)
3425 cfun->machine->has_hardware_loops++;
3428 /* Maximum loop nesting depth. */
3429 #define MAX_LOOP_DEPTH 2
3431 /* Maximum size of a loop. */
3432 #define MAX_LOOP_LENGTH 2042
3434 /* Maximum distance of the LSETUP instruction from the loop start. */
3435 #define MAX_LSETUP_DISTANCE 30
3437 /* Estimate the length of INSN conservatively. */
3439 static int
3440 length_for_loop (rtx_insn *insn)
3442 int length = 0;
3443 if (JUMP_P (insn) && any_condjump_p (insn) && !optimize_size)
3445 if (ENABLE_WA_SPECULATIVE_SYNCS)
3446 length = 8;
3447 else if (ENABLE_WA_SPECULATIVE_LOADS)
3448 length = 6;
3450 else if (LABEL_P (insn))
3452 if (ENABLE_WA_SPECULATIVE_SYNCS)
3453 length = 4;
3456 if (NONDEBUG_INSN_P (insn))
3457 length += get_attr_length (insn);
3459 return length;
3462 /* Optimize LOOP. */
3464 static bool
3465 hwloop_optimize (hwloop_info loop)
3467 basic_block bb;
3468 rtx_insn *insn, *last_insn;
3469 rtx loop_init, start_label, end_label;
3470 rtx iter_reg, scratchreg, scratch_init, scratch_init_insn;
3471 rtx lc_reg, lt_reg, lb_reg;
3472 rtx seq_end;
3473 rtx_insn *seq;
3474 int length;
3475 bool clobber0, clobber1;
3477 if (loop->depth > MAX_LOOP_DEPTH)
3479 if (dump_file)
3480 fprintf (dump_file, ";; loop %d too deep\n", loop->loop_no);
3481 return false;
3484 /* Get the loop iteration register. */
3485 iter_reg = loop->iter_reg;
3487 gcc_assert (REG_P (iter_reg));
3489 scratchreg = NULL_RTX;
3490 scratch_init = iter_reg;
3491 scratch_init_insn = NULL_RTX;
3492 if (!PREG_P (iter_reg) && loop->incoming_src)
3494 basic_block bb_in = loop->incoming_src;
3495 int i;
3496 for (i = REG_P0; i <= REG_P5; i++)
3497 if ((df_regs_ever_live_p (i)
3498 || (funkind (TREE_TYPE (current_function_decl)) == SUBROUTINE
3499 && call_used_regs[i]))
3500 && !REGNO_REG_SET_P (df_get_live_out (bb_in), i))
3502 scratchreg = gen_rtx_REG (SImode, i);
3503 break;
3505 for (insn = BB_END (bb_in); insn != BB_HEAD (bb_in);
3506 insn = PREV_INSN (insn))
3508 rtx set;
3509 if (NOTE_P (insn) || BARRIER_P (insn))
3510 continue;
3511 set = single_set (insn);
3512 if (set && rtx_equal_p (SET_DEST (set), iter_reg))
3514 if (CONSTANT_P (SET_SRC (set)))
3516 scratch_init = SET_SRC (set);
3517 scratch_init_insn = insn;
3519 break;
3521 else if (reg_mentioned_p (iter_reg, PATTERN (insn)))
3522 break;
3526 if (loop->incoming_src)
3528 /* Make sure the predecessor is before the loop start label, as required by
3529 the LSETUP instruction. */
3530 length = 0;
3531 insn = BB_END (loop->incoming_src);
3532 /* If we have to insert the LSETUP before a jump, count that jump in the
3533 length. */
3534 if (vec_safe_length (loop->incoming) > 1
3535 || !(loop->incoming->last ()->flags & EDGE_FALLTHRU))
3537 gcc_assert (JUMP_P (insn));
3538 insn = PREV_INSN (insn);
3541 for (; insn && insn != loop->start_label; insn = NEXT_INSN (insn))
3542 length += length_for_loop (insn);
3544 if (!insn)
3546 if (dump_file)
3547 fprintf (dump_file, ";; loop %d lsetup not before loop_start\n",
3548 loop->loop_no);
3549 return false;
3552 /* Account for the pop of a scratch register where necessary. */
3553 if (!PREG_P (iter_reg) && scratchreg == NULL_RTX
3554 && ENABLE_WA_LOAD_LCREGS)
3555 length += 2;
3557 if (length > MAX_LSETUP_DISTANCE)
3559 if (dump_file)
3560 fprintf (dump_file, ";; loop %d lsetup too far away\n", loop->loop_no);
3561 return false;
3565 /* Check if start_label appears before loop_end and calculate the
3566 offset between them. We calculate the length of instructions
3567 conservatively. */
3568 length = 0;
3569 for (insn = loop->start_label;
3570 insn && insn != loop->loop_end;
3571 insn = NEXT_INSN (insn))
3572 length += length_for_loop (insn);
3574 if (!insn)
3576 if (dump_file)
3577 fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
3578 loop->loop_no);
3579 return false;
3582 loop->length = length;
3583 if (loop->length > MAX_LOOP_LENGTH)
3585 if (dump_file)
3586 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
3587 return false;
3590 /* Scan all the blocks to make sure they don't use iter_reg. */
3591 if (loop->iter_reg_used || loop->iter_reg_used_outside)
3593 if (dump_file)
3594 fprintf (dump_file, ";; loop %d uses iterator\n", loop->loop_no);
3595 return false;
3598 clobber0 = (TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC0)
3599 || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LB0)
3600 || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LT0));
3601 clobber1 = (TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC1)
3602 || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LB1)
3603 || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LT1));
3604 if (clobber0 && clobber1)
3606 if (dump_file)
3607 fprintf (dump_file, ";; loop %d no loop reg available\n",
3608 loop->loop_no);
3609 return false;
3612 /* There should be an instruction before the loop_end instruction
3613 in the same basic block. And the instruction must not be
3614 - JUMP
3615 - CONDITIONAL BRANCH
3616 - CALL
3617 - CSYNC
3618 - SSYNC
3619 - Returns (RTS, RTN, etc.) */
3621 bb = loop->tail;
3622 last_insn = find_prev_insn_start (loop->loop_end);
3624 while (1)
3626 for (; last_insn != BB_HEAD (bb);
3627 last_insn = find_prev_insn_start (last_insn))
3628 if (NONDEBUG_INSN_P (last_insn))
3629 break;
3631 if (last_insn != BB_HEAD (bb))
3632 break;
3634 if (single_pred_p (bb)
3635 && single_pred_edge (bb)->flags & EDGE_FALLTHRU
3636 && single_pred (bb) != ENTRY_BLOCK_PTR_FOR_FN (cfun))
3638 bb = single_pred (bb);
3639 last_insn = BB_END (bb);
3640 continue;
3642 else
3644 last_insn = NULL;
3645 break;
3649 if (!last_insn)
3651 if (dump_file)
3652 fprintf (dump_file, ";; loop %d has no last instruction\n",
3653 loop->loop_no);
3654 return false;
3657 if (JUMP_P (last_insn) && !any_condjump_p (last_insn))
3659 if (dump_file)
3660 fprintf (dump_file, ";; loop %d has bad last instruction\n",
3661 loop->loop_no);
3662 return false;
3664 /* In all other cases, try to replace a bad last insn with a nop. */
3665 else if (JUMP_P (last_insn)
3666 || CALL_P (last_insn)
3667 || get_attr_type (last_insn) == TYPE_SYNC
3668 || get_attr_type (last_insn) == TYPE_CALL
3669 || get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI
3670 || recog_memoized (last_insn) == CODE_FOR_return_internal
3671 || GET_CODE (PATTERN (last_insn)) == ASM_INPUT
3672 || asm_noperands (PATTERN (last_insn)) >= 0)
3674 if (loop->length + 2 > MAX_LOOP_LENGTH)
3676 if (dump_file)
3677 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
3678 return false;
3680 if (dump_file)
3681 fprintf (dump_file, ";; loop %d has bad last insn; replace with nop\n",
3682 loop->loop_no);
3684 last_insn = emit_insn_after (gen_forced_nop (), last_insn);
3687 loop->last_insn = last_insn;
3689 /* The loop is good for replacement. */
3690 start_label = loop->start_label;
3691 end_label = gen_label_rtx ();
3692 iter_reg = loop->iter_reg;
3694 if (loop->depth == 1 && !clobber1)
3696 lc_reg = gen_rtx_REG (SImode, REG_LC1);
3697 lb_reg = gen_rtx_REG (SImode, REG_LB1);
3698 lt_reg = gen_rtx_REG (SImode, REG_LT1);
3699 SET_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC1);
3701 else
3703 lc_reg = gen_rtx_REG (SImode, REG_LC0);
3704 lb_reg = gen_rtx_REG (SImode, REG_LB0);
3705 lt_reg = gen_rtx_REG (SImode, REG_LT0);
3706 SET_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC0);
3709 loop->end_label = end_label;
3711 /* Create a sequence containing the loop setup. */
3712 start_sequence ();
3714 /* LSETUP only accepts P registers. If we have one, we can use it,
3715 otherwise there are several ways of working around the problem.
3716 If we're not affected by anomaly 312, we can load the LC register
3717 from any iteration register, and use LSETUP without initialization.
3718 If we've found a P scratch register that's not live here, we can
3719 instead copy the iter_reg into that and use an initializing LSETUP.
3720 If all else fails, push and pop P0 and use it as a scratch. */
3721 if (P_REGNO_P (REGNO (iter_reg)))
3723 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
3724 lb_reg, end_label,
3725 lc_reg, iter_reg);
3726 seq_end = emit_insn (loop_init);
3728 else if (!ENABLE_WA_LOAD_LCREGS && DPREG_P (iter_reg))
3730 emit_insn (gen_movsi (lc_reg, iter_reg));
3731 loop_init = gen_lsetup_without_autoinit (lt_reg, start_label,
3732 lb_reg, end_label,
3733 lc_reg);
3734 seq_end = emit_insn (loop_init);
3736 else if (scratchreg != NULL_RTX)
3738 emit_insn (gen_movsi (scratchreg, scratch_init));
3739 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
3740 lb_reg, end_label,
3741 lc_reg, scratchreg);
3742 seq_end = emit_insn (loop_init);
3743 if (scratch_init_insn != NULL_RTX)
3744 delete_insn (scratch_init_insn);
3746 else
3748 rtx p0reg = gen_rtx_REG (SImode, REG_P0);
3749 rtx push = gen_frame_mem (SImode,
3750 gen_rtx_PRE_DEC (SImode, stack_pointer_rtx));
3751 rtx pop = gen_frame_mem (SImode,
3752 gen_rtx_POST_INC (SImode, stack_pointer_rtx));
3753 emit_insn (gen_movsi (push, p0reg));
3754 emit_insn (gen_movsi (p0reg, scratch_init));
3755 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
3756 lb_reg, end_label,
3757 lc_reg, p0reg);
3758 emit_insn (loop_init);
3759 seq_end = emit_insn (gen_movsi (p0reg, pop));
3760 if (scratch_init_insn != NULL_RTX)
3761 delete_insn (scratch_init_insn);
3764 if (dump_file)
3766 fprintf (dump_file, ";; replacing loop %d initializer with\n",
3767 loop->loop_no);
3768 print_rtl_single (dump_file, loop_init);
3769 fprintf (dump_file, ";; replacing loop %d terminator with\n",
3770 loop->loop_no);
3771 print_rtl_single (dump_file, loop->loop_end);
3774 /* If the loop isn't entered at the top, also create a jump to the entry
3775 point. */
3776 if (!loop->incoming_src && loop->head != loop->incoming_dest)
3778 rtx label = BB_HEAD (loop->incoming_dest);
3779 /* If we're jumping to the final basic block in the loop, and there's
3780 only one cheap instruction before the end (typically an increment of
3781 an induction variable), we can just emit a copy here instead of a
3782 jump. */
3783 if (loop->incoming_dest == loop->tail
3784 && next_real_insn (label) == last_insn
3785 && asm_noperands (last_insn) < 0
3786 && GET_CODE (PATTERN (last_insn)) == SET)
3788 seq_end = emit_insn (copy_rtx (PATTERN (last_insn)));
3790 else
3792 emit_jump_insn (gen_jump (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);
3809 emit_insn_after (seq, prev);
3811 else
3813 basic_block new_bb;
3814 edge e;
3815 edge_iterator ei;
3817 #ifdef ENABLE_CHECKING
3818 if (loop->head != loop->incoming_dest)
3820 /* We aren't entering the loop at the top. Since we've established
3821 that the loop is entered only at one point, this means there
3822 can't be fallthru edges into the head. Any such fallthru edges
3823 would become invalid when we insert the new block, so verify
3824 that this does not in fact happen. */
3825 FOR_EACH_EDGE (e, ei, loop->head->preds)
3826 gcc_assert (!(e->flags & EDGE_FALLTHRU));
3828 #endif
3830 emit_insn_before (seq, BB_HEAD (loop->head));
3831 seq = emit_label_before (gen_label_rtx (), seq);
3833 new_bb = create_basic_block (seq, seq_end, loop->head->prev_bb);
3834 FOR_EACH_EDGE (e, ei, loop->incoming)
3836 if (!(e->flags & EDGE_FALLTHRU)
3837 || e->dest != loop->head)
3838 redirect_edge_and_branch_force (e, new_bb);
3839 else
3840 redirect_edge_succ (e, new_bb);
3842 e = make_edge (new_bb, loop->head, 0);
3845 delete_insn (loop->loop_end);
3846 /* Insert the loop end label before the last instruction of the loop. */
3847 emit_label_before (loop->end_label, loop->last_insn);
3849 return true;
3852 /* A callback for the hw-doloop pass. Called when a loop we have discovered
3853 turns out not to be optimizable; we have to split the doloop_end pattern
3854 into a subtract and a test. */
3855 static void
3856 hwloop_fail (hwloop_info loop)
3858 rtx insn = loop->loop_end;
3860 if (DPREG_P (loop->iter_reg))
3862 /* If loop->iter_reg is a DREG or PREG, we can split it here
3863 without scratch register. */
3864 rtx insn, test;
3866 emit_insn_before (gen_addsi3 (loop->iter_reg,
3867 loop->iter_reg,
3868 constm1_rtx),
3869 loop->loop_end);
3871 test = gen_rtx_NE (VOIDmode, loop->iter_reg, const0_rtx);
3872 insn = emit_jump_insn_before (gen_cbranchsi4 (test,
3873 loop->iter_reg, const0_rtx,
3874 loop->start_label),
3875 loop->loop_end);
3877 JUMP_LABEL (insn) = loop->start_label;
3878 LABEL_NUSES (loop->start_label)++;
3879 delete_insn (loop->loop_end);
3881 else
3883 splitting_loops = 1;
3884 try_split (PATTERN (insn), insn, 1);
3885 splitting_loops = 0;
3889 /* A callback for the hw-doloop pass. This function examines INSN; if
3890 it is a loop_end pattern we recognize, return the reg rtx for the
3891 loop counter. Otherwise, return NULL_RTX. */
3893 static rtx
3894 hwloop_pattern_reg (rtx_insn *insn)
3896 rtx reg;
3898 if (!JUMP_P (insn) || recog_memoized (insn) != CODE_FOR_loop_end)
3899 return NULL_RTX;
3901 reg = SET_DEST (XVECEXP (PATTERN (insn), 0, 1));
3902 if (!REG_P (reg))
3903 return NULL_RTX;
3904 return reg;
3907 static struct hw_doloop_hooks bfin_doloop_hooks =
3909 hwloop_pattern_reg,
3910 hwloop_optimize,
3911 hwloop_fail
3914 /* Run from machine_dependent_reorg, this pass looks for doloop_end insns
3915 and tries to rewrite the RTL of these loops so that proper Blackfin
3916 hardware loops are generated. */
3918 static void
3919 bfin_reorg_loops (void)
3921 reorg_loops (true, &bfin_doloop_hooks);
3924 /* Possibly generate a SEQUENCE out of three insns found in SLOT.
3925 Returns true if we modified the insn chain, false otherwise. */
3926 static bool
3927 gen_one_bundle (rtx_insn *slot[3])
3929 gcc_assert (slot[1] != NULL_RTX);
3931 /* Don't add extra NOPs if optimizing for size. */
3932 if (optimize_size
3933 && (slot[0] == NULL_RTX || slot[2] == NULL_RTX))
3934 return false;
3936 /* Verify that we really can do the multi-issue. */
3937 if (slot[0])
3939 rtx_insn *t = NEXT_INSN (slot[0]);
3940 while (t != slot[1])
3942 if (! NOTE_P (t) || NOTE_KIND (t) != NOTE_INSN_DELETED)
3943 return false;
3944 t = NEXT_INSN (t);
3947 if (slot[2])
3949 rtx_insn *t = NEXT_INSN (slot[1]);
3950 while (t != slot[2])
3952 if (! NOTE_P (t) || NOTE_KIND (t) != NOTE_INSN_DELETED)
3953 return false;
3954 t = NEXT_INSN (t);
3958 if (slot[0] == NULL_RTX)
3960 slot[0] = emit_insn_before (gen_mnop (), slot[1]);
3961 df_insn_rescan (slot[0]);
3963 if (slot[2] == NULL_RTX)
3965 slot[2] = emit_insn_after (gen_forced_nop (), slot[1]);
3966 df_insn_rescan (slot[2]);
3969 /* Avoid line number information being printed inside one bundle. */
3970 if (INSN_LOCATION (slot[1])
3971 && INSN_LOCATION (slot[1]) != INSN_LOCATION (slot[0]))
3972 INSN_LOCATION (slot[1]) = INSN_LOCATION (slot[0]);
3973 if (INSN_LOCATION (slot[2])
3974 && INSN_LOCATION (slot[2]) != INSN_LOCATION (slot[0]))
3975 INSN_LOCATION (slot[2]) = INSN_LOCATION (slot[0]);
3977 /* Terminate them with "|| " instead of ";" in the output. */
3978 PUT_MODE (slot[0], SImode);
3979 PUT_MODE (slot[1], SImode);
3980 /* Terminate the bundle, for the benefit of reorder_var_tracking_notes. */
3981 PUT_MODE (slot[2], QImode);
3982 return true;
3985 /* Go through all insns, and use the information generated during scheduling
3986 to generate SEQUENCEs to represent bundles of instructions issued
3987 simultaneously. */
3989 static void
3990 bfin_gen_bundles (void)
3992 basic_block bb;
3993 FOR_EACH_BB_FN (bb, cfun)
3995 rtx_insn *insn, *next;
3996 rtx_insn *slot[3];
3997 int n_filled = 0;
3999 slot[0] = slot[1] = slot[2] = NULL;
4000 for (insn = BB_HEAD (bb);; insn = next)
4002 int at_end;
4003 rtx delete_this = NULL_RTX;
4005 if (NONDEBUG_INSN_P (insn))
4007 enum attr_type type = get_attr_type (insn);
4009 if (type == TYPE_STALL)
4011 gcc_assert (n_filled == 0);
4012 delete_this = insn;
4014 else
4016 if (type == TYPE_DSP32 || type == TYPE_DSP32SHIFTIMM)
4017 slot[0] = insn;
4018 else if (slot[1] == NULL_RTX)
4019 slot[1] = insn;
4020 else
4021 slot[2] = insn;
4022 n_filled++;
4026 next = NEXT_INSN (insn);
4027 while (next && insn != BB_END (bb)
4028 && !(INSN_P (next)
4029 && GET_CODE (PATTERN (next)) != USE
4030 && GET_CODE (PATTERN (next)) != CLOBBER))
4032 insn = next;
4033 next = NEXT_INSN (insn);
4036 /* BB_END can change due to emitting extra NOPs, so check here. */
4037 at_end = insn == BB_END (bb);
4038 if (delete_this == NULL_RTX && (at_end || GET_MODE (next) == TImode))
4040 if ((n_filled < 2
4041 || !gen_one_bundle (slot))
4042 && slot[0] != NULL_RTX)
4044 rtx pat = PATTERN (slot[0]);
4045 if (GET_CODE (pat) == SET
4046 && GET_CODE (SET_SRC (pat)) == UNSPEC
4047 && XINT (SET_SRC (pat), 1) == UNSPEC_32BIT)
4049 SET_SRC (pat) = XVECEXP (SET_SRC (pat), 0, 0);
4050 INSN_CODE (slot[0]) = -1;
4051 df_insn_rescan (slot[0]);
4054 n_filled = 0;
4055 slot[0] = slot[1] = slot[2] = NULL;
4057 if (delete_this != NULL_RTX)
4058 delete_insn (delete_this);
4059 if (at_end)
4060 break;
4065 /* Ensure that no var tracking notes are emitted in the middle of a
4066 three-instruction bundle. */
4068 static void
4069 reorder_var_tracking_notes (void)
4071 basic_block bb;
4072 FOR_EACH_BB_FN (bb, cfun)
4074 rtx_insn *insn, *next;
4075 rtx_insn *queue = NULL;
4076 bool in_bundle = false;
4078 for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = next)
4080 next = NEXT_INSN (insn);
4082 if (INSN_P (insn))
4084 /* Emit queued up notes at the last instruction of a bundle. */
4085 if (GET_MODE (insn) == QImode)
4087 while (queue)
4089 rtx_insn *next_queue = PREV_INSN (queue);
4090 SET_PREV_INSN (NEXT_INSN (insn)) = queue;
4091 SET_NEXT_INSN (queue) = NEXT_INSN (insn);
4092 SET_NEXT_INSN (insn) = queue;
4093 SET_PREV_INSN (queue) = insn;
4094 queue = next_queue;
4096 in_bundle = false;
4098 else if (GET_MODE (insn) == SImode)
4099 in_bundle = true;
4101 else if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION)
4103 if (in_bundle)
4105 rtx_insn *prev = PREV_INSN (insn);
4106 SET_PREV_INSN (next) = prev;
4107 SET_NEXT_INSN (prev) = next;
4109 SET_PREV_INSN (insn) = queue;
4110 queue = insn;
4117 /* On some silicon revisions, functions shorter than a certain number of cycles
4118 can cause unpredictable behaviour. Work around this by adding NOPs as
4119 needed. */
4120 static void
4121 workaround_rts_anomaly (void)
4123 rtx_insn *insn, *first_insn = NULL;
4124 int cycles = 4;
4126 if (! ENABLE_WA_RETS)
4127 return;
4129 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4131 rtx pat;
4133 if (BARRIER_P (insn))
4134 return;
4136 if (NOTE_P (insn) || LABEL_P (insn))
4137 continue;
4139 if (JUMP_TABLE_DATA_P (insn))
4140 continue;
4142 if (first_insn == NULL_RTX)
4143 first_insn = insn;
4144 pat = PATTERN (insn);
4145 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4146 || GET_CODE (pat) == ASM_INPUT
4147 || asm_noperands (pat) >= 0)
4148 continue;
4150 if (CALL_P (insn))
4151 return;
4153 if (JUMP_P (insn))
4155 if (recog_memoized (insn) == CODE_FOR_return_internal)
4156 break;
4158 /* Nothing to worry about for direct jumps. */
4159 if (!any_condjump_p (insn))
4160 return;
4161 if (cycles <= 1)
4162 return;
4163 cycles--;
4165 else if (INSN_P (insn))
4167 rtx pat = PATTERN (insn);
4168 int this_cycles = 1;
4170 if (GET_CODE (pat) == PARALLEL)
4172 if (analyze_push_multiple_operation (pat)
4173 || analyze_pop_multiple_operation (pat))
4174 this_cycles = n_regs_to_save;
4176 else
4178 int icode = recog_memoized (insn);
4180 if (icode == CODE_FOR_link)
4181 this_cycles = 4;
4182 else if (icode == CODE_FOR_unlink)
4183 this_cycles = 3;
4184 else if (icode == CODE_FOR_mulsi3)
4185 this_cycles = 5;
4187 if (this_cycles >= cycles)
4188 return;
4190 cycles -= this_cycles;
4193 while (cycles > 0)
4195 emit_insn_before (gen_nop (), first_insn);
4196 cycles--;
4200 /* Return an insn type for INSN that can be used by the caller for anomaly
4201 workarounds. This differs from plain get_attr_type in that it handles
4202 SEQUENCEs. */
4204 static enum attr_type
4205 type_for_anomaly (rtx_insn *insn)
4207 rtx pat = PATTERN (insn);
4208 if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (pat))
4210 enum attr_type t;
4211 t = get_attr_type (seq->insn (1));
4212 if (t == TYPE_MCLD)
4213 return t;
4214 t = get_attr_type (seq->insn (2));
4215 if (t == TYPE_MCLD)
4216 return t;
4217 return TYPE_MCST;
4219 else
4220 return get_attr_type (insn);
4223 /* Return true iff the address found in MEM is based on the register
4224 NP_REG and optionally has a positive offset. */
4225 static bool
4226 harmless_null_pointer_p (rtx mem, int np_reg)
4228 mem = XEXP (mem, 0);
4229 if (GET_CODE (mem) == POST_INC || GET_CODE (mem) == POST_DEC)
4230 mem = XEXP (mem, 0);
4231 if (REG_P (mem) && (int) REGNO (mem) == np_reg)
4232 return true;
4233 if (GET_CODE (mem) == PLUS
4234 && REG_P (XEXP (mem, 0)) && (int) REGNO (XEXP (mem, 0)) == np_reg)
4236 mem = XEXP (mem, 1);
4237 if (GET_CODE (mem) == CONST_INT && INTVAL (mem) > 0)
4238 return true;
4240 return false;
4243 /* Return nonzero if INSN contains any loads that may trap. */
4245 static bool
4246 trapping_loads_p (rtx_insn *insn, int np_reg, bool after_np_branch)
4248 rtx mem = SET_SRC (single_set (insn));
4250 if (!after_np_branch)
4251 np_reg = -1;
4252 return ((np_reg == -1 || !harmless_null_pointer_p (mem, np_reg))
4253 && may_trap_p (mem));
4256 /* Return INSN if it is of TYPE_MCLD. Alternatively, if INSN is the start of
4257 a three-insn bundle, see if one of them is a load and return that if so.
4258 Return NULL if the insn does not contain loads. */
4259 static rtx_insn *
4260 find_load (rtx_insn *insn)
4262 if (!NONDEBUG_INSN_P (insn))
4263 return NULL;
4264 if (get_attr_type (insn) == TYPE_MCLD)
4265 return insn;
4266 if (GET_MODE (insn) != SImode)
4267 return NULL;
4268 do {
4269 insn = NEXT_INSN (insn);
4270 if ((GET_MODE (insn) == SImode || GET_MODE (insn) == QImode)
4271 && get_attr_type (insn) == TYPE_MCLD)
4272 return insn;
4273 } while (GET_MODE (insn) != QImode);
4274 return NULL;
4277 /* Determine whether PAT is an indirect call pattern. */
4278 static bool
4279 indirect_call_p (rtx pat)
4281 if (GET_CODE (pat) == PARALLEL)
4282 pat = XVECEXP (pat, 0, 0);
4283 if (GET_CODE (pat) == SET)
4284 pat = SET_SRC (pat);
4285 gcc_assert (GET_CODE (pat) == CALL);
4286 pat = XEXP (pat, 0);
4287 gcc_assert (GET_CODE (pat) == MEM);
4288 pat = XEXP (pat, 0);
4290 return REG_P (pat);
4293 /* During workaround_speculation, track whether we're in the shadow of a
4294 conditional branch that tests a P register for NULL. If so, we can omit
4295 emitting NOPs if we see a load from that P register, since a speculative
4296 access at address 0 isn't a problem, and the load is executed in all other
4297 cases anyway.
4298 Global for communication with note_np_check_stores through note_stores.
4300 int np_check_regno = -1;
4301 bool np_after_branch = false;
4303 /* Subroutine of workaround_speculation, called through note_stores. */
4304 static void
4305 note_np_check_stores (rtx x, const_rtx pat ATTRIBUTE_UNUSED,
4306 void *data ATTRIBUTE_UNUSED)
4308 if (REG_P (x) && (REGNO (x) == REG_CC || (int) REGNO (x) == np_check_regno))
4309 np_check_regno = -1;
4312 static void
4313 workaround_speculation (void)
4315 rtx_insn *insn, *next;
4316 rtx_insn *last_condjump = NULL;
4317 int cycles_since_jump = INT_MAX;
4318 int delay_added = 0;
4320 if (! ENABLE_WA_SPECULATIVE_LOADS && ! ENABLE_WA_SPECULATIVE_SYNCS
4321 && ! ENABLE_WA_INDIRECT_CALLS)
4322 return;
4324 /* First pass: find predicted-false branches; if something after them
4325 needs nops, insert them or change the branch to predict true. */
4326 for (insn = get_insns (); insn; insn = next)
4328 rtx pat;
4329 int delay_needed = 0;
4331 next = find_next_insn_start (insn);
4333 if (NOTE_P (insn) || BARRIER_P (insn))
4334 continue;
4335 if (JUMP_TABLE_DATA_P (insn))
4336 continue;
4338 if (LABEL_P (insn))
4340 np_check_regno = -1;
4341 continue;
4344 pat = PATTERN (insn);
4345 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
4346 continue;
4348 if (GET_CODE (pat) == ASM_INPUT || asm_noperands (pat) >= 0)
4350 np_check_regno = -1;
4351 continue;
4354 if (JUMP_P (insn))
4356 /* Is this a condjump based on a null pointer comparison we saw
4357 earlier? */
4358 if (np_check_regno != -1
4359 && recog_memoized (insn) == CODE_FOR_cbranchbi4)
4361 rtx op = XEXP (SET_SRC (PATTERN (insn)), 0);
4362 gcc_assert (GET_CODE (op) == EQ || GET_CODE (op) == NE);
4363 if (GET_CODE (op) == NE)
4364 np_after_branch = true;
4366 if (any_condjump_p (insn)
4367 && ! cbranch_predicted_taken_p (insn))
4369 last_condjump = insn;
4370 delay_added = 0;
4371 cycles_since_jump = 0;
4373 else
4374 cycles_since_jump = INT_MAX;
4376 else if (CALL_P (insn))
4378 np_check_regno = -1;
4379 if (cycles_since_jump < INT_MAX)
4380 cycles_since_jump++;
4381 if (indirect_call_p (pat) && ENABLE_WA_INDIRECT_CALLS)
4383 delay_needed = 3;
4386 else if (NONDEBUG_INSN_P (insn))
4388 rtx_insn *load_insn = find_load (insn);
4389 enum attr_type type = type_for_anomaly (insn);
4391 if (cycles_since_jump < INT_MAX)
4392 cycles_since_jump++;
4394 /* Detect a comparison of a P register with zero. If we later
4395 see a condjump based on it, we have found a null pointer
4396 check. */
4397 if (recog_memoized (insn) == CODE_FOR_compare_eq)
4399 rtx src = SET_SRC (PATTERN (insn));
4400 if (REG_P (XEXP (src, 0))
4401 && P_REGNO_P (REGNO (XEXP (src, 0)))
4402 && XEXP (src, 1) == const0_rtx)
4404 np_check_regno = REGNO (XEXP (src, 0));
4405 np_after_branch = false;
4407 else
4408 np_check_regno = -1;
4411 if (load_insn && ENABLE_WA_SPECULATIVE_LOADS)
4413 if (trapping_loads_p (load_insn, np_check_regno,
4414 np_after_branch))
4415 delay_needed = 4;
4417 else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS)
4418 delay_needed = 3;
4420 /* See if we need to forget about a null pointer comparison
4421 we found earlier. */
4422 if (recog_memoized (insn) != CODE_FOR_compare_eq)
4424 note_stores (PATTERN (insn), note_np_check_stores, NULL);
4425 if (np_check_regno != -1)
4427 if (find_regno_note (insn, REG_INC, np_check_regno))
4428 np_check_regno = -1;
4434 if (delay_needed > cycles_since_jump
4435 && (delay_needed - cycles_since_jump) > delay_added)
4437 rtx pat1;
4438 int num_clobbers;
4439 rtx *op = recog_data.operand;
4441 delay_needed -= cycles_since_jump;
4443 extract_insn (last_condjump);
4444 if (optimize_size)
4446 pat1 = gen_cbranch_predicted_taken (op[0], op[1], op[2],
4447 op[3]);
4448 cycles_since_jump = INT_MAX;
4450 else
4452 /* Do not adjust cycles_since_jump in this case, so that
4453 we'll increase the number of NOPs for a subsequent insn
4454 if necessary. */
4455 pat1 = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
4456 GEN_INT (delay_needed));
4457 delay_added = delay_needed;
4459 PATTERN (last_condjump) = pat1;
4460 INSN_CODE (last_condjump) = recog (pat1, insn, &num_clobbers);
4462 if (CALL_P (insn))
4464 cycles_since_jump = INT_MAX;
4465 delay_added = 0;
4469 /* Second pass: for predicted-true branches, see if anything at the
4470 branch destination needs extra nops. */
4471 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4473 int cycles_since_jump;
4474 if (JUMP_P (insn)
4475 && any_condjump_p (insn)
4476 && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken
4477 || cbranch_predicted_taken_p (insn)))
4479 rtx_insn *target = JUMP_LABEL_AS_INSN (insn);
4480 rtx label = target;
4481 rtx_insn *next_tgt;
4483 cycles_since_jump = 0;
4484 for (; target && cycles_since_jump < 3; target = next_tgt)
4486 rtx pat;
4488 next_tgt = find_next_insn_start (target);
4490 if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
4491 continue;
4493 if (JUMP_TABLE_DATA_P (target))
4494 continue;
4496 pat = PATTERN (target);
4497 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4498 || GET_CODE (pat) == ASM_INPUT
4499 || asm_noperands (pat) >= 0)
4500 continue;
4502 if (NONDEBUG_INSN_P (target))
4504 rtx_insn *load_insn = find_load (target);
4505 enum attr_type type = type_for_anomaly (target);
4506 int delay_needed = 0;
4507 if (cycles_since_jump < INT_MAX)
4508 cycles_since_jump++;
4510 if (load_insn && ENABLE_WA_SPECULATIVE_LOADS)
4512 if (trapping_loads_p (load_insn, -1, false))
4513 delay_needed = 2;
4515 else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS)
4516 delay_needed = 2;
4518 if (delay_needed > cycles_since_jump)
4520 rtx_insn *prev = prev_real_insn (label);
4521 delay_needed -= cycles_since_jump;
4522 if (dump_file)
4523 fprintf (dump_file, "Adding %d nops after %d\n",
4524 delay_needed, INSN_UID (label));
4525 if (JUMP_P (prev)
4526 && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops)
4528 rtx x;
4529 HOST_WIDE_INT v;
4531 if (dump_file)
4532 fprintf (dump_file,
4533 "Reducing nops on insn %d.\n",
4534 INSN_UID (prev));
4535 x = PATTERN (prev);
4536 x = XVECEXP (x, 0, 1);
4537 v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed;
4538 XVECEXP (x, 0, 0) = GEN_INT (v);
4540 while (delay_needed-- > 0)
4541 emit_insn_after (gen_nop (), label);
4542 break;
4550 /* Called just before the final scheduling pass. If we need to insert NOPs
4551 later on to work around speculative loads, insert special placeholder
4552 insns that cause loads to be delayed for as many cycles as necessary
4553 (and possible). This reduces the number of NOPs we need to add.
4554 The dummy insns we generate are later removed by bfin_gen_bundles. */
4555 static void
4556 add_sched_insns_for_speculation (void)
4558 rtx_insn *insn;
4560 if (! ENABLE_WA_SPECULATIVE_LOADS && ! ENABLE_WA_SPECULATIVE_SYNCS
4561 && ! ENABLE_WA_INDIRECT_CALLS)
4562 return;
4564 /* First pass: find predicted-false branches; if something after them
4565 needs nops, insert them or change the branch to predict true. */
4566 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4568 rtx pat;
4570 if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
4571 continue;
4572 if (JUMP_TABLE_DATA_P (insn))
4573 continue;
4575 pat = PATTERN (insn);
4576 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4577 || GET_CODE (pat) == ASM_INPUT
4578 || asm_noperands (pat) >= 0)
4579 continue;
4581 if (JUMP_P (insn))
4583 if (any_condjump_p (insn)
4584 && !cbranch_predicted_taken_p (insn))
4586 rtx_insn *n = next_real_insn (insn);
4587 emit_insn_before (gen_stall (GEN_INT (3)), n);
4592 /* Second pass: for predicted-true branches, see if anything at the
4593 branch destination needs extra nops. */
4594 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4596 if (JUMP_P (insn)
4597 && any_condjump_p (insn)
4598 && (cbranch_predicted_taken_p (insn)))
4600 rtx target = JUMP_LABEL (insn);
4601 rtx_insn *next = next_real_insn (target);
4603 if (GET_CODE (PATTERN (next)) == UNSPEC_VOLATILE
4604 && get_attr_type (next) == TYPE_STALL)
4605 continue;
4606 emit_insn_before (gen_stall (GEN_INT (1)), next);
4611 /* We use the machine specific reorg pass for emitting CSYNC instructions
4612 after conditional branches as needed.
4614 The Blackfin is unusual in that a code sequence like
4615 if cc jump label
4616 r0 = (p0)
4617 may speculatively perform the load even if the condition isn't true. This
4618 happens for a branch that is predicted not taken, because the pipeline
4619 isn't flushed or stalled, so the early stages of the following instructions,
4620 which perform the memory reference, are allowed to execute before the
4621 jump condition is evaluated.
4622 Therefore, we must insert additional instructions in all places where this
4623 could lead to incorrect behavior. The manual recommends CSYNC, while
4624 VDSP seems to use NOPs (even though its corresponding compiler option is
4625 named CSYNC).
4627 When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
4628 When optimizing for size, we turn the branch into a predicted taken one.
4629 This may be slower due to mispredicts, but saves code size. */
4631 static void
4632 bfin_reorg (void)
4634 /* We are freeing block_for_insn in the toplev to keep compatibility
4635 with old MDEP_REORGS that are not CFG based. Recompute it now. */
4636 compute_bb_for_insn ();
4638 if (flag_schedule_insns_after_reload)
4640 splitting_for_sched = 1;
4641 split_all_insns ();
4642 splitting_for_sched = 0;
4644 add_sched_insns_for_speculation ();
4646 timevar_push (TV_SCHED2);
4647 if (flag_selective_scheduling2
4648 && !maybe_skip_selective_scheduling ())
4649 run_selective_scheduling ();
4650 else
4651 schedule_insns ();
4652 timevar_pop (TV_SCHED2);
4654 /* Examine the schedule and insert nops as necessary for 64-bit parallel
4655 instructions. */
4656 bfin_gen_bundles ();
4659 df_analyze ();
4661 /* Doloop optimization */
4662 if (cfun->machine->has_hardware_loops)
4663 bfin_reorg_loops ();
4665 workaround_speculation ();
4667 if (flag_var_tracking)
4669 timevar_push (TV_VAR_TRACKING);
4670 variable_tracking_main ();
4671 reorder_var_tracking_notes ();
4672 timevar_pop (TV_VAR_TRACKING);
4675 df_finish_pass (false);
4677 workaround_rts_anomaly ();
4680 /* Handle interrupt_handler, exception_handler and nmi_handler function
4681 attributes; arguments as in struct attribute_spec.handler. */
4683 static tree
4684 handle_int_attribute (tree *node, tree name,
4685 tree args ATTRIBUTE_UNUSED,
4686 int flags ATTRIBUTE_UNUSED,
4687 bool *no_add_attrs)
4689 tree x = *node;
4690 if (TREE_CODE (x) == FUNCTION_DECL)
4691 x = TREE_TYPE (x);
4693 if (TREE_CODE (x) != FUNCTION_TYPE)
4695 warning (OPT_Wattributes, "%qE attribute only applies to functions",
4696 name);
4697 *no_add_attrs = true;
4699 else if (funkind (x) != SUBROUTINE)
4700 error ("multiple function type attributes specified");
4702 return NULL_TREE;
4705 /* Return 0 if the attributes for two types are incompatible, 1 if they
4706 are compatible, and 2 if they are nearly compatible (which causes a
4707 warning to be generated). */
4709 static int
4710 bfin_comp_type_attributes (const_tree type1, const_tree type2)
4712 e_funkind kind1, kind2;
4714 if (TREE_CODE (type1) != FUNCTION_TYPE)
4715 return 1;
4717 kind1 = funkind (type1);
4718 kind2 = funkind (type2);
4720 if (kind1 != kind2)
4721 return 0;
4723 /* Check for mismatched modifiers */
4724 if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
4725 != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
4726 return 0;
4728 if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
4729 != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
4730 return 0;
4732 if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
4733 != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
4734 return 0;
4736 if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1))
4737 != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2)))
4738 return 0;
4740 return 1;
4743 /* Handle a "longcall" or "shortcall" attribute; arguments as in
4744 struct attribute_spec.handler. */
4746 static tree
4747 bfin_handle_longcall_attribute (tree *node, tree name,
4748 tree args ATTRIBUTE_UNUSED,
4749 int flags ATTRIBUTE_UNUSED,
4750 bool *no_add_attrs)
4752 if (TREE_CODE (*node) != FUNCTION_TYPE
4753 && TREE_CODE (*node) != FIELD_DECL
4754 && TREE_CODE (*node) != TYPE_DECL)
4756 warning (OPT_Wattributes, "%qE attribute only applies to functions",
4757 name);
4758 *no_add_attrs = true;
4761 if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0
4762 && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node)))
4763 || (strcmp (IDENTIFIER_POINTER (name), "shortcall") == 0
4764 && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node))))
4766 warning (OPT_Wattributes,
4767 "can%'t apply both longcall and shortcall attributes to the same function");
4768 *no_add_attrs = true;
4771 return NULL_TREE;
4774 /* Handle a "l1_text" attribute; arguments as in
4775 struct attribute_spec.handler. */
4777 static tree
4778 bfin_handle_l1_text_attribute (tree *node, tree name, tree ARG_UNUSED (args),
4779 int ARG_UNUSED (flags), bool *no_add_attrs)
4781 tree decl = *node;
4783 if (TREE_CODE (decl) != FUNCTION_DECL)
4785 error ("%qE attribute only applies to functions",
4786 name);
4787 *no_add_attrs = true;
4790 /* The decl may have already been given a section attribute
4791 from a previous declaration. Ensure they match. */
4792 else if (DECL_SECTION_NAME (decl) != NULL
4793 && strcmp (DECL_SECTION_NAME (decl),
4794 ".l1.text") != 0)
4796 error ("section of %q+D conflicts with previous declaration",
4797 decl);
4798 *no_add_attrs = true;
4800 else
4801 set_decl_section_name (decl, ".l1.text");
4803 return NULL_TREE;
4806 /* Handle a "l1_data", "l1_data_A" or "l1_data_B" attribute;
4807 arguments as in struct attribute_spec.handler. */
4809 static tree
4810 bfin_handle_l1_data_attribute (tree *node, tree name, tree ARG_UNUSED (args),
4811 int ARG_UNUSED (flags), bool *no_add_attrs)
4813 tree decl = *node;
4815 if (TREE_CODE (decl) != VAR_DECL)
4817 error ("%qE attribute only applies to variables",
4818 name);
4819 *no_add_attrs = true;
4821 else if (current_function_decl != NULL_TREE
4822 && !TREE_STATIC (decl))
4824 error ("%qE attribute cannot be specified for local variables",
4825 name);
4826 *no_add_attrs = true;
4828 else
4830 const char *section_name;
4832 if (strcmp (IDENTIFIER_POINTER (name), "l1_data") == 0)
4833 section_name = ".l1.data";
4834 else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_A") == 0)
4835 section_name = ".l1.data.A";
4836 else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_B") == 0)
4837 section_name = ".l1.data.B";
4838 else
4839 gcc_unreachable ();
4841 /* The decl may have already been given a section attribute
4842 from a previous declaration. Ensure they match. */
4843 if (DECL_SECTION_NAME (decl) != NULL
4844 && strcmp (DECL_SECTION_NAME (decl),
4845 section_name) != 0)
4847 error ("section of %q+D conflicts with previous declaration",
4848 decl);
4849 *no_add_attrs = true;
4851 else
4852 set_decl_section_name (decl, section_name);
4855 return NULL_TREE;
4858 /* Handle a "l2" attribute; arguments as in struct attribute_spec.handler. */
4860 static tree
4861 bfin_handle_l2_attribute (tree *node, tree ARG_UNUSED (name),
4862 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
4863 bool *no_add_attrs)
4865 tree decl = *node;
4867 if (TREE_CODE (decl) == FUNCTION_DECL)
4869 if (DECL_SECTION_NAME (decl) != NULL
4870 && strcmp (DECL_SECTION_NAME (decl),
4871 ".l2.text") != 0)
4873 error ("section of %q+D conflicts with previous declaration",
4874 decl);
4875 *no_add_attrs = true;
4877 else
4878 set_decl_section_name (decl, ".l2.text");
4880 else if (TREE_CODE (decl) == VAR_DECL)
4882 if (DECL_SECTION_NAME (decl) != NULL
4883 && strcmp (DECL_SECTION_NAME (decl),
4884 ".l2.data") != 0)
4886 error ("section of %q+D conflicts with previous declaration",
4887 decl);
4888 *no_add_attrs = true;
4890 else
4891 set_decl_section_name (decl, ".l2.data");
4894 return NULL_TREE;
4897 /* Table of valid machine attributes. */
4898 static const struct attribute_spec bfin_attribute_table[] =
4900 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
4901 affects_type_identity } */
4902 { "interrupt_handler", 0, 0, false, true, true, handle_int_attribute,
4903 false },
4904 { "exception_handler", 0, 0, false, true, true, handle_int_attribute,
4905 false },
4906 { "nmi_handler", 0, 0, false, true, true, handle_int_attribute, false },
4907 { "nesting", 0, 0, false, true, true, NULL, false },
4908 { "kspisusp", 0, 0, false, true, true, NULL, false },
4909 { "saveall", 0, 0, false, true, true, NULL, false },
4910 { "longcall", 0, 0, false, true, true, bfin_handle_longcall_attribute,
4911 false },
4912 { "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute,
4913 false },
4914 { "l1_text", 0, 0, true, false, false, bfin_handle_l1_text_attribute,
4915 false },
4916 { "l1_data", 0, 0, true, false, false, bfin_handle_l1_data_attribute,
4917 false },
4918 { "l1_data_A", 0, 0, true, false, false, bfin_handle_l1_data_attribute,
4919 false },
4920 { "l1_data_B", 0, 0, true, false, false, bfin_handle_l1_data_attribute,
4921 false },
4922 { "l2", 0, 0, true, false, false, bfin_handle_l2_attribute, false },
4923 { NULL, 0, 0, false, false, false, NULL, false }
4926 /* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to
4927 tell the assembler to generate pointers to function descriptors in
4928 some cases. */
4930 static bool
4931 bfin_assemble_integer (rtx value, unsigned int size, int aligned_p)
4933 if (TARGET_FDPIC && size == UNITS_PER_WORD)
4935 if (GET_CODE (value) == SYMBOL_REF
4936 && SYMBOL_REF_FUNCTION_P (value))
4938 fputs ("\t.picptr\tfuncdesc(", asm_out_file);
4939 output_addr_const (asm_out_file, value);
4940 fputs (")\n", asm_out_file);
4941 return true;
4943 if (!aligned_p)
4945 /* We've set the unaligned SI op to NULL, so we always have to
4946 handle the unaligned case here. */
4947 assemble_integer_with_op ("\t.4byte\t", value);
4948 return true;
4951 return default_assemble_integer (value, size, aligned_p);
4954 /* Output the assembler code for a thunk function. THUNK_DECL is the
4955 declaration for the thunk function itself, FUNCTION is the decl for
4956 the target function. DELTA is an immediate constant offset to be
4957 added to THIS. If VCALL_OFFSET is nonzero, the word at
4958 *(*this + vcall_offset) should be added to THIS. */
4960 static void
4961 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
4962 tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
4963 HOST_WIDE_INT vcall_offset, tree function)
4965 rtx xops[3];
4966 /* The this parameter is passed as the first argument. */
4967 rtx this_rtx = gen_rtx_REG (Pmode, REG_R0);
4969 /* Adjust the this parameter by a fixed constant. */
4970 if (delta)
4972 xops[1] = this_rtx;
4973 if (delta >= -64 && delta <= 63)
4975 xops[0] = GEN_INT (delta);
4976 output_asm_insn ("%1 += %0;", xops);
4978 else if (delta >= -128 && delta < -64)
4980 xops[0] = GEN_INT (delta + 64);
4981 output_asm_insn ("%1 += -64; %1 += %0;", xops);
4983 else if (delta > 63 && delta <= 126)
4985 xops[0] = GEN_INT (delta - 63);
4986 output_asm_insn ("%1 += 63; %1 += %0;", xops);
4988 else
4990 xops[0] = GEN_INT (delta);
4991 output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
4995 /* Adjust the this parameter by a value stored in the vtable. */
4996 if (vcall_offset)
4998 rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
4999 rtx tmp = gen_rtx_REG (Pmode, REG_R3);
5001 xops[1] = tmp;
5002 xops[2] = p2tmp;
5003 output_asm_insn ("%2 = r0; %2 = [%2];", xops);
5005 /* Adjust the this parameter. */
5006 xops[0] = gen_rtx_MEM (Pmode, plus_constant (Pmode, p2tmp,
5007 vcall_offset));
5008 if (!memory_operand (xops[0], Pmode))
5010 rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
5011 xops[0] = GEN_INT (vcall_offset);
5012 xops[1] = tmp2;
5013 output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
5014 xops[0] = gen_rtx_MEM (Pmode, p2tmp);
5016 xops[2] = this_rtx;
5017 output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
5020 xops[0] = XEXP (DECL_RTL (function), 0);
5021 if (1 || !flag_pic || (*targetm.binds_local_p) (function))
5022 output_asm_insn ("jump.l\t%P0", xops);
5025 /* Codes for all the Blackfin builtins. */
5026 enum bfin_builtins
5028 BFIN_BUILTIN_CSYNC,
5029 BFIN_BUILTIN_SSYNC,
5030 BFIN_BUILTIN_ONES,
5031 BFIN_BUILTIN_COMPOSE_2X16,
5032 BFIN_BUILTIN_EXTRACTLO,
5033 BFIN_BUILTIN_EXTRACTHI,
5035 BFIN_BUILTIN_SSADD_2X16,
5036 BFIN_BUILTIN_SSSUB_2X16,
5037 BFIN_BUILTIN_SSADDSUB_2X16,
5038 BFIN_BUILTIN_SSSUBADD_2X16,
5039 BFIN_BUILTIN_MULT_2X16,
5040 BFIN_BUILTIN_MULTR_2X16,
5041 BFIN_BUILTIN_NEG_2X16,
5042 BFIN_BUILTIN_ABS_2X16,
5043 BFIN_BUILTIN_MIN_2X16,
5044 BFIN_BUILTIN_MAX_2X16,
5046 BFIN_BUILTIN_SSADD_1X16,
5047 BFIN_BUILTIN_SSSUB_1X16,
5048 BFIN_BUILTIN_MULT_1X16,
5049 BFIN_BUILTIN_MULTR_1X16,
5050 BFIN_BUILTIN_NORM_1X16,
5051 BFIN_BUILTIN_NEG_1X16,
5052 BFIN_BUILTIN_ABS_1X16,
5053 BFIN_BUILTIN_MIN_1X16,
5054 BFIN_BUILTIN_MAX_1X16,
5056 BFIN_BUILTIN_SUM_2X16,
5057 BFIN_BUILTIN_DIFFHL_2X16,
5058 BFIN_BUILTIN_DIFFLH_2X16,
5060 BFIN_BUILTIN_SSADD_1X32,
5061 BFIN_BUILTIN_SSSUB_1X32,
5062 BFIN_BUILTIN_NORM_1X32,
5063 BFIN_BUILTIN_ROUND_1X32,
5064 BFIN_BUILTIN_NEG_1X32,
5065 BFIN_BUILTIN_ABS_1X32,
5066 BFIN_BUILTIN_MIN_1X32,
5067 BFIN_BUILTIN_MAX_1X32,
5068 BFIN_BUILTIN_MULT_1X32,
5069 BFIN_BUILTIN_MULT_1X32X32,
5070 BFIN_BUILTIN_MULT_1X32X32NS,
5072 BFIN_BUILTIN_MULHISILL,
5073 BFIN_BUILTIN_MULHISILH,
5074 BFIN_BUILTIN_MULHISIHL,
5075 BFIN_BUILTIN_MULHISIHH,
5077 BFIN_BUILTIN_LSHIFT_1X16,
5078 BFIN_BUILTIN_LSHIFT_2X16,
5079 BFIN_BUILTIN_SSASHIFT_1X16,
5080 BFIN_BUILTIN_SSASHIFT_2X16,
5081 BFIN_BUILTIN_SSASHIFT_1X32,
5083 BFIN_BUILTIN_CPLX_MUL_16,
5084 BFIN_BUILTIN_CPLX_MAC_16,
5085 BFIN_BUILTIN_CPLX_MSU_16,
5087 BFIN_BUILTIN_CPLX_MUL_16_S40,
5088 BFIN_BUILTIN_CPLX_MAC_16_S40,
5089 BFIN_BUILTIN_CPLX_MSU_16_S40,
5091 BFIN_BUILTIN_CPLX_SQU,
5093 BFIN_BUILTIN_LOADBYTES,
5095 BFIN_BUILTIN_MAX
5098 #define def_builtin(NAME, TYPE, CODE) \
5099 do { \
5100 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
5101 NULL, NULL_TREE); \
5102 } while (0)
5104 /* Set up all builtin functions for this target. */
5105 static void
5106 bfin_init_builtins (void)
5108 tree V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
5109 tree void_ftype_void
5110 = build_function_type_list (void_type_node, NULL_TREE);
5111 tree short_ftype_short
5112 = build_function_type_list (short_integer_type_node, short_integer_type_node,
5113 NULL_TREE);
5114 tree short_ftype_int_int
5115 = build_function_type_list (short_integer_type_node, integer_type_node,
5116 integer_type_node, NULL_TREE);
5117 tree int_ftype_int_int
5118 = build_function_type_list (integer_type_node, integer_type_node,
5119 integer_type_node, NULL_TREE);
5120 tree int_ftype_int
5121 = build_function_type_list (integer_type_node, integer_type_node,
5122 NULL_TREE);
5123 tree short_ftype_int
5124 = build_function_type_list (short_integer_type_node, integer_type_node,
5125 NULL_TREE);
5126 tree int_ftype_v2hi_v2hi
5127 = build_function_type_list (integer_type_node, V2HI_type_node,
5128 V2HI_type_node, NULL_TREE);
5129 tree v2hi_ftype_v2hi_v2hi
5130 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5131 V2HI_type_node, NULL_TREE);
5132 tree v2hi_ftype_v2hi_v2hi_v2hi
5133 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5134 V2HI_type_node, V2HI_type_node, NULL_TREE);
5135 tree v2hi_ftype_int_int
5136 = build_function_type_list (V2HI_type_node, integer_type_node,
5137 integer_type_node, NULL_TREE);
5138 tree v2hi_ftype_v2hi_int
5139 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5140 integer_type_node, NULL_TREE);
5141 tree int_ftype_short_short
5142 = build_function_type_list (integer_type_node, short_integer_type_node,
5143 short_integer_type_node, NULL_TREE);
5144 tree v2hi_ftype_v2hi
5145 = build_function_type_list (V2HI_type_node, V2HI_type_node, NULL_TREE);
5146 tree short_ftype_v2hi
5147 = build_function_type_list (short_integer_type_node, V2HI_type_node,
5148 NULL_TREE);
5149 tree int_ftype_pint
5150 = build_function_type_list (integer_type_node,
5151 build_pointer_type (integer_type_node),
5152 NULL_TREE);
5154 /* Add the remaining MMX insns with somewhat more complicated types. */
5155 def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC);
5156 def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC);
5158 def_builtin ("__builtin_bfin_ones", short_ftype_int, BFIN_BUILTIN_ONES);
5160 def_builtin ("__builtin_bfin_compose_2x16", v2hi_ftype_int_int,
5161 BFIN_BUILTIN_COMPOSE_2X16);
5162 def_builtin ("__builtin_bfin_extract_hi", short_ftype_v2hi,
5163 BFIN_BUILTIN_EXTRACTHI);
5164 def_builtin ("__builtin_bfin_extract_lo", short_ftype_v2hi,
5165 BFIN_BUILTIN_EXTRACTLO);
5167 def_builtin ("__builtin_bfin_min_fr2x16", v2hi_ftype_v2hi_v2hi,
5168 BFIN_BUILTIN_MIN_2X16);
5169 def_builtin ("__builtin_bfin_max_fr2x16", v2hi_ftype_v2hi_v2hi,
5170 BFIN_BUILTIN_MAX_2X16);
5172 def_builtin ("__builtin_bfin_add_fr2x16", v2hi_ftype_v2hi_v2hi,
5173 BFIN_BUILTIN_SSADD_2X16);
5174 def_builtin ("__builtin_bfin_sub_fr2x16", v2hi_ftype_v2hi_v2hi,
5175 BFIN_BUILTIN_SSSUB_2X16);
5176 def_builtin ("__builtin_bfin_dspaddsubsat", v2hi_ftype_v2hi_v2hi,
5177 BFIN_BUILTIN_SSADDSUB_2X16);
5178 def_builtin ("__builtin_bfin_dspsubaddsat", v2hi_ftype_v2hi_v2hi,
5179 BFIN_BUILTIN_SSSUBADD_2X16);
5180 def_builtin ("__builtin_bfin_mult_fr2x16", v2hi_ftype_v2hi_v2hi,
5181 BFIN_BUILTIN_MULT_2X16);
5182 def_builtin ("__builtin_bfin_multr_fr2x16", v2hi_ftype_v2hi_v2hi,
5183 BFIN_BUILTIN_MULTR_2X16);
5184 def_builtin ("__builtin_bfin_negate_fr2x16", v2hi_ftype_v2hi,
5185 BFIN_BUILTIN_NEG_2X16);
5186 def_builtin ("__builtin_bfin_abs_fr2x16", v2hi_ftype_v2hi,
5187 BFIN_BUILTIN_ABS_2X16);
5189 def_builtin ("__builtin_bfin_min_fr1x16", short_ftype_int_int,
5190 BFIN_BUILTIN_MIN_1X16);
5191 def_builtin ("__builtin_bfin_max_fr1x16", short_ftype_int_int,
5192 BFIN_BUILTIN_MAX_1X16);
5194 def_builtin ("__builtin_bfin_add_fr1x16", short_ftype_int_int,
5195 BFIN_BUILTIN_SSADD_1X16);
5196 def_builtin ("__builtin_bfin_sub_fr1x16", short_ftype_int_int,
5197 BFIN_BUILTIN_SSSUB_1X16);
5198 def_builtin ("__builtin_bfin_mult_fr1x16", short_ftype_int_int,
5199 BFIN_BUILTIN_MULT_1X16);
5200 def_builtin ("__builtin_bfin_multr_fr1x16", short_ftype_int_int,
5201 BFIN_BUILTIN_MULTR_1X16);
5202 def_builtin ("__builtin_bfin_negate_fr1x16", short_ftype_short,
5203 BFIN_BUILTIN_NEG_1X16);
5204 def_builtin ("__builtin_bfin_abs_fr1x16", short_ftype_short,
5205 BFIN_BUILTIN_ABS_1X16);
5206 def_builtin ("__builtin_bfin_norm_fr1x16", short_ftype_int,
5207 BFIN_BUILTIN_NORM_1X16);
5209 def_builtin ("__builtin_bfin_sum_fr2x16", short_ftype_v2hi,
5210 BFIN_BUILTIN_SUM_2X16);
5211 def_builtin ("__builtin_bfin_diff_hl_fr2x16", short_ftype_v2hi,
5212 BFIN_BUILTIN_DIFFHL_2X16);
5213 def_builtin ("__builtin_bfin_diff_lh_fr2x16", short_ftype_v2hi,
5214 BFIN_BUILTIN_DIFFLH_2X16);
5216 def_builtin ("__builtin_bfin_mulhisill", int_ftype_v2hi_v2hi,
5217 BFIN_BUILTIN_MULHISILL);
5218 def_builtin ("__builtin_bfin_mulhisihl", int_ftype_v2hi_v2hi,
5219 BFIN_BUILTIN_MULHISIHL);
5220 def_builtin ("__builtin_bfin_mulhisilh", int_ftype_v2hi_v2hi,
5221 BFIN_BUILTIN_MULHISILH);
5222 def_builtin ("__builtin_bfin_mulhisihh", int_ftype_v2hi_v2hi,
5223 BFIN_BUILTIN_MULHISIHH);
5225 def_builtin ("__builtin_bfin_min_fr1x32", int_ftype_int_int,
5226 BFIN_BUILTIN_MIN_1X32);
5227 def_builtin ("__builtin_bfin_max_fr1x32", int_ftype_int_int,
5228 BFIN_BUILTIN_MAX_1X32);
5230 def_builtin ("__builtin_bfin_add_fr1x32", int_ftype_int_int,
5231 BFIN_BUILTIN_SSADD_1X32);
5232 def_builtin ("__builtin_bfin_sub_fr1x32", int_ftype_int_int,
5233 BFIN_BUILTIN_SSSUB_1X32);
5234 def_builtin ("__builtin_bfin_negate_fr1x32", int_ftype_int,
5235 BFIN_BUILTIN_NEG_1X32);
5236 def_builtin ("__builtin_bfin_abs_fr1x32", int_ftype_int,
5237 BFIN_BUILTIN_ABS_1X32);
5238 def_builtin ("__builtin_bfin_norm_fr1x32", short_ftype_int,
5239 BFIN_BUILTIN_NORM_1X32);
5240 def_builtin ("__builtin_bfin_round_fr1x32", short_ftype_int,
5241 BFIN_BUILTIN_ROUND_1X32);
5242 def_builtin ("__builtin_bfin_mult_fr1x32", int_ftype_short_short,
5243 BFIN_BUILTIN_MULT_1X32);
5244 def_builtin ("__builtin_bfin_mult_fr1x32x32", int_ftype_int_int,
5245 BFIN_BUILTIN_MULT_1X32X32);
5246 def_builtin ("__builtin_bfin_mult_fr1x32x32NS", int_ftype_int_int,
5247 BFIN_BUILTIN_MULT_1X32X32NS);
5249 /* Shifts. */
5250 def_builtin ("__builtin_bfin_shl_fr1x16", short_ftype_int_int,
5251 BFIN_BUILTIN_SSASHIFT_1X16);
5252 def_builtin ("__builtin_bfin_shl_fr2x16", v2hi_ftype_v2hi_int,
5253 BFIN_BUILTIN_SSASHIFT_2X16);
5254 def_builtin ("__builtin_bfin_lshl_fr1x16", short_ftype_int_int,
5255 BFIN_BUILTIN_LSHIFT_1X16);
5256 def_builtin ("__builtin_bfin_lshl_fr2x16", v2hi_ftype_v2hi_int,
5257 BFIN_BUILTIN_LSHIFT_2X16);
5258 def_builtin ("__builtin_bfin_shl_fr1x32", int_ftype_int_int,
5259 BFIN_BUILTIN_SSASHIFT_1X32);
5261 /* Complex numbers. */
5262 def_builtin ("__builtin_bfin_cmplx_add", v2hi_ftype_v2hi_v2hi,
5263 BFIN_BUILTIN_SSADD_2X16);
5264 def_builtin ("__builtin_bfin_cmplx_sub", v2hi_ftype_v2hi_v2hi,
5265 BFIN_BUILTIN_SSSUB_2X16);
5266 def_builtin ("__builtin_bfin_cmplx_mul", v2hi_ftype_v2hi_v2hi,
5267 BFIN_BUILTIN_CPLX_MUL_16);
5268 def_builtin ("__builtin_bfin_cmplx_mac", v2hi_ftype_v2hi_v2hi_v2hi,
5269 BFIN_BUILTIN_CPLX_MAC_16);
5270 def_builtin ("__builtin_bfin_cmplx_msu", v2hi_ftype_v2hi_v2hi_v2hi,
5271 BFIN_BUILTIN_CPLX_MSU_16);
5272 def_builtin ("__builtin_bfin_cmplx_mul_s40", v2hi_ftype_v2hi_v2hi,
5273 BFIN_BUILTIN_CPLX_MUL_16_S40);
5274 def_builtin ("__builtin_bfin_cmplx_mac_s40", v2hi_ftype_v2hi_v2hi_v2hi,
5275 BFIN_BUILTIN_CPLX_MAC_16_S40);
5276 def_builtin ("__builtin_bfin_cmplx_msu_s40", v2hi_ftype_v2hi_v2hi_v2hi,
5277 BFIN_BUILTIN_CPLX_MSU_16_S40);
5278 def_builtin ("__builtin_bfin_csqu_fr16", v2hi_ftype_v2hi,
5279 BFIN_BUILTIN_CPLX_SQU);
5281 /* "Unaligned" load. */
5282 def_builtin ("__builtin_bfin_loadbytes", int_ftype_pint,
5283 BFIN_BUILTIN_LOADBYTES);
5288 struct builtin_description
5290 const enum insn_code icode;
5291 const char *const name;
5292 const enum bfin_builtins code;
5293 int macflag;
5296 static const struct builtin_description bdesc_2arg[] =
5298 { CODE_FOR_composev2hi, "__builtin_bfin_compose_2x16", BFIN_BUILTIN_COMPOSE_2X16, -1 },
5300 { CODE_FOR_ssashiftv2hi3, "__builtin_bfin_shl_fr2x16", BFIN_BUILTIN_SSASHIFT_2X16, -1 },
5301 { CODE_FOR_ssashifthi3, "__builtin_bfin_shl_fr1x16", BFIN_BUILTIN_SSASHIFT_1X16, -1 },
5302 { CODE_FOR_lshiftv2hi3, "__builtin_bfin_lshl_fr2x16", BFIN_BUILTIN_LSHIFT_2X16, -1 },
5303 { CODE_FOR_lshifthi3, "__builtin_bfin_lshl_fr1x16", BFIN_BUILTIN_LSHIFT_1X16, -1 },
5304 { CODE_FOR_ssashiftsi3, "__builtin_bfin_shl_fr1x32", BFIN_BUILTIN_SSASHIFT_1X32, -1 },
5306 { CODE_FOR_sminhi3, "__builtin_bfin_min_fr1x16", BFIN_BUILTIN_MIN_1X16, -1 },
5307 { CODE_FOR_smaxhi3, "__builtin_bfin_max_fr1x16", BFIN_BUILTIN_MAX_1X16, -1 },
5308 { CODE_FOR_ssaddhi3, "__builtin_bfin_add_fr1x16", BFIN_BUILTIN_SSADD_1X16, -1 },
5309 { CODE_FOR_sssubhi3, "__builtin_bfin_sub_fr1x16", BFIN_BUILTIN_SSSUB_1X16, -1 },
5311 { CODE_FOR_sminsi3, "__builtin_bfin_min_fr1x32", BFIN_BUILTIN_MIN_1X32, -1 },
5312 { CODE_FOR_smaxsi3, "__builtin_bfin_max_fr1x32", BFIN_BUILTIN_MAX_1X32, -1 },
5313 { CODE_FOR_ssaddsi3, "__builtin_bfin_add_fr1x32", BFIN_BUILTIN_SSADD_1X32, -1 },
5314 { CODE_FOR_sssubsi3, "__builtin_bfin_sub_fr1x32", BFIN_BUILTIN_SSSUB_1X32, -1 },
5316 { CODE_FOR_sminv2hi3, "__builtin_bfin_min_fr2x16", BFIN_BUILTIN_MIN_2X16, -1 },
5317 { CODE_FOR_smaxv2hi3, "__builtin_bfin_max_fr2x16", BFIN_BUILTIN_MAX_2X16, -1 },
5318 { CODE_FOR_ssaddv2hi3, "__builtin_bfin_add_fr2x16", BFIN_BUILTIN_SSADD_2X16, -1 },
5319 { CODE_FOR_sssubv2hi3, "__builtin_bfin_sub_fr2x16", BFIN_BUILTIN_SSSUB_2X16, -1 },
5320 { CODE_FOR_ssaddsubv2hi3, "__builtin_bfin_dspaddsubsat", BFIN_BUILTIN_SSADDSUB_2X16, -1 },
5321 { CODE_FOR_sssubaddv2hi3, "__builtin_bfin_dspsubaddsat", BFIN_BUILTIN_SSSUBADD_2X16, -1 },
5323 { CODE_FOR_flag_mulhisi, "__builtin_bfin_mult_fr1x32", BFIN_BUILTIN_MULT_1X32, MACFLAG_NONE },
5324 { CODE_FOR_flag_mulhi, "__builtin_bfin_mult_fr1x16", BFIN_BUILTIN_MULT_1X16, MACFLAG_T },
5325 { CODE_FOR_flag_mulhi, "__builtin_bfin_multr_fr1x16", BFIN_BUILTIN_MULTR_1X16, MACFLAG_NONE },
5326 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_mult_fr2x16", BFIN_BUILTIN_MULT_2X16, MACFLAG_T },
5327 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_multr_fr2x16", BFIN_BUILTIN_MULTR_2X16, MACFLAG_NONE },
5329 { CODE_FOR_mulhisi_ll, "__builtin_bfin_mulhisill", BFIN_BUILTIN_MULHISILL, -1 },
5330 { CODE_FOR_mulhisi_lh, "__builtin_bfin_mulhisilh", BFIN_BUILTIN_MULHISILH, -1 },
5331 { CODE_FOR_mulhisi_hl, "__builtin_bfin_mulhisihl", BFIN_BUILTIN_MULHISIHL, -1 },
5332 { CODE_FOR_mulhisi_hh, "__builtin_bfin_mulhisihh", BFIN_BUILTIN_MULHISIHH, -1 }
5336 static const struct builtin_description bdesc_1arg[] =
5338 { CODE_FOR_loadbytes, "__builtin_bfin_loadbytes", BFIN_BUILTIN_LOADBYTES, 0 },
5340 { CODE_FOR_ones, "__builtin_bfin_ones", BFIN_BUILTIN_ONES, 0 },
5342 { CODE_FOR_clrsbhi2, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16, 0 },
5343 { CODE_FOR_ssneghi2, "__builtin_bfin_negate_fr1x16", BFIN_BUILTIN_NEG_1X16, 0 },
5344 { CODE_FOR_abshi2, "__builtin_bfin_abs_fr1x16", BFIN_BUILTIN_ABS_1X16, 0 },
5346 { CODE_FOR_clrsbsi2, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32, 0 },
5347 { CODE_FOR_ssroundsi2, "__builtin_bfin_round_fr1x32", BFIN_BUILTIN_ROUND_1X32, 0 },
5348 { CODE_FOR_ssnegsi2, "__builtin_bfin_negate_fr1x32", BFIN_BUILTIN_NEG_1X32, 0 },
5349 { CODE_FOR_ssabssi2, "__builtin_bfin_abs_fr1x32", BFIN_BUILTIN_ABS_1X32, 0 },
5351 { CODE_FOR_movv2hi_hi_low, "__builtin_bfin_extract_lo", BFIN_BUILTIN_EXTRACTLO, 0 },
5352 { CODE_FOR_movv2hi_hi_high, "__builtin_bfin_extract_hi", BFIN_BUILTIN_EXTRACTHI, 0 },
5353 { CODE_FOR_ssnegv2hi2, "__builtin_bfin_negate_fr2x16", BFIN_BUILTIN_NEG_2X16, 0 },
5354 { CODE_FOR_ssabsv2hi2, "__builtin_bfin_abs_fr2x16", BFIN_BUILTIN_ABS_2X16, 0 }
5357 /* Errors in the source file can cause expand_expr to return const0_rtx
5358 where we expect a vector. To avoid crashing, use one of the vector
5359 clear instructions. */
5360 static rtx
5361 safe_vector_operand (rtx x, machine_mode mode)
5363 if (x != const0_rtx)
5364 return x;
5365 x = gen_reg_rtx (SImode);
5367 emit_insn (gen_movsi (x, CONST0_RTX (SImode)));
5368 return gen_lowpart (mode, x);
5371 /* Subroutine of bfin_expand_builtin to take care of binop insns. MACFLAG is -1
5372 if this is a normal binary op, or one of the MACFLAG_xxx constants. */
5374 static rtx
5375 bfin_expand_binop_builtin (enum insn_code icode, tree exp, rtx target,
5376 int macflag)
5378 rtx pat;
5379 tree arg0 = CALL_EXPR_ARG (exp, 0);
5380 tree arg1 = CALL_EXPR_ARG (exp, 1);
5381 rtx op0 = expand_normal (arg0);
5382 rtx op1 = expand_normal (arg1);
5383 machine_mode op0mode = GET_MODE (op0);
5384 machine_mode op1mode = GET_MODE (op1);
5385 machine_mode tmode = insn_data[icode].operand[0].mode;
5386 machine_mode mode0 = insn_data[icode].operand[1].mode;
5387 machine_mode mode1 = insn_data[icode].operand[2].mode;
5389 if (VECTOR_MODE_P (mode0))
5390 op0 = safe_vector_operand (op0, mode0);
5391 if (VECTOR_MODE_P (mode1))
5392 op1 = safe_vector_operand (op1, mode1);
5394 if (! target
5395 || GET_MODE (target) != tmode
5396 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5397 target = gen_reg_rtx (tmode);
5399 if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode)
5401 op0mode = HImode;
5402 op0 = gen_lowpart (HImode, op0);
5404 if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode)
5406 op1mode = HImode;
5407 op1 = gen_lowpart (HImode, op1);
5409 /* In case the insn wants input operands in modes different from
5410 the result, abort. */
5411 gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
5412 && (op1mode == mode1 || op1mode == VOIDmode));
5414 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5415 op0 = copy_to_mode_reg (mode0, op0);
5416 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
5417 op1 = copy_to_mode_reg (mode1, op1);
5419 if (macflag == -1)
5420 pat = GEN_FCN (icode) (target, op0, op1);
5421 else
5422 pat = GEN_FCN (icode) (target, op0, op1, GEN_INT (macflag));
5423 if (! pat)
5424 return 0;
5426 emit_insn (pat);
5427 return target;
5430 /* Subroutine of bfin_expand_builtin to take care of unop insns. */
5432 static rtx
5433 bfin_expand_unop_builtin (enum insn_code icode, tree exp,
5434 rtx target)
5436 rtx pat;
5437 tree arg0 = CALL_EXPR_ARG (exp, 0);
5438 rtx op0 = expand_normal (arg0);
5439 machine_mode op0mode = GET_MODE (op0);
5440 machine_mode tmode = insn_data[icode].operand[0].mode;
5441 machine_mode mode0 = insn_data[icode].operand[1].mode;
5443 if (! target
5444 || GET_MODE (target) != tmode
5445 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5446 target = gen_reg_rtx (tmode);
5448 if (VECTOR_MODE_P (mode0))
5449 op0 = safe_vector_operand (op0, mode0);
5451 if (op0mode == SImode && mode0 == HImode)
5453 op0mode = HImode;
5454 op0 = gen_lowpart (HImode, op0);
5456 gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
5458 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5459 op0 = copy_to_mode_reg (mode0, op0);
5461 pat = GEN_FCN (icode) (target, op0);
5462 if (! pat)
5463 return 0;
5464 emit_insn (pat);
5465 return target;
5468 /* Expand an expression EXP that calls a built-in function,
5469 with result going to TARGET if that's convenient
5470 (and in mode MODE if that's convenient).
5471 SUBTARGET may be used as the target for computing one of EXP's operands.
5472 IGNORE is nonzero if the value is to be ignored. */
5474 static rtx
5475 bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
5476 rtx subtarget ATTRIBUTE_UNUSED,
5477 machine_mode mode ATTRIBUTE_UNUSED,
5478 int ignore ATTRIBUTE_UNUSED)
5480 size_t i;
5481 enum insn_code icode;
5482 const struct builtin_description *d;
5483 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
5484 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
5485 tree arg0, arg1, arg2;
5486 rtx op0, op1, op2, accvec, pat, tmp1, tmp2, a0reg, a1reg;
5487 machine_mode tmode, mode0;
5489 switch (fcode)
5491 case BFIN_BUILTIN_CSYNC:
5492 emit_insn (gen_csync ());
5493 return 0;
5494 case BFIN_BUILTIN_SSYNC:
5495 emit_insn (gen_ssync ());
5496 return 0;
5498 case BFIN_BUILTIN_DIFFHL_2X16:
5499 case BFIN_BUILTIN_DIFFLH_2X16:
5500 case BFIN_BUILTIN_SUM_2X16:
5501 arg0 = CALL_EXPR_ARG (exp, 0);
5502 op0 = expand_normal (arg0);
5503 icode = (fcode == BFIN_BUILTIN_DIFFHL_2X16 ? CODE_FOR_subhilov2hi3
5504 : fcode == BFIN_BUILTIN_DIFFLH_2X16 ? CODE_FOR_sublohiv2hi3
5505 : CODE_FOR_ssaddhilov2hi3);
5506 tmode = insn_data[icode].operand[0].mode;
5507 mode0 = insn_data[icode].operand[1].mode;
5509 if (! target
5510 || GET_MODE (target) != tmode
5511 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5512 target = gen_reg_rtx (tmode);
5514 if (VECTOR_MODE_P (mode0))
5515 op0 = safe_vector_operand (op0, mode0);
5517 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5518 op0 = copy_to_mode_reg (mode0, op0);
5520 pat = GEN_FCN (icode) (target, op0, op0);
5521 if (! pat)
5522 return 0;
5523 emit_insn (pat);
5524 return target;
5526 case BFIN_BUILTIN_MULT_1X32X32:
5527 case BFIN_BUILTIN_MULT_1X32X32NS:
5528 arg0 = CALL_EXPR_ARG (exp, 0);
5529 arg1 = CALL_EXPR_ARG (exp, 1);
5530 op0 = expand_normal (arg0);
5531 op1 = expand_normal (arg1);
5532 if (! target
5533 || !register_operand (target, SImode))
5534 target = gen_reg_rtx (SImode);
5535 if (! register_operand (op0, SImode))
5536 op0 = copy_to_mode_reg (SImode, op0);
5537 if (! register_operand (op1, SImode))
5538 op1 = copy_to_mode_reg (SImode, op1);
5540 a1reg = gen_rtx_REG (PDImode, REG_A1);
5541 a0reg = gen_rtx_REG (PDImode, REG_A0);
5542 tmp1 = gen_lowpart (V2HImode, op0);
5543 tmp2 = gen_lowpart (V2HImode, op1);
5544 emit_insn (gen_flag_macinit1hi (a1reg,
5545 gen_lowpart (HImode, op0),
5546 gen_lowpart (HImode, op1),
5547 GEN_INT (MACFLAG_FU)));
5548 emit_insn (gen_lshrpdi3 (a1reg, a1reg, GEN_INT (16)));
5550 if (fcode == BFIN_BUILTIN_MULT_1X32X32)
5551 emit_insn (gen_flag_mul_macv2hi_parts_acconly (a0reg, a1reg, tmp1, tmp2,
5552 const1_rtx, const1_rtx,
5553 const1_rtx, const0_rtx, a1reg,
5554 const0_rtx, GEN_INT (MACFLAG_NONE),
5555 GEN_INT (MACFLAG_M)));
5556 else
5558 /* For saturating multiplication, there's exactly one special case
5559 to be handled: multiplying the smallest negative value with
5560 itself. Due to shift correction in fractional multiplies, this
5561 can overflow. Iff this happens, OP2 will contain 1, which, when
5562 added in 32 bits to the smallest negative, wraps to the largest
5563 positive, which is the result we want. */
5564 op2 = gen_reg_rtx (V2HImode);
5565 emit_insn (gen_packv2hi (op2, tmp1, tmp2, const0_rtx, const0_rtx));
5566 emit_insn (gen_movsibi (gen_rtx_REG (BImode, REG_CC),
5567 gen_lowpart (SImode, op2)));
5568 emit_insn (gen_flag_mul_macv2hi_parts_acconly_andcc0 (a0reg, a1reg, tmp1, tmp2,
5569 const1_rtx, const1_rtx,
5570 const1_rtx, const0_rtx, a1reg,
5571 const0_rtx, GEN_INT (MACFLAG_NONE),
5572 GEN_INT (MACFLAG_M)));
5573 op2 = gen_reg_rtx (SImode);
5574 emit_insn (gen_movbisi (op2, gen_rtx_REG (BImode, REG_CC)));
5576 emit_insn (gen_flag_machi_parts_acconly (a1reg, tmp2, tmp1,
5577 const1_rtx, const0_rtx,
5578 a1reg, const0_rtx, GEN_INT (MACFLAG_M)));
5579 emit_insn (gen_ashrpdi3 (a1reg, a1reg, GEN_INT (15)));
5580 emit_insn (gen_sum_of_accumulators (target, a0reg, a0reg, a1reg));
5581 if (fcode == BFIN_BUILTIN_MULT_1X32X32NS)
5582 emit_insn (gen_addsi3 (target, target, op2));
5583 return target;
5585 case BFIN_BUILTIN_CPLX_MUL_16:
5586 case BFIN_BUILTIN_CPLX_MUL_16_S40:
5587 arg0 = CALL_EXPR_ARG (exp, 0);
5588 arg1 = CALL_EXPR_ARG (exp, 1);
5589 op0 = expand_normal (arg0);
5590 op1 = expand_normal (arg1);
5591 accvec = gen_reg_rtx (V2PDImode);
5592 icode = CODE_FOR_flag_macv2hi_parts;
5593 tmode = insn_data[icode].operand[0].mode;
5595 if (! target
5596 || GET_MODE (target) != V2HImode
5597 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5598 target = gen_reg_rtx (tmode);
5599 if (! register_operand (op0, GET_MODE (op0)))
5600 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
5601 if (! register_operand (op1, GET_MODE (op1)))
5602 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
5604 if (fcode == BFIN_BUILTIN_CPLX_MUL_16)
5605 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
5606 const0_rtx, const0_rtx,
5607 const1_rtx, GEN_INT (MACFLAG_W32)));
5608 else
5609 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
5610 const0_rtx, const0_rtx,
5611 const1_rtx, GEN_INT (MACFLAG_NONE)));
5612 emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
5613 const1_rtx, const1_rtx,
5614 const0_rtx, accvec, const1_rtx, const0_rtx,
5615 GEN_INT (MACFLAG_NONE), accvec));
5617 return target;
5619 case BFIN_BUILTIN_CPLX_MAC_16:
5620 case BFIN_BUILTIN_CPLX_MSU_16:
5621 case BFIN_BUILTIN_CPLX_MAC_16_S40:
5622 case BFIN_BUILTIN_CPLX_MSU_16_S40:
5623 arg0 = CALL_EXPR_ARG (exp, 0);
5624 arg1 = CALL_EXPR_ARG (exp, 1);
5625 arg2 = CALL_EXPR_ARG (exp, 2);
5626 op0 = expand_normal (arg0);
5627 op1 = expand_normal (arg1);
5628 op2 = expand_normal (arg2);
5629 accvec = gen_reg_rtx (V2PDImode);
5630 icode = CODE_FOR_flag_macv2hi_parts;
5631 tmode = insn_data[icode].operand[0].mode;
5633 if (! target
5634 || GET_MODE (target) != V2HImode
5635 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5636 target = gen_reg_rtx (tmode);
5637 if (! register_operand (op1, GET_MODE (op1)))
5638 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
5639 if (! register_operand (op2, GET_MODE (op2)))
5640 op2 = copy_to_mode_reg (GET_MODE (op2), op2);
5642 tmp1 = gen_reg_rtx (SImode);
5643 tmp2 = gen_reg_rtx (SImode);
5644 emit_insn (gen_ashlsi3 (tmp1, gen_lowpart (SImode, op0), GEN_INT (16)));
5645 emit_move_insn (tmp2, gen_lowpart (SImode, op0));
5646 emit_insn (gen_movstricthi_1 (gen_lowpart (HImode, tmp2), const0_rtx));
5647 emit_insn (gen_load_accumulator_pair (accvec, tmp1, tmp2));
5648 if (fcode == BFIN_BUILTIN_CPLX_MAC_16
5649 || fcode == BFIN_BUILTIN_CPLX_MSU_16)
5650 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx,
5651 const0_rtx, const0_rtx,
5652 const1_rtx, accvec, const0_rtx,
5653 const0_rtx,
5654 GEN_INT (MACFLAG_W32)));
5655 else
5656 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx,
5657 const0_rtx, const0_rtx,
5658 const1_rtx, accvec, const0_rtx,
5659 const0_rtx,
5660 GEN_INT (MACFLAG_NONE)));
5661 if (fcode == BFIN_BUILTIN_CPLX_MAC_16
5662 || fcode == BFIN_BUILTIN_CPLX_MAC_16_S40)
5664 tmp1 = const1_rtx;
5665 tmp2 = const0_rtx;
5667 else
5669 tmp1 = const0_rtx;
5670 tmp2 = const1_rtx;
5672 emit_insn (gen_flag_macv2hi_parts (target, op1, op2, const1_rtx,
5673 const1_rtx, const1_rtx,
5674 const0_rtx, accvec, tmp1, tmp2,
5675 GEN_INT (MACFLAG_NONE), accvec));
5677 return target;
5679 case BFIN_BUILTIN_CPLX_SQU:
5680 arg0 = CALL_EXPR_ARG (exp, 0);
5681 op0 = expand_normal (arg0);
5682 accvec = gen_reg_rtx (V2PDImode);
5683 icode = CODE_FOR_flag_mulv2hi;
5684 tmp1 = gen_reg_rtx (V2HImode);
5685 tmp2 = gen_reg_rtx (V2HImode);
5687 if (! target
5688 || GET_MODE (target) != V2HImode
5689 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5690 target = gen_reg_rtx (V2HImode);
5691 if (! register_operand (op0, GET_MODE (op0)))
5692 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
5694 emit_insn (gen_flag_mulv2hi (tmp1, op0, op0, GEN_INT (MACFLAG_NONE)));
5696 emit_insn (gen_flag_mulhi_parts (gen_lowpart (HImode, tmp2), op0, op0,
5697 const0_rtx, const1_rtx,
5698 GEN_INT (MACFLAG_NONE)));
5700 emit_insn (gen_ssaddhi3_high_parts (target, tmp2, tmp2, tmp2, const0_rtx,
5701 const0_rtx));
5702 emit_insn (gen_sssubhi3_low_parts (target, target, tmp1, tmp1,
5703 const0_rtx, const1_rtx));
5705 return target;
5707 default:
5708 break;
5711 for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
5712 if (d->code == fcode)
5713 return bfin_expand_binop_builtin (d->icode, exp, target,
5714 d->macflag);
5716 for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
5717 if (d->code == fcode)
5718 return bfin_expand_unop_builtin (d->icode, exp, target);
5720 gcc_unreachable ();
5723 static void
5724 bfin_conditional_register_usage (void)
5726 /* initialize condition code flag register rtx */
5727 bfin_cc_rtx = gen_rtx_REG (BImode, REG_CC);
5728 bfin_rets_rtx = gen_rtx_REG (Pmode, REG_RETS);
5729 if (TARGET_FDPIC)
5730 call_used_regs[FDPIC_REGNO] = 1;
5731 if (!TARGET_FDPIC && flag_pic)
5733 fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
5734 call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
5738 #undef TARGET_INIT_BUILTINS
5739 #define TARGET_INIT_BUILTINS bfin_init_builtins
5741 #undef TARGET_EXPAND_BUILTIN
5742 #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
5744 #undef TARGET_ASM_GLOBALIZE_LABEL
5745 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label
5747 #undef TARGET_ASM_FILE_START
5748 #define TARGET_ASM_FILE_START output_file_start
5750 #undef TARGET_ATTRIBUTE_TABLE
5751 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
5753 #undef TARGET_COMP_TYPE_ATTRIBUTES
5754 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
5756 #undef TARGET_RTX_COSTS
5757 #define TARGET_RTX_COSTS bfin_rtx_costs
5759 #undef TARGET_ADDRESS_COST
5760 #define TARGET_ADDRESS_COST bfin_address_cost
5762 #undef TARGET_REGISTER_MOVE_COST
5763 #define TARGET_REGISTER_MOVE_COST bfin_register_move_cost
5765 #undef TARGET_MEMORY_MOVE_COST
5766 #define TARGET_MEMORY_MOVE_COST bfin_memory_move_cost
5768 #undef TARGET_ASM_INTEGER
5769 #define TARGET_ASM_INTEGER bfin_assemble_integer
5771 #undef TARGET_MACHINE_DEPENDENT_REORG
5772 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
5774 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
5775 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
5777 #undef TARGET_ASM_OUTPUT_MI_THUNK
5778 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
5779 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
5780 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
5782 #undef TARGET_SCHED_ADJUST_COST
5783 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
5785 #undef TARGET_SCHED_ISSUE_RATE
5786 #define TARGET_SCHED_ISSUE_RATE bfin_issue_rate
5788 #undef TARGET_PROMOTE_FUNCTION_MODE
5789 #define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
5791 #undef TARGET_ARG_PARTIAL_BYTES
5792 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
5794 #undef TARGET_FUNCTION_ARG
5795 #define TARGET_FUNCTION_ARG bfin_function_arg
5797 #undef TARGET_FUNCTION_ARG_ADVANCE
5798 #define TARGET_FUNCTION_ARG_ADVANCE bfin_function_arg_advance
5800 #undef TARGET_PASS_BY_REFERENCE
5801 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
5803 #undef TARGET_SETUP_INCOMING_VARARGS
5804 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
5806 #undef TARGET_STRUCT_VALUE_RTX
5807 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
5809 #undef TARGET_VECTOR_MODE_SUPPORTED_P
5810 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
5812 #undef TARGET_OPTION_OVERRIDE
5813 #define TARGET_OPTION_OVERRIDE bfin_option_override
5815 #undef TARGET_SECONDARY_RELOAD
5816 #define TARGET_SECONDARY_RELOAD bfin_secondary_reload
5818 #undef TARGET_CLASS_LIKELY_SPILLED_P
5819 #define TARGET_CLASS_LIKELY_SPILLED_P bfin_class_likely_spilled_p
5821 #undef TARGET_DELEGITIMIZE_ADDRESS
5822 #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address
5824 #undef TARGET_LEGITIMATE_CONSTANT_P
5825 #define TARGET_LEGITIMATE_CONSTANT_P bfin_legitimate_constant_p
5827 #undef TARGET_CANNOT_FORCE_CONST_MEM
5828 #define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem
5830 #undef TARGET_RETURN_IN_MEMORY
5831 #define TARGET_RETURN_IN_MEMORY bfin_return_in_memory
5833 #undef TARGET_LEGITIMATE_ADDRESS_P
5834 #define TARGET_LEGITIMATE_ADDRESS_P bfin_legitimate_address_p
5836 #undef TARGET_FRAME_POINTER_REQUIRED
5837 #define TARGET_FRAME_POINTER_REQUIRED bfin_frame_pointer_required
5839 #undef TARGET_CAN_ELIMINATE
5840 #define TARGET_CAN_ELIMINATE bfin_can_eliminate
5842 #undef TARGET_CONDITIONAL_REGISTER_USAGE
5843 #define TARGET_CONDITIONAL_REGISTER_USAGE bfin_conditional_register_usage
5845 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
5846 #define TARGET_ASM_TRAMPOLINE_TEMPLATE bfin_asm_trampoline_template
5847 #undef TARGET_TRAMPOLINE_INIT
5848 #define TARGET_TRAMPOLINE_INIT bfin_trampoline_init
5850 #undef TARGET_EXTRA_LIVE_ON_ENTRY
5851 #define TARGET_EXTRA_LIVE_ON_ENTRY bfin_extra_live_on_entry
5853 /* Passes after sched2 can break the helpful TImode annotations that
5854 haifa-sched puts on every insn. Just do scheduling in reorg. */
5855 #undef TARGET_DELAY_SCHED2
5856 #define TARGET_DELAY_SCHED2 true
5858 /* Variable tracking should be run after all optimizations which
5859 change order of insns. It also needs a valid CFG. */
5860 #undef TARGET_DELAY_VARTRACK
5861 #define TARGET_DELAY_VARTRACK true
5863 #undef TARGET_CAN_USE_DOLOOP_P
5864 #define TARGET_CAN_USE_DOLOOP_P bfin_can_use_doloop_p
5866 struct gcc_target targetm = TARGET_INITIALIZER;