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