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