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