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