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