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