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