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;
67 /* Set if we create a memcpy pattern that uses loop registers. */
68 int has_loopreg_clobber;
71 /* RTX for condition code flag register and RETS register */
72 extern GTY(()) rtx bfin_cc_rtx;
73 extern GTY(()) rtx bfin_rets_rtx;
74 rtx bfin_cc_rtx, bfin_rets_rtx;
76 int max_arg_registers = 0;
78 /* Arrays used when emitting register names. */
79 const char *short_reg_names[] = SHORT_REGISTER_NAMES;
80 const char *high_reg_names[] = HIGH_REGISTER_NAMES;
81 const char *dregs_pair_names[] = DREGS_PAIR_NAMES;
82 const char *byte_reg_names[] = BYTE_REGISTER_NAMES;
84 static int arg_regs[] = FUNCTION_ARG_REGISTERS;
85 static int ret_regs[] = FUNCTION_RETURN_REGISTERS;
87 /* Nonzero if -mshared-library-id was given. */
88 static int bfin_lib_id_given;
90 /* Nonzero if -fschedule-insns2 was given. We override it and
91 call the scheduler ourselves during reorg. */
92 static int bfin_flag_schedule_insns2;
94 /* Determines whether we run variable tracking in machine dependent
96 static int bfin_flag_var_tracking;
99 bfin_cpu_t bfin_cpu_type = BFIN_CPU_UNKNOWN;
101 /* -msi-revision support. There are three special values:
102 -1 -msi-revision=none.
103 0xffff -msi-revision=any. */
104 int bfin_si_revision;
106 /* The workarounds enabled */
107 unsigned int bfin_workarounds = 0;
114 unsigned int workarounds;
117 struct bfin_cpu bfin_cpus[] =
119 {"bf512", BFIN_CPU_BF512, 0x0000,
120 WA_SPECULATIVE_LOADS | WA_05000074},
122 {"bf514", BFIN_CPU_BF514, 0x0000,
123 WA_SPECULATIVE_LOADS | WA_05000074},
125 {"bf516", BFIN_CPU_BF516, 0x0000,
126 WA_SPECULATIVE_LOADS | WA_05000074},
128 {"bf518", BFIN_CPU_BF518, 0x0000,
129 WA_SPECULATIVE_LOADS | WA_05000074},
131 {"bf522", BFIN_CPU_BF522, 0x0002,
132 WA_SPECULATIVE_LOADS | WA_05000074},
133 {"bf522", BFIN_CPU_BF522, 0x0001,
134 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
135 {"bf522", BFIN_CPU_BF522, 0x0000,
136 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
138 {"bf523", BFIN_CPU_BF523, 0x0002,
139 WA_SPECULATIVE_LOADS | WA_05000074},
140 {"bf523", BFIN_CPU_BF523, 0x0001,
141 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
142 {"bf523", BFIN_CPU_BF523, 0x0000,
143 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
145 {"bf524", BFIN_CPU_BF524, 0x0002,
146 WA_SPECULATIVE_LOADS | WA_05000074},
147 {"bf524", BFIN_CPU_BF524, 0x0001,
148 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
149 {"bf524", BFIN_CPU_BF524, 0x0000,
150 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
152 {"bf525", BFIN_CPU_BF525, 0x0002,
153 WA_SPECULATIVE_LOADS | WA_05000074},
154 {"bf525", BFIN_CPU_BF525, 0x0001,
155 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
156 {"bf525", BFIN_CPU_BF525, 0x0000,
157 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
159 {"bf526", BFIN_CPU_BF526, 0x0002,
160 WA_SPECULATIVE_LOADS | WA_05000074},
161 {"bf526", BFIN_CPU_BF526, 0x0001,
162 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
163 {"bf526", BFIN_CPU_BF526, 0x0000,
164 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
166 {"bf527", BFIN_CPU_BF527, 0x0002,
167 WA_SPECULATIVE_LOADS | WA_05000074},
168 {"bf527", BFIN_CPU_BF527, 0x0001,
169 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
170 {"bf527", BFIN_CPU_BF527, 0x0000,
171 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000074},
173 {"bf531", BFIN_CPU_BF531, 0x0006,
174 WA_SPECULATIVE_LOADS | WA_LOAD_LCREGS | WA_05000074},
175 {"bf531", BFIN_CPU_BF531, 0x0005,
176 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315
177 | WA_LOAD_LCREGS | WA_05000074},
178 {"bf531", BFIN_CPU_BF531, 0x0004,
179 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
180 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
182 {"bf531", BFIN_CPU_BF531, 0x0003,
183 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
184 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
187 {"bf532", BFIN_CPU_BF532, 0x0006,
188 WA_SPECULATIVE_LOADS | WA_LOAD_LCREGS | WA_05000074},
189 {"bf532", BFIN_CPU_BF532, 0x0005,
190 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315
191 | WA_LOAD_LCREGS | WA_05000074},
192 {"bf532", BFIN_CPU_BF532, 0x0004,
193 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
194 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
196 {"bf532", BFIN_CPU_BF532, 0x0003,
197 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
198 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
201 {"bf533", BFIN_CPU_BF533, 0x0006,
202 WA_SPECULATIVE_LOADS | WA_LOAD_LCREGS | WA_05000074},
203 {"bf533", BFIN_CPU_BF533, 0x0005,
204 WA_SPECULATIVE_LOADS | WA_RETS | WA_05000283 | WA_05000315
205 | WA_LOAD_LCREGS | WA_05000074},
206 {"bf533", BFIN_CPU_BF533, 0x0004,
207 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
208 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
210 {"bf533", BFIN_CPU_BF533, 0x0003,
211 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
212 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
215 {"bf534", BFIN_CPU_BF534, 0x0003,
216 WA_SPECULATIVE_LOADS | WA_RETS | WA_LOAD_LCREGS | WA_05000074},
217 {"bf534", BFIN_CPU_BF534, 0x0002,
218 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
219 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
221 {"bf534", BFIN_CPU_BF534, 0x0001,
222 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
223 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
226 {"bf536", BFIN_CPU_BF536, 0x0003,
227 WA_SPECULATIVE_LOADS | WA_RETS | WA_LOAD_LCREGS | WA_05000074},
228 {"bf536", BFIN_CPU_BF536, 0x0002,
229 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
230 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
232 {"bf536", BFIN_CPU_BF536, 0x0001,
233 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
234 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
237 {"bf537", BFIN_CPU_BF537, 0x0003,
238 WA_SPECULATIVE_LOADS | WA_RETS | WA_LOAD_LCREGS | WA_05000074},
239 {"bf537", BFIN_CPU_BF537, 0x0002,
240 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
241 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
243 {"bf537", BFIN_CPU_BF537, 0x0001,
244 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
245 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
248 {"bf538", BFIN_CPU_BF538, 0x0005,
249 WA_SPECULATIVE_LOADS | WA_LOAD_LCREGS | WA_05000074},
250 {"bf538", BFIN_CPU_BF538, 0x0004,
251 WA_SPECULATIVE_LOADS | WA_RETS | WA_LOAD_LCREGS | WA_05000074},
252 {"bf538", BFIN_CPU_BF538, 0x0003,
253 WA_SPECULATIVE_LOADS | WA_RETS
254 | WA_05000283 | WA_05000315 | WA_LOAD_LCREGS | WA_05000074},
255 {"bf538", BFIN_CPU_BF538, 0x0002,
256 WA_SPECULATIVE_LOADS | WA_RETS
257 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
260 {"bf539", BFIN_CPU_BF539, 0x0005,
261 WA_SPECULATIVE_LOADS | WA_LOAD_LCREGS | WA_05000074},
262 {"bf539", BFIN_CPU_BF539, 0x0004,
263 WA_SPECULATIVE_LOADS | WA_RETS | WA_LOAD_LCREGS | WA_05000074},
264 {"bf539", BFIN_CPU_BF539, 0x0003,
265 WA_SPECULATIVE_LOADS | WA_RETS
266 | WA_05000283 | WA_05000315 | WA_LOAD_LCREGS | WA_05000074},
267 {"bf539", BFIN_CPU_BF539, 0x0002,
268 WA_SPECULATIVE_LOADS | WA_RETS
269 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
272 {"bf542m", BFIN_CPU_BF542M, 0x0003,
273 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
275 {"bf542", BFIN_CPU_BF542, 0x0002,
276 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
277 {"bf542", BFIN_CPU_BF542, 0x0001,
278 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_05000074},
279 {"bf542", BFIN_CPU_BF542, 0x0000,
280 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_LOAD_LCREGS
283 {"bf544m", BFIN_CPU_BF544M, 0x0003,
284 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
286 {"bf544", BFIN_CPU_BF544, 0x0002,
287 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
288 {"bf544", BFIN_CPU_BF544, 0x0001,
289 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_05000074},
290 {"bf544", BFIN_CPU_BF544, 0x0000,
291 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_LOAD_LCREGS
294 {"bf547m", BFIN_CPU_BF547M, 0x0003,
295 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
297 {"bf547", BFIN_CPU_BF547, 0x0002,
298 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
299 {"bf547", BFIN_CPU_BF547, 0x0001,
300 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_05000074},
301 {"bf547", BFIN_CPU_BF547, 0x0000,
302 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_LOAD_LCREGS
305 {"bf548m", BFIN_CPU_BF548M, 0x0003,
306 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
308 {"bf548", BFIN_CPU_BF548, 0x0002,
309 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
310 {"bf548", BFIN_CPU_BF548, 0x0001,
311 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_05000074},
312 {"bf548", BFIN_CPU_BF548, 0x0000,
313 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_LOAD_LCREGS
316 {"bf549m", BFIN_CPU_BF549M, 0x0003,
317 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
319 {"bf549", BFIN_CPU_BF549, 0x0002,
320 WA_SPECULATIVE_LOADS | WA_INDIRECT_CALLS | WA_05000074},
321 {"bf549", BFIN_CPU_BF549, 0x0001,
322 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_05000074},
323 {"bf549", BFIN_CPU_BF549, 0x0000,
324 WA_SPECULATIVE_LOADS | WA_RETS | WA_INDIRECT_CALLS | WA_LOAD_LCREGS
327 {"bf561", BFIN_CPU_BF561, 0x0005, WA_RETS
328 | WA_05000283 | WA_05000315 | WA_LOAD_LCREGS | WA_05000074},
329 {"bf561", BFIN_CPU_BF561, 0x0003,
330 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
331 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
333 {"bf561", BFIN_CPU_BF561, 0x0002,
334 WA_SPECULATIVE_LOADS | WA_SPECULATIVE_SYNCS | WA_RETS
335 | WA_05000283 | WA_05000257 | WA_05000315 | WA_LOAD_LCREGS
341 int splitting_for_sched, splitting_loops;
344 bfin_globalize_label (FILE *stream, const char *name)
346 fputs (".global ", stream);
347 assemble_name (stream, name);
353 output_file_start (void)
355 FILE *file = asm_out_file;
358 /* Variable tracking should be run after all optimizations which change order
359 of insns. It also needs a valid CFG. This can't be done in
360 override_options, because flag_var_tracking is finalized after
362 bfin_flag_var_tracking = flag_var_tracking;
363 flag_var_tracking = 0;
365 fprintf (file, ".file \"%s\";\n", input_filename);
367 for (i = 0; arg_regs[i] >= 0; i++)
369 max_arg_registers = i; /* how many arg reg used */
372 /* Called early in the compilation to conditionally modify
373 fixed_regs/call_used_regs. */
376 conditional_register_usage (void)
378 /* initialize condition code flag register rtx */
379 bfin_cc_rtx = gen_rtx_REG (BImode, REG_CC);
380 bfin_rets_rtx = gen_rtx_REG (Pmode, REG_RETS);
383 /* Examine machine-dependent attributes of function type FUNTYPE and return its
384 type. See the definition of E_FUNKIND. */
387 funkind (const_tree funtype)
389 tree attrs = TYPE_ATTRIBUTES (funtype);
390 if (lookup_attribute ("interrupt_handler", attrs))
391 return INTERRUPT_HANDLER;
392 else if (lookup_attribute ("exception_handler", attrs))
393 return EXCPT_HANDLER;
394 else if (lookup_attribute ("nmi_handler", attrs))
400 /* Legitimize PIC addresses. If the address is already position-independent,
401 we return ORIG. Newly generated position-independent addresses go into a
402 reg. This is REG if nonzero, otherwise we allocate register(s) as
403 necessary. PICREG is the register holding the pointer to the PIC offset
407 legitimize_pic_address (rtx orig, rtx reg, rtx picreg)
412 if (GET_CODE (addr) == SYMBOL_REF || GET_CODE (addr) == LABEL_REF)
417 if (TARGET_ID_SHARED_LIBRARY)
418 unspec = UNSPEC_MOVE_PIC;
419 else if (GET_CODE (addr) == SYMBOL_REF
420 && SYMBOL_REF_FUNCTION_P (addr))
421 unspec = UNSPEC_FUNCDESC_GOT17M4;
423 unspec = UNSPEC_MOVE_FDPIC;
427 gcc_assert (can_create_pseudo_p ());
428 reg = gen_reg_rtx (Pmode);
431 tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), unspec);
432 new_rtx = gen_const_mem (Pmode, gen_rtx_PLUS (Pmode, picreg, tmp));
434 emit_move_insn (reg, new_rtx);
435 if (picreg == pic_offset_table_rtx)
436 crtl->uses_pic_offset_table = 1;
440 else if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
444 if (GET_CODE (addr) == CONST)
446 addr = XEXP (addr, 0);
447 gcc_assert (GET_CODE (addr) == PLUS);
450 if (XEXP (addr, 0) == picreg)
455 gcc_assert (can_create_pseudo_p ());
456 reg = gen_reg_rtx (Pmode);
459 base = legitimize_pic_address (XEXP (addr, 0), reg, picreg);
460 addr = legitimize_pic_address (XEXP (addr, 1),
461 base == reg ? NULL_RTX : reg,
464 if (GET_CODE (addr) == CONST_INT)
466 gcc_assert (! reload_in_progress && ! reload_completed);
467 addr = force_reg (Pmode, addr);
470 if (GET_CODE (addr) == PLUS && CONSTANT_P (XEXP (addr, 1)))
472 base = gen_rtx_PLUS (Pmode, base, XEXP (addr, 0));
473 addr = XEXP (addr, 1);
476 return gen_rtx_PLUS (Pmode, base, addr);
482 /* Stack frame layout. */
484 /* For a given REGNO, determine whether it must be saved in the function
485 prologue. IS_INTHANDLER specifies whether we're generating a normal
486 prologue or an interrupt/exception one. */
488 must_save_p (bool is_inthandler, unsigned regno)
490 if (D_REGNO_P (regno))
492 bool is_eh_return_reg = false;
493 if (crtl->calls_eh_return)
498 unsigned test = EH_RETURN_DATA_REGNO (j);
499 if (test == INVALID_REGNUM)
502 is_eh_return_reg = true;
506 return (is_eh_return_reg
507 || (df_regs_ever_live_p (regno)
508 && !fixed_regs[regno]
509 && (is_inthandler || !call_used_regs[regno])));
511 else if (P_REGNO_P (regno))
513 return ((df_regs_ever_live_p (regno)
514 && !fixed_regs[regno]
515 && (is_inthandler || !call_used_regs[regno]))
517 && (ENABLE_WA_05000283 || ENABLE_WA_05000315)
520 && regno == PIC_OFFSET_TABLE_REGNUM
521 && (crtl->uses_pic_offset_table
522 || (TARGET_ID_SHARED_LIBRARY && !current_function_is_leaf))));
525 return ((is_inthandler || !call_used_regs[regno])
526 && (df_regs_ever_live_p (regno)
527 || (!leaf_function_p () && call_used_regs[regno])));
531 /* Compute the number of DREGS to save with a push_multiple operation.
532 This could include registers that aren't modified in the function,
533 since push_multiple only takes a range of registers.
534 If IS_INTHANDLER, then everything that is live must be saved, even
535 if normally call-clobbered.
536 If CONSECUTIVE, return the number of registers we can save in one
537 instruction with a push/pop multiple instruction. */
540 n_dregs_to_save (bool is_inthandler, bool consecutive)
545 for (i = REG_R7 + 1; i-- != REG_R0;)
547 if (must_save_p (is_inthandler, i))
549 else if (consecutive)
555 /* Like n_dregs_to_save, but compute number of PREGS to save. */
558 n_pregs_to_save (bool is_inthandler, bool consecutive)
563 for (i = REG_P5 + 1; i-- != REG_P0;)
564 if (must_save_p (is_inthandler, i))
566 else if (consecutive)
571 /* Determine if we are going to save the frame pointer in the prologue. */
574 must_save_fp_p (void)
576 return df_regs_ever_live_p (REG_FP);
579 /* Determine if we are going to save the RETS register. */
581 must_save_rets_p (void)
583 return df_regs_ever_live_p (REG_RETS);
587 stack_frame_needed_p (void)
589 /* EH return puts a new return address into the frame using an
590 address relative to the frame pointer. */
591 if (crtl->calls_eh_return)
593 return frame_pointer_needed;
596 /* Emit code to save registers in the prologue. SAVEALL is nonzero if we
597 must save all registers; this is used for interrupt handlers.
598 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
599 this for an interrupt (or exception) handler. */
602 expand_prologue_reg_save (rtx spreg, int saveall, bool is_inthandler)
604 rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
605 rtx predec = gen_rtx_MEM (SImode, predec1);
606 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler, false);
607 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler, false);
608 int ndregs_consec = saveall ? 8 : n_dregs_to_save (is_inthandler, true);
609 int npregs_consec = saveall ? 6 : n_pregs_to_save (is_inthandler, true);
611 int total_consec = ndregs_consec + npregs_consec;
614 if (saveall || is_inthandler)
616 rtx insn = emit_move_insn (predec, gen_rtx_REG (SImode, REG_ASTAT));
618 RTX_FRAME_RELATED_P (insn) = 1;
619 for (dregno = REG_LT0; dregno <= REG_LB1; dregno++)
620 if (! current_function_is_leaf
621 || cfun->machine->has_hardware_loops
622 || cfun->machine->has_loopreg_clobber
623 || (ENABLE_WA_05000257
624 && (dregno == REG_LC0 || dregno == REG_LC1)))
626 insn = emit_move_insn (predec, gen_rtx_REG (SImode, dregno));
627 RTX_FRAME_RELATED_P (insn) = 1;
631 if (total_consec != 0)
634 rtx val = GEN_INT (-total_consec * 4);
635 rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_consec + 2));
637 XVECEXP (pat, 0, 0) = gen_rtx_UNSPEC (VOIDmode, gen_rtvec (1, val),
638 UNSPEC_PUSH_MULTIPLE);
639 XVECEXP (pat, 0, total_consec + 1) = gen_rtx_SET (VOIDmode, spreg,
643 RTX_FRAME_RELATED_P (XVECEXP (pat, 0, total_consec + 1)) = 1;
644 d_to_save = ndregs_consec;
645 dregno = REG_R7 + 1 - ndregs_consec;
646 pregno = REG_P5 + 1 - npregs_consec;
647 for (i = 0; i < total_consec; i++)
649 rtx memref = gen_rtx_MEM (word_mode,
650 gen_rtx_PLUS (Pmode, spreg,
651 GEN_INT (- i * 4 - 4)));
655 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
661 subpat = gen_rtx_SET (VOIDmode, memref, gen_rtx_REG (word_mode,
664 XVECEXP (pat, 0, i + 1) = subpat;
665 RTX_FRAME_RELATED_P (subpat) = 1;
667 insn = emit_insn (pat);
668 RTX_FRAME_RELATED_P (insn) = 1;
671 for (dregno = REG_R0; ndregs != ndregs_consec; dregno++)
673 if (must_save_p (is_inthandler, dregno))
675 rtx insn = emit_move_insn (predec, gen_rtx_REG (word_mode, dregno));
676 RTX_FRAME_RELATED_P (insn) = 1;
680 for (pregno = REG_P0; npregs != npregs_consec; pregno++)
682 if (must_save_p (is_inthandler, pregno))
684 rtx insn = emit_move_insn (predec, gen_rtx_REG (word_mode, pregno));
685 RTX_FRAME_RELATED_P (insn) = 1;
689 for (i = REG_P7 + 1; i < REG_CC; i++)
692 && (df_regs_ever_live_p (i)
693 || (!leaf_function_p () && call_used_regs[i]))))
696 if (i == REG_A0 || i == REG_A1)
697 insn = emit_move_insn (gen_rtx_MEM (PDImode, predec1),
698 gen_rtx_REG (PDImode, i));
700 insn = emit_move_insn (predec, gen_rtx_REG (SImode, i));
701 RTX_FRAME_RELATED_P (insn) = 1;
705 /* Emit code to restore registers in the epilogue. SAVEALL is nonzero if we
706 must save all registers; this is used for interrupt handlers.
707 SPREG contains (reg:SI REG_SP). IS_INTHANDLER is true if we're doing
708 this for an interrupt (or exception) handler. */
711 expand_epilogue_reg_restore (rtx spreg, bool saveall, bool is_inthandler)
713 rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
714 rtx postinc = gen_rtx_MEM (SImode, postinc1);
716 int ndregs = saveall ? 8 : n_dregs_to_save (is_inthandler, false);
717 int npregs = saveall ? 6 : n_pregs_to_save (is_inthandler, false);
718 int ndregs_consec = saveall ? 8 : n_dregs_to_save (is_inthandler, true);
719 int npregs_consec = saveall ? 6 : n_pregs_to_save (is_inthandler, true);
720 int total_consec = ndregs_consec + npregs_consec;
724 /* A slightly crude technique to stop flow from trying to delete "dead"
726 MEM_VOLATILE_P (postinc) = 1;
728 for (i = REG_CC - 1; i > REG_P7; i--)
731 && (df_regs_ever_live_p (i)
732 || (!leaf_function_p () && call_used_regs[i]))))
734 if (i == REG_A0 || i == REG_A1)
736 rtx mem = gen_rtx_MEM (PDImode, postinc1);
737 MEM_VOLATILE_P (mem) = 1;
738 emit_move_insn (gen_rtx_REG (PDImode, i), mem);
741 emit_move_insn (gen_rtx_REG (SImode, i), postinc);
744 regno = REG_P5 - npregs_consec;
745 for (; npregs != npregs_consec; regno--)
747 if (must_save_p (is_inthandler, regno))
749 emit_move_insn (gen_rtx_REG (word_mode, regno), postinc);
753 regno = REG_R7 - ndregs_consec;
754 for (; ndregs != ndregs_consec; regno--)
756 if (must_save_p (is_inthandler, regno))
758 emit_move_insn (gen_rtx_REG (word_mode, regno), postinc);
763 if (total_consec != 0)
765 rtx pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (total_consec + 1));
767 = gen_rtx_SET (VOIDmode, spreg,
768 gen_rtx_PLUS (Pmode, spreg,
769 GEN_INT (total_consec * 4)));
771 if (npregs_consec > 0)
776 for (i = 0; i < total_consec; i++)
779 ? gen_rtx_PLUS (Pmode, spreg, GEN_INT (i * 4))
781 rtx memref = gen_rtx_MEM (word_mode, addr);
784 XVECEXP (pat, 0, i + 1)
785 = gen_rtx_SET (VOIDmode, gen_rtx_REG (word_mode, regno), memref);
787 if (npregs_consec > 0)
789 if (--npregs_consec == 0)
794 insn = emit_insn (pat);
795 RTX_FRAME_RELATED_P (insn) = 1;
797 if (saveall || is_inthandler)
799 for (regno = REG_LB1; regno >= REG_LT0; regno--)
800 if (! current_function_is_leaf
801 || cfun->machine->has_hardware_loops
802 || cfun->machine->has_loopreg_clobber
803 || (ENABLE_WA_05000257 && (regno == REG_LC0 || regno == REG_LC1)))
804 emit_move_insn (gen_rtx_REG (SImode, regno), postinc);
806 emit_move_insn (gen_rtx_REG (SImode, REG_ASTAT), postinc);
810 /* Perform any needed actions needed for a function that is receiving a
811 variable number of arguments.
815 MODE and TYPE are the mode and type of the current parameter.
817 PRETEND_SIZE is a variable that should be set to the amount of stack
818 that must be pushed by the prolog to pretend that our caller pushed
821 Normally, this macro will push all remaining incoming registers on the
822 stack and set PRETEND_SIZE to the length of the registers pushed.
825 - VDSP C compiler manual (our ABI) says that a variable args function
826 should save the R0, R1 and R2 registers in the stack.
827 - The caller will always leave space on the stack for the
828 arguments that are passed in registers, so we dont have
829 to leave any extra space.
830 - now, the vastart pointer can access all arguments from the stack. */
833 setup_incoming_varargs (CUMULATIVE_ARGS *cum,
834 enum machine_mode mode ATTRIBUTE_UNUSED,
835 tree type ATTRIBUTE_UNUSED, int *pretend_size,
844 /* The move for named arguments will be generated automatically by the
845 compiler. We need to generate the move rtx for the unnamed arguments
846 if they are in the first 3 words. We assume at least 1 named argument
847 exists, so we never generate [ARGP] = R0 here. */
849 for (i = cum->words + 1; i < max_arg_registers; i++)
851 mem = gen_rtx_MEM (Pmode,
852 plus_constant (arg_pointer_rtx, (i * UNITS_PER_WORD)));
853 emit_move_insn (mem, gen_rtx_REG (Pmode, i));
859 /* Value should be nonzero if functions must have frame pointers.
860 Zero means the frame pointer need not be set up (and parms may
861 be accessed via the stack pointer) in functions that seem suitable. */
864 bfin_frame_pointer_required (void)
866 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
868 if (fkind != SUBROUTINE)
871 /* We turn on -fomit-frame-pointer if -momit-leaf-frame-pointer is used,
872 so we have to override it for non-leaf functions. */
873 if (TARGET_OMIT_LEAF_FRAME_POINTER && ! current_function_is_leaf)
879 /* Return the number of registers pushed during the prologue. */
882 n_regs_saved_by_prologue (void)
884 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
885 bool is_inthandler = fkind != SUBROUTINE;
886 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
887 bool all = (lookup_attribute ("saveall", attrs) != NULL_TREE
888 || (is_inthandler && !current_function_is_leaf));
889 int ndregs = all ? 8 : n_dregs_to_save (is_inthandler, false);
890 int npregs = all ? 6 : n_pregs_to_save (is_inthandler, false);
891 int n = ndregs + npregs;
894 if (all || stack_frame_needed_p ())
898 if (must_save_fp_p ())
900 if (must_save_rets_p ())
904 if (fkind != SUBROUTINE || all)
906 /* Increment once for ASTAT. */
908 if (! current_function_is_leaf
909 || cfun->machine->has_hardware_loops
910 || cfun->machine->has_loopreg_clobber)
916 if (fkind != SUBROUTINE)
919 if (lookup_attribute ("nesting", attrs))
923 for (i = REG_P7 + 1; i < REG_CC; i++)
925 || (fkind != SUBROUTINE
926 && (df_regs_ever_live_p (i)
927 || (!leaf_function_p () && call_used_regs[i]))))
928 n += i == REG_A0 || i == REG_A1 ? 2 : 1;
933 /* Given FROM and TO register numbers, say whether this elimination is
934 allowed. Frame pointer elimination is automatically handled.
936 All other eliminations are valid. */
939 bfin_can_eliminate (const int from ATTRIBUTE_UNUSED, const int to)
941 return (to == STACK_POINTER_REGNUM ? ! frame_pointer_needed : true);
944 /* Return the offset between two registers, one to be eliminated, and the other
945 its replacement, at the start of a routine. */
948 bfin_initial_elimination_offset (int from, int to)
950 HOST_WIDE_INT offset = 0;
952 if (from == ARG_POINTER_REGNUM)
953 offset = n_regs_saved_by_prologue () * 4;
955 if (to == STACK_POINTER_REGNUM)
957 if (crtl->outgoing_args_size >= FIXED_STACK_AREA)
958 offset += crtl->outgoing_args_size;
959 else if (crtl->outgoing_args_size)
960 offset += FIXED_STACK_AREA;
962 offset += get_frame_size ();
968 /* Emit code to load a constant CONSTANT into register REG; setting
969 RTX_FRAME_RELATED_P on all insns we generate if RELATED is true.
970 Make sure that the insns we generate need not be split. */
973 frame_related_constant_load (rtx reg, HOST_WIDE_INT constant, bool related)
976 rtx cst = GEN_INT (constant);
978 if (constant >= -32768 && constant < 65536)
979 insn = emit_move_insn (reg, cst);
982 /* We don't call split_load_immediate here, since dwarf2out.c can get
983 confused about some of the more clever sequences it can generate. */
984 insn = emit_insn (gen_movsi_high (reg, cst));
986 RTX_FRAME_RELATED_P (insn) = 1;
987 insn = emit_insn (gen_movsi_low (reg, reg, cst));
990 RTX_FRAME_RELATED_P (insn) = 1;
993 /* Generate efficient code to add a value to a P register.
994 Set RTX_FRAME_RELATED_P on the generated insns if FRAME is nonzero.
995 EPILOGUE_P is zero if this function is called for prologue,
996 otherwise it's nonzero. And it's less than zero if this is for
1000 add_to_reg (rtx reg, HOST_WIDE_INT value, int frame, int epilogue_p)
1005 /* Choose whether to use a sequence using a temporary register, or
1006 a sequence with multiple adds. We can add a signed 7-bit value
1007 in one instruction. */
1008 if (value > 120 || value < -120)
1016 /* For prologue or normal epilogue, P1 can be safely used
1017 as the temporary register. For sibcall epilogue, we try to find
1018 a call used P register, which will be restored in epilogue.
1019 If we cannot find such a P register, we have to use one I register
1022 if (epilogue_p >= 0)
1023 tmpreg = gen_rtx_REG (SImode, REG_P1);
1027 for (i = REG_P0; i <= REG_P5; i++)
1028 if ((df_regs_ever_live_p (i) && ! call_used_regs[i])
1030 && i == PIC_OFFSET_TABLE_REGNUM
1031 && (crtl->uses_pic_offset_table
1032 || (TARGET_ID_SHARED_LIBRARY
1033 && ! current_function_is_leaf))))
1036 tmpreg = gen_rtx_REG (SImode, i);
1039 tmpreg = gen_rtx_REG (SImode, REG_P1);
1040 tmpreg2 = gen_rtx_REG (SImode, REG_I0);
1041 emit_move_insn (tmpreg2, tmpreg);
1046 frame_related_constant_load (tmpreg, value, TRUE);
1048 insn = emit_move_insn (tmpreg, GEN_INT (value));
1050 insn = emit_insn (gen_addsi3 (reg, reg, tmpreg));
1052 RTX_FRAME_RELATED_P (insn) = 1;
1054 if (tmpreg2 != NULL_RTX)
1055 emit_move_insn (tmpreg, tmpreg2);
1065 else if (size < -60)
1066 /* We could use -62, but that would leave the stack unaligned, so
1070 insn = emit_insn (gen_addsi3 (reg, reg, GEN_INT (size)));
1072 RTX_FRAME_RELATED_P (insn) = 1;
1078 /* Generate a LINK insn for a frame sized FRAME_SIZE. If this constant
1079 is too large, generate a sequence of insns that has the same effect.
1080 SPREG contains (reg:SI REG_SP). */
1083 emit_link_insn (rtx spreg, HOST_WIDE_INT frame_size)
1085 HOST_WIDE_INT link_size = frame_size;
1089 if (link_size > 262140)
1092 /* Use a LINK insn with as big a constant as possible, then subtract
1093 any remaining size from the SP. */
1094 insn = emit_insn (gen_link (GEN_INT (-8 - link_size)));
1095 RTX_FRAME_RELATED_P (insn) = 1;
1097 for (i = 0; i < XVECLEN (PATTERN (insn), 0); i++)
1099 rtx set = XVECEXP (PATTERN (insn), 0, i);
1100 gcc_assert (GET_CODE (set) == SET);
1101 RTX_FRAME_RELATED_P (set) = 1;
1104 frame_size -= link_size;
1108 /* Must use a call-clobbered PREG that isn't the static chain. */
1109 rtx tmpreg = gen_rtx_REG (Pmode, REG_P1);
1111 frame_related_constant_load (tmpreg, -frame_size, TRUE);
1112 insn = emit_insn (gen_addsi3 (spreg, spreg, tmpreg));
1113 RTX_FRAME_RELATED_P (insn) = 1;
1117 /* Return the number of bytes we must reserve for outgoing arguments
1118 in the current function's stack frame. */
1120 static HOST_WIDE_INT
1121 arg_area_size (void)
1123 if (crtl->outgoing_args_size)
1125 if (crtl->outgoing_args_size >= FIXED_STACK_AREA)
1126 return crtl->outgoing_args_size;
1128 return FIXED_STACK_AREA;
1133 /* Save RETS and FP, and allocate a stack frame. ALL is true if the
1134 function must save all its registers (true only for certain interrupt
1138 do_link (rtx spreg, HOST_WIDE_INT frame_size, bool all)
1140 frame_size += arg_area_size ();
1143 || stack_frame_needed_p ()
1144 || (must_save_rets_p () && must_save_fp_p ()))
1145 emit_link_insn (spreg, frame_size);
1148 if (must_save_rets_p ())
1150 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
1151 gen_rtx_PRE_DEC (Pmode, spreg)),
1153 rtx insn = emit_insn (pat);
1154 RTX_FRAME_RELATED_P (insn) = 1;
1156 if (must_save_fp_p ())
1158 rtx pat = gen_movsi (gen_rtx_MEM (Pmode,
1159 gen_rtx_PRE_DEC (Pmode, spreg)),
1160 gen_rtx_REG (Pmode, REG_FP));
1161 rtx insn = emit_insn (pat);
1162 RTX_FRAME_RELATED_P (insn) = 1;
1164 add_to_reg (spreg, -frame_size, 1, 0);
1168 /* Like do_link, but used for epilogues to deallocate the stack frame.
1169 EPILOGUE_P is zero if this function is called for prologue,
1170 otherwise it's nonzero. And it's less than zero if this is for
1171 sibcall epilogue. */
1174 do_unlink (rtx spreg, HOST_WIDE_INT frame_size, bool all, int epilogue_p)
1176 frame_size += arg_area_size ();
1178 if (stack_frame_needed_p ())
1179 emit_insn (gen_unlink ());
1182 rtx postinc = gen_rtx_MEM (Pmode, gen_rtx_POST_INC (Pmode, spreg));
1184 add_to_reg (spreg, frame_size, 0, epilogue_p);
1185 if (all || must_save_fp_p ())
1187 rtx fpreg = gen_rtx_REG (Pmode, REG_FP);
1188 emit_move_insn (fpreg, postinc);
1191 if (all || must_save_rets_p ())
1193 emit_move_insn (bfin_rets_rtx, postinc);
1194 emit_use (bfin_rets_rtx);
1199 /* Generate a prologue suitable for a function of kind FKIND. This is
1200 called for interrupt and exception handler prologues.
1201 SPREG contains (reg:SI REG_SP). */
1204 expand_interrupt_handler_prologue (rtx spreg, e_funkind fkind, bool all)
1206 HOST_WIDE_INT frame_size = get_frame_size ();
1207 rtx predec1 = gen_rtx_PRE_DEC (SImode, spreg);
1208 rtx predec = gen_rtx_MEM (SImode, predec1);
1210 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1211 tree kspisusp = lookup_attribute ("kspisusp", attrs);
1215 insn = emit_move_insn (spreg, gen_rtx_REG (Pmode, REG_USP));
1216 RTX_FRAME_RELATED_P (insn) = 1;
1219 /* We need space on the stack in case we need to save the argument
1221 if (fkind == EXCPT_HANDLER)
1223 insn = emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (-12)));
1224 RTX_FRAME_RELATED_P (insn) = 1;
1227 /* If we're calling other functions, they won't save their call-clobbered
1228 registers, so we must save everything here. */
1229 if (!current_function_is_leaf)
1231 expand_prologue_reg_save (spreg, all, true);
1233 if (ENABLE_WA_05000283 || ENABLE_WA_05000315)
1235 rtx chipid = GEN_INT (trunc_int_for_mode (0xFFC00014, SImode));
1236 rtx p5reg = gen_rtx_REG (Pmode, REG_P5);
1237 emit_insn (gen_movbi (bfin_cc_rtx, const1_rtx));
1238 emit_insn (gen_movsi_high (p5reg, chipid));
1239 emit_insn (gen_movsi_low (p5reg, p5reg, chipid));
1240 emit_insn (gen_dummy_load (p5reg, bfin_cc_rtx));
1243 if (lookup_attribute ("nesting", attrs))
1245 rtx srcreg = gen_rtx_REG (Pmode, ret_regs[fkind]);
1246 insn = emit_move_insn (predec, srcreg);
1247 RTX_FRAME_RELATED_P (insn) = 1;
1250 do_link (spreg, frame_size, all);
1252 if (fkind == EXCPT_HANDLER)
1254 rtx r0reg = gen_rtx_REG (SImode, REG_R0);
1255 rtx r1reg = gen_rtx_REG (SImode, REG_R1);
1256 rtx r2reg = gen_rtx_REG (SImode, REG_R2);
1259 insn = emit_move_insn (r0reg, gen_rtx_REG (SImode, REG_SEQSTAT));
1260 insn = emit_insn (gen_ashrsi3 (r0reg, r0reg, GEN_INT (26)));
1261 insn = emit_insn (gen_ashlsi3 (r0reg, r0reg, GEN_INT (26)));
1262 insn = emit_move_insn (r1reg, spreg);
1263 insn = emit_move_insn (r2reg, gen_rtx_REG (Pmode, REG_FP));
1264 insn = emit_insn (gen_addsi3 (r2reg, r2reg, GEN_INT (8)));
1268 /* Generate an epilogue suitable for a function of kind FKIND. This is
1269 called for interrupt and exception handler epilogues.
1270 SPREG contains (reg:SI REG_SP). */
1273 expand_interrupt_handler_epilogue (rtx spreg, e_funkind fkind, bool all)
1275 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1276 rtx postinc1 = gen_rtx_POST_INC (SImode, spreg);
1277 rtx postinc = gen_rtx_MEM (SImode, postinc1);
1279 /* A slightly crude technique to stop flow from trying to delete "dead"
1281 MEM_VOLATILE_P (postinc) = 1;
1283 do_unlink (spreg, get_frame_size (), all, 1);
1285 if (lookup_attribute ("nesting", attrs))
1287 rtx srcreg = gen_rtx_REG (Pmode, ret_regs[fkind]);
1288 emit_move_insn (srcreg, postinc);
1291 /* If we're calling other functions, they won't save their call-clobbered
1292 registers, so we must save (and restore) everything here. */
1293 if (!current_function_is_leaf)
1296 expand_epilogue_reg_restore (spreg, all, true);
1298 /* Deallocate any space we left on the stack in case we needed to save the
1299 argument registers. */
1300 if (fkind == EXCPT_HANDLER)
1301 emit_insn (gen_addsi3 (spreg, spreg, GEN_INT (12)));
1303 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, ret_regs[fkind])));
1306 /* Used while emitting the prologue to generate code to load the correct value
1307 into the PIC register, which is passed in DEST. */
1310 bfin_load_pic_reg (rtx dest)
1312 struct cgraph_local_info *i = NULL;
1315 i = cgraph_local_info (current_function_decl);
1317 /* Functions local to the translation unit don't need to reload the
1318 pic reg, since the caller always passes a usable one. */
1320 return pic_offset_table_rtx;
1322 if (bfin_lib_id_given)
1323 addr = plus_constant (pic_offset_table_rtx, -4 - bfin_library_id * 4);
1325 addr = gen_rtx_PLUS (Pmode, pic_offset_table_rtx,
1326 gen_rtx_UNSPEC (Pmode, gen_rtvec (1, const0_rtx),
1327 UNSPEC_LIBRARY_OFFSET));
1328 insn = emit_insn (gen_movsi (dest, gen_rtx_MEM (Pmode, addr)));
1332 /* Generate RTL for the prologue of the current function. */
1335 bfin_expand_prologue (void)
1337 HOST_WIDE_INT frame_size = get_frame_size ();
1338 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
1339 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1340 rtx pic_reg_loaded = NULL_RTX;
1341 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1342 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
1344 if (fkind != SUBROUTINE)
1346 expand_interrupt_handler_prologue (spreg, fkind, all);
1350 if (crtl->limit_stack
1351 || (TARGET_STACK_CHECK_L1
1352 && !DECL_NO_LIMIT_STACK (current_function_decl)))
1354 HOST_WIDE_INT offset
1355 = bfin_initial_elimination_offset (ARG_POINTER_REGNUM,
1356 STACK_POINTER_REGNUM);
1357 rtx lim = crtl->limit_stack ? stack_limit_rtx : NULL_RTX;
1358 rtx p2reg = gen_rtx_REG (Pmode, REG_P2);
1362 emit_move_insn (p2reg, gen_int_mode (0xFFB00000, SImode));
1363 emit_move_insn (p2reg, gen_rtx_MEM (Pmode, p2reg));
1366 if (GET_CODE (lim) == SYMBOL_REF)
1368 if (TARGET_ID_SHARED_LIBRARY)
1370 rtx p1reg = gen_rtx_REG (Pmode, REG_P1);
1372 pic_reg_loaded = bfin_load_pic_reg (p2reg);
1373 val = legitimize_pic_address (stack_limit_rtx, p1reg,
1375 emit_move_insn (p1reg, val);
1376 frame_related_constant_load (p2reg, offset, FALSE);
1377 emit_insn (gen_addsi3 (p2reg, p2reg, p1reg));
1382 rtx limit = plus_constant (lim, offset);
1383 emit_move_insn (p2reg, limit);
1390 emit_move_insn (p2reg, lim);
1391 add_to_reg (p2reg, offset, 0, 0);
1394 emit_insn (gen_compare_lt (bfin_cc_rtx, spreg, lim));
1395 emit_insn (gen_trapifcc ());
1397 expand_prologue_reg_save (spreg, all, false);
1399 do_link (spreg, frame_size, all);
1401 if (TARGET_ID_SHARED_LIBRARY
1403 && (crtl->uses_pic_offset_table
1404 || !current_function_is_leaf))
1405 bfin_load_pic_reg (pic_offset_table_rtx);
1408 /* Generate RTL for the epilogue of the current function. NEED_RETURN is zero
1409 if this is for a sibcall. EH_RETURN is nonzero if we're expanding an
1410 eh_return pattern. SIBCALL_P is true if this is a sibcall epilogue,
1414 bfin_expand_epilogue (int need_return, int eh_return, bool sibcall_p)
1416 rtx spreg = gen_rtx_REG (Pmode, REG_SP);
1417 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
1418 int e = sibcall_p ? -1 : 1;
1419 tree attrs = TYPE_ATTRIBUTES (TREE_TYPE (current_function_decl));
1420 bool all = lookup_attribute ("saveall", attrs) != NULL_TREE;
1422 if (fkind != SUBROUTINE)
1424 expand_interrupt_handler_epilogue (spreg, fkind, all);
1428 do_unlink (spreg, get_frame_size (), all, e);
1430 expand_epilogue_reg_restore (spreg, all, false);
1432 /* Omit the return insn if this is for a sibcall. */
1437 emit_insn (gen_addsi3 (spreg, spreg, gen_rtx_REG (Pmode, REG_P2)));
1439 emit_jump_insn (gen_return_internal (gen_rtx_REG (Pmode, REG_RETS)));
1442 /* Return nonzero if register OLD_REG can be renamed to register NEW_REG. */
1445 bfin_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
1446 unsigned int new_reg)
1448 /* Interrupt functions can only use registers that have already been
1449 saved by the prologue, even if they would normally be
1452 if (funkind (TREE_TYPE (current_function_decl)) != SUBROUTINE
1453 && !df_regs_ever_live_p (new_reg))
1459 /* Return the value of the return address for the frame COUNT steps up
1460 from the current frame, after the prologue.
1461 We punt for everything but the current frame by returning const0_rtx. */
1464 bfin_return_addr_rtx (int count)
1469 return get_hard_reg_initial_val (Pmode, REG_RETS);
1473 bfin_delegitimize_address (rtx orig_x)
1477 if (GET_CODE (x) != MEM)
1481 if (GET_CODE (x) == PLUS
1482 && GET_CODE (XEXP (x, 1)) == UNSPEC
1483 && XINT (XEXP (x, 1), 1) == UNSPEC_MOVE_PIC
1484 && GET_CODE (XEXP (x, 0)) == REG
1485 && REGNO (XEXP (x, 0)) == PIC_OFFSET_TABLE_REGNUM)
1486 return XVECEXP (XEXP (x, 1), 0, 0);
1491 /* This predicate is used to compute the length of a load/store insn.
1492 OP is a MEM rtx, we return nonzero if its addressing mode requires a
1493 32-bit instruction. */
1496 effective_address_32bit_p (rtx op, enum machine_mode mode)
1498 HOST_WIDE_INT offset;
1500 mode = GET_MODE (op);
1503 if (GET_CODE (op) != PLUS)
1505 gcc_assert (REG_P (op) || GET_CODE (op) == POST_INC
1506 || GET_CODE (op) == PRE_DEC || GET_CODE (op) == POST_DEC);
1510 if (GET_CODE (XEXP (op, 1)) == UNSPEC)
1513 offset = INTVAL (XEXP (op, 1));
1515 /* All byte loads use a 16-bit offset. */
1516 if (GET_MODE_SIZE (mode) == 1)
1519 if (GET_MODE_SIZE (mode) == 4)
1521 /* Frame pointer relative loads can use a negative offset, all others
1522 are restricted to a small positive one. */
1523 if (XEXP (op, 0) == frame_pointer_rtx)
1524 return offset < -128 || offset > 60;
1525 return offset < 0 || offset > 60;
1528 /* Must be HImode now. */
1529 return offset < 0 || offset > 30;
1532 /* Returns true if X is a memory reference using an I register. */
1534 bfin_dsp_memref_p (rtx x)
1539 if (GET_CODE (x) == POST_INC || GET_CODE (x) == PRE_INC
1540 || GET_CODE (x) == POST_DEC || GET_CODE (x) == PRE_DEC)
1545 /* Return cost of the memory address ADDR.
1546 All addressing modes are equally cheap on the Blackfin. */
1549 bfin_address_cost (rtx addr ATTRIBUTE_UNUSED, bool speed ATTRIBUTE_UNUSED)
1554 /* Subroutine of print_operand; used to print a memory reference X to FILE. */
1557 print_address_operand (FILE *file, rtx x)
1559 switch (GET_CODE (x))
1562 output_address (XEXP (x, 0));
1563 fprintf (file, "+");
1564 output_address (XEXP (x, 1));
1568 fprintf (file, "--");
1569 output_address (XEXP (x, 0));
1572 output_address (XEXP (x, 0));
1573 fprintf (file, "++");
1576 output_address (XEXP (x, 0));
1577 fprintf (file, "--");
1581 gcc_assert (GET_CODE (x) != MEM);
1582 print_operand (file, x, 0);
1587 /* Adding intp DImode support by Tony
1593 print_operand (FILE *file, rtx x, char code)
1595 enum machine_mode mode;
1599 if (GET_MODE (current_output_insn) == SImode)
1600 fprintf (file, " ||");
1602 fprintf (file, ";");
1606 mode = GET_MODE (x);
1611 switch (GET_CODE (x))
1614 fprintf (file, "e");
1617 fprintf (file, "ne");
1620 fprintf (file, "g");
1623 fprintf (file, "l");
1626 fprintf (file, "ge");
1629 fprintf (file, "le");
1632 fprintf (file, "g");
1635 fprintf (file, "l");
1638 fprintf (file, "ge");
1641 fprintf (file, "le");
1644 output_operand_lossage ("invalid %%j value");
1648 case 'J': /* reverse logic */
1649 switch (GET_CODE(x))
1652 fprintf (file, "ne");
1655 fprintf (file, "e");
1658 fprintf (file, "le");
1661 fprintf (file, "ge");
1664 fprintf (file, "l");
1667 fprintf (file, "g");
1670 fprintf (file, "le");
1673 fprintf (file, "ge");
1676 fprintf (file, "l");
1679 fprintf (file, "g");
1682 output_operand_lossage ("invalid %%J value");
1687 switch (GET_CODE (x))
1693 fprintf (file, "%s", short_reg_names[REGNO (x)]);
1695 output_operand_lossage ("invalid operand for code '%c'", code);
1697 else if (code == 'd')
1700 fprintf (file, "%s", high_reg_names[REGNO (x)]);
1702 output_operand_lossage ("invalid operand for code '%c'", code);
1704 else if (code == 'w')
1706 if (REGNO (x) == REG_A0 || REGNO (x) == REG_A1)
1707 fprintf (file, "%s.w", reg_names[REGNO (x)]);
1709 output_operand_lossage ("invalid operand for code '%c'", code);
1711 else if (code == 'x')
1713 if (REGNO (x) == REG_A0 || REGNO (x) == REG_A1)
1714 fprintf (file, "%s.x", reg_names[REGNO (x)]);
1716 output_operand_lossage ("invalid operand for code '%c'", code);
1718 else if (code == 'v')
1720 if (REGNO (x) == REG_A0)
1721 fprintf (file, "AV0");
1722 else if (REGNO (x) == REG_A1)
1723 fprintf (file, "AV1");
1725 output_operand_lossage ("invalid operand for code '%c'", code);
1727 else if (code == 'D')
1729 if (D_REGNO_P (REGNO (x)))
1730 fprintf (file, "%s", dregs_pair_names[REGNO (x)]);
1732 output_operand_lossage ("invalid operand for code '%c'", code);
1734 else if (code == 'H')
1736 if ((mode == DImode || mode == DFmode) && REG_P (x))
1737 fprintf (file, "%s", reg_names[REGNO (x) + 1]);
1739 output_operand_lossage ("invalid operand for code '%c'", code);
1741 else if (code == 'T')
1743 if (D_REGNO_P (REGNO (x)))
1744 fprintf (file, "%s", byte_reg_names[REGNO (x)]);
1746 output_operand_lossage ("invalid operand for code '%c'", code);
1749 fprintf (file, "%s", reg_names[REGNO (x)]);
1755 print_address_operand (file, x);
1767 fputs ("(FU)", file);
1770 fputs ("(T)", file);
1773 fputs ("(TFU)", file);
1776 fputs ("(W32)", file);
1779 fputs ("(IS)", file);
1782 fputs ("(IU)", file);
1785 fputs ("(IH)", file);
1788 fputs ("(M)", file);
1791 fputs ("(IS,M)", file);
1794 fputs ("(ISS2)", file);
1797 fputs ("(S2RND)", file);
1804 else if (code == 'b')
1806 if (INTVAL (x) == 0)
1808 else if (INTVAL (x) == 1)
1814 /* Moves to half registers with d or h modifiers always use unsigned
1816 else if (code == 'd')
1817 x = GEN_INT ((INTVAL (x) >> 16) & 0xffff);
1818 else if (code == 'h')
1819 x = GEN_INT (INTVAL (x) & 0xffff);
1820 else if (code == 'N')
1821 x = GEN_INT (-INTVAL (x));
1822 else if (code == 'X')
1823 x = GEN_INT (exact_log2 (0xffffffff & INTVAL (x)));
1824 else if (code == 'Y')
1825 x = GEN_INT (exact_log2 (0xffffffff & ~INTVAL (x)));
1826 else if (code == 'Z')
1827 /* Used for LINK insns. */
1828 x = GEN_INT (-8 - INTVAL (x));
1833 output_addr_const (file, x);
1837 output_operand_lossage ("invalid const_double operand");
1841 switch (XINT (x, 1))
1843 case UNSPEC_MOVE_PIC:
1844 output_addr_const (file, XVECEXP (x, 0, 0));
1845 fprintf (file, "@GOT");
1848 case UNSPEC_MOVE_FDPIC:
1849 output_addr_const (file, XVECEXP (x, 0, 0));
1850 fprintf (file, "@GOT17M4");
1853 case UNSPEC_FUNCDESC_GOT17M4:
1854 output_addr_const (file, XVECEXP (x, 0, 0));
1855 fprintf (file, "@FUNCDESC_GOT17M4");
1858 case UNSPEC_LIBRARY_OFFSET:
1859 fprintf (file, "_current_shared_library_p5_offset_");
1868 output_addr_const (file, x);
1873 /* Argument support functions. */
1875 /* Initialize a variable CUM of type CUMULATIVE_ARGS
1876 for a call to a function whose data type is FNTYPE.
1877 For a library call, FNTYPE is 0.
1878 VDSP C Compiler manual, our ABI says that
1879 first 3 words of arguments will use R0, R1 and R2.
1883 init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype,
1884 rtx libname ATTRIBUTE_UNUSED)
1886 static CUMULATIVE_ARGS zero_cum;
1890 /* Set up the number of registers to use for passing arguments. */
1892 cum->nregs = max_arg_registers;
1893 cum->arg_regs = arg_regs;
1895 cum->call_cookie = CALL_NORMAL;
1896 /* Check for a longcall attribute. */
1897 if (fntype && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (fntype)))
1898 cum->call_cookie |= CALL_SHORT;
1899 else if (fntype && lookup_attribute ("longcall", TYPE_ATTRIBUTES (fntype)))
1900 cum->call_cookie |= CALL_LONG;
1905 /* Update the data in CUM to advance over an argument
1906 of mode MODE and data type TYPE.
1907 (TYPE is null for libcalls where that information may not be available.) */
1910 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1911 int named ATTRIBUTE_UNUSED)
1913 int count, bytes, words;
1915 bytes = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1916 words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
1918 cum->words += words;
1919 cum->nregs -= words;
1921 if (cum->nregs <= 0)
1924 cum->arg_regs = NULL;
1928 for (count = 1; count <= words; count++)
1935 /* Define where to put the arguments to a function.
1936 Value is zero to push the argument on the stack,
1937 or a hard register in which to store the argument.
1939 MODE is the argument's machine mode.
1940 TYPE is the data type of the argument (as a tree).
1941 This is null for libcalls where that information may
1943 CUM is a variable of type CUMULATIVE_ARGS which gives info about
1944 the preceding args and about the function being called.
1945 NAMED is nonzero if this argument is a named parameter
1946 (otherwise it is an extra parameter matching an ellipsis). */
1949 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
1950 int named ATTRIBUTE_UNUSED)
1953 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1955 if (mode == VOIDmode)
1956 /* Compute operand 2 of the call insn. */
1957 return GEN_INT (cum->call_cookie);
1963 return gen_rtx_REG (mode, *(cum->arg_regs));
1968 /* For an arg passed partly in registers and partly in memory,
1969 this is the number of bytes passed in registers.
1970 For args passed entirely in registers or entirely in memory, zero.
1972 Refer VDSP C Compiler manual, our ABI.
1973 First 3 words are in registers. So, if an argument is larger
1974 than the registers available, it will span the register and
1978 bfin_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
1979 tree type ATTRIBUTE_UNUSED,
1980 bool named ATTRIBUTE_UNUSED)
1983 = (mode == BLKmode) ? int_size_in_bytes (type) : GET_MODE_SIZE (mode);
1984 int bytes_left = cum->nregs * UNITS_PER_WORD;
1989 if (bytes_left == 0)
1991 if (bytes > bytes_left)
1996 /* Variable sized types are passed by reference. */
1999 bfin_pass_by_reference (CUMULATIVE_ARGS *cum ATTRIBUTE_UNUSED,
2000 enum machine_mode mode ATTRIBUTE_UNUSED,
2001 const_tree type, bool named ATTRIBUTE_UNUSED)
2003 return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
2006 /* Decide whether a type should be returned in memory (true)
2007 or in a register (false). This is called by the macro
2008 TARGET_RETURN_IN_MEMORY. */
2011 bfin_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
2013 int size = int_size_in_bytes (type);
2014 return size > 2 * UNITS_PER_WORD || size == -1;
2017 /* Register in which address to store a structure value
2018 is passed to a function. */
2020 bfin_struct_value_rtx (tree fntype ATTRIBUTE_UNUSED,
2021 int incoming ATTRIBUTE_UNUSED)
2023 return gen_rtx_REG (Pmode, REG_P0);
2026 /* Return true when register may be used to pass function parameters. */
2029 function_arg_regno_p (int n)
2032 for (i = 0; arg_regs[i] != -1; i++)
2033 if (n == arg_regs[i])
2038 /* Returns 1 if OP contains a symbol reference */
2041 symbolic_reference_mentioned_p (rtx op)
2043 register const char *fmt;
2046 if (GET_CODE (op) == SYMBOL_REF || GET_CODE (op) == LABEL_REF)
2049 fmt = GET_RTX_FORMAT (GET_CODE (op));
2050 for (i = GET_RTX_LENGTH (GET_CODE (op)) - 1; i >= 0; i--)
2056 for (j = XVECLEN (op, i) - 1; j >= 0; j--)
2057 if (symbolic_reference_mentioned_p (XVECEXP (op, i, j)))
2061 else if (fmt[i] == 'e' && symbolic_reference_mentioned_p (XEXP (op, i)))
2068 /* Decide whether we can make a sibling call to a function. DECL is the
2069 declaration of the function being targeted by the call and EXP is the
2070 CALL_EXPR representing the call. */
2073 bfin_function_ok_for_sibcall (tree decl ATTRIBUTE_UNUSED,
2074 tree exp ATTRIBUTE_UNUSED)
2076 struct cgraph_local_info *this_func, *called_func;
2077 e_funkind fkind = funkind (TREE_TYPE (current_function_decl));
2078 if (fkind != SUBROUTINE)
2080 if (!TARGET_ID_SHARED_LIBRARY || TARGET_SEP_DATA)
2083 /* When compiling for ID shared libraries, can't sibcall a local function
2084 from a non-local function, because the local function thinks it does
2085 not need to reload P5 in the prologue, but the sibcall wil pop P5 in the
2086 sibcall epilogue, and we end up with the wrong value in P5. */
2089 /* Not enough information. */
2092 this_func = cgraph_local_info (current_function_decl);
2093 called_func = cgraph_local_info (decl);
2094 return !called_func->local || this_func->local;
2097 /* Write a template for a trampoline to F. */
2100 bfin_asm_trampoline_template (FILE *f)
2104 fprintf (f, "\t.dd\t0x00000000\n"); /* 0 */
2105 fprintf (f, "\t.dd\t0x00000000\n"); /* 0 */
2106 fprintf (f, "\t.dd\t0x0000e109\n"); /* p1.l = fn low */
2107 fprintf (f, "\t.dd\t0x0000e149\n"); /* p1.h = fn high */
2108 fprintf (f, "\t.dd\t0x0000e10a\n"); /* p2.l = sc low */
2109 fprintf (f, "\t.dd\t0x0000e14a\n"); /* p2.h = sc high */
2110 fprintf (f, "\t.dw\t0xac4b\n"); /* p3 = [p1 + 4] */
2111 fprintf (f, "\t.dw\t0x9149\n"); /* p1 = [p1] */
2112 fprintf (f, "\t.dw\t0x0051\n"); /* jump (p1)*/
2116 fprintf (f, "\t.dd\t0x0000e109\n"); /* p1.l = fn low */
2117 fprintf (f, "\t.dd\t0x0000e149\n"); /* p1.h = fn high */
2118 fprintf (f, "\t.dd\t0x0000e10a\n"); /* p2.l = sc low */
2119 fprintf (f, "\t.dd\t0x0000e14a\n"); /* p2.h = sc high */
2120 fprintf (f, "\t.dw\t0x0051\n"); /* jump (p1)*/
2124 /* Emit RTL insns to initialize the variable parts of a trampoline at
2125 M_TRAMP. FNDECL is the target function. CHAIN_VALUE is an RTX for
2126 the static chain value for the function. */
2129 bfin_trampoline_init (rtx m_tramp, tree fndecl, rtx chain_value)
2131 rtx t1 = copy_to_reg (XEXP (DECL_RTL (fndecl), 0));
2132 rtx t2 = copy_to_reg (chain_value);
2136 emit_block_move (m_tramp, assemble_trampoline_template (),
2137 GEN_INT (TRAMPOLINE_SIZE), BLOCK_OP_NORMAL);
2141 rtx a = force_reg (Pmode, plus_constant (XEXP (m_tramp, 0), 8));
2142 mem = adjust_address (m_tramp, Pmode, 0);
2143 emit_move_insn (mem, a);
2147 mem = adjust_address (m_tramp, HImode, i + 2);
2148 emit_move_insn (mem, gen_lowpart (HImode, t1));
2149 emit_insn (gen_ashrsi3 (t1, t1, GEN_INT (16)));
2150 mem = adjust_address (m_tramp, HImode, i + 6);
2151 emit_move_insn (mem, gen_lowpart (HImode, t1));
2153 mem = adjust_address (m_tramp, HImode, i + 10);
2154 emit_move_insn (mem, gen_lowpart (HImode, t2));
2155 emit_insn (gen_ashrsi3 (t2, t2, GEN_INT (16)));
2156 mem = adjust_address (m_tramp, HImode, i + 14);
2157 emit_move_insn (mem, gen_lowpart (HImode, t2));
2160 /* Emit insns to move operands[1] into operands[0]. */
2163 emit_pic_move (rtx *operands, enum machine_mode mode ATTRIBUTE_UNUSED)
2165 rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
2167 gcc_assert (!TARGET_FDPIC || !(reload_in_progress || reload_completed));
2168 if (GET_CODE (operands[0]) == MEM && SYMBOLIC_CONST (operands[1]))
2169 operands[1] = force_reg (SImode, operands[1]);
2171 operands[1] = legitimize_pic_address (operands[1], temp,
2172 TARGET_FDPIC ? OUR_FDPIC_REG
2173 : pic_offset_table_rtx);
2176 /* Expand a move operation in mode MODE. The operands are in OPERANDS.
2177 Returns true if no further code must be generated, false if the caller
2178 should generate an insn to move OPERANDS[1] to OPERANDS[0]. */
2181 expand_move (rtx *operands, enum machine_mode mode)
2183 rtx op = operands[1];
2184 if ((TARGET_ID_SHARED_LIBRARY || TARGET_FDPIC)
2185 && SYMBOLIC_CONST (op))
2186 emit_pic_move (operands, mode);
2187 else if (mode == SImode && GET_CODE (op) == CONST
2188 && GET_CODE (XEXP (op, 0)) == PLUS
2189 && GET_CODE (XEXP (XEXP (op, 0), 0)) == SYMBOL_REF
2190 && !bfin_legitimate_constant_p (op))
2192 rtx dest = operands[0];
2194 gcc_assert (!reload_in_progress && !reload_completed);
2196 op0 = force_reg (mode, XEXP (op, 0));
2198 if (!insn_data[CODE_FOR_addsi3].operand[2].predicate (op1, mode))
2199 op1 = force_reg (mode, op1);
2200 if (GET_CODE (dest) == MEM)
2201 dest = gen_reg_rtx (mode);
2202 emit_insn (gen_addsi3 (dest, op0, op1));
2203 if (dest == operands[0])
2207 /* Don't generate memory->memory or constant->memory moves, go through a
2209 else if ((reload_in_progress | reload_completed) == 0
2210 && GET_CODE (operands[0]) == MEM
2211 && GET_CODE (operands[1]) != REG)
2212 operands[1] = force_reg (mode, operands[1]);
2216 /* Split one or more DImode RTL references into pairs of SImode
2217 references. The RTL can be REG, offsettable MEM, integer constant, or
2218 CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
2219 split and "num" is its length. lo_half and hi_half are output arrays
2220 that parallel "operands". */
2223 split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
2227 rtx op = operands[num];
2229 /* simplify_subreg refuse to split volatile memory addresses,
2230 but we still have to handle it. */
2231 if (GET_CODE (op) == MEM)
2233 lo_half[num] = adjust_address (op, SImode, 0);
2234 hi_half[num] = adjust_address (op, SImode, 4);
2238 lo_half[num] = simplify_gen_subreg (SImode, op,
2239 GET_MODE (op) == VOIDmode
2240 ? DImode : GET_MODE (op), 0);
2241 hi_half[num] = simplify_gen_subreg (SImode, op,
2242 GET_MODE (op) == VOIDmode
2243 ? DImode : GET_MODE (op), 4);
2249 bfin_longcall_p (rtx op, int call_cookie)
2251 gcc_assert (GET_CODE (op) == SYMBOL_REF);
2252 if (SYMBOL_REF_WEAK (op))
2254 if (call_cookie & CALL_SHORT)
2256 if (call_cookie & CALL_LONG)
2258 if (TARGET_LONG_CALLS)
2263 /* Expand a call instruction. FNADDR is the call target, RETVAL the return value.
2264 COOKIE is a CONST_INT holding the call_cookie prepared init_cumulative_args.
2265 SIBCALL is nonzero if this is a sibling call. */
2268 bfin_expand_call (rtx retval, rtx fnaddr, rtx callarg1, rtx cookie, int sibcall)
2270 rtx use = NULL, call;
2271 rtx callee = XEXP (fnaddr, 0);
2274 rtx picreg = get_hard_reg_initial_val (SImode, FDPIC_REGNO);
2275 rtx retsreg = gen_rtx_REG (Pmode, REG_RETS);
2278 /* In an untyped call, we can get NULL for operand 2. */
2279 if (cookie == NULL_RTX)
2280 cookie = const0_rtx;
2282 /* Static functions and indirect calls don't need the pic register. */
2283 if (!TARGET_FDPIC && flag_pic
2284 && GET_CODE (callee) == SYMBOL_REF
2285 && !SYMBOL_REF_LOCAL_P (callee))
2286 use_reg (&use, pic_offset_table_rtx);
2290 int caller_in_sram, callee_in_sram;
2292 /* 0 is not in sram, 1 is in L1 sram, 2 is in L2 sram. */
2293 caller_in_sram = callee_in_sram = 0;
2295 if (lookup_attribute ("l1_text",
2296 DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE)
2298 else if (lookup_attribute ("l2",
2299 DECL_ATTRIBUTES (cfun->decl)) != NULL_TREE)
2302 if (GET_CODE (callee) == SYMBOL_REF
2303 && SYMBOL_REF_DECL (callee) && DECL_P (SYMBOL_REF_DECL (callee)))
2305 if (lookup_attribute
2307 DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE)
2309 else if (lookup_attribute
2311 DECL_ATTRIBUTES (SYMBOL_REF_DECL (callee))) != NULL_TREE)
2315 if (GET_CODE (callee) != SYMBOL_REF
2316 || bfin_longcall_p (callee, INTVAL (cookie))
2317 || (GET_CODE (callee) == SYMBOL_REF
2318 && !SYMBOL_REF_LOCAL_P (callee)
2319 && TARGET_INLINE_PLT)
2320 || caller_in_sram != callee_in_sram
2321 || (caller_in_sram && callee_in_sram
2322 && (GET_CODE (callee) != SYMBOL_REF
2323 || !SYMBOL_REF_LOCAL_P (callee))))
2326 if (! address_operand (addr, Pmode))
2327 addr = force_reg (Pmode, addr);
2329 fnaddr = gen_reg_rtx (SImode);
2330 emit_insn (gen_load_funcdescsi (fnaddr, addr));
2331 fnaddr = gen_rtx_MEM (Pmode, fnaddr);
2333 picreg = gen_reg_rtx (SImode);
2334 emit_insn (gen_load_funcdescsi (picreg,
2335 plus_constant (addr, 4)));
2340 else if ((!register_no_elim_operand (callee, Pmode)
2341 && GET_CODE (callee) != SYMBOL_REF)
2342 || (GET_CODE (callee) == SYMBOL_REF
2343 && ((TARGET_ID_SHARED_LIBRARY && !TARGET_LEAF_ID_SHARED_LIBRARY)
2344 || bfin_longcall_p (callee, INTVAL (cookie)))))
2346 callee = copy_to_mode_reg (Pmode, callee);
2347 fnaddr = gen_rtx_MEM (Pmode, callee);
2349 call = gen_rtx_CALL (VOIDmode, fnaddr, callarg1);
2352 call = gen_rtx_SET (VOIDmode, retval, call);
2354 pat = gen_rtx_PARALLEL (VOIDmode, rtvec_alloc (nelts));
2356 XVECEXP (pat, 0, n++) = call;
2358 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, picreg);
2359 XVECEXP (pat, 0, n++) = gen_rtx_USE (VOIDmode, cookie);
2361 XVECEXP (pat, 0, n++) = gen_rtx_RETURN (VOIDmode);
2363 XVECEXP (pat, 0, n++) = gen_rtx_CLOBBER (VOIDmode, retsreg);
2364 call = emit_call_insn (pat);
2366 CALL_INSN_FUNCTION_USAGE (call) = use;
2369 /* Return 1 if hard register REGNO can hold a value of machine-mode MODE. */
2372 hard_regno_mode_ok (int regno, enum machine_mode mode)
2374 /* Allow only dregs to store value of mode HI or QI */
2375 enum reg_class rclass = REGNO_REG_CLASS (regno);
2380 if (mode == V2HImode)
2381 return D_REGNO_P (regno);
2382 if (rclass == CCREGS)
2383 return mode == BImode;
2384 if (mode == PDImode || mode == V2PDImode)
2385 return regno == REG_A0 || regno == REG_A1;
2387 /* Allow all normal 32-bit regs, except REG_M3, in case regclass ever comes
2388 up with a bad register class (such as ALL_REGS) for DImode. */
2390 return regno < REG_M3;
2393 && TEST_HARD_REG_BIT (reg_class_contents[PROLOGUE_REGS], regno))
2396 return TEST_HARD_REG_BIT (reg_class_contents[MOST_REGS], regno);
2399 /* Implements target hook vector_mode_supported_p. */
2402 bfin_vector_mode_supported_p (enum machine_mode mode)
2404 return mode == V2HImode;
2407 /* Return the cost of moving data from a register in class CLASS1 to
2408 one in class CLASS2. A cost of 2 is the default. */
2411 bfin_register_move_cost (enum machine_mode mode,
2412 enum reg_class class1, enum reg_class class2)
2414 /* These need secondary reloads, so they're more expensive. */
2415 if ((class1 == CCREGS && !reg_class_subset_p (class2, DREGS))
2416 || (class2 == CCREGS && !reg_class_subset_p (class1, DREGS)))
2419 /* If optimizing for size, always prefer reg-reg over reg-memory moves. */
2423 if (GET_MODE_CLASS (mode) == MODE_INT)
2425 /* Discourage trying to use the accumulators. */
2426 if (TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A0)
2427 || TEST_HARD_REG_BIT (reg_class_contents[class1], REG_A1)
2428 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A0)
2429 || TEST_HARD_REG_BIT (reg_class_contents[class2], REG_A1))
2435 /* Return the cost of moving data of mode M between a
2436 register and memory. A value of 2 is the default; this cost is
2437 relative to those in `REGISTER_MOVE_COST'.
2439 ??? In theory L1 memory has single-cycle latency. We should add a switch
2440 that tells the compiler whether we expect to use only L1 memory for the
2441 program; it'll make the costs more accurate. */
2444 bfin_memory_move_cost (enum machine_mode mode ATTRIBUTE_UNUSED,
2445 enum reg_class rclass,
2446 int in ATTRIBUTE_UNUSED)
2448 /* Make memory accesses slightly more expensive than any register-register
2449 move. Also, penalize non-DP registers, since they need secondary
2450 reloads to load and store. */
2451 if (! reg_class_subset_p (rclass, DPREGS))
2457 /* Inform reload about cases where moving X with a mode MODE to a register in
2458 RCLASS requires an extra scratch register. Return the class needed for the
2459 scratch register. */
2461 static enum reg_class
2462 bfin_secondary_reload (bool in_p, rtx x, enum reg_class rclass,
2463 enum machine_mode mode, secondary_reload_info *sri)
2465 /* If we have HImode or QImode, we can only use DREGS as secondary registers;
2466 in most other cases we can also use PREGS. */
2467 enum reg_class default_class = GET_MODE_SIZE (mode) >= 4 ? DPREGS : DREGS;
2468 enum reg_class x_class = NO_REGS;
2469 enum rtx_code code = GET_CODE (x);
2472 x = SUBREG_REG (x), code = GET_CODE (x);
2475 int regno = REGNO (x);
2476 if (regno >= FIRST_PSEUDO_REGISTER)
2477 regno = reg_renumber[regno];
2482 x_class = REGNO_REG_CLASS (regno);
2485 /* We can be asked to reload (plus (FP) (large_constant)) into a DREG.
2486 This happens as a side effect of register elimination, and we need
2487 a scratch register to do it. */
2488 if (fp_plus_const_operand (x, mode))
2490 rtx op2 = XEXP (x, 1);
2491 int large_constant_p = ! satisfies_constraint_Ks7 (op2);
2493 if (rclass == PREGS || rclass == PREGS_CLOBBERED)
2495 /* If destination is a DREG, we can do this without a scratch register
2496 if the constant is valid for an add instruction. */
2497 if ((rclass == DREGS || rclass == DPREGS)
2498 && ! large_constant_p)
2500 /* Reloading to anything other than a DREG? Use a PREG scratch
2502 sri->icode = CODE_FOR_reload_insi;
2506 /* Data can usually be moved freely between registers of most classes.
2507 AREGS are an exception; they can only move to or from another register
2508 in AREGS or one in DREGS. They can also be assigned the constant 0. */
2509 if (x_class == AREGS || x_class == EVEN_AREGS || x_class == ODD_AREGS)
2510 return (rclass == DREGS || rclass == AREGS || rclass == EVEN_AREGS
2511 || rclass == ODD_AREGS
2514 if (rclass == AREGS || rclass == EVEN_AREGS || rclass == ODD_AREGS)
2518 sri->icode = in_p ? CODE_FOR_reload_inpdi : CODE_FOR_reload_outpdi;
2522 if (x != const0_rtx && x_class != DREGS)
2530 /* CCREGS can only be moved from/to DREGS. */
2531 if (rclass == CCREGS && x_class != DREGS)
2533 if (x_class == CCREGS && rclass != DREGS)
2536 /* All registers other than AREGS can load arbitrary constants. The only
2537 case that remains is MEM. */
2539 if (! reg_class_subset_p (rclass, default_class))
2540 return default_class;
2545 /* Implement TARGET_HANDLE_OPTION. */
2548 bfin_handle_option (size_t code, const char *arg, int value)
2552 case OPT_mshared_library_id_:
2553 if (value > MAX_LIBRARY_ID)
2554 error ("-mshared-library-id=%s is not between 0 and %d",
2555 arg, MAX_LIBRARY_ID);
2556 bfin_lib_id_given = 1;
2565 while ((p = bfin_cpus[i].name) != NULL)
2567 if (strncmp (arg, p, strlen (p)) == 0)
2574 error ("-mcpu=%s is not valid", arg);
2578 bfin_cpu_type = bfin_cpus[i].type;
2580 q = arg + strlen (p);
2584 bfin_si_revision = bfin_cpus[i].si_revision;
2585 bfin_workarounds |= bfin_cpus[i].workarounds;
2587 else if (strcmp (q, "-none") == 0)
2588 bfin_si_revision = -1;
2589 else if (strcmp (q, "-any") == 0)
2591 bfin_si_revision = 0xffff;
2592 while (bfin_cpus[i].type == bfin_cpu_type)
2594 bfin_workarounds |= bfin_cpus[i].workarounds;
2600 unsigned int si_major, si_minor;
2603 rev_len = strlen (q);
2605 if (sscanf (q, "-%u.%u%n", &si_major, &si_minor, &n) != 2
2607 || si_major > 0xff || si_minor > 0xff)
2609 invalid_silicon_revision:
2610 error ("-mcpu=%s has invalid silicon revision", arg);
2614 bfin_si_revision = (si_major << 8) | si_minor;
2616 while (bfin_cpus[i].type == bfin_cpu_type
2617 && bfin_cpus[i].si_revision != bfin_si_revision)
2620 if (bfin_cpus[i].type != bfin_cpu_type)
2621 goto invalid_silicon_revision;
2623 bfin_workarounds |= bfin_cpus[i].workarounds;
2634 static struct machine_function *
2635 bfin_init_machine_status (void)
2637 struct machine_function *f;
2639 f = GGC_CNEW (struct machine_function);
2644 /* Implement the macro OVERRIDE_OPTIONS. */
2647 override_options (void)
2649 /* If processor type is not specified, enable all workarounds. */
2650 if (bfin_cpu_type == BFIN_CPU_UNKNOWN)
2654 for (i = 0; bfin_cpus[i].name != NULL; i++)
2655 bfin_workarounds |= bfin_cpus[i].workarounds;
2657 bfin_si_revision = 0xffff;
2660 if (bfin_csync_anomaly == 1)
2661 bfin_workarounds |= WA_SPECULATIVE_SYNCS;
2662 else if (bfin_csync_anomaly == 0)
2663 bfin_workarounds &= ~WA_SPECULATIVE_SYNCS;
2665 if (bfin_specld_anomaly == 1)
2666 bfin_workarounds |= WA_SPECULATIVE_LOADS;
2667 else if (bfin_specld_anomaly == 0)
2668 bfin_workarounds &= ~WA_SPECULATIVE_LOADS;
2670 if (TARGET_OMIT_LEAF_FRAME_POINTER)
2671 flag_omit_frame_pointer = 1;
2673 /* Library identification */
2674 if (bfin_lib_id_given && ! TARGET_ID_SHARED_LIBRARY)
2675 error ("-mshared-library-id= specified without -mid-shared-library");
2677 if (stack_limit_rtx && TARGET_STACK_CHECK_L1)
2678 error ("Can't use multiple stack checking methods together.");
2680 if (TARGET_ID_SHARED_LIBRARY && TARGET_FDPIC)
2681 error ("ID shared libraries and FD-PIC mode can't be used together.");
2683 /* Don't allow the user to specify -mid-shared-library and -msep-data
2684 together, as it makes little sense from a user's point of view... */
2685 if (TARGET_SEP_DATA && TARGET_ID_SHARED_LIBRARY)
2686 error ("cannot specify both -msep-data and -mid-shared-library");
2687 /* ... internally, however, it's nearly the same. */
2688 if (TARGET_SEP_DATA)
2689 target_flags |= MASK_ID_SHARED_LIBRARY | MASK_LEAF_ID_SHARED_LIBRARY;
2691 if (TARGET_ID_SHARED_LIBRARY && flag_pic == 0)
2694 /* There is no single unaligned SI op for PIC code. Sometimes we
2695 need to use ".4byte" and sometimes we need to use ".picptr".
2696 See bfin_assemble_integer for details. */
2698 targetm.asm_out.unaligned_op.si = 0;
2700 /* Silently turn off flag_pic if not doing FDPIC or ID shared libraries,
2701 since we don't support it and it'll just break. */
2702 if (flag_pic && !TARGET_FDPIC && !TARGET_ID_SHARED_LIBRARY)
2705 if (TARGET_MULTICORE && bfin_cpu_type != BFIN_CPU_BF561)
2706 error ("-mmulticore can only be used with BF561");
2708 if (TARGET_COREA && !TARGET_MULTICORE)
2709 error ("-mcorea should be used with -mmulticore");
2711 if (TARGET_COREB && !TARGET_MULTICORE)
2712 error ("-mcoreb should be used with -mmulticore");
2714 if (TARGET_COREA && TARGET_COREB)
2715 error ("-mcorea and -mcoreb can't be used together");
2717 flag_schedule_insns = 0;
2719 /* Passes after sched2 can break the helpful TImode annotations that
2720 haifa-sched puts on every insn. Just do scheduling in reorg. */
2721 bfin_flag_schedule_insns2 = flag_schedule_insns_after_reload;
2722 flag_schedule_insns_after_reload = 0;
2724 init_machine_status = bfin_init_machine_status;
2727 /* Return the destination address of BRANCH.
2728 We need to use this instead of get_attr_length, because the
2729 cbranch_with_nops pattern conservatively sets its length to 6, and
2730 we still prefer to use shorter sequences. */
2733 branch_dest (rtx branch)
2737 rtx pat = PATTERN (branch);
2738 if (GET_CODE (pat) == PARALLEL)
2739 pat = XVECEXP (pat, 0, 0);
2740 dest = SET_SRC (pat);
2741 if (GET_CODE (dest) == IF_THEN_ELSE)
2742 dest = XEXP (dest, 1);
2743 dest = XEXP (dest, 0);
2744 dest_uid = INSN_UID (dest);
2745 return INSN_ADDRESSES (dest_uid);
2748 /* Return nonzero if INSN is annotated with a REG_BR_PROB note that indicates
2749 it's a branch that's predicted taken. */
2752 cbranch_predicted_taken_p (rtx insn)
2754 rtx x = find_reg_note (insn, REG_BR_PROB, 0);
2758 int pred_val = INTVAL (XEXP (x, 0));
2760 return pred_val >= REG_BR_PROB_BASE / 2;
2766 /* Templates for use by asm_conditional_branch. */
2768 static const char *ccbranch_templates[][3] = {
2769 { "if !cc jump %3;", "if cc jump 4 (bp); jump.s %3;", "if cc jump 6 (bp); jump.l %3;" },
2770 { "if cc jump %3;", "if !cc jump 4 (bp); jump.s %3;", "if !cc jump 6 (bp); jump.l %3;" },
2771 { "if !cc jump %3 (bp);", "if cc jump 4; jump.s %3;", "if cc jump 6; jump.l %3;" },
2772 { "if cc jump %3 (bp);", "if !cc jump 4; jump.s %3;", "if !cc jump 6; jump.l %3;" },
2775 /* Output INSN, which is a conditional branch instruction with operands
2778 We deal with the various forms of conditional branches that can be generated
2779 by bfin_reorg to prevent the hardware from doing speculative loads, by
2780 - emitting a sufficient number of nops, if N_NOPS is nonzero, or
2781 - always emitting the branch as predicted taken, if PREDICT_TAKEN is true.
2782 Either of these is only necessary if the branch is short, otherwise the
2783 template we use ends in an unconditional jump which flushes the pipeline
2787 asm_conditional_branch (rtx insn, rtx *operands, int n_nops, int predict_taken)
2789 int offset = branch_dest (insn) - INSN_ADDRESSES (INSN_UID (insn));
2790 /* Note : offset for instructions like if cc jmp; jump.[sl] offset
2791 is to be taken from start of if cc rather than jump.
2792 Range for jump.s is (-4094, 4096) instead of (-4096, 4094)
2794 int len = (offset >= -1024 && offset <= 1022 ? 0
2795 : offset >= -4094 && offset <= 4096 ? 1
2797 int bp = predict_taken && len == 0 ? 1 : cbranch_predicted_taken_p (insn);
2798 int idx = (bp << 1) | (GET_CODE (operands[0]) == EQ ? BRF : BRT);
2799 output_asm_insn (ccbranch_templates[idx][len], operands);
2800 gcc_assert (n_nops == 0 || !bp);
2802 while (n_nops-- > 0)
2803 output_asm_insn ("nop;", NULL);
2806 /* Emit rtl for a comparison operation CMP in mode MODE. Operands have been
2807 stored in bfin_compare_op0 and bfin_compare_op1 already. */
2810 bfin_gen_compare (rtx cmp, enum machine_mode mode ATTRIBUTE_UNUSED)
2812 enum rtx_code code1, code2;
2813 rtx op0 = XEXP (cmp, 0), op1 = XEXP (cmp, 1);
2814 rtx tem = bfin_cc_rtx;
2815 enum rtx_code code = GET_CODE (cmp);
2817 /* If we have a BImode input, then we already have a compare result, and
2818 do not need to emit another comparison. */
2819 if (GET_MODE (op0) == BImode)
2821 gcc_assert ((code == NE || code == EQ) && op1 == const0_rtx);
2822 tem = op0, code2 = code;
2827 /* bfin has these conditions */
2837 code1 = reverse_condition (code);
2841 emit_insn (gen_rtx_SET (VOIDmode, tem,
2842 gen_rtx_fmt_ee (code1, BImode, op0, op1)));
2845 return gen_rtx_fmt_ee (code2, BImode, tem, CONST0_RTX (BImode));
2848 /* Return nonzero iff C has exactly one bit set if it is interpreted
2849 as a 32-bit constant. */
2852 log2constp (unsigned HOST_WIDE_INT c)
2855 return c != 0 && (c & (c-1)) == 0;
2858 /* Returns the number of consecutive least significant zeros in the binary
2859 representation of *V.
2860 We modify *V to contain the original value arithmetically shifted right by
2861 the number of zeroes. */
2864 shiftr_zero (HOST_WIDE_INT *v)
2866 unsigned HOST_WIDE_INT tmp = *v;
2867 unsigned HOST_WIDE_INT sgn;
2873 sgn = tmp & ((unsigned HOST_WIDE_INT) 1 << (HOST_BITS_PER_WIDE_INT - 1));
2874 while ((tmp & 0x1) == 0 && n <= 32)
2876 tmp = (tmp >> 1) | sgn;
2883 /* After reload, split the load of an immediate constant. OPERANDS are the
2884 operands of the movsi_insn pattern which we are splitting. We return
2885 nonzero if we emitted a sequence to load the constant, zero if we emitted
2886 nothing because we want to use the splitter's default sequence. */
2889 split_load_immediate (rtx operands[])
2891 HOST_WIDE_INT val = INTVAL (operands[1]);
2893 HOST_WIDE_INT shifted = val;
2894 HOST_WIDE_INT shifted_compl = ~val;
2895 int num_zero = shiftr_zero (&shifted);
2896 int num_compl_zero = shiftr_zero (&shifted_compl);
2897 unsigned int regno = REGNO (operands[0]);
2899 /* This case takes care of single-bit set/clear constants, which we could
2900 also implement with BITSET/BITCLR. */
2902 && shifted >= -32768 && shifted < 65536
2903 && (D_REGNO_P (regno)
2904 || (regno >= REG_P0 && regno <= REG_P7 && num_zero <= 2)))
2906 emit_insn (gen_movsi (operands[0], GEN_INT (shifted)));
2907 emit_insn (gen_ashlsi3 (operands[0], operands[0], GEN_INT (num_zero)));
2912 tmp |= -(tmp & 0x8000);
2914 /* If high word has one bit set or clear, try to use a bit operation. */
2915 if (D_REGNO_P (regno))
2917 if (log2constp (val & 0xFFFF0000))
2919 emit_insn (gen_movsi (operands[0], GEN_INT (val & 0xFFFF)));
2920 emit_insn (gen_iorsi3 (operands[0], operands[0], GEN_INT (val & 0xFFFF0000)));
2923 else if (log2constp (val | 0xFFFF) && (val & 0x8000) != 0)
2925 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2926 emit_insn (gen_andsi3 (operands[0], operands[0], GEN_INT (val | 0xFFFF)));
2930 if (D_REGNO_P (regno))
2932 if (tmp >= -64 && tmp <= 63)
2934 emit_insn (gen_movsi (operands[0], GEN_INT (tmp)));
2935 emit_insn (gen_movstricthi_high (operands[0], GEN_INT (val & -65536)));
2939 if ((val & 0xFFFF0000) == 0)
2941 emit_insn (gen_movsi (operands[0], const0_rtx));
2942 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2946 if ((val & 0xFFFF0000) == 0xFFFF0000)
2948 emit_insn (gen_movsi (operands[0], constm1_rtx));
2949 emit_insn (gen_movsi_low (operands[0], operands[0], operands[1]));
2954 /* Need DREGs for the remaining case. */
2959 && num_compl_zero && shifted_compl >= -64 && shifted_compl <= 63)
2961 /* If optimizing for size, generate a sequence that has more instructions
2963 emit_insn (gen_movsi (operands[0], GEN_INT (shifted_compl)));
2964 emit_insn (gen_ashlsi3 (operands[0], operands[0],
2965 GEN_INT (num_compl_zero)));
2966 emit_insn (gen_one_cmplsi2 (operands[0], operands[0]));
2972 /* Return true if the legitimate memory address for a memory operand of mode
2973 MODE. Return false if not. */
2976 bfin_valid_add (enum machine_mode mode, HOST_WIDE_INT value)
2978 unsigned HOST_WIDE_INT v = value > 0 ? value : -value;
2979 int sz = GET_MODE_SIZE (mode);
2980 int shift = sz == 1 ? 0 : sz == 2 ? 1 : 2;
2981 /* The usual offsettable_memref machinery doesn't work so well for this
2982 port, so we deal with the problem here. */
2983 if (value > 0 && sz == 8)
2985 return (v & ~(0x7fff << shift)) == 0;
2989 bfin_valid_reg_p (unsigned int regno, int strict, enum machine_mode mode,
2990 enum rtx_code outer_code)
2993 return REGNO_OK_FOR_BASE_STRICT_P (regno, mode, outer_code, SCRATCH);
2995 return REGNO_OK_FOR_BASE_NONSTRICT_P (regno, mode, outer_code, SCRATCH);
2998 /* Recognize an RTL expression that is a valid memory address for an
2999 instruction. The MODE argument is the machine mode for the MEM expression
3000 that wants to use this address.
3002 Blackfin addressing modes are as follows:
3008 W [ Preg + uimm16m2 ]
3017 bfin_legitimate_address_p (enum machine_mode mode, rtx x, bool strict)
3019 switch (GET_CODE (x)) {
3021 if (bfin_valid_reg_p (REGNO (x), strict, mode, MEM))
3025 if (REG_P (XEXP (x, 0))
3026 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PLUS)
3027 && ((GET_CODE (XEXP (x, 1)) == UNSPEC && mode == SImode)
3028 || (GET_CODE (XEXP (x, 1)) == CONST_INT
3029 && bfin_valid_add (mode, INTVAL (XEXP (x, 1))))))
3034 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
3035 && REG_P (XEXP (x, 0))
3036 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, POST_INC))
3039 if (LEGITIMATE_MODE_FOR_AUTOINC_P (mode)
3040 && XEXP (x, 0) == stack_pointer_rtx
3041 && REG_P (XEXP (x, 0))
3042 && bfin_valid_reg_p (REGNO (XEXP (x, 0)), strict, mode, PRE_DEC))
3051 /* Decide whether we can force certain constants to memory. If we
3052 decide we can't, the caller should be able to cope with it in
3056 bfin_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
3058 /* We have only one class of non-legitimate constants, and our movsi
3059 expander knows how to handle them. Dropping these constants into the
3060 data section would only shift the problem - we'd still get relocs
3061 outside the object, in the data section rather than the text section. */
3065 /* Ensure that for any constant of the form symbol + offset, the offset
3066 remains within the object. Any other constants are ok.
3067 This ensures that flat binaries never have to deal with relocations
3068 crossing section boundaries. */
3071 bfin_legitimate_constant_p (rtx x)
3074 HOST_WIDE_INT offset;
3076 if (GET_CODE (x) != CONST)
3080 gcc_assert (GET_CODE (x) == PLUS);
3084 if (GET_CODE (sym) != SYMBOL_REF
3085 || GET_CODE (x) != CONST_INT)
3087 offset = INTVAL (x);
3089 if (SYMBOL_REF_DECL (sym) == 0)
3092 || offset >= int_size_in_bytes (TREE_TYPE (SYMBOL_REF_DECL (sym))))
3099 bfin_rtx_costs (rtx x, int code, int outer_code, int *total, bool speed)
3101 int cost2 = COSTS_N_INSNS (1);
3107 if (outer_code == SET || outer_code == PLUS)
3108 *total = satisfies_constraint_Ks7 (x) ? 0 : cost2;
3109 else if (outer_code == AND)
3110 *total = log2constp (~INTVAL (x)) ? 0 : cost2;
3111 else if (outer_code == LE || outer_code == LT || outer_code == EQ)
3112 *total = (INTVAL (x) >= -4 && INTVAL (x) <= 3) ? 0 : cost2;
3113 else if (outer_code == LEU || outer_code == LTU)
3114 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 7) ? 0 : cost2;
3115 else if (outer_code == MULT)
3116 *total = (INTVAL (x) == 2 || INTVAL (x) == 4) ? 0 : cost2;
3117 else if (outer_code == ASHIFT && (INTVAL (x) == 1 || INTVAL (x) == 2))
3119 else if (outer_code == ASHIFT || outer_code == ASHIFTRT
3120 || outer_code == LSHIFTRT)
3121 *total = (INTVAL (x) >= 0 && INTVAL (x) <= 31) ? 0 : cost2;
3122 else if (outer_code == IOR || outer_code == XOR)
3123 *total = (INTVAL (x) & (INTVAL (x) - 1)) == 0 ? 0 : cost2;
3132 *total = COSTS_N_INSNS (2);
3138 if (GET_MODE (x) == SImode)
3140 if (GET_CODE (op0) == MULT
3141 && GET_CODE (XEXP (op0, 1)) == CONST_INT)
3143 HOST_WIDE_INT val = INTVAL (XEXP (op0, 1));
3144 if (val == 2 || val == 4)
3147 *total += rtx_cost (XEXP (op0, 0), outer_code, speed);
3148 *total += rtx_cost (op1, outer_code, speed);
3153 if (GET_CODE (op0) != REG
3154 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3155 *total += rtx_cost (op0, SET, speed);
3156 #if 0 /* We'd like to do this for accuracy, but it biases the loop optimizer
3157 towards creating too many induction variables. */
3158 if (!reg_or_7bit_operand (op1, SImode))
3159 *total += rtx_cost (op1, SET, speed);
3162 else if (GET_MODE (x) == DImode)
3165 if (GET_CODE (op1) != CONST_INT
3166 || !satisfies_constraint_Ks7 (op1))
3167 *total += rtx_cost (op1, PLUS, speed);
3168 if (GET_CODE (op0) != REG
3169 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3170 *total += rtx_cost (op0, PLUS, speed);
3175 if (GET_MODE (x) == DImode)
3184 if (GET_MODE (x) == DImode)
3191 if (GET_CODE (op0) != REG
3192 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3193 *total += rtx_cost (op0, code, speed);
3203 /* Handle special cases of IOR: rotates, ALIGN insns, movstricthi_high. */
3206 if ((GET_CODE (op0) == LSHIFTRT && GET_CODE (op1) == ASHIFT)
3207 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == ZERO_EXTEND)
3208 || (GET_CODE (op0) == ASHIFT && GET_CODE (op1) == LSHIFTRT)
3209 || (GET_CODE (op0) == AND && GET_CODE (op1) == CONST_INT))
3216 if (GET_CODE (op0) != REG
3217 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3218 *total += rtx_cost (op0, code, speed);
3220 if (GET_MODE (x) == DImode)
3226 if (GET_MODE (x) != SImode)
3231 if (! rhs_andsi3_operand (XEXP (x, 1), SImode))
3232 *total += rtx_cost (XEXP (x, 1), code, speed);
3236 if (! regorlog2_operand (XEXP (x, 1), SImode))
3237 *total += rtx_cost (XEXP (x, 1), code, speed);
3244 if (outer_code == SET
3245 && XEXP (x, 1) == const1_rtx
3246 && GET_CODE (XEXP (x, 2)) == CONST_INT)
3262 if (GET_CODE (op0) == GET_CODE (op1)
3263 && (GET_CODE (op0) == ZERO_EXTEND
3264 || GET_CODE (op0) == SIGN_EXTEND))
3266 *total = COSTS_N_INSNS (1);
3267 op0 = XEXP (op0, 0);
3268 op1 = XEXP (op1, 0);
3271 *total = COSTS_N_INSNS (1);
3273 *total = COSTS_N_INSNS (3);
3275 if (GET_CODE (op0) != REG
3276 && (GET_CODE (op0) != SUBREG || GET_CODE (SUBREG_REG (op0)) != REG))
3277 *total += rtx_cost (op0, MULT, speed);
3278 if (GET_CODE (op1) != REG
3279 && (GET_CODE (op1) != SUBREG || GET_CODE (SUBREG_REG (op1)) != REG))
3280 *total += rtx_cost (op1, MULT, speed);
3286 *total = COSTS_N_INSNS (32);
3291 if (outer_code == SET)
3300 /* Used for communication between {push,pop}_multiple_operation (which
3301 we use not only as a predicate) and the corresponding output functions. */
3302 static int first_preg_to_save, first_dreg_to_save;
3303 static int n_regs_to_save;
3306 push_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
3308 int lastdreg = 8, lastpreg = 6;
3311 first_preg_to_save = lastpreg;
3312 first_dreg_to_save = lastdreg;
3313 for (i = 1, group = 0; i < XVECLEN (op, 0) - 1; i++)
3315 rtx t = XVECEXP (op, 0, i);
3319 if (GET_CODE (t) != SET)
3323 dest = SET_DEST (t);
3324 if (GET_CODE (dest) != MEM || ! REG_P (src))
3326 dest = XEXP (dest, 0);
3327 if (GET_CODE (dest) != PLUS
3328 || ! REG_P (XEXP (dest, 0))
3329 || REGNO (XEXP (dest, 0)) != REG_SP
3330 || GET_CODE (XEXP (dest, 1)) != CONST_INT
3331 || INTVAL (XEXP (dest, 1)) != -i * 4)
3334 regno = REGNO (src);
3337 if (D_REGNO_P (regno))
3340 first_dreg_to_save = lastdreg = regno - REG_R0;
3342 else if (regno >= REG_P0 && regno <= REG_P7)
3345 first_preg_to_save = lastpreg = regno - REG_P0;
3355 if (regno >= REG_P0 && regno <= REG_P7)
3358 first_preg_to_save = lastpreg = regno - REG_P0;
3360 else if (regno != REG_R0 + lastdreg + 1)
3365 else if (group == 2)
3367 if (regno != REG_P0 + lastpreg + 1)
3372 n_regs_to_save = 8 - first_dreg_to_save + 6 - first_preg_to_save;
3377 pop_multiple_operation (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
3379 int lastdreg = 8, lastpreg = 6;
3382 for (i = 1, group = 0; i < XVECLEN (op, 0); i++)
3384 rtx t = XVECEXP (op, 0, i);
3388 if (GET_CODE (t) != SET)
3392 dest = SET_DEST (t);
3393 if (GET_CODE (src) != MEM || ! REG_P (dest))
3395 src = XEXP (src, 0);
3399 if (! REG_P (src) || REGNO (src) != REG_SP)
3402 else if (GET_CODE (src) != PLUS
3403 || ! REG_P (XEXP (src, 0))
3404 || REGNO (XEXP (src, 0)) != REG_SP
3405 || GET_CODE (XEXP (src, 1)) != CONST_INT
3406 || INTVAL (XEXP (src, 1)) != (i - 1) * 4)
3409 regno = REGNO (dest);
3412 if (regno == REG_R7)
3417 else if (regno != REG_P0 + lastpreg - 1)
3422 else if (group == 1)
3424 if (regno != REG_R0 + lastdreg - 1)
3430 first_dreg_to_save = lastdreg;
3431 first_preg_to_save = lastpreg;
3432 n_regs_to_save = 8 - first_dreg_to_save + 6 - first_preg_to_save;
3436 /* Emit assembly code for one multi-register push described by INSN, with
3437 operands in OPERANDS. */
3440 output_push_multiple (rtx insn, rtx *operands)
3445 /* Validate the insn again, and compute first_[dp]reg_to_save. */
3446 ok = push_multiple_operation (PATTERN (insn), VOIDmode);
3449 if (first_dreg_to_save == 8)
3450 sprintf (buf, "[--sp] = ( p5:%d );\n", first_preg_to_save);
3451 else if (first_preg_to_save == 6)
3452 sprintf (buf, "[--sp] = ( r7:%d );\n", first_dreg_to_save);
3454 sprintf (buf, "[--sp] = ( r7:%d, p5:%d );\n",
3455 first_dreg_to_save, first_preg_to_save);
3457 output_asm_insn (buf, operands);
3460 /* Emit assembly code for one multi-register pop described by INSN, with
3461 operands in OPERANDS. */
3464 output_pop_multiple (rtx insn, rtx *operands)
3469 /* Validate the insn again, and compute first_[dp]reg_to_save. */
3470 ok = pop_multiple_operation (PATTERN (insn), VOIDmode);
3473 if (first_dreg_to_save == 8)
3474 sprintf (buf, "( p5:%d ) = [sp++];\n", first_preg_to_save);
3475 else if (first_preg_to_save == 6)
3476 sprintf (buf, "( r7:%d ) = [sp++];\n", first_dreg_to_save);
3478 sprintf (buf, "( r7:%d, p5:%d ) = [sp++];\n",
3479 first_dreg_to_save, first_preg_to_save);
3481 output_asm_insn (buf, operands);
3484 /* Adjust DST and SRC by OFFSET bytes, and generate one move in mode MODE. */
3487 single_move_for_movmem (rtx dst, rtx src, enum machine_mode mode, HOST_WIDE_INT offset)
3489 rtx scratch = gen_reg_rtx (mode);
3492 srcmem = adjust_address_nv (src, mode, offset);
3493 dstmem = adjust_address_nv (dst, mode, offset);
3494 emit_move_insn (scratch, srcmem);
3495 emit_move_insn (dstmem, scratch);
3498 /* Expand a string move operation of COUNT_EXP bytes from SRC to DST, with
3499 alignment ALIGN_EXP. Return true if successful, false if we should fall
3500 back on a different method. */
3503 bfin_expand_movmem (rtx dst, rtx src, rtx count_exp, rtx align_exp)
3505 rtx srcreg, destreg, countreg;
3506 HOST_WIDE_INT align = 0;
3507 unsigned HOST_WIDE_INT count = 0;
3509 if (GET_CODE (align_exp) == CONST_INT)
3510 align = INTVAL (align_exp);
3511 if (GET_CODE (count_exp) == CONST_INT)
3513 count = INTVAL (count_exp);
3515 if (!TARGET_INLINE_ALL_STRINGOPS && count > 64)
3520 /* If optimizing for size, only do single copies inline. */
3523 if (count == 2 && align < 2)
3525 if (count == 4 && align < 4)
3527 if (count != 1 && count != 2 && count != 4)
3530 if (align < 2 && count != 1)
3533 destreg = copy_to_mode_reg (Pmode, XEXP (dst, 0));
3534 if (destreg != XEXP (dst, 0))
3535 dst = replace_equiv_address_nv (dst, destreg);
3536 srcreg = copy_to_mode_reg (Pmode, XEXP (src, 0));
3537 if (srcreg != XEXP (src, 0))
3538 src = replace_equiv_address_nv (src, srcreg);
3540 if (count != 0 && align >= 2)
3542 unsigned HOST_WIDE_INT offset = 0;
3546 if ((count & ~3) == 4)
3548 single_move_for_movmem (dst, src, SImode, offset);
3551 else if (count & ~3)
3553 HOST_WIDE_INT new_count = ((count >> 2) & 0x3fffffff) - 1;
3554 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3556 emit_insn (gen_rep_movsi (destreg, srcreg, countreg, destreg, srcreg));
3557 cfun->machine->has_loopreg_clobber = true;
3561 single_move_for_movmem (dst, src, HImode, offset);
3567 if ((count & ~1) == 2)
3569 single_move_for_movmem (dst, src, HImode, offset);
3572 else if (count & ~1)
3574 HOST_WIDE_INT new_count = ((count >> 1) & 0x7fffffff) - 1;
3575 countreg = copy_to_mode_reg (Pmode, GEN_INT (new_count));
3577 emit_insn (gen_rep_movhi (destreg, srcreg, countreg, destreg, srcreg));
3578 cfun->machine->has_loopreg_clobber = true;
3583 single_move_for_movmem (dst, src, QImode, offset);
3590 /* Compute the alignment for a local variable.
3591 TYPE is the data type, and ALIGN is the alignment that
3592 the object would ordinarily have. The value of this macro is used
3593 instead of that alignment to align the object. */
3596 bfin_local_alignment (tree type, int align)
3598 /* Increasing alignment for (relatively) big types allows the builtin
3599 memcpy can use 32 bit loads/stores. */
3600 if (TYPE_SIZE (type)
3601 && TREE_CODE (TYPE_SIZE (type)) == INTEGER_CST
3602 && (TREE_INT_CST_LOW (TYPE_SIZE (type)) > 8
3603 || TREE_INT_CST_HIGH (TYPE_SIZE (type))) && align < 32)
3608 /* Implement TARGET_SCHED_ISSUE_RATE. */
3611 bfin_issue_rate (void)
3617 bfin_adjust_cost (rtx insn, rtx link, rtx dep_insn, int cost)
3619 enum attr_type insn_type, dep_insn_type;
3620 int dep_insn_code_number;
3622 /* Anti and output dependencies have zero cost. */
3623 if (REG_NOTE_KIND (link) != 0)
3626 dep_insn_code_number = recog_memoized (dep_insn);
3628 /* If we can't recognize the insns, we can't really do anything. */
3629 if (dep_insn_code_number < 0 || recog_memoized (insn) < 0)
3632 insn_type = get_attr_type (insn);
3633 dep_insn_type = get_attr_type (dep_insn);
3635 if (dep_insn_type == TYPE_MOVE || dep_insn_type == TYPE_MCLD)
3637 rtx pat = PATTERN (dep_insn);
3638 if (GET_CODE (pat) == PARALLEL)
3639 pat = XVECEXP (pat, 0, 0);
3640 rtx dest = SET_DEST (pat);
3641 rtx src = SET_SRC (pat);
3642 if (! ADDRESS_REGNO_P (REGNO (dest))
3643 || ! (MEM_P (src) || D_REGNO_P (REGNO (src))))
3645 return cost + (dep_insn_type == TYPE_MOVE ? 4 : 3);
3651 /* This function acts like NEXT_INSN, but is aware of three-insn bundles and
3652 skips all subsequent parallel instructions if INSN is the start of such
3655 find_next_insn_start (rtx insn)
3657 if (GET_MODE (insn) == SImode)
3659 while (GET_MODE (insn) != QImode)
3660 insn = NEXT_INSN (insn);
3662 return NEXT_INSN (insn);
3665 /* This function acts like PREV_INSN, but is aware of three-insn bundles and
3666 skips all subsequent parallel instructions if INSN is the start of such
3669 find_prev_insn_start (rtx insn)
3671 insn = PREV_INSN (insn);
3672 gcc_assert (GET_MODE (insn) != SImode);
3673 if (GET_MODE (insn) == QImode)
3675 while (GET_MODE (PREV_INSN (insn)) == SImode)
3676 insn = PREV_INSN (insn);
3681 /* Increment the counter for the number of loop instructions in the
3682 current function. */
3685 bfin_hardware_loop (void)
3687 cfun->machine->has_hardware_loops++;
3690 /* Maximum loop nesting depth. */
3691 #define MAX_LOOP_DEPTH 2
3693 /* Maximum size of a loop. */
3694 #define MAX_LOOP_LENGTH 2042
3696 /* Maximum distance of the LSETUP instruction from the loop start. */
3697 #define MAX_LSETUP_DISTANCE 30
3699 /* We need to keep a vector of loops */
3700 typedef struct loop_info *loop_info;
3701 DEF_VEC_P (loop_info);
3702 DEF_VEC_ALLOC_P (loop_info,heap);
3704 /* Information about a loop we have found (or are in the process of
3706 struct GTY (()) loop_info
3708 /* loop number, for dumps */
3711 /* All edges that jump into and out of the loop. */
3712 VEC(edge,gc) *incoming;
3714 /* We can handle two cases: all incoming edges have the same destination
3715 block, or all incoming edges have the same source block. These two
3716 members are set to the common source or destination we found, or NULL
3717 if different blocks were found. If both are NULL the loop can't be
3719 basic_block incoming_src;
3720 basic_block incoming_dest;
3722 /* First block in the loop. This is the one branched to by the loop_end
3726 /* Last block in the loop (the one with the loop_end insn). */
3729 /* The successor block of the loop. This is the one the loop_end insn
3731 basic_block successor;
3733 /* The last instruction in the tail. */
3736 /* The loop_end insn. */
3739 /* The iteration register. */
3742 /* The new label placed at the beginning of the loop. */
3745 /* The new label placed at the end of the loop. */
3748 /* The length of the loop. */
3751 /* The nesting depth of the loop. */
3754 /* Nonzero if we can't optimize this loop. */
3757 /* True if we have visited this loop. */
3760 /* True if this loop body clobbers any of LC0, LT0, or LB0. */
3763 /* True if this loop body clobbers any of LC1, LT1, or LB1. */
3766 /* Next loop in the graph. */
3767 struct loop_info *next;
3769 /* Immediate outer loop of this loop. */
3770 struct loop_info *outer;
3772 /* Vector of blocks only within the loop, including those within
3774 VEC (basic_block,heap) *blocks;
3776 /* Same information in a bitmap. */
3777 bitmap block_bitmap;
3779 /* Vector of inner loops within this loop */
3780 VEC (loop_info,heap) *loops;
3784 bfin_dump_loops (loop_info loops)
3788 for (loop = loops; loop; loop = loop->next)
3794 fprintf (dump_file, ";; loop %d: ", loop->loop_no);
3796 fprintf (dump_file, "(bad) ");
3797 fprintf (dump_file, "{head:%d, depth:%d}", loop->head->index, loop->depth);
3799 fprintf (dump_file, " blocks: [ ");
3800 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, b); ix++)
3801 fprintf (dump_file, "%d ", b->index);
3802 fprintf (dump_file, "] ");
3804 fprintf (dump_file, " inner loops: [ ");
3805 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, i); ix++)
3806 fprintf (dump_file, "%d ", i->loop_no);
3807 fprintf (dump_file, "]\n");
3809 fprintf (dump_file, "\n");
3812 /* Scan the blocks of LOOP (and its inferiors) looking for basic block
3813 BB. Return true, if we find it. */
3816 bfin_bb_in_loop (loop_info loop, basic_block bb)
3818 return bitmap_bit_p (loop->block_bitmap, bb->index);
3821 /* Scan the blocks of LOOP (and its inferiors) looking for uses of
3822 REG. Return true, if we find any. Don't count the loop's loop_end
3823 insn if it matches LOOP_END. */
3826 bfin_scan_loop (loop_info loop, rtx reg, rtx loop_end)
3831 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
3835 for (insn = BB_HEAD (bb);
3836 insn != NEXT_INSN (BB_END (bb));
3837 insn = NEXT_INSN (insn))
3841 if (insn == loop_end)
3843 if (reg_mentioned_p (reg, PATTERN (insn)))
3850 /* Estimate the length of INSN conservatively. */
3853 length_for_loop (rtx insn)
3856 if (JUMP_P (insn) && any_condjump_p (insn) && !optimize_size)
3858 if (ENABLE_WA_SPECULATIVE_SYNCS)
3860 else if (ENABLE_WA_SPECULATIVE_LOADS)
3863 else if (LABEL_P (insn))
3865 if (ENABLE_WA_SPECULATIVE_SYNCS)
3869 if (NONDEBUG_INSN_P (insn))
3870 length += get_attr_length (insn);
3875 /* Optimize LOOP. */
3878 bfin_optimize_loop (loop_info loop)
3882 rtx insn, last_insn;
3883 rtx loop_init, start_label, end_label;
3884 rtx reg_lc0, reg_lc1, reg_lt0, reg_lt1, reg_lb0, reg_lb1;
3885 rtx iter_reg, scratchreg, scratch_init, scratch_init_insn;
3886 rtx lc_reg, lt_reg, lb_reg;
3890 int inner_depth = 0;
3900 fprintf (dump_file, ";; loop %d bad when found\n", loop->loop_no);
3904 /* Every loop contains in its list of inner loops every loop nested inside
3905 it, even if there are intermediate loops. This works because we're doing
3906 a depth-first search here and never visit a loop more than once. */
3907 for (ix = 0; VEC_iterate (loop_info, loop->loops, ix, inner); ix++)
3909 bfin_optimize_loop (inner);
3911 if (!inner->bad && inner_depth < inner->depth)
3913 inner_depth = inner->depth;
3915 loop->clobber_loop0 |= inner->clobber_loop0;
3916 loop->clobber_loop1 |= inner->clobber_loop1;
3920 loop->depth = inner_depth + 1;
3921 if (loop->depth > MAX_LOOP_DEPTH)
3924 fprintf (dump_file, ";; loop %d too deep\n", loop->loop_no);
3928 /* Get the loop iteration register. */
3929 iter_reg = loop->iter_reg;
3931 if (!REG_P (iter_reg))
3934 fprintf (dump_file, ";; loop %d iteration count not in a register\n",
3938 scratchreg = NULL_RTX;
3939 scratch_init = iter_reg;
3940 scratch_init_insn = NULL_RTX;
3941 if (!PREG_P (iter_reg) && loop->incoming_src)
3943 basic_block bb_in = loop->incoming_src;
3945 for (i = REG_P0; i <= REG_P5; i++)
3946 if ((df_regs_ever_live_p (i)
3947 || (funkind (TREE_TYPE (current_function_decl)) == SUBROUTINE
3948 && call_used_regs[i]))
3949 && !REGNO_REG_SET_P (df_get_live_out (bb_in), i))
3951 scratchreg = gen_rtx_REG (SImode, i);
3954 for (insn = BB_END (bb_in); insn != BB_HEAD (bb_in);
3955 insn = PREV_INSN (insn))
3958 if (NOTE_P (insn) || BARRIER_P (insn))
3960 set = single_set (insn);
3961 if (set && rtx_equal_p (SET_DEST (set), iter_reg))
3963 if (CONSTANT_P (SET_SRC (set)))
3965 scratch_init = SET_SRC (set);
3966 scratch_init_insn = insn;
3970 else if (reg_mentioned_p (iter_reg, PATTERN (insn)))
3975 if (loop->incoming_src)
3977 /* Make sure the predecessor is before the loop start label, as required by
3978 the LSETUP instruction. */
3980 insn = BB_END (loop->incoming_src);
3981 /* If we have to insert the LSETUP before a jump, count that jump in the
3983 if (VEC_length (edge, loop->incoming) > 1
3984 || !(VEC_last (edge, loop->incoming)->flags & EDGE_FALLTHRU))
3986 gcc_assert (JUMP_P (insn));
3987 insn = PREV_INSN (insn);
3990 for (; insn && insn != loop->start_label; insn = NEXT_INSN (insn))
3991 length += length_for_loop (insn);
3996 fprintf (dump_file, ";; loop %d lsetup not before loop_start\n",
4001 /* Account for the pop of a scratch register where necessary. */
4002 if (!PREG_P (iter_reg) && scratchreg == NULL_RTX
4003 && ENABLE_WA_LOAD_LCREGS)
4006 if (length > MAX_LSETUP_DISTANCE)
4009 fprintf (dump_file, ";; loop %d lsetup too far away\n", loop->loop_no);
4014 /* Check if start_label appears before loop_end and calculate the
4015 offset between them. We calculate the length of instructions
4018 for (insn = loop->start_label;
4019 insn && insn != loop->loop_end;
4020 insn = NEXT_INSN (insn))
4021 length += length_for_loop (insn);
4026 fprintf (dump_file, ";; loop %d start_label not before loop_end\n",
4031 loop->length = length;
4032 if (loop->length > MAX_LOOP_LENGTH)
4035 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
4039 /* Scan all the blocks to make sure they don't use iter_reg. */
4040 if (bfin_scan_loop (loop, iter_reg, loop->loop_end))
4043 fprintf (dump_file, ";; loop %d uses iterator\n", loop->loop_no);
4047 /* Scan all the insns to see if the loop body clobber
4048 any hardware loop registers. */
4050 reg_lc0 = gen_rtx_REG (SImode, REG_LC0);
4051 reg_lc1 = gen_rtx_REG (SImode, REG_LC1);
4052 reg_lt0 = gen_rtx_REG (SImode, REG_LT0);
4053 reg_lt1 = gen_rtx_REG (SImode, REG_LT1);
4054 reg_lb0 = gen_rtx_REG (SImode, REG_LB0);
4055 reg_lb1 = gen_rtx_REG (SImode, REG_LB1);
4057 for (ix = 0; VEC_iterate (basic_block, loop->blocks, ix, bb); ix++)
4061 for (insn = BB_HEAD (bb);
4062 insn != NEXT_INSN (BB_END (bb));
4063 insn = NEXT_INSN (insn))
4068 if (reg_set_p (reg_lc0, insn)
4069 || reg_set_p (reg_lt0, insn)
4070 || reg_set_p (reg_lb0, insn))
4071 loop->clobber_loop0 = 1;
4073 if (reg_set_p (reg_lc1, insn)
4074 || reg_set_p (reg_lt1, insn)
4075 || reg_set_p (reg_lb1, insn))
4076 loop->clobber_loop1 |= 1;
4080 if ((loop->clobber_loop0 && loop->clobber_loop1)
4081 || (loop->depth == MAX_LOOP_DEPTH && loop->clobber_loop0))
4083 loop->depth = MAX_LOOP_DEPTH + 1;
4085 fprintf (dump_file, ";; loop %d no loop reg available\n",
4090 /* There should be an instruction before the loop_end instruction
4091 in the same basic block. And the instruction must not be
4093 - CONDITIONAL BRANCH
4097 - Returns (RTS, RTN, etc.) */
4100 last_insn = find_prev_insn_start (loop->loop_end);
4104 for (; last_insn != BB_HEAD (bb);
4105 last_insn = find_prev_insn_start (last_insn))
4106 if (NONDEBUG_INSN_P (last_insn))
4109 if (last_insn != BB_HEAD (bb))
4112 if (single_pred_p (bb)
4113 && single_pred_edge (bb)->flags & EDGE_FALLTHRU
4114 && single_pred (bb) != ENTRY_BLOCK_PTR)
4116 bb = single_pred (bb);
4117 last_insn = BB_END (bb);
4122 last_insn = NULL_RTX;
4130 fprintf (dump_file, ";; loop %d has no last instruction\n",
4135 if (JUMP_P (last_insn) && !any_condjump_p (last_insn))
4138 fprintf (dump_file, ";; loop %d has bad last instruction\n",
4142 /* In all other cases, try to replace a bad last insn with a nop. */
4143 else if (JUMP_P (last_insn)
4144 || CALL_P (last_insn)
4145 || get_attr_type (last_insn) == TYPE_SYNC
4146 || get_attr_type (last_insn) == TYPE_CALL
4147 || get_attr_seq_insns (last_insn) == SEQ_INSNS_MULTI
4148 || recog_memoized (last_insn) == CODE_FOR_return_internal
4149 || GET_CODE (PATTERN (last_insn)) == ASM_INPUT
4150 || asm_noperands (PATTERN (last_insn)) >= 0)
4152 if (loop->length + 2 > MAX_LOOP_LENGTH)
4155 fprintf (dump_file, ";; loop %d too long\n", loop->loop_no);
4159 fprintf (dump_file, ";; loop %d has bad last insn; replace with nop\n",
4162 last_insn = emit_insn_after (gen_forced_nop (), last_insn);
4165 loop->last_insn = last_insn;
4167 /* The loop is good for replacement. */
4168 start_label = loop->start_label;
4169 end_label = gen_label_rtx ();
4170 iter_reg = loop->iter_reg;
4172 if (loop->depth == 1 && !loop->clobber_loop1)
4177 loop->clobber_loop1 = 1;
4184 loop->clobber_loop0 = 1;
4187 loop->end_label = end_label;
4189 /* Create a sequence containing the loop setup. */
4192 /* LSETUP only accepts P registers. If we have one, we can use it,
4193 otherwise there are several ways of working around the problem.
4194 If we're not affected by anomaly 312, we can load the LC register
4195 from any iteration register, and use LSETUP without initialization.
4196 If we've found a P scratch register that's not live here, we can
4197 instead copy the iter_reg into that and use an initializing LSETUP.
4198 If all else fails, push and pop P0 and use it as a scratch. */
4199 if (P_REGNO_P (REGNO (iter_reg)))
4201 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
4204 seq_end = emit_insn (loop_init);
4206 else if (!ENABLE_WA_LOAD_LCREGS && DPREG_P (iter_reg))
4208 emit_insn (gen_movsi (lc_reg, iter_reg));
4209 loop_init = gen_lsetup_without_autoinit (lt_reg, start_label,
4212 seq_end = emit_insn (loop_init);
4214 else if (scratchreg != NULL_RTX)
4216 emit_insn (gen_movsi (scratchreg, scratch_init));
4217 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
4219 lc_reg, scratchreg);
4220 seq_end = emit_insn (loop_init);
4221 if (scratch_init_insn != NULL_RTX)
4222 delete_insn (scratch_init_insn);
4226 rtx p0reg = gen_rtx_REG (SImode, REG_P0);
4227 rtx push = gen_frame_mem (SImode,
4228 gen_rtx_PRE_DEC (SImode, stack_pointer_rtx));
4229 rtx pop = gen_frame_mem (SImode,
4230 gen_rtx_POST_INC (SImode, stack_pointer_rtx));
4231 emit_insn (gen_movsi (push, p0reg));
4232 emit_insn (gen_movsi (p0reg, scratch_init));
4233 loop_init = gen_lsetup_with_autoinit (lt_reg, start_label,
4236 emit_insn (loop_init);
4237 seq_end = emit_insn (gen_movsi (p0reg, pop));
4238 if (scratch_init_insn != NULL_RTX)
4239 delete_insn (scratch_init_insn);
4244 fprintf (dump_file, ";; replacing loop %d initializer with\n",
4246 print_rtl_single (dump_file, loop_init);
4247 fprintf (dump_file, ";; replacing loop %d terminator with\n",
4249 print_rtl_single (dump_file, loop->loop_end);
4252 /* If the loop isn't entered at the top, also create a jump to the entry
4254 if (!loop->incoming_src && loop->head != loop->incoming_dest)
4256 rtx label = BB_HEAD (loop->incoming_dest);
4257 /* If we're jumping to the final basic block in the loop, and there's
4258 only one cheap instruction before the end (typically an increment of
4259 an induction variable), we can just emit a copy here instead of a
4261 if (loop->incoming_dest == loop->tail
4262 && next_real_insn (label) == last_insn
4263 && asm_noperands (last_insn) < 0
4264 && GET_CODE (PATTERN (last_insn)) == SET)
4266 seq_end = emit_insn (copy_rtx (PATTERN (last_insn)));
4270 emit_jump_insn (gen_jump (label));
4271 seq_end = emit_barrier ();
4278 if (loop->incoming_src)
4280 rtx prev = BB_END (loop->incoming_src);
4281 if (VEC_length (edge, loop->incoming) > 1
4282 || !(VEC_last (edge, loop->incoming)->flags & EDGE_FALLTHRU))
4284 gcc_assert (JUMP_P (prev));
4285 prev = PREV_INSN (prev);
4287 emit_insn_after (seq, prev);
4295 #ifdef ENABLE_CHECKING
4296 if (loop->head != loop->incoming_dest)
4298 /* We aren't entering the loop at the top. Since we've established
4299 that the loop is entered only at one point, this means there
4300 can't be fallthru edges into the head. Any such fallthru edges
4301 would become invalid when we insert the new block, so verify
4302 that this does not in fact happen. */
4303 FOR_EACH_EDGE (e, ei, loop->head->preds)
4304 gcc_assert (!(e->flags & EDGE_FALLTHRU));
4308 emit_insn_before (seq, BB_HEAD (loop->head));
4309 seq = emit_label_before (gen_label_rtx (), seq);
4311 new_bb = create_basic_block (seq, seq_end, loop->head->prev_bb);
4312 FOR_EACH_EDGE (e, ei, loop->incoming)
4314 if (!(e->flags & EDGE_FALLTHRU)
4315 || e->dest != loop->head)
4316 redirect_edge_and_branch_force (e, new_bb);
4318 redirect_edge_succ (e, new_bb);
4320 e = make_edge (new_bb, loop->head, 0);
4323 delete_insn (loop->loop_end);
4324 /* Insert the loop end label before the last instruction of the loop. */
4325 emit_label_before (loop->end_label, loop->last_insn);
4332 fprintf (dump_file, ";; loop %d is bad\n", loop->loop_no);
4336 if (DPREG_P (loop->iter_reg))
4338 /* If loop->iter_reg is a DREG or PREG, we can split it here
4339 without scratch register. */
4342 emit_insn_before (gen_addsi3 (loop->iter_reg,
4347 test = gen_rtx_NE (VOIDmode, loop->iter_reg, const0_rtx);
4348 insn = emit_jump_insn_before (gen_cbranchsi4 (test,
4349 loop->iter_reg, const0_rtx,
4353 JUMP_LABEL (insn) = loop->start_label;
4354 LABEL_NUSES (loop->start_label)++;
4355 delete_insn (loop->loop_end);
4359 /* Called from bfin_reorg_loops when a potential loop end is found. LOOP is
4360 a newly set up structure describing the loop, it is this function's
4361 responsibility to fill most of it. TAIL_BB and TAIL_INSN point to the
4362 loop_end insn and its enclosing basic block. */
4365 bfin_discover_loop (loop_info loop, basic_block tail_bb, rtx tail_insn)
4369 VEC (basic_block,heap) *works = VEC_alloc (basic_block,heap,20);
4371 loop->tail = tail_bb;
4372 loop->head = BRANCH_EDGE (tail_bb)->dest;
4373 loop->successor = FALLTHRU_EDGE (tail_bb)->dest;
4374 loop->loop_end = tail_insn;
4375 loop->last_insn = NULL_RTX;
4376 loop->iter_reg = SET_DEST (XVECEXP (PATTERN (tail_insn), 0, 1));
4377 loop->depth = loop->length = 0;
4379 loop->clobber_loop0 = loop->clobber_loop1 = 0;
4382 loop->incoming = VEC_alloc (edge, gc, 2);
4383 loop->start_label = XEXP (XEXP (SET_SRC (XVECEXP (PATTERN (tail_insn), 0, 0)), 1), 0);
4384 loop->end_label = NULL_RTX;
4387 VEC_safe_push (basic_block, heap, works, loop->head);
4389 while (VEC_iterate (basic_block, works, dwork++, bb))
4393 if (bb == EXIT_BLOCK_PTR)
4395 /* We've reached the exit block. The loop must be bad. */
4398 ";; Loop is bad - reached exit block while scanning\n");
4403 if (bitmap_bit_p (loop->block_bitmap, bb->index))
4406 /* We've not seen this block before. Add it to the loop's
4407 list and then add each successor to the work list. */
4409 VEC_safe_push (basic_block, heap, loop->blocks, bb);
4410 bitmap_set_bit (loop->block_bitmap, bb->index);
4414 FOR_EACH_EDGE (e, ei, bb->succs)
4416 basic_block succ = EDGE_SUCC (bb, ei.index)->dest;
4417 if (!REGNO_REG_SET_P (df_get_live_in (succ),
4418 REGNO (loop->iter_reg)))
4420 if (!VEC_space (basic_block, works, 1))
4424 VEC_block_remove (basic_block, works, 0, dwork);
4428 VEC_reserve (basic_block, heap, works, 1);
4430 VEC_quick_push (basic_block, works, succ);
4435 /* Find the predecessor, and make sure nothing else jumps into this loop. */
4439 for (dwork = 0; VEC_iterate (basic_block, loop->blocks, dwork, bb); dwork++)
4443 FOR_EACH_EDGE (e, ei, bb->preds)
4445 basic_block pred = e->src;
4447 if (!bfin_bb_in_loop (loop, pred))
4450 fprintf (dump_file, ";; Loop %d: incoming edge %d -> %d\n",
4451 loop->loop_no, pred->index,
4453 VEC_safe_push (edge, gc, loop->incoming, e);
4458 for (pass = 0, retry = 1; retry && pass < 2; pass++)
4465 FOR_EACH_EDGE (e, ei, loop->incoming)
4469 loop->incoming_src = e->src;
4470 loop->incoming_dest = e->dest;
4475 if (e->dest != loop->incoming_dest)
4476 loop->incoming_dest = NULL;
4477 if (e->src != loop->incoming_src)
4478 loop->incoming_src = NULL;
4480 if (loop->incoming_src == NULL && loop->incoming_dest == NULL)
4486 ";; retrying loop %d with forwarder blocks\n",
4494 ";; can't find suitable entry for loop %d\n",
4502 FOR_EACH_EDGE (e, ei, loop->incoming)
4504 if (forwarder_block_p (e->src))
4511 ";; Adding forwarder block %d to loop %d and retrying\n",
4512 e->src->index, loop->loop_no);
4513 VEC_safe_push (basic_block, heap, loop->blocks, e->src);
4514 bitmap_set_bit (loop->block_bitmap, e->src->index);
4515 FOR_EACH_EDGE (e2, ei2, e->src->preds)
4516 VEC_safe_push (edge, gc, loop->incoming, e2);
4517 VEC_unordered_remove (edge, loop->incoming, ei.index);
4525 fprintf (dump_file, ";; No forwarder blocks found\n");
4533 VEC_free (basic_block, heap, works);
4536 /* Analyze the structure of the loops in the current function. Use STACK
4537 for bitmap allocations. Returns all the valid candidates for hardware
4538 loops found in this function. */
4540 bfin_discover_loops (bitmap_obstack *stack, FILE *dump_file)
4542 loop_info loops = NULL;
4548 /* Find all the possible loop tails. This means searching for every
4549 loop_end instruction. For each one found, create a loop_info
4550 structure and add the head block to the work list. */
4553 rtx tail = BB_END (bb);
4555 while (GET_CODE (tail) == NOTE)
4556 tail = PREV_INSN (tail);
4560 if (INSN_P (tail) && recog_memoized (tail) == CODE_FOR_loop_end)
4563 /* A possible loop end */
4565 /* There's a degenerate case we can handle - an empty loop consisting
4566 of only a back branch. Handle that by deleting the branch. */
4567 insn = BB_HEAD (BRANCH_EDGE (bb)->dest);
4568 if (next_real_insn (insn) == tail)
4572 fprintf (dump_file, ";; degenerate loop ending at\n");
4573 print_rtl_single (dump_file, tail);
4575 delete_insn_and_edges (tail);
4579 loop = XNEW (struct loop_info);
4582 loop->loop_no = nloops++;
4583 loop->blocks = VEC_alloc (basic_block, heap, 20);
4584 loop->block_bitmap = BITMAP_ALLOC (stack);
4589 fprintf (dump_file, ";; potential loop %d ending at\n",
4591 print_rtl_single (dump_file, tail);
4594 bfin_discover_loop (loop, bb, tail);
4598 tmp_bitmap = BITMAP_ALLOC (stack);
4599 /* Compute loop nestings. */
4600 for (loop = loops; loop; loop = loop->next)
4606 for (other = loop->next; other; other = other->next)
4611 bitmap_and (tmp_bitmap, other->block_bitmap, loop->block_bitmap);
4612 if (bitmap_empty_p (tmp_bitmap))
4614 if (bitmap_equal_p (tmp_bitmap, other->block_bitmap))
4616 other->outer = loop;
4617 VEC_safe_push (loop_info, heap, loop->loops, other);
4619 else if (bitmap_equal_p (tmp_bitmap, loop->block_bitmap))
4621 loop->outer = other;
4622 VEC_safe_push (loop_info, heap, other->loops, loop);
4628 ";; can't find suitable nesting for loops %d and %d\n",
4629 loop->loop_no, other->loop_no);
4630 loop->bad = other->bad = 1;
4634 BITMAP_FREE (tmp_bitmap);
4639 /* Free up the loop structures in LOOPS. */
4641 free_loops (loop_info loops)
4645 loop_info loop = loops;
4647 VEC_free (loop_info, heap, loop->loops);
4648 VEC_free (basic_block, heap, loop->blocks);
4649 BITMAP_FREE (loop->block_bitmap);
4654 #define BB_AUX_INDEX(BB) ((unsigned)(BB)->aux)
4656 /* The taken-branch edge from the loop end can actually go forward. Since the
4657 Blackfin's LSETUP instruction requires that the loop end be after the loop
4658 start, try to reorder a loop's basic blocks when we find such a case. */
4660 bfin_reorder_loops (loop_info loops, FILE *dump_file)
4667 cfg_layout_initialize (0);
4669 for (loop = loops; loop; loop = loop->next)
4679 /* Recreate an index for basic blocks that represents their order. */
4680 for (bb = ENTRY_BLOCK_PTR->next_bb, index = 0;
4681 bb != EXIT_BLOCK_PTR;
4682 bb = bb->next_bb, index++)
4683 bb->aux = (PTR) index;
4685 if (BB_AUX_INDEX (loop->head) < BB_AUX_INDEX (loop->tail))
4688 FOR_EACH_EDGE (e, ei, loop->head->succs)
4690 if (bitmap_bit_p (loop->block_bitmap, e->dest->index)
4691 && BB_AUX_INDEX (e->dest) < BB_AUX_INDEX (loop->tail))
4693 basic_block start_bb = e->dest;
4694 basic_block start_prev_bb = start_bb->prev_bb;
4697 fprintf (dump_file, ";; Moving block %d before block %d\n",
4698 loop->head->index, start_bb->index);
4699 loop->head->prev_bb->next_bb = loop->head->next_bb;
4700 loop->head->next_bb->prev_bb = loop->head->prev_bb;
4702 loop->head->prev_bb = start_prev_bb;
4703 loop->head->next_bb = start_bb;
4704 start_prev_bb->next_bb = start_bb->prev_bb = loop->head;
4708 loops = loops->next;
4713 if (bb->next_bb != EXIT_BLOCK_PTR)
4714 bb->aux = bb->next_bb;
4718 cfg_layout_finalize ();
4722 /* Run from machine_dependent_reorg, this pass looks for doloop_end insns
4723 and tries to rewrite the RTL of these loops so that proper Blackfin
4724 hardware loops are generated. */
4727 bfin_reorg_loops (FILE *dump_file)
4729 loop_info loops = NULL;
4732 bitmap_obstack stack;
4734 bitmap_obstack_initialize (&stack);
4737 fprintf (dump_file, ";; Find loops, first pass\n\n");
4739 loops = bfin_discover_loops (&stack, dump_file);
4742 bfin_dump_loops (loops);
4744 bfin_reorder_loops (loops, dump_file);
4748 fprintf (dump_file, ";; Find loops, second pass\n\n");
4750 loops = bfin_discover_loops (&stack, dump_file);
4753 fprintf (dump_file, ";; All loops found:\n\n");
4754 bfin_dump_loops (loops);
4757 /* Now apply the optimizations. */
4758 for (loop = loops; loop; loop = loop->next)
4759 bfin_optimize_loop (loop);
4763 fprintf (dump_file, ";; After hardware loops optimization:\n\n");
4764 bfin_dump_loops (loops);
4770 print_rtl (dump_file, get_insns ());
4775 splitting_loops = 1;
4778 rtx insn = BB_END (bb);
4782 try_split (PATTERN (insn), insn, 1);
4784 splitting_loops = 0;
4787 /* Possibly generate a SEQUENCE out of three insns found in SLOT.
4788 Returns true if we modified the insn chain, false otherwise. */
4790 gen_one_bundle (rtx slot[3])
4792 gcc_assert (slot[1] != NULL_RTX);
4794 /* Don't add extra NOPs if optimizing for size. */
4796 && (slot[0] == NULL_RTX || slot[2] == NULL_RTX))
4799 /* Verify that we really can do the multi-issue. */
4802 rtx t = NEXT_INSN (slot[0]);
4803 while (t != slot[1])
4805 if (GET_CODE (t) != NOTE
4806 || NOTE_KIND (t) != NOTE_INSN_DELETED)
4813 rtx t = NEXT_INSN (slot[1]);
4814 while (t != slot[2])
4816 if (GET_CODE (t) != NOTE
4817 || NOTE_KIND (t) != NOTE_INSN_DELETED)
4823 if (slot[0] == NULL_RTX)
4825 slot[0] = emit_insn_before (gen_mnop (), slot[1]);
4826 df_insn_rescan (slot[0]);
4828 if (slot[2] == NULL_RTX)
4830 slot[2] = emit_insn_after (gen_forced_nop (), slot[1]);
4831 df_insn_rescan (slot[2]);
4834 /* Avoid line number information being printed inside one bundle. */
4835 if (INSN_LOCATOR (slot[1])
4836 && INSN_LOCATOR (slot[1]) != INSN_LOCATOR (slot[0]))
4837 INSN_LOCATOR (slot[1]) = INSN_LOCATOR (slot[0]);
4838 if (INSN_LOCATOR (slot[2])
4839 && INSN_LOCATOR (slot[2]) != INSN_LOCATOR (slot[0]))
4840 INSN_LOCATOR (slot[2]) = INSN_LOCATOR (slot[0]);
4842 /* Terminate them with "|| " instead of ";" in the output. */
4843 PUT_MODE (slot[0], SImode);
4844 PUT_MODE (slot[1], SImode);
4845 /* Terminate the bundle, for the benefit of reorder_var_tracking_notes. */
4846 PUT_MODE (slot[2], QImode);
4850 /* Go through all insns, and use the information generated during scheduling
4851 to generate SEQUENCEs to represent bundles of instructions issued
4855 bfin_gen_bundles (void)
4864 slot[0] = slot[1] = slot[2] = NULL_RTX;
4865 for (insn = BB_HEAD (bb);; insn = next)
4868 rtx delete_this = NULL_RTX;
4870 if (NONDEBUG_INSN_P (insn))
4872 enum attr_type type = get_attr_type (insn);
4874 if (type == TYPE_STALL)
4876 gcc_assert (n_filled == 0);
4881 if (type == TYPE_DSP32 || type == TYPE_DSP32SHIFTIMM)
4883 else if (slot[1] == NULL_RTX)
4891 next = NEXT_INSN (insn);
4892 while (next && insn != BB_END (bb)
4894 && GET_CODE (PATTERN (next)) != USE
4895 && GET_CODE (PATTERN (next)) != CLOBBER))
4898 next = NEXT_INSN (insn);
4901 /* BB_END can change due to emitting extra NOPs, so check here. */
4902 at_end = insn == BB_END (bb);
4903 if (delete_this == NULL_RTX && (at_end || GET_MODE (next) == TImode))
4906 || !gen_one_bundle (slot))
4907 && slot[0] != NULL_RTX)
4909 rtx pat = PATTERN (slot[0]);
4910 if (GET_CODE (pat) == SET
4911 && GET_CODE (SET_SRC (pat)) == UNSPEC
4912 && XINT (SET_SRC (pat), 1) == UNSPEC_32BIT)
4914 SET_SRC (pat) = XVECEXP (SET_SRC (pat), 0, 0);
4915 INSN_CODE (slot[0]) = -1;
4916 df_insn_rescan (slot[0]);
4920 slot[0] = slot[1] = slot[2] = NULL_RTX;
4922 if (delete_this != NULL_RTX)
4923 delete_insn (delete_this);
4930 /* Ensure that no var tracking notes are emitted in the middle of a
4931 three-instruction bundle. */
4934 reorder_var_tracking_notes (void)
4940 rtx queue = NULL_RTX;
4941 bool in_bundle = false;
4943 for (insn = BB_HEAD (bb); insn != BB_END (bb); insn = next)
4945 next = NEXT_INSN (insn);
4949 /* Emit queued up notes at the last instruction of a bundle. */
4950 if (GET_MODE (insn) == QImode)
4954 rtx next_queue = PREV_INSN (queue);
4955 PREV_INSN (NEXT_INSN (insn)) = queue;
4956 NEXT_INSN (queue) = NEXT_INSN (insn);
4957 NEXT_INSN (insn) = queue;
4958 PREV_INSN (queue) = insn;
4963 else if (GET_MODE (insn) == SImode)
4966 else if (NOTE_P (insn) && NOTE_KIND (insn) == NOTE_INSN_VAR_LOCATION)
4970 rtx prev = PREV_INSN (insn);
4971 PREV_INSN (next) = prev;
4972 NEXT_INSN (prev) = next;
4974 PREV_INSN (insn) = queue;
4982 /* On some silicon revisions, functions shorter than a certain number of cycles
4983 can cause unpredictable behaviour. Work around this by adding NOPs as
4986 workaround_rts_anomaly (void)
4988 rtx insn, first_insn = NULL_RTX;
4991 if (! ENABLE_WA_RETS)
4994 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
4998 if (BARRIER_P (insn))
5001 if (NOTE_P (insn) || LABEL_P (insn))
5004 if (first_insn == NULL_RTX)
5006 pat = PATTERN (insn);
5007 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
5008 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
5009 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
5017 if (recog_memoized (insn) == CODE_FOR_return_internal)
5020 /* Nothing to worry about for direct jumps. */
5021 if (!any_condjump_p (insn))
5027 else if (INSN_P (insn))
5029 rtx pat = PATTERN (insn);
5030 int this_cycles = 1;
5032 if (GET_CODE (pat) == PARALLEL)
5034 if (push_multiple_operation (pat, VOIDmode)
5035 || pop_multiple_operation (pat, VOIDmode))
5036 this_cycles = n_regs_to_save;
5040 enum insn_code icode = recog_memoized (insn);
5041 if (icode == CODE_FOR_link)
5043 else if (icode == CODE_FOR_unlink)
5045 else if (icode == CODE_FOR_mulsi3)
5048 if (this_cycles >= cycles)
5051 cycles -= this_cycles;
5056 emit_insn_before (gen_nop (), first_insn);
5061 /* Return an insn type for INSN that can be used by the caller for anomaly
5062 workarounds. This differs from plain get_attr_type in that it handles
5065 static enum attr_type
5066 type_for_anomaly (rtx insn)
5068 rtx pat = PATTERN (insn);
5069 if (GET_CODE (pat) == SEQUENCE)
5072 t = get_attr_type (XVECEXP (pat, 0, 1));
5075 t = get_attr_type (XVECEXP (pat, 0, 2));
5081 return get_attr_type (insn);
5084 /* Return true iff the address found in MEM is based on the register
5085 NP_REG and optionally has a positive offset. */
5087 harmless_null_pointer_p (rtx mem, int np_reg)
5089 mem = XEXP (mem, 0);
5090 if (GET_CODE (mem) == POST_INC || GET_CODE (mem) == POST_DEC)
5091 mem = XEXP (mem, 0);
5092 if (REG_P (mem) && REGNO (mem) == np_reg)
5094 if (GET_CODE (mem) == PLUS
5095 && REG_P (XEXP (mem, 0)) && REGNO (XEXP (mem, 0)) == np_reg)
5097 mem = XEXP (mem, 1);
5098 if (GET_CODE (mem) == CONST_INT && INTVAL (mem) > 0)
5104 /* Return nonzero if INSN contains any loads that may trap. */
5107 trapping_loads_p (rtx insn, int np_reg, bool after_np_branch)
5109 rtx pat = PATTERN (insn);
5110 rtx mem = SET_SRC (single_set (insn));
5112 if (!after_np_branch)
5114 return ((np_reg == -1 || !harmless_null_pointer_p (mem, np_reg))
5115 && may_trap_p (mem));
5118 /* Return INSN if it is of TYPE_MCLD. Alternatively, if INSN is the start of
5119 a three-insn bundle, see if one of them is a load and return that if so.
5120 Return NULL_RTX if the insn does not contain loads. */
5122 find_load (rtx insn)
5124 if (!NONDEBUG_INSN_P (insn))
5126 if (get_attr_type (insn) == TYPE_MCLD)
5128 if (GET_MODE (insn) != SImode)
5131 insn = NEXT_INSN (insn);
5132 if ((GET_MODE (insn) == SImode || GET_MODE (insn) == QImode)
5133 && get_attr_type (insn) == TYPE_MCLD)
5135 } while (GET_MODE (insn) != QImode);
5139 /* Determine whether PAT is an indirect call pattern. */
5141 indirect_call_p (rtx pat)
5143 if (GET_CODE (pat) == PARALLEL)
5144 pat = XVECEXP (pat, 0, 0);
5145 if (GET_CODE (pat) == SET)
5146 pat = SET_SRC (pat);
5147 gcc_assert (GET_CODE (pat) == CALL);
5148 pat = XEXP (pat, 0);
5149 gcc_assert (GET_CODE (pat) == MEM);
5150 pat = XEXP (pat, 0);
5155 /* During workaround_speculation, track whether we're in the shadow of a
5156 conditional branch that tests a P register for NULL. If so, we can omit
5157 emitting NOPs if we see a load from that P register, since a speculative
5158 access at address 0 isn't a problem, and the load is executed in all other
5160 Global for communication with note_np_check_stores through note_stores.
5162 int np_check_regno = -1;
5163 bool np_after_branch = false;
5165 /* Subroutine of workaround_speculation, called through note_stores. */
5167 note_np_check_stores (rtx x, const_rtx pat, void *data ATTRIBUTE_UNUSED)
5169 if (REG_P (x) && (REGNO (x) == REG_CC || REGNO (x) == np_check_regno))
5170 np_check_regno = -1;
5174 workaround_speculation (void)
5177 rtx last_condjump = NULL_RTX;
5178 int cycles_since_jump = INT_MAX;
5179 int delay_added = 0;
5181 if (! ENABLE_WA_SPECULATIVE_LOADS && ! ENABLE_WA_SPECULATIVE_SYNCS
5182 && ! ENABLE_WA_INDIRECT_CALLS)
5185 /* First pass: find predicted-false branches; if something after them
5186 needs nops, insert them or change the branch to predict true. */
5187 for (insn = get_insns (); insn; insn = next)
5190 int delay_needed = 0;
5192 next = find_next_insn_start (insn);
5194 if (NOTE_P (insn) || BARRIER_P (insn))
5199 np_check_regno = -1;
5203 pat = PATTERN (insn);
5204 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
5205 || GET_CODE (pat) == ADDR_VEC || GET_CODE (pat) == ADDR_DIFF_VEC)
5208 if (GET_CODE (pat) == ASM_INPUT || asm_noperands (pat) >= 0)
5210 np_check_regno = -1;
5216 /* Is this a condjump based on a null pointer comparison we saw
5218 if (np_check_regno != -1
5219 && recog_memoized (insn) == CODE_FOR_cbranchbi4)
5221 rtx op = XEXP (SET_SRC (PATTERN (insn)), 0);
5222 gcc_assert (GET_CODE (op) == EQ || GET_CODE (op) == NE);
5223 if (GET_CODE (op) == NE)
5224 np_after_branch = true;
5226 if (any_condjump_p (insn)
5227 && ! cbranch_predicted_taken_p (insn))
5229 last_condjump = insn;
5231 cycles_since_jump = 0;
5234 cycles_since_jump = INT_MAX;
5236 else if (CALL_P (insn))
5238 np_check_regno = -1;
5239 if (cycles_since_jump < INT_MAX)
5240 cycles_since_jump++;
5241 if (indirect_call_p (pat) && ENABLE_WA_INDIRECT_CALLS)
5246 else if (NONDEBUG_INSN_P (insn))
5248 rtx load_insn = find_load (insn);
5249 enum attr_type type = type_for_anomaly (insn);
5251 if (cycles_since_jump < INT_MAX)
5252 cycles_since_jump++;
5254 /* Detect a comparison of a P register with zero. If we later
5255 see a condjump based on it, we have found a null pointer
5257 if (recog_memoized (insn) == CODE_FOR_compare_eq)
5259 rtx src = SET_SRC (PATTERN (insn));
5260 if (REG_P (XEXP (src, 0))
5261 && P_REGNO_P (REGNO (XEXP (src, 0)))
5262 && XEXP (src, 1) == const0_rtx)
5264 np_check_regno = REGNO (XEXP (src, 0));
5265 np_after_branch = false;
5268 np_check_regno = -1;
5271 if (load_insn && ENABLE_WA_SPECULATIVE_LOADS)
5273 if (trapping_loads_p (load_insn, np_check_regno,
5277 else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS)
5280 /* See if we need to forget about a null pointer comparison
5281 we found earlier. */
5282 if (recog_memoized (insn) != CODE_FOR_compare_eq)
5284 note_stores (PATTERN (insn), note_np_check_stores, NULL);
5285 if (np_check_regno != -1)
5287 if (find_regno_note (insn, REG_INC, np_check_regno))
5288 np_check_regno = -1;
5294 if (delay_needed > cycles_since_jump
5295 && (delay_needed - cycles_since_jump) > delay_added)
5299 rtx *op = recog_data.operand;
5301 delay_needed -= cycles_since_jump;
5303 extract_insn (last_condjump);
5306 pat1 = gen_cbranch_predicted_taken (op[0], op[1], op[2],
5308 cycles_since_jump = INT_MAX;
5312 /* Do not adjust cycles_since_jump in this case, so that
5313 we'll increase the number of NOPs for a subsequent insn
5315 pat1 = gen_cbranch_with_nops (op[0], op[1], op[2], op[3],
5316 GEN_INT (delay_needed));
5317 delay_added = delay_needed;
5319 PATTERN (last_condjump) = pat1;
5320 INSN_CODE (last_condjump) = recog (pat1, insn, &num_clobbers);
5324 cycles_since_jump = INT_MAX;
5329 /* Second pass: for predicted-true branches, see if anything at the
5330 branch destination needs extra nops. */
5331 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5333 int cycles_since_jump;
5335 && any_condjump_p (insn)
5336 && (INSN_CODE (insn) == CODE_FOR_cbranch_predicted_taken
5337 || cbranch_predicted_taken_p (insn)))
5339 rtx target = JUMP_LABEL (insn);
5343 cycles_since_jump = 0;
5344 for (; target && cycles_since_jump < 3; target = next_tgt)
5348 next_tgt = find_next_insn_start (target);
5350 if (NOTE_P (target) || BARRIER_P (target) || LABEL_P (target))
5353 pat = PATTERN (target);
5354 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
5355 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
5356 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
5359 if (NONDEBUG_INSN_P (target))
5361 rtx load_insn = find_load (target);
5362 enum attr_type type = type_for_anomaly (target);
5363 int delay_needed = 0;
5364 if (cycles_since_jump < INT_MAX)
5365 cycles_since_jump++;
5367 if (load_insn && ENABLE_WA_SPECULATIVE_LOADS)
5369 if (trapping_loads_p (load_insn, -1, false))
5372 else if (type == TYPE_SYNC && ENABLE_WA_SPECULATIVE_SYNCS)
5375 if (delay_needed > cycles_since_jump)
5377 rtx prev = prev_real_insn (label);
5378 delay_needed -= cycles_since_jump;
5380 fprintf (dump_file, "Adding %d nops after %d\n",
5381 delay_needed, INSN_UID (label));
5383 && INSN_CODE (prev) == CODE_FOR_cbranch_with_nops)
5390 "Reducing nops on insn %d.\n",
5393 x = XVECEXP (x, 0, 1);
5394 v = INTVAL (XVECEXP (x, 0, 0)) - delay_needed;
5395 XVECEXP (x, 0, 0) = GEN_INT (v);
5397 while (delay_needed-- > 0)
5398 emit_insn_after (gen_nop (), label);
5407 /* Called just before the final scheduling pass. If we need to insert NOPs
5408 later on to work around speculative loads, insert special placeholder
5409 insns that cause loads to be delayed for as many cycles as necessary
5410 (and possible). This reduces the number of NOPs we need to add.
5411 The dummy insns we generate are later removed by bfin_gen_bundles. */
5413 add_sched_insns_for_speculation (void)
5417 if (! ENABLE_WA_SPECULATIVE_LOADS && ! ENABLE_WA_SPECULATIVE_SYNCS
5418 && ! ENABLE_WA_INDIRECT_CALLS)
5421 /* First pass: find predicted-false branches; if something after them
5422 needs nops, insert them or change the branch to predict true. */
5423 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5427 if (NOTE_P (insn) || BARRIER_P (insn) || LABEL_P (insn))
5430 pat = PATTERN (insn);
5431 if (GET_CODE (pat) == USE || GET_CODE (pat) == CLOBBER
5432 || GET_CODE (pat) == ASM_INPUT || GET_CODE (pat) == ADDR_VEC
5433 || GET_CODE (pat) == ADDR_DIFF_VEC || asm_noperands (pat) >= 0)
5438 if (any_condjump_p (insn)
5439 && !cbranch_predicted_taken_p (insn))
5441 rtx n = next_real_insn (insn);
5442 emit_insn_before (gen_stall (GEN_INT (3)), n);
5447 /* Second pass: for predicted-true branches, see if anything at the
5448 branch destination needs extra nops. */
5449 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
5452 && any_condjump_p (insn)
5453 && (cbranch_predicted_taken_p (insn)))
5455 rtx target = JUMP_LABEL (insn);
5456 rtx next = next_real_insn (target);
5458 if (GET_CODE (PATTERN (next)) == UNSPEC_VOLATILE
5459 && get_attr_type (next) == TYPE_STALL)
5461 emit_insn_before (gen_stall (GEN_INT (1)), next);
5466 /* We use the machine specific reorg pass for emitting CSYNC instructions
5467 after conditional branches as needed.
5469 The Blackfin is unusual in that a code sequence like
5472 may speculatively perform the load even if the condition isn't true. This
5473 happens for a branch that is predicted not taken, because the pipeline
5474 isn't flushed or stalled, so the early stages of the following instructions,
5475 which perform the memory reference, are allowed to execute before the
5476 jump condition is evaluated.
5477 Therefore, we must insert additional instructions in all places where this
5478 could lead to incorrect behavior. The manual recommends CSYNC, while
5479 VDSP seems to use NOPs (even though its corresponding compiler option is
5482 When optimizing for speed, we emit NOPs, which seems faster than a CSYNC.
5483 When optimizing for size, we turn the branch into a predicted taken one.
5484 This may be slower due to mispredicts, but saves code size. */
5489 /* We are freeing block_for_insn in the toplev to keep compatibility
5490 with old MDEP_REORGS that are not CFG based. Recompute it now. */
5491 compute_bb_for_insn ();
5493 if (bfin_flag_schedule_insns2)
5495 splitting_for_sched = 1;
5497 splitting_for_sched = 0;
5499 add_sched_insns_for_speculation ();
5501 timevar_push (TV_SCHED2);
5502 if (flag_selective_scheduling2
5503 && !maybe_skip_selective_scheduling ())
5504 run_selective_scheduling ();
5507 timevar_pop (TV_SCHED2);
5509 /* Examine the schedule and insert nops as necessary for 64-bit parallel
5511 bfin_gen_bundles ();
5516 /* Doloop optimization */
5517 if (cfun->machine->has_hardware_loops)
5518 bfin_reorg_loops (dump_file);
5520 workaround_speculation ();
5522 if (bfin_flag_var_tracking)
5524 timevar_push (TV_VAR_TRACKING);
5525 variable_tracking_main ();
5526 reorder_var_tracking_notes ();
5527 timevar_pop (TV_VAR_TRACKING);
5530 df_finish_pass (false);
5532 workaround_rts_anomaly ();
5535 /* Handle interrupt_handler, exception_handler and nmi_handler function
5536 attributes; arguments as in struct attribute_spec.handler. */
5539 handle_int_attribute (tree *node, tree name,
5540 tree args ATTRIBUTE_UNUSED,
5541 int flags ATTRIBUTE_UNUSED,
5545 if (TREE_CODE (x) == FUNCTION_DECL)
5548 if (TREE_CODE (x) != FUNCTION_TYPE)
5550 warning (OPT_Wattributes, "%qE attribute only applies to functions",
5552 *no_add_attrs = true;
5554 else if (funkind (x) != SUBROUTINE)
5555 error ("multiple function type attributes specified");
5560 /* Return 0 if the attributes for two types are incompatible, 1 if they
5561 are compatible, and 2 if they are nearly compatible (which causes a
5562 warning to be generated). */
5565 bfin_comp_type_attributes (const_tree type1, const_tree type2)
5567 e_funkind kind1, kind2;
5569 if (TREE_CODE (type1) != FUNCTION_TYPE)
5572 kind1 = funkind (type1);
5573 kind2 = funkind (type2);
5578 /* Check for mismatched modifiers */
5579 if (!lookup_attribute ("nesting", TYPE_ATTRIBUTES (type1))
5580 != !lookup_attribute ("nesting", TYPE_ATTRIBUTES (type2)))
5583 if (!lookup_attribute ("saveall", TYPE_ATTRIBUTES (type1))
5584 != !lookup_attribute ("saveall", TYPE_ATTRIBUTES (type2)))
5587 if (!lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type1))
5588 != !lookup_attribute ("kspisusp", TYPE_ATTRIBUTES (type2)))
5591 if (!lookup_attribute ("longcall", TYPE_ATTRIBUTES (type1))
5592 != !lookup_attribute ("longcall", TYPE_ATTRIBUTES (type2)))
5598 /* Handle a "longcall" or "shortcall" attribute; arguments as in
5599 struct attribute_spec.handler. */
5602 bfin_handle_longcall_attribute (tree *node, tree name,
5603 tree args ATTRIBUTE_UNUSED,
5604 int flags ATTRIBUTE_UNUSED,
5607 if (TREE_CODE (*node) != FUNCTION_TYPE
5608 && TREE_CODE (*node) != FIELD_DECL
5609 && TREE_CODE (*node) != TYPE_DECL)
5611 warning (OPT_Wattributes, "%qE attribute only applies to functions",
5613 *no_add_attrs = true;
5616 if ((strcmp (IDENTIFIER_POINTER (name), "longcall") == 0
5617 && lookup_attribute ("shortcall", TYPE_ATTRIBUTES (*node)))
5618 || (strcmp (IDENTIFIER_POINTER (name), "shortcall") == 0
5619 && lookup_attribute ("longcall", TYPE_ATTRIBUTES (*node))))
5621 warning (OPT_Wattributes,
5622 "can't apply both longcall and shortcall attributes to the same function");
5623 *no_add_attrs = true;
5629 /* Handle a "l1_text" attribute; arguments as in
5630 struct attribute_spec.handler. */
5633 bfin_handle_l1_text_attribute (tree *node, tree name, tree ARG_UNUSED (args),
5634 int ARG_UNUSED (flags), bool *no_add_attrs)
5638 if (TREE_CODE (decl) != FUNCTION_DECL)
5640 error ("%qE attribute only applies to functions",
5642 *no_add_attrs = true;
5645 /* The decl may have already been given a section attribute
5646 from a previous declaration. Ensure they match. */
5647 else if (DECL_SECTION_NAME (decl) != NULL_TREE
5648 && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
5651 error ("section of %q+D conflicts with previous declaration",
5653 *no_add_attrs = true;
5656 DECL_SECTION_NAME (decl) = build_string (9, ".l1.text");
5661 /* Handle a "l1_data", "l1_data_A" or "l1_data_B" attribute;
5662 arguments as in struct attribute_spec.handler. */
5665 bfin_handle_l1_data_attribute (tree *node, tree name, tree ARG_UNUSED (args),
5666 int ARG_UNUSED (flags), bool *no_add_attrs)
5670 if (TREE_CODE (decl) != VAR_DECL)
5672 error ("%qE attribute only applies to variables",
5674 *no_add_attrs = true;
5676 else if (current_function_decl != NULL_TREE
5677 && !TREE_STATIC (decl))
5679 error ("%qE attribute cannot be specified for local variables",
5681 *no_add_attrs = true;
5685 const char *section_name;
5687 if (strcmp (IDENTIFIER_POINTER (name), "l1_data") == 0)
5688 section_name = ".l1.data";
5689 else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_A") == 0)
5690 section_name = ".l1.data.A";
5691 else if (strcmp (IDENTIFIER_POINTER (name), "l1_data_B") == 0)
5692 section_name = ".l1.data.B";
5696 /* The decl may have already been given a section attribute
5697 from a previous declaration. Ensure they match. */
5698 if (DECL_SECTION_NAME (decl) != NULL_TREE
5699 && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
5702 error ("section of %q+D conflicts with previous declaration",
5704 *no_add_attrs = true;
5707 DECL_SECTION_NAME (decl)
5708 = build_string (strlen (section_name) + 1, section_name);
5714 /* Handle a "l2" attribute; arguments as in struct attribute_spec.handler. */
5717 bfin_handle_l2_attribute (tree *node, tree ARG_UNUSED (name),
5718 tree ARG_UNUSED (args), int ARG_UNUSED (flags),
5723 if (TREE_CODE (decl) == FUNCTION_DECL)
5725 if (DECL_SECTION_NAME (decl) != NULL_TREE
5726 && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
5729 error ("section of %q+D conflicts with previous declaration",
5731 *no_add_attrs = true;
5734 DECL_SECTION_NAME (decl) = build_string (9, ".l2.text");
5736 else if (TREE_CODE (decl) == VAR_DECL)
5738 if (DECL_SECTION_NAME (decl) != NULL_TREE
5739 && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
5742 error ("section of %q+D conflicts with previous declaration",
5744 *no_add_attrs = true;
5747 DECL_SECTION_NAME (decl) = build_string (9, ".l2.data");
5753 /* Table of valid machine attributes. */
5754 static const struct attribute_spec bfin_attribute_table[] =
5756 /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
5757 { "interrupt_handler", 0, 0, false, true, true, handle_int_attribute },
5758 { "exception_handler", 0, 0, false, true, true, handle_int_attribute },
5759 { "nmi_handler", 0, 0, false, true, true, handle_int_attribute },
5760 { "nesting", 0, 0, false, true, true, NULL },
5761 { "kspisusp", 0, 0, false, true, true, NULL },
5762 { "saveall", 0, 0, false, true, true, NULL },
5763 { "longcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
5764 { "shortcall", 0, 0, false, true, true, bfin_handle_longcall_attribute },
5765 { "l1_text", 0, 0, true, false, false, bfin_handle_l1_text_attribute },
5766 { "l1_data", 0, 0, true, false, false, bfin_handle_l1_data_attribute },
5767 { "l1_data_A", 0, 0, true, false, false, bfin_handle_l1_data_attribute },
5768 { "l1_data_B", 0, 0, true, false, false, bfin_handle_l1_data_attribute },
5769 { "l2", 0, 0, true, false, false, bfin_handle_l2_attribute },
5770 { NULL, 0, 0, false, false, false, NULL }
5773 /* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to
5774 tell the assembler to generate pointers to function descriptors in
5778 bfin_assemble_integer (rtx value, unsigned int size, int aligned_p)
5780 if (TARGET_FDPIC && size == UNITS_PER_WORD)
5782 if (GET_CODE (value) == SYMBOL_REF
5783 && SYMBOL_REF_FUNCTION_P (value))
5785 fputs ("\t.picptr\tfuncdesc(", asm_out_file);
5786 output_addr_const (asm_out_file, value);
5787 fputs (")\n", asm_out_file);
5792 /* We've set the unaligned SI op to NULL, so we always have to
5793 handle the unaligned case here. */
5794 assemble_integer_with_op ("\t.4byte\t", value);
5798 return default_assemble_integer (value, size, aligned_p);
5801 /* Output the assembler code for a thunk function. THUNK_DECL is the
5802 declaration for the thunk function itself, FUNCTION is the decl for
5803 the target function. DELTA is an immediate constant offset to be
5804 added to THIS. If VCALL_OFFSET is nonzero, the word at
5805 *(*this + vcall_offset) should be added to THIS. */
5808 bfin_output_mi_thunk (FILE *file ATTRIBUTE_UNUSED,
5809 tree thunk ATTRIBUTE_UNUSED, HOST_WIDE_INT delta,
5810 HOST_WIDE_INT vcall_offset, tree function)
5813 /* The this parameter is passed as the first argument. */
5814 rtx this_rtx = gen_rtx_REG (Pmode, REG_R0);
5816 /* Adjust the this parameter by a fixed constant. */
5820 if (delta >= -64 && delta <= 63)
5822 xops[0] = GEN_INT (delta);
5823 output_asm_insn ("%1 += %0;", xops);
5825 else if (delta >= -128 && delta < -64)
5827 xops[0] = GEN_INT (delta + 64);
5828 output_asm_insn ("%1 += -64; %1 += %0;", xops);
5830 else if (delta > 63 && delta <= 126)
5832 xops[0] = GEN_INT (delta - 63);
5833 output_asm_insn ("%1 += 63; %1 += %0;", xops);
5837 xops[0] = GEN_INT (delta);
5838 output_asm_insn ("r3.l = %h0; r3.h = %d0; %1 = %1 + r3;", xops);
5842 /* Adjust the this parameter by a value stored in the vtable. */
5845 rtx p2tmp = gen_rtx_REG (Pmode, REG_P2);
5846 rtx tmp = gen_rtx_REG (Pmode, REG_R3);
5850 output_asm_insn ("%2 = r0; %2 = [%2];", xops);
5852 /* Adjust the this parameter. */
5853 xops[0] = gen_rtx_MEM (Pmode, plus_constant (p2tmp, vcall_offset));
5854 if (!memory_operand (xops[0], Pmode))
5856 rtx tmp2 = gen_rtx_REG (Pmode, REG_P1);
5857 xops[0] = GEN_INT (vcall_offset);
5859 output_asm_insn ("%h1 = %h0; %d1 = %d0; %2 = %2 + %1", xops);
5860 xops[0] = gen_rtx_MEM (Pmode, p2tmp);
5863 output_asm_insn ("%1 = %0; %2 = %2 + %1;", xops);
5866 xops[0] = XEXP (DECL_RTL (function), 0);
5867 if (1 || !flag_pic || (*targetm.binds_local_p) (function))
5868 output_asm_insn ("jump.l\t%P0", xops);
5871 /* Codes for all the Blackfin builtins. */
5877 BFIN_BUILTIN_COMPOSE_2X16,
5878 BFIN_BUILTIN_EXTRACTLO,
5879 BFIN_BUILTIN_EXTRACTHI,
5881 BFIN_BUILTIN_SSADD_2X16,
5882 BFIN_BUILTIN_SSSUB_2X16,
5883 BFIN_BUILTIN_SSADDSUB_2X16,
5884 BFIN_BUILTIN_SSSUBADD_2X16,
5885 BFIN_BUILTIN_MULT_2X16,
5886 BFIN_BUILTIN_MULTR_2X16,
5887 BFIN_BUILTIN_NEG_2X16,
5888 BFIN_BUILTIN_ABS_2X16,
5889 BFIN_BUILTIN_MIN_2X16,
5890 BFIN_BUILTIN_MAX_2X16,
5892 BFIN_BUILTIN_SSADD_1X16,
5893 BFIN_BUILTIN_SSSUB_1X16,
5894 BFIN_BUILTIN_MULT_1X16,
5895 BFIN_BUILTIN_MULTR_1X16,
5896 BFIN_BUILTIN_NORM_1X16,
5897 BFIN_BUILTIN_NEG_1X16,
5898 BFIN_BUILTIN_ABS_1X16,
5899 BFIN_BUILTIN_MIN_1X16,
5900 BFIN_BUILTIN_MAX_1X16,
5902 BFIN_BUILTIN_SUM_2X16,
5903 BFIN_BUILTIN_DIFFHL_2X16,
5904 BFIN_BUILTIN_DIFFLH_2X16,
5906 BFIN_BUILTIN_SSADD_1X32,
5907 BFIN_BUILTIN_SSSUB_1X32,
5908 BFIN_BUILTIN_NORM_1X32,
5909 BFIN_BUILTIN_ROUND_1X32,
5910 BFIN_BUILTIN_NEG_1X32,
5911 BFIN_BUILTIN_ABS_1X32,
5912 BFIN_BUILTIN_MIN_1X32,
5913 BFIN_BUILTIN_MAX_1X32,
5914 BFIN_BUILTIN_MULT_1X32,
5915 BFIN_BUILTIN_MULT_1X32X32,
5916 BFIN_BUILTIN_MULT_1X32X32NS,
5918 BFIN_BUILTIN_MULHISILL,
5919 BFIN_BUILTIN_MULHISILH,
5920 BFIN_BUILTIN_MULHISIHL,
5921 BFIN_BUILTIN_MULHISIHH,
5923 BFIN_BUILTIN_LSHIFT_1X16,
5924 BFIN_BUILTIN_LSHIFT_2X16,
5925 BFIN_BUILTIN_SSASHIFT_1X16,
5926 BFIN_BUILTIN_SSASHIFT_2X16,
5927 BFIN_BUILTIN_SSASHIFT_1X32,
5929 BFIN_BUILTIN_CPLX_MUL_16,
5930 BFIN_BUILTIN_CPLX_MAC_16,
5931 BFIN_BUILTIN_CPLX_MSU_16,
5933 BFIN_BUILTIN_CPLX_MUL_16_S40,
5934 BFIN_BUILTIN_CPLX_MAC_16_S40,
5935 BFIN_BUILTIN_CPLX_MSU_16_S40,
5937 BFIN_BUILTIN_CPLX_SQU,
5939 BFIN_BUILTIN_LOADBYTES,
5944 #define def_builtin(NAME, TYPE, CODE) \
5946 add_builtin_function ((NAME), (TYPE), (CODE), BUILT_IN_MD, \
5950 /* Set up all builtin functions for this target. */
5952 bfin_init_builtins (void)
5954 tree V2HI_type_node = build_vector_type_for_mode (intHI_type_node, V2HImode);
5955 tree void_ftype_void
5956 = build_function_type (void_type_node, void_list_node);
5957 tree short_ftype_short
5958 = build_function_type_list (short_integer_type_node, short_integer_type_node,
5960 tree short_ftype_int_int
5961 = build_function_type_list (short_integer_type_node, integer_type_node,
5962 integer_type_node, NULL_TREE);
5963 tree int_ftype_int_int
5964 = build_function_type_list (integer_type_node, integer_type_node,
5965 integer_type_node, NULL_TREE);
5967 = build_function_type_list (integer_type_node, integer_type_node,
5969 tree short_ftype_int
5970 = build_function_type_list (short_integer_type_node, integer_type_node,
5972 tree int_ftype_v2hi_v2hi
5973 = build_function_type_list (integer_type_node, V2HI_type_node,
5974 V2HI_type_node, NULL_TREE);
5975 tree v2hi_ftype_v2hi_v2hi
5976 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5977 V2HI_type_node, NULL_TREE);
5978 tree v2hi_ftype_v2hi_v2hi_v2hi
5979 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5980 V2HI_type_node, V2HI_type_node, NULL_TREE);
5981 tree v2hi_ftype_int_int
5982 = build_function_type_list (V2HI_type_node, integer_type_node,
5983 integer_type_node, NULL_TREE);
5984 tree v2hi_ftype_v2hi_int
5985 = build_function_type_list (V2HI_type_node, V2HI_type_node,
5986 integer_type_node, NULL_TREE);
5987 tree int_ftype_short_short
5988 = build_function_type_list (integer_type_node, short_integer_type_node,
5989 short_integer_type_node, NULL_TREE);
5990 tree v2hi_ftype_v2hi
5991 = build_function_type_list (V2HI_type_node, V2HI_type_node, NULL_TREE);
5992 tree short_ftype_v2hi
5993 = build_function_type_list (short_integer_type_node, V2HI_type_node,
5996 = build_function_type_list (integer_type_node,
5997 build_pointer_type (integer_type_node),
6000 /* Add the remaining MMX insns with somewhat more complicated types. */
6001 def_builtin ("__builtin_bfin_csync", void_ftype_void, BFIN_BUILTIN_CSYNC);
6002 def_builtin ("__builtin_bfin_ssync", void_ftype_void, BFIN_BUILTIN_SSYNC);
6004 def_builtin ("__builtin_bfin_ones", short_ftype_int, BFIN_BUILTIN_ONES);
6006 def_builtin ("__builtin_bfin_compose_2x16", v2hi_ftype_int_int,
6007 BFIN_BUILTIN_COMPOSE_2X16);
6008 def_builtin ("__builtin_bfin_extract_hi", short_ftype_v2hi,
6009 BFIN_BUILTIN_EXTRACTHI);
6010 def_builtin ("__builtin_bfin_extract_lo", short_ftype_v2hi,
6011 BFIN_BUILTIN_EXTRACTLO);
6013 def_builtin ("__builtin_bfin_min_fr2x16", v2hi_ftype_v2hi_v2hi,
6014 BFIN_BUILTIN_MIN_2X16);
6015 def_builtin ("__builtin_bfin_max_fr2x16", v2hi_ftype_v2hi_v2hi,
6016 BFIN_BUILTIN_MAX_2X16);
6018 def_builtin ("__builtin_bfin_add_fr2x16", v2hi_ftype_v2hi_v2hi,
6019 BFIN_BUILTIN_SSADD_2X16);
6020 def_builtin ("__builtin_bfin_sub_fr2x16", v2hi_ftype_v2hi_v2hi,
6021 BFIN_BUILTIN_SSSUB_2X16);
6022 def_builtin ("__builtin_bfin_dspaddsubsat", v2hi_ftype_v2hi_v2hi,
6023 BFIN_BUILTIN_SSADDSUB_2X16);
6024 def_builtin ("__builtin_bfin_dspsubaddsat", v2hi_ftype_v2hi_v2hi,
6025 BFIN_BUILTIN_SSSUBADD_2X16);
6026 def_builtin ("__builtin_bfin_mult_fr2x16", v2hi_ftype_v2hi_v2hi,
6027 BFIN_BUILTIN_MULT_2X16);
6028 def_builtin ("__builtin_bfin_multr_fr2x16", v2hi_ftype_v2hi_v2hi,
6029 BFIN_BUILTIN_MULTR_2X16);
6030 def_builtin ("__builtin_bfin_negate_fr2x16", v2hi_ftype_v2hi,
6031 BFIN_BUILTIN_NEG_2X16);
6032 def_builtin ("__builtin_bfin_abs_fr2x16", v2hi_ftype_v2hi,
6033 BFIN_BUILTIN_ABS_2X16);
6035 def_builtin ("__builtin_bfin_min_fr1x16", short_ftype_int_int,
6036 BFIN_BUILTIN_MIN_1X16);
6037 def_builtin ("__builtin_bfin_max_fr1x16", short_ftype_int_int,
6038 BFIN_BUILTIN_MAX_1X16);
6040 def_builtin ("__builtin_bfin_add_fr1x16", short_ftype_int_int,
6041 BFIN_BUILTIN_SSADD_1X16);
6042 def_builtin ("__builtin_bfin_sub_fr1x16", short_ftype_int_int,
6043 BFIN_BUILTIN_SSSUB_1X16);
6044 def_builtin ("__builtin_bfin_mult_fr1x16", short_ftype_int_int,
6045 BFIN_BUILTIN_MULT_1X16);
6046 def_builtin ("__builtin_bfin_multr_fr1x16", short_ftype_int_int,
6047 BFIN_BUILTIN_MULTR_1X16);
6048 def_builtin ("__builtin_bfin_negate_fr1x16", short_ftype_short,
6049 BFIN_BUILTIN_NEG_1X16);
6050 def_builtin ("__builtin_bfin_abs_fr1x16", short_ftype_short,
6051 BFIN_BUILTIN_ABS_1X16);
6052 def_builtin ("__builtin_bfin_norm_fr1x16", short_ftype_int,
6053 BFIN_BUILTIN_NORM_1X16);
6055 def_builtin ("__builtin_bfin_sum_fr2x16", short_ftype_v2hi,
6056 BFIN_BUILTIN_SUM_2X16);
6057 def_builtin ("__builtin_bfin_diff_hl_fr2x16", short_ftype_v2hi,
6058 BFIN_BUILTIN_DIFFHL_2X16);
6059 def_builtin ("__builtin_bfin_diff_lh_fr2x16", short_ftype_v2hi,
6060 BFIN_BUILTIN_DIFFLH_2X16);
6062 def_builtin ("__builtin_bfin_mulhisill", int_ftype_v2hi_v2hi,
6063 BFIN_BUILTIN_MULHISILL);
6064 def_builtin ("__builtin_bfin_mulhisihl", int_ftype_v2hi_v2hi,
6065 BFIN_BUILTIN_MULHISIHL);
6066 def_builtin ("__builtin_bfin_mulhisilh", int_ftype_v2hi_v2hi,
6067 BFIN_BUILTIN_MULHISILH);
6068 def_builtin ("__builtin_bfin_mulhisihh", int_ftype_v2hi_v2hi,
6069 BFIN_BUILTIN_MULHISIHH);
6071 def_builtin ("__builtin_bfin_min_fr1x32", int_ftype_int_int,
6072 BFIN_BUILTIN_MIN_1X32);
6073 def_builtin ("__builtin_bfin_max_fr1x32", int_ftype_int_int,
6074 BFIN_BUILTIN_MAX_1X32);
6076 def_builtin ("__builtin_bfin_add_fr1x32", int_ftype_int_int,
6077 BFIN_BUILTIN_SSADD_1X32);
6078 def_builtin ("__builtin_bfin_sub_fr1x32", int_ftype_int_int,
6079 BFIN_BUILTIN_SSSUB_1X32);
6080 def_builtin ("__builtin_bfin_negate_fr1x32", int_ftype_int,
6081 BFIN_BUILTIN_NEG_1X32);
6082 def_builtin ("__builtin_bfin_abs_fr1x32", int_ftype_int,
6083 BFIN_BUILTIN_ABS_1X32);
6084 def_builtin ("__builtin_bfin_norm_fr1x32", short_ftype_int,
6085 BFIN_BUILTIN_NORM_1X32);
6086 def_builtin ("__builtin_bfin_round_fr1x32", short_ftype_int,
6087 BFIN_BUILTIN_ROUND_1X32);
6088 def_builtin ("__builtin_bfin_mult_fr1x32", int_ftype_short_short,
6089 BFIN_BUILTIN_MULT_1X32);
6090 def_builtin ("__builtin_bfin_mult_fr1x32x32", int_ftype_int_int,
6091 BFIN_BUILTIN_MULT_1X32X32);
6092 def_builtin ("__builtin_bfin_mult_fr1x32x32NS", int_ftype_int_int,
6093 BFIN_BUILTIN_MULT_1X32X32NS);
6096 def_builtin ("__builtin_bfin_shl_fr1x16", short_ftype_int_int,
6097 BFIN_BUILTIN_SSASHIFT_1X16);
6098 def_builtin ("__builtin_bfin_shl_fr2x16", v2hi_ftype_v2hi_int,
6099 BFIN_BUILTIN_SSASHIFT_2X16);
6100 def_builtin ("__builtin_bfin_lshl_fr1x16", short_ftype_int_int,
6101 BFIN_BUILTIN_LSHIFT_1X16);
6102 def_builtin ("__builtin_bfin_lshl_fr2x16", v2hi_ftype_v2hi_int,
6103 BFIN_BUILTIN_LSHIFT_2X16);
6104 def_builtin ("__builtin_bfin_shl_fr1x32", int_ftype_int_int,
6105 BFIN_BUILTIN_SSASHIFT_1X32);
6107 /* Complex numbers. */
6108 def_builtin ("__builtin_bfin_cmplx_add", v2hi_ftype_v2hi_v2hi,
6109 BFIN_BUILTIN_SSADD_2X16);
6110 def_builtin ("__builtin_bfin_cmplx_sub", v2hi_ftype_v2hi_v2hi,
6111 BFIN_BUILTIN_SSSUB_2X16);
6112 def_builtin ("__builtin_bfin_cmplx_mul", v2hi_ftype_v2hi_v2hi,
6113 BFIN_BUILTIN_CPLX_MUL_16);
6114 def_builtin ("__builtin_bfin_cmplx_mac", v2hi_ftype_v2hi_v2hi_v2hi,
6115 BFIN_BUILTIN_CPLX_MAC_16);
6116 def_builtin ("__builtin_bfin_cmplx_msu", v2hi_ftype_v2hi_v2hi_v2hi,
6117 BFIN_BUILTIN_CPLX_MSU_16);
6118 def_builtin ("__builtin_bfin_cmplx_mul_s40", v2hi_ftype_v2hi_v2hi,
6119 BFIN_BUILTIN_CPLX_MUL_16_S40);
6120 def_builtin ("__builtin_bfin_cmplx_mac_s40", v2hi_ftype_v2hi_v2hi_v2hi,
6121 BFIN_BUILTIN_CPLX_MAC_16_S40);
6122 def_builtin ("__builtin_bfin_cmplx_msu_s40", v2hi_ftype_v2hi_v2hi_v2hi,
6123 BFIN_BUILTIN_CPLX_MSU_16_S40);
6124 def_builtin ("__builtin_bfin_csqu_fr16", v2hi_ftype_v2hi,
6125 BFIN_BUILTIN_CPLX_SQU);
6127 /* "Unaligned" load. */
6128 def_builtin ("__builtin_bfin_loadbytes", int_ftype_pint,
6129 BFIN_BUILTIN_LOADBYTES);
6134 struct builtin_description
6136 const enum insn_code icode;
6137 const char *const name;
6138 const enum bfin_builtins code;
6142 static const struct builtin_description bdesc_2arg[] =
6144 { CODE_FOR_composev2hi, "__builtin_bfin_compose_2x16", BFIN_BUILTIN_COMPOSE_2X16, -1 },
6146 { CODE_FOR_ssashiftv2hi3, "__builtin_bfin_shl_fr2x16", BFIN_BUILTIN_SSASHIFT_2X16, -1 },
6147 { CODE_FOR_ssashifthi3, "__builtin_bfin_shl_fr1x16", BFIN_BUILTIN_SSASHIFT_1X16, -1 },
6148 { CODE_FOR_lshiftv2hi3, "__builtin_bfin_lshl_fr2x16", BFIN_BUILTIN_LSHIFT_2X16, -1 },
6149 { CODE_FOR_lshifthi3, "__builtin_bfin_lshl_fr1x16", BFIN_BUILTIN_LSHIFT_1X16, -1 },
6150 { CODE_FOR_ssashiftsi3, "__builtin_bfin_shl_fr1x32", BFIN_BUILTIN_SSASHIFT_1X32, -1 },
6152 { CODE_FOR_sminhi3, "__builtin_bfin_min_fr1x16", BFIN_BUILTIN_MIN_1X16, -1 },
6153 { CODE_FOR_smaxhi3, "__builtin_bfin_max_fr1x16", BFIN_BUILTIN_MAX_1X16, -1 },
6154 { CODE_FOR_ssaddhi3, "__builtin_bfin_add_fr1x16", BFIN_BUILTIN_SSADD_1X16, -1 },
6155 { CODE_FOR_sssubhi3, "__builtin_bfin_sub_fr1x16", BFIN_BUILTIN_SSSUB_1X16, -1 },
6157 { CODE_FOR_sminsi3, "__builtin_bfin_min_fr1x32", BFIN_BUILTIN_MIN_1X32, -1 },
6158 { CODE_FOR_smaxsi3, "__builtin_bfin_max_fr1x32", BFIN_BUILTIN_MAX_1X32, -1 },
6159 { CODE_FOR_ssaddsi3, "__builtin_bfin_add_fr1x32", BFIN_BUILTIN_SSADD_1X32, -1 },
6160 { CODE_FOR_sssubsi3, "__builtin_bfin_sub_fr1x32", BFIN_BUILTIN_SSSUB_1X32, -1 },
6162 { CODE_FOR_sminv2hi3, "__builtin_bfin_min_fr2x16", BFIN_BUILTIN_MIN_2X16, -1 },
6163 { CODE_FOR_smaxv2hi3, "__builtin_bfin_max_fr2x16", BFIN_BUILTIN_MAX_2X16, -1 },
6164 { CODE_FOR_ssaddv2hi3, "__builtin_bfin_add_fr2x16", BFIN_BUILTIN_SSADD_2X16, -1 },
6165 { CODE_FOR_sssubv2hi3, "__builtin_bfin_sub_fr2x16", BFIN_BUILTIN_SSSUB_2X16, -1 },
6166 { CODE_FOR_ssaddsubv2hi3, "__builtin_bfin_dspaddsubsat", BFIN_BUILTIN_SSADDSUB_2X16, -1 },
6167 { CODE_FOR_sssubaddv2hi3, "__builtin_bfin_dspsubaddsat", BFIN_BUILTIN_SSSUBADD_2X16, -1 },
6169 { CODE_FOR_flag_mulhisi, "__builtin_bfin_mult_fr1x32", BFIN_BUILTIN_MULT_1X32, MACFLAG_NONE },
6170 { CODE_FOR_flag_mulhi, "__builtin_bfin_mult_fr1x16", BFIN_BUILTIN_MULT_1X16, MACFLAG_T },
6171 { CODE_FOR_flag_mulhi, "__builtin_bfin_multr_fr1x16", BFIN_BUILTIN_MULTR_1X16, MACFLAG_NONE },
6172 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_mult_fr2x16", BFIN_BUILTIN_MULT_2X16, MACFLAG_T },
6173 { CODE_FOR_flag_mulv2hi, "__builtin_bfin_multr_fr2x16", BFIN_BUILTIN_MULTR_2X16, MACFLAG_NONE },
6175 { CODE_FOR_mulhisi_ll, "__builtin_bfin_mulhisill", BFIN_BUILTIN_MULHISILL, -1 },
6176 { CODE_FOR_mulhisi_lh, "__builtin_bfin_mulhisilh", BFIN_BUILTIN_MULHISILH, -1 },
6177 { CODE_FOR_mulhisi_hl, "__builtin_bfin_mulhisihl", BFIN_BUILTIN_MULHISIHL, -1 },
6178 { CODE_FOR_mulhisi_hh, "__builtin_bfin_mulhisihh", BFIN_BUILTIN_MULHISIHH, -1 }
6182 static const struct builtin_description bdesc_1arg[] =
6184 { CODE_FOR_loadbytes, "__builtin_bfin_loadbytes", BFIN_BUILTIN_LOADBYTES, 0 },
6186 { CODE_FOR_ones, "__builtin_bfin_ones", BFIN_BUILTIN_ONES, 0 },
6188 { CODE_FOR_signbitshi2, "__builtin_bfin_norm_fr1x16", BFIN_BUILTIN_NORM_1X16, 0 },
6189 { CODE_FOR_ssneghi2, "__builtin_bfin_negate_fr1x16", BFIN_BUILTIN_NEG_1X16, 0 },
6190 { CODE_FOR_abshi2, "__builtin_bfin_abs_fr1x16", BFIN_BUILTIN_ABS_1X16, 0 },
6192 { CODE_FOR_signbitssi2, "__builtin_bfin_norm_fr1x32", BFIN_BUILTIN_NORM_1X32, 0 },
6193 { CODE_FOR_ssroundsi2, "__builtin_bfin_round_fr1x32", BFIN_BUILTIN_ROUND_1X32, 0 },
6194 { CODE_FOR_ssnegsi2, "__builtin_bfin_negate_fr1x32", BFIN_BUILTIN_NEG_1X32, 0 },
6195 { CODE_FOR_ssabssi2, "__builtin_bfin_abs_fr1x32", BFIN_BUILTIN_ABS_1X32, 0 },
6197 { CODE_FOR_movv2hi_hi_low, "__builtin_bfin_extract_lo", BFIN_BUILTIN_EXTRACTLO, 0 },
6198 { CODE_FOR_movv2hi_hi_high, "__builtin_bfin_extract_hi", BFIN_BUILTIN_EXTRACTHI, 0 },
6199 { CODE_FOR_ssnegv2hi2, "__builtin_bfin_negate_fr2x16", BFIN_BUILTIN_NEG_2X16, 0 },
6200 { CODE_FOR_ssabsv2hi2, "__builtin_bfin_abs_fr2x16", BFIN_BUILTIN_ABS_2X16, 0 }
6203 /* Errors in the source file can cause expand_expr to return const0_rtx
6204 where we expect a vector. To avoid crashing, use one of the vector
6205 clear instructions. */
6207 safe_vector_operand (rtx x, enum machine_mode mode)
6209 if (x != const0_rtx)
6211 x = gen_reg_rtx (SImode);
6213 emit_insn (gen_movsi (x, CONST0_RTX (SImode)));
6214 return gen_lowpart (mode, x);
6217 /* Subroutine of bfin_expand_builtin to take care of binop insns. MACFLAG is -1
6218 if this is a normal binary op, or one of the MACFLAG_xxx constants. */
6221 bfin_expand_binop_builtin (enum insn_code icode, tree exp, rtx target,
6225 tree arg0 = CALL_EXPR_ARG (exp, 0);
6226 tree arg1 = CALL_EXPR_ARG (exp, 1);
6227 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
6228 rtx op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
6229 enum machine_mode op0mode = GET_MODE (op0);
6230 enum machine_mode op1mode = GET_MODE (op1);
6231 enum machine_mode tmode = insn_data[icode].operand[0].mode;
6232 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
6233 enum machine_mode mode1 = insn_data[icode].operand[2].mode;
6235 if (VECTOR_MODE_P (mode0))
6236 op0 = safe_vector_operand (op0, mode0);
6237 if (VECTOR_MODE_P (mode1))
6238 op1 = safe_vector_operand (op1, mode1);
6241 || GET_MODE (target) != tmode
6242 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
6243 target = gen_reg_rtx (tmode);
6245 if ((op0mode == SImode || op0mode == VOIDmode) && mode0 == HImode)
6248 op0 = gen_lowpart (HImode, op0);
6250 if ((op1mode == SImode || op1mode == VOIDmode) && mode1 == HImode)
6253 op1 = gen_lowpart (HImode, op1);
6255 /* In case the insn wants input operands in modes different from
6256 the result, abort. */
6257 gcc_assert ((op0mode == mode0 || op0mode == VOIDmode)
6258 && (op1mode == mode1 || op1mode == VOIDmode));
6260 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6261 op0 = copy_to_mode_reg (mode0, op0);
6262 if (! (*insn_data[icode].operand[2].predicate) (op1, mode1))
6263 op1 = copy_to_mode_reg (mode1, op1);
6266 pat = GEN_FCN (icode) (target, op0, op1);
6268 pat = GEN_FCN (icode) (target, op0, op1, GEN_INT (macflag));
6276 /* Subroutine of bfin_expand_builtin to take care of unop insns. */
6279 bfin_expand_unop_builtin (enum insn_code icode, tree exp,
6283 tree arg0 = CALL_EXPR_ARG (exp, 0);
6284 rtx op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
6285 enum machine_mode op0mode = GET_MODE (op0);
6286 enum machine_mode tmode = insn_data[icode].operand[0].mode;
6287 enum machine_mode mode0 = insn_data[icode].operand[1].mode;
6290 || GET_MODE (target) != tmode
6291 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
6292 target = gen_reg_rtx (tmode);
6294 if (VECTOR_MODE_P (mode0))
6295 op0 = safe_vector_operand (op0, mode0);
6297 if (op0mode == SImode && mode0 == HImode)
6300 op0 = gen_lowpart (HImode, op0);
6302 gcc_assert (op0mode == mode0 || op0mode == VOIDmode);
6304 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6305 op0 = copy_to_mode_reg (mode0, op0);
6307 pat = GEN_FCN (icode) (target, op0);
6314 /* Expand an expression EXP that calls a built-in function,
6315 with result going to TARGET if that's convenient
6316 (and in mode MODE if that's convenient).
6317 SUBTARGET may be used as the target for computing one of EXP's operands.
6318 IGNORE is nonzero if the value is to be ignored. */
6321 bfin_expand_builtin (tree exp, rtx target ATTRIBUTE_UNUSED,
6322 rtx subtarget ATTRIBUTE_UNUSED,
6323 enum machine_mode mode ATTRIBUTE_UNUSED,
6324 int ignore ATTRIBUTE_UNUSED)
6327 enum insn_code icode;
6328 const struct builtin_description *d;
6329 tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
6330 unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
6331 tree arg0, arg1, arg2;
6332 rtx op0, op1, op2, accvec, pat, tmp1, tmp2, a0reg, a1reg;
6333 enum machine_mode tmode, mode0;
6337 case BFIN_BUILTIN_CSYNC:
6338 emit_insn (gen_csync ());
6340 case BFIN_BUILTIN_SSYNC:
6341 emit_insn (gen_ssync ());
6344 case BFIN_BUILTIN_DIFFHL_2X16:
6345 case BFIN_BUILTIN_DIFFLH_2X16:
6346 case BFIN_BUILTIN_SUM_2X16:
6347 arg0 = CALL_EXPR_ARG (exp, 0);
6348 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
6349 icode = (fcode == BFIN_BUILTIN_DIFFHL_2X16 ? CODE_FOR_subhilov2hi3
6350 : fcode == BFIN_BUILTIN_DIFFLH_2X16 ? CODE_FOR_sublohiv2hi3
6351 : CODE_FOR_ssaddhilov2hi3);
6352 tmode = insn_data[icode].operand[0].mode;
6353 mode0 = insn_data[icode].operand[1].mode;
6356 || GET_MODE (target) != tmode
6357 || ! (*insn_data[icode].operand[0].predicate) (target, tmode))
6358 target = gen_reg_rtx (tmode);
6360 if (VECTOR_MODE_P (mode0))
6361 op0 = safe_vector_operand (op0, mode0);
6363 if (! (*insn_data[icode].operand[1].predicate) (op0, mode0))
6364 op0 = copy_to_mode_reg (mode0, op0);
6366 pat = GEN_FCN (icode) (target, op0, op0);
6372 case BFIN_BUILTIN_MULT_1X32X32:
6373 case BFIN_BUILTIN_MULT_1X32X32NS:
6374 arg0 = CALL_EXPR_ARG (exp, 0);
6375 arg1 = CALL_EXPR_ARG (exp, 1);
6376 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
6377 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
6379 || !register_operand (target, SImode))
6380 target = gen_reg_rtx (SImode);
6381 if (! register_operand (op0, SImode))
6382 op0 = copy_to_mode_reg (SImode, op0);
6383 if (! register_operand (op1, SImode))
6384 op1 = copy_to_mode_reg (SImode, op1);
6386 a1reg = gen_rtx_REG (PDImode, REG_A1);
6387 a0reg = gen_rtx_REG (PDImode, REG_A0);
6388 tmp1 = gen_lowpart (V2HImode, op0);
6389 tmp2 = gen_lowpart (V2HImode, op1);
6390 emit_insn (gen_flag_macinit1hi (a1reg,
6391 gen_lowpart (HImode, op0),
6392 gen_lowpart (HImode, op1),
6393 GEN_INT (MACFLAG_FU)));
6394 emit_insn (gen_lshrpdi3 (a1reg, a1reg, GEN_INT (16)));
6396 if (fcode == BFIN_BUILTIN_MULT_1X32X32)
6397 emit_insn (gen_flag_mul_macv2hi_parts_acconly (a0reg, a1reg, tmp1, tmp2,
6398 const1_rtx, const1_rtx,
6399 const1_rtx, const0_rtx, a1reg,
6400 const0_rtx, GEN_INT (MACFLAG_NONE),
6401 GEN_INT (MACFLAG_M)));
6404 /* For saturating multiplication, there's exactly one special case
6405 to be handled: multiplying the smallest negative value with
6406 itself. Due to shift correction in fractional multiplies, this
6407 can overflow. Iff this happens, OP2 will contain 1, which, when
6408 added in 32 bits to the smallest negative, wraps to the largest
6409 positive, which is the result we want. */
6410 op2 = gen_reg_rtx (V2HImode);
6411 emit_insn (gen_packv2hi (op2, tmp1, tmp2, const0_rtx, const0_rtx));
6412 emit_insn (gen_movsibi (gen_rtx_REG (BImode, REG_CC),
6413 gen_lowpart (SImode, op2)));
6414 emit_insn (gen_flag_mul_macv2hi_parts_acconly_andcc0 (a0reg, a1reg, tmp1, tmp2,
6415 const1_rtx, const1_rtx,
6416 const1_rtx, const0_rtx, a1reg,
6417 const0_rtx, GEN_INT (MACFLAG_NONE),
6418 GEN_INT (MACFLAG_M)));
6419 op2 = gen_reg_rtx (SImode);
6420 emit_insn (gen_movbisi (op2, gen_rtx_REG (BImode, REG_CC)));
6422 emit_insn (gen_flag_machi_parts_acconly (a1reg, tmp2, tmp1,
6423 const1_rtx, const0_rtx,
6424 a1reg, const0_rtx, GEN_INT (MACFLAG_M)));
6425 emit_insn (gen_ashrpdi3 (a1reg, a1reg, GEN_INT (15)));
6426 emit_insn (gen_sum_of_accumulators (target, a0reg, a0reg, a1reg));
6427 if (fcode == BFIN_BUILTIN_MULT_1X32X32NS)
6428 emit_insn (gen_addsi3 (target, target, op2));
6431 case BFIN_BUILTIN_CPLX_MUL_16:
6432 case BFIN_BUILTIN_CPLX_MUL_16_S40:
6433 arg0 = CALL_EXPR_ARG (exp, 0);
6434 arg1 = CALL_EXPR_ARG (exp, 1);
6435 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
6436 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
6437 accvec = gen_reg_rtx (V2PDImode);
6438 icode = CODE_FOR_flag_macv2hi_parts;
6441 || GET_MODE (target) != V2HImode
6442 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
6443 target = gen_reg_rtx (tmode);
6444 if (! register_operand (op0, GET_MODE (op0)))
6445 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
6446 if (! register_operand (op1, GET_MODE (op1)))
6447 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
6449 if (fcode == BFIN_BUILTIN_CPLX_MUL_16)
6450 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
6451 const0_rtx, const0_rtx,
6452 const1_rtx, GEN_INT (MACFLAG_W32)));
6454 emit_insn (gen_flag_macinit1v2hi_parts (accvec, op0, op1, const0_rtx,
6455 const0_rtx, const0_rtx,
6456 const1_rtx, GEN_INT (MACFLAG_NONE)));
6457 emit_insn (gen_flag_macv2hi_parts (target, op0, op1, const1_rtx,
6458 const1_rtx, const1_rtx,
6459 const0_rtx, accvec, const1_rtx, const0_rtx,
6460 GEN_INT (MACFLAG_NONE), accvec));
6464 case BFIN_BUILTIN_CPLX_MAC_16:
6465 case BFIN_BUILTIN_CPLX_MSU_16:
6466 case BFIN_BUILTIN_CPLX_MAC_16_S40:
6467 case BFIN_BUILTIN_CPLX_MSU_16_S40:
6468 arg0 = CALL_EXPR_ARG (exp, 0);
6469 arg1 = CALL_EXPR_ARG (exp, 1);
6470 arg2 = CALL_EXPR_ARG (exp, 2);
6471 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
6472 op1 = expand_expr (arg1, NULL_RTX, VOIDmode, 0);
6473 op2 = expand_expr (arg2, NULL_RTX, VOIDmode, 0);
6474 accvec = gen_reg_rtx (V2PDImode);
6475 icode = CODE_FOR_flag_macv2hi_parts;
6478 || GET_MODE (target) != V2HImode
6479 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
6480 target = gen_reg_rtx (tmode);
6481 if (! register_operand (op1, GET_MODE (op1)))
6482 op1 = copy_to_mode_reg (GET_MODE (op1), op1);
6483 if (! register_operand (op2, GET_MODE (op2)))
6484 op2 = copy_to_mode_reg (GET_MODE (op2), op2);
6486 tmp1 = gen_reg_rtx (SImode);
6487 tmp2 = gen_reg_rtx (SImode);
6488 emit_insn (gen_ashlsi3 (tmp1, gen_lowpart (SImode, op0), GEN_INT (16)));
6489 emit_move_insn (tmp2, gen_lowpart (SImode, op0));
6490 emit_insn (gen_movstricthi_1 (gen_lowpart (HImode, tmp2), const0_rtx));
6491 emit_insn (gen_load_accumulator_pair (accvec, tmp1, tmp2));
6492 if (fcode == BFIN_BUILTIN_CPLX_MAC_16
6493 || fcode == BFIN_BUILTIN_CPLX_MSU_16)
6494 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx,
6495 const0_rtx, const0_rtx,
6496 const1_rtx, accvec, const0_rtx,
6498 GEN_INT (MACFLAG_W32)));
6500 emit_insn (gen_flag_macv2hi_parts_acconly (accvec, op1, op2, const0_rtx,
6501 const0_rtx, const0_rtx,
6502 const1_rtx, accvec, const0_rtx,
6504 GEN_INT (MACFLAG_NONE)));
6505 if (fcode == BFIN_BUILTIN_CPLX_MAC_16
6506 || fcode == BFIN_BUILTIN_CPLX_MAC_16_S40)
6516 emit_insn (gen_flag_macv2hi_parts (target, op1, op2, const1_rtx,
6517 const1_rtx, const1_rtx,
6518 const0_rtx, accvec, tmp1, tmp2,
6519 GEN_INT (MACFLAG_NONE), accvec));
6523 case BFIN_BUILTIN_CPLX_SQU:
6524 arg0 = CALL_EXPR_ARG (exp, 0);
6525 op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
6526 accvec = gen_reg_rtx (V2PDImode);
6527 icode = CODE_FOR_flag_mulv2hi;
6528 tmp1 = gen_reg_rtx (V2HImode);
6529 tmp2 = gen_reg_rtx (V2HImode);
6532 || GET_MODE (target) != V2HImode
6533 || ! (*insn_data[icode].operand[0].predicate) (target, V2HImode))
6534 target = gen_reg_rtx (V2HImode);
6535 if (! register_operand (op0, GET_MODE (op0)))
6536 op0 = copy_to_mode_reg (GET_MODE (op0), op0);
6538 emit_insn (gen_flag_mulv2hi (tmp1, op0, op0, GEN_INT (MACFLAG_NONE)));
6540 emit_insn (gen_flag_mulhi_parts (gen_lowpart (HImode, tmp2), op0, op0,
6541 const0_rtx, const1_rtx,
6542 GEN_INT (MACFLAG_NONE)));
6544 emit_insn (gen_ssaddhi3_high_parts (target, tmp2, tmp2, tmp2, const0_rtx,
6546 emit_insn (gen_sssubhi3_low_parts (target, target, tmp1, tmp1,
6547 const0_rtx, const1_rtx));
6555 for (i = 0, d = bdesc_2arg; i < ARRAY_SIZE (bdesc_2arg); i++, d++)
6556 if (d->code == fcode)
6557 return bfin_expand_binop_builtin (d->icode, exp, target,
6560 for (i = 0, d = bdesc_1arg; i < ARRAY_SIZE (bdesc_1arg); i++, d++)
6561 if (d->code == fcode)
6562 return bfin_expand_unop_builtin (d->icode, exp, target);
6567 #undef TARGET_INIT_BUILTINS
6568 #define TARGET_INIT_BUILTINS bfin_init_builtins
6570 #undef TARGET_EXPAND_BUILTIN
6571 #define TARGET_EXPAND_BUILTIN bfin_expand_builtin
6573 #undef TARGET_ASM_GLOBALIZE_LABEL
6574 #define TARGET_ASM_GLOBALIZE_LABEL bfin_globalize_label
6576 #undef TARGET_ASM_FILE_START
6577 #define TARGET_ASM_FILE_START output_file_start
6579 #undef TARGET_ATTRIBUTE_TABLE
6580 #define TARGET_ATTRIBUTE_TABLE bfin_attribute_table
6582 #undef TARGET_COMP_TYPE_ATTRIBUTES
6583 #define TARGET_COMP_TYPE_ATTRIBUTES bfin_comp_type_attributes
6585 #undef TARGET_RTX_COSTS
6586 #define TARGET_RTX_COSTS bfin_rtx_costs
6588 #undef TARGET_ADDRESS_COST
6589 #define TARGET_ADDRESS_COST bfin_address_cost
6591 #undef TARGET_ASM_INTEGER
6592 #define TARGET_ASM_INTEGER bfin_assemble_integer
6594 #undef TARGET_MACHINE_DEPENDENT_REORG
6595 #define TARGET_MACHINE_DEPENDENT_REORG bfin_reorg
6597 #undef TARGET_FUNCTION_OK_FOR_SIBCALL
6598 #define TARGET_FUNCTION_OK_FOR_SIBCALL bfin_function_ok_for_sibcall
6600 #undef TARGET_ASM_OUTPUT_MI_THUNK
6601 #define TARGET_ASM_OUTPUT_MI_THUNK bfin_output_mi_thunk
6602 #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
6603 #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
6605 #undef TARGET_SCHED_ADJUST_COST
6606 #define TARGET_SCHED_ADJUST_COST bfin_adjust_cost
6608 #undef TARGET_SCHED_ISSUE_RATE
6609 #define TARGET_SCHED_ISSUE_RATE bfin_issue_rate
6611 #undef TARGET_PROMOTE_FUNCTION_MODE
6612 #define TARGET_PROMOTE_FUNCTION_MODE default_promote_function_mode_always_promote
6614 #undef TARGET_ARG_PARTIAL_BYTES
6615 #define TARGET_ARG_PARTIAL_BYTES bfin_arg_partial_bytes
6617 #undef TARGET_PASS_BY_REFERENCE
6618 #define TARGET_PASS_BY_REFERENCE bfin_pass_by_reference
6620 #undef TARGET_SETUP_INCOMING_VARARGS
6621 #define TARGET_SETUP_INCOMING_VARARGS setup_incoming_varargs
6623 #undef TARGET_STRUCT_VALUE_RTX
6624 #define TARGET_STRUCT_VALUE_RTX bfin_struct_value_rtx
6626 #undef TARGET_VECTOR_MODE_SUPPORTED_P
6627 #define TARGET_VECTOR_MODE_SUPPORTED_P bfin_vector_mode_supported_p
6629 #undef TARGET_HANDLE_OPTION
6630 #define TARGET_HANDLE_OPTION bfin_handle_option
6632 #undef TARGET_DEFAULT_TARGET_FLAGS
6633 #define TARGET_DEFAULT_TARGET_FLAGS TARGET_DEFAULT
6635 #undef TARGET_SECONDARY_RELOAD
6636 #define TARGET_SECONDARY_RELOAD bfin_secondary_reload
6638 #undef TARGET_DELEGITIMIZE_ADDRESS
6639 #define TARGET_DELEGITIMIZE_ADDRESS bfin_delegitimize_address
6641 #undef TARGET_CANNOT_FORCE_CONST_MEM
6642 #define TARGET_CANNOT_FORCE_CONST_MEM bfin_cannot_force_const_mem
6644 #undef TARGET_RETURN_IN_MEMORY
6645 #define TARGET_RETURN_IN_MEMORY bfin_return_in_memory
6647 #undef TARGET_LEGITIMATE_ADDRESS_P
6648 #define TARGET_LEGITIMATE_ADDRESS_P bfin_legitimate_address_p
6650 #undef TARGET_FRAME_POINTER_REQUIRED
6651 #define TARGET_FRAME_POINTER_REQUIRED bfin_frame_pointer_required
6653 #undef TARGET_CAN_ELIMINATE
6654 #define TARGET_CAN_ELIMINATE bfin_can_eliminate
6656 #undef TARGET_ASM_TRAMPOLINE_TEMPLATE
6657 #define TARGET_ASM_TRAMPOLINE_TEMPLATE bfin_asm_trampoline_template
6658 #undef TARGET_TRAMPOLINE_INIT
6659 #define TARGET_TRAMPOLINE_INIT bfin_trampoline_init
6661 struct gcc_target targetm = TARGET_INITIALIZER;