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