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