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