1 /* The Blackfin code generation auxiliary output file.
2 Copyright (C) 2005, 2006, 2007, 2008, 2009 Free Software Foundation, Inc.
3 Contributed by Analog Devices.
5 This file is part of GCC.
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 3, or (at your
10 option) any later version.
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.
17 You should have received a copy of the GNU General Public License
18 along with GCC; see the file COPYING3. If not see
19 <http://www.gnu.org/licenses/>. */
23 #include "coretypes.h"
27 #include "hard-reg-set.h"
29 #include "insn-config.h"
30 #include "insn-codes.h"
31 #include "conditions.h"
32 #include "insn-flags.h"
34 #include "insn-attr.h"
41 #include "target-def.h"
47 #include "integrate.h"
49 #include "langhooks.h"
50 #include "bfin-protos.h"
52 #include "tm-constrs.h"
54 #include "basic-block.h"
55 #include "cfglayout.h"
59 /* A C structure for machine-specific, per-function data.
60 This is added to the cfun structure. */
61 struct GTY(()) machine_function
63 /* Set if we are notified by the doloop pass that a hardware loop
65 int has_hardware_loops;
66 /* Set if we create a memcpy pattern that uses loop registers. */
67 int has_loopreg_clobber;
70 /* Test and compare insns in bfin.md store the information needed to
71 generate branch and scc insns here. */
72 rtx bfin_compare_op0, bfin_compare_op1;
74 /* RTX for condition code flag register and RETS register */
75 extern GTY(()) rtx bfin_cc_rtx;
76 extern GTY(()) rtx bfin_rets_rtx;
77 rtx bfin_cc_rtx, bfin_rets_rtx;
79 int max_arg_registers = 0;
81 /* Arrays used when emitting register names. */
82 const char *short_reg_names[] = SHORT_REGISTER_NAMES;
83 const char *high_reg_names[] = HIGH_REGISTER_NAMES;
84 const char *dregs_pair_names[] = DREGS_PAIR_NAMES;
85 const char *byte_reg_names[] = BYTE_REGISTER_NAMES;
87 static int arg_regs[] = FUNCTION_ARG_REGISTERS;
89 /* Nonzero if -mshared-library-id was given. */
90 static int bfin_lib_id_given;
92 /* Nonzero if -fschedule-insns2 was given. We override it and
93 call the scheduler ourselves during reorg. */
94 static int bfin_flag_schedule_insns2;
96 /* Determines whether we run variable tracking in machine dependent
98 static int bfin_flag_var_tracking;
101 bfin_cpu_t bfin_cpu_type = BFIN_CPU_UNKNOWN;
103 /* -msi-revision support. There are three special values:
104 -1 -msi-revision=none.
105 0xffff -msi-revision=any. */
106 int bfin_si_revision;
108 /* The workarounds enabled */
109 unsigned int bfin_workarounds = 0;
116 unsigned int workarounds;
119 struct bfin_cpu bfin_cpus[] =
121 {"bf512", BFIN_CPU_BF512, 0x0000,
122 WA_SPECULATIVE_LOADS},
124 {"bf514", BFIN_CPU_BF514, 0x0000,
125 WA_SPECULATIVE_LOADS},
127 {"bf516", BFIN_CPU_BF516, 0x0000,
128 WA_SPECULATIVE_LOADS},
130 {"bf518", BFIN_CPU_BF518, 0x0000,
131 WA_SPECULATIVE_LOADS},
133 {"bf522", BFIN_CPU_BF522, 0x0002,
134 WA_SPECULATIVE_LOADS},
135 {"bf522", BFIN_CPU_BF522, 0x0001,
136 WA_SPECULATIVE_LOADS | WA_RETS},
137 {"bf522", BFIN_CPU_BF522, 0x0000,
138 WA_SPECULATIVE_LOADS | WA_RETS},
140 {"bf523", BFIN_CPU_BF523, 0x0002,
141 WA_SPECULATIVE_LOADS},
142 {"bf523", BFIN_CPU_BF523, 0x0001,
143 WA_SPECULATIVE_LOADS | WA_RETS},
144 {"bf523", BFIN_CPU_BF523, 0x0000,
145 WA_SPECULATIVE_LOADS | WA_RETS},
147 {"bf524", BFIN_CPU_BF524, 0x0002,
148 WA_SPECULATIVE_LOADS},
149 {"bf524", BFIN_CPU_BF524, 0x0001,
150 WA_SPECULATIVE_LOADS | WA_RETS},
151 {"bf524", BFIN_CPU_BF524, 0x0000,
152 WA_SPECULATIVE_LOADS | WA_RETS},
154 {"bf525", BFIN_CPU_BF525, 0x0002,
155 WA_SPECULATIVE_LOADS},
156 {"bf525", BFIN_CPU_BF525, 0x0001,
157 WA_SPECULATIVE_LOADS | WA_RETS},
158 {"bf525", BFIN_CPU_BF525, 0x0000,
159 WA_SPECULATIVE_LOADS | WA_RETS},
161 {"bf526", BFIN_CPU_BF526, 0x0002,
162 WA_SPECULATIVE_LOADS},
163 {"bf526", BFIN_CPU_BF526, 0x0001,
164 WA_SPECULATIVE_LOADS | WA_RETS},
165 {"bf526", BFIN_CPU_BF526, 0x0000,
166 WA_SPECULATIVE_LOADS | WA_RETS},
168 {"bf527", BFIN_CPU_BF527, 0x0002,
169 WA_SPECULATIVE_LOADS},
170 {"bf527", BFIN_CPU_BF527, 0x0001,
171 WA_SPECULATIVE_LOADS | WA_RETS},
172 {"bf527", BFIN_CPU_BF527, 0x0000,
173 WA_SPECULATIVE_LOADS | WA_RETS},
175 {"bf531", BFIN_CPU_BF531, 0x0006,
176 WA_SPECULATIVE_LOADS},
177 {"bf531", BFIN_CPU_BF531, 0x0005,
178 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315},
179 {"bf531", BFIN_CPU_BF531, 0x0004,
180 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
181 | WA_05000283 | WA_05000257 | WA_05000315},
182 {"bf531", BFIN_CPU_BF531, 0x0003,
183 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
184 | WA_05000283 | WA_05000257 | WA_05000315},
186 {"bf532", BFIN_CPU_BF532, 0x0006,
187 WA_SPECULATIVE_LOADS},
188 {"bf532", BFIN_CPU_BF532, 0x0005,
189 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315},
190 {"bf532", BFIN_CPU_BF532, 0x0004,
191 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
192 | WA_05000283 | WA_05000257 | WA_05000315},
193 {"bf532", BFIN_CPU_BF532, 0x0003,
194 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
195 | WA_05000283 | WA_05000257 | WA_05000315},
197 {"bf533", BFIN_CPU_BF533, 0x0006,
198 WA_SPECULATIVE_LOADS},
199 {"bf533", BFIN_CPU_BF533, 0x0005,
200 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315},
201 {"bf533", BFIN_CPU_BF533, 0x0004,
202 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
203 | WA_05000283 | WA_05000257 | WA_05000315},
204 {"bf533", BFIN_CPU_BF533, 0x0003,
205 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
206 | WA_05000283 | WA_05000257 | WA_05000315},
208 {"bf534", BFIN_CPU_BF534, 0x0003,
209 WA_SPECULATIVE_LOADS | WA_RETS},
210 {"bf534", BFIN_CPU_BF534, 0x0002,
211 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
212 | WA_05000283 | WA_05000257 | WA_05000315},
213 {"bf534", BFIN_CPU_BF534, 0x0001,
214 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
215 | WA_05000283 | WA_05000257 | WA_05000315},
217 {"bf536", BFIN_CPU_BF536, 0x0003,
218 WA_SPECULATIVE_LOADS | WA_RETS},
219 {"bf536", BFIN_CPU_BF536, 0x0002,
220 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
221 | WA_05000283 | WA_05000257 | WA_05000315},
222 {"bf536", BFIN_CPU_BF536, 0x0001,
223 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
224 | WA_05000283 | WA_05000257 | WA_05000315},
226 {"bf537", BFIN_CPU_BF537, 0x0003,
227 WA_SPECULATIVE_LOADS | WA_RETS},
228 {"bf537", BFIN_CPU_BF537, 0x0002,
229 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
230 | WA_05000283 | WA_05000257 | WA_05000315},
231 {"bf537", BFIN_CPU_BF537, 0x0001,
232 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
233 | WA_05000283 | WA_05000257 | WA_05000315},
235 {"bf538", BFIN_CPU_BF538, 0x0005,
236 WA_SPECULATIVE_LOADS},
237 {"bf538", BFIN_CPU_BF538, 0x0004,
238 WA_SPECULATIVE_LOADS | WA_RETS},
239 {"bf538", BFIN_CPU_BF538, 0x0003,
240 WA_SPECULATIVE_LOADS | WA_RETS
241 | WA_05000283 | WA_05000315},
242 {"bf538", BFIN_CPU_BF538, 0x0002,
243 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000257 | WA_05000315},
245 {"bf539", BFIN_CPU_BF539, 0x0005,
246 WA_SPECULATIVE_LOADS},
247 {"bf539", BFIN_CPU_BF539, 0x0004,
248 WA_SPECULATIVE_LOADS | WA_RETS},
249 {"bf539", BFIN_CPU_BF539, 0x0003,
250 WA_SPECULATIVE_LOADS | WA_RETS
251 | WA_05000283 | WA_05000315},
252 {"bf539", BFIN_CPU_BF539, 0x0002,
253 WA_SPECULATIVE_LOADS | WA_RETS
254 | WA_05000283 | WA_05000257 | WA_05000315},
256 {"bf542", BFIN_CPU_BF542, 0x0002,
257 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS},
258 {"bf542", BFIN_CPU_BF542, 0x0001,
259 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
260 {"bf542", BFIN_CPU_BF542, 0x0000,
261 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
263 {"bf544", BFIN_CPU_BF544, 0x0002,
264 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS},
265 {"bf544", BFIN_CPU_BF544, 0x0001,
266 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
267 {"bf544", BFIN_CPU_BF544, 0x0000,
268 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
270 {"bf547", BFIN_CPU_BF547, 0x0002,
271 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS},
272 {"bf547", BFIN_CPU_BF547, 0x0001,
273 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
274 {"bf547", BFIN_CPU_BF547, 0x0000,
275 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
277 {"bf548", BFIN_CPU_BF548, 0x0002,
278 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS},
279 {"bf548", BFIN_CPU_BF548, 0x0001,
280 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
281 {"bf548", BFIN_CPU_BF548, 0x0000,
282 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
284 {"bf549", BFIN_CPU_BF549, 0x0002,
285 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS},
286 {"bf549", BFIN_CPU_BF549, 0x0001,
287 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
288 {"bf549", BFIN_CPU_BF549, 0x0000,
289 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS},
291 {"bf561", BFIN_CPU_BF561, 0x0005, WA_RETS
292 | WA_05000283 | WA_05000315},
293 {"bf561", BFIN_CPU_BF561, 0x0003,
294 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
295 | WA_05000283 | WA_05000257 | WA_05000315},
296 {"bf561", BFIN_CPU_BF561, 0x0002,
297 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
298 | WA_05000283 | WA_05000257 | WA_05000315},
303 int splitting_for_sched;
306 bfin_globalize_label (FILE *stream, const char *name)
308 fputs (".global ", stream);
309 assemble_name (stream, name);
315 output_file_start (void)
317 FILE *file = asm_out_file;
320 /* Variable tracking should be run after all optimizations which change order
321 of insns. It also needs a valid CFG. This can't be done in
322 override_options, because flag_var_tracking is finalized after
324 bfin_flag_var_tracking = flag_var_tracking;
325 flag_var_tracking = 0;
327 fprintf (file, ".file \"%s\";\n", input_filename);
329 for (i = 0; arg_regs[i] >= 0; i++)
331 max_arg_registers = i; /* how many arg reg used */
334 /* Called early in the compilation to conditionally modify
335 fixed_regs/call_used_regs. */
338 conditional_register_usage (void)
340 /* initialize condition code flag register rtx */
341 bfin_cc_rtx = gen_rtx_REG (BImode, REG_CC);
342 bfin_rets_rtx = gen_rtx_REG (Pmode, REG_RETS);
345 /* Examine machine-dependent attributes of function type FUNTYPE and return its
346 type. See the definition of E_FUNKIND. */
349 funkind (const_tree funtype)
351 tree attrs = TYPE_ATTRIBUTES (funtype);
352 if (lookup_attribute ("interrupt_handler", attrs))
353 return INTERRUPT_HANDLER;
354 else if (lookup_attribute ("exception_handler", attrs))
355 return EXCPT_HANDLER;
356 else if (lookup_attribute ("nmi_handler", attrs))
362 /* Legitimize PIC addresses. If the address is already position-independent,
363 we return ORIG. Newly generated position-independent addresses go into a
364 reg. This is REG if nonzero, otherwise we allocate register(s) as
365 necessary. PICREG is the register holding the pointer to the PIC offset
369 legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
374 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
379 if (TARGET_ID_SHARED_LIBRARY)
380 unspec = UNSPEC_MOVE_PIC;
381 else if (GET_CODE (addr) == SYMBOL_REF
382 && SYMBOL_REF_FUNCTION_P (addr))
383 unspec = UNSPEC_FUNCDESC_GOT17M4;
385 unspec = UNSPEC_MOVE_FDPIC;
389 gcc_assert (can_create_pseudo_p ());
390 reg = gen_reg_rtx (Pmode);
393 tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), unspec);
394 new_rtx = gen_const_mem (Pmode, gen_rtx_PLUS (Pmode, picreg, tmp));
396 emit_move_insn (reg, new_rtx);
397 if (picreg == pic_offset_table_rtx)
398 crtl->uses_pic_offset_table = 1;
402 else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
406 if (GET_CODE (addr) == CONST)
408 addr = XEXP (addr, 0);
409 gcc_assert (GET_CODE (addr) == PLUS);
412 if (XEXP (addr, 0) == picreg)
417 gcc_assert (can_create_pseudo_p ());
418 reg = gen_reg_rtx (Pmode);
421 base = legitimize_pic_address (XEXP (addr, 0), reg, picreg);
422 addr = legitimize_pic_address (XEXP (addr, 1),
423 base == reg ? NULL_RTX : reg,
426 if (GET_CODE (addr) == CONST_INT)
428 gcc_assert (! reload_in_progress && ! reload_completed);
429 addr = force_reg (Pmode, addr);
432 if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
434 base = gen_rtx_PLUS (Pmode, base, XEXP (addr, 0));
435 addr = XEXP (addr, 1);
438 return gen_rtx_PLUS (Pmode, base, addr);
444 /* Stack frame layout. */
446 /* For a given REGNO, determine whether it must be saved in the function
447 prologue. IS_INTHANDLER specifies whether we're generating a normal
448 prologue or an interrupt/exception one. */
450 must_save_p (bool is_inthandler, unsigned regno)
452 if (D_REGNO_P (regno))
454 bool is_eh_return_reg = false;
455 if (crtl->calls_eh_return)
460 unsigned test = EH_RETURN_DATA_REGNO (j);
461 if (test == INVALID_REGNUM)
464 is_eh_return_reg = true;
468 return (is_eh_return_reg
469 || (df_regs_ever_live_p (regno)
470 && !fixed_regs[regno]
471 && (is_inthandler || !call_used_regs[regno])));
473 else if (P_REGNO_P (regno))
475 return ((df_regs_ever_live_p (regno)
476 && !fixed_regs[regno]
477 && (is_inthandler || !call_used_regs[regno]))
479 && (ENABLE_WA_05000283 || ENABLE_WA_05000315)
482 && regno == PIC_OFFSET_TABLE_REGNUM
483 && (crtl->uses_pic_offset_table
484 || (TARGET_ID_SHARED_LIBRARY && !current_function_is_leaf))));
487 return ((is_inthandler || !call_used_regs[regno])
488 && (df_regs_ever_live_p (regno)
489 || (!leaf_function_p () && call_used_regs[regno])));
493 /* Compute the number of DREGS to save with a push_multiple operation.
494 This could include registers that aren't modified in the function,
495 since push_multiple only takes a range of registers.
496 If IS_INTHANDLER, then everything that is live must be saved, even
497 if normally call-clobbered.
498 If CONSECUTIVE, return the number of registers we can save in one
499 instruction with a push/pop multiple instruction. */
502 n_dregs_to_save (bool is_inthandler, bool consecutive)
507 for (i = REG_R7 + 1; i-- != REG_R0;)
509 if (must_save_p (is_inthandler, i))
511 else if (consecutive)
517 /* Like n_dregs_to_save, but compute number of PREGS to save. */
520 n_pregs_to_save (bool is_inthandler, bool consecutive)
525 for (i = REG_P5 + 1; i-- != REG_P0;)
526 if (must_save_p (is_inthandler, i))
528 else if (consecutive)
533 /* Determine if we are going to save the frame pointer in the prologue. */
536 must_save_fp_p (void)
538 return frame_pointer_needed || df_regs_ever_live_p (REG_FP);
542 stack_frame_needed_p (void)
544 /* EH return puts a new return address into the frame using an
545 address relative to the frame pointer. */
546 if (crtl->calls_eh_return)
548 return frame_pointer_needed;
551 /* Emit code to save registers in the prologue. SAVEALL is nonzero if we
552 must save all registers; this is used for interrupt handlers.
553 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
554 this for an interrupt (or exception) handler. */
557 expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler)
559 rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
560 rtx predec = gen_rtx_MEM (SImode, predec1);
561 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler, false);
562 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler, false);
563 int ndregs_consec = saveall ? 8 : n_dregs_to_save (is_inthandler, true);
564 int npregs_consec = saveall ? 6 : n_pregs_to_save (is_inthandler, true);
566 int total_consec = ndregs_consec + npregs_consec;
569 if (saveall || is_inthandler)
571 rtx insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
573 RTX_FRAME_RELATED_P (insn) = 1;
574 for (dregno = REG_LT0; dregno <= REG_LB1; dregno++)
575 if (! current_function_is_leaf
576 || cfun->machine->has_hardware_loops
577 || cfun->machine->has_loopreg_clobber
578 || (ENABLE_WA_05000257
579 && (dregno == REG_LC0 || dregno == REG_LC1)))
581 insn = emit_move_insn (predec, gen_rtx_REG (SImode, dregno));
582 RTX_FRAME_RELATED_P (insn) = 1;
586 if (total_consec != 0)
589 rtx val = GEN_INT (-total_consec * 4);
590 rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_consec + 2));
592 XVECEXP (pat, 0, 0) = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, val),
593 UNSPEC_PUSH_MULTIPLE);
594 XVECEXP (pat, 0, total_consec + 1) = gen_rtx_SET (VOIDmode, spreg,
598 RTX_FRAME_RELATED_P (XVECEXP (pat, 0, total_consec + 1)) = 1;
599 d_to_save = ndregs_consec;
600 dregno = REG_R7 + 1 - ndregs_consec;
601 pregno = REG_P5 + 1 - npregs_consec;
602 for (i = 0; i < total_consec; i++)
604 rtx memref = gen_rtx_MEM (word_mode,
605 gen_rtx_PLUS (Pmode, spreg,
606 GEN_INT (- i * 4 - 4)));
610 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
616 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
619 XVECEXP (pat, 0, i + 1) = subpat;
620 RTX_FRAME_RELATED_P (subpat) = 1;
622 insn = emit_insn (pat);
623 RTX_FRAME_RELATED_P (insn) = 1;
626 for (dregno = REG_R0; ndregs != ndregs_consec; dregno++)
628 if (must_save_p (is_inthandler, dregno))
630 rtx insn = emit_move_insn (predec, gen_rtx_REG (word_mode, dregno));
631 RTX_FRAME_RELATED_P (insn) = 1;
635 for (pregno = REG_P0; npregs != npregs_consec; pregno++)
637 if (must_save_p (is_inthandler, pregno))
639 rtx insn = emit_move_insn (predec, gen_rtx_REG (word_mode, pregno));
640 RTX_FRAME_RELATED_P (insn) = 1;
644 for (i = REG_P7 + 1; i < REG_CC; i++)
647 && (df_regs_ever_live_p (i)
648 || (!leaf_function_p () && call_used_regs[i]))))
651 if (i == REG_A0 || i == REG_A1)
652 insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1),
653 gen_rtx_REG (PDImode, i));
655 insn = emit_move_insn (predec, gen_rtx_REG (SImode, i));
656 RTX_FRAME_RELATED_P (insn) = 1;
660 /* Emit code to restore registers in the epilogue. SAVEALL is nonzero if we
661 must save all registers; this is used for interrupt handlers.
662 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
663 this for an interrupt (or exception) handler. */
666 expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler)
668 rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
669 rtx postinc = gen_rtx_MEM (SImode, postinc1);
671 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler, false);
672 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler, false);
673 int ndregs_consec = saveall ? 8 : n_dregs_to_save (is_inthandler, true);
674 int npregs_consec = saveall ? 6 : n_pregs_to_save (is_inthandler, true);
675 int total_consec = ndregs_consec + npregs_consec;
679 /* A slightly crude technique to stop flow from trying to delete "dead"
681 MEM_VOLATILE_P (postinc) = 1;
683 for (i = REG_CC - 1; i > REG_P7; i--)
686 && (df_regs_ever_live_p (i)
687 || (!leaf_function_p () && call_used_regs[i]))))
689 if (i == REG_A0 || i == REG_A1)
691 rtx mem = gen_rtx_MEM (PDImode, postinc1);
692 MEM_VOLATILE_P (mem) = 1;
693 emit_move_insn (gen_rtx_REG (PDImode, i), mem);
696 emit_move_insn (gen_rtx_REG (SImode, i), postinc);
699 regno = REG_P5 - npregs_consec;
700 for (; npregs != npregs_consec; regno--)
702 if (must_save_p (is_inthandler, regno))
704 emit_move_insn (gen_rtx_REG (word_mode, regno), postinc);
708 regno = REG_R7 - ndregs_consec;
709 for (; ndregs != ndregs_consec; regno--)
711 if (must_save_p (is_inthandler, regno))
713 emit_move_insn (gen_rtx_REG (word_mode, regno), postinc);
718 if (total_consec != 0)
720 rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_consec + 1));
722 = gen_rtx_SET (VOIDmode, spreg,
723 gen_rtx_PLUS (Pmode, spreg,
724 GEN_INT (total_consec * 4)));
726 if (npregs_consec > 0)
731 for (i = 0; i < total_consec; i++)
734 ? gen_rtx_PLUS (Pmode, spreg, GEN_INT (i * 4))
736 rtx memref = gen_rtx_MEM (word_mode, addr);
739 XVECEXP (pat, 0, i + 1)
740 = gen_rtx_SET (VOIDmode, gen_rtx_REG (word_mode, regno), memref);
742 if (npregs_consec > 0)
744 if (--npregs_consec == 0)
749 insn = emit_insn (pat);
750 RTX_FRAME_RELATED_P (insn) = 1;
752 if (saveall || is_inthandler)
754 for (regno = REG_LB1; regno >= REG_LT0; regno--)
755 if (! current_function_is_leaf
756 || cfun->machine->has_hardware_loops
757 || cfun->machine->has_loopreg_clobber
758 || (ENABLE_WA_05000257 && (regno == REG_LC0 || regno == REG_LC1)))
759 emit_move_insn (gen_rtx_REG (SImode, regno), postinc);
761 emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
765 /* Perform any needed actions needed for a function that is receiving a
766 variable number of arguments.
770 MODE and TYPE are the mode and type of the current parameter.
772 PRETEND_SIZE is a variable that should be set to the amount of stack
773 that must be pushed by the prolog to pretend that our caller pushed
776 Normally, this macro will push all remaining incoming registers on the
777 stack and set PRETEND_SIZE to the length of the registers pushed.
780 - VDSP C compiler manual (our ABI) says that a variable args function
781 should save the R0, R1 and R2 registers in the stack.
782 - The caller will always leave space on the stack for the
783 arguments that are passed in registers, so we dont have
784 to leave any extra space.
785 - now, the vastart pointer can access all arguments from the stack. */
788 setup_incoming_varargs (CUMULATIVE_ARGS *cum,
789 enum machine_mode mode ATTRIBUTE_UNUSED,
790 tree type ATTRIBUTE_UNUSED, int *pretend_size,
799 /* The move for named arguments will be generated automatically by the
800 compiler. We need to generate the move rtx for the unnamed arguments
801 if they are in the first 3 words. We assume at least 1 named argument
802 exists, so we never generate [ARGP] = R0 here. */
804 for (i = cum->words + 1; i < max_arg_registers; i++)
806 mem = gen_rtx_MEM (Pmode,
807 plus_constant (arg_pointer_rtx, (i * UNITS_PER_WORD)));
808 emit_move_insn (mem, gen_rtx_REG (Pmode, i));
814 /* Value should be nonzero if functions must have frame pointers.
815 Zero means the frame pointer need not be set up (and parms may
816 be accessed via the stack pointer) in functions that seem suitable. */
819 bfin_frame_pointer_required (void)
821 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
823 if (fkind != SUBROUTINE)
826 /* We turn on -fomit-frame-pointer if -momit-leaf-frame-pointer is used,
827 so we have to override it for non-leaf functions. */
828 if (TARGET_OMIT_LEAF_FRAME_POINTER && ! current_function_is_leaf)
834 /* Return the number of registers pushed during the prologue. */
837 n_regs_saved_by_prologue (void)
839 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
840 bool is_inthandler = fkind != SUBROUTINE;
841 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
842 bool all = (lookup_attribute ("saveall", attrs) != NULL_TREE
843 || (is_inthandler && !current_function_is_leaf));
844 int ndregs = all ? 8 : n_dregs_to_save (is_inthandler, false);
845 int npregs = all ? 6 : n_pregs_to_save (is_inthandler, false);
846 int n = ndregs + npregs;
849 if (all || stack_frame_needed_p ())
850 /* We use a LINK instruction in this case. */
854 if (must_save_fp_p ())
856 if (! current_function_is_leaf)
860 if (fkind != SUBROUTINE || all)
862 /* Increment once for ASTAT. */
864 if (! current_function_is_leaf
865 || cfun->machine->has_hardware_loops
866 || cfun->machine->has_loopreg_clobber)
872 if (fkind != SUBROUTINE)
875 if (lookup_attribute ("nesting", attrs))
879 for (i = REG_P7 + 1; i < REG_CC; i++)
881 || (fkind != SUBROUTINE
882 && (df_regs_ever_live_p (i)
883 || (!leaf_function_p () && call_used_regs[i]))))
884 n += i == REG_A0 || i == REG_A1 ? 2 : 1;
889 /* Return the offset between two registers, one to be eliminated, and the other
890 its replacement, at the start of a routine. */
893 bfin_initial_elimination_offset (int from, int to)
895 HOST_WIDE_INT offset = 0;
897 if (from == ARG_POINTER_REGNUM)
898 offset = n_regs_saved_by_prologue () * 4;
900 if (to == STACK_POINTER_REGNUM)
902 if (crtl->outgoing_args_size >= FIXED_STACK_AREA)
903 offset += crtl->outgoing_args_size;
904 else if (crtl->outgoing_args_size)
905 offset += FIXED_STACK_AREA;
907 offset += get_frame_size ();
913 /* Emit code to load a constant CONSTANT into register REG; setting
914 RTX_FRAME_RELATED_P on all insns we generate if RELATED is true.
915 Make sure that the insns we generate need not be split. */
918 frame_related_constant_load (rtx reg, HOST_WIDE_INT constant, bool related)
921 rtx cst = GEN_INT (constant);
923 if (constant >= -32768 && constant < 65536)
924 insn = emit_move_insn (reg, cst);
927 /* We don't call split_load_immediate here, since dwarf2out.c can get
928 confused about some of the more clever sequences it can generate. */
929 insn = emit_insn (gen_movsi_high (reg, cst));
931 RTX_FRAME_RELATED_P (insn) = 1;
932 insn = emit_insn (gen_movsi_low (reg, reg, cst));
935 RTX_FRAME_RELATED_P (insn) = 1;
938 /* Generate efficient code to add a value to a P register.
939 Set RTX_FRAME_RELATED_P on the generated insns if FRAME is nonzero.
940 EPILOGUE_P is zero if this function is called for prologue,
941 otherwise it's nonzero. And it's less than zero if this is for
945 add_to_reg (rtx reg, HOST_WIDE_INT value, int frame, int epilogue_p)
950 /* Choose whether to use a sequence using a temporary register, or
951 a sequence with multiple adds. We can add a signed 7-bit value
952 in one instruction. */
953 if (value > 120 || value < -120)
961 /* For prologue or normal epilogue, P1 can be safely used
962 as the temporary register. For sibcall epilogue, we try to find
963 a call used P register, which will be restored in epilogue.
964 If we cannot find such a P register, we have to use one I register
968 tmpreg = gen_rtx_REG (SImode, REG_P1);
972 for (i = REG_P0; i <= REG_P5; i++)
973 if ((df_regs_ever_live_p (i) && ! call_used_regs[i])
975 && i == PIC_OFFSET_TABLE_REGNUM
976 && (crtl->uses_pic_offset_table
977 || (TARGET_ID_SHARED_LIBRARY
978 && ! current_function_is_leaf))))
981 tmpreg = gen_rtx_REG (SImode, i);
984 tmpreg = gen_rtx_REG (SImode, REG_P1);
985 tmpreg2 = gen_rtx_REG (SImode, REG_I0);
986 emit_move_insn (tmpreg2, tmpreg);
991 frame_related_constant_load (tmpreg, value, TRUE);
993 insn = emit_move_insn (tmpreg, GEN_INT (value));
995 insn = emit_insn (gen_addsi3 (reg, reg, tmpreg));
997 RTX_FRAME_RELATED_P (insn) = 1;
999 if (tmpreg2 != NULL_RTX)
1000 emit_move_insn (tmpreg, tmpreg2);
1010 else if (size < -60)
1011 /* We could use -62, but that would leave the stack unaligned, so
1015 insn = emit_insn (gen_addsi3 (reg, reg, GEN_INT (size)));
1017 RTX_FRAME_RELATED_P (insn) = 1;
1023 /* Generate a LINK insn for a frame sized FRAME_SIZE. If this constant
1024 is too large, generate a sequence of insns that has the same effect.
1025 SPREG contains (reg:SI REG_SP). */
1028 emit_link_insn (rtx spreg, HOST_WIDE_INT frame_size)
1030 HOST_WIDE_INT link_size = frame_size;
1034 if (link_size > 262140)
1037 /* Use a LINK insn with as big a constant as possible, then subtract
1038 any remaining size from the SP. */
1039 insn = emit_insn (gen_link (GEN_INT (-8 - link_size)));
1040 RTX_FRAME_RELATED_P (insn) = 1;
1042 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
1044 rtx set = XVECEXP (PATTERN (insn), 0, i);
1045 gcc_assert (GET_CODE (set) == SET);
1046 RTX_FRAME_RELATED_P (set) = 1;
1049 frame_size -= link_size;
1053 /* Must use a call-clobbered PREG that isn't the static chain. */
1054 rtx tmpreg = gen_rtx_REG (Pmode, REG_P1);
1056 frame_related_constant_load (tmpreg, -frame_size, TRUE);
1057 insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg));
1058 RTX_FRAME_RELATED_P (insn) = 1;
1062 /* Return the number of bytes we must reserve for outgoing arguments
1063 in the current function's stack frame. */
1065 static HOST_WIDE_INT
1066 arg_area_size (void)
1068 if (crtl->outgoing_args_size)
1070 if (crtl->outgoing_args_size >= FIXED_STACK_AREA)
1071 return crtl->outgoing_args_size;
1073 return FIXED_STACK_AREA;
1078 /* Save RETS and FP, and allocate a stack frame. ALL is true if the
1079 function must save all its registers (true only for certain interrupt
1083 do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all)
1085 frame_size += arg_area_size ();
1087 if (all || stack_frame_needed_p ()
1088 || (must_save_fp_p () && ! current_function_is_leaf))
1089 emit_link_insn (spreg, frame_size);
1092 if (! current_function_is_leaf)
1094 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
1095 gen_rtx_PRE_DEC (Pmode, spreg)),
1097 rtx insn = emit_insn (pat);
1098 RTX_FRAME_RELATED_P (insn) = 1;
1100 if (must_save_fp_p ())
1102 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
1103 gen_rtx_PRE_DEC (Pmode, spreg)),
1104 gen_rtx_REG (Pmode, REG_FP));
1105 rtx insn = emit_insn (pat);
1106 RTX_FRAME_RELATED_P (insn) = 1;
1108 add_to_reg (spreg, -frame_size, 1, 0);
1112 /* Like do_link, but used for epilogues to deallocate the stack frame.
1113 EPILOGUE_P is zero if this function is called for prologue,
1114 otherwise it's nonzero. And it's less than zero if this is for
1115 sibcall epilogue. */
1118 do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all, int epilogue_p)
1120 frame_size += arg_area_size ();
1122 if (all || stack_frame_needed_p ())
1123 emit_insn (gen_unlink ());
1126 rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg));
1128 add_to_reg (spreg, frame_size, 0, epilogue_p);
1129 if (must_save_fp_p ())
1131 rtx fpreg = gen_rtx_REG (Pmode, REG_FP);
1132 emit_move_insn (fpreg, postinc);
1135 if (! current_function_is_leaf)
1137 emit_move_insn (bfin_rets_rtx, postinc);
1138 emit_use (bfin_rets_rtx);
1143 /* Generate a prologue suitable for a function of kind FKIND. This is
1144 called for interrupt and exception handler prologues.
1145 SPREG contains (reg:SI REG_SP). */
1148 expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind, bool all)
1150 HOST_WIDE_INT frame_size = get_frame_size ();
1151 rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
1152 rtx predec = gen_rtx_MEM (SImode, predec1);
1154 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1155 tree kspisusp = lookup_attribute ("kspisusp", attrs);
1159 insn = emit_move_insn (spreg, gen_rtx_REG (Pmode, REG_USP));
1160 RTX_FRAME_RELATED_P (insn) = 1;
1163 /* We need space on the stack in case we need to save the argument
1165 if (fkind == EXCPT_HANDLER)
1167 insn = emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (-12)));
1168 RTX_FRAME_RELATED_P (insn) = 1;
1171 /* If we're calling other functions, they won't save their call-clobbered
1172 registers, so we must save everything here. */
1173 if (!current_function_is_leaf)
1175 expand_prologue_reg_save (spreg, all, true);
1177 if (ENABLE_WA_05000283 || ENABLE_WA_05000315)
1179 rtx chipid = GEN_INT (trunc_int_for_mode (0xFFC00014, SImode));
1180 rtx p5reg = gen_rtx_REG (Pmode, REG_P5);
1181 emit_insn (gen_movbi (bfin_cc_rtx, const1_rtx));
1182 emit_insn (gen_movsi_high (p5reg, chipid));
1183 emit_insn (gen_movsi_low (p5reg, p5reg, chipid));
1184 emit_insn (gen_dummy_load (p5reg, bfin_cc_rtx));
1187 if (lookup_attribute ("nesting", attrs))
1189 rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
1190 : fkind == NMI_HANDLER ? REG_RETN
1192 insn = emit_move_insn (predec, srcreg);
1193 RTX_FRAME_RELATED_P (insn) = 1;
1196 do_link (spreg, frame_size, all);
1198 if (fkind == EXCPT_HANDLER)
1200 rtx r0reg = gen_rtx_REG (SImode, REG_R0);
1201 rtx r1reg = gen_rtx_REG (SImode, REG_R1);
1202 rtx r2reg = gen_rtx_REG (SImode, REG_R2);
1205 insn = emit_move_insn (r0reg, gen_rtx_REG (SImode, REG_SEQSTAT));
1206 insn = emit_insn (gen_ashrsi3 (r0reg, r0reg, GEN_INT (26)));
1207 insn = emit_insn (gen_ashlsi3 (r0reg, r0reg, GEN_INT (26)));
1208 insn = emit_move_insn (r1reg, spreg);
1209 insn = emit_move_insn (r2reg, gen_rtx_REG (Pmode, REG_FP));
1210 insn = emit_insn (gen_addsi3 (r2reg, r2reg, GEN_INT (8)));
1214 /* Generate an epilogue suitable for a function of kind FKIND. This is
1215 called for interrupt and exception handler epilogues.
1216 SPREG contains (reg:SI REG_SP). */
1219 expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind, bool all)
1221 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1222 rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
1223 rtx postinc = gen_rtx_MEM (SImode, postinc1);
1225 /* A slightly crude technique to stop flow from trying to delete "dead"
1227 MEM_VOLATILE_P (postinc) = 1;
1229 do_unlink (spreg, get_frame_size (), all, 1);
1231 if (lookup_attribute ("nesting", attrs))
1233 rtx srcreg = gen_rtx_REG (Pmode, (fkind == EXCPT_HANDLER ? REG_RETX
1234 : fkind == NMI_HANDLER ? REG_RETN
1236 emit_move_insn (srcreg, postinc);
1239 /* If we're calling other functions, they won't save their call-clobbered
1240 registers, so we must save (and restore) everything here. */
1241 if (!current_function_is_leaf)
1244 expand_epilogue_reg_restore (spreg, all, true);
1246 /* Deallocate any space we left on the stack in case we needed to save the
1247 argument registers. */
1248 if (fkind == EXCPT_HANDLER)
1249 emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (12)));
1251 emit_jump_insn (gen_return_internal (GEN_INT (fkind)));
1254 /* Used while emitting the prologue to generate code to load the correct value
1255 into the PIC register, which is passed in DEST. */
1258 bfin_load_pic_reg (rtx dest)
1260 struct cgraph_local_info *i = NULL;
1263 i = cgraph_local_info (current_function_decl);
1265 /* Functions local to the translation unit don't need to reload the
1266 pic reg, since the caller always passes a usable one. */
1268 return pic_offset_table_rtx;
1270 if (bfin_lib_id_given)
1271 addr = plus_constant (pic_offset_table_rtx, -4 - bfin_library_id * 4);
1273 addr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
1274 gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
1275 UNSPEC_LIBRARY_OFFSET));
1276 insn = emit_insn (gen_movsi (dest, gen_rtx_MEM (Pmode, addr)));
1280 /* Generate RTL for the prologue of the current function. */
1283 bfin_expand_prologue (void)
1285 HOST_WIDE_INT frame_size = get_frame_size ();
1286 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
1287 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1288 rtx pic_reg_loaded = NULL_RTX;
1289 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1290 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
1292 if (fkind != SUBROUTINE)
1294 expand_interrupt_handler_prologue (spreg, fkind, all);
1298 if (crtl->limit_stack
1299 || (TARGET_STACK_CHECK_L1
1300 && !DECL_NO_LIMIT_STACK (current_function_decl)))
1302 HOST_WIDE_INT offset
1303 = bfin_initial_elimination_offset (ARG_POINTER_REGNUM,
1304 STACK_POINTER_REGNUM);
1305 rtx lim = crtl->limit_stack ? stack_limit_rtx : NULL_RTX;
1306 rtx p2reg = gen_rtx_REG (Pmode, REG_P2);
1310 emit_move_insn (p2reg, gen_int_mode (0xFFB00000, SImode));
1311 emit_move_insn (p2reg, gen_rtx_MEM (Pmode, p2reg));
1314 if (GET_CODE (lim) == SYMBOL_REF)
1316 if (TARGET_ID_SHARED_LIBRARY)
1318 rtx p1reg = gen_rtx_REG (Pmode, REG_P1);
1320 pic_reg_loaded = bfin_load_pic_reg (p2reg);
1321 val = legitimize_pic_address (stack_limit_rtx, p1reg,
1323 emit_move_insn (p1reg, val);
1324 frame_related_constant_load (p2reg, offset, FALSE);
1325 emit_insn (gen_addsi3 (p2reg, p2reg, p1reg));
1330 rtx limit = plus_constant (lim, offset);
1331 emit_move_insn (p2reg, limit);
1338 emit_move_insn (p2reg, lim);
1339 add_to_reg (p2reg, offset, 0, 0);
1342 emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim));
1343 emit_insn (gen_trapifcc ());
1345 expand_prologue_reg_save (spreg, all, false);
1347 do_link (spreg, frame_size, false);
1349 if (TARGET_ID_SHARED_LIBRARY
1351 && (crtl->uses_pic_offset_table
1352 || !current_function_is_leaf))
1353 bfin_load_pic_reg (pic_offset_table_rtx);
1356 /* Generate RTL for the epilogue of the current function. NEED_RETURN is zero
1357 if this is for a sibcall. EH_RETURN is nonzero if we're expanding an
1358 eh_return pattern. SIBCALL_P is true if this is a sibcall epilogue,
1362 bfin_expand_epilogue (int need_return, int eh_return, bool sibcall_p)
1364 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
1365 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1366 int e = sibcall_p ? -1 : 1;
1367 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1368 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
1370 if (fkind != SUBROUTINE)
1372 expand_interrupt_handler_epilogue (spreg, fkind, all);
1376 do_unlink (spreg, get_frame_size (), false, e);
1378 expand_epilogue_reg_restore (spreg, all, false);
1380 /* Omit the return insn if this is for a sibcall. */
1385 emit_insn (gen_addsi3 (spreg, spreg, gen_rtx_REG (Pmode, REG_P2)));
1387 emit_jump_insn (gen_return_internal (GEN_INT (SUBROUTINE)));
1390 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
1393 bfin_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
1394 unsigned int new_reg)
1396 /* Interrupt functions can only use registers that have already been
1397 saved by the prologue, even if they would normally be
1400 if (funkind (TREE_TYPE (current_function_decl)) != SUBROUTINE
1401 && !df_regs_ever_live_p (new_reg))
1407 /* Return the value of the return address for the frame COUNT steps up
1408 from the current frame, after the prologue.
1409 We punt for everything but the current frame by returning const0_rtx. */
1412 bfin_return_addr_rtx (int count)
1417 return get_hard_reg_initial_val (Pmode, REG_RETS);
1420 /* Try machine-dependent ways of modifying an illegitimate address X
1421 to be legitimate. If we find one, return the new, valid address,
1422 otherwise return NULL_RTX.
1424 OLDX is the address as it was before break_out_memory_refs was called.
1425 In some cases it is useful to look at this to decide what needs to be done.
1427 MODE is the mode of the memory reference. */
1430 legitimize_address (rtx x ATTRIBUTE_UNUSED, rtx oldx ATTRIBUTE_UNUSED,
1431 enum machine_mode mode ATTRIBUTE_UNUSED)
1437 bfin_delegitimize_address (rtx orig_x)
1441 if (GET_CODE (x) != MEM)
1445 if (GET_CODE (x) == PLUS
1446 && GET_CODE (XEXP (x, 1)) == UNSPEC
1447 && XINT (XEXP (x, 1), 1) == UNSPEC_MOVE_PIC
1448 && GET_CODE (XEXP (x, 0)) == REG
1449 && REGNO (XEXP (x, 0)) == PIC_OFFSET_TABLE_REGNUM)
1450 return XVECEXP (XEXP (x, 1), 0, 0);
1455 /* This predicate is used to compute the length of a load/store insn.
1456 OP is a MEM rtx, we return nonzero if its addressing mode requires a
1457 32-bit instruction. */
1460 effective_address_32bit_p (rtx op, enum machine_mode mode)
1462 HOST_WIDE_INT offset;
1464 mode = GET_MODE (op);
1467 if (GET_CODE (op) != PLUS)
1469 gcc_assert (REG_P (op) || GET_CODE (op) == POST_INC
1470 || GET_CODE (op) == PRE_DEC || GET_CODE (op) == POST_DEC);
1474 if (GET_CODE (XEXP (op, 1)) == UNSPEC)
1477 offset = INTVAL (XEXP (op, 1));
1479 /* All byte loads use a 16-bit offset. */
1480 if (GET_MODE_SIZE (mode) == 1)
1483 if (GET_MODE_SIZE (mode) == 4)
1485 /* Frame pointer relative loads can use a negative offset, all others
1486 are restricted to a small positive one. */
1487 if (XEXP (op, 0) == frame_pointer_rtx)
1488 return offset < -128 || offset > 60;
1489 return offset < 0 || offset > 60;
1492 /* Must be HImode now. */
1493 return offset < 0 || offset > 30;
1496 /* Returns true if X is a memory reference using an I register. */
1498 bfin_dsp_memref_p (rtx x)
1503 if (GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_INC
1504 || GET_CODE (x) == POST_DEC || GET_CODE (x) == PRE_DEC)
1509 /* Return cost of the memory address ADDR.
1510 All addressing modes are equally cheap on the Blackfin. */
1513 bfin_address_cost (rtx addr ATTRIBUTE_UNUSED, bool speed ATTRIBUTE_UNUSED)
1518 /* Subroutine of print_operand; used to print a memory reference X to FILE. */
1521 print_address_operand (FILE *file, rtx x)
1523 switch (GET_CODE (x))
1526 output_address (XEXP (x, 0));
1527 fprintf (file, "+");
1528 output_address (XEXP (x, 1));
1532 fprintf (file, "--");
1533 output_address (XEXP (x, 0));
1536 output_address (XEXP (x, 0));
1537 fprintf (file, "++");
1540 output_address (XEXP (x, 0));
1541 fprintf (file, "--");
1545 gcc_assert (GET_CODE (x) != MEM);
1546 print_operand (file, x, 0);
1551 /* Adding intp DImode support by Tony
1557 print_operand (FILE *file, rtx x, char code)
1559 enum machine_mode mode;
1563 if (GET_MODE (current_output_insn) == SImode)
1564 fprintf (file, " ||");
1566 fprintf (file, ";");
1570 mode = GET_MODE (x);
1575 switch (GET_CODE (x))
1578 fprintf (file, "e");
1581 fprintf (file, "ne");
1584 fprintf (file, "g");
1587 fprintf (file, "l");
1590 fprintf (file, "ge");
1593 fprintf (file, "le");
1596 fprintf (file, "g");
1599 fprintf (file, "l");
1602 fprintf (file, "ge");
1605 fprintf (file, "le");
1608 output_operand_lossage ("invalid %%j value");
1612 case 'J': /* reverse logic */
1613 switch (GET_CODE(x))
1616 fprintf (file, "ne");
1619 fprintf (file, "e");
1622 fprintf (file, "le");
1625 fprintf (file, "ge");
1628 fprintf (file, "l");
1631 fprintf (file, "g");
1634 fprintf (file, "le");
1637 fprintf (file, "ge");
1640 fprintf (file, "l");
1643 fprintf (file, "g");
1646 output_operand_lossage ("invalid %%J value");
1651 switch (GET_CODE (x))
1657 fprintf (file, "%s", short_reg_names[REGNO (x)]);
1659 output_operand_lossage ("invalid operand for code '%c'", code);
1661 else if (code == 'd')
1664 fprintf (file, "%s", high_reg_names[REGNO (x)]);
1666 output_operand_lossage ("invalid operand for code '%c'", code);
1668 else if (code == 'w')
1670 if (REGNO (x) == REG_A0 || REGNO (x) == REG_A1)
1671 fprintf (file, "%s.w", reg_names[REGNO (x)]);
1673 output_operand_lossage ("invalid operand for code '%c'", code);
1675 else if (code == 'x')
1677 if (REGNO (x) == REG_A0 || REGNO (x) == REG_A1)
1678 fprintf (file, "%s.x", reg_names[REGNO (x)]);
1680 output_operand_lossage ("invalid operand for code '%c'", code);
1682 else if (code == 'v')
1684 if (REGNO (x) == REG_A0)
1685 fprintf (file, "AV0");
1686 else if (REGNO (x) == REG_A1)
1687 fprintf (file, "AV1");
1689 output_operand_lossage ("invalid operand for code '%c'", code);
1691 else if (code == 'D')
1693 if (D_REGNO_P (REGNO (x)))
1694 fprintf (file, "%s", dregs_pair_names[REGNO (x)]);
1696 output_operand_lossage ("invalid operand for code '%c'", code);
1698 else if (code == 'H')
1700 if ((mode == DImode || mode == DFmode) && REG_P (x))
1701 fprintf (file, "%s", reg_names[REGNO (x) + 1]);
1703 output_operand_lossage ("invalid operand for code '%c'", code);
1705 else if (code == 'T')
1707 if (D_REGNO_P (REGNO (x)))
1708 fprintf (file, "%s", byte_reg_names[REGNO (x)]);
1710 output_operand_lossage ("invalid operand for code '%c'", code);
1713 fprintf (file, "%s", reg_names[REGNO (x)]);
1719 print_address_operand (file, x);
1731 fputs ("(FU)", file);
1734 fputs ("(T)", file);
1737 fputs ("(TFU)", file);
1740 fputs ("(W32)", file);
1743 fputs ("(IS)", file);
1746 fputs ("(IU)", file);
1749 fputs ("(IH)", file);
1752 fputs ("(M)", file);
1755 fputs ("(IS,M)", file);
1758 fputs ("(ISS2)", file);
1761 fputs ("(S2RND)", file);
1768 else if (code == 'b')
1770 if (INTVAL (x) == 0)
1772 else if (INTVAL (x) == 1)
1778 /* Moves to half registers with d or h modifiers always use unsigned
1780 else if (code == 'd')
1781 x = GEN_INT ((INTVAL (x) >> 16) & 0xffff);
1782 else if (code == 'h')
1783 x = GEN_INT (INTVAL (x) & 0xffff);
1784 else if (code == 'N')
1785 x = GEN_INT (-INTVAL (x));
1786 else if (code == 'X')
1787 x = GEN_INT (exact_log2 (0xffffffff & INTVAL (x)));
1788 else if (code == 'Y')
1789 x = GEN_INT (exact_log2 (0xffffffff & ~INTVAL (x)));
1790 else if (code == 'Z')
1791 /* Used for LINK insns. */
1792 x = GEN_INT (-8 - INTVAL (x));
1797 output_addr_const (file, x);
1801 output_operand_lossage ("invalid const_double operand");
1805 switch (XINT (x, 1))
1807 case UNSPEC_MOVE_PIC:
1808 output_addr_const (file, XVECEXP (x, 0, 0));
1809 fprintf (file, "@GOT");
1812 case UNSPEC_MOVE_FDPIC:
1813 output_addr_const (file, XVECEXP (x, 0, 0));
1814 fprintf (file, "@GOT17M4");
1817 case UNSPEC_FUNCDESC_GOT17M4:
1818 output_addr_const (file, XVECEXP (x, 0, 0));
1819 fprintf (file, "@FUNCDESC_GOT17M4");
1822 case UNSPEC_LIBRARY_OFFSET:
1823 fprintf (file, "_current_shared_library_p5_offset_");
1832 output_addr_const (file, x);
1837 /* Argument support functions. */
1839 /* Initialize a variable CUM of type CUMULATIVE_ARGS
1840 for a call to a function whose data type is FNTYPE.
1841 For a library call, FNTYPE is 0.
1842 VDSP C Compiler manual, our ABI says that
1843 first 3 words of arguments will use R0, R1 and R2.
1847 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
1848 rtx libname ATTRIBUTE_UNUSED)
1850 static CUMULATIVE_ARGS zero_cum;
1854 /* Set up the number of registers to use for passing arguments. */
1856 cum->nregs = max_arg_registers;
1857 cum->arg_regs = arg_regs;
1859 cum->call_cookie = CALL_NORMAL;
1860 /* Check for a longcall attribute. */
1861 if (fntype && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype)))
1862 cum->call_cookie |= CALL_SHORT;
1863 else if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)))
1864 cum->call_cookie |= CALL_LONG;
1869 /* Update the data in CUM to advance over an argument
1870 of mode MODE and data type TYPE.
1871 (TYPE is null for libcalls where that information may not be available.) */
1874 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1875 int named ATTRIBUTE_UNUSED)
1877 int count, bytes, words;
1879 bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1880 words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1882 cum->words += words;
1883 cum->nregs -= words;
1885 if (cum->nregs <= 0)
1888 cum->arg_regs = NULL;
1892 for (count = 1; count <= words; count++)
1899 /* Define where to put the arguments to a function.
1900 Value is zero to push the argument on the stack,
1901 or a hard register in which to store the argument.
1903 MODE is the argument's machine mode.
1904 TYPE is the data type of the argument (as a tree).
1905 This is null for libcalls where that information may
1907 CUM is a variable of type CUMULATIVE_ARGS which gives info about
1908 the preceding args and about the function being called.
1909 NAMED is nonzero if this argument is a named parameter
1910 (otherwise it is an extra parameter matching an ellipsis). */
1913 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1914 int named ATTRIBUTE_UNUSED)
1917 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1919 if (mode == VOIDmode)
1920 /* Compute operand 2 of the call insn. */
1921 return GEN_INT (cum->call_cookie);
1927 return gen_rtx_REG (mode, *(cum->arg_regs));
1932 /* For an arg passed partly in registers and partly in memory,
1933 this is the number of bytes passed in registers.
1934 For args passed entirely in registers or entirely in memory, zero.
1936 Refer VDSP C Compiler manual, our ABI.
1937 First 3 words are in registers. So, if an argument is larger
1938 than the registers available, it will span the register and
1942 bfin_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1943 tree type ATTRIBUTE_UNUSED,
1944 bool named ATTRIBUTE_UNUSED)
1947 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1948 int bytes_left = cum->nregs * UNITS_PER_WORD;
1953 if (bytes_left == 0)
1955 if (bytes > bytes_left)
1960 /* Variable sized types are passed by reference. */
1963 bfin_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
1964 enum machine_mode mode ATTRIBUTE_UNUSED,
1965 const_tree type, bool named ATTRIBUTE_UNUSED)
1967 return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
1970 /* Decide whether a type should be returned in memory (true)
1971 or in a register (false). This is called by the macro
1972 TARGET_RETURN_IN_MEMORY. */
1975 bfin_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
1977 int size = int_size_in_bytes (type);
1978 return size > 2 * UNITS_PER_WORD || size == -1;
1981 /* Register in which address to store a structure value
1982 is passed to a function. */
1984 bfin_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
1985 int incoming ATTRIBUTE_UNUSED)
1987 return gen_rtx_REG (Pmode, REG_P0);
1990 /* Return true when register may be used to pass function parameters. */
1993 function_arg_regno_p (int n)
1996 for (i = 0; arg_regs[i] != -1; i++)
1997 if (n == arg_regs[i])
2002 /* Returns 1 if OP contains a symbol reference */
2005 symbolic_reference_mentioned_p (rtx op)
2007 register const char *fmt;
2010 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
2013 fmt = GET_RTX_FORMAT (GET_CODE (op));
2014 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
2020 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
2021 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
2025 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
2032 /* Decide whether we can make a sibling call to a function. DECL is the
2033 declaration of the function being targeted by the call and EXP is the
2034 CALL_EXPR representing the call. */
2037 bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
2038 tree exp ATTRIBUTE_UNUSED)
2040 struct cgraph_local_info *this_func, *called_func;
2041 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
2042 if (fkind != SUBROUTINE)
2044 if (!TARGET_ID_SHARED_LIBRARY || TARGET_SEP_DATA)
2047 /* When compiling for ID shared libraries, can't sibcall a local function
2048 from a non-local function, because the local function thinks it does
2049 not need to reload P5 in the prologue, but the sibcall wil pop P5 in the
2050 sibcall epilogue, and we end up with the wrong value in P5. */
2053 /* Not enough information. */
2056 this_func = cgraph_local_info (current_function_decl);
2057 called_func = cgraph_local_info (decl);
2058 return !called_func->local || this_func->local;
2061 /* Emit RTL insns to initialize the variable parts of a trampoline at
2062 TRAMP. FNADDR is an RTX for the address of the function's pure
2063 code. CXT is an RTX for the static chain value for the function. */
2066 initialize_trampoline (rtx tramp, rtx fnaddr, rtx cxt)
2068 rtx t1 = copy_to_reg (fnaddr);
2069 rtx t2 = copy_to_reg (cxt);
2075 rtx a = memory_address (Pmode, plus_constant (tramp, 8));
2076 addr = memory_address (Pmode, tramp);
2077 emit_move_insn (gen_rtx_MEM (SImode, addr), a);
2081 addr = memory_address (Pmode, plus_constant (tramp, i + 2));
2082 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
2083 emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16)));
2084 addr = memory_address (Pmode, plus_constant (tramp, i + 6));
2085 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t1));
2087 addr = memory_address (Pmode, plus_constant (tramp, i + 10));
2088 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
2089 emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16)));
2090 addr = memory_address (Pmode, plus_constant (tramp, i + 14));
2091 emit_move_insn (gen_rtx_MEM (HImode, addr), gen_lowpart (HImode, t2));
2094 /* Emit insns to move operands[1] into operands[0]. */
2097 emit_pic_move (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
2099 rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
2101 gcc_assert (!TARGET_FDPIC || !(reload_in_progress || reload_completed));
2102 if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
2103 operands[1] = force_reg (SImode, operands[1]);
2105 operands[1] = legitimize_pic_address (operands[1], temp,
2106 TARGET_FDPIC ? OUR_FDPIC_REG
2107 : pic_offset_table_rtx);
2110 /* Expand a move operation in mode MODE. The operands are in OPERANDS.
2111 Returns true if no further code must be generated, false if the caller
2112 should generate an insn to move OPERANDS[1] to OPERANDS[0]. */
2115 expand_move (rtx *operands, enum machine_mode mode)
2117 rtx op = operands[1];
2118 if ((TARGET_ID_SHARED_LIBRARY || TARGET_FDPIC)
2119 && SYMBOLIC_CONST (op))
2120 emit_pic_move (operands, mode);
2121 else if (mode == SImode && GET_CODE (op) == CONST
2122 && GET_CODE (XEXP (op, 0)) == PLUS
2123 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
2124 && !bfin_legitimate_constant_p (op))
2126 rtx dest = operands[0];
2128 gcc_assert (!reload_in_progress && !reload_completed);
2130 op0 = force_reg (mode, XEXP (op, 0));
2132 if (!insn_data[CODE_FOR_addsi3].operand[2].predicate (op1, mode))
2133 op1 = force_reg (mode, op1);
2134 if (GET_CODE (dest) == MEM)
2135 dest = gen_reg_rtx (mode);
2136 emit_insn (gen_addsi3 (dest, op0, op1));
2137 if (dest == operands[0])
2141 /* Don't generate memory->memory or constant->memory moves, go through a
2143 else if ((reload_in_progress | reload_completed) == 0
2144 && GET_CODE (operands[0]) == MEM
2145 && GET_CODE (operands[1]) != REG)
2146 operands[1] = force_reg (mode, operands[1]);
2150 /* Split one or more DImode RTL references into pairs of SImode
2151 references. The RTL can be REG, offsettable MEM, integer constant, or
2152 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
2153 split and "num" is its length. lo_half and hi_half are output arrays
2154 that parallel "operands". */
2157 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
2161 rtx op = operands[num];
2163 /* simplify_subreg refuse to split volatile memory addresses,
2164 but we still have to handle it. */
2165 if (GET_CODE (op) == MEM)
2167 lo_half[num] = adjust_address (op, SImode, 0);
2168 hi_half[num] = adjust_address (op, SImode, 4);
2172 lo_half[num] = simplify_gen_subreg (SImode, op,
2173 GET_MODE (op) == VOIDmode
2174 ? DImode : GET_MODE (op), 0);
2175 hi_half[num] = simplify_gen_subreg (SImode, op,
2176 GET_MODE (op) == VOIDmode
2177 ? DImode : GET_MODE (op), 4);
2183 bfin_longcall_p (rtx op, int call_cookie)
2185 gcc_assert (GET_CODE (op) == SYMBOL_REF);
2186 if (call_cookie & CALL_SHORT)
2188 if (call_cookie & CALL_LONG)
2190 if (TARGET_LONG_CALLS)
2195 /* Expand a call instruction. FNADDR is the call target, RETVAL the return value.
2196 COOKIE is a CONST_INT holding the call_cookie prepared init_cumulative_args.
2197 SIBCALL is nonzero if this is a sibling call. */
2200 bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
2202 rtx use = NULL, call;
2203 rtx callee = XEXP (fnaddr, 0);
2204 int nelts = 2 + !!sibcall;
2206 rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REGNO);
2209 /* In an untyped call, we can get NULL for operand 2. */
2210 if (cookie == NULL_RTX)
2211 cookie = const0_rtx;
2213 /* Static functions and indirect calls don't need the pic register. */
2214 if (!TARGET_FDPIC && flag_pic
2215 && GET_CODE (callee) == SYMBOL_REF
2216 && !SYMBOL_REF_LOCAL_P (callee))
2217 use_reg (&use, pic_offset_table_rtx);
2221 int caller_has_l1_text, callee_has_l1_text;
2223 caller_has_l1_text = callee_has_l1_text = 0;
2225 if (lookup_attribute ("l1_text",
2226 DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE)
2227 caller_has_l1_text = 1;
2229 if (GET_CODE (callee) == SYMBOL_REF
2230 && SYMBOL_REF_DECL (callee) && DECL_P (SYMBOL_REF_DECL (callee))
2233 DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE)
2234 callee_has_l1_text = 1;
2236 if (GET_CODE (callee) != SYMBOL_REF
2237 || bfin_longcall_p (callee, INTVAL (cookie))
2238 || (GET_CODE (callee) == SYMBOL_REF
2239 && !SYMBOL_REF_LOCAL_P (callee)
2240 && TARGET_INLINE_PLT)
2241 || caller_has_l1_text != callee_has_l1_text
2242 || (caller_has_l1_text && callee_has_l1_text
2243 && (GET_CODE (callee) != SYMBOL_REF
2244 || !SYMBOL_REF_LOCAL_P (callee))))
2247 if (! address_operand (addr, Pmode))
2248 addr = force_reg (Pmode, addr);
2250 fnaddr = gen_reg_rtx (SImode);
2251 emit_insn (gen_load_funcdescsi (fnaddr, addr));
2252 fnaddr = gen_rtx_MEM (Pmode, fnaddr);
2254 picreg = gen_reg_rtx (SImode);
2255 emit_insn (gen_load_funcdescsi (picreg,
2256 plus_constant (addr, 4)));
2261 else if ((!register_no_elim_operand (callee, Pmode)
2262 && GET_CODE (callee) != SYMBOL_REF)
2263 || (GET_CODE (callee) == SYMBOL_REF
2264 && ((TARGET_ID_SHARED_LIBRARY && !TARGET_LEAF_ID_SHARED_LIBRARY)
2265 || bfin_longcall_p (callee, INTVAL (cookie)))))
2267 callee = copy_to_mode_reg (Pmode, callee);
2268 fnaddr = gen_rtx_MEM (Pmode, callee);
2270 call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
2273 call = gen_rtx_SET (VOIDmode, retval, call);
2275 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nelts));
2277 XVECEXP (pat, 0, n++) = call;
2279 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, picreg);
2280 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie);
2282 XVECEXP (pat, 0, n++) = gen_rtx_RETURN (VOIDmode);
2283 call = emit_call_insn (pat);
2285 CALL_INSN_FUNCTION_USAGE (call) = use;
2288 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
2291 hard_regno_mode_ok (int regno, enum machine_mode mode)
2293 /* Allow only dregs to store value of mode HI or QI */
2294 enum reg_class rclass = REGNO_REG_CLASS (regno);
2299 if (mode == V2HImode)
2300 return D_REGNO_P (regno);
2301 if (rclass == CCREGS)
2302 return mode == BImode;
2303 if (mode == PDImode || mode == V2PDImode)
2304 return regno == REG_A0 || regno == REG_A1;
2306 /* Allow all normal 32-bit regs, except REG_M3, in case regclass ever comes
2307 up with a bad register class (such as ALL_REGS) for DImode. */
2309 return regno < REG_M3;
2312 && TEST_HARD_REG_BIT (reg_class_contents[PROLOGUE_REGS], regno))
2315 return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno);
2318 /* Implements target hook vector_mode_supported_p. */
2321 bfin_vector_mode_supported_p (enum machine_mode mode)
2323 return mode == V2HImode;
2326 /* Return the cost of moving data from a register in class CLASS1 to
2327 one in class CLASS2. A cost of 2 is the default. */
2330 bfin_register_move_cost (enum machine_mode mode,
2331 enum reg_class class1, enum reg_class class2)
2333 /* These need secondary reloads, so they're more expensive. */
2334 if ((class1 == CCREGS && class2 != DREGS)
2335 || (class1 != DREGS && class2 == CCREGS))
2338 /* If optimizing for size, always prefer reg-reg over reg-memory moves. */
2342 /* There are some stalls involved when moving from a DREG to a different
2343 class reg, and using the value in one of the following instructions.
2344 Attempt to model this by slightly discouraging such moves. */
2345 if (class1 == DREGS && class2 != DREGS)
2348 if (GET_MODE_CLASS (mode) == MODE_INT)
2350 /* Discourage trying to use the accumulators. */
2351 if (TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A0)
2352 || TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A1)
2353 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A0)
2354 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A1))
2360 /* Return the cost of moving data of mode M between a
2361 register and memory. A value of 2 is the default; this cost is
2362 relative to those in `REGISTER_MOVE_COST'.
2364 ??? In theory L1 memory has single-cycle latency. We should add a switch
2365 that tells the compiler whether we expect to use only L1 memory for the
2366 program; it'll make the costs more accurate. */
2369 bfin_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
2370 enum reg_class rclass,
2371 int in ATTRIBUTE_UNUSED)
2373 /* Make memory accesses slightly more expensive than any register-register
2374 move. Also, penalize non-DP registers, since they need secondary
2375 reloads to load and store. */
2376 if (! reg_class_subset_p (rclass, DPREGS))
2382 /* Inform reload about cases where moving X with a mode MODE to a register in
2383 RCLASS requires an extra scratch register. Return the class needed for the
2384 scratch register. */
2386 static enum reg_class
2387 bfin_secondary_reload (bool in_p, rtx x, enum reg_class rclass,
2388 enum machine_mode mode, secondary_reload_info *sri)
2390 /* If we have HImode or QImode, we can only use DREGS as secondary registers;
2391 in most other cases we can also use PREGS. */
2392 enum reg_class default_class = GET_MODE_SIZE (mode) >= 4 ? DPREGS : DREGS;
2393 enum reg_class x_class = NO_REGS;
2394 enum rtx_code code = GET_CODE (x);
2397 x = SUBREG_REG (x), code = GET_CODE (x);
2400 int regno = REGNO (x);
2401 if (regno >= FIRST_PSEUDO_REGISTER)
2402 regno = reg_renumber[regno];
2407 x_class = REGNO_REG_CLASS (regno);
2410 /* We can be asked to reload (plus (FP) (large_constant)) into a DREG.
2411 This happens as a side effect of register elimination, and we need
2412 a scratch register to do it. */
2413 if (fp_plus_const_operand (x, mode))
2415 rtx op2 = XEXP (x, 1);
2416 int large_constant_p = ! satisfies_constraint_Ks7 (op2);
2418 if (rclass == PREGS || rclass == PREGS_CLOBBERED)
2420 /* If destination is a DREG, we can do this without a scratch register
2421 if the constant is valid for an add instruction. */
2422 if ((rclass == DREGS || rclass == DPREGS)
2423 && ! large_constant_p)
2425 /* Reloading to anything other than a DREG? Use a PREG scratch
2427 sri->icode = CODE_FOR_reload_insi;
2431 /* Data can usually be moved freely between registers of most classes.
2432 AREGS are an exception; they can only move to or from another register
2433 in AREGS or one in DREGS. They can also be assigned the constant 0. */
2434 if (x_class == AREGS || x_class == EVEN_AREGS || x_class == ODD_AREGS)
2435 return (rclass == DREGS || rclass == AREGS || rclass == EVEN_AREGS
2436 || rclass == ODD_AREGS
2439 if (rclass == AREGS || rclass == EVEN_AREGS || rclass == ODD_AREGS)
2443 sri->icode = in_p ? CODE_FOR_reload_inpdi : CODE_FOR_reload_outpdi;
2447 if (x != const0_rtx && x_class != DREGS)
2455 /* CCREGS can only be moved from/to DREGS. */
2456 if (rclass == CCREGS && x_class != DREGS)
2458 if (x_class == CCREGS && rclass != DREGS)
2461 /* All registers other than AREGS can load arbitrary constants. The only
2462 case that remains is MEM. */
2464 if (! reg_class_subset_p (rclass, default_class))
2465 return default_class;
2470 /* Implement TARGET_HANDLE_OPTION. */
2473 bfin_handle_option (size_t code, const char *arg, int value)
2477 case OPT_mshared_library_id_:
2478 if (value > MAX_LIBRARY_ID)
2479 error ("-mshared-library-id=%s is not between 0 and %d",
2480 arg, MAX_LIBRARY_ID);
2481 bfin_lib_id_given = 1;
2490 while ((p = bfin_cpus[i].name) != NULL)
2492 if (strncmp (arg, p, strlen (p)) == 0)
2499 error ("-mcpu=%s is not valid", arg);
2503 bfin_cpu_type = bfin_cpus[i].type;
2505 q = arg + strlen (p);
2509 bfin_si_revision = bfin_cpus[i].si_revision;
2510 bfin_workarounds |= bfin_cpus[i].workarounds;
2512 else if (strcmp (q, "-none") == 0)
2513 bfin_si_revision = -1;
2514 else if (strcmp (q, "-any") == 0)
2516 bfin_si_revision = 0xffff;
2517 while (bfin_cpus[i].type == bfin_cpu_type)
2519 bfin_workarounds |= bfin_cpus[i].workarounds;
2525 unsigned int si_major, si_minor;
2528 rev_len = strlen (q);
2530 if (sscanf (q, "-%u.%u%n", &si_major, &si_minor, &n) != 2
2532 || si_major > 0xff || si_minor > 0xff)
2534 invalid_silicon_revision:
2535 error ("-mcpu=%s has invalid silicon revision", arg);
2539 bfin_si_revision = (si_major << 8) | si_minor;
2541 while (bfin_cpus[i].type == bfin_cpu_type
2542 && bfin_cpus[i].si_revision != bfin_si_revision)
2545 if (bfin_cpus[i].type != bfin_cpu_type)
2546 goto invalid_silicon_revision;
2548 bfin_workarounds |= bfin_cpus[i].workarounds;
2559 static struct machine_function *
2560 bfin_init_machine_status (void)
2562 struct machine_function *f;
2564 f = GGC_CNEW (struct machine_function);
2569 /* Implement the macro OVERRIDE_OPTIONS. */
2572 override_options (void)
2574 /* If processor type is not specified, enable all workarounds. */
2575 if (bfin_cpu_type == BFIN_CPU_UNKNOWN)
2579 for (i = 0; bfin_cpus[i].name != NULL; i++)
2580 bfin_workarounds |= bfin_cpus[i].workarounds;
2582 bfin_si_revision = 0xffff;
2585 if (bfin_csync_anomaly == 1)
2586 bfin_workarounds |= WA_SPECULATIVE_SYNCS;
2587 else if (bfin_csync_anomaly == 0)
2588 bfin_workarounds &= ~WA_SPECULATIVE_SYNCS;
2590 if (bfin_specld_anomaly == 1)
2591 bfin_workarounds |= WA_SPECULATIVE_LOADS;
2592 else if (bfin_specld_anomaly == 0)
2593 bfin_workarounds &= ~WA_SPECULATIVE_LOADS;
2595 if (TARGET_OMIT_LEAF_FRAME_POINTER)
2596 flag_omit_frame_pointer = 1;
2598 /* Library identification */
2599 if (bfin_lib_id_given && ! TARGET_ID_SHARED_LIBRARY)
2600 error ("-mshared-library-id= specified without -mid-shared-library");
2602 if (stack_limit_rtx && TARGET_STACK_CHECK_L1)
2603 error ("Can't use multiple stack checking methods together.");
2605 if (TARGET_ID_SHARED_LIBRARY && TARGET_FDPIC)
2606 error ("ID shared libraries and FD-PIC mode can't be used together.");
2608 /* Don't allow the user to specify -mid-shared-library and -msep-data
2609 together, as it makes little sense from a user's point of view... */
2610 if (TARGET_SEP_DATA && TARGET_ID_SHARED_LIBRARY)
2611 error ("cannot specify both -msep-data and -mid-shared-library");
2612 /* ... internally, however, it's nearly the same. */
2613 if (TARGET_SEP_DATA)
2614 target_flags |= MASK_ID_SHARED_LIBRARY | MASK_LEAF_ID_SHARED_LIBRARY;
2616 if (TARGET_ID_SHARED_LIBRARY && flag_pic == 0)
2619 /* There is no single unaligned SI op for PIC code. Sometimes we
2620 need to use ".4byte" and sometimes we need to use ".picptr".
2621 See bfin_assemble_integer for details. */
2623 targetm.asm_out.unaligned_op.si = 0;
2625 /* Silently turn off flag_pic if not doing FDPIC or ID shared libraries,
2626 since we don't support it and it'll just break. */
2627 if (flag_pic && !TARGET_FDPIC && !TARGET_ID_SHARED_LIBRARY)
2630 if (TARGET_MULTICORE && bfin_cpu_type != BFIN_CPU_BF561)
2631 error ("-mmulticore can only be used with BF561");
2633 if (TARGET_COREA && !TARGET_MULTICORE)
2634 error ("-mcorea should be used with -mmulticore");
2636 if (TARGET_COREB && !TARGET_MULTICORE)
2637 error ("-mcoreb should be used with -mmulticore");
2639 if (TARGET_COREA && TARGET_COREB)
2640 error ("-mcorea and -mcoreb can't be used together");
2642 flag_schedule_insns = 0;
2644 /* Passes after sched2 can break the helpful TImode annotations that
2645 haifa-sched puts on every insn. Just do scheduling in reorg. */
2646 bfin_flag_schedule_insns2 = flag_schedule_insns_after_reload;
2647 flag_schedule_insns_after_reload = 0;
2649 init_machine_status = bfin_init_machine_status;
2652 /* Return the destination address of BRANCH.
2653 We need to use this instead of get_attr_length, because the
2654 cbranch_with_nops pattern conservatively sets its length to 6, and
2655 we still prefer to use shorter sequences. */
2658 branch_dest (rtx branch)
2662 rtx pat = PATTERN (branch);
2663 if (GET_CODE (pat) == PARALLEL)
2664 pat = XVECEXP (pat, 0, 0);
2665 dest = SET_SRC (pat);
2666 if (GET_CODE (dest) == IF_THEN_ELSE)
2667 dest = XEXP (dest, 1);
2668 dest = XEXP (dest, 0);
2669 dest_uid = INSN_UID (dest);
2670 return INSN_ADDRESSES (dest_uid);
2673 /* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates
2674 it's a branch that's predicted taken. */
2677 cbranch_predicted_taken_p (rtx insn)
2679 rtx x = find_reg_note (insn, REG_BR_PROB, 0);
2683 int pred_val = INTVAL (XEXP (x, 0));
2685 return pred_val >= REG_BR_PROB_BASE / 2;
2691 /* Templates for use by asm_conditional_branch. */
2693 static const char *ccbranch_templates[][3] = {
2694 { "if !cc jump %3;", "if cc jump 4 (bp); jump.s %3;", "if cc jump 6 (bp); jump.l %3;" },
2695 { "if cc jump %3;", "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" },
2696 { "if !cc jump %3 (bp);", "if cc jump 4; jump.s %3;", "if cc jump 6; jump.l %3;" },
2697 { "if cc jump %3 (bp);", "if !cc jump 4; jump.s %3;", "if !cc jump 6; jump.l %3;" },
2700 /* Output INSN, which is a conditional branch instruction with operands
2703 We deal with the various forms of conditional branches that can be generated
2704 by bfin_reorg to prevent the hardware from doing speculative loads, by
2705 - emitting a sufficient number of nops, if N_NOPS is nonzero, or
2706 - always emitting the branch as predicted taken, if PREDICT_TAKEN is true.
2707 Either of these is only necessary if the branch is short, otherwise the
2708 template we use ends in an unconditional jump which flushes the pipeline
2712 asm_conditional_branch (rtx insn, rtx *operands, int n_nops, int predict_taken)
2714 int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
2715 /* Note : offset for instructions like if cc jmp; jump.[sl] offset
2716 is to be taken from start of if cc rather than jump.
2717 Range for jump.s is (-4094, 4096) instead of (-4096, 4094)
2719 int len = (offset >= -1024 && offset <= 1022 ? 0
2720 : offset >= -4094 && offset <= 4096 ? 1
2722 int bp = predict_taken && len == 0 ? 1 : cbranch_predicted_taken_p (insn);
2723 int idx = (bp << 1) | (GET_CODE (operands[0]) == EQ ? BRF : BRT);
2724 output_asm_insn (ccbranch_templates[idx][len], operands);
2725 gcc_assert (n_nops == 0 || !bp);
2727 while (n_nops-- > 0)
2728 output_asm_insn ("nop;", NULL);
2731 /* Emit rtl for a comparison operation CMP in mode MODE. Operands have been
2732 stored in bfin_compare_op0 and bfin_compare_op1 already. */
2735 bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED)
2737 enum rtx_code code1, code2;
2738 rtx op0 = bfin_compare_op0, op1 = bfin_compare_op1;
2739 rtx tem = bfin_cc_rtx;
2740 enum rtx_code code = GET_CODE (cmp);
2742 /* If we have a BImode input, then we already have a compare result, and
2743 do not need to emit another comparison. */
2744 if (GET_MODE (op0) == BImode)
2746 gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
2747 tem = op0, code2 = code;
2752 /* bfin has these conditions */
2762 code1 = reverse_condition (code);
2766 emit_insn (gen_rtx_SET (BImode, tem,
2767 gen_rtx_fmt_ee (code1, BImode, op0, op1)));
2770 return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode));
2773 /* Return nonzero iff C has exactly one bit set if it is interpreted
2774 as a 32-bit constant. */
2777 log2constp (unsigned HOST_WIDE_INT c)
2780 return c != 0 && (c & (c-1)) == 0;
2783 /* Returns the number of consecutive least significant zeros in the binary
2784 representation of *V.
2785 We modify *V to contain the original value arithmetically shifted right by
2786 the number of zeroes. */
2789 shiftr_zero (HOST_WIDE_INT *v)
2791 unsigned HOST_WIDE_INT tmp = *v;
2792 unsigned HOST_WIDE_INT sgn;
2798 sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1));
2799 while ((tmp & 0x1) == 0 && n <= 32)
2801 tmp = (tmp >> 1) | sgn;
2808 /* After reload, split the load of an immediate constant. OPERANDS are the
2809 operands of the movsi_insn pattern which we are splitting. We return
2810 nonzero if we emitted a sequence to load the constant, zero if we emitted
2811 nothing because we want to use the splitter's default sequence. */
2814 split_load_immediate (rtx operands[])
2816 HOST_WIDE_INT val = INTVAL (operands[1]);
2818 HOST_WIDE_INT shifted = val;
2819 HOST_WIDE_INT shifted_compl = ~val;
2820 int num_zero = shiftr_zero (&shifted);
2821 int num_compl_zero = shiftr_zero (&shifted_compl);
2822 unsigned int regno = REGNO (operands[0]);
2824 /* This case takes care of single-bit set/clear constants, which we could
2825 also implement with BITSET/BITCLR. */
2827 && shifted >= -32768 && shifted < 65536
2828 && (D_REGNO_P (regno)
2829 || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))
2831 emit_insn (gen_movsi (operands[0], GEN_INT (shifted)));
2832 emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));
2837 tmp |= -(tmp & 0x8000);
2839 /* If high word has one bit set or clear, try to use a bit operation. */
2840 if (D_REGNO_P (regno))
2842 if (log2constp (val & 0xFFFF0000))
2844 emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));
2845 emit_insn (gen_iorsi3 (operands[0], operands[0], GEN_INT (val & 0xFFFF0000)));
2848 else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)
2850 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2851 emit_insn (gen_andsi3 (operands[0], operands[0], GEN_INT (val | 0xFFFF)));
2855 if (D_REGNO_P (regno))
2857 if (tmp >= -64 && tmp <= 63)
2859 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2860 emit_insn (gen_movstricthi_high (operands[0], GEN_INT (val & -65536)));
2864 if ((val & 0xFFFF0000) == 0)
2866 emit_insn (gen_movsi (operands[0], const0_rtx));
2867 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2871 if ((val & 0xFFFF0000) == 0xFFFF0000)
2873 emit_insn (gen_movsi (operands[0], constm1_rtx));
2874 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2879 /* Need DREGs for the remaining case. */
2884 && num_compl_zero && shifted_compl >= -64 && shifted_compl <= 63)
2886 /* If optimizing for size, generate a sequence that has more instructions
2888 emit_insn (gen_movsi (operands[0], GEN_INT (shifted_compl)));
2889 emit_insn (gen_ashlsi3 (operands[0], operands[0],
2890 GEN_INT (num_compl_zero)));
2891 emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
2897 /* Return true if the legitimate memory address for a memory operand of mode
2898 MODE. Return false if not. */
2901 bfin_valid_add (enum machine_mode mode, HOST_WIDE_INT value)
2903 unsigned HOST_WIDE_INT v = value > 0 ? value : -value;
2904 int sz = GET_MODE_SIZE (mode);
2905 int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2;
2906 /* The usual offsettable_memref machinery doesn't work so well for this
2907 port, so we deal with the problem here. */
2908 if (value > 0 && sz == 8)
2910 return (v & ~(0x7fff << shift)) == 0;
2914 bfin_valid_reg_p (unsigned int regno, int strict, enum machine_mode mode,
2915 enum rtx_code outer_code)
2918 return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH);
2920 return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH);
2924 bfin_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
2926 switch (GET_CODE (x)) {
2928 if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM))
2932 if (REG_P (XEXP (x, 0))
2933 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS)
2934 && ((GET_CODE (XEXP (x, 1)) == UNSPEC && mode == SImode)
2935 || (GET_CODE (XEXP (x, 1)) == CONST_INT
2936 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
2941 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2942 && REG_P (XEXP (x, 0))
2943 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC))
2946 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
2947 && XEXP (x, 0) == stack_pointer_rtx
2948 && REG_P (XEXP (x, 0))
2949 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC))
2958 /* Decide whether we can force certain constants to memory. If we
2959 decide we can't, the caller should be able to cope with it in
2963 bfin_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
2965 /* We have only one class of non-legitimate constants, and our movsi
2966 expander knows how to handle them. Dropping these constants into the
2967 data section would only shift the problem - we'd still get relocs
2968 outside the object, in the data section rather than the text section. */
2972 /* Ensure that for any constant of the form symbol + offset, the offset
2973 remains within the object. Any other constants are ok.
2974 This ensures that flat binaries never have to deal with relocations
2975 crossing section boundaries. */
2978 bfin_legitimate_constant_p (rtx x)
2981 HOST_WIDE_INT offset;
2983 if (GET_CODE (x) != CONST)
2987 gcc_assert (GET_CODE (x) == PLUS);
2991 if (GET_CODE (sym) != SYMBOL_REF
2992 || GET_CODE (x) != CONST_INT)
2994 offset = INTVAL (x);
2996 if (SYMBOL_REF_DECL (sym) == 0)
2999 || offset >= int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (sym))))
3006 bfin_rtx_costs (rtx x, int code, int outer_code, int *total, bool speed)
3008 int cost2 = COSTS_N_INSNS (1);
3014 if (outer_code == SET || outer_code == PLUS)
3015 *total = satisfies_constraint_Ks7 (x) ? 0 : cost2;
3016 else if (outer_code == AND)
3017 *total = log2constp (~INTVAL (x)) ? 0 : cost2;
3018 else if (outer_code == LE || outer_code == LT || outer_code == EQ)
3019 *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
3020 else if (outer_code == LEU || outer_code == LTU)
3021 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
3022 else if (outer_code == MULT)
3023 *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
3024 else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
3026 else if (outer_code == ASHIFT || outer_code == ASHIFTRT
3027 || outer_code == LSHIFTRT)
3028 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
3029 else if (outer_code == IOR || outer_code == XOR)
3030 *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
3039 *total = COSTS_N_INSNS (2);
3045 if (GET_MODE (x) == SImode)
3047 if (GET_CODE (op0) == MULT
3048 && GET_CODE (XEXP (op0, 1)) == CONST_INT)
3050 HOST_WIDE_INT val = INTVAL (XEXP (op0, 1));
3051 if (val == 2 || val == 4)
3054 *total += rtx_cost (XEXP (op0, 0), outer_code, speed);
3055 *total += rtx_cost (op1, outer_code, speed);
3060 if (GET_CODE (op0) != REG
3061 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3062 *total += rtx_cost (op0, SET, speed);
3063 #if 0 /* We'd like to do this for accuracy, but it biases the loop optimizer
3064 towards creating too many induction variables. */
3065 if (!reg_or_7bit_operand (op1, SImode))
3066 *total += rtx_cost (op1, SET, speed);
3069 else if (GET_MODE (x) == DImode)
3072 if (GET_CODE (op1) != CONST_INT
3073 || !satisfies_constraint_Ks7 (op1))
3074 *total += rtx_cost (op1, PLUS, speed);
3075 if (GET_CODE (op0) != REG
3076 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3077 *total += rtx_cost (op0, PLUS, speed);
3082 if (GET_MODE (x) == DImode)
3091 if (GET_MODE (x) == DImode)
3098 if (GET_CODE (op0) != REG
3099 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3100 *total += rtx_cost (op0, code, speed);
3110 /* Handle special cases of IOR: rotates, ALIGN insns, movstricthi_high. */
3113 if ((GET_CODE (op0) == LSHIFTRT && GET_CODE (op1) == ASHIFT)
3114 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == ZERO_EXTEND)
3115 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT)
3116 || (GET_CODE (op0) == AND && GET_CODE (op1) == CONST_INT))
3123 if (GET_CODE (op0) != REG
3124 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3125 *total += rtx_cost (op0, code, speed);
3127 if (GET_MODE (x) == DImode)
3133 if (GET_MODE (x) != SImode)
3138 if (! rhs_andsi3_operand (XEXP (x, 1), SImode))
3139 *total += rtx_cost (XEXP (x, 1), code, speed);
3143 if (! regorlog2_operand (XEXP (x, 1), SImode))
3144 *total += rtx_cost (XEXP (x, 1), code, speed);
3151 if (outer_code == SET
3152 && XEXP (x, 1) == const1_rtx
3153 && GET_CODE (XEXP (x, 2)) == CONST_INT)
3169 if (GET_CODE (op0) == GET_CODE (op1)
3170 && (GET_CODE (op0) == ZERO_EXTEND
3171 || GET_CODE (op0) == SIGN_EXTEND))
3173 *total = COSTS_N_INSNS (1);
3174 op0 = XEXP (op0, 0);
3175 op1 = XEXP (op1, 0);
3178 *total = COSTS_N_INSNS (1);
3180 *total = COSTS_N_INSNS (3);
3182 if (GET_CODE (op0) != REG
3183 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3184 *total += rtx_cost (op0, MULT, speed);
3185 if (GET_CODE (op1) != REG
3186 && (GET_CODE (op1) != SUBREG || GET_CODE (SUBREG_REG (op1)) != REG))
3187 *total += rtx_cost (op1, MULT, speed);
3193 *total = COSTS_N_INSNS (32);
3198 if (outer_code == SET)
3207 /* Used for communication between {push,pop}_multiple_operation (which
3208 we use not only as a predicate) and the corresponding output functions. */
3209 static int first_preg_to_save, first_dreg_to_save;
3210 static int n_regs_to_save;
3213 push_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
3215 int lastdreg = 8, lastpreg = 6;
3218 first_preg_to_save = lastpreg;
3219 first_dreg_to_save = lastdreg;
3220 for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
3222 rtx t = XVECEXP (op, 0, i);
3226 if (GET_CODE (t) != SET)
3230 dest = SET_DEST (t);
3231 if (GET_CODE (dest) != MEM || ! REG_P (src))
3233 dest = XEXP (dest, 0);
3234 if (GET_CODE (dest) != PLUS
3235 || ! REG_P (XEXP (dest, 0))
3236 || REGNO (XEXP (dest, 0)) != REG_SP
3237 || GET_CODE (XEXP (dest, 1)) != CONST_INT
3238 || INTVAL (XEXP (dest, 1)) != -i * 4)
3241 regno = REGNO (src);
3244 if (D_REGNO_P (regno))
3247 first_dreg_to_save = lastdreg = regno - REG_R0;
3249 else if (regno >= REG_P0 && regno <= REG_P7)
3252 first_preg_to_save = lastpreg = regno - REG_P0;
3262 if (regno >= REG_P0 && regno <= REG_P7)
3265 first_preg_to_save = lastpreg = regno - REG_P0;
3267 else if (regno != REG_R0 + lastdreg + 1)
3272 else if (group == 2)
3274 if (regno != REG_P0 + lastpreg + 1)
3279 n_regs_to_save = 8 - first_dreg_to_save + 6 - first_preg_to_save;
3284 pop_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
3286 int lastdreg = 8, lastpreg = 6;
3289 for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
3291 rtx t = XVECEXP (op, 0, i);
3295 if (GET_CODE (t) != SET)
3299 dest = SET_DEST (t);
3300 if (GET_CODE (src) != MEM || ! REG_P (dest))
3302 src = XEXP (src, 0);
3306 if (! REG_P (src) || REGNO (src) != REG_SP)
3309 else if (GET_CODE (src) != PLUS
3310 || ! REG_P (XEXP (src, 0))
3311 || REGNO (XEXP (src, 0)) != REG_SP
3312 || GET_CODE (XEXP (src, 1)) != CONST_INT
3313 || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
3316 regno = REGNO (dest);
3319 if (regno == REG_R7)
3324 else if (regno != REG_P0 + lastpreg - 1)
3329 else if (group == 1)
3331 if (regno != REG_R0 + lastdreg - 1)
3337 first_dreg_to_save = lastdreg;
3338 first_preg_to_save = lastpreg;
3339 n_regs_to_save = 8 - first_dreg_to_save + 6 - first_preg_to_save;
3343 /* Emit assembly code for one multi-register push described by INSN, with
3344 operands in OPERANDS. */
3347 output_push_multiple (rtx insn, rtx *operands)
3352 /* Validate the insn again, and compute first_[dp]reg_to_save. */
3353 ok = push_multiple_operation (PATTERN (insn), VOIDmode);
3356 if (first_dreg_to_save == 8)
3357 sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
3358 else if (first_preg_to_save == 6)
3359 sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
3361 sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
3362 first_dreg_to_save, first_preg_to_save);
3364 output_asm_insn (buf, operands);
3367 /* Emit assembly code for one multi-register pop described by INSN, with
3368 operands in OPERANDS. */
3371 output_pop_multiple (rtx insn, rtx *operands)
3376 /* Validate the insn again, and compute first_[dp]reg_to_save. */
3377 ok = pop_multiple_operation (PATTERN (insn), VOIDmode);
3380 if (first_dreg_to_save == 8)
3381 sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
3382 else if (first_preg_to_save == 6)
3383 sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
3385 sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
3386 first_dreg_to_save, first_preg_to_save);
3388 output_asm_insn (buf, operands);
3391 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE. */
3394 single_move_for_movmem (rtx dst, rtx src, enum machine_mode mode, HOST_WIDE_INT offset)
3396 rtx scratch = gen_reg_rtx (mode);
3399 srcmem = adjust_address_nv (src, mode, offset);
3400 dstmem = adjust_address_nv (dst, mode, offset);
3401 emit_move_insn (scratch, srcmem);
3402 emit_move_insn (dstmem, scratch);
3405 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
3406 alignment ALIGN_EXP. Return true if successful, false if we should fall
3407 back on a different method. */
3410 bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
3412 rtx srcreg, destreg, countreg;
3413 HOST_WIDE_INT align = 0;
3414 unsigned HOST_WIDE_INT count = 0;
3416 if (GET_CODE (align_exp) == CONST_INT)
3417 align = INTVAL (align_exp);
3418 if (GET_CODE (count_exp) == CONST_INT)
3420 count = INTVAL (count_exp);
3422 if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
3427 /* If optimizing for size, only do single copies inline. */
3430 if (count == 2 && align < 2)
3432 if (count == 4 && align < 4)
3434 if (count != 1 && count != 2 && count != 4)
3437 if (align < 2 && count != 1)
3440 destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
3441 if (destreg != XEXP (dst, 0))
3442 dst = replace_equiv_address_nv (dst, destreg);
3443 srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
3444 if (srcreg != XEXP (src, 0))
3445 src = replace_equiv_address_nv (src, srcreg);
3447 if (count != 0 && align >= 2)
3449 unsigned HOST_WIDE_INT offset = 0;
3453 if ((count & ~3) == 4)
3455 single_move_for_movmem (dst, src, SImode, offset);
3458 else if (count & ~3)
3460 HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
3461 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3463 emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
3464 cfun->machine->has_loopreg_clobber = true;
3468 single_move_for_movmem (dst, src, HImode, offset);
3474 if ((count & ~1) == 2)
3476 single_move_for_movmem (dst, src, HImode, offset);
3479 else if (count & ~1)
3481 HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
3482 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3484 emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
3485 cfun->machine->has_loopreg_clobber = true;
3490 single_move_for_movmem (dst, src, QImode, offset);
3497 /* Compute the alignment for a local variable.
3498 TYPE is the data type, and ALIGN is the alignment that
3499 the object would ordinarily have. The value of this macro is used
3500 instead of that alignment to align the object. */
3503 bfin_local_alignment (tree type, int align)
3505 /* Increasing alignment for (relatively) big types allows the builtin
3506 memcpy can use 32 bit loads/stores. */
3507 if (TYPE_SIZE (type)
3508 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
3509 && (TREE_INT_CST_LOW (TYPE_SIZE (type)) > 8
3510 || TREE_INT_CST_HIGH (TYPE_SIZE (type))) && align < 32)
3515 /* Implement TARGET_SCHED_ISSUE_RATE. */
3518 bfin_issue_rate (void)
3524 bfin_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
3526 enum attr_type insn_type, dep_insn_type;
3527 int dep_insn_code_number;
3529 /* Anti and output dependencies have zero cost. */
3530 if (REG_NOTE_KIND (link) != 0)
3533 dep_insn_code_number = recog_memoized (dep_insn);
3535 /* If we can't recognize the insns, we can't really do anything. */
3536 if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
3539 insn_type = get_attr_type (insn);
3540 dep_insn_type = get_attr_type (dep_insn);
3542 if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)
3544 rtx pat = PATTERN (dep_insn);
3545 if (GET_CODE (pat) == PARALLEL)
3546 pat = XVECEXP (pat, 0, 0);
3547 rtx dest = SET_DEST (pat);
3548 rtx src = SET_SRC (pat);
3549 if (! ADDRESS_REGNO_P (REGNO (dest))
3550 || ! (MEM_P (src) || D_REGNO_P (REGNO (src))))
3552 return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);
3558 /* This function acts like NEXT_INSN, but is aware of three-insn bundles and
3559 skips all subsequent parallel instructions if INSN is the start of such
3562 find_next_insn_start (rtx insn)
3564 if (GET_MODE (insn) == SImode)
3566 while (GET_MODE (insn) != QImode)
3567 insn = NEXT_INSN (insn);
3569 return NEXT_INSN (insn);
3572 /* This function acts like PREV_INSN, but is aware of three-insn bundles and
3573 skips all subsequent parallel instructions if INSN is the start of such
3576 find_prev_insn_start (rtx insn)
3578 insn = PREV_INSN (insn);
3579 gcc_assert (GET_MODE (insn) != SImode);
3580 if (GET_MODE (insn) == QImode)
3582 while (GET_MODE (PREV_INSN (insn)) == SImode)
3583 insn = PREV_INSN (insn);
3588 /* Increment the counter for the number of loop instructions in the
3589 current function. */
3592 bfin_hardware_loop (void)
3594 cfun->machine->has_hardware_loops++;
3597 /* Maximum loop nesting depth. */
3598 #define MAX_LOOP_DEPTH 2
3600 /* Maximum size of a loop. */
3601 #define MAX_LOOP_LENGTH 2042
3603 /* Maximum distance of the LSETUP instruction from the loop start. */
3604 #define MAX_LSETUP_DISTANCE 30
3606 /* We need to keep a vector of loops */
3607 typedef struct loop_info *loop_info;
3608 DEF_VEC_P (loop_info);
3609 DEF_VEC_ALLOC_P (loop_info,heap);
3611 /* Information about a loop we have found (or are in the process of
3613 struct GTY (()) loop_info
3615 /* loop number, for dumps */
3618 /* All edges that jump into and out of the loop. */
3619 VEC(edge,gc) *incoming;
3621 /* We can handle two cases: all incoming edges have the same destination
3622 block, or all incoming edges have the same source block. These two
3623 members are set to the common source or destination we found, or NULL
3624 if different blocks were found. If both are NULL the loop can't be
3626 basic_block incoming_src;
3627 basic_block incoming_dest;
3629 /* First block in the loop. This is the one branched to by the loop_end
3633 /* Last block in the loop (the one with the loop_end insn). */
3636 /* The successor block of the loop. This is the one the loop_end insn
3638 basic_block successor;
3640 /* The last instruction in the tail. */
3643 /* The loop_end insn. */
3646 /* The iteration register. */
3649 /* The new initialization insn. */
3652 /* The new initialization instruction. */
3655 /* The new label placed at the beginning of the loop. */
3658 /* The new label placed at the end of the loop. */
3661 /* The length of the loop. */
3664 /* The nesting depth of the loop. */
3667 /* Nonzero if we can't optimize this loop. */
3670 /* True if we have visited this loop. */
3673 /* True if this loop body clobbers any of LC0, LT0, or LB0. */
3676 /* True if this loop body clobbers any of LC1, LT1, or LB1. */
3679 /* Next loop in the graph. */
3680 struct loop_info *next;
3682 /* Immediate outer loop of this loop. */
3683 struct loop_info *outer;
3685 /* Vector of blocks only within the loop, including those within
3687 VEC (basic_block,heap) *blocks;
3689 /* Same information in a bitmap. */
3690 bitmap block_bitmap;
3692 /* Vector of inner loops within this loop */
3693 VEC (loop_info,heap) *loops;
3697 bfin_dump_loops (loop_info loops)
3701 for (loop = loops; loop; loop = loop->next)
3707 fprintf (dump_file, ";; loop %d: ", loop->loop_no);
3709 fprintf (dump_file, "(bad) ");
3710 fprintf (dump_file, "{head:%d, depth:%d}", loop->head->index, loop->depth);
3712 fprintf (dump_file, " blocks: [ ");
3713 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, b); ix++)
3714 fprintf (dump_file, "%d ", b->index);
3715 fprintf (dump_file, "] ");
3717 fprintf (dump_file, " inner loops: [ ");
3718 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, i); ix++)
3719 fprintf (dump_file, "%d ", i->loop_no);
3720 fprintf (dump_file, "]\n");
3722 fprintf (dump_file, "\n");
3725 /* Scan the blocks of LOOP (and its inferiors) looking for basic block
3726 BB. Return true, if we find it. */
3729 bfin_bb_in_loop (loop_info loop, basic_block bb)
3731 return bitmap_bit_p (loop->block_bitmap, bb->index);
3734 /* Scan the blocks of LOOP (and its inferiors) looking for uses of
3735 REG. Return true, if we find any. Don't count the loop's loop_end
3736 insn if it matches LOOP_END. */
3739 bfin_scan_loop (loop_info loop, rtx reg, rtx loop_end)
3744 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
3748 for (insn = BB_HEAD (bb);
3749 insn != NEXT_INSN (BB_END (bb));
3750 insn = NEXT_INSN (insn))
3754 if (insn == loop_end)
3756 if (reg_mentioned_p (reg, PATTERN (insn)))
3763 /* Estimate the length of INSN conservatively. */
3766 length_for_loop (rtx insn)
3769 if (JUMP_P (insn) && any_condjump_p (insn) && !optimize_size)
3771 if (ENABLE_WA_SPECULATIVE_SYNCS)
3773 else if (ENABLE_WA_SPECULATIVE_LOADS)
3776 else if (LABEL_P (insn))
3778 if (ENABLE_WA_SPECULATIVE_SYNCS)
3783 length += get_attr_length (insn);
3788 /* Optimize LOOP. */
3791 bfin_optimize_loop (loop_info loop)
3795 rtx insn, init_insn, last_insn;
3796 rtx loop_init, start_label, end_label;
3797 rtx reg_lc0, reg_lc1, reg_lt0, reg_lt1, reg_lb0, reg_lb1;
3799 rtx lc_reg, lt_reg, lb_reg;
3803 int inner_depth = 0;
3813 fprintf (dump_file, ";; loop %d bad when found\n", loop->loop_no);
3817 /* Every loop contains in its list of inner loops every loop nested inside
3818 it, even if there are intermediate loops. This works because we're doing
3819 a depth-first search here and never visit a loop more than once. */
3820 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, inner); ix++)
3822 bfin_optimize_loop (inner);
3824 if (!inner->bad && inner_depth < inner->depth)
3826 inner_depth = inner->depth;
3828 loop->clobber_loop0 |= inner->clobber_loop0;
3829 loop->clobber_loop1 |= inner->clobber_loop1;
3833 loop->depth = inner_depth + 1;
3834 if (loop->depth > MAX_LOOP_DEPTH)
3837 fprintf (dump_file, ";; loop %d too deep\n", loop->loop_no);
3841 /* Get the loop iteration register. */
3842 iter_reg = loop->iter_reg;
3844 if (!DPREG_P (iter_reg))
3847 fprintf (dump_file, ";; loop %d iteration count NOT in PREG or DREG\n",
3852 if (loop->incoming_src)
3854 /* Make sure the predecessor is before the loop start label, as required by
3855 the LSETUP instruction. */
3857 insn = BB_END (loop->incoming_src);
3858 /* If we have to insert the LSETUP before a jump, count that jump in the
3860 if (VEC_length (edge, loop->incoming) > 1
3861 || !(VEC_last (edge, loop->incoming)->flags & EDGE_FALLTHRU))
3863 gcc_assert (JUMP_P (insn));
3864 insn = PREV_INSN (insn);
3867 for (; insn && insn != loop->start_label; insn = NEXT_INSN (insn))
3868 length += length_for_loop (insn);
3873 fprintf (dump_file, ";; loop %d lsetup not before loop_start\n",
3878 if (length > MAX_LSETUP_DISTANCE)
3881 fprintf (dump_file, ";; loop %d lsetup too far away\n", loop->loop_no);
3886 /* Check if start_label appears before loop_end and calculate the
3887 offset between them. We calculate the length of instructions
3890 for (insn = loop->start_label;
3891 insn && insn != loop->loop_end;
3892 insn = NEXT_INSN (insn))
3893 length += length_for_loop (insn);
3898 fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
3903 loop->length = length;
3904 if (loop->length > MAX_LOOP_LENGTH)
3907 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
3911 /* Scan all the blocks to make sure they don't use iter_reg. */
3912 if (bfin_scan_loop (loop, iter_reg, loop->loop_end))
3915 fprintf (dump_file, ";; loop %d uses iterator\n", loop->loop_no);
3919 /* Scan all the insns to see if the loop body clobber
3920 any hardware loop registers. */
3922 reg_lc0 = gen_rtx_REG (SImode, REG_LC0);
3923 reg_lc1 = gen_rtx_REG (SImode, REG_LC1);
3924 reg_lt0 = gen_rtx_REG (SImode, REG_LT0);
3925 reg_lt1 = gen_rtx_REG (SImode, REG_LT1);
3926 reg_lb0 = gen_rtx_REG (SImode, REG_LB0);
3927 reg_lb1 = gen_rtx_REG (SImode, REG_LB1);
3929 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
3933 for (insn = BB_HEAD (bb);
3934 insn != NEXT_INSN (BB_END (bb));
3935 insn = NEXT_INSN (insn))
3940 if (reg_set_p (reg_lc0, insn)
3941 || reg_set_p (reg_lt0, insn)
3942 || reg_set_p (reg_lb0, insn))
3943 loop->clobber_loop0 = 1;
3945 if (reg_set_p (reg_lc1, insn)
3946 || reg_set_p (reg_lt1, insn)
3947 || reg_set_p (reg_lb1, insn))
3948 loop->clobber_loop1 |= 1;
3952 if ((loop->clobber_loop0 && loop->clobber_loop1)
3953 || (loop->depth == MAX_LOOP_DEPTH && loop->clobber_loop0))
3955 loop->depth = MAX_LOOP_DEPTH + 1;
3957 fprintf (dump_file, ";; loop %d no loop reg available\n",
3962 /* There should be an instruction before the loop_end instruction
3963 in the same basic block. And the instruction must not be
3965 - CONDITIONAL BRANCH
3969 - Returns (RTS, RTN, etc.) */
3972 last_insn = find_prev_insn_start (loop->loop_end);
3976 for (; last_insn != BB_HEAD (bb);
3977 last_insn = find_prev_insn_start (last_insn))
3978 if (INSN_P (last_insn))
3981 if (last_insn != BB_HEAD (bb))
3984 if (single_pred_p (bb)
3985 && single_pred (bb) != ENTRY_BLOCK_PTR)
3987 bb = single_pred (bb);
3988 last_insn = BB_END (bb);
3993 last_insn = NULL_RTX;
4001 fprintf (dump_file, ";; loop %d has no last instruction\n",
4006 if (JUMP_P (last_insn) && !any_condjump_p (last_insn))
4009 fprintf (dump_file, ";; loop %d has bad last instruction\n",
4013 /* In all other cases, try to replace a bad last insn with a nop. */
4014 else if (JUMP_P (last_insn)
4015 || CALL_P (last_insn)
4016 || get_attr_type (last_insn) == TYPE_SYNC
4017 || get_attr_type (last_insn) == TYPE_CALL
4018 || get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI
4019 || recog_memoized (last_insn) == CODE_FOR_return_internal
4020 || GET_CODE (PATTERN (last_insn)) == ASM_INPUT
4021 || asm_noperands (PATTERN (last_insn)) >= 0)
4023 if (loop->length + 2 > MAX_LOOP_LENGTH)
4026 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
4030 fprintf (dump_file, ";; loop %d has bad last insn; replace with nop\n",
4033 last_insn = emit_insn_after (gen_forced_nop (), last_insn);
4036 loop->last_insn = last_insn;
4038 /* The loop is good for replacement. */
4039 start_label = loop->start_label;
4040 end_label = gen_label_rtx ();
4041 iter_reg = loop->iter_reg;
4043 if (loop->depth == 1 && !loop->clobber_loop1)
4048 loop->clobber_loop1 = 1;
4055 loop->clobber_loop0 = 1;
4058 /* If iter_reg is a DREG, we need generate an instruction to load
4059 the loop count into LC register. */
4060 if (D_REGNO_P (REGNO (iter_reg)))
4062 init_insn = gen_movsi (lc_reg, iter_reg);
4063 loop_init = gen_lsetup_without_autoinit (lt_reg, start_label,
4067 else if (P_REGNO_P (REGNO (iter_reg)))
4069 init_insn = NULL_RTX;
4070 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
4077 loop->init = init_insn;
4078 loop->end_label = end_label;
4079 loop->loop_init = loop_init;
4083 fprintf (dump_file, ";; replacing loop %d initializer with\n",
4085 print_rtl_single (dump_file, loop->loop_init);
4086 fprintf (dump_file, ";; replacing loop %d terminator with\n",
4088 print_rtl_single (dump_file, loop->loop_end);
4091 /* Create a sequence containing the loop setup. */
4094 if (loop->init != NULL_RTX)
4095 emit_insn (loop->init);
4096 seq_end = emit_insn (loop->loop_init);
4098 /* If the loop isn't entered at the top, also create a jump to the entry
4100 if (!loop->incoming_src && loop->head != loop->incoming_dest)
4102 rtx label = BB_HEAD (loop->incoming_dest);
4103 /* If we're jumping to the final basic block in the loop, and there's
4104 only one cheap instruction before the end (typically an increment of
4105 an induction variable), we can just emit a copy here instead of a
4107 if (loop->incoming_dest == loop->tail
4108 && next_real_insn (label) == last_insn
4109 && asm_noperands (last_insn) < 0
4110 && GET_CODE (PATTERN (last_insn)) == SET)
4112 seq_end = emit_insn (copy_rtx (PATTERN (last_insn)));
4115 seq_end = emit_insn (gen_jump (label));
4121 if (loop->incoming_src)
4123 rtx prev = BB_END (loop->incoming_src);
4124 if (VEC_length (edge, loop->incoming) > 1
4125 || !(VEC_last (edge, loop->incoming)->flags & EDGE_FALLTHRU))
4127 gcc_assert (JUMP_P (prev));
4128 prev = PREV_INSN (prev);
4130 emit_insn_after (seq, prev);
4138 #ifdef ENABLE_CHECKING
4139 if (loop->head != loop->incoming_dest)
4141 /* We aren't entering the loop at the top. Since we've established
4142 that the loop is entered only at one point, this means there
4143 can't be fallthru edges into the head. Any such fallthru edges
4144 would become invalid when we insert the new block, so verify
4145 that this does not in fact happen. */
4146 FOR_EACH_EDGE (e, ei, loop->head->preds)
4147 gcc_assert (!(e->flags & EDGE_FALLTHRU));
4151 emit_insn_before (seq, BB_HEAD (loop->head));
4152 seq = emit_label_before (gen_label_rtx (), seq);
4154 new_bb = create_basic_block (seq, seq_end, loop->head->prev_bb);
4155 FOR_EACH_EDGE (e, ei, loop->incoming)
4157 if (!(e->flags & EDGE_FALLTHRU)
4158 || e->dest != loop->head)
4159 redirect_edge_and_branch_force (e, new_bb);
4161 redirect_edge_succ (e, new_bb);
4165 delete_insn (loop->loop_end);
4166 /* Insert the loop end label before the last instruction of the loop. */
4167 emit_label_before (loop->end_label, loop->last_insn);
4174 fprintf (dump_file, ";; loop %d is bad\n", loop->loop_no);
4178 if (DPREG_P (loop->iter_reg))
4180 /* If loop->iter_reg is a DREG or PREG, we can split it here
4181 without scratch register. */
4184 emit_insn_before (gen_addsi3 (loop->iter_reg,
4189 emit_insn_before (gen_cmpsi (loop->iter_reg, const0_rtx),
4192 insn = emit_jump_insn_before (gen_bne (loop->start_label),
4195 JUMP_LABEL (insn) = loop->start_label;
4196 LABEL_NUSES (loop->start_label)++;
4197 delete_insn (loop->loop_end);
4201 /* Called from bfin_reorg_loops when a potential loop end is found. LOOP is
4202 a newly set up structure describing the loop, it is this function's
4203 responsibility to fill most of it. TAIL_BB and TAIL_INSN point to the
4204 loop_end insn and its enclosing basic block. */
4207 bfin_discover_loop (loop_info loop, basic_block tail_bb, rtx tail_insn)
4211 VEC (basic_block,heap) *works = VEC_alloc (basic_block,heap,20);
4213 loop->tail = tail_bb;
4214 loop->head = BRANCH_EDGE (tail_bb)->dest;
4215 loop->successor = FALLTHRU_EDGE (tail_bb)->dest;
4216 loop->loop_end = tail_insn;
4217 loop->last_insn = NULL_RTX;
4218 loop->iter_reg = SET_DEST (XVECEXP (PATTERN (tail_insn), 0, 1));
4219 loop->depth = loop->length = 0;
4221 loop->clobber_loop0 = loop->clobber_loop1 = 0;
4224 loop->incoming = VEC_alloc (edge, gc, 2);
4225 loop->init = loop->loop_init = NULL_RTX;
4226 loop->start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (tail_insn), 0, 0)), 1), 0);
4227 loop->end_label = NULL_RTX;
4230 VEC_safe_push (basic_block, heap, works, loop->head);
4232 while (VEC_iterate (basic_block, works, dwork++, bb))
4236 if (bb == EXIT_BLOCK_PTR)
4238 /* We've reached the exit block. The loop must be bad. */
4241 ";; Loop is bad - reached exit block while scanning\n");
4246 if (bitmap_bit_p (loop->block_bitmap, bb->index))
4249 /* We've not seen this block before. Add it to the loop's
4250 list and then add each successor to the work list. */
4252 VEC_safe_push (basic_block, heap, loop->blocks, bb);
4253 bitmap_set_bit (loop->block_bitmap, bb->index);
4257 FOR_EACH_EDGE (e, ei, bb->succs)
4259 basic_block succ = EDGE_SUCC (bb, ei.index)->dest;
4260 if (!REGNO_REG_SET_P (df_get_live_in (succ),
4261 REGNO (loop->iter_reg)))
4263 if (!VEC_space (basic_block, works, 1))
4267 VEC_block_remove (basic_block, works, 0, dwork);
4271 VEC_reserve (basic_block, heap, works, 1);
4273 VEC_quick_push (basic_block, works, succ);
4278 /* Find the predecessor, and make sure nothing else jumps into this loop. */
4282 for (dwork = 0; VEC_iterate (basic_block, loop->blocks, dwork, bb); dwork++)
4286 FOR_EACH_EDGE (e, ei, bb->preds)
4288 basic_block pred = e->src;
4290 if (!bfin_bb_in_loop (loop, pred))
4293 fprintf (dump_file, ";; Loop %d: incoming edge %d -> %d\n",
4294 loop->loop_no, pred->index,
4296 VEC_safe_push (edge, gc, loop->incoming, e);
4301 for (pass = 0, retry = 1; retry && pass < 2; pass++)
4308 FOR_EACH_EDGE (e, ei, loop->incoming)
4312 loop->incoming_src = e->src;
4313 loop->incoming_dest = e->dest;
4318 if (e->dest != loop->incoming_dest)
4319 loop->incoming_dest = NULL;
4320 if (e->src != loop->incoming_src)
4321 loop->incoming_src = NULL;
4323 if (loop->incoming_src == NULL && loop->incoming_dest == NULL)
4329 ";; retrying loop %d with forwarder blocks\n",
4337 ";; can't find suitable entry for loop %d\n",
4345 FOR_EACH_EDGE (e, ei, loop->incoming)
4347 if (forwarder_block_p (e->src))
4354 ";; Adding forwarder block %d to loop %d and retrying\n",
4355 e->src->index, loop->loop_no);
4356 VEC_safe_push (basic_block, heap, loop->blocks, e->src);
4357 bitmap_set_bit (loop->block_bitmap, e->src->index);
4358 FOR_EACH_EDGE (e2, ei2, e->src->preds)
4359 VEC_safe_push (edge, gc, loop->incoming, e2);
4360 VEC_unordered_remove (edge, loop->incoming, ei.index);
4368 fprintf (dump_file, ";; No forwarder blocks found\n");
4376 VEC_free (basic_block, heap, works);
4379 /* Analyze the structure of the loops in the current function. Use STACK
4380 for bitmap allocations. Returns all the valid candidates for hardware
4381 loops found in this function. */
4383 bfin_discover_loops (bitmap_obstack *stack, FILE *dump_file)
4385 loop_info loops = NULL;
4391 /* Find all the possible loop tails. This means searching for every
4392 loop_end instruction. For each one found, create a loop_info
4393 structure and add the head block to the work list. */
4396 rtx tail = BB_END (bb);
4398 while (GET_CODE (tail) == NOTE)
4399 tail = PREV_INSN (tail);
4403 if (INSN_P (tail) && recog_memoized (tail) == CODE_FOR_loop_end)
4406 /* A possible loop end */
4408 /* There's a degenerate case we can handle - an empty loop consisting
4409 of only a back branch. Handle that by deleting the branch. */
4410 insn = BB_HEAD (BRANCH_EDGE (bb)->dest);
4411 if (next_real_insn (insn) == tail)
4415 fprintf (dump_file, ";; degenerate loop ending at\n");
4416 print_rtl_single (dump_file, tail);
4418 delete_insn_and_edges (tail);
4422 loop = XNEW (struct loop_info);
4425 loop->loop_no = nloops++;
4426 loop->blocks = VEC_alloc (basic_block, heap, 20);
4427 loop->block_bitmap = BITMAP_ALLOC (stack);
4432 fprintf (dump_file, ";; potential loop %d ending at\n",
4434 print_rtl_single (dump_file, tail);
4437 bfin_discover_loop (loop, bb, tail);
4441 tmp_bitmap = BITMAP_ALLOC (stack);
4442 /* Compute loop nestings. */
4443 for (loop = loops; loop; loop = loop->next)
4449 for (other = loop->next; other; other = other->next)
4454 bitmap_and (tmp_bitmap, other->block_bitmap, loop->block_bitmap);
4455 if (bitmap_empty_p (tmp_bitmap))
4457 if (bitmap_equal_p (tmp_bitmap, other->block_bitmap))
4459 other->outer = loop;
4460 VEC_safe_push (loop_info, heap, loop->loops, other);
4462 else if (bitmap_equal_p (tmp_bitmap, loop->block_bitmap))
4464 loop->outer = other;
4465 VEC_safe_push (loop_info, heap, other->loops, loop);
4471 ";; can't find suitable nesting for loops %d and %d\n",
4472 loop->loop_no, other->loop_no);
4473 loop->bad = other->bad = 1;
4477 BITMAP_FREE (tmp_bitmap);
4482 /* Free up the loop structures in LOOPS. */
4484 free_loops (loop_info loops)
4488 loop_info loop = loops;
4490 VEC_free (loop_info, heap, loop->loops);
4491 VEC_free (basic_block, heap, loop->blocks);
4492 BITMAP_FREE (loop->block_bitmap);
4497 #define BB_AUX_INDEX(BB) ((unsigned)(BB)->aux)
4499 /* The taken-branch edge from the loop end can actually go forward. Since the
4500 Blackfin's LSETUP instruction requires that the loop end be after the loop
4501 start, try to reorder a loop's basic blocks when we find such a case. */
4503 bfin_reorder_loops (loop_info loops, FILE *dump_file)
4510 cfg_layout_initialize (0);
4512 for (loop = loops; loop; loop = loop->next)
4522 /* Recreate an index for basic blocks that represents their order. */
4523 for (bb = ENTRY_BLOCK_PTR->next_bb, index = 0;
4524 bb != EXIT_BLOCK_PTR;
4525 bb = bb->next_bb, index++)
4526 bb->aux = (PTR) index;
4528 if (BB_AUX_INDEX (loop->head) < BB_AUX_INDEX (loop->tail))
4531 FOR_EACH_EDGE (e, ei, loop->head->succs)
4533 if (bitmap_bit_p (loop->block_bitmap, e->dest->index)
4534 && BB_AUX_INDEX (e->dest) < BB_AUX_INDEX (loop->tail))
4536 basic_block start_bb = e->dest;
4537 basic_block start_prev_bb = start_bb->prev_bb;
4540 fprintf (dump_file, ";; Moving block %d before block %d\n",
4541 loop->head->index, start_bb->index);
4542 loop->head->prev_bb->next_bb = loop->head->next_bb;
4543 loop->head->next_bb->prev_bb = loop->head->prev_bb;
4545 loop->head->prev_bb = start_prev_bb;
4546 loop->head->next_bb = start_bb;
4547 start_prev_bb->next_bb = start_bb->prev_bb = loop->head;
4551 loops = loops->next;
4556 if (bb->next_bb != EXIT_BLOCK_PTR)
4557 bb->aux = bb->next_bb;
4561 cfg_layout_finalize ();
4565 /* Run from machine_dependent_reorg, this pass looks for doloop_end insns
4566 and tries to rewrite the RTL of these loops so that proper Blackfin
4567 hardware loops are generated. */
4570 bfin_reorg_loops (FILE *dump_file)
4572 loop_info loops = NULL;
4575 bitmap_obstack stack;
4577 bitmap_obstack_initialize (&stack);
4580 fprintf (dump_file, ";; Find loops, first pass\n\n");
4582 loops = bfin_discover_loops (&stack, dump_file);
4585 bfin_dump_loops (loops);
4587 bfin_reorder_loops (loops, dump_file);
4591 fprintf (dump_file, ";; Find loops, second pass\n\n");
4593 loops = bfin_discover_loops (&stack, dump_file);
4596 fprintf (dump_file, ";; All loops found:\n\n");
4597 bfin_dump_loops (loops);
4600 /* Now apply the optimizations. */
4601 for (loop = loops; loop; loop = loop->next)
4602 bfin_optimize_loop (loop);
4606 fprintf (dump_file, ";; After hardware loops optimization:\n\n");
4607 bfin_dump_loops (loops);
4613 print_rtl (dump_file, get_insns ());
4619 /* Possibly generate a SEQUENCE out of three insns found in SLOT.
4620 Returns true if we modified the insn chain, false otherwise. */
4622 gen_one_bundle (rtx slot[3])
4624 gcc_assert (slot[1] != NULL_RTX);
4626 /* Don't add extra NOPs if optimizing for size. */
4628 && (slot[0] == NULL_RTX || slot[2] == NULL_RTX))
4631 /* Verify that we really can do the multi-issue. */
4634 rtx t = NEXT_INSN (slot[0]);
4635 while (t != slot[1])
4637 if (GET_CODE (t) != NOTE
4638 || NOTE_KIND (t) != NOTE_INSN_DELETED)
4645 rtx t = NEXT_INSN (slot[1]);
4646 while (t != slot[2])
4648 if (GET_CODE (t) != NOTE
4649 || NOTE_KIND (t) != NOTE_INSN_DELETED)
4655 if (slot[0] == NULL_RTX)
4657 slot[0] = emit_insn_before (gen_mnop (), slot[1]);
4658 df_insn_rescan (slot[0]);
4660 if (slot[2] == NULL_RTX)
4662 slot[2] = emit_insn_after (gen_forced_nop (), slot[1]);
4663 df_insn_rescan (slot[2]);
4666 /* Avoid line number information being printed inside one bundle. */
4667 if (INSN_LOCATOR (slot[1])
4668 && INSN_LOCATOR (slot[1]) != INSN_LOCATOR (slot[0]))
4669 INSN_LOCATOR (slot[1]) = INSN_LOCATOR (slot[0]);
4670 if (INSN_LOCATOR (slot[2])
4671 && INSN_LOCATOR (slot[2]) != INSN_LOCATOR (slot[0]))
4672 INSN_LOCATOR (slot[2]) = INSN_LOCATOR (slot[0]);
4674 /* Terminate them with "|| " instead of ";" in the output. */
4675 PUT_MODE (slot[0], SImode);
4676 PUT_MODE (slot[1], SImode);
4677 /* Terminate the bundle, for the benefit of reorder_var_tracking_notes. */
4678 PUT_MODE (slot[2], QImode);
4682 /* Go through all insns, and use the information generated during scheduling
4683 to generate SEQUENCEs to represent bundles of instructions issued
4687 bfin_gen_bundles (void)
4696 slot[0] = slot[1] = slot[2] = NULL_RTX;
4697 for (insn = BB_HEAD (bb);; insn = next)
4702 if (get_attr_type (insn) == TYPE_DSP32)
4704 else if (slot[1] == NULL_RTX)
4711 next = NEXT_INSN (insn);
4712 while (next && insn != BB_END (bb)
4714 && GET_CODE (PATTERN (next)) != USE
4715 && GET_CODE (PATTERN (next)) != CLOBBER))
4718 next = NEXT_INSN (insn);
4721 /* BB_END can change due to emitting extra NOPs, so check here. */
4722 at_end = insn == BB_END (bb);
4723 if (at_end || GET_MODE (next) == TImode)
4726 || !gen_one_bundle (slot))
4727 && slot[0] != NULL_RTX)
4729 rtx pat = PATTERN (slot[0]);
4730 if (GET_CODE (pat) == SET
4731 && GET_CODE (SET_SRC (pat)) == UNSPEC
4732 && XINT (SET_SRC (pat), 1) == UNSPEC_32BIT)
4734 SET_SRC (pat) = XVECEXP (SET_SRC (pat), 0, 0);
4735 INSN_CODE (slot[0]) = -1;
4736 df_insn_rescan (slot[0]);
4740 slot[0] = slot[1] = slot[2] = NULL_RTX;
4748 /* Ensure that no var tracking notes are emitted in the middle of a
4749 three-instruction bundle. */
4752 reorder_var_tracking_notes (void)
4758 rtx queue = NULL_RTX;
4759 bool in_bundle = false;
4761 for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = next)
4763 next = NEXT_INSN (insn);
4767 /* Emit queued up notes at the last instruction of a bundle. */
4768 if (GET_MODE (insn) == QImode)
4772 rtx next_queue = PREV_INSN (queue);
4773 PREV_INSN (NEXT_INSN (insn)) = queue;
4774 NEXT_INSN (queue) = NEXT_INSN (insn);
4775 NEXT_INSN (insn) = queue;
4776 PREV_INSN (queue) = insn;
4781 else if (GET_MODE (insn) == SImode)
4784 else if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION)
4788 rtx prev = PREV_INSN (insn);
4789 PREV_INSN (next) = prev;
4790 NEXT_INSN (prev) = next;
4792 PREV_INSN (insn) = queue;
4800 /* On some silicon revisions, functions shorter than a certain number of cycles
4801 can cause unpredictable behaviour. Work around this by adding NOPs as
4804 workaround_rts_anomaly (void)
4806 rtx insn, first_insn = NULL_RTX;
4809 if (! ENABLE_WA_RETS)
4812 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4816 if (BARRIER_P (insn))
4819 if (NOTE_P (insn) || LABEL_P (insn))
4822 if (first_insn == NULL_RTX)
4824 pat = PATTERN (insn);
4825 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4826 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
4827 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
4835 if (recog_memoized (insn) == CODE_FOR_return_internal)
4838 /* Nothing to worry about for direct jumps. */
4839 if (!any_condjump_p (insn))
4845 else if (INSN_P (insn))
4847 rtx pat = PATTERN (insn);
4848 int this_cycles = 1;
4850 if (GET_CODE (pat) == PARALLEL)
4852 if (push_multiple_operation (pat, VOIDmode)
4853 || pop_multiple_operation (pat, VOIDmode))
4854 this_cycles = n_regs_to_save;
4858 enum insn_code icode = recog_memoized (insn);
4859 if (icode == CODE_FOR_link)
4861 else if (icode == CODE_FOR_unlink)
4863 else if (icode == CODE_FOR_mulsi3)
4866 if (this_cycles >= cycles)
4869 cycles -= this_cycles;
4874 emit_insn_before (gen_nop (), first_insn);
4879 /* Return an insn type for INSN that can be used by the caller for anomaly
4880 workarounds. This differs from plain get_attr_type in that it handles
4883 static enum attr_type
4884 type_for_anomaly (rtx insn)
4886 rtx pat = PATTERN (insn);
4887 if (GET_CODE (pat) == SEQUENCE)
4890 t = get_attr_type (XVECEXP (pat, 0, 1));
4893 t = get_attr_type (XVECEXP (pat, 0, 2));
4899 return get_attr_type (insn);
4902 /* Return nonzero if INSN contains any loads that may trap. It handles
4903 SEQUENCEs correctly. */
4906 trapping_loads_p (rtx insn)
4908 rtx pat = PATTERN (insn);
4909 if (GET_CODE (pat) == SEQUENCE)
4912 t = get_attr_type (XVECEXP (pat, 0, 1));
4914 && may_trap_p (SET_SRC (PATTERN (XVECEXP (pat, 0, 1)))))
4916 t = get_attr_type (XVECEXP (pat, 0, 2));
4918 && may_trap_p (SET_SRC (PATTERN (XVECEXP (pat, 0, 2)))))
4923 return may_trap_p (SET_SRC (single_set (insn)));
4926 /* Return INSN if it is of TYPE_MCLD. Alternatively, if INSN is the start of
4927 a three-insn bundle, see if one of them is a load and return that if so.
4928 Return NULL_RTX if the insn does not contain loads. */
4930 find_load (rtx insn)
4932 if (get_attr_type (insn) == TYPE_MCLD)
4934 if (GET_MODE (insn) != SImode)
4937 insn = NEXT_INSN (insn);
4938 if ((GET_MODE (insn) == SImode || GET_MODE (insn) == QImode)
4939 && get_attr_type (insn) == TYPE_MCLD)
4941 } while (GET_MODE (insn) != QImode);
4945 /* Determine whether PAT is an indirect call pattern. */
4947 indirect_call_p (rtx pat)
4949 if (GET_CODE (pat) == PARALLEL)
4950 pat = XVECEXP (pat, 0, 0);
4951 if (GET_CODE (pat) == SET)
4952 pat = SET_SRC (pat);
4953 gcc_assert (GET_CODE (pat) == CALL);
4954 pat = XEXP (pat, 0);
4955 gcc_assert (GET_CODE (pat) == MEM);
4956 pat = XEXP (pat, 0);
4962 workaround_speculation (void)
4965 rtx last_condjump = NULL_RTX;
4966 int cycles_since_jump = INT_MAX;
4967 int delay_added = 0;
4969 if (! ENABLE_WA_SPECULATIVE_LOADS && ! ENABLE_WA_SPECULATIVE_SYNCS
4970 && ! ENABLE_WA_INDIRECT_CALLS)
4973 /* First pass: find predicted-false branches; if something after them
4974 needs nops, insert them or change the branch to predict true. */
4975 for (insn = get_insns (); insn; insn = next)
4978 int delay_needed = 0;
4980 next = find_next_insn_start (insn);
4982 if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
4985 pat = PATTERN (insn);
4986 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
4987 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
4988 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
4993 if (any_condjump_p (insn)
4994 && ! cbranch_predicted_taken_p (insn))
4996 last_condjump = insn;
4998 cycles_since_jump = 0;
5001 cycles_since_jump = INT_MAX;
5003 else if (CALL_P (insn))
5005 if (cycles_since_jump < INT_MAX)
5006 cycles_since_jump++;
5007 if (indirect_call_p (pat) && ENABLE_WA_INDIRECT_CALLS)
5012 else if (INSN_P (insn))
5014 rtx load_insn = find_load (insn);
5015 enum attr_type type = type_for_anomaly (insn);
5017 if (cycles_since_jump < INT_MAX)
5018 cycles_since_jump++;
5020 if (load_insn && ENABLE_WA_SPECULATIVE_LOADS)
5022 if (trapping_loads_p (load_insn))
5025 else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS)
5029 if (delay_needed > cycles_since_jump
5030 && (delay_needed - cycles_since_jump) > delay_added)
5034 rtx *op = recog_data.operand;
5036 delay_needed -= cycles_since_jump;
5038 extract_insn (last_condjump);
5041 pat1 = gen_cbranch_predicted_taken (op[0], op[1], op[2],
5043 cycles_since_jump = INT_MAX;
5047 /* Do not adjust cycles_since_jump in this case, so that
5048 we'll increase the number of NOPs for a subsequent insn
5050 pat1 = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
5051 GEN_INT (delay_needed));
5052 delay_added = delay_needed;
5054 PATTERN (last_condjump) = pat1;
5055 INSN_CODE (last_condjump) = recog (pat1, insn, &num_clobbers);
5059 cycles_since_jump = INT_MAX;
5064 /* Second pass: for predicted-true branches, see if anything at the
5065 branch destination needs extra nops. */
5066 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5068 int cycles_since_jump;
5070 && any_condjump_p (insn)
5071 && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken
5072 || cbranch_predicted_taken_p (insn)))
5074 rtx target = JUMP_LABEL (insn);
5078 cycles_since_jump = 0;
5079 for (; target && cycles_since_jump < 3; target = next_tgt)
5083 next_tgt = find_next_insn_start (target);
5085 if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
5088 pat = PATTERN (target);
5089 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
5090 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
5091 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
5094 if (INSN_P (target))
5096 rtx load_insn = find_load (target);
5097 enum attr_type type = type_for_anomaly (target);
5098 int delay_needed = 0;
5099 if (cycles_since_jump < INT_MAX)
5100 cycles_since_jump++;
5102 if (load_insn && ENABLE_WA_SPECULATIVE_LOADS)
5104 if (trapping_loads_p (load_insn))
5107 else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS)
5110 if (delay_needed > cycles_since_jump)
5112 rtx prev = prev_real_insn (label);
5113 delay_needed -= cycles_since_jump;
5115 fprintf (dump_file, "Adding %d nops after %d\n",
5116 delay_needed, INSN_UID (label));
5118 && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops)
5125 "Reducing nops on insn %d.\n",
5128 x = XVECEXP (x, 0, 1);
5129 v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed;
5130 XVECEXP (x, 0, 0) = GEN_INT (v);
5132 while (delay_needed-- > 0)
5133 emit_insn_after (gen_nop (), label);
5142 /* We use the machine specific reorg pass for emitting CSYNC instructions
5143 after conditional branches as needed.
5145 The Blackfin is unusual in that a code sequence like
5148 may speculatively perform the load even if the condition isn't true. This
5149 happens for a branch that is predicted not taken, because the pipeline
5150 isn't flushed or stalled, so the early stages of the following instructions,
5151 which perform the memory reference, are allowed to execute before the
5152 jump condition is evaluated.
5153 Therefore, we must insert additional instructions in all places where this
5154 could lead to incorrect behavior. The manual recommends CSYNC, while
5155 VDSP seems to use NOPs (even though its corresponding compiler option is
5158 When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
5159 When optimizing for size, we turn the branch into a predicted taken one.
5160 This may be slower due to mispredicts, but saves code size. */
5165 /* We are freeing block_for_insn in the toplev to keep compatibility
5166 with old MDEP_REORGS that are not CFG based. Recompute it now. */
5167 compute_bb_for_insn ();
5169 if (bfin_flag_schedule_insns2)
5171 splitting_for_sched = 1;
5173 splitting_for_sched = 0;
5175 timevar_push (TV_SCHED2);
5177 timevar_pop (TV_SCHED2);
5179 /* Examine the schedule and insert nops as necessary for 64-bit parallel
5181 bfin_gen_bundles ();
5186 /* Doloop optimization */
5187 if (cfun->machine->has_hardware_loops)
5188 bfin_reorg_loops (dump_file);
5190 workaround_speculation ();
5192 if (bfin_flag_var_tracking)
5194 timevar_push (TV_VAR_TRACKING);
5195 variable_tracking_main ();
5196 reorder_var_tracking_notes ();
5197 timevar_pop (TV_VAR_TRACKING);
5200 df_finish_pass (false);
5202 workaround_rts_anomaly ();
5205 /* Handle interrupt_handler, exception_handler and nmi_handler function
5206 attributes; arguments as in struct attribute_spec.handler. */
5209 handle_int_attribute (tree *node, tree name,
5210 tree args ATTRIBUTE_UNUSED,
5211 int flags ATTRIBUTE_UNUSED,
5215 if (TREE_CODE (x) == FUNCTION_DECL)
5218 if (TREE_CODE (x) != FUNCTION_TYPE)
5220 warning (OPT_Wattributes, "%qs attribute only applies to functions",
5221 IDENTIFIER_POINTER (name));
5222 *no_add_attrs = true;
5224 else if (funkind (x) != SUBROUTINE)
5225 error ("multiple function type attributes specified");
5230 /* Return 0 if the attributes for two types are incompatible, 1 if they
5231 are compatible, and 2 if they are nearly compatible (which causes a
5232 warning to be generated). */
5235 bfin_comp_type_attributes (const_tree type1, const_tree type2)
5237 e_funkind kind1, kind2;
5239 if (TREE_CODE (type1) != FUNCTION_TYPE)
5242 kind1 = funkind (type1);
5243 kind2 = funkind (type2);
5248 /* Check for mismatched modifiers */
5249 if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
5250 != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
5253 if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
5254 != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
5257 if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
5258 != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
5261 if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1))
5262 != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2)))
5268 /* Handle a "longcall" or "shortcall" attribute; arguments as in
5269 struct attribute_spec.handler. */
5272 bfin_handle_longcall_attribute (tree *node, tree name,
5273 tree args ATTRIBUTE_UNUSED,
5274 int flags ATTRIBUTE_UNUSED,
5277 if (TREE_CODE (*node) != FUNCTION_TYPE
5278 && TREE_CODE (*node) != FIELD_DECL
5279 && TREE_CODE (*node) != TYPE_DECL)
5281 warning (OPT_Wattributes, "`%s' attribute only applies to functions",
5282 IDENTIFIER_POINTER (name));
5283 *no_add_attrs = true;
5286 if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0
5287 && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node)))
5288 || (strcmp (IDENTIFIER_POINTER (name), "shortcall") == 0
5289 && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node))))
5291 warning (OPT_Wattributes,
5292 "can't apply both longcall and shortcall attributes to the same function");
5293 *no_add_attrs = true;
5299 /* Handle a "l1_text" attribute; arguments as in
5300 struct attribute_spec.handler. */
5303 bfin_handle_l1_text_attribute (tree *node, tree name, tree ARG_UNUSED (args),
5304 int ARG_UNUSED (flags), bool *no_add_attrs)
5308 if (TREE_CODE (decl) != FUNCTION_DECL)
5310 error ("`%s' attribute only applies to functions",
5311 IDENTIFIER_POINTER (name));
5312 *no_add_attrs = true;
5315 /* The decl may have already been given a section attribute
5316 from a previous declaration. Ensure they match. */
5317 else if (DECL_SECTION_NAME (decl) != NULL_TREE
5318 && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
5321 error ("section of %q+D conflicts with previous declaration",
5323 *no_add_attrs = true;
5326 DECL_SECTION_NAME (decl) = build_string (9, ".l1.text");
5331 /* Handle a "l1_data", "l1_data_A" or "l1_data_B" attribute;
5332 arguments as in struct attribute_spec.handler. */
5335 bfin_handle_l1_data_attribute (tree *node, tree name, tree ARG_UNUSED (args),
5336 int ARG_UNUSED (flags), bool *no_add_attrs)
5340 if (TREE_CODE (decl) != VAR_DECL)
5342 error ("`%s' attribute only applies to variables",
5343 IDENTIFIER_POINTER (name));
5344 *no_add_attrs = true;
5346 else if (current_function_decl != NULL_TREE
5347 && !TREE_STATIC (decl))
5349 error ("`%s' attribute cannot be specified for local variables",
5350 IDENTIFIER_POINTER (name));
5351 *no_add_attrs = true;
5355 const char *section_name;
5357 if (strcmp (IDENTIFIER_POINTER (name), "l1_data") == 0)
5358 section_name = ".l1.data";
5359 else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_A") == 0)
5360 section_name = ".l1.data.A";
5361 else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_B") == 0)
5362 section_name = ".l1.data.B";
5366 /* The decl may have already been given a section attribute
5367 from a previous declaration. Ensure they match. */
5368 if (DECL_SECTION_NAME (decl) != NULL_TREE
5369 && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
5372 error ("section of %q+D conflicts with previous declaration",
5374 *no_add_attrs = true;
5377 DECL_SECTION_NAME (decl)
5378 = build_string (strlen (section_name) + 1, section_name);
5384 /* Table of valid machine attributes. */
5385 const struct attribute_spec bfin_attribute_table[] =
5387 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
5388 { "interrupt_handler", 0, 0, false, true, true, handle_int_attribute },
5389 { "exception_handler", 0, 0, false, true, true, handle_int_attribute },
5390 { "nmi_handler", 0, 0, false, true, true, handle_int_attribute },
5391 { "nesting", 0, 0, false, true, true, NULL },
5392 { "kspisusp", 0, 0, false, true, true, NULL },
5393 { "saveall", 0, 0, false, true, true, NULL },
5394 { "longcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
5395 { "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
5396 { "l1_text", 0, 0, true, false, false, bfin_handle_l1_text_attribute },
5397 { "l1_data", 0, 0, true, false, false, bfin_handle_l1_data_attribute },
5398 { "l1_data_A", 0, 0, true, false, false, bfin_handle_l1_data_attribute },
5399 { "l1_data_B", 0, 0, true, false, false, bfin_handle_l1_data_attribute },
5400 { NULL, 0, 0, false, false, false, NULL }
5403 /* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to
5404 tell the assembler to generate pointers to function descriptors in
5408 bfin_assemble_integer (rtx value, unsigned int size, int aligned_p)
5410 if (TARGET_FDPIC && size == UNITS_PER_WORD)
5412 if (GET_CODE (value) == SYMBOL_REF
5413 && SYMBOL_REF_FUNCTION_P (value))
5415 fputs ("\t.picptr\tfuncdesc(", asm_out_file);
5416 output_addr_const (asm_out_file, value);
5417 fputs (")\n", asm_out_file);
5422 /* We've set the unaligned SI op to NULL, so we always have to
5423 handle the unaligned case here. */
5424 assemble_integer_with_op ("\t.4byte\t", value);
5428 return default_assemble_integer (value, size, aligned_p);
5431 /* Output the assembler code for a thunk function. THUNK_DECL is the
5432 declaration for the thunk function itself, FUNCTION is the decl for
5433 the target function. DELTA is an immediate constant offset to be
5434 added to THIS. If VCALL_OFFSET is nonzero, the word at
5435 *(*this + vcall_offset) should be added to THIS. */
5438 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
5439 tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
5440 HOST_WIDE_INT vcall_offset, tree function)
5443 /* The this parameter is passed as the first argument. */
5444 rtx this_rtx = gen_rtx_REG (Pmode, REG_R0);
5446 /* Adjust the this parameter by a fixed constant. */
5450 if (delta >= -64 && delta <= 63)
5452 xops[0] = GEN_INT (delta);
5453 output_asm_insn ("%1 += %0;", xops);
5455 else if (delta >= -128 && delta < -64)
5457 xops[0] = GEN_INT (delta + 64);
5458 output_asm_insn ("%1 += -64; %1 += %0;", xops);
5460 else if (delta > 63 && delta <= 126)
5462 xops[0] = GEN_INT (delta - 63);
5463 output_asm_insn ("%1 += 63; %1 += %0;", xops);
5467 xops[0] = GEN_INT (delta);
5468 output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
5472 /* Adjust the this parameter by a value stored in the vtable. */
5475 rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
5476 rtx tmp = gen_rtx_REG (Pmode, REG_R3);
5480 output_asm_insn ("%2 = r0; %2 = [%2];", xops);
5482 /* Adjust the this parameter. */
5483 xops[0] = gen_rtx_MEM (Pmode, plus_constant (p2tmp, vcall_offset));
5484 if (!memory_operand (xops[0], Pmode))
5486 rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
5487 xops[0] = GEN_INT (vcall_offset);
5489 output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
5490 xops[0] = gen_rtx_MEM (Pmode, p2tmp);
5493 output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
5496 xops[0] = XEXP (DECL_RTL (function), 0);
5497 if (1 || !flag_pic || (*targetm.binds_local_p) (function))
5498 output_asm_insn ("jump.l\t%P0", xops);
5501 /* Codes for all the Blackfin builtins. */
5507 BFIN_BUILTIN_COMPOSE_2X16,
5508 BFIN_BUILTIN_EXTRACTLO,
5509 BFIN_BUILTIN_EXTRACTHI,
5511 BFIN_BUILTIN_SSADD_2X16,
5512 BFIN_BUILTIN_SSSUB_2X16,
5513 BFIN_BUILTIN_SSADDSUB_2X16,
5514 BFIN_BUILTIN_SSSUBADD_2X16,
5515 BFIN_BUILTIN_MULT_2X16,
5516 BFIN_BUILTIN_MULTR_2X16,
5517 BFIN_BUILTIN_NEG_2X16,
5518 BFIN_BUILTIN_ABS_2X16,
5519 BFIN_BUILTIN_MIN_2X16,
5520 BFIN_BUILTIN_MAX_2X16,
5522 BFIN_BUILTIN_SSADD_1X16,
5523 BFIN_BUILTIN_SSSUB_1X16,
5524 BFIN_BUILTIN_MULT_1X16,
5525 BFIN_BUILTIN_MULTR_1X16,
5526 BFIN_BUILTIN_NORM_1X16,
5527 BFIN_BUILTIN_NEG_1X16,
5528 BFIN_BUILTIN_ABS_1X16,
5529 BFIN_BUILTIN_MIN_1X16,
5530 BFIN_BUILTIN_MAX_1X16,
5532 BFIN_BUILTIN_SUM_2X16,
5533 BFIN_BUILTIN_DIFFHL_2X16,
5534 BFIN_BUILTIN_DIFFLH_2X16,
5536 BFIN_BUILTIN_SSADD_1X32,
5537 BFIN_BUILTIN_SSSUB_1X32,
5538 BFIN_BUILTIN_NORM_1X32,
5539 BFIN_BUILTIN_ROUND_1X32,
5540 BFIN_BUILTIN_NEG_1X32,
5541 BFIN_BUILTIN_ABS_1X32,
5542 BFIN_BUILTIN_MIN_1X32,
5543 BFIN_BUILTIN_MAX_1X32,
5544 BFIN_BUILTIN_MULT_1X32,
5545 BFIN_BUILTIN_MULT_1X32X32,
5546 BFIN_BUILTIN_MULT_1X32X32NS,
5548 BFIN_BUILTIN_MULHISILL,
5549 BFIN_BUILTIN_MULHISILH,
5550 BFIN_BUILTIN_MULHISIHL,
5551 BFIN_BUILTIN_MULHISIHH,
5553 BFIN_BUILTIN_LSHIFT_1X16,
5554 BFIN_BUILTIN_LSHIFT_2X16,
5555 BFIN_BUILTIN_SSASHIFT_1X16,
5556 BFIN_BUILTIN_SSASHIFT_2X16,
5557 BFIN_BUILTIN_SSASHIFT_1X32,
5559 BFIN_BUILTIN_CPLX_MUL_16,
5560 BFIN_BUILTIN_CPLX_MAC_16,
5561 BFIN_BUILTIN_CPLX_MSU_16,
5563 BFIN_BUILTIN_CPLX_MUL_16_S40,
5564 BFIN_BUILTIN_CPLX_MAC_16_S40,
5565 BFIN_BUILTIN_CPLX_MSU_16_S40,
5567 BFIN_BUILTIN_CPLX_SQU,
5569 BFIN_BUILTIN_LOADBYTES,
5574 #define def_builtin(NAME, TYPE, CODE) \
5576 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
5580 /* Set up all builtin functions for this target. */
5582 bfin_init_builtins (void)
5584 tree V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
5585 tree void_ftype_void
5586 = build_function_type (void_type_node, void_list_node);
5587 tree short_ftype_short
5588 = build_function_type_list (short_integer_type_node, short_integer_type_node,
5590 tree short_ftype_int_int
5591 = build_function_type_list (short_integer_type_node, integer_type_node,
5592 integer_type_node, NULL_TREE);
5593 tree int_ftype_int_int
5594 = build_function_type_list (integer_type_node, integer_type_node,
5595 integer_type_node, NULL_TREE);
5597 = build_function_type_list (integer_type_node, integer_type_node,
5599 tree short_ftype_int
5600 = build_function_type_list (short_integer_type_node, integer_type_node,
5602 tree int_ftype_v2hi_v2hi
5603 = build_function_type_list (integer_type_node, V2HI_type_node,
5604 V2HI_type_node, NULL_TREE);
5605 tree v2hi_ftype_v2hi_v2hi
5606 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5607 V2HI_type_node, NULL_TREE);
5608 tree v2hi_ftype_v2hi_v2hi_v2hi
5609 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5610 V2HI_type_node, V2HI_type_node, NULL_TREE);
5611 tree v2hi_ftype_int_int
5612 = build_function_type_list (V2HI_type_node, integer_type_node,
5613 integer_type_node, NULL_TREE);
5614 tree v2hi_ftype_v2hi_int
5615 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5616 integer_type_node, NULL_TREE);
5617 tree int_ftype_short_short
5618 = build_function_type_list (integer_type_node, short_integer_type_node,
5619 short_integer_type_node, NULL_TREE);
5620 tree v2hi_ftype_v2hi
5621 = build_function_type_list (V2HI_type_node, V2HI_type_node, NULL_TREE);
5622 tree short_ftype_v2hi
5623 = build_function_type_list (short_integer_type_node, V2HI_type_node,
5626 = build_function_type_list (integer_type_node,
5627 build_pointer_type (integer_type_node),
5630 /* Add the remaining MMX insns with somewhat more complicated types. */
5631 def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC);
5632 def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC);
5634 def_builtin ("__builtin_bfin_ones", short_ftype_int, BFIN_BUILTIN_ONES);
5636 def_builtin ("__builtin_bfin_compose_2x16", v2hi_ftype_int_int,
5637 BFIN_BUILTIN_COMPOSE_2X16);
5638 def_builtin ("__builtin_bfin_extract_hi", short_ftype_v2hi,
5639 BFIN_BUILTIN_EXTRACTHI);
5640 def_builtin ("__builtin_bfin_extract_lo", short_ftype_v2hi,
5641 BFIN_BUILTIN_EXTRACTLO);
5643 def_builtin ("__builtin_bfin_min_fr2x16", v2hi_ftype_v2hi_v2hi,
5644 BFIN_BUILTIN_MIN_2X16);
5645 def_builtin ("__builtin_bfin_max_fr2x16", v2hi_ftype_v2hi_v2hi,
5646 BFIN_BUILTIN_MAX_2X16);
5648 def_builtin ("__builtin_bfin_add_fr2x16", v2hi_ftype_v2hi_v2hi,
5649 BFIN_BUILTIN_SSADD_2X16);
5650 def_builtin ("__builtin_bfin_sub_fr2x16", v2hi_ftype_v2hi_v2hi,
5651 BFIN_BUILTIN_SSSUB_2X16);
5652 def_builtin ("__builtin_bfin_dspaddsubsat", v2hi_ftype_v2hi_v2hi,
5653 BFIN_BUILTIN_SSADDSUB_2X16);
5654 def_builtin ("__builtin_bfin_dspsubaddsat", v2hi_ftype_v2hi_v2hi,
5655 BFIN_BUILTIN_SSSUBADD_2X16);
5656 def_builtin ("__builtin_bfin_mult_fr2x16", v2hi_ftype_v2hi_v2hi,
5657 BFIN_BUILTIN_MULT_2X16);
5658 def_builtin ("__builtin_bfin_multr_fr2x16", v2hi_ftype_v2hi_v2hi,
5659 BFIN_BUILTIN_MULTR_2X16);
5660 def_builtin ("__builtin_bfin_negate_fr2x16", v2hi_ftype_v2hi,
5661 BFIN_BUILTIN_NEG_2X16);
5662 def_builtin ("__builtin_bfin_abs_fr2x16", v2hi_ftype_v2hi,
5663 BFIN_BUILTIN_ABS_2X16);
5665 def_builtin ("__builtin_bfin_min_fr1x16", short_ftype_int_int,
5666 BFIN_BUILTIN_MIN_1X16);
5667 def_builtin ("__builtin_bfin_max_fr1x16", short_ftype_int_int,
5668 BFIN_BUILTIN_MAX_1X16);
5670 def_builtin ("__builtin_bfin_add_fr1x16", short_ftype_int_int,
5671 BFIN_BUILTIN_SSADD_1X16);
5672 def_builtin ("__builtin_bfin_sub_fr1x16", short_ftype_int_int,
5673 BFIN_BUILTIN_SSSUB_1X16);
5674 def_builtin ("__builtin_bfin_mult_fr1x16", short_ftype_int_int,
5675 BFIN_BUILTIN_MULT_1X16);
5676 def_builtin ("__builtin_bfin_multr_fr1x16", short_ftype_int_int,
5677 BFIN_BUILTIN_MULTR_1X16);
5678 def_builtin ("__builtin_bfin_negate_fr1x16", short_ftype_short,
5679 BFIN_BUILTIN_NEG_1X16);
5680 def_builtin ("__builtin_bfin_abs_fr1x16", short_ftype_short,
5681 BFIN_BUILTIN_ABS_1X16);
5682 def_builtin ("__builtin_bfin_norm_fr1x16", short_ftype_int,
5683 BFIN_BUILTIN_NORM_1X16);
5685 def_builtin ("__builtin_bfin_sum_fr2x16", short_ftype_v2hi,
5686 BFIN_BUILTIN_SUM_2X16);
5687 def_builtin ("__builtin_bfin_diff_hl_fr2x16", short_ftype_v2hi,
5688 BFIN_BUILTIN_DIFFHL_2X16);
5689 def_builtin ("__builtin_bfin_diff_lh_fr2x16", short_ftype_v2hi,
5690 BFIN_BUILTIN_DIFFLH_2X16);
5692 def_builtin ("__builtin_bfin_mulhisill", int_ftype_v2hi_v2hi,
5693 BFIN_BUILTIN_MULHISILL);
5694 def_builtin ("__builtin_bfin_mulhisihl", int_ftype_v2hi_v2hi,
5695 BFIN_BUILTIN_MULHISIHL);
5696 def_builtin ("__builtin_bfin_mulhisilh", int_ftype_v2hi_v2hi,
5697 BFIN_BUILTIN_MULHISILH);
5698 def_builtin ("__builtin_bfin_mulhisihh", int_ftype_v2hi_v2hi,
5699 BFIN_BUILTIN_MULHISIHH);
5701 def_builtin ("__builtin_bfin_min_fr1x32", int_ftype_int_int,
5702 BFIN_BUILTIN_MIN_1X32);
5703 def_builtin ("__builtin_bfin_max_fr1x32", int_ftype_int_int,
5704 BFIN_BUILTIN_MAX_1X32);
5706 def_builtin ("__builtin_bfin_add_fr1x32", int_ftype_int_int,
5707 BFIN_BUILTIN_SSADD_1X32);
5708 def_builtin ("__builtin_bfin_sub_fr1x32", int_ftype_int_int,
5709 BFIN_BUILTIN_SSSUB_1X32);
5710 def_builtin ("__builtin_bfin_negate_fr1x32", int_ftype_int,
5711 BFIN_BUILTIN_NEG_1X32);
5712 def_builtin ("__builtin_bfin_abs_fr1x32", int_ftype_int,
5713 BFIN_BUILTIN_ABS_1X32);
5714 def_builtin ("__builtin_bfin_norm_fr1x32", short_ftype_int,
5715 BFIN_BUILTIN_NORM_1X32);
5716 def_builtin ("__builtin_bfin_round_fr1x32", short_ftype_int,
5717 BFIN_BUILTIN_ROUND_1X32);
5718 def_builtin ("__builtin_bfin_mult_fr1x32", int_ftype_short_short,
5719 BFIN_BUILTIN_MULT_1X32);
5720 def_builtin ("__builtin_bfin_mult_fr1x32x32", int_ftype_int_int,
5721 BFIN_BUILTIN_MULT_1X32X32);
5722 def_builtin ("__builtin_bfin_mult_fr1x32x32NS", int_ftype_int_int,
5723 BFIN_BUILTIN_MULT_1X32X32NS);
5726 def_builtin ("__builtin_bfin_shl_fr1x16", short_ftype_int_int,
5727 BFIN_BUILTIN_SSASHIFT_1X16);
5728 def_builtin ("__builtin_bfin_shl_fr2x16", v2hi_ftype_v2hi_int,
5729 BFIN_BUILTIN_SSASHIFT_2X16);
5730 def_builtin ("__builtin_bfin_lshl_fr1x16", short_ftype_int_int,
5731 BFIN_BUILTIN_LSHIFT_1X16);
5732 def_builtin ("__builtin_bfin_lshl_fr2x16", v2hi_ftype_v2hi_int,
5733 BFIN_BUILTIN_LSHIFT_2X16);
5734 def_builtin ("__builtin_bfin_shl_fr1x32", int_ftype_int_int,
5735 BFIN_BUILTIN_SSASHIFT_1X32);
5737 /* Complex numbers. */
5738 def_builtin ("__builtin_bfin_cmplx_add", v2hi_ftype_v2hi_v2hi,
5739 BFIN_BUILTIN_SSADD_2X16);
5740 def_builtin ("__builtin_bfin_cmplx_sub", v2hi_ftype_v2hi_v2hi,
5741 BFIN_BUILTIN_SSSUB_2X16);
5742 def_builtin ("__builtin_bfin_cmplx_mul", v2hi_ftype_v2hi_v2hi,
5743 BFIN_BUILTIN_CPLX_MUL_16);
5744 def_builtin ("__builtin_bfin_cmplx_mac", v2hi_ftype_v2hi_v2hi_v2hi,
5745 BFIN_BUILTIN_CPLX_MAC_16);
5746 def_builtin ("__builtin_bfin_cmplx_msu", v2hi_ftype_v2hi_v2hi_v2hi,
5747 BFIN_BUILTIN_CPLX_MSU_16);
5748 def_builtin ("__builtin_bfin_cmplx_mul_s40", v2hi_ftype_v2hi_v2hi,
5749 BFIN_BUILTIN_CPLX_MUL_16_S40);
5750 def_builtin ("__builtin_bfin_cmplx_mac_s40", v2hi_ftype_v2hi_v2hi_v2hi,
5751 BFIN_BUILTIN_CPLX_MAC_16_S40);
5752 def_builtin ("__builtin_bfin_cmplx_msu_s40", v2hi_ftype_v2hi_v2hi_v2hi,
5753 BFIN_BUILTIN_CPLX_MSU_16_S40);
5754 def_builtin ("__builtin_bfin_csqu_fr16", v2hi_ftype_v2hi,
5755 BFIN_BUILTIN_CPLX_SQU);
5757 /* "Unaligned" load. */
5758 def_builtin ("__builtin_bfin_loadbytes", int_ftype_pint,
5759 BFIN_BUILTIN_LOADBYTES);
5764 struct builtin_description
5766 const enum insn_code icode;
5767 const char *const name;
5768 const enum bfin_builtins code;
5772 static const struct builtin_description bdesc_2arg[] =
5774 { CODE_FOR_composev2hi, "__builtin_bfin_compose_2x16", BFIN_BUILTIN_COMPOSE_2X16, -1 },
5776 { CODE_FOR_ssashiftv2hi3, "__builtin_bfin_shl_fr2x16", BFIN_BUILTIN_SSASHIFT_2X16, -1 },
5777 { CODE_FOR_ssashifthi3, "__builtin_bfin_shl_fr1x16", BFIN_BUILTIN_SSASHIFT_1X16, -1 },
5778 { CODE_FOR_lshiftv2hi3, "__builtin_bfin_lshl_fr2x16", BFIN_BUILTIN_LSHIFT_2X16, -1 },
5779 { CODE_FOR_lshifthi3, "__builtin_bfin_lshl_fr1x16", BFIN_BUILTIN_LSHIFT_1X16, -1 },
5780 { CODE_FOR_ssashiftsi3, "__builtin_bfin_shl_fr1x32", BFIN_BUILTIN_SSASHIFT_1X32, -1 },
5782 { CODE_FOR_sminhi3, "__builtin_bfin_min_fr1x16", BFIN_BUILTIN_MIN_1X16, -1 },
5783 { CODE_FOR_smaxhi3, "__builtin_bfin_max_fr1x16", BFIN_BUILTIN_MAX_1X16, -1 },
5784 { CODE_FOR_ssaddhi3, "__builtin_bfin_add_fr1x16", BFIN_BUILTIN_SSADD_1X16, -1 },
5785 { CODE_FOR_sssubhi3, "__builtin_bfin_sub_fr1x16", BFIN_BUILTIN_SSSUB_1X16, -1 },
5787 { CODE_FOR_sminsi3, "__builtin_bfin_min_fr1x32", BFIN_BUILTIN_MIN_1X32, -1 },
5788 { CODE_FOR_smaxsi3, "__builtin_bfin_max_fr1x32", BFIN_BUILTIN_MAX_1X32, -1 },
5789 { CODE_FOR_ssaddsi3, "__builtin_bfin_add_fr1x32", BFIN_BUILTIN_SSADD_1X32, -1 },
5790 { CODE_FOR_sssubsi3, "__builtin_bfin_sub_fr1x32", BFIN_BUILTIN_SSSUB_1X32, -1 },
5792 { CODE_FOR_sminv2hi3, "__builtin_bfin_min_fr2x16", BFIN_BUILTIN_MIN_2X16, -1 },
5793 { CODE_FOR_smaxv2hi3, "__builtin_bfin_max_fr2x16", BFIN_BUILTIN_MAX_2X16, -1 },
5794 { CODE_FOR_ssaddv2hi3, "__builtin_bfin_add_fr2x16", BFIN_BUILTIN_SSADD_2X16, -1 },
5795 { CODE_FOR_sssubv2hi3, "__builtin_bfin_sub_fr2x16", BFIN_BUILTIN_SSSUB_2X16, -1 },
5796 { CODE_FOR_ssaddsubv2hi3, "__builtin_bfin_dspaddsubsat", BFIN_BUILTIN_SSADDSUB_2X16, -1 },
5797 { CODE_FOR_sssubaddv2hi3, "__builtin_bfin_dspsubaddsat", BFIN_BUILTIN_SSSUBADD_2X16, -1 },
5799 { CODE_FOR_flag_mulhisi, "__builtin_bfin_mult_fr1x32", BFIN_BUILTIN_MULT_1X32, MACFLAG_NONE },
5800 { CODE_FOR_flag_mulhi, "__builtin_bfin_mult_fr1x16", BFIN_BUILTIN_MULT_1X16, MACFLAG_T },
5801 { CODE_FOR_flag_mulhi, "__builtin_bfin_multr_fr1x16", BFIN_BUILTIN_MULTR_1X16, MACFLAG_NONE },
5802 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_mult_fr2x16", BFIN_BUILTIN_MULT_2X16, MACFLAG_T },
5803 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_multr_fr2x16", BFIN_BUILTIN_MULTR_2X16, MACFLAG_NONE },
5805 { CODE_FOR_mulhisi_ll, "__builtin_bfin_mulhisill", BFIN_BUILTIN_MULHISILL, -1 },
5806 { CODE_FOR_mulhisi_lh, "__builtin_bfin_mulhisilh", BFIN_BUILTIN_MULHISILH, -1 },
5807 { CODE_FOR_mulhisi_hl, "__builtin_bfin_mulhisihl", BFIN_BUILTIN_MULHISIHL, -1 },
5808 { CODE_FOR_mulhisi_hh, "__builtin_bfin_mulhisihh", BFIN_BUILTIN_MULHISIHH, -1 }
5812 static const struct builtin_description bdesc_1arg[] =
5814 { CODE_FOR_loadbytes, "__builtin_bfin_loadbytes", BFIN_BUILTIN_LOADBYTES, 0 },
5816 { CODE_FOR_ones, "__builtin_bfin_ones", BFIN_BUILTIN_ONES, 0 },
5818 { CODE_FOR_signbitshi2, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16, 0 },
5819 { CODE_FOR_ssneghi2, "__builtin_bfin_negate_fr1x16", BFIN_BUILTIN_NEG_1X16, 0 },
5820 { CODE_FOR_abshi2, "__builtin_bfin_abs_fr1x16", BFIN_BUILTIN_ABS_1X16, 0 },
5822 { CODE_FOR_signbitssi2, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32, 0 },
5823 { CODE_FOR_ssroundsi2, "__builtin_bfin_round_fr1x32", BFIN_BUILTIN_ROUND_1X32, 0 },
5824 { CODE_FOR_ssnegsi2, "__builtin_bfin_negate_fr1x32", BFIN_BUILTIN_NEG_1X32, 0 },
5825 { CODE_FOR_ssabssi2, "__builtin_bfin_abs_fr1x32", BFIN_BUILTIN_ABS_1X32, 0 },
5827 { CODE_FOR_movv2hi_hi_low, "__builtin_bfin_extract_lo", BFIN_BUILTIN_EXTRACTLO, 0 },
5828 { CODE_FOR_movv2hi_hi_high, "__builtin_bfin_extract_hi", BFIN_BUILTIN_EXTRACTHI, 0 },
5829 { CODE_FOR_ssnegv2hi2, "__builtin_bfin_negate_fr2x16", BFIN_BUILTIN_NEG_2X16, 0 },
5830 { CODE_FOR_ssabsv2hi2, "__builtin_bfin_abs_fr2x16", BFIN_BUILTIN_ABS_2X16, 0 }
5833 /* Errors in the source file can cause expand_expr to return const0_rtx
5834 where we expect a vector. To avoid crashing, use one of the vector
5835 clear instructions. */
5837 safe_vector_operand (rtx x, enum machine_mode mode)
5839 if (x != const0_rtx)
5841 x = gen_reg_rtx (SImode);
5843 emit_insn (gen_movsi (x, CONST0_RTX (SImode)));
5844 return gen_lowpart (mode, x);
5847 /* Subroutine of bfin_expand_builtin to take care of binop insns. MACFLAG is -1
5848 if this is a normal binary op, or one of the MACFLAG_xxx constants. */
5851 bfin_expand_binop_builtin (enum insn_code icode, tree exp, rtx target,
5855 tree arg0 = CALL_EXPR_ARG (exp, 0);
5856 tree arg1 = CALL_EXPR_ARG (exp, 1);
5857 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5858 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
5859 enum machine_mode op0mode = GET_MODE (op0);
5860 enum machine_mode op1mode = GET_MODE (op1);
5861 enum machine_mode tmode = insn_data[icode].operand[0].mode;
5862 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
5863 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
5865 if (VECTOR_MODE_P (mode0))
5866 op0 = safe_vector_operand (op0, mode0);
5867 if (VECTOR_MODE_P (mode1))
5868 op1 = safe_vector_operand (op1, mode1);
5871 || GET_MODE (target) != tmode
5872 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5873 target = gen_reg_rtx (tmode);
5875 if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode)
5878 op0 = gen_lowpart (HImode, op0);
5880 if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode)
5883 op1 = gen_lowpart (HImode, op1);
5885 /* In case the insn wants input operands in modes different from
5886 the result, abort. */
5887 gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
5888 && (op1mode == mode1 || op1mode == VOIDmode));
5890 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5891 op0 = copy_to_mode_reg (mode0, op0);
5892 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
5893 op1 = copy_to_mode_reg (mode1, op1);
5896 pat = GEN_FCN (icode) (target, op0, op1);
5898 pat = GEN_FCN (icode) (target, op0, op1, GEN_INT (macflag));
5906 /* Subroutine of bfin_expand_builtin to take care of unop insns. */
5909 bfin_expand_unop_builtin (enum insn_code icode, tree exp,
5913 tree arg0 = CALL_EXPR_ARG (exp, 0);
5914 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5915 enum machine_mode op0mode = GET_MODE (op0);
5916 enum machine_mode tmode = insn_data[icode].operand[0].mode;
5917 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
5920 || GET_MODE (target) != tmode
5921 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5922 target = gen_reg_rtx (tmode);
5924 if (VECTOR_MODE_P (mode0))
5925 op0 = safe_vector_operand (op0, mode0);
5927 if (op0mode == SImode && mode0 == HImode)
5930 op0 = gen_lowpart (HImode, op0);
5932 gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
5934 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5935 op0 = copy_to_mode_reg (mode0, op0);
5937 pat = GEN_FCN (icode) (target, op0);
5944 /* Expand an expression EXP that calls a built-in function,
5945 with result going to TARGET if that's convenient
5946 (and in mode MODE if that's convenient).
5947 SUBTARGET may be used as the target for computing one of EXP's operands.
5948 IGNORE is nonzero if the value is to be ignored. */
5951 bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
5952 rtx subtarget ATTRIBUTE_UNUSED,
5953 enum machine_mode mode ATTRIBUTE_UNUSED,
5954 int ignore ATTRIBUTE_UNUSED)
5957 enum insn_code icode;
5958 const struct builtin_description *d;
5959 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
5960 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
5961 tree arg0, arg1, arg2;
5962 rtx op0, op1, op2, accvec, pat, tmp1, tmp2, a0reg, a1reg;
5963 enum machine_mode tmode, mode0;
5967 case BFIN_BUILTIN_CSYNC:
5968 emit_insn (gen_csync ());
5970 case BFIN_BUILTIN_SSYNC:
5971 emit_insn (gen_ssync ());
5974 case BFIN_BUILTIN_DIFFHL_2X16:
5975 case BFIN_BUILTIN_DIFFLH_2X16:
5976 case BFIN_BUILTIN_SUM_2X16:
5977 arg0 = CALL_EXPR_ARG (exp, 0);
5978 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
5979 icode = (fcode == BFIN_BUILTIN_DIFFHL_2X16 ? CODE_FOR_subhilov2hi3
5980 : fcode == BFIN_BUILTIN_DIFFLH_2X16 ? CODE_FOR_sublohiv2hi3
5981 : CODE_FOR_ssaddhilov2hi3);
5982 tmode = insn_data[icode].operand[0].mode;
5983 mode0 = insn_data[icode].operand[1].mode;
5986 || GET_MODE (target) != tmode
5987 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
5988 target = gen_reg_rtx (tmode);
5990 if (VECTOR_MODE_P (mode0))
5991 op0 = safe_vector_operand (op0, mode0);
5993 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
5994 op0 = copy_to_mode_reg (mode0, op0);
5996 pat = GEN_FCN (icode) (target, op0, op0);
6002 case BFIN_BUILTIN_MULT_1X32X32:
6003 case BFIN_BUILTIN_MULT_1X32X32NS:
6004 arg0 = CALL_EXPR_ARG (exp, 0);
6005 arg1 = CALL_EXPR_ARG (exp, 1);
6006 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
6007 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
6009 || !register_operand (target, SImode))
6010 target = gen_reg_rtx (SImode);
6012 a1reg = gen_rtx_REG (PDImode, REG_A1);
6013 a0reg = gen_rtx_REG (PDImode, REG_A0);
6014 tmp1 = gen_lowpart (V2HImode, op0);
6015 tmp2 = gen_lowpart (V2HImode, op1);
6016 emit_insn (gen_flag_macinit1hi (a1reg,
6017 gen_lowpart (HImode, op0),
6018 gen_lowpart (HImode, op1),
6019 GEN_INT (MACFLAG_FU)));
6020 emit_insn (gen_lshrpdi3 (a1reg, a1reg, GEN_INT (16)));
6022 if (fcode == BFIN_BUILTIN_MULT_1X32X32)
6023 emit_insn (gen_flag_mul_macv2hi_parts_acconly (a0reg, a1reg, tmp1, tmp2,
6024 const1_rtx, const1_rtx,
6025 const1_rtx, const0_rtx, a1reg,
6026 const0_rtx, GEN_INT (MACFLAG_NONE),
6027 GEN_INT (MACFLAG_M)));
6030 /* For saturating multiplication, there's exactly one special case
6031 to be handled: multiplying the smallest negative value with
6032 itself. Due to shift correction in fractional multiplies, this
6033 can overflow. Iff this happens, OP2 will contain 1, which, when
6034 added in 32 bits to the smallest negative, wraps to the largest
6035 positive, which is the result we want. */
6036 op2 = gen_reg_rtx (V2HImode);
6037 emit_insn (gen_packv2hi (op2, tmp1, tmp2, const0_rtx, const0_rtx));
6038 emit_insn (gen_movsibi (gen_rtx_REG (BImode, REG_CC),
6039 gen_lowpart (SImode, op2)));
6040 emit_insn (gen_flag_mul_macv2hi_parts_acconly_andcc0 (a0reg, a1reg, tmp1, tmp2,
6041 const1_rtx, const1_rtx,
6042 const1_rtx, const0_rtx, a1reg,
6043 const0_rtx, GEN_INT (MACFLAG_NONE),
6044 GEN_INT (MACFLAG_M)));
6045 op2 = gen_reg_rtx (SImode);
6046 emit_insn (gen_movbisi (op2, gen_rtx_REG (BImode, REG_CC)));
6048 emit_insn (gen_flag_machi_parts_acconly (a1reg, tmp2, tmp1,
6049 const1_rtx, const0_rtx,
6050 a1reg, const0_rtx, GEN_INT (MACFLAG_M)));
6051 emit_insn (gen_ashrpdi3 (a1reg, a1reg, GEN_INT (15)));
6052 emit_insn (gen_sum_of_accumulators (target, a0reg, a0reg, a1reg));
6053 if (fcode == BFIN_BUILTIN_MULT_1X32X32NS)
6054 emit_insn (gen_addsi3 (target, target, op2));
6057 case BFIN_BUILTIN_CPLX_MUL_16:
6058 case BFIN_BUILTIN_CPLX_MUL_16_S40:
6059 arg0 = CALL_EXPR_ARG (exp, 0);
6060 arg1 = CALL_EXPR_ARG (exp, 1);
6061 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
6062 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
6063 accvec = gen_reg_rtx (V2PDImode);
6066 || GET_MODE (target) != V2HImode
6067 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
6068 target = gen_reg_rtx (tmode);
6069 if (! register_operand (op0, GET_MODE (op0)))
6070 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
6071 if (! register_operand (op1, GET_MODE (op1)))
6072 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
6074 if (fcode == BFIN_BUILTIN_CPLX_MUL_16)
6075 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
6076 const0_rtx, const0_rtx,
6077 const1_rtx, GEN_INT (MACFLAG_W32)));
6079 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
6080 const0_rtx, const0_rtx,
6081 const1_rtx, GEN_INT (MACFLAG_NONE)));
6082 emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
6083 const1_rtx, const1_rtx,
6084 const0_rtx, accvec, const1_rtx, const0_rtx,
6085 GEN_INT (MACFLAG_NONE), accvec));
6089 case BFIN_BUILTIN_CPLX_MAC_16:
6090 case BFIN_BUILTIN_CPLX_MSU_16:
6091 case BFIN_BUILTIN_CPLX_MAC_16_S40:
6092 case BFIN_BUILTIN_CPLX_MSU_16_S40:
6093 arg0 = CALL_EXPR_ARG (exp, 0);
6094 arg1 = CALL_EXPR_ARG (exp, 1);
6095 arg2 = CALL_EXPR_ARG (exp, 2);
6096 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
6097 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
6098 op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
6099 accvec = gen_reg_rtx (V2PDImode);
6102 || GET_MODE (target) != V2HImode
6103 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
6104 target = gen_reg_rtx (tmode);
6105 if (! register_operand (op1, GET_MODE (op1)))
6106 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
6107 if (! register_operand (op2, GET_MODE (op2)))
6108 op2 = copy_to_mode_reg (GET_MODE (op2), op2);
6110 tmp1 = gen_reg_rtx (SImode);
6111 tmp2 = gen_reg_rtx (SImode);
6112 emit_insn (gen_ashlsi3 (tmp1, gen_lowpart (SImode, op0), GEN_INT (16)));
6113 emit_move_insn (tmp2, gen_lowpart (SImode, op0));
6114 emit_insn (gen_movstricthi_1 (gen_lowpart (HImode, tmp2), const0_rtx));
6115 emit_insn (gen_load_accumulator_pair (accvec, tmp1, tmp2));
6116 if (fcode == BFIN_BUILTIN_CPLX_MAC_16
6117 || fcode == BFIN_BUILTIN_CPLX_MSU_16)
6118 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx,
6119 const0_rtx, const0_rtx,
6120 const1_rtx, accvec, const0_rtx,
6122 GEN_INT (MACFLAG_W32)));
6124 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx,
6125 const0_rtx, const0_rtx,
6126 const1_rtx, accvec, const0_rtx,
6128 GEN_INT (MACFLAG_NONE)));
6129 if (fcode == BFIN_BUILTIN_CPLX_MAC_16
6130 || fcode == BFIN_BUILTIN_CPLX_MAC_16_S40)
6140 emit_insn (gen_flag_macv2hi_parts (target, op1, op2, const1_rtx,
6141 const1_rtx, const1_rtx,
6142 const0_rtx, accvec, tmp1, tmp2,
6143 GEN_INT (MACFLAG_NONE), accvec));
6147 case BFIN_BUILTIN_CPLX_SQU:
6148 arg0 = CALL_EXPR_ARG (exp, 0);
6149 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
6150 accvec = gen_reg_rtx (V2PDImode);
6151 icode = CODE_FOR_flag_mulv2hi;
6152 tmp1 = gen_reg_rtx (V2HImode);
6153 tmp2 = gen_reg_rtx (V2HImode);
6156 || GET_MODE (target) != V2HImode
6157 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
6158 target = gen_reg_rtx (V2HImode);
6159 if (! register_operand (op0, GET_MODE (op0)))
6160 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
6162 emit_insn (gen_flag_mulv2hi (tmp1, op0, op0, GEN_INT (MACFLAG_NONE)));
6164 emit_insn (gen_flag_mulhi_parts (gen_lowpart (HImode, tmp2), op0, op0,
6165 const0_rtx, const1_rtx,
6166 GEN_INT (MACFLAG_NONE)));
6168 emit_insn (gen_ssaddhi3_high_parts (target, tmp2, tmp2, tmp2, const0_rtx,
6170 emit_insn (gen_sssubhi3_low_parts (target, target, tmp1, tmp1,
6171 const0_rtx, const1_rtx));
6179 for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
6180 if (d->code == fcode)
6181 return bfin_expand_binop_builtin (d->icode, exp, target,
6184 for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
6185 if (d->code == fcode)
6186 return bfin_expand_unop_builtin (d->icode, exp, target);
6191 #undef TARGET_INIT_BUILTINS
6192 #define TARGET_INIT_BUILTINS bfin_init_builtins
6194 #undef TARGET_EXPAND_BUILTIN
6195 #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
6197 #undef TARGET_ASM_GLOBALIZE_LABEL
6198 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label
6200 #undef TARGET_ASM_FILE_START
6201 #define TARGET_ASM_FILE_START output_file_start
6203 #undef TARGET_ATTRIBUTE_TABLE
6204 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
6206 #undef TARGET_COMP_TYPE_ATTRIBUTES
6207 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
6209 #undef TARGET_RTX_COSTS
6210 #define TARGET_RTX_COSTS bfin_rtx_costs
6212 #undef TARGET_ADDRESS_COST
6213 #define TARGET_ADDRESS_COST bfin_address_cost
6215 #undef TARGET_ASM_INTEGER
6216 #define TARGET_ASM_INTEGER bfin_assemble_integer
6218 #undef TARGET_MACHINE_DEPENDENT_REORG
6219 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
6221 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
6222 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
6224 #undef TARGET_ASM_OUTPUT_MI_THUNK
6225 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
6226 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
6227 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
6229 #undef TARGET_SCHED_ADJUST_COST
6230 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
6232 #undef TARGET_SCHED_ISSUE_RATE
6233 #define TARGET_SCHED_ISSUE_RATE bfin_issue_rate
6235 #undef TARGET_PROMOTE_PROTOTYPES
6236 #define TARGET_PROMOTE_PROTOTYPES hook_bool_const_tree_true
6237 #undef TARGET_PROMOTE_FUNCTION_ARGS
6238 #define TARGET_PROMOTE_FUNCTION_ARGS hook_bool_const_tree_true
6239 #undef TARGET_PROMOTE_FUNCTION_RETURN
6240 #define TARGET_PROMOTE_FUNCTION_RETURN hook_bool_const_tree_true
6242 #undef TARGET_ARG_PARTIAL_BYTES
6243 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
6245 #undef TARGET_PASS_BY_REFERENCE
6246 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
6248 #undef TARGET_SETUP_INCOMING_VARARGS
6249 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
6251 #undef TARGET_STRUCT_VALUE_RTX
6252 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
6254 #undef TARGET_VECTOR_MODE_SUPPORTED_P
6255 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
6257 #undef TARGET_HANDLE_OPTION
6258 #define TARGET_HANDLE_OPTION bfin_handle_option
6260 #undef TARGET_DEFAULT_TARGET_FLAGS
6261 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
6263 #undef TARGET_SECONDARY_RELOAD
6264 #define TARGET_SECONDARY_RELOAD bfin_secondary_reload
6266 #undef TARGET_DELEGITIMIZE_ADDRESS
6267 #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address
6269 #undef TARGET_CANNOT_FORCE_CONST_MEM
6270 #define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem
6272 #undef TARGET_RETURN_IN_MEMORY
6273 #define TARGET_RETURN_IN_MEMORY bfin_return_in_memory
6275 struct gcc_target targetm = TARGET_INITIALIZER;