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