]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/bfin/bfin.cc
Update copyright years.
[thirdparty/gcc.git] / gcc / config / bfin / bfin.cc
1 /* The Blackfin code generation auxiliary output file.
2 Copyright (C) 2005-2024 Free Software Foundation, Inc.
3 Contributed by Analog Devices.
4
5 This file is part of GCC.
6
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.
11
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.
16
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/>. */
20
21 #define IN_TARGET_CODE 1
22
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "backend.h"
27 #include "target.h"
28 #include "rtl.h"
29 #include "tree.h"
30 #include "stringpool.h"
31 #include "attribs.h"
32 #include "cfghooks.h"
33 #include "df.h"
34 #include "memmodel.h"
35 #include "tm_p.h"
36 #include "optabs.h"
37 #include "regs.h"
38 #include "emit-rtl.h"
39 #include "recog.h"
40 #include "cgraph.h"
41 #include "diagnostic-core.h"
42 #include "output.h"
43 #include "insn-attr.h"
44 #include "varasm.h"
45 #include "calls.h"
46 #include "explow.h"
47 #include "expr.h"
48 #include "cfgrtl.h"
49 #include "langhooks.h"
50 #include "tm-constrs.h"
51 #include "gt-bfin.h"
52 #include "sel-sched.h"
53 #include "hw-doloop.h"
54 #include "dumpfile.h"
55 #include "builtins.h"
56 #include "opts.h"
57
58 /* This file should be included last. */
59 #include "target-def.h"
60
61 /* A C structure for machine-specific, per-function data.
62 This is added to the cfun structure. */
63 struct GTY(()) machine_function
64 {
65 /* Set if we are notified by the doloop pass that a hardware loop
66 was created. */
67 int has_hardware_loops;
68
69 /* Set if we create a memcpy pattern that uses loop registers. */
70 int has_loopreg_clobber;
71 };
72
73 /* RTX for condition code flag register and RETS register */
74 extern GTY(()) rtx bfin_cc_rtx;
75 extern GTY(()) rtx bfin_rets_rtx;
76 rtx bfin_cc_rtx, bfin_rets_rtx;
77
78 int max_arg_registers = 0;
79
80 /* Arrays used when emitting register names. */
81 const char *short_reg_names[] = SHORT_REGISTER_NAMES;
82 const char *high_reg_names[] = HIGH_REGISTER_NAMES;
83 const char *dregs_pair_names[] = DREGS_PAIR_NAMES;
84 const char *byte_reg_names[] = BYTE_REGISTER_NAMES;
85
86 static int arg_regs[] = FUNCTION_ARG_REGISTERS;
87 static int ret_regs[] = FUNCTION_RETURN_REGISTERS;
88
89 int splitting_for_sched, splitting_loops;
90
91 static void
92 bfin_globalize_label (FILE *stream, const char *name)
93 {
94 fputs (".global ", stream);
95 assemble_name (stream, name);
96 fputc (';',stream);
97 fputc ('\n',stream);
98 }
99
100 static void
101 output_file_start (void)
102 {
103 FILE *file = asm_out_file;
104 int i;
105
106 fprintf (file, ".file \"%s\";\n", LOCATION_FILE (input_location));
107
108 for (i = 0; arg_regs[i] >= 0; i++)
109 ;
110 max_arg_registers = i; /* how many arg reg used */
111 }
112
113 /* Examine machine-dependent attributes of function type FUNTYPE and return its
114 type. See the definition of E_FUNKIND. */
115
116 static e_funkind
117 funkind (const_tree funtype)
118 {
119 tree attrs = TYPE_ATTRIBUTES (funtype);
120 if (lookup_attribute ("interrupt_handler", attrs))
121 return INTERRUPT_HANDLER;
122 else if (lookup_attribute ("exception_handler", attrs))
123 return EXCPT_HANDLER;
124 else if (lookup_attribute ("nmi_handler", attrs))
125 return NMI_HANDLER;
126 else
127 return SUBROUTINE;
128 }
129 \f
130 /* Legitimize PIC addresses. If the address is already position-independent,
131 we return ORIG. Newly generated position-independent addresses go into a
132 reg. This is REG if nonzero, otherwise we allocate register(s) as
133 necessary. PICREG is the register holding the pointer to the PIC offset
134 table. */
135
136 static rtx
137 legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
138 {
139 rtx addr = orig;
140 rtx new_rtx = orig;
141
142 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
143 {
144 int unspec;
145 rtx tmp;
146
147 if (TARGET_ID_SHARED_LIBRARY)
148 unspec = UNSPEC_MOVE_PIC;
149 else if (GET_CODE (addr) == SYMBOL_REF
150 && SYMBOL_REF_FUNCTION_P (addr))
151 unspec = UNSPEC_FUNCDESC_GOT17M4;
152 else
153 unspec = UNSPEC_MOVE_FDPIC;
154
155 if (reg == 0)
156 {
157 gcc_assert (can_create_pseudo_p ());
158 reg = gen_reg_rtx (Pmode);
159 }
160
161 tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), unspec);
162 new_rtx = gen_const_mem (Pmode, gen_rtx_PLUS (Pmode, picreg, tmp));
163
164 emit_move_insn (reg, new_rtx);
165 if (picreg == pic_offset_table_rtx)
166 crtl->uses_pic_offset_table = 1;
167 return reg;
168 }
169
170 else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
171 {
172 rtx base;
173
174 if (GET_CODE (addr) == CONST)
175 {
176 addr = XEXP (addr, 0);
177 gcc_assert (GET_CODE (addr) == PLUS);
178 }
179
180 if (XEXP (addr, 0) == picreg)
181 return orig;
182
183 if (reg == 0)
184 {
185 gcc_assert (can_create_pseudo_p ());
186 reg = gen_reg_rtx (Pmode);
187 }
188
189 base = legitimize_pic_address (XEXP (addr, 0), reg, picreg);
190 addr = legitimize_pic_address (XEXP (addr, 1),
191 base == reg ? NULL_RTX : reg,
192 picreg);
193
194 if (GET_CODE (addr) == CONST_INT)
195 {
196 gcc_assert (! reload_in_progress && ! reload_completed);
197 addr = force_reg (Pmode, addr);
198 }
199
200 if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
201 {
202 base = gen_rtx_PLUS (Pmode, base, XEXP (addr, 0));
203 addr = XEXP (addr, 1);
204 }
205
206 return gen_rtx_PLUS (Pmode, base, addr);
207 }
208
209 return new_rtx;
210 }
211 \f
212 /* Stack frame layout. */
213
214 /* For a given REGNO, determine whether it must be saved in the function
215 prologue. IS_INTHANDLER specifies whether we're generating a normal
216 prologue or an interrupt/exception one. */
217 static bool
218 must_save_p (bool is_inthandler, unsigned regno)
219 {
220 if (D_REGNO_P (regno))
221 {
222 bool is_eh_return_reg = false;
223 if (crtl->calls_eh_return)
224 {
225 unsigned j;
226 for (j = 0; ; j++)
227 {
228 unsigned test = EH_RETURN_DATA_REGNO (j);
229 if (test == INVALID_REGNUM)
230 break;
231 if (test == regno)
232 is_eh_return_reg = true;
233 }
234 }
235
236 return (is_eh_return_reg
237 || (df_regs_ever_live_p (regno)
238 && !fixed_regs[regno]
239 && (is_inthandler || !call_used_or_fixed_reg_p (regno))));
240 }
241 else if (P_REGNO_P (regno))
242 {
243 return ((df_regs_ever_live_p (regno)
244 && !fixed_regs[regno]
245 && (is_inthandler || !call_used_or_fixed_reg_p (regno)))
246 || (is_inthandler
247 && (ENABLE_WA_05000283 || ENABLE_WA_05000315)
248 && regno == REG_P5)
249 || (!TARGET_FDPIC
250 && regno == PIC_OFFSET_TABLE_REGNUM
251 && (crtl->uses_pic_offset_table
252 || (TARGET_ID_SHARED_LIBRARY && !crtl->is_leaf))));
253 }
254 else
255 return ((is_inthandler || !call_used_or_fixed_reg_p (regno))
256 && (df_regs_ever_live_p (regno)
257 || (!leaf_function_p () && call_used_or_fixed_reg_p (regno))));
258
259 }
260
261 /* Compute the number of DREGS to save with a push_multiple operation.
262 This could include registers that aren't modified in the function,
263 since push_multiple only takes a range of registers.
264 If IS_INTHANDLER, then everything that is live must be saved, even
265 if normally call-clobbered.
266 If CONSECUTIVE, return the number of registers we can save in one
267 instruction with a push/pop multiple instruction. */
268
269 static int
270 n_dregs_to_save (bool is_inthandler, bool consecutive)
271 {
272 int count = 0;
273 unsigned i;
274
275 for (i = REG_R7 + 1; i-- != REG_R0;)
276 {
277 if (must_save_p (is_inthandler, i))
278 count++;
279 else if (consecutive)
280 return count;
281 }
282 return count;
283 }
284
285 /* Like n_dregs_to_save, but compute number of PREGS to save. */
286
287 static int
288 n_pregs_to_save (bool is_inthandler, bool consecutive)
289 {
290 int count = 0;
291 unsigned i;
292
293 for (i = REG_P5 + 1; i-- != REG_P0;)
294 if (must_save_p (is_inthandler, i))
295 count++;
296 else if (consecutive)
297 return count;
298 return count;
299 }
300
301 /* Determine if we are going to save the frame pointer in the prologue. */
302
303 static bool
304 must_save_fp_p (void)
305 {
306 return df_regs_ever_live_p (REG_FP);
307 }
308
309 /* Determine if we are going to save the RETS register. */
310 static bool
311 must_save_rets_p (void)
312 {
313 return df_regs_ever_live_p (REG_RETS);
314 }
315
316 static bool
317 stack_frame_needed_p (void)
318 {
319 /* EH return puts a new return address into the frame using an
320 address relative to the frame pointer. */
321 if (crtl->calls_eh_return)
322 return true;
323 return frame_pointer_needed;
324 }
325
326 /* Emit code to save registers in the prologue. SAVEALL is nonzero if we
327 must save all registers; this is used for interrupt handlers.
328 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
329 this for an interrupt (or exception) handler. */
330
331 static void
332 expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler)
333 {
334 rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
335 rtx predec = gen_rtx_MEM (SImode, predec1);
336 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler, false);
337 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler, false);
338 int ndregs_consec = saveall ? 8 : n_dregs_to_save (is_inthandler, true);
339 int npregs_consec = saveall ? 6 : n_pregs_to_save (is_inthandler, true);
340 int dregno, pregno;
341 int total_consec = ndregs_consec + npregs_consec;
342 int i, d_to_save;
343
344 if (saveall || is_inthandler)
345 {
346 rtx_insn *insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
347
348 RTX_FRAME_RELATED_P (insn) = 1;
349 for (dregno = REG_LT0; dregno <= REG_LB1; dregno++)
350 if (! crtl->is_leaf
351 || cfun->machine->has_hardware_loops
352 || cfun->machine->has_loopreg_clobber
353 || (ENABLE_WA_05000257
354 && (dregno == REG_LC0 || dregno == REG_LC1)))
355 {
356 insn = emit_move_insn (predec, gen_rtx_REG (SImode, dregno));
357 RTX_FRAME_RELATED_P (insn) = 1;
358 }
359 }
360
361 if (total_consec != 0)
362 {
363 rtx_insn *insn;
364 rtx val = GEN_INT (-total_consec * 4);
365 rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_consec + 2));
366
367 XVECEXP (pat, 0, 0) = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, val),
368 UNSPEC_PUSH_MULTIPLE);
369 XVECEXP (pat, 0, total_consec + 1) = gen_rtx_SET (spreg,
370 gen_rtx_PLUS (Pmode,
371 spreg,
372 val));
373 RTX_FRAME_RELATED_P (XVECEXP (pat, 0, total_consec + 1)) = 1;
374 d_to_save = ndregs_consec;
375 dregno = REG_R7 + 1 - ndregs_consec;
376 pregno = REG_P5 + 1 - npregs_consec;
377 for (i = 0; i < total_consec; i++)
378 {
379 rtx memref = gen_rtx_MEM (word_mode,
380 gen_rtx_PLUS (Pmode, spreg,
381 GEN_INT (- i * 4 - 4)));
382 rtx subpat;
383 if (d_to_save > 0)
384 {
385 subpat = gen_rtx_SET (memref, gen_rtx_REG (word_mode, dregno++));
386 d_to_save--;
387 }
388 else
389 {
390 subpat = gen_rtx_SET (memref, gen_rtx_REG (word_mode, pregno++));
391 }
392 XVECEXP (pat, 0, i + 1) = subpat;
393 RTX_FRAME_RELATED_P (subpat) = 1;
394 }
395 insn = emit_insn (pat);
396 RTX_FRAME_RELATED_P (insn) = 1;
397 }
398
399 for (dregno = REG_R0; ndregs != ndregs_consec; dregno++)
400 {
401 if (must_save_p (is_inthandler, dregno))
402 {
403 rtx_insn *insn =
404 emit_move_insn (predec, gen_rtx_REG (word_mode, dregno));
405 RTX_FRAME_RELATED_P (insn) = 1;
406 ndregs--;
407 }
408 }
409 for (pregno = REG_P0; npregs != npregs_consec; pregno++)
410 {
411 if (must_save_p (is_inthandler, pregno))
412 {
413 rtx_insn *insn =
414 emit_move_insn (predec, gen_rtx_REG (word_mode, pregno));
415 RTX_FRAME_RELATED_P (insn) = 1;
416 npregs--;
417 }
418 }
419 for (i = REG_P7 + 1; i < REG_CC; i++)
420 if (saveall
421 || (is_inthandler
422 && (df_regs_ever_live_p (i)
423 || (!leaf_function_p () && call_used_or_fixed_reg_p (i)))))
424 {
425 rtx_insn *insn;
426 if (i == REG_A0 || i == REG_A1)
427 insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1),
428 gen_rtx_REG (PDImode, i));
429 else
430 insn = emit_move_insn (predec, gen_rtx_REG (SImode, i));
431 RTX_FRAME_RELATED_P (insn) = 1;
432 }
433 }
434
435 /* Emit code to restore registers in the epilogue. SAVEALL is nonzero if we
436 must save all registers; this is used for interrupt handlers.
437 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
438 this for an interrupt (or exception) handler. */
439
440 static void
441 expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler)
442 {
443 rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
444 rtx postinc = gen_rtx_MEM (SImode, postinc1);
445
446 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler, false);
447 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler, false);
448 int ndregs_consec = saveall ? 8 : n_dregs_to_save (is_inthandler, true);
449 int npregs_consec = saveall ? 6 : n_pregs_to_save (is_inthandler, true);
450 int total_consec = ndregs_consec + npregs_consec;
451 int i, regno;
452 rtx_insn *insn;
453
454 /* A slightly crude technique to stop flow from trying to delete "dead"
455 insns. */
456 MEM_VOLATILE_P (postinc) = 1;
457
458 for (i = REG_CC - 1; i > REG_P7; i--)
459 if (saveall
460 || (is_inthandler
461 && (df_regs_ever_live_p (i)
462 || (!leaf_function_p () && call_used_or_fixed_reg_p (i)))))
463 {
464 if (i == REG_A0 || i == REG_A1)
465 {
466 rtx mem = gen_rtx_MEM (PDImode, postinc1);
467 MEM_VOLATILE_P (mem) = 1;
468 emit_move_insn (gen_rtx_REG (PDImode, i), mem);
469 }
470 else
471 emit_move_insn (gen_rtx_REG (SImode, i), postinc);
472 }
473
474 regno = REG_P5 - npregs_consec;
475 for (; npregs != npregs_consec; regno--)
476 {
477 if (must_save_p (is_inthandler, regno))
478 {
479 emit_move_insn (gen_rtx_REG (word_mode, regno), postinc);
480 npregs--;
481 }
482 }
483 regno = REG_R7 - ndregs_consec;
484 for (; ndregs != ndregs_consec; regno--)
485 {
486 if (must_save_p (is_inthandler, regno))
487 {
488 emit_move_insn (gen_rtx_REG (word_mode, regno), postinc);
489 ndregs--;
490 }
491 }
492
493 if (total_consec != 0)
494 {
495 rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_consec + 1));
496 XVECEXP (pat, 0, 0)
497 = gen_rtx_SET (spreg, gen_rtx_PLUS (Pmode, spreg,
498 GEN_INT (total_consec * 4)));
499
500 if (npregs_consec > 0)
501 regno = REG_P5 + 1;
502 else
503 regno = REG_R7 + 1;
504
505 for (i = 0; i < total_consec; i++)
506 {
507 rtx addr = (i > 0
508 ? gen_rtx_PLUS (Pmode, spreg, GEN_INT (i * 4))
509 : spreg);
510 rtx memref = gen_rtx_MEM (word_mode, addr);
511
512 regno--;
513 XVECEXP (pat, 0, i + 1)
514 = gen_rtx_SET (gen_rtx_REG (word_mode, regno), memref);
515
516 if (npregs_consec > 0)
517 {
518 if (--npregs_consec == 0)
519 regno = REG_R7 + 1;
520 }
521 }
522
523 insn = emit_insn (pat);
524 RTX_FRAME_RELATED_P (insn) = 1;
525 }
526 if (saveall || is_inthandler)
527 {
528 for (regno = REG_LB1; regno >= REG_LT0; regno--)
529 if (! crtl->is_leaf
530 || cfun->machine->has_hardware_loops
531 || cfun->machine->has_loopreg_clobber
532 || (ENABLE_WA_05000257 && (regno == REG_LC0 || regno == REG_LC1)))
533 emit_move_insn (gen_rtx_REG (SImode, regno), postinc);
534
535 emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
536 }
537 }
538
539 /* Perform any needed actions needed for a function that is receiving a
540 variable number of arguments.
541
542 CUM is as above.
543
544 ARG is the last named argument.
545
546 PRETEND_SIZE is a variable that should be set to the amount of stack
547 that must be pushed by the prolog to pretend that our caller pushed
548 it.
549
550 Normally, this macro will push all remaining incoming registers on the
551 stack and set PRETEND_SIZE to the length of the registers pushed.
552
553 Blackfin specific :
554 - VDSP C compiler manual (our ABI) says that a variable args function
555 should save the R0, R1 and R2 registers in the stack.
556 - The caller will always leave space on the stack for the
557 arguments that are passed in registers, so we dont have
558 to leave any extra space.
559 - now, the vastart pointer can access all arguments from the stack. */
560
561 static void
562 setup_incoming_varargs (cumulative_args_t cum,
563 const function_arg_info &, int *pretend_size,
564 int no_rtl)
565 {
566 rtx mem;
567 int i;
568
569 if (no_rtl)
570 return;
571
572 /* The move for named arguments will be generated automatically by the
573 compiler. We need to generate the move rtx for the unnamed arguments
574 if they are in the first 3 words. We assume at least 1 named argument
575 exists, so we never generate [ARGP] = R0 here. */
576
577 for (i = get_cumulative_args (cum)->words + 1; i < max_arg_registers; i++)
578 {
579 mem = gen_rtx_MEM (Pmode,
580 plus_constant (Pmode, arg_pointer_rtx,
581 (i * UNITS_PER_WORD)));
582 emit_move_insn (mem, gen_rtx_REG (Pmode, i));
583 }
584
585 *pretend_size = 0;
586 }
587
588 /* Value should be nonzero if functions must have frame pointers.
589 Zero means the frame pointer need not be set up (and parms may
590 be accessed via the stack pointer) in functions that seem suitable. */
591
592 static bool
593 bfin_frame_pointer_required (void)
594 {
595 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
596
597 if (fkind != SUBROUTINE)
598 return true;
599
600 /* We turn on -fomit-frame-pointer if -momit-leaf-frame-pointer is used,
601 so we have to override it for non-leaf functions. */
602 if (TARGET_OMIT_LEAF_FRAME_POINTER && ! crtl->is_leaf)
603 return true;
604
605 return false;
606 }
607
608 /* Return the number of registers pushed during the prologue. */
609
610 static int
611 n_regs_saved_by_prologue (void)
612 {
613 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
614 bool is_inthandler = fkind != SUBROUTINE;
615 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
616 bool all = (lookup_attribute ("saveall", attrs) != NULL_TREE
617 || (is_inthandler && !crtl->is_leaf));
618 int ndregs = all ? 8 : n_dregs_to_save (is_inthandler, false);
619 int npregs = all ? 6 : n_pregs_to_save (is_inthandler, false);
620 int n = ndregs + npregs;
621 int i;
622
623 if (all || stack_frame_needed_p ())
624 n += 2;
625 else
626 {
627 if (must_save_fp_p ())
628 n++;
629 if (must_save_rets_p ())
630 n++;
631 }
632
633 if (fkind != SUBROUTINE || all)
634 {
635 /* Increment once for ASTAT. */
636 n++;
637 if (! crtl->is_leaf
638 || cfun->machine->has_hardware_loops
639 || cfun->machine->has_loopreg_clobber)
640 {
641 n += 6;
642 }
643 }
644
645 if (fkind != SUBROUTINE)
646 {
647 /* RETE/X/N. */
648 if (lookup_attribute ("nesting", attrs))
649 n++;
650 }
651
652 for (i = REG_P7 + 1; i < REG_CC; i++)
653 if (all
654 || (fkind != SUBROUTINE
655 && (df_regs_ever_live_p (i)
656 || (!leaf_function_p () && call_used_or_fixed_reg_p (i)))))
657 n += i == REG_A0 || i == REG_A1 ? 2 : 1;
658
659 return n;
660 }
661
662 /* Given FROM and TO register numbers, say whether this elimination is
663 allowed. Frame pointer elimination is automatically handled.
664
665 All other eliminations are valid. */
666
667 static bool
668 bfin_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
669 {
670 return (to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true);
671 }
672
673 /* Return the offset between two registers, one to be eliminated, and the other
674 its replacement, at the start of a routine. */
675
676 HOST_WIDE_INT
677 bfin_initial_elimination_offset (int from, int to)
678 {
679 HOST_WIDE_INT offset = 0;
680
681 if (from == ARG_POINTER_REGNUM)
682 offset = n_regs_saved_by_prologue () * 4;
683
684 if (to == STACK_POINTER_REGNUM)
685 {
686 if (crtl->outgoing_args_size >= FIXED_STACK_AREA)
687 offset += crtl->outgoing_args_size;
688 else if (crtl->outgoing_args_size)
689 offset += FIXED_STACK_AREA;
690
691 offset += get_frame_size ();
692 }
693
694 return offset;
695 }
696
697 /* Emit code to load a constant CONSTANT into register REG; setting
698 RTX_FRAME_RELATED_P on all insns we generate if RELATED is true.
699 Make sure that the insns we generate need not be split. */
700
701 static void
702 frame_related_constant_load (rtx reg, HOST_WIDE_INT constant, bool related)
703 {
704 rtx_insn *insn;
705 rtx cst = GEN_INT (constant);
706
707 if (constant >= -32768 && constant < 65536)
708 insn = emit_move_insn (reg, cst);
709 else
710 {
711 /* We don't call split_load_immediate here, since dwarf2out.cc can get
712 confused about some of the more clever sequences it can generate. */
713 insn = emit_insn (gen_movsi_high (reg, cst));
714 if (related)
715 RTX_FRAME_RELATED_P (insn) = 1;
716 insn = emit_insn (gen_movsi_low (reg, reg, cst));
717 }
718 if (related)
719 RTX_FRAME_RELATED_P (insn) = 1;
720 }
721
722 /* Generate efficient code to add a value to a P register.
723 Set RTX_FRAME_RELATED_P on the generated insns if FRAME is nonzero.
724 EPILOGUE_P is zero if this function is called for prologue,
725 otherwise it's nonzero. And it's less than zero if this is for
726 sibcall epilogue. */
727
728 static void
729 add_to_reg (rtx reg, HOST_WIDE_INT value, int frame, int epilogue_p)
730 {
731 if (value == 0)
732 return;
733
734 /* Choose whether to use a sequence using a temporary register, or
735 a sequence with multiple adds. We can add a signed 7-bit value
736 in one instruction. */
737 if (value > 120 || value < -120)
738 {
739 rtx tmpreg;
740 rtx tmpreg2;
741 rtx_insn *insn;
742
743 tmpreg2 = NULL_RTX;
744
745 /* For prologue or normal epilogue, P1 can be safely used
746 as the temporary register. For sibcall epilogue, we try to find
747 a call used P register, which will be restored in epilogue.
748 If we cannot find such a P register, we have to use one I register
749 to help us. */
750
751 if (epilogue_p >= 0)
752 tmpreg = gen_rtx_REG (SImode, REG_P1);
753 else
754 {
755 int i;
756 for (i = REG_P0; i <= REG_P5; i++)
757 if ((df_regs_ever_live_p (i) && ! call_used_or_fixed_reg_p (i))
758 || (!TARGET_FDPIC
759 && i == PIC_OFFSET_TABLE_REGNUM
760 && (crtl->uses_pic_offset_table
761 || (TARGET_ID_SHARED_LIBRARY
762 && ! crtl->is_leaf))))
763 break;
764 if (i <= REG_P5)
765 tmpreg = gen_rtx_REG (SImode, i);
766 else
767 {
768 tmpreg = gen_rtx_REG (SImode, REG_P1);
769 tmpreg2 = gen_rtx_REG (SImode, REG_I0);
770 emit_move_insn (tmpreg2, tmpreg);
771 }
772 }
773
774 if (frame)
775 frame_related_constant_load (tmpreg, value, TRUE);
776 else
777 insn = emit_move_insn (tmpreg, GEN_INT (value));
778
779 insn = emit_insn (gen_addsi3 (reg, reg, tmpreg));
780 if (frame)
781 RTX_FRAME_RELATED_P (insn) = 1;
782
783 if (tmpreg2 != NULL_RTX)
784 emit_move_insn (tmpreg, tmpreg2);
785 }
786 else
787 do
788 {
789 int size = value;
790 rtx_insn *insn;
791
792 if (size > 60)
793 size = 60;
794 else if (size < -60)
795 /* We could use -62, but that would leave the stack unaligned, so
796 it's no good. */
797 size = -60;
798
799 insn = emit_insn (gen_addsi3 (reg, reg, GEN_INT (size)));
800 if (frame)
801 RTX_FRAME_RELATED_P (insn) = 1;
802 value -= size;
803 }
804 while (value != 0);
805 }
806
807 /* Generate a LINK insn for a frame sized FRAME_SIZE. If this constant
808 is too large, generate a sequence of insns that has the same effect.
809 SPREG contains (reg:SI REG_SP). */
810
811 static void
812 emit_link_insn (rtx spreg, HOST_WIDE_INT frame_size)
813 {
814 HOST_WIDE_INT link_size = frame_size;
815 rtx_insn *insn;
816 int i;
817
818 if (link_size > 262140)
819 link_size = 262140;
820
821 /* Use a LINK insn with as big a constant as possible, then subtract
822 any remaining size from the SP. */
823 insn = emit_insn (gen_link (GEN_INT (-8 - link_size)));
824 RTX_FRAME_RELATED_P (insn) = 1;
825
826 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
827 {
828 rtx set = XVECEXP (PATTERN (insn), 0, i);
829 gcc_assert (GET_CODE (set) == SET);
830 RTX_FRAME_RELATED_P (set) = 1;
831 }
832
833 frame_size -= link_size;
834
835 if (frame_size > 0)
836 {
837 /* Must use a call-clobbered PREG that isn't the static chain. */
838 rtx tmpreg = gen_rtx_REG (Pmode, REG_P1);
839
840 frame_related_constant_load (tmpreg, -frame_size, TRUE);
841 insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg));
842 RTX_FRAME_RELATED_P (insn) = 1;
843 }
844 }
845
846 /* Return the number of bytes we must reserve for outgoing arguments
847 in the current function's stack frame. */
848
849 static HOST_WIDE_INT
850 arg_area_size (void)
851 {
852 if (crtl->outgoing_args_size)
853 {
854 if (crtl->outgoing_args_size >= FIXED_STACK_AREA)
855 return crtl->outgoing_args_size;
856 else
857 return FIXED_STACK_AREA;
858 }
859 return 0;
860 }
861
862 /* Save RETS and FP, and allocate a stack frame. ALL is true if the
863 function must save all its registers (true only for certain interrupt
864 handlers). */
865
866 static void
867 do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all)
868 {
869 frame_size += arg_area_size ();
870
871 if (all
872 || stack_frame_needed_p ()
873 || (must_save_rets_p () && must_save_fp_p ()))
874 emit_link_insn (spreg, frame_size);
875 else
876 {
877 if (must_save_rets_p ())
878 {
879 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
880 gen_rtx_PRE_DEC (Pmode, spreg)),
881 bfin_rets_rtx);
882 rtx_insn *insn = emit_insn (pat);
883 RTX_FRAME_RELATED_P (insn) = 1;
884 }
885 if (must_save_fp_p ())
886 {
887 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
888 gen_rtx_PRE_DEC (Pmode, spreg)),
889 gen_rtx_REG (Pmode, REG_FP));
890 rtx_insn *insn = emit_insn (pat);
891 RTX_FRAME_RELATED_P (insn) = 1;
892 }
893 add_to_reg (spreg, -frame_size, 1, 0);
894 }
895 }
896
897 /* Like do_link, but used for epilogues to deallocate the stack frame.
898 EPILOGUE_P is zero if this function is called for prologue,
899 otherwise it's nonzero. And it's less than zero if this is for
900 sibcall epilogue. */
901
902 static void
903 do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all, int epilogue_p)
904 {
905 frame_size += arg_area_size ();
906
907 if (stack_frame_needed_p ())
908 emit_insn (gen_unlink ());
909 else
910 {
911 rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg));
912
913 add_to_reg (spreg, frame_size, 0, epilogue_p);
914 if (all || must_save_fp_p ())
915 {
916 rtx fpreg = gen_rtx_REG (Pmode, REG_FP);
917 emit_move_insn (fpreg, postinc);
918 emit_use (fpreg);
919 }
920 if (all || must_save_rets_p ())
921 {
922 emit_move_insn (bfin_rets_rtx, postinc);
923 emit_use (bfin_rets_rtx);
924 }
925 }
926 }
927
928 /* Generate a prologue suitable for a function of kind FKIND. This is
929 called for interrupt and exception handler prologues.
930 SPREG contains (reg:SI REG_SP). */
931
932 static void
933 expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind, bool all)
934 {
935 HOST_WIDE_INT frame_size = get_frame_size ();
936 rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
937 rtx predec = gen_rtx_MEM (SImode, predec1);
938 rtx_insn *insn;
939 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
940 tree kspisusp = lookup_attribute ("kspisusp", attrs);
941
942 if (kspisusp)
943 {
944 insn = emit_move_insn (spreg, gen_rtx_REG (Pmode, REG_USP));
945 RTX_FRAME_RELATED_P (insn) = 1;
946 }
947
948 /* We need space on the stack in case we need to save the argument
949 registers. */
950 if (fkind == EXCPT_HANDLER)
951 {
952 insn = emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (-12)));
953 RTX_FRAME_RELATED_P (insn) = 1;
954 }
955
956 /* If we're calling other functions, they won't save their call-clobbered
957 registers, so we must save everything here. */
958 if (!crtl->is_leaf)
959 all = true;
960 expand_prologue_reg_save (spreg, all, true);
961
962 if (ENABLE_WA_05000283 || ENABLE_WA_05000315)
963 {
964 rtx chipid = GEN_INT (trunc_int_for_mode (0xFFC00014, SImode));
965 rtx p5reg = gen_rtx_REG (Pmode, REG_P5);
966 emit_insn (gen_movbi (bfin_cc_rtx, const1_rtx));
967 emit_insn (gen_movsi_high (p5reg, chipid));
968 emit_insn (gen_movsi_low (p5reg, p5reg, chipid));
969 emit_insn (gen_dummy_load (p5reg, bfin_cc_rtx));
970 }
971
972 if (lookup_attribute ("nesting", attrs))
973 {
974 rtx srcreg = gen_rtx_REG (Pmode, ret_regs[fkind]);
975 insn = emit_move_insn (predec, srcreg);
976 RTX_FRAME_RELATED_P (insn) = 1;
977 }
978
979 do_link (spreg, frame_size, all);
980
981 if (fkind == EXCPT_HANDLER)
982 {
983 rtx r0reg = gen_rtx_REG (SImode, REG_R0);
984 rtx r1reg = gen_rtx_REG (SImode, REG_R1);
985 rtx r2reg = gen_rtx_REG (SImode, REG_R2);
986
987 emit_move_insn (r0reg, gen_rtx_REG (SImode, REG_SEQSTAT));
988 emit_insn (gen_ashrsi3 (r0reg, r0reg, GEN_INT (26)));
989 emit_insn (gen_ashlsi3 (r0reg, r0reg, GEN_INT (26)));
990 emit_move_insn (r1reg, spreg);
991 emit_move_insn (r2reg, gen_rtx_REG (Pmode, REG_FP));
992 emit_insn (gen_addsi3 (r2reg, r2reg, GEN_INT (8)));
993 }
994 }
995
996 /* Generate an epilogue suitable for a function of kind FKIND. This is
997 called for interrupt and exception handler epilogues.
998 SPREG contains (reg:SI REG_SP). */
999
1000 static void
1001 expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind, bool all)
1002 {
1003 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1004 rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
1005 rtx postinc = gen_rtx_MEM (SImode, postinc1);
1006
1007 /* A slightly crude technique to stop flow from trying to delete "dead"
1008 insns. */
1009 MEM_VOLATILE_P (postinc) = 1;
1010
1011 do_unlink (spreg, get_frame_size (), all, 1);
1012
1013 if (lookup_attribute ("nesting", attrs))
1014 {
1015 rtx srcreg = gen_rtx_REG (Pmode, ret_regs[fkind]);
1016 emit_move_insn (srcreg, postinc);
1017 }
1018
1019 /* If we're calling other functions, they won't save their call-clobbered
1020 registers, so we must save (and restore) everything here. */
1021 if (!crtl->is_leaf)
1022 all = true;
1023
1024 expand_epilogue_reg_restore (spreg, all, true);
1025
1026 /* Deallocate any space we left on the stack in case we needed to save the
1027 argument registers. */
1028 if (fkind == EXCPT_HANDLER)
1029 emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (12)));
1030
1031 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, ret_regs[fkind])));
1032 }
1033
1034 /* Used while emitting the prologue to generate code to load the correct value
1035 into the PIC register, which is passed in DEST. */
1036
1037 static rtx
1038 bfin_load_pic_reg (rtx dest)
1039 {
1040 rtx addr;
1041
1042 cgraph_node *local_info_node
1043 = cgraph_node::local_info_node (current_function_decl);
1044
1045 /* Functions local to the translation unit don't need to reload the
1046 pic reg, since the caller always passes a usable one. */
1047 if (local_info_node && local_info_node->local)
1048 return pic_offset_table_rtx;
1049
1050 if (OPTION_SET_P (bfin_library_id))
1051 addr = plus_constant (Pmode, pic_offset_table_rtx,
1052 -4 - bfin_library_id * 4);
1053 else
1054 addr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
1055 gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
1056 UNSPEC_LIBRARY_OFFSET));
1057 emit_insn (gen_movsi (dest, gen_rtx_MEM (Pmode, addr)));
1058 return dest;
1059 }
1060
1061 /* Generate RTL for the prologue of the current function. */
1062
1063 void
1064 bfin_expand_prologue (void)
1065 {
1066 HOST_WIDE_INT frame_size = get_frame_size ();
1067 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
1068 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1069 rtx pic_reg_loaded = NULL_RTX;
1070 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1071 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
1072
1073 if (flag_stack_usage_info)
1074 current_function_static_stack_size = frame_size;
1075
1076 if (fkind != SUBROUTINE)
1077 {
1078 expand_interrupt_handler_prologue (spreg, fkind, all);
1079 return;
1080 }
1081
1082 if (crtl->limit_stack
1083 || (TARGET_STACK_CHECK_L1
1084 && !DECL_NO_LIMIT_STACK (current_function_decl)))
1085 {
1086 HOST_WIDE_INT offset
1087 = bfin_initial_elimination_offset (ARG_POINTER_REGNUM,
1088 STACK_POINTER_REGNUM);
1089 rtx lim = crtl->limit_stack ? stack_limit_rtx : NULL_RTX;
1090 rtx tmp = gen_rtx_REG (Pmode, REG_R3);
1091 rtx p2reg = gen_rtx_REG (Pmode, REG_P2);
1092
1093 emit_move_insn (tmp, p2reg);
1094 if (!lim)
1095 {
1096 emit_move_insn (p2reg, gen_int_mode (0xFFB00000, SImode));
1097 emit_move_insn (p2reg, gen_rtx_MEM (Pmode, p2reg));
1098 lim = p2reg;
1099 }
1100 if (GET_CODE (lim) == SYMBOL_REF)
1101 {
1102 if (TARGET_ID_SHARED_LIBRARY)
1103 {
1104 rtx p1reg = gen_rtx_REG (Pmode, REG_P1);
1105 rtx val;
1106 pic_reg_loaded = bfin_load_pic_reg (p2reg);
1107 val = legitimize_pic_address (stack_limit_rtx, p1reg,
1108 pic_reg_loaded);
1109 emit_move_insn (p1reg, val);
1110 frame_related_constant_load (p2reg, offset, FALSE);
1111 emit_insn (gen_addsi3 (p2reg, p2reg, p1reg));
1112 lim = p2reg;
1113 }
1114 else
1115 {
1116 rtx limit = plus_constant (Pmode, lim, offset);
1117 emit_move_insn (p2reg, limit);
1118 lim = p2reg;
1119 }
1120 }
1121 else
1122 {
1123 if (lim != p2reg)
1124 emit_move_insn (p2reg, lim);
1125 add_to_reg (p2reg, offset, 0, 0);
1126 lim = p2reg;
1127 }
1128 emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim));
1129 emit_insn (gen_trapifcc ());
1130 emit_move_insn (p2reg, tmp);
1131 }
1132 expand_prologue_reg_save (spreg, all, false);
1133
1134 do_link (spreg, frame_size, all);
1135
1136 if (TARGET_ID_SHARED_LIBRARY
1137 && !TARGET_SEP_DATA
1138 && (crtl->uses_pic_offset_table
1139 || !crtl->is_leaf))
1140 bfin_load_pic_reg (pic_offset_table_rtx);
1141 }
1142
1143 /* Generate RTL for the epilogue of the current function. NEED_RETURN is zero
1144 if this is for a sibcall. EH_RETURN is nonzero if we're expanding an
1145 eh_return pattern. SIBCALL_P is true if this is a sibcall epilogue,
1146 false otherwise. */
1147
1148 void
1149 bfin_expand_epilogue (int need_return, int eh_return, bool sibcall_p)
1150 {
1151 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
1152 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1153 int e = sibcall_p ? -1 : 1;
1154 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1155 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
1156
1157 if (fkind != SUBROUTINE)
1158 {
1159 expand_interrupt_handler_epilogue (spreg, fkind, all);
1160 return;
1161 }
1162
1163 do_unlink (spreg, get_frame_size (), all, e);
1164
1165 expand_epilogue_reg_restore (spreg, all, false);
1166
1167 /* Omit the return insn if this is for a sibcall. */
1168 if (! need_return)
1169 return;
1170
1171 if (eh_return)
1172 emit_insn (gen_addsi3 (spreg, spreg, gen_rtx_REG (Pmode, REG_P2)));
1173
1174 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, REG_RETS)));
1175 }
1176 \f
1177 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
1178
1179 int
1180 bfin_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
1181 unsigned int new_reg)
1182 {
1183 /* Interrupt functions can only use registers that have already been
1184 saved by the prologue, even if they would normally be
1185 call-clobbered. */
1186
1187 if (funkind (TREE_TYPE (current_function_decl)) != SUBROUTINE
1188 && !df_regs_ever_live_p (new_reg))
1189 return 0;
1190
1191 return 1;
1192 }
1193
1194 /* Implement TARGET_EXTRA_LIVE_ON_ENTRY. */
1195 static void
1196 bfin_extra_live_on_entry (bitmap regs)
1197 {
1198 if (TARGET_FDPIC)
1199 bitmap_set_bit (regs, FDPIC_REGNO);
1200 }
1201
1202 /* Return the value of the return address for the frame COUNT steps up
1203 from the current frame, after the prologue.
1204 We punt for everything but the current frame by returning const0_rtx. */
1205
1206 rtx
1207 bfin_return_addr_rtx (int count)
1208 {
1209 if (count != 0)
1210 return const0_rtx;
1211
1212 return get_hard_reg_initial_val (Pmode, REG_RETS);
1213 }
1214
1215 static rtx
1216 bfin_delegitimize_address (rtx orig_x)
1217 {
1218 rtx x = orig_x;
1219
1220 if (GET_CODE (x) != MEM)
1221 return orig_x;
1222
1223 x = XEXP (x, 0);
1224 if (GET_CODE (x) == PLUS
1225 && GET_CODE (XEXP (x, 1)) == UNSPEC
1226 && XINT (XEXP (x, 1), 1) == UNSPEC_MOVE_PIC
1227 && GET_CODE (XEXP (x, 0)) == REG
1228 && REGNO (XEXP (x, 0)) == PIC_OFFSET_TABLE_REGNUM)
1229 return XVECEXP (XEXP (x, 1), 0, 0);
1230
1231 return orig_x;
1232 }
1233
1234 /* This predicate is used to compute the length of a load/store insn.
1235 OP is a MEM rtx, we return nonzero if its addressing mode requires a
1236 32-bit instruction. */
1237
1238 int
1239 effective_address_32bit_p (rtx op, machine_mode mode)
1240 {
1241 HOST_WIDE_INT offset;
1242
1243 mode = GET_MODE (op);
1244 op = XEXP (op, 0);
1245
1246 if (GET_CODE (op) != PLUS)
1247 {
1248 gcc_assert (REG_P (op) || GET_CODE (op) == POST_INC
1249 || GET_CODE (op) == PRE_DEC || GET_CODE (op) == POST_DEC);
1250 return 0;
1251 }
1252
1253 if (GET_CODE (XEXP (op, 1)) == UNSPEC)
1254 return 1;
1255
1256 offset = INTVAL (XEXP (op, 1));
1257
1258 /* All byte loads use a 16-bit offset. */
1259 if (GET_MODE_SIZE (mode) == 1)
1260 return 1;
1261
1262 if (GET_MODE_SIZE (mode) == 4)
1263 {
1264 /* Frame pointer relative loads can use a negative offset, all others
1265 are restricted to a small positive one. */
1266 if (XEXP (op, 0) == frame_pointer_rtx)
1267 return offset < -128 || offset > 60;
1268 return offset < 0 || offset > 60;
1269 }
1270
1271 /* Must be HImode now. */
1272 return offset < 0 || offset > 30;
1273 }
1274
1275 /* Returns true if X is a memory reference using an I register. */
1276 bool
1277 bfin_dsp_memref_p (rtx x)
1278 {
1279 if (! MEM_P (x))
1280 return false;
1281 x = XEXP (x, 0);
1282 if (GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_INC
1283 || GET_CODE (x) == POST_DEC || GET_CODE (x) == PRE_DEC)
1284 x = XEXP (x, 0);
1285 return IREG_P (x);
1286 }
1287
1288 /* Return cost of the memory address ADDR.
1289 All addressing modes are equally cheap on the Blackfin. */
1290
1291 static int
1292 bfin_address_cost (rtx addr ATTRIBUTE_UNUSED,
1293 machine_mode mode ATTRIBUTE_UNUSED,
1294 addr_space_t as ATTRIBUTE_UNUSED,
1295 bool speed ATTRIBUTE_UNUSED)
1296 {
1297 return 1;
1298 }
1299
1300 /* Subroutine of print_operand; used to print a memory reference X to FILE. */
1301
1302 void
1303 print_address_operand (FILE *file, rtx x)
1304 {
1305 switch (GET_CODE (x))
1306 {
1307 case PLUS:
1308 output_address (VOIDmode, XEXP (x, 0));
1309 fprintf (file, "+");
1310 output_address (VOIDmode, XEXP (x, 1));
1311 break;
1312
1313 case PRE_DEC:
1314 fprintf (file, "--");
1315 output_address (VOIDmode, XEXP (x, 0));
1316 break;
1317 case POST_INC:
1318 output_address (VOIDmode, XEXP (x, 0));
1319 fprintf (file, "++");
1320 break;
1321 case POST_DEC:
1322 output_address (VOIDmode, XEXP (x, 0));
1323 fprintf (file, "--");
1324 break;
1325
1326 default:
1327 gcc_assert (GET_CODE (x) != MEM);
1328 print_operand (file, x, 0);
1329 break;
1330 }
1331 }
1332
1333 /* Adding intp DImode support by Tony
1334 * -- Q: (low word)
1335 * -- R: (high word)
1336 */
1337
1338 void
1339 print_operand (FILE *file, rtx x, char code)
1340 {
1341 machine_mode mode;
1342
1343 if (code == '!')
1344 {
1345 if (GET_MODE (current_output_insn) == SImode)
1346 fprintf (file, " ||");
1347 else
1348 fprintf (file, ";");
1349 return;
1350 }
1351
1352 mode = GET_MODE (x);
1353
1354 switch (code)
1355 {
1356 case 'j':
1357 switch (GET_CODE (x))
1358 {
1359 case EQ:
1360 fprintf (file, "e");
1361 break;
1362 case NE:
1363 fprintf (file, "ne");
1364 break;
1365 case GT:
1366 fprintf (file, "g");
1367 break;
1368 case LT:
1369 fprintf (file, "l");
1370 break;
1371 case GE:
1372 fprintf (file, "ge");
1373 break;
1374 case LE:
1375 fprintf (file, "le");
1376 break;
1377 case GTU:
1378 fprintf (file, "g");
1379 break;
1380 case LTU:
1381 fprintf (file, "l");
1382 break;
1383 case GEU:
1384 fprintf (file, "ge");
1385 break;
1386 case LEU:
1387 fprintf (file, "le");
1388 break;
1389 default:
1390 output_operand_lossage ("invalid %%j value");
1391 }
1392 break;
1393
1394 case 'J': /* reverse logic */
1395 switch (GET_CODE(x))
1396 {
1397 case EQ:
1398 fprintf (file, "ne");
1399 break;
1400 case NE:
1401 fprintf (file, "e");
1402 break;
1403 case GT:
1404 fprintf (file, "le");
1405 break;
1406 case LT:
1407 fprintf (file, "ge");
1408 break;
1409 case GE:
1410 fprintf (file, "l");
1411 break;
1412 case LE:
1413 fprintf (file, "g");
1414 break;
1415 case GTU:
1416 fprintf (file, "le");
1417 break;
1418 case LTU:
1419 fprintf (file, "ge");
1420 break;
1421 case GEU:
1422 fprintf (file, "l");
1423 break;
1424 case LEU:
1425 fprintf (file, "g");
1426 break;
1427 default:
1428 output_operand_lossage ("invalid %%J value");
1429 }
1430 break;
1431
1432 default:
1433 switch (GET_CODE (x))
1434 {
1435 case REG:
1436 if (code == 'h')
1437 {
1438 if (REGNO (x) < 32)
1439 fprintf (file, "%s", short_reg_names[REGNO (x)]);
1440 else
1441 output_operand_lossage ("invalid operand for code '%c'", code);
1442 }
1443 else if (code == 'd')
1444 {
1445 if (REGNO (x) < 32)
1446 fprintf (file, "%s", high_reg_names[REGNO (x)]);
1447 else
1448 output_operand_lossage ("invalid operand for code '%c'", code);
1449 }
1450 else if (code == 'w')
1451 {
1452 if (REGNO (x) == REG_A0 || REGNO (x) == REG_A1)
1453 fprintf (file, "%s.w", reg_names[REGNO (x)]);
1454 else
1455 output_operand_lossage ("invalid operand for code '%c'", code);
1456 }
1457 else if (code == 'x')
1458 {
1459 if (REGNO (x) == REG_A0 || REGNO (x) == REG_A1)
1460 fprintf (file, "%s.x", reg_names[REGNO (x)]);
1461 else
1462 output_operand_lossage ("invalid operand for code '%c'", code);
1463 }
1464 else if (code == 'v')
1465 {
1466 if (REGNO (x) == REG_A0)
1467 fprintf (file, "AV0");
1468 else if (REGNO (x) == REG_A1)
1469 fprintf (file, "AV1");
1470 else
1471 output_operand_lossage ("invalid operand for code '%c'", code);
1472 }
1473 else if (code == 'D')
1474 {
1475 if (D_REGNO_P (REGNO (x)))
1476 fprintf (file, "%s", dregs_pair_names[REGNO (x)]);
1477 else
1478 output_operand_lossage ("invalid operand for code '%c'", code);
1479 }
1480 else if (code == 'H')
1481 {
1482 if ((mode == DImode || mode == DFmode) && REG_P (x))
1483 fprintf (file, "%s", reg_names[REGNO (x) + 1]);
1484 else
1485 output_operand_lossage ("invalid operand for code '%c'", code);
1486 }
1487 else if (code == 'T')
1488 {
1489 if (D_REGNO_P (REGNO (x)))
1490 fprintf (file, "%s", byte_reg_names[REGNO (x)]);
1491 else
1492 output_operand_lossage ("invalid operand for code '%c'", code);
1493 }
1494 else
1495 fprintf (file, "%s", reg_names[REGNO (x)]);
1496 break;
1497
1498 case MEM:
1499 fputc ('[', file);
1500 x = XEXP (x,0);
1501 print_address_operand (file, x);
1502 fputc (']', file);
1503 break;
1504
1505 case CONST_INT:
1506 if (code == 'M')
1507 {
1508 switch (INTVAL (x))
1509 {
1510 case MACFLAG_NONE:
1511 break;
1512 case MACFLAG_FU:
1513 fputs ("(FU)", file);
1514 break;
1515 case MACFLAG_T:
1516 fputs ("(T)", file);
1517 break;
1518 case MACFLAG_TFU:
1519 fputs ("(TFU)", file);
1520 break;
1521 case MACFLAG_W32:
1522 fputs ("(W32)", file);
1523 break;
1524 case MACFLAG_IS:
1525 fputs ("(IS)", file);
1526 break;
1527 case MACFLAG_IU:
1528 fputs ("(IU)", file);
1529 break;
1530 case MACFLAG_IH:
1531 fputs ("(IH)", file);
1532 break;
1533 case MACFLAG_M:
1534 fputs ("(M)", file);
1535 break;
1536 case MACFLAG_IS_M:
1537 fputs ("(IS,M)", file);
1538 break;
1539 case MACFLAG_ISS2:
1540 fputs ("(ISS2)", file);
1541 break;
1542 case MACFLAG_S2RND:
1543 fputs ("(S2RND)", file);
1544 break;
1545 default:
1546 gcc_unreachable ();
1547 }
1548 break;
1549 }
1550 else if (code == 'b')
1551 {
1552 if (INTVAL (x) == 0)
1553 fputs ("+=", file);
1554 else if (INTVAL (x) == 1)
1555 fputs ("-=", file);
1556 else
1557 gcc_unreachable ();
1558 break;
1559 }
1560 /* Moves to half registers with d or h modifiers always use unsigned
1561 constants. */
1562 else if (code == 'd')
1563 x = GEN_INT ((INTVAL (x) >> 16) & 0xffff);
1564 else if (code == 'h')
1565 x = GEN_INT (INTVAL (x) & 0xffff);
1566 else if (code == 'N')
1567 x = GEN_INT (-INTVAL (x));
1568 else if (code == 'X')
1569 x = GEN_INT (exact_log2 (0xffffffff & INTVAL (x)));
1570 else if (code == 'Y')
1571 x = GEN_INT (exact_log2 (0xffffffff & ~INTVAL (x)));
1572 else if (code == 'Z')
1573 /* Used for LINK insns. */
1574 x = GEN_INT (-8 - INTVAL (x));
1575
1576 /* fall through */
1577
1578 case SYMBOL_REF:
1579 output_addr_const (file, x);
1580 break;
1581
1582 case CONST_DOUBLE:
1583 output_operand_lossage ("invalid const_double operand");
1584 break;
1585
1586 case UNSPEC:
1587 switch (XINT (x, 1))
1588 {
1589 case UNSPEC_MOVE_PIC:
1590 output_addr_const (file, XVECEXP (x, 0, 0));
1591 fprintf (file, "@GOT");
1592 break;
1593
1594 case UNSPEC_MOVE_FDPIC:
1595 output_addr_const (file, XVECEXP (x, 0, 0));
1596 fprintf (file, "@GOT17M4");
1597 break;
1598
1599 case UNSPEC_FUNCDESC_GOT17M4:
1600 output_addr_const (file, XVECEXP (x, 0, 0));
1601 fprintf (file, "@FUNCDESC_GOT17M4");
1602 break;
1603
1604 case UNSPEC_LIBRARY_OFFSET:
1605 fprintf (file, "_current_shared_library_p5_offset_");
1606 break;
1607
1608 default:
1609 gcc_unreachable ();
1610 }
1611 break;
1612
1613 default:
1614 output_addr_const (file, x);
1615 }
1616 }
1617 }
1618 \f
1619 /* Argument support functions. */
1620
1621 /* Initialize a variable CUM of type CUMULATIVE_ARGS
1622 for a call to a function whose data type is FNTYPE.
1623 For a library call, FNTYPE is 0.
1624 VDSP C Compiler manual, our ABI says that
1625 first 3 words of arguments will use R0, R1 and R2.
1626 */
1627
1628 void
1629 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
1630 rtx libname ATTRIBUTE_UNUSED)
1631 {
1632 static CUMULATIVE_ARGS zero_cum;
1633
1634 *cum = zero_cum;
1635
1636 /* Set up the number of registers to use for passing arguments. */
1637
1638 cum->nregs = max_arg_registers;
1639 cum->arg_regs = arg_regs;
1640
1641 cum->call_cookie = CALL_NORMAL;
1642 /* Check for a longcall attribute. */
1643 if (fntype && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype)))
1644 cum->call_cookie |= CALL_SHORT;
1645 else if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)))
1646 cum->call_cookie |= CALL_LONG;
1647
1648 return;
1649 }
1650
1651 /* Update the data in CUM to advance over argument ARG. */
1652
1653 static void
1654 bfin_function_arg_advance (cumulative_args_t cum_v,
1655 const function_arg_info &arg)
1656 {
1657 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
1658 int count, bytes, words;
1659
1660 bytes = arg.promoted_size_in_bytes ();
1661 words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1662
1663 cum->words += words;
1664 cum->nregs -= words;
1665
1666 if (cum->nregs <= 0)
1667 {
1668 cum->nregs = 0;
1669 cum->arg_regs = NULL;
1670 }
1671 else
1672 {
1673 for (count = 1; count <= words; count++)
1674 cum->arg_regs++;
1675 }
1676
1677 return;
1678 }
1679
1680 /* Define where to put the arguments to a function.
1681 Value is zero to push the argument on the stack,
1682 or a hard register in which to store the argument.
1683
1684 CUM is a variable of type CUMULATIVE_ARGS which gives info about
1685 the preceding args and about the function being called.
1686 ARG is a description of the argument. */
1687
1688 static rtx
1689 bfin_function_arg (cumulative_args_t cum_v, const function_arg_info &arg)
1690 {
1691 CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
1692 int bytes = arg.promoted_size_in_bytes ();
1693
1694 if (arg.end_marker_p ())
1695 /* Compute operand 2 of the call insn. */
1696 return GEN_INT (cum->call_cookie);
1697
1698 if (bytes == -1)
1699 return NULL_RTX;
1700
1701 if (cum->nregs)
1702 return gen_rtx_REG (arg.mode, *(cum->arg_regs));
1703
1704 return NULL_RTX;
1705 }
1706
1707 /* For an arg passed partly in registers and partly in memory,
1708 this is the number of bytes passed in registers.
1709 For args passed entirely in registers or entirely in memory, zero.
1710
1711 Refer VDSP C Compiler manual, our ABI.
1712 First 3 words are in registers. So, if an argument is larger
1713 than the registers available, it will span the register and
1714 stack. */
1715
1716 static int
1717 bfin_arg_partial_bytes (cumulative_args_t cum, const function_arg_info &arg)
1718 {
1719 int bytes = arg.promoted_size_in_bytes ();
1720 int bytes_left = get_cumulative_args (cum)->nregs * UNITS_PER_WORD;
1721
1722 if (bytes == -1)
1723 return 0;
1724
1725 if (bytes_left == 0)
1726 return 0;
1727 if (bytes > bytes_left)
1728 return bytes_left;
1729 return 0;
1730 }
1731
1732 /* Variable sized types are passed by reference. */
1733
1734 static bool
1735 bfin_pass_by_reference (cumulative_args_t, const function_arg_info &arg)
1736 {
1737 return arg.type && TREE_CODE (TYPE_SIZE (arg.type)) != INTEGER_CST;
1738 }
1739
1740 /* Decide whether a type should be returned in memory (true)
1741 or in a register (false). This is called by the macro
1742 TARGET_RETURN_IN_MEMORY. */
1743
1744 static bool
1745 bfin_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
1746 {
1747 int size = int_size_in_bytes (type);
1748 return size > 2 * UNITS_PER_WORD || size == -1;
1749 }
1750
1751 /* Register in which address to store a structure value
1752 is passed to a function. */
1753 static rtx
1754 bfin_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
1755 int incoming ATTRIBUTE_UNUSED)
1756 {
1757 return gen_rtx_REG (Pmode, REG_P0);
1758 }
1759
1760 /* Return true when register may be used to pass function parameters. */
1761
1762 bool
1763 function_arg_regno_p (int n)
1764 {
1765 int i;
1766 for (i = 0; arg_regs[i] != -1; i++)
1767 if (n == arg_regs[i])
1768 return true;
1769 return false;
1770 }
1771
1772 /* Returns 1 if OP contains a symbol reference */
1773
1774 int
1775 symbolic_reference_mentioned_p (rtx op)
1776 {
1777 const char *fmt;
1778 int i;
1779
1780 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
1781 return 1;
1782
1783 fmt = GET_RTX_FORMAT (GET_CODE (op));
1784 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
1785 {
1786 if (fmt[i] == 'E')
1787 {
1788 int j;
1789
1790 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
1791 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
1792 return 1;
1793 }
1794
1795 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
1796 return 1;
1797 }
1798
1799 return 0;
1800 }
1801
1802 /* Decide whether we can make a sibling call to a function. DECL is the
1803 declaration of the function being targeted by the call and EXP is the
1804 CALL_EXPR representing the call. */
1805
1806 static bool
1807 bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
1808 tree exp ATTRIBUTE_UNUSED)
1809 {
1810 cgraph_node *this_func, *called_func;
1811 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1812 if (fkind != SUBROUTINE)
1813 return false;
1814 if (!TARGET_ID_SHARED_LIBRARY || TARGET_SEP_DATA)
1815 return true;
1816
1817 /* When compiling for ID shared libraries, can't sibcall a local function
1818 from a non-local function, because the local function thinks it does
1819 not need to reload P5 in the prologue, but the sibcall wil pop P5 in the
1820 sibcall epilogue, and we end up with the wrong value in P5. */
1821
1822 if (!decl)
1823 /* Not enough information. */
1824 return false;
1825
1826 this_func = cgraph_node::local_info_node (current_function_decl);
1827 called_func = cgraph_node::local_info_node (decl);
1828 if (!called_func)
1829 return false;
1830 return !called_func->local || this_func->local;
1831 }
1832 \f
1833 /* Write a template for a trampoline to F. */
1834
1835 static void
1836 bfin_asm_trampoline_template (FILE *f)
1837 {
1838 if (TARGET_FDPIC)
1839 {
1840 fprintf (f, "\t.dd\t0x00000000\n"); /* 0 */
1841 fprintf (f, "\t.dd\t0x00000000\n"); /* 0 */
1842 fprintf (f, "\t.dd\t0x0000e109\n"); /* p1.l = fn low */
1843 fprintf (f, "\t.dd\t0x0000e149\n"); /* p1.h = fn high */
1844 fprintf (f, "\t.dd\t0x0000e10a\n"); /* p2.l = sc low */
1845 fprintf (f, "\t.dd\t0x0000e14a\n"); /* p2.h = sc high */
1846 fprintf (f, "\t.dw\t0xac4b\n"); /* p3 = [p1 + 4] */
1847 fprintf (f, "\t.dw\t0x9149\n"); /* p1 = [p1] */
1848 fprintf (f, "\t.dw\t0x0051\n"); /* jump (p1)*/
1849 }
1850 else
1851 {
1852 fprintf (f, "\t.dd\t0x0000e109\n"); /* p1.l = fn low */
1853 fprintf (f, "\t.dd\t0x0000e149\n"); /* p1.h = fn high */
1854 fprintf (f, "\t.dd\t0x0000e10a\n"); /* p2.l = sc low */
1855 fprintf (f, "\t.dd\t0x0000e14a\n"); /* p2.h = sc high */
1856 fprintf (f, "\t.dw\t0x0051\n"); /* jump (p1)*/
1857 }
1858 }
1859
1860 /* Emit RTL insns to initialize the variable parts of a trampoline at
1861 M_TRAMP. FNDECL is the target function. CHAIN_VALUE is an RTX for
1862 the static chain value for the function. */
1863
1864 static void
1865 bfin_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
1866 {
1867 rtx t1 = copy_to_reg (XEXP (DECL_RTL (fndecl), 0));
1868 rtx t2 = copy_to_reg (chain_value);
1869 rtx mem;
1870 int i = 0;
1871
1872 emit_block_move (m_tramp, assemble_trampoline_template (),
1873 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
1874
1875 if (TARGET_FDPIC)
1876 {
1877 rtx a = force_reg (Pmode, plus_constant (Pmode, XEXP (m_tramp, 0), 8));
1878 mem = adjust_address (m_tramp, Pmode, 0);
1879 emit_move_insn (mem, a);
1880 i = 8;
1881 }
1882
1883 mem = adjust_address (m_tramp, HImode, i + 2);
1884 emit_move_insn (mem, gen_lowpart (HImode, t1));
1885 emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16)));
1886 mem = adjust_address (m_tramp, HImode, i + 6);
1887 emit_move_insn (mem, gen_lowpart (HImode, t1));
1888
1889 mem = adjust_address (m_tramp, HImode, i + 10);
1890 emit_move_insn (mem, gen_lowpart (HImode, t2));
1891 emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16)));
1892 mem = adjust_address (m_tramp, HImode, i + 14);
1893 emit_move_insn (mem, gen_lowpart (HImode, t2));
1894 }
1895
1896 /* Emit insns to move operands[1] into operands[0]. */
1897
1898 void
1899 emit_pic_move (rtx *operands, machine_mode mode ATTRIBUTE_UNUSED)
1900 {
1901 rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
1902
1903 gcc_assert (!TARGET_FDPIC || !(reload_in_progress || reload_completed));
1904 if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
1905 operands[1] = force_reg (SImode, operands[1]);
1906 else
1907 operands[1] = legitimize_pic_address (operands[1], temp,
1908 TARGET_FDPIC ? OUR_FDPIC_REG
1909 : pic_offset_table_rtx);
1910 }
1911
1912 /* Expand a move operation in mode MODE. The operands are in OPERANDS.
1913 Returns true if no further code must be generated, false if the caller
1914 should generate an insn to move OPERANDS[1] to OPERANDS[0]. */
1915
1916 bool
1917 expand_move (rtx *operands, machine_mode mode)
1918 {
1919 rtx op = operands[1];
1920 if ((TARGET_ID_SHARED_LIBRARY || TARGET_FDPIC)
1921 && SYMBOLIC_CONST (op))
1922 emit_pic_move (operands, mode);
1923 else if (mode == SImode && GET_CODE (op) == CONST
1924 && GET_CODE (XEXP (op, 0)) == PLUS
1925 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
1926 && !targetm.legitimate_constant_p (mode, op))
1927 {
1928 rtx dest = operands[0];
1929 rtx op0, op1;
1930 gcc_assert (!reload_in_progress && !reload_completed);
1931 op = XEXP (op, 0);
1932 op0 = force_reg (mode, XEXP (op, 0));
1933 op1 = XEXP (op, 1);
1934 if (!insn_data[CODE_FOR_addsi3].operand[2].predicate (op1, mode))
1935 op1 = force_reg (mode, op1);
1936 if (GET_CODE (dest) == MEM)
1937 dest = gen_reg_rtx (mode);
1938 emit_insn (gen_addsi3 (dest, op0, op1));
1939 if (dest == operands[0])
1940 return true;
1941 operands[1] = dest;
1942 }
1943 /* Don't generate memory->memory or constant->memory moves, go through a
1944 register */
1945 else if ((reload_in_progress | reload_completed) == 0
1946 && GET_CODE (operands[0]) == MEM
1947 && GET_CODE (operands[1]) != REG)
1948 operands[1] = force_reg (mode, operands[1]);
1949 return false;
1950 }
1951 \f
1952 /* Split one or more DImode RTL references into pairs of SImode
1953 references. The RTL can be REG, offsettable MEM, integer constant, or
1954 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
1955 split and "num" is its length. lo_half and hi_half are output arrays
1956 that parallel "operands". */
1957
1958 void
1959 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
1960 {
1961 while (num--)
1962 {
1963 rtx op = operands[num];
1964
1965 /* simplify_subreg refuse to split volatile memory addresses,
1966 but we still have to handle it. */
1967 if (GET_CODE (op) == MEM)
1968 {
1969 lo_half[num] = adjust_address (op, SImode, 0);
1970 hi_half[num] = adjust_address (op, SImode, 4);
1971 }
1972 else
1973 {
1974 lo_half[num] = simplify_gen_subreg (SImode, op,
1975 GET_MODE (op) == VOIDmode
1976 ? DImode : GET_MODE (op), 0);
1977 hi_half[num] = simplify_gen_subreg (SImode, op,
1978 GET_MODE (op) == VOIDmode
1979 ? DImode : GET_MODE (op), 4);
1980 }
1981 }
1982 }
1983 \f
1984 bool
1985 bfin_longcall_p (rtx op, int call_cookie)
1986 {
1987 gcc_assert (GET_CODE (op) == SYMBOL_REF);
1988 if (SYMBOL_REF_WEAK (op))
1989 return 1;
1990 if (call_cookie & CALL_SHORT)
1991 return 0;
1992 if (call_cookie & CALL_LONG)
1993 return 1;
1994 if (TARGET_LONG_CALLS)
1995 return 1;
1996 return 0;
1997 }
1998
1999 /* Expand a call instruction. FNADDR is the call target, RETVAL the return value.
2000 COOKIE is a CONST_INT holding the call_cookie prepared init_cumulative_args.
2001 SIBCALL is nonzero if this is a sibling call. */
2002
2003 void
2004 bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
2005 {
2006 rtx use = NULL, call;
2007 rtx callee = XEXP (fnaddr, 0);
2008 int nelts = 3;
2009 rtx pat;
2010 rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REGNO);
2011 rtx retsreg = gen_rtx_REG (Pmode, REG_RETS);
2012 int n;
2013
2014 /* In an untyped call, we can get NULL for operand 2. */
2015 if (cookie == NULL_RTX)
2016 cookie = const0_rtx;
2017
2018 /* Static functions and indirect calls don't need the pic register. */
2019 if (!TARGET_FDPIC && flag_pic
2020 && GET_CODE (callee) == SYMBOL_REF
2021 && !SYMBOL_REF_LOCAL_P (callee))
2022 use_reg (&use, pic_offset_table_rtx);
2023
2024 if (TARGET_FDPIC)
2025 {
2026 int caller_in_sram, callee_in_sram;
2027
2028 /* 0 is not in sram, 1 is in L1 sram, 2 is in L2 sram. */
2029 caller_in_sram = callee_in_sram = 0;
2030
2031 if (lookup_attribute ("l1_text",
2032 DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE)
2033 caller_in_sram = 1;
2034 else if (lookup_attribute ("l2",
2035 DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE)
2036 caller_in_sram = 2;
2037
2038 if (GET_CODE (callee) == SYMBOL_REF
2039 && SYMBOL_REF_DECL (callee) && DECL_P (SYMBOL_REF_DECL (callee)))
2040 {
2041 if (lookup_attribute
2042 ("l1_text",
2043 DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE)
2044 callee_in_sram = 1;
2045 else if (lookup_attribute
2046 ("l2",
2047 DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE)
2048 callee_in_sram = 2;
2049 }
2050
2051 if (GET_CODE (callee) != SYMBOL_REF
2052 || bfin_longcall_p (callee, INTVAL (cookie))
2053 || (GET_CODE (callee) == SYMBOL_REF
2054 && !SYMBOL_REF_LOCAL_P (callee)
2055 && TARGET_INLINE_PLT)
2056 || caller_in_sram != callee_in_sram
2057 || (caller_in_sram && callee_in_sram
2058 && (GET_CODE (callee) != SYMBOL_REF
2059 || !SYMBOL_REF_LOCAL_P (callee))))
2060 {
2061 rtx addr = callee;
2062 if (! address_operand (addr, Pmode))
2063 addr = force_reg (Pmode, addr);
2064
2065 fnaddr = gen_reg_rtx (SImode);
2066 emit_insn (gen_load_funcdescsi (fnaddr, addr));
2067 fnaddr = gen_rtx_MEM (Pmode, fnaddr);
2068
2069 picreg = gen_reg_rtx (SImode);
2070 emit_insn (gen_load_funcdescsi (picreg,
2071 plus_constant (Pmode, addr, 4)));
2072 }
2073
2074 nelts++;
2075 }
2076 else if ((!register_no_elim_operand (callee, Pmode)
2077 && GET_CODE (callee) != SYMBOL_REF)
2078 || (GET_CODE (callee) == SYMBOL_REF
2079 && ((TARGET_ID_SHARED_LIBRARY && !TARGET_LEAF_ID_SHARED_LIBRARY)
2080 || bfin_longcall_p (callee, INTVAL (cookie)))))
2081 {
2082 callee = copy_to_mode_reg (Pmode, callee);
2083 fnaddr = gen_rtx_MEM (Pmode, callee);
2084 }
2085 call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
2086
2087 if (retval)
2088 call = gen_rtx_SET (retval, call);
2089
2090 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nelts));
2091 n = 0;
2092 XVECEXP (pat, 0, n++) = call;
2093 if (TARGET_FDPIC)
2094 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, picreg);
2095 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie);
2096 if (sibcall)
2097 XVECEXP (pat, 0, n++) = ret_rtx;
2098 else
2099 XVECEXP (pat, 0, n++) = gen_rtx_CLOBBER (VOIDmode, retsreg);
2100 call = emit_call_insn (pat);
2101 if (use)
2102 CALL_INSN_FUNCTION_USAGE (call) = use;
2103 }
2104 \f
2105 /* Implement TARGET_HARD_REGNO_NREGS. */
2106
2107 static unsigned int
2108 bfin_hard_regno_nregs (unsigned int regno, machine_mode mode)
2109 {
2110 if (mode == PDImode && (regno == REG_A0 || regno == REG_A1))
2111 return 1;
2112 if (mode == V2PDImode && (regno == REG_A0 || regno == REG_A1))
2113 return 2;
2114 return CLASS_MAX_NREGS (GENERAL_REGS, mode);
2115 }
2116
2117 /* Implement TARGET_HARD_REGNO_MODE_OK.
2118
2119 Do not allow to store a value in REG_CC for any mode.
2120 Do not allow to store value in pregs if mode is not SI. */
2121 static bool
2122 bfin_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
2123 {
2124 /* Allow only dregs to store value of mode HI or QI */
2125 enum reg_class rclass = REGNO_REG_CLASS (regno);
2126
2127 if (mode == CCmode)
2128 return false;
2129
2130 if (mode == V2HImode)
2131 return D_REGNO_P (regno);
2132 if (rclass == CCREGS)
2133 return mode == BImode;
2134 if (mode == PDImode || mode == V2PDImode)
2135 return regno == REG_A0 || regno == REG_A1;
2136
2137 /* Allow all normal 32-bit regs, except REG_M3, in case regclass ever comes
2138 up with a bad register class (such as ALL_REGS) for DImode. */
2139 if (mode == DImode)
2140 return regno < REG_M3;
2141
2142 if (mode == SImode
2143 && TEST_HARD_REG_BIT (reg_class_contents[PROLOGUE_REGS], regno))
2144 return true;
2145
2146 return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno);
2147 }
2148
2149 /* Implement TARGET_MODES_TIEABLE_P. */
2150
2151 static bool
2152 bfin_modes_tieable_p (machine_mode mode1, machine_mode mode2)
2153 {
2154 return (mode1 == mode2
2155 || ((GET_MODE_CLASS (mode1) == MODE_INT
2156 || GET_MODE_CLASS (mode1) == MODE_FLOAT)
2157 && (GET_MODE_CLASS (mode2) == MODE_INT
2158 || GET_MODE_CLASS (mode2) == MODE_FLOAT)
2159 && mode1 != BImode && mode2 != BImode
2160 && GET_MODE_SIZE (mode1) <= UNITS_PER_WORD
2161 && GET_MODE_SIZE (mode2) <= UNITS_PER_WORD));
2162 }
2163
2164 /* Implements target hook vector_mode_supported_p. */
2165
2166 static bool
2167 bfin_vector_mode_supported_p (machine_mode mode)
2168 {
2169 return mode == V2HImode;
2170 }
2171
2172 /* Worker function for TARGET_REGISTER_MOVE_COST. */
2173
2174 static int
2175 bfin_register_move_cost (machine_mode mode,
2176 reg_class_t class1, reg_class_t class2)
2177 {
2178 /* These need secondary reloads, so they're more expensive. */
2179 if ((class1 == CCREGS && !reg_class_subset_p (class2, DREGS))
2180 || (class2 == CCREGS && !reg_class_subset_p (class1, DREGS)))
2181 return 4;
2182
2183 /* If optimizing for size, always prefer reg-reg over reg-memory moves. */
2184 if (optimize_size)
2185 return 2;
2186
2187 if (GET_MODE_CLASS (mode) == MODE_INT)
2188 {
2189 /* Discourage trying to use the accumulators. */
2190 if (TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A0)
2191 || TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A1)
2192 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A0)
2193 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A1))
2194 return 20;
2195 }
2196 return 2;
2197 }
2198
2199 /* Worker function for TARGET_MEMORY_MOVE_COST.
2200
2201 ??? In theory L1 memory has single-cycle latency. We should add a switch
2202 that tells the compiler whether we expect to use only L1 memory for the
2203 program; it'll make the costs more accurate. */
2204
2205 static int
2206 bfin_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED,
2207 reg_class_t rclass,
2208 bool in ATTRIBUTE_UNUSED)
2209 {
2210 /* Make memory accesses slightly more expensive than any register-register
2211 move. Also, penalize non-DP registers, since they need secondary
2212 reloads to load and store. */
2213 if (! reg_class_subset_p (rclass, DPREGS))
2214 return 10;
2215
2216 return 8;
2217 }
2218
2219 /* Inform reload about cases where moving X with a mode MODE to a register in
2220 RCLASS requires an extra scratch register. Return the class needed for the
2221 scratch register. */
2222
2223 static reg_class_t
2224 bfin_secondary_reload (bool in_p, rtx x, reg_class_t rclass_i,
2225 machine_mode mode, secondary_reload_info *sri)
2226 {
2227 /* If we have HImode or QImode, we can only use DREGS as secondary registers;
2228 in most other cases we can also use PREGS. */
2229 enum reg_class default_class = GET_MODE_SIZE (mode) >= 4 ? DPREGS : DREGS;
2230 enum reg_class x_class = NO_REGS;
2231 enum rtx_code code = GET_CODE (x);
2232 enum reg_class rclass = (enum reg_class) rclass_i;
2233
2234 if (code == SUBREG)
2235 x = SUBREG_REG (x), code = GET_CODE (x);
2236 if (REG_P (x))
2237 {
2238 int regno = REGNO (x);
2239 if (regno >= FIRST_PSEUDO_REGISTER)
2240 regno = reg_renumber[regno];
2241
2242 if (regno == -1)
2243 code = MEM;
2244 else
2245 x_class = REGNO_REG_CLASS (regno);
2246 }
2247
2248 /* We can be asked to reload (plus (FP) (large_constant)) into a DREG.
2249 This happens as a side effect of register elimination, and we need
2250 a scratch register to do it. */
2251 if (fp_plus_const_operand (x, mode))
2252 {
2253 rtx op2 = XEXP (x, 1);
2254 int large_constant_p = ! satisfies_constraint_Ks7 (op2);
2255
2256 if (rclass == PREGS || rclass == PREGS_CLOBBERED)
2257 return NO_REGS;
2258 /* If destination is a DREG, we can do this without a scratch register
2259 if the constant is valid for an add instruction. */
2260 if ((rclass == DREGS || rclass == DPREGS)
2261 && ! large_constant_p)
2262 return NO_REGS;
2263 /* Reloading to anything other than a DREG? Use a PREG scratch
2264 register. */
2265 sri->icode = CODE_FOR_reload_insi;
2266 return NO_REGS;
2267 }
2268
2269 /* Data can usually be moved freely between registers of most classes.
2270 AREGS are an exception; they can only move to or from another register
2271 in AREGS or one in DREGS. They can also be assigned the constant 0. */
2272 if (x_class == AREGS || x_class == EVEN_AREGS || x_class == ODD_AREGS)
2273 return (rclass == DREGS || rclass == AREGS || rclass == EVEN_AREGS
2274 || rclass == ODD_AREGS
2275 ? NO_REGS : DREGS);
2276
2277 if (rclass == AREGS || rclass == EVEN_AREGS || rclass == ODD_AREGS)
2278 {
2279 if (code == MEM)
2280 {
2281 sri->icode = in_p ? CODE_FOR_reload_inpdi : CODE_FOR_reload_outpdi;
2282 return NO_REGS;
2283 }
2284
2285 if (x != const0_rtx && x_class != DREGS)
2286 {
2287 return DREGS;
2288 }
2289 else
2290 return NO_REGS;
2291 }
2292
2293 /* CCREGS can only be moved from/to DREGS. */
2294 if (rclass == CCREGS && x_class != DREGS)
2295 return DREGS;
2296 if (x_class == CCREGS && rclass != DREGS)
2297 return DREGS;
2298
2299 /* All registers other than AREGS can load arbitrary constants. The only
2300 case that remains is MEM. */
2301 if (code == MEM)
2302 if (! reg_class_subset_p (rclass, default_class))
2303 return default_class;
2304
2305 return NO_REGS;
2306 }
2307
2308 /* Implement TARGET_CLASS_LIKELY_SPILLED_P. */
2309
2310 static bool
2311 bfin_class_likely_spilled_p (reg_class_t rclass)
2312 {
2313 switch (rclass)
2314 {
2315 case PREGS_CLOBBERED:
2316 case PROLOGUE_REGS:
2317 case P0REGS:
2318 case D0REGS:
2319 case D1REGS:
2320 case D2REGS:
2321 case CCREGS:
2322 return true;
2323
2324 default:
2325 break;
2326 }
2327
2328 return false;
2329 }
2330 \f
2331 static struct machine_function *
2332 bfin_init_machine_status (void)
2333 {
2334 return ggc_cleared_alloc<machine_function> ();
2335 }
2336
2337 /* Implement the TARGET_OPTION_OVERRIDE hook. */
2338
2339 static void
2340 bfin_option_override (void)
2341 {
2342 /* If processor type is not specified, enable all workarounds. */
2343 if (bfin_cpu_type == BFIN_CPU_UNKNOWN)
2344 {
2345 int i;
2346
2347 for (i = 0; bfin_cpus[i].name != NULL; i++)
2348 bfin_workarounds |= bfin_cpus[i].workarounds;
2349
2350 bfin_si_revision = 0xffff;
2351 }
2352
2353 if (bfin_csync_anomaly == 1)
2354 bfin_workarounds |= WA_SPECULATIVE_SYNCS;
2355 else if (bfin_csync_anomaly == 0)
2356 bfin_workarounds &= ~WA_SPECULATIVE_SYNCS;
2357
2358 if (bfin_specld_anomaly == 1)
2359 bfin_workarounds |= WA_SPECULATIVE_LOADS;
2360 else if (bfin_specld_anomaly == 0)
2361 bfin_workarounds &= ~WA_SPECULATIVE_LOADS;
2362
2363 if (TARGET_OMIT_LEAF_FRAME_POINTER)
2364 flag_omit_frame_pointer = 1;
2365
2366 #ifdef SUBTARGET_FDPIC_NOT_SUPPORTED
2367 if (TARGET_FDPIC)
2368 error ("%<-mfdpic%> is not supported, please use a bfin-linux-uclibc "
2369 "target");
2370 #endif
2371
2372 /* Library identification */
2373 if (OPTION_SET_P (bfin_library_id) && ! TARGET_ID_SHARED_LIBRARY)
2374 error ("%<-mshared-library-id=%> specified without "
2375 "%<-mid-shared-library%>");
2376
2377 if (stack_limit_rtx && TARGET_FDPIC)
2378 {
2379 warning (0, "%<-fstack-limit-%> options are ignored with %<-mfdpic%>; "
2380 "use %<-mstack-check-l1%>");
2381 stack_limit_rtx = NULL_RTX;
2382 }
2383
2384 if (stack_limit_rtx && TARGET_STACK_CHECK_L1)
2385 error ("cannot use multiple stack checking methods together");
2386
2387 if (TARGET_ID_SHARED_LIBRARY && TARGET_FDPIC)
2388 error ("ID shared libraries and FD-PIC mode cannot be used together");
2389
2390 /* Don't allow the user to specify -mid-shared-library and -msep-data
2391 together, as it makes little sense from a user's point of view... */
2392 if (TARGET_SEP_DATA && TARGET_ID_SHARED_LIBRARY)
2393 error ("cannot specify both %<-msep-data%> and %<-mid-shared-library%>");
2394 /* ... internally, however, it's nearly the same. */
2395 if (TARGET_SEP_DATA)
2396 target_flags |= MASK_ID_SHARED_LIBRARY | MASK_LEAF_ID_SHARED_LIBRARY;
2397
2398 if (TARGET_ID_SHARED_LIBRARY && flag_pic == 0)
2399 flag_pic = 1;
2400
2401 /* There is no single unaligned SI op for PIC code. Sometimes we
2402 need to use ".4byte" and sometimes we need to use ".picptr".
2403 See bfin_assemble_integer for details. */
2404 if (TARGET_FDPIC)
2405 targetm.asm_out.unaligned_op.si = 0;
2406
2407 /* Silently turn off flag_pic if not doing FDPIC or ID shared libraries,
2408 since we don't support it and it'll just break. */
2409 if (flag_pic && !TARGET_FDPIC && !TARGET_ID_SHARED_LIBRARY)
2410 flag_pic = 0;
2411
2412 if (TARGET_MULTICORE && bfin_cpu_type != BFIN_CPU_BF561)
2413 error ("%<-mmulticore%> can only be used with BF561");
2414
2415 if (TARGET_COREA && !TARGET_MULTICORE)
2416 error ("%<-mcorea%> should be used with %<-mmulticore%>");
2417
2418 if (TARGET_COREB && !TARGET_MULTICORE)
2419 error ("%<-mcoreb%> should be used with %<-mmulticore%>");
2420
2421 if (TARGET_COREA && TARGET_COREB)
2422 error ("%<-mcorea%> and %<-mcoreb%> cannot be used together");
2423
2424 flag_schedule_insns = 0;
2425
2426 init_machine_status = bfin_init_machine_status;
2427 }
2428
2429 /* Return the destination address of BRANCH.
2430 We need to use this instead of get_attr_length, because the
2431 cbranch_with_nops pattern conservatively sets its length to 6, and
2432 we still prefer to use shorter sequences. */
2433
2434 static int
2435 branch_dest (rtx_insn *branch)
2436 {
2437 rtx dest;
2438 int dest_uid;
2439 rtx pat = PATTERN (branch);
2440 if (GET_CODE (pat) == PARALLEL)
2441 pat = XVECEXP (pat, 0, 0);
2442 dest = SET_SRC (pat);
2443 if (GET_CODE (dest) == IF_THEN_ELSE)
2444 dest = XEXP (dest, 1);
2445 dest = XEXP (dest, 0);
2446 dest_uid = INSN_UID (dest);
2447 return INSN_ADDRESSES (dest_uid);
2448 }
2449
2450 /* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates
2451 it's a branch that's predicted taken. */
2452
2453 static int
2454 cbranch_predicted_taken_p (rtx insn)
2455 {
2456 rtx x = find_reg_note (insn, REG_BR_PROB, 0);
2457
2458 if (x)
2459 {
2460 return profile_probability::from_reg_br_prob_note (XINT (x, 0))
2461 >= profile_probability::even ();
2462 }
2463
2464 return 0;
2465 }
2466
2467 /* Templates for use by asm_conditional_branch. */
2468
2469 static const char *ccbranch_templates[][3] = {
2470 { "if !cc jump %3;", "if cc jump 4 (bp); jump.s %3;", "if cc jump 6 (bp); jump.l %3;" },
2471 { "if cc jump %3;", "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" },
2472 { "if !cc jump %3 (bp);", "if cc jump 4; jump.s %3;", "if cc jump 6; jump.l %3;" },
2473 { "if cc jump %3 (bp);", "if !cc jump 4; jump.s %3;", "if !cc jump 6; jump.l %3;" },
2474 };
2475
2476 /* Output INSN, which is a conditional branch instruction with operands
2477 OPERANDS.
2478
2479 We deal with the various forms of conditional branches that can be generated
2480 by bfin_reorg to prevent the hardware from doing speculative loads, by
2481 - emitting a sufficient number of nops, if N_NOPS is nonzero, or
2482 - always emitting the branch as predicted taken, if PREDICT_TAKEN is true.
2483 Either of these is only necessary if the branch is short, otherwise the
2484 template we use ends in an unconditional jump which flushes the pipeline
2485 anyway. */
2486
2487 void
2488 asm_conditional_branch (rtx_insn *insn, rtx *operands, int n_nops, int predict_taken)
2489 {
2490 int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
2491 /* Note : offset for instructions like if cc jmp; jump.[sl] offset
2492 is to be taken from start of if cc rather than jump.
2493 Range for jump.s is (-4094, 4096) instead of (-4096, 4094)
2494 */
2495 int len = (offset >= -1024 && offset <= 1022 ? 0
2496 : offset >= -4094 && offset <= 4096 ? 1
2497 : 2);
2498 int bp = predict_taken && len == 0 ? 1 : cbranch_predicted_taken_p (insn);
2499 int idx = (bp << 1) | (GET_CODE (operands[0]) == EQ ? BRF : BRT);
2500 output_asm_insn (ccbranch_templates[idx][len], operands);
2501 gcc_assert (n_nops == 0 || !bp);
2502 if (len == 0)
2503 while (n_nops-- > 0)
2504 output_asm_insn ("nop;", NULL);
2505 }
2506
2507 /* Emit rtl for a comparison operation CMP in mode MODE. Operands have been
2508 stored in bfin_compare_op0 and bfin_compare_op1 already. */
2509
2510 rtx
2511 bfin_gen_compare (rtx cmp, machine_mode mode ATTRIBUTE_UNUSED)
2512 {
2513 enum rtx_code code1, code2;
2514 rtx op0 = XEXP (cmp, 0), op1 = XEXP (cmp, 1);
2515 rtx tem = bfin_cc_rtx;
2516 enum rtx_code code = GET_CODE (cmp);
2517
2518 /* If we have a BImode input, then we already have a compare result, and
2519 do not need to emit another comparison. */
2520 if (GET_MODE (op0) == BImode)
2521 {
2522 gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
2523 tem = op0, code2 = code;
2524 }
2525 else
2526 {
2527 switch (code) {
2528 /* bfin has these conditions */
2529 case EQ:
2530 case LT:
2531 case LE:
2532 case LEU:
2533 case LTU:
2534 code1 = code;
2535 code2 = NE;
2536 break;
2537 default:
2538 code1 = reverse_condition (code);
2539 code2 = EQ;
2540 break;
2541 }
2542 emit_insn (gen_rtx_SET (tem, gen_rtx_fmt_ee (code1, BImode, op0, op1)));
2543 }
2544
2545 return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode));
2546 }
2547 \f
2548 /* Return nonzero iff C has exactly one bit set if it is interpreted
2549 as a 32-bit constant. */
2550
2551 int
2552 log2constp (unsigned HOST_WIDE_INT c)
2553 {
2554 c &= 0xFFFFFFFF;
2555 return c != 0 && (c & (c-1)) == 0;
2556 }
2557
2558 /* Returns the number of consecutive least significant zeros in the binary
2559 representation of *V.
2560 We modify *V to contain the original value arithmetically shifted right by
2561 the number of zeroes. */
2562
2563 static int
2564 shiftr_zero (HOST_WIDE_INT *v)
2565 {
2566 unsigned HOST_WIDE_INT tmp = *v;
2567 unsigned HOST_WIDE_INT sgn;
2568 int n = 0;
2569
2570 if (tmp == 0)
2571 return 0;
2572
2573 sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1));
2574 while ((tmp & 0x1) == 0 && n <= 32)
2575 {
2576 tmp = (tmp >> 1) | sgn;
2577 n++;
2578 }
2579 *v = tmp;
2580 return n;
2581 }
2582
2583 /* After reload, split the load of an immediate constant. OPERANDS are the
2584 operands of the movsi_insn pattern which we are splitting. We return
2585 nonzero if we emitted a sequence to load the constant, zero if we emitted
2586 nothing because we want to use the splitter's default sequence. */
2587
2588 int
2589 split_load_immediate (rtx operands[])
2590 {
2591 HOST_WIDE_INT val = INTVAL (operands[1]);
2592 HOST_WIDE_INT tmp;
2593 HOST_WIDE_INT shifted = val;
2594 HOST_WIDE_INT shifted_compl = ~val;
2595 int num_zero = shiftr_zero (&shifted);
2596 int num_compl_zero = shiftr_zero (&shifted_compl);
2597 unsigned int regno = REGNO (operands[0]);
2598
2599 /* This case takes care of single-bit set/clear constants, which we could
2600 also implement with BITSET/BITCLR. */
2601 if (num_zero
2602 && shifted >= -32768 && shifted < 65536
2603 && (D_REGNO_P (regno)
2604 || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))
2605 {
2606 emit_insn (gen_movsi (operands[0], gen_int_mode (shifted, SImode)));
2607 emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));
2608 return 1;
2609 }
2610
2611 tmp = val & 0xFFFF;
2612 tmp |= -(tmp & 0x8000);
2613
2614 /* If high word has one bit set or clear, try to use a bit operation. */
2615 if (D_REGNO_P (regno))
2616 {
2617 if (log2constp (val & 0xFFFF0000))
2618 {
2619 emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));
2620 emit_insn (gen_iorsi3 (operands[0], operands[0],
2621 gen_int_mode (val & 0xFFFF0000, SImode)));
2622 return 1;
2623 }
2624 else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)
2625 {
2626 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2627 emit_insn (gen_andsi3 (operands[0], operands[0],
2628 gen_int_mode (val | 0xFFFF, SImode)));
2629 }
2630 }
2631
2632 if (D_REGNO_P (regno))
2633 {
2634 if (tmp >= -64 && tmp <= 63)
2635 {
2636 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2637 emit_insn (gen_movstricthi_high (operands[0],
2638 gen_int_mode (val & -65536,
2639 SImode)));
2640 return 1;
2641 }
2642
2643 if ((val & 0xFFFF0000) == 0)
2644 {
2645 emit_insn (gen_movsi (operands[0], const0_rtx));
2646 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2647 return 1;
2648 }
2649
2650 if ((val & 0xFFFF0000) == 0xFFFF0000)
2651 {
2652 emit_insn (gen_movsi (operands[0], constm1_rtx));
2653 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2654 return 1;
2655 }
2656 }
2657
2658 /* Need DREGs for the remaining case. */
2659 if (regno > REG_R7)
2660 return 0;
2661
2662 if (optimize_size
2663 && num_compl_zero && shifted_compl >= -64 && shifted_compl <= 63)
2664 {
2665 /* If optimizing for size, generate a sequence that has more instructions
2666 but is shorter. */
2667 emit_insn (gen_movsi (operands[0], gen_int_mode (shifted_compl, SImode)));
2668 emit_insn (gen_ashlsi3 (operands[0], operands[0],
2669 GEN_INT (num_compl_zero)));
2670 emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
2671 return 1;
2672 }
2673 return 0;
2674 }
2675 \f
2676 /* Return true if the legitimate memory address for a memory operand of mode
2677 MODE. Return false if not. */
2678
2679 static bool
2680 bfin_valid_add (machine_mode mode, HOST_WIDE_INT value)
2681 {
2682 unsigned HOST_WIDE_INT v = value > 0 ? value : -value;
2683 int sz = GET_MODE_SIZE (mode);
2684 int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2;
2685 /* The usual offsettable_memref machinery doesn't work so well for this
2686 port, so we deal with the problem here. */
2687 if (value > 0 && sz == 8)
2688 v += 4;
2689 return (v & ~(0x7fff << shift)) == 0;
2690 }
2691
2692 static bool
2693 bfin_valid_reg_p (unsigned int regno, int strict, machine_mode mode,
2694 enum rtx_code outer_code)
2695 {
2696 if (strict)
2697 return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH);
2698 else
2699 return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH);
2700 }
2701
2702 /* Recognize an RTL expression that is a valid memory address for an
2703 instruction. The MODE argument is the machine mode for the MEM expression
2704 that wants to use this address.
2705
2706 Blackfin addressing modes are as follows:
2707
2708 [preg]
2709 [preg + imm16]
2710
2711 B [ Preg + uimm15 ]
2712 W [ Preg + uimm16m2 ]
2713 [ Preg + uimm17m4 ]
2714
2715 [preg++]
2716 [preg--]
2717 [--sp]
2718 */
2719
2720 static bool
2721 bfin_legitimate_address_p (machine_mode mode, rtx x, bool strict,
2722 code_helper = ERROR_MARK)
2723 {
2724 switch (GET_CODE (x)) {
2725 case REG:
2726 if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM))
2727 return true;
2728 break;
2729 case PLUS:
2730 if (REG_P (XEXP (x, 0))
2731 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS)
2732 && ((GET_CODE (XEXP (x, 1)) == UNSPEC && mode == SImode)
2733 || (GET_CODE (XEXP (x, 1)) == CONST_INT
2734 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
2735 return true;
2736 break;
2737 case POST_INC:
2738 case POST_DEC:
2739 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2740 && REG_P (XEXP (x, 0))
2741 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC))
2742 return true;
2743 break;
2744 case PRE_DEC:
2745 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2746 && XEXP (x, 0) == stack_pointer_rtx
2747 && REG_P (XEXP (x, 0))
2748 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC))
2749 return true;
2750 break;
2751 default:
2752 break;
2753 }
2754 return false;
2755 }
2756
2757 /* Decide whether we can force certain constants to memory. If we
2758 decide we can't, the caller should be able to cope with it in
2759 another way. */
2760
2761 static bool
2762 bfin_cannot_force_const_mem (machine_mode mode ATTRIBUTE_UNUSED,
2763 rtx x ATTRIBUTE_UNUSED)
2764 {
2765 /* We have only one class of non-legitimate constants, and our movsi
2766 expander knows how to handle them. Dropping these constants into the
2767 data section would only shift the problem - we'd still get relocs
2768 outside the object, in the data section rather than the text section. */
2769 return true;
2770 }
2771
2772 /* Ensure that for any constant of the form symbol + offset, the offset
2773 remains within the object. Any other constants are ok.
2774 This ensures that flat binaries never have to deal with relocations
2775 crossing section boundaries. */
2776
2777 static bool
2778 bfin_legitimate_constant_p (machine_mode mode ATTRIBUTE_UNUSED, rtx x)
2779 {
2780 rtx sym;
2781 HOST_WIDE_INT offset;
2782
2783 if (GET_CODE (x) != CONST)
2784 return true;
2785
2786 x = XEXP (x, 0);
2787 gcc_assert (GET_CODE (x) == PLUS);
2788
2789 sym = XEXP (x, 0);
2790 x = XEXP (x, 1);
2791 if (GET_CODE (sym) != SYMBOL_REF
2792 || GET_CODE (x) != CONST_INT)
2793 return true;
2794 offset = INTVAL (x);
2795
2796 if (SYMBOL_REF_DECL (sym) == 0)
2797 return true;
2798 if (offset < 0
2799 || offset >= int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (sym))))
2800 return false;
2801
2802 return true;
2803 }
2804
2805 static bool
2806 bfin_rtx_costs (rtx x, machine_mode mode, int outer_code_i, int opno,
2807 int *total, bool speed)
2808 {
2809 enum rtx_code code = GET_CODE (x);
2810 enum rtx_code outer_code = (enum rtx_code) outer_code_i;
2811 int cost2 = COSTS_N_INSNS (1);
2812 rtx op0, op1;
2813
2814 switch (code)
2815 {
2816 case CONST_INT:
2817 if (outer_code == SET || outer_code == PLUS)
2818 *total = satisfies_constraint_Ks7 (x) ? 0 : cost2;
2819 else if (outer_code == AND)
2820 *total = log2constp (~INTVAL (x)) ? 0 : cost2;
2821 else if (outer_code == LE || outer_code == LT || outer_code == EQ)
2822 *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
2823 else if (outer_code == LEU || outer_code == LTU)
2824 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
2825 else if (outer_code == MULT)
2826 *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
2827 else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
2828 *total = 0;
2829 else if (outer_code == ASHIFT || outer_code == ASHIFTRT
2830 || outer_code == LSHIFTRT)
2831 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
2832 else if (outer_code == IOR || outer_code == XOR)
2833 *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
2834 else
2835 *total = cost2;
2836 return true;
2837
2838 case CONST:
2839 case LABEL_REF:
2840 case SYMBOL_REF:
2841 case CONST_DOUBLE:
2842 *total = COSTS_N_INSNS (2);
2843 return true;
2844
2845 case PLUS:
2846 op0 = XEXP (x, 0);
2847 op1 = XEXP (x, 1);
2848 if (mode == SImode)
2849 {
2850 if (GET_CODE (op0) == MULT
2851 && GET_CODE (XEXP (op0, 1)) == CONST_INT)
2852 {
2853 HOST_WIDE_INT val = INTVAL (XEXP (op0, 1));
2854 if (val == 2 || val == 4)
2855 {
2856 *total = cost2;
2857 *total += rtx_cost (XEXP (op0, 0), mode, outer_code,
2858 opno, speed);
2859 *total += rtx_cost (op1, mode, outer_code, opno, speed);
2860 return true;
2861 }
2862 }
2863 *total = cost2;
2864 if (GET_CODE (op0) != REG
2865 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2866 *total += set_src_cost (op0, mode, speed);
2867 #if 0 /* We'd like to do this for accuracy, but it biases the loop optimizer
2868 towards creating too many induction variables. */
2869 if (!reg_or_7bit_operand (op1, SImode))
2870 *total += set_src_cost (op1, mode, speed);
2871 #endif
2872 }
2873 else if (mode == DImode)
2874 {
2875 *total = 6 * cost2;
2876 if (GET_CODE (op1) != CONST_INT
2877 || !satisfies_constraint_Ks7 (op1))
2878 *total += rtx_cost (op1, mode, PLUS, 1, speed);
2879 if (GET_CODE (op0) != REG
2880 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2881 *total += rtx_cost (op0, mode, PLUS, 0, speed);
2882 }
2883 return true;
2884
2885 case MINUS:
2886 if (mode == DImode)
2887 *total = 6 * cost2;
2888 else
2889 *total = cost2;
2890 return true;
2891
2892 case ASHIFT:
2893 case ASHIFTRT:
2894 case LSHIFTRT:
2895 if (mode == DImode)
2896 *total = 6 * cost2;
2897 else
2898 *total = cost2;
2899
2900 op0 = XEXP (x, 0);
2901 op1 = XEXP (x, 1);
2902 if (GET_CODE (op0) != REG
2903 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2904 *total += rtx_cost (op0, mode, code, 0, speed);
2905
2906 return true;
2907
2908 case IOR:
2909 case AND:
2910 case XOR:
2911 op0 = XEXP (x, 0);
2912 op1 = XEXP (x, 1);
2913
2914 /* Handle special cases of IOR: rotates, ALIGN insns, movstricthi_high. */
2915 if (code == IOR)
2916 {
2917 if ((GET_CODE (op0) == LSHIFTRT && GET_CODE (op1) == ASHIFT)
2918 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == ZERO_EXTEND)
2919 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT)
2920 || (GET_CODE (op0) == AND && GET_CODE (op1) == CONST_INT))
2921 {
2922 *total = cost2;
2923 return true;
2924 }
2925 }
2926
2927 if (GET_CODE (op0) != REG
2928 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2929 *total += rtx_cost (op0, mode, code, 0, speed);
2930
2931 if (mode == DImode)
2932 {
2933 *total = 2 * cost2;
2934 return true;
2935 }
2936 *total = cost2;
2937 if (mode != SImode)
2938 return true;
2939
2940 if (code == AND)
2941 {
2942 if (! rhs_andsi3_operand (XEXP (x, 1), SImode))
2943 *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
2944 }
2945 else
2946 {
2947 if (! regorlog2_operand (XEXP (x, 1), SImode))
2948 *total += rtx_cost (XEXP (x, 1), mode, code, 1, speed);
2949 }
2950
2951 return true;
2952
2953 case ZERO_EXTRACT:
2954 case SIGN_EXTRACT:
2955 if (outer_code == SET
2956 && XEXP (x, 1) == const1_rtx
2957 && GET_CODE (XEXP (x, 2)) == CONST_INT)
2958 {
2959 *total = 2 * cost2;
2960 return true;
2961 }
2962 /* fall through */
2963
2964 case SIGN_EXTEND:
2965 case ZERO_EXTEND:
2966 *total = cost2;
2967 return true;
2968
2969 case MULT:
2970 {
2971 op0 = XEXP (x, 0);
2972 op1 = XEXP (x, 1);
2973 if (GET_CODE (op0) == GET_CODE (op1)
2974 && (GET_CODE (op0) == ZERO_EXTEND
2975 || GET_CODE (op0) == SIGN_EXTEND))
2976 {
2977 *total = COSTS_N_INSNS (1);
2978 op0 = XEXP (op0, 0);
2979 op1 = XEXP (op1, 0);
2980 }
2981 else if (!speed)
2982 *total = COSTS_N_INSNS (1);
2983 else
2984 *total = COSTS_N_INSNS (3);
2985
2986 if (GET_CODE (op0) != REG
2987 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
2988 *total += rtx_cost (op0, mode, MULT, 0, speed);
2989 if (GET_CODE (op1) != REG
2990 && (GET_CODE (op1) != SUBREG || GET_CODE (SUBREG_REG (op1)) != REG))
2991 *total += rtx_cost (op1, mode, MULT, 1, speed);
2992 }
2993 return true;
2994
2995 case UDIV:
2996 case UMOD:
2997 *total = COSTS_N_INSNS (32);
2998 return true;
2999
3000 case VEC_CONCAT:
3001 case VEC_SELECT:
3002 if (outer_code == SET)
3003 *total = cost2;
3004 return true;
3005
3006 default:
3007 return false;
3008 }
3009 }
3010 \f
3011 /* Used for communication between {push,pop}_multiple_operation (which
3012 we use not only as a predicate) and the corresponding output functions. */
3013 static int first_preg_to_save, first_dreg_to_save;
3014 static int n_regs_to_save;
3015
3016 int
3017 analyze_push_multiple_operation (rtx op)
3018 {
3019 int lastdreg = 8, lastpreg = 6;
3020 int i, group;
3021
3022 first_preg_to_save = lastpreg;
3023 first_dreg_to_save = lastdreg;
3024 for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
3025 {
3026 rtx t = XVECEXP (op, 0, i);
3027 rtx src, dest;
3028 int regno;
3029
3030 if (GET_CODE (t) != SET)
3031 return 0;
3032
3033 src = SET_SRC (t);
3034 dest = SET_DEST (t);
3035 if (GET_CODE (dest) != MEM || ! REG_P (src))
3036 return 0;
3037 dest = XEXP (dest, 0);
3038 if (GET_CODE (dest) != PLUS
3039 || ! REG_P (XEXP (dest, 0))
3040 || REGNO (XEXP (dest, 0)) != REG_SP
3041 || GET_CODE (XEXP (dest, 1)) != CONST_INT
3042 || INTVAL (XEXP (dest, 1)) != -i * 4)
3043 return 0;
3044
3045 regno = REGNO (src);
3046 if (group == 0)
3047 {
3048 if (D_REGNO_P (regno))
3049 {
3050 group = 1;
3051 first_dreg_to_save = lastdreg = regno - REG_R0;
3052 }
3053 else if (regno >= REG_P0 && regno <= REG_P7)
3054 {
3055 group = 2;
3056 first_preg_to_save = lastpreg = regno - REG_P0;
3057 }
3058 else
3059 return 0;
3060
3061 continue;
3062 }
3063
3064 if (group == 1)
3065 {
3066 if (regno >= REG_P0 && regno <= REG_P7)
3067 {
3068 group = 2;
3069 first_preg_to_save = lastpreg = regno - REG_P0;
3070 }
3071 else if (regno != REG_R0 + lastdreg + 1)
3072 return 0;
3073 else
3074 lastdreg++;
3075 }
3076 else if (group == 2)
3077 {
3078 if (regno != REG_P0 + lastpreg + 1)
3079 return 0;
3080 lastpreg++;
3081 }
3082 }
3083 n_regs_to_save = 8 - first_dreg_to_save + 6 - first_preg_to_save;
3084 return 1;
3085 }
3086
3087 int
3088 analyze_pop_multiple_operation (rtx op)
3089 {
3090 int lastdreg = 8, lastpreg = 6;
3091 int i, group;
3092
3093 for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
3094 {
3095 rtx t = XVECEXP (op, 0, i);
3096 rtx src, dest;
3097 int regno;
3098
3099 if (GET_CODE (t) != SET)
3100 return 0;
3101
3102 src = SET_SRC (t);
3103 dest = SET_DEST (t);
3104 if (GET_CODE (src) != MEM || ! REG_P (dest))
3105 return 0;
3106 src = XEXP (src, 0);
3107
3108 if (i == 1)
3109 {
3110 if (! REG_P (src) || REGNO (src) != REG_SP)
3111 return 0;
3112 }
3113 else if (GET_CODE (src) != PLUS
3114 || ! REG_P (XEXP (src, 0))
3115 || REGNO (XEXP (src, 0)) != REG_SP
3116 || GET_CODE (XEXP (src, 1)) != CONST_INT
3117 || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
3118 return 0;
3119
3120 regno = REGNO (dest);
3121 if (group == 0)
3122 {
3123 if (regno == REG_R7)
3124 {
3125 group = 1;
3126 lastdreg = 7;
3127 }
3128 else if (regno != REG_P0 + lastpreg - 1)
3129 return 0;
3130 else
3131 lastpreg--;
3132 }
3133 else if (group == 1)
3134 {
3135 if (regno != REG_R0 + lastdreg - 1)
3136 return 0;
3137 else
3138 lastdreg--;
3139 }
3140 }
3141 first_dreg_to_save = lastdreg;
3142 first_preg_to_save = lastpreg;
3143 n_regs_to_save = 8 - first_dreg_to_save + 6 - first_preg_to_save;
3144 return 1;
3145 }
3146
3147 /* Emit assembly code for one multi-register push described by INSN, with
3148 operands in OPERANDS. */
3149
3150 void
3151 output_push_multiple (rtx insn, rtx *operands)
3152 {
3153 char buf[80];
3154 int ok;
3155
3156 /* Validate the insn again, and compute first_[dp]reg_to_save. */
3157 ok = analyze_push_multiple_operation (PATTERN (insn));
3158 gcc_assert (ok);
3159
3160 if (first_dreg_to_save == 8)
3161 sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
3162 else if (first_preg_to_save == 6)
3163 sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
3164 else
3165 sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
3166 first_dreg_to_save, first_preg_to_save);
3167
3168 output_asm_insn (buf, operands);
3169 }
3170
3171 /* Emit assembly code for one multi-register pop described by INSN, with
3172 operands in OPERANDS. */
3173
3174 void
3175 output_pop_multiple (rtx insn, rtx *operands)
3176 {
3177 char buf[80];
3178 int ok;
3179
3180 /* Validate the insn again, and compute first_[dp]reg_to_save. */
3181 ok = analyze_pop_multiple_operation (PATTERN (insn));
3182 gcc_assert (ok);
3183
3184 if (first_dreg_to_save == 8)
3185 sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
3186 else if (first_preg_to_save == 6)
3187 sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
3188 else
3189 sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
3190 first_dreg_to_save, first_preg_to_save);
3191
3192 output_asm_insn (buf, operands);
3193 }
3194
3195 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE. */
3196
3197 static void
3198 single_move_for_cpymem (rtx dst, rtx src, machine_mode mode, HOST_WIDE_INT offset)
3199 {
3200 rtx scratch = gen_reg_rtx (mode);
3201 rtx srcmem, dstmem;
3202
3203 srcmem = adjust_address_nv (src, mode, offset);
3204 dstmem = adjust_address_nv (dst, mode, offset);
3205 emit_move_insn (scratch, srcmem);
3206 emit_move_insn (dstmem, scratch);
3207 }
3208
3209 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
3210 alignment ALIGN_EXP. Return true if successful, false if we should fall
3211 back on a different method. */
3212
3213 bool
3214 bfin_expand_cpymem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
3215 {
3216 rtx srcreg, destreg, countreg;
3217 HOST_WIDE_INT align = 0;
3218 unsigned HOST_WIDE_INT count = 0;
3219
3220 if (GET_CODE (align_exp) == CONST_INT)
3221 align = INTVAL (align_exp);
3222 if (GET_CODE (count_exp) == CONST_INT)
3223 {
3224 count = INTVAL (count_exp);
3225 #if 0
3226 if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
3227 return false;
3228 #endif
3229 }
3230
3231 /* If optimizing for size, only do single copies inline. */
3232 if (optimize_size)
3233 {
3234 if (count == 2 && align < 2)
3235 return false;
3236 if (count == 4 && align < 4)
3237 return false;
3238 if (count != 1 && count != 2 && count != 4)
3239 return false;
3240 }
3241 if (align < 2 && count != 1)
3242 return false;
3243
3244 destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
3245 if (destreg != XEXP (dst, 0))
3246 dst = replace_equiv_address_nv (dst, destreg);
3247 srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
3248 if (srcreg != XEXP (src, 0))
3249 src = replace_equiv_address_nv (src, srcreg);
3250
3251 if (count != 0 && align >= 2)
3252 {
3253 unsigned HOST_WIDE_INT offset = 0;
3254
3255 if (align >= 4)
3256 {
3257 if ((count & ~3) == 4)
3258 {
3259 single_move_for_cpymem (dst, src, SImode, offset);
3260 offset = 4;
3261 }
3262 else if (count & ~3)
3263 {
3264 HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
3265 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3266
3267 emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
3268 cfun->machine->has_loopreg_clobber = true;
3269 }
3270 if (count & 2)
3271 {
3272 single_move_for_cpymem (dst, src, HImode, offset);
3273 offset += 2;
3274 }
3275 }
3276 else
3277 {
3278 if ((count & ~1) == 2)
3279 {
3280 single_move_for_cpymem (dst, src, HImode, offset);
3281 offset = 2;
3282 }
3283 else if (count & ~1)
3284 {
3285 HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
3286 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3287
3288 emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
3289 cfun->machine->has_loopreg_clobber = true;
3290 }
3291 }
3292 if (count & 1)
3293 {
3294 single_move_for_cpymem (dst, src, QImode, offset);
3295 }
3296 return true;
3297 }
3298 return false;
3299 }
3300 \f
3301 /* Compute the alignment for a local variable.
3302 TYPE is the data type, and ALIGN is the alignment that
3303 the object would ordinarily have. The value of this macro is used
3304 instead of that alignment to align the object. */
3305
3306 unsigned
3307 bfin_local_alignment (tree type, unsigned align)
3308 {
3309 /* Increasing alignment for (relatively) big types allows the builtin
3310 memcpy can use 32 bit loads/stores. */
3311 if (TYPE_SIZE (type)
3312 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
3313 && wi::gtu_p (wi::to_wide (TYPE_SIZE (type)), 8)
3314 && align < 32)
3315 return 32;
3316 return align;
3317 }
3318 \f
3319 /* Implement TARGET_SCHED_ISSUE_RATE. */
3320
3321 static int
3322 bfin_issue_rate (void)
3323 {
3324 return 3;
3325 }
3326
3327 static int
3328 bfin_adjust_cost (rtx_insn *insn, int dep_type, rtx_insn *dep_insn, int cost,
3329 unsigned int)
3330 {
3331 enum attr_type dep_insn_type;
3332 int dep_insn_code_number;
3333
3334 /* Anti and output dependencies have zero cost. */
3335 if (dep_type != 0)
3336 return 0;
3337
3338 dep_insn_code_number = recog_memoized (dep_insn);
3339
3340 /* If we can't recognize the insns, we can't really do anything. */
3341 if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
3342 return cost;
3343
3344 dep_insn_type = get_attr_type (dep_insn);
3345
3346 if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)
3347 {
3348 rtx pat = PATTERN (dep_insn);
3349 rtx dest, src;
3350
3351 if (GET_CODE (pat) == PARALLEL)
3352 pat = XVECEXP (pat, 0, 0);
3353 dest = SET_DEST (pat);
3354 src = SET_SRC (pat);
3355 if (! ADDRESS_REGNO_P (REGNO (dest))
3356 || ! (MEM_P (src) || D_REGNO_P (REGNO (src))))
3357 return cost;
3358 return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);
3359 }
3360
3361 return cost;
3362 }
3363 \f
3364 /* This function acts like NEXT_INSN, but is aware of three-insn bundles and
3365 skips all subsequent parallel instructions if INSN is the start of such
3366 a group. */
3367 static rtx_insn *
3368 find_next_insn_start (rtx_insn *insn)
3369 {
3370 if (GET_MODE (insn) == SImode)
3371 {
3372 while (GET_MODE (insn) != QImode)
3373 insn = NEXT_INSN (insn);
3374 }
3375 return NEXT_INSN (insn);
3376 }
3377
3378 /* This function acts like PREV_INSN, but is aware of three-insn bundles and
3379 skips all subsequent parallel instructions if INSN is the start of such
3380 a group. */
3381 static rtx_insn *
3382 find_prev_insn_start (rtx_insn *insn)
3383 {
3384 insn = PREV_INSN (insn);
3385 gcc_assert (GET_MODE (insn) != SImode);
3386 if (GET_MODE (insn) == QImode)
3387 {
3388 while (GET_MODE (PREV_INSN (insn)) == SImode)
3389 insn = PREV_INSN (insn);
3390 }
3391 return insn;
3392 }
3393 \f
3394 /* Implement TARGET_CAN_USE_DOLOOP_P. */
3395
3396 static bool
3397 bfin_can_use_doloop_p (const widest_int &, const widest_int &iterations_max,
3398 unsigned int, bool)
3399 {
3400 /* Due to limitations in the hardware (an initial loop count of 0
3401 does not loop 2^32 times) we must avoid to generate a hardware
3402 loops when we cannot rule out this case. */
3403 return (wi::ltu_p (iterations_max, 0xFFFFFFFF));
3404 }
3405
3406 /* Increment the counter for the number of loop instructions in the
3407 current function. */
3408
3409 void
3410 bfin_hardware_loop (void)
3411 {
3412 cfun->machine->has_hardware_loops++;
3413 }
3414
3415 /* Maximum loop nesting depth. */
3416 #define MAX_LOOP_DEPTH 2
3417
3418 /* Maximum size of a loop. */
3419 #define MAX_LOOP_LENGTH 2042
3420
3421 /* Maximum distance of the LSETUP instruction from the loop start. */
3422 #define MAX_LSETUP_DISTANCE 30
3423
3424 /* Estimate the length of INSN conservatively. */
3425
3426 static int
3427 length_for_loop (rtx_insn *insn)
3428 {
3429 int length = 0;
3430 if (JUMP_P (insn) && any_condjump_p (insn) && !optimize_size)
3431 {
3432 if (ENABLE_WA_SPECULATIVE_SYNCS)
3433 length = 8;
3434 else if (ENABLE_WA_SPECULATIVE_LOADS)
3435 length = 6;
3436 }
3437 else if (LABEL_P (insn))
3438 {
3439 if (ENABLE_WA_SPECULATIVE_SYNCS)
3440 length = 4;
3441 }
3442
3443 if (NONDEBUG_INSN_P (insn))
3444 length += get_attr_length (insn);
3445
3446 return length;
3447 }
3448
3449 /* Optimize LOOP. */
3450
3451 static bool
3452 hwloop_optimize (hwloop_info loop)
3453 {
3454 basic_block bb;
3455 rtx_insn *insn, *last_insn;
3456 rtx loop_init, start_label, end_label;
3457 rtx iter_reg, scratchreg, scratch_init;
3458 rtx_insn *scratch_init_insn;
3459 rtx lc_reg, lt_reg, lb_reg;
3460 rtx seq_end;
3461 rtx_insn *seq;
3462 int length;
3463 bool clobber0, clobber1;
3464
3465 if (loop->depth > MAX_LOOP_DEPTH)
3466 {
3467 if (dump_file)
3468 fprintf (dump_file, ";; loop %d too deep\n", loop->loop_no);
3469 return false;
3470 }
3471
3472 /* Get the loop iteration register. */
3473 iter_reg = loop->iter_reg;
3474
3475 gcc_assert (REG_P (iter_reg));
3476
3477 scratchreg = NULL_RTX;
3478 scratch_init = iter_reg;
3479 scratch_init_insn = NULL;
3480 if (!PREG_P (iter_reg) && loop->incoming_src)
3481 {
3482 basic_block bb_in = loop->incoming_src;
3483 int i;
3484 for (i = REG_P0; i <= REG_P5; i++)
3485 if ((df_regs_ever_live_p (i)
3486 || (funkind (TREE_TYPE (current_function_decl)) == SUBROUTINE
3487 && call_used_or_fixed_reg_p (i)))
3488 && !REGNO_REG_SET_P (df_get_live_out (bb_in), i))
3489 {
3490 scratchreg = gen_rtx_REG (SImode, i);
3491 break;
3492 }
3493 for (insn = BB_END (bb_in); insn != BB_HEAD (bb_in);
3494 insn = PREV_INSN (insn))
3495 {
3496 rtx set;
3497 if (NOTE_P (insn) || BARRIER_P (insn))
3498 continue;
3499 set = single_set (insn);
3500 if (set && rtx_equal_p (SET_DEST (set), iter_reg))
3501 {
3502 if (CONSTANT_P (SET_SRC (set)))
3503 {
3504 scratch_init = SET_SRC (set);
3505 scratch_init_insn = insn;
3506 }
3507 break;
3508 }
3509 else if (reg_mentioned_p (iter_reg, PATTERN (insn)))
3510 break;
3511 }
3512 }
3513
3514 if (loop->incoming_src)
3515 {
3516 /* Make sure the predecessor is before the loop start label, as required by
3517 the LSETUP instruction. */
3518 length = 0;
3519 insn = BB_END (loop->incoming_src);
3520 /* If we have to insert the LSETUP before a jump, count that jump in the
3521 length. */
3522 if (vec_safe_length (loop->incoming) > 1
3523 || !(loop->incoming->last ()->flags & EDGE_FALLTHRU))
3524 {
3525 gcc_assert (JUMP_P (insn));
3526 insn = PREV_INSN (insn);
3527 }
3528
3529 for (; insn && insn != loop->start_label; insn = NEXT_INSN (insn))
3530 length += length_for_loop (insn);
3531
3532 if (!insn)
3533 {
3534 if (dump_file)
3535 fprintf (dump_file, ";; loop %d lsetup not before loop_start\n",
3536 loop->loop_no);
3537 return false;
3538 }
3539
3540 /* Account for the pop of a scratch register where necessary. */
3541 if (!PREG_P (iter_reg) && scratchreg == NULL_RTX
3542 && ENABLE_WA_LOAD_LCREGS)
3543 length += 2;
3544
3545 if (length > MAX_LSETUP_DISTANCE)
3546 {
3547 if (dump_file)
3548 fprintf (dump_file, ";; loop %d lsetup too far away\n", loop->loop_no);
3549 return false;
3550 }
3551 }
3552
3553 /* Check if start_label appears before loop_end and calculate the
3554 offset between them. We calculate the length of instructions
3555 conservatively. */
3556 length = 0;
3557 for (insn = loop->start_label;
3558 insn && insn != loop->loop_end;
3559 insn = NEXT_INSN (insn))
3560 length += length_for_loop (insn);
3561
3562 if (!insn)
3563 {
3564 if (dump_file)
3565 fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
3566 loop->loop_no);
3567 return false;
3568 }
3569
3570 loop->length = length;
3571 if (loop->length > MAX_LOOP_LENGTH)
3572 {
3573 if (dump_file)
3574 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
3575 return false;
3576 }
3577
3578 /* Scan all the blocks to make sure they don't use iter_reg. */
3579 if (loop->iter_reg_used || loop->iter_reg_used_outside)
3580 {
3581 if (dump_file)
3582 fprintf (dump_file, ";; loop %d uses iterator\n", loop->loop_no);
3583 return false;
3584 }
3585
3586 clobber0 = (TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC0)
3587 || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LB0)
3588 || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LT0));
3589 clobber1 = (TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC1)
3590 || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LB1)
3591 || TEST_HARD_REG_BIT (loop->regs_set_in_loop, REG_LT1));
3592 if (clobber0 && clobber1)
3593 {
3594 if (dump_file)
3595 fprintf (dump_file, ";; loop %d no loop reg available\n",
3596 loop->loop_no);
3597 return false;
3598 }
3599
3600 /* There should be an instruction before the loop_end instruction
3601 in the same basic block. And the instruction must not be
3602 - JUMP
3603 - CONDITIONAL BRANCH
3604 - CALL
3605 - CSYNC
3606 - SSYNC
3607 - Returns (RTS, RTN, etc.) */
3608
3609 bb = loop->tail;
3610 last_insn = find_prev_insn_start (loop->loop_end);
3611
3612 while (1)
3613 {
3614 for (; last_insn != BB_HEAD (bb);
3615 last_insn = find_prev_insn_start (last_insn))
3616 if (NONDEBUG_INSN_P (last_insn))
3617 break;
3618
3619 if (last_insn != BB_HEAD (bb))
3620 break;
3621
3622 if (single_pred_p (bb)
3623 && single_pred_edge (bb)->flags & EDGE_FALLTHRU
3624 && single_pred (bb) != ENTRY_BLOCK_PTR_FOR_FN (cfun))
3625 {
3626 bb = single_pred (bb);
3627 last_insn = BB_END (bb);
3628 continue;
3629 }
3630 else
3631 {
3632 last_insn = NULL;
3633 break;
3634 }
3635 }
3636
3637 if (!last_insn)
3638 {
3639 if (dump_file)
3640 fprintf (dump_file, ";; loop %d has no last instruction\n",
3641 loop->loop_no);
3642 return false;
3643 }
3644
3645 if (JUMP_P (last_insn) && !any_condjump_p (last_insn))
3646 {
3647 if (dump_file)
3648 fprintf (dump_file, ";; loop %d has bad last instruction\n",
3649 loop->loop_no);
3650 return false;
3651 }
3652 /* In all other cases, try to replace a bad last insn with a nop. */
3653 else if (JUMP_P (last_insn)
3654 || CALL_P (last_insn)
3655 || get_attr_type (last_insn) == TYPE_SYNC
3656 || get_attr_type (last_insn) == TYPE_CALL
3657 || get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI
3658 || recog_memoized (last_insn) == CODE_FOR_return_internal
3659 || GET_CODE (PATTERN (last_insn)) == ASM_INPUT
3660 || asm_noperands (PATTERN (last_insn)) >= 0)
3661 {
3662 if (loop->length + 2 > MAX_LOOP_LENGTH)
3663 {
3664 if (dump_file)
3665 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
3666 return false;
3667 }
3668 if (dump_file)
3669 fprintf (dump_file, ";; loop %d has bad last insn; replace with nop\n",
3670 loop->loop_no);
3671
3672 last_insn = emit_insn_after (gen_forced_nop (), last_insn);
3673 }
3674
3675 loop->last_insn = last_insn;
3676
3677 /* The loop is good for replacement. */
3678 start_label = loop->start_label;
3679 end_label = gen_label_rtx ();
3680 iter_reg = loop->iter_reg;
3681
3682 if (loop->depth == 1 && !clobber1)
3683 {
3684 lc_reg = gen_rtx_REG (SImode, REG_LC1);
3685 lb_reg = gen_rtx_REG (SImode, REG_LB1);
3686 lt_reg = gen_rtx_REG (SImode, REG_LT1);
3687 SET_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC1);
3688 }
3689 else
3690 {
3691 lc_reg = gen_rtx_REG (SImode, REG_LC0);
3692 lb_reg = gen_rtx_REG (SImode, REG_LB0);
3693 lt_reg = gen_rtx_REG (SImode, REG_LT0);
3694 SET_HARD_REG_BIT (loop->regs_set_in_loop, REG_LC0);
3695 }
3696
3697 loop->end_label = end_label;
3698
3699 /* Create a sequence containing the loop setup. */
3700 start_sequence ();
3701
3702 /* LSETUP only accepts P registers. If we have one, we can use it,
3703 otherwise there are several ways of working around the problem.
3704 If we're not affected by anomaly 312, we can load the LC register
3705 from any iteration register, and use LSETUP without initialization.
3706 If we've found a P scratch register that's not live here, we can
3707 instead copy the iter_reg into that and use an initializing LSETUP.
3708 If all else fails, push and pop P0 and use it as a scratch. */
3709 if (P_REGNO_P (REGNO (iter_reg)))
3710 {
3711 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
3712 lb_reg, end_label,
3713 lc_reg, iter_reg);
3714 seq_end = emit_insn (loop_init);
3715 }
3716 else if (!ENABLE_WA_LOAD_LCREGS && DPREG_P (iter_reg))
3717 {
3718 emit_insn (gen_movsi (lc_reg, iter_reg));
3719 loop_init = gen_lsetup_without_autoinit (lt_reg, start_label,
3720 lb_reg, end_label,
3721 lc_reg);
3722 seq_end = emit_insn (loop_init);
3723 }
3724 else if (scratchreg != NULL_RTX)
3725 {
3726 emit_insn (gen_movsi (scratchreg, scratch_init));
3727 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
3728 lb_reg, end_label,
3729 lc_reg, scratchreg);
3730 seq_end = emit_insn (loop_init);
3731 if (scratch_init_insn != NULL_RTX)
3732 delete_insn (scratch_init_insn);
3733 }
3734 else
3735 {
3736 rtx p0reg = gen_rtx_REG (SImode, REG_P0);
3737 rtx push = gen_frame_mem (SImode,
3738 gen_rtx_PRE_DEC (SImode, stack_pointer_rtx));
3739 rtx pop = gen_frame_mem (SImode,
3740 gen_rtx_POST_INC (SImode, stack_pointer_rtx));
3741 emit_insn (gen_movsi (push, p0reg));
3742 emit_insn (gen_movsi (p0reg, scratch_init));
3743 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
3744 lb_reg, end_label,
3745 lc_reg, p0reg);
3746 emit_insn (loop_init);
3747 seq_end = emit_insn (gen_movsi (p0reg, pop));
3748 if (scratch_init_insn != NULL_RTX)
3749 delete_insn (scratch_init_insn);
3750 }
3751
3752 if (dump_file)
3753 {
3754 fprintf (dump_file, ";; replacing loop %d initializer with\n",
3755 loop->loop_no);
3756 print_rtl_single (dump_file, loop_init);
3757 fprintf (dump_file, ";; replacing loop %d terminator with\n",
3758 loop->loop_no);
3759 print_rtl_single (dump_file, loop->loop_end);
3760 }
3761
3762 /* If the loop isn't entered at the top, also create a jump to the entry
3763 point. */
3764 if (!loop->incoming_src && loop->head != loop->incoming_dest)
3765 {
3766 rtx_insn *label = BB_HEAD (loop->incoming_dest);
3767 /* If we're jumping to the final basic block in the loop, and there's
3768 only one cheap instruction before the end (typically an increment of
3769 an induction variable), we can just emit a copy here instead of a
3770 jump. */
3771 if (loop->incoming_dest == loop->tail
3772 && next_real_insn (label) == last_insn
3773 && asm_noperands (last_insn) < 0
3774 && GET_CODE (PATTERN (last_insn)) == SET)
3775 {
3776 seq_end = emit_insn (copy_rtx (PATTERN (last_insn)));
3777 }
3778 else
3779 {
3780 rtx_insn *ret = emit_jump_insn (gen_jump (label));
3781 JUMP_LABEL (ret) = label;
3782 LABEL_NUSES (label)++;
3783 seq_end = emit_barrier ();
3784 }
3785 }
3786
3787 seq = get_insns ();
3788 end_sequence ();
3789
3790 if (loop->incoming_src)
3791 {
3792 rtx_insn *prev = BB_END (loop->incoming_src);
3793 if (vec_safe_length (loop->incoming) > 1
3794 || !(loop->incoming->last ()->flags & EDGE_FALLTHRU))
3795 {
3796 gcc_assert (JUMP_P (prev));
3797 prev = PREV_INSN (prev);
3798 emit_insn_after (seq, prev);
3799 }
3800 else
3801 {
3802 emit_insn_after (seq, prev);
3803 BB_END (loop->incoming_src) = prev;
3804 basic_block new_bb = create_basic_block (seq, seq_end,
3805 loop->head->prev_bb);
3806 edge e = loop->incoming->last ();
3807 gcc_assert (e->flags & EDGE_FALLTHRU);
3808 redirect_edge_succ (e, new_bb);
3809 make_edge (new_bb, loop->head, 0);
3810 }
3811 }
3812 else
3813 {
3814 basic_block new_bb;
3815 edge e;
3816 edge_iterator ei;
3817
3818 if (flag_checking && loop->head != loop->incoming_dest)
3819 {
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));
3827 }
3828
3829 emit_insn_before (seq, BB_HEAD (loop->head));
3830 seq = emit_label_before (gen_label_rtx (), seq);
3831
3832 new_bb = create_basic_block (seq, seq_end, loop->head->prev_bb);
3833 FOR_EACH_EDGE (e, ei, loop->incoming)
3834 {
3835 if (!(e->flags & EDGE_FALLTHRU)
3836 || e->dest != loop->head)
3837 redirect_edge_and_branch_force (e, new_bb);
3838 else
3839 redirect_edge_succ (e, new_bb);
3840 }
3841 e = make_edge (new_bb, loop->head, 0);
3842 }
3843
3844 delete_insn (loop->loop_end);
3845 /* Insert the loop end label before the last instruction of the loop. */
3846 emit_label_before (as_a <rtx_code_label *> (loop->end_label),
3847 loop->last_insn);
3848
3849 return true;
3850 }
3851
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)
3857 {
3858 rtx insn = loop->loop_end;
3859
3860 if (DPREG_P (loop->iter_reg))
3861 {
3862 /* If loop->iter_reg is a DREG or PREG, we can split it here
3863 without scratch register. */
3864 rtx insn, test;
3865
3866 emit_insn_before (gen_addsi3 (loop->iter_reg,
3867 loop->iter_reg,
3868 constm1_rtx),
3869 loop->loop_end);
3870
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);
3876
3877 JUMP_LABEL (insn) = loop->start_label;
3878 LABEL_NUSES (loop->start_label)++;
3879 delete_insn (loop->loop_end);
3880 }
3881 else
3882 {
3883 splitting_loops = 1;
3884 try_split (PATTERN (insn), safe_as_a <rtx_insn *> (insn), 1);
3885 splitting_loops = 0;
3886 }
3887 }
3888
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. */
3892
3893 static rtx
3894 hwloop_pattern_reg (rtx_insn *insn)
3895 {
3896 rtx reg;
3897
3898 if (!JUMP_P (insn) || recog_memoized (insn) != CODE_FOR_loop_end)
3899 return NULL_RTX;
3900
3901 reg = SET_DEST (XVECEXP (PATTERN (insn), 0, 1));
3902 if (!REG_P (reg))
3903 return NULL_RTX;
3904 return reg;
3905 }
3906
3907 static struct hw_doloop_hooks bfin_doloop_hooks =
3908 {
3909 hwloop_pattern_reg,
3910 hwloop_optimize,
3911 hwloop_fail
3912 };
3913
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. */
3917
3918 static void
3919 bfin_reorg_loops (void)
3920 {
3921 reorg_loops (true, &bfin_doloop_hooks);
3922 }
3923 \f
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])
3928 {
3929 gcc_assert (slot[1] != NULL_RTX);
3930
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;
3935
3936 /* Verify that we really can do the multi-issue. */
3937 if (slot[0])
3938 {
3939 rtx_insn *t = NEXT_INSN (slot[0]);
3940 while (t != slot[1])
3941 {
3942 if (! NOTE_P (t) || NOTE_KIND (t) != NOTE_INSN_DELETED)
3943 return false;
3944 t = NEXT_INSN (t);
3945 }
3946 }
3947 if (slot[2])
3948 {
3949 rtx_insn *t = NEXT_INSN (slot[1]);
3950 while (t != slot[2])
3951 {
3952 if (! NOTE_P (t) || NOTE_KIND (t) != NOTE_INSN_DELETED)
3953 return false;
3954 t = NEXT_INSN (t);
3955 }
3956 }
3957
3958 if (slot[0] == NULL_RTX)
3959 {
3960 slot[0] = emit_insn_before (gen_mnop (), slot[1]);
3961 df_insn_rescan (slot[0]);
3962 }
3963 if (slot[2] == NULL_RTX)
3964 {
3965 slot[2] = emit_insn_after (gen_forced_nop (), slot[1]);
3966 df_insn_rescan (slot[2]);
3967 }
3968
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]);
3976
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;
3983 }
3984
3985 /* Go through all insns, and use the information generated during scheduling
3986 to generate SEQUENCEs to represent bundles of instructions issued
3987 simultaneously. */
3988
3989 static void
3990 bfin_gen_bundles (void)
3991 {
3992 basic_block bb;
3993 FOR_EACH_BB_FN (bb, cfun)
3994 {
3995 rtx_insn *insn, *next;
3996 rtx_insn *slot[3];
3997 int n_filled = 0;
3998
3999 slot[0] = slot[1] = slot[2] = NULL;
4000 for (insn = BB_HEAD (bb);; insn = next)
4001 {
4002 int at_end;
4003 rtx_insn *delete_this = NULL;
4004
4005 if (NONDEBUG_INSN_P (insn))
4006 {
4007 enum attr_type type = get_attr_type (insn);
4008
4009 if (type == TYPE_STALL)
4010 {
4011 gcc_assert (n_filled == 0);
4012 delete_this = insn;
4013 }
4014 else
4015 {
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++;
4023 }
4024 }
4025
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))
4031 {
4032 insn = next;
4033 next = NEXT_INSN (insn);
4034 }
4035
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))
4039 {
4040 if ((n_filled < 2
4041 || !gen_one_bundle (slot))
4042 && slot[0] != NULL_RTX)
4043 {
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)
4048 {
4049 SET_SRC (pat) = XVECEXP (SET_SRC (pat), 0, 0);
4050 INSN_CODE (slot[0]) = -1;
4051 df_insn_rescan (slot[0]);
4052 }
4053 }
4054 n_filled = 0;
4055 slot[0] = slot[1] = slot[2] = NULL;
4056 }
4057 if (delete_this != NULL_RTX)
4058 delete_insn (delete_this);
4059 if (at_end)
4060 break;
4061 }
4062 }
4063 }
4064
4065 /* Ensure that no var tracking notes are emitted in the middle of a
4066 three-instruction bundle. */
4067
4068 static void
4069 reorder_var_tracking_notes (void)
4070 {
4071 basic_block bb;
4072 FOR_EACH_BB_FN (bb, cfun)
4073 {
4074 rtx_insn *insn, *next;
4075 rtx_insn *queue = NULL;
4076 bool in_bundle = false;
4077
4078 for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = next)
4079 {
4080 next = NEXT_INSN (insn);
4081
4082 if (INSN_P (insn))
4083 {
4084 /* Emit queued up notes at the last instruction of a bundle. */
4085 if (GET_MODE (insn) == QImode)
4086 {
4087 while (queue)
4088 {
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;
4095 }
4096 in_bundle = false;
4097 }
4098 else if (GET_MODE (insn) == SImode)
4099 in_bundle = true;
4100 }
4101 else if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION)
4102 {
4103 if (in_bundle)
4104 {
4105 rtx_insn *prev = PREV_INSN (insn);
4106 SET_PREV_INSN (next) = prev;
4107 SET_NEXT_INSN (prev) = next;
4108
4109 SET_PREV_INSN (insn) = queue;
4110 queue = insn;
4111 }
4112 }
4113 }
4114 }
4115 }
4116 \f
4117 /* On some silicon revisions, functions shorter than a certain number of cycles
4118 can cause unpredictable behavior. Work around this by adding NOPs as
4119 needed. */
4120 static void
4121 workaround_rts_anomaly (void)
4122 {
4123 rtx_insn *insn, *first_insn = NULL;
4124 int cycles = 4;
4125
4126 if (! ENABLE_WA_RETS)
4127 return;
4128
4129 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4130 {
4131 rtx pat;
4132
4133 if (BARRIER_P (insn))
4134 return;
4135
4136 if (NOTE_P (insn) || LABEL_P (insn))
4137 continue;
4138
4139 if (JUMP_TABLE_DATA_P (insn))
4140 continue;
4141
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;
4149
4150 if (CALL_P (insn))
4151 return;
4152
4153 if (JUMP_P (insn))
4154 {
4155 if (recog_memoized (insn) == CODE_FOR_return_internal)
4156 break;
4157
4158 /* Nothing to worry about for direct jumps. */
4159 if (!any_condjump_p (insn))
4160 return;
4161 if (cycles <= 1)
4162 return;
4163 cycles--;
4164 }
4165 else if (INSN_P (insn))
4166 {
4167 rtx pat = PATTERN (insn);
4168 int this_cycles = 1;
4169
4170 if (GET_CODE (pat) == PARALLEL)
4171 {
4172 if (analyze_push_multiple_operation (pat)
4173 || analyze_pop_multiple_operation (pat))
4174 this_cycles = n_regs_to_save;
4175 }
4176 else
4177 {
4178 int icode = recog_memoized (insn);
4179
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;
4186 }
4187 if (this_cycles >= cycles)
4188 return;
4189
4190 cycles -= this_cycles;
4191 }
4192 }
4193 while (cycles > 0)
4194 {
4195 emit_insn_before (gen_nop (), first_insn);
4196 cycles--;
4197 }
4198 }
4199
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. */
4203
4204 static enum attr_type
4205 type_for_anomaly (rtx_insn *insn)
4206 {
4207 rtx pat = PATTERN (insn);
4208 if (rtx_sequence *seq = dyn_cast <rtx_sequence *> (pat))
4209 {
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;
4218 }
4219 else
4220 return get_attr_type (insn);
4221 }
4222
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)
4227 {
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)
4235 {
4236 mem = XEXP (mem, 1);
4237 if (GET_CODE (mem) == CONST_INT && INTVAL (mem) > 0)
4238 return true;
4239 }
4240 return false;
4241 }
4242
4243 /* Return nonzero if INSN contains any loads that may trap. */
4244
4245 static bool
4246 trapping_loads_p (rtx_insn *insn, int np_reg, bool after_np_branch)
4247 {
4248 rtx mem = SET_SRC (single_set (insn));
4249
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));
4254 }
4255
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)
4261 {
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;
4275 }
4276
4277 /* Determine whether PAT is an indirect call pattern. */
4278 static bool
4279 indirect_call_p (rtx pat)
4280 {
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);
4289
4290 return REG_P (pat);
4291 }
4292
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.
4299 */
4300 int np_check_regno = -1;
4301 bool np_after_branch = false;
4302
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)
4307 {
4308 if (REG_P (x) && (REGNO (x) == REG_CC || (int) REGNO (x) == np_check_regno))
4309 np_check_regno = -1;
4310 }
4311
4312 static void
4313 workaround_speculation (void)
4314 {
4315 rtx_insn *insn, *next;
4316 rtx_insn *last_condjump = NULL;
4317 int cycles_since_jump = INT_MAX;
4318 int delay_added = 0;
4319
4320 if (! ENABLE_WA_SPECULATIVE_LOADS && ! ENABLE_WA_SPECULATIVE_SYNCS
4321 && ! ENABLE_WA_INDIRECT_CALLS)
4322 return;
4323
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)
4327 {
4328 rtx pat;
4329 int delay_needed = 0;
4330
4331 next = find_next_insn_start (insn);
4332
4333 if (NOTE_P (insn) || BARRIER_P (insn))
4334 continue;
4335 if (JUMP_TABLE_DATA_P (insn))
4336 continue;
4337
4338 if (LABEL_P (insn))
4339 {
4340 np_check_regno = -1;
4341 continue;
4342 }
4343
4344 pat = PATTERN (insn);
4345 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER)
4346 continue;
4347
4348 if (GET_CODE (pat) == ASM_INPUT || asm_noperands (pat) >= 0)
4349 {
4350 np_check_regno = -1;
4351 continue;
4352 }
4353
4354 if (JUMP_P (insn))
4355 {
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)
4360 {
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;
4365 }
4366 if (any_condjump_p (insn)
4367 && ! cbranch_predicted_taken_p (insn))
4368 {
4369 last_condjump = insn;
4370 delay_added = 0;
4371 cycles_since_jump = 0;
4372 }
4373 else
4374 cycles_since_jump = INT_MAX;
4375 }
4376 else if (CALL_P (insn))
4377 {
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)
4382 {
4383 delay_needed = 3;
4384 }
4385 }
4386 else if (NONDEBUG_INSN_P (insn))
4387 {
4388 rtx_insn *load_insn = find_load (insn);
4389 enum attr_type type = type_for_anomaly (insn);
4390
4391 if (cycles_since_jump < INT_MAX)
4392 cycles_since_jump++;
4393
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)
4398 {
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)
4403 {
4404 np_check_regno = REGNO (XEXP (src, 0));
4405 np_after_branch = false;
4406 }
4407 else
4408 np_check_regno = -1;
4409 }
4410
4411 if (load_insn && ENABLE_WA_SPECULATIVE_LOADS)
4412 {
4413 if (trapping_loads_p (load_insn, np_check_regno,
4414 np_after_branch))
4415 delay_needed = 4;
4416 }
4417 else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS)
4418 delay_needed = 3;
4419
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)
4423 {
4424 note_stores (insn, note_np_check_stores, NULL);
4425 if (np_check_regno != -1)
4426 {
4427 if (find_regno_note (insn, REG_INC, np_check_regno))
4428 np_check_regno = -1;
4429 }
4430 }
4431
4432 }
4433
4434 if (delay_needed > cycles_since_jump
4435 && (delay_needed - cycles_since_jump) > delay_added)
4436 {
4437 rtx pat1;
4438 int num_clobbers;
4439 rtx *op = recog_data.operand;
4440
4441 delay_needed -= cycles_since_jump;
4442
4443 extract_insn (last_condjump);
4444 if (optimize_size)
4445 {
4446 pat1 = gen_cbranch_predicted_taken (op[0], op[1], op[2],
4447 op[3]);
4448 cycles_since_jump = INT_MAX;
4449 }
4450 else
4451 {
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;
4458 }
4459 PATTERN (last_condjump) = pat1;
4460 INSN_CODE (last_condjump) = recog (pat1, insn, &num_clobbers);
4461 }
4462 if (CALL_P (insn))
4463 {
4464 cycles_since_jump = INT_MAX;
4465 delay_added = 0;
4466 }
4467 }
4468
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))
4472 {
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)))
4478 {
4479 rtx_insn *target = JUMP_LABEL_AS_INSN (insn);
4480 rtx_insn *label = target;
4481 rtx_insn *next_tgt;
4482
4483 cycles_since_jump = 0;
4484 for (; target && cycles_since_jump < 3; target = next_tgt)
4485 {
4486 rtx pat;
4487
4488 next_tgt = find_next_insn_start (target);
4489
4490 if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
4491 continue;
4492
4493 if (JUMP_TABLE_DATA_P (target))
4494 continue;
4495
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;
4501
4502 if (NONDEBUG_INSN_P (target))
4503 {
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++;
4509
4510 if (load_insn && ENABLE_WA_SPECULATIVE_LOADS)
4511 {
4512 if (trapping_loads_p (load_insn, -1, false))
4513 delay_needed = 2;
4514 }
4515 else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS)
4516 delay_needed = 2;
4517
4518 if (delay_needed > cycles_since_jump)
4519 {
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)
4527 {
4528 rtx x;
4529 HOST_WIDE_INT v;
4530
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);
4539 }
4540 while (delay_needed-- > 0)
4541 emit_insn_after (gen_nop (), label);
4542 break;
4543 }
4544 }
4545 }
4546 }
4547 }
4548 }
4549
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)
4557 {
4558 rtx_insn *insn;
4559
4560 if (! ENABLE_WA_SPECULATIVE_LOADS && ! ENABLE_WA_SPECULATIVE_SYNCS
4561 && ! ENABLE_WA_INDIRECT_CALLS)
4562 return;
4563
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))
4567 {
4568 rtx pat;
4569
4570 if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
4571 continue;
4572 if (JUMP_TABLE_DATA_P (insn))
4573 continue;
4574
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;
4580
4581 if (JUMP_P (insn))
4582 {
4583 if (any_condjump_p (insn)
4584 && !cbranch_predicted_taken_p (insn))
4585 {
4586 rtx_insn *n = next_real_insn (insn);
4587 emit_insn_before (gen_stall (GEN_INT (3)), n);
4588 }
4589 }
4590 }
4591
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))
4595 {
4596 if (JUMP_P (insn)
4597 && any_condjump_p (insn)
4598 && (cbranch_predicted_taken_p (insn)))
4599 {
4600 rtx_insn *target = JUMP_LABEL_AS_INSN (insn);
4601 rtx_insn *next = next_real_insn (target);
4602
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);
4607 }
4608 }
4609 }
4610
4611 /* We use the machine specific reorg pass for emitting CSYNC instructions
4612 after conditional branches as needed.
4613
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).
4626
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. */
4630
4631 static void
4632 bfin_reorg (void)
4633 {
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 ();
4637
4638 if (flag_schedule_insns_after_reload)
4639 {
4640 splitting_for_sched = 1;
4641 split_all_insns ();
4642 splitting_for_sched = 0;
4643
4644 add_sched_insns_for_speculation ();
4645
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);
4653
4654 /* Examine the schedule and insert nops as necessary for 64-bit parallel
4655 instructions. */
4656 bfin_gen_bundles ();
4657 }
4658
4659 df_analyze ();
4660
4661 /* Doloop optimization */
4662 if (cfun->machine->has_hardware_loops)
4663 bfin_reorg_loops ();
4664
4665 workaround_speculation ();
4666
4667 if (flag_var_tracking)
4668 {
4669 timevar_push (TV_VAR_TRACKING);
4670 variable_tracking_main ();
4671 reorder_var_tracking_notes ();
4672 timevar_pop (TV_VAR_TRACKING);
4673 }
4674
4675 df_finish_pass (false);
4676
4677 workaround_rts_anomaly ();
4678 }
4679 \f
4680 /* Handle interrupt_handler, exception_handler and nmi_handler function
4681 attributes; arguments as in struct attribute_spec.handler. */
4682
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)
4688 {
4689 tree x = *node;
4690 if (TREE_CODE (x) == FUNCTION_DECL)
4691 x = TREE_TYPE (x);
4692
4693 if (TREE_CODE (x) != FUNCTION_TYPE)
4694 {
4695 warning (OPT_Wattributes, "%qE attribute only applies to functions",
4696 name);
4697 *no_add_attrs = true;
4698 }
4699 else if (funkind (x) != SUBROUTINE)
4700 error ("multiple function type attributes specified");
4701
4702 return NULL_TREE;
4703 }
4704
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). */
4708
4709 static int
4710 bfin_comp_type_attributes (const_tree type1, const_tree type2)
4711 {
4712 e_funkind kind1, kind2;
4713
4714 if (TREE_CODE (type1) != FUNCTION_TYPE)
4715 return 1;
4716
4717 kind1 = funkind (type1);
4718 kind2 = funkind (type2);
4719
4720 if (kind1 != kind2)
4721 return 0;
4722
4723 /* Check for mismatched modifiers */
4724 if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
4725 != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
4726 return 0;
4727
4728 if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
4729 != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
4730 return 0;
4731
4732 if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
4733 != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
4734 return 0;
4735
4736 if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1))
4737 != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2)))
4738 return 0;
4739
4740 return 1;
4741 }
4742
4743 /* Handle a "longcall" or "shortcall" attribute; arguments as in
4744 struct attribute_spec.handler. */
4745
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)
4751 {
4752 if (TREE_CODE (*node) != FUNCTION_TYPE
4753 && TREE_CODE (*node) != FIELD_DECL
4754 && TREE_CODE (*node) != TYPE_DECL)
4755 {
4756 warning (OPT_Wattributes, "%qE attribute only applies to functions",
4757 name);
4758 *no_add_attrs = true;
4759 }
4760
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))))
4765 {
4766 warning (OPT_Wattributes,
4767 "cannot apply both %<longcall%> and %<shortcall%> attributes "
4768 "to the same function");
4769 *no_add_attrs = true;
4770 }
4771
4772 return NULL_TREE;
4773 }
4774
4775 /* Handle a "l1_text" attribute; arguments as in
4776 struct attribute_spec.handler. */
4777
4778 static tree
4779 bfin_handle_l1_text_attribute (tree *node, tree name, tree ARG_UNUSED (args),
4780 int ARG_UNUSED (flags), bool *no_add_attrs)
4781 {
4782 tree decl = *node;
4783
4784 if (TREE_CODE (decl) != FUNCTION_DECL)
4785 {
4786 error ("%qE attribute only applies to functions",
4787 name);
4788 *no_add_attrs = true;
4789 }
4790
4791 /* The decl may have already been given a section attribute
4792 from a previous declaration. Ensure they match. */
4793 else if (DECL_SECTION_NAME (decl) != NULL
4794 && strcmp (DECL_SECTION_NAME (decl),
4795 ".l1.text") != 0)
4796 {
4797 error ("section of %q+D conflicts with previous declaration",
4798 decl);
4799 *no_add_attrs = true;
4800 }
4801 else
4802 set_decl_section_name (decl, ".l1.text");
4803
4804 return NULL_TREE;
4805 }
4806
4807 /* Handle a "l1_data", "l1_data_A" or "l1_data_B" attribute;
4808 arguments as in struct attribute_spec.handler. */
4809
4810 static tree
4811 bfin_handle_l1_data_attribute (tree *node, tree name, tree ARG_UNUSED (args),
4812 int ARG_UNUSED (flags), bool *no_add_attrs)
4813 {
4814 tree decl = *node;
4815
4816 if (TREE_CODE (decl) != VAR_DECL)
4817 {
4818 error ("%qE attribute only applies to variables",
4819 name);
4820 *no_add_attrs = true;
4821 }
4822 else if (current_function_decl != NULL_TREE
4823 && !TREE_STATIC (decl))
4824 {
4825 error ("%qE attribute cannot be specified for local variables",
4826 name);
4827 *no_add_attrs = true;
4828 }
4829 else
4830 {
4831 const char *section_name;
4832
4833 if (strcmp (IDENTIFIER_POINTER (name), "l1_data") == 0)
4834 section_name = ".l1.data";
4835 else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_A") == 0)
4836 section_name = ".l1.data.A";
4837 else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_B") == 0)
4838 section_name = ".l1.data.B";
4839 else
4840 gcc_unreachable ();
4841
4842 /* The decl may have already been given a section attribute
4843 from a previous declaration. Ensure they match. */
4844 if (DECL_SECTION_NAME (decl) != NULL
4845 && strcmp (DECL_SECTION_NAME (decl),
4846 section_name) != 0)
4847 {
4848 error ("section of %q+D conflicts with previous declaration",
4849 decl);
4850 *no_add_attrs = true;
4851 }
4852 else
4853 set_decl_section_name (decl, section_name);
4854 }
4855
4856 return NULL_TREE;
4857 }
4858
4859 /* Handle a "l2" attribute; arguments as in struct attribute_spec.handler. */
4860
4861 static tree
4862 bfin_handle_l2_attribute (tree *node, tree ARG_UNUSED (name),
4863 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
4864 bool *no_add_attrs)
4865 {
4866 tree decl = *node;
4867
4868 if (TREE_CODE (decl) == FUNCTION_DECL)
4869 {
4870 if (DECL_SECTION_NAME (decl) != NULL
4871 && strcmp (DECL_SECTION_NAME (decl),
4872 ".l2.text") != 0)
4873 {
4874 error ("section of %q+D conflicts with previous declaration",
4875 decl);
4876 *no_add_attrs = true;
4877 }
4878 else
4879 set_decl_section_name (decl, ".l2.text");
4880 }
4881 else if (VAR_P (decl))
4882 {
4883 if (DECL_SECTION_NAME (decl) != NULL
4884 && strcmp (DECL_SECTION_NAME (decl),
4885 ".l2.data") != 0)
4886 {
4887 error ("section of %q+D conflicts with previous declaration",
4888 decl);
4889 *no_add_attrs = true;
4890 }
4891 else
4892 set_decl_section_name (decl, ".l2.data");
4893 }
4894
4895 return NULL_TREE;
4896 }
4897
4898 /* Table of valid machine attributes. */
4899 TARGET_GNU_ATTRIBUTES (bfin_attribute_table,
4900 {
4901 /* { name, min_len, max_len, decl_req, type_req, fn_type_req,
4902 affects_type_identity, handler, exclude } */
4903 { "interrupt_handler", 0, 0, false, true, true, false,
4904 handle_int_attribute, NULL },
4905 { "exception_handler", 0, 0, false, true, true, false,
4906 handle_int_attribute, NULL },
4907 { "nmi_handler", 0, 0, false, true, true, false, handle_int_attribute,
4908 NULL },
4909 { "nesting", 0, 0, false, true, true, false, NULL, NULL },
4910 { "kspisusp", 0, 0, false, true, true, false, NULL, NULL },
4911 { "saveall", 0, 0, false, true, true, false, NULL, NULL },
4912 { "longcall", 0, 0, false, true, true, false,
4913 bfin_handle_longcall_attribute, NULL },
4914 { "shortcall", 0, 0, false, true, true, false,
4915 bfin_handle_longcall_attribute, NULL },
4916 { "l1_text", 0, 0, true, false, false, false,
4917 bfin_handle_l1_text_attribute, NULL },
4918 { "l1_data", 0, 0, true, false, false, false,
4919 bfin_handle_l1_data_attribute, NULL },
4920 { "l1_data_A", 0, 0, true, false, false, false,
4921 bfin_handle_l1_data_attribute, NULL },
4922 { "l1_data_B", 0, 0, true, false, false, false,
4923 bfin_handle_l1_data_attribute, NULL },
4924 { "l2", 0, 0, true, false, false, false, bfin_handle_l2_attribute, NULL }
4925 });
4926 \f
4927 /* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to
4928 tell the assembler to generate pointers to function descriptors in
4929 some cases. */
4930
4931 static bool
4932 bfin_assemble_integer (rtx value, unsigned int size, int aligned_p)
4933 {
4934 if (TARGET_FDPIC && size == UNITS_PER_WORD)
4935 {
4936 if (GET_CODE (value) == SYMBOL_REF
4937 && SYMBOL_REF_FUNCTION_P (value))
4938 {
4939 fputs ("\t.picptr\tfuncdesc(", asm_out_file);
4940 output_addr_const (asm_out_file, value);
4941 fputs (")\n", asm_out_file);
4942 return true;
4943 }
4944 if (!aligned_p)
4945 {
4946 /* We've set the unaligned SI op to NULL, so we always have to
4947 handle the unaligned case here. */
4948 assemble_integer_with_op ("\t.4byte\t", value);
4949 return true;
4950 }
4951 }
4952 return default_assemble_integer (value, size, aligned_p);
4953 }
4954 \f
4955 /* Output the assembler code for a thunk function. THUNK_DECL is the
4956 declaration for the thunk function itself, FUNCTION is the decl for
4957 the target function. DELTA is an immediate constant offset to be
4958 added to THIS. If VCALL_OFFSET is nonzero, the word at
4959 *(*this + vcall_offset) should be added to THIS. */
4960
4961 static void
4962 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
4963 tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
4964 HOST_WIDE_INT vcall_offset, tree function)
4965 {
4966 const char *fnname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (thunk));
4967 rtx xops[3];
4968 /* The this parameter is passed as the first argument. */
4969 rtx this_rtx = gen_rtx_REG (Pmode, REG_R0);
4970
4971 assemble_start_function (thunk, fnname);
4972 /* Adjust the this parameter by a fixed constant. */
4973 if (delta)
4974 {
4975 xops[1] = this_rtx;
4976 if (delta >= -64 && delta <= 63)
4977 {
4978 xops[0] = GEN_INT (delta);
4979 output_asm_insn ("%1 += %0;", xops);
4980 }
4981 else if (delta >= -128 && delta < -64)
4982 {
4983 xops[0] = GEN_INT (delta + 64);
4984 output_asm_insn ("%1 += -64; %1 += %0;", xops);
4985 }
4986 else if (delta > 63 && delta <= 126)
4987 {
4988 xops[0] = GEN_INT (delta - 63);
4989 output_asm_insn ("%1 += 63; %1 += %0;", xops);
4990 }
4991 else
4992 {
4993 xops[0] = GEN_INT (delta);
4994 output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
4995 }
4996 }
4997
4998 /* Adjust the this parameter by a value stored in the vtable. */
4999 if (vcall_offset)
5000 {
5001 rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
5002 rtx tmp = gen_rtx_REG (Pmode, REG_R3);
5003
5004 xops[1] = tmp;
5005 xops[2] = p2tmp;
5006 output_asm_insn ("%2 = r0; %2 = [%2];", xops);
5007
5008 /* Adjust the this parameter. */
5009 xops[0] = gen_rtx_MEM (Pmode, plus_constant (Pmode, p2tmp,
5010 vcall_offset));
5011 if (!memory_operand (xops[0], Pmode))
5012 {
5013 rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
5014 xops[0] = GEN_INT (vcall_offset);
5015 xops[1] = tmp2;
5016 output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
5017 xops[0] = gen_rtx_MEM (Pmode, p2tmp);
5018 }
5019 xops[2] = this_rtx;
5020 output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
5021 }
5022
5023 xops[0] = XEXP (DECL_RTL (function), 0);
5024 if (1 || !flag_pic || (*targetm.binds_local_p) (function))
5025 output_asm_insn ("jump.l\t%P0", xops);
5026 assemble_end_function (thunk, fnname);
5027 }
5028 \f
5029 /* Codes for all the Blackfin builtins. */
5030 enum bfin_builtins
5031 {
5032 BFIN_BUILTIN_CSYNC,
5033 BFIN_BUILTIN_SSYNC,
5034 BFIN_BUILTIN_ONES,
5035 BFIN_BUILTIN_COMPOSE_2X16,
5036 BFIN_BUILTIN_EXTRACTLO,
5037 BFIN_BUILTIN_EXTRACTHI,
5038
5039 BFIN_BUILTIN_SSADD_2X16,
5040 BFIN_BUILTIN_SSSUB_2X16,
5041 BFIN_BUILTIN_SSADDSUB_2X16,
5042 BFIN_BUILTIN_SSSUBADD_2X16,
5043 BFIN_BUILTIN_MULT_2X16,
5044 BFIN_BUILTIN_MULTR_2X16,
5045 BFIN_BUILTIN_NEG_2X16,
5046 BFIN_BUILTIN_ABS_2X16,
5047 BFIN_BUILTIN_MIN_2X16,
5048 BFIN_BUILTIN_MAX_2X16,
5049
5050 BFIN_BUILTIN_SSADD_1X16,
5051 BFIN_BUILTIN_SSSUB_1X16,
5052 BFIN_BUILTIN_MULT_1X16,
5053 BFIN_BUILTIN_MULTR_1X16,
5054 BFIN_BUILTIN_NORM_1X16,
5055 BFIN_BUILTIN_NEG_1X16,
5056 BFIN_BUILTIN_ABS_1X16,
5057 BFIN_BUILTIN_MIN_1X16,
5058 BFIN_BUILTIN_MAX_1X16,
5059
5060 BFIN_BUILTIN_SUM_2X16,
5061 BFIN_BUILTIN_DIFFHL_2X16,
5062 BFIN_BUILTIN_DIFFLH_2X16,
5063
5064 BFIN_BUILTIN_SSADD_1X32,
5065 BFIN_BUILTIN_SSSUB_1X32,
5066 BFIN_BUILTIN_NORM_1X32,
5067 BFIN_BUILTIN_ROUND_1X32,
5068 BFIN_BUILTIN_NEG_1X32,
5069 BFIN_BUILTIN_ABS_1X32,
5070 BFIN_BUILTIN_MIN_1X32,
5071 BFIN_BUILTIN_MAX_1X32,
5072 BFIN_BUILTIN_MULT_1X32,
5073 BFIN_BUILTIN_MULT_1X32X32,
5074 BFIN_BUILTIN_MULT_1X32X32NS,
5075
5076 BFIN_BUILTIN_MULHISILL,
5077 BFIN_BUILTIN_MULHISILH,
5078 BFIN_BUILTIN_MULHISIHL,
5079 BFIN_BUILTIN_MULHISIHH,
5080
5081 BFIN_BUILTIN_LSHIFT_1X16,
5082 BFIN_BUILTIN_LSHIFT_2X16,
5083 BFIN_BUILTIN_SSASHIFT_1X16,
5084 BFIN_BUILTIN_SSASHIFT_2X16,
5085 BFIN_BUILTIN_SSASHIFT_1X32,
5086
5087 BFIN_BUILTIN_CPLX_MUL_16,
5088 BFIN_BUILTIN_CPLX_MAC_16,
5089 BFIN_BUILTIN_CPLX_MSU_16,
5090
5091 BFIN_BUILTIN_CPLX_MUL_16_S40,
5092 BFIN_BUILTIN_CPLX_MAC_16_S40,
5093 BFIN_BUILTIN_CPLX_MSU_16_S40,
5094
5095 BFIN_BUILTIN_CPLX_SQU,
5096
5097 BFIN_BUILTIN_LOADBYTES,
5098
5099 BFIN_BUILTIN_MAX
5100 };
5101
5102 #define def_builtin(NAME, TYPE, CODE) \
5103 do { \
5104 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
5105 NULL, NULL_TREE); \
5106 } while (0)
5107
5108 /* Set up all builtin functions for this target. */
5109 static void
5110 bfin_init_builtins (void)
5111 {
5112 tree V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
5113 tree void_ftype_void
5114 = build_function_type_list (void_type_node, NULL_TREE);
5115 tree short_ftype_short
5116 = build_function_type_list (short_integer_type_node, short_integer_type_node,
5117 NULL_TREE);
5118 tree short_ftype_int_int
5119 = build_function_type_list (short_integer_type_node, integer_type_node,
5120 integer_type_node, NULL_TREE);
5121 tree int_ftype_int_int
5122 = build_function_type_list (integer_type_node, integer_type_node,
5123 integer_type_node, NULL_TREE);
5124 tree int_ftype_int
5125 = build_function_type_list (integer_type_node, integer_type_node,
5126 NULL_TREE);
5127 tree short_ftype_int
5128 = build_function_type_list (short_integer_type_node, integer_type_node,
5129 NULL_TREE);
5130 tree int_ftype_v2hi_v2hi
5131 = build_function_type_list (integer_type_node, V2HI_type_node,
5132 V2HI_type_node, NULL_TREE);
5133 tree v2hi_ftype_v2hi_v2hi
5134 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5135 V2HI_type_node, NULL_TREE);
5136 tree v2hi_ftype_v2hi_v2hi_v2hi
5137 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5138 V2HI_type_node, V2HI_type_node, NULL_TREE);
5139 tree v2hi_ftype_int_int
5140 = build_function_type_list (V2HI_type_node, integer_type_node,
5141 integer_type_node, NULL_TREE);
5142 tree v2hi_ftype_v2hi_int
5143 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5144 integer_type_node, NULL_TREE);
5145 tree int_ftype_short_short
5146 = build_function_type_list (integer_type_node, short_integer_type_node,
5147 short_integer_type_node, NULL_TREE);
5148 tree v2hi_ftype_v2hi
5149 = build_function_type_list (V2HI_type_node, V2HI_type_node, NULL_TREE);
5150 tree short_ftype_v2hi
5151 = build_function_type_list (short_integer_type_node, V2HI_type_node,
5152 NULL_TREE);
5153 tree int_ftype_pint
5154 = build_function_type_list (integer_type_node,
5155 build_pointer_type (integer_type_node),
5156 NULL_TREE);
5157
5158 /* Add the remaining MMX insns with somewhat more complicated types. */
5159 def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC);
5160 def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC);
5161
5162 def_builtin ("__builtin_bfin_ones", short_ftype_int, BFIN_BUILTIN_ONES);
5163
5164 def_builtin ("__builtin_bfin_compose_2x16", v2hi_ftype_int_int,
5165 BFIN_BUILTIN_COMPOSE_2X16);
5166 def_builtin ("__builtin_bfin_extract_hi", short_ftype_v2hi,
5167 BFIN_BUILTIN_EXTRACTHI);
5168 def_builtin ("__builtin_bfin_extract_lo", short_ftype_v2hi,
5169 BFIN_BUILTIN_EXTRACTLO);
5170
5171 def_builtin ("__builtin_bfin_min_fr2x16", v2hi_ftype_v2hi_v2hi,
5172 BFIN_BUILTIN_MIN_2X16);
5173 def_builtin ("__builtin_bfin_max_fr2x16", v2hi_ftype_v2hi_v2hi,
5174 BFIN_BUILTIN_MAX_2X16);
5175
5176 def_builtin ("__builtin_bfin_add_fr2x16", v2hi_ftype_v2hi_v2hi,
5177 BFIN_BUILTIN_SSADD_2X16);
5178 def_builtin ("__builtin_bfin_sub_fr2x16", v2hi_ftype_v2hi_v2hi,
5179 BFIN_BUILTIN_SSSUB_2X16);
5180 def_builtin ("__builtin_bfin_dspaddsubsat", v2hi_ftype_v2hi_v2hi,
5181 BFIN_BUILTIN_SSADDSUB_2X16);
5182 def_builtin ("__builtin_bfin_dspsubaddsat", v2hi_ftype_v2hi_v2hi,
5183 BFIN_BUILTIN_SSSUBADD_2X16);
5184 def_builtin ("__builtin_bfin_mult_fr2x16", v2hi_ftype_v2hi_v2hi,
5185 BFIN_BUILTIN_MULT_2X16);
5186 def_builtin ("__builtin_bfin_multr_fr2x16", v2hi_ftype_v2hi_v2hi,
5187 BFIN_BUILTIN_MULTR_2X16);
5188 def_builtin ("__builtin_bfin_negate_fr2x16", v2hi_ftype_v2hi,
5189 BFIN_BUILTIN_NEG_2X16);
5190 def_builtin ("__builtin_bfin_abs_fr2x16", v2hi_ftype_v2hi,
5191 BFIN_BUILTIN_ABS_2X16);
5192
5193 def_builtin ("__builtin_bfin_min_fr1x16", short_ftype_int_int,
5194 BFIN_BUILTIN_MIN_1X16);
5195 def_builtin ("__builtin_bfin_max_fr1x16", short_ftype_int_int,
5196 BFIN_BUILTIN_MAX_1X16);
5197
5198 def_builtin ("__builtin_bfin_add_fr1x16", short_ftype_int_int,
5199 BFIN_BUILTIN_SSADD_1X16);
5200 def_builtin ("__builtin_bfin_sub_fr1x16", short_ftype_int_int,
5201 BFIN_BUILTIN_SSSUB_1X16);
5202 def_builtin ("__builtin_bfin_mult_fr1x16", short_ftype_int_int,
5203 BFIN_BUILTIN_MULT_1X16);
5204 def_builtin ("__builtin_bfin_multr_fr1x16", short_ftype_int_int,
5205 BFIN_BUILTIN_MULTR_1X16);
5206 def_builtin ("__builtin_bfin_negate_fr1x16", short_ftype_short,
5207 BFIN_BUILTIN_NEG_1X16);
5208 def_builtin ("__builtin_bfin_abs_fr1x16", short_ftype_short,
5209 BFIN_BUILTIN_ABS_1X16);
5210 def_builtin ("__builtin_bfin_norm_fr1x16", short_ftype_int,
5211 BFIN_BUILTIN_NORM_1X16);
5212
5213 def_builtin ("__builtin_bfin_sum_fr2x16", short_ftype_v2hi,
5214 BFIN_BUILTIN_SUM_2X16);
5215 def_builtin ("__builtin_bfin_diff_hl_fr2x16", short_ftype_v2hi,
5216 BFIN_BUILTIN_DIFFHL_2X16);
5217 def_builtin ("__builtin_bfin_diff_lh_fr2x16", short_ftype_v2hi,
5218 BFIN_BUILTIN_DIFFLH_2X16);
5219
5220 def_builtin ("__builtin_bfin_mulhisill", int_ftype_v2hi_v2hi,
5221 BFIN_BUILTIN_MULHISILL);
5222 def_builtin ("__builtin_bfin_mulhisihl", int_ftype_v2hi_v2hi,
5223 BFIN_BUILTIN_MULHISIHL);
5224 def_builtin ("__builtin_bfin_mulhisilh", int_ftype_v2hi_v2hi,
5225 BFIN_BUILTIN_MULHISILH);
5226 def_builtin ("__builtin_bfin_mulhisihh", int_ftype_v2hi_v2hi,
5227 BFIN_BUILTIN_MULHISIHH);
5228
5229 def_builtin ("__builtin_bfin_min_fr1x32", int_ftype_int_int,
5230 BFIN_BUILTIN_MIN_1X32);
5231 def_builtin ("__builtin_bfin_max_fr1x32", int_ftype_int_int,
5232 BFIN_BUILTIN_MAX_1X32);
5233
5234 def_builtin ("__builtin_bfin_add_fr1x32", int_ftype_int_int,
5235 BFIN_BUILTIN_SSADD_1X32);
5236 def_builtin ("__builtin_bfin_sub_fr1x32", int_ftype_int_int,
5237 BFIN_BUILTIN_SSSUB_1X32);
5238 def_builtin ("__builtin_bfin_negate_fr1x32", int_ftype_int,
5239 BFIN_BUILTIN_NEG_1X32);
5240 def_builtin ("__builtin_bfin_abs_fr1x32", int_ftype_int,
5241 BFIN_BUILTIN_ABS_1X32);
5242 def_builtin ("__builtin_bfin_norm_fr1x32", short_ftype_int,
5243 BFIN_BUILTIN_NORM_1X32);
5244 def_builtin ("__builtin_bfin_round_fr1x32", short_ftype_int,
5245 BFIN_BUILTIN_ROUND_1X32);
5246 def_builtin ("__builtin_bfin_mult_fr1x32", int_ftype_short_short,
5247 BFIN_BUILTIN_MULT_1X32);
5248 def_builtin ("__builtin_bfin_mult_fr1x32x32", int_ftype_int_int,
5249 BFIN_BUILTIN_MULT_1X32X32);
5250 def_builtin ("__builtin_bfin_mult_fr1x32x32NS", int_ftype_int_int,
5251 BFIN_BUILTIN_MULT_1X32X32NS);
5252
5253 /* Shifts. */
5254 def_builtin ("__builtin_bfin_shl_fr1x16", short_ftype_int_int,
5255 BFIN_BUILTIN_SSASHIFT_1X16);
5256 def_builtin ("__builtin_bfin_shl_fr2x16", v2hi_ftype_v2hi_int,
5257 BFIN_BUILTIN_SSASHIFT_2X16);
5258 def_builtin ("__builtin_bfin_lshl_fr1x16", short_ftype_int_int,
5259 BFIN_BUILTIN_LSHIFT_1X16);
5260 def_builtin ("__builtin_bfin_lshl_fr2x16", v2hi_ftype_v2hi_int,
5261 BFIN_BUILTIN_LSHIFT_2X16);
5262 def_builtin ("__builtin_bfin_shl_fr1x32", int_ftype_int_int,
5263 BFIN_BUILTIN_SSASHIFT_1X32);
5264
5265 /* Complex numbers. */
5266 def_builtin ("__builtin_bfin_cmplx_add", v2hi_ftype_v2hi_v2hi,
5267 BFIN_BUILTIN_SSADD_2X16);
5268 def_builtin ("__builtin_bfin_cmplx_sub", v2hi_ftype_v2hi_v2hi,
5269 BFIN_BUILTIN_SSSUB_2X16);
5270 def_builtin ("__builtin_bfin_cmplx_mul", v2hi_ftype_v2hi_v2hi,
5271 BFIN_BUILTIN_CPLX_MUL_16);
5272 def_builtin ("__builtin_bfin_cmplx_mac", v2hi_ftype_v2hi_v2hi_v2hi,
5273 BFIN_BUILTIN_CPLX_MAC_16);
5274 def_builtin ("__builtin_bfin_cmplx_msu", v2hi_ftype_v2hi_v2hi_v2hi,
5275 BFIN_BUILTIN_CPLX_MSU_16);
5276 def_builtin ("__builtin_bfin_cmplx_mul_s40", v2hi_ftype_v2hi_v2hi,
5277 BFIN_BUILTIN_CPLX_MUL_16_S40);
5278 def_builtin ("__builtin_bfin_cmplx_mac_s40", v2hi_ftype_v2hi_v2hi_v2hi,
5279 BFIN_BUILTIN_CPLX_MAC_16_S40);
5280 def_builtin ("__builtin_bfin_cmplx_msu_s40", v2hi_ftype_v2hi_v2hi_v2hi,
5281 BFIN_BUILTIN_CPLX_MSU_16_S40);
5282 def_builtin ("__builtin_bfin_csqu_fr16", v2hi_ftype_v2hi,
5283 BFIN_BUILTIN_CPLX_SQU);
5284
5285 /* "Unaligned" load. */
5286 def_builtin ("__builtin_bfin_loadbytes", int_ftype_pint,
5287 BFIN_BUILTIN_LOADBYTES);
5288
5289 }
5290
5291
5292 struct builtin_description
5293 {
5294 const enum insn_code icode;
5295 const char *const name;
5296 const enum bfin_builtins code;
5297 int macflag;
5298 };
5299
5300 static const struct builtin_description bdesc_2arg[] =
5301 {
5302 { CODE_FOR_composev2hi, "__builtin_bfin_compose_2x16", BFIN_BUILTIN_COMPOSE_2X16, -1 },
5303
5304 { CODE_FOR_ssashiftv2hi3, "__builtin_bfin_shl_fr2x16", BFIN_BUILTIN_SSASHIFT_2X16, -1 },
5305 { CODE_FOR_ssashifthi3, "__builtin_bfin_shl_fr1x16", BFIN_BUILTIN_SSASHIFT_1X16, -1 },
5306 { CODE_FOR_lshiftv2hi3, "__builtin_bfin_lshl_fr2x16", BFIN_BUILTIN_LSHIFT_2X16, -1 },
5307 { CODE_FOR_lshifthi3, "__builtin_bfin_lshl_fr1x16", BFIN_BUILTIN_LSHIFT_1X16, -1 },
5308 { CODE_FOR_ssashiftsi3, "__builtin_bfin_shl_fr1x32", BFIN_BUILTIN_SSASHIFT_1X32, -1 },
5309
5310 { CODE_FOR_sminhi3, "__builtin_bfin_min_fr1x16", BFIN_BUILTIN_MIN_1X16, -1 },
5311 { CODE_FOR_smaxhi3, "__builtin_bfin_max_fr1x16", BFIN_BUILTIN_MAX_1X16, -1 },
5312 { CODE_FOR_ssaddhi3, "__builtin_bfin_add_fr1x16", BFIN_BUILTIN_SSADD_1X16, -1 },
5313 { CODE_FOR_sssubhi3, "__builtin_bfin_sub_fr1x16", BFIN_BUILTIN_SSSUB_1X16, -1 },
5314
5315 { CODE_FOR_sminsi3, "__builtin_bfin_min_fr1x32", BFIN_BUILTIN_MIN_1X32, -1 },
5316 { CODE_FOR_smaxsi3, "__builtin_bfin_max_fr1x32", BFIN_BUILTIN_MAX_1X32, -1 },
5317 { CODE_FOR_ssaddsi3, "__builtin_bfin_add_fr1x32", BFIN_BUILTIN_SSADD_1X32, -1 },
5318 { CODE_FOR_sssubsi3, "__builtin_bfin_sub_fr1x32", BFIN_BUILTIN_SSSUB_1X32, -1 },
5319
5320 { CODE_FOR_sminv2hi3, "__builtin_bfin_min_fr2x16", BFIN_BUILTIN_MIN_2X16, -1 },
5321 { CODE_FOR_smaxv2hi3, "__builtin_bfin_max_fr2x16", BFIN_BUILTIN_MAX_2X16, -1 },
5322 { CODE_FOR_ssaddv2hi3, "__builtin_bfin_add_fr2x16", BFIN_BUILTIN_SSADD_2X16, -1 },
5323 { CODE_FOR_sssubv2hi3, "__builtin_bfin_sub_fr2x16", BFIN_BUILTIN_SSSUB_2X16, -1 },
5324 { CODE_FOR_ssaddsubv2hi3, "__builtin_bfin_dspaddsubsat", BFIN_BUILTIN_SSADDSUB_2X16, -1 },
5325 { CODE_FOR_sssubaddv2hi3, "__builtin_bfin_dspsubaddsat", BFIN_BUILTIN_SSSUBADD_2X16, -1 },
5326
5327 { CODE_FOR_flag_mulhisi, "__builtin_bfin_mult_fr1x32", BFIN_BUILTIN_MULT_1X32, MACFLAG_NONE },
5328 { CODE_FOR_flag_mulhi, "__builtin_bfin_mult_fr1x16", BFIN_BUILTIN_MULT_1X16, MACFLAG_T },
5329 { CODE_FOR_flag_mulhi, "__builtin_bfin_multr_fr1x16", BFIN_BUILTIN_MULTR_1X16, MACFLAG_NONE },
5330 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_mult_fr2x16", BFIN_BUILTIN_MULT_2X16, MACFLAG_T },
5331 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_multr_fr2x16", BFIN_BUILTIN_MULTR_2X16, MACFLAG_NONE },
5332
5333 { CODE_FOR_mulhisi_ll, "__builtin_bfin_mulhisill", BFIN_BUILTIN_MULHISILL, -1 },
5334 { CODE_FOR_mulhisi_lh, "__builtin_bfin_mulhisilh", BFIN_BUILTIN_MULHISILH, -1 },
5335 { CODE_FOR_mulhisi_hl, "__builtin_bfin_mulhisihl", BFIN_BUILTIN_MULHISIHL, -1 },
5336 { CODE_FOR_mulhisi_hh, "__builtin_bfin_mulhisihh", BFIN_BUILTIN_MULHISIHH, -1 }
5337
5338 };
5339
5340 static const struct builtin_description bdesc_1arg[] =
5341 {
5342 { CODE_FOR_loadbytes, "__builtin_bfin_loadbytes", BFIN_BUILTIN_LOADBYTES, 0 },
5343
5344 { CODE_FOR_ones, "__builtin_bfin_ones", BFIN_BUILTIN_ONES, 0 },
5345
5346 { CODE_FOR_clrsbhi2, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16, 0 },
5347 { CODE_FOR_ssneghi2, "__builtin_bfin_negate_fr1x16", BFIN_BUILTIN_NEG_1X16, 0 },
5348 { CODE_FOR_abshi2, "__builtin_bfin_abs_fr1x16", BFIN_BUILTIN_ABS_1X16, 0 },
5349
5350 { CODE_FOR_clrsbsi2, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32, 0 },
5351 { CODE_FOR_ssroundsi2, "__builtin_bfin_round_fr1x32", BFIN_BUILTIN_ROUND_1X32, 0 },
5352 { CODE_FOR_ssnegsi2, "__builtin_bfin_negate_fr1x32", BFIN_BUILTIN_NEG_1X32, 0 },
5353 { CODE_FOR_ssabssi2, "__builtin_bfin_abs_fr1x32", BFIN_BUILTIN_ABS_1X32, 0 },
5354
5355 { CODE_FOR_movv2hi_hi_low, "__builtin_bfin_extract_lo", BFIN_BUILTIN_EXTRACTLO, 0 },
5356 { CODE_FOR_movv2hi_hi_high, "__builtin_bfin_extract_hi", BFIN_BUILTIN_EXTRACTHI, 0 },
5357 { CODE_FOR_ssnegv2hi2, "__builtin_bfin_negate_fr2x16", BFIN_BUILTIN_NEG_2X16, 0 },
5358 { CODE_FOR_ssabsv2hi2, "__builtin_bfin_abs_fr2x16", BFIN_BUILTIN_ABS_2X16, 0 }
5359 };
5360
5361 /* Errors in the source file can cause expand_expr to return const0_rtx
5362 where we expect a vector. To avoid crashing, use one of the vector
5363 clear instructions. */
5364 static rtx
5365 safe_vector_operand (rtx x, machine_mode mode)
5366 {
5367 if (x != const0_rtx)
5368 return x;
5369 x = gen_reg_rtx (SImode);
5370
5371 emit_insn (gen_movsi (x, CONST0_RTX (SImode)));
5372 return gen_lowpart (mode, x);
5373 }
5374
5375 /* Subroutine of bfin_expand_builtin to take care of binop insns. MACFLAG is -1
5376 if this is a normal binary op, or one of the MACFLAG_xxx constants. */
5377
5378 static rtx
5379 bfin_expand_binop_builtin (enum insn_code icode, tree exp, rtx target,
5380 int macflag)
5381 {
5382 rtx pat;
5383 tree arg0 = CALL_EXPR_ARG (exp, 0);
5384 tree arg1 = CALL_EXPR_ARG (exp, 1);
5385 rtx op0 = expand_normal (arg0);
5386 rtx op1 = expand_normal (arg1);
5387 machine_mode op0mode = GET_MODE (op0);
5388 machine_mode op1mode = GET_MODE (op1);
5389 machine_mode tmode = insn_data[icode].operand[0].mode;
5390 machine_mode mode0 = insn_data[icode].operand[1].mode;
5391 machine_mode mode1 = insn_data[icode].operand[2].mode;
5392
5393 if (VECTOR_MODE_P (mode0))
5394 op0 = safe_vector_operand (op0, mode0);
5395 if (VECTOR_MODE_P (mode1))
5396 op1 = safe_vector_operand (op1, mode1);
5397
5398 if (! target
5399 || GET_MODE (target) != tmode
5400 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5401 target = gen_reg_rtx (tmode);
5402
5403 if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode)
5404 {
5405 op0mode = HImode;
5406 op0 = gen_lowpart (HImode, op0);
5407 }
5408 if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode)
5409 {
5410 op1mode = HImode;
5411 op1 = gen_lowpart (HImode, op1);
5412 }
5413 /* In case the insn wants input operands in modes different from
5414 the result, abort. */
5415 gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
5416 && (op1mode == mode1 || op1mode == VOIDmode));
5417
5418 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5419 op0 = copy_to_mode_reg (mode0, op0);
5420 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
5421 op1 = copy_to_mode_reg (mode1, op1);
5422
5423 if (macflag == -1)
5424 pat = GEN_FCN (icode) (target, op0, op1);
5425 else
5426 pat = GEN_FCN (icode) (target, op0, op1, GEN_INT (macflag));
5427 if (! pat)
5428 return 0;
5429
5430 emit_insn (pat);
5431 return target;
5432 }
5433
5434 /* Subroutine of bfin_expand_builtin to take care of unop insns. */
5435
5436 static rtx
5437 bfin_expand_unop_builtin (enum insn_code icode, tree exp,
5438 rtx target)
5439 {
5440 rtx pat;
5441 tree arg0 = CALL_EXPR_ARG (exp, 0);
5442 rtx op0 = expand_normal (arg0);
5443 machine_mode op0mode = GET_MODE (op0);
5444 machine_mode tmode = insn_data[icode].operand[0].mode;
5445 machine_mode mode0 = insn_data[icode].operand[1].mode;
5446
5447 if (! target
5448 || GET_MODE (target) != tmode
5449 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5450 target = gen_reg_rtx (tmode);
5451
5452 if (VECTOR_MODE_P (mode0))
5453 op0 = safe_vector_operand (op0, mode0);
5454
5455 if (op0mode == SImode && mode0 == HImode)
5456 {
5457 op0mode = HImode;
5458 op0 = gen_lowpart (HImode, op0);
5459 }
5460 gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
5461
5462 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5463 op0 = copy_to_mode_reg (mode0, op0);
5464
5465 pat = GEN_FCN (icode) (target, op0);
5466 if (! pat)
5467 return 0;
5468 emit_insn (pat);
5469 return target;
5470 }
5471
5472 /* Expand an expression EXP that calls a built-in function,
5473 with result going to TARGET if that's convenient
5474 (and in mode MODE if that's convenient).
5475 SUBTARGET may be used as the target for computing one of EXP's operands.
5476 IGNORE is nonzero if the value is to be ignored. */
5477
5478 static rtx
5479 bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
5480 rtx subtarget ATTRIBUTE_UNUSED,
5481 machine_mode mode ATTRIBUTE_UNUSED,
5482 int ignore ATTRIBUTE_UNUSED)
5483 {
5484 size_t i;
5485 enum insn_code icode;
5486 const struct builtin_description *d;
5487 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
5488 unsigned int fcode = DECL_MD_FUNCTION_CODE (fndecl);
5489 tree arg0, arg1, arg2;
5490 rtx op0, op1, op2, accvec, pat, tmp1, tmp2, a0reg, a1reg;
5491 machine_mode tmode, mode0;
5492
5493 switch (fcode)
5494 {
5495 case BFIN_BUILTIN_CSYNC:
5496 emit_insn (gen_csync ());
5497 return 0;
5498 case BFIN_BUILTIN_SSYNC:
5499 emit_insn (gen_ssync ());
5500 return 0;
5501
5502 case BFIN_BUILTIN_DIFFHL_2X16:
5503 case BFIN_BUILTIN_DIFFLH_2X16:
5504 case BFIN_BUILTIN_SUM_2X16:
5505 arg0 = CALL_EXPR_ARG (exp, 0);
5506 op0 = expand_normal (arg0);
5507 icode = (fcode == BFIN_BUILTIN_DIFFHL_2X16 ? CODE_FOR_subhilov2hi3
5508 : fcode == BFIN_BUILTIN_DIFFLH_2X16 ? CODE_FOR_sublohiv2hi3
5509 : CODE_FOR_ssaddhilov2hi3);
5510 tmode = insn_data[icode].operand[0].mode;
5511 mode0 = insn_data[icode].operand[1].mode;
5512
5513 if (! target
5514 || GET_MODE (target) != tmode
5515 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5516 target = gen_reg_rtx (tmode);
5517
5518 if (VECTOR_MODE_P (mode0))
5519 op0 = safe_vector_operand (op0, mode0);
5520
5521 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5522 op0 = copy_to_mode_reg (mode0, op0);
5523
5524 pat = GEN_FCN (icode) (target, op0, op0);
5525 if (! pat)
5526 return 0;
5527 emit_insn (pat);
5528 return target;
5529
5530 case BFIN_BUILTIN_MULT_1X32X32:
5531 case BFIN_BUILTIN_MULT_1X32X32NS:
5532 arg0 = CALL_EXPR_ARG (exp, 0);
5533 arg1 = CALL_EXPR_ARG (exp, 1);
5534 op0 = expand_normal (arg0);
5535 op1 = expand_normal (arg1);
5536 if (! target
5537 || !register_operand (target, SImode))
5538 target = gen_reg_rtx (SImode);
5539 if (! register_operand (op0, SImode))
5540 op0 = copy_to_mode_reg (SImode, op0);
5541 if (! register_operand (op1, SImode))
5542 op1 = copy_to_mode_reg (SImode, op1);
5543
5544 a1reg = gen_rtx_REG (PDImode, REG_A1);
5545 a0reg = gen_rtx_REG (PDImode, REG_A0);
5546 tmp1 = gen_lowpart (V2HImode, op0);
5547 tmp2 = gen_lowpart (V2HImode, op1);
5548 emit_insn (gen_flag_macinit1hi (a1reg,
5549 gen_lowpart (HImode, op0),
5550 gen_lowpart (HImode, op1),
5551 GEN_INT (MACFLAG_FU)));
5552 emit_insn (gen_lshrpdi3 (a1reg, a1reg, GEN_INT (16)));
5553
5554 if (fcode == BFIN_BUILTIN_MULT_1X32X32)
5555 emit_insn (gen_flag_mul_macv2hi_parts_acconly (a0reg, a1reg, tmp1, tmp2,
5556 const1_rtx, const1_rtx,
5557 const1_rtx, const0_rtx, a1reg,
5558 const0_rtx, GEN_INT (MACFLAG_NONE),
5559 GEN_INT (MACFLAG_M)));
5560 else
5561 {
5562 /* For saturating multiplication, there's exactly one special case
5563 to be handled: multiplying the smallest negative value with
5564 itself. Due to shift correction in fractional multiplies, this
5565 can overflow. Iff this happens, OP2 will contain 1, which, when
5566 added in 32 bits to the smallest negative, wraps to the largest
5567 positive, which is the result we want. */
5568 op2 = gen_reg_rtx (V2HImode);
5569 emit_insn (gen_packv2hi (op2, tmp1, tmp2, const0_rtx, const0_rtx));
5570 emit_insn (gen_movsibi (gen_rtx_REG (BImode, REG_CC),
5571 gen_lowpart (SImode, op2)));
5572 emit_insn (gen_flag_mul_macv2hi_parts_acconly_andcc0 (a0reg, a1reg, tmp1, tmp2,
5573 const1_rtx, const1_rtx,
5574 const1_rtx, const0_rtx, a1reg,
5575 const0_rtx, GEN_INT (MACFLAG_NONE),
5576 GEN_INT (MACFLAG_M)));
5577 op2 = gen_reg_rtx (SImode);
5578 emit_insn (gen_movbisi (op2, gen_rtx_REG (BImode, REG_CC)));
5579 }
5580 emit_insn (gen_flag_machi_parts_acconly (a1reg, tmp2, tmp1,
5581 const1_rtx, const0_rtx,
5582 a1reg, const0_rtx, GEN_INT (MACFLAG_M)));
5583 emit_insn (gen_ashrpdi3 (a1reg, a1reg, GEN_INT (15)));
5584 emit_insn (gen_sum_of_accumulators (target, a0reg, a0reg, a1reg));
5585 if (fcode == BFIN_BUILTIN_MULT_1X32X32NS)
5586 emit_insn (gen_addsi3 (target, target, op2));
5587 return target;
5588
5589 case BFIN_BUILTIN_CPLX_MUL_16:
5590 case BFIN_BUILTIN_CPLX_MUL_16_S40:
5591 arg0 = CALL_EXPR_ARG (exp, 0);
5592 arg1 = CALL_EXPR_ARG (exp, 1);
5593 op0 = expand_normal (arg0);
5594 op1 = expand_normal (arg1);
5595 accvec = gen_reg_rtx (V2PDImode);
5596 icode = CODE_FOR_flag_macv2hi_parts;
5597 tmode = insn_data[icode].operand[0].mode;
5598
5599 if (! target
5600 || GET_MODE (target) != V2HImode
5601 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5602 target = gen_reg_rtx (tmode);
5603 if (! register_operand (op0, GET_MODE (op0)))
5604 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
5605 if (! register_operand (op1, GET_MODE (op1)))
5606 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
5607
5608 if (fcode == BFIN_BUILTIN_CPLX_MUL_16)
5609 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
5610 const0_rtx, const0_rtx,
5611 const1_rtx, GEN_INT (MACFLAG_W32)));
5612 else
5613 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
5614 const0_rtx, const0_rtx,
5615 const1_rtx, GEN_INT (MACFLAG_NONE)));
5616 emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
5617 const1_rtx, const1_rtx,
5618 const0_rtx, accvec, const1_rtx, const0_rtx,
5619 GEN_INT (MACFLAG_NONE), accvec));
5620
5621 return target;
5622
5623 case BFIN_BUILTIN_CPLX_MAC_16:
5624 case BFIN_BUILTIN_CPLX_MSU_16:
5625 case BFIN_BUILTIN_CPLX_MAC_16_S40:
5626 case BFIN_BUILTIN_CPLX_MSU_16_S40:
5627 arg0 = CALL_EXPR_ARG (exp, 0);
5628 arg1 = CALL_EXPR_ARG (exp, 1);
5629 arg2 = CALL_EXPR_ARG (exp, 2);
5630 op0 = expand_normal (arg0);
5631 op1 = expand_normal (arg1);
5632 op2 = expand_normal (arg2);
5633 accvec = gen_reg_rtx (V2PDImode);
5634 icode = CODE_FOR_flag_macv2hi_parts;
5635 tmode = insn_data[icode].operand[0].mode;
5636
5637 if (! target
5638 || GET_MODE (target) != V2HImode
5639 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5640 target = gen_reg_rtx (tmode);
5641 if (! register_operand (op1, GET_MODE (op1)))
5642 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
5643 if (! register_operand (op2, GET_MODE (op2)))
5644 op2 = copy_to_mode_reg (GET_MODE (op2), op2);
5645
5646 tmp1 = gen_reg_rtx (SImode);
5647 tmp2 = gen_reg_rtx (SImode);
5648 emit_insn (gen_ashlsi3 (tmp1, gen_lowpart (SImode, op0), GEN_INT (16)));
5649 emit_move_insn (tmp2, gen_lowpart (SImode, op0));
5650 emit_insn (gen_movstricthi_1 (gen_lowpart (HImode, tmp2), const0_rtx));
5651 emit_insn (gen_load_accumulator_pair (accvec, tmp1, tmp2));
5652 if (fcode == BFIN_BUILTIN_CPLX_MAC_16
5653 || fcode == BFIN_BUILTIN_CPLX_MSU_16)
5654 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx,
5655 const0_rtx, const0_rtx,
5656 const1_rtx, accvec, const0_rtx,
5657 const0_rtx,
5658 GEN_INT (MACFLAG_W32)));
5659 else
5660 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx,
5661 const0_rtx, const0_rtx,
5662 const1_rtx, accvec, const0_rtx,
5663 const0_rtx,
5664 GEN_INT (MACFLAG_NONE)));
5665 if (fcode == BFIN_BUILTIN_CPLX_MAC_16
5666 || fcode == BFIN_BUILTIN_CPLX_MAC_16_S40)
5667 {
5668 tmp1 = const1_rtx;
5669 tmp2 = const0_rtx;
5670 }
5671 else
5672 {
5673 tmp1 = const0_rtx;
5674 tmp2 = const1_rtx;
5675 }
5676 emit_insn (gen_flag_macv2hi_parts (target, op1, op2, const1_rtx,
5677 const1_rtx, const1_rtx,
5678 const0_rtx, accvec, tmp1, tmp2,
5679 GEN_INT (MACFLAG_NONE), accvec));
5680
5681 return target;
5682
5683 case BFIN_BUILTIN_CPLX_SQU:
5684 arg0 = CALL_EXPR_ARG (exp, 0);
5685 op0 = expand_normal (arg0);
5686 accvec = gen_reg_rtx (V2PDImode);
5687 icode = CODE_FOR_flag_mulv2hi;
5688 tmp1 = gen_reg_rtx (V2HImode);
5689 tmp2 = gen_reg_rtx (V2HImode);
5690
5691 if (! target
5692 || GET_MODE (target) != V2HImode
5693 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
5694 target = gen_reg_rtx (V2HImode);
5695 if (! register_operand (op0, GET_MODE (op0)))
5696 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
5697
5698 emit_insn (gen_flag_mulv2hi (tmp1, op0, op0, GEN_INT (MACFLAG_NONE)));
5699
5700 emit_insn (gen_flag_mulhi_parts (gen_lowpart (HImode, tmp2), op0, op0,
5701 const0_rtx, const1_rtx,
5702 GEN_INT (MACFLAG_NONE)));
5703
5704 emit_insn (gen_ssaddhi3_high_parts (target, tmp2, tmp2, tmp2, const0_rtx,
5705 const0_rtx));
5706 emit_insn (gen_sssubhi3_low_parts (target, target, tmp1, tmp1,
5707 const0_rtx, const1_rtx));
5708
5709 return target;
5710
5711 default:
5712 break;
5713 }
5714
5715 for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
5716 if (d->code == fcode)
5717 return bfin_expand_binop_builtin (d->icode, exp, target,
5718 d->macflag);
5719
5720 for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
5721 if (d->code == fcode)
5722 return bfin_expand_unop_builtin (d->icode, exp, target);
5723
5724 gcc_unreachable ();
5725 }
5726
5727 static void
5728 bfin_conditional_register_usage (void)
5729 {
5730 /* initialize condition code flag register rtx */
5731 bfin_cc_rtx = gen_rtx_REG (BImode, REG_CC);
5732 bfin_rets_rtx = gen_rtx_REG (Pmode, REG_RETS);
5733 if (TARGET_FDPIC)
5734 call_used_regs[FDPIC_REGNO] = 1;
5735 if (!TARGET_FDPIC && flag_pic)
5736 {
5737 fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
5738 call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
5739 }
5740 }
5741 \f
5742 #undef TARGET_INIT_BUILTINS
5743 #define TARGET_INIT_BUILTINS bfin_init_builtins
5744
5745 #undef TARGET_EXPAND_BUILTIN
5746 #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
5747
5748 #undef TARGET_ASM_GLOBALIZE_LABEL
5749 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label
5750
5751 #undef TARGET_ASM_FILE_START
5752 #define TARGET_ASM_FILE_START output_file_start
5753
5754 #undef TARGET_ATTRIBUTE_TABLE
5755 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
5756
5757 #undef TARGET_COMP_TYPE_ATTRIBUTES
5758 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
5759
5760 #undef TARGET_RTX_COSTS
5761 #define TARGET_RTX_COSTS bfin_rtx_costs
5762
5763 #undef TARGET_ADDRESS_COST
5764 #define TARGET_ADDRESS_COST bfin_address_cost
5765
5766 #undef TARGET_REGISTER_MOVE_COST
5767 #define TARGET_REGISTER_MOVE_COST bfin_register_move_cost
5768
5769 #undef TARGET_MEMORY_MOVE_COST
5770 #define TARGET_MEMORY_MOVE_COST bfin_memory_move_cost
5771
5772 #undef TARGET_ASM_INTEGER
5773 #define TARGET_ASM_INTEGER bfin_assemble_integer
5774
5775 #undef TARGET_MACHINE_DEPENDENT_REORG
5776 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
5777
5778 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
5779 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
5780
5781 #undef TARGET_ASM_OUTPUT_MI_THUNK
5782 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
5783 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
5784 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
5785
5786 #undef TARGET_SCHED_ADJUST_COST
5787 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
5788
5789 #undef TARGET_SCHED_ISSUE_RATE
5790 #define TARGET_SCHED_ISSUE_RATE bfin_issue_rate
5791
5792 #undef TARGET_PROMOTE_FUNCTION_MODE
5793 #define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
5794
5795 #undef TARGET_ARG_PARTIAL_BYTES
5796 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
5797
5798 #undef TARGET_FUNCTION_ARG
5799 #define TARGET_FUNCTION_ARG bfin_function_arg
5800
5801 #undef TARGET_FUNCTION_ARG_ADVANCE
5802 #define TARGET_FUNCTION_ARG_ADVANCE bfin_function_arg_advance
5803
5804 #undef TARGET_PASS_BY_REFERENCE
5805 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
5806
5807 #undef TARGET_SETUP_INCOMING_VARARGS
5808 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
5809
5810 #undef TARGET_STRUCT_VALUE_RTX
5811 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
5812
5813 #undef TARGET_VECTOR_MODE_SUPPORTED_P
5814 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
5815
5816 #undef TARGET_OPTION_OVERRIDE
5817 #define TARGET_OPTION_OVERRIDE bfin_option_override
5818
5819 #undef TARGET_SECONDARY_RELOAD
5820 #define TARGET_SECONDARY_RELOAD bfin_secondary_reload
5821
5822 #undef TARGET_CLASS_LIKELY_SPILLED_P
5823 #define TARGET_CLASS_LIKELY_SPILLED_P bfin_class_likely_spilled_p
5824
5825 #undef TARGET_DELEGITIMIZE_ADDRESS
5826 #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address
5827
5828 #undef TARGET_LEGITIMATE_CONSTANT_P
5829 #define TARGET_LEGITIMATE_CONSTANT_P bfin_legitimate_constant_p
5830
5831 #undef TARGET_CANNOT_FORCE_CONST_MEM
5832 #define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem
5833
5834 #undef TARGET_RETURN_IN_MEMORY
5835 #define TARGET_RETURN_IN_MEMORY bfin_return_in_memory
5836
5837 #undef TARGET_LRA_P
5838 #define TARGET_LRA_P hook_bool_void_false
5839
5840 #undef TARGET_LEGITIMATE_ADDRESS_P
5841 #define TARGET_LEGITIMATE_ADDRESS_P bfin_legitimate_address_p
5842
5843 #undef TARGET_FRAME_POINTER_REQUIRED
5844 #define TARGET_FRAME_POINTER_REQUIRED bfin_frame_pointer_required
5845
5846 #undef TARGET_CAN_ELIMINATE
5847 #define TARGET_CAN_ELIMINATE bfin_can_eliminate
5848
5849 #undef TARGET_CONDITIONAL_REGISTER_USAGE
5850 #define TARGET_CONDITIONAL_REGISTER_USAGE bfin_conditional_register_usage
5851
5852 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
5853 #define TARGET_ASM_TRAMPOLINE_TEMPLATE bfin_asm_trampoline_template
5854 #undef TARGET_TRAMPOLINE_INIT
5855 #define TARGET_TRAMPOLINE_INIT bfin_trampoline_init
5856
5857 #undef TARGET_EXTRA_LIVE_ON_ENTRY
5858 #define TARGET_EXTRA_LIVE_ON_ENTRY bfin_extra_live_on_entry
5859
5860 /* Passes after sched2 can break the helpful TImode annotations that
5861 haifa-sched puts on every insn. Just do scheduling in reorg. */
5862 #undef TARGET_DELAY_SCHED2
5863 #define TARGET_DELAY_SCHED2 true
5864
5865 /* Variable tracking should be run after all optimizations which
5866 change order of insns. It also needs a valid CFG. */
5867 #undef TARGET_DELAY_VARTRACK
5868 #define TARGET_DELAY_VARTRACK true
5869
5870 #undef TARGET_CAN_USE_DOLOOP_P
5871 #define TARGET_CAN_USE_DOLOOP_P bfin_can_use_doloop_p
5872
5873 #undef TARGET_HARD_REGNO_NREGS
5874 #define TARGET_HARD_REGNO_NREGS bfin_hard_regno_nregs
5875 #undef TARGET_HARD_REGNO_MODE_OK
5876 #define TARGET_HARD_REGNO_MODE_OK bfin_hard_regno_mode_ok
5877
5878 #undef TARGET_MODES_TIEABLE_P
5879 #define TARGET_MODES_TIEABLE_P bfin_modes_tieable_p
5880
5881 #undef TARGET_CONSTANT_ALIGNMENT
5882 #define TARGET_CONSTANT_ALIGNMENT constant_alignment_word_strings
5883
5884 struct gcc_target targetm = TARGET_INITIALIZER;