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