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