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