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