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